diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 1749d9aea..43b867fb4 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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); diff --git a/src/d_netfil.c b/src/d_netfil.c index a51d44f80..2b32a7c5c 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -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 * diff --git a/src/d_netfil.h b/src/d_netfil.h index bcf1f6670..bd54b7661 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -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);