Christian Weisgerber <[EMAIL PROTECTED]> wrote: > I looked at the tracker responses, and they seemed fine. (Not that > I know the details of the protocol.) I suspect transmission just > fails to parse them. It keeps hammering away at the tracker for a > "correct" response, which looks like a fairly serious bug.
This corresponds to changeset 230 from the upstream SVN, which introduces a less haphazard tracker response parsing. Please test. Index: Makefile =================================================================== RCS file: /cvs/ports/net/transmission/Makefile,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 Makefile --- Makefile 26 Apr 2006 20:05:06 -0000 1.1.1.1 +++ Makefile 26 Apr 2006 21:36:57 -0000 @@ -4,8 +4,8 @@ COMMENT-gui= "lightweight BitTorrent client with graphical interface" DISTNAME= Transmission-0.5 -PKGNAME= ${DISTNAME:L} -PKGNAME-gui= ${DISTNAME:L:S/-/-gui-/} +PKGNAME= ${DISTNAME:L}p0 +PKGNAME-gui= ${DISTNAME:L:S/-/-gui-/}p0 CATEGORIES= net HOMEPAGE= http://transmission.m0k.org/ Index: patches/patch-libtransmission_tracker_c =================================================================== RCS file: patches/patch-libtransmission_tracker_c diff -N patches/patch-libtransmission_tracker_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-libtransmission_tracker_c 26 Apr 2006 21:36:57 -0000 @@ -0,0 +1,175 @@ +$OpenBSD$ +--- libtransmission/tracker.c.orig Sat Feb 11 17:37:11 2006 ++++ libtransmission/tracker.c Wed Apr 26 23:21:07 2006 +@@ -45,6 +45,11 @@ struct tr_tracker_s + #define TC_STATUS_RECV 4 + char status; + ++#define TC_ATTEMPT_NOREACH 1 ++#define TC_ATTEMPT_ERROR 2 ++#define TC_ATTEMPT_OK 4 ++ char lastAttempt; ++ + int socket; + uint8_t * buf; + int size; +@@ -67,10 +72,12 @@ tr_tracker_t * tr_trackerInit( tr_handle + + tc->started = 1; + ++ tc->interval = 300; + tc->seeders = -1; + tc->leechers = -1; + + tc->status = TC_STATUS_IDLE; ++ tc->lastAttempt = TC_ATTEMPT_NOREACH; + tc->size = 1024; + tc->buf = malloc( tc->size ); + +@@ -84,12 +91,22 @@ static int shouldConnect( tr_tracker_t * + { + uint64_t now = tr_date(); + +- /* In any case, always wait 5 seconds between two requests */ +- if( now < tc->dateTry + 5000 ) ++ /* Unreachable tracker, try 10 seconds before trying again */ ++ if( tc->lastAttempt == TC_ATTEMPT_NOREACH && ++ now < tc->dateTry + 10000 ) + { + return 0; + } + ++ /* The tracker rejected us (like 4XX code, unauthorized IP...), ++ don't hammer it - we'll probably get the same answer next time ++ anyway */ ++ if( tc->lastAttempt == TC_ATTEMPT_ERROR && ++ now < tc->dateTry + 1000 * tc->interval ) ++ { ++ return 0; ++ } ++ + /* Do we need to send an event? */ + if( tc->started || tc->completed || tc->stopped || 0 < tc->newPort ) + { +@@ -310,6 +327,8 @@ static void recvAnswer( tr_tracker_t * t + int i; + benc_val_t beAll; + benc_val_t * bePeers, * beFoo; ++ uint8_t * body; ++ int bodylen; + + if( tc->pos == tc->size ) + { +@@ -338,34 +357,70 @@ static void recvAnswer( tr_tracker_t * t + tc->status = TC_STATUS_IDLE; + tc->dateTry = tr_date(); + +- if( tc->pos < 1 ) ++ if( tc->pos < 12 || ( 0 != memcmp( tc->buf, "HTTP/1.0 ", 9 ) && ++ 0 != memcmp( tc->buf, "HTTP/1.1 ", 9 ) ) ) + { +- /* We got nothing */ ++ /* We don't have a complete HTTP status line */ ++ tr_inf( "Tracker: incomplete HTTP status line" ); ++ tc->lastAttempt = TC_ATTEMPT_NOREACH; + return; + } + ++ if( '2' != tc->buf[9] ) ++ { ++ /* we didn't get a 2xx status code */ ++ tr_err( "Tracker: invalid HTTP status code: %c%c%c", ++ tc->buf[9], tc->buf[10], tc->buf[11] ); ++ tc->lastAttempt = TC_ATTEMPT_ERROR; ++ return; ++ } ++ ++ /* find the end of the http headers */ ++ body = tr_memmem( tc->buf, tc->pos, "\015\012\015\012", 4 ); ++ if( NULL != body ) ++ { ++ body += 4; ++ } ++ /* hooray for trackers that violate the HTTP spec */ ++ else if( NULL != ( body = tr_memmem( tc->buf, tc->pos, "\015\015", 2 ) ) || ++ NULL != ( body = tr_memmem( tc->buf, tc->pos, "\012\012", 2 ) ) ) ++ { ++ body += 2; ++ } ++ else ++ { ++ tr_err( "Tracker: could not find end of HTTP headers" ); ++ tc->lastAttempt = TC_ATTEMPT_NOREACH; ++ return; ++ } ++ bodylen = tc->pos - (body - tc->buf); ++ + /* Find the beginning of the dictionary */ +- for( i = 0; i < tc->pos - 18; i++ ) ++ for( i = 0; i < bodylen; i++ ) + { +- /* Hem */ +- if( !memcmp( &tc->buf[i], "d8:interval", 11 ) || +- !memcmp( &tc->buf[i], "d8:complete", 11 ) || +- !memcmp( &tc->buf[i], "d14:failure reason", 18 ) ) ++ if( body[i] == 'd' ) + { ++ /* This must be it */ + break; + } + } + +- if( i >= tc->pos - 18 ) ++ if( i >= bodylen ) + { ++ if( tc->stopped || 0 < tc->newPort ) ++ { ++ tc->lastAttempt = TC_ATTEMPT_OK; ++ goto nodict; ++ } + tr_err( "Tracker: no dictionary in answer" ); +- // printf( "%s\n", tc->buf ); ++ tc->lastAttempt = TC_ATTEMPT_ERROR; + return; + } + +- if( tr_bencLoad( &tc->buf[i], &beAll, NULL ) ) ++ if( tr_bencLoad( &body[i], &beAll, NULL ) ) + { + tr_err( "Tracker: error parsing bencoded data" ); ++ tc->lastAttempt = TC_ATTEMPT_ERROR; + return; + } + +@@ -377,10 +432,12 @@ static void recvAnswer( tr_tracker_t * t + tor->status |= TR_TRACKER_ERROR; + snprintf( tor->error, sizeof( tor->error ), + "%s", bePeers->val.s.s ); ++ tc->lastAttempt = TC_ATTEMPT_ERROR; + goto cleanup; + } + + tor->status &= ~TR_TRACKER_ERROR; ++ tc->lastAttempt = TC_ATTEMPT_OK; + + if( !tc->interval ) + { +@@ -417,6 +474,10 @@ static void recvAnswer( tr_tracker_t * t + + if( !( bePeers = tr_bencDictFind( &beAll, "peers" ) ) ) + { ++ if( tc->stopped || 0 < tc->newPort ) ++ { ++ goto nodict; ++ } + tr_err( "Tracker: no \"peers\" field" ); + goto cleanup; + } +@@ -477,6 +538,7 @@ static void recvAnswer( tr_tracker_t * t + } + } + ++nodict: + /* Success */ + tc->started = 0; + tc->completed = 0; Index: patches/patch-libtransmission_utils_c =================================================================== RCS file: patches/patch-libtransmission_utils_c diff -N patches/patch-libtransmission_utils_c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-libtransmission_utils_c 26 Apr 2006 21:36:57 -0000 @@ -0,0 +1,37 @@ +$OpenBSD$ +--- libtransmission/utils.c.orig Sat Feb 11 17:37:11 2006 ++++ libtransmission/utils.c Wed Apr 26 23:18:43 2006 +@@ -61,3 +61,33 @@ int tr_rand( int sup ) + } + return rand() % sup; + } ++ ++void * tr_memmem( const void *vbig, size_t big_len, ++ const void *vlittle, size_t little_len ) ++{ ++ const char *big = vbig; ++ const char *little = vlittle; ++ size_t ii, jj; ++ ++ if( 0 == big_len || 0 == little_len ) ++ { ++ return NULL; ++ } ++ ++ for( ii = 0; ii + little_len <= big_len; ii++ ) ++ { ++ for( jj = 0; jj < little_len; jj++ ) ++ { ++ if( big[ii + jj] != little[jj] ) ++ { ++ break; ++ } ++ } ++ if( jj == little_len ) ++ { ++ return (char*)big + ii; ++ } ++ } ++ ++ return NULL; ++} Index: patches/patch-libtransmission_utils_h =================================================================== RCS file: patches/patch-libtransmission_utils_h diff -N patches/patch-libtransmission_utils_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-libtransmission_utils_h 26 Apr 2006 21:36:57 -0000 @@ -0,0 +1,12 @@ +$OpenBSD$ +--- libtransmission/utils.h.orig Sat Feb 11 17:37:11 2006 ++++ libtransmission/utils.h Wed Apr 26 23:18:43 2006 +@@ -33,6 +33,8 @@ void tr_msg ( int level, char * msg, .. + + int tr_rand ( int ); + ++void * tr_memmem( const void *, size_t, const void *, size_t ); ++ + /*********************************************************************** + * tr_date + *********************************************************************** -- Christian "naddy" Weisgerber [EMAIL PROTECTED]