libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
connection_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2015 by J.M.McGuiness, isimud@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 namespace isimud { namespace ISIMUD_VER_NAMESPACE { namespace exchanges { namespace common {
20 
21 template<class MsgDetails, class ConnPol> inline
22 connection<MsgDetails, ConnPol>::connection(conn_pol_t const &conn_pol, skt_mgr_t::socket_priority priority, std::size_t incoming_cpu)
24 }
25 
26 template<class MsgDetails, class ConnPol>
27 template<class Msg> inline
28 typename std::enable_if<
29  !std::is_same<
30  typename boost::mpl::find<typename MsgDetails::client_to_exchange_messages_t, Msg>::type,
31  typename boost::mpl::end<typename MsgDetails::client_to_exchange_messages_t>::type
32  >::value,
33  void
34 >::type
35 connection<MsgDetails, ConnPol>::send(Msg const &msg) {
36  link.write(msg);
37 }
38 
39 template<class MsgDetails, class ConnPol>
40 template<class Msg> inline
41 typename std::enable_if<
42  !std::is_same<
43  typename boost::mpl::find<typename MsgDetails::exchange_to_client_messages_t, Msg>::type,
44  typename boost::mpl::end<typename MsgDetails::exchange_to_client_messages_t>::type
45  >::value,
46  void
47 >::type
48 connection<MsgDetails, ConnPol>::receive(Msg &msg) {
49  link.read(msg);
50 }
51 
52 template<class MsgDetails, class ConnPol> inline void
53 connection<MsgDetails, ConnPol>::stop() {
54  link.stop();
55 }
56 
57 template<class MsgDetails, class ConnPol> inline std::string
58 connection<MsgDetails, ConnPol>::to_string() const noexcept(false) {
59  std::ostringstream ss;
60  ss
61  <<libjmmcg::ppd::api_threading_traits<libjmmcg::ppd::platform_api, libjmmcg::ppd::sequential_mode>::demangle_name(typeid(*this))
62  <<",\nlink: "<<link;
63  return ss.str();
64 }
65 
66 template<class MsgDetails, class ConnPol> inline std::ostream &
67 operator<<(std::ostream &os, connection<MsgDetails, ConnPol> const &ec) noexcept(false) {
68  os<<ec.to_string();
69  return os;
70 }
71 
72 template<class ExchgToClientProcessingRules, class ConnPol> inline
73 connection_processor<ExchgToClientProcessingRules, ConnPol>::connection_processor(ctor_args const &cxn_details, socket_priority priority, std::size_t incoming_cpu, proc_rules_t const &proc_rules)
74 : processor(proc_rules), cxn_(cxn_details, priority, incoming_cpu) {
75  cxn_.send(typename msg_details_t::LogonRequest(cxn_.conn_pol_.logon_args));
76  typename msg_details_t::LogonReply msg;
77  // We could get a heartbeat: ignore it until the logon is obtained.
78  do {
79  cxn_.receive(msg);
80  } while (static_cast<typename msg_details_t::MsgTypes_t>(msg.type())!=static_cast<typename msg_details_t::MsgTypes_t>(msg_details_t::LogonReply::static_type));
81  const typename msg_details_t::LogonReply::respond process_response{};
82  process_response(msg, [this]() {logged_on_=true;});
83 }
84 
85 template<class ExchgToClientProcessingRules, class ConnPol> inline
86 connection_processor<ExchgToClientProcessingRules, ConnPol>::~connection_processor() noexcept(false) {
87  cxn_.send(typename msg_details_t::LogoutRequest(cxn_.conn_pol_.logoff_args));
88 // TODO Don't check this because the socket may have closed whilst reading the message, so it may be gash...
89  typename msg_details_t::Logout msg;
90  // We could get a heartbeat: ignore it until the logout is obtained.
91  do {
92  cxn_.receive(msg);
93  } while (static_cast<typename msg_details_t::MsgTypes_t>(msg.type())!=static_cast<typename msg_details_t::MsgTypes_t>(msg_details_t::Logout::static_type));
94  assert(static_cast<typename msg_details_t::MsgTypes_t>(msg.type())==static_cast<typename msg_details_t::MsgTypes_t>(msg_details_t::Logout::static_type));
95  logged_on_=false;
96 }
97 
98 template<class ExchgToClientProcessingRules, class ConnPol>
99 template<class ClientCxn, class LatencyTimestamps>
100 inline bool
101 connection_processor<ExchgToClientProcessingRules, ConnPol>::read_and_process_a_msg(ClientCxn &dest_link, LatencyTimestamps &ts) noexcept(false) {
102  return processor.read_and_process_a_msg(cxn_.socket(), dest_link, ts);
103 }
104 
105 template<class ExchgToClientProcessingRules, class ConnPol>
106 inline void
107 connection_processor<ExchgToClientProcessingRules, ConnPol>::stop() {
108  cxn_.stop();
109 }
110 
111 template<class ExchgToClientProcessingRules, class ConnPol>
112 inline std::string
113 connection_processor<ExchgToClientProcessingRules, ConnPol>::to_string() const noexcept(false) {
114  std::ostringstream ss;
115  ss
116  <<libjmmcg::ppd::api_threading_traits<libjmmcg::ppd::platform_api, libjmmcg::ppd::sequential_mode>::demangle_name(typeid(*this))
117  <<",\nprocessor: "<<processor
118  <<", cxn_: "<<cxn_;
119  return ss.str();
120 }
121 
122 template<class ExchgToClientProcessingRules, class ConnPol> inline std::ostream &
123 operator<<(std::ostream &os, connection_processor<ExchgToClientProcessingRules, ConnPol> const &ec) noexcept(false) {
124  os<<ec.to_string();
125  return os;
126 }
127 
128 } } } }