Client disconnect code
Subversion-branch: /trunk/chocolate-doom Subversion-revision: 238
This commit is contained in:
parent
34c3dd253f
commit
93ac1b74ab
5 changed files with 266 additions and 25 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
143
src/net_client.c
143
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
126
src/net_server.c
126
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue