Changeset 10024
- Timestamp:
- Jan 27, 2010, 6:40:12 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/web.c
r10019 r10024 20 20 #include "list.h" 21 21 #include "net.h" 22 #include "ptrarray.h" 22 23 #include "session.h" 23 24 #include "trevent.h" … … 62 63 tr_session * session; 63 64 tr_address addr; 64 tr_ list *dns_cache;65 tr_ptrArray dns_cache; 65 66 struct event timer_event; 66 67 }; … … 75 76 curl_multi_cleanup( g->multi ); 76 77 evtimer_del( &g->timer_event ); 77 tr_ list_free( &g->dns_cache, (TrListForeachFunc)dns_cache_item_free );78 tr_ptrArrayDestruct( &g->dns_cache, (TrListForeachFunc)dns_cache_item_free ); 78 79 memset( g, TR_MEMORY_TRASH, sizeof( struct tr_web ) ); 79 80 tr_free( g ); … … 127 128 char * resolved_host; 128 129 time_t expiration; 130 tr_bool success; 129 131 }; 130 132 … … 137 139 } 138 140 139 static const char * 140 dns_get_cached_host( struct tr_web_task * task, const char * host ) 141 { 142 tr_list * l; 143 tr_web * g = task->session->web; 144 struct dns_cache_item * item = NULL; 145 146 if( g != NULL ) 147 { 148 /* do we have it cached? */ 149 for( l=g->dns_cache; l!=NULL; l=l->next ) { 150 struct dns_cache_item * tmp = l->data; 151 if( !strcmp( host, tmp->host ) ) { 152 item = tmp; 153 break; 154 } 155 } 141 static int 142 dns_cache_compare( const void * va, const void * vb ) 143 { 144 const struct dns_cache_item * a = va; 145 const struct dns_cache_item * b = vb; 146 return strcmp( a->host, b->host ); 147 } 148 149 static int 150 dns_cache_compare_key( const void * va, const void * key ) 151 { 152 const struct dns_cache_item * a = va; 153 return strcmp( a->host, key ); 154 } 155 156 typedef enum 157 { 158 TR_DNS_OK, 159 TR_DNS_FAIL, 160 TR_DNS_UNTESTED 161 } 162 tr_dns_result; 163 164 static tr_dns_result 165 dns_cache_lookup( struct tr_web_task * task, const char * host, const char ** resolved ) 166 { 167 tr_dns_result result = TR_DNS_UNTESTED; 168 169 if( task->session->web != NULL ) 170 { 171 tr_ptrArray * cache = &task->session->web->dns_cache; 172 173 struct dns_cache_item * item = tr_ptrArrayFindSorted( cache, host, 174 dns_cache_compare_key ); 156 175 157 176 /* has the ttl expired? */ 158 if( ( item != NULL ) && ( item->expiration <= tr_time( ) ) ) { 159 tr_list_remove_data( &g->dns_cache, item ); 177 if( ( item != NULL ) && ( item->expiration <= tr_time( ) ) ) 178 { 179 tr_ptrArrayRemoveSorted( cache, host, dns_cache_compare_key ); 160 180 dns_cache_item_free( item ); 161 181 item = NULL; 162 182 } 163 } 164 165 if( item != NULL ) 166 dbgmsg( "found cached dns entry for \"%s\": %s", 167 host, item->resolved_host ); 168 169 return item ? item->resolved_host : NULL; 183 184 if( item != NULL ) 185 { 186 result = item->success ? TR_DNS_OK : TR_DNS_FAIL; 187 188 if( result == TR_DNS_OK ) 189 { 190 *resolved = item->resolved_host; 191 192 dbgmsg( "found cached dns entry for \"%s\": %s", host, *resolved ); 193 } 194 } 195 } 196 197 return result; 198 } 199 200 static void 201 dns_cache_set_fail( struct tr_web_task * task, const char * host ) 202 { 203 if( task->session->web != NULL ) 204 { 205 struct dns_cache_item * item = tr_new( struct dns_cache_item, 1 ); 206 item->host = tr_strdup( host ); 207 item->resolved_host = NULL; 208 item->expiration = tr_time( ) + MIN_DNS_CACHE_TIME; 209 item->success = FALSE; 210 tr_ptrArrayInsertSorted( &task->session->web->dns_cache, item, dns_cache_compare ); 211 } 170 212 } 171 213 172 214 static const char* 173 dns_ set_cached_host( struct tr_web_task * task, const char * host,174 215 dns_cache_set_name( struct tr_web_task * task, const char * host, 216 const char * resolved, int ttl ) 175 217 { 176 218 char * ret = NULL; 177 tr_web * g;178 179 assert( task != NULL );180 assert( host != NULL );181 assert( resolved != NULL );182 assert( ttl >= 0 );183 219 184 220 ttl = MAX( MIN_DNS_CACHE_TIME, ttl ); 185 221 186 g = task->session->web; 187 if( g != NULL ) 222 if( task->session->web != NULL ) 188 223 { 189 224 struct dns_cache_item * item = tr_new( struct dns_cache_item, 1 ); … … 191 226 item->resolved_host = tr_strdup( resolved ); 192 227 item->expiration = tr_time( ) + ttl; 193 tr_list_append( &g->dns_cache, item ); 228 item->success = TRUE; 229 tr_ptrArrayInsertSorted( &task->session->web->dns_cache, item, dns_cache_compare ); 194 230 ret = item->resolved_host; 195 231 dbgmsg( "adding dns cache entry for \"%s\": %s", host, resolved ); … … 260 296 return; 261 297 262 if( task->resolved_host == NULL)298 if( !task->resolved_host ) 263 299 { 264 300 dbgmsg( "couldn't resolve host for \"%s\"... task failed", task->url ); … … 362 398 struct tr_web_task * task = vtask; 363 399 364 if( !err && ( task->host != NULL ) && ( count > 0 ) && ( ttl >= 0 ) && ( type ==DNS_IPv6_AAAA ) )400 if( !err && task->host && ( count>0 ) && ( ttl>=0 ) && ( type==DNS_IPv6_AAAA ) ) 365 401 { 366 402 int i; … … 372 408 if( b != NULL ) { 373 409 /* FIXME: is there a better way to tell which one to use if count > 1? */ 374 task->resolved_host = dns_ set_cached_host( task, task->host, b, ttl );410 task->resolved_host = dns_cache_set_name( task, task->host, b, ttl ); 375 411 break; 376 412 } … … 378 414 } 379 415 416 if( task->resolved_host == NULL ) 417 dns_cache_set_fail( task, task->host ); 418 380 419 addTask( task ); 381 420 } … … 386 425 struct tr_web_task * task = vtask; 387 426 388 if( !err && ( task->host != NULL ) && ( count > 0 ) && ( ttl >= 0 ) && ( type ==DNS_IPv4_A ) )427 if( !err && task->host && ( count>0 ) && ( ttl>=0 ) && ( type==DNS_IPv4_A ) ) 389 428 { 390 429 struct in_addr * in_addrs = addresses; 391 430 const char * resolved = inet_ntoa( in_addrs[0] ); 392 task->resolved_host = dns_ set_cached_host( task, task->host, resolved, ttl );431 task->resolved_host = dns_cache_set_name( task, task->host, resolved, ttl ); 393 432 /* FIXME: if count > 1, is there a way to decide which is best to use? */ 394 433 } … … 406 445 char * host = NULL; 407 446 struct tr_web_task * task = vtask; 447 tr_dns_result lookup_result = TR_DNS_UNTESTED; 408 448 409 449 assert( task->resolved_host == NULL ); 410 450 411 if( !tr_httpParseURL( task->url, -1, &host, &port, NULL ) ) { 451 if( !tr_httpParseURL( task->url, -1, &host, &port, NULL ) ) 452 { 412 453 task->port = port; 413 454 task->host = host; 414 task->resolved_host = dns_get_cached_host( task, host ); 415 } 416 417 if( ( task->resolved_host != NULL ) 418 || ( host == NULL ) 419 || evdns_resolve_ipv4( host, 0, dns_ipv4_done_cb, task ) ) 455 lookup_result = dns_cache_lookup( task, host, &task->resolved_host ); 456 } 457 458 if( lookup_result != TR_DNS_UNTESTED ) 459 { 460 addTask( task ); 461 } 462 else if( !host || evdns_resolve_ipv4( host, 0, dns_ipv4_done_cb, task ) ) 463 { 420 464 dns_ipv4_done_cb( DNS_ERR_UNKNOWN, DNS_IPv4_A, 0, 0, NULL, task ); 465 } 421 466 } 422 467 … … 623 668 624 669 web = tr_new0( struct tr_web, 1 ); 670 web->dns_cache = TR_PTR_ARRAY_INIT; 625 671 web->session = session; 626 672 web->timer_msec = DEFAULT_TIMER_MSEC; /* overwritten by multi_timer_cb() */
Note: See TracChangeset
for help on using the changeset viewer.