mirror of
https://github.com/transmission/transmission
synced 2024-12-26 09:37:56 +00:00
more hacking on libcurl + libevent integration
This commit is contained in:
parent
972964b641
commit
a44f3d75a0
1 changed files with 48 additions and 15 deletions
|
@ -28,6 +28,8 @@
|
||||||
#define curl_multi_socket_action(m,fd,mask,i) curl_multi_socket((m),(fd),(i))
|
#define curl_multi_socket_action(m,fd,mask,i) curl_multi_socket((m),(fd),(i))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_TIMER_MSEC 2000
|
||||||
|
|
||||||
#define dbgmsg( ... ) tr_deepLog( __FILE__, __LINE__, "web", __VA_ARGS__ )
|
#define dbgmsg( ... ) tr_deepLog( __FILE__, __LINE__, "web", __VA_ARGS__ )
|
||||||
/* #define dbgmsg(...) do { fprintf( stderr, __VA_ARGS__ ); fprintf( stderr, "\n" ); } while( 0 ) */
|
/* #define dbgmsg(...) do { fprintf( stderr, __VA_ARGS__ ); fprintf( stderr, "\n" ); } while( 0 ) */
|
||||||
|
|
||||||
|
@ -36,10 +38,11 @@ struct tr_web
|
||||||
unsigned int dying : 1;
|
unsigned int dying : 1;
|
||||||
int prev_running;
|
int prev_running;
|
||||||
int still_running;
|
int still_running;
|
||||||
|
long timer_ms;
|
||||||
CURLM * multi;
|
CURLM * multi;
|
||||||
tr_session * session;
|
tr_session * session;
|
||||||
struct event timer_event;
|
|
||||||
tr_list * easy_queue;
|
tr_list * easy_queue;
|
||||||
|
struct event timer_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -55,6 +58,7 @@ struct tr_web_task
|
||||||
tr_session * session;
|
tr_session * session;
|
||||||
tr_web_done_func * done_func;
|
tr_web_done_func * done_func;
|
||||||
void * done_func_user_data;
|
void * done_func_user_data;
|
||||||
|
long timer_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
|
@ -95,11 +99,13 @@ addTask( void * vtask )
|
||||||
if( !task->range && session->isProxyEnabled ) {
|
if( !task->range && session->isProxyEnabled ) {
|
||||||
curl_easy_setopt( easy, CURLOPT_PROXY, session->proxy );
|
curl_easy_setopt( easy, CURLOPT_PROXY, session->proxy );
|
||||||
curl_easy_setopt( easy, CURLOPT_PROXYPORT, session->proxyPort );
|
curl_easy_setopt( easy, CURLOPT_PROXYPORT, session->proxyPort );
|
||||||
curl_easy_setopt( easy, CURLOPT_PROXYTYPE, getCurlProxyType( session->proxyType ) );
|
curl_easy_setopt( easy, CURLOPT_PROXYTYPE,
|
||||||
|
getCurlProxyType( session->proxyType ) );
|
||||||
curl_easy_setopt( easy, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
|
curl_easy_setopt( easy, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
|
||||||
}
|
}
|
||||||
if( !task->range && session->isProxyAuthEnabled ) {
|
if( !task->range && session->isProxyAuthEnabled ) {
|
||||||
char * str = tr_strdup_printf( "%s:%s", session->proxyUsername, session->proxyPassword );
|
char * str = tr_strdup_printf( "%s:%s", session->proxyUsername,
|
||||||
|
session->proxyPassword );
|
||||||
curl_easy_setopt( easy, CURLOPT_PROXYUSERPWD, str );
|
curl_easy_setopt( easy, CURLOPT_PROXYUSERPWD, str );
|
||||||
tr_free( str );
|
tr_free( str );
|
||||||
}
|
}
|
||||||
|
@ -108,7 +114,8 @@ addTask( void * vtask )
|
||||||
curl_easy_setopt( easy, CURLOPT_URL, task->url );
|
curl_easy_setopt( easy, CURLOPT_URL, task->url );
|
||||||
curl_easy_setopt( easy, CURLOPT_WRITEFUNCTION, writeFunc );
|
curl_easy_setopt( easy, CURLOPT_WRITEFUNCTION, writeFunc );
|
||||||
curl_easy_setopt( easy, CURLOPT_WRITEDATA, task );
|
curl_easy_setopt( easy, CURLOPT_WRITEDATA, task );
|
||||||
curl_easy_setopt( easy, CURLOPT_USERAGENT, TR_NAME "/" LONG_VERSION_STRING );
|
curl_easy_setopt( easy, CURLOPT_USERAGENT,
|
||||||
|
TR_NAME "/" LONG_VERSION_STRING );
|
||||||
curl_easy_setopt( easy, CURLOPT_SSL_VERIFYHOST, 0 );
|
curl_easy_setopt( easy, CURLOPT_SSL_VERIFYHOST, 0 );
|
||||||
curl_easy_setopt( easy, CURLOPT_SSL_VERIFYPEER, 0 );
|
curl_easy_setopt( easy, CURLOPT_SSL_VERIFYPEER, 0 );
|
||||||
//curl_easy_setopt( easy, CURLOPT_FORBID_REUSE, 1 );
|
//curl_easy_setopt( easy, CURLOPT_FORBID_REUSE, 1 );
|
||||||
|
@ -116,15 +123,17 @@ addTask( void * vtask )
|
||||||
curl_easy_setopt( easy, CURLOPT_FOLLOWLOCATION, 1 );
|
curl_easy_setopt( easy, CURLOPT_FOLLOWLOCATION, 1 );
|
||||||
curl_easy_setopt( easy, CURLOPT_MAXREDIRS, 5 );
|
curl_easy_setopt( easy, CURLOPT_MAXREDIRS, 5 );
|
||||||
curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
|
curl_easy_setopt( easy, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
|
||||||
curl_easy_setopt( easy, CURLOPT_VERBOSE, getenv( "TR_CURL_VERBOSE" ) != NULL );
|
curl_easy_setopt( easy, CURLOPT_VERBOSE,
|
||||||
|
getenv( "TR_CURL_VERBOSE" ) != NULL );
|
||||||
if( task->range )
|
if( task->range )
|
||||||
curl_easy_setopt( easy, CURLOPT_RANGE, task->range );
|
curl_easy_setopt( easy, CURLOPT_RANGE, task->range );
|
||||||
else /* don't set encoding if range is sent; it messes up binary data */
|
else /* don't set encoding on webseeds; it messes up binary data */
|
||||||
curl_easy_setopt( easy, CURLOPT_ENCODING, "" );
|
curl_easy_setopt( easy, CURLOPT_ENCODING, "" );
|
||||||
|
|
||||||
if( web->still_running >= MAX_CONCURRENT_TASKS ) {
|
if( web->still_running >= MAX_CONCURRENT_TASKS ) {
|
||||||
tr_list_append( &web->easy_queue, easy );
|
tr_list_append( &web->easy_queue, easy );
|
||||||
dbgmsg( " >> adding a task to the curl queue... size is now %d", tr_list_size( web->easy_queue ) );
|
dbgmsg( " >> adding a task to the curl queue... size is now %d",
|
||||||
|
tr_list_size( web->easy_queue ) );
|
||||||
} else {
|
} else {
|
||||||
CURLMcode rc = curl_multi_add_handle( web->multi, easy );
|
CURLMcode rc = curl_multi_add_handle( web->multi, easy );
|
||||||
if( rc == CURLM_OK )
|
if( rc == CURLM_OK )
|
||||||
|
@ -245,6 +254,20 @@ dbgmsg( "--> still running: %d ... max: %d ... queue size: %d", g->still_running
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_timer( tr_web * g )
|
||||||
|
{
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
if( evtimer_pending( &g->timer_event, NULL ) )
|
||||||
|
evtimer_del( &g->timer_event );
|
||||||
|
|
||||||
|
dbgmsg( "adding a timeout for %ld seconds from now", g->timer_ms/1000l );
|
||||||
|
tr_timevalMsec( g->timer_ms, &timeout );
|
||||||
|
timeout_add( &g->timer_event, &timeout );
|
||||||
|
}
|
||||||
|
|
||||||
/* libevent says that sock is ready to be processed, so wake up libcurl */
|
/* libevent says that sock is ready to be processed, so wake up libcurl */
|
||||||
static void
|
static void
|
||||||
event_cb( int fd, short kind, void * vg )
|
event_cb( int fd, short kind, void * vg )
|
||||||
|
@ -272,10 +295,11 @@ event_cb( int fd, short kind, void * vg )
|
||||||
if( rc != CURLM_OK )
|
if( rc != CURLM_OK )
|
||||||
tr_err( "%s", curl_multi_strerror( rc ) );
|
tr_err( "%s", curl_multi_strerror( rc ) );
|
||||||
|
|
||||||
|
reset_timer( g );
|
||||||
check_run_count( g );
|
check_run_count( g );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* libevent says that timeout_ms have passed, so wake up libcurl */
|
/* libevent says that timer_ms have passed, so wake up libcurl */
|
||||||
static void
|
static void
|
||||||
timer_cb( int socket UNUSED, short action UNUSED, void * vg )
|
timer_cb( int socket UNUSED, short action UNUSED, void * vg )
|
||||||
{
|
{
|
||||||
|
@ -293,6 +317,7 @@ timer_cb( int socket UNUSED, short action UNUSED, void * vg )
|
||||||
if( rc != CURLM_OK )
|
if( rc != CURLM_OK )
|
||||||
tr_err( "%s", curl_multi_strerror( rc ) );
|
tr_err( "%s", curl_multi_strerror( rc ) );
|
||||||
|
|
||||||
|
reset_timer( g );
|
||||||
check_run_count( g );
|
check_run_count( g );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,15 +383,22 @@ sock_cb( CURL * e UNUSED,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* libcurl wants us to tell it when timeout_ms have passed */
|
/* from libcurl documentation: "The timeout value returned in the long timeout
|
||||||
|
points to, is in number of milliseconds at this very moment. If 0, it means
|
||||||
|
you should proceed immediately without waiting for anything. If it
|
||||||
|
returns -1, there's no timeout at all set. Note: if libcurl returns a -1
|
||||||
|
timeout here, it just means that libcurl currently has no stored timeout
|
||||||
|
value. You must not wait too long (more than a few seconds perhaps) before
|
||||||
|
you call curl_multi_perform() again." */
|
||||||
static void
|
static void
|
||||||
multi_timer_cb( CURLM *multi UNUSED, long timeout_ms, void * vweb )
|
multi_timer_cb( CURLM *multi UNUSED, long timer_ms, void * g )
|
||||||
{
|
{
|
||||||
tr_web * web = vweb;
|
if( timer_ms < 1 ) {
|
||||||
struct timeval timeout;
|
if( timer_ms == 0 ) /* call it immediately */
|
||||||
dbgmsg( "adding a timeout for %ld seconds from now", timeout_ms/1000l );
|
timer_cb( 0, 0, g );
|
||||||
tr_timevalMsec( timeout_ms, &timeout );
|
timer_ms = DEFAULT_TIMER_MSEC;
|
||||||
timeout_add( &web->timer_event, &timeout );
|
}
|
||||||
|
reset_timer( g );
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
|
@ -416,6 +448,7 @@ tr_webInit( tr_session * session )
|
||||||
web = tr_new0( struct tr_web, 1 );
|
web = tr_new0( struct tr_web, 1 );
|
||||||
web->multi = curl_multi_init( );
|
web->multi = curl_multi_init( );
|
||||||
web->session = session;
|
web->session = session;
|
||||||
|
web->timer_ms = DEFAULT_TIMER_MSEC; /* default value to overwrite in multi_timer_cb() */
|
||||||
|
|
||||||
timeout_set( &web->timer_event, timer_cb, web );
|
timeout_set( &web->timer_event, timer_cb, web );
|
||||||
curl_multi_setopt( web->multi, CURLMOPT_SOCKETDATA, web );
|
curl_multi_setopt( web->multi, CURLMOPT_SOCKETDATA, web );
|
||||||
|
|
Loading…
Reference in a new issue