void wswcurl_init( void ) { if( wswcurl_mempool ) { return; } wswcurl_mempool = Mem_AllocPool( NULL, "Curl" ); // HTTP proxy settings http_proxy = Cvar_Get( "http_proxy", "", CVAR_ARCHIVE ); http_proxyuserpwd = Cvar_Get( "http_proxyuserpwd", "", CVAR_ARCHIVE ); wswcurl_loadlib(); if( curlLibrary ) { qcurl_global_init( CURL_GLOBAL_ALL ); curldummy = qcurl_easy_init(); curlmulti = qcurl_multi_init(); } curldummy_mutex = QMutex_Create(); http_requests_mutex = QMutex_Create(); #ifdef USE_OPENSSL if( cryptoLibrary ) { int mutex_num; crypto_num_mutexes = qCRYPTO_num_locks(); crypto_mutexes = WMALLOC( crypto_num_mutexes * sizeof( *crypto_mutexes ) ); for( mutex_num = 0; mutex_num < crypto_num_mutexes; mutex_num++ ) crypto_mutexes[mutex_num] = QMutex_Create(); qCRYPTO_set_locking_callback( wswcurl_crypto_lockcallback ); } #endif }
struct WhenList *CreateWhen(struct Set *set, struct StatementList *sl) { register struct WhenList *result; WMALLOC(result); result->slist = sl; result->values =set; result->next = NULL; return result; }
struct WhenList *CopyWhenNode(struct WhenList *w) { register struct WhenList *result; assert(w!=NULL); WMALLOC(result); if (w->values) result->values = CopySetByReference(w->values); else result->values = w->values; result->slist = CopyListToModify(w->slist); result->next = NULL; return result; }
wswcurl_req *wswcurl_create(wswcurl_cb_done callback, char *furl, ...) { wswcurl_req req, *retreq = NULL; CURLcode res; char url[4 * 1024]; // 4kb url buffer? va_list arg; // Prepare url formatting with variable arguments va_start(arg, furl); vsnprintf(url, sizeof(url), furl, arg); va_end(arg); // Initialize structure memset(&req, 0, sizeof(req)); if (! (req.curl = curl_easy_init())) { return NULL; } CURLSETOPT(req.curl, res, CURLOPT_URL, url); CURLSETOPT(req.curl, res, CURLOPT_WRITEFUNCTION, wswcurl_write); CURLSETOPT(req.curl, res, CURLOPT_NOPROGRESS, 1); CURLSETOPT(req.curl, res, CURLOPT_FOLLOWLOCATION, 1); CURLSETOPT(req.curl, res, CURLOPT_HEADERFUNCTION, wswcurl_readheader); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // TODO: Warsow specific stuff? Modify!! //CURLSETOPT(req.curl, res, CURLOPT_USERAGENT, "Warsow 0.5"); //wswcurl_header(&req, "X-Warsow-Version", "0.5"); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if (!req.curl) { return NULL; } req.url = WSTRDUP(url); req.callback_done = callback; req.filenum = -1; // Everything OK, allocate, copy, prepend to list and return retreq = WMALLOC(sizeof(req)); memcpy(retreq, &req, sizeof(req)); retreq->prev = NULL; retreq->next = http_requests; if (retreq->next) retreq->next->prev = retreq; http_requests = retreq; // Set the wswcurl_req as data CURLSETOPT(retreq->curl, res, CURLOPT_WRITEDATA, (void*)retreq); CURLSETOPT(retreq->curl, res, CURLOPT_WRITEHEADER, (void*)retreq); return retreq; }
static size_t wswcurl_write(void *ptr, size_t size, size_t nmemb, void *stream) { float progress; long numb; wswcurl_req *req = (wswcurl_req*)stream; if( !req->headers_done ) { req->headers_done = 1; } numb = size * nmemb; req->rxreceived += numb; req->last_action = wswcurl_now(); progress = !req->rx_expsize ? 0.0 : (float)(((double)req->rxreceived / (double)req->rx_expsize) * 100.0); clamp( progress, 0, 100 ); if( req->callback_read ) { return req->callback_read( req, ptr, numb, progress, req->customp ); } else { chained_buffer_t *cb; // Allocate new buffer cb = ( chained_buffer_t* )WMALLOC( sizeof(*cb) + numb ); memset( cb, 0, sizeof(*cb) ); // Stick the buffer to the end of the chain if( req->btail ) req->btail->next = cb; req->btail = cb; if( !req->bhead ) req->bhead = cb; memcpy( cb->data, ptr, numb ); cb->data[numb] = '\0'; cb->rxsize = numb; } return numb; }
wswcurl_req *wswcurl_create( const char *furl, ... ) { wswcurl_req *retreq; CURL *curl; CURLcode res; char url[4 * 1024]; // 4kb url buffer? va_list arg; const char *proxy = http_proxy->string; const char *proxy_userpwd = http_proxyuserpwd->string; // Prepare url formatting with variable arguments va_start( arg, furl ); Q_vsnprintfz( url, sizeof( url ), furl, arg ); va_end( arg ); // Initialize structure if( !(curl = curl_easy_init()) ) { return NULL; } // allocate, copy retreq = ( wswcurl_req * )WMALLOC( sizeof( wswcurl_req ) ); memset( retreq, 0, sizeof( *retreq ) ); retreq->curl = curl; retreq->url = ( char* )WMALLOC( strlen( url ) + 1 ); memcpy( retreq->url, url, strlen( url ) + 1 ); CURLSETOPT( curl, res, CURLOPT_URL, retreq->url ); CURLSETOPT( curl, res, CURLOPT_WRITEFUNCTION, wswcurl_write ); CURLSETOPT( curl, res, CURLOPT_NOPROGRESS, 1 ); CURLSETOPT( curl, res, CURLOPT_FOLLOWLOCATION, 1 ); CURLSETOPT( curl, res, CURLOPT_HEADERFUNCTION, wswcurl_readheader ); CURLSETOPT( curl, res, CURLOPT_CONNECTTIMEOUT, WCONNECTTIMEOUT ); #if defined( APPLICATION ) && defined( APP_VERSION_STR ) && defined( OSNAME ) && defined( CPUSTRING ) CURLSETOPT( curl, res, CURLOPT_USERAGENT, APPLICATION"/"APP_VERSION_STR" (compatible; N; "OSNAME"; "CPUSTRING")" ); #endif CURLSETOPT( curl, res, CURLOPT_WRITEDATA, ( void * )retreq ); CURLSETOPT( curl, res, CURLOPT_WRITEHEADER, ( void * )retreq ); CURLSETOPT( curl, res, CURLOPT_PRIVATE, ( void * )retreq ); if( developer->integer ) { CURLSETOPT( curl, res, CURLOPT_DEBUGFUNCTION, &wswcurl_debug_callback ); CURLSETOPT( curl, res, CURLOPT_DEBUGDATA, ( void * )retreq ); CURLSETOPT( curl, res, CURLOPT_VERBOSE, 1 ); } // HTTP proxy settings if( proxy && *proxy ) { CURLSETOPT( curl, res, CURLOPT_PROXYTYPE, CURLPROXY_HTTP ); CURLSETOPT( curl, res, CURLOPT_PROXY, proxy ); if( proxy_userpwd && *proxy_userpwd ) { CURLSETOPT( curl, res, CURLOPT_PROXYUSERPWD, proxy_userpwd ); } } wswcurl_set_timeout( retreq, WTIMEOUT ); // link retreq->prev = NULL; retreq->next = http_requests; if( retreq->next ) { retreq->next->prev = retreq; } else { http_requests_hnode = retreq; } http_requests = retreq; CURLDBG((va(" CURL CREATE %s\n", url))); return retreq; }