mirror of
https://github.com/transmission/transmission
synced 2025-03-04 10:38:13 +00:00
Add iterator function for bencoded lists.
This commit is contained in:
parent
0c1c57a62a
commit
978b5cec11
5 changed files with 239 additions and 138 deletions
|
@ -24,33 +24,33 @@
|
|||
|
||||
#include "transmission.h"
|
||||
|
||||
#define LIST_SIZE 20
|
||||
/* setting to 1 to help expose bugs with tr_bencListAdd and tr_bencDictAdd */
|
||||
#define LIST_SIZE 20 /* number of items to increment list/dict buffer by */
|
||||
|
||||
static int makeroom( benc_val_t * val, int count )
|
||||
{
|
||||
int len;
|
||||
int len;
|
||||
void * new;
|
||||
|
||||
assert( TYPE_LIST == val->type || TYPE_DICT == val->type );
|
||||
|
||||
len = val->val.l.alloc;
|
||||
while( val->val.l.count + count >= len )
|
||||
if( val->val.l.count + count <= val->val.l.alloc )
|
||||
{
|
||||
len += LIST_SIZE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( len > val->val.l.alloc )
|
||||
/* We need a bigger boat */
|
||||
|
||||
len = val->val.l.alloc + count + ( count % LIST_SIZE ? 0 : LIST_SIZE );
|
||||
new = realloc( val->val.l.vals, len * sizeof( benc_val_t ) );
|
||||
if( NULL == new )
|
||||
{
|
||||
/* We need a bigger boat */
|
||||
new = realloc( val->val.l.vals, len * sizeof( benc_val_t ) );
|
||||
if( NULL == new )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
val->val.l.alloc = len;
|
||||
val->val.l.vals = new;
|
||||
return 1;
|
||||
}
|
||||
|
||||
val->val.l.alloc = len;
|
||||
val->val.l.vals = new;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -69,10 +69,10 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
end = &foo;
|
||||
}
|
||||
|
||||
val->begin = buf;
|
||||
|
||||
if( buf[0] == 'i' )
|
||||
{
|
||||
int64_t num;
|
||||
|
||||
e = memchr( &buf[1], 'e', len - 1 );
|
||||
if( NULL == e )
|
||||
{
|
||||
|
@ -80,16 +80,16 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
}
|
||||
|
||||
/* Integer: i1242e */
|
||||
val->type = TYPE_INT;
|
||||
*e = '\0';
|
||||
val->val.i = strtoll( &buf[1], &p, 10 );
|
||||
*e = 'e';
|
||||
*e = '\0';
|
||||
num = strtoll( &buf[1], &p, 10 );
|
||||
*e = 'e';
|
||||
|
||||
if( p != e )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
tr_bencInitInt( val, num );
|
||||
val->end = p + 1;
|
||||
}
|
||||
else if( buf[0] == 'l' || buf[0] == 'd' )
|
||||
|
@ -102,13 +102,10 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
char is_dict;
|
||||
char str_expected;
|
||||
|
||||
is_dict = ( buf[0] == 'd' );
|
||||
val->type = is_dict ? TYPE_DICT : TYPE_LIST;
|
||||
val->val.l.alloc = LIST_SIZE;
|
||||
val->val.l.count = 0;
|
||||
val->val.l.vals = malloc( LIST_SIZE * sizeof( benc_val_t ) );
|
||||
cur = &buf[1];
|
||||
str_expected = 1;
|
||||
is_dict = ( buf[0] == 'd' );
|
||||
cur = &buf[1];
|
||||
str_expected = 1;
|
||||
tr_bencInit( val, ( is_dict ? TYPE_DICT : TYPE_LIST ) );
|
||||
while( cur - buf < len && cur[0] != 'e' )
|
||||
{
|
||||
if( makeroom( val, 1 ) ||
|
||||
|
@ -140,6 +137,9 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
}
|
||||
else
|
||||
{
|
||||
int slen;
|
||||
char * sbuf;
|
||||
|
||||
e = memchr( buf, ':', len );
|
||||
if( NULL == e )
|
||||
{
|
||||
|
@ -147,24 +147,29 @@ int _tr_bencLoad( char * buf, int len, benc_val_t * val, char ** end )
|
|||
}
|
||||
|
||||
/* String: 12:whateverword */
|
||||
val->type = TYPE_STR;
|
||||
e[0] = '\0';
|
||||
val->val.s.i = strtol( buf, &p, 10 );
|
||||
e[0] = ':';
|
||||
e[0] = '\0';
|
||||
slen = strtol( buf, &p, 10 );
|
||||
e[0] = ':';
|
||||
|
||||
if( p != e || 0 > val->val.s.i ||
|
||||
val->val.s.i > len - ((p + 1) - buf) )
|
||||
if( p != e || 0 > slen || len - ( ( p + 1 ) - buf ) < slen )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
val->val.s.s = malloc( val->val.s.i + 1 );
|
||||
val->val.s.s[val->val.s.i] = 0;
|
||||
memcpy( val->val.s.s, p + 1, val->val.s.i );
|
||||
sbuf = malloc( slen + 1 );
|
||||
if( NULL == sbuf )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy( sbuf, p + 1, slen );
|
||||
sbuf[slen] = '\0';
|
||||
tr_bencInitStr( val, sbuf, slen, 0 );
|
||||
|
||||
val->end = p + 1 + val->val.s.i;
|
||||
}
|
||||
|
||||
val->begin = buf;
|
||||
*end = val->end;
|
||||
|
||||
return 0;
|
||||
|
@ -238,15 +243,23 @@ void tr_bencFree( benc_val_t * val )
|
|||
|
||||
benc_val_t * tr_bencDictFind( benc_val_t * val, const char * key )
|
||||
{
|
||||
int i;
|
||||
int len, i;
|
||||
|
||||
if( val->type != TYPE_DICT )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = strlen( key );
|
||||
|
||||
for( i = 0; i < val->val.l.count; i += 2 )
|
||||
{
|
||||
if( !strcmp( val->val.l.vals[i].val.s.s, key ) )
|
||||
if( TYPE_STR != val->val.l.vals[i].type ||
|
||||
len != val->val.l.vals[i].val.s.i )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if( 0 == memcmp(val->val.l.vals[i].val.s.s, key, len ) )
|
||||
{
|
||||
return &val->val.l.vals[i+1];
|
||||
}
|
||||
|
@ -275,6 +288,30 @@ benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... )
|
|||
return ret;
|
||||
}
|
||||
|
||||
benc_val_t * tr_bencListIter( benc_val_t * list, int * pos )
|
||||
{
|
||||
assert( TYPE_LIST == list->type );
|
||||
|
||||
if( NULL == list->val.l.vals )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( 0 > *pos )
|
||||
{
|
||||
*pos = 0;
|
||||
}
|
||||
|
||||
if( list->val.l.count <= *pos )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(*pos)++;
|
||||
|
||||
return &list->val.l.vals[ (*pos) - 1 ];
|
||||
}
|
||||
|
||||
char * tr_bencStealStr( benc_val_t * val )
|
||||
{
|
||||
assert( TYPE_STR == val->type );
|
||||
|
|
|
@ -60,6 +60,8 @@ void tr_bencFree( benc_val_t * val );
|
|||
benc_val_t * tr_bencDictFind( benc_val_t * val, const char * key );
|
||||
benc_val_t * tr_bencDictFindFirst( benc_val_t * val, ... );
|
||||
|
||||
benc_val_t * tr_bencListIter( benc_val_t * list, int * pos );
|
||||
|
||||
/* marks a string as 'do not free' and returns it */
|
||||
char * tr_bencStealStr( benc_val_t * val );
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@ static char * readtorrent( const char * path, const char * hash,
|
|||
static int savetorrent( const char * hash, const char * tag,
|
||||
const uint8_t * buf, size_t buflen );
|
||||
static int getfile( char * buf, int size,
|
||||
const char * prefix, const benc_val_t * name );
|
||||
const char * prefix, benc_val_t * name );
|
||||
static int getannounce( tr_info_t * inf, benc_val_t * meta );
|
||||
static char * announceToScrape( const char * announce );
|
||||
static int parseFiles( tr_info_t * inf, benc_val_t * name,
|
||||
benc_val_t * files, benc_val_t * length );
|
||||
static void strcatUTF8( char *, int, const char *, int );
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -50,7 +52,7 @@ int tr_metainfoParse( tr_info_t * inf, const char * tag, const char * path,
|
|||
const char * savedHash, int saveCopy )
|
||||
{
|
||||
char * buf;
|
||||
benc_val_t meta, * beInfo, * list, * val, * val2;
|
||||
benc_val_t meta, * beInfo, * val, * val2;
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
|
@ -173,60 +175,13 @@ int tr_metainfoParse( tr_info_t * inf, const char * tag, const char * path,
|
|||
|
||||
/* get file or top directory name */
|
||||
val = tr_bencDictFindFirst( beInfo, "name.utf-8", "name", NULL );
|
||||
if( NULL == val || TYPE_STR != val->type )
|
||||
if( parseFiles( inf, tr_bencDictFindFirst( beInfo,
|
||||
"name.utf-8", "name", NULL ),
|
||||
tr_bencDictFind( beInfo, "files" ),
|
||||
tr_bencDictFind( beInfo, "length" ) ) )
|
||||
{
|
||||
tr_err( "%s \"name\" string", ( val ? "Invalid" : "Missing" ) );
|
||||
goto fail;
|
||||
}
|
||||
strcatUTF8( inf->name, sizeof( inf->name ), val->val.s.s, 1 );
|
||||
if( '\0' == inf->name[0] )
|
||||
{
|
||||
tr_err( "Invalid \"name\" string" );
|
||||
goto fail;
|
||||
}
|
||||
inf->totalSize = 0;
|
||||
|
||||
if( ( list = tr_bencDictFind( beInfo, "files" ) ) )
|
||||
{
|
||||
/* Multi-file mode */
|
||||
inf->multifile = 1;
|
||||
inf->fileCount = list->val.l.count;
|
||||
inf->files = calloc( inf->fileCount, sizeof( tr_file_t ) );
|
||||
|
||||
for( i = 0; i < list->val.l.count; i++ )
|
||||
{
|
||||
val = tr_bencDictFindFirst( &list->val.l.vals[i],
|
||||
"path.utf-8", "path", NULL );
|
||||
if( getfile( inf->files[i].name, sizeof( inf->files[i].name ),
|
||||
inf->name, val ) )
|
||||
{
|
||||
tr_err( "%s \"path\" entry", ( val ? "Invalid" : "Missing" ) );
|
||||
goto fail;
|
||||
}
|
||||
val = tr_bencDictFind( &list->val.l.vals[i], "length" );
|
||||
inf->files[i].length = val->val.i;
|
||||
inf->totalSize += val->val.i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Single-file mode */
|
||||
inf->multifile = 0;
|
||||
inf->fileCount = 1;
|
||||
inf->files = calloc( sizeof( tr_file_t ), 1 );
|
||||
|
||||
strcatUTF8( inf->files[0].name, sizeof( inf->files[0].name),
|
||||
val->val.s.s, 1 );
|
||||
|
||||
val = tr_bencDictFind( beInfo, "length" );
|
||||
if( NULL == val || TYPE_INT != val->type )
|
||||
{
|
||||
tr_err( "%s \"length\" entry", ( val ? "Invalid" : "Missing" ) );
|
||||
goto fail;
|
||||
}
|
||||
inf->files[0].length = val->val.i;
|
||||
inf->totalSize += val->val.i;
|
||||
}
|
||||
|
||||
if( (uint64_t) inf->pieceCount !=
|
||||
( inf->totalSize + inf->pieceSize - 1 ) / inf->pieceSize )
|
||||
|
@ -271,11 +226,11 @@ void tr_metainfoFree( tr_info_t * inf )
|
|||
}
|
||||
|
||||
static int getfile( char * buf, int size,
|
||||
const char * prefix, const benc_val_t * name )
|
||||
const char * prefix, benc_val_t * name )
|
||||
{
|
||||
const benc_val_t * dir;
|
||||
const char ** list;
|
||||
int ii, jj;
|
||||
benc_val_t * dir;
|
||||
const char ** list;
|
||||
int ii, jj;
|
||||
|
||||
if( TYPE_LIST != name->type )
|
||||
{
|
||||
|
@ -288,13 +243,13 @@ static int getfile( char * buf, int size,
|
|||
return 1;
|
||||
}
|
||||
|
||||
for( ii = jj = 0; name->val.l.count > ii; ii++ )
|
||||
ii = jj = 0;
|
||||
while( NULL != ( dir = tr_bencListIter( name, &ii ) ) )
|
||||
{
|
||||
if( TYPE_STR != name->val.l.vals[ii].type )
|
||||
if( TYPE_STR != dir->type )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dir = &name->val.l.vals[ii];
|
||||
if( 0 == strcmp( "..", dir->val.s.s ) )
|
||||
{
|
||||
if( 0 < jj )
|
||||
|
@ -327,11 +282,10 @@ static int getfile( char * buf, int size,
|
|||
|
||||
static int getannounce( tr_info_t * inf, benc_val_t * meta )
|
||||
{
|
||||
benc_val_t * val, * subval, * urlval;
|
||||
char * address, * announce;
|
||||
int ii, jj, port, random;
|
||||
benc_val_t * val, * subval, * urlval;
|
||||
char * address, * announce;
|
||||
int ii, jj, port, random, subcount;
|
||||
tr_tracker_info_t * sublist;
|
||||
int subcount;
|
||||
void * swapping;
|
||||
|
||||
/* Announce-list */
|
||||
|
@ -343,9 +297,9 @@ static int getannounce( tr_info_t * inf, benc_val_t * meta )
|
|||
val->val.l.count );
|
||||
|
||||
/* iterate through the announce-list's tiers */
|
||||
for( ii = 0; ii < val->val.l.count; ii++ )
|
||||
ii = 0;
|
||||
while( NULL != ( subval = tr_bencListIter( val, &ii ) ) )
|
||||
{
|
||||
subval = &val->val.l.vals[ii];
|
||||
if( TYPE_LIST != subval->type || 0 >= subval->val.l.count )
|
||||
{
|
||||
continue;
|
||||
|
@ -354,9 +308,9 @@ static int getannounce( tr_info_t * inf, benc_val_t * meta )
|
|||
sublist = calloc( sizeof( sublist[0] ), subval->val.l.count );
|
||||
|
||||
/* iterate through the tier's items */
|
||||
for( jj = 0; jj < subval->val.l.count; jj++ )
|
||||
jj = 0;
|
||||
while( NULL != ( urlval = tr_bencListIter( subval, &jj ) ) )
|
||||
{
|
||||
urlval = &subval->val.l.vals[jj];
|
||||
if( TYPE_STR != urlval->type ||
|
||||
tr_httpParseUrl( urlval->val.s.s, urlval->val.s.i,
|
||||
&address, &port, &announce ) )
|
||||
|
@ -377,7 +331,7 @@ static int getannounce( tr_info_t * inf, benc_val_t * meta )
|
|||
subcount++;
|
||||
}
|
||||
|
||||
/* just use sublist as is if it's full */
|
||||
/* just use sublist as-is if it's full */
|
||||
if( subcount == subval->val.l.count )
|
||||
{
|
||||
inf->trackerList[inf->trackerTiers].list = sublist;
|
||||
|
@ -621,6 +575,90 @@ int savetorrent( const char * hash, const char * tag,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
parseFiles( tr_info_t * inf, benc_val_t * name,
|
||||
benc_val_t * files, benc_val_t * length )
|
||||
{
|
||||
benc_val_t * item, * path;
|
||||
int ii;
|
||||
|
||||
if( NULL == name || TYPE_STR != name->type )
|
||||
{
|
||||
tr_err( "%s \"name\" string", ( name ? "Invalid" : "Missing" ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcatUTF8( inf->name, sizeof( inf->name ), name->val.s.s, 1 );
|
||||
if( '\0' == inf->name[0] )
|
||||
{
|
||||
tr_err( "Invalid \"name\" string" );
|
||||
return 1;
|
||||
}
|
||||
inf->totalSize = 0;
|
||||
|
||||
if( files && TYPE_LIST == files->type )
|
||||
{
|
||||
/* Multi-file mode */
|
||||
inf->multifile = 1;
|
||||
inf->fileCount = files->val.l.count;
|
||||
inf->files = calloc( inf->fileCount, sizeof( inf->files[0] ) );
|
||||
|
||||
if( NULL == inf->files )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
item = NULL;
|
||||
ii = 0;
|
||||
while( NULL != ( item = tr_bencListIter( files, &ii ) ) )
|
||||
{
|
||||
path = tr_bencDictFindFirst( item, "path.utf-8", "path", NULL );
|
||||
if( getfile( inf->files[ii-1].name, sizeof( inf->files[ii-1].name ),
|
||||
inf->name, path ) )
|
||||
{
|
||||
tr_err( "%s \"path\" entry",
|
||||
( path ? "Invalid" : "Missing" ) );
|
||||
return 1;
|
||||
}
|
||||
length = tr_bencDictFind( item, "length" );
|
||||
if( NULL == length || TYPE_INT != length->type )
|
||||
{
|
||||
tr_err( "%s \"length\" entry",
|
||||
( length ? "Invalid" : "Missing" ) );
|
||||
return 1;
|
||||
}
|
||||
inf->files[ii-1].length = length->val.i;
|
||||
inf->totalSize += length->val.i;
|
||||
}
|
||||
}
|
||||
else if( NULL != length && TYPE_INT == length->type )
|
||||
{
|
||||
/* Single-file mode */
|
||||
inf->multifile = 0;
|
||||
inf->fileCount = 1;
|
||||
inf->files = calloc( 1, sizeof( inf->files[0] ) );
|
||||
|
||||
if( NULL == inf->files )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcatUTF8( inf->files[0].name, sizeof( inf->files[0].name ),
|
||||
name->val.s.s, 1 );
|
||||
|
||||
inf->files[0].length = length->val.i;
|
||||
inf->totalSize += length->val.i;
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_err( "%s \"files\" entry and %s \"length\" entry",
|
||||
( files ? "Invalid" : "Missing" ),
|
||||
( length ? "invalid" : "missing" ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* strcatUTF8
|
||||
***********************************************************************
|
||||
|
|
|
@ -382,9 +382,9 @@ parseAZHandshake( tr_peer_t * peer, uint8_t * buf, int len )
|
|||
|
||||
/* fill bitmask with supported message info */
|
||||
msgs = tr_bitfieldNew( azmsgCount() );
|
||||
for( ii = 0; ii < sub->val.l.count; ii++ )
|
||||
ii = -1;
|
||||
while( NULL != ( dict = tr_bencListIter( sub, &ii ) ) )
|
||||
{
|
||||
dict = &sub->val.l.vals[ii];
|
||||
if( TYPE_DICT != dict->type )
|
||||
{
|
||||
continue;
|
||||
|
@ -475,10 +475,9 @@ parseAZPex( tr_torrent_t * tor, tr_peer_t * peer, uint8_t * buf, int len )
|
|||
return TR_OK;
|
||||
}
|
||||
|
||||
used = 0;
|
||||
for( ii = 0; ii < list->val.l.count; ii++ )
|
||||
ii = used = 0;
|
||||
while( NULL != ( pair = tr_bencListIter( list, &ii ) ) )
|
||||
{
|
||||
pair = &list->val.l.vals[ii];
|
||||
if( TYPE_STR == pair->type && 6 == pair->val.s.i )
|
||||
{
|
||||
used += tr_torrentAddCompact( tor, TR_PEER_FROM_PEX,
|
||||
|
|
|
@ -94,6 +94,7 @@ static void readAnswer ( tr_tracker_t * tc, const char *, int,
|
|||
static void readScrapeAnswer ( tr_tracker_t * tc, const char *, int );
|
||||
static void killHttp ( tr_http_t ** http );
|
||||
static int shouldChangePort( tr_tracker_t * tc );
|
||||
static uint8_t * parseOriginalPeers( benc_val_t * bePeers, int * peerCount );
|
||||
|
||||
tr_tracker_t * tr_trackerInit( tr_torrent_t * tor )
|
||||
{
|
||||
|
@ -793,38 +794,15 @@ static void readAnswer( tr_tracker_t * tc, const char * data, int len,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if( bePeers->type & TYPE_LIST )
|
||||
if( TYPE_LIST == bePeers->type )
|
||||
{
|
||||
/* Original protocol */
|
||||
if( bePeers->val.l.count > 0 )
|
||||
{
|
||||
struct in_addr addr;
|
||||
in_port_t port;
|
||||
|
||||
peerCount = 0;
|
||||
peerCompact = malloc( 6 * bePeers->val.l.count );
|
||||
|
||||
/* Convert to compact form */
|
||||
for( i = 0; i < bePeers->val.l.count; i++ )
|
||||
{
|
||||
if( !( beFoo = tr_bencDictFind(
|
||||
&bePeers->val.l.vals[i], "ip" ) ) )
|
||||
continue;
|
||||
if( tr_netResolve( beFoo->val.s.s, &addr ) )
|
||||
continue;
|
||||
memcpy( &peerCompact[6 * peerCount], &addr, 4 );
|
||||
|
||||
if( !( beFoo = tr_bencDictFind(
|
||||
&bePeers->val.l.vals[i], "port" ) ) )
|
||||
continue;
|
||||
port = htons( beFoo->val.i );
|
||||
memcpy( &peerCompact[6 * peerCount + 4], &port, 2 );
|
||||
|
||||
peerCount++;
|
||||
}
|
||||
peerCompact = parseOriginalPeers( bePeers, &peerCount );
|
||||
}
|
||||
}
|
||||
else if( bePeers->type & TYPE_STR )
|
||||
else if( TYPE_STR == bePeers->type )
|
||||
{
|
||||
/* "Compact" extension */
|
||||
if( bePeers->val.s.i >= 6 )
|
||||
|
@ -1101,3 +1079,50 @@ static int shouldChangePort( tr_tracker_t * tc )
|
|||
|
||||
return ( tor->publicPort != tc->publicPort );
|
||||
}
|
||||
|
||||
/* Convert to compact form */
|
||||
static uint8_t *
|
||||
parseOriginalPeers( benc_val_t * bePeers, int * peerCount )
|
||||
{
|
||||
struct in_addr addr;
|
||||
in_port_t port;
|
||||
uint8_t * peerCompact;
|
||||
benc_val_t * peer, * addrval, * portval;
|
||||
int ii, count;
|
||||
|
||||
assert( TYPE_LIST == bePeers->type );
|
||||
|
||||
count = 0;
|
||||
peerCompact = malloc( 6 * bePeers->val.l.count );
|
||||
if( NULL == peerCompact )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ii = -1;
|
||||
while( NULL != ( peer = tr_bencListIter( bePeers, &ii ) ) )
|
||||
{
|
||||
addrval = tr_bencDictFind( peer, "ip" );
|
||||
if( NULL == addrval || TYPE_STR != addrval->type ||
|
||||
tr_netResolve( addrval->val.s.s, &addr ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
memcpy( &peerCompact[6 * count], &addr, 4 );
|
||||
|
||||
portval = tr_bencDictFind( peer, "port" );
|
||||
if( NULL == portval || TYPE_INT != portval->type ||
|
||||
0 > portval->val.i || 0xffff < portval->val.i )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
port = htons( portval->val.i );
|
||||
memcpy( &peerCompact[6 * count + 4], &port, 2 );
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
*peerCount = count;
|
||||
|
||||
return peerCompact;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue