hack on IPC a bit because it's been too long since I broke it

This commit is contained in:
Charles Kerr 2008-04-03 21:38:32 +00:00
parent 918f8f4936
commit fd0e71c00a
12 changed files with 305 additions and 299 deletions

View File

@ -794,7 +794,7 @@ flushreqs( struct con * con )
tr_bencInitStr( tr_bencListAdd( val ), tr_bencInitStr( tr_bencListAdd( val ),
jj->str, -1, 1 ); jj->str, -1, 1 );
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
} }
SAFEFREESTRLIST( req->strs ); SAFEFREESTRLIST( req->strs );
@ -805,7 +805,7 @@ flushreqs( struct con * con )
{ {
tr_bencInitStr( tr_bencDictAdd( val, "data" ), tr_bencInitStr( tr_bencDictAdd( val, "data" ),
req->buf, req->listlen, 1 ); req->buf, req->listlen, 1 );
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
} }
SAFEFREE( req->buf ); SAFEFREE( req->buf );
@ -833,7 +833,7 @@ flushreqs( struct con * con )
tr_bencInitInt( tr_bencListAdd( val ), tr_bencInitInt( tr_bencListAdd( val ),
req->numlist[ii] ); req->numlist[ii] );
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
} }
SAFEFREE( req->numlist ); SAFEFREE( req->numlist );

View File

@ -498,7 +498,7 @@ addmsg1( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
} }
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
tr_bencFree( &pk ); tr_bencFree( &pk );
queuemsg( client, buf, buflen ); queuemsg( client, buf, buflen );
free( buf ); free( buf );
@ -562,7 +562,7 @@ addmsg2( enum ipc_msg id UNUSED, benc_val_t * dict, int64_t tag, void * arg )
byebye( client->ev, EVBUFFER_EOF, NULL ); byebye( client->ev, EVBUFFER_EOF, NULL );
return; return;
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
tr_bencFree( &pk ); tr_bencFree( &pk );
queuemsg( client, buf, buflen ); queuemsg( client, buf, buflen );
free( buf ); free( buf );
@ -761,7 +761,7 @@ infomsg( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg )
} }
/* generate packet data and send it */ /* generate packet data and send it */
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
tr_bencFree( &pk ); tr_bencFree( &pk );
queuemsg( client, buf, buflen ); queuemsg( client, buf, buflen );
free( buf ); free( buf );
@ -906,7 +906,7 @@ lookmsg( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
} }
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
tr_bencFree( &pk ); tr_bencFree( &pk );
queuemsg( client, buf, buflen ); queuemsg( client, buf, buflen );
free( buf ); free( buf );
@ -1027,7 +1027,7 @@ supmsg( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg )
name->val.s.s, name->val.s.i, 1 ); name->val.s.s, name->val.s.i, 1 );
} }
buf = ipc_mkval( &pk, &buflen ); buf = ipc_serialize( &pk, &buflen );
tr_bencFree( &pk ); tr_bencFree( &pk );
queuemsg( client, buf, buflen ); queuemsg( client, buf, buflen );
free( buf ); free( buf );

View File

@ -183,7 +183,7 @@ client_sendmsg( struct constate * con )
{ {
tr_bencInitStr( tr_bencListAdd( val ), ii->data, -1, 0 ); tr_bencInitStr( tr_bencListAdd( val ), ii->data, -1, 0 );
} }
buf = ipc_mkval( &packet, &size ); buf = ipc_serialize( &packet, &size );
saved = errno; saved = errno;
tr_bencFree( &packet ); tr_bencFree( &packet );
g_slist_free( cli->files ); g_slist_free( cli->files );
@ -684,7 +684,7 @@ smsg_info( enum ipc_msg id, tr_benc * val, int64_t tag, void * arg )
} }
} }
buf = ipc_mkval( &packet, &size ); buf = ipc_serialize( &packet, &size );
tr_bencFree( &packet ); tr_bencFree( &packet );
if( NULL == buf ) if( NULL == buf )
{ {
@ -745,7 +745,7 @@ smsg_infoall( enum ipc_msg id, tr_benc * val, int64_t tag, void * arg )
while( gtk_tree_model_iter_next( model, &iter ) ); while( gtk_tree_model_iter_next( model, &iter ) );
} }
buf = ipc_mkval( &packet, &size ); buf = ipc_serialize( &packet, &size );
tr_bencFree( &packet ); tr_bencFree( &packet );
if( NULL == buf ) if( NULL == buf )
{ {
@ -829,7 +829,7 @@ smsg_look( enum ipc_msg id UNUSED, tr_benc * val, int64_t tag,
} }
} }
buf = ipc_mkval( &packet, &size ); buf = ipc_serialize( &packet, &size );
tr_bencFree( &packet ); tr_bencFree( &packet );
if( NULL == buf ) if( NULL == buf )
{ {
@ -1116,7 +1116,7 @@ smsg_sup( enum ipc_msg id UNUSED, tr_benc * val, int64_t tag, void * arg )
name->val.s.s, name->val.s.i, 1 ); name->val.s.s, name->val.s.i, 1 );
} }
buf = ipc_mkval( &packet, &size ); buf = ipc_serialize( &packet, &size );
tr_bencFree( &packet ); tr_bencFree( &packet );
if( NULL == buf ) if( NULL == buf )
{ {

View File

@ -440,19 +440,31 @@ tr_bencInitInt( tr_benc * val, int64_t num )
val->val.i = num; val->val.i = num;
} }
int
tr_bencInitList( tr_benc * val, int reserveCount )
{
tr_bencInit( val, TYPE_LIST );
return tr_bencListReserve( val, reserveCount );
}
int int
tr_bencListReserve( tr_benc * val, int count ) tr_bencListReserve( tr_benc * val, int count )
{ {
assert( isList( val ) ); assert( isList( val ) );
return makeroom( val, count ); return makeroom( val, count );
} }
int
tr_bencInitDict( tr_benc * val, int reserveCount )
{
tr_bencInit( val, TYPE_DICT );
return tr_bencDictReserve( val, reserveCount );
}
int int
tr_bencDictReserve( tr_benc * val, int count ) tr_bencDictReserve( tr_benc * val, int count )
{ {
assert( isDict( val ) ); assert( isDict( val ) );
return makeroom( val, count * 2 ); return makeroom( val, count * 2 );
} }

View File

@ -88,6 +88,8 @@ static inline void tr_bencInit( tr_benc * val, int type )
void _tr_bencInitStr( tr_benc * val, char * str, int len, int nofree ); void _tr_bencInitStr( tr_benc * val, char * str, int len, int nofree );
int tr_bencInitStrDup( tr_benc * val, const char * str ); int tr_bencInitStrDup( tr_benc * val, const char * str );
void tr_bencInitInt( tr_benc * val, int64_t num ); void tr_bencInitInt( tr_benc * val, int64_t num );
int tr_bencInitDict( tr_benc * val, int reserveCount );
int tr_bencInitList( tr_benc * val, int reserveCount );
int tr_bencListReserve( tr_benc * list, int count ); int tr_bencListReserve( tr_benc * list, int count );
/* note that for one key-value pair, count should be 1, not 2 */ /* note that for one key-value pair, count should be 1, not 2 */
int tr_bencDictReserve( tr_benc * dict, int count ); int tr_bencDictReserve( tr_benc * dict, int count );

View File

@ -94,40 +94,41 @@ void tr_cpClose( tr_completion * cp )
static void static void
tr_cpEnsureDoneValid( const tr_completion * ccp ) tr_cpEnsureDoneValid( const tr_completion * ccp )
{ {
const tr_torrent * tor = ccp->tor; if( ccp->doneDirty )
const tr_info * info = &tor->info; {
uint64_t have=0, total=0; const tr_torrent * tor = ccp->tor;
tr_piece_index_t i; const tr_info * info = &tor->info;
tr_completion * cp ; uint64_t have = 0;
uint64_t total = 0;
tr_piece_index_t i;
tr_completion * cp ;
if( !ccp->doneDirty ) /* too bad C doesn't have 'mutable' */
return; cp = (tr_completion*) ccp;
cp->doneDirty = FALSE;
/* too bad C doesn't have 'mutable' */ for( i=0; i<info->pieceCount; ++i ) {
cp = (tr_completion*) ccp; if( !info->pieces[i].dnd ) {
cp->doneDirty = FALSE; total += info->pieceSize;
have += cp->completeBlocks[ i ];
for( i=0; i<info->pieceCount; ++i ) { }
if( !info->pieces[i].dnd ) {
total += info->pieceSize;
have += cp->completeBlocks[ i ];
} }
have *= tor->blockSize;
/* the last piece/block is probably smaller than the others */
if( !info->pieces[info->pieceCount-1].dnd ) {
total -= ( info->pieceSize - tr_torPieceCountBytes(tor,info->pieceCount-1) );
if( tr_cpBlockIsComplete( cp, tor->blockCount-1 ) )
have -= ( tor->blockSize - tr_torBlockCountBytes(tor,tor->blockCount-1) );
}
assert( have <= total );
assert( total <= info->totalSize );
cp->doneHave = have;
cp->doneTotal = total;
} }
have *= tor->blockSize;
/* the last piece/block is probably smaller than the others */
if( !info->pieces[info->pieceCount-1].dnd ) {
total -= ( info->pieceSize - tr_torPieceCountBytes(tor,info->pieceCount-1) );
if( tr_cpBlockIsComplete( cp, tor->blockCount-1 ) )
have -= ( tor->blockSize - tr_torBlockCountBytes(tor,tor->blockCount-1) );
}
assert( have <= total );
assert( total <= info->totalSize );
cp->doneHave = have;
cp->doneTotal = total;
} }
void void
@ -311,10 +312,8 @@ tr_cpGetStatus ( const tr_completion * cp )
tr_cpEnsureDoneValid( cp ); tr_cpEnsureDoneValid( cp );
if( cp->doneHave >= cp->doneTotal ) return cp->doneHave >= cp->doneTotal ? TR_CP_DONE
return TR_CP_DONE; : TR_CP_INCOMPLETE;
return TR_CP_INCOMPLETE;
} }
uint64_t uint64_t

View File

@ -195,24 +195,24 @@ ipc_initmsgs( void )
} }
void void
ipc_addmsg( struct ipc_funcs * tree, enum ipc_msg id, trd_msgfunc func ) ipc_addmsg( struct ipc_funcs * funcs, enum ipc_msg msg_id, trd_msgfunc func )
{ {
assert( MSGVALID( id ) ); assert( MSGVALID( msg_id ) );
assert( IPC_MSG_VERSION != id ); assert( IPC_MSG_VERSION != msg_id );
tree->msgs[id] = func; funcs->msgs[msg_id] = func;
} }
void void
ipc_setdefmsg( struct ipc_funcs * tree, trd_msgfunc func ) ipc_setdefmsg( struct ipc_funcs * funcs, trd_msgfunc func )
{ {
tree->def = func; funcs->def = func;
} }
void void
ipc_freemsgs( struct ipc_funcs * tree ) ipc_freemsgs( struct ipc_funcs * funcs )
{ {
tr_free( tree ); tr_free( funcs );
} }
struct ipc_info * struct ipc_info *
@ -230,8 +230,28 @@ ipc_freecon( struct ipc_info * info )
tr_free( info ); tr_free( info );
} }
int
ipc_ishandled( const struct ipc_info * info, enum ipc_msg id )
{
assert( MSGVALID( id ) );
return info->funcs->msgs[id] != NULL;
}
int
ipc_havetags( const struct ipc_info * info )
{
return !DICTPAYLOAD( info );
}
static int static int
ipc_havemsg( const struct ipc_info * info, enum ipc_msg id ) sessionSupportsTags( const struct ipc_info * session )
{
return session->vers >= 2;
}
static int
sessionSupportsMessage( const struct ipc_info * info, enum ipc_msg id )
{ {
assert( MSGVALID( id ) ); assert( MSGVALID( id ) );
assert( ipc_hasvers( info ) ); assert( ipc_hasvers( info ) );
@ -239,51 +259,61 @@ ipc_havemsg( const struct ipc_info * info, enum ipc_msg id )
return gl_msgs[id].minvers <= info->vers; return gl_msgs[id].minvers <= info->vers;
} }
/**
* Creates the benc metainfo structure for a message
* and returns its child where payload should be set.
*
* In protocol version 1, the metainfo is a single-entry
* dictionary with a string from gl_msgs as the key
* and the return tr_benc pointer as the value.
*
* In protocol version 2, the metainfo is a list
* holding a string from gl_msgs, the return benc pointer,
* and (optionally) the integer tag.
*/
tr_benc * tr_benc *
ipc_initval( const struct ipc_info * info, enum ipc_msg id, int64_t tag, ipc_initval( const struct ipc_info * session,
tr_benc * pk, int type ) enum ipc_msg msg_id,
int64_t tag,
tr_benc * pk,
int benc_type )
{ {
tr_benc * ret; tr_benc * ret;
assert( MSGVALID( id ) ); assert( MSGVALID( msg_id ) );
if( !ipc_havemsg( info, id ) || ( 0 < tag && !ipc_havetags( info ) ) ) if( !sessionSupportsMessage( session, msg_id )
|| ( (tag>0) && !sessionSupportsTags( session ) ) )
{ {
errno = EPERM; errno = EPERM;
return NULL; return NULL;
} }
if( DICTPAYLOAD( info ) ) if( DICTPAYLOAD( session ) )
{ {
tr_bencInit( pk, TYPE_DICT ); tr_bencInitDict( pk, 1 );
if( tr_bencDictReserve( pk, 1 ) ) ret = tr_bencDictAdd( pk, MSGNAME( msg_id ) );
{
return NULL;
}
ret = tr_bencDictAdd( pk, MSGNAME( id ) );
} }
else else
{ {
tr_bencInit( pk, TYPE_LIST ); tr_bencInitList( pk, 3 );
if( tr_bencListReserve( pk, ( 0 < tag ? 3 : 2 ) ) ) tr_bencInitStr( tr_bencListAdd( pk ), MSGNAME( msg_id ), -1, 1 );
{
return NULL;
}
tr_bencInitStr( tr_bencListAdd( pk ), MSGNAME( id ), -1, 1 );
ret = tr_bencListAdd( pk ); ret = tr_bencListAdd( pk );
if( 0 < tag ) if( 0 < tag )
{
tr_bencInitInt( tr_bencListAdd( pk ), tag ); tr_bencInitInt( tr_bencListAdd( pk ), tag );
}
} }
tr_bencInit( ret, type ); tr_bencInit( ret, benc_type );
return ret; return ret;
} }
/**
* Serialize a benc message into a string appended to a
* printf()'ed string IPC_MIN_MSG_LEN bytes long that
* gives the length of the string.
*/
uint8_t * uint8_t *
ipc_mkval( const tr_benc * pk, size_t * setmeSize ) ipc_serialize( const tr_benc * pk, size_t * setmeSize )
{ {
int bencSize = 0; int bencSize = 0;
char * benc = tr_bencSave( pk, &bencSize ); char * benc = tr_bencSave( pk, &bencSize );
@ -303,137 +333,161 @@ ipc_mkval( const tr_benc * pk, size_t * setmeSize )
return ret; return ret;
} }
/**
* Create a serialized message whose payload is a NULL string
*/
uint8_t * uint8_t *
ipc_mkempty( const struct ipc_info * info, size_t * len, enum ipc_msg id, ipc_mkempty( const struct ipc_info * session,
int64_t tag ) size_t * setmeSize,
enum ipc_msg msg_id,
int64_t tag )
{ {
tr_benc pk; return ipc_mkstr( session, setmeSize, msg_id, tag, NULL );
uint8_t * ret = NULL;
if( ipc_initval( info, id, tag, &pk, TYPE_STR ) )
{
ret = ipc_mkval( &pk, len );
SAFEBENCFREE( &pk );
}
return ret;
} }
/**
* Create a serialized message whose payload is an integer
*/
uint8_t * uint8_t *
ipc_mkint( const struct ipc_info * info, size_t * len, enum ipc_msg id, ipc_mkint( const struct ipc_info * session,
int64_t tag, int64_t num ) size_t * setmeSize,
enum ipc_msg msg_id,
int64_t tag,
int64_t num )
{ {
tr_benc pk, * val; tr_benc pk, * val;
uint8_t * ret = NULL; uint8_t * ret = NULL;
if(( val = ipc_initval( info, id, tag, &pk, TYPE_INT ))) if(( val = ipc_initval( session, msg_id, tag, &pk, TYPE_INT )))
{ {
val->val.i = num; val->val.i = num;
ret = ipc_mkval( &pk, len ); ret = ipc_serialize( &pk, setmeSize );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
} }
return ret; return ret;
} }
/**
* Create a serialized message whose payload is a string
*/
uint8_t * uint8_t *
ipc_mkstr( const struct ipc_info * info, size_t * len, enum ipc_msg id, ipc_mkstr( const struct ipc_info * session,
int64_t tag, const char * str ) size_t * setmeSize,
enum ipc_msg msg_id,
int64_t tag,
const char * str )
{ {
tr_benc pk, * val; tr_benc pk, * val;
uint8_t * ret = NULL; uint8_t * ret = NULL;
if(( val = ipc_initval( info, id, tag, &pk, TYPE_STR ))) if(( val = ipc_initval( session, msg_id, tag, &pk, TYPE_STR )))
{ {
tr_bencInitStr( val, str, -1, 1 ); tr_bencInitStr( val, str, -1, 1 );
ret = ipc_mkval( &pk, len ); ret = ipc_serialize( &pk, setmeSize );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
} }
return ret; return ret;
} }
/**
* Create a serialized message whose payload is a dictionary
* giving the minimum and maximum protocol version we support,
* and (optionally) the label passed in.
*
* Note that this message is just the dictionary payload.
* It doesn't contain metainfo as the other ipc_mk*() functions do.
*/
uint8_t * uint8_t *
ipc_mkvers( size_t * len, const char * label ) ipc_mkvers( size_t * len, const char * label )
{ {
tr_benc pk, * dict; tr_benc pk, * dict;
uint8_t * ret; uint8_t * ret;
tr_bencInit( &pk, TYPE_DICT ); tr_bencInitDict( &pk, 1 );
if( tr_bencDictReserve( &pk, 1 ) )
{
return NULL;
}
dict = tr_bencDictAdd( &pk, MSGNAME( IPC_MSG_VERSION ) ); dict = tr_bencDictAdd( &pk, MSGNAME( IPC_MSG_VERSION ) );
tr_bencInit( dict, TYPE_DICT ); tr_bencInitDict( dict, 3 );
if( tr_bencDictReserve( dict, ( NULL == label ? 2 : 3 ) ) )
{
SAFEBENCFREE( &pk );
return NULL;
}
tr_bencInitInt( tr_bencDictAdd( dict, "min" ), PROTO_VERS_MIN ); tr_bencInitInt( tr_bencDictAdd( dict, "min" ), PROTO_VERS_MIN );
tr_bencInitInt( tr_bencDictAdd( dict, "max" ), PROTO_VERS_MAX ); tr_bencInitInt( tr_bencDictAdd( dict, "max" ), PROTO_VERS_MAX );
if( NULL != label ) if( label )
tr_bencInitStr( tr_bencDictAdd( dict, "label" ), label, -1, 1 ); tr_bencInitStr( tr_bencDictAdd( dict, "label" ), label, -1, 1 );
ret = ipc_mkval( &pk, len ); ret = ipc_serialize( &pk, len );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
return ret; return ret;
} }
/**
* Create a serialized message that is used to request
* torrent information or statistics.
*
* msg_id must be one of:
* IPC_MSG_GETINFO
* IPC_MSG_GETINFOALL
* IPC_MSG_GETSTAT
* IPC_MSG_GETSTATALL
*
* "ids" is an optional array of torrent IDs.
* The array, if included, must be terminated by a 0 torrent id.
*
* "types" is a bitwise-and'ed set of fields from either
* the IPC_INF_* or IPC_ST_* enums in ipc-parse.h.
* Which enums are used is dependent on the value of msg_id.
*
* If torrent ids are specified in the "ids" array,
* the payload is a dictionary of two lists, "id" and "type".
* The "id" list holds the torrent IDs, and
* the "type" list holds string keys from either
* gl_inf or gl_stat, depending on the value of msg_id
*
* If no torrent ids are specified, the payload is
* a single list identical to the "type" list described above.
*/
uint8_t * uint8_t *
ipc_mkgetinfo( const struct ipc_info * info, size_t * len, enum ipc_msg id, ipc_mkgetinfo( const struct ipc_info * session,
int64_t tag, int types, const int * ids ) size_t * setmeSize,
enum ipc_msg msg_id,
int64_t tag,
int types,
const int * ids )
{ {
tr_benc pk, * top, * idlist, * typelist; tr_benc pk;
tr_benc * typelist;
size_t ii, typecount, used; size_t ii, typecount, used;
const struct inf * typearray; const struct inf * typearray;
uint8_t * ret; uint8_t * ret;
/* no ID list, send an -all message */ /* no ID list, send an -all message */
if( NULL == ids ) if( !ids ) {
{ typelist = ipc_initval( session, msg_id, tag, &pk, TYPE_LIST );
typelist = ipc_initval( info, id, tag, &pk, TYPE_LIST ); if( !typelist )
if( NULL == typelist )
{
return NULL; return NULL;
}
} }
else else
{ {
top = ipc_initval( info, id, tag, &pk, TYPE_DICT ); tr_benc * top;
if( NULL == top ) tr_benc * idlist;
{
top = ipc_initval( session, msg_id, tag, &pk, TYPE_DICT );
if( !top )
return NULL; return NULL;
}
/* add the requested IDs */ /* add the requested IDs */
if( tr_bencDictReserve( top, 2 ) ) tr_bencDictReserve( top, 2 );
{
SAFEBENCFREE( &pk );
return NULL;
}
idlist = tr_bencDictAdd( top, "id" ); idlist = tr_bencDictAdd( top, "id" );
typelist = tr_bencDictAdd( top, "type" ); typelist = tr_bencDictAdd( top, "type" );
tr_bencInit( idlist, TYPE_LIST );
tr_bencInit( typelist, TYPE_LIST ); tr_bencInit( typelist, TYPE_LIST );
for( ii = 0; TORRENT_ID_VALID( ids[ii] ); ii++ ) { }
tr_bencInitList( idlist, ii );
for( ii = 0; TORRENT_ID_VALID( ids[ii] ); ii++ ) for( ii = 0; TORRENT_ID_VALID( ids[ii] ); ii++ )
{
}
if( tr_bencListReserve( idlist, ii ) )
{
SAFEBENCFREE( &pk );
return NULL;
}
for( ii = 0; TORRENT_ID_VALID( ids[ii] ); ii++ )
{
tr_bencInitInt( tr_bencListAdd( idlist ), ids[ii] ); tr_bencInitInt( tr_bencListAdd( idlist ), ids[ii] );
}
} }
/* get the type name array */ /* get the type name array */
switch( id ) switch( msg_id )
{ {
case IPC_MSG_GETINFO: case IPC_MSG_GETINFO:
case IPC_MSG_GETINFOALL: case IPC_MSG_GETINFOALL:
@ -452,53 +506,51 @@ ipc_mkgetinfo( const struct ipc_info * info, size_t * len, enum ipc_msg id,
/* add the type names */ /* add the type names */
for( ii = used = 0; typecount > ii; ii++ ) for( ii = used = 0; typecount > ii; ii++ )
{
if( types & ( 1 << ii ) ) if( types & ( 1 << ii ) )
{
used++; used++;
} tr_bencListReserve( typelist, used );
}
if( tr_bencListReserve( typelist, used ) )
{
SAFEBENCFREE( &pk );
return NULL;
}
for( ii = 0; typecount > ii; ii++ ) for( ii = 0; typecount > ii; ii++ )
{ {
if( !( types & ( 1 << ii ) ) ) if( !( types & ( 1 << ii ) ) )
{
continue; continue;
}
assert( typearray[ii].type == ( 1 << ii ) ); assert( typearray[ii].type == ( 1 << ii ) );
tr_bencInitStr( tr_bencListAdd( typelist ), tr_bencInitStr( tr_bencListAdd( typelist ),
typearray[ii].name, -1, 1 ); typearray[ii].name, -1, 1 );
} }
/* generate packet */ /* generate packet */
ret = ipc_mkval( &pk, len ); ret = ipc_serialize( &pk, setmeSize );
SAFEBENCFREE( &pk ); SAFEBENCFREE( &pk );
return ret; return ret;
} }
static int static void
filltracker( tr_benc * val, const tr_tracker_info * tk ) filltracker( tr_benc * val, const tr_tracker_info * tk )
{ {
tr_bencInit( val, TYPE_DICT ); tr_bencInitDict( val, 4 );
if( tr_bencDictReserve( val, ( NULL == tk->scrape ? 3 : 4 ) ) )
return -1;
tr_bencInitStr( tr_bencDictAdd( val, "address" ), tk->address, -1, 1 ); tr_bencInitStr( tr_bencDictAdd( val, "address" ), tk->address, -1, 1 );
tr_bencInitInt( tr_bencDictAdd( val, "port" ), tk->port ); tr_bencInitInt( tr_bencDictAdd( val, "port" ), tk->port );
tr_bencInitStr( tr_bencDictAdd( val, "announce" ), tk->announce, -1, 1 ); tr_bencInitStr( tr_bencDictAdd( val, "announce" ), tk->announce, -1, 1 );
if( NULL != tk->scrape ) if( NULL != tk->scrape )
tr_bencInitStr( tr_bencDictAdd( val, "scrape" ), tk->scrape, -1, 1 ); tr_bencInitStr( tr_bencDictAdd( val, "scrape" ), tk->scrape, -1, 1 );
return 0;
} }
/**
* append to "list" a dictionary whose keys are
* the string keys from gl_inf and whose values are
* torrent info set from "torrent_id" and "inf".
*
* "types" is a bitwise-and'ed set of fields
* from the IPC_INF_* enum in ipcparse.h.
* It specifies what to put in the dictionary.
*/
int int
ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types ) ipc_addinfo( tr_benc * list,
int torrent_id,
const tr_info * inf,
int types )
{ {
tr_benc * dict, * item, * file, * tier; tr_benc * dict, * item, * file, * tier;
int ii, jj, kk; int ii, jj, kk;
@ -507,75 +559,47 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
/* always send torrent id */ /* always send torrent id */
types |= IPC_INF_ID; types |= IPC_INF_ID;
if( tr_bencListReserve( list, 1 ) ) tr_bencListReserve( list, 1 );
{
return -1;
}
dict = tr_bencListAdd( list ); dict = tr_bencListAdd( list );
tr_bencInit( dict, TYPE_DICT );
/* count the number of info keys and allocate a dict for them */
for( ii = jj = 0; IPC_INF__MAX > 1 << ii; ii++ ) for( ii = jj = 0; IPC_INF__MAX > 1 << ii; ii++ )
{ {
if( !( types & ( 1 << ii ) ) ) if( !( types & ( 1 << ii ) ) )
{
continue; continue;
}
assert( TR_N_ELEMENTS( gl_inf ) > ( unsigned )ii ); assert( TR_N_ELEMENTS( gl_inf ) > ( unsigned )ii );
assert( gl_inf[ii].type == ( 1 << ii ) ); assert( gl_inf[ii].type == ( 1 << ii ) );
/* check for missing optional info */
if( ( IPC_INF_COMMENT == ( 1 << ii ) && !*inf->comment ) ||
( IPC_INF_CREATOR == ( 1 << ii ) && !*inf->creator ) ||
( IPC_INF_DATE == ( 1 << ii ) && 0 >= inf->dateCreated ) )
{
continue;
}
jj++; jj++;
} }
if( tr_bencDictReserve( dict, jj ) )
{
return -1;
}
tr_bencInitDict( dict, jj );
/* populate the dict with info key->value pairs */
for( ii = 0; IPC_INF__MAX > 1 << ii; ii++ ) for( ii = 0; IPC_INF__MAX > 1 << ii; ii++ )
{ {
if( !( types & ( 1 << ii ) ) ) if( !( types & ( 1 << ii ) ) )
{
continue; continue;
}
/* check for missing optional info */
if( ( IPC_INF_COMMENT == ( 1 << ii ) && !*inf->comment ) ||
( IPC_INF_CREATOR == ( 1 << ii ) && !*inf->creator ) ||
( IPC_INF_DATE == ( 1 << ii ) && 0 >= inf->dateCreated ) )
{
continue;
}
item = tr_bencDictAdd( dict, gl_inf[ii].name ); item = tr_bencDictAdd( dict, gl_inf[ii].name );
switch( 1 << ii ) switch( 1 << ii )
{ {
case IPC_INF_COMMENT: case IPC_INF_COMMENT:
tr_bencInitStr( item, inf->comment, -1, 1 ); tr_bencInitStr( item, inf->comment ? inf->comment : "", -1, 1 );
break; break;
case IPC_INF_CREATOR: case IPC_INF_CREATOR:
tr_bencInitStr( item, inf->creator, -1, 1 ); tr_bencInitStr( item, inf->creator ? inf->creator : "", -1, 1 );
break; break;
case IPC_INF_DATE: case IPC_INF_DATE:
tr_bencInitInt( item, inf->dateCreated ); tr_bencInitInt( item, inf->dateCreated );
break; break;
case IPC_INF_FILES: case IPC_INF_FILES:
tr_bencInit( item, TYPE_LIST ); tr_bencInitList( item, inf->fileCount );
if( tr_bencListReserve( item, inf->fileCount ) )
{
return -1;
}
for( ff = 0; inf->fileCount > ff; ff++ ) for( ff = 0; inf->fileCount > ff; ff++ )
{ {
file = tr_bencListAdd( item ); file = tr_bencListAdd( item );
tr_bencInit( file, TYPE_DICT ); tr_bencInitDict( file, 2 );
if( tr_bencDictReserve( file, 2 ) )
{
return -1;
}
tr_bencInitStr( tr_bencDictAdd( file, "name" ), tr_bencInitStr( tr_bencDictAdd( file, "name" ),
inf->files[ff].name, -1, 1 ); inf->files[ff].name, -1, 1 );
tr_bencInitInt( tr_bencDictAdd( file, "size" ), tr_bencInitInt( tr_bencDictAdd( file, "size" ),
@ -586,7 +610,7 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
tr_bencInitStr( item, inf->hashString, -1, 1 ); tr_bencInitStr( item, inf->hashString, -1, 1 );
break; break;
case IPC_INF_ID: case IPC_INF_ID:
tr_bencInitInt( item, tor ); tr_bencInitInt( item, torrent_id );
break; break;
case IPC_INF_NAME: case IPC_INF_NAME:
tr_bencInitStr( item, inf->name, -1, 1 ); tr_bencInitStr( item, inf->name, -1, 1 );
@ -601,28 +625,14 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
tr_bencInitInt( item, inf->totalSize ); tr_bencInitInt( item, inf->totalSize );
break; break;
case IPC_INF_TRACKERS: case IPC_INF_TRACKERS:
tr_bencInit( item, TYPE_LIST ); tr_bencInitList( item, inf->trackerTiers );
if( tr_bencListReserve( item, inf->trackerTiers ) )
{
return -1;
}
for( jj = 0; inf->trackerTiers > jj; jj++ ) for( jj = 0; inf->trackerTiers > jj; jj++ )
{ {
tier = tr_bencListAdd( item ); tier = tr_bencListAdd( item );
tr_bencInit( tier, TYPE_LIST ); tr_bencInitList( tier, inf->trackerList[jj].count );
if( tr_bencListReserve( tier,
inf->trackerList[jj].count ) )
{
return -1;
}
for( kk = 0; inf->trackerList[jj].count > kk; kk++ ) for( kk = 0; inf->trackerList[jj].count > kk; kk++ )
{ filltracker( tr_bencListAdd( tier ),
if( 0 > filltracker( tr_bencListAdd( tier ), &inf->trackerList[jj].list[kk] );
&inf->trackerList[jj].list[kk] ) )
{
return -1;
}
}
} }
break; break;
default: default:
@ -634,32 +644,42 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
return 0; return 0;
} }
/**
* append to "list" a dictionary whose keys are
* the string keys from gl_stat and whose values
* are torrent statistics set from "st".
*
* "types" is a bitwise-and'ed set of fields
* from the IPC_INF_* enum in ipcparse.h.
* It specifies what to put in the dictionary.
*/
int int
ipc_addstat( tr_benc * list, int tor, ipc_addstat( tr_benc * list,
const tr_stat * st, int types ) int torrent_id,
const tr_stat * st,
int types )
{ {
tr_benc * dict, * item; tr_benc * dict;
int ii, used; int ii, used;
tr_errno error;
/* add the dictionary child */
tr_bencListReserve( list, 1 );
dict = tr_bencListAdd( list );
/* always send torrent id */ /* always send torrent id */
types |= IPC_ST_ID; types |= IPC_ST_ID;
if( tr_bencListReserve( list, 1 ) ) /* count the number of stat keys and allocate a dict for them */
return -1;
dict = tr_bencListAdd( list );
for( ii = used = 0; IPC_ST__MAX > 1 << ii; ii++ ) for( ii = used = 0; IPC_ST__MAX > 1 << ii; ii++ )
if( types & ( 1 << ii ) ) if( types & ( 1 << ii ) )
used++; used++;
tr_bencInitDict( dict, used );
tr_bencInit( dict, TYPE_DICT ); /* populate the dict */
if( tr_bencDictReserve( dict, used ) )
return -1;
for( ii = 0; IPC_ST__MAX > 1 << ii; ii++ ) for( ii = 0; IPC_ST__MAX > 1 << ii; ii++ )
{ {
tr_benc * item;
if( !( types & ( 1 << ii ) ) ) if( !( types & ( 1 << ii ) ) )
continue; continue;
@ -678,8 +698,8 @@ ipc_addstat( tr_benc * list, int tor,
case IPC_ST_DOWNTOTAL: case IPC_ST_DOWNTOTAL:
tr_bencInitInt( item, st->downloadedEver ); tr_bencInitInt( item, st->downloadedEver );
break; break;
case IPC_ST_ERROR: case IPC_ST_ERROR: {
error = st->error; const tr_errno error = st->error;
if( TR_OK == error ) if( TR_OK == error )
{ {
tr_bencInitStr( item, "", -1, 1 ); tr_bencInitStr( item, "", -1, 1 );
@ -725,6 +745,7 @@ ipc_addstat( tr_benc * list, int tor,
tr_bencInitStr( item, "other", -1, 1 ); tr_bencInitStr( item, "other", -1, 1 );
} }
break; break;
}
case IPC_ST_ERRMSG: case IPC_ST_ERRMSG:
if( TR_OK == st->error ) if( TR_OK == st->error )
{ {
@ -743,17 +764,13 @@ ipc_addstat( tr_benc * list, int tor,
tr_bencInitInt( item, st->eta ); tr_bencInitInt( item, st->eta );
break; break;
case IPC_ST_ID: case IPC_ST_ID:
tr_bencInitInt( item, tor ); tr_bencInitInt( item, torrent_id );
break; break;
case IPC_ST_PEERDOWN: case IPC_ST_PEERDOWN:
tr_bencInitInt( item, st->peersSendingToUs ); tr_bencInitInt( item, st->peersSendingToUs );
break; break;
case IPC_ST_PEERFROM: case IPC_ST_PEERFROM:
tr_bencInit( item, TYPE_DICT ); tr_bencInitDict( item, 4 );
if( tr_bencDictReserve( item, 4 ) )
{
return -1;
}
tr_bencInitInt( tr_bencDictAdd( item, "incoming" ), tr_bencInitInt( tr_bencDictAdd( item, "incoming" ),
st->peersFrom[TR_PEER_FROM_INCOMING] ); st->peersFrom[TR_PEER_FROM_INCOMING] );
tr_bencInitInt( tr_bencDictAdd( item, "tracker" ), tr_bencInitInt( tr_bencDictAdd( item, "tracker" ),
@ -802,10 +819,7 @@ ipc_addstat( tr_benc * list, int tor,
tr_bencInitInt( item, st->swarmspeed * 1024 ); tr_bencInitInt( item, st->swarmspeed * 1024 );
break; break;
case IPC_ST_TRACKER: case IPC_ST_TRACKER:
if( 0 > filltracker( item, st->tracker ) ) filltracker( item, st->tracker );
{
return -1;
}
break; break;
case IPC_ST_TKDONE: case IPC_ST_TKDONE:
tr_bencInitInt( item, st->completedFromTracker ); tr_bencInitInt( item, st->completedFromTracker );
@ -906,6 +920,16 @@ msglookup( const char * name )
compareNameToMsg ); compareNameToMsg );
} }
enum ipc_msg
ipc_msgid( const struct ipc_info * info, const char * name )
{
const struct msg * msg = msglookup( name );
return msg && sessionSupportsMessage( info, msg->id )
? msg->id
: IPC__MSG_COUNT;
}
static int static int
gotmsg( const struct ipc_info * info, tr_benc * name, tr_benc * val, gotmsg( const struct ipc_info * info, tr_benc * name, tr_benc * val,
tr_benc * tagval, void * arg ) tr_benc * tagval, void * arg )
@ -1042,30 +1066,6 @@ ipc_parse( struct ipc_info * info, const uint8_t * buf, ssize_t total, void * ar
return off; return off;
} }
enum ipc_msg
ipc_msgid( const struct ipc_info * info, const char * name )
{
const struct msg * msg = msglookup( name );
return msg && ipc_havemsg( info, msg->id )
? msg->id
: IPC__MSG_COUNT;
}
int
ipc_ishandled( const struct ipc_info * info, enum ipc_msg id )
{
assert( MSGVALID( id ) );
return info->funcs->msgs[id] != NULL;
}
int
ipc_havetags( const struct ipc_info * info )
{
return !DICTPAYLOAD( info );
}
static int static int
compareNameToInf( const void * a, const void * b ) compareNameToInf( const void * a, const void * b )
{ {

View File

@ -152,20 +152,20 @@ int ipc_hasvers ( const struct ipc_info * );
/* sets errno to EPERM if requested message not supported by protocol vers */ /* sets errno to EPERM if requested message not supported by protocol vers */
struct tr_benc * ipc_initval ( const struct ipc_info *, enum ipc_msg, struct tr_benc * ipc_initval ( const struct ipc_info *, enum ipc_msg,
int64_t tag, struct tr_benc *, int ); int64_t tag, struct tr_benc *, int );
uint8_t * ipc_mkval ( const struct tr_benc *, size_t * ); uint8_t * ipc_serialize ( const struct tr_benc *, size_t * );
uint8_t * ipc_mkempty ( const struct ipc_info *, size_t *, enum ipc_msg, uint8_t * ipc_mkempty ( const struct ipc_info *, size_t *, enum ipc_msg,
int64_t ); int64_t );
uint8_t * ipc_mkint ( const struct ipc_info *, size_t *, enum ipc_msg, uint8_t * ipc_mkint ( const struct ipc_info *, size_t *, enum ipc_msg,
int64_t tag, int64_t val ); int64_t tag, int64_t val );
uint8_t * ipc_mkstr ( const struct ipc_info *, size_t *, enum ipc_msg, uint8_t * ipc_mkstr ( const struct ipc_info *, size_t *, enum ipc_msg,
int64_t tag, const char * val ); int64_t tag, const char * val );
uint8_t * ipc_mkvers ( size_t *, const char * ); uint8_t * ipc_mkvers ( size_t *, const char * );
uint8_t * ipc_mkgetinfo( const struct ipc_info *, size_t *, enum ipc_msg, uint8_t * ipc_mkgetinfo ( const struct ipc_info *, size_t *, enum ipc_msg,
int64_t, int, const int * ); int64_t, int, const int * );
int ipc_addinfo ( struct tr_benc *, int, int ipc_addinfo ( struct tr_benc *, int,
const struct tr_info *, int ); const struct tr_info *, int );
int ipc_addstat ( struct tr_benc *, int, int ipc_addstat ( struct tr_benc *, int,
const struct tr_stat *, int ); const struct tr_stat *, int );
/* sets errno to EINVAL on parse error or /* sets errno to EINVAL on parse error or
EPERM for unsupported protocol version */ EPERM for unsupported protocol version */

View File

@ -288,8 +288,7 @@ getFileInfo( const char * topFile,
for( pch=file->filename+topLen; *pch; ++pch ) for( pch=file->filename+topLen; *pch; ++pch )
if (*pch == TR_PATH_DELIMITER) if (*pch == TR_PATH_DELIMITER)
++n; ++n;
tr_bencInit( uninitialized_path, TYPE_LIST ); tr_bencInitList( uninitialized_path, n );
tr_bencListReserve( uninitialized_path, n );
for( prev=pch=file->filename+topLen; ; ++pch ) for( prev=pch=file->filename+topLen; ; ++pch )
{ {
char buf[MAX_PATH_LENGTH]; char buf[MAX_PATH_LENGTH];
@ -322,8 +321,7 @@ makeFilesList( tr_benc * list,
tr_benc * dict = tr_bencListAdd( list ); tr_benc * dict = tr_bencListAdd( list );
tr_benc *length, *pathVal; tr_benc *length, *pathVal;
tr_bencInit( dict, TYPE_DICT ); tr_bencInitDict( dict, 2 );
tr_bencDictReserve( dict, 2 );
length = tr_bencDictAdd( dict, "length" ); length = tr_bencDictAdd( dict, "length" );
pathVal = tr_bencDictAdd( dict, "path" ); pathVal = tr_bencDictAdd( dict, "path" );
getFileInfo( builder->top, &builder->files[i], length, pathVal ); getFileInfo( builder->top, &builder->files[i], length, pathVal );
@ -374,9 +372,8 @@ tr_realMakeMetaInfo ( tr_metainfo_builder * builder )
int n = 5; int n = 5;
tr_benc top, *val; tr_benc top, *val;
tr_bencInit ( &top, TYPE_DICT );
if ( builder->comment && *builder->comment ) ++n; if ( builder->comment && *builder->comment ) ++n;
tr_bencDictReserve( &top, n ); tr_bencInitDict( &top, n );
val = tr_bencDictAdd( &top, "announce" ); val = tr_bencDictAdd( &top, "announce" );
tr_bencInitStrDup( val, builder->announce ); tr_bencInitStrDup( val, builder->announce );
@ -402,8 +399,7 @@ tr_realMakeMetaInfo ( tr_metainfo_builder * builder )
tr_bencInitStrDup( val, "UTF-8" ); tr_bencInitStrDup( val, "UTF-8" );
val = tr_bencDictAdd( &top, "info" ); val = tr_bencDictAdd( &top, "info" );
tr_bencInit( val, TYPE_DICT ); tr_bencInitDict( val, 666 );
tr_bencDictReserve( val, 666 );
makeInfoDict( val, builder ); makeInfoDict( val, builder );
} }

View File

@ -871,8 +871,7 @@ sendLtepHandshake( tr_peermsgs * msgs )
else else
pex = 1; pex = 1;
tr_bencInit( &val, TYPE_DICT ); tr_bencInitDict( &val, 4 );
tr_bencDictReserve( &val, 4 );
tr_bencInitInt( tr_bencDictAdd( &val, "e" ), 1 ); tr_bencInitInt( tr_bencDictAdd( &val, "e" ), 1 );
m = tr_bencDictAdd( &val, "m" ); m = tr_bencDictAdd( &val, "m" );
tr_bencInit( m, TYPE_DICT ); tr_bencInit( m, TYPE_DICT );
@ -1840,8 +1839,7 @@ sendPex( tr_peermsgs * msgs )
msgs->pexCount = diffs.elementCount; msgs->pexCount = diffs.elementCount;
/* build the pex payload */ /* build the pex payload */
tr_bencInit( &val, TYPE_DICT ); tr_bencInitDict( &val, 3 );
tr_bencDictReserve( &val, 3 );
/* "added" */ /* "added" */
added = tr_bencDictAdd( &val, "added" ); added = tr_bencDictAdd( &val, "added" );

View File

@ -89,8 +89,7 @@ saveCumulativeStats( const tr_session_stats * stats )
int len; int len;
tr_benc top; tr_benc top;
tr_bencInit( &top, TYPE_DICT ); tr_bencInitDict( &top, 5 );
tr_bencDictReserve( &top, 5 );
tr_bencInitInt( tr_bencDictAdd( &top, "uploaded-bytes" ), stats->uploadedBytes ); tr_bencInitInt( tr_bencDictAdd( &top, "uploaded-bytes" ), stats->uploadedBytes );
tr_bencInitInt( tr_bencDictAdd( &top, "downloaded-bytes" ), stats->downloadedBytes ); tr_bencInitInt( tr_bencDictAdd( &top, "downloaded-bytes" ), stats->downloadedBytes );
tr_bencInitInt( tr_bencDictAdd( &top, "files-added" ), stats->filesAdded ); tr_bencInitInt( tr_bencDictAdd( &top, "files-added" ), stats->filesAdded );

View File

@ -723,7 +723,7 @@ struct tr_info
/* Torrent info */ /* Torrent info */
char * comment; char * comment;
char * creator; char * creator;
int dateCreated; time_t dateCreated;
/* Pieces info */ /* Pieces info */
uint32_t pieceSize; uint32_t pieceSize;