mirror of
https://github.com/transmission/transmission.git
synced 2026-05-08 09:39:08 +01:00
improved uTorrent handshaking, after talking to #utorrent-dev about minutae...
This commit is contained in:
@@ -104,7 +104,6 @@ extern const char* getPeerId( void ) ;
|
||||
|
||||
struct tr_handshake
|
||||
{
|
||||
unsigned int peerSupportsEncryption : 1;
|
||||
unsigned int havePeerID : 1;
|
||||
unsigned int haveSentBitTorrentHandshake : 1;
|
||||
unsigned int allowUnencryptedPeers : 1;
|
||||
@@ -406,7 +405,6 @@ readYb( tr_handshake * handshake, struct evbuffer * inbuf )
|
||||
|
||||
dbgmsg( handshake, "got a %s handshake", (isEncrypted ? "encrypted" : "plaintext") );
|
||||
|
||||
handshake->peerSupportsEncryption = isEncrypted;
|
||||
tr_peerIoSetEncryption( handshake->io, isEncrypted ? PEER_ENCRYPTION_RC4
|
||||
: PEER_ENCRYPTION_NONE );
|
||||
if( !isEncrypted ) {
|
||||
@@ -1001,7 +999,6 @@ fireDoneFunc( tr_handshake * handshake, int isConnected )
|
||||
handshake->io,
|
||||
isConnected,
|
||||
peer_id,
|
||||
handshake->peerSupportsEncryption,
|
||||
handshake->doneUserData );
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ typedef void (*handshakeDoneCB)(struct tr_handshake * handshake,
|
||||
struct tr_peerIo * io,
|
||||
int isConnected,
|
||||
const uint8_t * peerId,
|
||||
int peerSupportsEncryption,
|
||||
void * userData );
|
||||
|
||||
tr_handshake * tr_handshakeNew( struct tr_peerIo * io,
|
||||
|
||||
@@ -21,15 +21,22 @@ struct tr_bitfield;
|
||||
struct tr_peerIo;
|
||||
struct tr_peermsgs;
|
||||
|
||||
enum
|
||||
{
|
||||
ENCRYPTION_PREFERENCE_UNKNOWN,
|
||||
ENCRYPTION_PREFERENCE_YES,
|
||||
ENCRYPTION_PREFERENCE_NO
|
||||
};
|
||||
|
||||
typedef struct tr_peer
|
||||
{
|
||||
unsigned int peerIsChoked : 1;
|
||||
unsigned int peerIsInterested : 1;
|
||||
unsigned int clientIsChoked : 1;
|
||||
unsigned int clientIsInterested : 1;
|
||||
unsigned int peerSupportsEncryption : 1;
|
||||
unsigned int doPurge : 1;
|
||||
|
||||
uint8_t encryption_preference;
|
||||
uint8_t from;
|
||||
uint16_t port;
|
||||
struct in_addr in_addr;
|
||||
|
||||
@@ -746,7 +746,6 @@ myHandshakeDoneCB( tr_handshake * handshake,
|
||||
tr_peerIo * io,
|
||||
int isConnected,
|
||||
const uint8_t * peer_id,
|
||||
int peerSupportsEncryption,
|
||||
void * vmanager )
|
||||
{
|
||||
int ok = isConnected;
|
||||
@@ -759,7 +758,6 @@ myHandshakeDoneCB( tr_handshake * handshake,
|
||||
|
||||
assert( io != NULL );
|
||||
assert( isConnected==0 || isConnected==1 );
|
||||
assert( peerSupportsEncryption==0 || peerSupportsEncryption==1 );
|
||||
|
||||
ours = tr_ptrArrayRemoveSorted( manager->handshakes,
|
||||
handshake,
|
||||
@@ -807,7 +805,6 @@ myHandshakeDoneCB( tr_handshake * handshake,
|
||||
peer->msgs = tr_peerMsgsNew( t->tor, peer );
|
||||
tr_free( peer->client );
|
||||
peer->client = peer_id ? tr_clientForId( peer_id ) : NULL;
|
||||
peer->peerSupportsEncryption = peerSupportsEncryption ? 1 : 0;
|
||||
peer->msgsTag = tr_peerMsgsSubscribe( peer->msgs, msgsCallbackFunc, t );
|
||||
peer->connectionChangedAt = time( NULL );
|
||||
rechokeSoon( t );
|
||||
@@ -922,6 +919,17 @@ tr_pexCompare( const void * va, const void * vb )
|
||||
|
||||
int tr_pexCompare( const void * a, const void * b );
|
||||
|
||||
static int
|
||||
peerPrefersCrypto( const tr_peer * peer )
|
||||
{
|
||||
if( peer->encryption_preference == ENCRYPTION_PREFERENCE_YES )
|
||||
return TRUE;
|
||||
|
||||
if( peer->encryption_preference == ENCRYPTION_PREFERENCE_NO )
|
||||
return FALSE;
|
||||
|
||||
return tr_peerIoIsEncrypted( peer->io );
|
||||
};
|
||||
|
||||
int
|
||||
tr_peerMgrGetPeers( tr_peerMgr * manager,
|
||||
@@ -943,8 +951,8 @@ tr_peerMgrGetPeers( tr_peerMgr * manager,
|
||||
walk->port = peer->port;
|
||||
|
||||
walk->flags = 0;
|
||||
if( peer->peerSupportsEncryption ) walk->flags |= 1;
|
||||
if( peer->progress >= 1.0 ) walk->flags |= 2;
|
||||
if( peerPrefersCrypto(peer) ) walk->flags |= 1;
|
||||
if( peer->progress >= 1.0 ) walk->flags |= 2;
|
||||
}
|
||||
|
||||
assert( ( walk - pex ) == peerCount );
|
||||
|
||||
@@ -122,9 +122,10 @@ struct tr_peermsgs
|
||||
time_t clientSentPexAt;
|
||||
time_t clientSentAnythingAt;
|
||||
|
||||
unsigned int notListening : 1;
|
||||
unsigned int peerSupportsPex : 1;
|
||||
unsigned int hasSentLtepHandshake : 1;
|
||||
unsigned int notListening : 1;
|
||||
unsigned int peerSupportsPex : 1;
|
||||
unsigned int clientSentLtepHandshake : 1;
|
||||
unsigned int peerSentLtepHandshake : 1;
|
||||
|
||||
tr_bitfield * clientAllowedPieces;
|
||||
tr_bitfield * peerAllowedPieces;
|
||||
@@ -529,17 +530,34 @@ sendLtepHandshake( tr_peermsgs * msgs )
|
||||
benc_val_t val, *m;
|
||||
char * buf;
|
||||
int len;
|
||||
int pex;
|
||||
const char * v = TR_NAME " " USERAGENT_PREFIX;
|
||||
const int port = tr_getPublicPort( msgs->handle );
|
||||
struct evbuffer * outbuf = evbuffer_new( );
|
||||
|
||||
if( msgs->clientSentLtepHandshake )
|
||||
return;
|
||||
|
||||
dbgmsg( msgs, "sending an ltep handshake" );
|
||||
msgs->clientSentLtepHandshake = 1;
|
||||
|
||||
/* decide if we want to advertise pex support */
|
||||
if( msgs->torrent->pexDisabled )
|
||||
pex = 0;
|
||||
else if( msgs->peerSentLtepHandshake )
|
||||
pex = msgs->peerSupportsPex ? 1 : 0;
|
||||
else
|
||||
pex = 1;
|
||||
|
||||
tr_bencInit( &val, TYPE_DICT );
|
||||
tr_bencDictReserve( &val, 3 );
|
||||
tr_bencDictReserve( &val, 4 );
|
||||
tr_bencInitInt( tr_bencDictAdd( &val, "e" ), 1 );
|
||||
m = tr_bencDictAdd( &val, "m" );
|
||||
tr_bencInit( m, TYPE_DICT );
|
||||
tr_bencDictReserve( m, 1 );
|
||||
tr_bencInitInt( tr_bencDictAdd( m, "ut_pex" ), OUR_LTEP_PEX );
|
||||
if( pex ) {
|
||||
tr_bencDictReserve( m, 1 );
|
||||
tr_bencInitInt( tr_bencDictAdd( m, "ut_pex" ), OUR_LTEP_PEX );
|
||||
}
|
||||
if( port > 0 )
|
||||
tr_bencInitInt( tr_bencDictAdd( &val, "p" ), port );
|
||||
tr_bencInitStr( tr_bencDictAdd( &val, "v" ), v, 0, 1 );
|
||||
@@ -551,7 +569,9 @@ sendLtepHandshake( tr_peermsgs * msgs )
|
||||
tr_peerIoWriteBytes ( msgs->io, outbuf, buf, len );
|
||||
|
||||
tr_peerIoWriteBuf( msgs->io, outbuf );
|
||||
msgs->hasSentLtepHandshake = 1;
|
||||
|
||||
dbgmsg( msgs, "here is the ltep handshake we sent:" );
|
||||
tr_bencPrint( &val );
|
||||
|
||||
/* cleanup */
|
||||
tr_bencFree( &val );
|
||||
@@ -567,6 +587,7 @@ parseLtepHandshake( tr_peermsgs * msgs, int len, struct evbuffer * inbuf )
|
||||
uint8_t * tmp = tr_new( uint8_t, len );
|
||||
|
||||
tr_peerIoReadBytes( msgs->io, inbuf, tmp, len );
|
||||
msgs->peerSentLtepHandshake = 1;
|
||||
|
||||
if( tr_bencLoad( tmp, len, &val, NULL ) || val.type!=TYPE_DICT ) {
|
||||
dbgmsg( msgs, "GET extended-handshake, couldn't get dictionary" );
|
||||
@@ -574,6 +595,16 @@ parseLtepHandshake( tr_peermsgs * msgs, int len, struct evbuffer * inbuf )
|
||||
return;
|
||||
}
|
||||
|
||||
dbgmsg( msgs, "here is the ltep handshake we read:" );
|
||||
tr_bencPrint( &val );
|
||||
|
||||
/* does the peer prefer encrypted connections? */
|
||||
sub = tr_bencDictFind( &val, "e" );
|
||||
if( tr_bencIsInt( sub ) )
|
||||
msgs->info->encryption_preference = sub->val.i
|
||||
? ENCRYPTION_PREFERENCE_YES
|
||||
: ENCRYPTION_PREFERENCE_NO;
|
||||
|
||||
/* check supported messages for utorrent pex */
|
||||
sub = tr_bencDictFind( &val, "m" );
|
||||
if( tr_bencIsDict( sub ) ) {
|
||||
@@ -657,8 +688,7 @@ parseLtep( tr_peermsgs * msgs, int msglen, struct evbuffer * inbuf )
|
||||
{
|
||||
dbgmsg( msgs, "got ltep handshake" );
|
||||
parseLtepHandshake( msgs, msglen, inbuf );
|
||||
if( !msgs->hasSentLtepHandshake )
|
||||
sendLtepHandshake( msgs );
|
||||
sendLtepHandshake( msgs );
|
||||
}
|
||||
else if( ltep_msgid == msgs->ut_pex_id )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user