From 1548f11f0b7ace29a0f755222c429a9acdc0ccef Mon Sep 17 00:00:00 2001 From: divverent Date: Fri, 27 Feb 2009 08:50:10 +0000 Subject: [PATCH] improve keepalive handling (also send keepalives during map loading); but still not perfect (e.g. on redstarrepublic, client and server tend to send each other keepalive messages, and eventually the client gets dropped, no idea why) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8765 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_parse.c | 34 +++++++++++++++++++++++----------- client.h | 1 + gl_textures.c | 3 +++ image.c | 4 ++++ model_shared.c | 10 ++++++++++ netconn.c | 2 +- sv_main.c | 11 +++++++++-- 7 files changed, 51 insertions(+), 14 deletions(-) diff --git a/cl_parse.c b/cl_parse.c index 45b1890c..25330eec 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -290,12 +290,15 @@ void CL_KeepaliveMessage (qboolean readmessages) { float time; static double nextmsg = -1; +#if 0 + static double lasttime = -1; +#endif int oldreadcount; qboolean oldbadread; sizebuf_t old; // no need if server is local and definitely not if this is a demo - if (!cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD) + if (!cls.netcon || cls.protocol == PROTOCOL_QUAKEWORLD || cls.signon >= SIGNONS) return; if (readmessages) @@ -314,6 +317,14 @@ void CL_KeepaliveMessage (qboolean readmessages) memcpy(net_message.data, olddata, net_message.cursize); } +#if 0 + if((time = Sys_DoubleTime()) >= lasttime + 1) + { + Con_Printf("long delta: %f\n", time - lasttime); + } + lasttime = Sys_DoubleTime(); +#endif + if (cls.netcon && (time = Sys_DoubleTime()) >= nextmsg) { sizebuf_t msg; @@ -411,9 +422,15 @@ static void CL_SetupWorldModel(void) // load or reload .loc file for team chat messages CL_Locs_Reload_f(); + // make sure we send enough keepalives + CL_KeepaliveMessage(false); + // reset particles and other per-level things R_Modules_NewMap(); + // make sure we send enough keepalives + CL_KeepaliveMessage(false); + // load the team chat beep if possible cl.foundtalk2wav = FS_FileExists("sound/misc/talk2.wav"); @@ -1011,8 +1028,7 @@ void CL_BeginDownloads(qboolean aborteddownload) { if (cl.model_precache[cl.loadmodel_current] && cl.model_precache[cl.loadmodel_current]->Draw) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); + CL_KeepaliveMessage(true); cl.model_precache[cl.loadmodel_current] = Mod_ForName(cl.model_name[cl.loadmodel_current], false, false, cl.loadmodel_current == 1); if (cl.model_precache[cl.loadmodel_current] && cl.model_precache[cl.loadmodel_current]->Draw && cl.loadmodel_current == 1) { @@ -1039,8 +1055,7 @@ void CL_BeginDownloads(qboolean aborteddownload) { if (cl.sound_precache[cl.loadsound_current] && S_IsSoundPrecached(cl.sound_precache[cl.loadsound_current])) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); + CL_KeepaliveMessage(true); // Don't lock the sfx here, S_ServerSounds already did that cl.sound_precache[cl.loadsound_current] = S_PrecacheSound(cl.sound_name[cl.loadsound_current], false, false); } @@ -1086,8 +1101,7 @@ void CL_BeginDownloads(qboolean aborteddownload) } if (cl.model_precache[cl.downloadmodel_current] && cl.model_precache[cl.downloadmodel_current]->Draw) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); + CL_KeepaliveMessage(true); if (strcmp(cl.model_name[cl.downloadmodel_current], "null") && !FS_FileExists(cl.model_name[cl.downloadmodel_current])) { if (cl.downloadmodel_current == 1) @@ -1136,8 +1150,7 @@ void CL_BeginDownloads(qboolean aborteddownload) } if (cl.sound_precache[cl.downloadsound_current] && S_IsSoundPrecached(cl.sound_precache[cl.downloadsound_current])) continue; - if (cls.signon < SIGNONS) - CL_KeepaliveMessage(true); + CL_KeepaliveMessage(true); dpsnprintf(soundname, sizeof(soundname), "sound/%s", cl.sound_name[cl.downloadsound_current]); if (!FS_FileExists(soundname) && !FS_FileExists(cl.sound_name[cl.downloadsound_current])) { @@ -3091,8 +3104,7 @@ void CL_ParseServerMessage(void) cl.last_received_message = realtime; - if (cls.netcon && cls.signon < SIGNONS) - CL_KeepaliveMessage(false); + CL_KeepaliveMessage(false); // // if recording demos, copy the message out diff --git a/client.h b/client.h index f1d0c818..63502b51 100644 --- a/client.h +++ b/client.h @@ -1254,6 +1254,7 @@ void CL_Parse_DumpPacket(void); void CL_Parse_ErrorCleanUp(void); void QW_CL_StartUpload(unsigned char *data, int size); extern cvar_t qport; +void CL_KeepaliveMessage(qboolean readmessages); // call this during loading of large content // // view diff --git a/gl_textures.c b/gl_textures.c index e5d35a9a..fe13aca5 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -1064,6 +1064,9 @@ static rtexture_t *R_SetupTexture(rtexturepool_t *rtexturepool, const char *iden GL_Texture_CalcImageSize(glt->texturetype, glt->flags, glt->inputwidth, glt->inputheight, glt->inputdepth, &glt->tilewidth, &glt->tileheight, &glt->tiledepth); R_PrecacheTexture(glt); + // texture converting and uploading can take a while, so make sure we're sending keepalives + CL_KeepaliveMessage(false); + return (rtexture_t *)glt; } diff --git a/image.c b/image.c index a99176e5..538620fd 100644 --- a/image.c +++ b/image.c @@ -849,6 +849,10 @@ unsigned char *loadimagepixelsbgra (const char *filename, qboolean complain, qbo Con_Printf(format == firstformat ? "\"%s\"" : (format[1].formatstring ? ", \"%s\"" : " or \"%s\".\n"), format->formatstring); } } + + // texture loading can take a while, so make sure we're sending keepalives + CL_KeepaliveMessage(false); + if (developer_memorydebug.integer) Mem_CheckSentinelsGlobal(); return NULL; diff --git a/model_shared.c b/model_shared.c index c710eb0a..fb93d04f 100644 --- a/model_shared.c +++ b/model_shared.c @@ -985,10 +985,16 @@ void Mod_ShadowMesh_AddMesh(mempool_t *mempool, shadowmesh_t *mesh, rtexture_t * } Mod_ShadowMesh_AddTriangle(mempool, mesh, map_diffuse, map_specular, map_normal, vbuf); } + + // the triangle calculation can take a while, so let's do a keepalive here + CL_KeepaliveMessage(false); } shadowmesh_t *Mod_ShadowMesh_Begin(mempool_t *mempool, int maxverts, int maxtriangles, rtexture_t *map_diffuse, rtexture_t *map_specular, rtexture_t *map_normal, int light, int neighbors, int expandable) { + // the preparation before shadow mesh initialization can take a while, so let's do a keepalive here + CL_KeepaliveMessage(false); + return Mod_ShadowMesh_Alloc(mempool, maxverts, maxtriangles, map_diffuse, map_specular, map_normal, light, neighbors, expandable); } @@ -1055,6 +1061,10 @@ shadowmesh_t *Mod_ShadowMesh_Finish(mempool_t *mempool, shadowmesh_t *firstmesh, } Mem_Free(mesh); } + + // this can take a while, so let's do a keepalive here + CL_KeepaliveMessage(false); + return firstmesh; } diff --git a/netconn.c b/netconn.c index 36901489..01d8181c 100755 --- a/netconn.c +++ b/netconn.c @@ -62,7 +62,7 @@ sizebuf_t net_message; static unsigned char net_message_buf[NET_MAXMESSAGE]; cvar_t net_messagetimeout = {0, "net_messagetimeout","300", "drops players who have not sent any packets for this many seconds"}; -cvar_t net_connecttimeout = {0, "net_connecttimeout","10", "after requesting a connection, the client must reply within this many seconds or be dropped (cuts down on connect floods)"}; +cvar_t net_connecttimeout = {0, "net_connecttimeout","15", "after requesting a connection, the client must reply within this many seconds or be dropped (cuts down on connect floods). Must be above 10 seconds."}; cvar_t net_connectfloodblockingtimeout = {0, "net_connectfloodblockingtimeout", "5", "when a connection packet is received, it will block all future connect packets from that IP address for this many seconds (cuts down on connect floods)"}; cvar_t hostname = {CVAR_SAVE, "hostname", "UNNAMED", "server message to show in server browser"}; cvar_t developer_networking = {0, "developer_networking", "0", "prints all received and sent packets (recommended only for debugging)"}; diff --git a/sv_main.c b/sv_main.c index c1a328f2..54b6e4ea 100644 --- a/sv_main.c +++ b/sv_main.c @@ -28,6 +28,7 @@ static void SV_SaveEntFile_f(void); static void SV_StartDownload_f(void); static void SV_Download_f(void); static void SV_VM_Setup(); +extern cvar_t net_connecttimeout; void VM_CustomStats_Clear (void); void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats); @@ -872,6 +873,9 @@ void SV_SendServerinfo (client_t *client) client->num_pings = 0; #endif client->ping = 0; + + // allow the client some time to send his keepalives, even if map loading took ages + client->netconnection->timeout = realtime + net_connecttimeout.value; } /* @@ -2695,7 +2699,7 @@ void SV_SaveSpawnparms (void) /* ================ -SV_SpawnServer +SV_/pawnServer This is called at the start of each level ================ @@ -2931,7 +2935,10 @@ void SV_SpawnServer (const char *server) // create a baseline for more efficient communications if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_NEHAHRABJP || sv.protocol == PROTOCOL_NEHAHRABJP2 || sv.protocol == PROTOCOL_NEHAHRABJP3) SV_CreateBaseline (); - + + // to prevent network timeouts + realtime = Sys_DoubleTime(); + // send serverinfo to all connected clients, and set up botclients coming back from a level change for (i = 0, host_client = svs.clients;i < svs.maxclients;i++, host_client++) { -- 2.39.2