Changeset 1685
- Timestamp:
- Apr 8, 2007, 5:41:44 AM (15 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/internal.h
r1650 r1685 132 132 typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t; 133 133 134 #include "bsdqueue.h" 135 #include "bsdtree.h" 134 136 #include "platform.h" 135 137 #include "bencode.h" -
trunk/libtransmission/tracker.c
r1612 r1685 26 26 #include "shared.h" 27 27 28 typedef struct tr_announce_list_ptr_s tr_announce_list_ptr_t; 29 struct tr_announce_list_ptr_s 30 { 31 tr_tracker_info_t * item;32 tr_announce_list_ptr_t * nextItem;28 struct tclist 29 { 30 tr_tracker_info_t * tl_inf; 31 int tl_badscrape; 32 SLIST_ENTRY( tclist ) next; 33 33 }; 34 SLIST_HEAD( tchead, tclist ); 34 35 35 36 struct tr_tracker_s … … 40 41 char * trackerid; 41 42 42 tr_tracker_info_t * info; 43 44 tr_announce_list_ptr_t ** trackerAnnounceListPtr; 43 struct tchead * tiers; 44 size_t tierCount; 45 size_t tierIndex; 46 struct tclist * tcCur; 45 47 46 48 #define TC_CHANGE_NO 0 … … 49 51 #define TC_CHANGE_REDIRECT 4 50 52 int shouldChangeAnnounce; 51 int announceTier;52 int announceTierLast;53 53 54 54 char * redirectAddress; … … 86 86 }; 87 87 88 static void setAnnounce ( tr_tracker_t * tc, tr_announce_list_ptr_t * announceItem);88 static void setAnnounce ( tr_tracker_t * tc, struct tclist * new ); 89 89 static void failureAnnouncing( tr_tracker_t * tc ); 90 90 static tr_http_t * getQuery ( tr_tracker_t * tc ); … … 102 102 103 103 tr_tracker_t * tc; 104 tr_announce_list_ptr_t * prev, * cur; 105 int ii, jj; 106 107 tc = calloc( 1, sizeof( tr_tracker_t ) ); 104 struct tclist * item; 105 size_t ii, jj; 106 107 tc = calloc( 1, sizeof *tc ); 108 if( NULL == tc ) 109 { 110 return NULL; 111 } 112 108 113 tc->tor = tor; 109 114 tc->id = tor->id; … … 121 126 122 127 tc->publicPort = tor->publicPort; 123 124 tc->trackerAnnounceListPtr = calloc( sizeof( int ), inf->trackerTiers ); 125 for( ii = 0; ii < inf->trackerTiers; ii++ ) 126 { 127 prev = NULL; 128 for( jj = 0; jj < inf->trackerList[ii].count; jj++ ) 129 { 130 cur = calloc( sizeof( tr_announce_list_ptr_t ), 1 ); 131 cur->item = &inf->trackerList[ii].list[jj]; 132 if( NULL == prev ) 128 129 assert( 0 <= inf->trackerTiers ); 130 assert( sizeof( struct tchead ) == sizeof *tc->tiers ); 131 tc->tiers = calloc( inf->trackerTiers, sizeof *tc->tiers ); 132 tc->tierCount = inf->trackerTiers; 133 for( ii = 0; tc->tierCount > ii; ii++ ) 134 { 135 assert( 0 <= inf->trackerList[ii].count ); 136 SLIST_INIT( &tc->tiers[ii] ); 137 for( jj = inf->trackerList[ii].count; 0 < jj; jj-- ) 138 { 139 item = calloc( 1, sizeof *item ); 140 if( NULL == item ) 133 141 { 134 tc->trackerAnnounceListPtr[ii] = cur; 142 tr_trackerClose( tc ); 143 return NULL; 135 144 } 136 else 137 { 138 prev->nextItem = cur; 139 } 140 prev = cur; 141 } 142 } 143 144 setAnnounce( tc, tc->trackerAnnounceListPtr[0] ); 145 item->tl_inf = &inf->trackerList[ii].list[jj-1]; 146 SLIST_INSERT_HEAD( &tc->tiers[ii], item, next ); 147 } 148 } 149 150 setAnnounce( tc, SLIST_FIRST( &tc->tiers[0] ) ); 145 151 146 152 return tc; 147 153 } 148 154 149 static void setAnnounce( tr_tracker_t * tc, tr_announce_list_ptr_t * announcePtr)150 { 151 tc-> info = announcePtr->item;155 static void setAnnounce( tr_tracker_t * tc, struct tclist * new ) 156 { 157 tc->tcCur = new; 152 158 153 159 /* Needs a new scrape */ … … 160 166 static void failureAnnouncing( tr_tracker_t * tc ) 161 167 { 162 tr_info_t * inf = &tc->tor->info;163 164 tc->shouldChangeAnnounce = tc->announceTier + 1 < inf->trackerTiers165 || tc->announceTierLast + 1 < inf->trackerList[tc->announceTier].count166 ? TC_CHANGE_NEXT : TC_CHANGE_NONEXT;167 168 if( tc->shouldChangeAnnounce == TC_CHANGE_NONEXT )169 {168 if( NULL != SLIST_NEXT( tc->tcCur, next ) || 169 tc->tierIndex + 1 < tc->tierCount ) 170 { 171 tc->shouldChangeAnnounce = TC_CHANGE_NEXT; 172 } 173 else 174 { 175 tc->shouldChangeAnnounce = TC_CHANGE_NONEXT; 170 176 tc->completelyUnconnectable = 1; 171 177 } … … 186 192 now = tr_date(); 187 193 188 /* If last attempt was an error and it did not change trackers, then all must have been errors */ 194 /* If last attempt was an error and it did not change trackers, 195 then all must have been errors */ 189 196 if( tc->lastError ) 190 197 { 191 /* Unreachable trackers, wait 10 seconds + random value before trying again */ 198 /* Unreachable trackers, wait 10 seconds + random value before 199 trying again */ 192 200 if( tc->allUnreachIfError ) 193 201 { … … 197 205 } 198 206 } 199 /* The tracker rejected us (like 4XX code, unauthorized IP...), 200 don't hammer it - we'll probably get the same answer next time anyway */ 207 /* The tracker rejected us (like 4XX code, unauthorized 208 IP...), don't hammer it - we'll probably get the same 209 answer next time anyway */ 201 210 else 202 211 { … … 207 216 else 208 217 { 209 tc->allUnreachIfError = 1; //since starting at the top of the list, reset if any were reached previously 218 /* since starting at the top of the list, reset if any 219 were reached previously */ 220 tc->allUnreachIfError = 1; 210 221 } 211 222 } … … 263 274 /* in process of changing tracker or scrape not supported */ 264 275 if( tc->shouldChangeAnnounce != TC_CHANGE_NO || 265 NULL == tc->info->scrape || tc->stopped ) 276 NULL == tc->tcCur->tl_inf->scrape || tc->tcCur->tl_badscrape || 277 tc->stopped ) 266 278 { 267 279 return 0; … … 283 295 uint8_t ** peerCompact, int manual ) 284 296 { 285 tr_torrent_t * tor = tc->tor;286 tr_info_t * inf = &tor->info;287 297 const char * data; 288 298 char * address, * announce; 289 int len, i, port; 290 tr_announce_list_ptr_t * announcePtr, * prevAnnouncePtr; 299 int len, port; 300 struct tclist * next; 301 struct tchead * tier; 291 302 292 303 *peerCount = 0; … … 295 306 if( ( NULL == tc->http ) && ( manual || shouldConnect( tc ) ) ) 296 307 { 297 //if announcing manually, don't consider not reaching a tracker an error 308 /* if announcing manually, don't consider not reaching a 309 tracker an error */ 298 310 if( manual ) 299 311 { … … 313 325 { 314 326 tr_err( "Tracker: redirected URL: %s:%d", address, port ); 315 tc->http = tr_httpClient( TR_HTTP_GET, address, port, "%s", announce ); 327 tc->http = tr_httpClient( TR_HTTP_GET, address, port, 328 "%s", announce ); 316 329 317 330 free( address ); … … 327 340 if( tc->shouldChangeAnnounce == TC_CHANGE_NEXT ) 328 341 { 329 tr_inf( "Tracker: failed to connect to %s , trying next",330 tc-> info->address);331 332 if( tc->announceTierLast + 1 < inf->trackerList[tc->announceTier].count )342 tr_inf( "Tracker: failed to connect to %s:%i, trying next", 343 tc->tcCur->tl_inf->address, tc->tcCur->tl_inf->port ); 344 next = SLIST_NEXT( tc->tcCur, next ); 345 if( NULL == next ) 333 346 { 334 tc->announceTierLast++; 335 336 announcePtr = tc->trackerAnnounceListPtr[tc->announceTier]; 337 for( i = 0; i < tc->announceTierLast; i++ ) 338 { 339 announcePtr = announcePtr->nextItem; 340 } 341 } 342 else 343 { 344 tc->announceTierLast = 0; 345 tc->announceTier++; 346 347 announcePtr = tc->trackerAnnounceListPtr[tc->announceTier]; 347 assert( tc->tierCount > tc->tierIndex + 1 ); 348 tc->tierIndex++; 349 next = SLIST_FIRST( &tc->tiers[tc->tierIndex] ); 350 /* XXX will there always be at least one tracker 351 in a tier? */ 348 352 } 349 353 350 tr_inf( "Tracker: tracker address set to %s", tc->trackerAnnounceListPtr[tc->announceTier]->item->address ); 351 setAnnounce( tc, announcePtr ); 354 tr_inf( "Tracker: switching to tracker http://%s:%i%s", 355 next->tl_inf->address, next->tl_inf->port, 356 next->tl_inf->announce ); 357 setAnnounce( tc, next ); 352 358 } 353 359 /* Need to change to first in list */ 354 else if( tc->announceTier != 0 || tc->announceTierLast != 0)360 else if( SLIST_FIRST( &tc->tiers[0] ) != tc->tcCur ) 355 361 { 356 /* Check if the last announce was successful and wasn't the first in the sublist */ 357 if( tc->shouldChangeAnnounce == TC_CHANGE_NO && tc->announceTierLast != 0 ) 362 tier = &tc->tiers[tc->tierIndex]; 363 /* Check if the last announce was successful and 364 wasn't the first in the sublist */ 365 if( tc->shouldChangeAnnounce == TC_CHANGE_NO && 366 SLIST_FIRST( tier ) != tc->tcCur ) 358 367 { 359 announcePtr = tc->trackerAnnounceListPtr[tc->announceTier]; 360 prevAnnouncePtr = NULL; 361 for( i = 0; i < tc->announceTierLast; i++ ) 362 { 363 prevAnnouncePtr = announcePtr; 364 announcePtr = announcePtr->nextItem; 365 } 366 367 /* Move address to front of tier in announce list */ 368 prevAnnouncePtr->nextItem = announcePtr->nextItem; 369 announcePtr->nextItem = tc->trackerAnnounceListPtr[tc->announceTier]; 370 tc->trackerAnnounceListPtr[tc->announceTier] = announcePtr; 368 SLIST_REMOVE( tier, tc->tcCur, tclist, next ); 369 SLIST_INSERT_HEAD( tier, tc->tcCur, next ); 371 370 } 372 371 373 setAnnounce( tc, tc->trackerAnnounceListPtr[0] ); 374 tc->announceTier = 0; 375 tc->announceTierLast = 0; 372 setAnnounce( tc, SLIST_FIRST( tier ) ); 376 373 } 377 374 378 375 tc->http = getQuery( tc ); 379 376 380 377 tr_inf( "Tracker: connecting to %s:%d (%s)", 381 tc-> info->address, tc->info->port,378 tc->tcCur->tl_inf->address, tc->tcCur->tl_inf->port, 382 379 tc->started ? "sending 'started'" : 383 380 ( tc->completed ? "sending 'completed'" : 384 381 ( tc->stopped ? "sending 'stopped'" : 385 ( shouldChangePort( tc ) ? "sending 'stopped' to change port" : 382 ( shouldChangePort( tc ) ? 383 "sending 'stopped' to change port" : 386 384 "getting peers" ) ) ) ); 387 385 } … … 420 418 { 421 419 /* Use redirected address */ 422 if( !tr_httpParseUrl( tc->redirectScrapeAddress, tc->redirectScrapeAddressLen, 423 &address, &port, &announce ) ) 420 if( !tr_httpParseUrl( tc->redirectScrapeAddress, 421 tc->redirectScrapeAddressLen, 422 &address, &port, &announce ) ) 424 423 { 425 424 tr_err( "Scrape: redirected URL: %s:%d", address, port ); 426 tc->httpScrape = tr_httpClient( TR_HTTP_GET, address, port, "%s", announce ); 425 tc->httpScrape = tr_httpClient( TR_HTTP_GET, address, port, 426 "%s", announce ); 427 427 428 428 free( address ); … … 436 436 { 437 437 tc->httpScrape = getScrapeQuery( tc ); 438 tr_inf( "Scrape: sent HTTP request to %s:%d%s", 439 tc->info->address, tc->info->port, tc->info->scrape ); 438 tr_inf( "Scrape: sent HTTP request for http://%s:%d%s", 439 tc->tcCur->tl_inf->address, 440 tc->tcCur->tl_inf->port, 441 tc->tcCur->tl_inf->scrape ); 440 442 } 441 443 } … … 486 488 void tr_trackerClose( tr_tracker_t * tc ) 487 489 { 488 tr_torrent_t * tor = tc->tor; 489 tr_info_t * inf = &tor->info; 490 tr_announce_list_ptr_t * cur, * curFree; 491 int ii; 490 size_t ii; 491 struct tclist * dead; 492 492 493 493 killHttp( &tc->http ); 494 494 killHttp( &tc->httpScrape ); 495 495 496 for( ii = 0; ii < inf->trackerTiers; ii++ )497 { 498 for( cur = tc->trackerAnnounceListPtr[ii]; cur;)499 { 500 curFree = cur;501 cur = cur->nextItem;502 free( curFree);503 } 504 } 505 free( tc->t rackerAnnounceListPtr);496 for( ii = 0; tc->tierCount > ii; ii++ ) 497 { 498 while( !SLIST_EMPTY( &tc->tiers[ii] ) ) 499 { 500 dead = SLIST_FIRST( &tc->tiers[ii] ); 501 SLIST_REMOVE_HEAD( &tc->tiers[ii], next ); 502 free( dead ); 503 } 504 } 505 free( tc->tiers ); 506 506 507 507 free( tc->trackerid ); … … 512 512 { 513 513 tr_torrent_t * tor = tc->tor; 514 tr_tracker_info_t * tcInf = tc->tcCur->tl_inf; 514 515 515 516 char * event, * trackerid, * idparam; … … 558 559 } 559 560 560 start = ( strchr( tc ->info->announce, '?' ) ? '&' : '?' );561 start = ( strchr( tcInf->announce, '?' ) ? '&' : '?' ); 561 562 left = tr_cpLeftBytes( tor->completion ); 562 563 563 return tr_httpClient( TR_HTTP_GET, tc ->info->address, tc->info->port,564 return tr_httpClient( TR_HTTP_GET, tcInf->address, tcInf->port, 564 565 "%s%c" 565 566 "info_hash=%s&" … … 574 575 "%s%s" 575 576 "%s", 576 tc ->info->announce, start, tor->escapedHashString,577 tcInf->announce, start, tor->escapedHashString, 577 578 tc->id, tc->publicPort, up, down, left, numwant, 578 579 tor->key, idparam, trackerid, event ); … … 582 583 { 583 584 tr_torrent_t * tor = tc->tor; 585 tr_tracker_info_t * tcInf = tc->tcCur->tl_inf; 584 586 char start; 585 587 586 start = ( strchr( tc ->info->scrape, '?' ) ? '&' : '?' );587 588 return tr_httpClient( TR_HTTP_GET, tc ->info->address, tc->info->port,588 start = ( strchr( tcInf->scrape, '?' ) ? '&' : '?' ); 589 590 return tr_httpClient( TR_HTTP_GET, tcInf->address, tcInf->port, 589 591 "%s%c" 590 592 "info_hash=%s", 591 tc ->info->scrape, start, tor->escapedHashString );593 tcInf->scrape, start, tor->escapedHashString ); 592 594 } 593 595 … … 685 687 } 686 688 687 / / tr_bencPrint( &beAll );689 /* tr_bencPrint( &beAll ); */ 688 690 689 691 if( ( bePeers = tr_bencDictFind( &beAll, "failure reason" ) ) ) … … 891 893 if( TR_HTTP_STATUS_FAIL_CLIENT( code ) ) 892 894 { 893 free( tc->info->scrape ); 894 tc->info->scrape = NULL; 895 tc->tcCur->tl_badscrape = 1; 895 896 } 896 897 tc->lastScrapeFailed = 1; … … 1003 1004 return NULL; 1004 1005 } 1005 return tc-> info;1006 return tc->tcCur->tl_inf; 1006 1007 } 1007 1008 … … 1026 1027 tc = tr_trackerInit( tor ); 1027 1028 1028 if( NULL == tc-> info->scrape )1029 if( NULL == tc->tcCur->tl_inf->scrape || tc->tcCur->tl_badscrape ) 1029 1030 { 1030 1031 return 1;
Note: See TracChangeset
for help on using the changeset viewer.