From bbe0a19340c91c2d935bd7c9cddd8e31c05bdb12 Mon Sep 17 00:00:00 2001 From: lotodore Date: Tue, 22 Feb 2011 21:53:56 +0000 Subject: [PATCH] Preparing integration of SCTP support (again). Note that server error messages are currently broken. --- src/net/common/receivebuffer.cpp | 1 - src/net/common/sendbuffer.cpp | 1 - src/net/common/serveraccepthelper.cpp | 101 +------------------- src/net/common/servermanager.cpp | 20 ++-- src/net/serveraccepthelper.h | 128 +++++++++++++++++++++++--- src/net/serveradminbot.h | 1 - src/net/serverlobbybot.h | 1 - src/net/servermanager.h | 4 +- 8 files changed, 127 insertions(+), 130 deletions(-) diff --git a/src/net/common/receivebuffer.cpp b/src/net/common/receivebuffer.cpp index 884f2dac..34c499ac 100644 --- a/src/net/common/receivebuffer.cpp +++ b/src/net/common/receivebuffer.cpp @@ -27,7 +27,6 @@ #include using namespace std; -using boost::asio::ip::tcp; ReceiveBuffer::ReceiveBuffer() diff --git a/src/net/common/sendbuffer.cpp b/src/net/common/sendbuffer.cpp index c78bbe82..d331223f 100644 --- a/src/net/common/sendbuffer.cpp +++ b/src/net/common/sendbuffer.cpp @@ -24,7 +24,6 @@ #include using namespace std; -using boost::asio::ip::tcp; SendBuffer::SendBuffer() diff --git a/src/net/common/serveraccepthelper.cpp b/src/net/common/serveraccepthelper.cpp index 2f484eb0..881b716a 100644 --- a/src/net/common/serveraccepthelper.cpp +++ b/src/net/common/serveraccepthelper.cpp @@ -18,109 +18,10 @@ ***************************************************************************/ #include -#include -#include -#include -#include -using namespace std; -using boost::asio::ip::tcp; - -ServerAcceptHelper::ServerAcceptHelper(ServerCallback &serverCallback, boost::shared_ptr ioService) - : m_ioService(ioService), m_serverCallback(serverCallback) -{ - m_acceptor.reset(new tcp::acceptor(*m_ioService)); -} - -ServerAcceptHelper::~ServerAcceptHelper() +ServerAcceptInterface::~ServerAcceptInterface() { } -void -ServerAcceptHelper::Listen(unsigned serverPort, bool ipv6, bool sctp, const string &/*logDir*/, boost::shared_ptr lobbyThread) -{ - m_lobbyThread = lobbyThread; - - try { - InternalListen(serverPort, ipv6, sctp); - } catch (const PokerTHException &e) { - LOG_ERROR(e.what()); - GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); - } catch (...) { - // This is probably an asio exception. Assume that bind failed, - // which is the most frequent case. - LOG_ERROR("Cannot bind/listen on TCP port."); - GetCallback().SignalNetServerError(ERR_SOCK_BIND_FAILED, 0); - } -} - -void -ServerAcceptHelper::InternalListen(unsigned serverPort, bool ipv6, bool /*sctp*/) -{ - if (serverPort < 1024) - throw ServerException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); - - // TODO consider sctp - // Prepare Listen. - if (ipv6) - m_endpoint.reset(new tcp::endpoint(tcp::v6(), serverPort)); - else - m_endpoint.reset(new tcp::endpoint(tcp::v4(), serverPort)); - - m_acceptor->open(m_endpoint->protocol()); - // TODO cannot set non blocking I/O with asio. - //boost::asio::socket_base::non_blocking_io command(true); - //m_acceptor->io_control(command); - m_acceptor->set_option(tcp::acceptor::reuse_address(true)); - if (ipv6) // In IPv6 mode: Be compatible with IPv4. - m_acceptor->set_option(boost::asio::ip::v6_only(false)); - m_acceptor->bind(*m_endpoint); - m_acceptor->listen(); - - // Start first asynchronous Accept. - boost::shared_ptr newSocket(new tcp::socket(*m_ioService)); - m_acceptor->async_accept( - *newSocket, - boost::bind(&ServerAcceptHelper::HandleAccept, this, newSocket, - boost::asio::placeholders::error) - ); -} - -void -ServerAcceptHelper::HandleAccept(boost::shared_ptr acceptedSocket, - const boost::system::error_code &error) -{ - if (!error) { - boost::asio::socket_base::non_blocking_io command(true); - acceptedSocket->io_control(command); - acceptedSocket->set_option(tcp::no_delay(true)); - acceptedSocket->set_option(boost::asio::socket_base::keep_alive(true)); - GetLobbyThread().AddConnection(acceptedSocket); - - boost::shared_ptr newSocket(new tcp::socket(*m_ioService)); - m_acceptor->async_accept( - *newSocket, - boost::bind(&ServerAcceptHelper::HandleAccept, this, newSocket, - boost::asio::placeholders::error) - ); - } else { - // Accept failed. This is a fatal error. - LOG_ERROR("In boost::asio handler: Accept failed."); - GetCallback().SignalNetServerError(ERR_SOCK_ACCEPT_FAILED, 0); - } -} - -ServerCallback & -ServerAcceptHelper::GetCallback() -{ - return m_serverCallback; -} - -ServerLobbyThread & -ServerAcceptHelper::GetLobbyThread() -{ - assert(m_lobbyThread.get()); - return *m_lobbyThread; -} diff --git a/src/net/common/servermanager.cpp b/src/net/common/servermanager.cpp index 0e404f99..c0134ac0 100644 --- a/src/net/common/servermanager.cpp +++ b/src/net/common/servermanager.cpp @@ -17,8 +17,9 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include +#include #include +#include #include #include #include @@ -53,17 +54,16 @@ ServerManager::Init(unsigned serverPort, bool ipv6, ServerTransportProtocol prot m_lobbyBot->Init(m_lobbyThread, ircLobbyThread); if (proto & TRANSPORT_PROTOCOL_TCP) { - boost::shared_ptr tcpAcceptHelper(new ServerAcceptHelper(GetGui(), m_ioService)); - tcpAcceptHelper->Listen(serverPort, ipv6, false, logDir, m_lobbyThread); + boost::shared_ptr tcpAcceptHelper(new ServerAcceptHelper(GetGui(), m_ioService)); + tcpAcceptHelper->Listen(serverPort, ipv6, logDir, m_lobbyThread); m_acceptHelperPool.push_back(tcpAcceptHelper); } - // TODO: Re-add SCTP support once asio supports SCTP. - /* if (mode & TRANSPORT_PROTOCOL_SCTP) - { - boost::shared_ptr sctpAcceptHelper(new ServerAcceptHelper(GetGui(), m_ioService)); - sctpAcceptHelper->Listen(serverPort, ipv6, true, logDir, m_lobbyThread); - m_acceptHelperPool.push_back(sctpAcceptHelper); - }*/ +/* if (proto & TRANSPORT_PROTOCOL_SCTP) + { + boost::shared_ptr sctpAcceptHelper(new ServerAcceptHelper(GetGui(), m_ioService)); + sctpAcceptHelper->Listen(serverPort, ipv6, logDir, m_lobbyThread); + m_acceptHelperPool.push_back(sctpAcceptHelper); + }*/ } GuiInterface & diff --git a/src/net/serveraccepthelper.h b/src/net/serveraccepthelper.h index 9c561dd1..d63c19c3 100644 --- a/src/net/serveraccepthelper.h +++ b/src/net/serveraccepthelper.h @@ -24,35 +24,135 @@ #include #include +#include +#include +#include +#include #include #include -class ServerLobbyThread; - -class ServerAcceptHelper +class ServerAcceptInterface { public: - ServerAcceptHelper(ServerCallback &serverCallback, boost::shared_ptr ioService); - virtual ~ServerAcceptHelper(); + virtual ~ServerAcceptInterface(); + + virtual void Listen(unsigned serverPort, bool ipv6, const std::string &logDir, + boost::shared_ptr lobbyThread) = 0; + + virtual void Close() = 0; +}; + +template +class ServerAcceptHelper : public ServerAcceptInterface +{ +public: + typedef typename P::acceptor P_acceptor; + typedef typename P::endpoint P_endpoint; + + ServerAcceptHelper(ServerCallback &serverCallback, boost::shared_ptr ioService) + : m_ioService(ioService), m_serverCallback(serverCallback) + { + m_acceptor.reset(new P_acceptor(*m_ioService)); + } + + virtual ~ServerAcceptHelper() + { + } // Set the parameters. - void Listen(unsigned serverPort, bool ipv6, bool sctp, const std::string &logDir, - boost::shared_ptr lobbyThread); + virtual void Listen(unsigned serverPort, bool ipv6, const std::string &/*logDir*/, + boost::shared_ptr lobbyThread) + { + m_lobbyThread = lobbyThread; + try { + InternalListen(serverPort, ipv6); + } catch (const PokerTHException &e) { + LOG_ERROR(e.what()); + GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); + } catch (...) { + // This is probably an asio exception. Assume that bind failed, + // which is the most frequent case. + LOG_ERROR("Cannot bind/listen on port."); + GetCallback().SignalNetServerError(ERR_SOCK_BIND_FAILED, 0); + } + } + + virtual void Close() + { + boost::system::error_code ec; + m_acceptor->close(ec); + // Ignore any error, because we are terminating. + } protected: - void InternalListen(unsigned serverPort, bool ipv6, bool sctp); - void HandleAccept(boost::shared_ptr acceptedSocket, - const boost::system::error_code &error); + void InternalListen(unsigned serverPort, bool ipv6) + { + if (serverPort < 1024) + throw ServerException(__FILE__, __LINE__, ERR_SOCK_INVALID_PORT, 0); - ServerCallback &GetCallback(); + // TODO consider sctp + // Prepare Listen. + if (ipv6) { + m_endpoint.reset(new P_endpoint(P::v6(), serverPort)); + } else { + m_endpoint.reset(new P_endpoint(P::v4(), serverPort)); + } - ServerLobbyThread &GetLobbyThread(); + m_acceptor->open(m_endpoint->protocol()); + m_acceptor->set_option(typename P::acceptor::reuse_address(true)); + if (ipv6) { // In IPv6 mode: Be compatible with IPv4. + m_acceptor->set_option(boost::asio::ip::v6_only(false)); + } + m_acceptor->bind(*m_endpoint); + m_acceptor->listen(); + + // Start first asynchronous Accept. + boost::shared_ptr newSocket(new typename P::socket(*m_ioService)); + m_acceptor->async_accept( + *newSocket, + boost::bind(&ServerAcceptHelper::HandleAccept, this, newSocket, + boost::asio::placeholders::error) + ); + } + + void HandleAccept(boost::shared_ptr acceptedSocket, + const boost::system::error_code &error) + { + if (!error) { + boost::asio::socket_base::non_blocking_io command(true); + acceptedSocket->io_control(command); + acceptedSocket->set_option(typename P::no_delay(true)); + acceptedSocket->set_option(boost::asio::socket_base::keep_alive(true)); + GetLobbyThread().AddConnection(acceptedSocket); + + boost::shared_ptr newSocket(new typename P::socket(*m_ioService)); + m_acceptor->async_accept( + *newSocket, + boost::bind(&ServerAcceptHelper::HandleAccept, this, newSocket, + boost::asio::placeholders::error) + ); + } else { + // Accept failed. This is a fatal error. + LOG_ERROR("In boost::asio handler: Accept failed."); + GetCallback().SignalNetServerError(ERR_SOCK_ACCEPT_FAILED, 0); + } + } + + ServerCallback &GetCallback() + { + return m_serverCallback; + } + + ServerLobbyThread &GetLobbyThread() + { + return *m_lobbyThread; + } private: boost::shared_ptr m_ioService; - boost::shared_ptr m_acceptor; - boost::shared_ptr m_endpoint; + boost::shared_ptr m_acceptor; + boost::shared_ptr m_endpoint; ServerCallback &m_serverCallback; boost::shared_ptr m_lobbyThread; diff --git a/src/net/serveradminbot.h b/src/net/serveradminbot.h index 40436694..c8c86fb7 100644 --- a/src/net/serveradminbot.h +++ b/src/net/serveradminbot.h @@ -32,7 +32,6 @@ #include class ServerLobbyThread; -class ServerAcceptHelper; class SenderThread; class ConfigFile; class AvatarManager; diff --git a/src/net/serverlobbybot.h b/src/net/serverlobbybot.h index e418b4a9..8f14560e 100644 --- a/src/net/serverlobbybot.h +++ b/src/net/serverlobbybot.h @@ -31,7 +31,6 @@ #include class ServerLobbyThread; -class ServerAcceptHelper; class SenderThread; class ConfigFile; class AvatarManager; diff --git a/src/net/servermanager.h b/src/net/servermanager.h index 8fca6dac..8de8f36c 100644 --- a/src/net/servermanager.h +++ b/src/net/servermanager.h @@ -32,7 +32,7 @@ class ServerLobbyThread; class IrcThread; -class ServerAcceptHelper; +class ServerAcceptInterface; class SenderThread; class ConfigFile; class AvatarManager; @@ -60,7 +60,7 @@ public: ServerLobbyBot &GetLobbyBot(); protected: - typedef std::list > AcceptHelperList; + typedef std::list > AcceptHelperList; ServerLobbyThread &GetLobbyThread();