summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net_client.c7
-rw-r--r--src/net_common.c195
-rw-r--r--src/net_common.h14
-rw-r--r--src/net_defs.h10
-rw-r--r--src/net_server.c7
5 files changed, 217 insertions, 16 deletions
diff --git a/src/net_client.c b/src/net_client.c
index eae95cc9..6ff437cb 100644
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_client.c 278 2006-01-09 02:03:39Z fraggle $
+// $Id: net_client.c 279 2006-01-10 19:59:26Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,9 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.16 2006/01/10 19:59:25 fraggle
+// Reliable packet transport mechanism
+//
// Revision 1.15 2006/01/09 02:03:39 fraggle
// Send clients their player number, and indicate on the waiting screen
// which client we are.
@@ -219,7 +222,7 @@ static void NET_CL_ParsePacket(net_packet_t *packet)
return;
}
- if (NET_Conn_Packet(&client_connection, packet, packet_type))
+ if (NET_Conn_Packet(&client_connection, packet, &packet_type))
{
// Packet eaten by the common connection code
}
diff --git a/src/net_common.c b/src/net_common.c
index a89b1bba..92c050e1 100644
--- a/src/net_common.c
+++ b/src/net_common.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_common.c 268 2006-01-08 04:52:26Z fraggle $
+// $Id: net_common.c 279 2006-01-10 19:59:26Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,9 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.4 2006/01/10 19:59:26 fraggle
+// Reliable packet transport mechanism
+//
// Revision 1.3 2006/01/08 04:52:26 fraggle
// Allow the server to reject clients
//
@@ -36,6 +39,8 @@
// Common code shared between the client and server
//
+#include <stdlib.h>
+
#include "doomdef.h"
#include "i_system.h"
@@ -51,24 +56,40 @@
#define KEEPALIVE_PERIOD 1
-// Initialise as a client connection
+// reliable packet that is guaranteed to reach its destination
-void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr)
+struct net_reliable_packet_s
+{
+ net_packet_t *packet;
+ int last_send_time;
+ int seq;
+ net_reliable_packet_t *next;
+};
+
+static void NET_Conn_Init(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;
+ conn->reliable_packets = NULL;
+ conn->reliable_send_seq = 0;
+ conn->reliable_recv_seq = 0;
+}
+
+// Initialise as a client connection
+
+void NET_Conn_InitClient(net_connection_t *conn, net_addr_t *addr)
+{
+ NET_Conn_Init(conn, addr);
+ conn->state = NET_CONN_STATE_CONNECTING;
}
// Initialise as a server connection
void NET_Conn_InitServer(net_connection_t *conn, net_addr_t *addr)
{
+ NET_Conn_Init(conn, addr);
conn->state = NET_CONN_STATE_WAITING_ACK;
- conn->last_send_time = -1;
- conn->num_retries = 0;
- conn->addr = addr;
}
// Send a packet to a connection
@@ -158,16 +179,117 @@ static void NET_Conn_ParseReject(net_connection_t *conn, net_packet_t *packet)
}
}
+static void NET_Conn_ParseReliableACK(net_connection_t *conn, net_packet_t *packet)
+{
+ unsigned int seq;
+
+ if (!NET_ReadInt8(packet, &seq))
+ {
+ return;
+ }
+
+ if (conn->reliable_packets == NULL)
+ {
+ return;
+ }
+
+ // Is this an acknowledgement for the first packet in the list?
+
+ if (seq == ((conn->reliable_packets->seq + 1) & 0xff))
+ {
+ net_reliable_packet_t *rp;
+
+ // Discard it, then.
+ // Unlink from the list.
+
+ rp = conn->reliable_packets;
+ conn->reliable_packets = rp->next;
+
+ NET_FreePacket(rp->packet);
+ free(rp);
+ }
+}
+
+// Process the header of a reliable packet
+//
+// Returns true if the packet should be discarded (incorrect sequence)
+
+static boolean NET_Conn_ReliablePacket(net_connection_t *conn,
+ net_packet_t *packet)
+{
+ unsigned int seq;
+ net_packet_t *reply;
+ boolean result;
+
+ // Read the sequence number
+
+ if (!NET_ReadInt8(packet, &seq))
+ {
+ return true;
+ }
+
+ if (seq != (conn->reliable_recv_seq & 0xff))
+ {
+ // This is not the next expected packet in the sequence!
+ //
+ // Discard the packet. If we were smart, we would use a proper
+ // sliding window protocol to do this, but I'm lazy.
+
+ result = true;
+ }
+ else
+ {
+ // Now we can receive the next packet in the sequence.
+
+ conn->reliable_recv_seq = (conn->reliable_recv_seq + 1) & 0xff;
+
+ result = false;
+ }
+
+ // Send an acknowledgement
+
+ // Note: this is braindead. It would be much more sensible to
+ // include this in the next packet, rather than the overhead of
+ // sending a complete packet just for one byte of information.
+
+ reply = NET_NewPacket(10);
+
+ NET_WriteInt16(reply, NET_PACKET_TYPE_RELIABLE_ACK);
+ NET_WriteInt8(reply, conn->reliable_recv_seq & 0xff);
+
+ NET_Conn_SendPacket(conn, reply);
+
+ NET_FreePacket(reply);
+
+ return result;
+}
+
// 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)
+ unsigned int *packet_type)
{
conn->keepalive_recv_time = I_GetTimeMS();
+
+ // Is this a reliable packet?
+
+ if (*packet_type & NET_RELIABLE_PACKET)
+ {
+ if (NET_Conn_ReliablePacket(conn, packet))
+ {
+ // Invalid packet: eat it.
+
+ return true;
+ }
+
+ // Remove the reliable bit
+
+ *packet_type &= ~NET_RELIABLE_PACKET;
+ }
- switch (packet_type)
+ switch (*packet_type)
{
case NET_PACKET_TYPE_ACK:
NET_Conn_ParseACK(conn, packet);
@@ -184,6 +306,9 @@ boolean NET_Conn_Packet(net_connection_t *conn, net_packet_t *packet,
case NET_PACKET_TYPE_REJECTED:
NET_Conn_ParseReject(conn, packet);
break;
+ case NET_PACKET_TYPE_RELIABLE_ACK:
+ NET_Conn_ParseReliableACK(conn, packet);
+ break;
default:
// Not a common packet
@@ -236,6 +361,21 @@ void NET_Conn_Run(net_connection_t *conn)
NET_Conn_SendPacket(conn, packet);
NET_FreePacket(packet);
}
+
+ // Check the reliable packet list. Has the first packet in the
+ // list timed out?
+ //
+ // NB. This is braindead, we have a fixed time of one second.
+
+ if (conn->reliable_packets != NULL
+ && (conn->reliable_packets->last_send_time < 0
+ || nowtime - conn->reliable_packets->last_send_time > 1000))
+ {
+ // Packet timed out, time to resend
+
+ NET_Conn_SendPacket(conn, conn->reliable_packets->packet);
+ conn->reliable_packets->last_send_time = nowtime;
+ }
}
else if (conn->state == NET_CONN_STATE_WAITING_ACK)
{
@@ -310,5 +450,42 @@ void NET_Conn_Run(net_connection_t *conn)
}
}
+net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type)
+{
+ net_packet_t *packet;
+ net_reliable_packet_t *rp;
+ net_reliable_packet_t **listend;
+
+ // Generate a packet with the right header
+
+ packet = NET_NewPacket(100);
+ NET_WriteInt16(packet, packet_type | NET_RELIABLE_PACKET);
+
+ // write the low byte of the send sequence number
+
+ NET_WriteInt8(packet, conn->reliable_send_seq & 0xff);
+
+ // Add to the list of reliable packets
+
+ rp = malloc(sizeof(net_reliable_packet_t));
+ rp->packet = packet;
+ rp->next = NULL;
+ rp->seq = conn->reliable_send_seq;
+ rp->last_send_time = -1;
+
+ for (listend = &conn->reliable_packets;
+ *listend != NULL;
+ listend = &((*listend)->next));
+
+ *listend = rp;
+
+ // Count along the sequence
+
+ conn->reliable_send_seq = (conn->reliable_send_seq + 1) & 0xff;
+
+ // Finished
+
+ return packet;
+}
diff --git a/src/net_common.h b/src/net_common.h
index 530a0e0d..4f5605dc 100644
--- a/src/net_common.h
+++ b/src/net_common.h
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_common.h 264 2006-01-08 02:53:05Z fraggle $
+// $Id: net_common.h 279 2006-01-10 19:59:26Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,9 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.3 2006/01/10 19:59:26 fraggle
+// Reliable packet transport mechanism
+//
// Revision 1.2 2006/01/08 02:53:05 fraggle
// Send keepalives if the connection is not doing anything else.
// Send all packets using a new NET_Conn_SendPacket to support this.
@@ -37,6 +40,7 @@
#define NET_COMMON_H
#include "net_defs.h"
+#include "net_packet.h"
typedef enum
{
@@ -74,6 +78,8 @@ typedef enum
#define MAX_RETRIES 5
+typedef struct net_reliable_packet_s net_reliable_packet_t;
+
typedef struct
{
net_connstate_t state;
@@ -82,6 +88,9 @@ typedef struct
int num_retries;
int keepalive_send_time;
int keepalive_recv_time;
+ net_reliable_packet_t *reliable_packets;
+ int reliable_send_seq;
+ int reliable_recv_seq;
} net_connection_t;
@@ -89,9 +98,10 @@ void NET_Conn_SendPacket(net_connection_t *conn, net_packet_t *packet);
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);
+ unsigned int *packet_type);
void NET_Conn_Disconnect(net_connection_t *conn);
void NET_Conn_Run(net_connection_t *conn);
+net_packet_t *NET_Conn_NewReliable(net_connection_t *conn, int packet_type);
#endif /* #ifndef NET_COMMON_H */
diff --git a/src/net_defs.h b/src/net_defs.h
index ccaa3a08..6a8e20cb 100644
--- a/src/net_defs.h
+++ b/src/net_defs.h
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_defs.h 268 2006-01-08 04:52:26Z fraggle $
+// $Id: net_defs.h 279 2006-01-10 19:59:26Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,9 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.7 2006/01/10 19:59:26 fraggle
+// Reliable packet transport mechanism
+//
// Revision 1.6 2006/01/08 04:52:26 fraggle
// Allow the server to reject clients
//
@@ -112,6 +115,10 @@ struct _net_addr_s
#define NET_MAGIC_NUMBER 3436803284U
+// header field value indicating that the packet is a reliable packet
+
+#define NET_RELIABLE_PACKET (1 << 15)
+
// packet types
typedef enum
@@ -125,6 +132,7 @@ typedef enum
NET_PACKET_TYPE_GAMEDATA,
NET_PACKET_TYPE_DISCONNECT,
NET_PACKET_TYPE_DISCONNECT_ACK,
+ NET_PACKET_TYPE_RELIABLE_ACK,
} net_packet_type_t;
typedef struct
diff --git a/src/net_server.c b/src/net_server.c
index 4ed2e2b3..0fb058a0 100644
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -1,7 +1,7 @@
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
-// $Id: net_server.c 278 2006-01-09 02:03:39Z fraggle $
+// $Id: net_server.c 279 2006-01-10 19:59:26Z fraggle $
//
// Copyright(C) 2005 Simon Howard
//
@@ -21,6 +21,9 @@
// 02111-1307, USA.
//
// $Log$
+// Revision 1.19 2006/01/10 19:59:26 fraggle
+// Reliable packet transport mechanism
+//
// Revision 1.18 2006/01/09 02:03:39 fraggle
// Send clients their player number, and indicate on the waiting screen
// which client we are.
@@ -408,7 +411,7 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
{
// Must come from a valid client; ignore otherwise
}
- else if (NET_Conn_Packet(&client->connection, packet, packet_type))
+ else if (NET_Conn_Packet(&client->connection, packet, &packet_type))
{
// Packet was eaten by the common connection code
}