Changeset 7767


Ignore:
Timestamp:
Jan 20, 2009, 6:31:37 PM (12 years ago)
Author:
charles
Message:

(1.5x) backport trunk changes to 1.5x branch

Location:
branches/1.5x
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • branches/1.5x/daemon/remote.c

    r7737 r7767  
    5959static tr_option opts[] =
    6060{
    61     { 'a', "add",                  "Add torrent files", "a",  0, NULL },
     61    { 'a', "add",                  "Add torrent files by filename or URL", "a",  0, NULL },
    6262    { 'b', "debug",                "Print debugging information", "b",  0, NULL },
    6363    { 'd', "downlimit",            "Set the maximum global download speed in KB/s", "d",  1, "<speed>" },
     
    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                }
     
    947947                        }
    948948                        printf( "%3d: %3.0f%% %-8s %-3s %9s  %s\n",
    949                                 ( j + 1 ),
     949                                j,
    950950                                ( 100.0 * percent ),
    951951                                pristr,
  • branches/1.5x/daemon/transmission-remote.1

    r7664 r7767  
    1212.Nm
    1313.Op Ar host:port | host | port
    14 .Op Fl a Ar torrent-files
     14.Op Fl a Ar filenames-or-URLs
    1515.Op Fl b
    1616.Op Fl d Ar number | Fl D
     
    5252.Sh OPTIONS
    5353.Bl -tag -width Ds
    54 .It Fl a Fl -add Ar torrent-file(s)
    55 Add
    56 .Ar torrent-file(s)
    57 into transmission.
     54.It Fl a Fl -add Ar filenames-or-URLs
     55Add torrents to transmission.
    5856
    5957.It Fl b Fl -debug
  • branches/1.5x/gtk/main.c

    r7722 r7767  
    13811381    tr_session * session = tr_core_session( data->core );
    13821382    const char * cmd = "{ \"method\": \"torrent-stop\" }";
    1383     tr_rpc_request_exec_json( session, cmd, strlen( cmd ), NULL );
     1383    tr_rpc_request_exec_json( session, cmd, strlen( cmd ), NULL, NULL );
    13841384}
    13851385
  • branches/1.5x/gtk/util.c

    r7664 r7767  
    2424
    2525#include <ctype.h> /* isxdigit() */
     26#include <errno.h>
    2627#include <stdarg.h>
    2728#include <stdlib.h> /* free() */
     
    522523        gboolean trashed = FALSE;
    523524#ifdef HAVE_GIO
     525        GError * err = NULL;
    524526        GFile *  file = g_file_new_for_path( filename );
    525         trashed = g_file_trash( file, NULL, NULL );
     527        trashed = g_file_trash( file, NULL, &err );
     528        if( err )
     529            g_message( "Unable to trash file \"%s\": %s", filename, err->message );
     530        g_clear_error( &err );
    526531        g_object_unref( G_OBJECT( file ) );
    527 #endif
    528         if( !trashed )
    529             g_unlink( filename );
     532       
     533       
     534#endif
     535        if( !trashed ) {
     536            if( g_unlink( filename ) ) {
     537                const int err = errno;
     538                g_message( "Unable to unlink file \"%s\": %s", filename, g_strerror( err ) );
     539            }
     540        }
    530541    }
    531542
  • branches/1.5x/libtransmission/ConvertUTF.c

    r7664 r7767  
    4444#endif
    4545#include <string.h> /* strlen() */
    46 #include <unistd.h> /* ssize_t */
    4746#include "ConvertUTF.h"
    4847
     
    352351 */
    353352Boolean
    354 tr_utf8_validate( const char * str, ssize_t max_len, const char ** end )
     353tr_utf8_validate( const char * str, int max_len, const char ** end )
    355354{
    356355    const UTF8* source = (const UTF8*) str;
  • branches/1.5x/libtransmission/ConvertUTF.h

    r7664 r7767  
    55#error only libtransmission should #include this header.
    66#endif
    7 
    8 #include <unistd.h> /* ssize_t */
    97
    108/*
     
    154152
    155153/* intended to work the same as g_utf8_validate */
    156 Boolean tr_utf8_validate( const char * str, ssize_t max_len, const char ** end );
     154Boolean tr_utf8_validate( const char * str, int max_len, const char ** end );
    157155
    158156
  • branches/1.5x/libtransmission/bandwidth.c

    r7664 r7767  
    224224    {
    225225        const size_t increment = 1024;
    226         const ssize_t bytesUsed = tr_peerIoFlush( peers[i], dir, increment );
    227 
    228         dbgmsg( "peer #%d of %d used %zd bytes in this pass", i, n, bytesUsed );
    229 
    230         if( bytesUsed == (ssize_t)increment )
     226        const int bytesUsed = tr_peerIoFlush( peers[i], dir, increment );
     227
     228        dbgmsg( "peer #%d of %d used %d bytes in this pass", i, n, bytesUsed );
     229
     230        if( bytesUsed == (int)increment )
    231231            ++i;
    232232        else {
  • branches/1.5x/libtransmission/fdlimit.c

    r7734 r7767  
    612612    tr_lockFree( gFd->lock );
    613613
     614    tr_free( gFd->openFiles );
    614615    tr_free( gFd );
    615616    gFd = NULL;
  • branches/1.5x/libtransmission/peer-io.c

    r7729 r7767  
    191191    assert( tr_isPeerIo( io ) );
    192192
     193    io->hasFinishedConnecting = TRUE;
     194
    193195    curlen = EVBUFFER_LENGTH( io->inbuf );
    194196    howmuch = curlen >= max ? 0 : max - curlen;
     
    235237}
    236238
    237 static ssize_t
     239static int
    238240tr_evbuffer_write( tr_peerIo * io, int fd, size_t howmuch )
    239241{
    240242    int e;
    241     ssize_t n;
     243    int n;
    242244    struct evbuffer * buffer = io->outbuf;
    243245
     
    246248    errno = 0;
    247249#ifdef WIN32
    248     n = send(fd, buffer->buffer, howmuch,  0 );
     250    n = (int) send(fd, buffer->buffer, howmuch,  0 );
    249251#else
    250     n = write(fd, buffer->buffer, howmuch );
     252    n = (int) write(fd, buffer->buffer, howmuch );
    251253#endif
    252254    e = errno;
    253     dbgmsg( io, "wrote %zd to peer (%s)", n, (n==-1?strerror(e):"") );
     255    dbgmsg( io, "wrote %d to peer (%s)", n, (n==-1?strerror(e):"") );
    254256
    255257    if( n > 0 )
     
    270272
    271273    assert( tr_isPeerIo( io ) );
     274
     275    io->hasFinishedConnecting = TRUE;
    272276
    273277    dbgmsg( io, "libevent says this peer is ready to write" );
     
    353357    io->socket = socket;
    354358    io->isIncoming = isIncoming != 0;
     359    io->hasFinishedConnecting = FALSE;
    355360    io->timeCreated = time( NULL );
    356361    io->inbuf = evbuffer_new( );
     
    758763***/
    759764
    760 static ssize_t
     765static int
    761766tr_peerIoTryRead( tr_peerIo * io, size_t howmuch )
    762767{
    763     ssize_t res = 0;
     768    int res = 0;
    764769
    765770    if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch )))
     
    770775        e = errno;
    771776
    772         dbgmsg( io, "read %zd from peer (%s)", res, (res==-1?strerror(e):"") );
     777        dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(e):"") );
    773778
    774779        if( EVBUFFER_LENGTH( io->inbuf ) )
     
    780785            if( res == 0 )
    781786                what |= EVBUFFER_EOF;
    782             dbgmsg( io, "tr_peerIoTryRead got an error. res is %zd, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) );
     787            dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) );
    783788            io->gotError( io, what, io->userData );
    784789        }
     
    788793}
    789794
    790 static ssize_t
     795static int
    791796tr_peerIoTryWrite( tr_peerIo * io, size_t howmuch )
    792797{
    793     ssize_t n = 0;
     798    int n = 0;
    794799
    795800    if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_UP, howmuch )))
     
    806811        {
    807812            const short what = EVBUFFER_WRITE | EVBUFFER_ERROR;
    808             dbgmsg( io, "tr_peerIoTryWrite got an error. res is %zd, what is %hd, errno is %d (%s)", n, what, e, strerror( e ) );
     813            dbgmsg( io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, strerror( e ) );
    809814            io->gotError( io, what, io->userData );
    810815        }
     
    814819}
    815820
    816 ssize_t
     821int
    817822tr_peerIoFlush( tr_peerIo  * io, tr_direction dir, size_t limit )
    818823{
    819     ssize_t bytesUsed;
     824    int bytesUsed = 0;
    820825
    821826    assert( tr_isPeerIo( io ) );
    822827    assert( tr_isDirection( dir ) );
    823828
    824     if( dir == TR_DOWN )
    825         bytesUsed = tr_peerIoTryRead( io, limit );
    826     else
    827         bytesUsed = tr_peerIoTryWrite( io, limit );
    828 
    829     dbgmsg( io, "flushing peer-io, direction %d, limit %zu, bytesUsed %zd", (int)dir, limit, bytesUsed );
     829    if( io->hasFinishedConnecting )
     830    {
     831        if( dir == TR_DOWN )
     832            bytesUsed = tr_peerIoTryRead( io, limit );
     833        else
     834            bytesUsed = tr_peerIoTryWrite( io, limit );
     835    }
     836
     837    dbgmsg( io, "flushing peer-io, direction %d, limit %zu, bytesUsed %d", (int)dir, limit, bytesUsed );
    830838    return bytesUsed;
    831839}
  • branches/1.5x/libtransmission/peer-io.h

    r7729 r7767  
    6565    tr_bool               fastExtensionSupported;
    6666
     67    /* we create the socket in a nonblocking way, so this flag is initially
     68     * false and then set to true when libevent says that the socket is ready
     69     * for reading or writing */
     70    tr_bool               hasFinishedConnecting;
     71
    6772    int                   magicNumber;
    6873
     
    7277    int                   socket;
    7378
    74     ssize_t               refCount;
     79    int                   refCount;
    7580
    7681    uint8_t               peerId[SHA_DIGEST_LENGTH];
     
    356361                               tr_bool        isEnabled );
    357362                       
    358 ssize_t   tr_peerIoFlush( tr_peerIo     * io,
     363int       tr_peerIoFlush( tr_peerIo     * io,
    359364                          tr_direction    dir,
    360365                          size_t          byteLimit );
  • branches/1.5x/libtransmission/peer-mgr.c

    r7741 r7767  
    19841984***/
    19851985
    1986 static int
    1987 shouldPeerBeClosed( const Torrent * t,
    1988                     const tr_peer * peer,
    1989                     int             peerCount )
     1986typedef enum
     1987{
     1988    TR_CAN_KEEP,
     1989    TR_CAN_CLOSE,
     1990    TR_MUST_CLOSE,
     1991}
     1992tr_close_type_t;
     1993
     1994static tr_close_type_t
     1995shouldPeerBeClosed( const Torrent    * t,
     1996                    const tr_peer    * peer,
     1997                    int                peerCount )
    19901998{
    19911999    const tr_torrent *       tor = t->tor;
     
    19982006        tordbg( t, "purging peer %s because its doPurge flag is set",
    19992007                tr_peerIoAddrStr( &atom->addr, atom->port ) );
    2000         return TRUE;
     2008        return TR_MUST_CLOSE;
    20012009    }
    20022010
     
    20212029            tordbg( t, "purging peer %s because we're both seeds",
    20222030                    tr_peerIoAddrStr( &atom->addr, atom->port ) );
    2023             return TRUE;
     2031            return TR_MUST_CLOSE;
    20242032        }
    20252033    }
     
    20322040         * if we have zero connections, strictness is 0% */
    20332041        const float strictness = peerCount >= relaxStrictnessIfFewerThanN
    2034             ? 1.0
    2035             : peerCount / (float)relaxStrictnessIfFewerThanN;
     2042                               ? 1.0
     2043                               : peerCount / (float)relaxStrictnessIfFewerThanN;
    20362044        const int lo = MIN_UPLOAD_IDLE_SECS;
    20372045        const int hi = MAX_UPLOAD_IDLE_SECS;
     
    20422050            tordbg( t, "purging peer %s because it's been %d secs since we shared anything",
    20432051                       tr_peerIoAddrStr( &atom->addr, atom->port ), idleTime );
    2044             return TRUE;
    2045         }
    2046     }
    2047 
    2048     return FALSE;
     2052            return TR_CAN_CLOSE;
     2053        }
     2054    }
     2055
     2056    return TR_CAN_KEEP;
    20492057}
    20502058
    20512059static tr_peer **
    2052 getPeersToClose( Torrent * t, int * setmeSize )
     2060getPeersToClose( Torrent * t, tr_close_type_t closeType, int * setmeSize )
    20532061{
    20542062    int i, peerCount, outsize;
     
    20592067
    20602068    for( i = outsize = 0; i < peerCount; ++i )
    2061         if( shouldPeerBeClosed( t, peers[i], peerCount ) )
     2069        if( shouldPeerBeClosed( t, peers[i], peerCount ) == closeType )
    20622070            ret[outsize++] = peers[i];
    20632071
     
    21872195}
    21882196
     2197static void
     2198closePeer( Torrent * t, tr_peer * peer )
     2199{
     2200    struct peer_atom * atom;
     2201
     2202    assert( t != NULL );
     2203    assert( peer != NULL );
     2204
     2205    /* if we transferred piece data, then they might be good peers,
     2206       so reset their `numFails' weight to zero.  otherwise we connected
     2207       to them fruitlessly, so mark it as another fail */
     2208    atom = getExistingAtom( t, &peer->addr );
     2209    if( atom->piece_data_time )
     2210        atom->numFails = 0;
     2211    else
     2212        ++atom->numFails;
     2213
     2214    tordbg( t, "removing bad peer %s", tr_peerIoGetAddrStr( peer->io ) );
     2215    removePeer( t, peer );
     2216}
     2217
    21892218static int
    21902219reconnectPulse( void * vtorrent )
     
    22102239    else
    22112240    {
    2212         int i, nCandidates, nBad;
    2213         struct peer_atom ** candidates = getPeerCandidates( t, &nCandidates );
    2214         struct tr_peer ** connections = getPeersToClose( t, &nBad );
    2215 
    2216         //if( nBad || nCandidates )
    2217             tordbg( t, "reconnect pulse for [%s]: %d bad connections, "
    2218                     "%d connection candidates, %d atoms, max per pulse is %d",
    2219                     t->tor->info.name, nBad, nCandidates,
    2220                     tr_ptrArraySize( &t->pool ),
    2221                     (int)MAX_RECONNECTIONS_PER_PULSE );
    2222 
    2223         /* disconnect some peers.
    2224            if we transferred piece data, then they might be good peers,
    2225            so reset their `numFails' weight to zero.  otherwise we connected
    2226            to them fruitlessly, so mark it as another fail */
    2227         for( i = 0; i < nBad; ++i ) {
    2228             tr_peer * peer = connections[i];
    2229             struct peer_atom * atom = getExistingAtom( t, &peer->addr );
    2230             if( atom->piece_data_time )
    2231                 atom->numFails = 0;
    2232             else
    2233                 ++atom->numFails;
    2234             tordbg( t, "removing bad peer %s", tr_peerIoGetAddrStr( peer->io ) );
    2235             removePeer( t, peer );
    2236         }
    2237 
    2238 tordbg( t, "nCandidates is %d, MAX_RECONNECTIONS_PER_PULSE is %d, getPeerCount(t) is %d, getMaxPeerCount(t) is %d, newConnectionsThisSecond is %d, MAX_CONNECTIONS_PER_SECOND is %d",
    2239         (int)nCandidates, (int)MAX_RECONNECTIONS_PER_PULSE, (int)getPeerCount( t ), (int)getMaxPeerCount( t->tor ), (int)newConnectionsThisSecond, (int)MAX_CONNECTIONS_PER_SECOND );
     2241        int i;
     2242        int canCloseCount;
     2243        int mustCloseCount;
     2244        int candidateCount;
     2245        int maxCandidates;
     2246        struct tr_peer ** canClose = getPeersToClose( t, TR_CAN_CLOSE, &canCloseCount );
     2247        struct tr_peer ** mustClose = getPeersToClose( t, TR_MUST_CLOSE, &mustCloseCount );
     2248        struct peer_atom ** candidates = getPeerCandidates( t, &candidateCount );
     2249
     2250        tordbg( t, "reconnect pulse for [%s]: "
     2251                   "%d must-close connections, "
     2252                   "%d can-close connections, "
     2253                   "%d connection candidates, "
     2254                   "%d atoms, "
     2255                   "max per pulse is %d",
     2256                   t->tor->info.name,
     2257                   mustCloseCount,
     2258                   canCloseCount,
     2259                   candidateCount,
     2260                   tr_ptrArraySize( &t->pool ),
     2261                   MAX_RECONNECTIONS_PER_PULSE );
     2262
     2263        /* disconnect the really bad peers */
     2264        for( i=0; i<mustCloseCount; ++i )
     2265            closePeer( t, mustClose[i] );
     2266
     2267        /* decide how many peers can we try to add in this pass */
     2268        maxCandidates = candidateCount;
     2269        maxCandidates = MIN( maxCandidates, MAX_RECONNECTIONS_PER_PULSE );
     2270        maxCandidates = MIN( maxCandidates, getMaxPeerCount( t->tor ) - getPeerCount( t ) );
     2271        maxCandidates = MIN( maxCandidates, MAX_CONNECTIONS_PER_SECOND - newConnectionsThisSecond );
     2272
     2273        /* maybe disconnect some lesser peers, if we have candidates to replace them with */
     2274        for( i=0; ( i<canCloseCount ) && ( i<maxCandidates ); ++i )
     2275            closePeer( t, canClose[i] );
     2276
     2277        tordbg( t, "candidateCount is %d, MAX_RECONNECTIONS_PER_PULSE is %d,"
     2278                   " getPeerCount(t) is %d, getMaxPeerCount(t) is %d, "
     2279                   "newConnectionsThisSecond is %d, MAX_CONNECTIONS_PER_SECOND is %d",
     2280                   candidateCount,
     2281                   MAX_RECONNECTIONS_PER_PULSE,
     2282                   getPeerCount( t ),
     2283                   getMaxPeerCount( t->tor ),
     2284                   newConnectionsThisSecond, MAX_CONNECTIONS_PER_SECOND );
    22402285
    22412286        /* add some new ones */
    2242         for( i = 0;    ( i < nCandidates )
    2243            && ( i < MAX_RECONNECTIONS_PER_PULSE )
    2244            && ( getPeerCount( t ) < getMaxPeerCount( t->tor ) )
    2245            && ( newConnectionsThisSecond < MAX_CONNECTIONS_PER_SECOND ); ++i )
     2287        for( i=0; i<maxCandidates; ++i )
    22462288        {
    2247             tr_peerMgr *      mgr = t->manager;
    2248             struct peer_atom * atom = candidates[i];
    2249             tr_peerIo *        io;
     2289            tr_peerMgr        * mgr = t->manager;
     2290            struct peer_atom  * atom = candidates[i];
     2291            tr_peerIo         * io;
    22502292
    22512293            tordbg( t, "Starting an OUTGOING connection with %s",
     
    22812323
    22822324        /* cleanup */
    2283         tr_free( connections );
    22842325        tr_free( candidates );
     2326        tr_free( mustClose );
     2327        tr_free( canClose );
    22852328    }
    22862329
  • branches/1.5x/libtransmission/rpc-server.c

    r7722 r7767  
    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
  • branches/1.5x/libtransmission/rpcimpl.c

    r7733 r7767  
    1616#include <string.h> /* strcmp */
    1717
     18#include <event.h> /* evbuffer */
     19
    1820#include "transmission.h"
    1921#include "bencode.h"
     
    2123#include "json.h"
    2224#include "session.h"
     25#include "stats.h"
    2326#include "torrent.h"
    2427#include "utils.h"
     28#include "web.h"
    2529
    2630#define TR_N_ELEMENTS( ary ) ( sizeof( ary ) / sizeof( *ary ) )
     31
     32#if 0
     33#define dbgmsg(fmt, ...) \
     34    do { \
     35        fprintf( stderr, "%s:%d"#fmt, __FILE__, __LINE__, __VA_ARGS__ ); \
     36        fprintf( stderr, "\n" ); \
     37    } while( 0 )
     38#else
     39#define dbgmsg( ... ) \
     40    do { \
     41        if( tr_deepLoggingIsActive( ) ) \
     42            tr_deepLog( __FILE__, __LINE__, "RPC", __VA_ARGS__ ); \
     43    } while( 0 )
     44#endif
     45
    2746
    2847/***
     
    4261
    4362    return status;
     63}
     64
     65/***
     66****
     67***/
     68
     69/* For functions that can't be immediately executed, like torrentAdd,
     70 * this is the callback data used to pass a response to the caller
     71 * when the task is complete */
     72struct tr_rpc_idle_data
     73{
     74    tr_session            * session;
     75    tr_benc               * response;
     76    tr_benc               * args_out;
     77    tr_rpc_response_func    callback;
     78    void                  * callback_user_data;
     79};
     80
     81static void
     82tr_idle_function_done( struct tr_rpc_idle_data * data, const char * result )
     83{
     84    struct evbuffer * buf = tr_getBuffer( );
     85
     86    if( result == NULL )
     87        result = "success";
     88    tr_bencDictAddStr( data->response, "result", result );
     89
     90    tr_bencSaveAsJSON( data->response, buf );
     91    (*data->callback)( data->session, (const char*)EVBUFFER_DATA(buf),
     92                       EVBUFFER_LENGTH(buf), data->callback_user_data );
     93
     94    tr_releaseBuffer( buf );
     95    tr_bencFree( data->response );
     96    tr_free( data->response );
     97    tr_free( data );
    4498}
    4599
     
    100154
    101155static const char*
    102 torrentStart( tr_session * session,
    103               tr_benc    * args_in,
    104               tr_benc    * args_out UNUSED )
     156torrentStart( tr_session               * session,
     157              tr_benc                  * args_in,
     158              tr_benc                  * args_out UNUSED,
     159              struct tr_rpc_idle_data  * idle_data )
    105160{
    106161    int           i, torrentCount;
    107162    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     163
     164    assert( idle_data == NULL );
    108165
    109166    for( i = 0; i < torrentCount; ++i )
     
    118175
    119176static const char*
    120 torrentStop( tr_session * session,
    121              tr_benc    * args_in,
    122              tr_benc    * args_out UNUSED )
     177torrentStop( tr_session               * session,
     178             tr_benc                  * args_in,
     179             tr_benc                  * args_out UNUSED,
     180             struct tr_rpc_idle_data  * idle_data )
    123181{
    124182    int           i, torrentCount;
    125183    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     184
     185    assert( idle_data == NULL );
    126186
    127187    for( i = 0; i < torrentCount; ++i )
     
    136196
    137197static const char*
    138 torrentRemove( tr_session  * session,
    139                tr_benc     * args_in,
    140                tr_benc     * args_out UNUSED )
     198torrentRemove( tr_session               * session,
     199               tr_benc                  * args_in,
     200               tr_benc                  * args_out UNUSED,
     201               struct tr_rpc_idle_data  * idle_data )
    141202{
    142203    int i;
    143204    int torrentCount;
    144205    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     206
     207    assert( idle_data == NULL );
    145208
    146209    for( i=0; i<torrentCount; ++i )
     
    160223
    161224static const char*
    162 torrentVerify( tr_session  * session,
    163                tr_benc     * args_in,
    164                tr_benc     * args_out UNUSED )
     225torrentVerify( tr_session               * session,
     226               tr_benc                  * args_in,
     227               tr_benc                  * args_out UNUSED,
     228               struct tr_rpc_idle_data  * idle_data )
    165229{
    166230    int           i, torrentCount;
    167231    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     232
     233    assert( idle_data == NULL );
    168234
    169235    for( i = 0; i < torrentCount; ++i )
     
    436502
    437503static const char*
    438 torrentGet( tr_session * session,
    439             tr_benc    * args_in,
    440             tr_benc    * args_out )
     504torrentGet( tr_session               * session,
     505            tr_benc                  * args_in,
     506            tr_benc                  * args_out,
     507            struct tr_rpc_idle_data  * idle_data )
    441508{
    442509    int           i, torrentCount;
    443510    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
    444     tr_benc *     list = tr_bencDictAddList( args_out, "torrents",
    445                                              torrentCount );
     511    tr_benc *     list = tr_bencDictAddList( args_out, "torrents", torrentCount );
    446512    tr_benc *     fields;
    447513    char *        msg = NULL;
     514
     515    assert( idle_data == NULL );
    448516
    449517    if( !tr_bencDictFindList( args_in, "fields", &fields ) )
     
    523591
    524592static const char*
    525 torrentSet( tr_session * session,
    526             tr_benc    * args_in,
    527             tr_benc    * args_out UNUSED )
     593torrentSet( tr_session               * session,
     594            tr_benc                  * args_in,
     595            tr_benc                  * args_out UNUSED,
     596            struct tr_rpc_idle_data  * idle_data )
    528597{
    529598    int           i, torrentCount;
    530599    tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount );
     600
     601    assert( idle_data == NULL );
    531602
    532603    for( i = 0; i < torrentCount; ++i )
     
    571642***/
    572643
     644static void
     645addTorrentImpl( struct tr_rpc_idle_data * data, tr_ctor * ctor )
     646{
     647    int err = 0;
     648    const char * result = NULL;
     649    tr_torrent * tor = tr_torrentNew( data->session, ctor, &err );
     650
     651    tr_ctorFree( ctor );
     652
     653    if( tor )
     654    {
     655        tr_benc fields;
     656        tr_bencInitList( &fields, 3 );
     657        tr_bencListAddStr( &fields, "id" );
     658        tr_bencListAddStr( &fields, "name" );
     659        tr_bencListAddStr( &fields, "hashString" );
     660        addInfo( tor, tr_bencDictAdd( data->args_out, "torrent-added" ), &fields );
     661        notify( data->session, TR_RPC_TORRENT_ADDED, tor );
     662        tr_bencFree( &fields );
     663    }
     664    else if( err == TR_EDUPLICATE )
     665    {
     666        result = "duplicate torrent";
     667    }
     668    else if( err == TR_EINVALID )
     669    {
     670        result = "invalid or corrupt torrent file";
     671    }
     672
     673    tr_idle_function_done( data, result );
     674}
     675
     676
     677struct add_torrent_idle_data
     678{
     679    struct tr_rpc_idle_data * data;
     680    tr_ctor * ctor;
     681};
     682
     683static void
     684gotMetadataFromURL( tr_session       * session UNUSED,
     685                    long               response_code,
     686                    const void       * response,
     687                    size_t             response_byte_count,
     688                    void             * user_data )
     689{
     690    struct add_torrent_idle_data * data = user_data;
     691
     692    dbgmsg( "torrentAdd: HTTP response code was %ld (%s); response length was %zu bytes",
     693            response_code, tr_webGetResponseStr( response_code ), response_byte_count );
     694
     695    if( response_code == 200 )
     696    {
     697        tr_ctorSetMetainfo( data->ctor, response, response_byte_count );
     698        addTorrentImpl( data->data, data->ctor );
     699    }
     700    else
     701    {
     702        char result[1024];
     703        tr_snprintf( result, sizeof( result ), "http error %ld: %s",
     704                     response_code, tr_webGetResponseStr( response_code ) );
     705        tr_idle_function_done( data->data, result );
     706    }
     707
     708    tr_free( data );
     709}
     710
     711static tr_bool
     712isCurlURL( const char * filename )
     713{
     714    if( filename == NULL )
     715        return FALSE;
     716
     717    return ( strstr( filename, "ftp://" ) != NULL )
     718        || ( strstr( filename, "http://" ) != NULL )
     719        || ( strstr( filename, "https://" ) != NULL );
     720}
     721
    573722static const char*
    574 torrentAdd( tr_session * session,
    575             tr_benc    * args_in,
    576             tr_benc    * args_out )
     723torrentAdd( tr_session               * session,
     724            tr_benc                  * args_in,
     725            tr_benc                  * args_out UNUSED,
     726            struct tr_rpc_idle_data  * idle_data )
    577727{
    578728    const char * filename = NULL;
    579729    const char * metainfo_base64 = NULL;
     730
     731    assert( idle_data != NULL );
    580732
    581733    tr_bencDictFindStr( args_in, "filename", &filename );
     
    586738    {
    587739        int64_t      i;
    588         int          err = 0;
    589740        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         }
     741        tr_ctor    * ctor = tr_ctorNew( session );
    605742
    606743        /* set the optional arguments */
     
    612749            tr_ctorSetPeerLimit( ctor, TR_FORCE, i );
    613750
    614         tor = tr_torrentNew( session, ctor, &err );
    615         tr_ctorFree( ctor );
    616 
    617         if( tor )
     751        dbgmsg( "torrentAdd: filename is \"%s\"", filename );
     752
     753        if( isCurlURL( filename ) )
    618754        {
    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 );
     755            struct add_torrent_idle_data * d = tr_new0( struct add_torrent_idle_data, 1 );
     756            d->data = idle_data;
     757            d->ctor = ctor;
     758            tr_webRun( session, filename, NULL, gotMetadataFromURL, d );
    628759        }
    629         else if( err == TR_EDUPLICATE )
     760        else
    630761        {
    631             return "duplicate torrent";
     762            if( filename != NULL )
     763                tr_ctorSetMetainfoFromFile( ctor, filename );
     764            else {
     765                int len;
     766                char * metainfo = tr_base64_decode( metainfo_base64, -1,  &len );
     767                tr_ctorSetMetainfo( ctor, (uint8_t*)metainfo, len );
     768                tr_free( metainfo );
     769            }
     770            addTorrentImpl( idle_data, ctor );
    632771        }
    633         else if( err == TR_EINVALID )
    634         {
    635             return "invalid or corrupt torrent file";
    636         }
     772
    637773    }
    638774
     
    645781
    646782static const char*
    647 sessionSet( tr_session * session,
    648             tr_benc    * args_in,
    649             tr_benc    * args_out UNUSED )
     783sessionSet( tr_session               * session,
     784            tr_benc                  * args_in,
     785            tr_benc                  * args_out UNUSED,
     786            struct tr_rpc_idle_data  * idle_data )
    650787{
    651788    int64_t      i;
    652789    const char * str;
     790
     791    assert( idle_data == NULL );
    653792
    654793    if( tr_bencDictFindStr( args_in, "download-dir", &str ) )
     
    686825
    687826static const char*
    688 sessionStats( tr_session  * session,
    689               tr_benc     * args_in UNUSED,
    690               tr_benc     * args_out )
     827sessionStats( tr_session               * session,
     828              tr_benc                  * args_in UNUSED,
     829              tr_benc                  * args_out,
     830              struct tr_rpc_idle_data  * idle_data )
    691831{
    692832    int running = 0;
    693833    int total = 0;
     834    tr_benc * d; 
     835    tr_session_stats currentStats = { 0.0f, 0, 0, 0, 0, 0 };
     836    tr_session_stats cumulativeStats = { 0.0f, 0, 0, 0, 0, 0 };
    694837    tr_torrent * tor = NULL;
     838
     839    assert( idle_data == NULL );
    695840
    696841    while(( tor = tr_torrentNext( session, tor ))) {
     
    699844            ++running;
    700845    }
     846
     847    tr_sessionGetStats( session, &currentStats );
     848    tr_sessionGetCumulativeStats( session, &cumulativeStats );
    701849
    702850    tr_bencDictAddInt( args_out, "activeTorrentCount", running );
     
    705853    tr_bencDictAddInt( args_out, "torrentCount", total );
    706854    tr_bencDictAddInt( args_out, "uploadSpeed", (int)( tr_sessionGetPieceSpeed( session, TR_UP ) * 1024 ) );
     855
     856    d = tr_bencDictAddDict( args_out, "cumulative-stats", 5 ); 
     857    tr_bencDictAddInt( d, "downloadedBytes", cumulativeStats.downloadedBytes );
     858    tr_bencDictAddInt( d, "filesAdded", cumulativeStats.filesAdded );
     859    tr_bencDictAddInt( d, "secondsActive", cumulativeStats.secondsActive );
     860    tr_bencDictAddInt( d, "sessionCount", cumulativeStats.sessionCount );
     861    tr_bencDictAddInt( d, "uploadedBytes", cumulativeStats.uploadedBytes );
     862
     863    d = tr_bencDictAddDict( args_out, "current-stats", 5 ); 
     864    tr_bencDictAddInt( d, "downloadedBytes", currentStats.downloadedBytes );
     865    tr_bencDictAddInt( d, "filesAdded", currentStats.filesAdded );
     866    tr_bencDictAddInt( d, "secondsActive", currentStats.secondsActive );
     867    tr_bencDictAddInt( d, "sessionCount", currentStats.sessionCount );
     868    tr_bencDictAddInt( d, "uploadedBytes", currentStats.uploadedBytes );
     869
    707870    return NULL;
    708871}
    709872
    710873static const char*
    711 sessionGet( tr_session * session,
    712             tr_benc    * args_in UNUSED,
    713             tr_benc    * args_out )
     874sessionGet( tr_session               * session,
     875            tr_benc                  * args_in UNUSED,
     876            tr_benc                  * args_out,
     877            struct tr_rpc_idle_data  * idle_data )
    714878{
    715879    const char * str;
    716880    tr_benc *    d = args_out;
     881
     882    assert( idle_data == NULL );
    717883
    718884    tr_bencDictAddStr( d, "download-dir", tr_sessionGetDownloadDir( session ) );
     
    742908***/
    743909
    744 typedef const char* ( handler )( tr_session*, tr_benc*, tr_benc* );
     910typedef const char* ( *handler )( tr_session*, tr_benc*, tr_benc*, struct tr_rpc_idle_data * );
    745911
    746912static struct method
    747913{
    748914    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       }
     915    tr_bool       immediate;
     916    handler       func;
     917}
     918methods[] =
     919{
     920    { "session-get",    TRUE,  sessionGet          },
     921    { "session-set",    TRUE,  sessionSet          },
     922    { "session-stats",  TRUE,  sessionStats        },
     923    { "torrent-add",    FALSE, torrentAdd          },
     924    { "torrent-get",    TRUE,  torrentGet          },
     925    { "torrent-remove", TRUE,  torrentRemove       },
     926    { "torrent-set",    TRUE,  torrentSet          },
     927    { "torrent-start",  TRUE,  torrentStart        },
     928    { "torrent-stop",   TRUE,  torrentStop         },
     929    { "torrent-verify", TRUE,  torrentVerify       }
    761930};
    762931
    763932static void
    764 request_exec( tr_session       * session,
    765               tr_benc          * request,
    766               struct evbuffer  * response_buf )
    767 {
    768     int64_t      i;
     933noop_response_callback( tr_session * session UNUSED,
     934                        const char * response UNUSED,
     935                        size_t       response_len UNUSED,
     936                        void       * user_data UNUSED )
     937{
     938}
     939
     940static void
     941request_exec( tr_session             * session,
     942              tr_benc                * request,
     943              tr_rpc_response_func     callback,
     944              void                   * callback_user_data )
     945{
     946    int i;
    769947    const char * str;
    770     tr_benc      response;
    771     tr_benc *    args_in = tr_bencDictFind( request, "arguments" );
    772     tr_benc *    args_out = NULL;
     948    tr_benc * args_in = tr_bencDictFind( request, "arguments" );
    773949    const char * result = NULL;
    774950
    775     /* build the response skeleton */
    776     tr_bencInitDict( &response, 3 );
    777     args_out = tr_bencDictAddDict( &response, "arguments", 0 );
     951    if( callback == NULL )
     952        callback = noop_response_callback;
    778953
    779954    /* parse the request */
    780955    if( !tr_bencDictFindStr( request, "method", &str ) )
    781956        result = "no method name";
    782     else
    783     {
     957    else {
    784958        const int n = TR_N_ELEMENTS( methods );
    785959        for( i = 0; i < n; ++i )
    786960            if( !strcmp( str, methods[i].name ) )
    787961                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 );
     962        if( i ==n )
     963            result = "method name not recognized";
     964    }
     965
     966    /* if we couldn't figure out which method to use, return an error */
     967    if( result != NULL )
     968    {
     969        int64_t tag;
     970        tr_benc response;
     971        struct evbuffer * buf = tr_getBuffer( );
     972
     973        tr_bencInitDict( &response, 3 );
     974        tr_bencDictAddDict( &response, "arguments", 0 );
     975        tr_bencDictAddStr( &response, "result", result );
     976        if( tr_bencDictFindInt( request, "tag", &tag ) )
     977            tr_bencDictAddInt( &response, "tag", tag );
     978        tr_bencSaveAsJSON( &response, buf );
     979        (*callback)( session, (const char*)EVBUFFER_DATA(buf),
     980                     EVBUFFER_LENGTH( buf ), callback_user_data );
     981
     982        tr_releaseBuffer( buf );
     983        tr_bencFree( &response );
     984    }
     985
     986    if( methods[i].immediate )
     987    {
     988        int64_t tag;
     989        tr_benc response;
     990        tr_benc * args_out;
     991        struct evbuffer * buf = tr_getBuffer( );
     992
     993        tr_bencInitDict( &response, 3 );
     994        args_out = tr_bencDictAddDict( &response, "arguments", 0 );
     995        result = (*methods[i].func)( session, args_in, args_out, NULL );
     996        if( result == NULL )
     997            result = "success";
     998        tr_bencDictAddStr( &response, "result", result );
     999        if( tr_bencDictFindInt( request, "tag", &tag ) )
     1000            tr_bencDictAddInt( &response, "tag", tag );
     1001        tr_bencSaveAsJSON( &response, buf );
     1002        (*callback)( session, (const char*)EVBUFFER_DATA(buf),
     1003                     EVBUFFER_LENGTH(buf), callback_user_data );
     1004
     1005        tr_releaseBuffer( buf );
     1006        tr_bencFree( &response );
     1007    }
     1008    else
     1009    {
     1010        int64_t tag;
     1011        struct tr_rpc_idle_data * data = tr_new0( struct tr_rpc_idle_data, 1 );
     1012        data->session = session;
     1013        data->response = tr_new0( tr_benc, 1 );
     1014        tr_bencInitDict( data->response, 3 );
     1015        if( tr_bencDictFindInt( request, "tag", &tag ) )
     1016            tr_bencDictAddInt( data->response, "tag", tag );
     1017        data->args_out = tr_bencDictAddDict( data->response, "arguments", 0 );
     1018        data->callback = callback;
     1019        data->callback_user_data = callback_user_data;
     1020        (*methods[i].func)( session, args_in, data->args_out, data );
     1021    }
    8021022}
    8031023
    8041024void
    805 tr_rpc_request_exec_json( tr_session      * session,
    806                           const void      * request_json,
    807                           int               request_len,
    808                           struct evbuffer * response )
     1025tr_rpc_request_exec_json( tr_session            * session,
     1026                          const void            * request_json,
     1027                          int                     request_len,
     1028                          tr_rpc_response_func    callback,
     1029                          void                  * callback_user_data )
    8091030{
    8101031    tr_benc top;
     
    8151036
    8161037    have_content = !tr_jsonParse( request_json, request_len, &top, NULL );
    817     request_exec( session, have_content ? &top : NULL, response );
     1038    request_exec( session, have_content ? &top : NULL, callback, callback_user_data );
    8181039
    8191040    if( have_content )
     
    8541075 */
    8551076void
    856 tr_rpc_parse_list_str( tr_benc *    setme,
    857                        const char * str_in,
    858                        size_t       len )
     1077tr_rpc_parse_list_str( tr_benc     * setme,
     1078                       const char  * str_in,
     1079                       int           len )
    8591080
    8601081{
     
    9011122
    9021123void
    903 tr_rpc_request_exec_uri( tr_session      * session,
    904                          const void      * request_uri,
    905                          int               request_len,
    906                          struct evbuffer * response )
     1124tr_rpc_request_exec_uri( tr_session           * session,
     1125                         const void           * request_uri,
     1126                         int                    request_len,
     1127                         tr_rpc_response_func   callback,
     1128                         void                 * callback_user_data )
    9071129{
    9081130    tr_benc      top, * args;
     
    9341156    }
    9351157
    936     request_exec( session, &top, response );
     1158    request_exec( session, &top, callback, callback_user_data );
    9371159
    9381160    /* cleanup */
  • branches/1.5x/libtransmission/rpcimpl.h

    r7664 r7767  
    1818***/
    1919
    20 struct evbuffer;
    2120struct tr_benc;
    2221
     22typedef void( *tr_rpc_response_func )( tr_session      * session,
     23                                       const char      * response,
     24                                       size_t            response_len,
     25                                       void            * user_data );
    2326/* 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 );
     27void tr_rpc_request_exec_json( tr_session            * session,
     28                               const void            * request_json,
     29                               int                     request_len,
     30                               tr_rpc_response_func    callback,
     31                               void                  * callback_user_data );
    2832
    2933/* 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 );
     34void tr_rpc_request_exec_uri( tr_session           * session,
     35                              const void           * request_uri,
     36                              int                    request_len,
     37                              tr_rpc_response_func   callback,
     38                              void                 * callback_user_data );
    3439
    3540void tr_rpc_parse_list_str( struct tr_benc * setme,
    3641                            const char     * list_str,
    37                             size_t           list_str_len );
     42                            int              list_str_len );
    3843
    3944
  • branches/1.5x/libtransmission/utils-test.c

    r7664 r7767  
    22#include <string.h> /* strcmp */
    33#include "transmission.h"
    4 #include <unistd.h> /* ssize_t */
    54#include "ConvertUTF.h" /* tr_utf8_validate*/
    65#include "platform.h"
  • branches/1.5x/libtransmission/utils.c

    r7664 r7767  
    638638
    639639char*
    640 tr_strndup( const void * in,
    641             int          len )
     640tr_strndup( const void * in, int len )
    642641{
    643642    char * out = NULL;
     
    13271326
    13281327char*
    1329 tr_utf8clean( const char * str, ssize_t max_len, tr_bool * err )
     1328tr_utf8clean( const char * str, int max_len, tr_bool * err )
    13301329{
    13311330    const char zero = '\0';
     
    13381337
    13391338    if( max_len < 0 )
    1340         max_len = (ssize_t) strlen( str );
     1339        max_len = (int) strlen( str );
    13411340
    13421341    while( !tr_utf8_validate ( str, max_len, &end ) )
    13431342    {
    1344         const ssize_t good_len = end - str;
     1343        const int good_len = end - str;
    13451344
    13461345        evbuffer_add( buf, str, good_len );
  • branches/1.5x/libtransmission/utils.h

    r7664 r7767  
    239239
    240240char*          tr_utf8clean( const char  * str,
    241                              ssize_t       max_len,
     241                             int           max_len,
    242242                             tr_bool     * err );
    243243
Note: See TracChangeset for help on using the changeset viewer.