summaryrefslogtreecommitdiff
path: root/src/net_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net_common.c')
-rw-r--r--src/net_common.c272
1 files changed, 272 insertions, 0 deletions
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;
+ }
+ }
+}
+
+
+