Ignore:
Timestamp:
Aug 6, 2008, 11:33:29 PM (13 years ago)
Author:
charles
Message:

possible fix for #1134: revert libtransmission/web.c back to r6354

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/web.c

    r6417 r6447  
    1818
    1919#include "transmission.h"
    20 #include "list.h"
    2120#include "trevent.h"
    2221#include "utils.h"
    2322#include "web.h"
    2423
     24#define CURL_CHECK_VERSION(major,minor,micro)    \
     25    (LIBCURL_VERSION_MAJOR > (major) || \
     26     (LIBCURL_VERSION_MAJOR == (major) && LIBCURL_VERSION_MINOR > (minor)) || \
     27     (LIBCURL_VERSION_MAJOR == (major) && LIBCURL_VERSION_MINOR == (minor) && \
     28      LIBCURL_VERSION_PATCH >= (micro)))
     29
     30#define PULSE_MSEC 500
     31
    2532#define dbgmsg(fmt...) tr_deepLog( __FILE__, __LINE__, "web", ##fmt )
    2633
    2734struct tr_web
    2835{
     36    unsigned int dying     : 1;
     37    unsigned int running   : 1;
    2938    int remain;
    3039    CURLM * cm;
    3140    tr_session * session;
    32     tr_list * socket_events;
    3341    struct event timer;
    3442};
     
    8593}
    8694
     95static void
     96pump( tr_web * web )
     97{
     98    int unused;
     99    CURLMcode rc;
     100    do {
     101        rc = curl_multi_perform( web->cm, &unused );
     102    } while( rc == CURLM_CALL_MULTI_PERFORM );
     103    if ( rc == CURLM_OK  )
     104        processCompletedTasks( web );
     105    else
     106        tr_err( "%s", curl_multi_strerror(rc) );
     107}
     108
    87109static size_t
    88110writeFunc( void * ptr, size_t size, size_t nmemb, void * task )
     
    91113    evbuffer_add( ((struct tr_web_task*)task)->response, ptr, byteCount );
    92114    return byteCount;
     115}
     116
     117static void
     118ensureTimerIsRunning( tr_web * web )
     119{
     120    if( !web->running )
     121    {
     122        struct timeval tv = tr_timevalMsec( PULSE_MSEC );
     123        dbgmsg( "starting web timer" );
     124        web->running = 1;
     125        evtimer_add( &web->timer, &tv );
     126    }
    93127}
    94128
     
    117151        CURL * ch;
    118152
     153        ensureTimerIsRunning( web );
     154
    119155        ++web->remain;
    120156        dbgmsg( "adding task #%lu [%s] (%d remain)", task->tag, task->url, web->remain );
    121157
    122158        ch = curl_easy_init( );
    123 
    124         if( getenv( "TRANSMISSION_LIBCURL_VERBOSE" ) != 0 )
    125             curl_easy_setopt( ch, CURLOPT_VERBOSE, 1 );
    126159
    127160        if( !task->range && session->isProxyEnabled ) {
     
    182215}
    183216
    184 /* libevent says that sock is ready to be processed, so wake up libcurl */
    185 static void
    186 event_callback( int sock, short action, void * vweb )
     217static void
     218webDestroy( tr_web * web )
     219{
     220    dbgmsg( "deleting web timer" );
     221    assert( !web->running );
     222    evtimer_del( &web->timer );
     223    curl_multi_cleanup( web->cm );
     224    tr_free( web );
     225}
     226
     227static void
     228pulse( int socket UNUSED, short action UNUSED, void * vweb )
    187229{
    188230    tr_web * web = vweb;
    189     CURLMcode rc;
    190     int mask;
    191 
    192 #if 0
    193     static const char *strings[] = {
    194         "NONE","TIMEOUT","READ","TIMEOUT|READ","WRITE","TIMEOUT|WRITE",
    195         "READ|WRITE","TIMEOUT|READ|WRITE","SIGNAL" };
    196      fprintf( stderr, "%s:%d (%s) event on socket %d (%s)\n",
    197               __FILE__, __LINE__, __FUNCTION__,
    198               sock, strings[action] );
    199 #endif
    200 
    201     mask = 0;
    202     if( action & EV_READ  ) mask |= CURL_CSELECT_IN;
    203     if( action & EV_WRITE ) mask |= CURL_CSELECT_OUT;
    204 
    205     do
    206         rc = curl_multi_socket_action( web->cm, sock, mask, &web->remain );
    207     while( rc == CURLM_CALL_MULTI_PERFORM );
    208 
    209     if ( rc != CURLM_OK  )
    210         tr_err( "%s (%d)", curl_multi_strerror(rc), (int)sock );
    211 
    212     processCompletedTasks( web );
    213 }
    214 
    215 /* libcurl wants us to tell it when sock is ready to be processed */
    216 static int
    217 socket_callback( CURL            * easy UNUSED,
    218                  curl_socket_t     sock,
    219                  int               action,
    220                  void            * vweb,
    221                  void            * assigndata )
    222 {
    223     tr_web * web = vweb;
    224     int events = EV_PERSIST;
    225     struct event * ev = assigndata;
    226 
    227     if( ev )
    228         event_del( ev );
    229     else {
    230         ev = tr_new0( struct event, 1 );
    231         tr_list_prepend( &web->socket_events, ev );
    232         curl_multi_assign( web->cm, sock, ev );
    233     }
    234 
    235 #if 0
    236     {
    237         static const char *actions[] = {"NONE", "IN", "OUT", "INOUT", "REMOVE"};
    238         fprintf( stderr, "%s:%d (%s) callback on socket %d (%s)\n",
    239                  __FILE__, __LINE__, __FUNCTION__,
    240                  (int)sock, actions[action]);
    241     }
    242 #endif
    243 
    244     switch (action) {
    245         case CURL_POLL_IN: events |= EV_READ; break;
    246         case CURL_POLL_OUT: events |= EV_WRITE; break;
    247         case CURL_POLL_INOUT: events |= EV_READ|EV_WRITE; break;
    248         case CURL_POLL_REMOVE: tr_list_remove_data( &web->socket_events, ev );
    249                                tr_free( ev );
    250                                /* fallthrough */
    251         case CURL_POLL_NONE: return 0;
    252         default: tr_err( "Unknown socket action %d", action ); return -1;
    253     }
    254 
    255     event_set( ev, sock, events, event_callback, web );
    256     event_add( ev, NULL );
    257     return 0;
    258 }
    259 
    260 /* libevent says that timeout_ms have passed, so wake up libcurl */
    261 static void
    262 timeout_callback( int socket UNUSED, short action UNUSED, void * vweb )
    263 {
    264     CURLMcode rc;
    265     tr_web * web = vweb;
    266 
    267     do
    268         rc = curl_multi_socket( web->cm, CURL_SOCKET_TIMEOUT, &web->remain );
    269     while( rc == CURLM_CALL_MULTI_PERFORM );
    270 
    271     if( rc != CURLM_OK )
    272         tr_err( "%s", curl_multi_strerror( rc ) );
    273 
    274     processCompletedTasks( web );
    275 }
    276 
    277 /* libcurl wants us to tell it when timeout_ms have passed */
    278 static void
    279 timer_callback( CURLM *multi UNUSED, long timeout_ms, void * vweb )
    280 {
    281     tr_web * web = vweb;
    282     struct timeval timeout = tr_timevalMsec( timeout_ms );
    283     timeout_add( &web->timer, &timeout );
     231    assert( web->running );
     232
     233    pump( web );
     234
     235    evtimer_del( &web->timer );
     236
     237    web->running = web->remain > 0;
     238
     239    if( web->running ) {
     240        struct timeval tv = tr_timevalMsec( PULSE_MSEC );
     241        evtimer_add( &web->timer, &tv );
     242    } else if( web->dying ) {
     243        webDestroy( web );
     244    } else {
     245        dbgmsg( "stopping web timer" );
     246    }
    284247}
    285248
     
    303266    web->session = session;
    304267
    305     timeout_set( &web->timer, timeout_callback, web );
    306     curl_multi_setopt( web->cm, CURLMOPT_SOCKETDATA, web );
    307     curl_multi_setopt( web->cm, CURLMOPT_SOCKETFUNCTION, socket_callback );
    308     curl_multi_setopt( web->cm, CURLMOPT_TIMERDATA, web );
    309     curl_multi_setopt( web->cm, CURLMOPT_TIMERFUNCTION, timer_callback );
     268    evtimer_set( &web->timer, pulse, web );
     269#if CURL_CHECK_VERSION(7,16,3)
     270    curl_multi_setopt( web->cm, CURLMOPT_MAXCONNECTS, 10 );
     271#endif
     272    pump( web );
    310273
    311274    return web;
    312 }
    313 
    314 static void
    315 event_del_and_free( void * e )
    316 {
    317     event_del( e );
    318     tr_free( e );
    319275}
    320276
     
    325281    *web_in = NULL;
    326282
    327     timeout_del( &web->timer );
    328     tr_list_free( &web->socket_events, event_del_and_free );
    329     curl_multi_cleanup( web->cm );
    330     tr_free( web );
     283    if( !web->running )
     284        webDestroy( web );
     285    else
     286        web->dying = 1;
    331287}
    332288
Note: See TracChangeset for help on using the changeset viewer.