Error messages are shown when joining a network game fails. Still need to handle players which left and kicking players.
This commit is contained in:
@@ -357,26 +357,34 @@ ClientStateWaitSession::~ClientStateWaitSession()
|
||||
int
|
||||
ClientStateWaitSession::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->ToNetPacketJoinGameAck())
|
||||
if (tmpPacket.get())
|
||||
{
|
||||
// Initialise game configuration.
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
tmpPacket->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
|
||||
client.SetGameData(joinGameAckData.gameData);
|
||||
if (tmpPacket->ToNetPacketJoinGameAck())
|
||||
{
|
||||
// Everything is fine - we joined the game.
|
||||
// Initialize game configuration.
|
||||
NetPacketJoinGameAck::Data joinGameAckData;
|
||||
tmpPacket->ToNetPacketJoinGameAck()->GetData(joinGameAckData);
|
||||
client.SetGameData(joinGameAckData.gameData);
|
||||
|
||||
client.SetState(ClientStateWaitGame::Instance());
|
||||
retVal = MSG_SOCK_SESSION_DONE;
|
||||
}
|
||||
else // TODO: handle error packet
|
||||
{
|
||||
retVal = MSG_SOCK_INTERNAL_PENDING;
|
||||
client.SetState(ClientStateWaitGame::Instance());
|
||||
retVal = MSG_SOCK_SESSION_DONE;
|
||||
}
|
||||
else if (tmpPacket->ToNetPacketError())
|
||||
{
|
||||
// Server reported an error.
|
||||
NetPacketError::Data errorData;
|
||||
tmpPacket->ToNetPacketError()->GetData(errorData);
|
||||
// Show the error.
|
||||
throw ClientException(errorData.errorCode, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@@ -412,7 +420,7 @@ ClientStateWaitGame::Process(ClientThread &client)
|
||||
if (tmpPacket.get() && tmpPacket->ToNetPacketGameStart())
|
||||
{
|
||||
client.SetState(ClientStateFinal::Instance());
|
||||
retVal = MSG_SOCK_GAME_START;
|
||||
retVal = MSG_NET_GAME_START;
|
||||
}
|
||||
else // TODO: handle error packet
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ ClientThread::Main()
|
||||
GetCallback().SignalNetClientGameInfo(msg);
|
||||
|
||||
// Additionally signal the start of the game.
|
||||
if (msg == MSG_SOCK_GAME_START)
|
||||
if (msg == MSG_NET_GAME_START)
|
||||
GetCallback().SignalNetClientGameStart(GetGameData());
|
||||
}
|
||||
}
|
||||
|
||||
+172
-126
@@ -27,23 +27,25 @@ using namespace std;
|
||||
|
||||
#define ADD_PADDING(x) ((((x) + 3) >> 2) << 2)
|
||||
|
||||
#define NET_TYPE_JOIN_GAME 1
|
||||
#define NET_TYPE_JOIN_GAME_ACK 2
|
||||
#define NET_TYPE_JOIN_GAME_ERROR 3
|
||||
#define NET_TYPE_PLAYER_JOINED 4
|
||||
#define NET_TYPE_PLAYER_LEFT 5
|
||||
#define NET_TYPE_GAME_START 6
|
||||
#define NET_TYPE_JOIN_GAME 0x0001
|
||||
#define NET_TYPE_JOIN_GAME_ACK 0x0002
|
||||
#define NET_TYPE_PLAYER_JOINED 0x0003
|
||||
#define NET_TYPE_PLAYER_LEFT 0x0004
|
||||
#define NET_TYPE_GAME_START 0x0005
|
||||
|
||||
#define NET_PLAYER_FLAG_HUMAN 0x01
|
||||
#define NET_TYPE_ERROR 0x0400
|
||||
|
||||
#define NET_JOIN_ERR_UNSUPPORTED_VERSION 0x01
|
||||
#define NET_JOIN_ERR_SERVER_FULL 0x02
|
||||
#define NET_JOIN_ERR_GAME_RUNNING 0x03
|
||||
#define NET_JOIN_ERR_INVALID_PASSWORD 0x04
|
||||
#define NET_JOIN_ERR_OTHER 0xFF
|
||||
#define NET_PLAYER_FLAG_HUMAN 0x01
|
||||
|
||||
#define NET_VERSION_MAJOR 1
|
||||
#define NET_VERSION_MINOR 0
|
||||
#define NET_ERR_JOIN_GAME_VERSION_NOT_SUPPORTED 0x0001
|
||||
#define NET_ERR_JOIN_GAME_SERVER_FULL 0x0002
|
||||
#define NET_ERR_JOIN_GAME_ALREADY_RUNNING 0x0003
|
||||
#define NET_ERR_JOIN_GAME_INVALID_PASSWORD 0x0004
|
||||
#define NET_ERR_JOIN_GAME_PLAYER_NAME_IN_USE 0x0005
|
||||
#define NET_ERR_JOIN_GAME_INVALID_PLAYER_NAME 0x0006
|
||||
#define NET_ERR_GENERAL_INVALID_PACKET 0xFF01
|
||||
#define NET_ERR_GENERAL_INVALID_STATE 0xFF02
|
||||
#define NET_ERR_OTHER 0xFFFF
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 2)
|
||||
@@ -112,6 +114,13 @@ struct NetPacketGameStartData
|
||||
u_int16_t yourCards[2];
|
||||
};
|
||||
|
||||
struct NetPacketErrorData
|
||||
{
|
||||
NetPacketHeader head;
|
||||
u_int16_t reason;
|
||||
u_int16_t reserved;
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#else
|
||||
@@ -149,6 +158,9 @@ NetPacket::Create(char *data, unsigned &dataSize)
|
||||
case NET_TYPE_GAME_START:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
|
||||
break;
|
||||
case NET_TYPE_ERROR:
|
||||
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketError);
|
||||
break;
|
||||
}
|
||||
if (tmpPacket.get())
|
||||
tmpPacket->SetRawData(tmpHeader);
|
||||
@@ -242,14 +254,14 @@ NetPacket::ToNetPacketJoinGameAck() const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketJoinGameError *
|
||||
NetPacket::ToNetPacketJoinGameError() const
|
||||
const NetPacketGameStart *
|
||||
NetPacket::ToNetPacketGameStart() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const NetPacketGameStart *
|
||||
NetPacket::ToNetPacketGameStart() const
|
||||
const NetPacketError *
|
||||
NetPacket::ToNetPacketError() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -321,9 +333,9 @@ NetPacketJoinGame::SetData(const NetPacketJoinGame::Data &inData)
|
||||
u_int16_t passwordLen = (u_int16_t)inData.password.length();
|
||||
|
||||
if (!playerNameLen || playerNameLen > MAX_NAME_SIZE)
|
||||
throw NetException(ERR_SOCK_INVALID_NAME_STR, 0);
|
||||
throw NetException(ERR_NET_INVALID_PLAYER_NAME, 0);
|
||||
if (passwordLen > MAX_PASSWORD_SIZE)
|
||||
throw NetException(ERR_SOCK_INVALID_PWD_STR, 0);
|
||||
throw NetException(ERR_NET_INVALID_PASSWORD_STR, 0);
|
||||
|
||||
// Resize the packet so that the data fits in.
|
||||
Resize((u_int16_t)
|
||||
@@ -347,6 +359,9 @@ NetPacketJoinGame::GetData(NetPacketJoinGame::Data &outData) const
|
||||
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
outData.versionMajor = ntohs(tmpData->requestedVersionMajor);
|
||||
outData.versionMinor = ntohs(tmpData->requestedVersionMinor);
|
||||
|
||||
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
|
||||
|
||||
u_int16_t passwordLen = ntohs(tmpData->passwordLength);
|
||||
@@ -366,17 +381,26 @@ NetPacketJoinGame::Check(const NetPacketHeader* data) const
|
||||
assert(data);
|
||||
|
||||
u_int16_t dataLen = ntohs(data->length);
|
||||
if (dataLen < sizeof(NetPacketJoinGameData)
|
||||
|| dataLen > sizeof(NetPacketJoinGameData) + MAX_NAME_SIZE + MAX_PASSWORD_SIZE)
|
||||
if (dataLen < sizeof(NetPacketJoinGameData))
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
|
||||
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)data;
|
||||
if (dataLen !=
|
||||
int passwordLength = ntohs(tmpData->passwordLength);
|
||||
int playerNameLength = ntohs(tmpData->playerNameLength);
|
||||
// Generous checking - larger packets are allowed.
|
||||
if (dataLen <
|
||||
sizeof(NetPacketJoinGameData)
|
||||
+ ADD_PADDING(ntohs(tmpData->passwordLength))
|
||||
+ ADD_PADDING(ntohs(tmpData->playerNameLength)))
|
||||
+ ADD_PADDING(passwordLength)
|
||||
+ ADD_PADDING(playerNameLength))
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
// Check string sizes.
|
||||
if (passwordLength > MAX_PASSWORD_SIZE
|
||||
|| !playerNameLength
|
||||
|| playerNameLength > MAX_NAME_SIZE)
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
@@ -458,107 +482,6 @@ NetPacketJoinGameAck::Check(const NetPacketHeader* data) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketJoinGameError::NetPacketJoinGameError()
|
||||
: NetPacket(NET_TYPE_JOIN_GAME_ERROR, sizeof(NetPacketJoinGameErrorData))
|
||||
{
|
||||
}
|
||||
|
||||
NetPacketJoinGameError::~NetPacketJoinGameError()
|
||||
{
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
NetPacketJoinGameError::Clone() const
|
||||
{
|
||||
boost::shared_ptr<NetPacket> newPacket(new NetPacketJoinGameError);
|
||||
try
|
||||
{
|
||||
newPacket->SetRawData(GetRawData());
|
||||
} catch (const NetException &)
|
||||
{
|
||||
// Need to return the new packet anyway.
|
||||
}
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketJoinGameError::SetData(const NetPacketJoinGameError::Data &inData)
|
||||
{
|
||||
NetPacketJoinGameErrorData *tmpData = (NetPacketJoinGameErrorData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
switch (inData.reason)
|
||||
{
|
||||
case JOIN_UNSUPPORTED_VERSION :
|
||||
tmpData->errorReason = htons(NET_JOIN_ERR_UNSUPPORTED_VERSION);
|
||||
break;
|
||||
case JOIN_SERVER_FULL :
|
||||
tmpData->errorReason = htons(NET_JOIN_ERR_SERVER_FULL);
|
||||
break;
|
||||
case JOIN_GAME_RUNNING :
|
||||
tmpData->errorReason = htons(NET_JOIN_ERR_GAME_RUNNING);
|
||||
break;
|
||||
case JOIN_INVALID_PASSWORD :
|
||||
tmpData->errorReason = htons(NET_JOIN_ERR_INVALID_PASSWORD);
|
||||
break;
|
||||
default :
|
||||
tmpData->errorReason = htons(NET_JOIN_ERR_OTHER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketJoinGameError::GetData(NetPacketJoinGameError::Data &outData) const
|
||||
{
|
||||
NetPacketJoinGameErrorData *tmpData = (NetPacketJoinGameErrorData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
switch (ntohs(tmpData->errorReason))
|
||||
{
|
||||
case NET_JOIN_ERR_UNSUPPORTED_VERSION :
|
||||
outData.reason = JOIN_UNSUPPORTED_VERSION;
|
||||
break;
|
||||
case NET_JOIN_ERR_SERVER_FULL :
|
||||
outData.reason = JOIN_SERVER_FULL;
|
||||
break;
|
||||
case NET_JOIN_ERR_GAME_RUNNING :
|
||||
outData.reason = JOIN_GAME_RUNNING;
|
||||
break;
|
||||
case NET_JOIN_ERR_INVALID_PASSWORD :
|
||||
outData.reason = JOIN_INVALID_PASSWORD;
|
||||
break;
|
||||
default :
|
||||
outData.reason = JOIN_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const NetPacketJoinGameError *
|
||||
NetPacketJoinGameError::ToNetPacketJoinGameError() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketJoinGameError::Check(const NetPacketHeader* data) const
|
||||
{
|
||||
assert(data);
|
||||
|
||||
u_int16_t dataLen = ntohs(data->length);
|
||||
if (dataLen < sizeof(NetPacketJoinGameErrorData))
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
|
||||
NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData();
|
||||
if (tmpData->yourCards[0] > 51 || tmpData->yourCards[1] > 51)
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketGameStart::NetPacketGameStart()
|
||||
: NetPacket(NET_TYPE_GAME_START, sizeof(NetPacketGameStartData))
|
||||
{
|
||||
@@ -628,3 +551,126 @@ NetPacketGameStart::Check(const NetPacketHeader* data) const
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NetPacketError::NetPacketError()
|
||||
: NetPacket(NET_TYPE_ERROR, sizeof(NetPacketErrorData))
|
||||
{
|
||||
}
|
||||
|
||||
NetPacketError::~NetPacketError()
|
||||
{
|
||||
}
|
||||
|
||||
boost::shared_ptr<NetPacket>
|
||||
NetPacketError::Clone() const
|
||||
{
|
||||
boost::shared_ptr<NetPacket> newPacket(new NetPacketError);
|
||||
try
|
||||
{
|
||||
newPacket->SetRawData(GetRawData());
|
||||
} catch (const NetException &)
|
||||
{
|
||||
// Need to return the new packet anyway.
|
||||
}
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketError::SetData(const NetPacketError::Data &inData)
|
||||
{
|
||||
NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
switch (inData.errorCode)
|
||||
{
|
||||
// Join Game Errors.
|
||||
case ERR_NET_VERSION_NOT_SUPPORTED :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_VERSION_NOT_SUPPORTED);
|
||||
break;
|
||||
case ERR_NET_SERVER_FULL :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_SERVER_FULL);
|
||||
break;
|
||||
case ERR_NET_GAME_ALREADY_RUNNING :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_ALREADY_RUNNING);
|
||||
break;
|
||||
case ERR_NET_INVALID_PASSWORD :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_INVALID_PASSWORD);
|
||||
break;
|
||||
case ERR_NET_PLAYER_NAME_IN_USE :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_PLAYER_NAME_IN_USE);
|
||||
break;
|
||||
case ERR_NET_INVALID_PLAYER_NAME :
|
||||
tmpData->reason = htons(NET_ERR_JOIN_GAME_INVALID_PLAYER_NAME);
|
||||
break;
|
||||
// General Errors.
|
||||
case ERR_SOCK_INVALID_PACKET :
|
||||
tmpData->reason = htons(NET_ERR_GENERAL_INVALID_PACKET);
|
||||
break;
|
||||
case ERR_SOCK_INVALID_STATE :
|
||||
tmpData->reason = htons(NET_ERR_GENERAL_INVALID_STATE);
|
||||
break;
|
||||
default :
|
||||
tmpData->reason = htons(NET_ERR_OTHER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketError::GetData(NetPacketError::Data &outData) const
|
||||
{
|
||||
NetPacketErrorData *tmpData = (NetPacketErrorData *)GetRawData();
|
||||
assert(tmpData);
|
||||
|
||||
switch (ntohs(tmpData->reason))
|
||||
{
|
||||
// Join Game Errors.
|
||||
case NET_ERR_JOIN_GAME_VERSION_NOT_SUPPORTED :
|
||||
outData.errorCode = ERR_NET_VERSION_NOT_SUPPORTED;
|
||||
break;
|
||||
case NET_ERR_JOIN_GAME_SERVER_FULL :
|
||||
outData.errorCode = ERR_NET_SERVER_FULL;
|
||||
break;
|
||||
case NET_ERR_JOIN_GAME_ALREADY_RUNNING :
|
||||
outData.errorCode = ERR_NET_GAME_ALREADY_RUNNING;
|
||||
break;
|
||||
case NET_ERR_JOIN_GAME_INVALID_PASSWORD :
|
||||
outData.errorCode = ERR_NET_INVALID_PASSWORD;
|
||||
break;
|
||||
case NET_ERR_JOIN_GAME_PLAYER_NAME_IN_USE :
|
||||
outData.errorCode = ERR_NET_PLAYER_NAME_IN_USE;
|
||||
break;
|
||||
case NET_ERR_JOIN_GAME_INVALID_PLAYER_NAME :
|
||||
outData.errorCode = ERR_NET_INVALID_PLAYER_NAME;
|
||||
break;
|
||||
// General Errors.
|
||||
case NET_ERR_GENERAL_INVALID_PACKET :
|
||||
outData.errorCode = ERR_SOCK_INVALID_PACKET;
|
||||
break;
|
||||
case NET_ERR_GENERAL_INVALID_STATE :
|
||||
outData.errorCode = ERR_SOCK_INVALID_STATE;
|
||||
break;
|
||||
default :
|
||||
outData.errorCode = ERR_SOCK_INTERNAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const NetPacketError *
|
||||
NetPacketError::ToNetPacketError() const
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
NetPacketError::Check(const NetPacketHeader* data) const
|
||||
{
|
||||
assert(data);
|
||||
|
||||
u_int16_t dataLen = ntohs(data->length);
|
||||
if (dataLen < sizeof(NetPacketErrorData))
|
||||
{
|
||||
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include <net/senderthread.h>
|
||||
#include <net/netpacket.h>
|
||||
#include <net/socket_msg.h>
|
||||
#include <core/rand.h>
|
||||
#include <gamedata.h>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -56,13 +56,20 @@ ServerRecvStateInit::~ServerRecvStateInit()
|
||||
void
|
||||
ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr<ConnectData> connData)
|
||||
{
|
||||
boost::shared_ptr<SessionData> sessionData(new SessionData);
|
||||
// Create a random session id.
|
||||
// This id can be used to reconnect to the server if the connection was lost.
|
||||
unsigned sessionId;
|
||||
RandomBytes((unsigned char *)&sessionId, sizeof(sessionId)); // TODO: check for collisions.
|
||||
|
||||
// Create a new session.
|
||||
boost::shared_ptr<SessionData> sessionData(new SessionData(sessionId));
|
||||
server.AddSession(connData, sessionData);
|
||||
}
|
||||
|
||||
int
|
||||
ServerRecvStateInit::Process(ServerRecvThread &server)
|
||||
{
|
||||
int retVal = MSG_SOCK_INIT_DONE;
|
||||
SOCKET recvSock = server.Select();
|
||||
|
||||
if (recvSock != INVALID_SOCKET)
|
||||
@@ -73,73 +80,86 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
|
||||
// Ignore if no session / no packet.
|
||||
if (packet.get() && session.get())
|
||||
{
|
||||
if (session->GetState() == SessionData::Init)
|
||||
// Session should be in initial state.
|
||||
if (session->GetState() != SessionData::Init)
|
||||
{
|
||||
// Only accept join game packets.
|
||||
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
|
||||
if (tmpPacket)
|
||||
{
|
||||
NetPacketJoinGame::Data joinGameData;
|
||||
tmpPacket->GetData(joinGameData);
|
||||
// Check the server password.
|
||||
if (server.CheckPassword(joinGameData.password))
|
||||
{
|
||||
PlayerDataList &playerDataList = server.GetPlayerDataList();
|
||||
// Check whether this player is already connected.
|
||||
PlayerDataList::const_iterator player_i = playerDataList.begin();
|
||||
PlayerDataList::const_iterator player_end = playerDataList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
if ((*player_i)->GetName() == joinGameData.playerName)
|
||||
break;
|
||||
++player_i;
|
||||
}
|
||||
if (player_i == player_end)
|
||||
{
|
||||
// Create player data object.
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(new PlayerData(m_curUniquePlayerId++));
|
||||
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 = playerDataList.size();
|
||||
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);
|
||||
|
||||
// Store player data in list.
|
||||
playerDataList.push_back(tmpPlayerData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO send error message, duplicate name
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO send error message, invalid password
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO send error message, invalid packet
|
||||
}
|
||||
server.SendError(ERR_SOCK_INVALID_STATE, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
else
|
||||
|
||||
// Only accept join game packets.
|
||||
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
|
||||
if (!tmpPacket)
|
||||
{
|
||||
// TODO send error message, invalid state
|
||||
server.SendError(ERR_SOCK_INVALID_PACKET, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
NetPacketJoinGame::Data joinGameData;
|
||||
tmpPacket->GetData(joinGameData);
|
||||
|
||||
// Check the protocol version.
|
||||
if (joinGameData.versionMajor != NET_VERSION_MAJOR)
|
||||
{
|
||||
server.SendError(ERR_NET_VERSION_NOT_SUPPORTED, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check the server password.
|
||||
if (!server.CheckPassword(joinGameData.password))
|
||||
{
|
||||
server.SendError(ERR_NET_INVALID_PASSWORD, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
PlayerDataList &playerDataList = server.GetPlayerDataList();
|
||||
|
||||
// Check the number of players.
|
||||
if (playerDataList.size() >= (size_t)server.GetGameData().numberOfPlayers)
|
||||
{
|
||||
server.SendError(ERR_NET_SERVER_FULL, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Check whether this player is already connected.
|
||||
PlayerDataList::const_iterator player_i = playerDataList.begin();
|
||||
PlayerDataList::const_iterator player_end = playerDataList.end();
|
||||
while (player_i != player_end)
|
||||
{
|
||||
if ((*player_i)->GetName() == joinGameData.playerName)
|
||||
break;
|
||||
++player_i;
|
||||
}
|
||||
if (player_i != player_end)
|
||||
{
|
||||
server.SendError(ERR_NET_PLAYER_NAME_IN_USE, recvSock);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Create player data object.
|
||||
boost::shared_ptr<PlayerData> tmpPlayerData(new PlayerData(m_curUniquePlayerId++));
|
||||
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 = playerDataList.size();
|
||||
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);
|
||||
|
||||
// Store player data in list.
|
||||
playerDataList.push_back(tmpPlayerData);
|
||||
}
|
||||
}
|
||||
return MSG_SOCK_INIT_DONE;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -66,6 +66,16 @@ ServerRecvThread::Init(const string &pwd, const GameData &gameData)
|
||||
*m_gameData = gameData;
|
||||
}
|
||||
|
||||
void
|
||||
ServerRecvThread::SendError(int errorCode, SOCKET s)
|
||||
{
|
||||
boost::shared_ptr<NetPacket> packet(new NetPacketError);
|
||||
NetPacketError::Data errorData;
|
||||
errorData.errorCode = errorCode;
|
||||
static_cast<NetPacketError *>(packet.get())->SetData(errorData);
|
||||
GetSender().Send(packet, s);
|
||||
}
|
||||
|
||||
void
|
||||
ServerRecvThread::SendToAllPlayers(boost::shared_ptr<NetPacket> packet)
|
||||
{
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#include <net/sessiondata.h>
|
||||
|
||||
SessionData::SessionData()
|
||||
: m_id(SESSION_ID_INIT), m_state(SessionData::Init)
|
||||
SessionData::SessionData(unsigned id)
|
||||
: m_id(id), m_state(SessionData::Init)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user