Changeset 7744


Ignore:
Timestamp:
Jan 18, 2009, 3:24:26 PM (12 years ago)
Author:
charles
Message:

(trunk libT) In RPC, add general support for nonblocking methods, and specific support for adding a torrent via its URL and fetching it via curl without blocking.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/remote.c

    r7736 r7744  
    301301                    else
    302302                    {
    303                         fprintf( stderr, "Couldn't add file: %s\n", optarg );
    304                         addArg = FALSE;
     303                        tr_bencDictAddStr( &top, "method", "torrent-add" );
     304                        tr_bencDictAddStr( args, "filename", optarg );
    305305                    }
    306306                }
  • trunk/doc/rpc-spec.txt

    r7732 r7744  
    282282   -------------------+-------------------------------------------------
    283283   "download-dir"     | string      path to download the torrent to
    284    "filename"         | string      location of the .torrent file
     284   "filename"         | string      filename or URL of the .torrent file
    285285   "metainfo"         | string      base64-encoded .torrent content
    286286   "paused"           | 'boolean'   if true, don't start the torrent
  • trunk/libtransmission/rpc-server.c

    r7706 r7744  
    177177                                                  EVBUFFER_DATA( json ),
    178178                                                  EVBUFFER_LENGTH( json ),
    179                                                   NULL );
     179                                                  NULL, NULL );
    180180
    181181                        tr_releaseBuffer( json );
     
    375375}
    376376
     377struct rpc_response_data
     378{
     379    struct evhttp_request * req;
     380    struct tr_rpc_server  * server;
     381};
     382
     383static void
     384rpc_response_func( tr_session      * session UNUSED,
     385                   const char      * response,
     386                   size_t            response_len,
     387                   void            * user_data )
     388{
     389    struct rpc_response_data * data = user_data;
     390    struct evbuffer * buf = tr_getBuffer( );
     391
     392    add_response( data->req, data->server, buf, response, response_len );
     393    evhttp_add_header( data->req->output_headers,
     394                           "Content-Type", "application/json; charset=UTF-8" );
     395    evhttp_send_reply( data->req, HTTP_OK, "OK", buf );
     396
     397    tr_releaseBuffer( buf );
     398    tr_free( data );
     399}
     400
     401
    377402static void
    378403handle_rpc( struct evhttp_request * req,
    379404            struct tr_rpc_server  * server )
    380405{
    381     struct evbuffer * response = tr_getBuffer( );
    382 
     406    struct rpc_response_data * data = tr_new0( struct rpc_response_data, 1 );
     407
     408    data->req = req;
     409    data->server = server;
     410   
    383411    if( req->type == EVHTTP_REQ_GET )
    384412    {
    385413        const char * q;
    386414        if( ( q = strchr( req->uri, '?' ) ) )
    387             tr_rpc_request_exec_uri( server->session, q + 1, strlen( q + 1 ), response );
     415            tr_rpc_request_exec_uri( server->session, q+1, -1, rpc_response_func, data );
    388416    }
    389417    else if( req->type == EVHTTP_REQ_POST )
     
    392420                                  EVBUFFER_DATA( req->input_buffer ),
    393421                                  EVBUFFER_LENGTH( req->input_buffer ),
    394                                   response );
    395     }
    396 
    397     {
    398         struct evbuffer * buf = tr_getBuffer( );
    399         add_response( req, server, buf,
    400                       EVBUFFER_DATA( response ),
    401                       EVBUFFER_LENGTH( response ) );
    402         evhttp_add_header( req->output_headers, "Content-Type",
    403                                                 "application/json; charset=UTF-8" );
    404         evhttp_send_reply( req, HTTP_OK, "OK", buf );
    405         tr_releaseBuffer( buf );
    406     }
    407 
    408     /* cleanup */
    409     tr_releaseBuffer( response );
     422                                  rpc_response_func, data );
     423    }
     424
    410425}
    411426
  • trunk/libtransmission/rpcimpl.c

    r7732 r7744  
    1616#include <string.h> /* strcmp */
    1717
     18#include <event.h> /* evbuffer */
     19
    1820#include "transmission.h"
    1921#include "bencode.h"
     
    2325#include "torrent.h"
    2426#include "utils.h"
     27#include "web.h"
    2528
    2629#define TR_N_ELEMENTS( ary ) ( sizeof( ary ) / sizeof( *ary ) )
     30
     31#define dbgmsg( ... ) \
     32    do { \
     33        if( tr_deepLoggingIsActive( ) ) \
     34            tr_deepLog( __FILE__, __LINE__, "RPC", __VA_ARGS__ ); \
     35    } while( 0 )
     36
    2737
    2838/***
     
    4252
    4353    return status;
     54}
     55
     56/***
     57****
     58***/
     59
     60/* For functions that can't be immediately executed, like torrentAdd,
     61 * this is the callback data used to pass a response to the caller
     62 * when the task is complete */
     63struct tr_rpc_idle_data
     64{
     65    tr_session            * session;
     66    tr_benc               * response;
     67    tr_benc               * args_out;
     68    tr_rpc_response_func  * callback;
     69    void                  * callback_user_data;
     70};
     71
     72static void
     73function_done( struct tr_rpc_idle_data * data, const char * result )
     74{
     75    struct evbuffer * buf = tr_getBuffer( );
     76
     77    if( result == NULL )
     78        result = "success";
     79    tr_bencDictAddStr( data->response, "result", result );
     80
     81    tr_bencSaveAsJSON( data->response, buf );
     82    data->callback( data->session, (const char*)EVBUFFER_DATA(buf),
     83                    EVBUFFER_LENGTH(buf), data->callback_user_data );
     84
     85    tr_releaseBuffer( buf );
     86    tr_bencFree( data->response );
     87    tr_free( data->response );
     88    tr_free( data );
    4489}
    4590
     
    100145
    101146static const char*
    102 torrentStart( tr_session * session,
    103               tr_benc    * args_in,
    104               tr_benc    * args_out UNUSED )
     147torrentStart( tr_session               * session,
     148              tr_benc                  * args_in,
     149              tr_benc                  * args_out UNUSED,
     150              struct tr_rpc_idle_data  * idle_data )
    105151{
    106152    int           i, torrentCount;
    107153    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     154
     155    assert( idle_data == NULL );
    108156
    109157    for( i = 0; i < torrentCount; ++i )
     
    118166
    119167static const char*
    120 torrentStop( tr_session * session,
    121              tr_benc    * args_in,
    122              tr_benc    * args_out UNUSED )
     168torrentStop( tr_session               * session,
     169             tr_benc                  * args_in,
     170             tr_benc                  * args_out UNUSED,
     171             struct tr_rpc_idle_data  * idle_data )
    123172{
    124173    int           i, torrentCount;
    125174    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     175
     176    assert( idle_data == NULL );
    126177
    127178    for( i = 0; i < torrentCount; ++i )
     
    136187
    137188static const char*
    138 torrentRemove( tr_session  * session,
    139                tr_benc     * args_in,
    140                tr_benc     * args_out UNUSED )
     189torrentRemove( tr_session               * session,
     190               tr_benc                  * args_in,
     191               tr_benc                  * args_out UNUSED,
     192               struct tr_rpc_idle_data  * idle_data )
    141193{
    142194    int i;
    143195    int torrentCount;
    144196    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     197
     198    assert( idle_data == NULL );
    145199
    146200    for( i=0; i<torrentCount; ++i )
     
    160214
    161215static const char*
    162 torrentVerify( tr_session  * session,
    163                tr_benc     * args_in,
    164                tr_benc     * args_out UNUSED )
     216torrentVerify( tr_session               * session,
     217               tr_benc                  * args_in,
     218               tr_benc                  * args_out UNUSED,
     219               struct tr_rpc_idle_data  * idle_data )
    165220{
    166221    int           i, torrentCount;
    167222    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     223
     224    assert( idle_data == NULL );
    168225
    169226    for( i = 0; i < torrentCount; ++i )
     
    436493
    437494static const char*
    438 torrentGet( tr_session * session,
    439             tr_benc    * args_in,
    440             tr_benc    * args_out )
     495torrentGet( tr_session               * session,
     496            tr_benc                  * args_in,
     497            tr_benc                  * args_out,
     498            struct tr_rpc_idle_data  * idle_data )
    441499{
    442500    int           i, torrentCount;
    443501    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
    444     tr_benc *     list = tr_bencDictAddList( args_out, "torrents",
    445                                              torrentCount );
     502    tr_benc *     list = tr_bencDictAddList( args_out, "torrents", torrentCount );
    446503    tr_benc *     fields;
    447504    char *        msg = NULL;
     505
     506    assert( idle_data == NULL );
    448507
    449508    if( !tr_bencDictFindList( args_in, "fields", &fields ) )
     
    523582
    524583static const char*
    525 torrentSet( tr_session * session,
    526             tr_benc    * args_in,
    527             tr_benc    * args_out UNUSED )
     584torrentSet( tr_session               * session,
     585            tr_benc                  * args_in,
     586            tr_benc                  * args_out UNUSED,
     587            struct tr_rpc_idle_data  * idle_data )
    528588{
    529589    int           i, torrentCount;
    530590    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     591
     592    assert( idle_data == NULL );
    531593
    532594    for( i = 0; i < torrentCount; ++i )
     
    571633***/
    572634
     635static void
     636addTorrentImpl( struct tr_rpc_idle_data * data, tr_ctor * ctor )
     637{
     638    int err = 0;
     639    const char * result = NULL;
     640    tr_torrent * tor = tr_torrentNew( data->session, ctor, &err );
     641
     642    tr_ctorFree( ctor );
     643
     644    if( tor )
     645    {
     646        tr_benc fields;
     647        tr_bencInitList( &fields, 3 );
     648        tr_bencListAddStr( &fields, "id" );
     649        tr_bencListAddStr( &fields, "name" );
     650        tr_bencListAddStr( &fields, "hashString" );
     651        addInfo( tor, tr_bencDictAdd( data->args_out, "torrent-added" ), &fields );
     652        notify( data->session, TR_RPC_TORRENT_ADDED, tor );
     653        tr_bencFree( &fields );
     654    }
     655    else if( err == TR_EDUPLICATE )
     656    {
     657        result = "duplicate torrent";
     658    }
     659    else if( err == TR_EINVALID )
     660    {
     661        result = "invalid or corrupt torrent file";
     662    }
     663
     664    function_done( data, result );
     665}
     666
     667
     668struct add_torrent_idle_data
     669{
     670    struct tr_rpc_idle_data * data;
     671    tr_ctor * ctor;
     672};
     673
     674static void
     675gotMetadataFromURL( tr_session       * session UNUSED,
     676                    long               response_code,
     677                    const void       * response,
     678                    size_t             response_byte_count,
     679                    void             * user_data )
     680{
     681    struct add_torrent_idle_data * data = user_data;
     682
     683    dbgmsg( "torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes",
     684            response_code, tr_webGetResponseStr( response_code ), response_byte_count );
     685
     686    if( response_code == 200 )
     687    {
     688        tr_ctorSetMetainfo( data->ctor, response, response_byte_count );
     689        addTorrentImpl( data->data, data->ctor );
     690    }
     691    else
     692    {
     693        char result[1024];
     694        tr_snprintf( result, sizeof( result ), "http error %ld: %s",
     695                     response_code, tr_webGetResponseStr( response_code ) );
     696        function_done( data->data, result );
     697    }
     698
     699    tr_free( data );
     700}
     701
     702static tr_bool
     703isCurlURL( const char * filename )
     704{
     705    if( filename == NULL )
     706        return FALSE;
     707
     708    return ( strstr( filename, "ftp://" ) != NULL )
     709        || ( strstr( filename, "http://" ) != NULL )
     710        || ( strstr( filename, "https://" ) != NULL );
     711}
     712
    573713static const char*
    574 torrentAdd( tr_session * session,
    575             tr_benc    * args_in,
    576             tr_benc    * args_out )
     714torrentAdd( tr_session               * session,
     715            tr_benc                  * args_in,
     716            tr_benc                  * args_out UNUSED,
     717            struct tr_rpc_idle_data  * idle_data )
    577718{
    578719    const char * filename = NULL;
    579720    const char * metainfo_base64 = NULL;
     721
     722    assert( idle_data != NULL );
    580723
    581724    tr_bencDictFindStr( args_in, "filename", &filename );
     
    586729    {
    587730        int64_t      i;
    588         int          err = 0;
    589731        const char * str;
    590         tr_ctor *    ctor;
    591         tr_torrent * tor;
    592 
    593         ctor = tr_ctorNew( session );
    594 
    595         /* set the metainfo */
    596         if( filename )
    597             tr_ctorSetMetainfoFromFile( ctor, filename );
    598         else
    599         {
    600             int    len;
    601             char * metainfo = tr_base64_decode( metainfo_base64, -1,  &len );
    602             tr_ctorSetMetainfo( ctor, (uint8_t*)metainfo, len );
    603             tr_free( metainfo );
    604         }
     732        tr_ctor    * ctor = tr_ctorNew( session );
    605733
    606734        /* set the optional arguments */
     
    612740            tr_ctorSetPeerLimit( ctor, TR_FORCE, i );
    613741
    614         tor = tr_torrentNew( session, ctor, &err );
    615         tr_ctorFree( ctor );
    616 
    617         if( tor )
     742        dbgmsg( "torrentAdd: filename is \"%s\"", filename );
     743
     744        if( isCurlURL( filename ) )
    618745        {
    619             tr_benc fields;
    620             tr_bencInitList( &fields, 3 );
    621             tr_bencListAddStr( &fields, "id" );
    622             tr_bencListAddStr( &fields, "name" );
    623             tr_bencListAddStr( &fields, "hashString" );
    624             addInfo( tor, tr_bencDictAdd( args_out,
    625                                           "torrent-added" ), &fields );
    626             notify( session, TR_RPC_TORRENT_ADDED, tor );
    627             tr_bencFree( &fields );
     746            struct add_torrent_idle_data * d = tr_new0( struct add_torrent_idle_data, 1 );
     747            d->data = idle_data;
     748            d->ctor = ctor;
     749            tr_webRun( session, filename, NULL, gotMetadataFromURL, d );
    628750        }
    629         else if( err == TR_EDUPLICATE )
     751        else
    630752        {
    631             return "duplicate torrent";
     753            if( filename != NULL )
     754                tr_ctorSetMetainfoFromFile( ctor, filename );
     755            else {
     756                int len;
     757                char * metainfo = tr_base64_decode( metainfo_base64, -1,  &len );
     758                tr_ctorSetMetainfo( ctor, (uint8_t*)metainfo, len );
     759                tr_free( metainfo );
     760            }
     761            addTorrentImpl( idle_data, ctor );
    632762        }
    633         else if( err == TR_EINVALID )
    634         {
    635             return "invalid or corrupt torrent file";
    636         }
     763
    637764    }
    638765
     
    645772
    646773static const char*
    647 sessionSet( tr_session * session,
    648             tr_benc    * args_in,
    649             tr_benc    * args_out UNUSED )
     774sessionSet( tr_session               * session,
     775            tr_benc                  * args_in,
     776            tr_benc                  * args_out UNUSED,
     777            struct tr_rpc_idle_data  * idle_data )
    650778{
    651779    int64_t      i;
    652780    const char * str;
     781
     782    assert( idle_data == NULL );
    653783
    654784    if( tr_bencDictFindStr( args_in, "download-dir", &str ) )
     
    686816
    687817static const char*
    688 sessionStats( tr_session  * session,
    689               tr_benc     * args_in UNUSED,
    690               tr_benc     * args_out )
     818sessionStats( tr_session               * session,
     819              tr_benc                  * args_in UNUSED,
     820              tr_benc                  * args_out,
     821              struct tr_rpc_idle_data  * idle_data )
    691822{
    692823    int running = 0;
    693824    int total = 0;
    694825    tr_torrent * tor = NULL;
     826
     827    assert( idle_data == NULL );
    695828
    696829    while(( tor = tr_torrentNext( session, tor ))) {
     
    709842
    710843static const char*
    711 sessionGet( tr_session * session,
    712             tr_benc    * args_in UNUSED,
    713             tr_benc    * args_out )
     844sessionGet( tr_session               * session,
     845            tr_benc                  * args_in UNUSED,
     846            tr_benc                  * args_out,
     847            struct tr_rpc_idle_data  * idle_data )
    714848{
    715849    const char * str;
    716850    tr_benc *    d = args_out;
     851
     852    assert( idle_data == NULL );
    717853
    718854    tr_bencDictAddStr( d, "download-dir", tr_sessionGetDownloadDir( session ) );
     
    742878***/
    743879
    744 typedef const char* ( handler )( tr_session*, tr_benc*, tr_benc* );
     880typedef const char* ( handler )( tr_session*, tr_benc*, tr_benc*, struct tr_rpc_idle_data * );
    745881
    746882static struct method
    747883{
    748884    const char *  name;
    749     handler *     func;
    750 } methods[] = {
    751     { "session-get",    sessionGet          },
    752     { "session-set",    sessionSet          },
    753     { "session-stats",  sessionStats        },
    754     { "torrent-add",    torrentAdd          },
    755     { "torrent-get",    torrentGet          },
    756     { "torrent-remove", torrentRemove       },
    757     { "torrent-set",    torrentSet          },
    758     { "torrent-start",  torrentStart        },
    759     { "torrent-stop",   torrentStop         },
    760     { "torrent-verify", torrentVerify       }
     885    tr_bool       immediate;
     886    handler    *  func;
     887}
     888methods[] =
     889{
     890    { "session-get",    TRUE,  sessionGet          },
     891    { "session-set",    TRUE,  sessionSet          },
     892    { "session-stats",  TRUE,  sessionStats        },
     893    { "torrent-add",    FALSE, torrentAdd          },
     894    { "torrent-get",    TRUE,  torrentGet          },
     895    { "torrent-remove", TRUE,  torrentRemove       },
     896    { "torrent-set",    TRUE,  torrentSet          },
     897    { "torrent-start",  TRUE,  torrentStart        },
     898    { "torrent-stop",   TRUE,  torrentStop         },
     899    { "torrent-verify", TRUE,  torrentVerify       }
    761900};
    762901
    763902static void
    764 request_exec( tr_session       * session,
    765               tr_benc          * request,
    766               struct evbuffer  * response_buf )
     903request_exec( tr_session             * session,
     904              tr_benc                * request,
     905              tr_rpc_response_func     callback,
     906              void                   * callback_user_data )
    767907{
    768908    int64_t      i;
    769909    const char * str;
    770     tr_benc      response;
    771910    tr_benc *    args_in = tr_bencDictFind( request, "arguments" );
    772     tr_benc *    args_out = NULL;
    773911    const char * result = NULL;
    774 
    775     /* build the response skeleton */
    776     tr_bencInitDict( &response, 3 );
    777     args_out = tr_bencDictAddDict( &response, "arguments", 0 );
    778912
    779913    /* parse the request */
    780914    if( !tr_bencDictFindStr( request, "method", &str ) )
    781915        result = "no method name";
    782     else
    783     {
     916    else {
    784917        const int n = TR_N_ELEMENTS( methods );
    785918        for( i = 0; i < n; ++i )
    786919            if( !strcmp( str, methods[i].name ) )
    787920                break;
    788         result = i == n
    789                  ? "method name not recognized"
    790                  : ( *methods[i].func )( session, args_in, args_out );
    791     }
    792 
    793     /* serialize & return the response */
    794     if( !result )
    795         result = "success";
    796     tr_bencDictAddStr( &response, "result", result );
    797     if( tr_bencDictFindInt( request, "tag", &i ) )
    798         tr_bencDictAddInt( &response, "tag", i );
    799     if( response_buf != NULL )
    800         tr_bencSaveAsJSON( &response, response_buf );
    801     tr_bencFree( &response );
     921        if( i ==n )
     922            result = "method name not recognized";
     923    }
     924
     925    /* if we couldn't figure out which method to use, return an error */
     926    if( result != NULL )
     927    {
     928        tr_benc response;
     929        struct evbuffer * buf = tr_getBuffer( );
     930
     931        tr_bencInitDict( &response, 3 );
     932        tr_bencDictAddDict( &response, "arguments", 0 );
     933        tr_bencDictAddStr( &response, "result", result );
     934        if( tr_bencDictFindInt( request, "tag", &i ) )
     935            tr_bencDictAddInt( &response, "tag", i );
     936        tr_bencSaveAsJSON( &response, buf );
     937        callback( session, (const char*)EVBUFFER_DATA(buf),
     938                  EVBUFFER_LENGTH( buf ), callback_user_data );
     939
     940        tr_releaseBuffer( buf );
     941        tr_bencFree( &response );
     942    }
     943
     944    if( methods[i].immediate )
     945    {
     946        tr_benc response;
     947        tr_benc * args_out;
     948        struct evbuffer * buf = tr_getBuffer( );
     949
     950        tr_bencInitDict( &response, 3 );
     951        args_out = tr_bencDictAddDict( &response, "arguments", 0 );
     952        result = (*methods[i].func)( session, args_in, args_out, NULL );
     953        if( result == NULL )
     954            result = "success";
     955        tr_bencDictAddStr( &response, "result", result );
     956        if( tr_bencDictFindInt( request, "tag", &i ) )
     957            tr_bencDictAddInt( &response, "tag", i );
     958        tr_bencSaveAsJSON( &response, buf );
     959        callback( session, (const char*)EVBUFFER_DATA(buf),
     960                  EVBUFFER_LENGTH(buf), callback_user_data );
     961
     962        tr_releaseBuffer( buf );
     963        tr_bencFree( &response );
     964    }
     965    else
     966    {
     967        struct tr_rpc_idle_data * data = tr_new0( struct tr_rpc_idle_data, 1 );
     968        data->session = session;
     969        data->response = tr_new0( tr_benc, 1 );
     970        if( tr_bencDictFindInt( request, "tag", &i ) )
     971            tr_bencDictAddInt( data->response, "tag", i );
     972        tr_bencInitDict( data->response, 3 );
     973        data->args_out = tr_bencDictAddDict( data->response, "arguments", 0 );
     974        data->callback = callback;
     975        data->callback_user_data = callback_user_data;
     976        (*methods[i].func)( session, args_in, data->args_out, data );
     977    }
    802978}
    803979
    804980void
    805 tr_rpc_request_exec_json( tr_session      * session,
    806                           const void      * request_json,
    807                           int               request_len,
    808                           struct evbuffer * response )
     981tr_rpc_request_exec_json( tr_session            * session,
     982                          const void            * request_json,
     983                          ssize_t                 request_len,
     984                          tr_rpc_response_func    callback,
     985                          void                  * callback_user_data )
    809986{
    810987    tr_benc top;
     
    815992
    816993    have_content = !tr_jsonParse( request_json, request_len, &top, NULL );
    817     request_exec( session, have_content ? &top : NULL, response );
     994    request_exec( session, have_content ? &top : NULL, callback, callback_user_data );
    818995
    819996    if( have_content )
     
    8541031 */
    8551032void
    856 tr_rpc_parse_list_str( tr_benc *    setme,
    857                        const char * str_in,
    858                        size_t       len )
     1033tr_rpc_parse_list_str( tr_benc     * setme,
     1034                       const char  * str_in,
     1035                       ssize_t       len )
    8591036
    8601037{
     
    9011078
    9021079void
    903 tr_rpc_request_exec_uri( tr_session      * session,
    904                          const void      * request_uri,
    905                          int               request_len,
    906                          struct evbuffer * response )
     1080tr_rpc_request_exec_uri( tr_session           * session,
     1081                         const void           * request_uri,
     1082                         ssize_t                request_len,
     1083                         tr_rpc_response_func   callback,
     1084                         void                 * callback_user_data )
    9071085{
    9081086    tr_benc      top, * args;
     
    9341112    }
    9351113
    936     request_exec( session, &top, response );
     1114    request_exec( session, &top, callback, callback_user_data );
    9371115
    9381116    /* cleanup */
  • trunk/libtransmission/rpcimpl.h

    r7658 r7744  
    1414#define TR_RPC_H
    1515
     16#include <unistd.h> /* ssize_t */
     17
    1618/***
    1719****  RPC processing
    1820***/
    1921
    20 struct evbuffer;
    2122struct tr_benc;
    2223
     24typedef void( tr_rpc_response_func )( tr_session      * session,
     25                                      const char      * response,
     26                                      size_t            response_len,
     27                                      void            * user_data );
    2328/* http://www.json.org/ */
    24 void tr_rpc_request_exec_json( tr_session       * session,
    25                                const void       * request_json,
    26                                int                request_len,
    27                                struct evbuffer  * setme_response );
     29void tr_rpc_request_exec_json( tr_session            * session,
     30                               const void            * request_json,
     31                               ssize_t                 request_len,
     32                               tr_rpc_response_func    callback,
     33                               void                  * callback_user_data );
    2834
    2935/* see the RPC spec's "Request URI Notation" section */
    30 void tr_rpc_request_exec_uri( tr_session        * session,
    31                               const void        * request_uri,
    32                                int                request_len,
    33                               struct evbuffer   * setme_response );
     36void tr_rpc_request_exec_uri( tr_session           * session,
     37                              const void           * request_uri,
     38                              ssize_t                request_len,
     39                              tr_rpc_response_func   callback,
     40                              void                 * callback_user_data );
    3441
    3542void tr_rpc_parse_list_str( struct tr_benc * setme,
    3643                            const char     * list_str,
    37                             size_t           list_str_len );
     44                            ssize_t          list_str_len );
    3845
    3946
Note: See TracChangeset for help on using the changeset viewer.