diff --git a/libtransmission/handshake.c b/libtransmission/handshake.c index 2cc4ba25b..b7c25129d 100644 --- a/libtransmission/handshake.c +++ b/libtransmission/handshake.c @@ -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 ); } diff --git a/libtransmission/handshake.h b/libtransmission/handshake.h index 7231fc8f0..51f5bcdff 100644 --- a/libtransmission/handshake.h +++ b/libtransmission/handshake.h @@ -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, diff --git a/libtransmission/peer-mgr-private.h b/libtransmission/peer-mgr-private.h index 6269b8360..8ca7de3d8 100644 --- a/libtransmission/peer-mgr-private.h +++ b/libtransmission/peer-mgr-private.h @@ -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; diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c index 30569514d..d04371a2e 100644 --- a/libtransmission/peer-mgr.c +++ b/libtransmission/peer-mgr.c @@ -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 ); diff --git a/libtransmission/peer-msgs.c b/libtransmission/peer-msgs.c index e4ecc7bbb..51c23c860 100644 --- a/libtransmission/peer-msgs.c +++ b/libtransmission/peer-msgs.c @@ -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 ) {