Changeset 7234


Ignore:
Timestamp:
Dec 2, 2008, 5:10:54 PM (12 years ago)
Author:
charles
Message:

(libT) #1549: support fast exensions' "reject" and "have all/none" messages

Location:
trunk/libtransmission
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/Makefile.am

    r7186 r7234  
    110110    clients-test \
    111111    json-test \
     112    peer-msgs-test \
    112113    rpc-test \
    113114    test-peer-id \
     
    155156test_peer_id_LDFLAGS = ${apps_ldflags}
    156157
     158peer_msgs_test_SOURCES = peer-msgs-test.c
     159peer_msgs_test_LDADD = ${apps_ldadd}
     160peer_msgs_test_LDFLAGS = ${apps_ldflags}
     161
    157162utils_test_SOURCES = utils-test.c
    158163utils_test_LDADD = ${apps_ldadd}
  • trunk/libtransmission/handshake.c

    r7231 r7234  
    3434/* enable LibTransmission extension protocol */
    3535#define ENABLE_LTEP * /
     36/* fast extensions */
     37#define ENABLE_FAST * /
    3638
    3739/***
     
    6971 #define HANDSHAKE_SET_LTEP( bits ) ( (void)0 )
    7072#endif
     73
     74#ifdef ENABLE_FAST
     75 #define HANDSHAKE_HAS_FASTEXT( bits ) ( ( ( bits )[7] & 0x04 ) ? 1 : 0 )
     76 #define HANDSHAKE_SET_FASTEXT( bits ) ( ( bits )[7] |= 0x04 )
     77#else
     78 #define HANDSHAKE_HAS_FASTEXT( bits ) ( 0 )
     79 #define HANDSHAKE_SET_FASTEXT( bits ) ( (void)0 )
     80#endif
    7181
    7282/* http://www.azureuswiki.com/index.php/Extension_negotiation_protocol
     
    204214    memset( walk, 0, HANDSHAKE_FLAGS_LEN );
    205215    HANDSHAKE_SET_LTEP( walk );
     216    HANDSHAKE_SET_FASTEXT( walk );
    206217
    207218    walk += HANDSHAKE_FLAGS_LEN;
     
    280291    **/
    281292
    282     if( HANDSHAKE_HAS_LTEP( reserved ) )
    283     {
    284         tr_peerIoEnableLTEP( handshake->io, 1 );
    285         dbgmsg( handshake, "using ltep" );
    286     }
     293    tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) );
     294
     295    tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) );
    287296
    288297    return HANDSHAKE_OK;
     
    644653
    645654    /**
    646     *** Extension negotiation
     655    *** Extensions
    647656    **/
    648657
    649     if( HANDSHAKE_HAS_LTEP( reserved ) )
    650     {
    651         tr_peerIoEnableLTEP( handshake->io, 1 );
    652         dbgmsg( handshake, "using ltep" );
    653     }
     658    tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) );
     659
     660    tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) );
    654661
    655662    /* torrent hash */
  • trunk/libtransmission/peer-common.h

    r7151 r7234  
    4343    TR_PEER_CLIENT_GOT_BLOCK,
    4444    TR_PEER_CLIENT_GOT_DATA,
     45    TR_PEER_CLIENT_GOT_ALLOWED_FAST,
     46    TR_PEER_CLIENT_GOT_SUGGEST,
    4547    TR_PEER_PEER_GOT_DATA,
    4648    TR_PEER_PEER_PROGRESS,
     
    5456{
    5557    PeerEventType    eventType;
    56     uint32_t         pieceIndex;   /* for GOT_BLOCK, CANCEL */
     58    uint32_t         pieceIndex;   /* for GOT_BLOCK, CANCEL, ALLOWED, SUGGEST */
    5759    uint32_t         offset;       /* for GOT_BLOCK */
    5860    uint32_t         length;       /* for GOT_BLOCK + GOT_DATA */
  • trunk/libtransmission/peer-io.c

    r7231 r7234  
    8484    tr_bool                  peerIdIsSet;
    8585    tr_bool                  extendedProtocolSupported;
     86    tr_bool                  fastExtensionSupported;
    8687
    8788    int                      magicNumber;
     
    235236{
    236237    return ( io != NULL ) && ( io->magicNumber == MAGIC_NUMBER );
     238}
     239
     240static int
     241isFlag( int flag )
     242{
     243    return( ( flag == 0 ) || ( flag == 1 ) );
    237244}
    238245
     
    488495
    489496void
     497tr_peerIoEnableFEXT( tr_peerIo * io,
     498                     int         flag )
     499{
     500    assert( isPeerIo( io ) );
     501    assert( isFlag( flag ) );
     502
     503    dbgmsg( io, "setting FEXT support flag to %d", (flag?1:0) );
     504    io->fastExtensionSupported = flag;
     505}
     506
     507int
     508tr_peerIoSupportsFEXT( const tr_peerIo * io )
     509{
     510    assert( isPeerIo( io ) );
     511
     512    return io->fastExtensionSupported;
     513}
     514
     515/**
     516***
     517**/
     518
     519void
    490520tr_peerIoEnableLTEP( tr_peerIo * io,
    491521                     int         flag )
    492522{
    493523    assert( isPeerIo( io ) );
    494     assert( flag == 0 || flag == 1 );
    495 
     524    assert( isFlag( flag ) );
     525
     526    dbgmsg( io, "setting LTEP support flag to %d", (flag?1:0) );
    496527    io->extendedProtocolSupported = flag;
    497528}
  • trunk/libtransmission/peer-io.h

    r7231 r7234  
    5050**/
    5151
    52 void        tr_peerIoEnableLTEP( tr_peerIo * io,
    53                                  int         flag );
     52void        tr_peerIoEnableLTEP( tr_peerIo * io, int flag );
    5453
    5554int         tr_peerIoSupportsLTEP( const tr_peerIo * io );
     55
     56void        tr_peerIoEnableFEXT( tr_peerIo * io, int flag );
     57
     58int         tr_peerIoSupportsFEXT( const tr_peerIo * io );
    5659
    5760/**
  • trunk/libtransmission/peer-mgr.c

    r7231 r7234  
    338338{
    339339    assert( peer );
    340     assert( peer->msgs );
    341 
    342     tr_peerMsgsUnsubscribe( peer->msgs, peer->msgsTag );
    343     tr_peerMsgsFree( peer->msgs );
     340
     341    if( peer->msgs != NULL )
     342    {
     343        tr_peerMsgsUnsubscribe( peer->msgs, peer->msgsTag );
     344        tr_peerMsgsFree( peer->msgs );
     345    }
    344346
    345347    tr_peerIoFree( peer->io );
     
    811813        for( j=0; !handled && j<peerCount; )
    812814        {
    813             const int val = tr_peerMsgsAddRequest( peers[j]->msgs,
    814                                                    index, offset, length );
     815            const int val = tr_peerMsgsAddRequest( peers[j]->msgs, index, offset, length, FALSE );
    815816            switch( val )
    816817            {
     
    922923
    923924static void
     925peerSuggestedPiece( Torrent            * t,
     926                    tr_peer            * peer,
     927                    tr_piece_index_t     pieceIndex,
     928                    int                  isFastAllowed )
     929{
     930    assert( t );
     931    assert( peer );
     932    assert( peer->msgs );
     933
     934    /* is this a valid piece? */
     935    if(  pieceIndex >= t->tor->info.pieceCount )
     936        return;
     937
     938    /* don't ask for it if we've already got it */
     939    if( tr_cpPieceIsComplete( t->tor->completion, pieceIndex ) )
     940        return;
     941
     942    /* don't ask for it if they don't have it */
     943    if( !tr_bitfieldHas( peer->have, pieceIndex ) )
     944        return;
     945
     946    /* don't ask for it if we're choked and it's not fast */
     947    if( !isFastAllowed && peer->clientIsChoked )
     948        return;
     949
     950    /* request the blocks that we don't have in this piece */
     951    {
     952        tr_block_index_t block;
     953        const tr_torrent * tor = t->tor;
     954        const tr_block_index_t start = tr_torPieceFirstBlock( tor, pieceIndex );
     955        const tr_block_index_t end = start + tr_torPieceCountBlocks( tor, pieceIndex );
     956
     957        for( block=start; block<end; ++block )
     958        {
     959            if( !tr_cpBlockIsComplete( tor->completion, block ) )
     960            {
     961                const uint32_t offset = getBlockOffsetInPiece( tor, block );
     962                const uint32_t length = tr_torBlockCountBytes( tor, block );
     963                tr_peerMsgsAddRequest( peer->msgs, pieceIndex, offset, length, TRUE );
     964                incrementPieceRequests( t, pieceIndex );
     965            }
     966        }
     967    }
     968}
     969
     970static void
    924971peerCallbackFunc( void * vpeer,
    925972                  void * vevent,
     
    9641011            break;
    9651012        }
     1013
     1014        case TR_PEER_CLIENT_GOT_SUGGEST:
     1015            if( peer )
     1016                peerSuggestedPiece( t, peer, e->pieceIndex, FALSE );
     1017            break;
     1018
     1019        case TR_PEER_CLIENT_GOT_ALLOWED_FAST:
     1020            if( peer )
     1021                peerSuggestedPiece( t, peer, e->pieceIndex, TRUE );
     1022            break;
    9661023
    9671024        case TR_PEER_CLIENT_GOT_DATA:
  • trunk/libtransmission/peer-msgs.c

    r7231 r7234  
    5555    BT_CANCEL               = 8,
    5656    BT_PORT                 = 9,
    57     BT_SUGGEST              = 13,
    58     BT_HAVE_ALL             = 14,
    59     BT_HAVE_NONE            = 15,
    60     BT_REJECT               = 16,
     57
     58    BT_FEXT_SUGGEST         = 13,
     59    BT_FEXT_HAVE_ALL        = 14,
     60    BT_FEXT_HAVE_NONE       = 15,
     61    BT_FEXT_REJECT          = 16,
     62    BT_FEXT_ALLOWED_FAST    = 17,
     63
    6164    BT_LTEP                 = 20,
    6265
     
    6467
    6568    TR_LTEP_PEX             = 1,
     69
     70
    6671
    6772    MIN_CHOKE_PERIOD_SEC    = ( 10 ),
     
    9196    /* number of pieces to remove from the bitfield when
    9297     * lazy bitfields are turned on */
    93     LAZY_PIECE_COUNT = 26
     98    LAZY_PIECE_COUNT = 26,
     99
     100    /* number of pieces we'll allow in our fast set */
     101    MAX_FAST_SET_SIZE = 3
    94102};
    95103
     
    259267    tr_bool         clientSentLtepHandshake;
    260268    tr_bool         peerSentLtepHandshake;
     269    tr_bool         haveFastSet;
    261270
    262271    uint8_t         state;
     
    265274    uint16_t        minActiveRequests;
    266275    uint16_t        maxActiveRequests;
     276
     277    size_t                 fastsetSize;
     278    tr_piece_index_t       fastset[MAX_FAST_SET_SIZE];
    267279
    268280    /* how long the outMessages batch should be allowed to grow before
     
    358370
    359371static void
     372dbgOutMessageLen( tr_peermsgs * msgs )
     373{
     374    dbgmsg( msgs, "outMessage size is now %zu", EVBUFFER_LENGTH( msgs->outMessages ) );
     375}
     376
     377static void
     378protocolSendReject( tr_peermsgs * msgs, const struct peer_request * req )
     379{
     380    tr_peerIo       * io  = msgs->io;
     381    struct evbuffer * out = msgs->outMessages;
     382
     383    assert( tr_peerIoSupportsFEXT( msgs->io ) );
     384
     385    tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 3 * sizeof( uint32_t ) );
     386    tr_peerIoWriteUint8 ( io, out, BT_FEXT_REJECT );
     387    tr_peerIoWriteUint32( io, out, req->index );
     388    tr_peerIoWriteUint32( io, out, req->offset );
     389    tr_peerIoWriteUint32( io, out, req->length );
     390
     391    dbgmsg( msgs, "rejecting %u:%u->%u...", req->index, req->offset, req->length );
     392    dbgOutMessageLen( msgs );
     393}
     394
     395static void
    360396protocolSendRequest( tr_peermsgs *               msgs,
    361397                     const struct peer_request * req )
    362398{
    363     tr_peerIo *       io = msgs->io;
     399    tr_peerIo       * io = msgs->io;
    364400    struct evbuffer * out = msgs->outMessages;
    365401
     
    369405    tr_peerIoWriteUint32( io, out, req->offset );
    370406    tr_peerIoWriteUint32( io, out, req->length );
    371     dbgmsg( msgs, "requesting %u:%u->%u... outMessage size is now %d",
    372            req->index, req->offset, req->length, (int)EVBUFFER_LENGTH( out ) );
     407
     408    dbgmsg( msgs, "requesting %u:%u->%u...", req->index, req->offset, req->length );
     409    dbgOutMessageLen( msgs );
    373410    pokeBatchPeriod( msgs, HIGH_PRIORITY_INTERVAL_SECS );
    374411}
     
    378415                    const struct peer_request * req )
    379416{
    380     tr_peerIo *       io = msgs->io;
     417    tr_peerIo       * io = msgs->io;
    381418    struct evbuffer * out = msgs->outMessages;
    382419
     
    386423    tr_peerIoWriteUint32( io, out, req->offset );
    387424    tr_peerIoWriteUint32( io, out, req->length );
    388     dbgmsg( msgs, "cancelling %u:%u->%u... outMessage size is now %d",
    389            req->index, req->offset, req->length, (int)EVBUFFER_LENGTH( out ) );
     425
     426    dbgmsg( msgs, "cancelling %u:%u->%u...", req->index, req->offset, req->length );
     427    dbgOutMessageLen( msgs );
    390428    pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
    391429}
     
    395433                  uint32_t      index )
    396434{
    397     tr_peerIo *       io = msgs->io;
     435    tr_peerIo       * io = msgs->io;
    398436    struct evbuffer * out = msgs->outMessages;
    399437
    400     tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + sizeof( uint32_t ) );
     438    tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + sizeof(uint32_t) );
    401439    tr_peerIoWriteUint8 ( io, out, BT_HAVE );
    402440    tr_peerIoWriteUint32( io, out, index );
    403     dbgmsg( msgs, "sending Have %u.. outMessage size is now %d",
    404            index, (int)EVBUFFER_LENGTH( out ) );
     441
     442    dbgmsg( msgs, "sending Have %u...", index );
     443    dbgOutMessageLen( msgs );
    405444    pokeBatchPeriod( msgs, LOW_PRIORITY_INTERVAL_SECS );
     445}
     446
     447static void
     448protocolSendAllowedFast( tr_peermsgs * msgs, uint32_t pieceIndex )
     449{
     450    tr_peerIo       * io  = msgs->io;
     451    struct evbuffer * out = msgs->outMessages;
     452
     453    assert( tr_peerIoSupportsFEXT( msgs->io ) );
     454
     455    tr_peerIoWriteUint32( io, out, sizeof(uint8_t) + sizeof(uint32_t) );
     456    tr_peerIoWriteUint8 ( io, out, BT_FEXT_ALLOWED_FAST );
     457    tr_peerIoWriteUint32( io, out, pieceIndex );
     458
     459    dbgmsg( msgs, "sending Allowed Fast %u...", pieceIndex );
     460    dbgOutMessageLen( msgs );
    406461}
    407462
     
    410465                   int           choke )
    411466{
    412     tr_peerIo *       io = msgs->io;
     467    tr_peerIo       * io = msgs->io;
    413468    struct evbuffer * out = msgs->outMessages;
    414469
    415470    tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) );
    416471    tr_peerIoWriteUint8 ( io, out, choke ? BT_CHOKE : BT_UNCHOKE );
    417     dbgmsg( msgs, "sending %s... outMessage size is now %d",
    418            ( choke ? "Choke" : "Unchoke" ),
    419            (int)EVBUFFER_LENGTH( out ) );
     472
     473    dbgmsg( msgs, "sending %s...", choke ? "Choke" : "Unchoke" );
     474    dbgOutMessageLen( msgs );
     475    pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
     476}
     477
     478static void
     479protocolSendHaveAll( tr_peermsgs * msgs )
     480{
     481    tr_peerIo       * io  = msgs->io;
     482    struct evbuffer * out = msgs->outMessages;
     483
     484    assert( tr_peerIoSupportsFEXT( msgs->io ) );
     485
     486    tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) );
     487    tr_peerIoWriteUint8 ( io, out, BT_FEXT_HAVE_ALL );
     488
     489    dbgmsg( msgs, "sending HAVE_ALL..." );
     490    dbgOutMessageLen( msgs );
     491    pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
     492}
     493
     494static void
     495protocolSendHaveNone( tr_peermsgs * msgs )
     496{
     497    tr_peerIo       * io  = msgs->io;
     498    struct evbuffer * out = msgs->outMessages;
     499
     500    assert( tr_peerIoSupportsFEXT( msgs->io ) );
     501
     502    tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) );
     503    tr_peerIoWriteUint8 ( io, out, BT_FEXT_HAVE_NONE );
     504
     505    dbgmsg( msgs, "sending HAVE_NONE..." );
     506    dbgOutMessageLen( msgs );
    420507    pokeBatchPeriod( msgs, IMMEDIATE_PRIORITY_INTERVAL_SECS );
    421508}
     
    487574    e.eventType = TR_PEER_CLIENT_GOT_DATA;
    488575    e.wasPieceData = wasPieceData;
     576    publish( msgs, &e );
     577}
     578
     579static void
     580fireClientGotSuggest( tr_peermsgs * msgs, uint32_t pieceIndex )
     581{
     582    tr_peer_event e = blankEvent;
     583    e.eventType = TR_PEER_CLIENT_GOT_SUGGEST;
     584    e.pieceIndex = pieceIndex;
     585    publish( msgs, &e );
     586}
     587
     588static void
     589fireClientGotAllowedFast( tr_peermsgs * msgs, uint32_t pieceIndex )
     590{
     591    tr_peer_event e = blankEvent;
     592    e.eventType = TR_PEER_CLIENT_GOT_ALLOWED_FAST;
     593    e.pieceIndex = pieceIndex;
    489594    publish( msgs, &e );
    490595}
     
    513618    e.length = req->length;
    514619    publish( msgs, &e );
     620}
     621
     622/**
     623***  ALLOWED FAST SET
     624***  For explanation, see http://www.bittorrent.org/beps/bep_0006.html
     625**/
     626
     627size_t
     628tr_generateAllowedSet( tr_piece_index_t * setmePieces,
     629                       size_t             desiredSetSize,
     630                       size_t             pieceCount,
     631                       const uint8_t    * infohash,
     632                       const tr_address * addr )
     633{
     634    size_t setSize = 0;
     635
     636    assert( setmePieces );
     637    assert( desiredSetSize <= pieceCount );
     638    assert( desiredSetSize );
     639    assert( pieceCount );
     640    assert( infohash );
     641    assert( addr );
     642
     643    if( addr->type == TR_AF_INET )
     644    {
     645        uint8_t w[SHA_DIGEST_LENGTH + 4];
     646        uint8_t x[SHA_DIGEST_LENGTH];
     647
     648        *(uint32_t*)w = ntohl( htonl( addr->addr.addr4.s_addr ) & 0xffffff00 );   /* (1) */
     649        memcpy( w + 4, infohash, SHA_DIGEST_LENGTH );                /* (2) */
     650        tr_sha1( x, w, sizeof( w ), NULL );                          /* (3) */
     651
     652        while( setSize<desiredSetSize )
     653        {
     654            int i;
     655            for( i=0; i<5 && setSize<desiredSetSize; ++i )           /* (4) */
     656            {
     657                size_t k;
     658                uint32_t j = i * 4;                                  /* (5) */
     659                uint32_t y = ntohl( *( uint32_t* )( x + j ) );       /* (6) */
     660                uint32_t index = y % pieceCount;                     /* (7) */
     661
     662                for( k=0; k<setSize; ++k )                           /* (8) */
     663                    if( setmePieces[k] == index )
     664                        break;
     665
     666                if( k == setSize )
     667                    setmePieces[setSize++] = index;                  /* (9) */
     668            }
     669
     670            tr_sha1( x, x, sizeof( x ), NULL );                      /* (3) */
     671        }
     672    }
     673
     674    return setSize;
     675}
     676
     677static void
     678updateFastSet( tr_peermsgs * msgs UNUSED )
     679{
     680#if 0
     681    const int fext = tr_peerIoSupportsFEXT( msgs->io );
     682    const int peerIsNeedy = msgs->info->progress < 0.10;
     683
     684    if( fext && peerIsNeedy && !msgs->haveFastSet )
     685    {
     686        size_t i;
     687        const struct tr_address * addr = tr_peerIoGetAddress( msgs->io, NULL );
     688        const tr_info * inf = &msgs->torrent->info;
     689        const size_t numwant = MIN( MAX_FAST_SET_SIZE, inf->pieceCount );
     690
     691        /* build the fast set */
     692        msgs->fastsetSize = tr_generateAllowedSet( msgs->fastset, numwant, inf->pieceCount, inf->hash, addr );
     693        msgs->haveFastSet = 1;
     694
     695        /* send it to the peer */
     696        for( i=0; i<msgs->fastsetSize; ++i )
     697            protocolSendAllowedFast( msgs, msgs->fastset[i] );
     698    }
     699#endif
    515700}
    516701
     
    591776}
    592777
     778static int
     779popNextRequest( tr_peermsgs *         msgs,
     780                struct peer_request * setme )
     781{
     782    return reqListPop( &msgs->peerAskedFor, setme );
     783}
     784
    593785static void
    594786cancelAllRequestsToClient( tr_peermsgs * msgs )
    595787{
    596     reqListClear( &msgs->peerAskedFor );
     788    struct peer_request req;
     789
     790    while( popNextRequest( msgs, &req ) )
     791        protocolSendReject( msgs, &req );
    597792}
    598793
     
    662857    time_t              oldestAllowed;
    663858    struct request_list tmp = REQUEST_LIST_INIT;
     859    const int fext = tr_peerIoSupportsFEXT( msgs->io );
    664860
    665861    /* cancel requests that have been queued for too long */
    666862    oldestAllowed = now - QUEUED_REQUEST_TTL_SECS;
    667863    reqListCopy( &tmp, &msgs->clientWillAskFor );
    668     for( i = 0; i < tmp.count; ++i )
    669     {
     864    for( i = 0; i < tmp.count; ++i ) {
    670865        const struct peer_request * req = &tmp.requests[i];
    671866        if( req->time_requested < oldestAllowed )
     
    674869    reqListClear( &tmp );
    675870
    676     /* cancel requests that were sent too long ago */
    677     oldestAllowed = now - SENT_REQUEST_TTL_SECS;
    678     reqListCopy( &tmp, &msgs->clientAskedFor );
    679     for( i = 0; i < tmp.count; ++i )
    680     {
    681         const struct peer_request * req = &tmp.requests[i];
    682         if( req->time_requested < oldestAllowed )
    683             tr_peerMsgsCancel( msgs, req->index, req->offset, req->length );
    684     }
    685     reqListClear( &tmp );
     871    /* if the peer doesn't support "Reject Request",
     872     * cancel requests that were sent too long ago. */
     873    if( !fext ) {
     874        oldestAllowed = now - SENT_REQUEST_TTL_SECS;
     875        reqListCopy( &tmp, &msgs->clientAskedFor );
     876        for( i=0; i<tmp.count; ++i ) {
     877            const struct peer_request * req = &tmp.requests[i];
     878            if( req->time_requested < oldestAllowed )
     879                tr_peerMsgsCancel( msgs, req->index, req->offset, req->length );
     880        }
     881        reqListClear( &tmp );
     882    }
    686883}
    687884
     
    745942                       uint32_t         index,
    746943                       uint32_t         offset,
    747                        uint32_t         length )
     944                       uint32_t         length,
     945                       int              doForce )
    748946{
    749947    struct peer_request req;
     
    758956
    759957    /* don't send requests to choked clients */
    760     if( msgs->info->clientIsChoked )
    761     {
     958    if( !doForce && msgs->info->clientIsChoked ) {
    762959        dbgmsg( msgs, "declining request because they're choking us" );
    763960        return TR_ADDREQ_CLIENT_CHOKED;
     
    765962
    766963    /* peer doesn't have this piece */
    767     if( !tr_bitfieldHas( msgs->info->have, index ) )
     964    if( !doForce && !tr_bitfieldHas( msgs->info->have, index ) )
    768965        return TR_ADDREQ_MISSING;
    769966
    770967    /* peer's queue is full */
    771     if( requestQueueIsFull( msgs ) ) {
     968    if( !doForce && requestQueueIsFull( msgs ) ) {
    772969        dbgmsg( msgs, "declining request because we're full" );
    773970        return TR_ADDREQ_FULL;
     
    778975    req.offset = offset;
    779976    req.length = length;
    780     if( reqListFind( &msgs->clientAskedFor, &req ) != -1 ) {
    781         dbgmsg( msgs, "declining because it's a duplicate" );
    782         return TR_ADDREQ_DUPLICATE;
    783     }
    784     if( reqListFind( &msgs->clientWillAskFor, &req ) != -1 ) {
    785         dbgmsg( msgs, "declining because it's a duplicate" );
    786         return TR_ADDREQ_DUPLICATE;
     977    if( !doForce ) {
     978        if( reqListFind( &msgs->clientAskedFor, &req ) != -1 ) {
     979            dbgmsg( msgs, "declining because it's a duplicate" );
     980            return TR_ADDREQ_DUPLICATE;
     981        }
     982        if( reqListFind( &msgs->clientWillAskFor, &req ) != -1 ) {
     983            dbgmsg( msgs, "declining because it's a duplicate" );
     984            return TR_ADDREQ_DUPLICATE;
     985        }
    787986    }
    788987
     
    8511050    }
    8521051}
     1052
    8531053
    8541054/**
     
    10781278updatePeerProgress( tr_peermsgs * msgs )
    10791279{
    1080     msgs->info->progress = tr_bitfieldCountTrueBits( msgs->info->have )
    1081                            / (float)msgs->torrent->info.pieceCount;
     1280    msgs->info->progress = tr_bitfieldCountTrueBits( msgs->info->have ) / (float)msgs->torrent->info.pieceCount;
    10821281    dbgmsg( msgs, "peer progress is %f", msgs->info->progress );
     1282    updateFastSet( msgs );
    10831283    updateInterest( msgs );
    10841284    firePeerProgress( msgs );
     
    10891289                 const struct peer_request * req )
    10901290{
     1291    const int fext = tr_peerIoSupportsFEXT( msgs->io );
    10911292    const int reqIsValid = requestIsValid( msgs, req );
    1092     const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete(
    1093         msgs->torrent->completion, req->index );
     1293    const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete( msgs->torrent->completion, req->index );
    10941294    const int peerIsChoked = msgs->info->peerIsChoked;
    10951295
    1096     if( !reqIsValid ) /* bad request */
    1097     {
     1296    int allow = FALSE;
     1297
     1298    if( !reqIsValid )
    10981299        dbgmsg( msgs, "rejecting an invalid request." );
    1099     }
    1100     else if( !clientHasPiece ) /* we don't have it */
    1101     {
     1300    else if( !clientHasPiece )
    11021301        dbgmsg( msgs, "rejecting request for a piece we don't have." );
    1103     }
    1104     else if( peerIsChoked ) /* doesn't he know he's choked? */
    1105     {
    1106         tr_peerMsgsSetChoke( msgs, 1 );
    1107     }
    1108     else /* YAY */
    1109     {
     1302    else if( peerIsChoked )
     1303        dbgmsg( msgs, "rejecting request from choked peer" );
     1304    else
     1305        allow = TRUE;
     1306
     1307    if( allow )
    11101308        reqListAppend( &msgs->peerAskedFor, req );
    1111     }
     1309    else if( fext )
     1310        protocolSendReject( msgs, req );
    11121311}
    11131312
     
    11231322        case BT_INTERESTED:
    11241323        case BT_NOT_INTERESTED:
    1125         case BT_HAVE_ALL:
    1126         case BT_HAVE_NONE:
     1324        case BT_FEXT_HAVE_ALL:
     1325        case BT_FEXT_HAVE_NONE:
    11271326            return len == 1;
    11281327
    11291328        case BT_HAVE:
    1130         case BT_SUGGEST:
     1329        case BT_FEXT_SUGGEST:
     1330        case BT_FEXT_ALLOWED_FAST:
    11311331            return len == 5;
    11321332
     
    11361336        case BT_REQUEST:
    11371337        case BT_CANCEL:
    1138         case BT_REJECT:
     1338        case BT_FEXT_REJECT:
    11391339            return len == 13;
    11401340
     
    12301430    const uint8_t id = msgs->incoming.id;
    12311431    const size_t  startBufLen = EVBUFFER_LENGTH( inbuf );
     1432    const int     fext = tr_peerIoSupportsFEXT( msgs->io );
    12321433
    12331434    --msglen; /* id length */
     
    12531454            dbgmsg( msgs, "got Choke" );
    12541455            msgs->info->clientIsChoked = 1;
    1255             cancelAllRequestsToPeer( msgs );
     1456            if( !fext )
     1457                cancelAllRequestsToPeer( msgs );
    12561458            cancelAllRequestsToClient( msgs );
    12571459            break;
     
    13151517            tr_peerIoReadUint32( msgs->io, inbuf, &r.length );
    13161518            dbgmsg( msgs, "got a Cancel %u:%u->%u", r.index, r.offset, r.length );
    1317             reqListRemove( &msgs->peerAskedFor, &r );
     1519            if( reqListRemove( &msgs->peerAskedFor, &r ) && fext )
     1520                protocolSendReject( msgs, &r );
    13181521            break;
    13191522        }
     
    13281531            break;
    13291532
    1330         case BT_SUGGEST:
    1331         {
    1332             dbgmsg( msgs, "Got a BT_SUGGEST" );
     1533        case BT_FEXT_SUGGEST:
     1534            dbgmsg( msgs, "Got a BT_FEXT_SUGGEST" );
    13331535            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
    1334             /* we don't do anything with this yet */
     1536            if( fext )
     1537                fireClientGotSuggest( msgs, ui32 );
     1538            else {
     1539                fireError( msgs, EPROTO );
     1540                return READ_ERR;
     1541            }
    13351542            break;
    1336         }
    1337 
    1338         case BT_HAVE_ALL:
    1339             dbgmsg( msgs, "Got a BT_HAVE_ALL" );
    1340             tr_bitfieldAddRange( msgs->info->have, 0,
    1341                                  msgs->torrent->info.pieceCount );
    1342             updatePeerProgress( msgs );
     1543
     1544        case BT_FEXT_ALLOWED_FAST:
     1545            dbgmsg( msgs, "Got a BT_FEXT_ALLOWED_FAST" );
     1546            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
     1547            if( fext )
     1548                fireClientGotAllowedFast( msgs, ui32 );
     1549            else {
     1550                fireError( msgs, EPROTO );
     1551                return READ_ERR;
     1552            }
    13431553            break;
    13441554
    1345 
    1346         case BT_HAVE_NONE:
    1347             dbgmsg( msgs, "Got a BT_HAVE_NONE" );
    1348             tr_bitfieldClear( msgs->info->have );
    1349             updatePeerProgress( msgs );
     1555        case BT_FEXT_HAVE_ALL:
     1556            dbgmsg( msgs, "Got a BT_FEXT_HAVE_ALL" );
     1557            if( fext ) {
     1558                tr_bitfieldAddRange( msgs->info->have, 0, msgs->torrent->info.pieceCount );
     1559                updatePeerProgress( msgs );
     1560            } else {
     1561                fireError( msgs, EPROTO );
     1562                return READ_ERR;
     1563            }
    13501564            break;
    13511565
    1352         case BT_REJECT:
     1566
     1567        case BT_FEXT_HAVE_NONE:
     1568            dbgmsg( msgs, "Got a BT_FEXT_HAVE_NONE" );
     1569            if( fext ) {
     1570                tr_bitfieldClear( msgs->info->have );
     1571                updatePeerProgress( msgs );
     1572            } else {
     1573                fireError( msgs, EPROTO );
     1574                return READ_ERR;
     1575            }
     1576            break;
     1577
     1578        case BT_FEXT_REJECT:
    13531579        {
    13541580            struct peer_request r;
    1355             dbgmsg( msgs, "Got a BT_REJECT" );
     1581            dbgmsg( msgs, "Got a BT_FEXT_REJECT" );
    13561582            tr_peerIoReadUint32( msgs->io, inbuf, &r.index );
    13571583            tr_peerIoReadUint32( msgs->io, inbuf, &r.offset );
    13581584            tr_peerIoReadUint32( msgs->io, inbuf, &r.length );
    1359             reqListRemove( &msgs->clientAskedFor, &r );
     1585            if( fext )
     1586                reqListRemove( &msgs->clientAskedFor, &r );
     1587            else {
     1588                fireError( msgs, EPROTO );
     1589                return READ_ERR;
     1590            }
    13601591            break;
    13611592        }
     
    15321763}
    15331764
    1534 static int
    1535 popNextRequest( tr_peermsgs *         msgs,
    1536                 struct peer_request * setme )
    1537 {
    1538     return reqListPop( &msgs->peerAskedFor, setme );
    1539 }
    1540 
    15411765static size_t
    15421766fillOutputBuffer( tr_peermsgs * msgs, time_t now )
     
    15451769    struct peer_request req;
    15461770    const int haveMessages = EVBUFFER_LENGTH( msgs->outMessages ) != 0;
     1771    const int fext = tr_peerIoSupportsFEXT( msgs->io );
    15471772
    15481773    /**
     
    15721797
    15731798    if( ( tr_peerIoGetWriteBufferSpace( msgs->io ) >= msgs->torrent->blockSize )
    1574         && popNextRequest( msgs, &req )
    1575         && requestIsValid( msgs, &req )
    1576         && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) )
    1577     {
    1578         /* send a block */
    1579         uint8_t * buf = tr_new( uint8_t, req.length );
    1580         const int err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf );
    1581         if( err ) {
    1582             fireError( msgs, err );
    1583             bytesWritten = 0;
    1584             msgs = NULL;
    1585         } else {
    1586             tr_peerIo * io = msgs->io;
    1587             struct evbuffer * out = evbuffer_new( );
    1588             dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length );
    1589             tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) + req.length );
    1590             tr_peerIoWriteUint8 ( io, out, BT_PIECE );
    1591             tr_peerIoWriteUint32( io, out, req.index );
    1592             tr_peerIoWriteUint32( io, out, req.offset );
    1593             tr_peerIoWriteBytes ( io, out, buf, req.length );
    1594             tr_peerIoWriteBuf( io, out, TRUE );
    1595             bytesWritten += EVBUFFER_LENGTH( out );
    1596             evbuffer_free( out );
    1597             msgs->clientSentAnythingAt = now;
     1799        && popNextRequest( msgs, &req ) )
     1800    {
     1801        if( requestIsValid( msgs, &req )
     1802            && tr_cpPieceIsComplete( msgs->torrent->completion, req.index ) )
     1803        {
     1804            /* send a block */
     1805            uint8_t * buf = tr_new( uint8_t, req.length );
     1806            const int err = tr_ioRead( msgs->torrent, req.index, req.offset, req.length, buf );
     1807            if( err ) {
     1808                fireError( msgs, err );
     1809                bytesWritten = 0;
     1810                msgs = NULL;
     1811            } else {
     1812                tr_peerIo * io = msgs->io;
     1813                struct evbuffer * out = evbuffer_new( );
     1814                dbgmsg( msgs, "sending block %u:%u->%u", req.index, req.offset, req.length );
     1815                tr_peerIoWriteUint32( io, out, sizeof( uint8_t ) + 2 * sizeof( uint32_t ) + req.length );
     1816                tr_peerIoWriteUint8 ( io, out, BT_PIECE );
     1817                tr_peerIoWriteUint32( io, out, req.index );
     1818                tr_peerIoWriteUint32( io, out, req.offset );
     1819                tr_peerIoWriteBytes ( io, out, buf, req.length );
     1820                tr_peerIoWriteBuf( io, out, TRUE );
     1821                bytesWritten += EVBUFFER_LENGTH( out );
     1822                evbuffer_free( out );
     1823                msgs->clientSentAnythingAt = now;
     1824            }
     1825            tr_free( buf );
    15981826        }
    1599         tr_free( buf );
     1827        else if( fext ) /* peer needs a reject message */
     1828        {
     1829            protocolSendReject( msgs, &req );
     1830        }
    16001831    }
    16011832
     
    17051936
    17061937    tr_bitfieldFree( field );
     1938}
     1939
     1940static void
     1941tellPeerWhatWeHave( tr_peermsgs * msgs )
     1942{
     1943    const int fext = tr_peerIoSupportsFEXT( msgs->io );
     1944
     1945    if( fext && ( tr_cpGetStatus( msgs->torrent->completion ) == TR_SEED ) )
     1946    {
     1947        protocolSendHaveAll( msgs );
     1948    }
     1949    else if( fext && ( tr_cpHaveValid( msgs->torrent->completion ) == 0 ) )
     1950    {
     1951        protocolSendHaveNone( msgs );
     1952    }
     1953    else
     1954    {
     1955        sendBitfield( msgs );
     1956    }
    17071957}
    17081958
     
    19132163        sendLtepHandshake( m );
    19142164
    1915     sendBitfield( m );
     2165    tellPeerWhatWeHave( m );
    19162166
    19172167    tr_peerIoSetTimeoutSecs( m->io, 150 ); /* timeout after N seconds of
  • trunk/libtransmission/peer-msgs.h

    r7151 r7234  
    5454                                    uint32_t      pieceIndex,
    5555                                    uint32_t      offset,
    56                                     uint32_t      length );
     56                                    uint32_t      length,
     57                                    int           doForce );
    5758
    58 void         tr_peerMsgsUnsubscribe( tr_peermsgs *    peer,
    59                                      tr_publisher_tag tag );
     59void         tr_peerMsgsUnsubscribe( tr_peermsgs      * peer,
     60                                     tr_publisher_tag   tag );
     61
     62size_t       tr_generateAllowedSet( tr_piece_index_t  * setmePieces,
     63                                    size_t              desiredSetSize,
     64                                    size_t              pieceCount,
     65                                    const uint8_t     * infohash,
     66                                    const tr_address  * addr );
     67
    6068
    6169#endif
Note: See TracChangeset for help on using the changeset viewer.