Example #1
0
static int wswcurl_checkmsg( void )
{
	int cnt = 0;
	CURLMsg *msg;
	wswcurl_req *r;
	int ret = 0;
	char *info;

	do {
		msg = qcurl_multi_info_read( curlmulti, &cnt );
		if( !msg || !msg->easy_handle ) {
			continue;
		}

		// Treat received message.
		qcurl_easy_getinfo( msg->easy_handle, CURLINFO_PRIVATE, &info );
		r = ( wswcurl_req * )(( void * )info);

		if( !r ) {
			//Com_Printf("OOPS: Message from unknown source!\n");
			continue; // Not for us - oops :)
		}

		if( msg->msg != CURLMSG_DONE ) {
			//Com_Printf("Other message for %s: %d\n", r->url, msg->msg);
			continue;
		}

		ret++;

		if( msg->data.result == CURLE_OK ) {
			// Done!
			r->status = WSTATUS_FINISHED;
			qcurl_easy_getinfo( r->curl, CURLINFO_RESPONSE_CODE, &(r->respcode) );

			if( r->callback_done ) {
				r->callback_done( r, r->respcode, r->customp );
			}
		}
		else {
			// failed, store and pass to callback negative status value
			r->status = -abs( msg->data.result ); 
			r->respcode = -1;

			if( r->callback_done ) {
				r->callback_done( r, r->status, r->customp );
			}
		}
	} while( cnt && msg );

	return ret;
}
Example #2
0
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();
}
Example #3
0
/*
====================
Curl_GetDownloadSpeed

returns the speed of the given download in bytes per second
====================
*/
static double Curl_GetDownloadSpeed(downloadinfo *di)
{
	if(!curl_dll)
		return -2;
	if(di->curle)
	{
		double speed;
		qcurl_easy_getinfo(di->curle, CURLINFO_SPEED_DOWNLOAD, &speed);
		return speed;
	}
	else
		return -1;
}
Example #4
0
// Some versions of CURL don't report the correct exepected size when following redirects
// This manual interpretation of the expected size fixes this.
static size_t wswcurl_readheader( void *ptr, size_t size, size_t nmemb, void *stream ) {
	char buf[1024], *str;
	int slen;
	wswcurl_req *req = (wswcurl_req*)stream;

	memset( buf, 0, sizeof( buf ) );
	memcpy( buf, ptr, ( size * nmemb ) > ( sizeof( buf ) - 1 ) ? ( sizeof( buf ) - 1 ) : ( size * nmemb ) );
	str = buf;
	while( *str ) {
		if( ( *str >= 'a' ) && ( *str <= 'z' ) ) {
			*str -= 'a' - 'A';
		}
		str++;
	}

	if( ( str = (char*)strstr( buf, "CONTENT-LENGTH:" ) ) ) {
		int length;

		while( *str && ( *str != ':' ) ) {
			str++;
		}
		str++;

		while( *str && ( *str == ' ' ) ) {
			str++;
		}
		slen = strlen( str ) - 1;

		while( ( slen > 0 ) && ( ( str[slen] == '\n' ) || ( str[slen] == '\r' ) || ( str[slen] == ' ' ) ) ) {
			str[slen] = '\0';
			slen = strlen( str ) - 1;
		}

		length = atoi( str );
		if( length >= 0 ) {
			req->rx_expsize = length;
		}
	} else if( ( str  = (char*)strstr( buf, "TRANSFER-ENCODING:" ) ) ) {
		req->rx_expsize = 0;
	}

	qcurl_easy_getinfo( req->curl, CURLINFO_RESPONSE_CODE, &( req->respcode ) );

	// call header callback function
	if( req->callback_header ) {
		req->callback_header( req, buf, req->customp );
	}

	req->last_action = wswcurl_now();
	return size * nmemb;
}
Example #5
0
/*
====================
Curl_GetDownloadAmount

returns a value from 0.0 to 1.0 which represents the downloaded amount of data
for the given download.
====================
*/
static double Curl_GetDownloadAmount(downloadinfo *di)
{
	if(!curl_dll)
		return -2;
	if(di->curle)
	{
		double length;
		qcurl_easy_getinfo(di->curle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length);
		if(length > 0)
			return (di->startpos + di->bytes_received) / (di->startpos + length);
		else
			return 0;
	}
	else
		return -1;
}
Example #6
0
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();
}
Example #7
0
/*
====================
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;
}
Example #8
0
const char *wswcurl_get_effective_url( wswcurl_req *req ) {
	char *last_url = NULL;
	qcurl_easy_getinfo( req->curl, CURLINFO_EFFECTIVE_URL, &last_url );
	return last_url;
}
Example #9
0
const char *wswcurl_getip( wswcurl_req *req ) {
	char *ipstr = NULL;
	qcurl_easy_getinfo( req->curl, CURLINFO_PRIMARY_IP, &ipstr );
	return ipstr;
}
Example #10
0
const char *wswcurl_get_content_type( wswcurl_req *req ) {
	char *content_type = NULL;
	qcurl_easy_getinfo( req->curl, CURLINFO_CONTENT_TYPE, &content_type );
	return content_type;
}