root/core/socket_server_impl.hpp

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. signal_handler
  2. manager
  3. manager
  4. stop
  5. main
  6. empty
  7. find
  8. to_string
  9. read_and_process_msgs
  10. run

   1 /******************************************************************************
   2 ** $Header: svn+ssh://jmmcg@svn.code.sf.net/p/libjmmcg/code/trunk/libjmmcg/core/socket_server_impl.hpp 2219 2017-11-07 22:42:03Z jmmcg $
   3 **
   4 ** Copyright (C) 2015 by J.M.McGuiness, coder@hussar.me.uk
   5 **
   6 ** This library is free software; you can redistribute it and/or
   7 ** modify it under the terms of the GNU Lesser General Public
   8 ** License as published by the Free Software Foundation; either
   9 ** version 2.1 of the License, or (at your option) any later version.
  10 **
  11 ** This library is distributed in the hope that it will be useful,
  12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 ** Lesser General Public License for more details.
  15 **
  16 ** You should have received a copy of the GNU Lesser General Public
  17 ** License along with this library; if not, write to the Free Software
  18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 */
  20 
  21 namespace boost { namespace asio { namespace ip {
  22 
  23 /// Extract a v4 TCP/IP address from the supplied stream.
  24 /**
  25         Boost.asio.ip lacks stream-in operators, so isn't compatible with boost.program_options by default. Rather an omission in my opinion...
  26 */
  27 inline std::istream &
  28 operator>>(std::istream &is, boost::asio::ip::address &addr) {
  29         std::string s;
  30         is>>s;
  31         boost::asio::ip::address_v4 addr_v4;
  32         addr_v4.from_string(s);
  33         addr=addr_v4;
  34         return is;
  35 }
  36 
  37 } } }
  38 
  39 namespace jmmcg { namespace socket {
  40 
  41 template<class ProcessingRules, class SvrMgr>
  42 volatile std::sig_atomic_t svr<ProcessingRules, SvrMgr>::signal_status=0;
  43 
  44 template<class ProcessingRules, class SvrMgr> inline void
  45 svr<ProcessingRules, SvrMgr>::signal_handler(int signal) noexcept(true) {
  46         signal_status=signal;
  47 }
  48 
  49 template<class ProcessingRules, class SvrMgr> inline
  50 svr<ProcessingRules, SvrMgr>::svr(boost::asio::ip::address const &addr, unsigned short port_num, proc_rules_t const &proc_ops) noexcept(false)
  51 : address(addr), port_number(port_num), processor(proc_ops), manager(address, port_number, proc_rules_t::src_msg_details_t::min_msg_size, proc_rules_t::src_msg_details_t::max_msg_size) {
  52         manager.start_accept(std::bind(&svr::read_and_process_msgs, this, std::placeholders::_1, std::placeholders::_2));
  53         // This must come after the accept otherwise starting subsequent servers will fail.
  54         io_thread=std::thread(&svr::run, this);
  55 }
  56 
  57 template<class ProcessingRules, class SvrMgr> inline
  58 svr<ProcessingRules, SvrMgr>::svr(boost::asio::ip::address const &addr, unsigned short port_num, proc_rules_t const &proc_ops, socket_t &dest_skt) noexcept(false)
  59 : address(addr), port_number(port_num), processor(proc_ops), manager(address, port_number, proc_rules_t::src_msg_details_t::min_msg_size, proc_rules_t::src_msg_details_t::max_msg_size, dest_skt) {
  60         manager.start_accept(std::bind(&svr::read_and_process_msgs, this, std::placeholders::_1, std::placeholders::_2));
  61         // This must come after the accept otherwise starting subsequent servers will fail.
  62         io_thread=std::thread(&svr::run, this);
  63 }
  64 
  65 template<class ProcessingRules, class SvrMgr> inline
  66 svr<ProcessingRules, SvrMgr>::svr(ctor_args const &args) noexcept(false)
  67 : svr(args.addr, args.port, args.proc_ops) {
  68 }
  69 
  70 template<class ProcessingRules, class SvrMgr> inline
  71 svr<ProcessingRules, SvrMgr>::svr(ctor_args const &args, socket_t &dest_skt) noexcept(false)
  72 : svr(args.addr, args.port, args.proc_ops, dest_skt) {
  73 }
  74 
  75 template<class ProcessingRules, class SvrMgr> inline
  76 svr<ProcessingRules, SvrMgr>::~svr() noexcept(true) {
  77         stop();
  78         if (io_thread.joinable()) {
  79                 io_thread.join();
  80         }
  81 }
  82 
  83 template<class ProcessingRules, class SvrMgr> inline void
  84 svr<ProcessingRules, SvrMgr>::stop() noexcept(true) {
  85         exit_=true;
  86         manager.stop();
  87 }
  88 
  89 template<class ProcessingRules, class SvrMgr> inline int
  90 svr<ProcessingRules, SvrMgr>::main(int argc, char const * const *argv) noexcept(true) {
  91         try {
  92                 boost::program_options::options_description desc(
  93                         "A simple exchange-simulator that listens to an IPADDR:PORT combination. The file name indicates the message version implemented. For details regarding the properties of the simulator see the documentation that came with the distribution. Copyright (c) J.M.McGuiness, coder@hussar.me.uk. http://libjmmcg.sf.net/ Distributed under the terms of the GPL v2.1."
  94                 );
  95                 desc.add_options()
  96                         ("help", "Print this help message.")
  97                         ("version", "Print the build number of this program.")
  98                         ("address", boost::program_options::value<boost::asio::ip::address>()->default_value(boost::asio::ip::address_v4::loopback()), "IP address (in v4 format) to which the server should listen.")
  99                         ("port", boost::program_options::value<unsigned short>()->required(), "An unused port to which the server should listen.")
 100                 ;
 101                 boost::program_options::variables_map vm;
 102                 boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
 103                 if (vm.count("help")) {
 104                         std::cout<<desc<<std::endl;
 105                         return exit_print_help;
 106                 }
 107                 if (vm.count("version")) {
 108                         std::cout<<"Build: "<<libjmmcg_VERSION_NUMBER<<std::endl;
 109                         return exit_print_version;
 110                 }
 111                 boost::program_options::notify(vm);    
 112                 std::signal(SIGINT, svr::signal_handler);
 113                 proc_rules_t proc_rules;
 114                 svr sim(vm["address"].as<boost::asio::ip::address>(), vm["port"].as<unsigned short>(), proc_rules);
 115                 std::clog<<sim<<std::endl;
 116                 while (!signal_status) {
 117                         std::this_thread::yield();
 118                 }
 119                 std::clog<<sim<<std::endl;
 120                 return exit_codes::exit_success;
 121         } catch (exception_type const &ex) {
 122                 std::cerr<<"CRT exception. Detail: "<<ex.what()<<std::endl;
 123                 return exit_codes::exit_crt_exception;
 124         } catch (std::exception const &ex) {
 125                 std::cerr<<"STL exception. Detail: "<<ex.what()<<std::endl;
 126                 return exit_codes::exit_stl_exception;
 127         } catch (...) {
 128                 std::cerr<<"Unknown exception."<<std::endl;
 129                 return exit_codes::exit_unknown_exception;
 130         }
 131         return exit_codes::exit_unknown_failure;
 132 }
 133 
 134 template<class ProcessingRules, class SvrMgr> inline bool
 135 svr<ProcessingRules, SvrMgr>::empty() const noexcept(true) {
 136         return manager.empty();
 137 }
 138 
 139 template<class ProcessingRules, class SvrMgr> inline typename svr<ProcessingRules, SvrMgr>::svr_mgr_t::client_cxns_t::const_iterator
 140 svr<ProcessingRules, SvrMgr>::find(typename svr_mgr_t::client_cxns_t::key_type const &k) const noexcept(true) {
 141         return manager.find(k);
 142 }
 143 
 144 template<class ProcessingRules, class SvrMgr> inline std::string
 145 svr<ProcessingRules, SvrMgr>::to_string() const noexcept(false) {
 146         std::ostringstream ss;
 147         ss
 148                 <<typeid(*this).name()
 149                 <<",\naddress="<<address
 150                 <<", port_number: "<<port_number
 151                 <<", exit="<<static_cast<bool>(exit_)
 152                 <<", client processing-error: '"<<ex<<"'"
 153                 <<", processor: "<<processor
 154                 <<", manager: "<<manager;
 155         return ss.str();
 156 }
 157 
 158 template<class ProcessingRules, class SvrMgr> inline bool
 159 svr<ProcessingRules, SvrMgr>::read_and_process_msgs(typename svr_mgr_t::tcp_connection::ptr_type src_cxn, socket_t &dest_skt) noexcept(false) {
 160         while (LIKELY(!static_cast<bool>(exit_))) {
 161                 assert(src_cxn->socket().is_open());
 162                 if (UNLIKELY(processor.read_and_process_a_msg(src_cxn->socket(), dest_skt))) {
 163                         break;
 164                 }
 165         }
 166         return static_cast<bool>(exit_);
 167 }
 168 
 169 template<class ProcessingRules, class SvrMgr> inline void
 170 svr<ProcessingRules, SvrMgr>::run() noexcept(true) {
 171         try {
 172                 manager.run();
 173         } catch (std::exception const &e) {
 174                 ex=std::make_exception_ptr(e);
 175         }
 176 }
 177 
 178 template<class ProcessingRules, class SvrMgr> inline std::ostream &
 179 operator<<(std::ostream &os, svr<ProcessingRules, SvrMgr> const &ec) noexcept(false) {
 180         os<<ec.to_string();
 181         return os;
 182 }
 183 
 184 } }

/* [<][>][^][v][top][bottom][index][help] */