mirror of
https://github.com/transmission/transmission
synced 2024-12-25 17:17:31 +00:00
(trunk libT) patch from wereHamster to simplify BT message parsing
This commit is contained in:
parent
694a980348
commit
53b25c7b49
1 changed files with 38 additions and 115 deletions
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue