Пример #1
0
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;
}
Пример #2
0
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;
    }
}
Пример #3
0
static void
addTask( void * vtask )
{
    struct tr_web_task * task = vtask;
    const tr_handle * session = task->session;

    if( session && session->web )
    {
        struct tr_web * web = session->web;
        CURL * easy;

        dbgmsg( "adding task #%lu [%s]", task->tag, task->url );

        easy = curl_easy_init( );

        if( !task->range && session->isProxyEnabled ) {
            curl_easy_setopt( easy, CURLOPT_PROXY, session->proxy );
            curl_easy_setopt( easy, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
            curl_easy_setopt( easy, CURLOPT_PROXYPORT, session->proxyPort );
            curl_easy_setopt( easy, CURLOPT_PROXYTYPE,
                                      getCurlProxyType( session->proxyType ) );
        }
        if( !task->range && session->isProxyAuthEnabled ) {
            char * str = tr_strdup_printf( "%s:%s", session->proxyUsername,
                                                    session->proxyPassword );
            curl_easy_setopt( easy, CURLOPT_PROXYUSERPWD, str );
            tr_free( str );
        }

        curl_easy_setopt( easy, CURLOPT_DNS_CACHE_TIMEOUT, 360L );
        curl_easy_setopt( easy, CURLOPT_CONNECTTIMEOUT, 60L );
        curl_easy_setopt( easy, CURLOPT_FOLLOWLOCATION, 1L );
        curl_easy_setopt( easy, CURLOPT_MAXREDIRS, 16L );
        curl_easy_setopt( easy, CURLOPT_NOSIGNAL, 1L );
        curl_easy_setopt( easy, CURLOPT_PRIVATE, task );
        curl_easy_setopt( easy, CURLOPT_SSL_VERIFYHOST, 0L );
        curl_easy_setopt( easy, CURLOPT_SSL_VERIFYPEER, 0L );
        curl_easy_setopt( easy, CURLOPT_URL, task->url );
        curl_easy_setopt( easy, CURLOPT_USERAGENT,
                                           TR_NAME "/" LONG_VERSION_STRING );
        curl_easy_setopt( easy, CURLOPT_VERBOSE,
                                       getenv( "TR_CURL_VERBOSE" ) != NULL );
        curl_easy_setopt( easy, CURLOPT_WRITEDATA, task );
        curl_easy_setopt( easy, CURLOPT_WRITEFUNCTION, writeFunc );
        if( task->range )
            curl_easy_setopt( easy, CURLOPT_RANGE, task->range );
        else /* don't set encoding on webseeds; it messes up binary data */
            curl_easy_setopt( easy, CURLOPT_ENCODING, "" );

        if( web->still_running >= MAX_CONCURRENT_TASKS ) {
            tr_list_append( &web->easy_queue, easy );
            dbgmsg( " >> enqueueing a task ... size is now %d",
                                           tr_list_size( web->easy_queue ) );
        } else {
            const CURLMcode rc = curl_multi_add_handle( web->multi, easy );
            if( rc == CURLM_OK )
                ++web->still_running;
            else
                tr_err( "%s", curl_multi_strerror( rc ) );
        }
    }
}