diff --git a/daemon/daemon.c b/daemon/daemon.c index 9c446a7aa..b9c1b20b4 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -23,6 +23,8 @@ #include #include /* daemon */ +#include + #include #include #include @@ -245,9 +247,12 @@ main( int argc, if( dumpSettings ) { - char * str = tr_bencSaveAsJSON( &settings, NULL ); - fprintf( stderr, "%s", str ); - tr_free( str ); + struct evbuffer * buf = tr_getBuffer( ); + + tr_bencSaveAsJSON( &settings, buf ); + fprintf( stderr, "%s", (char*)EVBUFFER_DATA(buf) ); + + tr_releaseBuffer( buf ); return 0; } diff --git a/daemon/remote.c b/daemon/remote.c index 31de01060..4b6aab6c2 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -524,7 +524,12 @@ readargs( int argc, } if( addArg ) - reqs[reqCount++] = tr_bencSaveAsJSON( &top, NULL ); + { + struct evbuffer * buf = tr_getBuffer( ); + reqs[reqCount++] = tr_strdup( tr_bencSaveAsJSON( &top, buf ) ); + tr_releaseBuffer( buf ); + } + tr_bencFree( &top ); } } diff --git a/gtk/main.c b/gtk/main.c index 410061048..3b509ab62 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1384,8 +1384,7 @@ pauseAllTorrents( struct cbdata * data ) { tr_session * session = tr_core_session( data->core ); const char * cmd = "{ \"method\": \"torrent-stop\" }"; - char * response = tr_rpc_request_exec_json( session, cmd, strlen( cmd ), NULL ); - tr_free( response ); + tr_rpc_request_exec_json( session, cmd, strlen( cmd ), NULL ); } void diff --git a/libtransmission/bencode-test.c b/libtransmission/bencode-test.c index 41f7b3cfb..3ec6fef5d 100644 --- a/libtransmission/bencode-test.c +++ b/libtransmission/bencode-test.c @@ -2,6 +2,9 @@ #include #include #include + +#include "event.h" + #include "transmission.h" #include "bencode.h" #include "json.h" @@ -309,10 +312,11 @@ testJSONSnippet( const char * benc_str, const char * expected ) { tr_benc top; - char * serialized; + struct evbuffer * buf = tr_getBuffer( ); + char * serialized; tr_bencLoad( benc_str, strlen( benc_str ), &top, NULL ); - serialized = tr_bencSaveAsJSON( &top, NULL ); + serialized = tr_bencSaveAsJSON( &top, buf ); stripWhitespace( serialized ); #if 0 fprintf( stderr, "benc: %s\n", benc_str ); @@ -320,8 +324,8 @@ testJSONSnippet( const char * benc_str, fprintf( stderr, "want: %s\n", expected ); #endif check( !strcmp( serialized, expected ) ); - tr_free( serialized ); tr_bencFree( &top ); + tr_releaseBuffer( buf ); return 0; } diff --git a/libtransmission/bencode.c b/libtransmission/bencode.c index 459d69188..b54156017 100644 --- a/libtransmission/bencode.c +++ b/libtransmission/bencode.c @@ -1311,14 +1311,14 @@ jsonContainerEndFunc( const tr_benc * val, } char* -tr_bencSaveAsJSON( const tr_benc * top, - int * len ) +tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out ) { - char * ret; struct WalkFuncs walkFuncs; struct jsonWalk data; - data.out = tr_getBuffer( ); + evbuffer_drain( out, EVBUFFER_LENGTH( out ) ); + + data.out = out; data.parents = NULL; walkFuncs.intFunc = jsonIntFunc; @@ -1329,14 +1329,10 @@ tr_bencSaveAsJSON( const tr_benc * top, bencWalk( top, &walkFuncs, &data ); - if( EVBUFFER_LENGTH( data.out ) ) - evbuffer_add_printf( data.out, "\n" ); - if( len ) - *len = EVBUFFER_LENGTH( data.out ); - ret = tr_strndup( EVBUFFER_DATA( data.out ), EVBUFFER_LENGTH( data.out ) ); + if( EVBUFFER_LENGTH( out ) ) + evbuffer_add_printf( out, "\n" ); - tr_releaseBuffer( data.out ); - return ret; + return (char*) EVBUFFER_DATA( out ); } /*** @@ -1465,11 +1461,10 @@ int tr_bencSaveJSONFile( const char * filename, const tr_benc * b ) { - int len; - char * content = tr_bencSaveAsJSON( b, &len ); - const int err = saveFile( filename, content, len ); - - tr_free( content ); + struct evbuffer * buf = tr_getBuffer( ); + const char * json = tr_bencSaveAsJSON( b, buf ); + const int err = saveFile( filename, json, EVBUFFER_LENGTH( buf ) ); + tr_releaseBuffer( buf ); return err; } diff --git a/libtransmission/bencode.h b/libtransmission/bencode.h index af32a7489..fe70c9f4c 100644 --- a/libtransmission/bencode.h +++ b/libtransmission/bencode.h @@ -15,6 +15,8 @@ #include /* for int64_t */ +struct evbuffer; + enum { TYPE_INT = 1, @@ -72,7 +74,7 @@ void tr_bencFree( tr_benc * ); char* tr_bencSave( const tr_benc * val, int * len ); -char* tr_bencSaveAsJSON( const tr_benc * top, int * len ); +char* tr_bencSaveAsJSON( const tr_benc * top, struct evbuffer * out ); int tr_bencSaveFile( const char * filename, const tr_benc * ); diff --git a/libtransmission/json-test.c b/libtransmission/json-test.c index 622017d4a..6cef82c0a 100644 --- a/libtransmission/json-test.c +++ b/libtransmission/json-test.c @@ -28,12 +28,12 @@ static int test = 0; static int test_utf8( void ) { - const char * in = "{ \"key\": \"Letöltések\" }"; - tr_benc top; - const char * str; - char * json; - int json_len; - int err; + const char * in = "{ \"key\": \"Letöltések\" }"; + tr_benc top; + const char * str; + char * json; + int err; + struct evbuffer * buf = tr_getBuffer( ); err = tr_jsonParse( in, strlen( in ), &top, NULL ); check( !err ); @@ -66,13 +66,13 @@ test_utf8( void ) check( tr_bencIsDict( &top ) ); check( tr_bencDictFindStr( &top, "key", &str ) ); check( !strcmp( str, "Letöltések" ) ); - json = tr_bencSaveAsJSON( &top, &json_len ); + json = tr_bencSaveAsJSON( &top, buf ); if( !err ) tr_bencFree( &top ); check( json ); check( strstr( json, "\\u00f6" ) != NULL ); check( strstr( json, "\\u00e9" ) != NULL ); - err = tr_jsonParse( json, json_len, &top, NULL ); + err = tr_jsonParse( json, strlen( json ), &top, NULL ); check( !err ); check( tr_bencIsDict( &top ) ); check( tr_bencDictFindStr( &top, "key", &str ) ); diff --git a/libtransmission/rpc-server.c b/libtransmission/rpc-server.c index 9d106a2dc..94479a806 100644 --- a/libtransmission/rpc-server.c +++ b/libtransmission/rpc-server.c @@ -155,10 +155,10 @@ handle_upload( struct evhttp_request * req, const char * body = strstr( text, "\r\n\r\n" ); if( body ) { - char * b64, *json, *freeme; - int json_len; + char * b64; size_t body_len; tr_benc top, *args; + struct evbuffer * json = tr_getBuffer( ); body += 4; /* walk past the \r\n\r\n */ body_len = part_len - ( body - text ); @@ -172,13 +172,13 @@ handle_upload( struct evhttp_request * req, b64 = tr_base64_encode( body, body_len, NULL ); tr_bencDictAddStr( args, "metainfo", b64 ); tr_bencDictAddInt( args, "paused", paused ); - json = tr_bencSaveAsJSON( &top, &json_len ); - freeme = tr_rpc_request_exec_json( server->session, - json, json_len, - NULL ); + tr_bencSaveAsJSON( &top, json ); + tr_rpc_request_exec_json( server->session, + EVBUFFER_DATA( json ), + EVBUFFER_LENGTH( json ), + NULL ); - tr_free( freeme ); - tr_free( json ); + tr_releaseBuffer( json ); tr_free( b64 ); tr_bencFree( &top ); } @@ -376,38 +376,37 @@ handle_clutch( struct evhttp_request * req, static void handle_rpc( struct evhttp_request * req, - struct tr_rpc_server * server ) + struct tr_rpc_server * server ) { - int len = 0; - char * out = NULL; - struct evbuffer * buf; + struct evbuffer * response = tr_getBuffer( ); if( req->type == EVHTTP_REQ_GET ) { const char * q; if( ( q = strchr( req->uri, '?' ) ) ) - out = tr_rpc_request_exec_uri( server->session, - q + 1, - strlen( q + 1 ), - &len ); + tr_rpc_request_exec_uri( server->session, q + 1, strlen( q + 1 ), response ); } else if( req->type == EVHTTP_REQ_POST ) { - out = tr_rpc_request_exec_json( server->session, - EVBUFFER_DATA( req->input_buffer ), - EVBUFFER_LENGTH( req->input_buffer ), - &len ); + tr_rpc_request_exec_json( server->session, + EVBUFFER_DATA( req->input_buffer ), + EVBUFFER_LENGTH( req->input_buffer ), + response ); } - buf = tr_getBuffer( ); - add_response( req, server, buf, out, len ); - evhttp_add_header( req->output_headers, "Content-Type", - "application/json; charset=UTF-8" ); - evhttp_send_reply( req, HTTP_OK, "OK", buf ); + { + struct evbuffer * buf = tr_getBuffer( ); + add_response( req, server, buf, + EVBUFFER_DATA( response ), + EVBUFFER_LENGTH( response ) ); + evhttp_add_header( req->output_headers, "Content-Type", + "application/json; charset=UTF-8" ); + evhttp_send_reply( req, HTTP_OK, "OK", buf ); + tr_releaseBuffer( buf ); + } /* cleanup */ - tr_releaseBuffer( buf ); - tr_free( out ); + tr_releaseBuffer( response ); } static tr_bool diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c index 13fefbee4..833141829 100644 --- a/libtransmission/rpcimpl.c +++ b/libtransmission/rpcimpl.c @@ -761,14 +761,13 @@ static struct method { "torrent-verify", torrentVerify } }; -static char* -request_exec( tr_session * session, - tr_benc * request, - int * response_len ) +static void +request_exec( tr_session * session, + tr_benc * request, + struct evbuffer * response_buf ) { int64_t i; const char * str; - char * out; tr_benc response; tr_benc * args_in = tr_bencDictFind( request, "arguments" ); tr_benc * args_out = NULL; @@ -798,30 +797,28 @@ request_exec( tr_session * session, tr_bencDictAddStr( &response, "result", result ); if( tr_bencDictFindInt( request, "tag", &i ) ) tr_bencDictAddInt( &response, "tag", i ); - out = tr_bencSaveAsJSON( &response, response_len ); + if( response_buf != NULL ) + tr_bencSaveAsJSON( &response, response_buf ); tr_bencFree( &response ); - return out; } -char* -tr_rpc_request_exec_json( tr_session * session, - const void * request_json, - int request_len, - int * response_len ) +void +tr_rpc_request_exec_json( tr_session * session, + const void * request_json, + int request_len, + struct evbuffer * response ) { tr_benc top; - int have_content; - char * ret; + int have_content; if( request_len < 0 ) request_len = strlen( request_json ); have_content = !tr_jsonParse( request_json, request_len, &top, NULL ); - ret = request_exec( session, have_content ? &top : NULL, response_len ); + request_exec( session, have_content ? &top : NULL, response ); if( have_content ) tr_bencFree( &top ); - return ret; } static void @@ -903,13 +900,12 @@ tr_rpc_parse_list_str( tr_benc * setme, tr_free( str ); } -char* -tr_rpc_request_exec_uri( tr_session * session, - const void * request_uri, - int request_len, - int * response_len ) +void +tr_rpc_request_exec_uri( tr_session * session, + const void * request_uri, + int request_len, + struct evbuffer * response ) { - char * ret = NULL; tr_benc top, * args; char * request = tr_strndup( request_uri, request_len ); const char * pch; @@ -938,11 +934,9 @@ tr_rpc_request_exec_uri( tr_session * session, pch = next ? next + 1 : NULL; } - ret = request_exec( session, &top, response_len ); + request_exec( session, &top, response ); /* cleanup */ tr_bencFree( &top ); tr_free( request ); - return ret; } - diff --git a/libtransmission/rpcimpl.h b/libtransmission/rpcimpl.h index 26a5cdf9c..ee464d977 100644 --- a/libtransmission/rpcimpl.h +++ b/libtransmission/rpcimpl.h @@ -17,19 +17,20 @@ **** RPC processing ***/ +struct evbuffer; struct tr_benc; /* http://www.json.org/ */ -char*tr_rpc_request_exec_json( tr_session * session, - const void * request_json, - int request_len, - int * response_len ); +void tr_rpc_request_exec_json( tr_session * session, + const void * request_json, + int request_len, + struct evbuffer * setme_response ); /* see the RPC spec's "Request URI Notation" section */ -char*tr_rpc_request_exec_uri( tr_session * session, - const void * request_uri, - int request_len, - int * response_len ); +void tr_rpc_request_exec_uri( tr_session * session, + const void * request_uri, + int request_len, + struct evbuffer * setme_response ); void tr_rpc_parse_list_str( struct tr_benc * setme, const char * list_str,