hack on IPC a bit because it's been too long since I broke it
This commit is contained in:
parent
918f8f4936
commit
fd0e71c00a
|
@ -794,7 +794,7 @@ flushreqs( struct con * con )
|
|||
tr_bencInitStr( tr_bencListAdd( val ),
|
||||
jj->str, -1, 1 );
|
||||
}
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
SAFEFREESTRLIST( req->strs );
|
||||
|
@ -805,7 +805,7 @@ flushreqs( struct con * con )
|
|||
{
|
||||
tr_bencInitStr( tr_bencDictAdd( val, "data" ),
|
||||
req->buf, req->listlen, 1 );
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
SAFEFREE( req->buf );
|
||||
|
@ -833,7 +833,7 @@ flushreqs( struct con * con )
|
|||
tr_bencInitInt( tr_bencListAdd( val ),
|
||||
req->numlist[ii] );
|
||||
}
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
SAFEFREE( req->numlist );
|
||||
|
|
|
@ -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 );
|
||||
queuemsg( client, buf, buflen );
|
||||
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 );
|
||||
return;
|
||||
}
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
tr_bencFree( &pk );
|
||||
queuemsg( client, buf, buflen );
|
||||
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 */
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
tr_bencFree( &pk );
|
||||
queuemsg( client, buf, buflen );
|
||||
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 );
|
||||
queuemsg( client, buf, buflen );
|
||||
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 );
|
||||
}
|
||||
|
||||
buf = ipc_mkval( &pk, &buflen );
|
||||
buf = ipc_serialize( &pk, &buflen );
|
||||
tr_bencFree( &pk );
|
||||
queuemsg( client, buf, buflen );
|
||||
free( buf );
|
||||
|
|
10
gtk/ipc.c
10
gtk/ipc.c
|
@ -183,7 +183,7 @@ client_sendmsg( struct constate * con )
|
|||
{
|
||||
tr_bencInitStr( tr_bencListAdd( val ), ii->data, -1, 0 );
|
||||
}
|
||||
buf = ipc_mkval( &packet, &size );
|
||||
buf = ipc_serialize( &packet, &size );
|
||||
saved = errno;
|
||||
tr_bencFree( &packet );
|
||||
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 );
|
||||
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 ) );
|
||||
}
|
||||
|
||||
buf = ipc_mkval( &packet, &size );
|
||||
buf = ipc_serialize( &packet, &size );
|
||||
tr_bencFree( &packet );
|
||||
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 );
|
||||
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 );
|
||||
}
|
||||
|
||||
buf = ipc_mkval( &packet, &size );
|
||||
buf = ipc_serialize( &packet, &size );
|
||||
tr_bencFree( &packet );
|
||||
if( NULL == buf )
|
||||
{
|
||||
|
|
|
@ -440,19 +440,31 @@ tr_bencInitInt( tr_benc * val, int64_t num )
|
|||
val->val.i = num;
|
||||
}
|
||||
|
||||
int
|
||||
tr_bencInitList( tr_benc * val, int reserveCount )
|
||||
{
|
||||
tr_bencInit( val, TYPE_LIST );
|
||||
return tr_bencListReserve( val, reserveCount );
|
||||
}
|
||||
|
||||
int
|
||||
tr_bencListReserve( tr_benc * val, int count )
|
||||
{
|
||||
assert( isList( val ) );
|
||||
|
||||
return makeroom( val, count );
|
||||
}
|
||||
|
||||
int
|
||||
tr_bencInitDict( tr_benc * val, int reserveCount )
|
||||
{
|
||||
tr_bencInit( val, TYPE_DICT );
|
||||
return tr_bencDictReserve( val, reserveCount );
|
||||
}
|
||||
|
||||
int
|
||||
tr_bencDictReserve( tr_benc * val, int count )
|
||||
{
|
||||
assert( isDict( val ) );
|
||||
|
||||
return makeroom( val, count * 2 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
int tr_bencInitStrDup( tr_benc * val, const char * str );
|
||||
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 );
|
||||
/* note that for one key-value pair, count should be 1, not 2 */
|
||||
int tr_bencDictReserve( tr_benc * dict, int count );
|
||||
|
|
|
@ -94,40 +94,41 @@ void tr_cpClose( tr_completion * cp )
|
|||
static void
|
||||
tr_cpEnsureDoneValid( const tr_completion * ccp )
|
||||
{
|
||||
const tr_torrent * tor = ccp->tor;
|
||||
const tr_info * info = &tor->info;
|
||||
uint64_t have=0, total=0;
|
||||
tr_piece_index_t i;
|
||||
tr_completion * cp ;
|
||||
if( ccp->doneDirty )
|
||||
{
|
||||
const tr_torrent * tor = ccp->tor;
|
||||
const tr_info * info = &tor->info;
|
||||
uint64_t have = 0;
|
||||
uint64_t total = 0;
|
||||
tr_piece_index_t i;
|
||||
tr_completion * cp ;
|
||||
|
||||
if( !ccp->doneDirty )
|
||||
return;
|
||||
/* too bad C doesn't have 'mutable' */
|
||||
cp = (tr_completion*) ccp;
|
||||
cp->doneDirty = FALSE;
|
||||
|
||||
/* too bad C doesn't have 'mutable' */
|
||||
cp = (tr_completion*) ccp;
|
||||
cp->doneDirty = FALSE;
|
||||
|
||||
for( i=0; i<info->pieceCount; ++i ) {
|
||||
if( !info->pieces[i].dnd ) {
|
||||
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
|
||||
|
@ -311,10 +312,8 @@ tr_cpGetStatus ( const tr_completion * cp )
|
|||
|
||||
tr_cpEnsureDoneValid( cp );
|
||||
|
||||
if( cp->doneHave >= cp->doneTotal )
|
||||
return TR_CP_DONE;
|
||||
|
||||
return TR_CP_INCOMPLETE;
|
||||
return cp->doneHave >= cp->doneTotal ? TR_CP_DONE
|
||||
: TR_CP_INCOMPLETE;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
|
|
|
@ -195,24 +195,24 @@ ipc_initmsgs( 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( IPC_MSG_VERSION != id );
|
||||
assert( MSGVALID( msg_id ) );
|
||||
assert( IPC_MSG_VERSION != msg_id );
|
||||
|
||||
tree->msgs[id] = func;
|
||||
funcs->msgs[msg_id] = func;
|
||||
}
|
||||
|
||||
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
|
||||
ipc_freemsgs( struct ipc_funcs * tree )
|
||||
ipc_freemsgs( struct ipc_funcs * funcs )
|
||||
{
|
||||
tr_free( tree );
|
||||
tr_free( funcs );
|
||||
}
|
||||
|
||||
struct ipc_info *
|
||||
|
@ -230,8 +230,28 @@ ipc_freecon( struct ipc_info * 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
|
||||
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( 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 *
|
||||
ipc_initval( const struct ipc_info * info, enum ipc_msg id, int64_t tag,
|
||||
tr_benc * pk, int type )
|
||||
ipc_initval( const struct ipc_info * session,
|
||||
enum ipc_msg msg_id,
|
||||
int64_t tag,
|
||||
tr_benc * pk,
|
||||
int benc_type )
|
||||
{
|
||||
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;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( DICTPAYLOAD( info ) )
|
||||
if( DICTPAYLOAD( session ) )
|
||||
{
|
||||
tr_bencInit( pk, TYPE_DICT );
|
||||
if( tr_bencDictReserve( pk, 1 ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
ret = tr_bencDictAdd( pk, MSGNAME( id ) );
|
||||
tr_bencInitDict( pk, 1 );
|
||||
ret = tr_bencDictAdd( pk, MSGNAME( msg_id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_bencInit( pk, TYPE_LIST );
|
||||
if( tr_bencListReserve( pk, ( 0 < tag ? 3 : 2 ) ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
tr_bencInitStr( tr_bencListAdd( pk ), MSGNAME( id ), -1, 1 );
|
||||
tr_bencInitList( pk, 3 );
|
||||
tr_bencInitStr( tr_bencListAdd( pk ), MSGNAME( msg_id ), -1, 1 );
|
||||
ret = tr_bencListAdd( pk );
|
||||
if( 0 < tag )
|
||||
{
|
||||
tr_bencInitInt( tr_bencListAdd( pk ), tag );
|
||||
}
|
||||
}
|
||||
|
||||
tr_bencInit( ret, type );
|
||||
|
||||
tr_bencInit( ret, benc_type );
|
||||
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 *
|
||||
ipc_mkval( const tr_benc * pk, size_t * setmeSize )
|
||||
ipc_serialize( const tr_benc * pk, size_t * setmeSize )
|
||||
{
|
||||
int bencSize = 0;
|
||||
char * benc = tr_bencSave( pk, &bencSize );
|
||||
|
@ -303,137 +333,161 @@ ipc_mkval( const tr_benc * pk, size_t * setmeSize )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a serialized message whose payload is a NULL string
|
||||
*/
|
||||
uint8_t *
|
||||
ipc_mkempty( const struct ipc_info * info, size_t * len, enum ipc_msg id,
|
||||
int64_t tag )
|
||||
ipc_mkempty( const struct ipc_info * session,
|
||||
size_t * setmeSize,
|
||||
enum ipc_msg msg_id,
|
||||
int64_t tag )
|
||||
{
|
||||
tr_benc pk;
|
||||
uint8_t * ret = NULL;
|
||||
|
||||
if( ipc_initval( info, id, tag, &pk, TYPE_STR ) )
|
||||
{
|
||||
ret = ipc_mkval( &pk, len );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ipc_mkstr( session, setmeSize, msg_id, tag, NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a serialized message whose payload is an integer
|
||||
*/
|
||||
uint8_t *
|
||||
ipc_mkint( const struct ipc_info * info, size_t * len, enum ipc_msg id,
|
||||
int64_t tag, int64_t num )
|
||||
ipc_mkint( const struct ipc_info * session,
|
||||
size_t * setmeSize,
|
||||
enum ipc_msg msg_id,
|
||||
int64_t tag,
|
||||
int64_t num )
|
||||
{
|
||||
tr_benc pk, * val;
|
||||
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;
|
||||
ret = ipc_mkval( &pk, len );
|
||||
ret = ipc_serialize( &pk, setmeSize );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a serialized message whose payload is a string
|
||||
*/
|
||||
uint8_t *
|
||||
ipc_mkstr( const struct ipc_info * info, size_t * len, enum ipc_msg id,
|
||||
int64_t tag, const char * str )
|
||||
ipc_mkstr( const struct ipc_info * session,
|
||||
size_t * setmeSize,
|
||||
enum ipc_msg msg_id,
|
||||
int64_t tag,
|
||||
const char * str )
|
||||
{
|
||||
tr_benc pk, * val;
|
||||
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 );
|
||||
ret = ipc_mkval( &pk, len );
|
||||
ret = ipc_serialize( &pk, setmeSize );
|
||||
SAFEBENCFREE( &pk );
|
||||
}
|
||||
|
||||
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 *
|
||||
ipc_mkvers( size_t * len, const char * label )
|
||||
{
|
||||
tr_benc pk, * dict;
|
||||
uint8_t * ret;
|
||||
|
||||
tr_bencInit( &pk, TYPE_DICT );
|
||||
if( tr_bencDictReserve( &pk, 1 ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
tr_bencInitDict( &pk, 1 );
|
||||
dict = tr_bencDictAdd( &pk, MSGNAME( IPC_MSG_VERSION ) );
|
||||
|
||||
tr_bencInit( dict, TYPE_DICT );
|
||||
if( tr_bencDictReserve( dict, ( NULL == label ? 2 : 3 ) ) )
|
||||
{
|
||||
SAFEBENCFREE( &pk );
|
||||
return NULL;
|
||||
}
|
||||
tr_bencInitDict( dict, 3 );
|
||||
tr_bencInitInt( tr_bencDictAdd( dict, "min" ), PROTO_VERS_MIN );
|
||||
tr_bencInitInt( tr_bencDictAdd( dict, "max" ), PROTO_VERS_MAX );
|
||||
if( NULL != label )
|
||||
if( label )
|
||||
tr_bencInitStr( tr_bencDictAdd( dict, "label" ), label, -1, 1 );
|
||||
|
||||
ret = ipc_mkval( &pk, len );
|
||||
ret = ipc_serialize( &pk, len );
|
||||
SAFEBENCFREE( &pk );
|
||||
|
||||
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 *
|
||||
ipc_mkgetinfo( const struct ipc_info * info, size_t * len, enum ipc_msg id,
|
||||
int64_t tag, int types, const int * ids )
|
||||
ipc_mkgetinfo( const struct ipc_info * session,
|
||||
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;
|
||||
const struct inf * typearray;
|
||||
uint8_t * ret;
|
||||
|
||||
/* no ID list, send an -all message */
|
||||
if( NULL == ids )
|
||||
{
|
||||
typelist = ipc_initval( info, id, tag, &pk, TYPE_LIST );
|
||||
if( NULL == typelist )
|
||||
{
|
||||
if( !ids ) {
|
||||
typelist = ipc_initval( session, msg_id, tag, &pk, TYPE_LIST );
|
||||
if( !typelist )
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
top = ipc_initval( info, id, tag, &pk, TYPE_DICT );
|
||||
if( NULL == top )
|
||||
{
|
||||
tr_benc * top;
|
||||
tr_benc * idlist;
|
||||
|
||||
top = ipc_initval( session, msg_id, tag, &pk, TYPE_DICT );
|
||||
if( !top )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add the requested IDs */
|
||||
if( tr_bencDictReserve( top, 2 ) )
|
||||
{
|
||||
SAFEBENCFREE( &pk );
|
||||
return NULL;
|
||||
}
|
||||
tr_bencDictReserve( top, 2 );
|
||||
idlist = tr_bencDictAdd( top, "id" );
|
||||
typelist = tr_bencDictAdd( top, "type" );
|
||||
tr_bencInit( idlist, 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++ )
|
||||
{
|
||||
}
|
||||
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] );
|
||||
}
|
||||
}
|
||||
|
||||
/* get the type name array */
|
||||
switch( id )
|
||||
switch( msg_id )
|
||||
{
|
||||
case IPC_MSG_GETINFO:
|
||||
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 */
|
||||
for( ii = used = 0; typecount > ii; ii++ )
|
||||
{
|
||||
if( types & ( 1 << ii ) )
|
||||
{
|
||||
used++;
|
||||
}
|
||||
}
|
||||
if( tr_bencListReserve( typelist, used ) )
|
||||
{
|
||||
SAFEBENCFREE( &pk );
|
||||
return NULL;
|
||||
}
|
||||
tr_bencListReserve( typelist, used );
|
||||
|
||||
for( ii = 0; typecount > ii; ii++ )
|
||||
{
|
||||
if( !( types & ( 1 << ii ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
assert( typearray[ii].type == ( 1 << ii ) );
|
||||
tr_bencInitStr( tr_bencListAdd( typelist ),
|
||||
typearray[ii].name, -1, 1 );
|
||||
}
|
||||
|
||||
/* generate packet */
|
||||
ret = ipc_mkval( &pk, len );
|
||||
ret = ipc_serialize( &pk, setmeSize );
|
||||
SAFEBENCFREE( &pk );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
filltracker( tr_benc * val, const tr_tracker_info * tk )
|
||||
{
|
||||
tr_bencInit( val, TYPE_DICT );
|
||||
if( tr_bencDictReserve( val, ( NULL == tk->scrape ? 3 : 4 ) ) )
|
||||
return -1;
|
||||
|
||||
tr_bencInitDict( val, 4 );
|
||||
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 )
|
||||
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
|
||||
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;
|
||||
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 */
|
||||
types |= IPC_INF_ID;
|
||||
|
||||
if( tr_bencListReserve( list, 1 ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencListReserve( list, 1 );
|
||||
|
||||
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++ )
|
||||
{
|
||||
if( !( types & ( 1 << ii ) ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
assert( TR_N_ELEMENTS( gl_inf ) > ( unsigned )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++;
|
||||
}
|
||||
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++ )
|
||||
{
|
||||
if( !( types & ( 1 << ii ) ) )
|
||||
{
|
||||
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 );
|
||||
switch( 1 << ii )
|
||||
{
|
||||
case IPC_INF_COMMENT:
|
||||
tr_bencInitStr( item, inf->comment, -1, 1 );
|
||||
tr_bencInitStr( item, inf->comment ? inf->comment : "", -1, 1 );
|
||||
break;
|
||||
case IPC_INF_CREATOR:
|
||||
tr_bencInitStr( item, inf->creator, -1, 1 );
|
||||
tr_bencInitStr( item, inf->creator ? inf->creator : "", -1, 1 );
|
||||
break;
|
||||
case IPC_INF_DATE:
|
||||
tr_bencInitInt( item, inf->dateCreated );
|
||||
break;
|
||||
case IPC_INF_FILES:
|
||||
tr_bencInit( item, TYPE_LIST );
|
||||
if( tr_bencListReserve( item, inf->fileCount ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencInitList( item, inf->fileCount );
|
||||
for( ff = 0; inf->fileCount > ff; ff++ )
|
||||
{
|
||||
file = tr_bencListAdd( item );
|
||||
tr_bencInit( file, TYPE_DICT );
|
||||
if( tr_bencDictReserve( file, 2 ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencInitDict( file, 2 );
|
||||
tr_bencInitStr( tr_bencDictAdd( file, "name" ),
|
||||
inf->files[ff].name, -1, 1 );
|
||||
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 );
|
||||
break;
|
||||
case IPC_INF_ID:
|
||||
tr_bencInitInt( item, tor );
|
||||
tr_bencInitInt( item, torrent_id );
|
||||
break;
|
||||
case IPC_INF_NAME:
|
||||
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 );
|
||||
break;
|
||||
case IPC_INF_TRACKERS:
|
||||
tr_bencInit( item, TYPE_LIST );
|
||||
if( tr_bencListReserve( item, inf->trackerTiers ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencInitList( item, inf->trackerTiers );
|
||||
for( jj = 0; inf->trackerTiers > jj; jj++ )
|
||||
{
|
||||
tier = tr_bencListAdd( item );
|
||||
tr_bencInit( tier, TYPE_LIST );
|
||||
if( tr_bencListReserve( tier,
|
||||
inf->trackerList[jj].count ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencInitList( tier, inf->trackerList[jj].count );
|
||||
for( kk = 0; inf->trackerList[jj].count > kk; kk++ )
|
||||
{
|
||||
if( 0 > filltracker( tr_bencListAdd( tier ),
|
||||
&inf->trackerList[jj].list[kk] ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
filltracker( tr_bencListAdd( tier ),
|
||||
&inf->trackerList[jj].list[kk] );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -634,32 +644,42 @@ ipc_addinfo( tr_benc * list, int tor, const tr_info * inf, int types )
|
|||
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
|
||||
ipc_addstat( tr_benc * list, int tor,
|
||||
const tr_stat * st, int types )
|
||||
ipc_addstat( tr_benc * list,
|
||||
int torrent_id,
|
||||
const tr_stat * st,
|
||||
int types )
|
||||
{
|
||||
tr_benc * dict, * item;
|
||||
int ii, used;
|
||||
tr_errno error;
|
||||
tr_benc * dict;
|
||||
int ii, used;
|
||||
|
||||
/* add the dictionary child */
|
||||
tr_bencListReserve( list, 1 );
|
||||
dict = tr_bencListAdd( list );
|
||||
|
||||
/* always send torrent id */
|
||||
types |= IPC_ST_ID;
|
||||
|
||||
if( tr_bencListReserve( list, 1 ) )
|
||||
return -1;
|
||||
|
||||
dict = tr_bencListAdd( list );
|
||||
|
||||
/* count the number of stat keys and allocate a dict for them */
|
||||
for( ii = used = 0; IPC_ST__MAX > 1 << ii; ii++ )
|
||||
if( types & ( 1 << ii ) )
|
||||
used++;
|
||||
tr_bencInitDict( dict, used );
|
||||
|
||||
tr_bencInit( dict, TYPE_DICT );
|
||||
if( tr_bencDictReserve( dict, used ) )
|
||||
return -1;
|
||||
|
||||
/* populate the dict */
|
||||
for( ii = 0; IPC_ST__MAX > 1 << ii; ii++ )
|
||||
{
|
||||
tr_benc * item;
|
||||
|
||||
if( !( types & ( 1 << ii ) ) )
|
||||
continue;
|
||||
|
||||
|
@ -678,8 +698,8 @@ ipc_addstat( tr_benc * list, int tor,
|
|||
case IPC_ST_DOWNTOTAL:
|
||||
tr_bencInitInt( item, st->downloadedEver );
|
||||
break;
|
||||
case IPC_ST_ERROR:
|
||||
error = st->error;
|
||||
case IPC_ST_ERROR: {
|
||||
const tr_errno error = st->error;
|
||||
if( TR_OK == error )
|
||||
{
|
||||
tr_bencInitStr( item, "", -1, 1 );
|
||||
|
@ -725,6 +745,7 @@ ipc_addstat( tr_benc * list, int tor,
|
|||
tr_bencInitStr( item, "other", -1, 1 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPC_ST_ERRMSG:
|
||||
if( TR_OK == st->error )
|
||||
{
|
||||
|
@ -743,17 +764,13 @@ ipc_addstat( tr_benc * list, int tor,
|
|||
tr_bencInitInt( item, st->eta );
|
||||
break;
|
||||
case IPC_ST_ID:
|
||||
tr_bencInitInt( item, tor );
|
||||
tr_bencInitInt( item, torrent_id );
|
||||
break;
|
||||
case IPC_ST_PEERDOWN:
|
||||
tr_bencInitInt( item, st->peersSendingToUs );
|
||||
break;
|
||||
case IPC_ST_PEERFROM:
|
||||
tr_bencInit( item, TYPE_DICT );
|
||||
if( tr_bencDictReserve( item, 4 ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
tr_bencInitDict( item, 4 );
|
||||
tr_bencInitInt( tr_bencDictAdd( item, "incoming" ),
|
||||
st->peersFrom[TR_PEER_FROM_INCOMING] );
|
||||
tr_bencInitInt( tr_bencDictAdd( item, "tracker" ),
|
||||
|
@ -802,10 +819,7 @@ ipc_addstat( tr_benc * list, int tor,
|
|||
tr_bencInitInt( item, st->swarmspeed * 1024 );
|
||||
break;
|
||||
case IPC_ST_TRACKER:
|
||||
if( 0 > filltracker( item, st->tracker ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
filltracker( item, st->tracker );
|
||||
break;
|
||||
case IPC_ST_TKDONE:
|
||||
tr_bencInitInt( item, st->completedFromTracker );
|
||||
|
@ -906,6 +920,16 @@ msglookup( const char * name )
|
|||
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
|
||||
gotmsg( const struct ipc_info * info, tr_benc * name, tr_benc * val,
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
compareNameToInf( const void * a, const void * b )
|
||||
{
|
||||
|
|
|
@ -152,20 +152,20 @@ int ipc_hasvers ( const struct ipc_info * );
|
|||
/* sets errno to EPERM if requested message not supported by protocol vers */
|
||||
struct tr_benc * ipc_initval ( const struct ipc_info *, enum ipc_msg,
|
||||
int64_t tag, struct tr_benc *, int );
|
||||
uint8_t * ipc_mkval ( const struct tr_benc *, size_t * );
|
||||
uint8_t * ipc_mkempty ( const struct ipc_info *, size_t *, enum ipc_msg,
|
||||
int64_t );
|
||||
uint8_t * ipc_mkint ( const struct ipc_info *, size_t *, enum ipc_msg,
|
||||
int64_t tag, int64_t val );
|
||||
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,
|
||||
uint8_t * ipc_serialize ( const struct tr_benc *, size_t * );
|
||||
uint8_t * ipc_mkempty ( const struct ipc_info *, size_t *, enum ipc_msg,
|
||||
int64_t );
|
||||
uint8_t * ipc_mkint ( const struct ipc_info *, size_t *, enum ipc_msg,
|
||||
int64_t tag, int64_t val );
|
||||
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 * );
|
||||
int ipc_addinfo ( struct tr_benc *, int,
|
||||
const struct tr_info *, int );
|
||||
int ipc_addstat ( struct tr_benc *, int,
|
||||
const struct tr_stat *, int );
|
||||
int ipc_addinfo ( struct tr_benc *, int,
|
||||
const struct tr_info *, int );
|
||||
int ipc_addstat ( struct tr_benc *, int,
|
||||
const struct tr_stat *, int );
|
||||
|
||||
/* sets errno to EINVAL on parse error or
|
||||
EPERM for unsupported protocol version */
|
||||
|
|
|
@ -288,8 +288,7 @@ getFileInfo( const char * topFile,
|
|||
for( pch=file->filename+topLen; *pch; ++pch )
|
||||
if (*pch == TR_PATH_DELIMITER)
|
||||
++n;
|
||||
tr_bencInit( uninitialized_path, TYPE_LIST );
|
||||
tr_bencListReserve( uninitialized_path, n );
|
||||
tr_bencInitList( uninitialized_path, n );
|
||||
for( prev=pch=file->filename+topLen; ; ++pch )
|
||||
{
|
||||
char buf[MAX_PATH_LENGTH];
|
||||
|
@ -322,8 +321,7 @@ makeFilesList( tr_benc * list,
|
|||
tr_benc * dict = tr_bencListAdd( list );
|
||||
tr_benc *length, *pathVal;
|
||||
|
||||
tr_bencInit( dict, TYPE_DICT );
|
||||
tr_bencDictReserve( dict, 2 );
|
||||
tr_bencInitDict( dict, 2 );
|
||||
length = tr_bencDictAdd( dict, "length" );
|
||||
pathVal = tr_bencDictAdd( dict, "path" );
|
||||
getFileInfo( builder->top, &builder->files[i], length, pathVal );
|
||||
|
@ -374,9 +372,8 @@ tr_realMakeMetaInfo ( tr_metainfo_builder * builder )
|
|||
int n = 5;
|
||||
tr_benc top, *val;
|
||||
|
||||
tr_bencInit ( &top, TYPE_DICT );
|
||||
if ( builder->comment && *builder->comment ) ++n;
|
||||
tr_bencDictReserve( &top, n );
|
||||
tr_bencInitDict( &top, n );
|
||||
|
||||
val = tr_bencDictAdd( &top, "announce" );
|
||||
tr_bencInitStrDup( val, builder->announce );
|
||||
|
@ -402,8 +399,7 @@ tr_realMakeMetaInfo ( tr_metainfo_builder * builder )
|
|||
tr_bencInitStrDup( val, "UTF-8" );
|
||||
|
||||
val = tr_bencDictAdd( &top, "info" );
|
||||
tr_bencInit( val, TYPE_DICT );
|
||||
tr_bencDictReserve( val, 666 );
|
||||
tr_bencInitDict( val, 666 );
|
||||
makeInfoDict( val, builder );
|
||||
}
|
||||
|
||||
|
|
|
@ -871,8 +871,7 @@ sendLtepHandshake( tr_peermsgs * msgs )
|
|||
else
|
||||
pex = 1;
|
||||
|
||||
tr_bencInit( &val, TYPE_DICT );
|
||||
tr_bencDictReserve( &val, 4 );
|
||||
tr_bencInitDict( &val, 4 );
|
||||
tr_bencInitInt( tr_bencDictAdd( &val, "e" ), 1 );
|
||||
m = tr_bencDictAdd( &val, "m" );
|
||||
tr_bencInit( m, TYPE_DICT );
|
||||
|
@ -1840,8 +1839,7 @@ sendPex( tr_peermsgs * msgs )
|
|||
msgs->pexCount = diffs.elementCount;
|
||||
|
||||
/* build the pex payload */
|
||||
tr_bencInit( &val, TYPE_DICT );
|
||||
tr_bencDictReserve( &val, 3 );
|
||||
tr_bencInitDict( &val, 3 );
|
||||
|
||||
/* "added" */
|
||||
added = tr_bencDictAdd( &val, "added" );
|
||||
|
|
|
@ -89,8 +89,7 @@ saveCumulativeStats( const tr_session_stats * stats )
|
|||
int len;
|
||||
tr_benc top;
|
||||
|
||||
tr_bencInit( &top, TYPE_DICT );
|
||||
tr_bencDictReserve( &top, 5 );
|
||||
tr_bencInitDict( &top, 5 );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "uploaded-bytes" ), stats->uploadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "downloaded-bytes" ), stats->downloadedBytes );
|
||||
tr_bencInitInt( tr_bencDictAdd( &top, "files-added" ), stats->filesAdded );
|
||||
|
|
|
@ -723,7 +723,7 @@ struct tr_info
|
|||
/* Torrent info */
|
||||
char * comment;
|
||||
char * creator;
|
||||
int dateCreated;
|
||||
time_t dateCreated;
|
||||
|
||||
/* Pieces info */
|
||||
uint32_t pieceSize;
|
||||
|
|
Loading…
Reference in New Issue