about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2009-01-10 11:48:24 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2009-01-10 11:48:24 +0000
commit6eefa58b52c4d842aff576e0674b58949f8ad2d7 (patch)
treeaec25abcf5e75a6af21613239170d89afbee638a
parentd0d91c412dc8a63cbf2dc0c4f74400a64ad5638b (diff)
downloadzcatch-6eefa58b52c4d842aff576e0674b58949f8ad2d7.tar.gz
zcatch-6eefa58b52c4d842aff576e0674b58949f8ad2d7.zip
fixed resending algorithm
-rw-r--r--src/engine/e_network.c24
-rw-r--r--src/engine/e_network_conn.c36
-rw-r--r--src/engine/e_network_internal.h2
3 files changed, 48 insertions, 14 deletions
diff --git a/src/engine/e_network.c b/src/engine/e_network.c
index 2b4ed013..5b6dbf27 100644
--- a/src/engine/e_network.c
+++ b/src/engine/e_network.c
@@ -23,6 +23,26 @@ void recvinfo_start(NETRECVINFO *info, NETADDR *addr, NETCONNECTION *conn, int c
 	info->valid = 1;
 }
 
+
+int seq_in_backroom(int seq, int ack)
+{
+	int bottom = (ack-NET_MAX_SEQUENCE/2);
+	if(bottom < 0)
+	{
+		if(seq <= ack)
+			return 1;
+		if(seq >= (bottom + NET_MAX_SEQUENCE))
+			return 1;
+	}
+	else
+	{
+		if(seq <= ack && seq >= bottom)
+			return 1;
+	}
+	
+	return 0;
+}
+
 /* TODO: rename this function */
 int recvinfo_fetch_chunk(NETRECVINFO *info, NETCHUNK *chunk)
 {
@@ -68,6 +88,10 @@ int recvinfo_fetch_chunk(NETRECVINFO *info, NETCHUNK *chunk)
 			}
 			else
 			{
+				/* old packet that we already got */
+				if(seq_in_backroom(header.sequence, info->conn->ack))
+					continue;
+
 				/* out of sequence, request resend */
 				dbg_msg("conn", "asking for resend %d %d", header.sequence, (info->conn->ack+1)%NET_MAX_SEQUENCE);
 				conn_want_resend(info->conn);
diff --git a/src/engine/e_network_conn.c b/src/engine/e_network_conn.c
index 1d241d06..7f6b255a 100644
--- a/src/engine/e_network_conn.c
+++ b/src/engine/e_network_conn.c
@@ -48,13 +48,14 @@ void conn_init(NETCONNECTION *conn, NETSOCKET socket)
 
 static void conn_ack(NETCONNECTION *conn, int ack)
 {
+	
 	while(1)
 	{
 		NETCHUNKDATA *resend = (NETCHUNKDATA *)ringbuf_first(conn->buffer);
 		if(!resend)
 			break;
-			
-		if(resend->sequence <= ack || (ack < NET_MAX_SEQUENCE/3 && resend->sequence > NET_MAX_SEQUENCE/2))
+		
+		if(seq_in_backroom(resend->sequence, ack))
 			ringbuf_popfirst(conn->buffer);
 		else
 			break;
@@ -84,7 +85,7 @@ int conn_flush(NETCONNECTION *conn)
 	return num_chunks;
 }
 
-void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void *data)
+static void conn_queue_chunk_ex(NETCONNECTION *conn, int flags, int data_size, const void *data, int sequence)
 {
 	unsigned char *chunk_data;
 	
@@ -92,12 +93,9 @@ void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void
 	if(conn->construct.data_size + data_size + NET_MAX_CHUNKHEADERSIZE > sizeof(conn->construct.chunk_data))
 		conn_flush(conn);
 
-	if(flags&NET_CHUNKFLAG_VITAL && !(flags&NET_CHUNKFLAG_RESEND))
-		conn->seq = (conn->seq+1)%NET_MAX_SEQUENCE;
-
 	/* pack all the data */
 	chunk_data = &conn->construct.chunk_data[conn->construct.data_size];
-	chunk_data = pack_chunk_header(chunk_data, flags, data_size, conn->seq);
+	chunk_data = pack_chunk_header(chunk_data, flags, data_size, sequence);
 	mem_copy(chunk_data, data, data_size);
 	chunk_data += data_size;
 
@@ -113,7 +111,7 @@ void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void
 		NETCHUNKDATA *resend = (NETCHUNKDATA *)ringbuf_allocate(conn->buffer, sizeof(NETCHUNKDATA)+data_size);
 		if(resend)
 		{
-			resend->sequence = conn->seq;
+			resend->sequence = sequence;
 			resend->flags = flags;
 			resend->data_size = data_size;
 			resend->data = (unsigned char *)(resend+1);
@@ -129,6 +127,13 @@ void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void
 	}
 }
 
+void conn_queue_chunk(NETCONNECTION *conn, int flags, int data_size, const void *data)
+{
+	if(flags&NET_CHUNKFLAG_VITAL)
+		conn->seq = (conn->seq+1)%NET_MAX_SEQUENCE;
+	conn_queue_chunk_ex(conn, flags, data_size, data, conn->seq);
+}
+
 
 static void conn_send_control(NETCONNECTION *conn, int controlmsg, const void *extra, int extra_size)
 {
@@ -138,28 +143,31 @@ static void conn_send_control(NETCONNECTION *conn, int controlmsg, const void *e
 
 static void conn_resend_chunk(NETCONNECTION *conn, NETCHUNKDATA *resend)
 {
-	conn_queue_chunk(conn, resend->flags|NET_CHUNKFLAG_RESEND, resend->data_size, resend->data);
+	conn_queue_chunk_ex(conn, resend->flags|NET_CHUNKFLAG_RESEND, resend->data_size, resend->data, resend->sequence);
 	resend->last_send_time = time_get();
 }
 
 static void conn_resend(NETCONNECTION *conn)
 {
 	int resend_count = 0;
-	int max = 10;
+	int first = 0, last = 0;
 	void *item = ringbuf_first(conn->buffer);
+	
 	while(item)
 	{
 		NETCHUNKDATA *resend = item;
+		
+		if(resend_count == 0)
+			first = resend->sequence;
+		last = resend->sequence;
+			
 		conn_resend_chunk(conn, resend);
 		item = ringbuf_next(conn->buffer, item);
-		max--;
 		resend_count++;
-		if(!max)
-			break;
 	}
 	
 	if(config.debug)
-		dbg_msg("conn", "resent %d packets", resend_count);
+		dbg_msg("conn", "resent %d packets (%d to %d)", resend_count, first, last);
 }
 
 int conn_connect(NETCONNECTION *conn, NETADDR *addr)
diff --git a/src/engine/e_network_internal.h b/src/engine/e_network_internal.h
index 6c58ec88..f1a25b31 100644
--- a/src/engine/e_network_internal.h
+++ b/src/engine/e_network_internal.h
@@ -146,6 +146,8 @@ void recvinfo_start(NETRECVINFO *info, NETADDR *addr, NETCONNECTION *conn, int c
 int recvinfo_fetch_chunk(NETRECVINFO *info, NETCHUNK *chunk);
 
 /* misc helper functions */
+/* The backroom is ack-NET_MAX_SEQUENCE/2. Used for knowing if we acked a packet or not */
+int seq_in_backroom(int seq, int ack);
 void send_controlmsg(NETSOCKET socket, NETADDR *addr, int ack, int controlmsg, const void *extra, int extra_size);
 void send_packet_connless(NETSOCKET socket, NETADDR *addr, const void *data, int data_size);
 void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet);