Ignore:
Timestamp:
Oct 27, 2007, 3:45:00 PM (15 years ago)
Author:
charles
Message:

Ticket #398 (peer-msgs.c:905: failed assertion `msglen == 0' in 0.90)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/0.9x/libtransmission/peer-msgs.c

    r3553 r3598  
    114114    struct evbuffer * inBlock;     /* the block we're currently receiving */
    115115    tr_list * peerAskedFor;
     116    tr_list * peerAskedForFast;
    116117    tr_list * clientAskedFor;
    117118    tr_list * clientWillAskFor;
     
    394395#define MIN_CHOKE_PERIOD_SEC 10
    395396
     397static void
     398cancelAllRequestsToClientExceptFast( tr_peermsgs * msgs )
     399{
     400    tr_list_free( &msgs->peerAskedFor, tr_free );
     401}
     402
    396403void
    397404tr_peerMsgsSetChoke( tr_peermsgs * msgs, int choke )
     
    410417    {
    411418        msgs->info->peerIsChoked = choke;
    412        
    413419        if( choke )
    414         {
    415             tr_list * walk;
    416             for( walk = msgs->peerAskedFor; walk != NULL; )
    417             {
    418                 tr_list * next = walk->next;
    419                 /* don't reject a peer's fast allowed requests at choke */
    420                 struct peer_request *req = walk->data;
    421                 if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index ) )
    422                 {
    423                     tr_list_remove_data( &msgs->peerAskedFor, req );
    424                     tr_free( req );
    425                 }
    426                 walk = next;
    427             }
    428         }
    429 
     420            cancelAllRequestsToClientExceptFast( msgs );
    430421        protocolSendChoke( msgs, choke );
    431422        msgs->info->chokeChangedAt = time( NULL );
     
    478469    assert( msgs != NULL );
    479470    assert( length > 0 );
    480    
    481     /* reject the request */
    482     const uint32_t len = sizeof(uint8_t) + 3 * sizeof(uint32_t);
    483     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, len );
    484     tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_REJECT );
    485     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
    486     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, offset );
    487     tr_peerIoWriteUint32( msgs->io, msgs->outMessages, length );
     471
     472    if( tr_peerIoSupportsFEXT( msgs->io ) )
     473    {
     474        const uint32_t len = sizeof(uint8_t) + 3 * sizeof(uint32_t);
     475        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, len );
     476        tr_peerIoWriteUint8( msgs->io, msgs->outMessages, BT_REJECT );
     477        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, pieceIndex );
     478        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, offset );
     479        tr_peerIoWriteUint32( msgs->io, msgs->outMessages, length );
     480    }
    488481}
    489482
     
    535528
    536529static int
    537 requestIsValid( const tr_peermsgs * msgs, struct peer_request * req )
     530requestIsValid( const tr_peermsgs * msgs, const struct peer_request * req )
    538531{
    539532    return reqIsValid( msgs, req->index, req->offset, req->length );
     
    631624
    632625static void
    633 tr_peerMsgsCancelAllRequests( tr_peermsgs * msgs )
     626cancelAllRequestsToPeer( tr_peermsgs * msgs )
    634627{
    635628    struct peer_request * req;
     
    886879
    887880static int
     881clientCanSendFastBlock( const tr_peermsgs * msgs UNUSED )
     882{
     883    /* FIXME(tiennou): base this on how many blocks we've already sent this
     884     * peer, or maybe how many fast blocks per minute we've sent overall,
     885     * or maybe how much bandwidth we're already using up w/o fast peers.
     886     * I don't know what the Right Thing here is, but
     887     * the previous measurement of how many pieces we have is not enough. */
     888    return FALSE;
     889}
     890
     891static void
     892peerMadeRequest( tr_peermsgs * msgs, const struct peer_request * req )
     893{
     894    const int reqIsValid = requestIsValid( msgs, req );
     895    const int clientHasPiece = reqIsValid && tr_cpPieceIsComplete( msgs->torrent->completion, req->index );
     896    const int peerIsChoked = msgs->info->peerIsChoked;
     897    const int peerIsFast = tr_peerIoSupportsFEXT( msgs->io );
     898    const int pieceIsFast = reqIsValid && tr_bitfieldHas( msgs->peerAllowedPieces, req->index );
     899    const int canSendFast = clientCanSendFastBlock( msgs );
     900
     901    if( !reqIsValid ) /* bad request */
     902    {
     903        dbgmsg( msgs, "rejecting an invalid request." );
     904        sendFastReject( msgs, req->index, req->offset, req->length );
     905    }
     906    else if( !clientHasPiece ) /* we don't have it */
     907    {
     908        dbgmsg( msgs, "rejecting request for a piece we don't have." );
     909        sendFastReject( msgs, req->index, req->offset, req->length );
     910    }
     911    else if( peerIsChoked && !peerIsFast ) /* maybe he doesn't know he's choked? */
     912    {
     913        tr_peerMsgsSetChoke( msgs, 1 );
     914        sendFastReject( msgs, req->index, req->offset, req->length );
     915    }
     916    else if( peerIsChoked && peerIsFast && ( !pieceIsFast || !canSendFast ) )
     917    {
     918        sendFastReject( msgs, req->index, req->offset, req->length );
     919    }
     920    else /* YAY */
     921    {
     922        struct peer_request * tmp = tr_new( struct peer_request, 1 );
     923        *tmp = *req;
     924        if( peerIsFast && pieceIsFast )
     925            tr_list_append( &msgs->peerAskedForFast, tmp );
     926        else
     927            tr_list_append( &msgs->peerAskedFor, tmp );
     928    }
     929}
     930
     931static int
     932messageLengthIsCorrect( const tr_peermsgs * msg, uint8_t id, uint32_t len )
     933{
     934    switch( id )
     935    {
     936        case BT_CHOKE:
     937        case BT_UNCHOKE:
     938        case BT_INTERESTED:
     939        case BT_NOT_INTERESTED:
     940        case BT_HAVE_ALL:
     941        case BT_HAVE_NONE:
     942            return len==1;
     943
     944        case BT_HAVE:
     945        case BT_SUGGEST:
     946        case BT_ALLOWED_FAST:
     947            return len==5;
     948
     949        case BT_BITFIELD:
     950            return len == (msg->torrent->info.pieceCount+7u)/8u + 1u;
     951       
     952        case BT_REQUEST:
     953        case BT_CANCEL:
     954        case BT_REJECT:
     955            return len==13;
     956
     957        case BT_PIECE:
     958            return len > 9;
     959
     960        case BT_PORT:
     961            return len==3;
     962
     963        case BT_LTEP:
     964            return len >= 2;
     965
     966        default:
     967            return FALSE;
     968    }
     969}
     970
     971
     972static int
    888973readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf )
    889974{
     
    896981
    897982    tr_peerIoReadUint8( msgs->io, inbuf, &id );
    898     msglen--;
    899983    dbgmsg( msgs, "got BT id %d, len %d", (int)id, (int)msglen );
    900984
     985    if( !messageLengthIsCorrect( msgs, id, msglen ) )
     986    {
     987        fireGotError( msgs );
     988        return READ_DONE;
     989    }
     990
     991    --msglen;
     992
    901993    switch( id )
    902994    {
    903         case BT_CHOKE:
    904             dbgmsg( msgs, "got Choke" );
    905             assert( msglen == 0 );
    906             msgs->info->clientIsChoked = 1;
    907 #if 0
    908             tr_list * walk;
    909             for( walk = msgs->peerAskedFor; walk != NULL; )
    910             {
    911                 tr_list * next = walk->next;
    912                 /* We shouldn't reject a peer's fast allowed requests at choke */
    913                 struct peer_request *req = walk->data;
    914                 if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index ) )
    915                 {
    916                     tr_list_remove_data( &msgs->peerAskedFor, req );
    917                     tr_free( req );
    918                 }
    919                 walk = next;
    920             }
    921 #endif
    922             tr_peerMsgsCancelAllRequests( msgs );
    923             break;
    924 
    925         case BT_UNCHOKE:
    926             dbgmsg( msgs, "got Unchoke" );
    927             assert( msglen == 0 );
    928             msgs->info->clientIsChoked = 0;
    929             fireNeedReq( msgs );
    930             break;
    931 
    932         case BT_INTERESTED:
    933             dbgmsg( msgs, "got Interested" );
    934             assert( msglen == 0 );
    935             msgs->info->peerIsInterested = 1;
    936             tr_peerMsgsSetChoke( msgs, 0 );
    937             break;
    938 
    939         case BT_NOT_INTERESTED:
    940             dbgmsg( msgs, "got Not Interested" );
    941             assert( msglen == 0 );
    942             msgs->info->peerIsInterested = 0;
    943             break;
    944 
    945         case BT_HAVE:
    946             assert( msglen == 4 );
    947             tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
    948             tr_bitfieldAdd( msgs->info->have, ui32 );
    949             updatePeerProgress( msgs );
    950             tr_rcTransferred( msgs->torrent->swarmspeed, msgs->torrent->info.pieceSize );
    951             dbgmsg( msgs, "got Have: %u", ui32 );
    952             break;
    953 
    954         case BT_BITFIELD: {
    955             const int clientIsSeed = tr_torrentIsSeed( msgs->torrent );
    956             dbgmsg( msgs, "got a bitfield" );
    957             assert( msglen == msgs->info->have->len );
    958             tr_peerIoReadBytes( msgs->io, inbuf, msgs->info->have->bits, msglen );
    959             updatePeerProgress( msgs );
    960             tr_peerMsgsSetChoke( msgs, !clientIsSeed || (msgs->info->progress<1.0) );
    961             fireNeedReq( msgs );
    962             break;
    963         }
    964 
    965         case BT_REQUEST: {
    966             struct peer_request * req;
    967             assert( msglen == 12 );
    968             req = tr_new( struct peer_request, 1 );
    969             tr_peerIoReadUint32( msgs->io, inbuf, &req->index );
    970             tr_peerIoReadUint32( msgs->io, inbuf, &req->offset );
    971             tr_peerIoReadUint32( msgs->io, inbuf, &req->length );
    972             dbgmsg( msgs, "got Request: %u:%u->%u", req->index, req->offset, req->length );
    973            
    974             if ( !requestIsValid( msgs, req ) )
    975             {
    976                 dbgmsg( msgs, "BT_REQUEST: invalid request, ignoring" );
    977                 tr_free( req );
    978                 break;
    979             }
    980             /*
    981                 If we're not choking him -> continue
    982                 If we're choking him
    983                     it doesn't support FPE -> He's deaf, reCHOKE and bail...
    984                     it support FPE
    985                         If the asked piece is not allowed
    986                             OR he's above our threshold
    987                             OR we don't have the requested piece -> Reject
    988                         Else
    989                         Asked piece allowed AND he's below our threshold -> continue...
    990              */
     995        case BT_CHOKE:
     996            dbgmsg( msgs, "got Choke" );
     997            msgs->info->clientIsChoked = 1;
     998            cancelAllRequestsToPeer( msgs );
     999            cancelAllRequestsToClientExceptFast( msgs );
     1000            break;
     1001
     1002        case BT_UNCHOKE:
     1003            dbgmsg( msgs, "got Unchoke" );
     1004            msgs->info->clientIsChoked = 0;
     1005            fireNeedReq( msgs );
     1006            break;
     1007
     1008        case BT_INTERESTED:
     1009            dbgmsg( msgs, "got Interested" );
     1010            msgs->info->peerIsInterested = 1;
     1011            tr_peerMsgsSetChoke( msgs, 0 );
     1012            break;
     1013
     1014        case BT_NOT_INTERESTED:
     1015            dbgmsg( msgs, "got Not Interested" );
     1016            msgs->info->peerIsInterested = 0;
     1017            break;
     1018
     1019        case BT_HAVE:
     1020            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
     1021            dbgmsg( msgs, "got Have: %u", ui32 );
     1022            tr_bitfieldAdd( msgs->info->have, ui32 );
     1023            updatePeerProgress( msgs );
     1024            tr_rcTransferred( msgs->torrent->swarmspeed, msgs->torrent->info.pieceSize );
     1025            break;
     1026
     1027        case BT_BITFIELD: {
     1028            const int clientIsSeed = tr_torrentIsSeed( msgs->torrent );
     1029            dbgmsg( msgs, "got a bitfield" );
     1030            tr_peerIoReadBytes( msgs->io, inbuf, msgs->info->have->bits, msglen );
     1031            updatePeerProgress( msgs );
     1032            tr_peerMsgsSetChoke( msgs, !clientIsSeed || (msgs->info->progress<1.0) );
     1033            fireNeedReq( msgs );
     1034            break;
     1035        }
     1036
     1037        case BT_REQUEST: {
     1038            struct peer_request req;
     1039            tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
     1040            tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
     1041            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
     1042            dbgmsg( msgs, "got Request: %u:%u->%u", req.index, req.offset, req.length );
     1043            peerMadeRequest( msgs, &req );
     1044            break;
     1045        }
     1046
     1047        case BT_CANCEL: {
     1048            struct peer_request req;
     1049            tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
     1050            tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
     1051            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
     1052            dbgmsg( msgs, "got a Cancel %u:%u->%u", req.index, req.offset, req.length );
     1053            tr_free( tr_list_remove( &msgs->peerAskedForFast, &req, compareRequest ) );
     1054            tr_free( tr_list_remove( &msgs->peerAskedFor, &req, compareRequest ) );
     1055            break;
     1056        }
     1057
     1058        case BT_PIECE: {
     1059            dbgmsg( msgs, "got a Piece!" );
     1060            assert( msgs->blockToUs.length == 0 );
     1061            tr_peerIoReadUint32( msgs->io, inbuf, &msgs->blockToUs.index );
     1062            tr_peerIoReadUint32( msgs->io, inbuf, &msgs->blockToUs.offset );
     1063            msgs->blockToUs.length = msglen - 8;
     1064            assert( EVBUFFER_LENGTH(msgs->inBlock) == 0 );
     1065            msgs->state = msgs->blockToUs.length ? READING_BT_PIECE : AWAITING_BT_LENGTH;
     1066            return READ_AGAIN;
     1067            break;
     1068        }
     1069
     1070        case BT_PORT: {
     1071            dbgmsg( msgs, "Got a BT_PORT" );
     1072            tr_peerIoReadUint16( msgs->io, inbuf, &msgs->info->port );
     1073            break;
     1074        }
    9911075   
    992 
    993             if ( msgs->info->peerIsChoked )
    994             {
    995                 if ( !tr_peerIoSupportsFEXT( msgs->io ) )
    996                 {
    997                     dbgmsg( msgs, "BT_REQUEST: peer is choked, ignoring" );
    998                     /* Didn't he get it? */
    999                     tr_peerMsgsSetChoke( msgs, 1 );
    1000                     tr_free( req );
    1001                     break;
    1002                 }
    1003                 else
    1004                 {
    1005                     if ( !tr_bitfieldHas( msgs->peerAllowedPieces, req->index )
    1006                          || ( msgs->info->progress * (float)msgs->torrent->info.pieceCount) >= MAX_ALLOWED_SET_COUNT
    1007                          || !tr_cpPieceIsComplete( msgs->torrent->completion, req->index ) )
    1008                     {
    1009                         dbgmsg( msgs, "BT_REQUEST: peer requests an un-fastallowed piece" );
    1010                         sendFastReject( msgs, req->index, req->offset, req->length );
    1011                         tr_free( req );
    1012                         break;
    1013                     }
    1014                     dbgmsg( msgs, "BT_REQUEST: fast allowed piece, accepting request" );
    1015                 }   
    1016             }
    1017            
    1018             tr_list_append( &msgs->peerAskedFor, req );
    1019             break;
    1020         }
    1021 
    1022         case BT_CANCEL: {
    1023             struct peer_request req;
    1024             void * data;
    1025             assert( msglen == 12 );
    1026             tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
    1027             tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
    1028             tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
    1029             dbgmsg( msgs, "got a Cancel %u:%u->%u", req.index, req.offset, req.length );
    1030             data = tr_list_remove( &msgs->peerAskedFor, &req, compareRequest );
    1031             tr_free( data );
    1032             break;
    1033         }
    1034 
    1035         case BT_PIECE: {
    1036             dbgmsg( msgs, "got a Piece!" );
    1037             assert( msgs->blockToUs.length == 0 );
    1038             tr_peerIoReadUint32( msgs->io, inbuf, &msgs->blockToUs.index );
    1039             tr_peerIoReadUint32( msgs->io, inbuf, &msgs->blockToUs.offset );
    1040             msgs->blockToUs.length = msglen - 8;
    1041             assert( EVBUFFER_LENGTH(msgs->inBlock) == 0 );
    1042             msgs->state = msgs->blockToUs.length ? READING_BT_PIECE : AWAITING_BT_LENGTH;
    1043             return READ_AGAIN;
    1044             break;
    1045         }
    1046 
    1047         case BT_PORT: {
    1048             dbgmsg( msgs, "Got a BT_PORT" );
    1049             assert( msglen == 2 );
    1050             tr_peerIoReadUint16( msgs->io, inbuf, &msgs->info->port );
    1051             break;
    1052         }
    1053        
    1054         case BT_SUGGEST: {
    1055             /* tiennou TODO */
    1056             break;
    1057         }
    1058            
    1059         case BT_HAVE_ALL: {
    1060             assert( msglen == 0 );
    1061             dbgmsg( msgs, "Got a BT_HAVE_ALL" );
    1062             memset( msgs->info->have->bits, 1, msgs->info->have->len );
    1063             updatePeerProgress( msgs );
    1064             break;
    1065         }
    1066            
    1067         case BT_HAVE_NONE: {
    1068             assert( msglen == 0 );
    1069             dbgmsg( msgs, "Got a BT_HAVE_NONE" );
    1070             tr_bitfieldClear( msgs->info->have );
    1071             updatePeerProgress( msgs );
    1072             break;
    1073         }
    1074            
    1075         case BT_REJECT: {
    1076             struct peer_request req;
    1077             tr_list * node;
    1078             assert( msglen == 12 );
    1079             dbgmsg( msgs, "Got a BT_REJECT" );
    1080             tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
    1081             tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
    1082             tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
    1083             node = tr_list_find( msgs->peerAskedFor, &req, compareRequest );
    1084             if( node != NULL ) {
    1085                 void * data = node->data;
    1086                 tr_list_remove_data( &msgs->peerAskedFor, data );
    1087                 tr_free( data );
    1088                 dbgmsg( msgs, "found the req that peer has rejected... cancelled." );
    1089             }
    1090             break;
    1091         }
    1092            
    1093         case BT_ALLOWED_FAST: {
    1094             assert( msglen == 4 );
    1095             dbgmsg( msgs, "Got a BT_ALLOWED_FAST" );
    1096             tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
    1097             tr_bitfieldAdd( msgs->clientAllowedPieces, ui32 );
    1098             break;
    1099         }
    1100            
    1101         case BT_LTEP:
    1102             dbgmsg( msgs, "Got a BT_LTEP" );
    1103             parseLtep( msgs, msglen, inbuf );
    1104             break;
    1105 
    1106         default:
    1107             dbgmsg( msgs, "peer sent us an UNKNOWN: %d", (int)id );
    1108             tr_peerIoDrain( msgs->io, inbuf, msglen );
    1109             assert( 0 );
     1076        case BT_SUGGEST: {
     1077            /* FIXME(tiennou) */
     1078            uint32_t index;
     1079            tr_peerIoReadUint32( msgs->io, inbuf, &index );
     1080            break;
     1081        }
     1082       
     1083        case BT_HAVE_ALL:
     1084            dbgmsg( msgs, "Got a BT_HAVE_ALL" );
     1085            tr_bitfieldAddRange( msgs->info->have, 0, msgs->torrent->info.pieceCount );
     1086            updatePeerProgress( msgs );
     1087            break;
     1088       
     1089        case BT_HAVE_NONE:
     1090            dbgmsg( msgs, "Got a BT_HAVE_NONE" );
     1091            tr_bitfieldClear( msgs->info->have );
     1092            updatePeerProgress( msgs );
     1093            break;
     1094       
     1095        case BT_REJECT: {
     1096            struct peer_request req;
     1097            dbgmsg( msgs, "Got a BT_REJECT" );
     1098            tr_peerIoReadUint32( msgs->io, inbuf, &req.index );
     1099            tr_peerIoReadUint32( msgs->io, inbuf, &req.offset );
     1100            tr_peerIoReadUint32( msgs->io, inbuf, &req.length );
     1101            tr_free( tr_list_remove( &msgs->clientAskedFor, &req, compareRequest ) );
     1102            break;
     1103        }
     1104       
     1105        case BT_ALLOWED_FAST: {
     1106            dbgmsg( msgs, "Got a BT_ALLOWED_FAST" );
     1107            tr_peerIoReadUint32( msgs->io, inbuf, &ui32 );
     1108            tr_bitfieldAdd( msgs->clientAllowedPieces, ui32 );
     1109            break;
     1110        }
     1111       
     1112        case BT_LTEP:
     1113            dbgmsg( msgs, "Got a BT_LTEP" );
     1114            parseLtep( msgs, msglen, inbuf );
     1115            break;
     1116
     1117        default:
     1118            dbgmsg( msgs, "peer sent us an UNKNOWN: %d", (int)id );
     1119            tr_peerIoDrain( msgs->io, inbuf, msglen );
     1120            break;
    11101121    }
    11111122
     
    14121423        msgs->clientSentAnythingAt = now;
    14131424    }
    1414     else if(( msgs->peerAskedFor ))
     1425    else if( msgs->peerAskedForFast || msgs->peerAskedFor )
    14151426    {
    14161427        if( canUpload( msgs ) )
    14171428        {
    1418             struct peer_request * r = tr_list_pop_front( &msgs->peerAskedFor );
    1419             uint8_t * buf = tr_new( uint8_t, r->length );
     1429            struct peer_request * r;
     1430            uint8_t * buf;
     1431
     1432            r = tr_list_pop_front( &msgs->peerAskedForFast );
     1433            if( r == NULL )
     1434                r = tr_list_pop_front( &msgs->peerAskedFor);
     1435
     1436            buf = tr_new( uint8_t, r->length );
    14201437
    14211438            if( requestIsValid( msgs, r )
     
    17041721        tr_list_free( &msgs->clientWillAskFor, tr_free );
    17051722        tr_list_free( &msgs->clientAskedFor, tr_free );
     1723        tr_list_free( &msgs->peerAskedForFast, tr_free );
    17061724        tr_list_free( &msgs->peerAskedFor, tr_free );
    17071725        evbuffer_free( msgs->outMessages );
Note: See TracChangeset for help on using the changeset viewer.