Replace CInitMessage by more specific classes.

This commit is contained in:
joris 2013-04-01 12:54:48 +02:00
parent 829e03df97
commit 9e6958e19b
5 changed files with 676 additions and 272 deletions

View file

@ -51,8 +51,9 @@
class CNetworkHost
{
public:
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
CNetworkHost() { Clear(); }
size_t Serialize(unsigned char *) const;
size_t Deserialize(const unsigned char *p);
void Clear();
static size_t Size() { return 4 + 2 + 2 + NetPlayerNameSize; }
@ -64,15 +65,15 @@ public:
char PlyName[NetPlayerNameSize]; /// Name of player
};
/**
** Multiplayer game setup menu state
*/
class CServerSetup
{
public:
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
CServerSetup() { Clear(); }
size_t Serialize(unsigned char *p) const;
size_t Deserialize(const unsigned char *p);
static size_t Size() { return 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 * PlayerMax + 1 * PlayerMax + 1 * PlayerMax; }
void Clear() {
ResourcesOption = 0;
@ -111,7 +112,7 @@ enum _ic_message_subtype_ {
ICMEngineMismatch, /// Stratagus engine version doesn't match
ICMProtocolMismatch, /// Network protocol version doesn't match
ICMEngineConfMismatch, /// Engine configuration isn't identical
ICMEngineConfMismatch, /// UNUSED:Engine configuration isn't identical
ICMMapUidMismatch, /// MAP UID doesn't match
ICMGameFull, /// No player slots available
@ -132,36 +133,145 @@ enum _ic_message_subtype_ {
ICMIAH /// Client answers I am here
};
/**
** Network init message.
**
** @todo Transfering the same data in each message is waste of bandwidth.
** I mean the versions and the UID ...
*/
class CInitMessage
class CInitMessage_Header
{
public:
CInitMessage();
CInitMessage(uint8_t type, uint8_t subtype);
CInitMessage_Header() {}
CInitMessage_Header(unsigned char type, unsigned char subtype) :
type(type),
subtype(subtype)
{}
unsigned char GetType() const { return type; }
unsigned char GetSubType() const { return subtype; }
size_t Serialize(unsigned char *p) const;
size_t Deserialize(const unsigned char *p);
static size_t Size() { return 2; }
private:
unsigned char type;
unsigned char subtype;
};
class CInitMessage_Hello
{
public:
CInitMessage_Hello() {}
explicit CInitMessage_Hello(const char *name);
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return 1 + 1 + 1 + 1 + 4 + 4 + 4 + 4 + 4 + 4 + std::max<size_t>(256u, std::max(CNetworkHost::Size() * PlayerMax, CServerSetup::Size())); }
uint8_t Type; /// Init message type
uint8_t SubType; /// Init message subtype
uint8_t HostsCount; /// Number of hosts
uint8_t padding; /// padding for alignment
static size_t Size() { return CInitMessage_Header::Size() + NetPlayerNameSize + 2 * 4; }
private:
CInitMessage_Header header;
public:
char PlyName[NetPlayerNameSize]; /// Name of player
int32_t Stratagus; /// Stratagus engine version
int32_t Version; /// Network protocol version
uint32_t MapUID; /// UID of map to play. FIXME: add MAP name, path, etc
};
class CInitMessage_Config
{
public:
CInitMessage_Config();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + 4 + PlayerMax * CNetworkHost::Size(); }
private:
CInitMessage_Header header;
public:
int32_t HostsCount; /// Number of hosts
CNetworkHost Hosts[PlayerMax]; /// Participant information
};
class CInitMessage_EngineMismatch
{
public:
CInitMessage_EngineMismatch();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + 4; }
private:
CInitMessage_Header header;
public:
int32_t Stratagus; /// Stratagus engine version
};
class CInitMessage_ProtocolMismatch
{
public:
CInitMessage_ProtocolMismatch();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + 4; }
private:
CInitMessage_Header header;
public:
int32_t Version; /// Network protocol version
};
class CInitMessage_Welcome
{
public:
CInitMessage_Welcome();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + PlayerMax * CNetworkHost::Size() + 2 * 4; }
private:
CInitMessage_Header header;
public:
CNetworkHost hosts[PlayerMax]; /// Participant information
int32_t Lag; /// Lag time
int32_t Updates; /// Update frequency
};
union {
CNetworkHost Hosts[PlayerMax]; /// Participant information
class CInitMessage_Map
{
public:
CInitMessage_Map() {}
CInitMessage_Map(const char *path, uint32_t mapUID);
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + 256 + 4; }
private:
CInitMessage_Header header;
public:
char MapPath[256];
uint32_t MapUID; /// UID of map to play.
};
class CInitMessage_State
{
public:
CInitMessage_State() {}
CInitMessage_State(int type, const CServerSetup &data);
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + CServerSetup::Size(); }
private:
CInitMessage_Header header;
public:
CServerSetup State; /// Server Setup State information
} u;
};
class CInitMessage_Resync
{
public:
CInitMessage_Resync();
const CInitMessage_Header &GetHeader() const { return header; }
const unsigned char *Serialize() const;
void Deserialize(const unsigned char *p);
static size_t Size() { return CInitMessage_Header::Size() + CNetworkHost::Size() * PlayerMax; }
private:
CInitMessage_Header header;
public:
CNetworkHost hosts[PlayerMax]; /// Participant information
};
/**

View file

@ -31,7 +31,6 @@
//@{
#include <stdint.h>
#include "net_message.h"
/*----------------------------------------------------------------------------

View file

@ -84,6 +84,14 @@ int serialize8(unsigned char *buf, int8_t data)
}
return sizeof(data);
}
template <int N>
int serialize(unsigned char *buf, const char (&data)[N])
{
if (buf) {
memcpy(buf, data, N);
}
return N;
}
int deserialize32(const unsigned char *buf, uint32_t *data)
{
@ -115,30 +123,38 @@ int deserialize8(const unsigned char *buf, int8_t *data)
*data = *buf;
return sizeof(*data);
}
template <int N>
int deserialize(const unsigned char *buf, char (&data)[N])
{
memcpy(data, buf, N);
return N;
}
//
// CNetworkHost
//
const unsigned char *CNetworkHost::Serialize() const
size_t CNetworkHost::Serialize(unsigned char *buf) const
{
unsigned char *buf = new unsigned char[CNetworkHost::Size()];
unsigned char *p = buf;
p += serialize32(p, this->Host);
p += serialize16(p, this->Port);
p += serialize16(p, this->PlyNr);
memcpy(p, this->PlyName, sizeof(this->PlyName));
p += serialize(p, this->PlyName);
return buf;
return p - buf;
}
void CNetworkHost::Deserialize(const unsigned char *p)
size_t CNetworkHost::Deserialize(const unsigned char *p)
{
const unsigned char *buf = p;
p += deserialize32(p, &Host);
p += deserialize16(p, &Port);
p += deserialize16(p, &PlyNr);
memcpy(this->PlyName, p, sizeof(this->PlyName));
p += deserialize(p, this->PlyName);
return p - buf;
}
void CNetworkHost::Clear()
@ -158,9 +174,8 @@ void CNetworkHost::SetName(const char *name)
// CServerSetup
//
const unsigned char *CServerSetup::Serialize() const
size_t CServerSetup::Serialize(unsigned char *buf) const
{
unsigned char *buf = new unsigned char[CServerSetup::Size()];
unsigned char *p = buf;
p += serialize8(p, this->ResourcesOption);
@ -180,11 +195,12 @@ const unsigned char *CServerSetup::Serialize() const
for (int i = 0; i < PlayerMax; ++i) {
p += serialize8(p, this->Race[i]);
}
return buf;
return p - buf;
}
void CServerSetup::Deserialize(const unsigned char *p)
size_t CServerSetup::Deserialize(const unsigned char *p)
{
const unsigned char *buf = p;
p += deserialize8(p, &this->ResourcesOption);
p += deserialize8(p, &this->UnitsOption);
p += deserialize8(p, &this->FogOfWar);
@ -202,101 +218,260 @@ void CServerSetup::Deserialize(const unsigned char *p)
for (int i = 0; i < PlayerMax; ++i) {
p += deserialize8(p, &this->Race[i]);
}
return p - buf;
}
//
// CInitMessage
// CInitMessage_Header
//
CInitMessage::CInitMessage()
size_t CInitMessage_Header::Serialize(unsigned char *p) const
{
memset(this, 0, sizeof(CInitMessage));
unsigned char *buf = p;
p += serialize8(p, type);
p += serialize8(p, subtype);
return p - buf;
}
CInitMessage::CInitMessage(uint8_t type, uint8_t subtype)
size_t CInitMessage_Header::Deserialize(const unsigned char *p)
{
this->Type = type;
this->SubType = subtype;
const unsigned char *buf = p;
p += deserialize8(p, &type);
p += deserialize8(p, &subtype);
return p - buf;
}
//
// CInitMessage_Hello
//
CInitMessage_Hello::CInitMessage_Hello(const char *name) :
header(MessageInit_FromClient, ICMHello)
{
strncpy_s(this->PlyName, sizeof(this->PlyName), name, _TRUNCATE);
this->Stratagus = StratagusVersion;
this->Version = NetworkProtocolVersion;
this->Lag = NetworkLag;
this->Updates = NetworkUpdates;
}
const unsigned char *CInitMessage::Serialize() const
const unsigned char *CInitMessage_Hello::Serialize() const
{
unsigned char *buf = new unsigned char[CInitMessage::Size()];
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += serialize8(p, this->Type);
p += serialize8(p, this->SubType);
p += serialize8(p, this->HostsCount);
p += serialize8(p, this->padding);
p += header.Serialize(p);
p += serialize(p, this->PlyName);
p += serialize32(p, this->Stratagus);
p += serialize32(p, this->Version);
p += serialize32(p, this->MapUID);
p += serialize32(p, this->Lag);
p += serialize32(p, this->Updates);
return buf;
}
switch (this->SubType) {
case ICMHello:
case ICMConfig:
case ICMWelcome:
case ICMResync:
case ICMGo:
for (int i = 0; i < PlayerMax; ++i) {
const unsigned char *x = this->u.Hosts[i].Serialize();
memcpy(p, x, CNetworkHost::Size());
p += CNetworkHost::Size();
delete[] x;
}
break;
case ICMMap:
memcpy(p, this->u.MapPath, sizeof(this->u.MapPath));
p += sizeof(this->u.MapPath);
break;
case ICMState: {
const unsigned char *x = this->u.State.Serialize();
memcpy(p, x, CServerSetup::Size());
p += CServerSetup::Size();
delete[] x;
break;
}
void CInitMessage_Hello::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
p += deserialize(p, this->PlyName);
p += deserialize32(p, &this->Stratagus);
p += deserialize32(p, &this->Version);
}
//
// CInitMessage_Config
//
CInitMessage_Config::CInitMessage_Config() :
header(MessageInit_FromServer, ICMConfig)
{
}
const unsigned char *CInitMessage_Config::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
p += serialize32(p, this->HostsCount);
for (int i = 0; i != PlayerMax; ++i) {
p += this->Hosts[i].Serialize(p);
}
return buf;
}
void CInitMessage::Deserialize(const unsigned char *p)
void CInitMessage_Config::Deserialize(const unsigned char *p)
{
p += deserialize8(p, &this->Type);
p += deserialize8(p, &this->SubType);
p += deserialize8(p, &this->HostsCount);
p += deserialize8(p, &this->padding);
p += header.Deserialize(p);
p += deserialize32(p, &this->HostsCount);
for (int i = 0; i != PlayerMax; ++i) {
p += this->Hosts[i].Deserialize(p);
}
}
//
// CInitMessage_EngineMismatch
//
CInitMessage_EngineMismatch::CInitMessage_EngineMismatch() :
header(MessageInit_FromServer, ICMEngineMismatch)
{
this->Stratagus = StratagusVersion;
}
const unsigned char *CInitMessage_EngineMismatch::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
p += serialize32(p, this->Stratagus);
return buf;
}
void CInitMessage_EngineMismatch::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
p += deserialize32(p, &this->Stratagus);
}
//
// CInitMessage_ProtocolMismatch
//
CInitMessage_ProtocolMismatch::CInitMessage_ProtocolMismatch() :
header(MessageInit_FromServer, ICMProtocolMismatch)
{
this->Version = NetworkProtocolVersion;
}
const unsigned char *CInitMessage_ProtocolMismatch::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
p += serialize32(p, this->Version);
return buf;
}
void CInitMessage_ProtocolMismatch::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
p += deserialize32(p, &this->Version);
p += deserialize32(p, &this->MapUID);
}
//
// CInitMessage_Welcome
//
CInitMessage_Welcome::CInitMessage_Welcome() :
header(MessageInit_FromServer, ICMWelcome)
{
this->Lag = NetworkLag;
this->Updates = NetworkUpdates;
}
const unsigned char *CInitMessage_Welcome::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
for (int i = 0; i < PlayerMax; ++i) {
p += this->hosts[i].Serialize(p);
}
p += serialize32(p, this->Lag);
p += serialize32(p, this->Updates);
return buf;
}
void CInitMessage_Welcome::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
for (int i = 0; i < PlayerMax; ++i) {
p += this->hosts[i].Deserialize(p);
}
p += deserialize32(p, &this->Lag);
p += deserialize32(p, &this->Updates);
}
switch (this->SubType) {
case ICMHello:
case ICMConfig:
case ICMWelcome:
case ICMResync:
case ICMGo:
//
// CInitMessage_Map
//
CInitMessage_Map::CInitMessage_Map(const char *path, uint32_t mapUID) :
header(MessageInit_FromServer, ICMMap),
MapUID(mapUID)
{
strncpy_s(MapPath, sizeof(MapPath), path, _TRUNCATE);
}
const unsigned char *CInitMessage_Map::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
p += serialize(p, MapPath);
p += serialize32(p, this->MapUID);
return buf;
}
void CInitMessage_Map::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
p += deserialize(p, this->MapPath);
p += deserialize32(p, &this->MapUID);
}
//
// CInitMessage_State
//
CInitMessage_State::CInitMessage_State(int type, const CServerSetup &data) :
header(type, ICMState),
State(data)
{
}
const unsigned char *CInitMessage_State::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
p += this->State.Serialize(p);
return buf;
}
void CInitMessage_State::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
p += this->State.Deserialize(p);
}
//
// CInitMessage_Resync
//
CInitMessage_Resync::CInitMessage_Resync() :
header(MessageInit_FromServer, ICMResync)
{
}
const unsigned char *CInitMessage_Resync::Serialize() const
{
unsigned char *buf = new unsigned char[Size()];
unsigned char *p = buf;
p += header.Serialize(p);
for (int i = 0; i < PlayerMax; ++i) {
this->u.Hosts[i].Deserialize(p);
p += CNetworkHost::Size();
p += this->hosts[i].Serialize(p);
}
break;
case ICMMap:
memcpy(this->u.MapPath, p, sizeof(this->u.MapPath));
p += sizeof(this->u.MapPath);
break;
case ICMState:
this->u.State.Deserialize(p);
p += CServerSetup::Size();
break;
return buf;
}
void CInitMessage_Resync::Deserialize(const unsigned char *p)
{
p += header.Deserialize(p);
for (int i = 0; i < PlayerMax; ++i) {
p += this->hosts[i].Deserialize(p);
}
}

View file

@ -104,11 +104,11 @@ public:
void MarkClientsAsResync();
void KickClient(int c);
private:
int Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int port);
int Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long host, int port);
void Parse_Resync(const int h);
void Parse_Waiting(const int h);
void Parse_Map(const int h);
void Parse_State(const int h, const CInitMessage &msg);
void Parse_State(const int h, const CInitMessage_State &msg);
void Parse_GoodBye(const int h);
void Parse_SeeYou(const int h);
@ -162,11 +162,12 @@ private:
void Send_Hello(unsigned long tick);
void Send_GoodBye(unsigned long tick);
void NetworkSendRateLimitedClientMessage(const CInitMessage &msg, unsigned long tick, unsigned long msecs);
template <typename T>
void SendRateLimited(const T &msg, unsigned long tick, unsigned long msecs);
void NetClientCheckLocalState();
void SetConfig(const CInitMessage &msg, unsigned long host, int port);
void SetState(const CInitMessage &msg);
void SetConfig(const CInitMessage_Config &msg, unsigned long host, int port);
void SetState(const CInitMessage_State &msg);
void Parse_GameFull();
void Parse_ProtocolMismatch(const unsigned char *buf);
@ -198,14 +199,20 @@ static CClient Client;
** @param host Host to send to (network byte order).
** @param port Port of host to send to (network byte order).
** @param msg The message to send
**
** @todo FIXME: we don't need to put the header into all messages.
** (header = msg->Stratagus ... )
*/
static void NetworkSendICMessage(unsigned long host, int port, const CInitMessage &msg)
template <typename T>
static void NetworkSendICMessage(unsigned long host, int port, const T &msg)
{
const unsigned char *buf = msg.Serialize();
NetSendUDP(NetworkFildes, host, port, buf, CInitMessage::Size());
NetSendUDP(NetworkFildes, host, port, buf, msg.Size());
delete[] buf;
}
void NetworkSendICMessage(unsigned long host, int port, const CInitMessage_Header &msg)
{
unsigned char *buf = new unsigned char [msg.Size()];
msg.Serialize(buf);
NetSendUDP(NetworkFildes, host, port, buf, msg.Size());
delete[] buf;
}
@ -258,13 +265,23 @@ static const char *icmsgsubtypenames[] = {
};
#endif
static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMessage &msg)
template <typename T>
static void NetworkSendICMessage_Log(unsigned long ip, int port, const T &msg)
{
NetworkSendICMessage(ip, port, msg);
DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n"
_C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port)
_C_ icmsgsubtypenames[msg.SubType]);
_C_ icmsgsubtypenames[msg.GetHeader().GetSubType()]);
}
static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMessage_Header &msg)
{
NetworkSendICMessage(ip, port, msg);
DebugPrint("Sending to %d.%d.%d.%d:%d -> %s\n"
_C_ NIPQUAD(ntohl(ip)) _C_ ntohs(port)
_C_ icmsgsubtypenames[msg.GetSubType()]);
}
/**
@ -274,23 +291,46 @@ static void NetworkSendICMessage_Log(unsigned long ip, int port, const CInitMess
** @param tick current tick
** @param msecs microseconds to delay
*/
void CClient::NetworkSendRateLimitedClientMessage(const CInitMessage &msg, unsigned long tick, unsigned long msecs)
template <typename T>
void CClient::SendRateLimited(const T &msg, unsigned long tick, unsigned long msecs)
{
const unsigned long now = tick;
if (now - networkState.LastFrame < msecs) {
return;
}
networkState.LastFrame = now;
if (msg.SubType == lastMsgTypeSent) {
const unsigned char subtype = msg.GetHeader().GetSubType();
if (subtype == lastMsgTypeSent) {
++networkState.MsgCnt;
} else {
networkState.MsgCnt = 0;
lastMsgTypeSent = msg.SubType;
lastMsgTypeSent = subtype;
}
NetworkSendICMessage(serverIP, serverPort, msg);
DebugPrint("[%s] Sending (%s:#%d)\n" _C_
ncconstatenames[networkState.State] _C_
icmsgsubtypenames[msg.SubType] _C_ networkState.MsgCnt);
icmsgsubtypenames[subtype] _C_ networkState.MsgCnt);
}
template<>
void CClient::SendRateLimited<CInitMessage_Header>(const CInitMessage_Header &msg, unsigned long tick, unsigned long msecs)
{
const unsigned long now = tick;
if (now - networkState.LastFrame < msecs) {
return;
}
networkState.LastFrame = now;
const unsigned char subtype = msg.GetSubType();
if (subtype == lastMsgTypeSent) {
++networkState.MsgCnt;
} else {
networkState.MsgCnt = 0;
lastMsgTypeSent = subtype;
}
NetworkSendICMessage(serverIP, serverPort, msg);
DebugPrint("[%s] Sending (%s:#%d)\n" _C_
ncconstatenames[networkState.State] _C_
icmsgsubtypenames[subtype] _C_ networkState.MsgCnt);
}
bool CClient::SetupServerAddress(const std::string &serveraddr, int port)
@ -339,7 +379,7 @@ void CClient::NetClientCheckLocalState()
bool CClient::Update_disconnected()
{
Assert(networkState.State == ccs_disconnected);
const CInitMessage message(MessageInit_FromClient, ICMSeeYou);
const CInitMessage_Header message(MessageInit_FromClient, ICMSeeYou);
// Spew out 5 and trust in God that they arrive
for (int i = 0; i < 5; ++i) {
@ -489,69 +529,65 @@ bool CClient::Update_started(unsigned long tick)
void CClient::Send_Go(unsigned long tick)
{
const CInitMessage message(MessageInit_FromClient, ICMGo);
const CInitMessage_Header message(MessageInit_FromClient, ICMGo);
NetworkSendRateLimitedClientMessage(message, tick, 250);
SendRateLimited(message, tick, 250);
}
void CClient::Send_Config(unsigned long tick)
{
const CInitMessage message(MessageInit_FromClient, ICMConfig);
const CInitMessage_Header message(MessageInit_FromClient, ICMConfig);
NetworkSendRateLimitedClientMessage(message, tick, 250);
SendRateLimited(message, tick, 250);
}
void CClient::Send_MapUidMismatch(unsigned long tick)
{
CInitMessage message(MessageInit_FromClient, ICMMapUidMismatch);
const CInitMessage_Header message(MessageInit_FromClient, ICMMapUidMismatch); // MAP Uid doesn't match
message.MapUID = Map.Info.MapUID; // MAP Uid doesn't match
NetworkSendRateLimitedClientMessage(message, tick, 650);
SendRateLimited(message, tick, 650);
}
void CClient::Send_Map(unsigned long tick)
{
CInitMessage message(MessageInit_FromClient, ICMMap);
CInitMessage_Header message(MessageInit_FromClient, ICMMap);
message.MapUID = Map.Info.MapUID;
NetworkSendRateLimitedClientMessage(message, tick, 650);
SendRateLimited(message, tick, 650);
}
void CClient::Send_Resync(unsigned long tick)
{
const CInitMessage message(MessageInit_FromClient, ICMResync);
const CInitMessage_Header message(MessageInit_FromClient, ICMResync);
NetworkSendRateLimitedClientMessage(message, tick, 450);
SendRateLimited(message, tick, 450);
}
void CClient::Send_State(unsigned long tick)
{
CInitMessage message(MessageInit_FromClient, ICMState);
const CInitMessage_State message(MessageInit_FromClient, LocalSetupState);
message.u.State = LocalSetupState;
message.MapUID = Map.Info.MapUID;
NetworkSendRateLimitedClientMessage(message, tick, 450);
SendRateLimited(message, tick, 450);
}
void CClient::Send_Waiting(unsigned long tick, unsigned long msec)
{
const CInitMessage message(MessageInit_FromClient, ICMWaiting);
NetworkSendRateLimitedClientMessage(message, tick, msec);
const CInitMessage_Header message(MessageInit_FromClient, ICMWaiting);
SendRateLimited(message, tick, msec);
}
void CClient::Send_Hello(unsigned long tick)
{
CInitMessage message(MessageInit_FromClient, ICMHello);
const CInitMessage_Hello message(Parameters::Instance.LocalPlayerName.c_str());
message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str());
NetworkSendRateLimitedClientMessage(message, tick, 500);
SendRateLimited(message, tick, 500);
}
void CClient::Send_GoodBye(unsigned long tick)
{
const CInitMessage message(MessageInit_FromClient, ICMGoodBye);
const CInitMessage_Header message(MessageInit_FromClient, ICMGoodBye);
NetworkSendRateLimitedClientMessage(message, tick, 100);
SendRateLimited(message, tick, 100);
}
/*
@ -576,42 +612,42 @@ bool CClient::Update(unsigned long tick)
return true;
}
void CClient::SetState(const CInitMessage &msg)
void CClient::SetState(const CInitMessage_State &msg)
{
ServerSetupState = msg.u.State;
ServerSetupState = msg.State;
}
void CClient::SetConfig(const CInitMessage &msg, unsigned long host, int port)
void CClient::SetConfig(const CInitMessage_Config &msg, unsigned long host, int port)
{
HostsCount = 0;
for (int i = 0; i < msg.HostsCount - 1; ++i) {
if (msg.u.Hosts[i].Host || msg.u.Hosts[i].Port) {
Hosts[HostsCount] = msg.u.Hosts[i];
if (msg.Hosts[i].Host || msg.Hosts[i].Port) {
Hosts[HostsCount] = msg.Hosts[i];
HostsCount++;
DebugPrint("Client %d = %d.%d.%d.%d:%d [%.*s]\n" _C_
msg.u.Hosts[i].PlyNr _C_ NIPQUAD(ntohl(msg.u.Hosts[i].Host)) _C_
ntohs(msg.u.Hosts[i].Port) _C_
static_cast<int>(sizeof(msg.u.Hosts[i].PlyName)) _C_
msg.u.Hosts[i].PlyName);
msg.Hosts[i].PlyNr _C_ NIPQUAD(ntohl(msg.Hosts[i].Host)) _C_
ntohs(msg.Hosts[i].Port) _C_
static_cast<int>(sizeof(msg.Hosts[i].PlyName)) _C_
msg.Hosts[i].PlyName);
} else { // Own client
NetLocalPlayerNumber = msg.u.Hosts[i].PlyNr;
DebugPrint("SELF %d [%.*s]\n" _C_ msg.u.Hosts[i].PlyNr _C_
static_cast<int>(sizeof(msg.u.Hosts[i].PlyName)) _C_
msg.u.Hosts[i].PlyName);
NetLocalPlayerNumber = msg.Hosts[i].PlyNr;
DebugPrint("SELF %d [%.*s]\n" _C_ msg.Hosts[i].PlyNr _C_
static_cast<int>(sizeof(msg.Hosts[i].PlyName)) _C_
msg.Hosts[i].PlyName);
}
}
// server is last:
Hosts[HostsCount].Host = host;
Hosts[HostsCount].Port = port;
Hosts[HostsCount].PlyNr = msg.u.Hosts[msg.HostsCount - 1].PlyNr;
Hosts[HostsCount].SetName(msg.u.Hosts[msg.HostsCount - 1].PlyName);
Hosts[HostsCount].PlyNr = msg.Hosts[msg.HostsCount - 1].PlyNr;
Hosts[HostsCount].SetName(msg.Hosts[msg.HostsCount - 1].PlyName);
++HostsCount;
NetPlayers = HostsCount + 1;
DebugPrint("Server %d = %d.%d.%d.%d:%d [%.*s]\n" _C_
msg.u.Hosts[msg.HostsCount - 1].PlyNr _C_ NIPQUAD(ntohl(host)) _C_
msg.Hosts[msg.HostsCount - 1].PlyNr _C_ NIPQUAD(ntohl(host)) _C_
ntohs(port) _C_
static_cast<int>(sizeof(msg.u.Hosts[msg.HostsCount - 1].PlyName)) _C_
msg.u.Hosts[msg.HostsCount - 1].PlyName);
static_cast<int>(sizeof(msg.Hosts[msg.HostsCount - 1].PlyName)) _C_
msg.Hosts[msg.HostsCount - 1].PlyName);
// put ourselves to the end, like on the server..
Hosts[HostsCount].Host = 0;
@ -622,14 +658,15 @@ void CClient::SetConfig(const CInitMessage &msg, unsigned long host, int port)
bool CClient::Parse(const unsigned char *buf, unsigned long host, int port)
{
const unsigned char msgtype = buf[0];
CInitMessage_Header header;
header.Deserialize(buf);
if (msgtype != MessageInit_FromServer) {
if (header.GetType() != MessageInit_FromServer) {
return true;
}
// Assert(host == this->serverIP);
// Assert(port == this->serverPort);
const unsigned char msgsubtype = buf[1];
const unsigned char msgsubtype = header.GetSubType();
DebugPrint("Received %s in state %s\n" _C_ icmsgsubtypenames[msgsubtype]
_C_ ncconstatenames[networkState.State]);
@ -733,15 +770,15 @@ void CClient::Parse_Map(const unsigned char *buf)
if (networkState.State != ccs_connected) {
return;
}
CInitMessage msg;
CInitMessage_Map msg;
msg.Deserialize(buf);
if (!IsSafeMapName(msg.u.MapPath)) {
if (!IsSafeMapName(msg.MapPath)) {
fprintf(stderr, "Unsecure map name!\n");
networkState.State = ccs_badmap;
return;
}
NetworkMapName = std::string(msg.u.MapPath, sizeof(msg.u.MapPath));
NetworkMapName = std::string(msg.MapPath, sizeof(msg.MapPath));
std::string mappath = StratagusLibPath + "/" + NetworkMapName;
LoadStratagusMapInfo(mappath);
if (msg.MapUID != Map.Info.MapUID) {
@ -759,13 +796,13 @@ void CClient::Parse_Welcome(const unsigned char *buf)
if (networkState.State != ccs_connecting) {
return;
}
CInitMessage msg;
CInitMessage_Welcome msg;
msg.Deserialize(buf);
networkState.State = ccs_connected;
networkState.MsgCnt = 0;
NetLocalHostsSlot = msg.u.Hosts[0].PlyNr;
Hosts[0].SetName(msg.u.Hosts[0].PlyName); // Name of server player
NetLocalHostsSlot = msg.hosts[0].PlyNr;
Hosts[0].SetName(msg.hosts[0].PlyName); // Name of server player
NetworkLag = msg.Lag;
NetworkUpdates = msg.Updates;
@ -773,7 +810,7 @@ void CClient::Parse_Welcome(const unsigned char *buf)
Hosts[0].Port = serverPort;
for (int i = 1; i < PlayerMax; ++i) {
if (i != NetLocalHostsSlot) {
Hosts[i] = msg.u.Hosts[i];
Hosts[i] = msg.hosts[i];
} else {
Hosts[i].PlyNr = i;
Hosts[i].SetName(Parameters::Instance.LocalPlayerName.c_str());
@ -783,7 +820,7 @@ void CClient::Parse_Welcome(const unsigned char *buf)
void CClient::Parse_State(const unsigned char *buf)
{
CInitMessage msg;
CInitMessage_State msg;
msg.Deserialize(buf);
if (networkState.State == ccs_mapinfo) {
@ -809,7 +846,7 @@ void CClient::Parse_Config(const unsigned char *buf, unsigned long ip, int port)
if (networkState.State != ccs_synced) {
return;
}
CInitMessage msg;
CInitMessage_Config msg;
msg.Deserialize(buf);
SetConfig(msg, ip, port);
@ -822,14 +859,14 @@ void CClient::Parse_Resync(const unsigned char *buf)
if (networkState.State != ccs_async) {
return;
}
CInitMessage msg;
CInitMessage_Resync msg;
msg.Deserialize(buf);
for (int i = 1; i < PlayerMax - 1; ++i) {
if (i != NetLocalHostsSlot) {
Hosts[i] = msg.u.Hosts[i];
Hosts[i] = msg.hosts[i];
} else {
Hosts[i].PlyNr = msg.u.Hosts[i].PlyNr;
Hosts[i].PlyNr = msg.hosts[i].PlyNr;
Hosts[i].SetName(Parameters::Instance.LocalPlayerName.c_str());
}
}
@ -852,7 +889,7 @@ void CClient::Parse_ProtocolMismatch(const unsigned char *buf)
if (networkState.State != ccs_connecting) {
return;
}
CInitMessage msg;
CInitMessage_ProtocolMismatch msg;
msg.Deserialize(buf);
fprintf(stderr, "Incompatible network protocol version "
@ -868,7 +905,7 @@ void CClient::Parse_EngineMismatch(const unsigned char *buf)
if (networkState.State != ccs_connecting) {
return;
}
CInitMessage msg;
CInitMessage_EngineMismatch msg;
msg.Deserialize(buf);
fprintf(stderr, "Incompatible Stratagus version %d <-> %d\n"
@ -885,7 +922,7 @@ void CClient::Parse_EngineMismatch(const unsigned char *buf)
*/
void CClient::Parse_AreYouThere()
{
const CInitMessage message(MessageInit_FromClient, ICMIAH); // IAmHere
const CInitMessage_Header message(MessageInit_FromClient, ICMIAH); // IAmHere
NetworkSendICMessage(serverIP, serverPort, message);
}
@ -930,31 +967,27 @@ void CServer::Init()
void CServer::Send_AreYouThere(const CNetworkHost &host)
{
const CInitMessage message(MessageInit_FromServer, ICMAYT); // AreYouThere
const CInitMessage_Header message(MessageInit_FromServer, ICMAYT); // AreYouThere
NetworkSendICMessage(host.Host, host.Port, message);
}
void CServer::Send_GameFull(unsigned long host, int port)
{
const CInitMessage message(MessageInit_FromServer, ICMGameFull);
const CInitMessage_Header message(MessageInit_FromServer, ICMGameFull);
NetworkSendICMessage_Log(host, port, message);
}
void CServer::Send_Welcome(const CNetworkHost &host, int index)
{
CInitMessage message(MessageInit_FromServer, ICMWelcome);
CInitMessage_Welcome message;
message.u.Hosts[0].PlyNr = index; // Host array slot number
message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); // Name of server player
message.hosts[0].PlyNr = index; // Host array slot number
message.hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); // Name of server player
for (int i = 1; i < PlayerMax - 1; ++i) { // Info about other clients
if (i != index) {
if (Hosts[i].PlyNr) {
message.u.Hosts[i] = Hosts[i];
} else {
message.u.Hosts[i].Clear();
}
if (i != index && Hosts[i].PlyNr) {
message.hosts[i] = Hosts[i];
}
}
NetworkSendICMessage_Log(host.Host, host.Port, message);
@ -962,15 +995,11 @@ void CServer::Send_Welcome(const CNetworkHost &host, int index)
void CServer::Send_Resync(const CNetworkHost &host, int hostIndex)
{
CInitMessage message(MessageInit_FromServer, ICMResync);
CInitMessage_Resync message;
for (int i = 1; i < PlayerMax - 1; ++i) { // Info about other clients
if (i != hostIndex) {
if (Hosts[i].PlyNr) {
message.u.Hosts[i] = Hosts[i];
} else {
message.u.Hosts[i].Clear();
}
if (i != hostIndex && Hosts[i].PlyNr) {
message.hosts[i] = Hosts[i];
}
}
NetworkSendICMessage_Log(host.Host, host.Port, message);
@ -978,25 +1007,21 @@ void CServer::Send_Resync(const CNetworkHost &host, int hostIndex)
void CServer::Send_Map(const CNetworkHost& host)
{
CInitMessage message(MessageInit_FromServer, ICMMap);
const CInitMessage_Map message(NetworkMapName.c_str(), Map.Info.MapUID);
strncpy_s(message.u.MapPath, sizeof(message.u.MapPath), NetworkMapName.c_str(), NetworkMapName.size());
message.MapUID = Map.Info.MapUID;
NetworkSendICMessage_Log(host.Host, host.Port, message);
}
void CServer::Send_State(const CNetworkHost& host)
{
CInitMessage message(MessageInit_FromServer, ICMState);
const CInitMessage_State message(MessageInit_FromServer, ServerSetupState);
message.u.State = ServerSetupState;
message.MapUID = Map.Info.MapUID;
NetworkSendICMessage_Log(host.Host, host.Port, message);
}
void CServer::Send_GoodBye(const CNetworkHost& host)
{
const CInitMessage message(MessageInit_FromServer, ICMGoodBye);
const CInitMessage_Header message(MessageInit_FromServer, ICMGoodBye);
NetworkSendICMessage_Log(host.Host, host.Port, message);
}
@ -1037,7 +1062,7 @@ void CServer::MarkClientsAsResync()
**
** @return host index
*/
int CServer::Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int port)
int CServer::Parse_Hello(int h, const CInitMessage_Hello &msg, unsigned long host, int port)
{
if (h == -1) { // it is a new client
for (int i = 1; i < PlayerMax - 1; ++i) {
@ -1053,7 +1078,7 @@ int CServer::Parse_Hello(int h, const CInitMessage &msg, unsigned long host, int
Hosts[h].Host = host;
Hosts[h].Port = port;
Hosts[h].PlyNr = h;
Hosts[h].SetName(msg.u.Hosts[0].PlyName);
Hosts[h].SetName(msg.PlyName);
DebugPrint("New client %d.%d.%d.%d:%d [%s]\n" _C_
NIPQUAD(ntohl(host)) _C_ ntohs(port) _C_ Hosts[h].PlyName);
networkStates[h].State = ccs_connecting;
@ -1181,7 +1206,7 @@ void CServer::Parse_Map(const int h)
networkStates[h].MsgCnt = 0;
/* Fall through */
case ccs_mapinfo: {
// this code path happens until client acknoledges the state info
// this code path happens until client acknowledges the state info
// by falling back to ICMWaiting with prev. State synced
Send_State(Hosts[h]);
@ -1203,7 +1228,7 @@ void CServer::Parse_Map(const int h)
** @param h slot number of host msg originates from
** @param msg message received
*/
void CServer::Parse_State(const int h, const CInitMessage &msg)
void CServer::Parse_State(const int h, const CInitMessage_State &msg)
{
switch (networkStates[h].State) {
case ccs_mapinfo:
@ -1214,8 +1239,8 @@ void CServer::Parse_State(const int h, const CInitMessage &msg)
// networkStates[h].State = ccs_async;
networkStates[h].MsgCnt = 0;
// Use information supplied by the client:
ServerSetupState.Ready[h] = msg.u.State.Ready[h];
ServerSetupState.Race[h] = msg.u.State.Race[h];
ServerSetupState.Ready[h] = msg.State.Ready[h];
ServerSetupState.Race[h] = msg.State.Race[h];
// Add additional info usage here!
// Resync other clients (and us..)
@ -1297,16 +1322,16 @@ void CServer::Parse_SeeYou(const int h)
**
** @return 0 if the versions match, -1 otherwise
*/
static int CheckVersions(const CInitMessage &msg, unsigned long host, int port)
static int CheckVersions(const CInitMessage_Hello &msg, unsigned long host, int port)
{
if (msg.Stratagus != StratagusVersion) {
fprintf(stderr, "Incompatible Stratagus version "
"%d <-> %d\n"
"from %d.%d.%d.%d:%d\n",
msg.Stratagus, StratagusVersion,
StratagusVersion, msg.Stratagus,
NIPQUAD(ntohl(host)), ntohs(port));
const CInitMessage message(MessageInit_FromServer, ICMEngineMismatch);
const CInitMessage_EngineMismatch message;
NetworkSendICMessage_Log(host, port, message);
return -1;
}
@ -1316,11 +1341,11 @@ static int CheckVersions(const CInitMessage &msg, unsigned long host, int port)
NetworkProtocolFormatString " <-> "
NetworkProtocolFormatString "\n"
"from %d.%d.%d.%d:%d\n",
NetworkProtocolFormatArgs(msg.Version),
NetworkProtocolFormatArgs(NetworkProtocolVersion),
NetworkProtocolFormatArgs(msg.Version),
NIPQUAD(ntohl(host)), ntohs(port));
const CInitMessage message(MessageInit_FromServer, ICMProtocolMismatch);
const CInitMessage_ProtocolMismatch message;
NetworkSendICMessage_Log(host, port, message);
return -1;
}
@ -1334,7 +1359,7 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign
if (index == -1) {
if (msgsubtype == ICMHello) {
CInitMessage msg;
CInitMessage_Hello msg;
msg.Deserialize(buf);
if (CheckVersions(msg, host, port)) {
@ -1349,7 +1374,7 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign
networkStates[index].LastFrame = frameCounter;
switch (msgsubtype) {
case ICMHello: { // a new client has arrived
CInitMessage msg;
CInitMessage_Hello msg;
msg.Deserialize(buf);
Parse_Hello(index, msg, host, port);
@ -1360,19 +1385,15 @@ void CServer::Parse(unsigned long frameCounter, const unsigned char *buf, unsign
case ICMMap: Parse_Map(index); break;
case ICMState: {
CInitMessage msg;
CInitMessage_State msg;
msg.Deserialize(buf);
Parse_State(index, msg);
break;
}
case ICMMapUidMismatch:
case ICMGoodBye:
Parse_GoodBye(index);
break;
case ICMMapUidMismatch: // Parse_MapUidMismatch(index, buf); break;
case ICMGoodBye: Parse_GoodBye(index); break;
case ICMSeeYou: Parse_SeeYou(index); break;
case ICMIAH: break;
default:
@ -1399,7 +1420,9 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos
{
Assert(NetConnectRunning != 0);
const char msgtype = buf[0];
CInitMessage_Header header;
header.Deserialize(buf);
const unsigned char msgtype = header.GetType();
if ((msgtype == MessageInit_FromClient && NetConnectRunning != 1)
|| (msgtype == MessageInit_FromServer && NetConnectRunning != 2)) {
if (NetConnectRunning == 2 && Client.GetNetworkState() == ccs_started) {
@ -1410,7 +1433,7 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos
}
return 0;
}
const char msgsubtype = buf[1];
const unsigned char msgsubtype = header.GetSubType();
DebugPrint("Received %s (%d) from %d.%d.%d.%d:%d\n" _C_
icmsgsubtypenames[int(msgsubtype)] _C_ msgsubtype _C_
@ -1476,6 +1499,7 @@ void NetworkInitClientConnect()
ServerSetupState.Clear();
LocalSetupState.Clear();
}
/**
** Server user has finally hit the start game button
*/
@ -1625,19 +1649,15 @@ void NetworkServerStartGame()
std::swap(Hosts[0], Hosts[HostsCount]);
// Prepare the final config message:
CInitMessage message(MessageInit_FromServer, ICMConfig);
CInitMessage_Config message;
message.HostsCount = NetPlayers;
message.MapUID = Map.Info.MapUID;
for (int i = 0; i < NetPlayers; ++i) {
message.u.Hosts[i] = Hosts[i];
message.u.Hosts[i].PlyNr = Hosts[i].PlyNr;
message.Hosts[i] = Hosts[i];
message.Hosts[i].PlyNr = Hosts[i].PlyNr;
}
// Prepare the final state message:
CInitMessage statemsg(MessageInit_FromServer, ICMState);
statemsg.HostsCount = NetPlayers;
statemsg.u.State = ServerSetupState;
statemsg.MapUID = Map.Info.MapUID;
const CInitMessage_State statemsg(MessageInit_FromServer, ServerSetupState);
DebugPrint("Ready, sending InitConfig to %d host(s)\n" _C_ HostsCount);
// Send all clients host:ports to all clients.
@ -1647,15 +1667,15 @@ breakout:
// Send to all clients.
for (int i = 0; i < HostsCount; ++i) {
if (num[Hosts[i].PlyNr] == 1) { // not acknowledged yet
unsigned long host = message.u.Hosts[i].Host;
int port = message.u.Hosts[i].Port;
message.u.Hosts[i].Host = message.u.Hosts[i].Port = 0;
unsigned long host = message.Hosts[i].Host;
int port = message.Hosts[i].Port;
message.Hosts[i].Host = message.Hosts[i].Port = 0;
NetworkSendICMessage_Log(host, port, message);
message.u.Hosts[i].Host = host;
message.u.Hosts[i].Port = port;
message.Hosts[i].Host = host;
message.Hosts[i].Port = port;
} else if (num[Hosts[i].PlyNr] == 2) {
unsigned long host = message.u.Hosts[i].Host;
int port = message.u.Hosts[i].Port;
unsigned long host = message.Hosts[i].Host;
int port = message.Hosts[i].Port;
NetworkSendICMessage_Log(host, port, statemsg);
}
}
@ -1671,16 +1691,13 @@ breakout:
len _C_ NIPQUAD(ntohl(host)) _C_ ntohs(port));
continue;
}
CInitMessage_Header header;
header.Deserialize(buf);
const unsigned char type = header.GetType();
const unsigned char subtype = header.GetSubType();
if (len != (int)CInitMessage::Size()) {
DebugPrint("Unexpected message size\n");
continue;
}
CInitMessage msg;
msg.Deserialize(buf);
if (msg.Type == MessageInit_FromClient) {
switch (msg.SubType) {
if (type == MessageInit_FromClient) {
switch (subtype) {
case ICMConfig: {
DebugPrint("Got ack for InitConfig from %d.%d.%d.%d:%d\n"
_C_ NIPQUAD(ntohl(host)) _C_ ntohs(port));
@ -1709,23 +1726,22 @@ breakout:
break;
}
default:
DebugPrint("Server: Config ACK: Unhandled subtype %d\n" _C_ msg.SubType);
DebugPrint("Server: Config ACK: Unhandled subtype %d\n" _C_ subtype);
break;
}
} else {
DebugPrint("Unexpected Message Type %d while waiting for Config ACK\n" _C_ msg.Type);
DebugPrint("Unexpected Message Type %d while waiting for Config ACK\n" _C_ type);
}
}
}
DebugPrint("DONE: All configs acked - Now starting..\n");
// Give clients a quick-start kick..
message.SubType = ICMGo;
const CInitMessage_Header message_go(MessageInit_FromServer, ICMGo);
for (int i = 0; i < HostsCount; ++i) {
const unsigned long host = message.u.Hosts[i].Host;
const int port = message.u.Hosts[i].Port;
NetworkSendICMessage_Log(host, port, message);
const unsigned long host = Hosts[i].Host;
const int port = Hosts[i].Port;
NetworkSendICMessage_Log(host, port, message_go);
}
}

View file

@ -37,7 +37,7 @@ void FillCustomValue(CNetworkHost *obj)
{
obj->Host = 0x12345678;
obj->Port = 0x9ABC;
for (int i = 0; i != sizeof(CNetworkHost::PlyName); ++i) {
for (int i = 0; i != sizeof(obj->PlyName); ++i) {
obj->PlyName[i] = i + 1;
}
obj->PlyNr = 0xDEF0;
@ -64,20 +64,64 @@ void FillCustomValue(CServerSetup *obj)
}
}
void FillCustomValue(CInitMessage *obj)
void FillCustomValue(CInitMessage_Header *obj)
{
obj->Type = 0x22;
obj->SubType = ICMHello;
obj->HostsCount = 0x04;
obj->padding = 0x33;
*obj = CInitMessage_Header(0x12, 0x34);
}
void FillCustomValue(CInitMessage_Hello *obj)
{
for (int i = 0; i != sizeof(obj->PlyName); ++i) {
obj->PlyName[i] = i + 1;
}
obj->Stratagus = 0x12345678;
obj->Version = 0x90ABCDEF;
obj->MapUID = 0x09BADCFE;
obj->Lag = 0x13245768;
obj->Updates = 0x9A0BCEDF;
// it is the biggest data size.
}
void FillCustomValue(CInitMessage_Config *obj)
{
obj->HostsCount = PlayerMax;
for (int i = 0; i != PlayerMax; ++i) {
FillCustomValue(&obj->u.Hosts[i]);
FillCustomValue(&obj->Hosts[i]);
}
}
void FillCustomValue(CInitMessage_EngineMismatch *obj)
{
obj->Stratagus = 0x01020304;
}
void FillCustomValue(CInitMessage_ProtocolMismatch *obj)
{
obj->Version = 0x01020304;
}
void FillCustomValue(CInitMessage_Welcome *obj)
{
obj->Lag = 0x01020304;
obj->Updates = 0x05060708;
for (int i = 0; i != PlayerMax; ++i) {
FillCustomValue(&obj->hosts[i]);
}
}
void FillCustomValue(CInitMessage_Map *obj)
{
obj->MapUID = 0x01234567;
for (int i = 0; i != sizeof(obj->MapPath); ++i) {
obj->MapPath[i] = 1 + i;
}
}
void FillCustomValue(CInitMessage_State *obj)
{
FillCustomValue(&obj->State);
}
void FillCustomValue(CInitMessage_Resync *obj)
{
for (int i = 0; i != PlayerMax; ++i) {
FillCustomValue(&obj->hosts[i]);
}
}
@ -86,16 +130,36 @@ bool CheckSerialization()
{
T obj1;
FillCustomValue(&obj1);
unsigned char *buffer = new unsigned char [obj1.Size()];
unsigned char *end = buffer + obj1.Serialize(buffer);
bool res = size_t(end - buffer) == obj1.Size();
T obj2;
obj2.Deserialize(buffer);
delete [] buffer;
res &= memcmp(&obj1, &obj2, sizeof(T)) == 0; // may fail with padding
return res;
}
template <typename T>
bool CheckSerialization_return()
{
T obj1;
memset(&obj1, 0, sizeof(T));
FillCustomValue(&obj1);
const unsigned char *buffer = obj1.Serialize();
T obj2;
memset(&obj2, 0, sizeof(T));
obj2.Deserialize(buffer);
bool res = memcmp(&obj1, &obj2, sizeof(T)) == 0;
bool res = memcmp(&obj1, &obj2, sizeof(T)) == 0; // may fail with padding
delete [] buffer;
return res;
}
TEST(CNetworkHost)
{
CHECK(CheckSerialization<CNetworkHost>());
@ -106,7 +170,47 @@ TEST(CServerSetup)
CHECK(CheckSerialization<CServerSetup>());
}
TEST(CInitMessage)
TEST(CInitMessage_Header)
{
CHECK(CheckSerialization<CInitMessage>());
CHECK(CheckSerialization<CInitMessage_Header>());
}
TEST(CInitMessage_Hello)
{
CHECK(CheckSerialization_return<CInitMessage_Hello>());
}
TEST(CInitMessage_Config)
{
CHECK(CheckSerialization_return<CInitMessage_Config>());
}
TEST(CInitMessage_EngineMismatch)
{
CHECK(CheckSerialization_return<CInitMessage_EngineMismatch>());
}
TEST(CInitMessage_ProtocolMismatch)
{
CHECK(CheckSerialization_return<CInitMessage_ProtocolMismatch>());
}
TEST(CInitMessage_Welcome)
{
CHECK(CheckSerialization_return<CInitMessage_Welcome>());
}
TEST(CInitMessage_Map)
{
CHECK(CheckSerialization_return<CInitMessage_Map>());
}
TEST(CInitMessage_State)
{
CHECK(CheckSerialization_return<CInitMessage_State>());
}
TEST(CInitMessage_Resync)
{
CHECK(CheckSerialization_return<CInitMessage_Resync>());
}