void CL_cURL_PerformDownload(void) { CURLMcode res; CURLMsg *msg; int c; int i = 0; res = qcurl_multi_perform(clc.downloadCURLM, &c); while(res == CURLM_CALL_MULTI_PERFORM && i < 100) { res = qcurl_multi_perform(clc.downloadCURLM, &c); i++; } if(res == CURLM_CALL_MULTI_PERFORM) return; msg = qcurl_multi_info_read(clc.downloadCURLM, &c); if(msg == NULL) { return; } FS_FCloseFile(clc.download); if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) { FS_SV_Rename(clc.downloadTempName, clc.downloadName, false); clc.downloadRestart = true; } else { long code; qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &code); Com_Error(ERR_DROP, "Download Error: %s Code: %ld URL: %s", qcurl_easy_strerror(msg->data.result), code, clc.downloadURL); } CL_NextDownload(); }
void CL_cURL_PerformDownload(void) { CURLMcode res; CURLMsg *msg; int c; int i = 0; res = qcurl_multi_perform(clc.downloadCURLM, &c); while(res == CURLM_CALL_MULTI_PERFORM && i < 100) { res = qcurl_multi_perform(clc.downloadCURLM, &c); i++; } if(res == CURLM_CALL_MULTI_PERFORM) return; msg = qcurl_multi_info_read(clc.downloadCURLM, &c); if(msg == NULL) { return; } FS_FCloseFile(clc.download); if(msg->msg == CURLMSG_DONE && msg->data.result == CURLE_OK) { FS_SV_Rename(clc.downloadTempName, clc.downloadName); } else { long code; qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &code); Com_Error(ERR_DROP, "Download Error: %s Code: %d", qcurl_easy_strerror(msg->data.result), code); } *clc.downloadTempName = *clc.downloadName = 0; Cvar_Set( "cl_downloadName", "" ); CL_cURL_Cleanup(); FS_Restart(clc.checksumFeed); CL_Reconnect_f(); }
/* ==================== Curl_Run call this regularily as this will always download as much as possible without blocking. ==================== */ void Curl_Run(void) { double maxspeed; downloadinfo *di; noclear = FALSE; if(!cl_curl_enabled.integer) return; if(!curl_dll) return; Curl_CheckCommandWhenDone(); if(!downloads) return; if(realtime < curltime) // throttle return; { int remaining; CURLMcode mc; do { mc = qcurl_multi_perform(curlm, &remaining); } while(mc == CURLM_CALL_MULTI_PERFORM); for(di = downloads; di; di = di->next) { double b = 0; qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_UPLOAD, &b); bytes_sent += (b - di->bytes_sent_curl); di->bytes_sent_curl = b; qcurl_easy_getinfo(di->curle, CURLINFO_SIZE_DOWNLOAD, &b); bytes_sent += (b - di->bytes_received_curl); di->bytes_received_curl = b; } for(;;) { CURLMsg *msg = qcurl_multi_info_read(curlm, &remaining); if(!msg) break; if(msg->msg == CURLMSG_DONE) { CurlStatus failed = CURL_DOWNLOAD_SUCCESS; CURLcode result; qcurl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &di); result = msg->data.result; if(result) { failed = CURL_DOWNLOAD_FAILED; } else { long code; qcurl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &code); switch(code / 100) { case 4: // e.g. 404? case 5: // e.g. 500? failed = CURL_DOWNLOAD_SERVERERROR; result = (CURLcode) code; break; } } Curl_EndDownload(di, failed, result); } } } CheckPendingDownloads(); // when will we curl the next time? // we will wait a bit to ensure our download rate is kept. // we now know that realtime >= curltime... so set up a new curltime // use the slowest allowing download to derive the maxspeed... this CAN // be done better, but maybe later maxspeed = cl_curl_maxspeed.value; for(di = downloads; di; di = di->next) if(di->maxspeed > 0) if(di->maxspeed < maxspeed || maxspeed <= 0) maxspeed = di->maxspeed; if(maxspeed > 0) { double bytes = bytes_sent + bytes_received; // maybe smoothen a bit? curltime = realtime + bytes / (cl_curl_maxspeed.value * 1024.0); bytes_sent = 0; bytes_received = 0; } else curltime = realtime; }
int wswcurl_perform() { int ret = 0; wswcurl_req *r, *next; if( !curlmulti ) { return 0; } // process requests in FIFO manner QMutex_Lock( http_requests_mutex ); // check for timed out requests and requests that need to be paused r = http_requests_hnode; while( r ) { next = r->prev; if( r->status == WSTATUS_QUEUED ) { // queued if( curlmulti_num_handles < WMAXMULTIHANDLES ) { if( qcurl_multi_add_handle( curlmulti, r->curl ) ) { CURLDBG( ( "OOPS: CURL MULTI ADD HANDLE FAIL!!!" ) ); } r->status = WSTATUS_STARTED; r->last_action = wswcurl_now(); curlmulti_num_handles++; } else { // stay in queue } } // handle pauses for synchronous requests if( r->status == WSTATUS_STARTED && !r->callback_read ) { if( r->rxreceived >= r->rxreturned + WMAXBUFFERING ) { wswcurl_pause( r ); } } // handle timeouts if( r->status == WSTATUS_STARTED ) { time_t now = wswcurl_now(); if( r->paused ) { // paused r->last_action = now; } else if( r->timeout && ( r->last_action + r->timeout <= now ) ) { // timed out r->respcode = -1; r->status = -CURLE_OPERATION_TIMEDOUT; if( r->callback_done ) { r->callback_done( r, r->status, r->customp ); } } } r = next; } QMutex_Unlock( http_requests_mutex ); //CURLDBG(("CURL BEFORE MULTI_PERFORM\n")); while( qcurl_multi_perform( curlmulti, &ret ) == CURLM_CALL_MULTI_PERFORM ) { CURLDBG( ( " CURL MULTI LOOP\n" ) ); } ret += wswcurl_checkmsg(); //CURLDBG(("CURL after checkmsg\n")); return ret; }