Changeset 7548


Ignore:
Timestamp:
Dec 30, 2008, 7:44:49 PM (12 years ago)
Author:
charles
Message:

(trunk libT) patch from wereHamster to simplify BT message parsing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/peer-msgs.c

    r7546 r7548  
    107107**/
    108108
    109 enum
    110 {
    111     AWAITING_BT_LENGTH,
    112     AWAITING_BT_ID,
    113     AWAITING_BT_MESSAGE,
    114     AWAITING_BT_PIECE
    115 };
    116 
    117109struct peer_request
    118110{
     
    253245struct tr_incoming
    254246{
    255     uint8_t                id;
    256     uint32_t               length; /* includes the +1 for id length */
    257     struct peer_request    blockReq; /* metadata for incoming blocks */
    258     struct evbuffer *      block; /* piece data for incoming blocks */
     247    uint32_t          length; /* includes the +1 for id length */
     248    struct evbuffer * block; /* piece data for incoming blocks */
    259249};
    260250
     
    281271    tr_bool         haveFastSet;
    282272
    283     uint8_t         state;
    284273    uint8_t         ut_pex_id;
    285274    uint16_t        pexCount;
     
    12801269
    12811270    tr_peerIoReadUint32( msgs->peer->io, inbuf, &len );
     1271    msgs->incoming.length = len;
    12821272
    12831273    if( len == 0 ) /* peer sent us a keepalive message */
    12841274        dbgmsg( msgs, "got KeepAlive" );
    1285     else
    1286     {
    1287         msgs->incoming.length = len;
    1288         msgs->state = AWAITING_BT_ID;
    1289     }
    12901275
    12911276    return READ_NOW;
    1292 }
    1293 
    1294 static int readBtMessage( tr_peermsgs *     msgs,
    1295                           struct evbuffer * inbuf,
    1296                           size_t            inlen );
    1297 
    1298 static int
    1299 readBtId( tr_peermsgs *     msgs,
    1300           struct evbuffer * inbuf,
    1301           size_t            inlen )
    1302 {
    1303     uint8_t id;
    1304 
    1305     if( inlen < sizeof( uint8_t ) )
    1306         return READ_LATER;
    1307 
    1308     tr_peerIoReadUint8( msgs->peer->io, inbuf, &id );
    1309     msgs->incoming.id = id;
    1310 
    1311     if( id == BT_PIECE )
    1312     {
    1313         msgs->state = AWAITING_BT_PIECE;
    1314         return READ_NOW;
    1315     }
    1316     else if( msgs->incoming.length != 1 )
    1317     {
    1318         msgs->state = AWAITING_BT_MESSAGE;
    1319         return READ_NOW;
    1320     }
    1321     else return readBtMessage( msgs, inbuf, inlen - 1 );
    13221277}
    13231278
     
    14081363             size_t           * setme_piece_bytes_read )
    14091364{
    1410     struct peer_request * req = &msgs->incoming.blockReq;
     1365    struct peer_request req;
    14111366
    14121367    assert( EVBUFFER_LENGTH( inbuf ) >= inlen );
    14131368    dbgmsg( msgs, "In readBtPiece" );
    14141369
    1415     if( !req->length )
    1416     {
    1417         if( inlen < 8 )
    1418             return READ_LATER;
    1419 
    1420         tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->index );
    1421         tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->offset );
    1422         req->length = msgs->incoming.length - 9;
    1423         dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length );
    1424         return READ_NOW;
    1425     }
    1426     else
    1427     {
     1370    tr_peerIoReadUint32( msgs->peer->io, inbuf, &req.index );
     1371    tr_peerIoReadUint32( msgs->peer->io, inbuf, &req.offset );
     1372    req.length = msgs->incoming.length - 9;
     1373    dbgmsg( msgs, "got incoming block header %u:%u->%u", req.index, req.offset, req.length );
     1374
     1375    {
    14281376        int err;
    14291377
    1430         /* read in another chunk of data */
    1431         const size_t nLeft = req->length - EVBUFFER_LENGTH( msgs->incoming.block );
    1432         size_t n = MIN( nLeft, inlen );
    1433         size_t i = n;
    1434 
    1435         while( i > 0 )
    1436         {
    1437             uint8_t buf[MAX_STACK_ARRAY_SIZE];
    1438             const size_t thisPass = MIN( i, sizeof( buf ) );
    1439             tr_peerIoReadBytes( msgs->peer->io, inbuf, buf, thisPass );
    1440             evbuffer_add( msgs->incoming.block, buf, thisPass );
    1441             i -= thisPass;
    1442         }
    1443 
    1444         fireClientGotData( msgs, n, TRUE );
    1445         *setme_piece_bytes_read += n;
    1446         dbgmsg( msgs, "got %zu bytes for block %u:%u->%u ... %d remain",
    1447                n, req->index, req->offset, req->length,
    1448                (int)( req->length - EVBUFFER_LENGTH( msgs->incoming.block ) ) );
    1449         if( EVBUFFER_LENGTH( msgs->incoming.block ) < req->length )
    1450             return READ_LATER;
     1378        /* decrypt the whole block in one go */
     1379        evbuffer_expand( msgs->incoming.block, req.length );
     1380        tr_peerIoReadBytes( msgs->peer->io, inbuf, EVBUFFER_DATA( msgs->incoming.block ), req.length );
     1381        EVBUFFER_LENGTH( msgs->incoming.block ) += req.length;
     1382
     1383        fireClientGotData( msgs, req.length, TRUE );
     1384        *setme_piece_bytes_read += req.length;
     1385        dbgmsg( msgs, "got block %u:%u->%u", req.index, req.offset, req.length );
     1386        assert( EVBUFFER_LENGTH( msgs->incoming.block ) == req.length );
    14511387
    14521388        /* we've got the whole block ... process it */
    1453         err = clientGotBlock( msgs, EVBUFFER_DATA( msgs->incoming.block ), req );
     1389        err = clientGotBlock( msgs, EVBUFFER_DATA( msgs->incoming.block ), &req );
    14541390
    14551391        /* cleanup */
    14561392        evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH( msgs->incoming.block ) );
    1457         req->length = 0;
    1458         msgs->state = AWAITING_BT_LENGTH;
    14591393        if( !err )
    14601394            return READ_NOW;
     
    14671401
    14681402static int
    1469 readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
    1470 {
     1403readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen, size_t * piece )
     1404{
     1405    int           ret = READ_NOW;
     1406    uint8_t       id;
    14711407    uint32_t      ui32;
    14721408    uint32_t      msglen = msgs->incoming.length;
    1473     const uint8_t id = msgs->incoming.id;
    14741409    const size_t  startBufLen = EVBUFFER_LENGTH( inbuf );
    14751410    const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io );
    14761411
    1477     --msglen; /* id length */
    1478 
    14791412    if( inlen < msglen )
    14801413        return READ_LATER;
    14811414
     1415    tr_peerIoReadUint8( msgs->peer->io, inbuf, &id );
     1416
    14821417    dbgmsg( msgs, "got BT id %d, len %d, buffer size is %zu", (int)id, (int)msglen, inlen );
    14831418
    1484     if( !messageLengthIsCorrect( msgs, id, msglen + 1 ) )
     1419    if( !messageLengthIsCorrect( msgs, id, msglen ) )
    14851420    {
    14861421        dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen );
     
    14881423        return READ_ERR;
    14891424    }
     1425
     1426    --msglen;
    14901427
    14911428    switch( id )
     
    15601497
    15611498        case BT_PIECE:
    1562             assert( 0 ); /* handled elsewhere! */
     1499            ret = readBtPiece( msgs, inbuf, msglen, piece );
    15631500            break;
    15641501
     
    16391576    }
    16401577
    1641     assert( msglen + 1 == msgs->incoming.length );
    1642     assert( EVBUFFER_LENGTH( inbuf ) == startBufLen - msglen );
    1643 
    1644     msgs->state = AWAITING_BT_LENGTH;
    1645     return READ_NOW;
     1578    assert( EVBUFFER_LENGTH( inbuf ) == startBufLen - msglen - 1 );
     1579
     1580    msgs->incoming.length = 0;
     1581    return ret;
    16461582}
    16471583
     
    17441680
    17451681    if( !inlen )
    1746     {
    1747         ret = READ_LATER;
    1748     }
    1749     else if( msgs->state == AWAITING_BT_PIECE )
    1750     {
    1751         ret = inlen ? readBtPiece( msgs, in, inlen, piece ) : READ_LATER;
    1752     }
    1753     else switch( msgs->state )
    1754     {
    1755         case AWAITING_BT_LENGTH:
    1756             ret = readBtLength ( msgs, in, inlen ); break;
    1757 
    1758         case AWAITING_BT_ID:
    1759             ret = readBtId     ( msgs, in, inlen ); break;
    1760 
    1761         case AWAITING_BT_MESSAGE:
    1762             ret = readBtMessage( msgs, in, inlen ); break;
    1763 
    1764         default:
    1765             assert( 0 );
    1766     }
     1682        return READ_LATER;
     1683
     1684    /* Incoming data is processed in two stages. First the length is read
     1685     * and then readBtMessage() waits until all the data has arrived in
     1686     * the input buffer before starting to parse it */
     1687    if( msgs->incoming.length == 0 )
     1688        ret = readBtLength ( msgs, in, inlen );
     1689    else
     1690        ret = readBtMessage( msgs, in, inlen, piece );
    17671691
    17681692    /* log the raw data that was read */
     
    22472171    m->peer->peerIsInterested = 0;
    22482172    m->peer->have = tr_bitfieldNew( torrent->info.pieceCount );
    2249     m->state = AWAITING_BT_LENGTH;
    22502173    m->pexTimer = tr_timerNew( m->session, pexPulse, m, PEX_INTERVAL );
    22512174    m->outMessages = evbuffer_new( );
Note: See TracChangeset for help on using the changeset viewer.