Redone network packet abstraction. Prepared for easy access to packet data.

This commit is contained in:
lotodore
2007-04-08 16:18:20 +00:00
parent 6f458ec012
commit 2f5c8d7da1
14 changed files with 656 additions and 230 deletions
+5 -6
View File
@@ -45,6 +45,9 @@ Additional values for major version = 1:
[Future versions will include the name of the game, to support
multiple games per server.]
Player Flags:
0x01 set: Player is human
Server Reply: Join Game ACK
@@ -83,7 +86,7 @@ Server Reply: Join Game Error
Reason:
0x01 - Version not supported
0x02 - Server full
0x03 - Game has already started
0x03 - Game is already running
0x04 - Invalid Password
0xFF - Other cause
@@ -95,7 +98,7 @@ Server Notification: Player Joined
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type = 4 | Message Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Player ID | Player Number |
| Player ID | Player Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Player Flags | Name Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -105,10 +108,6 @@ Server Notification: Player Joined
/ | padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Player Flags:
0x01 set: Player is human
Server Notification: Player Left
-6
View File
@@ -4223,17 +4223,11 @@
<property name="text" >
<string>Create Network Game ...</string>
</property>
<property name="visible" >
<bool>false</bool>
</property>
</action>
<action name="actionJoin_network_Game" >
<property name="text" >
<string>Join Network Game ...</string>
</property>
<property name="visible" >
<bool>false</bool>
</property>
</action>
<action name="actionFullScreen" >
<property name="text" >
+5
View File
@@ -55,6 +55,10 @@ public:
{return &m_clientSockaddr;}
sockaddr_storage *GetClientSockaddr()
{return &m_clientSockaddr;}
const std::string &GetPlayerName() const
{return m_playerName;}
void SetPlayerName(const std::string &playerName)
{m_playerName = playerName;}
int GetClientSockaddrSize() const
{return m_addrFamily == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);}
@@ -66,6 +70,7 @@ private:
unsigned m_serverPort;
std::string m_password;
sockaddr_storage m_clientSockaddr;
std::string m_playerName; // TODO: use player interface.
};
#endif
+6 -1
View File
@@ -41,7 +41,12 @@ public:
// Set the parameters. Does not do any error checking.
// Error checking will be done during connect
// (i.e. after starting the thread).
void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &pwd);
void Init(
const std::string &serverAddress,
unsigned serverPort,
bool ipv6,
const std::string &pwd,
const std::string &playerName);
ClientCallback &GetCallback();
+12 -3
View File
@@ -320,8 +320,17 @@ ClientStateStartSession::~ClientStateStartSession()
int
ClientStateStartSession::Process(ClientThread &client)
{
boost::shared_ptr<NetPacket> packet(new NetPacketInit(10));
client.GetSender().Send(packet, client.GetContext().GetSocket());
ClientContext &context = client.GetContext();
NetPacketJoinGame::Data initData;
initData.password = context.GetPassword();
initData.playerName = context.GetPlayerName();
initData.ptype = PLAYER_TYPE_HUMAN; // TODO
boost::shared_ptr<NetPacket> packet(new NetPacketJoinGame);
((NetPacketJoinGame *)packet.get())->SetData(initData);
client.GetSender().Send(packet, context.GetSocket());
client.SetState(ClientStateWaitSession::Instance());
@@ -355,7 +364,7 @@ ClientStateWaitSession::Process(ClientThread &client)
boost::shared_ptr<NetPacket> tmpPacket = client.GetReceiver().Recv(context.GetSocket());
if (tmpPacket.get() && tmpPacket->ToNetPacketInitAck())
if (tmpPacket.get() && tmpPacket->ToNetPacketJoinGameAck())
{
client.SetState(ClientStateWaitGame::Instance());
retVal = MSG_SOCK_SESSION_DONE;
+3 -1
View File
@@ -64,7 +64,8 @@ ClientThread::~ClientThread()
}
void
ClientThread::Init(const string &serverAddress, unsigned serverPort, bool ipv6, const string &pwd)
ClientThread::Init(
const string &serverAddress, unsigned serverPort, bool ipv6, const string &pwd, const string &playerName)
{
if (IsRunning())
return; // TODO: throw exception
@@ -75,6 +76,7 @@ ClientThread::Init(const string &serverAddress, unsigned serverPort, bool ipv6,
context.SetServerAddr(serverAddress);
context.SetServerPort(serverPort);
context.SetPassword(pwd);
context.SetPlayerName(playerName);
}
ClientCallback &
+493 -98
View File
@@ -21,18 +21,229 @@
#include <net/netexception.h>
#include <net/socket_msg.h>
NetPacket::~NetPacket()
#include <string>
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_PLAYER_FLAG_HUMAN 0x01
#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_VERSION_MAJOR 1
#define NET_VERSION_MINOR 0
#ifdef _MSC_VER
#pragma pack(push, 2)
#else
#pragma align 2
#endif
struct NetPacketHeader
{
u_int16_t type;
u_int16_t length;
};
struct NetPacketJoinGameData
{
NetPacketHeader head;
u_int16_t requestedVersionMajor;
u_int16_t requestedVersionMinor;
u_int16_t passwordLength;
u_int16_t playerFlags;
u_int16_t playerNameLength;
u_int16_t reserved;
char password[1];
};
struct NetPacketJoinGameAckData
{
NetPacketHeader head;
u_int32_t sessionId;
u_int16_t playerId;
u_int16_t playerNumber;
u_int16_t numberOfPlayers;
u_int16_t smallBlind;
u_int16_t handsBeforeRaise;
u_int16_t gameSpeed;
u_int32_t startCash;
};
struct NetPacketJoinGameErrorData
{
NetPacketHeader head;
u_int16_t errorReason;
u_int16_t reserved;
};
struct NetPacketPlayerJoinedData
{
NetPacketHeader head;
u_int16_t playerId;
u_int16_t playerNumber;
u_int16_t playerFlags;
u_int16_t playerNameLength;
char playerName[1];
};
struct NetPacketPlayerLeftData
{
NetPacketHeader head;
u_int16_t playerId;
u_int16_t reserved;
};
struct NetPacketGameStartData
{
NetPacketHeader head;
u_int16_t yourCards[2];
};
#ifdef _MSC_VER
#pragma pack(pop)
#else
#pragma align 0
#endif
boost::shared_ptr<NetPacket>
NetPacket::Create(char *data, unsigned &dataSize)
{
boost::shared_ptr<NetPacket> tmpPacket;
NetPacketHeader *tmpHeader = (NetPacketHeader *)data;
u_int16_t tmpLen = ntohs(tmpHeader->length);
// Check size restrictions.
if (tmpLen < sizeof(NetPacketHeader)
|| tmpLen > MAX_PACKET_SIZE)
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
else if (dataSize >= tmpLen)
{
// OK - we have a complete packet. Construct a corresponding object.
try
{
switch(ntohs(tmpHeader->type))
{
case NET_TYPE_JOIN_GAME:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketJoinGame);
break;
case NET_TYPE_JOIN_GAME_ACK:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketJoinGameAck);
break;
case NET_TYPE_GAME_START:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
break;
}
if (tmpPacket.get())
tmpPacket->SetRawData(tmpHeader);
} catch (const NetException &)
{
tmpPacket.reset();
}
if (tmpLen < dataSize)
{
dataSize -= tmpLen;
memmove(data, data + tmpLen, dataSize);
}
else
dataSize = 0;
}
return tmpPacket;
}
const NetPacketInit *
NetPacket::ToNetPacketInit() const
NetPacket::NetPacket(u_int16_t type, u_int16_t initialLen)
: m_data(NULL)
{
assert(initialLen >= sizeof(NetPacketHeader));
m_data = (NetPacketHeader *)malloc(initialLen);
assert(m_data);
memset(m_data, 0, initialLen);
m_data->type = htons(type);
m_data->length = htons(initialLen);
}
NetPacket::~NetPacket()
{
if (m_data)
free(m_data);
}
const NetPacketHeader *
NetPacket::GetRawData() const
{
assert(m_data);
return m_data;
}
NetPacketHeader *
NetPacket::GetRawData()
{
assert(m_data);
return m_data;
}
void
NetPacket::SetRawData(const NetPacketHeader *p)
{
if (!p)
return;
assert(m_data);
u_int16_t tmpLen = ntohs(p->length);
if (ntohs(p->type) != GetType())
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
// Check whether the data is valid.
Check(p);
// Resize makes sure m_data is large enough.
Resize(tmpLen);
memcpy(m_data, p, tmpLen);
}
u_int16_t
NetPacket::GetType() const
{
return ntohs(GetRawData()->type);
}
u_int16_t
NetPacket::GetLen() const
{
return ntohs(GetRawData()->length);
}
const NetPacketJoinGame *
NetPacket::ToNetPacketJoinGame() const
{
return NULL;
}
const NetPacketInitAck *
NetPacket::ToNetPacketInitAck() const
const NetPacketJoinGameAck *
NetPacket::ToNetPacketJoinGameAck() const
{
return NULL;
}
const NetPacketJoinGameError *
NetPacket::ToNetPacketJoinGameError() const
{
return NULL;
}
@@ -43,38 +254,59 @@ NetPacket::ToNetPacketGameStart() const
return NULL;
}
void
NetPacket::Resize(u_int16_t newLen)
{
assert(m_data);
u_int16_t oldLen = GetLen();
if (newLen != oldLen)
{
if (newLen < sizeof(NetPacketHeader))
throw NetException(ERR_SOCK_INTERNAL, 0);
else
{
NetPacketHeader *newData = (NetPacketHeader *)malloc(newLen);
if (!newData)
throw NetException(ERR_SOCK_INTERNAL, 0);
else
{
// Copy as much data as possible.
memcpy(newData, m_data, newLen > oldLen ? oldLen : newLen);
// Initialize new data to 0.
if (newLen > oldLen)
memset(((unsigned char *)newData) + oldLen, 0, newLen - oldLen);
// Set new len.
newData->length = htons(newLen);
// Switch over to new data.
free(m_data);
m_data = newData;
}
}
}
}
//-----------------------------------------------------------------------------
NetPacketInit::NetPacketInit()
NetPacketJoinGame::NetPacketJoinGame()
: NetPacket(NET_TYPE_JOIN_GAME, sizeof(NetPacketJoinGameData))
{
Init();
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData();
assert(tmpData);
tmpData->requestedVersionMajor = htons(NET_VERSION_MAJOR);
tmpData->requestedVersionMinor = htons(NET_VERSION_MINOR);
}
NetPacketInit::NetPacketInit(u_int32_t value)
NetPacketJoinGame::~NetPacketJoinGame()
{
Init();
m_data.test = htonl(value);
}
NetPacketInit::~NetPacketInit()
{
}
void
NetPacketInit::Init()
{
m_data.head.type = htons(NET_TYPE_INIT);
m_data.head.length = htons(sizeof(m_data));
m_data.test = htonl(0);
}
boost::shared_ptr<NetPacket>
NetPacketInit::Clone() const
NetPacketJoinGame::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketInit);
boost::shared_ptr<NetPacket> newPacket(new NetPacketJoinGame);
try
{
newPacket->SetData(GetData());
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
@@ -82,63 +314,92 @@ NetPacketInit::Clone() const
return newPacket;
}
const NetPacketHeader *
NetPacketInit::GetData() const
void
NetPacketJoinGame::SetData(const NetPacketJoinGame::Data &inData)
{
return (const NetPacketHeader *)&m_data;
u_int16_t playerNameLen = (u_int16_t)inData.playerName.length();
u_int16_t passwordLen = (u_int16_t)inData.password.length();
if (!playerNameLen || playerNameLen > MAX_NAME_SIZE)
throw NetException(ERR_SOCK_INVALID_NAME_STR, 0);
if (passwordLen > MAX_PASSWORD_SIZE)
throw NetException(ERR_SOCK_INVALID_PWD_STR, 0);
// Resize the packet so that the data fits in.
Resize((u_int16_t)
(sizeof(NetPacketJoinGameData) + ADD_PADDING(playerNameLen) + ADD_PADDING(passwordLen)));
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData();
assert(tmpData);
// Set the data.
tmpData->passwordLength = htons(passwordLen);
tmpData->playerFlags = htons((inData.ptype == PLAYER_TYPE_HUMAN) ? NET_PLAYER_FLAG_HUMAN : 0);
tmpData->playerNameLength = htons(playerNameLen);
memcpy(tmpData->password, inData.password.c_str(), passwordLen);
memcpy(tmpData->password + ADD_PADDING(passwordLen), inData.playerName.c_str(), playerNameLen);
}
void
NetPacketInit::SetData(const NetPacketHeader *p)
NetPacketJoinGame::GetData(NetPacketJoinGame::Data &outData) const
{
u_int16_t tmpLen = ntohs(p->length);
if (tmpLen != sizeof(m_data)
|| ntohs(p->type) != NET_TYPE_INIT)
{
throw NetException(ERR_SOCK_INTERNAL, 0);
}
// We assume that the data is valid. Validity has already been checked.
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)GetRawData();
assert(tmpData);
memcpy(&m_data, p, tmpLen);
outData.ptype = (ntohs(tmpData->playerFlags) & NET_PLAYER_FLAG_HUMAN) ? PLAYER_TYPE_HUMAN : PLAYER_TYPE_COMPUTER;
u_int16_t passwordLen = ntohs(tmpData->passwordLength);
outData.password = string(tmpData->password, passwordLen);
outData.playerName = string(tmpData->password + ADD_PADDING(passwordLen), ntohs(tmpData->playerNameLength));
}
const NetPacketInit *
NetPacketInit::ToNetPacketInit() const
const NetPacketJoinGame *
NetPacketJoinGame::ToNetPacketJoinGame() const
{
return this;
}
void
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)
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
NetPacketJoinGameData *tmpData = (NetPacketJoinGameData *)data;
if (dataLen !=
sizeof(NetPacketJoinGameData)
+ ADD_PADDING(ntohs(tmpData->passwordLength))
+ ADD_PADDING(ntohs(tmpData->playerNameLength)))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
}
//-----------------------------------------------------------------------------
NetPacketInitAck::NetPacketInitAck()
{
Init();
}
NetPacketInitAck::NetPacketInitAck(u_int32_t value)
{
Init();
m_data.test = htonl(value);
}
NetPacketInitAck::~NetPacketInitAck()
NetPacketJoinGameAck::NetPacketJoinGameAck()
: NetPacket(NET_TYPE_JOIN_GAME_ACK, sizeof(NetPacketJoinGameAckData))
{
}
void
NetPacketInitAck::Init()
NetPacketJoinGameAck::~NetPacketJoinGameAck()
{
m_data.head.type = htons(NET_TYPE_INIT_ACK);
m_data.head.length = htons(sizeof(m_data));
m_data.test = htonl(0);
}
boost::shared_ptr<NetPacket>
NetPacketInitAck::Clone() const
NetPacketJoinGameAck::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketInitAck);
boost::shared_ptr<NetPacket> newPacket(new NetPacketJoinGameAck);
try
{
newPacket->SetData(GetData());
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
@@ -146,63 +407,176 @@ NetPacketInitAck::Clone() const
return newPacket;
}
const NetPacketHeader *
NetPacketInitAck::GetData() const
void
NetPacketJoinGameAck::SetData(const NetPacketJoinGameAck::Data &inData)
{
return (const NetPacketHeader *)&m_data;
NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData();
assert(tmpData);
tmpData->sessionId = htonl(inData.sessionId);
tmpData->playerId = htons(inData.playerId);
tmpData->playerNumber = htons(inData.playerNumber);
tmpData->numberOfPlayers = htons(inData.numberOfPlayers);
tmpData->smallBlind = htons(inData.smallBlind);
tmpData->handsBeforeRaise = htons(inData.handsBeforeRaise);
tmpData->gameSpeed = htons(inData.gameSpeed);
tmpData->startCash = htonl(inData.startCash);
}
void
NetPacketInitAck::SetData(const NetPacketHeader *p)
NetPacketJoinGameAck::GetData(NetPacketJoinGameAck::Data &outData) const
{
u_int16_t tmpLen = ntohs(p->length);
if (tmpLen != sizeof(m_data)
|| ntohs(p->type) != NET_TYPE_INIT_ACK)
{
throw NetException(ERR_SOCK_INTERNAL, 0);
}
NetPacketJoinGameAckData *tmpData = (NetPacketJoinGameAckData *)GetRawData();
assert(tmpData);
memcpy(&m_data, p, tmpLen);
outData.sessionId = ntohl(tmpData->sessionId);
outData.playerId = ntohs(tmpData->playerId);
outData.playerNumber = ntohs(tmpData->playerNumber);
outData.numberOfPlayers = ntohs(tmpData->numberOfPlayers);
outData.smallBlind = ntohs(tmpData->smallBlind);
outData.handsBeforeRaise = ntohs(tmpData->handsBeforeRaise);
outData.gameSpeed = ntohs(tmpData->gameSpeed);
outData.startCash = ntohl(tmpData->startCash);
}
const NetPacketInitAck *
NetPacketInitAck::ToNetPacketInitAck() const
const NetPacketJoinGameAck *
NetPacketJoinGameAck::ToNetPacketJoinGameAck() const
{
return this;
}
void
NetPacketJoinGameAck::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketJoinGameAckData))
{
throw NetException(ERR_SOCK_INVALID_PACKET, 0);
}
// TODO: maybe some semantic checks
}
//-----------------------------------------------------------------------------
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))
{
Init();
}
NetPacketGameStart::NetPacketGameStart(u_int32_t value)
{
Init();
m_data.test = htonl(value);
}
NetPacketGameStart::~NetPacketGameStart()
{
}
void
NetPacketGameStart::Init()
{
m_data.head.type = htons(NET_TYPE_GAME_START);
m_data.head.length = htons(sizeof(m_data));
m_data.test = htonl(0);
}
boost::shared_ptr<NetPacket>
NetPacketGameStart::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketGameStart);
try
{
newPacket->SetData(GetData());
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
@@ -210,23 +584,24 @@ NetPacketGameStart::Clone() const
return newPacket;
}
const NetPacketHeader *
NetPacketGameStart::GetData() const
void
NetPacketGameStart::SetData(const NetPacketGameStart::Data &inData)
{
return (NetPacketHeader *)&m_data;
NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData();
assert(tmpData);
tmpData->yourCards[0] = htons(inData.yourCards[0]);
tmpData->yourCards[1] = htons(inData.yourCards[1]);
}
void
NetPacketGameStart::SetData(const NetPacketHeader *p)
NetPacketGameStart::GetData(NetPacketGameStart::Data &outData) const
{
u_int16_t tmpLen = ntohs(p->length);
if (tmpLen != sizeof(m_data)
|| ntohs(p->type) != NET_TYPE_GAME_START)
{
throw NetException(ERR_SOCK_INTERNAL, 0);
}
NetPacketGameStartData *tmpData = (NetPacketGameStartData *)GetRawData();
assert(tmpData);
memcpy(&m_data, p, tmpLen);
outData.yourCards[0] = ntohs(tmpData->yourCards[0]);
outData.yourCards[1] = ntohs(tmpData->yourCards[1]);
}
const NetPacketGameStart *
@@ -235,3 +610,23 @@ NetPacketGameStart::ToNetPacketGameStart() const
return this;
}
void
NetPacketGameStart::Check(const NetPacketHeader* data) const
{
assert(data);
u_int16_t dataLen = ntohs(data->length);
if (dataLen < sizeof(NetPacketGameStartData))
{
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);
}
}
//-----------------------------------------------------------------------------
+8 -40
View File
@@ -98,50 +98,18 @@ ReceiverHelper::InternalGetPacket()
// This is necessary, because we use TCP.
// Packets may be received in multiple chunks or
// several packets may be received at once.
if (m_tmpInBufSize >= sizeof(NetPacketHeader))
if (m_tmpInBufSize >= MIN_PACKET_SIZE)
{
NetPacketHeader *tmpHeader = (NetPacketHeader *)m_tmpInBuf;
u_int16_t tmpLen = ntohs(tmpHeader->length);
if (tmpLen < sizeof(NetPacketHeader)
|| tmpLen > MAX_PACKET_SIZE)
try
{
// Invalid packet - reset input buffer.
// This call will also handle the memmove stuff, i.e.
// buffering for partial packets.
tmpPacket = NetPacket::Create(m_tmpInBuf, m_tmpInBufSize);
} catch (const NetException &)
{
// Reset buffer on error.
m_tmpInBufSize = 0;
}
else if (m_tmpInBufSize >= tmpLen)
{
tmpPacket = InternalCreateNetPacket(tmpHeader);
m_tmpInBufSize -= tmpLen;
}
}
return tmpPacket;
}
boost::shared_ptr<NetPacket>
ReceiverHelper::InternalCreateNetPacket(const NetPacketHeader *p)
{
boost::shared_ptr<NetPacket> tmpPacket;
try
{
switch(ntohs(p->type))
{
case NET_TYPE_INIT:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketInit);
break;
case NET_TYPE_INIT_ACK:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketInitAck);
break;
case NET_TYPE_GAME_START:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameStart);
break;
}
if (tmpPacket.get())
tmpPacket->SetData(p);
} catch (const NetException &)
{
tmpPacket.reset();
}
return tmpPacket;
}
+3 -3
View File
@@ -71,11 +71,11 @@ SenderThread::Main()
if (IS_VALID_SOCKET(tmpData.second))
m_curSocket = tmpData.second;
u_int16_t tmpLen = ntohs(tmpData.first->GetData()->length);
u_int16_t tmpLen = tmpData.first->GetLen();
if (tmpLen <= MAX_PACKET_SIZE)
{
m_tmpOutBufSize = tmpLen;
memcpy(m_tmpOutBuf, tmpData.first->GetData(), m_tmpOutBufSize);
memcpy(m_tmpOutBuf, tmpData.first->GetRawData(), tmpLen);
}
}
}
@@ -109,7 +109,7 @@ SenderThread::Main()
}
else if ((unsigned)bytesSent < m_tmpOutBufSize)
{
m_tmpOutBufSize = m_tmpOutBufSize - (unsigned)bytesSent;
m_tmpOutBufSize -= (unsigned)bytesSent;
memmove(m_tmpOutBuf, m_tmpOutBuf + bytesSent, m_tmpOutBufSize);
}
else
+6 -3
View File
@@ -72,10 +72,13 @@ ServerRecvStateInit::Process(ServerRecvThread &server)
{
if (session->GetState() == SessionData::Init)
{
// Only accept init packets.
if (packet->ToNetPacketInit())
// Only accept join game packets.
const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame();
if (tmpPacket)
{
boost::shared_ptr<NetPacket> answer(new NetPacketInitAck);
// TODO: check password
// TODO: display name
boost::shared_ptr<NetPacket> answer(new NetPacketJoinGameAck);
server.GetSender().Send(answer, recvSock);
session->SetState(SessionData::Established);
}
+104 -66
View File
@@ -25,128 +25,166 @@
#include <boost/shared_ptr.hpp>
#include <net/socket_helper.h>
#define MAX_PACKET_SIZE 256
#define MIN_PACKET_SIZE 4
#define MAX_PACKET_SIZE 256
#define MAX_NAME_SIZE 64
#define MAX_PASSWORD_SIZE 64
#define NET_TYPE_INIT 0
#define NET_TYPE_INIT_ACK 1
#define NET_TYPE_GAME_START 2
#ifdef _MSC_VER
#pragma pack(push, 2)
#else
#pragma align 2
#endif
struct NetPacketHeader
// TODO: move this somewhere else
enum PlayerType
{
u_int16_t type;
u_int16_t length;
PLAYER_TYPE_COMPUTER,
PLAYER_TYPE_HUMAN
};
struct NetPacketInitData
enum JoinGameErrorReason
{
NetPacketHeader head;
u_int32_t test;
JOIN_UNSUPPORTED_VERSION,
JOIN_SERVER_FULL,
JOIN_GAME_RUNNING,
JOIN_INVALID_PASSWORD,
JOIN_UNKNOWN
};
struct NetPacketInitAckData
{
NetPacketHeader head;
u_int32_t test;
};
struct NetPacketHeader;
struct NetPacketGameStartData
{
NetPacketHeader head;
u_int32_t test;
};
#ifdef _MSC_VER
#pragma pack(pop)
#else
#pragma align 0
#endif
class NetPacketInit;
class NetPacketInitAck;
class NetPacketJoinGame;
class NetPacketJoinGameAck;
class NetPacketJoinGameError;
class NetPacketGameStart;
class NetPacket
{
public:
static boost::shared_ptr<NetPacket> Create(char *data, unsigned &dataSize);
NetPacket(u_int16_t type, u_int16_t initialLen);
virtual ~NetPacket();
virtual boost::shared_ptr<NetPacket> Clone() const = 0;
virtual void SetData(const NetPacketHeader *p) = 0;
virtual const NetPacketHeader *GetData() const = 0;
const NetPacketHeader *GetRawData() const;
NetPacketHeader *GetRawData();
void SetRawData(const NetPacketHeader *p);
virtual const NetPacketInit *ToNetPacketInit() const;
virtual const NetPacketInitAck *ToNetPacketInitAck() const;
u_int16_t GetType() const;
u_int16_t GetLen() const;
virtual const NetPacketJoinGame *ToNetPacketJoinGame() const;
virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const;
virtual const NetPacketJoinGameError *ToNetPacketJoinGameError() const;
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
protected:
virtual void Check(const NetPacketHeader* data) const = 0;
void Resize(u_int16_t newLen);
private:
NetPacketHeader *m_data;
};
class NetPacketInit : public NetPacket
class NetPacketJoinGame : public NetPacket
{
public:
NetPacketInit();
NetPacketInit(u_int32_t value);
virtual ~NetPacketInit();
struct Data
{
PlayerType ptype;
std::string playerName;
std::string password;
};
NetPacketJoinGame();
virtual ~NetPacketJoinGame();
virtual boost::shared_ptr<NetPacket> Clone() const;
virtual const NetPacketHeader *GetData() const;
virtual void SetData(const NetPacketHeader *p);
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketInit *ToNetPacketInit() const;
virtual const NetPacketJoinGame *ToNetPacketJoinGame() const;
protected:
void Init();
private:
NetPacketInitData m_data;
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketInitAck : public NetPacket
class NetPacketJoinGameAck : public NetPacket
{
public:
NetPacketInitAck();
NetPacketInitAck(u_int32_t value);
virtual ~NetPacketInitAck();
struct Data
{
u_int32_t sessionId;
u_int16_t playerId;
u_int16_t playerNumber;
u_int16_t numberOfPlayers;
u_int16_t smallBlind;
u_int16_t handsBeforeRaise;
u_int16_t gameSpeed;
u_int32_t startCash;
};
NetPacketJoinGameAck();
virtual ~NetPacketJoinGameAck();
virtual boost::shared_ptr<NetPacket> Clone() const;
virtual const NetPacketHeader *GetData() const;
virtual void SetData(const NetPacketHeader *p);
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketInitAck *ToNetPacketInitAck() const;
virtual const NetPacketJoinGameAck *ToNetPacketJoinGameAck() const;
protected:
void Init();
private:
NetPacketInitAckData m_data;
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketJoinGameError : public NetPacket
{
public:
struct Data
{
JoinGameErrorReason reason;
};
NetPacketJoinGameError();
virtual ~NetPacketJoinGameError();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketJoinGameError *ToNetPacketJoinGameError() const;
protected:
virtual void Check(const NetPacketHeader* data) const;
};
class NetPacketGameStart : public NetPacket
{
public:
struct Data
{
u_int16_t yourCards[2];
};
NetPacketGameStart();
NetPacketGameStart(u_int32_t value);
virtual ~NetPacketGameStart();
virtual boost::shared_ptr<NetPacket> Clone() const;
virtual const NetPacketHeader *GetData() const;
virtual void SetData(const NetPacketHeader *p);
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketGameStart *ToNetPacketGameStart() const;
protected:
void Init();
private:
NetPacketGameStartData m_data;
virtual void Check(const NetPacketHeader* data) const;
};
#endif
-1
View File
@@ -45,7 +45,6 @@ public:
protected:
boost::shared_ptr<NetPacket> InternalGetPacket();
boost::shared_ptr<NetPacket> InternalCreateNetPacket(const NetPacketHeader *p);
private:
+3
View File
@@ -36,6 +36,9 @@
#define ERR_SOCK_SEND_FAILED 14
#define ERR_SOCK_CONN_RESET 15
#define ERR_SOCK_CONN_EXISTS 16
#define ERR_SOCK_INVALID_NAME_STR 17
#define ERR_SOCK_INVALID_PWD_STR 18
#define ERR_SOCK_INVALID_PACKET 19
// This is an internal message which is not reported.
#define MSG_SOCK_INTERNAL_PENDING 0
+8 -2
View File
@@ -64,7 +64,12 @@ void Session::startNetworkClient(const string &serverAddress, unsigned serverPor
if (myNetClient || !myGui)
return; // TODO: throw exception
myNetClient = new ClientThread(*myGui);
myNetClient->Init(serverAddress, serverPort, ipv6, pwd);
myNetClient->Init(
serverAddress,
serverPort,
ipv6,
pwd,
myConfig->readConfigString("MyName"));
myNetClient->Run();
}
@@ -77,7 +82,8 @@ void Session::startNetworkClientForLocalServer()
"localhost",
myConfig->readConfigInt("ServerPort"),
myConfig->readConfigInt("ServerUseIpv6") == 1,
myConfig->readConfigString("ServerPassword"));
myConfig->readConfigString("ServerPassword"),
myConfig->readConfigString("MyName"));
myNetClient->Run();
}