return;
}
- res = ipc_parse( con->ipc, buf, len, con );
+ res = ipc_handleMessages( con->ipc, buf, len, con );
if( 0 > res )
{
switch( errno )
break;
case IPC_MSG_GETINFOALL:
case IPC_MSG_GETSTATALL:
- buf = ipc_mkgetinfo( con->ipc, &buflen, req->id, req->tag,
- req->types, NULL );
+ buf = ipc_createInfoRequest( con->ipc, &buflen, req->id, req->tag,
+ req->types, NULL );
break;
default:
assert( 0 );
infomsg( enum ipc_msg msgid, benc_val_t * list, int64_t tag,
void * arg UNUSED )
{
- benc_val_t * dict;
int ii;
struct cl_info inf;
int64_t id;
assert( IPC_MSG_INFO == msgid );
- if( TYPE_LIST != list->type )
- {
+ if( !tr_bencIsList( list ) )
return;
- }
memset( &key, 0, sizeof key );
key.tag = tag;
for( ii = 0; list->val.l.count > ii; ii++ )
{
- dict = &list->val.l.vals[ii];
- if( TYPE_DICT != dict->type )
- {
+ tr_benc * dict = &list->val.l.vals[ii];
+
+ if( !tr_bencIsDict( dict ) )
continue;
- }
id = getinfoint( msgid, dict, IPC_INF_ID, -1 );
inf.name = getinfostr( msgid, dict, IPC_INF_NAME, NULL );
statmsg( enum ipc_msg msgid, benc_val_t * list, int64_t tag,
void * arg UNUSED )
{
- benc_val_t * dict;
int ii;
int64_t id;
struct cl_stat st;
assert( IPC_MSG_STAT == msgid );
- if( TYPE_LIST != list->type )
- {
+ if( !tr_bencIsList( list ) )
return;
- }
memset( &key, 0, sizeof key );
key.tag = tag;
for( ii = 0; list->val.l.count > ii; ii++ )
{
- dict = &list->val.l.vals[ii];
- if( TYPE_DICT != dict->type )
- {
+ tr_benc * dict = &list->val.l.vals[ii];
+
+ if( !tr_bencIsDict( dict ) )
continue;
- }
id = getinfoint( msgid, dict, IPC_ST_ID, -1 );
st.state = getinfostr( msgid, dict, IPC_ST_STATE, NULL );
void
cbdone( struct resp * resp )
{
- if( NULL != resp->infocb )
+ if( resp->infocb )
{
resp->infocb( NULL );
}
- else if( NULL != resp->statcb )
+ else if( resp->statcb )
{
resp->statcb( NULL );
}
int64_t
getinfoint( enum ipc_msg msgid, benc_val_t * dict, int type, int64_t defval )
{
- benc_val_t * val;
-
- val = tr_bencDictFind( dict, ipc_infoname( msgid, type ) );
-
- if( NULL != val && TYPE_INT == val->type )
- {
- return val->val.i;
- }
-
- return defval;
+ const char * key = ipc_infoname( msgid, type );
+ benc_val_t * val = tr_bencDictFind( dict, key );
+ return tr_bencIsInt( val ) ? val->val.i : defval;
}
char *
getinfostr( enum ipc_msg msgid, benc_val_t * dict, int type, char * defval )
{
- benc_val_t * val;
-
- val = tr_bencDictFind( dict, ipc_infoname( msgid, type ) );
-
- if( NULL != val && TYPE_STR == val->type )
- {
- return val->val.s.s ;
- }
-
- return defval;
+ const char * key = ipc_infoname( msgid, type );
+ benc_val_t * val = tr_bencDictFind( dict, key );
+ return tr_bencIsString( val ) ? val->val.s.s : defval;
}
return;
}
- res = ipc_parse( client->ipc, buf, len, client );
+ res = ipc_handleMessages( client->ipc, buf, len, client );
if( gl_exiting )
{
addmsg1( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
{
struct client * client = arg;
- benc_val_t pk, * added, * file;
+ benc_val_t pk, * added;
int ii, tor;
size_t buflen;
uint8_t * buf;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
for( ii = 0; ii < val->val.l.count; ii++ )
{
- file = &val->val.l.vals[ii];
- if( TYPE_STR != file->type )
- {
+ tr_benc * file = &val->val.l.vals[ii];
+ if( !tr_bencIsString( file ) )
continue;
- }
+
/* XXX need to somehow inform client of skipped or failed files */
tor = torrent_add_file( file->val.s.s, NULL, -1 );
if( TORRENT_ID_VALID( tor ) )
uint8_t * buf;
const char * dir;
- if( NULL == dict || TYPE_DICT != dict->type )
+ if( !tr_bencIsDict( dict ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
}
val = tr_bencDictFind( dict, "directory" );
- dir = ( NULL == val || TYPE_STR != val->type ? NULL : val->val.s.s );
+ dir = tr_bencIsString( val ) ? val->val.s.s : NULL;
val = tr_bencDictFind( dict, "autostart" );
- start = ( NULL == val || TYPE_INT != val->type ? -1 :
- ( val->val.i ? 1 : 0 ) );
+ start = tr_bencIsInt( val ) ? (val->val.i!=0) : -1;
val = tr_bencDictFind( dict, "data" );
- if( NULL != val && TYPE_STR == val->type )
+ if( tr_bencIsString( val ) )
{
/* XXX detect duplicates and return a message indicating so */
tor = torrent_add_data( ( uint8_t * )val->val.s.s, val->val.s.i,
else
{
val = tr_bencDictFind( dict, "file" );
- if( NULL == val || TYPE_STR != val->type )
+ if( !tr_bencIsString( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
struct client * client = arg;
int num;
- if( NULL == val || TYPE_INT != val->type )
+ if( !tr_bencIsInt( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
{
struct client * client = arg;
- if( NULL == val || TYPE_STR != val->type )
+ if( !tr_bencIsString( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
/* add info/status for all torrents */
if( all )
{
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
tr_bencFree( &pk );
/* add info/status for the requested IDs */
else
{
- if( NULL == val || TYPE_DICT != val->type )
+ if( !tr_bencIsDict( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
tr_bencFree( &pk );
}
typelist = tr_bencDictFind( val, "type" );
idlist = tr_bencDictFind( val, "id" );
- if( NULL == typelist || TYPE_LIST != typelist->type ||
- NULL == idlist || TYPE_LIST != idlist->type )
+ if( !tr_bencIsList(typelist) || !tr_bencIsList(idlist) )
{
msgresp( client, tag, IPC_MSG_BAD );
tr_bencFree( &pk );
/* remove/start/stop requested list of torrents */
else
{
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
benc_val_t * hash, pk, * pkinf;
int64_t found;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
{
const tr_info * inf;
hash = &val->val.l.vals[ii];
- if( NULL == hash || TYPE_STR != hash->type ||
- SHA_DIGEST_LENGTH * 2 != hash->val.s.i )
+ if( !tr_bencIsString(hash) || SHA_DIGEST_LENGTH * 2 != hash->val.s.i )
{
tr_bencFree( &pk );
msgresp( client, tag, IPC_MSG_BAD );
uint8_t * buf;
size_t buflen;
int ii;
- benc_val_t pk, *pkval, * name;
+ benc_val_t pk, *pkval;
enum ipc_msg found;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
msgresp( client, tag, IPC_MSG_BAD );
return;
for( ii = 0; val->val.l.count > ii; ii++ )
{
- name = &val->val.l.vals[ii];
- if( NULL == name || TYPE_STR != name->type )
+ tr_benc * name = &val->val.l.vals[ii];
+ if( !tr_bencIsString( name ) )
{
tr_bencFree( &pk );
msgresp( client, tag, IPC_MSG_BAD );
{
uint8_t * buf;
size_t len;
- benc_val_t top, * num, * str, * list, * dict;
+ benc_val_t top, * num, * str, * list;
int ii;
struct tor * tor;
const char * dir;
free( buf );
num = tr_bencDictFind( &top, "autostart" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
gl_autostart = ( num->val.i ? 1 : 0 );
- }
num = tr_bencDictFind( &top, "port" );
- if( NULL != num && TYPE_INT == num->type &&
- 0 < num->val.i && 0xffff > num->val.i )
+ if( tr_bencIsInt( num ) && 0 < num->val.i && 0xffff > num->val.i )
{
gl_port = num->val.i;
}
tr_setBindPort( gl_handle, gl_port );
num = tr_bencDictFind( &top, "default-pex" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
gl_pex = ( num->val.i ? 1 : 0 );
- }
num = tr_bencDictFind( &top, "port-mapping" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
gl_mapping = ( num->val.i ? 1 : 0 );
- }
tr_natTraversalEnable( gl_handle, gl_mapping );
num = tr_bencDictFind( &top, "upload-limit" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
gl_uplimit = num->val.i;
- }
tr_setGlobalSpeedLimit( gl_handle, TR_UP, gl_uplimit );
tr_setUseGlobalSpeedLimit( gl_handle, TR_UP, gl_uplimit > 0 );
num = tr_bencDictFind( &top, "download-limit" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
gl_downlimit = num->val.i;
- }
tr_setGlobalSpeedLimit( gl_handle, TR_DOWN, gl_downlimit );
tr_setUseGlobalSpeedLimit( gl_handle, TR_DOWN, gl_downlimit > 0 );
str = tr_bencDictFind( &top, "default-directory" );
- if( NULL != str && TYPE_STR == str->type )
- {
+ if( tr_bencIsString( str ) )
strlcpy( gl_dir, str->val.s.s, sizeof gl_dir );
- }
str = tr_bencDictFind( &top, "encryption-mode" );
- if( NULL != str && TYPE_STR == str->type )
+ if( tr_bencIsString( str ) )
{
if(!strcasecmp(str->val.s.s, "preferred"))
gl_crypto = TR_ENCRYPTION_PREFERRED;
tr_setEncryptionMode(gl_handle, gl_crypto);
list = tr_bencDictFind( &top, "torrents" );
- if( NULL == list || TYPE_LIST != list->type )
- {
+ if( !tr_bencIsList( list ) )
return 0;
- }
for( ii = 0; ii < list->val.l.count; ii++ )
{
- dict = &list->val.l.vals[ii];
- if( TYPE_DICT != dict->type )
- {
+ tr_benc * dict = &list->val.l.vals[ii];
+ if( !tr_bencIsDict( dict ) )
continue;
- }
str = tr_bencDictFind( dict, "directory" );
- dir = ( NULL != str && TYPE_STR == str->type ? str->val.s.s : NULL );
+ dir = tr_bencIsString( str ) ? str->val.s.s : NULL;
str = tr_bencDictFind( dict, "hash" );
- if( NULL == str || TYPE_STR != str->type ||
- 2 * SHA_DIGEST_LENGTH != str->val.s.i )
- {
+ if( !tr_bencIsString( str ) || 2 * SHA_DIGEST_LENGTH != str->val.s.i )
continue;
- }
tor = opentor( NULL, str->val.s.s, NULL, 0, dir );
- if( NULL == tor )
- {
+ if( !tor )
continue;
- }
num = tr_bencDictFind( dict, "pex" );
- if( NULL != num && TYPE_INT == num->type )
- {
+ if( tr_bencIsInt( num ) )
fprintf( stderr, "warning: obsolete command 'pex'\n" );
- }
num = tr_bencDictFind( dict, "paused" );
- if( NULL != num && TYPE_INT == num->type && !num->val.i )
- {
+ if( tr_bencIsInt( num ) && !num->val.i )
tr_torrentStart( tor->tor );
- }
}
return 0;
return 0;
}
- res = ipc_parse( con->ipc, data, len, con );
+ res = ipc_handleMessages( con->ipc, data, len, con );
if( 0 > res )
{
destroycon( con );
}
- res = ipc_parse( con->ipc, data, len, con );
+ res = ipc_handleMessages( con->ipc, data, len, con );
if( 0 > res )
{
int ii;
GSList * list = NULL;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
tr_benc * file, * data, * dir, * start;
tr_ctor * ctor;
- if( !val || ( val->type != TYPE_DICT ) )
+ if( !tr_bencIsDict( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
dir = tr_bencDictFind( val, "directory" );
start = tr_bencDictFind( val, "autostart" );
- if( ( NULL != file && TYPE_STR != file->type ) ||
- ( NULL != data && TYPE_STR != data->type ) ||
- ( NULL != dir && TYPE_STR != dir->type ) ||
- ( NULL != start && TYPE_INT != start->type ) )
+ if( ( file && !tr_bencIsString( file ) ) ||
+ ( data && !tr_bencIsString( data ) ) ||
+ ( dir && !tr_bencIsString( dir ) ) ||
+ ( start && !tr_bencIsInt( start ) ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
uint8_t * buf;
size_t size;
- if( NULL == val || TYPE_DICT != val->type )
+ if( !tr_bencIsDict( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
respid = ( IPC_MSG_GETINFO == id ? IPC_MSG_INFO : IPC_MSG_STAT );
ids = tr_bencDictFind( val, "id" );
types = tr_bencDictFind( val, "types" );
- if( NULL == ids || TYPE_LIST != ids->type ||
- NULL == types || TYPE_LIST != types->type )
+ if( !tr_bencIsList(ids) || !tr_bencIsList(types) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
uint8_t * buf;
size_t size;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
uint8_t * buf;
size_t size;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
GtkTreeIter iter;
int ii;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
struct constate * con = arg;
struct constate_serv * srv = &con->u.serv;
- if( NULL == val || TYPE_INT != val->type || INT_MAX < val->val.i )
+ if( !tr_bencIsInt( val ) || INT_MAX < val->val.i )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
struct constate * con = arg;
struct constate_serv * srv = &con->u.serv;
- if( NULL == val || TYPE_STR != val->type )
+ if( !tr_bencIsString( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
smsg_sup( enum ipc_msg id UNUSED, tr_benc * val, int64_t tag, void * arg )
{
struct constate * con = arg;
- tr_benc packet, * pkval, * name;
+ tr_benc packet, * pkval;
int ii;
enum ipc_msg found;
uint8_t * buf;
size_t size;
- if( NULL == val || TYPE_LIST != val->type )
+ if( !tr_bencIsList( val ) )
{
simpleresp( con, tag, IPC_MSG_BAD );
return;
for( ii = 0; val->val.l.count > ii; ii++ )
{
- name = &val->val.l.vals[ii];
- if( NULL == name || TYPE_STR != name->type )
- {
+ tr_benc * name = &val->val.l.vals[ii];
+
+ if( !tr_bencIsString( name ) )
continue;
- }
+
found = ipc_msgid( con->ipc, name->val.s.s );
if( IPC__MSG_COUNT == found || !ipc_ishandled( con->ipc, found ) )
- {
continue;
- }
+
tr_bencInitStr( tr_bencListAdd( pkval ),
name->val.s.s, name->val.s.i, 1 );
}
buf = ipc_serialize( &packet, &size );
tr_bencFree( &packet );
- if( NULL == buf )
- {
+
+ if( !buf )
simpleresp( con, tag, IPC_MSG_FAIL );
- }
else
- {
io_send_keepdata( con->source, buf, size );
- }
}
void
***
**/
-static int
-isType( const tr_benc * val, int type )
+int
+tr_bencIsType( const tr_benc * val, int type )
{
return ( ( val != NULL ) && ( val->type == type ) );
}
-#define isInt(v) ( isType( ( v ), TYPE_INT ) )
-#define isString(v) ( isType( ( v ), TYPE_STR ) )
-#define isList(v) ( isType( ( v ), TYPE_LIST ) )
-#define isDict(v) ( isType( ( v ), TYPE_DICT ) )
-
static int
isContainer( const tr_benc * val )
{
- return isList(val) || isDict(val);
+ return tr_bencIsList(val) || tr_bencIsDict(val);
}
static int
isSomething( const tr_benc * val )
{
- return isContainer(val) || isInt(val) || isString(val);
+ return isContainer(val) || tr_bencIsInt(val) || tr_bencIsString(val);
}
/***
return TR_ERROR;
node = tr_ptrArrayBack( parentStack );
- if( isDict( node ) && ( node->val.l.count % 2 ) )
+ if( tr_bencIsDict( node ) && ( node->val.l.count % 2 ) )
return TR_ERROR; /* odd # of children in dict */
tr_ptrArrayPop( parentStack );
{
int len, ii;
- if( !isDict( val ) )
+ if( !tr_bencIsDict( val ) )
return NULL;
len = strlen( key );
tr_bencListGetNthChild( tr_benc * val, int i )
{
tr_benc * ret = NULL;
- if( isList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
+ if( tr_bencIsList( val ) && ( i >= 0 ) && ( i < val->val.l.count ) )
ret = val->val.l.vals + i;
return ret;
}
int64_t
tr_bencGetInt ( const tr_benc * val )
{
- assert( isInt( val ) );
+ assert( tr_bencIsInt( val ) );
return val->val.i;
}
char *
tr_bencStealStr( tr_benc * val )
{
- assert( isString( val ) );
+ assert( tr_bencIsString( val ) );
val->val.s.nofree = 1;
return val->val.s.s;
}
int
tr_bencListReserve( tr_benc * val, int count )
{
- assert( isList( val ) );
+ assert( tr_bencIsList( val ) );
return makeroom( val, count );
}
int
tr_bencDictReserve( tr_benc * val, int count )
{
- assert( isDict( val ) );
+ assert( tr_bencIsDict( val ) );
return makeroom( val, count * 2 );
}
{
tr_benc * item;
- assert( isList( list ) );
+ assert( tr_bencIsList( list ) );
assert( list->val.l.count < list->val.l.alloc );
item = &list->val.l.vals[list->val.l.count];
{
tr_benc * keyval, * itemval;
- assert( isDict( dict ) );
+ assert( tr_bencIsDict( dict ) );
assert( dict->val.l.count + 2 <= dict->val.l.alloc );
keyval = dict->val.l.vals + dict->val.l.count++;
struct SaveNode * node;
struct KeyIndex * indices;
- assert( isDict( val ) );
+ assert( tr_bencIsDict( val ) );
nKeys = val->val.l.count / 2;
node = tr_new0( struct SaveNode, 1 );
int i, n;
struct SaveNode * node;
- assert( isList( val ) );
+ assert( tr_bencIsList( val ) );
n = val->val.l.count;
node = tr_new0( struct SaveNode, 1 );
{
struct SaveNode * node;
- if( isList( val ) )
+ if( tr_bencIsList( val ) )
node = nodeNewList( val );
- else if( isDict( val ) )
+ else if( tr_bencIsDict( val ) )
node = nodeNewDict( val );
else
node = nodeNewLeaf( val );
int64_t tr_bencGetInt( const tr_benc * val );
+int tr_bencIsType( const tr_benc *, int type );
+#define tr_bencIsInt(b) (tr_bencIsType(b,TYPE_INT))
+#define tr_bencIsDict(b) (tr_bencIsType(b,TYPE_DICT))
+#define tr_bencIsList(b) (tr_bencIsType(b,TYPE_LIST))
+#define tr_bencIsString(b) (tr_bencIsType(b,TYPE_STR))
/**
*** Treat these as private -- they're only made public here
#define MSGNAME( id ) ( gl_msgs[(id)].name )
#define DICTPAYLOAD( info ) ( 2 > (info)->vers )
+struct ipc_funcs
+{
+ trd_msgfunc msgs[IPC__MSG_COUNT];
+ trd_msgfunc def;
+};
+
struct ipc_info
{
struct ipc_funcs * funcs;
const enum ipc_msg id;
};
-struct inf
-{
- const char * name;
- const int type;
-};
-
-struct msgfunc
-{
- int id;
- trd_msgfunc func;
-};
-
-struct ipc_funcs
-{
- trd_msgfunc msgs[IPC__MSG_COUNT];
- trd_msgfunc def;
-};
-
/* these names must be sorted for strcmp() */
static const struct msg gl_msgs[] =
{
{ "version", 1, IPC_MSG_VERSION }
};
+struct inf
+{
+ const char * name;
+ const int type;
+};
+
/* these names must be sorted for strcmp() */
static const struct inf gl_inf[] =
{
}
void
-ipc_addmsg( struct ipc_funcs * funcs, enum ipc_msg msg_id, trd_msgfunc func )
+ipc_addmsg( struct ipc_funcs * funcs,
+ enum ipc_msg msg_id,
+ trd_msgfunc func )
{
assert( MSGVALID( msg_id ) );
assert( IPC_MSG_VERSION != msg_id );
}
void
-ipc_freecon( struct ipc_info * info )
+ipc_freecon( struct ipc_info * session )
{
- tr_free( info );
+ tr_free( session );
}
int
-ipc_ishandled( const struct ipc_info * info, enum ipc_msg id )
+ipc_ishandled( const struct ipc_info * session, enum ipc_msg msg_id )
{
- assert( MSGVALID( id ) );
+ assert( MSGVALID( msg_id ) );
- return info->funcs->msgs[id] != NULL;
+ return session->funcs->msgs[msg_id] != NULL;
}
int
-ipc_havetags( const struct ipc_info * info )
+ipc_havetags( const struct ipc_info * session )
{
- return !DICTPAYLOAD( info );
+ return !DICTPAYLOAD( session );
}
static int
}
static int
-sessionSupportsMessage( const struct ipc_info * info, enum ipc_msg id )
+sessionSupportsMessage( const struct ipc_info * session, enum ipc_msg id )
{
assert( MSGVALID( id ) );
- assert( ipc_hasvers( info ) );
+ assert( ipc_hasvers( session ) );
- return gl_msgs[id].minvers <= info->vers;
+ return gl_msgs[id].minvers <= session->vers;
}
/**
* gives the length of the string.
*/
uint8_t *
-ipc_serialize( const tr_benc * pk, size_t * setmeSize )
+ipc_serialize( const tr_benc * benc, size_t * setmeSize )
{
- int bencSize = 0;
- char * benc = tr_bencSave( pk, &bencSize );
uint8_t * ret = NULL;
+ int len = 0;
+ char * str = tr_bencSave( benc, &len );
- if( bencSize > IPC_MAX_MSG_LEN )
+ if( len > IPC_MAX_MSG_LEN )
errno = EFBIG;
else {
- const size_t size = IPC_MIN_MSG_LEN + bencSize;
+ const size_t size = IPC_MIN_MSG_LEN + len;
ret = tr_new( uint8_t, size );
- snprintf( (char*)ret, size, "%0*X", IPC_MIN_MSG_LEN, bencSize );
- memcpy( ret + IPC_MIN_MSG_LEN, benc, bencSize );
+ snprintf( (char*)ret, size, "%0*X", IPC_MIN_MSG_LEN, len );
+ memcpy( ret + IPC_MIN_MSG_LEN, str, len );
*setmeSize = size;
}
- tr_free( benc );
+ tr_free( str );
return ret;
}
*
* Note that this message is just the dictionary payload.
* It doesn't contain metainfo as the other ipc_mk*() functions do.
+ * That's because the metainfo is dependent on the protocol version,
+ * and this is a handshake message to negotiate protocol versions.
+ *
+ * @see handlevers()
*/
uint8_t *
ipc_mkvers( size_t * len, const char * label )
* a single list identical to the "type" list described above.
*/
uint8_t *
-ipc_mkgetinfo( const struct ipc_info * session,
- size_t * setmeSize,
- enum ipc_msg msg_id,
- int64_t tag,
- int types,
- const int * ids )
+ipc_createInfoRequest( const struct ipc_info * session,
+ size_t * setmeSize,
+ enum ipc_msg msg_id,
+ int64_t tag,
+ int types,
+ const int * ids )
{
tr_benc pk;
tr_benc * typelist;
tr_bencInitStr( tr_bencDictAdd( val, "address" ), tk->address, -1, 1 );
tr_bencInitInt( tr_bencDictAdd( val, "port" ), tk->port );
tr_bencInitStr( tr_bencDictAdd( val, "announce" ), tk->announce, -1, 1 );
- if( NULL != tk->scrape )
+ if( tk->scrape )
tr_bencInitStr( tr_bencDictAdd( val, "scrape" ), tk->scrape, -1, 1 );
}
const tr_info * inf,
int types )
{
- tr_benc * dict, * item, * file, * tier;
+ tr_benc * dict;
int ii, jj, kk;
tr_file_index_t ff;
/* populate the dict with info key->value pairs */
for( ii = 0; IPC_INF__MAX > 1 << ii; ii++ )
{
+ tr_benc * item;
+
if( !( types & ( 1 << ii ) ) )
continue;
tr_bencInitList( item, inf->fileCount );
for( ff = 0; inf->fileCount > ff; ff++ )
{
- file = tr_bencListAdd( item );
+ tr_benc * file = tr_bencListAdd( item );
tr_bencInitDict( file, 2 );
tr_bencInitStr( tr_bencDictAdd( file, "name" ),
inf->files[ff].name, -1, 1 );
tr_bencInitList( item, inf->trackerTiers );
for( jj = 0; inf->trackerTiers > jj; jj++ )
{
- tier = tr_bencListAdd( item );
+ tr_benc * tier = tr_bencListAdd( item );
tr_bencInitList( tier, inf->trackerList[jj].count );
for( kk = 0; inf->trackerList[jj].count > kk; kk++ )
filltracker( tr_bencListAdd( tier ),
return 0;
}
+/**
+ * This reads a handshake message from the client to decide
+ * which IPC protocol version to use.
+ * Returns 0 on success; otherwise, returns -1 and sets errno.
+ *
+ * @see ipc_handleMessages()
+ * @see ipc_mkvers()
+ */
static int
handlevers( struct ipc_info * info, tr_benc * dict )
{
- tr_benc * vers, * num;
+ tr_benc * vers;
int64_t min, max;
- if( TYPE_DICT != dict->type )
+ if( !tr_bencIsDict( dict ) )
{
errno = EINVAL;
return -1;
min = vers->val.i;
max = vers->val.i;
break;
- case TYPE_DICT:
- num = tr_bencDictFind( vers, "min" );
- min = ( NULL == num || TYPE_INT != num->type ? -1 : num->val.i );
+ case TYPE_DICT: {
+ tr_benc * num = tr_bencDictFind( vers, "min" );
+ min = tr_bencIsInt( num ) ? num->val.i : -1;
num = tr_bencDictFind( vers, "max" );
- max = ( NULL == num || TYPE_INT != num->type ? -1 : num->val.i );
+ max = tr_bencIsInt( num ) ? num->val.i : -1;
break;
+ }
default:
min = -1;
max = -1;
: IPC__MSG_COUNT;
}
+/**
+ * Invokes the trd_msgfunc for the message passed in.
+ * Returns 0 on success; otherwise, returns -1 and sets errno.
+ */
static int
-gotmsg( const struct ipc_info * info, tr_benc * name, tr_benc * val,
- tr_benc * tagval, void * arg )
+callmsgfunc( const struct ipc_info * info,
+ tr_benc * name,
+ tr_benc * val,
+ tr_benc * tagval,
+ void * user_data )
{
const struct msg * msg;
int64_t tag;
- if( TYPE_STR != name->type )
- {
+ /* extract tag from tagval */
+ if( !tagval )
+ tag = -1;
+ else if( tr_bencIsInt( tagval ) )
+ tag = tagval->val.i;
+ else {
errno = EINVAL;
return -1;
}
- if( NULL == tagval )
- {
- tag = -1;
- }
- else
- {
- if( TYPE_INT != tagval->type )
- {
- errno = EINVAL;
- return -1;
- }
- tag = tagval->val.i;
+ /* find the msg corresponding to `name' */
+ if( !tr_bencIsString( name ) ) {
+ errno = EINVAL;
+ return -1;
}
-
msg = msglookup( name->val.s.s );
+
if( msg && msg->minvers <= info->vers )
{
if( info->funcs->msgs[msg->id] != NULL )
{
- (*info->funcs->msgs[msg->id])( msg->id, val, tag, arg );
+ (*info->funcs->msgs[msg->id])( msg->id, val, tag, user_data );
}
else if( info->funcs->def )
{
- info->funcs->def( msg->id, val, tag, arg );
+ info->funcs->def( msg->id, val, tag, user_data );
}
}
else if( NULL != info->funcs->def )
- info->funcs->def( IPC__MSG_UNKNOWN, NULL, tag, arg );
+ info->funcs->def( IPC__MSG_UNKNOWN, NULL, tag, user_data );
return 0;
}
static int
-handlemsgs( const struct ipc_info * info, tr_benc * pay, void * arg )
+handlemsgs( const struct ipc_info * session,
+ tr_benc * message,
+ void * user_data )
{
tr_benc * name, * val, * tag;
- int ii;
- assert( ipc_hasvers( info ) );
+ assert( ipc_hasvers( session ) );
- if( DICTPAYLOAD( info ) )
+ if( DICTPAYLOAD( session ) )
{
- if( TYPE_DICT != pay->type || pay->val.l.count % 2 )
+ int ii;
+
+ if( TYPE_DICT != message->type || message->val.l.count % 2 )
{
errno = EINVAL;
return -1;
}
- for( ii = 0; ii < pay->val.l.count; ii += 2 )
+ for( ii = 0; ii < message->val.l.count; ii += 2 )
{
- assert( ii + 1 < pay->val.l.count );
- name = &pay->val.l.vals[ii];
- val = &pay->val.l.vals[ii+1];
- if( 0 > gotmsg( info, name, val, NULL, arg ) )
- {
+ assert( ii + 1 < message->val.l.count );
+ name = &message->val.l.vals[ii];
+ val = &message->val.l.vals[ii+1];
+ if( 0 > callmsgfunc( session, name, val, NULL, user_data ) )
return -1;
- }
}
}
else
{
- if( TYPE_LIST != pay->type || 2 > pay->val.l.count )
+ if( TYPE_LIST != message->type || 2 > message->val.l.count )
{
errno = EINVAL;
return -1;
}
- name = &pay->val.l.vals[0];
- val = &pay->val.l.vals[1];
- tag = ( 2 == pay->val.l.count ? NULL : &pay->val.l.vals[2] );
- if( 0 > gotmsg( info, name, val, tag, arg ) )
- {
+ name = &message->val.l.vals[0];
+ val = &message->val.l.vals[1];
+ tag = ( 2 == message->val.l.count ? NULL : &message->val.l.vals[2] );
+ if( 0 > callmsgfunc( session, name, val, tag, user_data ) )
return -1;
- }
}
return 0;
}
ssize_t
-ipc_parse( struct ipc_info * info, const uint8_t * buf, ssize_t total, void * arg )
+ipc_handleMessages( struct ipc_info * info,
+ const uint8_t * msgs,
+ ssize_t msgslen,
+ void * user_data )
{
char hex[IPC_MIN_MSG_LEN+1], * end;
ssize_t off, len;
tr_benc benc;
- for( off = 0; off + IPC_MIN_MSG_LEN < total; off += IPC_MIN_MSG_LEN + len )
+ for( off = 0; off + IPC_MIN_MSG_LEN < msgslen; off += IPC_MIN_MSG_LEN + len )
{
- memcpy( hex, buf + off, IPC_MIN_MSG_LEN );
+ memcpy( hex, msgs + off, IPC_MIN_MSG_LEN );
hex[IPC_MIN_MSG_LEN] = '\0';
end = NULL;
len = strtol( hex, &end, 16 );
errno = EINVAL;
return -1;
}
- if( off + IPC_MIN_MSG_LEN + len > total )
+ if( off + IPC_MIN_MSG_LEN + len > msgslen )
{
break;
}
errno = 0;
- if( tr_bencLoad( buf + off + IPC_MIN_MSG_LEN, len, &benc, NULL ) )
+ if( tr_bencLoad( msgs + off + IPC_MIN_MSG_LEN, len, &benc, NULL ) )
{
if( 0 == errno )
{
}
return -1;
}
- if( 0 > ( ipc_hasvers( info ) ? handlemsgs( info, &benc, arg ) :
+ if( 0 > ( ipc_hasvers( info ) ? handlemsgs( info, &benc, user_data ) :
handlevers( info, &benc ) ) )
{
SAFEBENCFREE( &benc );
return strcmp( a, inf->name );
}
+/**
+ * Convert a benc list of string keys from gl_inf or gl_stat
+ * into a bitwise-or'ed int representation.
+ * msg_id must be either IPC_MSG_INFO or IPC_MSG_STAT.
+ * @see ipc_infoname()
+ */
int
ipc_infotypes( enum ipc_msg id, const tr_benc * list )
{
ret = IPC_INF_ID;
- if( NULL == list || TYPE_LIST != list->type )
- {
+ if( !tr_bencIsList( list ) )
return ret;
- }
for( i=0; i<list->val.l.count; ++i )
{
const tr_benc * name = &list->val.l.vals[i];
const struct inf * inf;
- if( TYPE_STR != name->type )
+ if( !tr_bencIsString( name ) )
continue;
inf = bsearch( name->val.s.s,
return ret;
}
+/**
+ * This function is the reverse of ipc_infotypes:
+ * it returns the string key that corresponds to the type passed in.
+ * Type is one of the IPC_INF_* or IPC_ST_* enums from ipcparse.h.
+ * msg_id must be either IPC_MSG_INFO or IPC_MSG_STAT.
+ * @see ipc_infotypes()
+ */
const char *
ipc_infoname( enum ipc_msg id, int type )
{
uint8_t * ipc_mkstr ( const struct ipc_info *, size_t *, enum ipc_msg,
int64_t tag, const char * val );
uint8_t * ipc_mkvers ( size_t *, const char * );
-uint8_t * ipc_mkgetinfo ( const struct ipc_info *, size_t *, enum ipc_msg,
- int64_t, int, const int * );
+
+uint8_t * ipc_createInfoRequest( const struct ipc_info * session,
+ size_t * setme_len,
+ enum ipc_msg msg_id,
+ int64_t tag,
+ int types,
+ const int * ids );
+
int ipc_addinfo ( struct tr_benc *, int,
const struct tr_info *, int );
int ipc_addstat ( struct tr_benc *, int,
/* sets errno to EINVAL on parse error or
EPERM for unsupported protocol version */
-ssize_t ipc_parse ( struct ipc_info *, const uint8_t *,
- ssize_t, void * );
+ssize_t ipc_handleMessages( struct ipc_info * session,
+ const uint8_t * serializedMessages ,
+ ssize_t serializedLength,
+ void * user_data );
/* misc info functions, these will always succeed */
enum ipc_msg ipc_msgid ( const struct ipc_info *, const char * );
/* comment */
memset( buf, '\0', sizeof( buf ) );
val = tr_bencDictFindFirst( meta, "comment.utf-8", "comment", NULL );
- if( val && val->type == TYPE_STR )
+ if( tr_bencIsString( val ) )
strlcat_utf8( buf, val->val.s.s, sizeof( buf ), 0 );
tr_free( inf->comment );
inf->comment = tr_strdup( buf );
/* creator */
memset( buf, '\0', sizeof( buf ) );
val = tr_bencDictFindFirst( meta, "created by.utf-8", "created by", NULL );
- if( val && val->type == TYPE_STR )
+ if( tr_bencIsString( val ) )
strlcat_utf8( buf, val->val.s.s, sizeof( buf ), 0 );
tr_free( inf->creator );
inf->creator = tr_strdup( buf );
/* Date created */
inf->dateCreated = 0;
val = tr_bencDictFind( meta, "creation date" );
- if( NULL != val && TYPE_INT == val->type )
- {
+ if( tr_bencIsInt( val ) )
inf->dateCreated = val->val.i;
- }
/* Private torrent */
val = tr_bencDictFind( beInfo, "private" );
val2 = tr_bencDictFind( meta, "private" );
- if( ( NULL != val && ( TYPE_INT != val->type || 0 != val->val.i ) ) ||
- ( NULL != val2 && ( TYPE_INT != val2->type || 0 != val2->val.i ) ) )
+ if( ( tr_bencIsInt(val) && val->val.i ) ||
+ ( tr_bencIsInt(val2) && val2->val.i ) )
{
inf->isPrivate = 1;
}
/* Piece length */
val = tr_bencDictFind( beInfo, "piece length" );
- if( NULL == val || TYPE_INT != val->type )
+ if( !tr_bencIsInt( val ) )
{
if( val )
tr_err( _( "Invalid metadata entry \"%s\"" ), "piece length" );
/* Hashes */
val = tr_bencDictFind( beInfo, "pieces" );
- if( NULL == val || TYPE_STR != val->type )
+ if( !tr_bencIsString( val ) )
{
if( val )
tr_err( _( "Invalid metadata entry \"%s\"" ), "pieces" );
static int
getfile( char ** setme, const char * prefix, tr_benc * name )
{
- tr_benc * dir;
const char ** list;
int ii, jj;
char buf[4096];
- if( TYPE_LIST != name->type )
- {
+ if( !tr_bencIsList( name ) )
return TR_EINVALID;
- }
list = calloc( name->val.l.count, sizeof( list[0] ) );
- if( NULL == list )
- {
+ if( !list )
return TR_EINVALID;
- }
for( ii = jj = 0; name->val.l.count > ii; ii++ )
{
- dir = &name->val.l.vals[ii];
- if( TYPE_STR != dir->type )
- {
+ tr_benc * dir = &name->val.l.vals[ii];
+
+ if( !tr_bencIsString( dir ) )
continue;
- }
+
if( 0 == strcmp( "..", dir->val.s.s ) )
{
if( 0 < jj )
static int getannounce( tr_info * inf, tr_benc * meta )
{
- tr_benc * val, * subval, * urlval;
+ tr_benc * val, * urlval;
char * address, * announce;
- int ii, jj, port, random, subcount;
+ int ii, jj, port, random;
tr_tracker_info * sublist;
void * swapping;
/* Announce-list */
val = tr_bencDictFind( meta, "announce-list" );
- if( NULL != val && TYPE_LIST == val->type && 0 < val->val.l.count )
+ if( tr_bencIsList(val) && 0 < val->val.l.count )
{
inf->trackerTiers = 0;
inf->trackerList = calloc( val->val.l.count,
/* iterate through the announce-list's tiers */
for( ii = 0; ii < val->val.l.count; ii++ )
{
- subval = &val->val.l.vals[ii];
- if( TYPE_LIST != subval->type || 0 >= subval->val.l.count )
- {
+ int subcount = 0;
+ tr_benc * subval = &val->val.l.vals[ii];
+
+ if( !tr_bencIsList(subval) || 0 >= subval->val.l.count )
continue;
- }
- subcount = 0;
+
sublist = calloc( subval->val.l.count, sizeof( sublist[0] ) );
/* iterate through the tier's items */
/* Regular announce value */
val = tr_bencDictFind( meta, "announce" );
- if( NULL == val || TYPE_STR != val->type )
+ if( !tr_bencIsString( val ) )
{
tr_err( _( "Missing metadata entry \"%s\"" ), "announce" );
return TR_EINVALID;
tr_benc * item, * path;
int ii;
- if( NULL == name || TYPE_STR != name->type )
+ if( !tr_bencIsString( name ) )
{
if( name )
tr_err( _( "Invalid metadata entry \"%s\"" ), "name" );
}
inf->totalSize = 0;
- if( files && TYPE_LIST == files->type )
+ if( tr_bencIsList( files ) )
{
/* Multi-file mode */
inf->isMultifile = 1;
return TR_EINVALID;
}
length = tr_bencDictFind( item, "length" );
- if( NULL == length || TYPE_INT != length->type )
+ if( !tr_bencIsInt( length ) )
{
if( length )
tr_err( _( "Invalid metadata entry \"%s\"" ), "length" );
inf->totalSize += length->val.i;
}
}
- else if( NULL != length && TYPE_INT == length->type )
+ else if( tr_bencIsInt( length ) )
{
char buf[4096];
if( IPC_MIN_MSG_LEN > [_buf length] )
return;
- res = ipc_parse( _ipc, [_buf mutableBytes], [_buf length], self );
+ res = ipc_handleMessages( _ipc, [_buf mutableBytes], [_buf length], self );
if( 0 > res )
{