diff options
author | Simon Howard | 2006-01-01 23:54:31 +0000 |
---|---|---|
committer | Simon Howard | 2006-01-01 23:54:31 +0000 |
commit | 93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802 (patch) | |
tree | 882b8662d6237d09f3d26e7b046aee5ed66fe8b9 | |
parent | 34c3dd253fa3d56b16c11a5263ffb3378529fc33 (diff) | |
download | chocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.tar.gz chocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.tar.bz2 chocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.zip |
Client disconnect code
Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 238
-rw-r--r-- | src/d_net.c | 9 | ||||
-rw-r--r-- | src/net_client.c | 143 | ||||
-rw-r--r-- | src/net_client.h | 6 | ||||
-rw-r--r-- | src/net_defs.h | 7 | ||||
-rw-r--r-- | src/net_server.c | 126 |
5 files changed, 266 insertions, 25 deletions
diff --git a/src/d_net.c b/src/d_net.c index 73f57612..f404d4ca 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: d_net.c 237 2006-01-01 23:53:15Z fraggle $ +// $Id: d_net.c 238 2006-01-01 23:54:31Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -22,6 +22,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.11 2006/01/01 23:54:31 fraggle +// Client disconnect code +// // Revision 1.10 2006/01/01 23:53:15 fraggle // Remove GS_WAITINGSTART gamestate. This will be independent of the main // loop to avoid interfering with the main game code too much. @@ -67,7 +70,7 @@ //----------------------------------------------------------------------------- -static const char rcsid[] = "$Id: d_net.c 237 2006-01-01 23:53:15Z fraggle $"; +static const char rcsid[] = "$Id: d_net.c 238 2006-01-01 23:54:31Z fraggle $"; #include "m_menu.h" @@ -684,6 +687,8 @@ void D_QuitNetGame (void) if (debugfile) fclose (debugfile); + NET_ClientDisconnect(); + if (!netgame || !usergame || consoleplayer == -1 || demoplayback) return; diff --git a/src/net_client.c b/src/net_client.c index 241f0227..e75ad2b2 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.c 235 2005-12-30 18:58:22Z fraggle $ +// $Id: net_client.c 238 2006-01-01 23:54:31Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.4 2006/01/01 23:54:31 fraggle +// Client disconnect code +// // Revision 1.3 2005/12/30 18:58:22 fraggle // Fix client code to correctly send reply to server on connection. // Add "waiting screen" while waiting for the game to start. @@ -60,6 +63,14 @@ typedef enum // in game CLIENT_STATE_IN_GAME, + + // in disconnect state: sent DISCONNECT, waiting for DISCONNECT_ACK reply + + CLIENT_STATE_DISCONNECTING, + + // successfully disconnected + + CLIENT_STATE_DISCONNECTED, } net_clientstate_t; static boolean client_initialised = false; @@ -109,6 +120,42 @@ static void ClientParseACK(net_packet_t *packet) } } +// parse a DISCONNECT packet + +static void ClientParseDisconnect(net_packet_t *packet) +{ + net_packet_t *reply; + + // construct a DISCONNECT_ACK reply packet + + reply = NET_NewPacket(10); + NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); + + // send the reply several times, in case of packet loss + + NET_SendPacket(server_addr, reply); + NET_SendPacket(server_addr, reply); + NET_SendPacket(server_addr, reply); + + client_state = CLIENT_STATE_DISCONNECTED; + + I_Error("Disconnected from server.\n"); +} + +// parse a DISCONNECT_ACK packet + +static void ClientParseDisconnectACK(net_packet_t *packet) +{ + if (client_state == CLIENT_STATE_DISCONNECTING) + { + // successfully disconnected from the server. + + client_state = CLIENT_STATE_DISCONNECTED; + + // now what? + } +} + // parse a received packet static void ClientParsePacket(net_packet_t *packet) @@ -139,6 +186,15 @@ static void ClientParsePacket(net_packet_t *packet) case NET_PACKET_TYPE_GAMEDATA: break; + + case NET_PACKET_TYPE_DISCONNECT: + ClientParseDisconnect(packet); + break; + + case NET_PACKET_TYPE_DISCONNECT_ACK: + ClientParseDisconnectACK(packet); + break; + default: break; } @@ -176,6 +232,35 @@ static void ClientConnecting(void) } } +// Called when we are in the "disconnecting" state, disconnecting from +// the server. + +static void ClientDisconnecting(void) +{ + net_packet_t *packet; + + // send a DISCONNECT packet every second + + if (last_send_time < 0 || I_GetTimeMS() - last_send_time > 1000) + { + // construct packet + + packet = NET_NewPacket(10); + + // packet type + + NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT); + + // send to the server + + NET_SendPacket(server_addr, packet); + + NET_FreePacket(packet); + + last_send_time = I_GetTimeMS(); + } +} + // "Run" the client code: check for new packets, send packets as // needed @@ -208,9 +293,10 @@ void NET_ClientRun(void) case CLIENT_STATE_CONNECTING: ClientConnecting(); break; - case CLIENT_STATE_WAITING_START: + case CLIENT_STATE_DISCONNECTING: + ClientDisconnecting(); break; - case CLIENT_STATE_IN_GAME: + default: break; } } @@ -263,6 +349,10 @@ boolean NET_ClientConnect(net_addr_t *addr) // connect NET_ServerRun(); + + // Don't hog the CPU + + I_Sleep(10); } if (client_state != CLIENT_STATE_CONNECTING) @@ -279,4 +369,51 @@ boolean NET_ClientConnect(net_addr_t *addr) } } +// disconnect from the server + +void NET_ClientDisconnect(void) +{ + int start_time; + + if (!client_initialised) + { + return; + } + + // set the client into the DISCONNECTING state + + if (client_state != CLIENT_STATE_DISCONNECTED) + { + client_state = CLIENT_STATE_DISCONNECTING; + last_send_time = -1; + } + + start_time = I_GetTimeMS(); + + while (client_state != CLIENT_STATE_DISCONNECTED) + { + if (I_GetTimeMS() - start_time > 5000) + { + // time out after 5 seconds + + client_state = CLIENT_STATE_DISCONNECTED; + + fprintf(stderr, "NET_ClientDisconnect: Timeout while disconnecting from server\n"); + break; + } + + NET_ClientRun(); + NET_ServerRun(); + + I_Sleep(10); + } + + // Finished sending disconnect packets, etc. + + // Shut down network module, etc. To do. + + NET_FreeAddress(server_addr); + + client_initialised = false; +} diff --git a/src/net_client.h b/src/net_client.h index 47a1a45b..7f3c08d5 100644 --- a/src/net_client.h +++ b/src/net_client.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_client.h 235 2005-12-30 18:58:22Z fraggle $ +// $Id: net_client.h 238 2006-01-01 23:54:31Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.4 2006/01/01 23:54:31 fraggle +// Client disconnect code +// // Revision 1.3 2005/12/30 18:58:22 fraggle // Fix client code to correctly send reply to server on connection. // Add "waiting screen" while waiting for the game to start. @@ -43,6 +46,7 @@ #include "net_defs.h" boolean NET_ClientConnect(net_addr_t *addr); +void NET_ClientDisconnect(void); void NET_ClientRun(void); #endif /* #ifndef NET_CLIENT_H */ diff --git a/src/net_defs.h b/src/net_defs.h index ea732793..d01fa576 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_defs.h 235 2005-12-30 18:58:22Z fraggle $ +// $Id: net_defs.h 238 2006-01-01 23:54:31Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.4 2006/01/01 23:54:31 fraggle +// Client disconnect code +// // Revision 1.3 2005/12/30 18:58:22 fraggle // Fix client code to correctly send reply to server on connection. // Add "waiting screen" while waiting for the game to start. @@ -111,6 +114,8 @@ typedef enum NET_PACKET_TYPE_WAITING_DATA, NET_PACKET_TYPE_GAMESTART, NET_PACKET_TYPE_GAMEDATA, + NET_PACKET_TYPE_DISCONNECT, + NET_PACKET_TYPE_DISCONNECT_ACK, } net_packet_type_t; typedef struct diff --git a/src/net_server.c b/src/net_server.c index ee9ff91b..85c4eeed 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_server.c 235 2005-12-30 18:58:22Z fraggle $ +// $Id: net_server.c 238 2006-01-01 23:54:31Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -21,6 +21,9 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.4 2006/01/01 23:54:31 fraggle +// Client disconnect code +// // Revision 1.3 2005/12/30 18:58:22 fraggle // Fix client code to correctly send reply to server on connection. // Add "waiting screen" while waiting for the game to start. @@ -60,6 +63,13 @@ typedef enum CLIENT_STATE_IN_GAME, + // sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply + + CLIENT_STATE_DISCONNECTING, + + // client successfully disconnected + + CLIENT_STATE_DISCONNECTED, } net_clientstate_t; #define MAX_RETRIES 5 @@ -77,6 +87,17 @@ static boolean server_initialised = false; static net_client_t clients[MAXNETNODES]; static net_context_t *server_context; +static boolean ClientConnected(net_client_t *client) +{ + // Check that the client is properly connected: ie. not in the + // process of connecting or disconnecting + + return clients->active + && clients->state != CLIENT_STATE_DISCONNECTING + && clients->state != CLIENT_STATE_DISCONNECTED + && clients->state != CLIENT_STATE_WAITING_ACK; +} + // returns the number of clients connected static int ServerNumClients(void) @@ -88,7 +109,7 @@ static int ServerNumClients(void) for (i=0; i<MAXNETNODES; ++i) { - if (clients[i].active) + if (ClientConnected(&clients[i])) { ++count; } @@ -107,7 +128,7 @@ static net_client_t *ServerController(void) for (i=0; i<MAXNETNODES; ++i) { - if (clients[i].active) + if (ClientConnected(&clients[i])) { return &clients[i]; } @@ -116,6 +137,25 @@ static net_client_t *ServerController(void) return NULL; } +// Given an address, find the corresponding client + +static net_client_t *ServerFindClient(net_addr_t *addr) +{ + int i; + + for (i=0; i<MAXNETNODES; ++i) + { + if (clients[i].active && clients[i].addr == addr) + { + // found the client + + return &clients[i]; + } + } + + return NULL; +} + // parse a SYN from a client(initiating a connection) static void ServerParseSYN(net_packet_t *packet, @@ -195,28 +235,51 @@ static void ServerParseACK(net_packet_t *packet, net_client_t *client) } } +static void ServerParseDisconnect(net_packet_t *packet, net_client_t *client) +{ + net_packet_t *reply; + + // sanity check + + if (client == NULL) + { + return; + } + + // This client wants to disconnect from the server. + // Send a DISCONNECT_ACK reply. + + reply = NET_NewPacket(10); + NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK); + NET_SendPacket(client->addr, reply); + NET_FreePacket(reply); + + client->last_send_time = I_GetTimeMS(); + + // Do not set to inactive immediately. Instead, set to the + // DISCONNECTED state. This is in case our acknowledgement is + // not received and another must be sent. + // + // After a few seconds, the client will get properly removed + // and cleaned up from the clients list. + + client->state = CLIENT_STATE_DISCONNECTED; + + printf("client %i disconnected\n", client-clients); +} + // Process a packet received by the server static void ServerPacket(net_packet_t *packet, net_addr_t *addr) { net_client_t *client; unsigned int packet_type; - int i; - // find which client this packet came from + // Find which client this packet came from - client = NULL; + client = ServerFindClient(addr); - for (i=0; i<MAXNETNODES; ++i) - { - if (clients[i].active && clients[i].addr == addr) - { - // found the client - - client = &clients[i]; - break; - } - } + // Read the packet type if (!NET_ReadInt16(packet, &packet_type)) { @@ -237,11 +300,22 @@ static void ServerPacket(net_packet_t *packet, net_addr_t *addr) break; case NET_PACKET_TYPE_GAMEDATA: break; + case NET_PACKET_TYPE_DISCONNECT: + ServerParseDisconnect(packet, client); + break; default: // unknown packet type break; } + + // If this address is not in the list of clients, be sure to + // free it back. + + if (ServerFindClient(addr) == NULL) + { + NET_FreeAddress(addr); + } } @@ -302,9 +376,8 @@ static void ServerRunClient(net_client_t *client) { // no more retries allowed. - NET_FreeAddress(client->addr); - client->active = false; + NET_FreeAddress(client->addr); } } } @@ -313,12 +386,29 @@ static void ServerRunClient(net_client_t *client) if (client->state == CLIENT_STATE_WAITING_START) { + // Send information once every second + if (client->last_send_time < 0 || I_GetTimeMS() - client->last_send_time > 1000) { ServerSendWaitingData(client); } } + + // Client has disconnected. + // + // See ServerParseDisconnect() above. + + if (client->state == CLIENT_STATE_DISCONNECTED) + { + // Remove from the list after five seconds + + if (I_GetTimeMS() - client->last_send_time > 5000) + { + client->active = false; + NET_FreeAddress(client->addr); + } + } } // Initialise server and wait for connections |