Players can now join and leave as they wish. Still TODO: Need to fix player number.

This commit is contained in:
lotodore
2007-05-06 23:27:08 +00:00
parent 87a1abfa42
commit a85ec4ee5a
16 changed files with 439 additions and 39 deletions
+4
View File
@@ -21,6 +21,8 @@
#ifndef _CLIENTCALLBACK_H_
#define _CLIENTCALLBACK_H_
#include <string>
struct GameData;
class ClientCallback
@@ -33,6 +35,8 @@ public:
virtual void SignalNetClientError(int errorID, int osErrorID) = 0;
virtual void SignalNetClientGameStart(const GameData &gameData) = 0;
virtual void SignalNetClientPlayerJoined(const std::string &playerName) = 0;
virtual void SignalNetClientPlayerLeft(const std::string &playerName) = 0;
};
#endif
+5
View File
@@ -22,6 +22,7 @@
#define _CLIENTTHREAD_H_
#include <core/thread.h>
#include <map>
#include <string>
#include <memory>
#include <net/clientcallback.h>
@@ -52,6 +53,7 @@ public:
ClientCallback &GetCallback();
protected:
typedef std::map<unsigned, std::string> PlayerMap;
// Main function of the thread.
virtual void Main();
@@ -70,6 +72,8 @@ protected:
ClientSenderCallback &GetSenderCallback();
PlayerMap &GetPlayerMap();
private:
std::auto_ptr<ClientContext> m_context;
@@ -81,6 +85,7 @@ private:
std::auto_ptr<ReceiverHelper> m_receiver;
std::auto_ptr<GameData> m_gameData;
PlayerMap m_playerMap;
friend class ClientStateInit;
friend class ClientStateStartResolve;
+26 -9
View File
@@ -330,7 +330,7 @@ ClientStateStartSession::Process(ClientThread &client)
boost::shared_ptr<NetPacket> packet(new NetPacketJoinGame);
((NetPacketJoinGame *)packet.get())->SetData(initData);
client.GetSender().Send(packet, context.GetSocket());
client.GetSender().Send(context.GetSocket(), packet);
client.SetState(ClientStateWaitSession::Instance());
@@ -374,6 +374,8 @@ ClientStateWaitSession::Process(ClientThread &client)
tmpPacket->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
client.SetGameData(joinGameAckData.gameData);
client.GetCallback().SignalNetClientPlayerJoined(context.GetPlayerName());
client.SetState(ClientStateWaitGame::Instance());
retVal = MSG_SOCK_SESSION_DONE;
}
@@ -410,22 +412,37 @@ ClientStateWaitGame::~ClientStateWaitGame()
int
ClientStateWaitGame::Process(ClientThread &client)
{
int retVal;
int retVal = MSG_SOCK_INTERNAL_PENDING;
ClientContext &context = client.GetContext();
// delegate to receiver helper class
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get() && tmpPacket->ToNetPacketGameStart())
if (tmpPacket.get())
{
client.SetState(ClientStateFinal::Instance());
retVal = MSG_NET_GAME_START;
}
else // TODO: handle error packet
{
retVal = MSG_SOCK_INTERNAL_PENDING;
if (tmpPacket->ToNetPacketGameStart())
{
client.SetState(ClientStateFinal::Instance());
retVal = MSG_NET_GAME_START;
}
else if (tmpPacket->ToNetPacketPlayerJoined())
{
NetPacketPlayerJoined::Data playerData;
tmpPacket->ToNetPacketPlayerJoined()->GetData(playerData);
client.GetCallback().SignalNetClientPlayerJoined(playerData.playerName);
client.GetPlayerMap()[playerData.playerId] = playerData.playerName;
}
else if (tmpPacket->ToNetPacketPlayerLeft())
{
// TODO hacked.
NetPacketPlayerLeft::Data playerData;
tmpPacket->ToNetPacketPlayerLeft()->GetData(playerData);
client.GetCallback().SignalNetClientPlayerLeft(client.GetPlayerMap()[playerData.playerId]);
client.GetPlayerMap().erase(playerData.playerId);
}
}
// TODO: handle error packet
return retVal;
}
+6
View File
@@ -180,3 +180,9 @@ ClientThread::GetSenderCallback()
return *m_senderCallback;
}
ClientThread::PlayerMap &
ClientThread::GetPlayerMap()
{
return m_playerMap;
}
+176
View File
@@ -158,6 +158,12 @@ NetPacket::Create(char *data, unsigned &dataSize)
case NET_TYPE_GAME_START:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
break;
case NET_TYPE_PLAYER_JOINED:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketPlayerJoined);
break;
case NET_TYPE_PLAYER_LEFT:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketPlayerLeft);
break;
case NET_TYPE_ERROR:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketError);
break;
@@ -260,6 +266,18 @@ NetPacket::ToNetPacketGameStart() const
return NULL;
}
const NetPacketPlayerJoined *
NetPacket::ToNetPacketPlayerJoined() const
{
return NULL;
}
const NetPacketPlayerLeft *
NetPacket::ToNetPacketPlayerLeft() const
{
return NULL;
}
const NetPacketError *
NetPacket::ToNetPacketError() const
{
@@ -553,6 +571,164 @@ NetPacketGameStart::Check(const NetPacketHeader* data) const
//-----------------------------------------------------------------------------
NetPacketPlayerJoined::NetPacketPlayerJoined()
: NetPacket(NET_TYPE_PLAYER_JOINED, sizeof(NetPacketPlayerJoinedData))
{
}
NetPacketPlayerJoined::~NetPacketPlayerJoined()
{
}
boost::shared_ptr<NetPacket>
NetPacketPlayerJoined::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketPlayerJoined);
try
{
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
}
return newPacket;
}
void
NetPacketPlayerJoined::SetData(const NetPacketPlayerJoined::Data &inData)
{
u_int16_t playerNameLen = (u_int16_t)inData.playerName.length();
if (!playerNameLen || playerNameLen > MAX_NAME_SIZE)
throw NetException(ERR_NET_INVALID_PLAYER_NAME, 0);
// Resize the packet so that the data fits in.
Resize((u_int16_t)
(sizeof(NetPacketPlayerJoinedData) + ADD_PADDING(playerNameLen)));
NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData();
assert(tmpData);
// Set the data.
tmpData->playerFlags = htons((inData.ptype == PLAYER_TYPE_HUMAN) ? NET_PLAYER_FLAG_HUMAN : 0);
tmpData->playerId = htons(inData.playerId);
tmpData->playerNumber = htons(inData.playerNumber);
tmpData->playerNameLength = htons(playerNameLen);
memcpy(tmpData->playerName, inData.playerName.c_str(), playerNameLen);
}
void
NetPacketPlayerJoined::GetData(NetPacketPlayerJoined::Data &outData) const
{
// We assume that the data is valid. Validity has already been checked.
NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)GetRawData();
assert(tmpData);
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
outData.playerId = ntohs(tmpData->playerId);
outData.playerNumber = ntohs(tmpData->playerNumber);
outData.playerName = string(tmpData->playerName, ntohs(tmpData->playerNameLength));
}
const NetPacketPlayerJoined *
NetPacketPlayerJoined::ToNetPacketPlayerJoined() const
{
return this;
}
void
NetPacketPlayerJoined::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketPlayerJoinedData))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
NetPacketPlayerJoinedData *tmpData = (NetPacketPlayerJoinedData *)data;
int playerNameLength = ntohs(tmpData->playerNameLength);
// Generous checking - larger packets are allowed.
if (dataLen <
sizeof(NetPacketPlayerJoinedData)
+ ADD_PADDING(playerNameLength))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
// Check string sizes.
if (!playerNameLength
|| playerNameLength > MAX_NAME_SIZE)
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
}
//-----------------------------------------------------------------------------
NetPacketPlayerLeft::NetPacketPlayerLeft()
: NetPacket(NET_TYPE_PLAYER_LEFT, sizeof(NetPacketPlayerLeftData))
{
}
NetPacketPlayerLeft::~NetPacketPlayerLeft()
{
}
boost::shared_ptr<NetPacket>
NetPacketPlayerLeft::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketPlayerLeft);
try
{
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
}
return newPacket;
}
void
NetPacketPlayerLeft::SetData(const NetPacketPlayerLeft::Data &inData)
{
NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData();
assert(tmpData);
// Set the data.
tmpData->playerId = htons(inData.playerId);
}
void
NetPacketPlayerLeft::GetData(NetPacketPlayerLeft::Data &outData) const
{
// We assume that the data is valid. Validity has already been checked.
NetPacketPlayerLeftData *tmpData = (NetPacketPlayerLeftData *)GetRawData();
assert(tmpData);
outData.playerId = ntohs(tmpData->playerId);
}
const NetPacketPlayerLeft *
NetPacketPlayerLeft::ToNetPacketPlayerLeft() const
{
return this;
}
void
NetPacketPlayerLeft::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketPlayerLeftData))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
}
//-----------------------------------------------------------------------------
NetPacketError::NetPacketError()
: NetPacket(NET_TYPE_ERROR, sizeof(NetPacketErrorData))
{
+1 -1
View File
@@ -35,7 +35,7 @@ SenderThread::~SenderThread()
}
void
SenderThread::Send(boost::shared_ptr<NetPacket> packet, SOCKET sock)
SenderThread::Send(SOCKET sock, boost::shared_ptr<NetPacket> packet)
{
if (packet.get() && IS_VALID_SOCKET(sock))
{
+44 -14
View File
@@ -27,8 +27,6 @@
#include <core/rand.h>
#include <gamedata.h>
#include <core/boost/timer.hpp>
using namespace std;
#define SERVER_WAIT_TIMEOUT_MSEC 50
@@ -82,12 +80,11 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
try
{
packet = server.GetReceiver().Recv(recvSock);
} catch (const NetException &e)
} catch (const NetException &)
{
if (session.get())
{
//server.CloseSessionDelayed(session);
Thread::Msleep(10);
server.CloseSessionDelayed(session);
return retVal;
}
}
@@ -99,6 +96,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (session->GetState() != SessionData::Init)
{
server.SessionError(session, ERR_SOCK_INVALID_STATE);
server.CloseSessionDelayed(session);
return retVal;
}
@@ -107,6 +105,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (!tmpPacket)
{
server.SessionError(session, ERR_SOCK_INVALID_PACKET);
server.CloseSessionDelayed(session);
return retVal;
}
@@ -117,6 +116,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
{
server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED);
server.CloseSessionDelayed(session);
return retVal;
}
@@ -124,6 +124,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (!server.CheckPassword(joinGameData.password))
{
server.SessionError(session, ERR_NET_INVALID_PASSWORD);
server.CloseSessionDelayed(session);
return retVal;
}
@@ -133,6 +134,7 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (curNumPlayers >= (size_t)server.GetGameData().numberOfPlayers)
{
server.SessionError(session, ERR_NET_SERVER_FULL);
server.CloseSessionDelayed(session);
return retVal;
}
@@ -140,30 +142,58 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
if (server.IsPlayerConnected(joinGameData.playerName))
{
server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE);
server.CloseSessionDelayed(session);
return retVal;
}
// Create player data object.
boost::shared_ptr<PlayerData> tmpPlayerData(new PlayerData(m_curUniquePlayerId++));
boost::shared_ptr<PlayerData> tmpPlayerData(new PlayerData(m_curUniquePlayerId++, 0));
tmpPlayerData->SetName(joinGameData.playerName);
tmpPlayerData->SetPlayerType(joinGameData.ptype);
// Signal joining player to GUI.
server.GetCallback().SignalNetServerPlayerJoined(tmpPlayerData->GetName());
// Send ACK to client.
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
NetPacketJoinGameAck::Data joinGameAckData;
joinGameAckData.playerId = tmpPlayerData->GetUniqueId();
joinGameAckData.playerNumber = 0;//playerDataList.size();
joinGameAckData.playerNumber = tmpPlayerData->GetNumber();
joinGameAckData.sessionId = session->GetId(); // TODO: currently unused.
joinGameAckData.gameData = server.GetGameData();
static_cast<NetPacketJoinGameAck *>(answer.get())->SetData(joinGameAckData);
server.GetSender().Send(answer, recvSock);
session->SetState(SessionData::Established);
server.GetSender().Send(recvSock, answer);
// Store player data in list.
//playerDataList.push_back(tmpPlayerData);
// Send notifications for connected players to client.
PlayerDataList tmpPlayerList = server.GetPlayerDataList();
PlayerDataList::iterator player_i = tmpPlayerList.begin();
PlayerDataList::iterator player_end = tmpPlayerList.end();
while (player_i != player_end)
{
boost::shared_ptr<NetPacket> otherPlayerJoined(new NetPacketPlayerJoined);
NetPacketPlayerJoined::Data otherPlayerJoinedData;
otherPlayerJoinedData.playerId = (*player_i)->GetUniqueId();
otherPlayerJoinedData.playerName = (*player_i)->GetName();
otherPlayerJoinedData.playerNumber = (*player_i)->GetNumber();
otherPlayerJoinedData.ptype = (*player_i)->GetType();
static_cast<NetPacketPlayerJoined *>(otherPlayerJoined.get())->SetData(otherPlayerJoinedData);
server.GetSender().Send(session->GetSocket(), otherPlayerJoined);
++player_i;
}
// Send "Player Joined" to other clients.
boost::shared_ptr<NetPacket> thisPlayerJoined(new NetPacketPlayerJoined);
NetPacketPlayerJoined::Data thisPlayerJoinedData;
thisPlayerJoinedData.playerId = tmpPlayerData->GetUniqueId();
thisPlayerJoinedData.playerName = tmpPlayerData->GetName();
thisPlayerJoinedData.playerNumber = tmpPlayerData->GetNumber();
thisPlayerJoinedData.ptype = tmpPlayerData->GetType();
static_cast<NetPacketPlayerJoined *>(thisPlayerJoined.get())->SetData(thisPlayerJoinedData);
server.SendToAllButOnePlayers(thisPlayerJoined, session->GetSocket());
// Set player data for session.
server.SetSessionPlayerData(session, tmpPlayerData);
// Session is now established.
session->SetState(SessionData::Established);
}
}
return retVal;
+97 -4
View File
@@ -26,6 +26,8 @@
#include <net/socket_msg.h>
#include <gamedata.h>
#define SERVER_CLOSE_SESSION_DELAY_SEC 10
using namespace std;
class ServerSenderCallback : public SenderCallback
@@ -69,13 +71,13 @@ ServerRecvThread::Init(const string &pwd, const GameData &gameData)
}
void
ServerRecvThread::SendError(int errorCode, SOCKET s)
ServerRecvThread::SendError(SOCKET s, int errorCode)
{
boost::shared_ptr<NetPacket> packet(new NetPacketError);
NetPacketError::Data errorData;
errorData.errorCode = errorCode;
static_cast<NetPacketError *>(packet.get())->SetData(errorData);
GetSender().Send(packet, s);
GetSender().Send(s, packet);
}
void
@@ -90,11 +92,57 @@ ServerRecvThread::SendToAllPlayers(boost::shared_ptr<NetPacket> packet)
while (i != end)
{
// Send each client a copy of the packet.
GetSender().Send(boost::shared_ptr<NetPacket>(packet->Clone()), i->first);
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
++i;
}
}
void
ServerRecvThread::SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SOCKET except)
{
// This function needs to be thread safe.
boost::mutex::scoped_lock lock(m_sessionMapMutex);
SocketSessionMap::iterator i = m_sessionMap.begin();
SocketSessionMap::iterator end = m_sessionMap.end();
while (i != end)
{
// Send each client but one a copy of the packet.
if (i->first != except)
GetSender().Send(i->first, boost::shared_ptr<NetPacket>(packet->Clone()));
++i;
}
}
void
ServerRecvThread::CloseSessionDelayed(boost::shared_ptr<SessionData> sessionData)
{
{
boost::mutex::scoped_lock lock(m_sessionMapMutex);
m_sessionMap.erase(sessionData->GetSocket());
}
boost::shared_ptr<PlayerData> tmpPlayerData = sessionData->GetPlayerData();
if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty())
{
GetCallback().SignalNetServerPlayerLeft(tmpPlayerData->GetName());
// Send "Player Left" to clients.
boost::shared_ptr<NetPacket> thisPlayerLeft(new NetPacketPlayerLeft);
NetPacketPlayerLeft::Data thisPlayerLeftData;
thisPlayerLeftData.playerId = tmpPlayerData->GetUniqueId();
static_cast<NetPacketPlayerLeft *>(thisPlayerLeft.get())->SetData(thisPlayerLeftData);
SendToAllPlayers(thisPlayerLeft);
}
boost::microsec_timer closeTimer;
closeTimer.start();
CloseSessionList::value_type closeSessionData(closeTimer, sessionData);
m_closeSessionList.push_back(closeSessionData);
}
void
ServerRecvThread::AddConnection(boost::shared_ptr<ConnectData> data)
{
@@ -143,6 +191,8 @@ ServerRecvThread::Main()
GetState().Process(*this);
// Process thread-safe notifications.
NotificationLoop();
// Close sessions.
CloseSessionLoop();
}
} catch (const NetException &)
{
@@ -174,6 +224,21 @@ ServerRecvThread::NotificationLoop()
}
}
void
ServerRecvThread::CloseSessionLoop()
{
CloseSessionList::iterator i = m_closeSessionList.begin();
CloseSessionList::iterator end = m_closeSessionList.end();
while (i != end)
{
CloseSessionList::iterator cur = i++;
if (cur->first.elapsed().seconds() >= SERVER_CLOSE_SESSION_DELAY_SEC)
m_closeSessionList.erase(cur);
}
}
SOCKET
ServerRecvThread::Select()
{
@@ -300,7 +365,7 @@ void
ServerRecvThread::SessionError(boost::shared_ptr<SessionData> sessionData, int errorCode)
{
assert(sessionData.get());
SendError(errorCode, sessionData->GetSocket());
SendError(sessionData->GetSocket(), errorCode);
}
SenderThread &
@@ -360,6 +425,34 @@ ServerRecvThread::IsPlayerConnected(const std::string &playerName) const
return retVal;
}
void
ServerRecvThread::SetSessionPlayerData(boost::shared_ptr<SessionData> sessionData, boost::shared_ptr<PlayerData> playerData)
{
boost::mutex::scoped_lock lock(m_sessionMapMutex); // Paranoia
sessionData->SetPlayerData(playerData);
// Signal joining player to GUI.
GetCallback().SignalNetServerPlayerJoined(playerData->GetName());
}
PlayerDataList
ServerRecvThread::GetPlayerDataList() const
{
PlayerDataList playerList;
boost::mutex::scoped_lock lock(m_sessionMapMutex);
SocketSessionMap::const_iterator session_i = m_sessionMap.begin();
SocketSessionMap::const_iterator session_end = m_sessionMap.end();
while (session_i != session_end)
{
boost::shared_ptr<PlayerData> tmpPlayer(session_i->second->GetPlayerData());
if (tmpPlayer.get() && !tmpPlayer->GetName().empty())
playerList.push_back(tmpPlayer);
++session_i;
}
return playerList;
}
ServerSenderCallback &
ServerRecvThread::GetSenderCallback()
{
+53
View File
@@ -39,6 +39,8 @@ struct NetPacketHeader;
class NetPacketJoinGame;
class NetPacketJoinGameAck;
class NetPacketGameStart;
class NetPacketPlayerJoined;
class NetPacketPlayerLeft;
class NetPacketError;
class NetPacket
@@ -61,6 +63,8 @@ public:
virtual const NetPacketJoinGame *ToNetPacketJoinGame() const;
virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const;
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const;
virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const;
virtual const NetPacketError *ToNetPacketError() const;
protected:
@@ -150,6 +154,55 @@ protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketPlayerJoined : public NetPacket
{
public:
struct Data
{
u_int16_t playerId;
u_int16_t playerNumber;
PlayerType ptype;
std::string playerName;
};
NetPacketPlayerJoined();
virtual ~NetPacketPlayerJoined();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketPlayerJoined *ToNetPacketPlayerJoined() const;
protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketPlayerLeft : public NetPacket
{
public:
struct Data
{
u_int16_t playerId;
};
NetPacketPlayerLeft();
virtual ~NetPacketPlayerLeft();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketPlayerLeft *ToNetPacketPlayerLeft() const;
protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketError : public NetPacket
{
public:
+1 -1
View File
@@ -39,7 +39,7 @@ public:
SenderThread(SenderCallback &cb);
virtual ~SenderThread();
void Send(boost::shared_ptr<NetPacket> packet, SOCKET sock);
void Send(SOCKET sock, boost::shared_ptr<NetPacket> packet);
protected:
+1
View File
@@ -32,6 +32,7 @@ public:
virtual void SignalNetServerError(int errorID, int osErrorID) = 0;
virtual void SignalNetServerPlayerJoined(const std::string &playerName) = 0;
virtual void SignalNetServerPlayerLeft(const std::string &playerName) = 0;
};
#endif
+17 -6
View File
@@ -22,15 +22,17 @@
#define _SERVERRECVTHREAD_H_
#include <core/thread.h>
#include <deque>
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
#include <net/connectdata.h>
#include <net/sessiondata.h>
#include <net/servercallback.h>
#include <deque>
#include <map>
#include <list>
#include <string>
#include <boost/shared_ptr.hpp>
#include <core/boost/timer.hpp>
#define RECEIVER_THREAD_TERMINATE_TIMEOUT 200
// Notifications
@@ -61,11 +63,13 @@ protected:
typedef std::deque<boost::shared_ptr<ConnectData> > ConnectQueue;
typedef std::map<SOCKET, boost::shared_ptr<SessionData> > SocketSessionMap;
typedef std::deque<unsigned> NotificationQueue;
typedef std::list<std::pair<boost::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
// Main function of the thread.
virtual void Main();
void NotificationLoop();
void CloseSessionLoop();
SOCKET Select();
@@ -79,8 +83,11 @@ protected:
void AddSession(boost::shared_ptr<SessionData> sessionData);
void SessionError(boost::shared_ptr<SessionData> sessionData, int errorCode);
void SendError(int errorCode, SOCKET s);
void SendError(SOCKET s, int errorCode);
void SendToAllPlayers(boost::shared_ptr<NetPacket> packet);
void SendToAllButOnePlayers(boost::shared_ptr<NetPacket> packet, SOCKET except);
void CloseSessionDelayed(boost::shared_ptr<SessionData> sessionData);
SenderThread &GetSender();
ReceiverHelper &GetReceiver();
@@ -90,6 +97,8 @@ protected:
size_t GetCurNumberOfPlayers() const;
bool IsPlayerConnected(const std::string &playerName) const;
void SetSessionPlayerData(boost::shared_ptr<SessionData> sessionData, boost::shared_ptr<PlayerData> playerData);
PlayerDataList GetPlayerDataList() const;
ServerSenderCallback &GetSenderCallback();
@@ -105,6 +114,8 @@ private:
SocketSessionMap m_sessionMap;
mutable boost::mutex m_sessionMapMutex;
CloseSessionList m_closeSessionList;
std::auto_ptr<ReceiverHelper> m_receiver;
std::auto_ptr<SenderThread> m_sender;