diff --git a/daemon/client.c b/daemon/client.c index d6bd6b3ca..9d21ccfb4 100644 --- a/daemon/client.c +++ b/daemon/client.c @@ -51,7 +51,7 @@ struct con { int infd; int outfd; - struct ipc_info ipc; + struct ipc_info * ipc; struct bufferevent * evin; struct bufferevent * evout; }; @@ -168,13 +168,20 @@ client_new_sock( const char * path ) close( fd ); return -1; } - ipc_newcon( &con->ipc, gl_tree ); + con->ipc = ipc_newcon( gl_tree ); + if( NULL == con->ipc ) + { + mallocmsg( sizeof *con->ipc ); + close( fd ); + free( con ); + } con->infd = fd; con->evin = bufferevent_new( fd, canread, didwrite, ohshit, con ); if( NULL == con->evin ) { - mallocmsg( -1 ); + errnomsg( "failed to create bufferevent" ); close( fd ); + ipc_freecon( con->ipc ); free( con ); return -1; } @@ -274,6 +281,7 @@ client_new_cmd( char * const * cmd ) if( NULL == con->evout ) { bufferevent_free( con->evin ); + bufferevent_free( con->evout ); free( con ); close( tocmd[1] ); close( fromcmd[0] ); @@ -283,7 +291,18 @@ client_new_cmd( char * const * cmd ) bufferevent_settimeout( con->evout, SERVER_TIMEOUT, SERVER_TIMEOUT ); bufferevent_enable( con->evout, EV_READ ); - ipc_newcon( &con->ipc, gl_tree ); + con->ipc = ipc_newcon( gl_tree ); + if( NULL == con->ipc ) + { + mallocmsg( sizeof *con->ipc ); + bufferevent_free( con->evin ); + bufferevent_free( con->evout ); + free( con ); + close( tocmd[1] ); + close( fromcmd[0] ); + return -1; + } + if( 0 > sendvers( con ) ) { exit( 1 ); @@ -686,7 +705,7 @@ canread( struct bufferevent * evin, void * arg ) return; } - res = ipc_parse( &con->ipc, buf, len, con ); + res = ipc_parse( con->ipc, buf, len, con ); if( 0 > res ) { switch( errno ) @@ -720,7 +739,7 @@ flushreqs( struct con * con ) benc_val_t pk, * val; struct stritem * jj; - if( !HASVERS( &con->ipc ) ) + if( !HASVERS( con->ipc ) ) { return; } @@ -741,7 +760,7 @@ flushreqs( struct con * con ) case IPC_MSG_STARTALL: case IPC_MSG_STOPALL: case IPC_MSG_REMOVEALL: - buf = ipc_mkempty( &con->ipc, &buflen, req->id, req->tag ); + buf = ipc_mkempty( con->ipc, &buflen, req->id, req->tag ); break; case IPC_MSG_ADDMANYFILES: ii = 0; @@ -749,7 +768,7 @@ flushreqs( struct con * con ) { ii++; } - val = ipc_initval( &con->ipc, req->id, -1, &pk, TYPE_LIST ); + val = ipc_initval( con->ipc, req->id, -1, &pk, TYPE_LIST ); if( NULL != val && !tr_bencListReserve( val, ii ) ) { SLIST_FOREACH( jj, req->strs, next ) @@ -763,7 +782,7 @@ flushreqs( struct con * con ) SAFEFREESTRLIST( req->strs ); break; case IPC_MSG_ADDONEFILE: - val = ipc_initval( &con->ipc, req->id, -1, &pk, TYPE_DICT ); + val = ipc_initval( con->ipc, req->id, -1, &pk, TYPE_DICT ); if( NULL != val && !tr_bencDictReserve( val, 1 ) ) { tr_bencInitStr( tr_bencDictAdd( val, "data" ), @@ -778,16 +797,16 @@ flushreqs( struct con * con ) case IPC_MSG_DOWNLIMIT: case IPC_MSG_UPLIMIT: case IPC_MSG_PEX: - buf = ipc_mkint( &con->ipc, &buflen, req->id, -1, req->num ); + buf = ipc_mkint( con->ipc, &buflen, req->id, -1, req->num ); break; case IPC_MSG_DIR: - buf = ipc_mkstr( &con->ipc, &buflen, req->id, -1, req->str ); + buf = ipc_mkstr( con->ipc, &buflen, req->id, -1, req->str ); SAFEFREE( req->str ); break; case IPC_MSG_START: case IPC_MSG_STOP: case IPC_MSG_REMOVE: - val = ipc_initval( &con->ipc, req->id, -1, &pk, TYPE_LIST ); + val = ipc_initval( con->ipc, req->id, -1, &pk, TYPE_LIST ); if( NULL != val && !tr_bencListReserve( val, req->listlen ) ) { for( ii = 0; ii < req->listlen; ii++ ) @@ -802,7 +821,7 @@ flushreqs( struct con * con ) break; case IPC_MSG_GETINFOALL: case IPC_MSG_GETSTATALL: - buf = ipc_mkgetinfo( &con->ipc, &buflen, req->id, req->tag, + buf = ipc_mkgetinfo( con->ipc, &buflen, req->id, req->tag, req->types, NULL ); break; default: @@ -838,7 +857,7 @@ sendvers( struct con * con ) uint8_t * buf; size_t len; - buf = ipc_mkvers( &len ); + buf = ipc_mkvers( &len, "Transmission remote" VERSION_STRING ); if( NULL == buf ) { if( EPERM == errno ) diff --git a/daemon/server.c b/daemon/server.c index 50e9e1ca1..f55b1e136 100644 --- a/daemon/server.c +++ b/daemon/server.c @@ -51,7 +51,7 @@ struct client { int fd; struct bufferevent * ev; - struct ipc_info ipc; + struct ipc_info * ipc; RB_ENTRY( client ) link; }; @@ -223,19 +223,28 @@ newclient( int fd, short event UNUSED, void * arg ) break; } + client->ipc = ipc_newcon( gl_tree ); + if( NULL == client->ipc ) + { + mallocmsg( sizeof *client->ipc ); + close( clfd ); + free( client ); + return; + } + clev = bufferevent_new( clfd, doread, noop, byebye, client ); if( NULL == clev ) { + errnomsg( "failed to create bufferevent" ); close( clfd ); + ipc_freecon( client->ipc ); free( client ); - mallocmsg( -1 ); return; } /* XXX bufferevent_base_set( gl_base, clev ); */ bufferevent_settimeout( clev, CLIENT_TIMEOUT, CLIENT_TIMEOUT ); client->fd = clfd; - ipc_newcon( &client->ipc, gl_tree ); client->ev = clev; old = RB_INSERT( allclients, &gl_clients, client ); assert( NULL == old ); @@ -246,7 +255,7 @@ newclient( int fd, short event UNUSED, void * arg ) } bufferevent_enable( clev, EV_READ ); - buf = ipc_mkvers( &buflen ); + buf = ipc_mkvers( &buflen, "Transmission daemon " VERSION_STRING ); if( 0 > queuemsg( client, buf, buflen ) ) { free( buf ); @@ -298,6 +307,7 @@ byebye( struct bufferevent * ev, short what, void * arg UNUSED ) RB_REMOVE( allclients, &gl_clients, client ); bufferevent_free( ev ); close( client->fd ); + ipc_freecon( client->ipc ); if( gl_debug ) { printf( "*** client %i went bye-bye\n", client->fd ); @@ -330,7 +340,7 @@ doread( struct bufferevent * ev, void * arg ) return; } - res = ipc_parse( &client->ipc, buf, len, client ); + res = ipc_parse( client->ipc, buf, len, client ); if( gl_exiting ) { @@ -400,7 +410,7 @@ msgresp( struct client * client, int64_t tag, enum ipc_msg id ) return 0; } - buf = ipc_mkempty( &client->ipc, &buflen, id, tag ); + buf = ipc_mkempty( client->ipc, &buflen, id, tag ); ret = queuemsg( client, buf, buflen ); free( buf ); @@ -441,7 +451,7 @@ addmsg1( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg ) return; } - added = ipc_initval( &client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); + added = ipc_initval( client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); if( NULL == added ) { errnomsg( "failed to build message" ); @@ -520,7 +530,7 @@ addmsg2( enum ipc_msg id UNUSED, benc_val_t * dict, int64_t tag, void * arg ) if( TORRENT_ID_VALID( tor ) ) { - val = ipc_initval( &client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); + val = ipc_initval( client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); if( NULL == val ) { errnomsg( "failed to build message" ); @@ -662,7 +672,7 @@ infomsg( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg ) } /* initialize packet */ - pkinf = ipc_initval( &client->ipc, respid, tag, &pk, TYPE_LIST ); + pkinf = ipc_initval( client->ipc, respid, tag, &pk, TYPE_LIST ); if( NULL == pkinf ) { errnomsg( "failed to build message" ); @@ -847,7 +857,7 @@ lookmsg( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg ) return; } - pkinf = ipc_initval( &client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); + pkinf = ipc_initval( client->ipc, IPC_MSG_INFO, tag, &pk, TYPE_LIST ); if( NULL == pkinf ) { errnomsg( "failed to build message" ); @@ -897,31 +907,31 @@ prefmsg( enum ipc_msg id, benc_val_t * val UNUSED, int64_t tag, void * arg ) switch( id ) { case IPC_MSG_GETAUTOMAP: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_AUTOMAP, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_AUTOMAP, tag, torrent_get_port_mapping() ); break; case IPC_MSG_GETAUTOSTART: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_AUTOSTART, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_AUTOSTART, tag, torrent_get_autostart() ); break; case IPC_MSG_GETDIR: - buf = ipc_mkstr( &client->ipc, &buflen, IPC_MSG_DIR, tag, + buf = ipc_mkstr( client->ipc, &buflen, IPC_MSG_DIR, tag, torrent_get_directory() ); break; case IPC_MSG_GETDOWNLIMIT: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_DOWNLIMIT, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_DOWNLIMIT, tag, torrent_get_downlimit() ); break; case IPC_MSG_GETPEX: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_PEX, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_PEX, tag, torrent_get_pex() ); break; case IPC_MSG_GETPORT: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_PORT, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_PORT, tag, torrent_get_port() ); break; case IPC_MSG_GETUPLIMIT: - buf = ipc_mkint( &client->ipc, &buflen, IPC_MSG_UPLIMIT, tag, + buf = ipc_mkint( client->ipc, &buflen, IPC_MSG_UPLIMIT, tag, torrent_get_uplimit() ); break; default: @@ -949,7 +959,7 @@ supmsg( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg ) return; } - pkval = ipc_initval( &client->ipc, IPC_MSG_SUP, tag, &pk, TYPE_LIST ); + pkval = ipc_initval( client->ipc, IPC_MSG_SUP, tag, &pk, TYPE_LIST ); if( NULL == pkval ) { errnomsg( "failed to build message" ); @@ -974,8 +984,8 @@ supmsg( enum ipc_msg id UNUSED, benc_val_t * val, int64_t tag, void * arg ) msgresp( client, tag, IPC_MSG_BAD ); return; } - found = ipc_msgid( &client->ipc, name->val.s.s ); - if( IPC__MSG_COUNT == found || !ipc_ishandled( &client->ipc, found ) ) + found = ipc_msgid( client->ipc, name->val.s.s ); + if( IPC__MSG_COUNT == found || !ipc_ishandled( client->ipc, found ) ) { continue; } diff --git a/gtk/ipc.c b/gtk/ipc.c index 1a574e014..38964fe5e 100644 --- a/gtk/ipc.c +++ b/gtk/ipc.c @@ -71,7 +71,7 @@ struct constate int fd; enum contype type; struct ipc_funcs * msgs; - struct ipc_info ipc; + struct ipc_info * ipc; union { struct constate_serv serv; @@ -221,8 +221,15 @@ blocking_client( enum ipc_msg msgid, GList * files ) return FALSE; } + con->ipc = ipc_newcon( con->msgs ); + if( NULL == con->ipc ) + { + ipc_freemsgs( con->msgs ); + g_free( con ); + return FALSE; + } + ipc_setdefmsg( con->msgs, all_default ); - ipc_newcon( &con->ipc, con->msgs ); con->u.client.loop = g_main_loop_new(NULL, TRUE); con->u.client.msg = msgid; @@ -333,7 +340,7 @@ client_connect(char *path, struct constate *con) { return FALSE; } - buf = ipc_mkvers( &size ); + buf = ipc_mkvers( &size, "Transmission GTK+ " VERSION_STRING ); if( NULL == buf ) { close( con->fd ); @@ -356,19 +363,28 @@ srv_io_accept(GSource *source SHUTUP, int fd, struct sockaddr *sa SHUTUP, newcon = g_new(struct constate, 1); memcpy(newcon, con, sizeof(*newcon)); newcon->fd = fd; - ipc_newcon( &newcon->ipc, con->msgs ); - newcon->source = io_new(fd, NULL, srv_io_received, all_io_closed, newcon); - if( NULL == newcon->source ) + newcon->ipc = ipc_newcon( con->msgs ); + if( NULL == newcon->ipc ) { g_free( newcon ); close( fd ); return; } - buf = ipc_mkvers( &size ); + newcon->source = io_new(fd, NULL, srv_io_received, all_io_closed, newcon); + if( NULL == newcon->source ) + { + ipc_freecon( newcon->ipc ); + g_free( newcon ); + close( fd ); + return; + } + + buf = ipc_mkvers( &size, "Transmission GTK+ " VERSION_STRING ); if( NULL == buf ) { + ipc_freecon( newcon->ipc ); g_free( newcon ); close( fd ); return; @@ -395,7 +411,7 @@ srv_io_received( GSource * source SHUTUP, void * data, size_t len, destroycon( con ); } - res = ipc_parse( &con->ipc, data, len, con ); + res = ipc_parse( con->ipc, data, len, con ); if( 0 > res ) { @@ -431,7 +447,7 @@ cli_io_received( GSource * source SHUTUP, void * data, size_t len, return 0; } - res = ipc_parse( &con->ipc, data, len, con ); + res = ipc_parse( con->ipc, data, len, con ); if( 0 > res ) { @@ -452,7 +468,7 @@ cli_io_received( GSource * source SHUTUP, void * data, size_t len, return 0; } - if( HASVERS( &con->ipc ) && 0 == cli->msgid ) + if( HASVERS( con->ipc ) && 0 == cli->msgid ) { client_sendmsg( con ); } @@ -473,7 +489,7 @@ client_sendmsg( struct constate * con ) switch( cli->msg ) { case IPC_MSG_ADDMANYFILES: - val = ipc_initval( &con->ipc, cli->msg, -1, &packet, TYPE_LIST ); + val = ipc_initval( con->ipc, cli->msg, -1, &packet, TYPE_LIST ); if( NULL == val || tr_bencListReserve( val, g_list_length( cli->files ) ) ) { @@ -492,7 +508,7 @@ client_sendmsg( struct constate * con ) cli->files = NULL; break; case IPC_MSG_QUIT: - buf = ipc_mkempty( &con->ipc, &size, cli->msg, -1 ); + buf = ipc_mkempty( con->ipc, &size, cli->msg, -1 ); saved = errno; break; default: @@ -518,6 +534,7 @@ destroycon(struct constate *con) { if(0 <= con->fd) close(con->fd); con->fd = -1; + ipc_freecon( con->ipc ); switch(con->type) { case CON_SERV: @@ -689,7 +706,7 @@ smsg_info( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg ) } typeflags = ipc_infotypes( respid, types ); - pkval = ipc_initval( &con->ipc, respid, tag, &packet, TYPE_LIST ); + pkval = ipc_initval( con->ipc, respid, tag, &packet, TYPE_LIST ); if( NULL == pkval ) { simpleresp( con, tag, IPC_MSG_FAIL ); @@ -747,7 +764,7 @@ smsg_infoall( enum ipc_msg id, benc_val_t * val, int64_t tag, void * arg ) respid = ( IPC_MSG_GETINFOALL == id ? IPC_MSG_INFO : IPC_MSG_STAT ); typeflags = ipc_infotypes( respid, val ); - pkval = ipc_initval( &con->ipc, respid, tag, &packet, TYPE_LIST ); + pkval = ipc_initval( con->ipc, respid, tag, &packet, TYPE_LIST ); if( NULL == pkval ) { simpleresp( con, tag, IPC_MSG_FAIL ); @@ -819,7 +836,7 @@ smsg_look( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag, return; } - pkval = ipc_initval( &con->ipc, IPC_MSG_INFO, tag, &packet, TYPE_LIST ); + pkval = ipc_initval( con->ipc, IPC_MSG_INFO, tag, &packet, TYPE_LIST ); if( NULL == pkval ) { simpleresp( con, tag, IPC_MSG_FAIL ); @@ -962,18 +979,18 @@ smsg_pref( enum ipc_msg id, benc_val_t * val SHUTUP, int64_t tag, void * arg ) { case IPC_MSG_GETAUTOMAP: hstat = tr_handleStatus( tr_core_handle( srv->core ) ); - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_AUTOMAP, tag, + buf = ipc_mkint( con->ipc, &size, IPC_MSG_AUTOMAP, tag, !TR_NAT_TRAVERSAL_IS_DISABLED( hstat->natTraversalStatus ) ); break; case IPC_MSG_GETAUTOSTART: - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_AUTOSTART, tag, 1 ); + buf = ipc_mkint( con->ipc, &size, IPC_MSG_AUTOSTART, tag, 1 ); break; case IPC_MSG_GETDIR: pref = tr_prefs_get( PREF_ID_ASKDIR ); /* XXX sending back "" when we're prompting is kind of bogus */ pref = strbool( pref ) ? "" : getdownloaddir(); - buf = ipc_mkstr( &con->ipc, &size, IPC_MSG_DIR, tag, pref ); + buf = ipc_mkstr( con->ipc, &size, IPC_MSG_DIR, tag, pref ); break; case IPC_MSG_GETDOWNLIMIT: num = -1; @@ -981,14 +998,14 @@ smsg_pref( enum ipc_msg id, benc_val_t * val SHUTUP, int64_t tag, void * arg ) { num = tr_prefs_get_int_with_default( PREF_ID_DOWNLIMIT ); } - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_DOWNLIMIT, tag, num ); + buf = ipc_mkint( con->ipc, &size, IPC_MSG_DOWNLIMIT, tag, num ); break; case IPC_MSG_GETPEX: - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_PEX, tag, + buf = ipc_mkint( con->ipc, &size, IPC_MSG_PEX, tag, tr_prefs_get_bool_with_default( PREF_ID_PEX ) ); break; case IPC_MSG_GETPORT: - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_PORT, tag, + buf = ipc_mkint( con->ipc, &size, IPC_MSG_PORT, tag, tr_prefs_get_int_with_default( PREF_ID_PORT ) ); break; case IPC_MSG_GETUPLIMIT: @@ -997,7 +1014,7 @@ smsg_pref( enum ipc_msg id, benc_val_t * val SHUTUP, int64_t tag, void * arg ) { num = tr_prefs_get_int_with_default( PREF_ID_UPLIMIT ); } - buf = ipc_mkint( &con->ipc, &size, IPC_MSG_UPLIMIT, tag, num ); + buf = ipc_mkint( con->ipc, &size, IPC_MSG_UPLIMIT, tag, num ); break; default: g_assert_not_reached(); @@ -1107,7 +1124,7 @@ smsg_sup( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag, void * arg ) return; } - pkval = ipc_initval( &con->ipc, IPC_MSG_SUP, tag, &packet, TYPE_LIST ); + pkval = ipc_initval( con->ipc, IPC_MSG_SUP, tag, &packet, TYPE_LIST ); if( NULL == pkval ) { simpleresp( con, tag, IPC_MSG_FAIL ); @@ -1127,8 +1144,8 @@ smsg_sup( enum ipc_msg id SHUTUP, benc_val_t * val, int64_t tag, void * arg ) { continue; } - found = ipc_msgid( &con->ipc, name->val.s.s ); - if( IPC__MSG_COUNT == found || !ipc_ishandled( &con->ipc, found ) ) + found = ipc_msgid( con->ipc, name->val.s.s ); + if( IPC__MSG_COUNT == found || !ipc_ishandled( con->ipc, found ) ) { continue; } @@ -1170,7 +1187,7 @@ simpleresp( struct constate * con, int64_t tag, enum ipc_msg id ) uint8_t * buf; size_t size; - buf = ipc_mkempty( &con->ipc, &size, id, tag ); + buf = ipc_mkempty( con->ipc, &size, id, tag ); if( NULL == buf ) { return FALSE; diff --git a/libtransmission/ipcparse.c b/libtransmission/ipcparse.c index 29b8cc4cb..d90eee4c4 100644 --- a/libtransmission/ipcparse.c +++ b/libtransmission/ipcparse.c @@ -292,12 +292,29 @@ ipc_freemsgs( struct ipc_funcs * tree ) free( tree ); } -void -ipc_newcon( struct ipc_info * info, struct ipc_funcs * funcs ) +struct ipc_info * +ipc_newcon( struct ipc_funcs * funcs ) { - bzero( info, sizeof *info ); - info->funcs = funcs; - info->vers = -1; + struct ipc_info * info; + + info = calloc( 1, sizeof *info ); + if( NULL != info ) + { + info->funcs = funcs; + info->vers = -1; + } + + return info; +} + +void +ipc_freecon( struct ipc_info * info ) +{ + if( NULL != info ) + { + free( info->label ); + free( info ); + } } benc_val_t * @@ -439,7 +456,7 @@ ipc_mkstr( struct ipc_info * info, size_t * len, enum ipc_msg id, int64_t tag, } uint8_t * -ipc_mkvers( size_t * len ) +ipc_mkvers( size_t * len, const char * label ) { benc_val_t pk, * dict; uint8_t * ret; @@ -452,13 +469,15 @@ ipc_mkvers( size_t * len ) dict = tr_bencDictAdd( &pk, MSGNAME( IPC_MSG_VERSION ) ); tr_bencInit( dict, TYPE_DICT ); - if( tr_bencDictReserve( dict, 2 ) ) + 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, "max" ), PROTO_VERS_MAX ); + if( NULL != label ) + tr_bencInitStr( tr_bencDictAdd( dict, "label" ), label, -1, 1 ); ret = ipc_mkval( &pk, len ); SAFEBENCFREE( &pk ); diff --git a/libtransmission/ipcparse.h b/libtransmission/ipcparse.h index 6ac330f67..52e06ce8d 100644 --- a/libtransmission/ipcparse.h +++ b/libtransmission/ipcparse.h @@ -123,9 +123,11 @@ struct ipc_info { struct ipc_funcs * funcs; int vers; + char * label; }; #define HASVERS( info ) ( 0 < (info)->vers ) +#define VERSLABEL( info ) ( (info)->label ) #define TORRENT_ID_VALID( id ) ( 0 < (id) && INT_MAX > (id) ) @@ -139,7 +141,8 @@ struct ipc_funcs * ipc_initmsgs ( void ); int ipc_addmsg ( struct ipc_funcs *, enum ipc_msg, trd_msgfunc ); void ipc_setdefmsg( struct ipc_funcs *, trd_msgfunc ); void ipc_freemsgs ( struct ipc_funcs * ); -void ipc_newcon ( struct ipc_info *, struct ipc_funcs * ); +struct ipc_info * ipc_newcon( struct ipc_funcs * ); +void ipc_freecon ( struct ipc_info * ); /* message creation */ /* sets errno to EPERM if requested message not supported by protocol vers */ @@ -152,7 +155,7 @@ uint8_t * ipc_mkint ( struct ipc_info *, size_t *, enum ipc_msg, int64_t, int64_t ); uint8_t * ipc_mkstr ( struct ipc_info *, size_t *, enum ipc_msg, int64_t, const char * ); -uint8_t * ipc_mkvers ( size_t * ); +uint8_t * ipc_mkvers ( size_t *, const char * ); uint8_t * ipc_mkgetinfo( struct ipc_info *, size_t *, enum ipc_msg, int64_t, int, const int * ); int ipc_addinfo ( benc_val_t *, int, tr_info_t *, int ); diff --git a/macosx/IPCController.m b/macosx/IPCController.m index 8028a33eb..4f6c8dd91 100644 --- a/macosx/IPCController.m +++ b/macosx/IPCController.m @@ -76,10 +76,10 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); @interface IPCClient : NSObject { - NSFileHandle * _handle; - struct ipc_info _ipc; - IPCController * _controller; - NSMutableData * _buf; + NSFileHandle * _handle; + struct ipc_info * _ipc; + IPCController * _controller; + NSMutableData * _buf; } - (id) initClient: (IPCController *) controller @@ -269,12 +269,13 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); return nil; _handle = [handle retain]; - ipc_newcon( &_ipc, funcs ); + _ipc = ipc_newcon( funcs ); _controller = controller; _buf = [[NSMutableData alloc] init]; - buf = ipc_mkvers( &size ); - if( nil == _buf || NULL == buf || ![self sendresp: buf size: size] ) + buf = ipc_mkvers( &size, "Transmission MacOS X " VERSION_STRING ); + if( NULL == _ipc || nil == _buf || NULL == buf || + ![self sendresp: buf size: size] ) { [self release]; return nil; @@ -295,6 +296,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); [[NSNotificationCenter defaultCenter] removeObserver: self]; [_handle release]; [_buf release]; + ipc_freecon( _ipc ); [super dealloc]; } @@ -305,7 +307,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); - (struct ipc_info *) ipc { - return &_ipc; + return _ipc; } - (void) gotdata: (NSNotification *) notification @@ -338,7 +340,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); if( IPC_MIN_MSG_LEN > [_buf length] ) return; - res = ipc_parse( &_ipc, [_buf mutableBytes], [_buf length], self ); + res = ipc_parse( _ipc, [_buf mutableBytes], [_buf length], self ); if( 0 > res ) { @@ -392,7 +394,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); uint8_t * buf; size_t size; - buf = ipc_mkempty( &_ipc, &size, msgid, tag ); + buf = ipc_mkempty( _ipc, &size, msgid, tag ); if( NULL == buf ) return FALSE; @@ -407,7 +409,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); uint8_t * buf; size_t size; - buf = ipc_mkint( &_ipc, &size, msgid, tag, val ); + buf = ipc_mkint( _ipc, &size, msgid, tag, val ); if( NULL == buf ) return FALSE; @@ -425,7 +427,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); NSMutableData * sucky; if( [val canBeConvertedToEncoding: NSUTF8StringEncoding] ) - buf = ipc_mkstr( &_ipc, &size, msgid, tag, + buf = ipc_mkstr( _ipc, &size, msgid, tag, [val cStringUsingEncoding: NSUTF8StringEncoding] ); else { @@ -434,7 +436,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); /* XXX this sucks, I should add a length argument to ipc_mkstr() */ sucky = [NSMutableData dataWithData: data]; [sucky appendBytes: "" length: 1]; - buf = ipc_mkstr( &_ipc, &size, msgid, tag, [sucky bytes] ); + buf = ipc_mkstr( _ipc, &size, msgid, tag, [sucky bytes] ); } if( NULL == buf ) return FALSE; @@ -455,7 +457,7 @@ msg_default ( enum ipc_msg msgid, benc_val_t * val, int64_t tag, void * arg ); size_t size; int res; - pkinf = ipc_initval( &_ipc, respid, tag, &packet, TYPE_LIST ); + pkinf = ipc_initval( _ipc, respid, tag, &packet, TYPE_LIST ); if( NULL == pkinf ) goto fail; if( tr_bencListReserve( pkinf, [tors count] ) ) diff --git a/misc/ipcproto.txt b/misc/ipcproto.txt index 344fed4d3..e38402ebe 100644 --- a/misc/ipcproto.txt +++ b/misc/ipcproto.txt @@ -72,6 +72,10 @@ receive a version value that is an integer instead of a dictionary with "min" and "max" keys. This deprecated version format indicates the only version supported by the server. +The version dictionary may optionally contain a key "label". This is a +human-readable name for the software, it is not machine-readable and +neither servers nor clients should attempt to parse it. + An example message containing minimum and maximum versions 1 and 2: 0000001Dd7:versiond3:mini1e3:maxi2eee