(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.
This commit is contained in:
Jordan Lee 2011-01-22 17:45:54 +00:00
parent 68130d9c4e
commit 75ffe999d4
3 changed files with 72 additions and 116 deletions

View File

@ -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;
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;
}
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 );
tr_free( array );
return peerCount;
}
static int
publishNewPeersCompact6( tr_tier * tier, int seeds, int leechers,
static size_t
publishPeersCompact6( 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 / 18;
const int arrayLen = peerCount * ( sizeof( tr_address ) + 2 );
tr_address addr;
tr_port port;
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;
}
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 )
static size_t
publishPeersDict( tr_tier * tier, int seeds, int leechers, tr_benc * peerList )
{
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;
pex[n].addr = addr;
pex[n].port = htons( (uint16_t)port );
++n;
}
publishNewPeers( tier, seeds, leechers, array, arrayLen );
tr_free( array );
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;
}

View File

@ -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;

View File

@ -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 );
else
tr_tordbg( tor, "Got %d peers from tracker", (int)n );
for( i = 0; i < n; ++i )
tr_peerMgrAddPex( tor, TR_PEER_FROM_TRACKER, pex+i, seedProbability );
if( allAreSeeds )
tr_tordbg( tor, "Got %zu seeds from tracker", event->pexCount );
else
tr_tordbg( tor, "Got %zu peers from tracker", event->pexCount );
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;
}