1 #ifndef jmmcg_core_socket_server_hpp 2 #define jmmcg_core_socket_server_hpp 3 4 /****************************************************************************** 5 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/socket_server.hpp 2353 2018-10-21 20:22:18Z jmmcg $ 6 ** 7 ** Copyright (C) 2015 by J.M.McGuiness, coder@hussar.me.uk 8 ** 9 ** This library is free software; you can redistribute it and/or 10 ** modify it under the terms of the GNU Lesser General Public 11 ** License as published by the Free Software Foundation; either 12 ** version 2.1 of the License, or (at your option) any later version. 13 ** 14 ** This library is distributed in the hope that it will be useful, 15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 ** Lesser General Public License for more details. 18 ** 19 ** You should have received a copy of the GNU Lesser General Public 20 ** License along with this library; if not, write to the Free Software 21 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24 #include "exception.hpp" 25 #include "msg_processor.hpp" 26 #include "socket_server_manager.hpp" 27 28 #include "config.h" 29 30 #include <boost/program_options.hpp> 31 32 #include <atomic> 33 #include <iostream> 34 #include <iterator> 35 #include <thread> 36 37 namespace jmmcg { 38 39 namespace socket { 40 41 /// A very simple socket-based server. 42 template< 43 class ProcessingRules, ///< The translation rules to use to convert messages received from the client to server-side messages & via-versa. 44 class SvrMgr ///< The particular type of server that should be run. e.g. does it forward messages, or send them back? 45 > 46 class svr final { 47 public: 48 using exception_type=crt_exception<ppd::platform_api, ppd::sequential_mode>; 49 using svr_mgr_t=SvrMgr; 50 using socket_t=typename svr_mgr_t::socket_t; 51 using msg_processor_t=msg_processor<ProcessingRules>; 52 using proc_rules_t=typename msg_processor_t::proc_rules_t; 53 54 struct ctor_args { 55 using addr_t=boost::asio::ip::address; 56 using port_t=unsigned short; 57 using pr_t=proc_rules_t; 58 59 addr_t addr; 60 port_t port; 61 pr_t proc_ops; 62 }; 63 64 /// A simple socket-based server that listens to connections to the specified endpoint and responds to messages received in the specified manner. i.e. loops them back. 65 /** 66 \param addr The IPv4 or IPv6 address to which the connection should be made. 67 \param port_num The port number to which the connection should be made. 68 \param proc_ops The responses that the server should make to messages received on the endpoint, sent back to the connected endpoint. 69 70 \see ctor_args 71 */ 72 svr(boost::asio::ip::address const &addr, unsigned short port_num, proc_rules_t const &proc_ops) noexcept(false); 73 /// A simple socket-based server that listens to connections to the specified endpoint (e.g. a client that sends FIX messages) and responds to messages received in the specified manner. i.e. forwards the messages. 74 /** 75 \param addr The IPv4 or IPv6 address to which the connection should be made. 76 \param port_num The port number to which the connection should be made. 77 \param proc_ops The responses that the server should make to messages received on the endpoint. 78 \param dest_skt The socket to which the received messages should be forwarded after suitable processing. e.g. the exchange. 79 80 \see ctor_args 81 */ 82 svr(boost::asio::ip::address const &addr, unsigned short port_num, proc_rules_t const &proc_ops, socket_t &dest_skt) noexcept(false); 83 explicit svr(ctor_args const &args) noexcept(false); 84 explicit svr(ctor_args const &args, socket_t &dest_skt) noexcept(false); 85 ~svr() noexcept(true); 86 87 void stop() noexcept(true); 88 89 /// A main() method for instantiating a stand-alone simulator. 90 /** 91 Use this within the CRT-main(). 92 */ 93 static int main(int argc, char const * const *argv) noexcept(true); 94 95 bool empty() const noexcept(true); 96 typename svr_mgr_t::client_cxns_t::const_iterator find(typename svr_mgr_t::client_cxns_t::key_type const &k) const noexcept(true); 97 98 std::string to_string() const noexcept(false); 99 100 private: 101 static volatile std::sig_atomic_t signal_status; 102 boost::asio::ip::address const address; 103 const unsigned short port_number; 104 std::atomic<bool> exit_{false}; 105 /** 106 \todo Need to check this for errors. 107 */ 108 std::exception_ptr ex=nullptr; 109 msg_processor_t processor; 110 svr_mgr_t manager; 111 /** 112 \todo Ideally this should run at high priority. 113 */ 114 std::thread io_thread; 115 116 static void signal_handler(int signal) noexcept(true); 117 118 /// In a single thread, handle any connections from the client connected on the specified socket and forward those messages on. 119 /** 120 \param src_cxn The client socket, e.g. a FIX client. 121 \param dest_skt The destination socket, e.g. an exchange connection. 122 \return False to continue processing messages, true otherwise. 123 */ 124 bool read_and_process_msgs(typename svr_mgr_t::tcp_connection::ptr_type src_cxn, socket_t &dest_skt) noexcept(false); 125 126 void run() noexcept(true); 127 }; 128 129 template<class ProcessingRules, class SvrMgr> inline std::ostream & 130 operator<<(std::ostream &os, svr<ProcessingRules, SvrMgr> const &ec) noexcept(false); 131 132 } 133 134 } 135 136 #include "socket_server_impl.hpp" 137 138 #endif