summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Howard2006-01-01 23:54:31 +0000
committerSimon Howard2006-01-01 23:54:31 +0000
commit93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802 (patch)
tree882b8662d6237d09f3d26e7b046aee5ed66fe8b9 /src
parent34c3dd253fa3d56b16c11a5263ffb3378529fc33 (diff)
downloadchocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.tar.gz
chocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.tar.bz2
chocolate-doom-93ac1b74ab0f082a3ee8f1efc0ccd7f47bac3802.zip
Client disconnect code
Subversion-branch: /trunk/chocolate-doom Subversion-revision: 238
Diffstat (limited to 'src')
-rw-r--r--src/d_net.c9
-rw-r--r--src/net_client.c143
-rw-r--r--src/net_client.h6
-rw-r--r--src/net_defs.h7
-rw-r--r--src/net_server.c126
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