All net messages begin with messageType.

This commit is contained in:
joris 2013-03-26 00:03:43 +01:00
parent 8de9c57c85
commit e18421875a
4 changed files with 166 additions and 121 deletions

View file

@ -45,7 +45,6 @@
#define MaxNetworkCommands 9 /// Max Commands In A Packet
/**
** Network systems active in current game.
*/
@ -171,9 +170,8 @@ public:
*/
enum _message_type_ {
MessageNone, /// When Nothing Is Happening
MessageInitHello, /// Start connection
MessageInitReply, /// Connection reply
MessageInitConfig, /// Setup message configure clients
MessageInit_FromClient, /// Start connection
MessageInit_FromServer, /// Connection reply
MessageSync, /// Heart beat
MessageSelection, /// Update a Selection from Team Player
@ -313,8 +311,8 @@ public:
void Deserialize(const unsigned char *p);
static size_t Size() { return 1 + 1 * MaxNetworkCommands; }
uint8_t Cycle; /// Destination game cycle
uint8_t Type[MaxNetworkCommands]; /// Commands in packet
uint8_t Cycle; /// Destination game cycle
};
/**
@ -325,7 +323,7 @@ public:
class CNetworkPacket
{
public:
unsigned char *Serialize(int numcommands) const;
void Serialize(unsigned char *buf, int numcommands) const;
int Deserialize(const unsigned char *p, unsigned int len);
static size_t Size(int numcommands) {
return CNetworkPacketHeader::Size() + numcommands * CNetworkCommand::Size();

View file

@ -42,6 +42,80 @@
#include "network.h"
#include "version.h"
int serialize32(unsigned char *buf, uint32_t data)
{
if (buf) {
*reinterpret_cast<uint32_t *>(buf) = htonl(data);
}
return sizeof(data);
}
int serialize32(unsigned char *buf, int32_t data)
{
if (buf) {
*reinterpret_cast<int32_t *>(buf) = htonl(data);
}
return sizeof(data);
}
int serialize16(unsigned char *buf, uint16_t data)
{
if (buf) {
*reinterpret_cast<uint16_t *>(buf) = htons(data);
}
return sizeof(data);
}
int serialize16(unsigned char *buf, int16_t data)
{
if (buf) {
*reinterpret_cast<int16_t *>(buf) = htons(data);
}
return sizeof(data);
}
int serialize8(unsigned char *buf, uint8_t data)
{
if (buf) {
*buf = data;
}
return sizeof(data);
}
int serialize8(unsigned char *buf, int8_t data)
{
if (buf) {
*buf = data;
}
return sizeof(data);
}
int deserialize32(const unsigned char *buf, uint32_t *data)
{
*data = ntohl(*reinterpret_cast<const uint32_t *>(buf));
return sizeof(*data);
}
int deserialize32(const unsigned char *buf, int32_t *data)
{
*data = ntohl(*reinterpret_cast<const int32_t *>(buf));
return sizeof(*data);
}
int deserialize16(const unsigned char *buf, uint16_t *data)
{
*data = ntohs(*reinterpret_cast<const uint16_t *>(buf));
return sizeof(*data);
}
int deserialize16(const unsigned char *buf, int16_t *data)
{
*data = ntohs(*reinterpret_cast<const int16_t *>(buf));
return sizeof(*data);
}
int deserialize8(const unsigned char *buf, uint8_t *data)
{
*data = *buf;
return sizeof(*data);
}
int deserialize8(const unsigned char *buf, int8_t *data)
{
*data = *buf;
return sizeof(*data);
}
//
// CNetworkHost
//
@ -51,12 +125,9 @@ const unsigned char *CNetworkHost::Serialize() const
unsigned char *buf = new unsigned char[CNetworkHost::Size()];
unsigned char *p = buf;
*(uint32_t *)p = htonl(this->Host);
p += 4;
*(uint16_t *)p = htons(this->Port);
p += 2;
*(uint16_t *)p = htons(this->PlyNr);
p += 2;
p += serialize32(p, this->Host);
p += serialize16(p, this->Port);
p += serialize16(p, this->PlyNr);
memcpy(p, this->PlyName, sizeof(this->PlyName));
return buf;
@ -64,12 +135,9 @@ const unsigned char *CNetworkHost::Serialize() const
void CNetworkHost::Deserialize(const unsigned char *p)
{
this->Host = ntohl(*(uint32_t *)p);
p += 4;
this->Port = ntohs(*(uint16_t *)p);
p += 2;
this->PlyNr = ntohs(*(uint16_t *)p);
p += 2;
p += deserialize32(p, &Host);
p += deserialize16(p, &Port);
p += deserialize16(p, &PlyNr);
memcpy(this->PlyName, p, sizeof(this->PlyName));
}
@ -95,44 +163,44 @@ const unsigned char *CServerSetup::Serialize() const
unsigned char *buf = new unsigned char[CServerSetup::Size()];
unsigned char *p = buf;
*p++ = this->ResourcesOption;
*p++ = this->UnitsOption;
*p++ = this->FogOfWar;
*p++ = this->RevealMap;
*p++ = this->TilesetSelection;
*p++ = this->GameTypeOption;
*p++ = this->Difficulty;
*p++ = this->MapRichness;
p += serialize8(p, this->ResourcesOption);
p += serialize8(p, this->UnitsOption);
p += serialize8(p, this->FogOfWar);
p += serialize8(p, this->RevealMap);
p += serialize8(p, this->TilesetSelection);
p += serialize8(p, this->GameTypeOption);
p += serialize8(p, this->Difficulty);
p += serialize8(p, this->MapRichness);
for (int i = 0; i < PlayerMax; ++i) {
*p++ = this->CompOpt[i];
p += serialize8(p, this->CompOpt[i]);
}
for (int i = 0; i < PlayerMax; ++i) {
*p++ = this->Ready[i];
p += serialize8(p, this->Ready[i]);
}
for (int i = 0; i < PlayerMax; ++i) {
*p++ = this->Race[i];
p += serialize8(p, this->Race[i]);
}
return buf;
}
void CServerSetup::Deserialize(const unsigned char *p)
{
this->ResourcesOption = *p++;
this->UnitsOption = *p++;
this->FogOfWar = *p++;
this->RevealMap = *p++;
this->TilesetSelection = *p++;
this->GameTypeOption = *p++;
this->Difficulty = *p++;
this->MapRichness = *p++;
p += deserialize8(p, &this->ResourcesOption);
p += deserialize8(p, &this->UnitsOption);
p += deserialize8(p, &this->FogOfWar);
p += deserialize8(p, &this->RevealMap);
p += deserialize8(p, &this->TilesetSelection);
p += deserialize8(p, &this->GameTypeOption);
p += deserialize8(p, &this->Difficulty);
p += deserialize8(p, &this->MapRichness);
for (int i = 0; i < PlayerMax; ++i) {
this->CompOpt[i] = *p++;
p += deserialize8(p, &this->CompOpt[i]);
}
for (int i = 0; i < PlayerMax; ++i) {
this->Ready[i] = *p++;
p += deserialize8(p, &this->Ready[i]);
}
for (int i = 0; i < PlayerMax; ++i) {
this->Race[i] = *p++;
p += deserialize8(p, &this->Race[i]);
}
}
@ -155,20 +223,15 @@ const unsigned char *CInitMessage::Serialize() const
unsigned char *buf = new unsigned char[CInitMessage::Size()];
unsigned char *p = buf;
*p++ = this->Type;
*p++ = this->SubType;
*p++ = this->HostsCount;
*p++ = this->padding;
*(int32_t *)p = htonl(this->Stratagus);
p += 4;
*(int32_t *)p = htonl(this->Version);
p += 4;
*(uint32_t *)p = htonl(this->MapUID);
p += 4;
*(int32_t *)p = htonl(this->Lag);
p += 4;
*(int32_t *)p = htonl(this->Updates);
p += 4;
p += serialize8(p, this->Type);
p += serialize8(p, this->SubType);
p += serialize8(p, this->HostsCount);
p += serialize8(p, this->padding);
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);
switch (this->SubType) {
case ICMHello:
@ -200,20 +263,15 @@ const unsigned char *CInitMessage::Serialize() const
void CInitMessage::Deserialize(const unsigned char *p)
{
this->Type = *p++;
this->SubType = *p++;
this->HostsCount = *p++;
this->padding = *p++;
this->Stratagus = ntohl(*(int32_t *)p);
p += 4;
this->Version = ntohl(*(int32_t *)p);
p += 4;
this->MapUID = ntohl(*(uint32_t *)p);
p += 4;
this->Lag = ntohl(*(int32_t *)p);
p += 4;
this->Updates = ntohl(*(int32_t *)p);
p += 4;
p += deserialize8(p, &this->Type);
p += deserialize8(p, &this->SubType);
p += deserialize8(p, &this->HostsCount);
p += deserialize8(p, &this->padding);
p += deserialize32(p, &this->Stratagus);
p += deserialize32(p, &this->Version);
p += deserialize32(p, &this->MapUID);
p += deserialize32(p, &this->Lag);
p += deserialize32(p, &this->Updates);
switch (this->SubType) {
case ICMHello:
@ -237,7 +295,6 @@ void CInitMessage::Deserialize(const unsigned char *p)
}
}
//
// CNetworkCommand
//
@ -266,7 +323,6 @@ void CNetworkCommand::Deserialize(const unsigned char *p)
p += 2;
}
//
// CNetworkExtendedCommand
//
@ -321,18 +377,18 @@ void CNetworkChat::Deserialize(const unsigned char *p)
void CNetworkPacketHeader::Serialize(unsigned char *p) const
{
*p++ = this->Cycle;
for (int i = 0; i < MaxNetworkCommands; ++i) {
*p++ = this->Type[i];
}
*p++ = this->Cycle;
}
void CNetworkPacketHeader::Deserialize(const unsigned char *p)
{
this->Cycle = *p++;
for (int i = 0; i < MaxNetworkCommands; ++i) {
this->Type[i] = *p++;
}
this->Cycle = *p++;
}
@ -340,9 +396,8 @@ void CNetworkPacketHeader::Deserialize(const unsigned char *p)
// CNetworkPacket
//
unsigned char *CNetworkPacket::Serialize(int numcommands) const
void CNetworkPacket::Serialize(unsigned char *buf, int numcommands) const
{
unsigned char *buf = new unsigned char[CNetworkPacket::Size(numcommands)];
unsigned char *p = buf;
this->Header.Serialize(p);
@ -358,8 +413,6 @@ unsigned char *CNetworkPacket::Serialize(int numcommands) const
}
p += CNetworkCommand::Size();
}
return buf;
}
int CNetworkPacket::Deserialize(const unsigned char *p, unsigned int len)

View file

@ -333,7 +333,7 @@ bool CClient::Update_disconnected()
Assert(networkState.State == ccs_disconnected);
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMSeeYou;
// Spew out 5 and trust in God that they arrive
for (int i = 0; i < 5; ++i) {
@ -350,7 +350,7 @@ bool CClient::Update_detaching(unsigned long tick)
if (networkState.MsgCnt < 10) { // 10 retries = 1 second
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMGoodBye;
NetworkSendRateLimitedClientMessage(message, tick, 100);
return true;
@ -368,7 +368,7 @@ bool CClient::Update_connecting(unsigned long tick)
if (networkState.MsgCnt < 48) { // 48 retries = 24 seconds
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMHello;
message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str());
NetworkSendRateLimitedClientMessage(message, tick, 500);
@ -386,7 +386,7 @@ bool CClient::Update_connected(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMWaiting;
NetworkSendRateLimitedClientMessage(message, tick, 650);
return true;
@ -407,7 +407,7 @@ bool CClient::Update_synced(unsigned long tick)
return Update(tick);
}
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMWaiting;
NetworkSendRateLimitedClientMessage(message, tick, 850);
return true;
@ -420,7 +420,7 @@ bool CClient::Update_changed(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMState;
message.u.State = LocalSetupState;
message.MapUID = Map.Info.MapUID;
@ -440,7 +440,7 @@ bool CClient::Update_async(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMResync;
NetworkSendRateLimitedClientMessage(message, tick, 450);
return true;
@ -458,7 +458,7 @@ bool CClient::Update_mapinfo(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMMap; // ICMMapAck..
message.MapUID = Map.Info.MapUID;
NetworkSendRateLimitedClientMessage(message, tick, 650);
@ -477,7 +477,7 @@ bool CClient::Update_badmap(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMMapUidMismatch;
message.MapUID = Map.Info.MapUID; // MAP Uid doesn't match
NetworkSendRateLimitedClientMessage(message, tick, 650);
@ -496,7 +496,7 @@ bool CClient::Update_goahead(unsigned long tick)
if (networkState.MsgCnt < 50) { // 50 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMConfig;
NetworkSendRateLimitedClientMessage(message, tick, 250);
return true;
@ -514,7 +514,7 @@ bool CClient::Update_started(unsigned long tick)
if (networkState.MsgCnt < 20) { // 20 retries
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMGo;
NetworkSendRateLimitedClientMessage(message, tick, 250);
return true;
@ -591,7 +591,7 @@ void CClient::ParseMsgConfig(const CInitMessage &msg, unsigned long host, int po
bool CClient::NetworkParseMenuPacket(const CInitMessage &msg, unsigned long host, int port)
{
if (msg.Type != MessageInitReply) {
if (msg.Type != MessageInit_FromServer) {
return true;
}
if (msg.SubType == ICMServerQuit) { // Server user canceled, should work in all states
@ -930,7 +930,7 @@ void CClient::ParseAreYouThere()
{
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMIAH;
NetworkSendICMessage(serverIP, serverPort, message);
}
@ -942,7 +942,7 @@ bool CClient::ParseBadMap()
{
CInitMessage message;
message.Type = MessageInitHello;
message.Type = MessageInit_FromClient;
message.SubType = ICMSeeYou;
// Spew out 5 and trust in God that they arrive
for (int i = 0; i < 5; ++i) {
@ -1000,7 +1000,7 @@ void CServer::Update(unsigned long frameCounter)
if (fcd > CLIENT_IS_DEAD) {
KickDeadClient(i);
} else if (fcd % 5 == 0) {
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMAYT; // Probe for the client
message.MapUID = 0L;
const int n = NetworkSendICMessage(Hosts[i].Host, Hosts[i].Port, message);
@ -1058,7 +1058,7 @@ int CServer::ParseHello(int h, const CInitMessage &msg, unsigned long host, int
} else {
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMGameFull; // Game is full - reject connnection
NetworkSendICMessage_Log(host, port, message);
return -1;
@ -1067,7 +1067,7 @@ int CServer::ParseHello(int h, const CInitMessage &msg, unsigned long host, int
// this code path happens until client sends waiting (= has received this message)
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMWelcome; // Acknowledge: Client is welcome
message.u.Hosts[0].PlyNr = h; // Host array slot number
message.u.Hosts[0].SetName(Parameters::Instance.LocalPlayerName.c_str()); // Name of server player
@ -1114,7 +1114,7 @@ void CServer::ParseResync(const int h, unsigned long host, int port)
// this code path happens until client falls back to ICMWaiting
// (indicating Resync has completed)
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMResync;
for (int i = 1; i < PlayerMax - 1; ++i) { // Info about other clients
if (i != h) {
@ -1160,7 +1160,7 @@ void CServer::ParseWaiting(const int h, unsigned long host, int port)
case ccs_connected: {
// this code path happens until client acknowledges the map
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMMap; // Send Map info to the client
strncpy_s(message.u.MapPath, sizeof(message.u.MapPath), NetworkMapName.c_str(), NetworkMapName.size());
message.MapUID = Map.Info.MapUID;
@ -1194,7 +1194,7 @@ void CServer::ParseWaiting(const int h, unsigned long host, int port)
// this code path happens until client acknoledges the state change
// by sending ICMResync
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMState; // Send new state info to the client
message.u.State = ServerSetupState;
message.MapUID = Map.Info.MapUID;
@ -1231,7 +1231,7 @@ void CServer::ParseMap(const int h, unsigned long host, int port)
// this code path happens until client acknoledges the state info
// by falling back to ICMWaiting with prev. State synced
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMState; // Send State info to the client
message.u.State = ServerSetupState;
message.MapUID = Map.Info.MapUID;
@ -1284,7 +1284,7 @@ void CServer::ParseState(const int h, const CInitMessage &msg, unsigned long hos
// by sending ICMResync
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMState; // Send new state info to the client
message.u.State = ServerSetupState;
message.MapUID = Map.Info.MapUID;
@ -1322,7 +1322,7 @@ void CServer::ParseGoodBye(const int h, unsigned long host, int port)
// this code path happens until client acknoledges the GoodBye
// by sending ICMSeeYou;
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMGoodBye;
NetworkSendICMessage_Log(host, port, message);
@ -1373,7 +1373,7 @@ static int CheckVersions(const CInitMessage &msg, unsigned long host, int port)
NIPQUAD(ntohl(host)), ntohs(port));
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMEngineMismatch; // Stratagus engine version doesn't match
NetworkSendICMessage_Log(host, port, message);
return -1;
@ -1389,7 +1389,7 @@ static int CheckVersions(const CInitMessage &msg, unsigned long host, int port)
NIPQUAD(ntohl(host)), ntohs(port));
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMProtocolMismatch; // Network protocol version doesn't match
NetworkSendICMessage_Log(host, port, message);
return -1;
@ -1459,8 +1459,9 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos
{
Assert(NetConnectRunning != 0);
if (size != (int)CInitMessage::Size()) {
// FIXME: could be a bad packet
const char msgtype = *buf;
if ((msgtype == MessageInit_FromClient && NetConnectRunning != 1)
|| (msgtype == MessageInit_FromServer && NetConnectRunning != 2)) {
if (NetConnectRunning == 2 && Client.GetNetworkState() == ccs_started) {
// Client has acked ready to start and receives first real network packet.
// This indicates that we missed the 'Go' in started state and the game
@ -1472,19 +1473,10 @@ int NetworkParseSetupEvent(const unsigned char *buf, int size, unsigned long hos
CInitMessage msg;
msg.Deserialize(buf);
if (msg.Type > MessageInitConfig) {
if (NetConnectRunning == 2 && Client.GetNetworkState() == ccs_started) {
// Client has acked ready to start and receives first real network packet.
// This indicates that we missed the 'Go' in started state and the game
// has been started by the server, so do the same for the client.
NetConnectRunning = 0; // End the menu..
}
return 0;
}
DebugPrint("Received %s Init Message %d:%d from %d.%d.%d.%d:%d (%ld)\n" _C_
icmsgsubtypenames[msg.SubType] _C_ msg.Type _C_ msg.SubType _C_ NIPQUAD(ntohl(host)) _C_
ntohs(port) _C_ FrameCounter);
DebugPrint("Received %s (%d) from %d.%d.%d.%d:%d\n" _C_
icmsgsubtypenames[msg.SubType] _C_ msg.SubType _C_
NIPQUAD(ntohl(host)) _C_ ntohs(port));
if (NetConnectRunning == 2) { // client
if (Client.NetworkParseMenuPacket(msg, host, port) == false) {
@ -1696,7 +1688,7 @@ void NetworkServerStartGame()
// Prepare the final config message:
CInitMessage message;
message.Type = MessageInitReply;
message.Type = MessageInit_FromServer;
message.SubType = ICMConfig;
message.HostsCount = NetPlayers;
message.MapUID = Map.Info.MapUID;
@ -1707,7 +1699,7 @@ void NetworkServerStartGame()
// Prepare the final state message:
CInitMessage statemsg;
statemsg.Type = MessageInitReply;
statemsg.Type = MessageInit_FromServer;
statemsg.SubType = ICMState;
statemsg.HostsCount = NetPlayers;
statemsg.u.State = ServerSetupState;
@ -1753,7 +1745,7 @@ breakout:
CInitMessage msg;
msg.Deserialize(buf);
if (msg.Type == MessageInitHello) {
if (msg.Type == MessageInit_FromClient) {
switch (msg.SubType) {
case ICMConfig: {
DebugPrint("Got ack for InitConfig from %d.%d.%d.%d:%d\n"

View file

@ -259,10 +259,10 @@ public:
*/
struct NetworkSelectionHeader
{
unsigned char Type[MaxNetworkCommands]; /// Command
unsigned NumberSent : 6; /// New Number Selected
unsigned Add : 1; /// Adding to Selection
unsigned Remove : 1; /// Removing from Selection
unsigned char Type[MaxNetworkCommands]; /// Command
};
//----------------------------------------------------------------------------
@ -317,7 +317,8 @@ static int NumNCQs; /// Number of NCQs in use
*/
static void NetworkBroadcast(const CNetworkPacket &packet, int numcommands)
{
unsigned char *buf = packet.Serialize(numcommands);
unsigned char *buf = new unsigned char[CNetworkPacket::Size(numcommands)];
packet.Serialize(buf, numcommands);
// Send to all clients.
for (int i = 0; i < HostsCount; ++i) {
@ -667,7 +668,8 @@ void NetworkSendSelection(CUnit **units, int count)
// Send the Constructed packet to team members
const int numcommands = (nosent + 3) / 4;
const unsigned char *buf = packet.Serialize(numcommands);
unsigned char *buf = new unsigned char [CNetworkPacket::Size(numcommands)];
packet.Serialize(buf, numcommands);
const int len = CNetworkPacketHeader::Size() + CNetworkSelection::Size() * numcommands;
for (int i = 0; i < numteammates; ++i) {