ref: e15ddb2d293570992ca8b486f4b6233a648105a1
parent: 79b77612579be43566fcbac7a153da22b4cd9dd7
author: Simon Howard <fraggle@gmail.com>
date: Sat Jan 7 19:10:48 EST 2006
Move common connection code into net_common.c, shared by server and client code. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 263
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -57,7 +57,8 @@
mmus2mid.c mmus2mid.h \
m_random.c m_random.h \
m_swap.c m_swap.h \
-net_client.c \
+net_client.c net_client.h \
+net_common.c net_common.h \
net_defs.h \
net_gui.c net_gui.h \
net_io.c net_io.h \
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_client.c 262 2006-01-07 20:08:11Z fraggle $
+// $Id: net_client.c 263 2006-01-08 00:10:48Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,10 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.10 2006/01/08 00:10:47 fraggle
+// Move common connection code into net_common.c, shared by server
+// and client code.
+//
// Revision 1.9 2006/01/07 20:08:11 fraggle
// Send player name and address in the waiting data packets. Display these
// on the waiting screen, and improve the waiting screen appearance.
@@ -63,6 +67,7 @@
#include "doomstat.h"
#include "i_system.h"
#include "net_client.h"
+#include "net_common.h"
#include "net_defs.h"
#include "net_gui.h"
#include "net_io.h"
@@ -71,10 +76,6 @@
typedef enum
{
- // sent a syn, not received an ack yet
-
- CLIENT_STATE_CONNECTING,
-
// waiting for the game to start
CLIENT_STATE_WAITING_START,
@@ -83,23 +84,17 @@
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 net_connection_t client_connection;
static net_clientstate_t client_state;
static net_addr_t *server_addr;
static net_context_t *client_context;
static int last_send_time;
-// if TRUE, we are connected to a server
+// TRUE if the client code is in use
-boolean net_client_connected = false;
+boolean net_client_connected;
// if TRUE, this client is the controller of the game
@@ -179,69 +174,6 @@
}
}
-// Received an ACK
-
-static void NET_CL_ParseACK(net_packet_t *packet)
-{
- net_packet_t *reply;
-
- // send an ACK back
-
- reply = NET_NewPacket(10);
- NET_WriteInt16(reply, NET_PACKET_TYPE_ACK);
- NET_SendPacket(server_addr, reply);
- NET_FreePacket(reply);
-
- // set the client state if we havent already
-
- if (client_state == CLIENT_STATE_CONNECTING)
- {
- client_state = CLIENT_STATE_WAITING_START;
- }
-}
-
-// parse a DISCONNECT packet
-
-static void NET_CL_ParseDisconnect(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);
- NET_FreePacket(reply);
-
- client_state = CLIENT_STATE_DISCONNECTED;
-
- //I_Error("Disconnected from server.\n");
- fprintf(stderr, "Disconnected from server.\n");
-
- // Now what?
-
- NET_CL_Disconnect();
-}
-
-// parse a DISCONNECT_ACK packet
-
-static void NET_CL_ParseDisconnectACK(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 NET_CL_ParsePacket(net_packet_t *packet)
@@ -253,100 +185,30 @@
return;
}
- switch (packet_type)
+ if (NET_Conn_Packet(&client_connection, packet, packet_type))
{
- case NET_PACKET_TYPE_ACK:
-
- // received an acknowledgement to the SYN we sent
-
- NET_CL_ParseACK(packet);
- break;
-
- case NET_PACKET_TYPE_WAITING_DATA:
-
- NET_CL_ParseWaitingData(packet);
- break;
-
- case NET_PACKET_TYPE_GAMESTART:
- break;
-
- case NET_PACKET_TYPE_GAMEDATA:
- break;
-
- case NET_PACKET_TYPE_DISCONNECT:
- NET_CL_ParseDisconnect(packet);
- break;
-
- case NET_PACKET_TYPE_DISCONNECT_ACK:
- NET_CL_ParseDisconnectACK(packet);
- break;
-
- default:
- break;
+ // Packet eaten by the common connection code
}
-}
-
-// called when we are in the "connecting" state
-
-static void NET_CL_Connecting(void)
-{
- net_packet_t *packet;
-
- // send a SYN packet every second
-
- if (last_send_time < 0 || I_GetTimeMS() - last_send_time > 1000)
+ else
{
- // construct a SYN packet
+ switch (packet_type)
+ {
+ case NET_PACKET_TYPE_WAITING_DATA:
+ NET_CL_ParseWaitingData(packet);
+ break;
- packet = NET_NewPacket(10);
+ case NET_PACKET_TYPE_GAMESTART:
+ break;
- // packet type
-
- NET_WriteInt16(packet, NET_PACKET_TYPE_SYN);
+ case NET_PACKET_TYPE_GAMEDATA:
+ break;
- // magic number
-
- NET_WriteInt32(packet, NET_MAGIC_NUMBER);
-
- // send to the server
-
- NET_SendPacket(server_addr, packet);
-
- NET_FreePacket(packet);
-
- last_send_time = I_GetTimeMS();
+ default:
+ break;
+ }
}
}
-// Called when we are in the "disconnecting" state, disconnecting from
-// the server.
-
-static void NET_CL_Disconnecting(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
@@ -372,19 +234,12 @@
NET_FreePacket(packet);
}
- // send packets as needed
+ // Run the common connection code to send any packets as needed
- switch (client_state)
- {
- case CLIENT_STATE_CONNECTING:
- NET_CL_Connecting();
- break;
- case CLIENT_STATE_DISCONNECTING:
- NET_CL_Disconnecting();
- break;
- default:
- break;
- }
+ NET_Conn_Run(&client_connection);
+
+ net_waiting_for_start = client_connection.state == NET_CONN_STATE_CONNECTED
+ && client_state == CLIENT_STATE_WAITING_START;
}
// connect to a server
@@ -410,16 +265,18 @@
NET_AddModule(client_context, addr->module);
net_client_connected = true;
- net_waiting_for_start = true;
+ // Initialise connection
+
+ NET_Conn_InitClient(&client_connection, addr);
+
// try to connect
- client_state = CLIENT_STATE_CONNECTING;
last_send_time = -1;
start_time = I_GetTimeMS();
- while (client_state == CLIENT_STATE_CONNECTING)
+ while (client_connection.state == NET_CONN_STATE_CONNECTING)
{
// time out after 5 seconds
@@ -442,10 +299,12 @@
I_Sleep(10);
}
- if (client_state != CLIENT_STATE_CONNECTING)
+ if (client_connection.state == NET_CONN_STATE_CONNECTED)
{
// connected ok!
+ client_state = CLIENT_STATE_WAITING_START;
+
return true;
}
else
@@ -469,23 +328,18 @@
return;
}
- // set the client into the DISCONNECTING state
+ NET_Conn_Disconnect(&client_connection);
- 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)
+ while (client_connection.state != NET_CONN_STATE_DISCONNECTED
+ && client_connection.state != NET_CONN_STATE_DISCONNECTED_SLEEP)
{
if (I_GetTimeMS() - start_time > 5000)
{
// time out after 5 seconds
- client_state = CLIENT_STATE_DISCONNECTED;
+ client_state = NET_CONN_STATE_DISCONNECTED;
fprintf(stderr, "NET_CL_Disconnect: Timeout while disconnecting from server\n");
break;
--- /dev/null
+++ b/src/net_common.c
@@ -1,0 +1,272 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// $Id: net_common.c 263 2006-01-08 00:10:48Z fraggle $
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// $Log$
+// Revision 1.1 2006/01/08 00:10:48 fraggle
+// Move common connection code into net_common.c, shared by server
+// and client code.
+//
+//
+// Common code shared between the client and server
+//
+
+#include "doomdef.h"
+#include "i_system.h"
+
+#include "net_common.h"
+#include "net_io.h"
+#include "net_packet.h"
+
+// Initialise as a client connection
+
+void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr)
+{
+ conn->state = NET_CONN_STATE_CONNECTING;
+ conn->last_send_time = -1;
+ conn->num_retries = 0;
+ conn->addr = addr;
+}
+
+// Initialise as a server connection
+
+void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr)
+{
+ conn->state = NET_CONN_STATE_WAITING_ACK;
+ conn->last_send_time = -1;
+ conn->num_retries = 0;
+ conn->addr = addr;
+}
+
+// parse an ACK packet from a client
+
+static void NET_Conn_ParseACK(net_connection_t *conn, net_packet_t *packet)
+{
+ net_packet_t *reply;
+
+ if (conn->state == NET_CONN_STATE_CONNECTING)
+ {
+ // We are a client
+
+ // received a response from the server to our SYN
+
+ conn->state = NET_CONN_STATE_CONNECTED;
+
+ // We must send an ACK reply to the server's ACK
+
+ reply = NET_NewPacket(10);
+ NET_WriteInt16(reply, NET_PACKET_TYPE_ACK);
+ NET_SendPacket(conn->addr, reply);
+ NET_FreePacket(reply);
+ }
+
+ if (conn->state == NET_CONN_STATE_WAITING_ACK)
+ {
+ // We are a server
+
+ // Client is connected
+
+ conn->state = NET_CONN_STATE_CONNECTED;
+ }
+}
+
+static void NET_Conn_ParseDisconnect(net_connection_t *conn, net_packet_t *packet)
+{
+ net_packet_t *reply;
+
+ // Other end wants to disconnect
+ // Send a DISCONNECT_ACK reply.
+
+ reply = NET_NewPacket(10);
+ NET_WriteInt16(reply, NET_PACKET_TYPE_DISCONNECT_ACK);
+ NET_SendPacket(conn->addr, reply);
+ NET_FreePacket(reply);
+
+ conn->last_send_time = I_GetTimeMS();
+
+ conn->state = NET_CONN_STATE_DISCONNECTED_SLEEP;
+}
+
+// Parse a DISCONNECT_ACK packet
+
+static void NET_Conn_ParseDisconnectACK(net_connection_t *conn,
+ net_packet_t *packet)
+{
+
+ if (conn->state == NET_CONN_STATE_DISCONNECTING)
+ {
+ // We have received an acknowledgement to our disconnect
+ // request. We have been disconnected successfully.
+
+ conn->state = NET_CONN_STATE_DISCONNECTED;
+ conn->last_send_time = -1;
+ }
+}
+
+// Process a packet received by the server
+//
+// Returns true if eaten by common code
+
+boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet,
+ int packet_type)
+{
+ //printf("Conn: %s: %i\n", NET_AddrToString(addr), packet_type);
+
+ switch (packet_type)
+ {
+ case NET_PACKET_TYPE_ACK:
+ NET_Conn_ParseACK(conn, packet);
+ break;
+ case NET_PACKET_TYPE_DISCONNECT:
+ NET_Conn_ParseDisconnect(conn, packet);
+ break;
+ case NET_PACKET_TYPE_DISCONNECT_ACK:
+ NET_Conn_ParseDisconnectACK(conn, packet);
+ break;
+ default:
+ // Not a common packet
+
+ return false;
+ }
+
+ // We found a packet that we found interesting, and ate it.
+
+ return true;
+}
+
+void NET_Conn_Disconnect(net_connection_t *conn)
+{
+ if (conn->state != NET_CONN_STATE_DISCONNECTED
+ && conn->state != NET_CONN_STATE_DISCONNECTING
+ && conn->state != NET_CONN_STATE_DISCONNECTED_SLEEP)
+ {
+ conn->state = NET_CONN_STATE_DISCONNECTING;
+ conn->last_send_time = -1;
+ conn->num_retries = 0;
+ }
+}
+
+void NET_Conn_Run(net_connection_t *conn)
+{
+ net_packet_t *packet;
+
+ if (conn->state == NET_CONN_STATE_CONNECTING)
+ {
+ if (conn->last_send_time < 0
+ || I_GetTimeMS() - conn->last_send_time > 1000)
+ {
+ // It has been a second since the last SYN was sent, and no
+ // reply.
+
+ if (conn->num_retries < MAX_RETRIES)
+ {
+ // send another SYN
+
+ packet = NET_NewPacket(10);
+ NET_WriteInt16(packet, NET_PACKET_TYPE_SYN);
+ NET_WriteInt32(packet, NET_MAGIC_NUMBER);
+ NET_SendPacket(conn->addr, packet);
+ NET_FreePacket(packet);
+ conn->last_send_time = I_GetTimeMS();
+
+ ++conn->num_retries;
+ }
+ else
+ {
+ conn->state = NET_CONN_STATE_DISCONNECTED;
+ }
+ }
+ }
+ else if (conn->state == NET_CONN_STATE_WAITING_ACK)
+ {
+ if (conn->last_send_time < 0
+ || I_GetTimeMS() - conn->last_send_time > 1000)
+ {
+ // it has been a second since the last ACK was sent, and
+ // still no reply.
+
+ if (conn->num_retries < MAX_RETRIES)
+ {
+ // send another ACK
+
+ packet = NET_NewPacket(10);
+ NET_WriteInt16(packet, NET_PACKET_TYPE_ACK);
+ NET_SendPacket(conn->addr, packet);
+ NET_FreePacket(packet);
+ conn->last_send_time = I_GetTimeMS();
+
+ ++conn->num_retries;
+ }
+ else
+ {
+ // no more retries allowed.
+
+ conn->state = NET_CONN_STATE_DISCONNECTED;
+ }
+ }
+ }
+ else if (conn->state == NET_CONN_STATE_DISCONNECTING)
+ {
+ // Waiting for a reply to our DISCONNECT request.
+
+ if (conn->last_send_time < 0
+ || I_GetTimeMS() - conn->last_send_time > 1000)
+ {
+ // it has been a second since the last disconnect packet
+ // was sent, and still no reply.
+
+ if (conn->num_retries < MAX_RETRIES)
+ {
+ // send another disconnect
+
+ packet = NET_NewPacket(10);
+ NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT);
+ NET_SendPacket(conn->addr, packet);
+ NET_FreePacket(packet);
+ conn->last_send_time = I_GetTimeMS();
+
+ ++conn->num_retries;
+ }
+ else
+ {
+ // No more retries allowed.
+ // Force disconnect.
+
+ conn->state = NET_CONN_STATE_DISCONNECTED;
+ }
+ }
+ }
+ else if (conn->state == NET_CONN_STATE_DISCONNECTED_SLEEP)
+ {
+ // We are disconnected, waiting in case we need to send
+ // a DISCONNECT_ACK to the server again.
+
+ if (I_GetTimeMS() - conn->last_send_time > 5000)
+ {
+ // Idle for 5 seconds, switch state
+
+ conn->state = NET_CONN_STATE_DISCONNECTED;
+ }
+ }
+}
+
+
+
--- /dev/null
+++ b/src/net_common.h
@@ -1,0 +1,90 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// $Id: net_common.h 263 2006-01-08 00:10:48Z fraggle $
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+// $Log$
+// Revision 1.1 2006/01/08 00:10:48 fraggle
+// Move common connection code into net_common.c, shared by server
+// and client code.
+//
+//
+// Common code shared between the client and server
+//
+
+#ifndef NET_COMMON_H
+#define NET_COMMON_H
+
+#include "net_defs.h"
+
+typedef enum
+{
+ // sending syn packets, waiting for an ACK reply
+ // (client side)
+
+ NET_CONN_STATE_CONNECTING,
+
+ // received a syn, sent an ack, waiting for an ack reply
+ // (server side)
+
+ NET_CONN_STATE_WAITING_ACK,
+
+ // successfully connected
+
+ NET_CONN_STATE_CONNECTED,
+
+ // sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply
+
+ NET_CONN_STATE_DISCONNECTING,
+
+ // client successfully disconnected
+
+ NET_CONN_STATE_DISCONNECTED,
+
+ // We are disconnected, but in a sleep state, waiting for several
+ // seconds. This is in case the DISCONNECT_ACK we sent failed
+ // to arrive, and we need to send another one. We keep this as
+ // a valid connection for a few seconds until we are sure that
+ // the other end has successfully disconnected as well.
+
+ NET_CONN_STATE_DISCONNECTED_SLEEP,
+
+} net_connstate_t;
+
+#define MAX_RETRIES 5
+
+typedef struct
+{
+ net_connstate_t state;
+ net_addr_t *addr;
+ int last_send_time;
+ int num_retries;
+} net_connection_t;
+
+
+void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr);
+void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr);
+boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet,
+ int packet_type);
+void NET_Conn_Disconnect(net_connection_t *conn);
+void NET_Conn_Run(net_connection_t *conn);
+
+#endif /* #ifndef NET_COMMON_H */
+
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_server.c 262 2006-01-07 20:08:11Z fraggle $
+// $Id: net_server.c 263 2006-01-08 00:10:48Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,10 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.12 2006/01/08 00:10:48 fraggle
+// Move common connection code into net_common.c, shared by server
+// and client code.
+//
// Revision 1.11 2006/01/07 20:08:11 fraggle
// Send player name and address in the waiting data packets. Display these
// on the waiting screen, and improve the waiting screen appearance.
@@ -71,6 +75,7 @@
#include "doomstat.h"
#include "i_system.h"
#include "net_client.h"
+#include "net_common.h"
#include "net_defs.h"
#include "net_io.h"
#include "net_loop.h"
@@ -78,40 +83,26 @@
#include "net_server.h"
#include "net_sdl.h"
-typedef enum
+typedef enum
{
- // received a syn, sent an ack, waiting for an ack reply
+ // waiting for the game to start
- CLIENT_STATE_WAITING_ACK,
-
- // waiting for a game to start
+ SERVER_WAITING_START,
- CLIENT_STATE_WAITING_START,
+ // in a game
- // in game
+ SERVER_IN_GAME,
+} net_server_state_t;
- 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
-
typedef struct
{
boolean active;
- net_clientstate_t state;
net_addr_t *addr;
+ net_connection_t connection;
int last_send_time;
- int num_retries;
} net_client_t;
+static net_server_state_t server_state;
static boolean server_initialised = false;
static net_client_t clients[MAXNETNODES];
static net_context_t *server_context;
@@ -118,13 +109,9 @@
static void NET_SV_DisconnectClient(net_client_t *client)
{
- if (client->active
- && client->state != CLIENT_STATE_DISCONNECTING
- && client->state != CLIENT_STATE_DISCONNECTED)
+ if (client->active)
{
- client->state = CLIENT_STATE_DISCONNECTING;
- client->num_retries = 0;
- client->last_send_time = -1;
+ NET_Conn_Disconnect(&client->connection);
}
}
@@ -133,10 +120,8 @@
// Check that the client is properly connected: ie. not in the
// process of connecting or disconnecting
- return client->active
- && client->state != CLIENT_STATE_DISCONNECTING
- && client->state != CLIENT_STATE_DISCONNECTED
- && client->state != CLIENT_STATE_WAITING_ACK;
+ return client->active
+ && client->connection.state == NET_CONN_STATE_CONNECTED;
}
// returns the number of clients connected
@@ -233,9 +218,6 @@
if (!clients[i].active)
{
client = &clients[i];
- client->active = true;
- client->addr = addr;
- client->state = CLIENT_STATE_DISCONNECTED;
break;
}
}
@@ -245,102 +227,35 @@
return;
}
}
-
- // Set into the correct state if necessary
- // Allow immediate reconnects from clients which just disconnected.
-
- if (client->state == CLIENT_STATE_DISCONNECTED)
+ else
{
- client->state = CLIENT_STATE_WAITING_ACK;
- client->num_retries = 0;
- }
+ // If this is a recently-disconnected client, deactivate
+ // to allow immediate reconnection
- if (client->state == CLIENT_STATE_WAITING_ACK)
- {
- // force an acknowledgement
-
- client->last_send_time = -1;
+ if (client->connection.state == NET_CONN_STATE_DISCONNECTED)
+ {
+ client->active = false;
+ }
}
-}
-// parse an ACK packet from a client
+ // New client?
-static void NET_SV_ParseACK(net_packet_t *packet, net_client_t *client)
-{
- if (client == NULL)
+ if (!client->active)
{
- return;
- }
-
- if (client->state == CLIENT_STATE_WAITING_ACK)
- {
- // now waiting for the game to start
-
- client->state = CLIENT_STATE_WAITING_START;
-
- // force a waiting data packet to be sent immediately
-
+ // Activate, initialise connection
+ client->active = true;
+ NET_Conn_InitServer(&client->connection, addr);
+ client->addr = addr;
client->last_send_time = -1;
}
-}
-static void NET_SV_ParseDisconnect(net_packet_t *packet, net_client_t *client)
-{
- net_packet_t *reply;
-
- // sanity check
-
- if (client == NULL)
+ if (client->connection.state == NET_CONN_STATE_WAITING_ACK)
{
- return;
+ // force an acknowledgement
+ client->connection.last_send_time = -1;
}
-
- // 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("SV: %s: client disconnected\n", NET_AddrToString(client->addr));
}
-// Parse a DISCONNECT_ACK packet
-
-static void NET_SV_ParseDisconnectACK(net_packet_t *packet,
- net_client_t *client)
-{
- // Sanity check
-
- if (client == NULL)
- {
- return;
- }
-
- if (client->state == CLIENT_STATE_DISCONNECTING)
- {
- // We have received an acknowledgement to our disconnect
- // request. Client has been disconnected successfully.
-
- // Place into the DISCONNECTED state to allow for cleanup.
-
- client->state = CLIENT_STATE_DISCONNECTED;
- client->last_send_time = -1;
- }
-}
-
// Process a packet received by the server
static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
@@ -361,30 +276,31 @@
return;
}
- //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type);
-
- switch (packet_type)
+ if (packet_type == NET_PACKET_TYPE_SYN)
{
- case NET_PACKET_TYPE_SYN:
- NET_SV_ParseSYN(packet, client, addr);
- break;
- case NET_PACKET_TYPE_ACK:
- NET_SV_ParseACK(packet, client);
- break;
- case NET_PACKET_TYPE_GAMESTART:
- break;
- case NET_PACKET_TYPE_GAMEDATA:
- break;
- case NET_PACKET_TYPE_DISCONNECT:
- NET_SV_ParseDisconnect(packet, client);
- break;
- case NET_PACKET_TYPE_DISCONNECT_ACK:
- NET_SV_ParseDisconnectACK(packet, client);
- break;
- default:
- // unknown packet type
+ NET_SV_ParseSYN(packet, client, addr);
+ }
+ else if (client == NULL)
+ {
+ // Must come from a valid client; ignore otherwise
+ }
+ else if (NET_Conn_Packet(&client->connection, packet, packet_type))
+ {
+ // Packet was eaten by the common connection code
+ }
+ else
+ {
+ //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type);
- break;
+ switch (packet_type)
+ {
+ case NET_PACKET_TYPE_GAMESTART:
+ break;
+ default:
+ // unknown packet type
+
+ break;
+ }
}
// If this address is not in the list of clients, be sure to
@@ -439,10 +355,6 @@
NET_SendPacket(client->addr, packet);
NET_FreePacket(packet);
-
- // update time
-
- client->last_send_time = I_GetTimeMS();
}
// Perform any needed action on a client
@@ -449,38 +361,28 @@
static void NET_SV_RunClient(net_client_t *client)
{
- net_packet_t *packet;
+ // Run common code
- if (client->state == CLIENT_STATE_WAITING_ACK)
+ NET_Conn_Run(&client->connection);
+
+ // Is this client disconnected?
+
+ if (client->connection.state == NET_CONN_STATE_DISCONNECTED)
{
- if (client->last_send_time < 0
- || I_GetTimeMS() - client->last_send_time > 1000)
- {
- // it has been a second since the last ACK was sent, and
- // still no reply.
+ // deactivate and free back
- if (client->num_retries < MAX_RETRIES)
- {
- // send another ACK
+ client->active = false;
+ NET_FreeAddress(client->addr);
+ }
+
+ if (!ClientConnected(client))
+ {
+ // client has not yet finished connecting
- packet = NET_NewPacket(10);
- NET_WriteInt16(packet, NET_PACKET_TYPE_ACK);
- NET_SendPacket(client->addr, packet);
- NET_FreePacket(packet);
- client->last_send_time = I_GetTimeMS();
-
- ++client->num_retries;
- }
- else
- {
- // no more retries allowed.
-
- client->active = false;
- NET_FreeAddress(client->addr);
- }
- }
+ return;
}
- else if (client->state == CLIENT_STATE_WAITING_START)
+
+ if (server_state == SERVER_WAITING_START)
{
// Waiting for the game to start
@@ -490,57 +392,9 @@
|| I_GetTimeMS() - client->last_send_time > 1000)
{
NET_SV_SendWaitingData(client);
+ client->last_send_time = I_GetTimeMS();
}
}
- else if (client->state == CLIENT_STATE_DISCONNECTING)
- {
- // Waiting for a reply to our DISCONNECT request.
-
- if (client->last_send_time < 0
- || I_GetTimeMS() - client->last_send_time > 1000)
- {
- // it has been a second since the last disconnect packet
- // was sent, and still no reply.
-
- if (client->num_retries < MAX_RETRIES)
- {
- // send another disconnect
-
- packet = NET_NewPacket(10);
- NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT);
- NET_SendPacket(client->addr, packet);
- NET_FreePacket(packet);
- client->last_send_time = I_GetTimeMS();
-
- ++client->num_retries;
- }
- else
- {
- // No more retries allowed.
- // Force disconnect.
-
- client->active = false;
- NET_FreeAddress(client->addr);
- }
- }
-
- }
- else if (client->state == CLIENT_STATE_DISCONNECTED)
- {
- // Client has disconnected.
- //
- // See NET_SV_ParseDisconnect() above.
-
- // Remove from the list after five seconds
-
- if (client->last_send_time < 0
- || I_GetTimeMS() - client->last_send_time > 5000)
- {
- //printf("SV: %s: deactivated\n", NET_AddrToString(client->addr));
- client->active = false;
- NET_FreeAddress(client->addr);
- }
- }
}
// Initialise server and wait for connections
@@ -564,6 +418,7 @@
clients[i].active = false;
}
+ server_state = SERVER_WAITING_START;
server_initialised = true;
}