I attach my implementation of a fair-ping server.

The admin sets sv_packetdelay and that makes the server try to get
everyone on at least that ping. It does so by delaying the sending of
packets.

Every packet that is to be sent is put on a queue. The packets get
sent by a thread that runs regularly.
The control adjusts itself every 30 packets (control_c var). Keeps
track of the delay to apply on the control array.

I didn't get the chance to test the server on many loads, but I did
test it with users with different pings, and the ping seems quite
stable.

I probably modified the makefile wrong, so please check it. Basically,
the server needs to get built with -lpthreads and -lrt
I made the modifications against
svn://svn.clanwtf.net/repos/ioquake3-UrT-server-4.1 which supposedly
tracks the ioquake3 repo with the URT patches necessary.

I hope you like the patch!

Ismael
Index: Makefile.local
===================================================================
--- Makefile.local	(revisión: 837)
+++ Makefile.local	(copia de trabajo)
@@ -2,3 +2,7 @@
 BUILD_CLIENT = 0
 BUILD_GAME_SO = 0
 BUILD_GAME_QVM = 0
+LIBS += -lpthreads
Index: code/server/sv_init.c
===================================================================
--- code/server/sv_init.c	(revisión: 837)
+++ code/server/sv_init.c	(copia de trabajo)
@@ -632,6 +632,27 @@
 */
 void SV_BotInitBotLib(void);
 
+#include "../qcommon/thread.h"
+void* runFlush(void* d){
+	struct timespec t;
+        struct timespec rem;
+        rem.tv_nsec = 0;
+        rem.tv_sec = 0;
+	t.tv_sec = 0;
+        t.tv_nsec = 0;
+
+	while(1){
+		NET_FlushPacketQueue();
+		t.tv_nsec = 200000;
+		if(clock_nanosleep(CLOCK_MONOTONIC, 0, &t, &rem) == -1){
+                    while(clock_nanosleep(CLOCK_MONOTONIC, 0, &t, &rem) == -1);
+                    rem.tv_nsec = 0;
+                    rem.tv_sec = 0;
+                }
+
+	}
+}
+
 void SV_Init (void) {
 	SV_AddOperatorCommands ();
 
@@ -699,6 +720,12 @@
 	
 	// Load saved bans
 	Cbuf_AddText("rehashbans\n");
+
+
+	// THREADS
+	pthread_t	thread;
+	pthread_mutex_init(&mutexnetqueue, NULL);
+	pthread_create( &thread, NULL, runFlush, (void*) 0);
 }
 
 
Index: code/qcommon/net_chan.c
===================================================================
--- code/qcommon/net_chan.c	(revisión: 837)
+++ code/qcommon/net_chan.c	(copia de trabajo)
@@ -22,6 +22,8 @@
 
 #include "q_shared.h"
 #include "qcommon.h"
+#include "thread.h"
+#include "../server/server.h"
 
 /*
 
@@ -537,10 +539,58 @@
 
 packetQueue_t *packetQueue = NULL;
 
+int cmp_netaddr(netadr_t *n1, netadr_t *n2){
+    if (n1->type == n2->type){
+        if(n1->type == NA_IP){
+            if(n1->port == n2->port){
+                if(memcmp(n1->ip, n2->ip, 4) == 0){
+                    return 1;
+                }
+            }
+        }
+        if(n1->type == NA_IP6){
+            if(n1->port == n2->port){
+                if(n1->scope_id == n2->scope_id){
+                    if(memcmp(n1->ip6, n2->ip6, 16) == 0){
+                        return 1;
+                    }
+                }
+            }    
+        }
+    }
+
+    return 0;
+}
+
+int control[64];
+int control_c[64];
+
+int control_proc(int user, int ping, int offset){
+    control_c[user]--;
+    if (control_c[user] < 0) control_c[user] = 30;
+
+    int dif = offset - ping;
+
+    if(abs(dif) > 50){
+        control[user] = offset * 3.3;
+    }
+
+    if(control_c[user] == 0){
+        if (dif > 0) {
+            if (dif > 10) control[user]++;
+            control[user]++;
+        } else {
+            if(dif < -10) control[user]--;
+            control[user]--;
+        }
+    }
+    return control[user];
+}
+
 static void NET_QueuePacket( int length, const void *data, netadr_t to,
 	int offset )
 {
-	packetQueue_t *new, *next = packetQueue;
+	packetQueue_t *new, *next;
 
 	if(offset > 999)
 		offset = 999;
@@ -550,16 +600,39 @@
 	Com_Memcpy(new->data, data, length);
 	new->length = length;
 	new->to = to;
-	new->release = Sys_Milliseconds() + offset;	
+        new->release = 0;
+        
+        client_t *cl;
+        int i;
+        for (i=0 ; i < sv_maxclients->integer ; i++) {
+            cl = &svs.clients[i];
+
+            //If not fully connected, don't delay it
+            if(!(cl->state == CS_ACTIVE)) continue;
+
+            //Find the owning client, to get their ping
+            if(cmp_netaddr(&(cl->netchan.remoteAddress), &to) == 1){
+                //If in a really high ping situation, don't further delay the packets
+                if(cl->ping > 900) break;
+
+                new->release = control_proc(i, cl->ping, offset);
+                break;
+            }
+        }
+
 	new->next = NULL;
 
+        pthread_mutex_lock(&mutexnetqueue);
 	if(!packetQueue) {
 		packetQueue = new;
+                pthread_mutex_unlock(&mutexnetqueue);
 		return;
 	}
+        next = packetQueue;
 	while(next) {
 		if(!next->next) {
 			next->next = new;
+                        pthread_mutex_unlock(&mutexnetqueue);
 			return;
 		}
 		next = next->next;
@@ -569,19 +642,30 @@
 void NET_FlushPacketQueue(void)
 {
 	packetQueue_t *last;
-	int now;
+        packetQueue_t *h, *p;
+        pthread_mutex_lock(&mutexnetqueue);
+        h = packetQueue;
+        while(h){
+            h->release--;
+            h = h->next;
+        }
 
-	while(packetQueue) {
-		now = Sys_Milliseconds();
-		if(packetQueue->release >= now)
-			break;
-		Sys_SendPacket(packetQueue->length, packetQueue->data,
-			packetQueue->to);
-		last = packetQueue;
-		packetQueue = packetQueue->next;
+        p = h = packetQueue;
+	while(h) {
+            if(h->release <= 0){
+		Sys_SendPacket(h->length, h->data, h->to);
+		last = h;
+                if(h == packetQueue) packetQueue = h->next;
+		h = h->next;
+                if(p->next) p->next = h;
 		Z_Free(last->data);
 		Z_Free(last);
-	}
+            } else {
+                p = h;
+                h = h->next;
+            }
+        }
+        pthread_mutex_unlock(&mutexnetqueue);
 }
 
 void NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to ) {
Index: code/qcommon/common.c
===================================================================
--- code/qcommon/common.c	(revisión: 837)
+++ code/qcommon/common.c	(copia de trabajo)
@@ -2198,7 +2198,7 @@
 	MSG_Init( &buf, bufData, sizeof( bufData ) );
 
 	while ( 1 ) {
-		NET_FlushPacketQueue();
 		ev = Com_GetEvent();
 
 		// if no more events are available
@@ -2218,7 +2218,6 @@
 			return ev.evTime;
 		}
 
-
 		switch ( ev.evType ) {
 		default:
 			Com_Error( ERR_FATAL, "Com_EventLoop: bad event type %i", ev.evType );
@@ -2605,7 +2604,7 @@
 	cl_paused = Cvar_Get ("cl_paused", "0", CVAR_ROM);
 	sv_paused = Cvar_Get ("sv_paused", "0", CVAR_ROM);
 	cl_packetdelay = Cvar_Get ("cl_packetdelay", "0", CVAR_CHEAT);
-	sv_packetdelay = Cvar_Get ("sv_packetdelay", "0", CVAR_CHEAT);
+	sv_packetdelay = Cvar_Get ("sv_packetdelay", "0", 0);
 	com_sv_running = Cvar_Get ("sv_running", "0", CVAR_ROM);
 	com_cl_running = Cvar_Get ("cl_running", "0", CVAR_ROM);
 	com_buildScript = Cvar_Get( "com_buildScript", "0", 0 );
Index: Makefile
===================================================================
--- Makefile	(revisión: 837)
+++ Makefile	(copia de trabajo)
@@ -297,7 +297,7 @@
   SHLIBLDFLAGS=-shared $(LDFLAGS)
 
   THREAD_LIBS=-lpthread
-  LIBS=-ldl -lm
+  LIBS=-ldl -lm -lpthread -lrt
 
   CLIENT_LIBS=$(shell sdl-config --libs) -lGL
 
@@ -653,7 +653,7 @@
   LIBS=-lm
   SHLIBEXT=so
   SHLIBCFLAGS=-fPIC
-  SHLIBLDFLAGS=-shared $(LDFLAGS)
+  SHLIBLDFLAGS=-shared $(LDFLAGS)pthread
   THREAD_LIBS=-lpthread
 
   BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes
_______________________________________________
ioquake3 mailing list
ioquake3@lists.ioquake.org
http://lists.ioquake.org/listinfo.cgi/ioquake3-ioquake.org
By sending this message I agree to love ioquake3 and libsdl.

Reply via email to