Changeset 9990
- Timestamp:
- Jan 22, 2010, 2:40:11 AM (12 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/trevent.c
r9868 r9990 19 19 #include <signal.h> 20 20 21 #include <event.h> 22 #include <evdns.h> 23 21 24 #include "transmission.h" 22 25 #include "net.h" … … 218 221 eh->base = event_init( ); 219 222 eh->session->events = eh; 223 evdns_init( ); 224 220 225 221 226 /* listen to the pipe's read fd */ -
trunk/libtransmission/web.c
r9911 r9990 15 15 #include <curl/curl.h> 16 16 #include <event.h> 17 #include <evdns.h> 17 18 18 19 #include "transmission.h" 20 #include "list.h" 19 21 #include "net.h" 20 22 #include "session.h" … … 58 60 tr_session * session; 59 61 tr_address addr; 62 tr_list * dns_cache; 60 63 struct event timer_event; 61 64 }; 62 65 66 struct dns_cache_item; 67 static void dns_cache_item_free( struct dns_cache_item * ); 68 63 69 static void 64 70 web_free( tr_web * g ) … … 66 72 curl_multi_cleanup( g->multi ); 67 73 evtimer_del( &g->timer_event ); 74 tr_list_free( &g->dns_cache, (TrListForeachFunc)dns_cache_item_free ); 68 75 memset( g, TR_MEMORY_TRASH, sizeof( struct tr_web ) ); 69 76 tr_free( g ); … … 79 86 struct evbuffer * response; 80 87 char * url; 88 char * host; 89 const char * resolved_host; 81 90 char * range; 82 91 tr_session * session; … … 93 102 evtimer_del( &task->timer_event ); 94 103 evbuffer_free( task->response ); 104 tr_free( task->host ); 95 105 tr_free( task->range ); 96 106 tr_free( task->url ); 97 107 memset( task, TR_MEMORY_TRASH, sizeof( struct tr_web_task ) ); 98 108 tr_free( task ); 109 } 110 111 /*** 112 **** 113 ***/ 114 115 struct dns_cache_item 116 { 117 char * host; 118 char * resolved_host; 119 time_t expiration; 120 }; 121 122 static void 123 dns_cache_item_free( struct dns_cache_item * item ) 124 { 125 tr_free( item->host ); 126 tr_free( item->resolved_host ); 127 tr_free( item ); 128 } 129 130 static const char * 131 dns_get_cached_host( struct tr_web_task * task, const char * host ) 132 { 133 tr_list * l; 134 tr_web * g = task->session->web; 135 struct dns_cache_item * item = NULL; 136 137 if( g != NULL ) 138 { 139 /* do we have it cached? */ 140 for( l=g->dns_cache; l!=NULL; l=l->next ) { 141 struct dns_cache_item * tmp = l->data; 142 if( !strcmp( host, tmp->host ) ) { 143 item = tmp; 144 break; 145 } 146 } 147 148 /* has the ttl expired? */ 149 if( ( item != NULL ) && ( item->expiration <= tr_time( ) ) ) { 150 tr_list_remove_data( &g->dns_cache, item ); 151 dns_cache_item_free( item ); 152 item = NULL; 153 } 154 } 155 156 if( item != NULL ) 157 dbgmsg( "found cached dns entry for \"%s\": %s", host, item->resolved_host ); 158 159 return item ? item->resolved_host : NULL; 160 } 161 162 static const char* 163 dns_set_cached_host( struct tr_web_task * task, const char * host, const char * resolved, int ttl ) 164 { 165 char * ret = NULL; 166 tr_web * g; 167 168 assert( task != NULL ); 169 assert( host != NULL ); 170 assert( resolved != NULL ); 171 assert( ttl >= 0 ); 172 173 g = task->session->web; 174 if( g != NULL ) 175 { 176 struct dns_cache_item * item = tr_new( struct dns_cache_item, 1 ); 177 item->host = tr_strdup( host ); 178 item->resolved_host = tr_strdup( resolved ); 179 item->expiration = tr_time( ) + ttl; 180 tr_list_append( &g->dns_cache, item ); 181 ret = item->resolved_host; 182 dbgmsg( "adding dns cache entry for \"%s\": %s", host, resolved ); 183 } 184 return ret; 99 185 } 100 186 … … 164 250 const long verbose = getenv( "TR_CURL_VERBOSE" ) != NULL; 165 251 const char * user_agent = TR_NAME "/" LONG_VERSION_STRING; 166 167 dbgmsg( "adding task #%lu [%s]", task->tag, task->url ); 252 char * url = NULL; 253 254 /* If we've got a resolved host, insert it into the URL: replace 255 * "http://www.craptrackular.org/announce?key=val&key2=..." with 256 * "http://127.0.0.1/announce?key=val&key2=..." 257 * so that curl's DNS won't block */ 258 if( task->resolved_host != NULL ) 259 { 260 struct evbuffer * buf = evbuffer_new( ); 261 char * pch = strstr( task->url, task->host ); 262 char * tail = pch + strlen( task->host ); 263 evbuffer_add( buf, task->url, pch - task->url ); 264 evbuffer_add_printf( buf, "%s", task->resolved_host ); 265 evbuffer_add_printf( buf, "%s", tail ); 266 url = tr_strndup( EVBUFFER_DATA( buf ), EVBUFFER_LENGTH( buf ) ); 267 dbgmsg( "old url: \"%s\" -- new url: \"%s\"", task->url, url ); 268 evbuffer_free( buf ); 269 } 270 271 dbgmsg( "adding task #%lu [%s]", task->tag, url ? url : task->url ); 168 272 169 273 if( !task->range && session->isProxyEnabled ) { … … 203 307 curl_easy_setopt( e, CURLOPT_SSL_VERIFYHOST, 0L ); 204 308 curl_easy_setopt( e, CURLOPT_SSL_VERIFYPEER, 0L ); 205 curl_easy_setopt( e, CURLOPT_URL, task->url );309 curl_easy_setopt( e, CURLOPT_URL, url ? url : task->url ); 206 310 curl_easy_setopt( e, CURLOPT_USERAGENT, user_agent ); 207 311 curl_easy_setopt( e, CURLOPT_VERBOSE, verbose ); … … 213 317 if( curl_multi_add_handle( web->multi, e ) == CURLM_OK ) 214 318 ++web->taskCount; 215 } 319 320 tr_free( url ); 321 } 322 } 323 324 static void 325 dns_ipv6_done_cb( int err, char type, int count, int ttl, void * addresses, void * vtask ) 326 { 327 struct tr_web_task * task = vtask; 328 329 if( !err && ( task->host != NULL ) && ( count > 0 ) && ( ttl >= 0 ) && ( type == DNS_IPv6_AAAA ) ) 330 { 331 int i; 332 char buf[INET6_ADDRSTRLEN+1]; 333 struct in6_addr *in6_addrs = addresses; 334 335 for( i=0; i<count; ++i ) { 336 const char * b = inet_ntop(AF_INET6, &in6_addrs[i], buf,sizeof(buf)); 337 if( b != NULL ) { 338 /* FIXME: is there a better way to tell which one to use if count > 1? */ 339 task->resolved_host = dns_set_cached_host( task, task->host, b, ttl ); 340 break; 341 } 342 } 343 } 344 345 addTask( task ); 346 } 347 348 static void 349 dns_ipv4_done_cb( int err, char type, int count, int ttl, void * addresses, void * vtask ) 350 { 351 struct tr_web_task * task = vtask; 352 353 if( !err && ( task->host != NULL ) && ( count > 0 ) && ( ttl >= 0 ) && ( type == DNS_IPv4_A ) ) 354 { 355 struct in_addr * in_addrs = addresses; 356 const char * resolved = inet_ntoa( in_addrs[0] ); 357 task->resolved_host = dns_set_cached_host( task, task->host, resolved, ttl ); 358 /* FIXME: if count > 1, is there a way to decide which is best to use? */ 359 } 360 361 if( task->resolved_host || evdns_resolve_ipv6( task->host, 0, dns_ipv6_done_cb, task ) ) 362 dns_ipv6_done_cb( DNS_ERR_UNKNOWN, DNS_IPv6_AAAA, 0, 0, NULL, task ); 363 } 364 365 static void 366 doDNS( void * vtask ) 367 { 368 char * host = NULL; 369 struct tr_web_task * task = vtask; 370 371 assert( task->resolved_host == NULL ); 372 373 if( !tr_httpParseURL( task->url, -1, &host, NULL, NULL ) ) { 374 task->host = host; 375 task->resolved_host = dns_get_cached_host( task, host ); 376 } 377 378 if( task->resolved_host || evdns_resolve_ipv4( host, 0, dns_ipv4_done_cb, task ) ) 379 dns_ipv4_done_cb( DNS_ERR_UNKNOWN, DNS_IPv4_A, 0, 0, NULL, task ); 216 380 } 217 381 … … 396 560 task->tag = ++tag; 397 561 task->response = evbuffer_new( ); 398 tr_runInEventThread( session, addTask, task );562 tr_runInEventThread( session, doDNS, task ); 399 563 } 400 564 }
Note: See TracChangeset
for help on using the changeset viewer.