Put HTTP downloading on a background thread #116

Merged
alufolie91 merged 1 commits from httpbackthread into Saturn-Next 2024-03-17 15:06:34 +01:00
3 changed files with 96 additions and 82 deletions

No files matched your search

+19 -24
View File
@@ -2164,6 +2164,18 @@ static void M_ConfirmConnect(event_t *ev)
#endif
}
static void AbortConnection(void)
{
CURLAbortFile();
D_QuitNetGame();
CL_Reset();
D_StartTitle();
// Will be reset by caller. Signals refusal.
cl_mode = CL_ABORTED;
}
static boolean CL_FinishedFileList(void)
{
INT32 i;
@@ -2176,9 +2188,7 @@ static boolean CL_FinishedFileList(void)
}
else if (i == 3) // too many files
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
M_StartMessage(M_GetText(
"You have too many WAD files loaded\n"
"to add ones the server is using.\n"
@@ -2189,9 +2199,7 @@ static boolean CL_FinishedFileList(void)
}
else if (i == 2) // cannot join for some reason
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n"
"To play on this server, restart\n"
@@ -2228,9 +2236,7 @@ static boolean CL_FinishedFileList(void)
{
if (!CL_CheckDownloadable()) // nope!
{
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
M_StartMessage(M_GetText(
"An error occured when trying to\n"
"download missing addons.\n"
@@ -2455,9 +2461,6 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
break;
}
if (curl_running)
CURLGetFile();
if (waitmore)
break; // exit the case
@@ -2491,9 +2494,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
CONS_Printf(M_GetText("Legacy downloader request packet failed.\n"));
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
M_StartMessage(M_GetText(
"The direct download encountered an error.\n"
"See the logfile for more info.\n"
@@ -2520,9 +2521,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
CONS_Printf("%d minute wait time exceeded.\n", cv_connectawaittime.value);
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
M_StartMessage(va(
"%d minute wait time exceeded.\n"
"You may retry connection.\n"
@@ -2594,9 +2593,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (!modeattacking && (key == KEY_ESCAPE || key == KEY_JOY1+1 || cl_mode == CL_ABORTED))
{
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
return false;
}
@@ -3836,9 +3833,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
#ifdef DUMPCONSISTENCY
if (msg == KICK_MSG_CON_FAIL) SV_SavedGame();
#endif
D_QuitNetGame();
CL_Reset();
D_StartTitle();
AbortConnection();
if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress ESC\n"), NULL, MM_NOTHING);
+76 -58
View File
@@ -1237,10 +1237,13 @@ void CURLPrepareFile(const char* url, int dfilenum)
I_Error("Attempted to download files in -nodownload mode");
#endif
curl_global_init(CURL_GLOBAL_ALL);
if (!multi_handle)
{
curl_global_init(CURL_GLOBAL_ALL);
multi_handle = curl_multi_init();
}
http_handle = curl_easy_init();
multi_handle = curl_multi_init();
if (http_handle && multi_handle)
{
@@ -1296,98 +1299,113 @@ void CURLPrepareFile(const char* url, int dfilenum)
curl_multi_perform(multi_handle, &curl_runninghandles);
curl_starttime = time(NULL);
curl_running = true;
I_spawn_thread("http-download", (I_thread_fn)CURLGetFile, NULL);
}
}
void CURLAbortFile(void)
{
curl_running = false;
}
void CURLGetFile(void)
{
CURLMcode mc; /* return code used by curl_multi_wait() */
CURLcode easyres; /* Return from easy interface */
int numfds;
CURLMsg *m; /* for picking up messages with the transfer status */
CURL *e;
int msgs_left; /* how many messages are left */
const char *easy_handle_error;
boolean running = true;
long response_code = 0;
static char *filename;
if (curl_runninghandles)
while (running && curl_running)
{
curl_multi_perform(multi_handle, &curl_runninghandles);
/* wait for activity, timeout or "nothing" */
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
if (mc != CURLM_OK)
if (curl_runninghandles)
{
CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc);
return;
}
curl_curfile->currentsize = curl_dlnow;
curl_curfile->totalsize = curl_dltotal;
}
curl_multi_perform(multi_handle, &curl_runninghandles);
/* See how the transfers went */
while ((m = curl_multi_info_read(multi_handle, &msgs_left)))
{
if (m && (m->msg == CURLMSG_DONE))
{
e = m->easy_handle;
easyres = m->data.result;
filename = Z_StrDup(curl_realname);
nameonly(filename);
if (easyres != CURLE_OK)
/* wait for activity, timeout or "nothing" */
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, NULL);
if (mc != CURLM_OK)
{
if (easyres == CURLE_HTTP_RETURNED_ERROR)
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres);
curl_curfile->status = FS_FALLBACK;
curl_curfile->currentsize = curl_origfilesize;
curl_curfile->totalsize = curl_origtotalfilesize;
curl_failedwebdownload = true;
fclose(curl_curfile->file);
remove(curl_curfile->filename);
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc);
continue;
}
else
{
fclose(curl_curfile->file);
curl_curfile->currentsize = curl_dlnow;
curl_curfile->totalsize = curl_dltotal;
}
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD)
/* See how the transfers went */
while ((m = curl_multi_info_read(multi_handle, &msgs_left)))
{
if (m && (m->msg == CURLMSG_DONE))
{
running = false;
e = m->easy_handle;
easyres = m->data.result;
filename = Z_StrDup(curl_realname);
nameonly(filename);
if (easyres != CURLE_OK)
{
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
if (easyres == CURLE_HTTP_RETURNED_ERROR)
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres);
curl_curfile->status = FS_FALLBACK;
curl_curfile->currentsize = curl_origfilesize;
curl_curfile->totalsize = curl_origtotalfilesize;
curl_failedwebdownload = true;
fclose(curl_curfile->file);
remove(curl_curfile->filename);
CONS_Printf(M_GetText("Failed to download %s (%s)\n"), filename, easy_handle_error);
}
else
{
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
downloadcompletednum++;
downloadcompletedsize += curl_curfile->totalsize;
curl_curfile->status = FS_FOUND;
fclose(curl_curfile->file);
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD)
{
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
curl_curfile->status = FS_FALLBACK;
curl_failedwebdownload = true;
}
else
{
CONS_Printf(M_GetText("Finished HTTP download of %s\n"), filename);
downloadcompletednum++;
downloadcompletedsize += curl_curfile->totalsize;
curl_curfile->status = FS_FOUND;
}
}
Z_Free(filename);
curl_curfile->file = NULL;
curl_transfers--;
curl_multi_remove_handle(multi_handle, e);
curl_easy_cleanup(e);
if (!curl_transfers)
break;
}
Z_Free(filename);
curl_curfile->file = NULL;
curl_running = false;
curl_transfers--;
curl_multi_remove_handle(multi_handle, e);
curl_easy_cleanup(e);
if (!curl_transfers)
break;
}
}
if (!curl_transfers)
if (!curl_transfers || !curl_running)
{
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
multi_handle = NULL;
}
curl_running = false;
}
HTTP_login *
+1
View File
@@ -107,6 +107,7 @@ size_t nameonlylength(const char *s);
#ifdef HAVE_CURL
void CURLPrepareFile(const char* url, int dfilenum);
void CURLAbortFile(void);
void CURLGetFile(void);
HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream);