From 5730cd321d44d3fd91d3729a0b7a460668434689 Mon Sep 17 00:00:00 2001 From: lotodore Date: Sat, 19 Feb 2011 23:47:24 +0000 Subject: [PATCH] Rewriting network receive functions. This is still work in progress to make it more efficient. --- pokerth_lib.pro | 5 +- src/net/clientthread.h | 16 ++- src/net/common/clientstate.cpp | 1 - src/net/common/clientthread.cpp | 58 +---------- src/net/common/receivebuffer.cpp | 126 ++++++++++++++++++++++++ src/net/common/receiverhelper.cpp | 70 -------------- src/net/common/senderhelper.cpp | 6 +- src/net/common/servergame.cpp | 10 -- src/net/common/servergamestate.cpp | 1 - src/net/common/serverlobbythread.cpp | 140 ++++++++------------------- src/net/common/sessiondata.cpp | 3 +- src/net/receivebuffer.h | 24 ++++- src/net/receiverhelper.h | 38 -------- src/net/sendbuffer.h | 6 +- src/net/senderhelper.h | 5 +- src/net/servergame.h | 4 - src/net/serverlobbythread.h | 7 +- src/net/sessiondata.h | 15 ++- src/net/sessiondatacallback.h | 9 +- src/net/sessionmanager.h | 1 + 20 files changed, 232 insertions(+), 313 deletions(-) create mode 100644 src/net/common/receivebuffer.cpp delete mode 100644 src/net/common/receiverhelper.cpp delete mode 100644 src/net/receiverhelper.h diff --git a/pokerth_lib.pro b/pokerth_lib.pro index 9c4c2671..b43da587 100644 --- a/pokerth_lib.pro +++ b/pokerth_lib.pro @@ -96,7 +96,6 @@ HEADERS += \ src/net/irccallback.h \ src/net/ircthread.h \ src/net/netexception.h \ - src/net/receiverhelper.h \ src/net/servermanager.h \ src/net/transferdata.h \ src/net/transferhelper.h \ @@ -201,7 +200,6 @@ SOURCES += \ src/net/common/clientexception.cpp \ src/net/common/netcontext.cpp \ src/net/common/netexception.cpp \ - src/net/common/receiverhelper.cpp \ src/net/common/irccallback.cpp \ src/net/common/ircthread.cpp \ src/net/common/servermanager.cpp \ @@ -211,7 +209,8 @@ SOURCES += \ src/net/common/internalchatcleanerpacket.cpp \ src/gui/generic/serverguiwrapper.cpp \ src/gui/qttoolsinterface.cpp \ - src/net/common/sendbuffer.cpp + src/net/common/sendbuffer.cpp \ + src/net/common/receivebuffer.cpp official_server{ INCLUDEPATH += pkth_stat/daemon_lib/src diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 4e163b57..71dc7845 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -35,9 +36,7 @@ class ClientContext; class ClientState; class SenderHelper; -class ReceiverHelper; class DownloaderThread; -class ClientSenderCallback; class Game; class NetPacket; class AvatarManager; @@ -45,7 +44,7 @@ class Log; class QtToolsInterface; struct Gsasl; -class ClientThread : public Thread, public boost::enable_shared_from_this +class ClientThread : public Thread, public boost::enable_shared_from_this, public SessionDataCallback { public: ClientThread(GuiInterface &gui, AvatarManager &avatarManager); @@ -86,7 +85,10 @@ public: void SendReportAvatar(unsigned reportedPlayerId, const std::string &avatarHash); void StartAsyncRead(); - void HandleRead(const boost::system::error_code& ec, size_t bytesRead); + virtual void CloseSession(boost::shared_ptr /*session*/) { + // TODO + } + virtual void HandlePacket(boost::shared_ptr session, boost::shared_ptr packet); void SelectServer(unsigned serverId); void SetLogin(const std::string &userName, const std::string &password, bool isGuest); @@ -158,7 +160,6 @@ protected: boost::asio::deadline_timer &GetStateTimer(); SenderHelper &GetSender(); - ReceiverHelper &GetReceiver(); void SetGameId(unsigned id); const GameData &GetGameData() const; @@ -169,8 +170,6 @@ protected: boost::shared_ptr GetGame(); - ClientSenderCallback &GetSenderCallback(); - QtToolsInterface &GetQtToolsInterface(); void AddPlayerData(boost::shared_ptr playerData); @@ -213,7 +212,6 @@ protected: private: boost::shared_ptr m_ioService; - boost::shared_ptr m_senderCallback; boost::shared_ptr m_clientLog; Gsasl *m_authContext; @@ -226,7 +224,6 @@ private: AvatarManager &m_avatarManager; boost::shared_ptr m_senderHelper; - boost::shared_ptr m_receiver; boost::shared_ptr m_avatarDownloader; @@ -298,7 +295,6 @@ private: friend class ClientStateWaitHand; friend class ClientStateRunHand; friend class ClientStateFinal; - friend class ClientSenderCallback; }; #endif diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 71d1c2bc..989bd2df 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index bd5cda80..79f8a6fb 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -48,22 +47,6 @@ using namespace std; using boost::asio::ip::tcp; - -class ClientSenderCallback : public SenderCallback, public SessionDataCallback -{ -public: - ClientSenderCallback() {} - virtual ~ClientSenderCallback() {} - - virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/) { - } - - virtual void SignalSessionTerminated(unsigned /*session*/) { - } - -private: -}; - ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager) : m_ioService(new boost::asio::io_service), m_curState(NULL), m_gui(gui), m_avatarManager(avatarManager), m_isServerSelected(false), @@ -72,10 +55,8 @@ ClientThread::ClientThread(GuiInterface &gui, AvatarManager &avatarManager) { m_clientLog.reset(new Log("", 0)); m_context.reset(new ClientContext); - m_receiver.reset(new ReceiverHelper); myQtToolsInterface.reset(CreateQtToolsWrapper()); - m_senderCallback.reset(new ClientSenderCallback()); - m_senderHelper.reset(new SenderHelper(*m_senderCallback, m_ioService)); + m_senderHelper.reset(new SenderHelper(m_ioService)); } ClientThread::~ClientThread() @@ -381,35 +362,13 @@ ClientThread::SendReportAvatar(unsigned reportedPlayerId, const std::string &ava void ClientThread::StartAsyncRead() { - ReceiveBuffer &buf = GetContext().GetSessionData()->GetReceiveBuffer(); - GetContext().GetSessionData()->GetAsioSocket()->async_read_some( - boost::asio::buffer(buf.recvBuf + buf.recvBufUsed, RECV_BUF_SIZE - buf.recvBufUsed), - boost::bind( - &ClientThread::HandleRead, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred)); + GetContext().GetSessionData()->GetReceiveBuffer().StartAsyncRead(GetContext().GetSessionData()); } void -ClientThread::HandleRead(const boost::system::error_code& ec, size_t bytesRead) +ClientThread::HandlePacket(boost::shared_ptr /*session*/, boost::shared_ptr packet) { - if (!ec) { - ReceiveBuffer &buf = GetContext().GetSessionData()->GetReceiveBuffer(); - buf.recvBufUsed += bytesRead; - GetReceiver().ScanPackets(buf); - - while (!buf.receivedPackets.empty()) { - boost::shared_ptr packet = buf.receivedPackets.front(); - buf.receivedPackets.pop_front(); - if (packet) - GetState().HandlePacket(shared_from_this(), packet); - } - StartAsyncRead(); - } else { - if (ec != boost::asio::error::operation_aborted) - throw NetException(__FILE__, __LINE__, ERR_SOCK_CONN_RESET, 0); - } + GetState().HandlePacket(shared_from_this(), packet); } void @@ -926,7 +885,7 @@ ClientThread::CreateContextSession() GetContext().SetSessionData(boost::shared_ptr(new SessionData( newSock, SESSION_ID_GENERIC, - *m_senderCallback))); + *this))); GetContext().SetResolver(boost::shared_ptr( new boost::asio::ip::tcp::resolver(*m_ioService))); validSocket = true; @@ -965,13 +924,6 @@ ClientThread::GetSender() return *m_senderHelper; } -ReceiverHelper & -ClientThread::GetReceiver() -{ - assert(m_receiver); - return *m_receiver; -} - unsigned ClientThread::GetGameId() const { diff --git a/src/net/common/receivebuffer.cpp b/src/net/common/receivebuffer.cpp new file mode 100644 index 00000000..884f2dac --- /dev/null +++ b/src/net/common/receivebuffer.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2011 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +using namespace std; +using boost::asio::ip::tcp; + + +ReceiveBuffer::ReceiveBuffer() + : recvBufUsed(0) +{ + recvBuf[0] = 0; +} + +void +ReceiveBuffer::StartAsyncRead(boost::shared_ptr session) +{ + session->GetAsioSocket()->async_read_some( + boost::asio::buffer(recvBuf + recvBufUsed, RECV_BUF_SIZE - recvBufUsed), + boost::bind( + &ReceiveBuffer::HandleRead, + shared_from_this(), + session, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); +} + +void +ReceiveBuffer::HandleRead(boost::shared_ptr session, const boost::system::error_code &error, size_t bytesRead) +{ + if (error != boost::asio::error::operation_aborted) { + try { + if (!error) { + recvBufUsed += bytesRead; + ScanPackets(); + ProcessPackets(session); + StartAsyncRead(session); + } else if (error == boost::asio::error::interrupted || error == boost::asio::error::try_again) { + LOG_ERROR("Session " << session->GetId() << " - recv interrupted: " << error); + StartAsyncRead(session); + } else { + LOG_ERROR("Session " << session->GetId() << " - Connection closed: " << error); + // On error: Close this session. + session->Close(); + } + } catch (const exception &e) { + LOG_ERROR("Session " << session->GetId() << " - unhandled exception in HandleRead: " << e.what()); + } + } +} + +void +ReceiveBuffer::ScanPackets() +{ + bool dataAvailable = true; + do { + boost::shared_ptr tmpPacket; + // This is necessary, because we use TCP. + // Packets may be received in multiple chunks or + // several packets may be received at once. + if (recvBufUsed) { + try { + // This call will also handle the memmove stuff, i.e. + // buffering for partial packets. + tmpPacket = NetPacket::Create(recvBuf, recvBufUsed); + } catch (const exception &e) { + // Reset buffer on error. + recvBufUsed = 0; + LOG_ERROR(e.what()); + } + } + if (tmpPacket) { + //cerr << "IN:" << endl << tmpPacket->ToString() << endl; + if (asn_check_constraints(&asn_DEF_PokerTHMessage, tmpPacket->GetMsg(), NULL, NULL) == 0) + receivedPackets.push_back(tmpPacket); + else + LOG_ERROR("Invalid packet: " << endl << tmpPacket->ToString()); + } else + dataAvailable = false; + } while(dataAvailable); +} + +void +ReceiveBuffer::ProcessPackets(boost::shared_ptr session) +{ + while (!receivedPackets.empty()) { + boost::shared_ptr p = receivedPackets.front(); + receivedPackets.pop_front(); + // We need to catch specific exceptions, so that they do not affect the server. + try { + session->HandlePacket(p); + } catch (const PokerTHException &e) { + LOG_ERROR("Session " << session->GetId() << " - Read handler exception: " << e.what()); + // TODO add error handling, close session. + } + } + if (recvBufUsed >= RECV_BUF_SIZE) { + LOG_ERROR("Session " << session->GetId() << " - Receive buf full: " << recvBufUsed); + recvBufUsed = 0; + } +} + diff --git a/src/net/common/receiverhelper.cpp b/src/net/common/receiverhelper.cpp deleted file mode 100644 index 962c0daa..00000000 --- a/src/net/common/receiverhelper.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifdef _WIN32 -#define FD_SETSIZE 512 -#endif - -#include -#include -#include -#include - -using namespace std; - - -ReceiverHelper::ReceiverHelper() -{ -} - -ReceiverHelper::~ReceiverHelper() -{ -} - -void -ReceiverHelper::ScanPackets(ReceiveBuffer &buf) -{ - bool dataAvailable = true; - do { - boost::shared_ptr tmpPacket; - // This is necessary, because we use TCP. - // Packets may be received in multiple chunks or - // several packets may be received at once. - if (buf.recvBufUsed) { - try { - // This call will also handle the memmove stuff, i.e. - // buffering for partial packets. - tmpPacket = NetPacket::Create(buf.recvBuf, buf.recvBufUsed); - } catch (const exception &e) { - // Reset buffer on error. - buf.recvBufUsed = 0; - LOG_ERROR(e.what()); - } - } - if (tmpPacket) { - //cerr << "IN:" << endl << tmpPacket->ToString() << endl; - if (asn_check_constraints(&asn_DEF_PokerTHMessage, tmpPacket->GetMsg(), NULL, NULL) == 0) - buf.receivedPackets.push_back(tmpPacket); - else - LOG_ERROR("Invalid packet: " << endl << tmpPacket->ToString()); - } else - dataAvailable = false; - } while(dataAvailable); -} - diff --git a/src/net/common/senderhelper.cpp b/src/net/common/senderhelper.cpp index fa24fec2..2f01a25a 100644 --- a/src/net/common/senderhelper.cpp +++ b/src/net/common/senderhelper.cpp @@ -18,8 +18,8 @@ ***************************************************************************/ #include +#include #include -#include #include #include #include @@ -28,8 +28,8 @@ using namespace std; -SenderHelper::SenderHelper(SenderCallback &cb, boost::shared_ptr ioService) - : m_callback(cb), m_ioService(ioService) +SenderHelper::SenderHelper(boost::shared_ptr ioService) + : m_ioService(ioService) { } diff --git a/src/net/common/servergame.cpp b/src/net/common/servergame.cpp index e9547ee0..360c3c89 100644 --- a/src/net/common/servergame.cpp +++ b/src/net/common/servergame.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -57,8 +56,6 @@ ServerGame::ServerGame(boost::shared_ptr lobbyThread, u_int32 m_stateTimer1(lobbyThread->GetIOService()), m_stateTimer2(lobbyThread->GetIOService()) { LOG_VERBOSE("Game object " << GetId() << " created."); - - m_receiver.reset(new ReceiverHelper); } ServerGame::~ServerGame() @@ -918,13 +915,6 @@ ServerGame::GetStateTimer2() return m_stateTimer2; } -ReceiverHelper & -ServerGame::GetReceiver() -{ - assert(m_receiver.get()); - return *m_receiver; -} - unsigned ServerGame::GetSmallDelaySec() const { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index d405f7c4..ef052020 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 02d8748b..214e4a04 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -21,10 +21,9 @@ #include #include #include +#include #include -#include #include -#include #include #include #include @@ -83,18 +82,18 @@ using namespace std; using boost::asio::ip::tcp; -class InternalServerCallback : public SenderCallback, public SessionDataCallback, public ChatCleanerCallback, public ServerDBCallback +class InternalServerCallback : public SessionDataCallback, public ChatCleanerCallback, public ServerDBCallback { public: InternalServerCallback(ServerLobbyThread &server) : m_server(server) {} virtual ~InternalServerCallback() {} - virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/) { - // We just ignore send errors for now, on server side. - // A serious send error should trigger a read error or a read - // returning 0 afterwards, and we will handle this error. + virtual void CloseSession(boost::shared_ptr session) { + m_server.CloseSession(session->GetId()); } - virtual void SignalSessionTerminated(unsigned /*session*/) { + + virtual void HandlePacket(boost::shared_ptr session, boost::shared_ptr packet) { + m_server.DispatchPacket(session, packet); } virtual void SignalChatBotMessage(const string &msg) { @@ -181,8 +180,7 @@ ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ServerMode mode, ServerI m_startTime(boost::posix_time::second_clock::local_time()) { m_internalServerCallback.reset(new InternalServerCallback(*this)); - m_sender.reset(new SenderHelper(*m_internalServerCallback, m_ioService)); - m_receiver.reset(new ReceiverHelper); + m_sender.reset(new SenderHelper(m_ioService)); m_banManager.reset(new ServerBanManager(m_ioService)); m_chatCleanerManager.reset(new ChatCleanerManager(*m_internalServerCallback, m_ioService)); DBFactory dbFactory; @@ -276,15 +274,7 @@ ServerLobbyThread::AddConnection(boost::shared_ptr sock) netAnnounce->numPlayersOnServer = m_statData.numberOfPlayersOnServer; } GetSender().Send(sessionData, packet); - - sock->async_read_some( - boost::asio::buffer(sessionData->GetReceiveBuffer().recvBuf, RECV_BUF_SIZE), - boost::bind( - &ServerLobbyThread::HandleRead, - this, - boost::asio::placeholders::error, - sessionData->GetId(), - boost::asio::placeholders::bytes_transferred)); + sessionData->GetReceiveBuffer().StartAsyncRead(sessionData); } } if (!hasClientIp) { @@ -359,7 +349,22 @@ ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session) { // Just remove the session. Only for fatal errors. CloseSession(session); - session.sessionData->SetGameId(0); +} + +void +ServerLobbyThread::CloseSession(SessionId sessionId) +{ + SessionWrapper session = m_sessionManager.GetSessionById(sessionId); + if (!session.sessionData) + session = m_gameSessionManager.GetSessionById(sessionId); + if (session.sessionData) { + GameMap::iterator pos = m_gameMap.find(session.sessionData->GetGameId()); + if (pos != m_gameMap.end()) { + pos->second->ErrorRemoveSession(session); + } else { + CloseSession(session); + } + } } void @@ -376,6 +381,7 @@ ServerLobbyThread::CloseSession(SessionWrapper session) NotifyPlayerLeftLobby(session.playerData->GetUniqueId()); // Update stats (if needed). UpdateStatisticsNumberOfPlayers(); + session.sessionData->SetGameId(0); } } @@ -838,78 +844,25 @@ ServerLobbyThread::InitChatCleaner() } void -ServerLobbyThread::HandleRead(const boost::system::error_code &ec, SessionId sessionId, size_t bytesRead) +ServerLobbyThread::DispatchPacket(boost::shared_ptr s, boost::shared_ptr packet) { - if (ec != boost::asio::error::operation_aborted) { - try { - // Find the session. - SessionWrapper session = m_sessionManager.GetSessionById(sessionId); - if (!session.sessionData) - session = m_gameSessionManager.GetSessionById(sessionId); - if (session.sessionData) { - ReceiveBuffer &buf = session.sessionData->GetReceiveBuffer(); - if (!ec) { - if (buf.recvBufUsed + bytesRead > RECV_BUF_SIZE) - LOG_ERROR("Session " << session.sessionData->GetId() << " - Internal error: Receive buffer overflow!"); - buf.recvBufUsed += bytesRead; - GetReceiver().ScanPackets(buf); - bool errorFlag = false; - - while (!buf.receivedPackets.empty()) { - boost::shared_ptr packet = buf.receivedPackets.front(); - buf.receivedPackets.pop_front(); - // Retrieve current game, if applicable. - boost::shared_ptr game = InternalGetGameFromId(session.sessionData->GetGameId()); - if (game) { - // We need to catch game-specific exceptions, so that they do not affect the server. - try { - game->HandlePacket(session, packet); - } catch (const PokerTHException &e) { - LOG_ERROR("Game " << game->GetId() << " - Read handler exception: " << e.what()); - game->RemoveAllSessions(); - errorFlag = true; - break; - } - } else - HandlePacket(session, packet); - } - if (buf.recvBufUsed >= RECV_BUF_SIZE) { - LOG_ERROR("Session " << session.sessionData->GetId() << " - Full receive buf but no valid packet."); - buf.recvBufUsed = 0; - } - if (!errorFlag) { - session.sessionData->GetAsioSocket()->async_read_some( - boost::asio::buffer(buf.recvBuf + buf.recvBufUsed, RECV_BUF_SIZE - buf.recvBufUsed), - boost::bind( - &ServerLobbyThread::HandleRead, - this, - boost::asio::placeholders::error, - sessionId, - boost::asio::placeholders::bytes_transferred)); - } - } else if (ec == boost::asio::error::interrupted || ec == boost::asio::error::try_again) { - LOG_ERROR("Session " << sessionId << " - recv interrupted: " << ec); - session.sessionData->GetAsioSocket()->async_read_some( - boost::asio::buffer(buf.recvBuf + buf.recvBufUsed, RECV_BUF_SIZE - buf.recvBufUsed), - boost::bind( - &ServerLobbyThread::HandleRead, - this, - boost::asio::placeholders::error, - sessionId, - boost::asio::placeholders::bytes_transferred)); - } else { - LOG_ERROR("Session " << sessionId << " - Connection closed: " << ec); - // On error: Close this session. - boost::shared_ptr game = InternalGetGameFromId(session.sessionData->GetGameId()); - if (game) - game->ErrorRemoveSession(session); - else - CloseSession(session); - } + // Find the session. + SessionWrapper session = m_sessionManager.GetSessionById(s->GetId()); + if (!session.sessionData) + session = m_gameSessionManager.GetSessionById(s->GetId()); + if (session.sessionData) { + // Retrieve current game, if applicable. + boost::shared_ptr game = InternalGetGameFromId(session.sessionData->GetGameId()); + if (game) { + // We need to catch game-specific exceptions, so that they do not affect the server. + try { + game->HandlePacket(session, packet); + } catch (const PokerTHException &e) { + LOG_ERROR("Game " << game->GetId() << " - Read handler exception: " << e.what()); + game->RemoveAllSessions(); } - } catch (const exception &e) { - LOG_ERROR("Session " << sessionId << " - unhandled exception in HandleRead: " << e.what()); - } + } else + HandlePacket(session, packet); } } @@ -2106,13 +2059,6 @@ ServerLobbyThread::GetIrcBotCallback() return m_ircBotCb; } -ReceiverHelper & -ServerLobbyThread::GetReceiver() -{ - assert(m_receiver.get()); - return *m_receiver; -} - InternalServerCallback & ServerLobbyThread::GetSenderCallback() { diff --git a/src/net/common/sessiondata.cpp b/src/net/common/sessiondata.cpp index 57929088..feaeabd2 100644 --- a/src/net/common/sessiondata.cpp +++ b/src/net/common/sessiondata.cpp @@ -18,6 +18,7 @@ ***************************************************************************/ #include +#include #include #include @@ -30,12 +31,12 @@ SessionData::SessionData(boost::shared_ptr sock, S m_autoDisconnectTimer(boost::posix_time::time_duration(0, 0, 0), boost::timers::portable::microsec_timer::auto_start), m_callback(cb), m_authSession(NULL), m_curAuthStep(0) { + m_receiveBuffer.reset(new ReceiveBuffer); m_sendBuffer.reset(new SendBuffer); } SessionData::~SessionData() { - m_callback.SignalSessionTerminated(m_id); InternalClearAuthSession(); } diff --git a/src/net/receivebuffer.h b/src/net/receivebuffer.h index d954ada9..9bcaccb0 100644 --- a/src/net/receivebuffer.h +++ b/src/net/receivebuffer.h @@ -21,15 +21,29 @@ #ifndef _RECEIVEBUFFER_H_ #define _RECEIVEBUFFER_H_ +#include #include // MUST be larger than MAX_PACKET_SIZE -#define RECV_BUF_SIZE 2 * MAX_PACKET_SIZE +#define RECV_BUF_SIZE 5 * MAX_PACKET_SIZE -struct ReceiveBuffer { - ReceiveBuffer() : recvBufUsed(0) { - recvBuf[0] = 0; - } +class SessionData; + +class ReceiveBuffer : public boost::enable_shared_from_this +{ +public: + ReceiveBuffer(); + + void StartAsyncRead(boost::shared_ptr session); + +protected: + void HandleRead(boost::shared_ptr session, const boost::system::error_code &error, size_t bytesRead); + + void ScanPackets(); + void ProcessPackets(boost::shared_ptr session); + + +private: NetPacketList receivedPackets; char recvBuf[RECV_BUF_SIZE]; unsigned recvBufUsed; diff --git a/src/net/receiverhelper.h b/src/net/receiverhelper.h deleted file mode 100644 index 803771e5..00000000 --- a/src/net/receiverhelper.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* Network receiver helper class. NOTE: By design, this is not a thread. */ - -#ifndef _RECEIVERHELPER_H_ -#define _RECEIVERHELPER_H_ - -#include -#include - - -class ReceiverHelper -{ -public: - ReceiverHelper(); - virtual ~ReceiverHelper(); - - void ScanPackets(ReceiveBuffer &buf); -}; - -#endif - diff --git a/src/net/sendbuffer.h b/src/net/sendbuffer.h index 90fea047..75fed886 100644 --- a/src/net/sendbuffer.h +++ b/src/net/sendbuffer.h @@ -16,10 +16,10 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -/* Manager for sending network data. */ +/* Buffer for sending network data. */ -#ifndef _SENDDATAMANAGER_H_ -#define _SENDDATAMANAGER_H_ +#ifndef _SENDBUFFER_H_ +#define _SENDBUFFER_H_ #include #include diff --git a/src/net/senderhelper.h b/src/net/senderhelper.h index 97a49bb9..361d1e4a 100644 --- a/src/net/senderhelper.h +++ b/src/net/senderhelper.h @@ -21,8 +21,8 @@ #ifndef _SENDERHELPER_H_ #define _SENDERHELPER_H_ +#include #include -#include class SessionData; class SendBuffer; @@ -30,7 +30,7 @@ class SendBuffer; class SenderHelper { public: - SenderHelper(SenderCallback &cb, boost::shared_ptr ioService); + SenderHelper(boost::shared_ptr ioService); ~SenderHelper(); void Send(boost::shared_ptr session, boost::shared_ptr packet); @@ -41,7 +41,6 @@ protected: private: - SenderCallback &m_callback; boost::shared_ptr m_ioService; }; diff --git a/src/net/servergame.h b/src/net/servergame.h index 6903f36d..c7e4a55b 100644 --- a/src/net/servergame.h +++ b/src/net/servergame.h @@ -31,7 +31,6 @@ #include -class ReceiverHelper; class ServerLobbyThread; class ServerGameState; class ServerDBInterface; @@ -152,8 +151,6 @@ protected: boost::asio::deadline_timer &GetStateTimer1(); boost::asio::deadline_timer &GetStateTimer2(); - ReceiverHelper &GetReceiver(); - const StartData &GetStartData() const; void SetStartData(const StartData &startData); @@ -187,7 +184,6 @@ private: boost::shared_ptr m_voteKickData; boost::shared_ptr m_lobbyThread; - boost::shared_ptr m_receiver; boost::shared_ptr m_database; GuiInterface &m_gui; diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 3c68a270..30135e6b 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -38,7 +38,6 @@ class Log; class SenderHelper; -class ReceiverHelper; class InternalServerCallback; class ServerIrcBotCallback; class ServerGame; @@ -75,6 +74,7 @@ public: void NotifyStartingGame(unsigned gameId); void NotifyReopeningGame(unsigned gameId); + void DispatchPacket(boost::shared_ptr session, boost::shared_ptr packet); void HandleGameRetrievePlayerInfo(SessionWrapper session, const PlayerInfoRequestMessage_t &playerInfoRequest); void HandleGameRetrieveAvatar(SessionWrapper session, const AvatarRequestMessage_t &retrieveAvatar); void HandleChatRequest(SessionWrapper session, const ChatRequestMessage_t &chatRequest); @@ -131,7 +131,6 @@ protected: void ClearAuthContext(); void InitChatCleaner(); - void HandleRead(const boost::system::error_code &ec, SessionId sessionId, size_t bytesRead); void HandlePacket(SessionWrapper session, boost::shared_ptr packet); void HandleNetPacketInit(SessionWrapper session, const InitMessage_t &initMessage); void HandleNetPacketAuthClientResponse(SessionWrapper session, const AuthClientResponse_t &clientResponse); @@ -178,6 +177,7 @@ protected: void CleanupSessionMap(); + void CloseSession(SessionId sessionId); void CloseSession(SessionWrapper session); void SendError(boost::shared_ptr s, int errorCode); void SendJoinGameFailed(boost::shared_ptr s, unsigned gameId, int reason); @@ -189,8 +189,6 @@ protected: void ReadStatisticsFile(); void TimerSaveStatisticsFile(const boost::system::error_code &ec); - ReceiverHelper &GetReceiver(); - InternalServerCallback &GetSenderCallback(); GuiInterface &GetGui(); ServerIrcBotCallback &GetIrcBotCallback(); @@ -208,7 +206,6 @@ private: boost::shared_ptr m_internalServerCallback; boost::shared_ptr m_sender; - boost::shared_ptr m_receiver; SessionManager m_sessionManager; SessionManager m_gameSessionManager; diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index 2045a3fa..9799731b 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -25,11 +25,11 @@ typedef unsigned SessionId; #include #include +#include #include #include #include -#include #include #define INVALID_SESSION 0 @@ -38,9 +38,11 @@ typedef unsigned SessionId; struct Gsasl; struct Gsasl_session; +class ReceiveBuffer; class SendBuffer; +class NetPacket; -class SessionData +class SessionData : public boost::enable_shared_from_this { public: enum State { Init, ReceivingAvatar, Established, Game, Closed }; @@ -78,12 +80,15 @@ public: void SetClientAddr(const std::string &addr); ReceiveBuffer &GetReceiveBuffer() { - return m_receiveBuffer; + return *m_receiveBuffer; } SendBuffer &GetSendBuffer() { return *m_sendBuffer; } + void Close() {m_callback.CloseSession(shared_from_this());} + void HandlePacket(boost::shared_ptr packet) {m_callback.HandlePacket(shared_from_this(), packet);} + void ResetActivityTimer(); unsigned GetActivityTimerElapsedSec() const; bool HasActivityNoticeBeenSent() const; @@ -101,8 +106,8 @@ private: unsigned m_gameId; State m_state; std::string m_clientAddr; - ReceiveBuffer m_receiveBuffer; - boost::shared_ptr m_sendBuffer; + boost::shared_ptr m_receiveBuffer; + boost::shared_ptr m_sendBuffer; bool m_readyFlag; bool m_wantsLobbyMsg; boost::timers::portable::microsec_timer m_activityTimer; diff --git a/src/net/sessiondatacallback.h b/src/net/sessiondatacallback.h index 8f4429b3..52bda819 100644 --- a/src/net/sessiondatacallback.h +++ b/src/net/sessiondatacallback.h @@ -21,12 +21,19 @@ #ifndef _SESSIONDATACALLBACK_H_ #define _SESSIONDATACALLBACK_H_ +#include + + +class NetPacket; +class SessionData; + class SessionDataCallback { public: virtual ~SessionDataCallback(); - virtual void SignalSessionTerminated(unsigned session) = 0; + virtual void CloseSession(boost::shared_ptr session) = 0; + virtual void HandlePacket(boost::shared_ptr session, boost::shared_ptr packet) = 0; }; #endif diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 6fca94e3..d0a5ff60 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -26,6 +26,7 @@ #include #include +#include #include class NetPacket;