Changeset 3227


Ignore:
Timestamp:
Sep 28, 2007, 4:40:21 PM (15 years ago)
Author:
charles
Message:

commit the next step of tiennou's fastpeers code.

Location:
trunk/libtransmission
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/handshake.c

    r3203 r3227  
    3737
    3838/* enable fast peers extension protocol */
    39 /* (disabled because it's not fully implemented yet) */
    4039/* #define ENABLE_FASTPEER */
    4140
     
    240239    }
    241240   
    242     HANDSHAKE_SET_FASTEXT ( walk );
     241    HANDSHAKE_SET_FASTEXT( walk );
    243242
    244243    walk += HANDSHAKE_FLAGS_LEN;
     
    331330    assert( !ltep || !azmp );
    332331   
    333          if( ltep ) { tr_peerIoEnableLTEP( handshake->io, 1 ); dbgmsg(handshake,"using ltep" ); }
    334     else if( azmp ) { tr_peerIoEnableAZMP( handshake->io, 1 ); dbgmsg(handshake,"using azmp" ); }
    335     else if( fpex ) { tr_peerIoEnableFEXT( handshake->io, 1 ); dbgmsg(handshake,"using fext" ); }
    336     else            { dbgmsg(handshake,"using no extensions" ); }
    337 
     332    if( ltep ) { tr_peerIoEnableLTEP( handshake->io, 1 ); dbgmsg(handshake,"using ltep" ); }
     333    if( azmp ) { tr_peerIoEnableAZMP( handshake->io, 1 ); dbgmsg(handshake,"using azmp" ); }
     334    if( fpex ) { tr_peerIoEnableFEXT( handshake->io, 1 ); dbgmsg(handshake,"using fext" ); }
     335       
    338336    return HANDSHAKE_OK;
    339337}
     
    699697    assert( !ltep || !azmp );
    700698   
    701          if( ltep ) { tr_peerIoEnableLTEP( handshake->io, 1 ); dbgmsg(handshake,"using ltep" ); }
    702     else if( azmp ) { tr_peerIoEnableAZMP( handshake->io, 1 ); dbgmsg(handshake,"using azmp" ); }
    703     else if( fpex ) { tr_peerIoEnableFEXT( handshake->io, 1 ); dbgmsg(handshake,"using fext" ); }
    704     else            { dbgmsg(handshake,"using no extensions" ); }
     699    if( ltep ) { tr_peerIoEnableLTEP( handshake->io, 1 ); dbgmsg(handshake,"using ltep" ); }
     700    if( azmp ) { tr_peerIoEnableAZMP( handshake->io, 1 ); dbgmsg(handshake,"using azmp" ); }
     701    if( fpex ) { tr_peerIoEnableFEXT( handshake->io, 1 ); dbgmsg(handshake,"using fext" ); }
    705702   
    706703    /**
     
    946943            ext = 0;
    947944
    948         /* FIXME: do we do something with fast peers here? */
    949 
    950945        msg = buildHandshakeMessage( handshake, ext, &msgSize );
    951946        tr_peerIoWriteBytes( handshake->io, outbuf, msg, msgSize );
     
    10301025{
    10311026    tr_handshake * handshake = (tr_handshake *) arg;
    1032 dbgmsg( handshake, "handshake evbuffer got an error!!!!!" );
    10331027
    10341028    /* if the error happened while we were sending a public key, we might
     
    10391033        && ( !tr_peerIoReconnect( handshake->io ) ) )
    10401034    {
     1035        dbgmsg( handshake, "handshake failed, trying plaintext..." );
    10411036        int msgSize;
    10421037        uint8_t * msg = buildHandshakeMessage( handshake, HANDSHAKE_EXTPREF_LTEP_PREFER, &msgSize );
     
    10471042    else
    10481043    {
    1049 dbgmsg( handshake, "handshake evbuffer got an error!!!!!" );
     1044        dbgmsg( handshake, "handshake evbuffer got an error!!!!!" );
    10501045        tr_handshakeDone( handshake, FALSE );
    10511046    }
  • trunk/libtransmission/peer-io.c

    r3184 r3227  
    3434    unsigned int extendedProtocolSupported : 1;
    3535    unsigned int fastPeersSupported : 1;
    36     /* unsigned int DHTSupported : 1; */
    3736};
    3837
  • trunk/libtransmission/peer-mgr.c

    r3225 r3227  
    2020#include "clients.h"
    2121#include "completion.h"
     22#include "crypto.h"
    2223#include "handshake.h"
    2324#include "net.h"
     
    275276**/
    276277
     278struct tr_bitfield *
     279tr_peerMgrGenerateAllowedSet( const uint32_t         setCount,
     280                              const uint32_t         pieceCount,
     281                              const uint8_t          infohash[20],
     282                              const struct in_addr * ip )
     283{
     284    /* This has been checked against the spec example implementation. Feeding it with :
     285    setCount = 9, pieceCount = 1313, infohash = Oxaa,0xaa,...0xaa, ip = 80.4.4.200
     286generate :
     287    1059, 431, 808, 1217, 287, 376, 1188, 353, 508
     288    but since we're storing in a bitfield, it won't be in this order... */
     289    /* TODO : We should translate link-local IPv4 adresses to external IP,
     290     * so that being on same local network gives us the same allowed pieces */
     291   
     292    printf( "%d piece allowed fast set for torrent with %d pieces and hex infohash\n", setCount, pieceCount );
     293    printf( "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x for node with IP %s:\n",
     294            infohash[0], infohash[1], infohash[2], infohash[3], infohash[4], infohash[5], infohash[6], infohash[7], infohash[8], infohash[9],
     295            infohash[10], infohash[11], infohash[12], infohash[13], infohash[14], infohash[15], infohash[16], infohash[7], infohash[18], infohash[19],
     296            inet_ntoa( *ip ) );
     297   
     298    uint8_t *seed = malloc(4 + SHA_DIGEST_LENGTH);
     299    char buf[4];
     300    uint32_t allowedPieceCount = 0;
     301    tr_bitfield_t * ret;
     302   
     303    ret = tr_bitfieldNew( pieceCount );
     304   
     305    /* We need a seed based on most significant bytes of peer address
     306        concatenated with torrent's infohash */
     307    *(uint32_t*)buf = ntohl( htonl(ip->s_addr) & 0xffffff00 );
     308   
     309    memcpy( seed, &buf, 4 );
     310    memcpy( seed + 4, infohash, SHA_DIGEST_LENGTH );
     311   
     312    tr_sha1( seed, seed, 4 + SHA_DIGEST_LENGTH, NULL );
     313   
     314    while ( allowedPieceCount < setCount )
     315    {
     316        int i;
     317        for ( i = 0 ; i < 5 && allowedPieceCount < setCount ; i++ )
     318        {
     319            /* We generate indices from 4-byte chunks of the seed */
     320            uint32_t j = i * 4;
     321            uint32_t y = ntohl( *(uint32_t*)(seed + j) );
     322            uint32_t index = y % pieceCount;
     323           
     324            if ( !tr_bitfieldHas( ret, index ) )
     325            {
     326                tr_bitfieldAdd( ret, index );
     327                allowedPieceCount++;
     328            }
     329        }
     330        /* We randomize the seed, in case we need to iterate more */
     331        tr_sha1( seed, seed, SHA_DIGEST_LENGTH, NULL );
     332    }
     333    tr_free( seed );
     334   
     335    return ret;
     336}
     337
    277338tr_peerMgr*
    278339tr_peerMgrNew( tr_handle * handle )
     
    323384    uint32_t piece;
    324385    uint32_t peerCount;
     386    uint32_t fastAllowed;
    325387};
    326388
     
    338400    if (a->peerCount != b->peerCount)
    339401        return a->peerCount < b->peerCount ? -1 : 1;
     402   
     403    /* otherwise if one *might be* fastallowed to us */
     404    if (a->fastAllowed != b->fastAllowed)
     405        return a->fastAllowed < b->fastAllowed ? -1 : 1;
    340406
    341407    /* otherwise go with the earlier piece */
     
    389455            setme->priority = inf->pieces[piece].priority;
    390456            setme->peerCount = 0;
     457            /* FIXME */
     458//            setme->fastAllowed = tr_bitfieldHas( t->tor->allowedList, i);
    391459
    392460            for( k=0; k<peerCount; ++k ) {
     
    11181186    tr_peer ** peers = getConnectedPeers( t, &peerCount );
    11191187    ChokeData * choke = tr_new0( ChokeData, peerCount );
    1120 
     1188   
    11211189    /* sort the peers by preference and rate */
    11221190    for( i=0; i<peerCount; ++i )
  • trunk/libtransmission/peer-mgr.h

    r3197 r3227  
    9797                                           int               * setmeCount );
    9898
    99 
     99                             
     100struct tr_bitfield *
     101tr_peerMgrGenerateAllowedSet( const uint32_t         setCount,
     102                              const uint32_t         pieceCount,
     103                              const uint8_t          infohash[20],
     104                              const struct in_addr * ip );
    100105
    101106
  • trunk/libtransmission/peer-msgs.c

    r3226 r3227  
    3838***
    3939**/
     40
     41#define MAX_ALLOWED_SET_COUNT   10 /* number of pieces generated for allow-fast,
     42                                    threshold for fast-allowing others */
    4043
    4144enum
     
    123126    unsigned int peerSupportsPex       : 1;
    124127    unsigned int hasSentLtepHandshake  : 1;
    125 
     128   
     129    tr_bitfield * clientAllowedPieces;
     130    tr_bitfield * peerAllowedPieces;
     131   
    126132    uint8_t state;
    127133
     
    300306    if( msgs->info->peerIsChoked != choke )
    301307    {
    302         msgs->info->peerIsChoked = choke ? 1 : 0;
    303 
     308        msgs->info->peerIsChoked = choke;
     309        tr_list * walk;
     310       
    304311        if( choke )
    305             tr_list_free( &msgs->peerAskedFor, tr_free );
     312            for( walk = msgs->peerAskedFor; walk != NULL; )
     313            {
     314                tr_list * next = walk->next;
     315                /* We shouldn't reject a peer's fast allowed requests at choke */
     316                struct peer_request *req = walk->data;
     317                if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index ) )
     318                {
     319                    tr_list_remove_data( &msgs->peerAskedFor, req );
     320                    tr_free( req );
     321                }
     322                walk = next;
     323            }
    306324
    307325        dbgmsg( msgs, "sending a %s message", (choke ? "CHOKE" : "UNCHOKE") );
     
    360378    updateInterest( msgs );
    361379}
     380#if 0
     381static void
     382sendFastSuggest( tr_peermsgs * msgs,
     383                 uint32_t      pieceIndex )
     384{
     385    dbgmsg( msgs, "w00t SUGGESTing them piece #%d", pieceIndex );
     386    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
     387    tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_SUGGEST );
     388    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     389   
     390    updateInterest( msgs );
     391}
     392#endif
     393static void
     394sendFastHave( tr_peermsgs * msgs,
     395              int           all)
     396{
     397    dbgmsg( msgs, "w00t telling them we %s pieces", (all ? "HAVE_ALL" : "HAVE_NONE" ) );
     398    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) );
     399    tr_peerIoWriteUint8( msgs->io, msgs->outMessages, ( all ? BT_HAVE_ALL : BT_HAVE_NONE ) );
     400   
     401    updateInterest( msgs );
     402}
     403
     404static void
     405sendFastReject( tr_peermsgs * msgs,
     406                uint32_t      pieceIndex,
     407                uint32_t      offset,
     408                uint32_t      length )
     409{
     410    assert( msgs != NULL );
     411    assert( length > 0 );
     412   
     413    /* reject the request */
     414    const uint32_t len = sizeof(uint8_t) + 3 * sizeof(uint32_t);
     415    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, len );
     416    tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_REJECT );
     417    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     418    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, offset );
     419    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, length );
     420}
     421
     422static void
     423sendFastAllowed( tr_peermsgs * msgs,
     424                 uint32_t      pieceIndex)
     425{
     426    dbgmsg( msgs, "w00t telling them we ALLOW_FAST piece #%d", pieceIndex );
     427    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, sizeof(uint8_t) + sizeof(uint32_t) );
     428    tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_ALLOWED_FAST );
     429    tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     430}
     431
     432
     433
     434static void
     435sendFastAllowedSet( tr_peermsgs * msgs )
     436{
     437    int i = 0;
     438    while (i <= msgs->torrent->info.pieceCount )
     439    {
     440        if ( tr_bitfieldHas( msgs->peerAllowedPieces, i) )
     441            sendFastAllowed( msgs, i );
     442        i++;
     443    }
     444}
     445
    362446
    363447/**
     
    633717            assert( msglen == 0 );
    634718            msgs->info->clientIsChoked = 1;
    635             tr_list_free( &msgs->peerAskedFor, tr_free );
     719           
     720            tr_list * walk;
     721            for( walk = msgs->peerAskedFor; walk != NULL; )
     722            {
     723                tr_list * next = walk->next;
     724                /* We shouldn't reject a peer's fast allowed requests at choke */
     725                struct peer_request *req = walk->data;
     726                if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index ) )
     727                {
     728                    tr_list_remove_data( &msgs->peerAskedFor, req );
     729                    tr_free( req );
     730                }
     731                walk = next;
     732            }
    636733            tr_list_free( &msgs->clientAskedFor, tr_free );
    637734            break;
     
    686783            tr_peerIoReadUint32( msgs->io, inbuf, &req->offset );
    687784            tr_peerIoReadUint32( msgs->io, inbuf, &req->length );
    688             if( !msgs->info->peerIsChoked && requestIsValid( msgs, req ) )
    689                 tr_list_append( &msgs->peerAskedFor, req );
    690             else
     785           
     786            if ( !requestIsValid( msgs, req ) )
     787            {
     788                dbgmsg( msgs, "BT_REQUEST: invalid request, ignoring" );
    691789                tr_free( req );
     790                break;
     791            }
     792            /*
     793                If we're not choking him -> continue
     794                If we're choking him
     795                    it doesn't support FPE -> He's deaf, reCHOKE and bail...
     796                    it support FPE
     797                        If the asked piece is not allowed
     798                            OR he's above our threshold
     799                            OR we don't have the requested piece -> Reject
     800                        Else
     801                        Asked piece allowed AND he's below our threshold -> continue...
     802             */
     803   
     804
     805            if ( msgs->info->peerIsChoked )
     806            {
     807                if ( !tr_peerIoSupportsFEXT( msgs->io ) )
     808                {
     809                    dbgmsg( msgs, "BT_REQUEST: peer is choked, ignoring" );
     810                    /* Didn't he get it? */
     811                    tr_peerMsgsSetChoke( msgs, 1 );
     812                    tr_free( req );
     813                    break;
     814                }
     815                else
     816                {
     817                    if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index )
     818                         || ( msgs->info->progress * (float)msgs->torrent->info.pieceCount) >= MAX_ALLOWED_SET_COUNT
     819                         || !tr_cpPieceIsComplete( msgs->torrent->completion, req->index ) )
     820                    {
     821                        dbgmsg( msgs, "BT_REQUEST: peer requests an un-fastallowed piece" );
     822                        sendFastReject( msgs, req->index, req->offset, req->length );
     823                        tr_free( req );
     824                        break;
     825                    }
     826                    dbgmsg( msgs, "BT_REQUEST: fast allowed piece, accepting request" );
     827                }   
     828            }
     829           
     830            tr_list_append( &msgs->peerAskedFor, req );
    692831            break;
    693832        }
     
    732871           
    733872        case BT_HAVE_ALL: {
    734             /* tiennou TODO */
     873            assert( msglen == 0 );
     874            dbgmsg( msgs, "peer sent us a BT_HAVE_ALL" );
     875            memset( msgs->info->have->bits, 1, msgs->info->have->len );
     876            msgs->info->progress = tr_bitfieldCountTrueBits( msgs->info->have ) / (float)msgs->torrent->info.pieceCount;
     877            dbgmsg( msgs, "after the HAVE_ALL message, peer progress is %f", msgs->info->progress );
     878            updateInterest( msgs );
     879            firePeerProgress( msgs );
    735880            break;
    736881        }
    737882           
    738883        case BT_HAVE_NONE: {
    739             /* tiennou TODO */
     884            assert( msglen == 0 );
     885            dbgmsg( msgs, "peer sent us a BT_HAVE_NONE" );
     886            memset( msgs->info->have->bits, 1, msgs->info->have->len );
     887            msgs->info->progress = tr_bitfieldCountTrueBits( msgs->info->have ) / (float)msgs->torrent->info.pieceCount;
     888            dbgmsg( msgs, "after the HAVE_NONE message, peer progress is %f", msgs->info->progress );
     889            updateInterest( msgs );
     890            firePeerProgress( msgs );
    740891            break;
    741892        }
    742893           
    743894        case BT_REJECT: {
    744             /* tiennou TODO */
     895            struct peer_request req;
     896            tr_list * node;
     897            assert( msglen == 12 );
     898            dbgmsg( msgs, "peer sent us a BT_REJECT" );
     899            tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
     900            tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
     901            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
     902            node = tr_list_find( msgs->peerAskedFor, &req, peer_request_compare );
     903            if( node != NULL ) {
     904                void * data = node->data;
     905                tr_list_remove_data( &msgs->peerAskedFor, data );
     906                tr_free( data );
     907                dbgmsg( msgs, "found the req that peer has rejected... cancelled." );
     908            }
    745909            break;
    746910        }
    747911           
    748912        case BT_ALLOWED_FAST: {
    749             /* tiennou TODO */
     913            assert( msglen == 4 );
     914            dbgmsg( msgs, "peer sent us a BT_ALLOWED_FAST" );
     915            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
     916            tr_bitfieldAdd( msgs->clientAllowedPieces, ui32 );
    750917            break;
    751918        }
     
    12841451    msgs->outBlock = evbuffer_new( );
    12851452    msgs->inBlock = evbuffer_new( );
    1286 
     1453    msgs->peerAllowedPieces = NULL;
     1454    msgs->clientAllowedPieces = NULL;
     1455   
     1456    if ( tr_peerIoSupportsFEXT( msgs->io ) )
     1457    {
     1458        /* This peer is fastpeer-enabled, generate its allowed set
     1459         * (before registering our callbacks) */
     1460        if ( !msgs->peerAllowedPieces ) {
     1461            const struct in_addr *peerAddr = tr_peerIoGetAddress( msgs->io, NULL );
     1462           
     1463            msgs->peerAllowedPieces = tr_peerMgrGenerateAllowedSet( MAX_ALLOWED_SET_COUNT,
     1464                                                                    msgs->torrent->info.pieceCount,
     1465                                                                    msgs->torrent->info.hash,
     1466                                                                    peerAddr );
     1467        }
     1468        msgs->clientAllowedPieces = tr_bitfieldNew( msgs->torrent->info.pieceCount );
     1469    }
     1470   
    12871471    tr_peerIoSetIOFuncs( msgs->io, canRead, didWrite, gotError, msgs );
    12881472    tr_peerIoSetIOMode( msgs->io, EV_READ|EV_WRITE, 0 );
     
    13051489        }
    13061490    }
    1307 
    1308     sendBitfield( msgs );
     1491   
     1492    if ( tr_peerIoSupportsFEXT( msgs->io ) )
     1493    {
     1494        /* This peer is fastpeer-enabled, send it have-all or have-none if appropriate */
     1495        float completion = tr_cpPercentComplete( msgs->torrent->completion );
     1496        if ( completion == 0.0f ) {
     1497            sendFastHave( msgs, 0 );
     1498        } else if ( completion == 1.0f ) {
     1499            sendFastHave( msgs, 1 );
     1500        } else {
     1501            sendBitfield( msgs );
     1502        }
     1503        uint32_t peerProgress = msgs->torrent->info.pieceCount * msgs->info->progress;
     1504       
     1505        if ( peerProgress < MAX_ALLOWED_SET_COUNT )
     1506            sendFastAllowedSet( msgs );
     1507    } else {
     1508        sendBitfield( msgs );
     1509    }
    13091510    return msgs;
    13101511}
Note: See TracChangeset for help on using the changeset viewer.