void CL_cURL_Cleanup(void) { if(clc.downloadCURLM) { CURLMcode result; if(clc.downloadCURL) { result = qcurl_multi_remove_handle(clc.downloadCURLM, clc.downloadCURL); if(result != CURLM_OK) { Com_DPrintf("qcurl_multi_remove_handle failed: %s\n", qcurl_multi_strerror(result)); } qcurl_easy_cleanup(clc.downloadCURL); } result = qcurl_multi_cleanup(clc.downloadCURLM); if(result != CURLM_OK) { Com_DPrintf("CL_cURL_Cleanup: qcurl_multi_cleanup failed: %s\n", qcurl_multi_strerror(result)); } clc.downloadCURLM = NULL; clc.downloadCURL = NULL; } else if(clc.downloadCURL) { qcurl_easy_cleanup(clc.downloadCURL); clc.downloadCURL = NULL; } }
void CL_cURL_Cleanup(void) { if(clc.curl.downloadCURLM) { if(clc.curl.downloadCURL) { qcurl_multi_remove_handle(clc.curl.downloadCURLM, clc.curl.downloadCURL); qcurl_easy_cleanup(clc.curl.downloadCURL); } qcurl_multi_cleanup(clc.curl.downloadCURLM); clc.curl.downloadCURLM = NULL; clc.curl.downloadCURL = NULL; } else if(clc.curl.downloadCURL) { qcurl_easy_cleanup(clc.curl.downloadCURL); clc.curl.downloadCURL = NULL; } }
void wswcurl_cleanup( void ) { if( !wswcurl_mempool ) return; while( http_requests ) { wswcurl_delete( http_requests ); } if( curldummy ) { qcurl_easy_cleanup( curldummy ); curldummy = NULL; } if( curlmulti ) { qcurl_multi_cleanup( curlmulti ); curlmulti = NULL; } QMutex_Destroy( &curldummy_mutex ); QMutex_Destroy( &http_requests_mutex ); #ifdef USE_OPENSSL if( cryptoLibrary ) { qCRYPTO_set_locking_callback( NULL ); if( crypto_num_mutexes && crypto_mutexes ) { int mutex_num; for( mutex_num = 0; mutex_num < crypto_num_mutexes; mutex_num++ ) QMutex_Destroy( &crypto_mutexes[mutex_num] ); WFREE( crypto_mutexes ); crypto_mutexes = NULL; } crypto_num_mutexes = 0; } #endif if( curlLibrary ) { qcurl_global_cleanup(); } wswcurl_unloadlib(); Mem_FreePool( &wswcurl_mempool ); }
static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error) { qboolean ok = false; if(!curl_dll) return; switch(status) { case CURL_DOWNLOAD_SUCCESS: ok = true; di->callback(CURLCBSTATUS_OK, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_FAILED: di->callback(CURLCBSTATUS_FAILED, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_ABORTED: di->callback(CURLCBSTATUS_ABORTED, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_SERVERERROR: // reopen to enforce it to have zero bytes again if(di->stream) { FS_Close(di->stream); di->stream = FS_OpenRealFile(di->filename, "wb", false); } if(di->callback) di->callback(error ? (int) error : CURLCBSTATUS_SERVERERROR, di->bytes_received, di->buffer, di->callback_data); break; default: if(di->callback) di->callback(CURLCBSTATUS_UNKNOWN, di->bytes_received, di->buffer, di->callback_data); break; } if(di->curle) { qcurl_multi_remove_handle(curlm, di->curle); qcurl_easy_cleanup(di->curle); if(di->slist) qcurl_slist_free_all(di->slist); } if(!di->callback && ok && !di->bytes_received) { Con_Printf("ERROR: empty file\n"); ok = false; } if(di->stream) FS_Close(di->stream); if(ok && di->ispak) { ok = FS_AddPack(di->filename, NULL, true); if(!ok) { // pack loading failed? // this is critical // better clear the file again... di->stream = FS_OpenRealFile(di->filename, "wb", false); FS_Close(di->stream); if(di->startpos && !di->callback) { // this was a resume? // then try to redownload it without reporting the error Curl_Begin(di->url, di->extraheaders, di->maxspeed, di->filename, di->ispak, di->forthismap, di->post_content_type, di->postbuf, di->postbufsize, NULL, 0, NULL, NULL); di->forthismap = false; // don't count the error } } } if(di->prev) di->prev->next = di->next; else downloads = di->next; if(di->next) di->next->prev = di->prev; --numdownloads; if(di->forthismap) { if(ok) ++numdownloads_success; else ++numdownloads_fail; } Z_Free(di); }
void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { clc.cURLUsed = qtrue; Com_Printf("URL: %s\n", remoteURL); Com_DPrintf("***** CL_cURL_BeginDownload *****\n" "Localname: %s\n" "RemoteURL: %s\n" "****************************\n", localName, remoteURL); CL_cURL_Cleanup(); Q_strncpyz(clc.downloadURL, remoteURL, sizeof(clc.downloadURL)); Q_strncpyz(clc.downloadName, localName, sizeof(clc.downloadName)); Com_sprintf(clc.downloadTempName, sizeof(clc.downloadTempName), "%s.tmp", localName); // Set so UI gets access to it Cvar_Set("cl_downloadName", localName); Cvar_Set("cl_downloadSize", "0"); Cvar_Set("cl_downloadCount", "0"); Cvar_SetValue("cl_downloadTime", cls.realtime); clc.downloadBlock = 0; // Starting new file clc.downloadCount = 0; clc.downloadCURL = qcurl_easy_init(); if(!clc.downloadCURL) { Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_easy_init() " "failed\n"); return; } clc.download = FS_SV_FOpenFileWrite(clc.downloadTempName); if(!clc.download) { Com_Error(ERR_DROP, "CL_cURL_BeginDownload: failed to open " "%s for writing\n", clc.downloadTempName); return; } qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, clc.download); if(com_developer->integer) qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s", NET_AdrToString(clc.serverAddress))); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); clc.downloadCURL = NULL; Com_Error(ERR_DROP, "CL_cURL_BeginDownload: qcurl_multi_init() " "failed\n"); return; } qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) && !clc.cURLDisconnected) { CL_AddReliableCommand("disconnect"); CL_WritePacket(); CL_WritePacket(); CL_WritePacket(); clc.cURLDisconnected = qtrue; } }
static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error, const char *content_type_) { char content_type[64]; qboolean ok = false; if(!curl_dll) return; switch(status) { case CURL_DOWNLOAD_SUCCESS: ok = true; di->callback(CURLCBSTATUS_OK, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_FAILED: di->callback(CURLCBSTATUS_FAILED, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_ABORTED: di->callback(CURLCBSTATUS_ABORTED, di->bytes_received, di->buffer, di->callback_data); break; case CURL_DOWNLOAD_SERVERERROR: // reopen to enforce it to have zero bytes again if(di->stream) { FS_Close(di->stream); di->stream = FS_OpenRealFile(di->filename, "wb", false); } if(di->callback) di->callback(error ? (int) error : CURLCBSTATUS_SERVERERROR, di->bytes_received, di->buffer, di->callback_data); break; default: if(di->callback) di->callback(CURLCBSTATUS_UNKNOWN, di->bytes_received, di->buffer, di->callback_data); break; } if(content_type_) strlcpy(content_type, content_type_, sizeof(content_type)); else *content_type = 0; if(di->curle) { qcurl_multi_remove_handle(curlm, di->curle); qcurl_easy_cleanup(di->curle); if(di->slist) qcurl_slist_free_all(di->slist); } if(!di->callback && ok && !di->bytes_received) { Con_Printf("ERROR: empty file\n"); ok = false; } if(di->stream) FS_Close(di->stream); #define CLEAR_AND_RETRY() \ do \ { \ di->stream = FS_OpenRealFile(di->filename, "wb", false); \ FS_Close(di->stream); \ if(di->startpos && !di->callback) \ { \ Curl_Begin(di->url, di->extraheaders, di->maxspeed, di->filename, di->loadtype, di->forthismap, di->post_content_type, di->postbuf, di->postbufsize, NULL, 0, NULL, NULL); \ di->forthismap = false; \ } \ } \ while(0) if(ok && di->loadtype == LOADTYPE_PAK) { ok = FS_AddPack(di->filename, NULL, true); if(!ok) CLEAR_AND_RETRY(); } else if(ok && di->loadtype == LOADTYPE_CACHEPIC) { const char *p; unsigned char *pixels = NULL; p = di->filename; #ifdef WE_ARE_EVIL if(!strncmp(p, "dlcache/", 8)) p += 8; #endif pixels = decode_image(di, content_type); if(pixels) Draw_NewPic(p, image_width, image_height, true, pixels); else CLEAR_AND_RETRY(); } else if(ok && di->loadtype == LOADTYPE_SKINFRAME) { const char *p; unsigned char *pixels = NULL; p = di->filename; #ifdef WE_ARE_EVIL if(!strncmp(p, "dlcache/", 8)) p += 8; #endif pixels = decode_image(di, content_type); if(pixels) R_SkinFrame_LoadInternalBGRA(p, TEXF_FORCE_RELOAD | TEXF_MIPMAP | TEXF_ALPHA, pixels, image_width, image_height, false); // TODO what sRGB argument to put here? else CLEAR_AND_RETRY(); } if(di->prev) di->prev->next = di->next; else downloads = di->next; if(di->next) di->next->prev = di->prev; --numdownloads; if(di->forthismap) { if(ok) ++numdownloads_success; else ++numdownloads_fail; } Z_Free(di); }
void wswcurl_delete( wswcurl_req *req ) { if( ( !req ) || ( !wswcurl_isvalidhandle( req ) ) ) { return; } // if (req->callback_done && req->active ) // req->callback_done ( req, 0, req->customp ); if( req->txhead ) { qcurl_slist_free_all( req->txhead ); req->txhead = NULL; } if( req->post ) { qcurl_formfree( req->post ); req->post = NULL; req->post_last = NULL; } if( req->url ) { WFREE( req->url ); } if( req->bhead ) { chained_buffer_t *cb = req->bhead; chained_buffer_t *next = cb->next; while( cb ) { WFREE( cb ); cb = next; if( cb ) { next = cb->next; } } } // remove from list QMutex_Lock( http_requests_mutex ); if( req->curl ) { if( curlmulti && req->status && req->status != WSTATUS_QUEUED ) { qcurl_multi_remove_handle( curlmulti, req->curl ); curlmulti_num_handles--; } qcurl_easy_cleanup( req->curl ); req->curl = NULL; } if( http_requests_hnode == req ) { http_requests_hnode = req->prev; } if( http_requests == req ) { http_requests = req->next; } if( req->prev ) { req->prev->next = req->next; } if( req->next ) { req->next->prev = req->prev; } QMutex_Unlock( http_requests_mutex ); WFREE( req ); }