diff options
author | Simon Howard | 2006-02-17 20:15:16 +0000 |
---|---|---|
committer | Simon Howard | 2006-02-17 20:15:16 +0000 |
commit | 65ba9ecd3c61235e618a208e0595d71bcefcf9f4 (patch) | |
tree | 2af381a429f7ec37a688ee8c1edfdf2726b3c0b5 | |
parent | 4af352a213431e577a48dd8b3ece7822cb7168bc (diff) | |
download | chocolate-doom-65ba9ecd3c61235e618a208e0595d71bcefcf9f4.tar.gz chocolate-doom-65ba9ecd3c61235e618a208e0595d71bcefcf9f4.tar.bz2 chocolate-doom-65ba9ecd3c61235e618a208e0595d71bcefcf9f4.zip |
Request resends for missed packets
Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 370
-rw-r--r-- | src/net_client.c | 72 | ||||
-rw-r--r-- | src/net_defs.h | 6 | ||||
-rw-r--r-- | src/net_server.c | 158 |
3 files changed, 210 insertions, 26 deletions
diff --git a/src/net_client.c b/src/net_client.c index b1f14c20..c5bb5ed1 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.c 323 2006-01-22 22:29:42Z fraggle $ +// $Id: net_client.c 370 2006-02-17 20:15:16Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.24 2006/02/17 20:15:16 fraggle +// Request resends for missed packets +// // Revision 1.23 2006/01/22 22:29:42 fraggle // Periodically request the time from clients to estimate their offset to // the server time. @@ -217,34 +220,13 @@ void NET_CL_StartGame(void) NET_WriteSettings(packet, &settings); } -// Add a new ticcmd to the send queue - -void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic) +static void NET_CL_SendTics(int start, int end) { - net_ticdiff_t diff; net_packet_t *packet; - int start, end; int i; - - // Calculate the difference to the last ticcmd - - NET_TiccmdDiff(&last_ticcmd, ticcmd, &diff); - - // Store in the send queue - - ticcmd_send_queue[maketic % NET_TICCMD_QUEUE_SIZE] = diff; - - last_ticcmd = *ticcmd; - - // We need to generate a new packet containing the new ticcmd to send - // to the server. Work out which ticcmds we are sending. - -// start = maketic - extratics; if (start < 0) start = 0; - - end = maketic; // Build a new packet to send to the server @@ -277,6 +259,27 @@ void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic) NET_FreePacket(packet); } +// Add a new ticcmd to the send queue + +void NET_CL_SendTiccmd(ticcmd_t *ticcmd, int maketic) +{ + net_ticdiff_t diff; + + // Calculate the difference to the last ticcmd + + NET_TiccmdDiff(&last_ticcmd, ticcmd, &diff); + + // Store in the send queue + + ticcmd_send_queue[maketic % NET_TICCMD_QUEUE_SIZE] = diff; + + last_ticcmd = *ticcmd; + + // Send to server. + + NET_CL_SendTics(maketic, maketic); +} + // data received while we are waiting for the game to start static void NET_CL_ParseWaitingData(net_packet_t *packet) @@ -399,6 +402,26 @@ static void NET_CL_ParseTimeRequest(net_packet_t *packet) NET_FreePacket(reply); } +// Parse a resend request from the server due to a dropped packet + +static void NET_CL_ParseResendRequest(net_packet_t *packet) +{ + static unsigned int start; + static unsigned int num_tics; + + if (!NET_ReadInt32(packet, &start) + || !NET_ReadInt8(packet, &num_tics)) + { + return; + } + + // Resend those tics + + printf("CL: resend %i-%i\n", start, start+num_tics-1); + + NET_CL_SendTics(start, start + num_tics - 1); +} + // parse a received packet static void NET_CL_ParsePacket(net_packet_t *packet) @@ -433,6 +456,9 @@ static void NET_CL_ParsePacket(net_packet_t *packet) NET_CL_ParseTimeRequest(packet); break; + case NET_PACKET_TYPE_GAMEDATA_RESEND: + NET_CL_ParseResendRequest(packet); + default: break; } diff --git a/src/net_defs.h b/src/net_defs.h index ffb84152..9dc12d8d 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_defs.h 369 2006-02-16 01:12:28Z fraggle $ +// $Id: net_defs.h 370 2006-02-17 20:15:16Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.13 2006/02/17 20:15:16 fraggle +// Request resends for missed packets +// // Revision 1.12 2006/02/16 01:12:28 fraggle // Define a new type net_full_ticcmd_t, a structure containing all ticcmds // for a given tic. Store received game data in a receive window. Add @@ -161,6 +164,7 @@ typedef enum NET_PACKET_TYPE_RELIABLE_ACK, NET_PACKET_TYPE_TIME_REQ, NET_PACKET_TYPE_TIME_RESP, + NET_PACKET_TYPE_GAMEDATA_RESEND, } net_packet_type_t; typedef struct diff --git a/src/net_server.c b/src/net_server.c index 7922596e..c8bdad4a 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_server.c 369 2006-02-16 01:12:28Z fraggle $ +// $Id: net_server.c 370 2006-02-17 20:15:16Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.25 2006/02/17 20:15:16 fraggle +// Request resends for missed packets +// // Revision 1.24 2006/02/16 01:12:28 fraggle // Define a new type net_full_ticcmd_t, a structure containing all ticcmds // for a given tic. Store received game data in a receive window. Add @@ -171,8 +174,21 @@ typedef struct typedef struct { + // Whether this tic has been received yet + boolean active; + + // Time this tic was generated (adjusted for time offset between + // client and server + unsigned int time; + + // Last time we sent a resend request for this tic + + unsigned int resend_time; + + // Tic data itself + net_ticdiff_t diff; } net_client_recv_t; @@ -653,6 +669,48 @@ static void NET_SV_ParseTimeResponse(net_packet_t *packet, net_client_t *client) printf("client %p time offset: %i(%i)->%i\n", client, time_offset, rtt, client->time_offset); } +// Send a resend request to a client + +static void NET_SV_SendResendRequest(net_client_t *client, int start, int end) +{ + net_packet_t *packet; + net_client_recv_t *recvobj; + int i; + unsigned int nowtime; + int index; + + printf("SV: send resend for %i-%i\n", start, end); + + packet = NET_NewPacket(20); + + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA_RESEND); + NET_WriteInt32(packet, start); + NET_WriteInt8(packet, end - start + 1); + + NET_Conn_SendPacket(&client->connection, packet); + NET_FreePacket(packet); + + // Store the time we send the resend request + + nowtime = I_GetTimeMS(); + + for (i=start; i<=end; ++i) + { + index = i - recvwindow_start; + + if (index >= BACKUPTICS) + { + // Outside the range + + continue; + } + + recvobj = &recvwindow[index][client->player_number]; + + recvobj->resend_time = nowtime; + } +} + // Process game data from a client static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) @@ -660,8 +718,11 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) net_client_recv_t *recvobj; unsigned int seq; unsigned int num_tics; + unsigned int nowtime; int i; int player; + int resend_start; + int index; if (server_state != SERVER_IN_GAME) { @@ -680,14 +741,19 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) // Expand 8-bit value to the full sequence number + printf("SV: expanding %i ", seq); + seq = NET_SV_ExpandTicNum(seq); + printf("to %i(%i)\n", seq, recvwindow_start); + // Sanity checks + printf("SV: data %i-%i\n", seq, seq+num_tics-1); + for (i=0; i<num_tics; ++i) { net_ticdiff_t diff; - int index; if (!NET_ReadTiccmdDiff(packet, &diff, false)) { @@ -707,6 +773,50 @@ static void NET_SV_ParseGameData(net_packet_t *packet, net_client_t *client) recvobj->active = true; recvobj->diff = diff; } + + // Has this been received out of sequence, ie. have we not received + // all tics before the first tic in this packet? If so, send a + // resend request. + + nowtime = I_GetTimeMS(); + resend_start = seq; + + for (i = seq - 1; i >= recvwindow_start; --i) + { + index = i - recvwindow_start; + + if (index >= recvwindow_start + BACKUPTICS) + { + // Outside of the range of the recv window + + continue; + } + + recvobj = &recvwindow[index][player]; + + if (recvobj->active) + { + // ended our run of unreceived tics + + break; + } + + if (recvobj->resend_time != 0) + { + // Already sent a resend request for this tic + + break; + } + + resend_start = i; + } + + // Possibly send a resend request + + if (resend_start < seq) + { + NET_SV_SendResendRequest(client, resend_start, seq - 1); + } } // Process a packet received by the server @@ -840,6 +950,45 @@ static void NET_SV_SendTimeRequest(net_client_t *client) client->last_time_req_time = I_GetTimeMS(); } +static void NET_SV_SendTics(net_client_t *client, int start, int end) +{ + net_packet_t *packet; + int i; + + packet = NET_NewPacket(500); + + NET_WriteInt16(packet, NET_PACKET_TYPE_GAMEDATA); + + // Send the start tic and number of tics + + NET_WriteInt8(packet, start & 0xff); + NET_WriteInt8(packet, end-start + 1); + + // Write the tics + + for (i=start; i<=end; ++i) + { + net_full_ticcmd_t *cmd; + + cmd = &client->sendqueue[i % BACKUPTICS]; + + if (i != cmd->seq) + { + I_Error("Wanted to send %i, but %i is in its place", i, cmd->seq); + } + + // Add command + + NET_WriteFullTiccmd(packet, cmd); + } + + // Send packet + + NET_Conn_SendPacket(&client->connection, packet); + + NET_FreePacket(packet); +} + static void NET_SV_PumpSendQueue(net_client_t *client) { net_full_ticcmd_t cmd; @@ -903,6 +1052,11 @@ static void NET_SV_PumpSendQueue(net_client_t *client) client->sendqueue[client->sendseq % BACKUPTICS] = cmd; + // Transmit the new tic to the client + // TODO: extratics + + NET_SV_SendTics(client, client->sendseq, client->sendseq); + ++client->sendseq; } |