libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
socket_server_manager_asio.hpp
Go to the documentation of this file.
1 #ifndef LIBJMMCG_CORE_SERVER_MANAGER_ASIO_HPP
2 #define LIBJMMCG_CORE_SERVER_MANAGER_ASIO_HPP
3 
4 /******************************************************************************
5 ** Copyright © 2015 by J.M.McGuiness, coder@hussar.me.uk
6 **
7 ** This library is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU Lesser General Public
9 ** License as published by the Free Software Foundation; either
10 ** version 2.1 of the License, or (at your option) any later version.
11 **
12 ** This library is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 ** Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public
18 ** License along with this library; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
23 
24 #include <functional>
25 #include <memory>
26 
27 #ifdef __GCC__
28 # pragma GCC diagnostic push
29 # pragma GCC diagnostic ignored "-Wsuggest-final-methods"
30 # pragma GCC diagnostic ignored "-Wsuggest-final-types"
31 #endif
32 
33 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace socket { namespace server_manager { namespace asio {
34 
35 /// A simple TCP/IP socket wrapper using socket_wrapper for servers.
36 /**
37  Developed from:
38  <a href="https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp"/>
39 
40  \see socket::asio::socket_wrapper
41 */
42 template<class LkT>
43 class manager {
44 public:
45  using acceptor_t=boost::asio::ip::tcp::acceptor;
46  using socket_t=socket::asio::socket_wrapper<LkT>;
47  using socket_priority=typename socket_t::socket_priority;
48  using thread_traits=ppd::api_threading_traits<ppd::platform_api, ppd::heavyweight_threading>;
49 
50  /// A wrapper for a new client connection to the server.
51  class session : public std::enable_shared_from_this<session> {
52  public:
53  using ptr_type=std::shared_ptr<session>;
54 
55  explicit session(boost::asio::ip::tcp::socket &&socket)
56  : socket_(std::move(socket)) {
57  // Stuff to set once the socket is open...
58  }
59 
60  virtual ~session()=default;
61 
62  /// For loop-back connections, such as simulators.
63  template<class RecvProcMsgs>
64  bool process(RecvProcMsgs proc_fn) noexcept(false) {
65  return proc_fn(*this, *this);
66  }
67 
68  /// For forwarding connections, such as the translator.
69  template<class RecvProcMsgs>
70  bool process(RecvProcMsgs proc_fn, socket_t &dest_socket) noexcept(false) {
71  return proc_fn(*this, dest_socket);
72  }
73 
74  virtual void start() {
75  }
76 
77  virtual void stop() {
78  socket_.close();
79  }
80 
81  socket_t &socket() noexcept(true) {
82  return socket_;
83  }
84 
85  std::string to_string() const noexcept(false);
86 
87  static ptr_type make(boost::asio::ip::tcp::socket &&socket) noexcept(false) {
88  return std::make_shared<typename ptr_type::element_type>(std::move(socket));
89  }
90 
91  protected:
92  socket_t socket_;
93  };
94  using server_to_client_flow_t=std::function<void (typename session::ptr_type)>;
95 
96  /// Create a new connection to the specified TCP socket using the TCP/IP protocol.
97  /**
98  \param addr The IPv4 or IPv6 address to which the connection should be made.
99  \param port_num The port number to which the connection should be made.
100  */
101  manager(boost::asio::ip::address const &addr, unsigned short port_num, std::size_t min_message_size, std::size_t max_message_size, unsigned short timeout, socket_priority priority, std::size_t incoming_cpu, server_to_client_flow_t &&server_to_client_flow);
102 
103  /// Blocking wait for a new connection from a client.
104  void run();
105 
106  void stop();
107 
108  static void set_options(acceptor_t &acceptor, socket_t &skt);
109 
110  std::string to_string() const noexcept(false);
111 
112 protected:
113  boost::asio::io_context io_context{};
114  acceptor_t acceptor;
115  server_to_client_flow_t server_to_client_flow_;
116 
117  ~manager()=default;
118 
119  void set_options(socket_t &skt);
120 };
121 
122 template<class LkT>
123 inline std::ostream &
124 operator<<(std::ostream &os, typename manager<LkT>::tcp_connection const &ec) noexcept(false);
125 
126 template<class LkT>
127 inline std::ostream &
128 operator<<(std::ostream &os, manager<LkT> const &ec) noexcept(false);
129 
130 /// A simple TCP/IP socket wrapper using boost::asio for loop-back servers.
131 template<class SvrHBs, class LkT>
132 class loopback : public manager<LkT> {
133 public:
134  using base_t=manager<LkT>;
135  /// Start sending heartbeats upon a connection.
136  using heartbeats_t=SvrHBs;
137  using socket_t=typename base_t::socket_t;
138  using socket_priority=typename base_t::socket_priority;
139  using server_to_client_flow_t=typename base_t::server_to_client_flow_t;
140  using base_t::base_t;
141 
142  /**
143  \param dest The socket to which the received messages should be forwarded after suitable processing.
144  */
145  loopback(boost::asio::ip::address const &addr, unsigned short port_num, std::size_t, std::size_t max_message_size, unsigned short timeout, socket_priority priority, std::size_t incoming_cpu, server_to_client_flow_t &&server_to_client_flow);
146 
147  /// Non-blocking call to wait for new connections from a client.
148  /**
149  \param proc_fn The operations to perform upon receiving a connection request from a client.
150  */
151  template<class RecvProcMsgs>
152  void start_accept(RecvProcMsgs proc_fn) noexcept(false);
153 
154 private:
155  class send_heartbeats;
156 };
157 
158 /// A simple TCP/IP socket wrapper using a socket wrapper for forwarding servers.
159 template<class LkT>
160 class forwarding : public manager<LkT> {
161 public:
162  using base_t=manager<LkT>;
163  using socket_t=typename base_t::socket_t;
164  using socket_priority=typename base_t::socket_priority;
165  using server_to_client_flow_t=typename base_t::server_to_client_flow_t;
166 
167  /**
168  \param dest The socket to which the received messages should be forwarded after suitable processing.
169  */
170  forwarding(boost::asio::ip::address const &addr, unsigned short port_num, std::size_t min_message_size, std::size_t max_message_size, unsigned short timeout, socket_priority priority, std::size_t incoming_cpu, server_to_client_flow_t &&server_to_client_flow, socket_t &dest);
171 
172  /// Non-blocking call to wait for new connections from a client.
173  /**
174  \param proc_fn The operations to perform upon receiving a connection request from a client.
175  */
176  template<class RecvProcMsgs>
177  void start_accept(RecvProcMsgs proc_fn) noexcept(false);
178 
179 private:
180  socket_t &dest_socket_;
181 };
182 
183 } } } } }
184 
186 
187 #ifdef __GCC__
188 # pragma GCC diagnostic pop
189 #endif
190 
191 #endif