Rewriting network receive functions. This is still work in progress to make it more efficient.
This commit is contained in:
+2
-3
@@ -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
|
||||
|
||||
+6
-10
@@ -27,6 +27,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <core/thread.h>
|
||||
#include <net/sessiondatacallback.h>
|
||||
#include <guiinterface.h>
|
||||
#include <serverdata.h>
|
||||
#include <playerdata.h>
|
||||
@@ -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<ClientThread>
|
||||
class ClientThread : public Thread, public boost::enable_shared_from_this<ClientThread>, 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<SessionData> /*session*/) {
|
||||
// TODO
|
||||
}
|
||||
virtual void HandlePacket(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> 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<Game> GetGame();
|
||||
|
||||
ClientSenderCallback &GetSenderCallback();
|
||||
|
||||
QtToolsInterface &GetQtToolsInterface();
|
||||
|
||||
void AddPlayerData(boost::shared_ptr<PlayerData> playerData);
|
||||
@@ -213,7 +212,6 @@ protected:
|
||||
private:
|
||||
|
||||
boost::shared_ptr<boost::asio::io_service> m_ioService;
|
||||
boost::shared_ptr<ClientSenderCallback> m_senderCallback;
|
||||
boost::shared_ptr<Log> m_clientLog;
|
||||
|
||||
Gsasl *m_authContext;
|
||||
@@ -226,7 +224,6 @@ private:
|
||||
AvatarManager &m_avatarManager;
|
||||
|
||||
boost::shared_ptr<SenderHelper> m_senderHelper;
|
||||
boost::shared_ptr<ReceiverHelper> m_receiver;
|
||||
|
||||
boost::shared_ptr<DownloaderThread> m_avatarDownloader;
|
||||
|
||||
@@ -298,7 +295,6 @@ private:
|
||||
friend class ClientStateWaitHand;
|
||||
friend class ClientStateRunHand;
|
||||
friend class ClientStateFinal;
|
||||
friend class ClientSenderCallback;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include <net/clientthread.h>
|
||||
#include <net/clientcontext.h>
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/receiverhelper.h>
|
||||
#include <net/netpacket.h>
|
||||
#include <net/resolverthread.h>
|
||||
#include <net/clientexception.h>
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <net/clientstate.h>
|
||||
#include <net/clientcontext.h>
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/receiverhelper.h>
|
||||
#include <net/downloaderthread.h>
|
||||
#include <net/clientexception.h>
|
||||
#include <net/socket_msg.h>
|
||||
@@ -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<SessionData> /*session*/, boost::shared_ptr<NetPacket> packet)
|
||||
{
|
||||
if (!ec) {
|
||||
ReceiveBuffer &buf = GetContext().GetSessionData()->GetReceiveBuffer();
|
||||
buf.recvBufUsed += bytesRead;
|
||||
GetReceiver().ScanPackets(buf);
|
||||
|
||||
while (!buf.receivedPackets.empty()) {
|
||||
boost::shared_ptr<NetPacket> 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<SessionData>(new SessionData(
|
||||
newSock,
|
||||
SESSION_ID_GENERIC,
|
||||
*m_senderCallback)));
|
||||
*this)));
|
||||
GetContext().SetResolver(boost::shared_ptr<boost::asio::ip::tcp::resolver>(
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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 <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <net/receivebuffer.h>
|
||||
#include <net/sessiondata.h>
|
||||
#include <core/loghelper.h>
|
||||
#include <core/pokerthexception.h>
|
||||
#include <boost/swap.hpp>
|
||||
|
||||
using namespace std;
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
|
||||
ReceiveBuffer::ReceiveBuffer()
|
||||
: recvBufUsed(0)
|
||||
{
|
||||
recvBuf[0] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ReceiveBuffer::StartAsyncRead(boost::shared_ptr<SessionData> 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<SessionData> 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<NetPacket> 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<SessionData> session)
|
||||
{
|
||||
while (!receivedPackets.empty()) {
|
||||
boost::shared_ptr<NetPacket> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <net/receiverhelper.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <net/netexception.h>
|
||||
#include <core/loghelper.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
ReceiverHelper::ReceiverHelper()
|
||||
{
|
||||
}
|
||||
|
||||
ReceiverHelper::~ReceiverHelper()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ReceiverHelper::ScanPackets(ReceiveBuffer &buf)
|
||||
{
|
||||
bool dataAvailable = true;
|
||||
do {
|
||||
boost::shared_ptr<NetPacket> 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);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/sessiondata.h>
|
||||
#include <net/sendbuffer.h>
|
||||
#include <net/sendercallback.h>
|
||||
#include <net/socket_helper.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <core/loghelper.h>
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
SenderHelper::SenderHelper(SenderCallback &cb, boost::shared_ptr<boost::asio::io_service> ioService)
|
||||
: m_callback(cb), m_ioService(ioService)
|
||||
SenderHelper::SenderHelper(boost::shared_ptr<boost::asio::io_service> ioService)
|
||||
: m_ioService(ioService)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <net/serverlobbythread.h>
|
||||
#include <net/serverexception.h>
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/receiverhelper.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <core/loghelper.h>
|
||||
#include <db/serverdbinterface.h>
|
||||
@@ -57,8 +56,6 @@ ServerGame::ServerGame(boost::shared_ptr<ServerLobbyThread> 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
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <net/servergamestate.h>
|
||||
#include <net/servergame.h>
|
||||
#include <net/serverlobbythread.h>
|
||||
#include <net/receiverhelper.h>
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/netpacket.h>
|
||||
#include <net/socket_msg.h>
|
||||
|
||||
@@ -21,10 +21,9 @@
|
||||
#include <net/servergame.h>
|
||||
#include <net/serverbanmanager.h>
|
||||
#include <net/serverexception.h>
|
||||
#include <net/receivebuffer.h>
|
||||
#include <net/senderhelper.h>
|
||||
#include <net/sendercallback.h>
|
||||
#include <net/serverircbotcallback.h>
|
||||
#include <net/receiverhelper.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <net/chatcleanermanager.h>
|
||||
#include <net/net_helper.h>
|
||||
@@ -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<SessionData> session) {
|
||||
m_server.CloseSession(session->GetId());
|
||||
}
|
||||
virtual void SignalSessionTerminated(unsigned /*session*/) {
|
||||
|
||||
virtual void HandlePacket(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> 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<tcp::socket> 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<SessionData> s, boost::shared_ptr<NetPacket> 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<NetPacket> packet = buf.receivedPackets.front();
|
||||
buf.receivedPackets.pop_front();
|
||||
// Retrieve current game, if applicable.
|
||||
boost::shared_ptr<ServerGame> 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<ServerGame> 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<ServerGame> 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()
|
||||
{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <net/sessiondata.h>
|
||||
#include <net/receivebuffer.h>
|
||||
#include <net/sendbuffer.h>
|
||||
#include <gsasl.h>
|
||||
|
||||
@@ -30,12 +31,12 @@ SessionData::SessionData(boost::shared_ptr<boost::asio::ip::tcp::socket> 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();
|
||||
}
|
||||
|
||||
|
||||
+19
-5
@@ -21,15 +21,29 @@
|
||||
#ifndef _RECEIVEBUFFER_H_
|
||||
#define _RECEIVEBUFFER_H_
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <net/netpacket.h>
|
||||
|
||||
// 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<ReceiveBuffer>
|
||||
{
|
||||
public:
|
||||
ReceiveBuffer();
|
||||
|
||||
void StartAsyncRead(boost::shared_ptr<SessionData> session);
|
||||
|
||||
protected:
|
||||
void HandleRead(boost::shared_ptr<SessionData> session, const boost::system::error_code &error, size_t bytesRead);
|
||||
|
||||
void ScanPackets();
|
||||
void ProcessPackets(boost::shared_ptr<SessionData> session);
|
||||
|
||||
|
||||
private:
|
||||
NetPacketList receivedPackets;
|
||||
char recvBuf[RECV_BUF_SIZE];
|
||||
unsigned recvBufUsed;
|
||||
|
||||
@@ -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 <net/netpacket.h>
|
||||
#include <net/receivebuffer.h>
|
||||
|
||||
|
||||
class ReceiverHelper
|
||||
{
|
||||
public:
|
||||
ReceiverHelper();
|
||||
virtual ~ReceiverHelper();
|
||||
|
||||
void ScanPackets(ReceiveBuffer &buf);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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 <boost/asio.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#ifndef _SENDERHELPER_H_
|
||||
#define _SENDERHELPER_H_
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <net/netpacket.h>
|
||||
#include <net/sendercallback.h>
|
||||
|
||||
class SessionData;
|
||||
class SendBuffer;
|
||||
@@ -30,7 +30,7 @@ class SendBuffer;
|
||||
class SenderHelper
|
||||
{
|
||||
public:
|
||||
SenderHelper(SenderCallback &cb, boost::shared_ptr<boost::asio::io_service> ioService);
|
||||
SenderHelper(boost::shared_ptr<boost::asio::io_service> ioService);
|
||||
~SenderHelper();
|
||||
|
||||
void Send(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet);
|
||||
@@ -41,7 +41,6 @@ protected:
|
||||
|
||||
private:
|
||||
|
||||
SenderCallback &m_callback;
|
||||
boost::shared_ptr<boost::asio::io_service> m_ioService;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <gamedata.h>
|
||||
|
||||
|
||||
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<VoteKickData> m_voteKickData;
|
||||
|
||||
boost::shared_ptr<ServerLobbyThread> m_lobbyThread;
|
||||
boost::shared_ptr<ReceiverHelper> m_receiver;
|
||||
boost::shared_ptr<ServerDBInterface> m_database;
|
||||
GuiInterface &m_gui;
|
||||
|
||||
|
||||
@@ -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<SessionData> session, boost::shared_ptr<NetPacket> 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<NetPacket> 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<SessionData> s, int errorCode);
|
||||
void SendJoinGameFailed(boost::shared_ptr<SessionData> 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<InternalServerCallback> m_internalServerCallback;
|
||||
boost::shared_ptr<SenderHelper> m_sender;
|
||||
boost::shared_ptr<ReceiverHelper> m_receiver;
|
||||
|
||||
SessionManager m_sessionManager;
|
||||
SessionManager m_gameSessionManager;
|
||||
|
||||
+10
-5
@@ -25,11 +25,11 @@ typedef unsigned SessionId;
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <third_party/boost/timers.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <net/socket_helper.h>
|
||||
#include <net/receivebuffer.h>
|
||||
#include <net/sessiondatacallback.h>
|
||||
|
||||
#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<SessionData>
|
||||
{
|
||||
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<NetPacket> 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<SendBuffer> m_sendBuffer;
|
||||
boost::shared_ptr<ReceiveBuffer> m_receiveBuffer;
|
||||
boost::shared_ptr<SendBuffer> m_sendBuffer;
|
||||
bool m_readyFlag;
|
||||
bool m_wantsLobbyMsg;
|
||||
boost::timers::portable::microsec_timer m_activityTimer;
|
||||
|
||||
@@ -21,12 +21,19 @@
|
||||
#ifndef _SESSIONDATACALLBACK_H_
|
||||
#define _SESSIONDATACALLBACK_H_
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
class NetPacket;
|
||||
class SessionData;
|
||||
|
||||
class SessionDataCallback
|
||||
{
|
||||
public:
|
||||
virtual ~SessionDataCallback();
|
||||
|
||||
virtual void SignalSessionTerminated(unsigned session) = 0;
|
||||
virtual void CloseSession(boost::shared_ptr<SessionData> session) = 0;
|
||||
virtual void HandlePacket(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <net/sessiondata.h>
|
||||
#include <playerdata.h>
|
||||
#include <gamedata.h>
|
||||
#include <core/thread.h>
|
||||
|
||||
class NetPacket;
|
||||
|
||||
Reference in New Issue
Block a user