mirror of
https://github.com/transmission/transmission
synced 2024-12-25 17:17:31 +00:00
#890: be smarter about noticing seeds from tracker & pex
This commit is contained in:
parent
1ae1607025
commit
08b27749ba
6 changed files with 83 additions and 78 deletions
|
@ -98,12 +98,6 @@ enum
|
|||
/* number of unchoked peers per torrent */
|
||||
MAX_UNCHOKED_PEERS = 12,
|
||||
|
||||
/* corresponds to ut_pex's added.f flags */
|
||||
ADDED_F_ENCRYPTION_FLAG = 1,
|
||||
|
||||
/* corresponds to ut_pex's added.f flags */
|
||||
ADDED_F_SEED_FLAG = 2,
|
||||
|
||||
/* number of bad pieces a peer is allowed to send before we ban them */
|
||||
MAX_BAD_PIECES_PER_PEER = 3,
|
||||
|
||||
|
@ -1168,30 +1162,24 @@ tr_peerMgrAddPex( tr_peerMgr * manager,
|
|||
managerUnlock( manager );
|
||||
}
|
||||
|
||||
void
|
||||
tr_peerMgrAddPeers( tr_peerMgr * manager,
|
||||
const uint8_t * torrentHash,
|
||||
uint8_t from,
|
||||
const uint8_t * peerCompact,
|
||||
int peerCount )
|
||||
tr_pex *
|
||||
tr_peerMgrCompactToPex( const void * compact,
|
||||
size_t compactLen,
|
||||
const char * added_f,
|
||||
size_t * pexCount )
|
||||
{
|
||||
int i;
|
||||
const uint8_t * walk = peerCompact;
|
||||
Torrent * t;
|
||||
|
||||
managerLock( manager );
|
||||
|
||||
t = getExistingTorrent( manager, torrentHash );
|
||||
for( i=0; t!=NULL && i<peerCount; ++i )
|
||||
{
|
||||
struct in_addr addr;
|
||||
uint16_t port;
|
||||
memcpy( &addr, walk, 4 ); walk += 4;
|
||||
memcpy( &port, walk, 2 ); walk += 2;
|
||||
maybeEnsureAtomExists( t, &addr, port, 0, from );
|
||||
size_t i;
|
||||
size_t n = compactLen / 6;
|
||||
const uint8_t * walk = compact;
|
||||
tr_pex * pex = tr_new0( tr_pex, n );
|
||||
for( i=0; i<n; ++i ) {
|
||||
memcpy( &pex[i].in_addr, walk, 4 ); walk += 4;
|
||||
memcpy( &pex[i].port, walk, 2 ); walk += 2;
|
||||
if( added_f )
|
||||
pex[i].flags = added_f[i];
|
||||
}
|
||||
|
||||
managerUnlock( manager );
|
||||
*pexCount = n;
|
||||
return pex;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,6 +27,15 @@ struct tr_peer_stat;
|
|||
struct tr_torrent;
|
||||
typedef struct tr_peerMgr tr_peerMgr;
|
||||
|
||||
enum
|
||||
{
|
||||
/* corresponds to ut_pex's added.f flags */
|
||||
ADDED_F_ENCRYPTION_FLAG = 1,
|
||||
|
||||
/* corresponds to ut_pex's added.f flags */
|
||||
ADDED_F_SEED_FLAG = 2,
|
||||
};
|
||||
|
||||
typedef struct tr_pex
|
||||
{
|
||||
struct in_addr in_addr;
|
||||
|
@ -50,12 +59,11 @@ void tr_peerMgrAddIncoming( tr_peerMgr * manager,
|
|||
uint16_t port,
|
||||
int socket );
|
||||
|
||||
void tr_peerMgrAddPeers( tr_peerMgr * manager,
|
||||
const uint8_t * torrentHash,
|
||||
uint8_t from,
|
||||
const uint8_t * peerCompact,
|
||||
int peerCount );
|
||||
|
||||
tr_pex * tr_peerMgrCompactToPex( const void * compact,
|
||||
size_t compactLen,
|
||||
const char * added_f,
|
||||
size_t * pexCount );
|
||||
|
||||
void tr_peerMgrAddPex( tr_peerMgr * manager,
|
||||
const uint8_t * torrentHash,
|
||||
uint8_t from,
|
||||
|
|
|
@ -941,21 +941,23 @@ parseUtPex( tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf )
|
|||
{
|
||||
int loaded = 0;
|
||||
uint8_t * tmp = tr_new( uint8_t, msglen );
|
||||
tr_benc val, *sub;
|
||||
tr_benc val, *added;
|
||||
const tr_torrent * tor = msgs->torrent;
|
||||
tr_peerIoReadBytes( msgs->io, inbuf, tmp, msglen );
|
||||
|
||||
if( tr_torrentAllowsPex( tor )
|
||||
&& (( loaded = !tr_bencLoad( tmp, msglen, &val, NULL )))
|
||||
&& (( sub = tr_bencDictFindType( &val, "added", TYPE_STR ))))
|
||||
&& (( added = tr_bencDictFindType( &val, "added", TYPE_STR ))))
|
||||
{
|
||||
const int n = sub->val.s.i / 6 ;
|
||||
if( n )
|
||||
tr_tordbg( tor, "Got %d peers from peer exchange", n );
|
||||
tr_peerMgrAddPeers( msgs->handle->peerMgr,
|
||||
tor->info.hash,
|
||||
TR_PEER_FROM_PEX,
|
||||
(uint8_t*)sub->val.s.s, n );
|
||||
const char * added_f = NULL;
|
||||
tr_pex * pex;
|
||||
size_t i, n;
|
||||
tr_bencDictFindStr( &val, "added.f", &added_f );
|
||||
pex = tr_peerMgrCompactToPex( added->val.s.s, added->val.s.i, added_f, &n );
|
||||
for( i=0; i<n; ++i )
|
||||
tr_peerMgrAddPex( msgs->handle->peerMgr, tor->info.hash,
|
||||
TR_PEER_FROM_PEX, pex+i );
|
||||
tr_free( pex );
|
||||
}
|
||||
|
||||
if( loaded )
|
||||
|
@ -1797,7 +1799,7 @@ sendPex( tr_peermsgs * msgs )
|
|||
tr_pex * newPex = NULL;
|
||||
const int newCount = tr_peerMgrGetPeers( msgs->handle->peerMgr, msgs->torrent->info.hash, &newPex );
|
||||
PexDiffs diffs;
|
||||
tr_benc val, *added, *dropped, *flags;
|
||||
tr_benc val, *added, *dropped;
|
||||
uint8_t *tmp, *walk;
|
||||
char * benc;
|
||||
int bencLen;
|
||||
|
@ -1834,12 +1836,11 @@ sendPex( tr_peermsgs * msgs )
|
|||
tr_bencInitStr( added, tmp, walk-tmp, FALSE );
|
||||
|
||||
/* "added.f" */
|
||||
flags = tr_bencDictAdd( &val, "added.f" );
|
||||
tmp = walk = tr_new( uint8_t, diffs.addedCount );
|
||||
for( i=0; i<diffs.addedCount; ++i )
|
||||
*walk++ = diffs.added[i].flags;
|
||||
assert( ( walk - tmp ) == diffs.addedCount );
|
||||
tr_bencInitStr( flags, tmp, walk-tmp, FALSE );
|
||||
tr_bencDictAddRaw( &val, "added.f", tmp, walk-tmp );
|
||||
|
||||
/* "dropped" */
|
||||
dropped = tr_bencDictAdd( &val, "dropped" );
|
||||
|
|
|
@ -152,13 +152,26 @@ onTrackerResponse( void * tracker UNUSED, void * vevent, void * user_data )
|
|||
|
||||
switch( event->messageType )
|
||||
{
|
||||
case TR_TRACKER_PEERS:
|
||||
tr_peerMgrAddPeers( tor->handle->peerMgr,
|
||||
tor->info.hash,
|
||||
TR_PEER_FROM_TRACKER,
|
||||
event->peerCompact,
|
||||
event->peerCount );
|
||||
case TR_TRACKER_PEERS: {
|
||||
size_t i, n;
|
||||
tr_pex * pex = tr_peerMgrCompactToPex( event->compact,
|
||||
event->compactLen,
|
||||
NULL, &n );
|
||||
if( event->allAreSeeds )
|
||||
tr_tordbg( tor, "Got %d seeds from tracker", (int)n );
|
||||
else
|
||||
tr_torinf( tor, _( "Got %d peers from tracker" ), (int)n );
|
||||
|
||||
for( i=0; i<n; ++i ) {
|
||||
if( event->allAreSeeds )
|
||||
pex[i].flags |= ADDED_F_SEED_FLAG;
|
||||
tr_peerMgrAddPex( tor->handle->peerMgr, tor->info.hash,
|
||||
TR_PEER_FROM_TRACKER, pex+i );
|
||||
}
|
||||
|
||||
tr_free( pex );
|
||||
break;
|
||||
}
|
||||
|
||||
case TR_TRACKER_WARNING:
|
||||
tr_torerr( tor, _( "Tracker warning: \"%s\"" ), event->text );
|
||||
|
|
|
@ -221,7 +221,7 @@ findTracker( tr_handle * handle, const uint8_t * hash )
|
|||
**** PUBLISH
|
||||
***/
|
||||
|
||||
static const tr_tracker_event emptyEvent = { 0, NULL, NULL, NULL, 0 };
|
||||
static const tr_tracker_event emptyEvent = { 0, NULL, NULL, NULL, 0, 0 };
|
||||
|
||||
static void
|
||||
publishMessage( tr_tracker * t, const char * msg, int type )
|
||||
|
@ -256,15 +256,15 @@ publishWarning( tr_tracker * t, const char * msg )
|
|||
}
|
||||
|
||||
static void
|
||||
publishNewPeers( tr_tracker * t, int count, uint8_t * peers )
|
||||
publishNewPeers( tr_tracker * t, int allAreSeeds, void * compact, int compactLen )
|
||||
{
|
||||
tr_tracker_event event = emptyEvent;
|
||||
event.hash = t->hash;
|
||||
event.messageType = TR_TRACKER_PEERS;
|
||||
event.peerCount = count;
|
||||
event.peerCompact = peers;
|
||||
tr_ndbg( t->name, "Torrent got %d new peers", count );
|
||||
if( count )
|
||||
event.allAreSeeds = allAreSeeds;
|
||||
event.compact = compact;
|
||||
event.compactLen = compactLen;
|
||||
if( compactLen )
|
||||
tr_publisherPublish( t->publisher, t, &event );
|
||||
}
|
||||
|
||||
|
@ -360,7 +360,7 @@ updateAddresses( tr_tracker * t, const struct evhttp_request * req, int * tryAga
|
|||
|
||||
/* Convert to compact form */
|
||||
static uint8_t *
|
||||
parseOldPeers( tr_benc * bePeers, int * setmePeerCount )
|
||||
parseOldPeers( tr_benc * bePeers, size_t * byteCount )
|
||||
{
|
||||
int i;
|
||||
uint8_t *compact, *walk;
|
||||
|
@ -393,7 +393,7 @@ parseOldPeers( tr_benc * bePeers, int * setmePeerCount )
|
|||
walk += 2;
|
||||
}
|
||||
|
||||
*setmePeerCount = peerCount;
|
||||
*byteCount = peerCount * 6;
|
||||
return compact;
|
||||
}
|
||||
|
||||
|
@ -432,6 +432,7 @@ onTrackerResponse( struct evhttp_request * req, void * vhash )
|
|||
if( bencLoaded && benc.type==TYPE_DICT )
|
||||
{
|
||||
tr_benc * tmp;
|
||||
int incomplete = -1;
|
||||
|
||||
if(( tmp = tr_bencDictFind( &benc, "failure reason" ))) {
|
||||
dbgmsg( t, "got failure message [%s]", tmp->val.s.s );
|
||||
|
@ -460,30 +461,23 @@ onTrackerResponse( struct evhttp_request * req, void * vhash )
|
|||
t->seederCount = tmp->val.i;
|
||||
|
||||
if(( tmp = tr_bencDictFind( &benc, "incomplete" )))
|
||||
t->leecherCount = tmp->val.i;
|
||||
t->leecherCount = incomplete = tmp->val.i;
|
||||
|
||||
if(( tmp = tr_bencDictFind( &benc, "peers" )))
|
||||
{
|
||||
int peerCount = 0;
|
||||
uint8_t * peerCompact = NULL;
|
||||
const int allAreSeeds = incomplete == 0;
|
||||
|
||||
if( tmp->type == TYPE_LIST ) /* original protocol */
|
||||
if( tmp->type == TYPE_STR ) /* "compact" extension */
|
||||
{
|
||||
if( tmp->val.l.count > 0 )
|
||||
peerCompact = parseOldPeers( tmp, &peerCount );
|
||||
publishNewPeers( t, allAreSeeds, tmp->val.s.s, tmp->val.s.i );
|
||||
}
|
||||
else if( tmp->type == TYPE_STR ) /* "compact" extension */
|
||||
else if( tmp->type == TYPE_LIST ) /* original protocol */
|
||||
{
|
||||
if( tmp->val.s.i >= 6 )
|
||||
{
|
||||
peerCount = tmp->val.s.i / 6;
|
||||
peerCompact = tr_new( uint8_t, tmp->val.s.i );
|
||||
memcpy( peerCompact, tmp->val.s.s, tmp->val.s.i );
|
||||
}
|
||||
size_t byteCount = 0;
|
||||
uint8_t * compact = parseOldPeers( tmp, &byteCount );
|
||||
publishNewPeers( t, allAreSeeds, compact, byteCount );
|
||||
tr_free( compact );
|
||||
}
|
||||
|
||||
publishNewPeers( t, peerCount, peerCompact );
|
||||
tr_free( peerCompact );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,8 +54,9 @@ typedef struct
|
|||
const char * text;
|
||||
|
||||
/* for TR_TRACKER_PEERS */
|
||||
const uint8_t * peerCompact;
|
||||
int peerCount;
|
||||
const uint8_t * compact;
|
||||
int compactLen;
|
||||
int allAreSeeds;
|
||||
}
|
||||
tr_tracker_event;
|
||||
|
||||
|
|
Loading…
Reference in a new issue