Fixed a very nasty bug concerning the sender thread. SOCKETs were assumed to be kind of unique, but Windows tends to return the socket number of a socket which was just closed as new socket number in accept. This led to very strange behavior when the server was flooded with inits, because the sender thread still had entries for this socket number (which were not removed because they should just fail).
No longer use socket as key in maps, instead, use the session id. Only use the session id in the sender thread, "resolve" it to the socket only in the moment when it is needed. Outstanding requests will be detected to have an invalid session id then. Also, as side effect, fixed an issue with two callback classes which were named the same and caused unexpected behavior.
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <net/netcontext.h>
|
#include <net/netcontext.h>
|
||||||
#include <net/receivebuffer.h>
|
#include <net/receivebuffer.h>
|
||||||
|
#include <net/sessiondata.h>
|
||||||
|
|
||||||
class ClientContext : public NetContext
|
class ClientContext : public NetContext
|
||||||
{
|
{
|
||||||
@@ -31,10 +32,12 @@ public:
|
|||||||
virtual ~ClientContext();
|
virtual ~ClientContext();
|
||||||
|
|
||||||
virtual SOCKET GetSocket() const;
|
virtual SOCKET GetSocket() const;
|
||||||
virtual u_int32_t GetId() const;
|
|
||||||
|
|
||||||
void SetSocket(SOCKET sockfd);
|
void SetSocket(SOCKET sockfd);
|
||||||
|
|
||||||
|
SessionId GetSessionId() const
|
||||||
|
{return m_sessionId;}
|
||||||
|
void SetSessionId(SessionId sessionId)
|
||||||
|
{m_sessionId = sessionId;}
|
||||||
int GetProtocol() const
|
int GetProtocol() const
|
||||||
{return m_protocol;}
|
{return m_protocol;}
|
||||||
void SetProtocol(int protocol)
|
void SetProtocol(int protocol)
|
||||||
@@ -76,6 +79,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SOCKET m_sockfd;
|
SOCKET m_sockfd;
|
||||||
|
SessionId m_sessionId;
|
||||||
int m_protocol;
|
int m_protocol;
|
||||||
int m_addrFamily;
|
int m_addrFamily;
|
||||||
std::string m_serverAddr;
|
std::string m_serverAddr;
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ friend class ClientStateWaitStart;
|
|||||||
friend class ClientStateWaitHand;
|
friend class ClientStateWaitHand;
|
||||||
friend class ClientStateRunHand;
|
friend class ClientStateRunHand;
|
||||||
friend class ClientStateFinal;
|
friend class ClientStateFinal;
|
||||||
|
friend class ClientSenderCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include <net/clientcontext.h>
|
#include <net/clientcontext.h>
|
||||||
|
|
||||||
ClientContext::ClientContext()
|
ClientContext::ClientContext()
|
||||||
: m_sockfd(INVALID_SOCKET), m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0)
|
: m_sockfd(INVALID_SOCKET), m_sessionId(SESSION_ID_GENERIC), m_protocol(0), m_addrFamily(AF_INET), m_serverPort(0)
|
||||||
{
|
{
|
||||||
bzero(&m_clientSockaddr, sizeof(m_clientSockaddr));
|
bzero(&m_clientSockaddr, sizeof(m_clientSockaddr));
|
||||||
}
|
}
|
||||||
@@ -37,13 +37,6 @@ ClientContext::GetSocket() const
|
|||||||
return m_sockfd;
|
return m_sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int32_t
|
|
||||||
ClientContext::GetId() const
|
|
||||||
{
|
|
||||||
// Id is unused for clients.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientContext::SetSocket(SOCKET sockfd)
|
ClientContext::SetSocket(SOCKET sockfd)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ ClientStateStartSession::Process(ClientThread &client)
|
|||||||
boost::shared_ptr<NetPacket> packet(new NetPacketInit);
|
boost::shared_ptr<NetPacket> packet(new NetPacketInit);
|
||||||
((NetPacketInit *)packet.get())->SetData(initData);
|
((NetPacketInit *)packet.get())->SetData(initData);
|
||||||
|
|
||||||
client.GetSender().Send(context.GetSocket(), packet);
|
client.GetSender().Send(context.GetSessionId(), packet);
|
||||||
|
|
||||||
client.SetState(ClientStateWaitSession::Instance());
|
client.SetState(ClientStateWaitSession::Instance());
|
||||||
|
|
||||||
@@ -592,7 +592,7 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr<
|
|||||||
tmpList);
|
tmpList);
|
||||||
|
|
||||||
if (!avatarError)
|
if (!avatarError)
|
||||||
client.GetSender().SendLowPrio(client.GetContext().GetSocket(), tmpList);
|
client.GetSender().SendLowPrio(client.GetContext().GetSessionId(), tmpList);
|
||||||
else
|
else
|
||||||
throw ClientException(__FILE__, __LINE__, avatarError, 0);
|
throw ClientException(__FILE__, __LINE__, avatarError, 0);
|
||||||
}
|
}
|
||||||
@@ -740,7 +740,7 @@ ClientStateSynchronizeStart::Process(ClientThread &client)
|
|||||||
if (client.IsSynchronized())
|
if (client.IsSynchronized())
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> startAck(new NetPacketStartEventAck);
|
boost::shared_ptr<NetPacket> startAck(new NetPacketStartEventAck);
|
||||||
client.GetSender().Send(client.GetContext().GetSocket(), startAck);
|
client.GetSender().Send(client.GetContext().GetSessionId(), startAck);
|
||||||
client.SetState(ClientStateWaitStart::Instance());
|
client.SetState(ClientStateWaitStart::Instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,14 @@ public:
|
|||||||
ClientSenderCallback(ClientThread &client) : m_client(client) {}
|
ClientSenderCallback(ClientThread &client) : m_client(client) {}
|
||||||
virtual ~ClientSenderCallback() {}
|
virtual ~ClientSenderCallback() {}
|
||||||
|
|
||||||
virtual void SignalNetError(SOCKET /*sock*/, int errorID, int osErrorID)
|
virtual bool GetSocketForSession(SessionId session, SOCKET &outSocket)
|
||||||
|
{
|
||||||
|
assert(session == m_client.GetContext().GetSessionId());
|
||||||
|
outSocket = m_client.GetContext().GetSocket();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual void SignalNetError(SessionId /*session*/, int errorID, int osErrorID)
|
||||||
{
|
{
|
||||||
// For now, we ignore the socket.
|
|
||||||
// Just signal the error.
|
// Just signal the error.
|
||||||
// We assume that the client thread will be terminated.
|
// We assume that the client thread will be terminated.
|
||||||
m_client.GetCallback().SignalNetClientError(errorID, osErrorID);
|
m_client.GetCallback().SignalNetClientError(errorID, osErrorID);
|
||||||
@@ -369,7 +374,7 @@ ClientThread::SendPacketLoop()
|
|||||||
|
|
||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
GetSender().Send(GetContext().GetSocket(), *i);
|
GetSender().Send(GetContext().GetSessionId(), *i);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
m_outPacketList.clear();
|
m_outPacketList.clear();
|
||||||
@@ -400,7 +405,7 @@ ClientThread::RequestPlayerInfo(unsigned id)
|
|||||||
NetPacketRetrievePlayerInfo::Data reqData;
|
NetPacketRetrievePlayerInfo::Data reqData;
|
||||||
reqData.playerId = id;
|
reqData.playerId = id;
|
||||||
static_cast<NetPacketRetrievePlayerInfo *>(req.get())->SetData(reqData);
|
static_cast<NetPacketRetrievePlayerInfo *>(req.get())->SetData(reqData);
|
||||||
GetSender().Send(GetContext().GetSocket(), req);
|
GetSender().Send(GetContext().GetSessionId(), req);
|
||||||
|
|
||||||
m_playerInfoRequestList.push_back(id);
|
m_playerInfoRequestList.push_back(id);
|
||||||
}
|
}
|
||||||
@@ -438,7 +443,7 @@ ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info, bool retrieveAv
|
|||||||
retrieveAvatarData.requestId = id;
|
retrieveAvatarData.requestId = id;
|
||||||
retrieveAvatarData.avatar = info.avatar;
|
retrieveAvatarData.avatar = info.avatar;
|
||||||
static_cast<NetPacketRetrieveAvatar *>(retrieveAvatar.get())->SetData(retrieveAvatarData);
|
static_cast<NetPacketRetrieveAvatar *>(retrieveAvatar.get())->SetData(retrieveAvatarData);
|
||||||
GetSender().Send(GetContext().GetSocket(), retrieveAvatar);
|
GetSender().Send(GetContext().GetSessionId(), retrieveAvatar);
|
||||||
|
|
||||||
// Insert empty value in list to synchronize waiting.
|
// Insert empty value in list to synchronize waiting.
|
||||||
m_tempAvatarMap[id] = boost::shared_ptr<AvatarData>();
|
m_tempAvatarMap[id] = boost::shared_ptr<AvatarData>();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ using namespace std;
|
|||||||
|
|
||||||
|
|
||||||
SenderThread::SenderThread(SenderCallback &cb)
|
SenderThread::SenderThread(SenderCallback &cb)
|
||||||
: m_curSocket(INVALID_SOCKET), m_tmpOutBufSize(0), m_callback(cb)
|
: m_curSession(INVALID_SESSION), m_tmpOutBufSize(0), m_callback(cb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,55 +37,55 @@ SenderThread::~SenderThread()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::Send(SOCKET sock, boost::shared_ptr<NetPacket> packet)
|
SenderThread::Send(SessionId session, boost::shared_ptr<NetPacket> packet)
|
||||||
{
|
{
|
||||||
if (packet.get() && IS_VALID_SOCKET(sock))
|
if (packet.get() && session != INVALID_SESSION)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_outBufMutex);
|
boost::mutex::scoped_lock lock(m_outBufMutex);
|
||||||
InternalStore(m_outBuf, SEND_QUEUE_SIZE, sock, packet);
|
InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::Send(SOCKET sock, const NetPacketList &packetList)
|
SenderThread::Send(SessionId session, const NetPacketList &packetList)
|
||||||
{
|
{
|
||||||
if (!packetList.empty() && IS_VALID_SOCKET(sock))
|
if (!packetList.empty() && session != INVALID_SESSION)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_outBufMutex);
|
boost::mutex::scoped_lock lock(m_outBufMutex);
|
||||||
InternalStore(m_outBuf, SEND_QUEUE_SIZE, sock, packetList);
|
InternalStore(m_outBuf, SEND_QUEUE_SIZE, session, packetList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::SendLowPrio(SOCKET sock, boost::shared_ptr<NetPacket> packet)
|
SenderThread::SendLowPrio(SessionId session, boost::shared_ptr<NetPacket> packet)
|
||||||
{
|
{
|
||||||
if (packet.get() && IS_VALID_SOCKET(sock))
|
if (packet.get() && session != INVALID_SESSION)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex);
|
boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex);
|
||||||
InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, sock, packet);
|
InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::SendLowPrio(SOCKET sock, const NetPacketList &packetList)
|
SenderThread::SendLowPrio(SessionId session, const NetPacketList &packetList)
|
||||||
{
|
{
|
||||||
if (!packetList.empty() && IS_VALID_SOCKET(sock))
|
if (!packetList.empty() && session != INVALID_SESSION)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex);
|
boost::mutex::scoped_lock lock(m_lowPrioOutBufMutex);
|
||||||
InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, sock, packetList);
|
InternalStore(m_lowPrioOutBuf, SEND_LOW_PRIO_QUEUE_SIZE, session, packetList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SOCKET sock, boost::shared_ptr<NetPacket> packet)
|
SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SessionId session, boost::shared_ptr<NetPacket> packet)
|
||||||
{
|
{
|
||||||
if (sendQueue.size() < maxQueueSize) // Queue is limited in size.
|
if (sendQueue.size() < maxQueueSize) // Queue is limited in size.
|
||||||
sendQueue.push_back(std::make_pair(packet, sock));
|
sendQueue.push_back(std::make_pair(packet, session));
|
||||||
// TODO: Throw exception if failed.
|
// TODO: Throw exception if failed.
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SOCKET sock, const NetPacketList &packetList)
|
SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SessionId session, const NetPacketList &packetList)
|
||||||
{
|
{
|
||||||
if (sendQueue.size() + packetList.size() < maxQueueSize)
|
if (sendQueue.size() + packetList.size() < maxQueueSize)
|
||||||
{
|
{
|
||||||
@@ -93,7 +93,7 @@ SenderThread::InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SOC
|
|||||||
NetPacketList::const_iterator end = packetList.end();
|
NetPacketList::const_iterator end = packetList.end();
|
||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
sendQueue.push_back(std::make_pair(*i, sock));
|
sendQueue.push_back(std::make_pair(*i, session));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,8 +134,8 @@ SenderThread::Main()
|
|||||||
|
|
||||||
if (tmpData.first.get())
|
if (tmpData.first.get())
|
||||||
{
|
{
|
||||||
if (IS_VALID_SOCKET(tmpData.second))
|
if (tmpData.second != INVALID_SESSION)
|
||||||
m_curSocket = tmpData.second;
|
m_curSession = tmpData.second;
|
||||||
|
|
||||||
u_int16_t tmpLen = tmpData.first->GetLen();
|
u_int16_t tmpLen = tmpData.first->GetLen();
|
||||||
if (tmpLen <= MAX_PACKET_SIZE)
|
if (tmpLen <= MAX_PACKET_SIZE)
|
||||||
@@ -146,16 +146,25 @@ SenderThread::Main()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_tmpOutBufSize)
|
if (m_tmpOutBufSize)
|
||||||
|
{
|
||||||
|
SOCKET tmpSocket;
|
||||||
|
if (!m_callback.GetSocketForSession(m_curSession, tmpSocket))
|
||||||
|
{
|
||||||
|
// Invalid session - skip.
|
||||||
|
m_tmpOutBufSize = 0;
|
||||||
|
m_curSession = INVALID_SESSION;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
fd_set writeSet;
|
fd_set writeSet;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
|
|
||||||
FD_ZERO(&writeSet);
|
FD_ZERO(&writeSet);
|
||||||
FD_SET(m_curSocket, &writeSet);
|
FD_SET(tmpSocket, &writeSet);
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000;
|
timeout.tv_usec = SEND_TIMEOUT_MSEC * 1000;
|
||||||
int selectResult = select(m_curSocket + 1, NULL, &writeSet, NULL, &timeout);
|
int selectResult = select(tmpSocket + 1, NULL, &writeSet, NULL, &timeout);
|
||||||
if (!IS_VALID_SELECT(selectResult))
|
if (!IS_VALID_SELECT(selectResult))
|
||||||
{
|
{
|
||||||
// Never assume that this is a fatal error.
|
// Never assume that this is a fatal error.
|
||||||
@@ -165,15 +174,16 @@ SenderThread::Main()
|
|||||||
// Skip this packet - this is bad, and is therefore reported.
|
// Skip this packet - this is bad, and is therefore reported.
|
||||||
// Ignore invalid or not connected sockets.
|
// Ignore invalid or not connected sockets.
|
||||||
if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK)
|
if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK)
|
||||||
m_callback.SignalNetError(m_curSocket, ERR_SOCK_SELECT_FAILED, errCode);
|
m_callback.SignalNetError(m_curSession, ERR_SOCK_SELECT_FAILED, errCode);
|
||||||
m_tmpOutBufSize = 0;
|
m_tmpOutBufSize = 0;
|
||||||
|
m_curSession = INVALID_SESSION;
|
||||||
}
|
}
|
||||||
Msleep(SEND_TIMEOUT_MSEC);
|
Msleep(SEND_TIMEOUT_MSEC);
|
||||||
}
|
}
|
||||||
if (selectResult > 0) // send is possible
|
if (selectResult > 0) // send is possible
|
||||||
{
|
{
|
||||||
// send next chunk of data
|
// send next chunk of data
|
||||||
int bytesSent = send(m_curSocket, m_tmpOutBuf, m_tmpOutBufSize, 0);
|
int bytesSent = send(tmpSocket, m_tmpOutBuf, m_tmpOutBufSize, 0);
|
||||||
|
|
||||||
if (!IS_VALID_SEND(bytesSent))
|
if (!IS_VALID_SEND(bytesSent))
|
||||||
{
|
{
|
||||||
@@ -184,8 +194,9 @@ SenderThread::Main()
|
|||||||
// Skip this packet - this is bad, and is therefore reported.
|
// Skip this packet - this is bad, and is therefore reported.
|
||||||
// Ignore invalid or not connected sockets.
|
// Ignore invalid or not connected sockets.
|
||||||
if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK)
|
if (errCode != SOCKET_ERR_NOTCONN && errCode != SOCKET_ERR_NOTSOCK)
|
||||||
m_callback.SignalNetError(m_curSocket, ERR_SOCK_SEND_FAILED, errCode);
|
m_callback.SignalNetError(m_curSession, ERR_SOCK_SEND_FAILED, errCode);
|
||||||
m_tmpOutBufSize = 0;
|
m_tmpOutBufSize = 0;
|
||||||
|
m_curSession = INVALID_SESSION;
|
||||||
}
|
}
|
||||||
Msleep(SEND_TIMEOUT_MSEC);
|
Msleep(SEND_TIMEOUT_MSEC);
|
||||||
}
|
}
|
||||||
@@ -197,6 +208,8 @@ SenderThread::Main()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_tmpOutBufSize = 0;
|
m_tmpOutBufSize = 0;
|
||||||
|
m_curSession = INVALID_SESSION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,13 +37,6 @@ ServerContext::GetSocket() const
|
|||||||
return m_sockfd;
|
return m_sockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
u_int32_t
|
|
||||||
ServerContext::GetId() const
|
|
||||||
{
|
|
||||||
// Id is unused for main server thread.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerContext::SetSocket(SOCKET sockfd)
|
ServerContext::SetSocket(SOCKET sockfd)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper s
|
|||||||
joinGameAckData.prights = session.playerData->GetRights();
|
joinGameAckData.prights = session.playerData->GetRights();
|
||||||
joinGameAckData.gameData = server.GetGameData();
|
joinGameAckData.gameData = server.GetGameData();
|
||||||
static_cast<NetPacketJoinGameAck *>(joinGameAck.get())->SetData(joinGameAckData);
|
static_cast<NetPacketJoinGameAck *>(joinGameAck.get())->SetData(joinGameAckData);
|
||||||
server.GetSender().Send(session.sessionData->GetSocket(), joinGameAck);
|
server.GetSender().Send(session.sessionData->GetId(), joinGameAck);
|
||||||
|
|
||||||
// Send notifications for connected players to client.
|
// Send notifications for connected players to client.
|
||||||
PlayerDataList tmpPlayerList = server.GetFullPlayerDataList();
|
PlayerDataList tmpPlayerList = server.GetFullPlayerDataList();
|
||||||
@@ -279,7 +279,7 @@ ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper s
|
|||||||
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
PlayerDataList::iterator player_end = tmpPlayerList.end();
|
||||||
while (player_i != player_end)
|
while (player_i != player_end)
|
||||||
{
|
{
|
||||||
server.GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketPlayerJoined(*(*player_i)));
|
server.GetSender().Send(session.sessionData->GetId(), CreateNetPacketPlayerJoined(*(*player_i)));
|
||||||
++player_i;
|
++player_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,7 +538,7 @@ ServerGameStateStartHand::Process(ServerGameThread &server)
|
|||||||
handStartData.smallBlind = curGame.getCurrentHand()->getSmallBlind();
|
handStartData.smallBlind = curGame.getCurrentHand()->getSmallBlind();
|
||||||
static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData);
|
static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData);
|
||||||
|
|
||||||
server.GetSender().Send(tmpPlayer->getNetSessionData()->GetSocket(), notifyCards);
|
server.GetSender().Send(tmpPlayer->getNetSessionData()->GetId(), notifyCards);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -908,7 +908,7 @@ ServerGameStateWaitPlayerAction::InternalProcess(ServerGameThread &server, Sessi
|
|||||||
rejectData.playerBet = actionData.playerBet;
|
rejectData.playerBet = actionData.playerBet;
|
||||||
rejectData.rejectionReason = code;
|
rejectData.rejectionReason = code;
|
||||||
static_cast<NetPacketPlayersActionRejected *>(reject.get())->SetData(rejectData);
|
static_cast<NetPacketPlayersActionRejected *>(reject.get())->SetData(rejectData);
|
||||||
server.GetSender().Send(session.sessionData->GetSocket(), reject);
|
server.GetSender().Send(session.sessionData->GetId(), reject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,17 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
class ServerSenderCallback : public SenderCallback
|
class GameSenderCallback : public SenderCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerSenderCallback(ServerGameThread &server) : m_server(server) {}
|
GameSenderCallback(ServerGameThread &server) : m_server(server) {}
|
||||||
virtual ~ServerSenderCallback() {}
|
virtual ~GameSenderCallback() {}
|
||||||
|
|
||||||
virtual void SignalNetError(SOCKET /*sock*/, int /*errorID*/, int /*osErrorID*/)
|
virtual bool GetSocketForSession(SessionId session, SOCKET &outSocket)
|
||||||
|
{
|
||||||
|
return m_server.GetSessionManager().GetSocketForSession(session, outSocket);
|
||||||
|
}
|
||||||
|
virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/)
|
||||||
{
|
{
|
||||||
// We just ignore send errors for now, on server side.
|
// We just ignore send errors for now, on server side.
|
||||||
// A serious send error should trigger a read error or a read
|
// A serious send error should trigger a read error or a read
|
||||||
@@ -57,7 +61,7 @@ ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, u_int32_t id,
|
|||||||
m_name(name), m_password(pwd), m_gameData(gameData), m_playerConfig(playerConfig),
|
m_name(name), m_password(pwd), m_gameData(gameData), m_playerConfig(playerConfig),
|
||||||
m_curState(NULL), m_gameNum(1)
|
m_curState(NULL), m_gameNum(1)
|
||||||
{
|
{
|
||||||
m_senderCallback.reset(new ServerSenderCallback(*this));
|
m_senderCallback.reset(new GameSenderCallback(*this));
|
||||||
m_sender.reset(new SenderThread(GetSenderCallback()));
|
m_sender.reset(new SenderThread(GetSenderCallback()));
|
||||||
m_receiver.reset(new ReceiverHelper);
|
m_receiver.reset(new ReceiverHelper);
|
||||||
}
|
}
|
||||||
@@ -319,7 +323,7 @@ void
|
|||||||
ServerGameThread::GracefulRemoveSession(SessionWrapper session)
|
ServerGameThread::GracefulRemoveSession(SessionWrapper session)
|
||||||
{
|
{
|
||||||
assert(session.sessionData.get());
|
assert(session.sessionData.get());
|
||||||
GetSessionManager().RemoveSession(session.sessionData->GetSocket());
|
GetSessionManager().RemoveSession(session.sessionData->GetId());
|
||||||
|
|
||||||
boost::shared_ptr<PlayerData> tmpPlayerData = session.playerData;
|
boost::shared_ptr<PlayerData> tmpPlayerData = session.playerData;
|
||||||
if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty())
|
if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty())
|
||||||
@@ -526,7 +530,7 @@ ServerGameThread::CheckPassword(const string &password) const
|
|||||||
return (password == m_password);
|
return (password == m_password);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerSenderCallback &
|
GameSenderCallback &
|
||||||
ServerGameThread::GetSenderCallback()
|
ServerGameThread::GetSenderCallback()
|
||||||
{
|
{
|
||||||
assert(m_senderCallback.get());
|
assert(m_senderCallback.get());
|
||||||
|
|||||||
@@ -46,7 +46,11 @@ public:
|
|||||||
ServerSenderCallback(ServerLobbyThread &server) : m_server(server) {}
|
ServerSenderCallback(ServerLobbyThread &server) : m_server(server) {}
|
||||||
virtual ~ServerSenderCallback() {}
|
virtual ~ServerSenderCallback() {}
|
||||||
|
|
||||||
virtual void SignalNetError(SOCKET /*sock*/, int /*errorID*/, int /*osErrorID*/)
|
virtual bool GetSocketForSession(SessionId session, SOCKET &outSocket)
|
||||||
|
{
|
||||||
|
return m_server.GetSocketForSession(session, outSocket);
|
||||||
|
}
|
||||||
|
virtual void SignalNetError(SessionId /*session*/, int /*errorID*/, int /*osErrorID*/)
|
||||||
{
|
{
|
||||||
// We just ignore send errors for now, on server side.
|
// We just ignore send errors for now, on server side.
|
||||||
// A serious send error should trigger a read error or a read
|
// A serious send error should trigger a read error or a read
|
||||||
@@ -60,7 +64,8 @@ private:
|
|||||||
|
|
||||||
ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager)
|
ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager)
|
||||||
: m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig),
|
: m_gui(gui), m_avatarManager(avatarManager), m_playerConfig(playerConfig),
|
||||||
m_curGameId(0), m_curUniquePlayerId(0), m_totalPlayersLoggedIn(0), m_totalGamesStarted(0)
|
m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1),
|
||||||
|
m_totalPlayersLoggedIn(0), m_totalGamesStarted(0)
|
||||||
{
|
{
|
||||||
m_senderCallback.reset(new ServerSenderCallback(*this));
|
m_senderCallback.reset(new ServerSenderCallback(*this));
|
||||||
m_sender.reset(new SenderThread(GetSenderCallback()));
|
m_sender.reset(new SenderThread(GetSenderCallback()));
|
||||||
@@ -92,7 +97,7 @@ ServerLobbyThread::ReAddSession(SessionWrapper session, int reason)
|
|||||||
NetPacketRemovedFromGame::Data removedData;
|
NetPacketRemovedFromGame::Data removedData;
|
||||||
removedData.removeReason = reason;
|
removedData.removeReason = reason;
|
||||||
static_cast<NetPacketRemovedFromGame *>(packet.get())->SetData(removedData);
|
static_cast<NetPacketRemovedFromGame *>(packet.get())->SetData(removedData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), packet);
|
GetSender().Send(session.sessionData->GetId(), packet);
|
||||||
|
|
||||||
boost::mutex::scoped_lock lock(m_sessionQueueMutex);
|
boost::mutex::scoped_lock lock(m_sessionQueueMutex);
|
||||||
m_sessionQueue.push_back(session);
|
m_sessionQueue.push_back(session);
|
||||||
@@ -102,7 +107,7 @@ void
|
|||||||
ServerLobbyThread::MoveSessionToGame(ServerGameThread &game, SessionWrapper session)
|
ServerLobbyThread::MoveSessionToGame(ServerGameThread &game, SessionWrapper session)
|
||||||
{
|
{
|
||||||
// Remove session from the lobby.
|
// Remove session from the lobby.
|
||||||
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_sessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
// Session is now in game state.
|
// Session is now in game state.
|
||||||
session.sessionData->SetState(SessionData::Game);
|
session.sessionData->SetState(SessionData::Game);
|
||||||
// Store it in the list of game sessions.
|
// Store it in the list of game sessions.
|
||||||
@@ -115,7 +120,7 @@ void
|
|||||||
ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session)
|
ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session)
|
||||||
{
|
{
|
||||||
// Just remove the session. Only for fatal errors.
|
// Just remove the session. Only for fatal errors.
|
||||||
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_gameSessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
// Update stats (if needed).
|
// Update stats (if needed).
|
||||||
BroadcastStatisticsUpdate();
|
BroadcastStatisticsUpdate();
|
||||||
}
|
}
|
||||||
@@ -123,9 +128,9 @@ ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session)
|
|||||||
void
|
void
|
||||||
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
|
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
|
||||||
{
|
{
|
||||||
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
m_initTimerSessionMap.erase(session.sessionData->GetId());
|
||||||
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_sessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_gameSessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
|
|
||||||
boost::timers::portable::microsec_timer closeTimer;
|
boost::timers::portable::microsec_timer closeTimer;
|
||||||
CloseSessionList::value_type closeSessionData(closeTimer, session.sessionData);
|
CloseSessionList::value_type closeSessionData(closeTimer, session.sessionData);
|
||||||
@@ -227,6 +232,15 @@ ServerLobbyThread::RemoveGame(unsigned id)
|
|||||||
m_removeGameList.push_back(id);
|
m_removeGameList.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ServerLobbyThread::GetSocketForSession(SessionId session, SOCKET &outSocket)
|
||||||
|
{
|
||||||
|
bool retVal = m_sessionManager.GetSocketForSession(session, outSocket);
|
||||||
|
if (!retVal)
|
||||||
|
retVal = m_gameSessionManager.GetSocketForSession(session, outSocket);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
AvatarManager &
|
AvatarManager &
|
||||||
ServerLobbyThread::GetAvatarManager()
|
ServerLobbyThread::GetAvatarManager()
|
||||||
{
|
{
|
||||||
@@ -298,8 +312,8 @@ ServerLobbyThread::ProcessLoop()
|
|||||||
} catch (const NetException &)
|
} catch (const NetException &)
|
||||||
{
|
{
|
||||||
// On error: Close this session.
|
// On error: Close this session.
|
||||||
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
m_initTimerSessionMap.erase(session.sessionData->GetId());
|
||||||
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_sessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
// Update stats (if needed).
|
// Update stats (if needed).
|
||||||
BroadcastStatisticsUpdate();
|
BroadcastStatisticsUpdate();
|
||||||
return;
|
return;
|
||||||
@@ -391,7 +405,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketIn
|
|||||||
tmpPlayerData->SetAvatarMD5(initData.avatar);
|
tmpPlayerData->SetAvatarMD5(initData.avatar);
|
||||||
|
|
||||||
// Set player data for session.
|
// Set player data for session.
|
||||||
m_sessionManager.SetSessionPlayerData(session.sessionData->GetSocket(), tmpPlayerData);
|
m_sessionManager.SetSessionPlayerData(session.sessionData->GetId(), tmpPlayerData);
|
||||||
session.playerData = tmpPlayerData;
|
session.playerData = tmpPlayerData;
|
||||||
|
|
||||||
if (initData.showAvatar && !GetAvatarManager().HasAvatar(initData.avatar))
|
if (initData.showAvatar && !GetAvatarManager().HasAvatar(initData.avatar))
|
||||||
@@ -510,7 +524,7 @@ ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, con
|
|||||||
if (infoData.playerInfo.hasAvatar)
|
if (infoData.playerInfo.hasAvatar)
|
||||||
infoData.playerInfo.avatar = tmpPlayer->GetAvatarMD5();
|
infoData.playerInfo.avatar = tmpPlayer->GetAvatarMD5();
|
||||||
static_cast<NetPacketPlayerInfo *>(info.get())->SetData(infoData);
|
static_cast<NetPacketPlayerInfo *>(info.get())->SetData(infoData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), info);
|
GetSender().Send(session.sessionData->GetId(), info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -519,7 +533,7 @@ ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, con
|
|||||||
NetPacketUnknownPlayerId::Data unknownData;
|
NetPacketUnknownPlayerId::Data unknownData;
|
||||||
unknownData.playerId = request.playerId;
|
unknownData.playerId = request.playerId;
|
||||||
static_cast<NetPacketUnknownPlayerId *>(unknown.get())->SetData(unknownData);
|
static_cast<NetPacketUnknownPlayerId *>(unknown.get())->SetData(unknownData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), unknown);
|
GetSender().Send(session.sessionData->GetId(), unknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +551,7 @@ ServerLobbyThread::HandleNetPacketRetrieveAvatar(SessionWrapper session, const N
|
|||||||
if (GetAvatarManager().AvatarFileToNetPackets(tmpFile, request.requestId, tmpPackets) == 0)
|
if (GetAvatarManager().AvatarFileToNetPackets(tmpFile, request.requestId, tmpPackets) == 0)
|
||||||
{
|
{
|
||||||
avatarFound = true;
|
avatarFound = true;
|
||||||
GetSender().SendLowPrio(session.sessionData->GetSocket(), tmpPackets);
|
GetSender().SendLowPrio(session.sessionData->GetId(), tmpPackets);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_ERROR("Failed to read avatar file for network transmission.");
|
LOG_ERROR("Failed to read avatar file for network transmission.");
|
||||||
@@ -550,7 +564,7 @@ ServerLobbyThread::HandleNetPacketRetrieveAvatar(SessionWrapper session, const N
|
|||||||
NetPacketUnknownAvatar::Data unknownData;
|
NetPacketUnknownAvatar::Data unknownData;
|
||||||
unknownData.requestId = request.requestId;
|
unknownData.requestId = request.requestId;
|
||||||
static_cast<NetPacketUnknownAvatar *>(unknown.get())->SetData(unknownData);
|
static_cast<NetPacketUnknownAvatar *>(unknown.get())->SetData(unknownData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), unknown);
|
GetSender().Send(session.sessionData->GetId(), unknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,7 +613,7 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SendJoinGameFailed(session.sessionData->GetSocket(), NTF_NET_JOIN_INVALID_PASSWORD);
|
SendJoinGameFailed(session.sessionData->GetId(), NTF_NET_JOIN_INVALID_PASSWORD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -620,13 +634,13 @@ ServerLobbyThread::EstablishSession(SessionWrapper session)
|
|||||||
initAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
|
initAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused.
|
||||||
initAckData.playerId = session.playerData->GetUniqueId();
|
initAckData.playerId = session.playerData->GetUniqueId();
|
||||||
static_cast<NetPacketInitAck *>(initAck.get())->SetData(initAckData);
|
static_cast<NetPacketInitAck *>(initAck.get())->SetData(initAckData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), initAck);
|
GetSender().Send(session.sessionData->GetId(), initAck);
|
||||||
|
|
||||||
// Send the game list to the client.
|
// Send the game list to the client.
|
||||||
SendGameList(session.sessionData->GetSocket());
|
SendGameList(session.sessionData->GetId());
|
||||||
|
|
||||||
// Session is now established.
|
// Session is now established.
|
||||||
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
m_initTimerSessionMap.erase(session.sessionData->GetId());
|
||||||
session.sessionData->SetState(SessionData::Established);
|
session.sessionData->SetState(SessionData::Established);
|
||||||
|
|
||||||
++m_totalPlayersLoggedIn;
|
++m_totalPlayersLoggedIn;
|
||||||
@@ -644,7 +658,7 @@ ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session)
|
|||||||
retrieveAvatarData.requestId = session.playerData->GetUniqueId();
|
retrieveAvatarData.requestId = session.playerData->GetUniqueId();
|
||||||
retrieveAvatarData.avatar = session.playerData->GetAvatarMD5();
|
retrieveAvatarData.avatar = session.playerData->GetAvatarMD5();
|
||||||
static_cast<NetPacketRetrieveAvatar *>(retrieveAvatar.get())->SetData(retrieveAvatarData);
|
static_cast<NetPacketRetrieveAvatar *>(retrieveAvatar.get())->SetData(retrieveAvatarData);
|
||||||
GetSender().Send(session.sessionData->GetSocket(), retrieveAvatar);
|
GetSender().Send(session.sessionData->GetId(), retrieveAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -797,29 +811,28 @@ ServerLobbyThread::TerminateGames()
|
|||||||
|
|
||||||
void
|
void
|
||||||
ServerLobbyThread::HandleNewConnection(boost::shared_ptr<ConnectData> connData)
|
ServerLobbyThread::HandleNewConnection(boost::shared_ptr<ConnectData> connData)
|
||||||
{
|
|
||||||
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS)
|
|
||||||
{
|
{
|
||||||
// Create a random session id.
|
// Create a random session id.
|
||||||
// This id can be used to reconnect to the server if the connection was lost.
|
// This id can be used to reconnect to the server if the connection was lost.
|
||||||
unsigned sessionId;
|
//unsigned sessionId;
|
||||||
|
|
||||||
// TODO: check for collisions.
|
// TODO: use randomized method.
|
||||||
if(!RAND_bytes((unsigned char *)&sessionId, sizeof(sessionId)))
|
//if(!RAND_bytes((unsigned char *)&sessionId, sizeof(sessionId)))
|
||||||
{
|
//{
|
||||||
RAND_pseudo_bytes((unsigned char *)&sessionId, sizeof(sessionId));
|
// RAND_pseudo_bytes((unsigned char *)&sessionId, sizeof(sessionId));
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Create a new session.
|
// Create a new session.
|
||||||
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), sessionId));
|
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), m_curSessionId++));
|
||||||
m_sessionManager.AddSession(sessionData);
|
m_sessionManager.AddSession(sessionData);
|
||||||
m_initTimerSessionMap[sessionData->GetSocket()] = boost::timers::portable::microsec_timer();
|
|
||||||
|
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS)
|
||||||
|
{
|
||||||
|
m_initTimerSessionMap[sessionData->GetId()] = boost::timers::portable::microsec_timer();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Server is full.
|
// Server is full.
|
||||||
// Create a generic session with Id 0.
|
|
||||||
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), 0));
|
|
||||||
// Gracefully close this session.
|
// Gracefully close this session.
|
||||||
SessionError(SessionWrapper(sessionData, boost::shared_ptr<PlayerData>()), ERR_NET_SERVER_FULL);
|
SessionError(SessionWrapper(sessionData, boost::shared_ptr<PlayerData>()), ERR_NET_SERVER_FULL);
|
||||||
}
|
}
|
||||||
@@ -829,7 +842,7 @@ void
|
|||||||
ServerLobbyThread::HandleReAddedSession(SessionWrapper session)
|
ServerLobbyThread::HandleReAddedSession(SessionWrapper session)
|
||||||
{
|
{
|
||||||
// Remove session from game session list.
|
// Remove session from game session list.
|
||||||
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_gameSessionManager.RemoveSession(session.sessionData->GetId());
|
||||||
|
|
||||||
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS)
|
if (m_sessionManager.GetRawSessionCount() <= SERVER_MAX_NUM_SESSIONS)
|
||||||
{
|
{
|
||||||
@@ -859,13 +872,13 @@ ServerLobbyThread::SessionError(SessionWrapper session, int errorCode)
|
|||||||
{
|
{
|
||||||
if (session.sessionData.get())
|
if (session.sessionData.get())
|
||||||
{
|
{
|
||||||
SendError(session.sessionData->GetSocket(), errorCode);
|
SendError(session.sessionData->GetId(), errorCode);
|
||||||
CloseSessionDelayed(session);
|
CloseSessionDelayed(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerLobbyThread::SendError(SOCKET s, int errorCode)
|
ServerLobbyThread::SendError(SessionId s, int errorCode)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> packet(new NetPacketError);
|
boost::shared_ptr<NetPacket> packet(new NetPacketError);
|
||||||
NetPacketError::Data errorData;
|
NetPacketError::Data errorData;
|
||||||
@@ -875,7 +888,7 @@ ServerLobbyThread::SendError(SOCKET s, int errorCode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerLobbyThread::SendJoinGameFailed(SOCKET s, int reason)
|
ServerLobbyThread::SendJoinGameFailed(SessionId s, int reason)
|
||||||
{
|
{
|
||||||
boost::shared_ptr<NetPacket> packet(new NetPacketJoinGameFailed);
|
boost::shared_ptr<NetPacket> packet(new NetPacketJoinGameFailed);
|
||||||
NetPacketJoinGameFailed::Data failedData;
|
NetPacketJoinGameFailed::Data failedData;
|
||||||
@@ -885,7 +898,7 @@ ServerLobbyThread::SendJoinGameFailed(SOCKET s, int reason)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServerLobbyThread::SendGameList(SOCKET s)
|
ServerLobbyThread::SendGameList(SessionId s)
|
||||||
{
|
{
|
||||||
GameMap::const_iterator game_i = m_gameMap.begin();
|
GameMap::const_iterator game_i = m_gameMap.begin();
|
||||||
GameMap::const_iterator game_end = m_gameMap.end();
|
GameMap::const_iterator game_end = m_gameMap.end();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include <net/sessiondata.h>
|
#include <net/sessiondata.h>
|
||||||
|
|
||||||
SessionData::SessionData(SOCKET sockfd, unsigned id)
|
SessionData::SessionData(SOCKET sockfd, SessionId id)
|
||||||
: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false)
|
: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ SessionData::~SessionData()
|
|||||||
CLOSESOCKET(m_sockfd);
|
CLOSESOCKET(m_sockfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
SessionId
|
||||||
SessionData::GetId() const
|
SessionData::GetId() const
|
||||||
{
|
{
|
||||||
// const value - no mutex needed.
|
// const value - no mutex needed.
|
||||||
|
|||||||
@@ -52,19 +52,19 @@ SessionManager::AddSession(SessionWrapper session)
|
|||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
|
|
||||||
SessionMap::iterator pos = m_sessionMap.lower_bound(session.sessionData->GetSocket());
|
SessionMap::iterator pos = m_sessionMap.lower_bound(session.sessionData->GetId());
|
||||||
|
|
||||||
// If pos points to a pair whose key is equivalent to the socket, this handle
|
// If pos points to a pair whose key is equivalent to the socket, this handle
|
||||||
// already exists within the list.
|
// already exists within the list.
|
||||||
if (pos != m_sessionMap.end() && session.sessionData->GetSocket() == pos->first)
|
if (pos != m_sessionMap.end() && session.sessionData->GetId() == pos->first)
|
||||||
{
|
{
|
||||||
throw ServerException(__FILE__, __LINE__, ERR_SOCK_CONN_EXISTS, 0);
|
throw ServerException(__FILE__, __LINE__, ERR_SOCK_CONN_EXISTS, 0);
|
||||||
}
|
}
|
||||||
m_sessionMap.insert(pos, SessionMap::value_type(session.sessionData->GetSocket(), session));
|
m_sessionMap.insert(pos, SessionMap::value_type(session.sessionData->GetId(), session));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SessionManager::SetSessionPlayerData(SOCKET session, boost::shared_ptr<PlayerData> playerData)
|
SessionManager::SetSessionPlayerData(SessionId session, boost::shared_ptr<PlayerData> playerData)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
SessionMap::iterator pos = m_sessionMap.find(session);
|
SessionMap::iterator pos = m_sessionMap.find(session);
|
||||||
@@ -74,7 +74,7 @@ SessionManager::SetSessionPlayerData(SOCKET session, boost::shared_ptr<PlayerDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SessionManager::RemoveSession(SOCKET session)
|
SessionManager::RemoveSession(SessionId session)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
m_sessionMap.erase(session);
|
m_sessionMap.erase(session);
|
||||||
@@ -96,7 +96,7 @@ SessionManager::Select(unsigned timeoutMsec)
|
|||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
// Collect all sockets.
|
// Collect all sockets.
|
||||||
SOCKET tmpSock = i->first;
|
SOCKET tmpSock = i->second.sessionData->GetSocket();
|
||||||
FD_SET(tmpSock, &rdset);
|
FD_SET(tmpSock, &rdset);
|
||||||
if (tmpSock > maxSock || maxSock == INVALID_SOCKET)
|
if (tmpSock > maxSock || maxSock == INVALID_SOCKET)
|
||||||
maxSock = tmpSock;
|
maxSock = tmpSock;
|
||||||
@@ -137,7 +137,7 @@ SessionManager::Select(unsigned timeoutMsec)
|
|||||||
|
|
||||||
while (i != end)
|
while (i != end)
|
||||||
{
|
{
|
||||||
if (FD_ISSET(i->first, &rdset))
|
if (FD_ISSET(i->second.sessionData->GetSocket(), &rdset))
|
||||||
{
|
{
|
||||||
retSession = i->second;
|
retSession = i->second;
|
||||||
break;
|
break;
|
||||||
@@ -206,6 +206,21 @@ SessionManager::GetSessionByUniquePlayerId(unsigned uniqueId) const
|
|||||||
return tmpSession;
|
return tmpSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SessionManager::GetSocketForSession(SessionId session, SOCKET &outSocket)
|
||||||
|
{
|
||||||
|
bool retVal = false;
|
||||||
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
|
SessionMap::iterator pos = m_sessionMap.find(session);
|
||||||
|
|
||||||
|
if (pos != m_sessionMap.end())
|
||||||
|
{
|
||||||
|
outSocket = pos->second.sessionData->GetSocket();
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
PlayerDataList
|
PlayerDataList
|
||||||
SessionManager::GetPlayerDataList() const
|
SessionManager::GetPlayerDataList() const
|
||||||
{
|
{
|
||||||
@@ -361,7 +376,7 @@ SessionManager::SendToAllSessions(SenderThread &sender, boost::shared_ptr<NetPac
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SessionManager::SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SOCKET except, SessionData::State state)
|
SessionManager::SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionId except, SessionData::State state)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
boost::mutex::scoped_lock lock(m_sessionMapMutex);
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public:
|
|||||||
virtual ~NetContext();
|
virtual ~NetContext();
|
||||||
|
|
||||||
virtual SOCKET GetSocket() const = 0;
|
virtual SOCKET GetSocket() const = 0;
|
||||||
virtual u_int32_t GetId() const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#ifndef _SENDERCALLBACK_H_
|
#ifndef _SENDERCALLBACK_H_
|
||||||
#define _SENDERCALLBACK_H_
|
#define _SENDERCALLBACK_H_
|
||||||
|
|
||||||
|
#include <net/sessiondata.h>
|
||||||
#include <net/socket_helper.h>
|
#include <net/socket_helper.h>
|
||||||
|
|
||||||
class SenderCallback
|
class SenderCallback
|
||||||
@@ -28,7 +29,8 @@ class SenderCallback
|
|||||||
public:
|
public:
|
||||||
virtual ~SenderCallback();
|
virtual ~SenderCallback();
|
||||||
|
|
||||||
virtual void SignalNetError(SOCKET sock, int errorID, int osErrorID) = 0;
|
virtual bool GetSocketForSession(SessionId session, SOCKET &outSocket) = 0;
|
||||||
|
virtual void SignalNetError(SessionId session, int errorID, int osErrorID) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <core/thread.h>
|
#include <core/thread.h>
|
||||||
#include <net/socket_helper.h>
|
#include <net/socket_helper.h>
|
||||||
|
#include <net/sessiondata.h>
|
||||||
#include <net/netpacket.h>
|
#include <net/netpacket.h>
|
||||||
#include <net/sendercallback.h>
|
#include <net/sendercallback.h>
|
||||||
|
|
||||||
@@ -40,25 +41,25 @@ public:
|
|||||||
SenderThread(SenderCallback &cb);
|
SenderThread(SenderCallback &cb);
|
||||||
virtual ~SenderThread();
|
virtual ~SenderThread();
|
||||||
|
|
||||||
void Send(SOCKET sock, boost::shared_ptr<NetPacket> packet);
|
void Send(SessionId session, boost::shared_ptr<NetPacket> packet);
|
||||||
void Send(SOCKET sock, const NetPacketList &packetList);
|
void Send(SessionId session, const NetPacketList &packetList);
|
||||||
|
|
||||||
void SendLowPrio(SOCKET sock, boost::shared_ptr<NetPacket> packet);
|
void SendLowPrio(SessionId session, boost::shared_ptr<NetPacket> packet);
|
||||||
void SendLowPrio(SOCKET sock, const NetPacketList &packetList);
|
void SendLowPrio(SessionId session, const NetPacketList &packetList);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::pair<boost::shared_ptr<NetPacket>, SOCKET> SendData;
|
typedef std::pair<boost::shared_ptr<NetPacket>, SessionId> SendData;
|
||||||
typedef std::deque<SendData> SendDataDeque;
|
typedef std::deque<SendData> SendDataDeque;
|
||||||
|
|
||||||
// Main function of the thread.
|
// Main function of the thread.
|
||||||
virtual void Main();
|
virtual void Main();
|
||||||
|
|
||||||
void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SOCKET sock, boost::shared_ptr<NetPacket> packet);
|
void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SessionId session, boost::shared_ptr<NetPacket> packet);
|
||||||
void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SOCKET sock, const NetPacketList &packetList);
|
void InternalStore(SendDataDeque &sendQueue, unsigned maxQueueSize, SessionId session, const NetPacketList &packetList);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SOCKET m_curSocket;
|
SessionId m_curSession;
|
||||||
|
|
||||||
std::deque<SendData> m_outBuf;
|
std::deque<SendData> m_outBuf;
|
||||||
mutable boost::mutex m_outBufMutex;
|
mutable boost::mutex m_outBufMutex;
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public:
|
|||||||
virtual ~ServerContext();
|
virtual ~ServerContext();
|
||||||
|
|
||||||
virtual SOCKET GetSocket() const;
|
virtual SOCKET GetSocket() const;
|
||||||
virtual u_int32_t GetId() const;
|
|
||||||
|
|
||||||
void SetSocket(SOCKET sockfd);
|
void SetSocket(SOCKET sockfd);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
class SenderThread;
|
class SenderThread;
|
||||||
class ReceiverHelper;
|
class ReceiverHelper;
|
||||||
class ServerLobbyThread;
|
class ServerLobbyThread;
|
||||||
class ServerSenderCallback;
|
class GameSenderCallback;
|
||||||
class ServerGameState;
|
class ServerGameState;
|
||||||
class ConfigFile;
|
class ConfigFile;
|
||||||
struct GameData;
|
struct GameData;
|
||||||
@@ -112,7 +112,7 @@ protected:
|
|||||||
const StartData &GetStartData() const;
|
const StartData &GetStartData() const;
|
||||||
void SetStartData(const StartData &startData);
|
void SetStartData(const StartData &startData);
|
||||||
|
|
||||||
ServerSenderCallback &GetSenderCallback();
|
GameSenderCallback &GetSenderCallback();
|
||||||
GuiInterface &GetGui();
|
GuiInterface &GetGui();
|
||||||
|
|
||||||
unsigned GetNextGameNum();
|
unsigned GetNextGameNum();
|
||||||
@@ -135,7 +135,7 @@ private:
|
|||||||
ServerLobbyThread &m_lobbyThread;
|
ServerLobbyThread &m_lobbyThread;
|
||||||
std::auto_ptr<ReceiverHelper> m_receiver;
|
std::auto_ptr<ReceiverHelper> m_receiver;
|
||||||
std::auto_ptr<SenderThread> m_sender;
|
std::auto_ptr<SenderThread> m_sender;
|
||||||
std::auto_ptr<ServerSenderCallback> m_senderCallback;
|
boost::shared_ptr<GameSenderCallback> m_senderCallback;
|
||||||
GuiInterface &m_gui;
|
GuiInterface &m_gui;
|
||||||
|
|
||||||
const GameData m_gameData;
|
const GameData m_gameData;
|
||||||
@@ -161,6 +161,7 @@ friend class ServerGameStateDealCardsDelay;
|
|||||||
friend class ServerGameStateShowCardsDelay;
|
friend class ServerGameStateShowCardsDelay;
|
||||||
friend class ServerGameStateNextHandDelay;
|
friend class ServerGameStateNextHandDelay;
|
||||||
friend class ServerGameStateNextGameDelay;
|
friend class ServerGameStateNextGameDelay;
|
||||||
|
friend class GameSenderCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public:
|
|||||||
|
|
||||||
void RemoveGame(unsigned id);
|
void RemoveGame(unsigned id);
|
||||||
|
|
||||||
|
bool GetSocketForSession(SessionId session, SOCKET &outSocket);
|
||||||
|
|
||||||
u_int32_t GetNextUniquePlayerId();
|
u_int32_t GetNextUniquePlayerId();
|
||||||
u_int32_t GetNextGameId();
|
u_int32_t GetNextGameId();
|
||||||
ServerCallback &GetCallback();
|
ServerCallback &GetCallback();
|
||||||
@@ -82,7 +84,7 @@ protected:
|
|||||||
typedef std::deque<SessionWrapper> SessionQueue;
|
typedef std::deque<SessionWrapper> SessionQueue;
|
||||||
typedef std::list<SessionWrapper> SessionList;
|
typedef std::list<SessionWrapper> SessionList;
|
||||||
typedef std::list<std::pair<boost::timers::portable::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
typedef std::list<std::pair<boost::timers::portable::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
||||||
typedef std::map<SOCKET, boost::timers::portable::microsec_timer> InitTimerSessionMap;
|
typedef std::map<SessionId, boost::timers::portable::microsec_timer> InitTimerSessionMap;
|
||||||
typedef std::map<unsigned, boost::shared_ptr<ServerGameThread> > GameMap;
|
typedef std::map<unsigned, boost::shared_ptr<ServerGameThread> > GameMap;
|
||||||
typedef std::list<unsigned> RemoveGameList;
|
typedef std::list<unsigned> RemoveGameList;
|
||||||
|
|
||||||
@@ -121,9 +123,9 @@ protected:
|
|||||||
void CleanupSessionMap();
|
void CleanupSessionMap();
|
||||||
|
|
||||||
void CloseSessionDelayed(SessionWrapper session);
|
void CloseSessionDelayed(SessionWrapper session);
|
||||||
void SendError(SOCKET s, int errorCode);
|
void SendError(SessionId s, int errorCode);
|
||||||
void SendJoinGameFailed(SOCKET s, int reason);
|
void SendJoinGameFailed(SessionId s, int reason);
|
||||||
void SendGameList(SOCKET s);
|
void SendGameList(SessionId s);
|
||||||
void BroadcastStatisticsUpdate();
|
void BroadcastStatisticsUpdate();
|
||||||
|
|
||||||
SenderThread &GetSender();
|
SenderThread &GetSender();
|
||||||
@@ -165,7 +167,7 @@ private:
|
|||||||
|
|
||||||
std::auto_ptr<ReceiverHelper> m_receiver;
|
std::auto_ptr<ReceiverHelper> m_receiver;
|
||||||
std::auto_ptr<SenderThread> m_sender;
|
std::auto_ptr<SenderThread> m_sender;
|
||||||
std::auto_ptr<ServerSenderCallback> m_senderCallback;
|
boost::shared_ptr<ServerSenderCallback> m_senderCallback;
|
||||||
GuiInterface &m_gui;
|
GuiInterface &m_gui;
|
||||||
AvatarManager &m_avatarManager;
|
AvatarManager &m_avatarManager;
|
||||||
|
|
||||||
@@ -174,6 +176,7 @@ private:
|
|||||||
u_int32_t m_curGameId;
|
u_int32_t m_curGameId;
|
||||||
|
|
||||||
u_int32_t m_curUniquePlayerId;
|
u_int32_t m_curUniquePlayerId;
|
||||||
|
u_int32_t m_curSessionId;
|
||||||
mutable boost::mutex m_curUniquePlayerIdMutex;
|
mutable boost::mutex m_curUniquePlayerIdMutex;
|
||||||
|
|
||||||
unsigned m_totalPlayersLoggedIn;
|
unsigned m_totalPlayersLoggedIn;
|
||||||
|
|||||||
+13
-4
@@ -26,17 +26,26 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#define SESSION_ID_INIT 0
|
#define INVALID_SESSION 0
|
||||||
|
#define SESSION_ID_INIT INVALID_SESSION
|
||||||
|
#define SESSION_ID_GENERIC 0xFFFFFFFF
|
||||||
|
|
||||||
|
typedef unsigned SessionId;
|
||||||
|
/*struct SessionId
|
||||||
|
{
|
||||||
|
unsigned id;
|
||||||
|
};*/
|
||||||
|
|
||||||
|
|
||||||
class SessionData
|
class SessionData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum State { Init, ReceivingAvatar, Established, Game };
|
enum State { Init, ReceivingAvatar, Established, Game };
|
||||||
|
|
||||||
SessionData(SOCKET sockfd, unsigned id);
|
SessionData(SOCKET sockfd, SessionId id);
|
||||||
~SessionData();
|
~SessionData();
|
||||||
|
|
||||||
unsigned GetId() const;
|
SessionId GetId() const;
|
||||||
State GetState() const;
|
State GetState() const;
|
||||||
void SetState(State state);
|
void SetState(State state);
|
||||||
|
|
||||||
@@ -53,7 +62,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
SOCKET m_sockfd;
|
SOCKET m_sockfd;
|
||||||
const unsigned m_id;
|
const SessionId m_id;
|
||||||
State m_state;
|
State m_state;
|
||||||
std::string m_clientAddr;
|
std::string m_clientAddr;
|
||||||
ReceiveBuffer m_receiveBuffer;
|
ReceiveBuffer m_receiveBuffer;
|
||||||
|
|||||||
@@ -51,13 +51,15 @@ public:
|
|||||||
|
|
||||||
void AddSession(boost::shared_ptr<SessionData> sessionData); // new Sessions without player data
|
void AddSession(boost::shared_ptr<SessionData> sessionData); // new Sessions without player data
|
||||||
void AddSession(SessionWrapper session);
|
void AddSession(SessionWrapper session);
|
||||||
void SetSessionPlayerData(SOCKET session, boost::shared_ptr<PlayerData> playerData);
|
void SetSessionPlayerData(SessionId session, boost::shared_ptr<PlayerData> playerData);
|
||||||
void RemoveSession(SOCKET session);
|
void RemoveSession(SessionId session);
|
||||||
|
|
||||||
SessionWrapper Select(unsigned timeoutMsec);
|
SessionWrapper Select(unsigned timeoutMsec);
|
||||||
SessionWrapper GetSessionByPlayerName(const std::string playerName) const;
|
SessionWrapper GetSessionByPlayerName(const std::string playerName) const;
|
||||||
SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const;
|
SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const;
|
||||||
|
|
||||||
|
bool GetSocketForSession(SessionId session, SOCKET &outSocket);
|
||||||
|
|
||||||
PlayerDataList GetPlayerDataList() const;
|
PlayerDataList GetPlayerDataList() const;
|
||||||
PlayerIdList GetPlayerIdList() const;
|
PlayerIdList GetPlayerIdList() const;
|
||||||
bool IsPlayerConnected(const std::string &playerName) const;
|
bool IsPlayerConnected(const std::string &playerName) const;
|
||||||
@@ -72,11 +74,11 @@ public:
|
|||||||
unsigned GetRawSessionCount();
|
unsigned GetRawSessionCount();
|
||||||
|
|
||||||
void SendToAllSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionData::State state);
|
void SendToAllSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionData::State state);
|
||||||
void SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SOCKET except, SessionData::State state);
|
void SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionId except, SessionData::State state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
typedef std::map<SOCKET, SessionWrapper> SessionMap;
|
typedef std::map<SessionId, SessionWrapper> SessionMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user