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; val->val.i = num;
} }
int tr_bencListAppend( benc_val_t * val, ... ) int tr_bencListReserve( benc_val_t * val, int count )
{
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 )
{ {
assert( TYPE_LIST == val->type ); assert( TYPE_LIST == val->type );
@ -363,75 +330,48 @@ int tr_bencListExtend( benc_val_t * val, int count )
return 0; return 0;
} }
static inline int _tr_bencDictAppend( benc_val_t * val, va_list ap, int tr_bencDictReserve( benc_val_t * val, int count )
va_list ap2, int nofree )
{ {
int len;
char * key;
benc_val_t ** ptr;
assert( TYPE_DICT == val->type ); assert( TYPE_DICT == val->type );
len = 0; if( makeroom( val, count * 2 ) )
while( NULL != va_arg( ap, char * ) )
{
ptr = va_arg( ap, benc_val_t ** );
assert( NULL != ptr );
len += 2;
}
if( makeroom( val, len ) )
{ {
return 1; 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; return 0;
} }
int tr_bencDictAppend( benc_val_t * val, ... ) benc_val_t * tr_bencListAdd( benc_val_t * list )
{ {
va_list ap, ap2; benc_val_t * item;
int ret;
va_start( ap, val ); assert( TYPE_LIST == list->type );
va_start( ap2, val ); assert( list->val.l.count < list->val.l.alloc );
ret = _tr_bencDictAppend( val, ap, ap2, 0 );
va_end( ap2 );
va_end( ap );
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; benc_val_t * keyval, * itemval;
int ret;
va_start( ap, val ); assert( TYPE_DICT == dict->type );
va_start( ap2, val ); assert( dict->val.l.count + 2 <= dict->val.l.alloc );
ret = _tr_bencDictAppend( val, ap, ap2, 1 );
va_end( ap2 );
va_end( ap );
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 ) 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 ); void _tr_bencInitStr( benc_val_t * val, char * str, int len, int nofree );
int tr_bencInitStrDup( benc_val_t * val, const char * str ); int tr_bencInitStrDup( benc_val_t * val, const char * str );
void tr_bencInitInt( benc_val_t * val, int64_t num ); void tr_bencInitInt( benc_val_t * val, int64_t num );
/* args are a NULL terminated list of benc_val_t** */ int tr_bencListReserve( benc_val_t * list, int count );
int tr_bencListAppend( benc_val_t * val, ... ); /* note that for one key-value pair, count should be 1, not 2 */
/* args are a NULL terminated list of pairs of char * key, benc_val_t ** val */ int tr_bencDictReserve( benc_val_t * dict, int count );
int tr_bencDictAppend( benc_val_t * val, ... ); benc_val_t * tr_bencListAdd( benc_val_t * list );
/* like tr_bencDictAppend but char * key args are marked nofree */ /* note: key must not be freed or modified while val is in use */
int tr_bencDictAppendNofree( benc_val_t * val, ... ); benc_val_t * tr_bencDictAdd( benc_val_t * dict, const char * key );
/* insure val has room for at least count more items */
int tr_bencListExtend( benc_val_t * val, int count );
char * tr_bencSaveMalloc( benc_val_t * val, int * len ); char * tr_bencSaveMalloc( benc_val_t * val, int * len );
int tr_bencSave( benc_val_t * val, char ** buf, 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 ) makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
{ {
char * buf; char * buf;
benc_val_t val, * idval, * clientval, * versval; benc_val_t val, * msgsval, * msgdictval;
benc_val_t * tcpval, * msgsval, * msgdictval, * msgidval, * msgversval;
int len, max, idx; int len, max, idx;
uint8_t vers; 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 */ /* start building a dictionary for handshake data */
tr_bencInit( &val, TYPE_DICT ); tr_bencInit( &val, TYPE_DICT );
if( tr_bencDictAppendNofree( &val, if( tr_bencDictReserve( &val, 5 ) )
"identity", &idval,
"client", &clientval,
"version", &versval,
"tcp_port", &tcpval,
"messages", &msgsval,
NULL ) )
{ {
free( buf ); free( buf );
tr_bencFree( &val ); tr_bencFree( &val );
@ -137,13 +130,23 @@ makeAZHandshake( tr_torrent_t * tor, tr_peer_t * peer, int * buflen )
} }
/* fill in the dictionary values */ /* fill in the dictionary values */
tr_bencInitStr( idval, tor->azId, TR_AZ_ID_LEN, 1 ); tr_bencInitStr( tr_bencDictAdd( &val, "identity" ),
tr_bencInitStr( clientval, TR_NAME, 0, 1 ); tor->azId, TR_AZ_ID_LEN, 1 );
tr_bencInitStr( versval, VERSION_STRING, 0, 1 ); tr_bencInitStr( tr_bencDictAdd( &val, "client" ), TR_NAME, 0, 1 );
tr_bencInitInt( tcpval, tor->publicPort ); tr_bencInitStr( tr_bencDictAdd( &val, "version" ), VERSION_STRING, 0, 1 );
tr_bencInit( msgsval, TYPE_LIST ); 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; vers = AZ_EXT_VERSION;
for( idx = 0; azmsgCount() > idx; idx++ ) 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 */ /* no point in saying we can do pex if the torrent is private */
continue; 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 */ /* each item in the list is a dict with id and ver keys */
msgdictval = tr_bencListAdd( msgsval );
tr_bencInit( msgdictval, TYPE_DICT ); tr_bencInit( msgdictval, TYPE_DICT );
if( tr_bencDictAppendNofree( msgdictval, if( tr_bencDictReserve( msgdictval, 2 ) )
"id", &msgidval,
"ver", &msgversval,
NULL ) )
{ {
tr_bencFree( &val ); tr_bencFree( &val );
free( buf ); free( buf );
return NULL; return NULL;
} }
tr_bencInitStr( msgidval, azmsgStr( idx ), azmsgLen( idx ), 1 ); tr_bencInitStr( tr_bencDictAdd( msgdictval, "id" ),
tr_bencInitStr( msgversval, &vers, 1, 1 ); azmsgStr( idx ), azmsgLen( idx ), 1 );
tr_bencInitStr( tr_bencDictAdd( msgdictval, "ver" ), &vers, 1, 1 );
} }
/* bencode the dictionary and append it to the buffer */ /* 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 static int
peertreeToBencAZ( tr_peertree_t * tree, benc_val_t * val ) peertreeToBencAZ( tr_peertree_t * tree, benc_val_t * val )
{ {
int count, jj; int count;
tr_peertree_entry_t * ii; tr_peertree_entry_t * ii;
tr_bencInit( val, TYPE_LIST ); tr_bencInit( val, TYPE_LIST );
@ -209,20 +205,16 @@ peertreeToBencAZ( tr_peertree_t * tree, benc_val_t * val )
{ {
return 0; return 0;
} }
if( tr_bencListExtend( val, count ) ) if( tr_bencListReserve( val, count ) )
{ {
return 1; return 1;
} }
ii = peertreeFirst( tree ); ii = peertreeFirst( tree );
jj = val->val.l.count;
while( NULL != ii ) while( NULL != ii )
{ {
assert( jj < val->val.l.alloc ); tr_bencInitStr( tr_bencListAdd( val ), ii->peer, 6, 1 );
tr_bencInitStr( &val->val.l.vals[jj], ii->peer, 6, 1 );
val->val.l.count++;
ii = peertreeNext( tree, ii ); ii = peertreeNext( tree, ii );
jj++;
} }
return 0; return 0;

View File

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