Fix stupid endless loop in HTTP->UDP Fallback handling.

The fallback logic is: r1q2 style URLs -> q2pro style URLs -> UDP. In
case that an r1q2 or q2pro server is missing files, we may fall through
to UDP and download files over abysmal slow UDP that are available over
HTTP. To work around this problem we reset the precacher iterations back
to 0 and start over with r1q2 style URLs. This works as long as we're
able to download all files. But if one or more files are unavailable
over all three download options we'll run into an endless loop. Mitigate
this by starting over only once. This comes with the drawback that on
servers that miss more than one file downloads might done over UDP were
HTTP is available. In that case the server should be fixed.

This closes #429.
This commit is contained in:
Yamagi Burmeister 2019-09-04 18:02:06 +02:00
parent b7bb9f2550
commit 5ae4a73acd

View file

@ -40,7 +40,11 @@ extern int precache_model_skin;
extern byte *precache_model; extern byte *precache_model;
// Forces all downloads to UDP. // Forces all downloads to UDP.
qboolean forceudp = false; static qboolean forceudp;
// Gives HTTP downloads a second chance after
// we've fallen trough to UDP downloads.
static qboolean httpSecondChance = true;
/* This - and some more code down below - is the 'Crazy Fallback /* This - and some more code down below - is the 'Crazy Fallback
Magic'. First we're trying to download all files over HTTP with Magic'. First we're trying to download all files over HTTP with
@ -53,7 +57,7 @@ qboolean forceudp = false;
static unsigned int precacherIteration; static unsigned int precacherIteration;
// r1q2 searches the global filelist at /, q2pro at /gamedir... // r1q2 searches the global filelist at /, q2pro at /gamedir...
static qboolean gamedirForFilelist = false; static qboolean gamedirForFilelist;
static const char *env_suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; static const char *env_suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
@ -506,6 +510,7 @@ CL_RequestNextDownload(void)
forceudp = false; forceudp = false;
precacherIteration = 0; precacherIteration = 0;
gamedirForFilelist = false; gamedirForFilelist = false;
httpSecondChance = true;
#ifdef USE_CURL #ifdef USE_CURL
dlquirks.filelist = true; dlquirks.filelist = true;
@ -587,10 +592,24 @@ CL_CheckOrDownloadFile(char *filename)
false. */ false. */
forceudp = false; forceudp = false;
/* We might be connected to an r1q2-style HTTP server /* This is one of the nasty special cases. A r1q2
that missed just one file. So reset the precacher server might miss only one file. This missing
iteration counter to start over. */ file may lead to a fallthrough to q2pro URLs,
precacherIteration = 0; since it isn't a q2pro server all files would
yield error 404 and we're falling back to UDP
downloads. To work around this we need to start
over with the r1q2 case and see what happens.
But we can't do that unconditionally, because
we would run in endless loops r1q2 -> q2pro ->
UDP -> r1q2. So hack in a variable that allows
for one and only one second chance. If the r1q2
server is missing more than file we've lost and
we're doing unnecessary UDP downloads. */
if (httpSecondChance)
{
precacherIteration = 0;
httpSecondChance = false;
}
} }
#endif #endif
strcpy(cls.downloadname, filename); strcpy(cls.downloadname, filename);