[chocolate-doom] 10/79: Client disconnect code

Jonathan Dowland jmtd at moszumanska.debian.org
Mon Jan 30 15:07:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

jmtd pushed a commit to annotated tag chocolate-doom-0.1.3
in repository chocolate-doom.

commit 93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802
Author: Simon Howard <fraggle at gmail.com>
Date:   Sun Jan 1 23:54:31 2006 +0000

    Client disconnect code
    
    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 238
---
 src/d_net.c      |   9 +++-
 src/net_client.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/net_client.h |   6 ++-
 src/net_defs.h   |   7 ++-
 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 73f5761..f404d4c 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 241f022..e75ad2b 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 47a1a45..7f3c08d 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 ea73279..d01fa57 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 ee9ff91..85c4eee 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

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/chocolate-doom.git



More information about the Pkg-games-commits mailing list