Eliminate an error-prone varargs function.

This commit is contained in:
Josh Elsasser 2007-03-29 21:02:59 +00:00
parent b8530669e6
commit 0c1c57a62a
4 changed files with 86 additions and 152 deletions

View File

@ -318,40 +318,7 @@ void tr_bencInitInt( benc_val_t * val, int64_t num )
val->val.i = num;
}
int tr_bencListAppend( benc_val_t * val, ... )
{
va_list ap;
int len;
benc_val_t ** ptr;
assert( TYPE_LIST == val->type );
len = 0;
va_start( ap, val );
while( NULL != va_arg( ap, benc_val_t ** ) )
{
len++;
}
va_end( ap );
if( makeroom( val, len ) )
{
return 1;
}
va_start( ap, val );
while( NULL != ( ptr = va_arg( ap, benc_val_t ** ) ) )
{
*ptr = &val->val.l.vals[val->val.l.count];
tr_bencInit( *ptr, TYPE_INT );
val->val.l.count++;
}
va_end( ap );
return 0;
}
int tr_bencListExtend( benc_val_t * val, int count )
int tr_bencListReserve( benc_val_t * val, int count )
{
assert( TYPE_LIST == val->type );
@ -363,75 +330,48 @@ int tr_bencListExtend( benc_val_t * val, int count )
return 0;
}
static inline int _tr_bencDictAppend( benc_val_t * val, va_list ap,
va_list ap2, int nofree )
int tr_bencDictReserve( benc_val_t * val, int count )
{
int len;
char * key;
benc_val_t ** ptr;
assert( TYPE_DICT == val->type );
len = 0;
while( NULL != va_arg( ap, char * ) )
{
ptr = va_arg( ap, benc_val_t ** );
assert( NULL != ptr );
len += 2;
}
if( makeroom( val, len ) )
if( makeroom( val, count * 2 ) )
{
return 1;
}
while( NULL != ( key = va_arg( ap2, char * ) ) )
{
if( !nofree )
{
key = strdup( key );
if( NULL == key )
{
return 1;
}
}
ptr = va_arg( ap2, benc_val_t ** );
tr_bencInitStr( &val->val.l.vals[val->val.l.count], key, 0, nofree );
val->val.l.count++;
*ptr = &val->val.l.vals[val->val.l.count];
tr_bencInit( *ptr, TYPE_INT );
val->val.l.count++;
}
return 0;
}
int tr_bencDictAppend( benc_val_t * val, ... )
benc_val_t * tr_bencListAdd( benc_val_t * list )
{
va_list ap, ap2;
int ret;
benc_val_t * item;
va_start( ap, val );
va_start( ap2, val );
ret = _tr_bencDictAppend( val, ap, ap2, 0 );
va_end( ap2 );
va_end( ap );
assert( TYPE_LIST == list->type );
assert( list->val.l.count < list->val.l.alloc );
return ret;
item = &list->val.l.vals[list->val.l.count];
list->val.l.count++;
tr_bencInit( item, TYPE_INT );
return item;
}
int tr_bencDictAppendNofree( benc_val_t * val, ... )
benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key )
{
va_list ap, ap2;
int ret;
benc_val_t * keyval, * itemval;
va_start( ap, val );
va_start( ap2, val );
ret = _tr_bencDictAppend( val, ap, ap2, 1 );
va_end( ap2 );
va_end( ap );
assert( TYPE_DICT == dict->type );
assert( dict->val.l.count + 2 <= dict->val.l.alloc );
return ret;
keyval = &dict->val.l.vals[dict->val.l.count];
dict->val.l.count++;
itemval = &dict->val.l.vals[dict->val.l.count];
dict->val.l.count++;
tr_bencInitStr( keyval, key, -1, 1 );
tr_bencInit( itemval, TYPE_INT );
return itemval;
}
char * tr_bencSaveMalloc( benc_val_t * val, int * len )

View File

@ -76,15 +76,12 @@ static inline void tr_bencInit( benc_val_t * val, int type )
void _tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree );
int tr_bencInitStrDup( benc_val_t * val, const char * str );
void tr_bencInitInt( benc_val_t * val, int64_t num );
/* args are a NULL terminated list of benc_val_t** */
int tr_bencListAppend( benc_val_t * val, ... );
/* args are a NULL terminated list of pairs of char * key, benc_val_t ** val */
int tr_bencDictAppend( benc_val_t * val, ... );
/* like tr_bencDictAppend but char * key args are marked nofree */
int tr_bencDictAppendNofree( benc_val_t * val, ... );
/* insure val has room for at least count more items */
int tr_bencListExtend( benc_val_t * val, int count );
int tr_bencListReserve( benc_val_t * list, int count );
/* note that for one key-value pair, count should be 1, not 2 */
int tr_bencDictReserve( benc_val_t * dict, int count );
benc_val_t * tr_bencListAdd( benc_val_t * list );
/* note: key must not be freed or modified while val is in use */
benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key );
char * tr_bencSaveMalloc( benc_val_t * val, int * len );
int tr_bencSave( benc_val_t * val, char ** buf,

View File

@ -100,8 +100,7 @@ static uint8_t *
makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
{
char * buf;
benc_val_t val, * idval, * clientval, * versval;
benc_val_t * tcpval, * msgsval, * msgdictval, * msgidval, * msgversval;
benc_val_t val, * msgsval, * msgdictval;
int len, max, idx;
uint8_t vers;
@ -123,13 +122,7 @@ makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
/* start building a dictionary for handshake data */
tr_bencInit( &val, TYPE_DICT );
if( tr_bencDictAppendNofree( &val,
"identity", &idval,
"client", &clientval,
"version", &versval,
"tcp_port", &tcpval,
"messages", &msgsval,
NULL ) )
if( tr_bencDictReserve( &val, 5 ) )
{
free( buf );
tr_bencFree( &val );
@ -137,13 +130,23 @@ makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
}
/* fill in the dictionary values */
tr_bencInitStr( idval, tor->azId, TR_AZ_ID_LEN, 1 );
tr_bencInitStr( clientval, TR_NAME, 0, 1 );
tr_bencInitStr( versval, VERSION_STRING, 0, 1 );
tr_bencInitInt( tcpval, tor->publicPort );
tr_bencInit( msgsval, TYPE_LIST );
tr_bencInitStr( tr_bencDictAdd( &val, "identity" ),
tor->azId, TR_AZ_ID_LEN, 1 );
tr_bencInitStr( tr_bencDictAdd( &val, "client" ), TR_NAME, 0, 1 );
tr_bencInitStr( tr_bencDictAdd( &val, "version" ), VERSION_STRING, 0, 1 );
tr_bencInitInt( tr_bencDictAdd( &val, "tcp_port" ), tor->publicPort );
/* fill in the supported message list */
/* initialize supported message list */
msgsval = tr_bencDictAdd( &val, "messages" );
tr_bencInit( msgsval, TYPE_LIST );
if( tr_bencListReserve( msgsval, azmsgCount() ) )
{
tr_bencFree( &val );
free( buf );
return NULL;
}
/* fill in the message list */
vers = AZ_EXT_VERSION;
for( idx = 0; azmsgCount() > idx; idx++ )
{
@ -156,25 +159,18 @@ makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
/* no point in saying we can do pex if the torrent is private */
continue;
}
if( tr_bencListAppend( msgsval, &msgdictval, NULL ) )
{
tr_bencFree( &val );
free( buf );
return NULL;
}
/* each item in the list is a dict with id and ver keys */
msgdictval = tr_bencListAdd( msgsval );
tr_bencInit( msgdictval, TYPE_DICT );
if( tr_bencDictAppendNofree( msgdictval,
"id", &msgidval,
"ver", &msgversval,
NULL ) )
if( tr_bencDictReserve( msgdictval, 2 ) )
{
tr_bencFree( &val );
free( buf );
return NULL;
}
tr_bencInitStr( msgidval, azmsgStr( idx ), azmsgLen( idx ), 1 );
tr_bencInitStr( msgversval, &vers, 1, 1 );
tr_bencInitStr( tr_bencDictAdd( msgdictval, "id" ),
azmsgStr( idx ), azmsgLen( idx ), 1 );
tr_bencInitStr( tr_bencDictAdd( msgdictval, "ver" ), &vers, 1, 1 );
}
/* bencode the dictionary and append it to the buffer */
@ -200,7 +196,7 @@ makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
static int
peertreeToBencAZ( tr_peertree_t * tree, benc_val_t * val )
{
int count, jj;
int count;
tr_peertree_entry_t * ii;
tr_bencInit( val, TYPE_LIST );
@ -209,20 +205,16 @@ peertreeToBencAZ( tr_peertree_t * tree, benc_val_t * val )
{
return 0;
}
if( tr_bencListExtend( val, count ) )
if( tr_bencListReserve( val, count ) )
{
return 1;
}
ii = peertreeFirst( tree );
jj = val->val.l.count;
while( NULL != ii )
{
assert( jj < val->val.l.alloc );
tr_bencInitStr( &val->val.l.vals[jj], ii->peer, 6, 1 );
val->val.l.count++;
tr_bencInitStr( tr_bencListAdd( val ), ii->peer, 6, 1 );
ii = peertreeNext( tree, ii );
jj++;
}
return 0;

View File

@ -67,10 +67,19 @@ makeCommonPex( tr_torrent_t * tor, tr_peer_t * peer, int * len,
/* build the dictionaries */
tr_bencInit( &val, TYPE_DICT );
if( ( peertreeEmpty( &added ) && peertreeEmpty( sent ) ) ||
tr_bencDictAppendNofree( &val, extrakey, &extra, "added", &addval,
"dropped", &delval, NULL ) ||
(*peerfunc)( &added, addval ) ||
(*peerfunc)( sent, delval ) )
tr_bencDictReserve( &val, 3 ) )
{
tr_bencFree( &val );
peertreeMerge( sent, &common );
peertreeFree( &added );
tr_bencFree( extraval );
return NULL;
}
extra = tr_bencDictAdd( &val, extrakey );
addval = tr_bencDictAdd( &val, "added" );
delval = tr_bencDictAdd( &val, "dropped" );
assert( NULL != extra && NULL != addval && NULL != delval );
if( (*peerfunc)( &added, addval ) || (*peerfunc)( sent, delval ) )
{
tr_bencFree( &val );
peertreeMerge( sent, &common );
@ -101,12 +110,9 @@ makeCommonPex( tr_torrent_t * tor, tr_peer_t * peer, int * len,
static char *
makeExtendedHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * len )
{
benc_val_t val, * msgsval, * portval, * versval, * pexval;
benc_val_t val, * msgsval;
char * buf, * vers;
peer_dbg( "SEND extended-handshake, %s pex",
( peer->private ? "without" : "with" ) );
/* get human-readable version string */
vers = NULL;
asprintf( &vers, "%s %s", TR_NAME, VERSION_STRING );
@ -115,10 +121,9 @@ makeExtendedHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * len )
return NULL;
}
/* reserve space in toplevel dictionary for v, m, and possibly p */
tr_bencInit( &val, TYPE_DICT );
/* append v str and m dict to toplevel dictionary */
if( tr_bencDictAppendNofree( &val, "v", &versval, "m", &msgsval, NULL ) )
if( tr_bencDictReserve( &val, ( 0 < tor->publicPort ? 3 : 2 ) ) )
{
free( vers );
tr_bencFree( &val );
@ -126,41 +131,41 @@ makeExtendedHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * len )
}
/* human readable version string */
tr_bencInitStr( versval, vers, 0, 0 );
tr_bencInitStr( tr_bencDictAdd( &val, "v" ), vers, 0, 0 );
/* create dict of supported extended messages */
msgsval = tr_bencDictAdd( &val, "m" );
tr_bencInit( msgsval, TYPE_DICT );
if( !peer->private )
{
/* for public torrents advertise utorrent pex message */
if( tr_bencDictAppendNofree( msgsval, "ut_pex", &pexval, NULL ) )
/* for public torrents, advertise utorrent pex message */
if( tr_bencDictReserve( msgsval, 1 ) )
{
tr_bencFree( &val );
return NULL;
}
tr_bencInitInt( pexval, EXTENDED_PEX_ID );
tr_bencInitInt( tr_bencDictAdd( msgsval, "ut_pex" ), EXTENDED_PEX_ID );
}
/* our listening port */
if( 0 < tor->publicPort )
{
if( tr_bencDictAppendNofree( &val, "p", &portval, NULL ) )
{
tr_bencFree( &val );
return NULL;
}
tr_bencInitInt( portval, tor->publicPort );
tr_bencInitInt( tr_bencDictAdd( &val, "p" ), tor->publicPort );
}
/* bencode it */
buf = tr_bencSaveMalloc( &val, len );
tr_bencFree( &val );
if( NULL != buf )
if( NULL == buf )
{
peer->advertisedPort = tor->publicPort;
return NULL;
}
peer->advertisedPort = tor->publicPort;
peer_dbg( "SEND extended-handshake, %s pex",
( peer->private ? "without" : "with" ) );
return buf;
}