github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/3rd_party/fflib/src/net/middleware/net_nervure.cpp (about)

     1  /***********************************************
     2    The MIT License (MIT)
     3  
     4    Copyright (c) 2012 Athrun Arthur <athrunarthur@gmail.com>
     5  
     6    Permission is hereby granted, free of charge, to any person obtaining a copy
     7    of this software and associated documentation files (the "Software"), to deal
     8    in the Software without restriction, including without limitation the rights
     9    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10    copies of the Software, and to permit persons to whom the Software is
    11    furnished to do so, subject to the following conditions:
    12  
    13    The above copyright notice and this permission notice shall be included in
    14    all copies or substantial portions of the Software.
    15  
    16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    22    THE SOFTWARE.
    23   *************************************************/
    24  #include "ff/net/middleware/net_nervure.h"
    25  #include "ff/net/common/defines.h"
    26  #include "ff/net/middleware/event_handler.h"
    27  #include "ff/net/network/asio_point.h"
    28  #include "ff/net/network/end_point.h"
    29  #include "ff/net/network/events.h"
    30  #include "ff/net/network/tcp_client.h"
    31  #include "ff/net/network/tcp_server.h"
    32  #include "ff/net/network/udp_point.h"
    33  
    34  namespace ff {
    35  namespace net {
    36  using namespace event;
    37  
    38  net_nervure::net_nervure(net_mode nm)
    39      : m_oIOService(), mi_mode(nm), m_safe_to_stop(true) {
    40    m_pEH = new event_handler();
    41    m_pBS = new length_packer();
    42    m_pEH->listen<event::more::tcp_server_accept_connection>(std::bind(
    43        &net_nervure::on_tcp_server_accept_connect, this, std::placeholders::_1));
    44    m_pEH->listen<event::more::tcp_client_get_connection_succ>(std::bind(
    45        &net_nervure::on_tcp_client_get_connect, this, std::placeholders::_1));
    46    m_pEH->listen<event::more::tcp_recv_stream_error>(
    47        std::bind(&net_nervure::on_conn_recv_or_send_error, this,
    48                  std::placeholders::_1, std::placeholders::_2));
    49    m_pEH->listen<event::more::tcp_send_stream_error>(
    50        std::bind(&net_nervure::on_conn_recv_or_send_error, this,
    51                  std::placeholders::_1, std::placeholders::_2));
    52  }
    53  
    54  void net_nervure::add_pkg_handler(tcp_pkg_handler *p_tcp_handler,
    55                                    udp_pkg_handler *p_udp_handler) {
    56    if (p_tcp_handler)
    57      m_pTCPHandler.push_back(p_tcp_handler);
    58    if (p_udp_handler)
    59      m_pUDPHandler.push_back(p_udp_handler);
    60  }
    61  
    62  net_nervure::~net_nervure() {
    63    if (m_pEH != NULL) {
    64      delete m_pEH;
    65      m_pEH = NULL;
    66    }
    67    if (m_pBS) {
    68      delete m_pBS;
    69      m_pBS = NULL;
    70    }
    71  }
    72  
    73  tcp_connection_base_ptr net_nervure::add_tcp_client(const std::string &ip,
    74                                                      uint16_t iTCPPort) {
    75    tcp_endpoint ep(boost::asio::ip::address_v4::from_string(ip), iTCPPort);
    76    return add_tcp_client(ep);
    77  }
    78  
    79  tcp_connection_base_ptr net_nervure::add_tcp_client(const tcp_endpoint &ep) {
    80    tcp_connection_base *p = NULL;
    81    switch (mi_mode) {
    82    case real_net:
    83      p = new net_tcp_client(m_oIOService, m_pBS, m_pEH, m_pTCPHandler, ep);
    84      break;
    85    default:
    86      assert(0 && "not impl");
    87      break;
    88    }
    89    tcp_connection_base_ptr pclient(p);
    90    m_oClients.push_back(pclient);
    91    return pclient;
    92  }
    93  
    94  tcp_server_ptr net_nervure::add_tcp_server(const std::string &ip,
    95                                             uint16_t iTCPPort) {
    96    tcp_endpoint ep(boost::asio::ip::address_v4::from_string(ip), iTCPPort);
    97    return add_tcp_server(ep);
    98  }
    99  
   100  tcp_server_ptr net_nervure::add_tcp_server(const tcp_endpoint &ep) {
   101    tcp_server *p = NULL;
   102    switch (mi_mode) {
   103    case real_net:
   104      p = new net_tcp_server(m_oIOService, m_pBS, m_pEH, m_pTCPHandler, ep);
   105      p->start_accept();
   106      break;
   107    default:
   108      assert(0 && "not impl");
   109      break;
   110    }
   111    tcp_server_ptr pserver(p);
   112    m_oServers.push_back(pserver);
   113    return pserver;
   114  }
   115  
   116  udp_point_ptr net_nervure::add_udp_point(const std::string &ip,
   117                                           uint16_t iUDPPort) {
   118    udp_endpoint ep(boost::asio::ip::address_v4::from_string(ip), iUDPPort);
   119    return add_udp_point(ep);
   120  }
   121  
   122  udp_point_ptr net_nervure::add_udp_point(const udp_endpoint &ep) {
   123    udp_point *p = NULL;
   124    switch (mi_mode) {
   125    case real_net:
   126      p = new net_udp_point(m_oIOService, m_pBS, m_pEH, m_pUDPHandler, ep);
   127      break;
   128    // case simu_net:
   129    // p = new simu_udp_point(m_oIOService, m_pBS, m_pEH, m_pUDPHandler,
   130    // ep);  break;
   131    default:
   132      assert(0 && "not impl");
   133      break;
   134    }
   135    udp_point_ptr ppoint(p);
   136    m_oUDPPoints.push_back(ppoint);
   137    return ppoint;
   138  }
   139  
   140  void net_nervure::on_conn_recv_or_send_error(tcp_connection_base *pConn,
   141                                               boost::system::error_code ec) {
   142    // todo, should revise the connections.
   143    for (tcp_clients_t::iterator it = m_oClients.begin(); it != m_oClients.end();
   144         ++it) {
   145      tcp_connection_base_ptr p = *it;
   146      if (p.get() == pConn) {
   147        pConn->close();
   148        m_oClients.erase(it);
   149        m_pEH->triger<tcp_lost_connection>(pConn);
   150        break;
   151      }
   152    }
   153    for (tcp_connections_t::iterator it = m_oTCPConnections.begin();
   154         it != m_oTCPConnections.end(); ++it) {
   155      tcp_connection_base_ptr p = *it;
   156      if (p.get() == pConn) {
   157        pConn->close();
   158        m_oTCPConnections.erase(it);
   159        m_pEH->triger<tcp_lost_connection>(pConn);
   160        break;
   161      }
   162    }
   163  }
   164  
   165  void net_nervure::on_tcp_client_get_connect(tcp_connection_base *pClient) {
   166    m_pEH->triger<tcp_get_connection>(pClient);
   167  }
   168  
   169  void net_nervure::on_tcp_server_accept_connect(tcp_connection_base_ptr pConn) {
   170    m_oTCPConnections.push_back(pConn);
   171    m_pEH->triger<tcp_get_connection>(pConn.get());
   172  }
   173  
   174  void net_nervure::stop() {
   175    std::thread::id cid = std::this_thread::get_id();
   176    if (m_safe_to_stop)
   177      return;
   178  
   179    if (cid == m_io_service_thrd) {
   180      internal_stop();
   181    } else {
   182      std::unique_lock<std::mutex> _lock(m_stop_mutex);
   183      m_oIOService.post(std::bind(&net_nervure::internal_stop, this));
   184      while (!m_safe_to_stop) {
   185        m_stop_cond.wait(_lock);
   186      }
   187    }
   188  }
   189  
   190  void net_nervure::internal_stop() {
   191    m_oIOService.stop();
   192    for (tcp_servers_t::iterator it = m_oServers.begin(); it != m_oServers.end();
   193         ++it) {
   194      tcp_server_ptr p = *it;
   195      p->close();
   196    }
   197    m_oServers.clear();
   198    for (tcp_connections_t::iterator it = m_oTCPConnections.begin();
   199         it != m_oTCPConnections.end(); ++it) {
   200      tcp_connection_base_ptr p = *it;
   201      p->close();
   202    }
   203    m_oTCPConnections.clear();
   204    for (tcp_clients_t::iterator it = m_oClients.begin(); it != m_oClients.end();
   205         ++it) {
   206      tcp_connection_base_ptr p = *it;
   207      p->close();
   208    }
   209    m_oClients.clear();
   210    std::unique_lock<std::mutex> _lock(m_stop_mutex);
   211    m_safe_to_stop = true;
   212    m_stop_cond.notify_one();
   213  }
   214  
   215  void net_nervure::run() {
   216    m_safe_to_stop = false;
   217    m_io_service_thrd = std::this_thread::get_id();
   218    m_oIOService.run();
   219  }
   220  
   221  } // namespace net
   222  
   223  } // namespace ff