From e15ddb2d293570992ca8b486f4b6233a648105a1 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 8 Jan 2006 00:10:48 +0000 Subject: Move common connection code into net_common.c, shared by server and client code. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 263 --- src/Makefile.am | 3 +- src/net_client.c | 228 ++++++++---------------------------------- src/net_common.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/net_common.h | 90 +++++++++++++++++ src/net_server.c | 299 ++++++++++++++----------------------------------------- 5 files changed, 482 insertions(+), 410 deletions(-) create mode 100644 src/net_common.c create mode 100644 src/net_common.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 22425ff7..c34bba53 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -57,7 +57,8 @@ m_misc.c m_misc.h \ 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 \ diff --git a/src/net_client.c b/src/net_client.c index 7628530e..68906cb1 100644 --- 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 @@ typedef enum 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 @@ static void NET_CL_ParseWaitingData(net_packet_t *packet) } } -// 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,97 +185,27 @@ static void NET_CL_ParsePacket(net_packet_t *packet) return; } - switch (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; - } -} - -// 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) + if (NET_Conn_Packet(&client_connection, packet, packet_type)) { - // construct a SYN packet - - packet = NET_NewPacket(10); - - // packet type - - NET_WriteInt16(packet, NET_PACKET_TYPE_SYN); - - // 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(); + // Packet eaten by the common connection code } -} - -// 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) + else { - // construct packet - - packet = NET_NewPacket(10); - - // packet type - - NET_WriteInt16(packet, NET_PACKET_TYPE_DISCONNECT); - - // send to the server + switch (packet_type) + { + case NET_PACKET_TYPE_WAITING_DATA: + NET_CL_ParseWaitingData(packet); + break; - NET_SendPacket(server_addr, packet); + case NET_PACKET_TYPE_GAMESTART: + break; - NET_FreePacket(packet); + case NET_PACKET_TYPE_GAMEDATA: + break; - last_send_time = I_GetTimeMS(); + default: + break; + } } } @@ -372,19 +234,12 @@ void NET_CL_Run(void) 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 @@ boolean NET_CL_Connect(net_addr_t *addr) 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 @@ boolean NET_CL_Connect(net_addr_t *addr) 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 @@ void NET_CL_Disconnect(void) return; } - // set the client into the DISCONNECTING state - - if (client_state != CLIENT_STATE_DISCONNECTED) - { - client_state = CLIENT_STATE_DISCONNECTING; - last_send_time = -1; - } + NET_Conn_Disconnect(&client_connection); 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; diff --git a/src/net_common.c b/src/net_common.c new file mode 100644 index 00000000..27d82965 --- /dev/null +++ b/src/net_common.c @@ -0,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; + } + } +} + + + diff --git a/src/net_common.h b/src/net_common.h new file mode 100644 index 00000000..f24c6cec --- /dev/null +++ b/src/net_common.h @@ -0,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 */ + diff --git a/src/net_server.c b/src/net_server.c index b50d7035..82427b0b 100644 --- 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,53 +83,35 @@ #include "net_server.h" #include "net_sdl.h" -typedef enum +typedef enum { - // received a syn, sent an ack, waiting for an ack reply - - CLIENT_STATE_WAITING_ACK, - - // waiting for a game to start - - CLIENT_STATE_WAITING_START, - - // in game - - CLIENT_STATE_IN_GAME, - - // sent a DISCONNECT packet, waiting for a DISCONNECT_ACK reply + // waiting for the game to start - CLIENT_STATE_DISCONNECTING, + SERVER_WAITING_START, - // client successfully disconnected + // in a game - CLIENT_STATE_DISCONNECTED, -} net_clientstate_t; - -#define MAX_RETRIES 5 + SERVER_IN_GAME, +} net_server_state_t; 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; 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 @@ static boolean ClientConnected(net_client_t *client) // 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 @@ static void NET_SV_ParseSYN(net_packet_t *packet, if (!clients[i].active) { client = &clients[i]; - client->active = true; - client->addr = addr; - client->state = CLIENT_STATE_DISCONNECTED; break; } } @@ -245,99 +227,32 @@ static void NET_SV_ParseSYN(net_packet_t *packet, 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) - { - return; - } - - if (client->state == CLIENT_STATE_WAITING_ACK) + if (!client->active) { - // 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; - } - - // 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; + // force an acknowledgement + client->connection.last_send_time = -1; } } @@ -361,30 +276,31 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) return; } - //printf("SV: %s: %i\n", NET_AddrToString(addr), packet_type); - - switch (packet_type) + if (packet_type == NET_PACKET_TYPE_SYN) + { + NET_SV_ParseSYN(packet, client, addr); + } + else if (client == NULL) { - 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 - - break; + // 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); + + 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,48 +355,34 @@ static void NET_SV_SendWaitingData(net_client_t *client) NET_SendPacket(client->addr, packet); NET_FreePacket(packet); - - // update time - - client->last_send_time = I_GetTimeMS(); } // Perform any needed action on a client static void NET_SV_RunClient(net_client_t *client) { - net_packet_t *packet; + // Run common code - if (client->state == CLIENT_STATE_WAITING_ACK) - { - 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. - - if (client->num_retries < MAX_RETRIES) - { - // send another ACK + NET_Conn_Run(&client->connection); + + // Is this client disconnected? - 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(); + if (client->connection.state == NET_CONN_STATE_DISCONNECTED) + { + // deactivate and free back - ++client->num_retries; - } - else - { - // no more retries allowed. + client->active = false; + NET_FreeAddress(client->addr); + } + + if (!ClientConnected(client)) + { + // client has not yet finished connecting - 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,55 +392,7 @@ static void NET_SV_RunClient(net_client_t *client) || I_GetTimeMS() - client->last_send_time > 1000) { NET_SV_SendWaitingData(client); - } - } - 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); + client->last_send_time = I_GetTimeMS(); } } } @@ -564,6 +418,7 @@ void NET_SV_Init(void) clients[i].active = false; } + server_state = SERVER_WAITING_START; server_initialised = true; } -- cgit v1.2.3