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.