From 75ffe999d47d41b39b01ed2f091f414a9dd8bb4c Mon Sep 17 00:00:00 2001 From: Jordan Lee <jordan@transmissionbt.com> Date: Sat, 22 Jan 2011 17:45:54 +0000 Subject: [PATCH] (trunk libT) #3933 "announcer.c peer parsing could be simpler" -- fixed. Remove redundant code by using tr_peerMgrCompactToPex() and tr_peerMgrCompact6ToPex() to parse compact ipv4 and ipv6 peer lists. Simplify the old-style benc peer list parsing and fix a bug that returned too few bytes in the old-style peer array. --- libtransmission/announcer.c | 164 +++++++++++++----------------------- libtransmission/announcer.h | 6 +- libtransmission/torrent.c | 14 ++- 3 files changed, 70 insertions(+), 114 deletions(-) diff --git a/libtransmission/announcer.c b/libtransmission/announcer.c index f784ca1a4..fa8a63468 100644 --- a/libtransmission/announcer.c +++ b/libtransmission/announcer.c @@ -21,6 +21,7 @@ #include "announcer.h" #include "crypto.h" #include "net.h" +#include "peer-mgr.h" /* tr_peerMgrCompactToPex() */ #include "ptrarray.h" #include "session.h" #include "tr-dht.h" @@ -631,87 +632,82 @@ getSeedProbability( int seeds, int leechers ) return -1; /* unknown */ } -static int -publishNewPeers( tr_tier * tier, int seeds, int leechers, - const void * compact, int compactLen ) +static void +publishPeersPex( tr_tier * tier, int seeds, int leechers, + const tr_pex * pex, int n ) { tr_tracker_event e = emptyEvent; e.messageType = TR_TRACKER_PEERS; e.seedProbability = getSeedProbability( seeds, leechers ); - e.compact = compact; - e.compactLen = compactLen; + e.pex = pex; + e.pexCount = n; if( tier->tor->tiers->callback != NULL ) tier->tor->tiers->callback( tier->tor, &e, NULL ); - - return compactLen / 6; } -static int -publishNewPeersCompact( tr_tier * tier, int seeds, int leechers, +static size_t +publishPeersCompact( tr_tier * tier, int seeds, int leechers, const void * compact, int compactLen ) { - int i; - const uint8_t *compactWalk; - uint8_t *array, *walk; - const int peerCount = compactLen / 6; - const int arrayLen = peerCount * ( sizeof( tr_address ) + 2 ); - tr_address addr; - tr_port port; - - addr.type = TR_AF_INET; - memset( &addr.addr, 0, sizeof( addr.addr ) ); - array = tr_new( uint8_t, arrayLen ); - for ( i=0, walk=array, compactWalk=compact ; i<peerCount ; ++i ) - { - memcpy( &addr.addr.addr4, compactWalk, 4 ); - memcpy( &port, compactWalk + 4, 2 ); - - memcpy( walk, &addr, sizeof( addr ) ); - memcpy( walk + sizeof( addr ), &port, 2 ); - - walk += sizeof( tr_address ) + 2; - compactWalk += 6; - } - - publishNewPeers( tier, seeds, leechers, array, arrayLen ); + size_t n = 0; + tr_pex * pex = tr_peerMgrCompactToPex( compact, compactLen, NULL, 0, &n ); + publishPeersPex( tier, seeds, leechers, pex, n ); + dbgmsg( tier, "got IPv4 list of %zu peers", n ); + tr_free( pex ); + return n; +} - tr_free( array ); - - return peerCount; +static size_t +publishPeersCompact6( tr_tier * tier, int seeds, int leechers, + const void * compact, int compactLen ) +{ + size_t n = 0; + tr_pex * pex = tr_peerMgrCompact6ToPex( compact, compactLen, NULL, 0, &n ); + dbgmsg( tier, "got IPv6 list of %zu peers", n ); + publishPeersPex( tier, seeds, leechers, pex, n ); + tr_free( pex ); + return n; } -static int -publishNewPeersCompact6( tr_tier * tier, int seeds, int leechers, - const void * compact, int compactLen ) +static size_t +publishPeersDict( tr_tier * tier, int seeds, int leechers, tr_benc * peerList ) { - int i; - const uint8_t *compactWalk; - uint8_t *array, *walk; - const int peerCount = compactLen / 18; - const int arrayLen = peerCount * ( sizeof( tr_address ) + 2 ); - tr_address addr; - tr_port port; - - addr.type = TR_AF_INET6; - memset( &addr.addr, 0, sizeof( addr.addr ) ); - array = tr_new( uint8_t, arrayLen ); - for ( i = 0, walk = array, compactWalk = compact ; i < peerCount ; ++i ) + size_t i; + size_t n; + const size_t len = tr_bencListSize( peerList ); + tr_pex * pex = tr_new0( tr_pex, len ); + + for( i=n=0; i<len; ++i ) { - memcpy( &addr.addr.addr6, compactWalk, 16 ); - memcpy( &port, compactWalk + 16, 2 ); - compactWalk += 18; + int64_t port; + const char * ip; + tr_address addr; + tr_benc * peer = tr_bencListChild( peerList, i ); - memcpy( walk, &addr, sizeof( addr ) ); - memcpy( walk + sizeof( addr ), &port, 2 ); - walk += sizeof( tr_address ) + 2; - } + if( peer == NULL ) + continue; + if( !tr_bencDictFindStr( peer, "ip", &ip ) ) + continue; + if( tr_pton( ip, &addr ) == NULL ) + continue; + if( !tr_bencDictFindInt( peer, "port", &port ) ) + continue; + if( ( port < 0 ) || ( port > USHRT_MAX ) ) + continue; + if( !tr_isValidPeerAddress( &addr, port ) ) + continue; - publishNewPeers( tier, seeds, leechers, array, arrayLen ); - tr_free( array ); + pex[n].addr = addr; + pex[n].port = htons( (uint16_t)port ); + ++n; + } - return peerCount; + dbgmsg( tier, "got benc list of %zu peers", n ); + publishPeersPex( tier, seeds, leechers, pex, n ); + tr_free( pex ); + return n; } static char* @@ -1163,43 +1159,6 @@ compareTiers( const void * va, const void * vb ) return ret; } -static uint8_t * -parseOldPeers( tr_benc * bePeers, size_t * byteCount ) -{ - int i; - uint8_t * array, *walk; - const int peerCount = bePeers->val.l.count; - - assert( tr_bencIsList( bePeers ) ); - - array = tr_new( uint8_t, peerCount * ( sizeof( tr_address ) + 2 ) ); - - for( i = 0, walk = array; i < peerCount; ++i ) - { - const char * s; - int64_t itmp; - tr_address addr; - tr_port port; - tr_benc * peer = &bePeers->val.l.vals[i]; - - if( tr_bencDictFindStr( peer, "ip", &s ) ) - if( tr_pton( s, &addr ) == NULL ) - continue; - - if( !tr_bencDictFindInt( peer, "port", &itmp ) - || itmp < 0 - || itmp > USHRT_MAX ) - continue; - - memcpy( walk, &addr, sizeof( tr_address ) ); - port = htons( (uint16_t)itmp ); - memcpy( walk + sizeof( tr_address ), &port, 2 ); - walk += sizeof( tr_address ) + 2; - } - - *byteCount = peerCount * sizeof( tr_address ) + 2; - return array; -} static tr_bool parseAnnounceResponse( tr_tier * tier, @@ -1292,7 +1251,7 @@ parseAnnounceResponse( tr_tier * tier, /* "compact" extension */ const int seeders = tier->currentTracker->seederCount; const int leechers = tier->currentTracker->leecherCount; - peerCount += publishNewPeersCompact( tier, seeders, leechers, raw, rawlen ); + peerCount += publishPeersCompact( tier, seeders, leechers, raw, rawlen ); gotPeers = TRUE; } else if( tr_bencDictFindList( &benc, "peers", &tmp ) ) @@ -1300,11 +1259,8 @@ parseAnnounceResponse( tr_tier * tier, /* original version of peers */ const int seeders = tier->currentTracker->seederCount; const int leechers = tier->currentTracker->leecherCount; - size_t byteCount = 0; - uint8_t * array = parseOldPeers( tmp, &byteCount ); - peerCount += publishNewPeers( tier, seeders, leechers, array, byteCount ); + peerCount += publishPeersDict( tier, seeders, leechers, tmp ); gotPeers = TRUE; - tr_free( array ); } if( tr_bencDictFindRaw( &benc, "peers6", &raw, &rawlen ) ) @@ -1312,7 +1268,7 @@ parseAnnounceResponse( tr_tier * tier, /* "compact" extension */ const int seeders = tier->currentTracker->seederCount; const int leechers = tier->currentTracker->leecherCount; - peerCount += publishNewPeersCompact6( tier, seeders, leechers, raw, rawlen ); + peerCount += publishPeersCompact6( tier, seeders, leechers, raw, rawlen ); gotPeers = TRUE; } diff --git a/libtransmission/announcer.h b/libtransmission/announcer.h index a051d8bd3..54cc052e5 100644 --- a/libtransmission/announcer.h +++ b/libtransmission/announcer.h @@ -35,6 +35,8 @@ typedef enum } TrackerEventType; +struct tr_pex; + /** @brief Notification object to tell listeners about announce or scrape occurences */ typedef struct { @@ -46,8 +48,8 @@ typedef struct const char * tracker; /* for TR_TRACKER_PEERS */ - const uint8_t * compact; - int compactLen; + const struct tr_pex * pex; + size_t pexCount; /* [0...100] for probability a peer is a seed. calculated by the leecher/seeder ratio */ int8_t seedProbability; diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c index 53642ee06..10b07a6e3 100644 --- a/libtransmission/torrent.c +++ b/libtransmission/torrent.c @@ -493,23 +493,21 @@ onTrackerResponse( tr_torrent * tor, const tr_tracker_event * event, void * unus { case TR_TRACKER_PEERS: { - size_t i, n; + size_t i; const int8_t seedProbability = event->seedProbability; const tr_bool allAreSeeds = seedProbability == 100; - tr_pex * pex = tr_peerMgrArrayToPex( event->compact, - event->compactLen, &n ); + if( allAreSeeds ) - tr_tordbg( tor, "Got %d seeds from tracker", (int)n ); + tr_tordbg( tor, "Got %zu seeds from tracker", event->pexCount ); else - tr_tordbg( tor, "Got %d peers from tracker", (int)n ); + tr_tordbg( tor, "Got %zu peers from tracker", event->pexCount ); - for( i = 0; i < n; ++i ) - tr_peerMgrAddPex( tor, TR_PEER_FROM_TRACKER, pex+i, seedProbability ); + for( i = 0; i < event->pexCount; ++i ) + tr_peerMgrAddPex( tor, TR_PEER_FROM_TRACKER, &event->pex[i], seedProbability ); if( allAreSeeds && tr_torrentIsPrivate( tor ) ) tr_peerMgrMarkAllAsSeeds( tor ); - tr_free( pex ); break; } -- 2.40.0