static CURL * createEasy (tr_session * s, struct tr_web * web, struct tr_web_task * task) { bool is_default_value; const tr_address * addr; CURL * e = task->curl_easy = curl_easy_init (); task->timeout_secs = getTimeoutFromURL (task); curl_easy_setopt (e, CURLOPT_AUTOREFERER, 1L); curl_easy_setopt (e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity"); curl_easy_setopt (e, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt (e, CURLOPT_MAXREDIRS, -1L); curl_easy_setopt (e, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt (e, CURLOPT_PRIVATE, task); #ifdef USE_LIBCURL_SOCKOPT curl_easy_setopt (e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction); curl_easy_setopt (e, CURLOPT_SOCKOPTDATA, task); #endif if (web->curl_ssl_verify) { curl_easy_setopt (e, CURLOPT_CAINFO, web->curl_ca_bundle); } else { curl_easy_setopt (e, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt (e, CURLOPT_SSL_VERIFYPEER, 0L); } curl_easy_setopt (e, CURLOPT_TIMEOUT, task->timeout_secs); curl_easy_setopt (e, CURLOPT_URL, task->url); curl_easy_setopt (e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING); curl_easy_setopt (e, CURLOPT_VERBOSE, (long)(web->curl_verbose?1:0)); curl_easy_setopt (e, CURLOPT_WRITEDATA, task); curl_easy_setopt (e, CURLOPT_WRITEFUNCTION, writeFunc); if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET, &is_default_value))) && !is_default_value) curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr)); else if (((addr = tr_sessionGetPublicAddress (s, TR_AF_INET6, &is_default_value))) && !is_default_value) curl_easy_setopt (e, CURLOPT_INTERFACE, tr_address_to_string (addr)); if (task->cookies != NULL) curl_easy_setopt (e, CURLOPT_COOKIE, task->cookies); if (web->cookie_filename != NULL) curl_easy_setopt (e, CURLOPT_COOKIEFILE, web->cookie_filename); if (task->range != NULL) { curl_easy_setopt (e, CURLOPT_RANGE, task->range); /* don't bother asking the server to compress webseed fragments */ curl_easy_setopt (e, CURLOPT_ENCODING, "identity"); } return e; }
static CURL * createEasy( tr_session * s, struct tr_web_task * task ) { const tr_address * addr; CURL * e = curl_easy_init( ); const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL; if( !task->range && s->isProxyEnabled ) { const long proxyType = getCurlProxyType( s->proxyType ); curl_easy_setopt( e, CURLOPT_PROXY, s->proxy ); curl_easy_setopt( e, CURLOPT_PROXYAUTH, CURLAUTH_ANY ); curl_easy_setopt( e, CURLOPT_PROXYPORT, s->proxyPort ); curl_easy_setopt( e, CURLOPT_PROXYTYPE, proxyType ); } if( !task->range && s->isProxyAuthEnabled ) { char * str = tr_strdup_printf( "%s:%s", s->proxyUsername, s->proxyPassword ); curl_easy_setopt( e, CURLOPT_PROXYUSERPWD, str ); tr_free( str ); } curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L ); curl_easy_setopt( e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity" ); curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L ); curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L ); curl_easy_setopt( e, CURLOPT_NOSIGNAL, 1L ); curl_easy_setopt( e, CURLOPT_PRIVATE, task ); #ifdef USE_LIBCURL_SOCKOPT curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction ); curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task ); #endif curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L ); curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L ); curl_easy_setopt( e, CURLOPT_TIMEOUT, getTimeoutFromURL( task->url ) ); curl_easy_setopt( e, CURLOPT_URL, task->url ); curl_easy_setopt( e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING ); curl_easy_setopt( e, CURLOPT_VERBOSE, verbose ); curl_easy_setopt( e, CURLOPT_WRITEDATA, task ); curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc ); if(( addr = tr_sessionGetPublicAddress( s, TR_AF_INET ))) curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) ); if( task->range ) curl_easy_setopt( e, CURLOPT_RANGE, task->range ); return e; }
static CURL * createEasy( tr_session * s, struct tr_web_task * task ) { const tr_address * addr; tr_bool is_default_value; CURL * e = curl_easy_init( ); const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL; char * cookie_filename = tr_buildPath( s->configDir, "cookies.txt", NULL ); task->timeout_secs = getTimeoutFromURL( task ); curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L ); curl_easy_setopt( e, CURLOPT_COOKIEFILE, cookie_filename ); curl_easy_setopt( e, CURLOPT_ENCODING, "gzip;q=1.0, deflate, identity" ); curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L ); curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L ); curl_easy_setopt( e, CURLOPT_NOSIGNAL, 1L ); curl_easy_setopt( e, CURLOPT_PRIVATE, task ); #ifdef USE_LIBCURL_SOCKOPT curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction ); curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task ); #endif curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L ); curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L ); curl_easy_setopt( e, CURLOPT_TIMEOUT, task->timeout_secs ); curl_easy_setopt( e, CURLOPT_URL, task->url ); curl_easy_setopt( e, CURLOPT_USERAGENT, TR_NAME "/" SHORT_VERSION_STRING ); curl_easy_setopt( e, CURLOPT_VERBOSE, verbose ); curl_easy_setopt( e, CURLOPT_WRITEDATA, task ); curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc ); if((( addr = tr_sessionGetPublicAddress( s, TR_AF_INET, &is_default_value ))) && !is_default_value ) curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) ); else if ((( addr = tr_sessionGetPublicAddress( s, TR_AF_INET6, &is_default_value ))) && !is_default_value ) curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( addr ) ); if( task->range ) curl_easy_setopt( e, CURLOPT_RANGE, task->range ); if( s->curl_easy_config_func != NULL ) s->curl_easy_config_func( s, e, task->url ); tr_free( cookie_filename ); return e; }
static void addTask( void * vtask ) { struct tr_web_task * task = vtask; const tr_session * session = task->session; if( ( session == NULL ) || ( session->web == NULL ) ) return; if( !task->resolved_host ) { dbgmsg( "couldn't resolve host for \"%s\"... task failed", task->url ); task_finish( task, 0 ); } else { CURL * e = curl_easy_init( ); struct tr_web * web = session->web; const int timeout = getTimeoutFromURL( task->url ); const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL; const char * user_agent = TR_NAME "/" SHORT_VERSION_STRING; /* insert the resolved host into the URL s.t. curl's DNS won't block * even if -- like on most OSes -- it wasn't built with C-Ares :( * "http://www.craptrackular.org/announce?key=val&key2=..." becomes * "http://127.0.0.1/announce?key=val&key2=..." */ { char * host; struct evbuffer * buf = evbuffer_new( ); char * pch = strstr( task->url, task->host ); char * tail = pch + strlen( task->host ); evbuffer_add( buf, task->url, pch - task->url ); evbuffer_add_printf( buf, "%s", task->resolved_host ); evbuffer_add_printf( buf, "%s", tail ); task->resolved_url = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) ); dbgmsg( "old url: \"%s\" -- new url: \"%s\"", task->url, task->resolved_url ); evbuffer_free( buf ); /* Manually add a Host: argument that refers to the true URL */ if( ( ( task->port <= 0 ) ) || ( ( task->port == 80 ) && !strncmp( task->url, "http://", 7 ) ) || ( ( task->port == 443 ) && !strncmp( task->url, "https://", 8 ) ) ) host = tr_strdup_printf( "Host: %s", task->host ); else host = tr_strdup_printf( "Host: %s:%d", task->host, task->port ); task->slist = curl_slist_append( NULL, host ); task->slist = curl_slist_append( task->slist, "Accept:" ); curl_easy_setopt( e, CURLOPT_HTTPHEADER, task->slist ); tr_free( host ); } dbgmsg( "adding task #%lu [%s]", task->tag, task->resolved_url ? task->resolved_url : task->url ); if( !task->range && session->isProxyEnabled ) { curl_easy_setopt( e, CURLOPT_PROXY, session->proxy ); curl_easy_setopt( e, CURLOPT_PROXYAUTH, CURLAUTH_ANY ); curl_easy_setopt( e, CURLOPT_PROXYPORT, session->proxyPort ); curl_easy_setopt( e, CURLOPT_PROXYTYPE, getCurlProxyType( session->proxyType ) ); } if( !task->range && session->isProxyAuthEnabled ) { char * str = tr_strdup_printf( "%s:%s", session->proxyUsername, session->proxyPassword ); curl_easy_setopt( e, CURLOPT_PROXYUSERPWD, str ); tr_free( str ); } task->easy = e; task->multi = web->multi; /* use our own timeout instead of CURLOPT_TIMEOUT because the latter * doesn't play nicely with curl_multi. See curl bug #2501457 */ task->timer_event_isSet = TRUE; evtimer_set( &task->timer_event, task_timeout_cb, task ); tr_timerAdd( &task->timer_event, timeout, 0 ); curl_easy_setopt( e, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); curl_easy_setopt( e, CURLOPT_SOCKOPTFUNCTION, sockoptfunction ); curl_easy_setopt( e, CURLOPT_SOCKOPTDATA, task ); curl_easy_setopt( e, CURLOPT_WRITEDATA, task ); curl_easy_setopt( e, CURLOPT_WRITEFUNCTION, writeFunc ); curl_easy_setopt( e, CURLOPT_DNS_CACHE_TIMEOUT, MIN_DNS_CACHE_TIME ); curl_easy_setopt( e, CURLOPT_FOLLOWLOCATION, 1L ); curl_easy_setopt( e, CURLOPT_AUTOREFERER, 1L ); curl_easy_setopt( e, CURLOPT_FORBID_REUSE, 1L ); curl_easy_setopt( e, CURLOPT_MAXREDIRS, -1L ); curl_easy_setopt( e, CURLOPT_PRIVATE, task ); curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L ); curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L ); curl_easy_setopt( e, CURLOPT_URL, task->resolved_url ? task->resolved_url : task->url ); curl_easy_setopt( e, CURLOPT_USERAGENT, user_agent ); curl_easy_setopt( e, CURLOPT_VERBOSE, verbose ); if( web->haveAddr ) curl_easy_setopt( e, CURLOPT_INTERFACE, tr_ntop_non_ts( &web->addr ) ); if( task->range ) curl_easy_setopt( e, CURLOPT_RANGE, task->range ); if( curl_multi_add_handle( web->multi, e ) == CURLM_OK ) ++web->taskCount; } }