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

This commit is contained in:
Charles Kerr 2008-12-30 19:44:49 +00:00
parent 694a980348
commit 53b25c7b49
1 changed files with 38 additions and 115 deletions

View File

@ -106,14 +106,6 @@ enum
*** REQUEST MANAGEMENT *** REQUEST MANAGEMENT
**/ **/
enum
{
AWAITING_BT_LENGTH,
AWAITING_BT_ID,
AWAITING_BT_MESSAGE,
AWAITING_BT_PIECE
};
struct peer_request struct peer_request
{ {
uint32_t index; uint32_t index;
@ -252,10 +244,8 @@ reqListRemove( struct request_list * list,
* the current message that it's sending us. */ * the current message that it's sending us. */
struct tr_incoming struct tr_incoming
{ {
uint8_t id; uint32_t length; /* includes the +1 for id length */
uint32_t length; /* includes the +1 for id length */ struct evbuffer * block; /* piece data for incoming blocks */
struct peer_request blockReq; /* metadata for incoming blocks */
struct evbuffer * block; /* piece data for incoming blocks */
}; };
/** /**
@ -280,7 +270,6 @@ struct tr_peermsgs
tr_bool peerSentLtepHandshake; tr_bool peerSentLtepHandshake;
tr_bool haveFastSet; tr_bool haveFastSet;
uint8_t state;
uint8_t ut_pex_id; uint8_t ut_pex_id;
uint16_t pexCount; uint16_t pexCount;
uint16_t pexCount6; uint16_t pexCount6;
@ -1279,48 +1268,14 @@ readBtLength( tr_peermsgs * msgs,
return READ_LATER; return READ_LATER;
tr_peerIoReadUint32( msgs->peer->io, inbuf, &len ); tr_peerIoReadUint32( msgs->peer->io, inbuf, &len );
msgs->incoming.length = len;
if( len == 0 ) /* peer sent us a keepalive message */ if( len == 0 ) /* peer sent us a keepalive message */
dbgmsg( msgs, "got KeepAlive" ); dbgmsg( msgs, "got KeepAlive" );
else
{
msgs->incoming.length = len;
msgs->state = AWAITING_BT_ID;
}
return READ_NOW; return READ_NOW;
} }
static int readBtMessage( tr_peermsgs * msgs,
struct evbuffer * inbuf,
size_t inlen );
static int
readBtId( tr_peermsgs * msgs,
struct evbuffer * inbuf,
size_t inlen )
{
uint8_t id;
if( inlen < sizeof( uint8_t ) )
return READ_LATER;
tr_peerIoReadUint8( msgs->peer->io, inbuf, &id );
msgs->incoming.id = id;
if( id == BT_PIECE )
{
msgs->state = AWAITING_BT_PIECE;
return READ_NOW;
}
else if( msgs->incoming.length != 1 )
{
msgs->state = AWAITING_BT_MESSAGE;
return READ_NOW;
}
else return readBtMessage( msgs, inbuf, inlen - 1 );
}
static void static void
updatePeerProgress( tr_peermsgs * msgs ) updatePeerProgress( tr_peermsgs * msgs )
{ {
@ -1407,55 +1362,34 @@ readBtPiece( tr_peermsgs * msgs,
size_t inlen, size_t inlen,
size_t * setme_piece_bytes_read ) size_t * setme_piece_bytes_read )
{ {
struct peer_request * req = &msgs->incoming.blockReq; struct peer_request req;
assert( EVBUFFER_LENGTH( inbuf ) >= inlen ); assert( EVBUFFER_LENGTH( inbuf ) >= inlen );
dbgmsg( msgs, "In readBtPiece" ); dbgmsg( msgs, "In readBtPiece" );
if( !req->length ) tr_peerIoReadUint32( msgs->peer->io, inbuf, &req.index );
{ tr_peerIoReadUint32( msgs->peer->io, inbuf, &req.offset );
if( inlen < 8 ) req.length = msgs->incoming.length - 9;
return READ_LATER; dbgmsg( msgs, "got incoming block header %u:%u->%u", req.index, req.offset, req.length );
tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->index ); {
tr_peerIoReadUint32( msgs->peer->io, inbuf, &req->offset );
req->length = msgs->incoming.length - 9;
dbgmsg( msgs, "got incoming block header %u:%u->%u", req->index, req->offset, req->length );
return READ_NOW;
}
else
{
int err; int err;
/* read in another chunk of data */ /* decrypt the whole block in one go */
const size_t nLeft = req->length - EVBUFFER_LENGTH( msgs->incoming.block ); evbuffer_expand( msgs->incoming.block, req.length );
size_t n = MIN( nLeft, inlen ); tr_peerIoReadBytes( msgs->peer->io, inbuf, EVBUFFER_DATA( msgs->incoming.block ), req.length );
size_t i = n; EVBUFFER_LENGTH( msgs->incoming.block ) += req.length;
while( i > 0 ) fireClientGotData( msgs, req.length, TRUE );
{ *setme_piece_bytes_read += req.length;
uint8_t buf[MAX_STACK_ARRAY_SIZE]; dbgmsg( msgs, "got block %u:%u->%u", req.index, req.offset, req.length );
const size_t thisPass = MIN( i, sizeof( buf ) ); assert( EVBUFFER_LENGTH( msgs->incoming.block ) == req.length );
tr_peerIoReadBytes( msgs->peer->io, inbuf, buf, thisPass );
evbuffer_add( msgs->incoming.block, buf, thisPass );
i -= thisPass;
}
fireClientGotData( msgs, n, TRUE );
*setme_piece_bytes_read += n;
dbgmsg( msgs, "got %zu bytes for block %u:%u->%u ... %d remain",
n, req->index, req->offset, req->length,
(int)( req->length - EVBUFFER_LENGTH( msgs->incoming.block ) ) );
if( EVBUFFER_LENGTH( msgs->incoming.block ) < req->length )
return READ_LATER;
/* we've got the whole block ... process it */ /* we've got the whole block ... process it */
err = clientGotBlock( msgs, EVBUFFER_DATA( msgs->incoming.block ), req ); err = clientGotBlock( msgs, EVBUFFER_DATA( msgs->incoming.block ), &req );
/* cleanup */ /* cleanup */
evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH( msgs->incoming.block ) ); evbuffer_drain( msgs->incoming.block, EVBUFFER_LENGTH( msgs->incoming.block ) );
req->length = 0;
msgs->state = AWAITING_BT_LENGTH;
if( !err ) if( !err )
return READ_NOW; return READ_NOW;
else { else {
@ -1466,28 +1400,31 @@ readBtPiece( tr_peermsgs * msgs,
} }
static int static int
readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen ) readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen, size_t * piece )
{ {
int ret = READ_NOW;
uint8_t id;
uint32_t ui32; uint32_t ui32;
uint32_t msglen = msgs->incoming.length; uint32_t msglen = msgs->incoming.length;
const uint8_t id = msgs->incoming.id;
const size_t startBufLen = EVBUFFER_LENGTH( inbuf ); const size_t startBufLen = EVBUFFER_LENGTH( inbuf );
const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io ); const tr_bool fext = tr_peerIoSupportsFEXT( msgs->peer->io );
--msglen; /* id length */
if( inlen < msglen ) if( inlen < msglen )
return READ_LATER; return READ_LATER;
tr_peerIoReadUint8( msgs->peer->io, inbuf, &id );
dbgmsg( msgs, "got BT id %d, len %d, buffer size is %zu", (int)id, (int)msglen, inlen ); dbgmsg( msgs, "got BT id %d, len %d, buffer size is %zu", (int)id, (int)msglen, inlen );
if( !messageLengthIsCorrect( msgs, id, msglen + 1 ) ) if( !messageLengthIsCorrect( msgs, id, msglen ) )
{ {
dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen ); dbgmsg( msgs, "bad packet - BT message #%d with a length of %d", (int)id, (int)msglen );
fireError( msgs, EMSGSIZE ); fireError( msgs, EMSGSIZE );
return READ_ERR; return READ_ERR;
} }
--msglen;
switch( id ) switch( id )
{ {
case BT_CHOKE: case BT_CHOKE:
@ -1559,7 +1496,7 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
} }
case BT_PIECE: case BT_PIECE:
assert( 0 ); /* handled elsewhere! */ ret = readBtPiece( msgs, inbuf, msglen, piece );
break; break;
case BT_PORT: case BT_PORT:
@ -1638,11 +1575,10 @@ readBtMessage( tr_peermsgs * msgs, struct evbuffer * inbuf, size_t inlen )
break; break;
} }
assert( msglen + 1 == msgs->incoming.length ); assert( EVBUFFER_LENGTH( inbuf ) == startBufLen - msglen - 1 );
assert( EVBUFFER_LENGTH( inbuf ) == startBufLen - msglen );
msgs->state = AWAITING_BT_LENGTH; msgs->incoming.length = 0;
return READ_NOW; return ret;
} }
static void static void
@ -1743,27 +1679,15 @@ canRead( tr_peerIo * io, void * vmsgs, size_t * piece )
const size_t inlen = EVBUFFER_LENGTH( in ); const size_t inlen = EVBUFFER_LENGTH( in );
if( !inlen ) if( !inlen )
{ return READ_LATER;
ret = READ_LATER;
}
else if( msgs->state == AWAITING_BT_PIECE )
{
ret = inlen ? readBtPiece( msgs, in, inlen, piece ) : READ_LATER;
}
else switch( msgs->state )
{
case AWAITING_BT_LENGTH:
ret = readBtLength ( msgs, in, inlen ); break;
case AWAITING_BT_ID: /* Incoming data is processed in two stages. First the length is read
ret = readBtId ( msgs, in, inlen ); break; * and then readBtMessage() waits until all the data has arrived in
* the input buffer before starting to parse it */
case AWAITING_BT_MESSAGE: if( msgs->incoming.length == 0 )
ret = readBtMessage( msgs, in, inlen ); break; ret = readBtLength ( msgs, in, inlen );
else
default: ret = readBtMessage( msgs, in, inlen, piece );
assert( 0 );
}
/* log the raw data that was read */ /* log the raw data that was read */
if( ( ret != READ_ERR ) && ( EVBUFFER_LENGTH( in ) != inlen ) ) if( ( ret != READ_ERR ) && ( EVBUFFER_LENGTH( in ) != inlen ) )
@ -2246,7 +2170,6 @@ tr_peerMsgsNew( struct tr_torrent * torrent,
m->peer->clientIsInterested = 0; m->peer->clientIsInterested = 0;
m->peer->peerIsInterested = 0; m->peer->peerIsInterested = 0;
m->peer->have = tr_bitfieldNew( torrent->info.pieceCount ); m->peer->have = tr_bitfieldNew( torrent->info.pieceCount );
m->state = AWAITING_BT_LENGTH;
m->pexTimer = tr_timerNew( m->session, pexPulse, m, PEX_INTERVAL ); m->pexTimer = tr_timerNew( m->session, pexPulse, m, PEX_INTERVAL );
m->outMessages = evbuffer_new( ); m->outMessages = evbuffer_new( );
m->outMessagesBatchedAt = 0; m->outMessagesBatchedAt = 0;