Changeset 7767
- Timestamp:
- Jan 20, 2009, 6:31:37 PM (12 years ago)
- Location:
- branches/1.5x
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.5x/daemon/remote.c
r7737 r7767 59 59 static tr_option opts[] = 60 60 { 61 { 'a', "add", "Add torrent files ", "a", 0, NULL },61 { 'a', "add", "Add torrent files by filename or URL", "a", 0, NULL }, 62 62 { 'b', "debug", "Print debugging information", "b", 0, NULL }, 63 63 { 'd', "downlimit", "Set the maximum global download speed in KB/s", "d", 1, "<speed>" }, … … 301 301 else 302 302 { 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 ); 305 305 } 306 306 } … … 947 947 } 948 948 printf( "%3d: %3.0f%% %-8s %-3s %9s %s\n", 949 ( j + 1 ),949 j, 950 950 ( 100.0 * percent ), 951 951 pristr, -
branches/1.5x/daemon/transmission-remote.1
r7664 r7767 12 12 .Nm 13 13 .Op Ar host:port | host | port 14 .Op Fl a Ar torrent-files14 .Op Fl a Ar filenames-or-URLs 15 15 .Op Fl b 16 16 .Op Fl d Ar number | Fl D … … 52 52 .Sh OPTIONS 53 53 .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 55 Add torrents to transmission. 58 56 59 57 .It Fl b Fl -debug -
branches/1.5x/gtk/main.c
r7722 r7767 1381 1381 tr_session * session = tr_core_session( data->core ); 1382 1382 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 ); 1384 1384 } 1385 1385 -
branches/1.5x/gtk/util.c
r7664 r7767 24 24 25 25 #include <ctype.h> /* isxdigit() */ 26 #include <errno.h> 26 27 #include <stdarg.h> 27 28 #include <stdlib.h> /* free() */ … … 522 523 gboolean trashed = FALSE; 523 524 #ifdef HAVE_GIO 525 GError * err = NULL; 524 526 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 ); 526 531 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 } 530 541 } 531 542 -
branches/1.5x/libtransmission/ConvertUTF.c
r7664 r7767 44 44 #endif 45 45 #include <string.h> /* strlen() */ 46 #include <unistd.h> /* ssize_t */47 46 #include "ConvertUTF.h" 48 47 … … 352 351 */ 353 352 Boolean 354 tr_utf8_validate( const char * str, ssize_t max_len, const char ** end )353 tr_utf8_validate( const char * str, int max_len, const char ** end ) 355 354 { 356 355 const UTF8* source = (const UTF8*) str; -
branches/1.5x/libtransmission/ConvertUTF.h
r7664 r7767 5 5 #error only libtransmission should #include this header. 6 6 #endif 7 8 #include <unistd.h> /* ssize_t */9 7 10 8 /* … … 154 152 155 153 /* intended to work the same as g_utf8_validate */ 156 Boolean tr_utf8_validate( const char * str, ssize_t max_len, const char ** end );154 Boolean tr_utf8_validate( const char * str, int max_len, const char ** end ); 157 155 158 156 -
branches/1.5x/libtransmission/bandwidth.c
r7664 r7767 224 224 { 225 225 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 ) 231 231 ++i; 232 232 else { -
branches/1.5x/libtransmission/fdlimit.c
r7734 r7767 612 612 tr_lockFree( gFd->lock ); 613 613 614 tr_free( gFd->openFiles ); 614 615 tr_free( gFd ); 615 616 gFd = NULL; -
branches/1.5x/libtransmission/peer-io.c
r7729 r7767 191 191 assert( tr_isPeerIo( io ) ); 192 192 193 io->hasFinishedConnecting = TRUE; 194 193 195 curlen = EVBUFFER_LENGTH( io->inbuf ); 194 196 howmuch = curlen >= max ? 0 : max - curlen; … … 235 237 } 236 238 237 static ssize_t239 static int 238 240 tr_evbuffer_write( tr_peerIo * io, int fd, size_t howmuch ) 239 241 { 240 242 int e; 241 ssize_t n;243 int n; 242 244 struct evbuffer * buffer = io->outbuf; 243 245 … … 246 248 errno = 0; 247 249 #ifdef WIN32 248 n = send(fd, buffer->buffer, howmuch, 0 );250 n = (int) send(fd, buffer->buffer, howmuch, 0 ); 249 251 #else 250 n = write(fd, buffer->buffer, howmuch );252 n = (int) write(fd, buffer->buffer, howmuch ); 251 253 #endif 252 254 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):"") ); 254 256 255 257 if( n > 0 ) … … 270 272 271 273 assert( tr_isPeerIo( io ) ); 274 275 io->hasFinishedConnecting = TRUE; 272 276 273 277 dbgmsg( io, "libevent says this peer is ready to write" ); … … 353 357 io->socket = socket; 354 358 io->isIncoming = isIncoming != 0; 359 io->hasFinishedConnecting = FALSE; 355 360 io->timeCreated = time( NULL ); 356 361 io->inbuf = evbuffer_new( ); … … 758 763 ***/ 759 764 760 static ssize_t765 static int 761 766 tr_peerIoTryRead( tr_peerIo * io, size_t howmuch ) 762 767 { 763 ssize_t res = 0;768 int res = 0; 764 769 765 770 if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch ))) … … 770 775 e = errno; 771 776 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):"") ); 773 778 774 779 if( EVBUFFER_LENGTH( io->inbuf ) ) … … 780 785 if( res == 0 ) 781 786 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 ) ); 783 788 io->gotError( io, what, io->userData ); 784 789 } … … 788 793 } 789 794 790 static ssize_t795 static int 791 796 tr_peerIoTryWrite( tr_peerIo * io, size_t howmuch ) 792 797 { 793 ssize_t n = 0;798 int n = 0; 794 799 795 800 if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_UP, howmuch ))) … … 806 811 { 807 812 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 ) ); 809 814 io->gotError( io, what, io->userData ); 810 815 } … … 814 819 } 815 820 816 ssize_t821 int 817 822 tr_peerIoFlush( tr_peerIo * io, tr_direction dir, size_t limit ) 818 823 { 819 ssize_t bytesUsed;824 int bytesUsed = 0; 820 825 821 826 assert( tr_isPeerIo( io ) ); 822 827 assert( tr_isDirection( dir ) ); 823 828 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 ); 830 838 return bytesUsed; 831 839 } -
branches/1.5x/libtransmission/peer-io.h
r7729 r7767 65 65 tr_bool fastExtensionSupported; 66 66 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 67 72 int magicNumber; 68 73 … … 72 77 int socket; 73 78 74 ssize_trefCount;79 int refCount; 75 80 76 81 uint8_t peerId[SHA_DIGEST_LENGTH]; … … 356 361 tr_bool isEnabled ); 357 362 358 ssize_ttr_peerIoFlush( tr_peerIo * io,363 int tr_peerIoFlush( tr_peerIo * io, 359 364 tr_direction dir, 360 365 size_t byteLimit ); -
branches/1.5x/libtransmission/peer-mgr.c
r7741 r7767 1984 1984 ***/ 1985 1985 1986 static int 1987 shouldPeerBeClosed( const Torrent * t, 1988 const tr_peer * peer, 1989 int peerCount ) 1986 typedef enum 1987 { 1988 TR_CAN_KEEP, 1989 TR_CAN_CLOSE, 1990 TR_MUST_CLOSE, 1991 } 1992 tr_close_type_t; 1993 1994 static tr_close_type_t 1995 shouldPeerBeClosed( const Torrent * t, 1996 const tr_peer * peer, 1997 int peerCount ) 1990 1998 { 1991 1999 const tr_torrent * tor = t->tor; … … 1998 2006 tordbg( t, "purging peer %s because its doPurge flag is set", 1999 2007 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 2000 return TR UE;2008 return TR_MUST_CLOSE; 2001 2009 } 2002 2010 … … 2021 2029 tordbg( t, "purging peer %s because we're both seeds", 2022 2030 tr_peerIoAddrStr( &atom->addr, atom->port ) ); 2023 return TR UE;2031 return TR_MUST_CLOSE; 2024 2032 } 2025 2033 } … … 2032 2040 * if we have zero connections, strictness is 0% */ 2033 2041 const float strictness = peerCount >= relaxStrictnessIfFewerThanN 2034 ? 1.02035 : peerCount / (float)relaxStrictnessIfFewerThanN;2042 ? 1.0 2043 : peerCount / (float)relaxStrictnessIfFewerThanN; 2036 2044 const int lo = MIN_UPLOAD_IDLE_SECS; 2037 2045 const int hi = MAX_UPLOAD_IDLE_SECS; … … 2042 2050 tordbg( t, "purging peer %s because it's been %d secs since we shared anything", 2043 2051 tr_peerIoAddrStr( &atom->addr, atom->port ), idleTime ); 2044 return TR UE;2045 } 2046 } 2047 2048 return FALSE;2052 return TR_CAN_CLOSE; 2053 } 2054 } 2055 2056 return TR_CAN_KEEP; 2049 2057 } 2050 2058 2051 2059 static tr_peer ** 2052 getPeersToClose( Torrent * t, int * setmeSize )2060 getPeersToClose( Torrent * t, tr_close_type_t closeType, int * setmeSize ) 2053 2061 { 2054 2062 int i, peerCount, outsize; … … 2059 2067 2060 2068 for( i = outsize = 0; i < peerCount; ++i ) 2061 if( shouldPeerBeClosed( t, peers[i], peerCount ) )2069 if( shouldPeerBeClosed( t, peers[i], peerCount ) == closeType ) 2062 2070 ret[outsize++] = peers[i]; 2063 2071 … … 2187 2195 } 2188 2196 2197 static void 2198 closePeer( 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 2189 2218 static int 2190 2219 reconnectPulse( void * vtorrent ) … … 2210 2239 else 2211 2240 { 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 ); 2240 2285 2241 2286 /* 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 ) 2246 2288 { 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; 2250 2292 2251 2293 tordbg( t, "Starting an OUTGOING connection with %s", … … 2281 2323 2282 2324 /* cleanup */ 2283 tr_free( connections );2284 2325 tr_free( candidates ); 2326 tr_free( mustClose ); 2327 tr_free( canClose ); 2285 2328 } 2286 2329 -
branches/1.5x/libtransmission/rpc-server.c
r7722 r7767 177 177 EVBUFFER_DATA( json ), 178 178 EVBUFFER_LENGTH( json ), 179 NULL );179 NULL, NULL ); 180 180 181 181 tr_releaseBuffer( json ); … … 375 375 } 376 376 377 struct rpc_response_data 378 { 379 struct evhttp_request * req; 380 struct tr_rpc_server * server; 381 }; 382 383 static void 384 rpc_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 377 402 static void 378 403 handle_rpc( struct evhttp_request * req, 379 404 struct tr_rpc_server * server ) 380 405 { 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 383 411 if( req->type == EVHTTP_REQ_GET ) 384 412 { 385 413 const char * q; 386 414 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 ); 388 416 } 389 417 else if( req->type == EVHTTP_REQ_POST ) … … 392 420 EVBUFFER_DATA( req->input_buffer ), 393 421 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 410 425 } 411 426 -
branches/1.5x/libtransmission/rpcimpl.c
r7733 r7767 16 16 #include <string.h> /* strcmp */ 17 17 18 #include <event.h> /* evbuffer */ 19 18 20 #include "transmission.h" 19 21 #include "bencode.h" … … 21 23 #include "json.h" 22 24 #include "session.h" 25 #include "stats.h" 23 26 #include "torrent.h" 24 27 #include "utils.h" 28 #include "web.h" 25 29 26 30 #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 27 46 28 47 /*** … … 42 61 43 62 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 */ 72 struct 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 81 static void 82 tr_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 ); 44 98 } 45 99 … … 100 154 101 155 static const char* 102 torrentStart( tr_session * session, 103 tr_benc * args_in, 104 tr_benc * args_out UNUSED ) 156 torrentStart( tr_session * session, 157 tr_benc * args_in, 158 tr_benc * args_out UNUSED, 159 struct tr_rpc_idle_data * idle_data ) 105 160 { 106 161 int i, torrentCount; 107 162 tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount ); 163 164 assert( idle_data == NULL ); 108 165 109 166 for( i = 0; i < torrentCount; ++i ) … … 118 175 119 176 static const char* 120 torrentStop( tr_session * session, 121 tr_benc * args_in, 122 tr_benc * args_out UNUSED ) 177 torrentStop( tr_session * session, 178 tr_benc * args_in, 179 tr_benc * args_out UNUSED, 180 struct tr_rpc_idle_data * idle_data ) 123 181 { 124 182 int i, torrentCount; 125 183 tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount ); 184 185 assert( idle_data == NULL ); 126 186 127 187 for( i = 0; i < torrentCount; ++i ) … … 136 196 137 197 static const char* 138 torrentRemove( tr_session * session, 139 tr_benc * args_in, 140 tr_benc * args_out UNUSED ) 198 torrentRemove( tr_session * session, 199 tr_benc * args_in, 200 tr_benc * args_out UNUSED, 201 struct tr_rpc_idle_data * idle_data ) 141 202 { 142 203 int i; 143 204 int torrentCount; 144 205 tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount ); 206 207 assert( idle_data == NULL ); 145 208 146 209 for( i=0; i<torrentCount; ++i ) … … 160 223 161 224 static const char* 162 torrentVerify( tr_session * session, 163 tr_benc * args_in, 164 tr_benc * args_out UNUSED ) 225 torrentVerify( tr_session * session, 226 tr_benc * args_in, 227 tr_benc * args_out UNUSED, 228 struct tr_rpc_idle_data * idle_data ) 165 229 { 166 230 int i, torrentCount; 167 231 tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount ); 232 233 assert( idle_data == NULL ); 168 234 169 235 for( i = 0; i < torrentCount; ++i ) … … 436 502 437 503 static const char* 438 torrentGet( tr_session * session, 439 tr_benc * args_in, 440 tr_benc * args_out ) 504 torrentGet( tr_session * session, 505 tr_benc * args_in, 506 tr_benc * args_out, 507 struct tr_rpc_idle_data * idle_data ) 441 508 { 442 509 int i, torrentCount; 443 510 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 ); 446 512 tr_benc * fields; 447 513 char * msg = NULL; 514 515 assert( idle_data == NULL ); 448 516 449 517 if( !tr_bencDictFindList( args_in, "fields", &fields ) ) … … 523 591 524 592 static const char* 525 torrentSet( tr_session * session, 526 tr_benc * args_in, 527 tr_benc * args_out UNUSED ) 593 torrentSet( tr_session * session, 594 tr_benc * args_in, 595 tr_benc * args_out UNUSED, 596 struct tr_rpc_idle_data * idle_data ) 528 597 { 529 598 int i, torrentCount; 530 599 tr_torrent ** torrents = getTorrents( session, args_in, &torrentCount ); 600 601 assert( idle_data == NULL ); 531 602 532 603 for( i = 0; i < torrentCount; ++i ) … … 571 642 ***/ 572 643 644 static void 645 addTorrentImpl( 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 677 struct add_torrent_idle_data 678 { 679 struct tr_rpc_idle_data * data; 680 tr_ctor * ctor; 681 }; 682 683 static void 684 gotMetadataFromURL( 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 711 static tr_bool 712 isCurlURL( 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 573 722 static const char* 574 torrentAdd( tr_session * session, 575 tr_benc * args_in, 576 tr_benc * args_out ) 723 torrentAdd( tr_session * session, 724 tr_benc * args_in, 725 tr_benc * args_out UNUSED, 726 struct tr_rpc_idle_data * idle_data ) 577 727 { 578 728 const char * filename = NULL; 579 729 const char * metainfo_base64 = NULL; 730 731 assert( idle_data != NULL ); 580 732 581 733 tr_bencDictFindStr( args_in, "filename", &filename ); … … 586 738 { 587 739 int64_t i; 588 int err = 0;589 740 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 ); 605 742 606 743 /* set the optional arguments */ … … 612 749 tr_ctorSetPeerLimit( ctor, TR_FORCE, i ); 613 750 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 ) ) 618 754 { 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 ); 628 759 } 629 else if( err == TR_EDUPLICATE )760 else 630 761 { 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 ); 632 771 } 633 else if( err == TR_EINVALID ) 634 { 635 return "invalid or corrupt torrent file"; 636 } 772 637 773 } 638 774 … … 645 781 646 782 static const char* 647 sessionSet( tr_session * session, 648 tr_benc * args_in, 649 tr_benc * args_out UNUSED ) 783 sessionSet( tr_session * session, 784 tr_benc * args_in, 785 tr_benc * args_out UNUSED, 786 struct tr_rpc_idle_data * idle_data ) 650 787 { 651 788 int64_t i; 652 789 const char * str; 790 791 assert( idle_data == NULL ); 653 792 654 793 if( tr_bencDictFindStr( args_in, "download-dir", &str ) ) … … 686 825 687 826 static const char* 688 sessionStats( tr_session * session, 689 tr_benc * args_in UNUSED, 690 tr_benc * args_out ) 827 sessionStats( tr_session * session, 828 tr_benc * args_in UNUSED, 829 tr_benc * args_out, 830 struct tr_rpc_idle_data * idle_data ) 691 831 { 692 832 int running = 0; 693 833 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 }; 694 837 tr_torrent * tor = NULL; 838 839 assert( idle_data == NULL ); 695 840 696 841 while(( tor = tr_torrentNext( session, tor ))) { … … 699 844 ++running; 700 845 } 846 847 tr_sessionGetStats( session, ¤tStats ); 848 tr_sessionGetCumulativeStats( session, &cumulativeStats ); 701 849 702 850 tr_bencDictAddInt( args_out, "activeTorrentCount", running ); … … 705 853 tr_bencDictAddInt( args_out, "torrentCount", total ); 706 854 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 707 870 return NULL; 708 871 } 709 872 710 873 static const char* 711 sessionGet( tr_session * session, 712 tr_benc * args_in UNUSED, 713 tr_benc * args_out ) 874 sessionGet( tr_session * session, 875 tr_benc * args_in UNUSED, 876 tr_benc * args_out, 877 struct tr_rpc_idle_data * idle_data ) 714 878 { 715 879 const char * str; 716 880 tr_benc * d = args_out; 881 882 assert( idle_data == NULL ); 717 883 718 884 tr_bencDictAddStr( d, "download-dir", tr_sessionGetDownloadDir( session ) ); … … 742 908 ***/ 743 909 744 typedef const char* ( handler )( tr_session*, tr_benc*, tr_benc* );910 typedef const char* ( *handler )( tr_session*, tr_benc*, tr_benc*, struct tr_rpc_idle_data * ); 745 911 746 912 static struct method 747 913 { 748 914 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 } 918 methods[] = 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 } 761 930 }; 762 931 763 932 static void 764 request_exec( tr_session * session, 765 tr_benc * request, 766 struct evbuffer * response_buf ) 767 { 768 int64_t i; 933 noop_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 940 static void 941 request_exec( tr_session * session, 942 tr_benc * request, 943 tr_rpc_response_func callback, 944 void * callback_user_data ) 945 { 946 int i; 769 947 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" ); 773 949 const char * result = NULL; 774 950 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; 778 953 779 954 /* parse the request */ 780 955 if( !tr_bencDictFindStr( request, "method", &str ) ) 781 956 result = "no method name"; 782 else 783 { 957 else { 784 958 const int n = TR_N_ELEMENTS( methods ); 785 959 for( i = 0; i < n; ++i ) 786 960 if( !strcmp( str, methods[i].name ) ) 787 961 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 } 802 1022 } 803 1023 804 1024 void 805 tr_rpc_request_exec_json( tr_session * session, 806 const void * request_json, 807 int request_len, 808 struct evbuffer * response ) 1025 tr_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 ) 809 1030 { 810 1031 tr_benc top; … … 815 1036 816 1037 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 ); 818 1039 819 1040 if( have_content ) … … 854 1075 */ 855 1076 void 856 tr_rpc_parse_list_str( tr_benc *setme,857 const char * str_in,858 size_tlen )1077 tr_rpc_parse_list_str( tr_benc * setme, 1078 const char * str_in, 1079 int len ) 859 1080 860 1081 { … … 901 1122 902 1123 void 903 tr_rpc_request_exec_uri( tr_session * session, 904 const void * request_uri, 905 int request_len, 906 struct evbuffer * response ) 1124 tr_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 ) 907 1129 { 908 1130 tr_benc top, * args; … … 934 1156 } 935 1157 936 request_exec( session, &top, response);1158 request_exec( session, &top, callback, callback_user_data ); 937 1159 938 1160 /* cleanup */ -
branches/1.5x/libtransmission/rpcimpl.h
r7664 r7767 18 18 ***/ 19 19 20 struct evbuffer;21 20 struct tr_benc; 22 21 22 typedef void( *tr_rpc_response_func )( tr_session * session, 23 const char * response, 24 size_t response_len, 25 void * user_data ); 23 26 /* 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 ); 27 void 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 ); 28 32 29 33 /* 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 ); 34 void 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 ); 34 39 35 40 void tr_rpc_parse_list_str( struct tr_benc * setme, 36 41 const char * list_str, 37 size_tlist_str_len );42 int list_str_len ); 38 43 39 44 -
branches/1.5x/libtransmission/utils-test.c
r7664 r7767 2 2 #include <string.h> /* strcmp */ 3 3 #include "transmission.h" 4 #include <unistd.h> /* ssize_t */5 4 #include "ConvertUTF.h" /* tr_utf8_validate*/ 6 5 #include "platform.h" -
branches/1.5x/libtransmission/utils.c
r7664 r7767 638 638 639 639 char* 640 tr_strndup( const void * in, 641 int len ) 640 tr_strndup( const void * in, int len ) 642 641 { 643 642 char * out = NULL; … … 1327 1326 1328 1327 char* 1329 tr_utf8clean( const char * str, ssize_t max_len, tr_bool * err )1328 tr_utf8clean( const char * str, int max_len, tr_bool * err ) 1330 1329 { 1331 1330 const char zero = '\0'; … … 1338 1337 1339 1338 if( max_len < 0 ) 1340 max_len = ( ssize_t) strlen( str );1339 max_len = (int) strlen( str ); 1341 1340 1342 1341 while( !tr_utf8_validate ( str, max_len, &end ) ) 1343 1342 { 1344 const ssize_t good_len = end - str;1343 const int good_len = end - str; 1345 1344 1346 1345 evbuffer_add( buf, str, good_len ); -
branches/1.5x/libtransmission/utils.h
r7664 r7767 239 239 240 240 char* tr_utf8clean( const char * str, 241 ssize_tmax_len,241 int max_len, 242 242 tr_bool * err ); 243 243
Note: See TracChangeset
for help on using the changeset viewer.