Networking updates.

- Added preprocessor value NETVERSION, to be incremented in the source whenever changes are made to the network protocol.
- Implemented proper server-side version verification of all clients upon connection.
- Implemented connection refusal when we reach MAXPLAYERS. (Should be expanded to implement server player caps.)
- Protected against OOB array accesses if an invalid player id is received.
- Renamed all "Recieve" to "Receive".

git-svn-id: https://svn.eduke32.com/eduke32@4322 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2014-02-10 11:00:25 +00:00
parent 3b5dea7347
commit c2cb6a9754
3 changed files with 159 additions and 100 deletions

View file

@ -325,6 +325,34 @@ static inline uint32_t B_SWAP32(uint32_t l) { return ((l>>8)&0xff00)|((l&0xff0
static inline uint64_t B_SWAP64(uint64_t l) { return (l>>56)|((l>>40)&0xff00)|((l>>24)&0xff0000)|((l>>8)&0xff000000)|((l&255)<<56)|((l&0xff00)<<40)|((l&0xff0000)<<24)|((l&0xff000000)<<8); } static inline uint64_t B_SWAP64(uint64_t l) { return (l>>56)|((l>>40)&0xff00)|((l>>24)&0xff0000)|((l>>8)&0xff000000)|((l&255)<<56)|((l&0xff00)<<40)|((l&0xff0000)<<24)|((l&0xff000000)<<8); }
#endif #endif
static inline void B_BUF16(uint8_t *buf, uint16_t x)
{
buf[0] = (x & 0x00FF);
buf[1] = (x & 0xFF00) >> 8;
}
static inline void B_BUF32(uint8_t *buf, uint32_t x)
{
buf[0] = (x & 0x000000FF);
buf[1] = (x & 0x0000FF00) >> 8;
buf[2] = (x & 0x00FF0000) >> 16;
buf[3] = (x & 0xFF000000) >> 24;
}
static inline void B_BUF64(uint8_t *buf, uint64_t x)
{
buf[0] = (x & 0x00000000000000FF);
buf[1] = (x & 0x000000000000FF00) >> 8;
buf[2] = (x & 0x0000000000FF0000) >> 16;
buf[3] = (x & 0x00000000FF000000) >> 24;
buf[4] = (x & 0x000000FF00000000) >> 32;
buf[5] = (x & 0x0000FF0000000000) >> 40;
buf[6] = (x & 0x00FF000000000000) >> 48;
buf[7] = (x & 0xFF00000000000000) >> 56;
}
static inline uint16_t B_UNBUF16(const uint8_t *buf) { return (buf[1] << 8) | (buf[0]); }
static inline uint32_t B_UNBUF32(const uint8_t *buf) { return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]); }
static inline uint64_t B_UNBUF64(const uint8_t *buf) { return ((uint64_t)buf[7] << 56) | ((uint64_t)buf[6] << 48) | ((uint64_t)buf[5] << 40) | ((uint64_t)buf[4] << 32) | (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | (buf[0]); }
#if defined(USE_MSC_PRAGMAS) #if defined(USE_MSC_PRAGMAS)
static inline void ftol(float f, int32_t *a) static inline void ftol(float f, int32_t *a)
{ {

View file

@ -71,7 +71,7 @@ int16_t g_netStatnums[] =
uint32_t g_netMapRevision = 0; uint32_t g_netMapRevision = 0;
netmapstate_t g_mapStartState; netmapstate_t g_mapStartState;
netmapstate_t *g_mapStateHistory[NET_REVISIONS]; netmapstate_t *g_mapStateHistory[NET_REVISIONS];
char tempnetbuf[sizeof(netmapstate_t) + 400]; uint8_t tempnetbuf[sizeof(netmapstate_t) + 400];
netmapdiff_t tempMapDiff; netmapdiff_t tempMapDiff;
#pragma pack(pop) #pragma pack(pop)
#define tempnetbufsize sizeof(tempnetbuf) #define tempnetbufsize sizeof(tempnetbuf)
@ -85,8 +85,8 @@ static void P_RemovePlayer(int32_t p)
g_player[p].playerquitflag = 0; g_player[p].playerquitflag = 0;
Bsprintf(buf,"%s^00 is history!",g_player[p].user_name); Bsprintf(recbuf,"%s^00 is history!",g_player[p].user_name);
G_AddUserQuote(buf); G_AddUserQuote(recbuf);
if (numplayers == 1) if (numplayers == 1)
S_PlaySound(GENERIC_AMBIENCE17); S_PlaySound(GENERIC_AMBIENCE17);
@ -112,7 +112,7 @@ static void P_RemovePlayer(int32_t p)
voting = -1; voting = -1;
} }
Bstrcpy(ScriptQuotes[QUOTE_RESERVED2],buf); Bstrcpy(ScriptQuotes[QUOTE_RESERVED2],recbuf);
g_player[myconnectindex].ps->ftq = QUOTE_RESERVED2; g_player[myconnectindex].ps->ftq = QUOTE_RESERVED2;
g_player[myconnectindex].ps->fta = 180; g_player[myconnectindex].ps->fta = 180;
} }
@ -123,6 +123,13 @@ void Net_SyncPlayer(ENetEvent *event)
{ {
int32_t i, j; int32_t i, j;
if (numplayers + g_netPlayersWaiting >= MAXPLAYERS)
{
enet_peer_disconnect_later(event->peer, DISC_SERVER_FULL);
initprintf("Refused peer; server full.\n");
return;
}
g_netPlayersWaiting++; g_netPlayersWaiting++;
S_PlaySound(DUKE_GETWEAPON2); S_PlaySound(DUKE_GETWEAPON2);
@ -156,6 +163,7 @@ void Net_SyncPlayer(ENetEvent *event)
G_MaybeAllocPlayer(i); G_MaybeAllocPlayer(i);
g_netPlayersWaiting--;
++numplayers; ++numplayers;
++ud.multimode; ++ud.multimode;
Net_SendNewPlayer(i); Net_SendNewPlayer(i);
@ -350,7 +358,7 @@ void Net_Disconnect(void)
ENetEvent event; ENetEvent event;
for (i=0; i<(signed)g_netServer->peerCount; i++) for (i=0; i<(signed)g_netServer->peerCount; i++)
enet_peer_disconnect_later(&g_netServer->peers[i], 0); enet_peer_disconnect_later(&g_netServer->peers[i], DISC_SERVER_QUIT);
while (enet_host_service(g_netServer, & event, 3000) > 0) while (enet_host_service(g_netServer, & event, 3000) > 0)
{ {
@ -382,6 +390,18 @@ void Net_ReceiveDisconnect(ENetEvent *event)
case DISC_BAD_PASSWORD: case DISC_BAD_PASSWORD:
initprintf("Bad password.\n"); initprintf("Bad password.\n");
return; return;
case DISC_VERSION_MISMATCH:
initprintf("Version mismatch.\n");
return;
case DISC_INVALID:
initprintf("Invalid data detected.\n");
return;
case DISC_SERVER_QUIT:
initprintf("The server is quitting.\n");
return;
case DISC_SERVER_FULL:
initprintf("The server is full.\n");
return;
case DISC_KICKED: case DISC_KICKED:
initprintf("You have been kicked from the server.\n"); initprintf("You have been kicked from the server.\n");
return; return;
@ -442,6 +462,13 @@ void Net_HandleClientPackets(void)
{ {
const intptr_t playeridx = (intptr_t)event.peer->data; const intptr_t playeridx = (intptr_t)event.peer->data;
if (playeridx < 0 || playeridx >= MAXPLAYERS)
{
enet_peer_disconnect_later(event.peer, DISC_INVALID);
initprintf("Invalid player id (%" PRIdPTR ") from client.\n", playeridx);
continue;
}
switch (event.type) switch (event.type)
{ {
case ENET_EVENT_TYPE_CONNECT: case ENET_EVENT_TYPE_CONNECT:
@ -452,7 +479,7 @@ void Net_HandleClientPackets(void)
initprintf("A new client connected from %s:%u.\n", ipaddr, event.peer->address.port); initprintf("A new client connected from %s:%u.\n", ipaddr, event.peer->address.port);
Net_SendVersion(event.peer); Net_SendAcknowledge(event.peer);
break; break;
} }
@ -579,7 +606,7 @@ void Net_ParseClientPacket(ENetEvent *event)
break; break;
case PACKET_AUTH: case PACKET_AUTH:
Net_RecieveChallenge(pbuf, packbufleng, event); Net_ReceiveChallenge(pbuf, packbufleng, event);
break; break;
default: default:
@ -624,16 +651,16 @@ void Net_ParseServerPacket(ENetEvent *event)
Net_ReceiveNewGame(event); Net_ReceiveNewGame(event);
break; break;
case PACKET_VERSION: case PACKET_ACK:
Net_RecieveVersion(pbuf, packbufleng); Net_ReceiveAcknowledge(pbuf, packbufleng);
break; break;
case PACKET_NUM_PLAYERS: case PACKET_NUM_PLAYERS:
Net_RecieveNewPlayer(event->packet->data, event->packet->dataLength); Net_ReceiveNewPlayer(event->packet->data, event->packet->dataLength);
break; break;
case PACKET_PLAYER_INDEX: case PACKET_PLAYER_INDEX:
Net_RecievePlayerIndex(event->packet->data, event->packet->dataLength); Net_ReceivePlayerIndex(event->packet->data, event->packet->dataLength);
break; break;
case PACKET_PLAYER_DISCONNECTED: case PACKET_PLAYER_DISCONNECTED:
@ -660,7 +687,7 @@ void Net_ParseServerPacket(ENetEvent *event)
if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) break; if (!(g_player[myconnectindex].ps->gm & MODE_GAME)) break;
g_player[pbuf[1]].ps->frag_ps = pbuf[2]; g_player[pbuf[1]].ps->frag_ps = pbuf[2];
actor[g_player[pbuf[1]].ps->i].picnum = pbuf[3]; actor[g_player[pbuf[1]].ps->i].picnum = pbuf[3];
ticrandomseed = *(int32_t *)&pbuf[4]; ticrandomseed = B_UNBUF32(&pbuf[4]);
P_FragPlayer(pbuf[1]); P_FragPlayer(pbuf[1]);
break; break;
@ -691,91 +718,83 @@ void Net_ParsePacketCommon(uint8_t *pbuf, int32_t packbufleng, int32_t serverpac
break; break;
case PACKET_MAP_VOTE: case PACKET_MAP_VOTE:
Net_RecieveMapVote(pbuf); Net_ReceiveMapVote(pbuf);
break; break;
case PACKET_MAP_VOTE_INITIATE: // call map vote case PACKET_MAP_VOTE_INITIATE: // call map vote
Net_RecieveMapVoteInitiate(pbuf); Net_ReceiveMapVoteInitiate(pbuf);
break; break;
case PACKET_MAP_VOTE_CANCEL: // cancel map vote case PACKET_MAP_VOTE_CANCEL: // cancel map vote
Net_RecieveMapVoteCancel(pbuf); Net_ReceiveMapVoteCancel(pbuf);
break; break;
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Version Packets // Acknowledgement Packets
// TODO: switch this around so the client sends their version to the server for void Net_SendAcknowledge(ENetPeer *client)
// verification, instead of the other way around like it is now
void Net_SendVersion(ENetPeer *client)
{ {
if (!g_netServer) if (!g_netServer)
return; return;
buf[0] = PACKET_VERSION; tempnetbuf[0] = PACKET_ACK;
*(uint16_t *)&buf[1] = BYTEVERSION; tempnetbuf[1] = myconnectindex;
// XXX: s_buildDate is outdated and useless; uint8 is not enough :/
buf[3] = (uint8_t)atoi(s_buildDate);
buf[4] = myconnectindex;
enet_peer_send(client, CHAN_GAMESTATE, enet_packet_create(&buf[0], 5, ENET_PACKET_FLAG_RELIABLE)); enet_peer_send(client, CHAN_GAMESTATE, enet_packet_create(&tempnetbuf[0], 2, ENET_PACKET_FLAG_RELIABLE));
} }
void Net_RecieveVersion(uint8_t *pbuf, int32_t packbufleng) void Net_ReceiveAcknowledge(uint8_t *pbuf, int32_t packbufleng)
{ {
UNREFERENCED_PARAMETER(pbuf); // remove when this variable is used
UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used
if (*(uint16_t *)&pbuf[1] != BYTEVERSION || pbuf[3] != (uint8_t)atoi(s_buildDate))
{
initprintf("Server protocol is version %d.%d, expecting %d.%d\n",
*(uint16_t *)&pbuf[1], pbuf[3], BYTEVERSION, (uint8_t)atoi(s_buildDate));
initprintf("Server version mismatch! You cannot play Duke with different versions!\n");
g_netDisconnect = 1;
return;
}
Net_SendChallenge(); Net_SendChallenge();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Challenge Packets // Challenge Packets
// sends a simple crc32 of the current password, verified by the server before the connection can continue // sends the version and a simple crc32 of the current password, all verified by the server before the connection can continue
void Net_SendChallenge() void Net_SendChallenge()
{ {
int32_t l = 1;
if (!g_netClientPeer) if (!g_netClientPeer)
{ {
return; return;
} }
buf[0] = PACKET_AUTH; tempnetbuf[0] = PACKET_AUTH;
*(uint32_t *)&buf[1] = crc32once((uint8_t *)g_netPassword, Bstrlen(g_netPassword)); B_BUF16(&tempnetbuf[1], BYTEVERSION);
l += sizeof(int32_t); B_BUF16(&tempnetbuf[3], NETVERSION);
B_BUF32(&tempnetbuf[5], crc32once((uint8_t *)g_netPassword, Bstrlen(g_netPassword)));
tempnetbuf[9] = myconnectindex;
buf[l++] = myconnectindex; enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&tempnetbuf[0], 10, ENET_PACKET_FLAG_RELIABLE));
enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&buf[0], l, ENET_PACKET_FLAG_RELIABLE));
} }
void Net_RecieveChallenge(uint8_t *pbuf, int32_t packbufleng, ENetEvent *event) void Net_ReceiveChallenge(uint8_t *pbuf, int32_t packbufleng, ENetEvent *event)
{ {
uint32_t crc = *(uint32_t *)&pbuf[1]; const uint16_t byteVersion = B_UNBUF16(&pbuf[1]);
const uint16_t netVersion = B_UNBUF16(&pbuf[3]);
const uint32_t crc = B_UNBUF32(&pbuf[5]);
UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used
if (crc == crc32once((uint8_t *)g_netPassword, Bstrlen(g_netPassword))) if (byteVersion != BYTEVERSION || netVersion != NETVERSION)
{ {
Net_SyncPlayer(event); enet_peer_disconnect_later(event->peer, DISC_VERSION_MISMATCH);
initprintf("Bad client protocol: version %u.%u\n", byteVersion, netVersion);
return;
} }
else if (crc != crc32once((uint8_t *)g_netPassword, Bstrlen(g_netPassword)))
{ {
enet_peer_disconnect_later(event->peer, DISC_BAD_PASSWORD); enet_peer_disconnect_later(event->peer, DISC_BAD_PASSWORD);
initprintf("Bad password from client.\n"); initprintf("Bad password from client.\n");
return;
} }
Net_SyncPlayer(event);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -793,7 +812,7 @@ void Net_SendNewPlayer(int32_t newplayerindex)
enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, 7, ENET_PACKET_FLAG_RELIABLE)); enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(packbuf, 7, ENET_PACKET_FLAG_RELIABLE));
} }
void Net_RecieveNewPlayer(uint8_t *pbuf, int32_t packbufleng) void Net_ReceiveNewPlayer(uint8_t *pbuf, int32_t packbufleng)
{ {
int32_t i; int32_t i;
@ -848,7 +867,7 @@ void Net_SendPlayerIndex(int32_t index, ENetPeer *peer)
enet_peer_send(peer, CHAN_GAMESTATE, enet_packet_create(packbuf, 3, ENET_PACKET_FLAG_RELIABLE)); enet_peer_send(peer, CHAN_GAMESTATE, enet_packet_create(packbuf, 3, ENET_PACKET_FLAG_RELIABLE));
} }
void Net_RecievePlayerIndex(uint8_t *pbuf, int32_t packbufleng) void Net_ReceivePlayerIndex(uint8_t *pbuf, int32_t packbufleng)
{ {
UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used UNREFERENCED_PARAMETER(packbufleng); // remove when this variable is used
@ -869,38 +888,38 @@ void Net_SendClientInfo(void)
if (numplayers < 2) return; if (numplayers < 2) return;
buf[0] = PACKET_CLIENT_INFO; tempnetbuf[0] = PACKET_CLIENT_INFO;
l = 1; l = 1;
//null terminated player name to send //null terminated player name to send
for (i=0; szPlayerName[i]; i++) for (i=0; szPlayerName[i]; i++)
{ {
buf[l++] = szPlayerName[i]; tempnetbuf[l++] = szPlayerName[i];
} }
buf[l++] = 0; tempnetbuf[l++] = 0;
buf[l++] = g_player[myconnectindex].ps->aim_mode = ud.mouseaiming; tempnetbuf[l++] = g_player[myconnectindex].ps->aim_mode = ud.mouseaiming;
buf[l++] = g_player[myconnectindex].ps->auto_aim = ud.config.AutoAim; tempnetbuf[l++] = g_player[myconnectindex].ps->auto_aim = ud.config.AutoAim;
buf[l++] = g_player[myconnectindex].ps->weaponswitch = ud.weaponswitch; tempnetbuf[l++] = g_player[myconnectindex].ps->weaponswitch = ud.weaponswitch;
buf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = ud.color; tempnetbuf[l++] = g_player[myconnectindex].ps->palookup = g_player[myconnectindex].pcolor = ud.color;
buf[l++] = g_player[myconnectindex].pteam = ud.team; tempnetbuf[l++] = g_player[myconnectindex].pteam = ud.team;
for (i=0; i<10; i++) for (i=0; i<10; i++)
{ {
g_player[myconnectindex].wchoice[i] = g_player[0].wchoice[i]; g_player[myconnectindex].wchoice[i] = g_player[0].wchoice[i];
buf[l++] = (uint8_t)g_player[0].wchoice[i]; tempnetbuf[l++] = (uint8_t)g_player[0].wchoice[i];
} }
buf[l++] = myconnectindex; tempnetbuf[l++] = myconnectindex;
if (g_netClient) if (g_netClient)
{ {
enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&buf[0], l, ENET_PACKET_FLAG_RELIABLE)); enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&tempnetbuf[0], l, ENET_PACKET_FLAG_RELIABLE));
} }
else if (g_netServer) else if (g_netServer)
{ {
enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(&buf[0], l, ENET_PACKET_FLAG_RELIABLE)); enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(&tempnetbuf[0], l, ENET_PACKET_FLAG_RELIABLE));
} }
} }
@ -1036,6 +1055,11 @@ void Net_SendMapUpdate(void)
ENetPeer *const currentPeer = &g_netServer->peers[pi]; ENetPeer *const currentPeer = &g_netServer->peers[pi];
const intptr_t playeridx = (intptr_t) currentPeer->data; const intptr_t playeridx = (intptr_t) currentPeer->data;
if (playeridx < 0 || playeridx >= MAXPLAYERS)
{
continue;
}
if (currentPeer->state != ENET_PEER_STATE_CONNECTED || !g_player[playeridx].playerquitflag) if (currentPeer->state != ENET_PEER_STATE_CONNECTED || !g_player[playeridx].playerquitflag)
{ {
continue; continue;
@ -1052,7 +1076,7 @@ void Net_SendMapUpdate(void)
diffsize += tempMapDiff.numActors * sizeof(netactor_t); diffsize += tempMapDiff.numActors * sizeof(netactor_t);
diffsize += tempMapDiff.numToDelete * sizeof(int32_t); diffsize += tempMapDiff.numToDelete * sizeof(int32_t);
packetsize = LZ4_compress_limitedOutput((const char*)&tempMapDiff, &tempnetbuf[5], diffsize, tempnetbufsize - 5); packetsize = LZ4_compress_limitedOutput((const char*)&tempMapDiff, (char*)&tempnetbuf[5], diffsize, tempnetbufsize - 5);
if (packetsize == 0) if (packetsize == 0)
return; return;
@ -1061,10 +1085,7 @@ void Net_SendMapUpdate(void)
tempnetbuf[0] = PACKET_MAP_STREAM; tempnetbuf[0] = PACKET_MAP_STREAM;
// apply uncompressed size // apply uncompressed size
tempnetbuf[1] = (diffsize & 0x000000FF); B_BUF32(&tempnetbuf[1], diffsize);
tempnetbuf[2] = (diffsize & 0x0000FF00) >> 8;
tempnetbuf[3] = (diffsize & 0x00FF0000) >> 16;
tempnetbuf[4] = (diffsize & 0xFF000000) >> 24;
packetsize += 5; packetsize += 5;
@ -1076,9 +1097,9 @@ void Net_SendMapUpdate(void)
void Net_ReceiveMapUpdate(ENetEvent *event) void Net_ReceiveMapUpdate(ENetEvent *event)
{ {
char *pktBuf = (char *) event->packet->data; const uint8_t *pktBuf = (uint8_t *) event->packet->data;
uint32_t diffsize = (pktBuf[4] << 24) | (pktBuf[3] << 16) | (pktBuf[2] << 8) | (pktBuf[1]); uint32_t diffsize = B_UNBUF32(&pktBuf[1]);
LZ4_decompress_safe(&pktBuf[5], (char*)&tempMapDiff, diffsize, sizeof(netmapdiff_t)); LZ4_decompress_safe((const char*)&pktBuf[5], (char*)&tempMapDiff, diffsize, sizeof(netmapdiff_t));
Net_RestoreMapState(); Net_RestoreMapState();
//initprintf("Update packet size: %d - num actors: %d\n", event->packet->dataLength, tempMapDiff.numActors); //initprintf("Update packet size: %d - num actors: %d\n", event->packet->dataLength, tempMapDiff.numActors);
@ -1510,7 +1531,7 @@ typedef struct
void Net_SendServerUpdates(void) void Net_SendServerUpdates(void)
{ {
int16_t i; int16_t i;
char *updatebuf; uint8_t *updatebuf;
serverupdate_t serverupdate; serverupdate_t serverupdate;
serverplayerupdate_t playerupdate; serverplayerupdate_t playerupdate;
input_t *osyn = (input_t *)&inputfifo[1][0]; input_t *osyn = (input_t *)&inputfifo[1][0];
@ -1585,7 +1606,7 @@ void Net_SendServerUpdates(void)
void Net_ReceiveServerUpdate(ENetEvent *event) void Net_ReceiveServerUpdate(ENetEvent *event)
{ {
int32_t i; int32_t i;
char *updatebuf; uint8_t *updatebuf;
// int8_t numupdates; // int8_t numupdates;
serverupdate_t serverupdate; serverupdate_t serverupdate;
serverplayerupdate_t playerupdate; serverplayerupdate_t playerupdate;
@ -1595,7 +1616,7 @@ void Net_ReceiveServerUpdate(ENetEvent *event)
return; return;
} }
updatebuf = (char *) event->packet->data; updatebuf = (uint8_t *) event->packet->data;
Bmemcpy(&serverupdate, updatebuf, sizeof(serverupdate_t)); Bmemcpy(&serverupdate, updatebuf, sizeof(serverupdate_t));
updatebuf += sizeof(serverupdate_t); updatebuf += sizeof(serverupdate_t);
inputfifo[0][0] = serverupdate.nsyn; inputfifo[0][0] = serverupdate.nsyn;
@ -1673,6 +1694,11 @@ void Net_ReceiveClientUpdate(ENetEvent *event)
playeridx = (int32_t)(intptr_t) event->peer->data; playeridx = (int32_t)(intptr_t) event->peer->data;
if (playeridx < 0 || playeridx >= MAXPLAYERS)
{
return;
}
g_player[playeridx].revision = update.revision; g_player[playeridx].revision = update.revision;
inputfifo[0][playeridx] = update.nsyn; inputfifo[0][playeridx] = update.nsyn;
@ -1757,9 +1783,9 @@ void Net_SendMessage(void)
} }
else else
{ {
Bsprintf(buf," %d - %s",i+1,g_player[i].user_name); Bsprintf(recbuf," %d - %s",i+1,g_player[i].user_name);
minitextshade((320>>1)-40-6+1,j+1,buf,26,0,2+8+16); minitextshade((320>>1)-40-6+1,j+1,recbuf,26,0,2+8+16);
minitext((320>>1)-40-6,j,buf,0,2+8+16); minitext((320>>1)-40-6,j,recbuf,0,2+8+16);
j += 7; j += 7;
} }
} }
@ -1920,8 +1946,6 @@ void Net_SendNewGame(int32_t frommenu, ENetPeer *peer)
{ {
enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(&newgame, sizeof(newgame_t), ENET_PACKET_FLAG_RELIABLE)); enet_host_broadcast(g_netServer, CHAN_GAMESTATE, enet_packet_create(&newgame, sizeof(newgame_t), ENET_PACKET_FLAG_RELIABLE));
} }
g_netPlayersWaiting--;
} }
void Net_ReceiveNewGame(ENetEvent *event) void Net_ReceiveNewGame(ENetEvent *event)
@ -2023,7 +2047,7 @@ void Net_SendMapVoteInitiate(void)
enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&newgame, sizeof(newgame_t), ENET_PACKET_FLAG_RELIABLE)); enet_peer_send(g_netClientPeer, CHAN_GAMESTATE, enet_packet_create(&newgame, sizeof(newgame_t), ENET_PACKET_FLAG_RELIABLE));
} }
void Net_RecieveMapVoteInitiate(uint8_t *pbuf) void Net_ReceiveMapVoteInitiate(uint8_t *pbuf)
{ {
int32_t i; int32_t i;
@ -2075,7 +2099,7 @@ void Net_SendMapVote(int32_t votefor)
Net_CheckForEnoughVotes(); Net_CheckForEnoughVotes();
} }
void Net_RecieveMapVote(uint8_t *pbuf) void Net_ReceiveMapVote(uint8_t *pbuf)
{ {
if (voting == myconnectindex && g_player[(uint8_t)pbuf[1]].gotvote == 0) if (voting == myconnectindex && g_player[(uint8_t)pbuf[1]].gotvote == 0)
{ {
@ -2178,7 +2202,7 @@ void Net_SendMapVoteCancel(int32_t failed)
} }
} }
void Net_RecieveMapVoteCancel(uint8_t *pbuf) void Net_ReceiveMapVoteCancel(uint8_t *pbuf)
{ {
// int32_t numvotes; // int32_t numvotes;

View file

@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "enet/enet.h" #include "enet/enet.h"
// net packet specification/compatibility version
#define NETVERSION 1
extern ENetHost *g_netClient; extern ENetHost *g_netClient;
extern ENetHost *g_netServer; extern ENetHost *g_netServer;
extern ENetPeer *g_netClientPeer; extern ENetPeer *g_netClientPeer;
@ -60,7 +63,7 @@ enum DukePacket_t
PACKET_PLAYER_DISCONNECTED, PACKET_PLAYER_DISCONNECTED,
PACKET_PLAYER_SPAWN, PACKET_PLAYER_SPAWN,
PACKET_FRAG, PACKET_FRAG,
PACKET_VERSION, PACKET_ACK,
PACKET_AUTH, PACKET_AUTH,
PACKET_PLAYER_PING, PACKET_PLAYER_PING,
PACKET_PLAYER_READY, PACKET_PLAYER_READY,
@ -87,6 +90,10 @@ enum DukePacket_t
enum netdisconnect_t enum netdisconnect_t
{ {
DISC_BAD_PASSWORD = 1, DISC_BAD_PASSWORD = 1,
DISC_VERSION_MISMATCH,
DISC_INVALID,
DISC_SERVER_QUIT,
DISC_SERVER_FULL,
DISC_KICKED, DISC_KICKED,
DISC_BANNED DISC_BANNED
}; };
@ -179,17 +186,17 @@ void Net_ParseClientPacket(ENetEvent *event);
void Net_ParseServerPacket(ENetEvent *event); void Net_ParseServerPacket(ENetEvent *event);
void Net_ParsePacketCommon(uint8_t *pbuf, int32_t packbufleng, int32_t serverpacketp); void Net_ParsePacketCommon(uint8_t *pbuf, int32_t packbufleng, int32_t serverpacketp);
void Net_SendVersion(ENetPeer *client); void Net_SendAcknowledge(ENetPeer *client);
void Net_RecieveVersion(uint8_t *pbuf, int32_t packbufleng); void Net_ReceiveAcknowledge(uint8_t *pbuf, int32_t packbufleng);
void Net_SendChallenge(); void Net_SendChallenge();
void Net_RecieveChallenge(uint8_t *pbuf, int32_t packbufleng, ENetEvent *event); void Net_ReceiveChallenge(uint8_t *pbuf, int32_t packbufleng, ENetEvent *event);
void Net_SendNewPlayer(int32_t newplayerindex); void Net_SendNewPlayer(int32_t newplayerindex);
void Net_RecieveNewPlayer(uint8_t *pbuf, int32_t packbufleng); void Net_ReceiveNewPlayer(uint8_t *pbuf, int32_t packbufleng);
void Net_SendPlayerIndex(int32_t index, ENetPeer *peer); void Net_SendPlayerIndex(int32_t index, ENetPeer *peer);
void Net_RecievePlayerIndex(uint8_t *pbuf, int32_t packbufleng); void Net_ReceivePlayerIndex(uint8_t *pbuf, int32_t packbufleng);
void Net_SendClientInfo(void); void Net_SendClientInfo(void);
void Net_ReceiveClientInfo(uint8_t *pbuf, int32_t packbufleng, int32_t fromserver); void Net_ReceiveClientInfo(uint8_t *pbuf, int32_t packbufleng, int32_t fromserver);
@ -235,14 +242,14 @@ void Net_FillNewGame(newgame_t *newgame, int32_t frommenu);
void Net_ExtractNewGame(newgame_t *newgame, int32_t menuonly); void Net_ExtractNewGame(newgame_t *newgame, int32_t menuonly);
void Net_SendMapVoteInitiate(void); void Net_SendMapVoteInitiate(void);
void Net_RecieveMapVoteInitiate(uint8_t *pbuf); void Net_ReceiveMapVoteInitiate(uint8_t *pbuf);
void Net_SendMapVote(int32_t votefor); void Net_SendMapVote(int32_t votefor);
void Net_RecieveMapVote(uint8_t *pbuf); void Net_ReceiveMapVote(uint8_t *pbuf);
void Net_CheckForEnoughVotes(); void Net_CheckForEnoughVotes();
void Net_SendMapVoteCancel(int32_t failed); void Net_SendMapVoteCancel(int32_t failed);
void Net_RecieveMapVoteCancel(uint8_t *pbuf); void Net_ReceiveMapVoteCancel(uint8_t *pbuf);
////////// //////////
@ -268,17 +275,17 @@ void faketimerhandler(void);
#define Net_ParseServerPacket(...) ((void)0) #define Net_ParseServerPacket(...) ((void)0)
#define Net_ParsePacketCommon(...) ((void)0) #define Net_ParsePacketCommon(...) ((void)0)
#define Net_SendVersion(...) ((void)0) #define Net_SendAcknowledge(...) ((void)0)
#define Net_RecieveVersion(...) ((void)0) #define Net_ReceiveAcknowledge(...) ((void)0)
#define Net_SendChallenge(...) ((void)0) #define Net_SendChallenge(...) ((void)0)
#define Net_RecieveChallenge(...) ((void)0) #define Net_ReceiveChallenge(...) ((void)0)
#define Net_SendNewPlayer(...) ((void)0) #define Net_SendNewPlayer(...) ((void)0)
#define Net_RecieveNewPlayer(...) ((void)0) #define Net_ReceiveNewPlayer(...) ((void)0)
#define Net_SendPlayerIndex(...) ((void)0) #define Net_SendPlayerIndex(...) ((void)0)
#define Net_RecievePlayerIndex(...) ((void)0) #define Net_ReceivePlayerIndex(...) ((void)0)
#define Net_SendClientInfo(...) ((void)0) #define Net_SendClientInfo(...) ((void)0)
#define Net_ReceiveClientInfo(...) ((void)0) #define Net_ReceiveClientInfo(...) ((void)0)
@ -312,14 +319,14 @@ void faketimerhandler(void);
#define Net_ExtractNewGame(...) ((void)0) #define Net_ExtractNewGame(...) ((void)0)
#define Net_SendMapVoteInitiate(...) ((void)0) #define Net_SendMapVoteInitiate(...) ((void)0)
#define Net_RecieveMapVoteInitiate(...) ((void)0) #define Net_ReceiveMapVoteInitiate(...) ((void)0)
#define Net_SendMapVote(...) ((void)0) #define Net_SendMapVote(...) ((void)0)
#define Net_RecieveMapVote(...) ((void)0) #define Net_ReceiveMapVote(...) ((void)0)
#define Net_CheckForEnoughVotes(...) ((void)0) #define Net_CheckForEnoughVotes(...) ((void)0)
#define Net_SendMapVoteCancel(...) ((void)0) #define Net_SendMapVoteCancel(...) ((void)0)
#define Net_RecieveMapVoteCancel(...) ((void)0) #define Net_ReceiveMapVoteCancel(...) ((void)0)
////////// //////////