2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: session.c 12545 2011-07-13 03:23:37Z jordan $
14 #include <errno.h> /* ENOENT */
16 #include <string.h> /* memcpy */
19 #include <sys/types.h> /* stat(), umask() */
20 #include <sys/stat.h> /* stat(), umask() */
21 #include <unistd.h> /* stat */
22 #include <dirent.h> /* opendir */
24 #include <event2/dns.h> /* evdns_base_free() */
25 #include <event2/event.h>
27 //#define TR_SHOW_DEPRECATED
28 #include "transmission.h"
29 #include "announcer.h"
30 #include "bandwidth.h"
32 #include "blocklist.h"
40 #include "platform.h" /* tr_lock, tr_getTorrentDir(), tr_getFreeSpace() */
41 #include "port-forwarding.h"
42 #include "rpc-server.h"
46 #include "tr-dht.h" /* tr_dhtUpkeep() */
59 DEFAULT_CACHE_SIZE_MB
= 2,
60 DEFAULT_PREFETCH_ENABLED
= false,
62 DEFAULT_CACHE_SIZE_MB
= 4,
63 DEFAULT_PREFETCH_ENABLED
= true,
65 SAVE_INTERVAL_SECS
= 360
69 #define dbgmsg( ... ) \
71 if( tr_deepLoggingIsActive( ) ) \
72 tr_deepLog( __FILE__, __LINE__, NULL, __VA_ARGS__ ); \
76 getRandomPort( tr_session
* s
)
78 return tr_cryptoWeakRandInt( s
->randomPortHigh
- s
->randomPortLow
+ 1) + s
->randomPortLow
;
81 /* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
82 characters, where x is the major version number, y is the
83 minor version number, z is the maintenance number, and b
84 designates beta (Azureus-style) */
86 tr_peerIdInit( uint8_t * buf
)
91 const char * pool
= "0123456789abcdefghijklmnopqrstuvwxyz";
94 memcpy( buf
, PEERID_PREFIX
, 8 );
96 tr_cryptoRandBuf( buf
+8, 11 );
97 for( i
=8; i
<19; ++i
) {
103 val
= total
% base
? base
- ( total
% base
) : 0;
113 tr_sessionGetEncryption( tr_session
* session
)
117 return session
->encryptionMode
;
121 tr_sessionSetEncryption( tr_session
* session
,
122 tr_encryption_mode mode
)
125 assert( mode
== TR_ENCRYPTION_PREFERRED
126 || mode
== TR_ENCRYPTION_REQUIRED
127 || mode
== TR_CLEAR_PREFERRED
);
129 session
->encryptionMode
= mode
;
145 close_bindinfo( struct tr_bindinfo
* b
)
147 if( ( b
!= NULL
) && ( b
->socket
>=0 ) )
151 tr_netCloseSocket( b
->socket
);
156 close_incoming_peer_port( tr_session
* session
)
158 close_bindinfo( session
->public_ipv4
);
159 close_bindinfo( session
->public_ipv6
);
163 free_incoming_peer_port( tr_session
* session
)
165 close_bindinfo( session
->public_ipv4
);
166 tr_free( session
->public_ipv4
);
167 session
->public_ipv4
= NULL
;
169 close_bindinfo( session
->public_ipv6
);
170 tr_free( session
->public_ipv6
);
171 session
->public_ipv6
= NULL
;
175 accept_incoming_peer( int fd
, short what UNUSED
, void * vsession
)
179 tr_address clientAddr
;
180 tr_session
* session
= vsession
;
182 clientSocket
= tr_netAccept( session
, fd
, &clientAddr
, &clientPort
);
183 if( clientSocket
> 0 ) {
184 tr_deepLog( __FILE__
, __LINE__
, NULL
, "new incoming connection %d (%s)",
185 clientSocket
, tr_peerIoAddrStr( &clientAddr
, clientPort
) );
186 tr_peerMgrAddIncoming( session
->peerMgr
, &clientAddr
, clientPort
,
187 clientSocket
, NULL
);
192 open_incoming_peer_port( tr_session
* session
)
194 struct tr_bindinfo
* b
;
196 /* bind an ipv4 port to listen for incoming peers... */
197 b
= session
->public_ipv4
;
198 b
->socket
= tr_netBindTCP( &b
->addr
, session
->private_peer_port
, false );
199 if( b
->socket
>= 0 ) {
200 b
->ev
= event_new( session
->event_base
, b
->socket
, EV_READ
| EV_PERSIST
, accept_incoming_peer
, session
);
201 event_add( b
->ev
, NULL
);
204 /* and do the exact same thing for ipv6, if it's supported... */
205 if( tr_net_hasIPv6( session
->private_peer_port
) ) {
206 b
= session
->public_ipv6
;
207 b
->socket
= tr_netBindTCP( &b
->addr
, session
->private_peer_port
, false );
208 if( b
->socket
>= 0 ) {
209 b
->ev
= event_new( session
->event_base
, b
->socket
, EV_READ
| EV_PERSIST
, accept_incoming_peer
, session
);
210 event_add( b
->ev
, NULL
);
216 tr_sessionGetPublicAddress( const tr_session
* session
, int tr_af_type
, bool * is_default_value
)
218 const char * default_value
;
219 const struct tr_bindinfo
* bindinfo
;
224 bindinfo
= session
->public_ipv4
;
225 default_value
= TR_DEFAULT_BIND_ADDRESS_IPV4
;
229 bindinfo
= session
->public_ipv6
;
230 default_value
= TR_DEFAULT_BIND_ADDRESS_IPV6
;
239 if( is_default_value
&& bindinfo
)
240 *is_default_value
= !tr_strcmp0( default_value
, tr_address_to_string( &bindinfo
->addr
) );
242 return bindinfo
? &bindinfo
->addr
: NULL
;
249 #ifdef TR_LIGHTWEIGHT
250 #define TR_DEFAULT_ENCRYPTION TR_CLEAR_PREFERRED
252 #define TR_DEFAULT_ENCRYPTION TR_ENCRYPTION_PREFERRED
256 parse_tos( const char *str
)
261 if( !evutil_ascii_strcasecmp( str
, "" ) )
263 if( !evutil_ascii_strcasecmp( str
, "default" ) )
266 if( !evutil_ascii_strcasecmp( str
, "lowcost" ) )
268 if( !evutil_ascii_strcasecmp( str
, "mincost" ) )
271 if( !evutil_ascii_strcasecmp( str
, "throughput" ) )
273 if( !evutil_ascii_strcasecmp( str
, "reliability" ) )
275 if( !evutil_ascii_strcasecmp( str
, "lowdelay" ) )
278 value
= strtol( str
, &p
, 0 );
279 if( !p
|| ( p
== str
) )
286 format_tos(int value
)
290 case 0: return "default";
291 case 0x10: return "lowcost";
292 case 0x08: return "throughput";
293 case 0x04: return "reliability";
294 case 0x02: return "lowdelay";
296 snprintf(buf
, 8, "%d", value
);
302 tr_sessionGetDefaultSettings( tr_benc
* d
)
304 assert( tr_bencIsDict( d
) );
306 tr_bencDictReserve( d
, 60 );
307 tr_bencDictAddBool( d
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, false );
308 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BLOCKLIST_URL
, "http://www.example.com/blocklist" );
309 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MAX_CACHE_SIZE_MB
, DEFAULT_CACHE_SIZE_MB
);
310 tr_bencDictAddBool( d
, TR_PREFS_KEY_DHT_ENABLED
, true );
311 tr_bencDictAddBool( d
, TR_PREFS_KEY_UTP_ENABLED
, true );
312 tr_bencDictAddBool( d
, TR_PREFS_KEY_LPD_ENABLED
, false );
313 tr_bencDictAddStr ( d
, TR_PREFS_KEY_DOWNLOAD_DIR
, tr_getDefaultDownloadDir( ) );
314 tr_bencDictAddInt ( d
, TR_PREFS_KEY_DSPEED_KBps
, 100 );
315 tr_bencDictAddBool( d
, TR_PREFS_KEY_DSPEED_ENABLED
, false );
316 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ENCRYPTION
, TR_DEFAULT_ENCRYPTION
);
317 tr_bencDictAddInt ( d
, TR_PREFS_KEY_IDLE_LIMIT
, 30 );
318 tr_bencDictAddBool( d
, TR_PREFS_KEY_IDLE_LIMIT_ENABLED
, false );
319 tr_bencDictAddStr ( d
, TR_PREFS_KEY_INCOMPLETE_DIR
, tr_getDefaultDownloadDir( ) );
320 tr_bencDictAddBool( d
, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED
, false );
321 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MSGLEVEL
, TR_MSG_INF
);
322 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR
) );
323 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR
) );
324 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT
, atoi( TR_DEFAULT_PEER_PORT_STR
) );
325 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, false );
326 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, 49152 );
327 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, 65535 );
328 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_SOCKET_TOS
, TR_DEFAULT_PEER_SOCKET_TOS_STR
);
329 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEX_ENABLED
, true );
330 tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, true );
331 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREALLOCATION
, TR_PREALLOCATE_SPARSE
);
332 tr_bencDictAddBool( d
, TR_PREFS_KEY_PREFETCH_ENABLED
, DEFAULT_PREFETCH_ENABLED
);
333 tr_bencDictAddReal( d
, TR_PREFS_KEY_RATIO
, 2.0 );
334 tr_bencDictAddBool( d
, TR_PREFS_KEY_RATIO_ENABLED
, false );
335 tr_bencDictAddBool( d
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, true );
336 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_AUTH_REQUIRED
, false );
337 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_BIND_ADDRESS
, "0.0.0.0" );
338 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_ENABLED
, false );
339 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_PASSWORD
, "" );
340 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_USERNAME
, "" );
341 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_WHITELIST
, TR_DEFAULT_RPC_WHITELIST
);
342 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_WHITELIST_ENABLED
, true );
343 tr_bencDictAddInt ( d
, TR_PREFS_KEY_RPC_PORT
, atoi( TR_DEFAULT_RPC_PORT_STR
) );
344 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_URL
, TR_DEFAULT_RPC_URL_STR
);
345 tr_bencDictAddStr ( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, "" );
346 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, false );
347 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, false );
348 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, 50 ); /* half the regular */
349 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, 50 ); /* half the regular */
350 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, 540 ); /* 9am */
351 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, false );
352 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, 1020 ); /* 5pm */
353 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, TR_SCHED_ALL
);
354 tr_bencDictAddInt ( d
, TR_PREFS_KEY_USPEED_KBps
, 100 );
355 tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, false );
356 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UMASK
, 022 );
357 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, 14 );
358 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, TR_DEFAULT_BIND_ADDRESS_IPV4
);
359 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, TR_DEFAULT_BIND_ADDRESS_IPV6
);
360 tr_bencDictAddBool( d
, TR_PREFS_KEY_START
, true );
361 tr_bencDictAddBool( d
, TR_PREFS_KEY_TRASH_ORIGINAL
, false );
365 tr_sessionGetSettings( tr_session
* s
, struct tr_benc
* d
)
367 assert( tr_bencIsDict( d
) );
369 tr_bencDictReserve( d
, 60 );
370 tr_bencDictAddBool( d
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, tr_blocklistIsEnabled( s
) );
371 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BLOCKLIST_URL
, tr_blocklistGetURL( s
) );
372 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MAX_CACHE_SIZE_MB
, tr_sessionGetCacheLimit_MB( s
) );
373 tr_bencDictAddBool( d
, TR_PREFS_KEY_DHT_ENABLED
, s
->isDHTEnabled
);
374 tr_bencDictAddBool( d
, TR_PREFS_KEY_UTP_ENABLED
, s
->isUTPEnabled
);
375 tr_bencDictAddBool( d
, TR_PREFS_KEY_LPD_ENABLED
, s
->isLPDEnabled
);
376 tr_bencDictAddStr ( d
, TR_PREFS_KEY_DOWNLOAD_DIR
, s
->downloadDir
);
377 tr_bencDictAddInt ( d
, TR_PREFS_KEY_DSPEED_KBps
, tr_sessionGetSpeedLimit_KBps( s
, TR_DOWN
) );
378 tr_bencDictAddBool( d
, TR_PREFS_KEY_DSPEED_ENABLED
, tr_sessionIsSpeedLimited( s
, TR_DOWN
) );
379 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ENCRYPTION
, s
->encryptionMode
);
380 tr_bencDictAddInt ( d
, TR_PREFS_KEY_IDLE_LIMIT
, tr_sessionGetIdleLimit( s
) );
381 tr_bencDictAddBool( d
, TR_PREFS_KEY_IDLE_LIMIT_ENABLED
, tr_sessionIsIdleLimited( s
) );
382 tr_bencDictAddStr ( d
, TR_PREFS_KEY_INCOMPLETE_DIR
, tr_sessionGetIncompleteDir( s
) );
383 tr_bencDictAddBool( d
, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED
, tr_sessionIsIncompleteDirEnabled( s
) );
384 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MSGLEVEL
, tr_getMessageLevel( ) );
385 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, s
->peerLimit
);
386 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, s
->peerLimitPerTorrent
);
387 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT
, tr_sessionGetPeerPort( s
) );
388 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, s
->isPortRandom
);
389 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, s
->randomPortLow
);
390 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, s
->randomPortHigh
);
391 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_SOCKET_TOS
, format_tos(s
->peerSocketTOS
) );
392 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM
, s
->peer_congestion_algorithm
);
393 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEX_ENABLED
, s
->isPexEnabled
);
394 tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, tr_sessionIsPortForwardingEnabled( s
) );
395 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREALLOCATION
, s
->preallocationMode
);
396 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREFETCH_ENABLED
, s
->isPrefetchEnabled
);
397 tr_bencDictAddReal( d
, TR_PREFS_KEY_RATIO
, s
->desiredRatio
);
398 tr_bencDictAddBool( d
, TR_PREFS_KEY_RATIO_ENABLED
, s
->isRatioLimited
);
399 tr_bencDictAddBool( d
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, tr_sessionIsIncompleteFileNamingEnabled( s
) );
400 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_AUTH_REQUIRED
, tr_sessionIsRPCPasswordEnabled( s
) );
401 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_BIND_ADDRESS
, tr_sessionGetRPCBindAddress( s
) );
402 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_ENABLED
, tr_sessionIsRPCEnabled( s
) );
403 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_PASSWORD
, tr_sessionGetRPCPassword( s
) );
404 tr_bencDictAddInt ( d
, TR_PREFS_KEY_RPC_PORT
, tr_sessionGetRPCPort( s
) );
405 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_URL
, tr_sessionGetRPCUrl( s
) );
406 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_USERNAME
, tr_sessionGetRPCUsername( s
) );
407 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_WHITELIST
, tr_sessionGetRPCWhitelist( s
) );
408 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_WHITELIST_ENABLED
, tr_sessionGetRPCWhitelistEnabled( s
) );
409 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, tr_sessionIsTorrentDoneScriptEnabled( s
) );
410 tr_bencDictAddStr ( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, tr_sessionGetTorrentDoneScript( s
) );
411 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, tr_sessionUsesAltSpeed( s
) );
412 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, tr_sessionGetAltSpeed_KBps( s
, TR_UP
) );
413 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, tr_sessionGetAltSpeed_KBps( s
, TR_DOWN
) );
414 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, tr_sessionGetAltSpeedBegin( s
) );
415 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, tr_sessionUsesAltSpeedTime( s
) );
416 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, tr_sessionGetAltSpeedEnd( s
) );
417 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, tr_sessionGetAltSpeedDay( s
) );
418 tr_bencDictAddInt ( d
, TR_PREFS_KEY_USPEED_KBps
, tr_sessionGetSpeedLimit_KBps( s
, TR_UP
) );
419 tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, tr_sessionIsSpeedLimited( s
, TR_UP
) );
420 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UMASK
, s
->umask
);
421 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, s
->uploadSlotsPerTorrent
);
422 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, tr_address_to_string( &s
->public_ipv4
->addr
) );
423 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, tr_address_to_string( &s
->public_ipv6
->addr
) );
424 tr_bencDictAddBool( d
, TR_PREFS_KEY_START
, !tr_sessionGetPaused( s
) );
425 tr_bencDictAddBool( d
, TR_PREFS_KEY_TRASH_ORIGINAL
, tr_sessionGetDeleteSource( s
) );
429 tr_sessionLoadSettings( tr_benc
* d
, const char * configDir
, const char * appName
)
433 tr_benc fileSettings
;
434 tr_benc sessionDefaults
;
436 bool success
= false;
438 assert( tr_bencIsDict( d
) );
440 /* initializing the defaults: caller may have passed in some app-level defaults.
441 * preserve those and use the session defaults to fill in any missing gaps. */
442 tr_bencInitDict( &sessionDefaults
, 0 );
443 tr_sessionGetDefaultSettings( &sessionDefaults
);
444 tr_bencMergeDicts( &sessionDefaults
, d
);
445 tmp
= *d
; *d
= sessionDefaults
; sessionDefaults
= tmp
;
447 /* if caller didn't specify a config dir, use the default */
448 if( !configDir
|| !*configDir
)
449 configDir
= tr_getDefaultConfigDir( appName
);
451 /* file settings override the defaults */
452 filename
= tr_buildPath( configDir
, "settings.json", NULL
);
453 err
= tr_bencLoadFile( &fileSettings
, TR_FMT_JSON
, filename
);
455 tr_bencMergeDicts( d
, &fileSettings
);
456 tr_bencFree( &fileSettings
);
460 tr_bencFree( &sessionDefaults
);
462 success
= (err
==0) || (err
==ENOENT
);
467 tr_sessionSaveSettings( tr_session
* session
,
468 const char * configDir
,
469 const tr_benc
* clientSettings
)
472 char * filename
= tr_buildPath( configDir
, "settings.json", NULL
);
474 assert( tr_bencIsDict( clientSettings
) );
476 tr_bencInitDict( &settings
, 0 );
478 /* the existing file settings are the fallback values */
480 tr_benc fileSettings
;
481 const int err
= tr_bencLoadFile( &fileSettings
, TR_FMT_JSON
, filename
);
484 tr_bencMergeDicts( &settings
, &fileSettings
);
485 tr_bencFree( &fileSettings
);
489 /* the client's settings override the file settings */
490 tr_bencMergeDicts( &settings
, clientSettings
);
492 /* the session's true values override the file & client settings */
494 tr_benc sessionSettings
;
495 tr_bencInitDict( &sessionSettings
, 0 );
496 tr_sessionGetSettings( session
, &sessionSettings
);
497 tr_bencMergeDicts( &settings
, &sessionSettings
);
498 tr_bencFree( &sessionSettings
);
501 /* save the result */
502 tr_bencToFile( &settings
, TR_FMT_JSON
, filename
);
506 tr_bencFree( &settings
);
514 * Periodically save the .resume files of any torrents whose
515 * status has recently changed. This prevents loss of metadata
516 * in the case of a crash, unclean shutdown, clumsy user, etc.
519 onSaveTimer( int foo UNUSED
, short bar UNUSED
, void * vsession
)
521 tr_torrent
* tor
= NULL
;
522 tr_session
* session
= vsession
;
524 if( tr_cacheFlushDone( session
->cache
) )
525 tr_err( "Error while flushing completed pieces from cache" );
527 while(( tor
= tr_torrentNext( session
, tor
)))
528 tr_torrentSave( tor
);
530 tr_statsSaveDirty( session
);
532 tr_timerAdd( session
->saveTimer
, SAVE_INTERVAL_SECS
, 0 );
539 static void tr_sessionInitImpl( void * );
543 tr_session
* session
;
544 const char * configDir
;
546 bool messageQueuingEnabled
;
547 tr_benc
* clientSettings
;
551 tr_sessionInit( const char * tag
,
552 const char * configDir
,
553 bool messageQueuingEnabled
,
554 tr_benc
* clientSettings
)
557 tr_session
* session
;
558 struct init_data data
;
560 assert( tr_bencIsDict( clientSettings
) );
562 tr_timeUpdate( time( NULL
) );
564 /* initialize the bare skeleton of the session object */
565 session
= tr_new0( tr_session
, 1 );
566 session
->udp_socket
= -1;
567 session
->udp6_socket
= -1;
568 session
->lock
= tr_lockNew( );
569 session
->cache
= tr_cacheNew( 1024*1024*2 );
570 session
->tag
= tr_strdup( tag
);
571 session
->magicNumber
= SESSION_MAGIC_NUMBER
;
572 tr_bandwidthConstruct( &session
->bandwidth
, session
, NULL
);
573 tr_peerIdInit( session
->peer_id
);
574 tr_bencInitList( &session
->removedTorrents
, 0 );
576 /* nice to start logging at the very beginning */
577 if( tr_bencDictFindInt( clientSettings
, TR_PREFS_KEY_MSGLEVEL
, &i
) )
578 tr_setMessageLevel( i
);
580 /* start the libtransmission thread */
581 tr_netInit( ); /* must go before tr_eventInit */
582 tr_eventInit( session
);
583 assert( session
->events
!= NULL
);
585 /* run the rest in the libtransmission thread */
587 data
.session
= session
;
588 data
.configDir
= configDir
;
589 data
.messageQueuingEnabled
= messageQueuingEnabled
;
590 data
.clientSettings
= clientSettings
;
591 tr_runInEventThread( session
, tr_sessionInitImpl
, &data
);
598 static void turtleCheckClock( tr_session
* s
, struct tr_turtle_info
* t
);
601 onNowTimer( int foo UNUSED
, short bar UNUSED
, void * vsession
)
605 const int max
= 999999;
607 tr_torrent
* tor
= NULL
;
608 tr_session
* session
= vsession
;
609 const time_t now
= time( NULL
);
611 assert( tr_isSession( session
) );
612 assert( session
->nowTimer
!= NULL
);
615 *** tr_session things to do once per second
618 tr_timeUpdate( now
);
620 tr_dhtUpkeep( session
);
622 if( session
->turtle
.isClockEnabled
)
623 turtleCheckClock( session
, &session
->turtle
);
625 while(( tor
= tr_torrentNext( session
, tor
))) {
626 if( tor
->isRunning
) {
627 if( tr_torrentIsSeed( tor
) )
628 ++tor
->secondsSeeding
;
630 ++tor
->secondsDownloading
;
638 /* schedule the next timer for right after the next second begins */
639 gettimeofday( &tv
, NULL
);
640 usec
= 1000000 - tv
.tv_usec
;
641 if( usec
> max
) usec
= max
;
642 if( usec
< min
) usec
= min
;
643 tr_timerAdd( session
->nowTimer
, 0, usec
);
644 /* fprintf( stderr, "time %zu sec, %zu microsec\n", (size_t)tr_time(), (size_t)tv.tv_usec ); */
647 static void loadBlocklists( tr_session
* session
);
650 tr_sessionInitImpl( void * vdata
)
653 struct init_data
* data
= vdata
;
654 tr_benc
* clientSettings
= data
->clientSettings
;
655 tr_session
* session
= data
->session
;
657 assert( tr_amInEventThread( session
) );
658 assert( tr_bencIsDict( clientSettings
) );
660 dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p",
661 &session
->bandwidth
);
663 tr_bencInitDict( &settings
, 0 );
664 tr_sessionGetDefaultSettings( &settings
);
665 tr_bencMergeDicts( &settings
, clientSettings
);
667 assert( session
->event_base
!= NULL
);
668 session
->nowTimer
= evtimer_new( session
->event_base
, onNowTimer
, session
);
669 onNowTimer( 0, 0, session
);
672 /* Don't exit when writing on a broken socket */
673 signal( SIGPIPE
, SIG_IGN
);
676 tr_setMessageQueuing( data
->messageQueuingEnabled
);
678 tr_setConfigDir( session
, data
->configDir
);
680 session
->peerMgr
= tr_peerMgrNew( session
);
682 session
->shared
= tr_sharedInit( session
);
689 char * filename
= tr_buildPath( session
->configDir
, "blocklists", NULL
);
690 tr_mkdirp( filename
, 0777 );
692 loadBlocklists( session
);
695 assert( tr_isSession( session
) );
697 session
->saveTimer
= evtimer_new( session
->event_base
, onSaveTimer
, session
);
698 tr_timerAdd( session
->saveTimer
, SAVE_INTERVAL_SECS
, 0 );
700 tr_announcerInit( session
);
702 /* first %s is the application name
703 second %s is the version number */
704 tr_inf( _( "%s %s started" ), TR_NAME
, LONG_VERSION_STRING
);
706 tr_statsInit( session
);
708 tr_webInit( session
);
710 tr_sessionSet( session
, &settings
);
712 tr_udpInit( session
);
714 if( session
->isLPDEnabled
)
715 tr_lpdInit( session
, &session
->public_ipv4
->addr
);
718 tr_bencFree( &settings
);
722 static void turtleBootstrap( tr_session
*, struct tr_turtle_info
* );
723 static void setPeerPort( tr_session
* session
, tr_port port
);
726 sessionSetImpl( void * vdata
)
732 struct tr_bindinfo b
;
733 struct init_data
* data
= vdata
;
734 tr_session
* session
= data
->session
;
735 tr_benc
* settings
= data
->clientSettings
;
736 struct tr_turtle_info
* turtle
= &session
->turtle
;
738 assert( tr_isSession( session
) );
739 assert( tr_bencIsDict( settings
) );
740 assert( tr_amInEventThread( session
) );
742 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_MSGLEVEL
, &i
) )
743 tr_setMessageLevel( i
);
745 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_UMASK
, &i
) ) {
746 session
->umask
= (mode_t
)i
;
747 umask( session
->umask
);
751 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_MAX_CACHE_SIZE_MB
, &i
) )
752 tr_sessionSetCacheLimit_MB( session
, i
);
753 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, &i
) )
754 tr_sessionSetPeerLimitPerTorrent( session
, i
);
755 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PEX_ENABLED
, &boolVal
) )
756 tr_sessionSetPexEnabled( session
, boolVal
);
757 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_DHT_ENABLED
, &boolVal
) )
758 tr_sessionSetDHTEnabled( session
, boolVal
);
759 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_UTP_ENABLED
, &boolVal
) )
760 tr_sessionSetUTPEnabled( session
, boolVal
);
761 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_LPD_ENABLED
, &boolVal
) )
762 tr_sessionSetLPDEnabled( session
, boolVal
);
763 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ENCRYPTION
, &i
) )
764 tr_sessionSetEncryption( session
, i
);
765 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_PEER_SOCKET_TOS
, &str
) )
766 session
->peerSocketTOS
= parse_tos( str
);
767 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM
, &str
) )
768 session
->peer_congestion_algorithm
= tr_strdup(str
);
770 session
->peer_congestion_algorithm
= tr_strdup("");
771 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, &boolVal
) )
772 tr_blocklistSetEnabled( session
, boolVal
);
773 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_BLOCKLIST_URL
, &str
) )
774 tr_blocklistSetURL( session
, str
);
775 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_START
, &boolVal
) )
776 tr_sessionSetPaused( session
, !boolVal
);
777 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_TRASH_ORIGINAL
, &boolVal
) )
778 tr_sessionSetDeleteSource( session
, boolVal
);
780 /* files and directories */
781 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PREFETCH_ENABLED
, &boolVal
) )
782 session
->isPrefetchEnabled
= boolVal
;
783 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PREALLOCATION
, &i
) )
784 session
->preallocationMode
= i
;
785 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_DOWNLOAD_DIR
, &str
) )
786 tr_sessionSetDownloadDir( session
, str
);
787 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_INCOMPLETE_DIR
, &str
) )
788 tr_sessionSetIncompleteDir( session
, str
);
789 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED
, &boolVal
) )
790 tr_sessionSetIncompleteDirEnabled( session
, boolVal
);
791 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, &boolVal
) )
792 tr_sessionSetIncompleteFileNamingEnabled( session
, boolVal
);
795 if( session
->rpcServer
!= NULL
) /* close the old one */
796 tr_rpcClose( &session
->rpcServer
);
797 session
->rpcServer
= tr_rpcInit( session
, settings
);
799 /* public addresses */
801 free_incoming_peer_port( session
);
803 str
= TR_PREFS_KEY_BIND_ADDRESS_IPV4
;
804 tr_bencDictFindStr( settings
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, &str
);
805 if( !tr_address_from_string( &b
.addr
, str
) || ( b
.addr
.type
!= TR_AF_INET
) )
806 b
.addr
= tr_inaddr_any
;
808 session
->public_ipv4
= tr_memdup( &b
, sizeof( struct tr_bindinfo
) );
810 str
= TR_PREFS_KEY_BIND_ADDRESS_IPV6
;
811 tr_bencDictFindStr( settings
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, &str
);
812 if( !tr_address_from_string( &b
.addr
, str
) || ( b
.addr
.type
!= TR_AF_INET6
) )
813 b
.addr
= tr_in6addr_any
;
815 session
->public_ipv6
= tr_memdup( &b
, sizeof( struct tr_bindinfo
) );
817 /* incoming peer port */
818 if( tr_bencDictFindInt ( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, &i
) )
819 session
->randomPortLow
= i
;
820 if( tr_bencDictFindInt ( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, &i
) )
821 session
->randomPortHigh
= i
;
822 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, &boolVal
) )
823 tr_sessionSetPeerPortRandomOnStart( session
, boolVal
);
824 if( !tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_PORT
, &i
) )
825 i
= session
->private_peer_port
;
826 setPeerPort( session
, boolVal
? getRandomPort( session
) : i
);
827 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PORT_FORWARDING
, &boolVal
) )
828 tr_sessionSetPortForwardingEnabled( session
, boolVal
);
830 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, &i
) )
831 session
->peerLimit
= i
;
836 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, &i
) )
837 session
->uploadSlotsPerTorrent
= i
;
839 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_USPEED_KBps
, &i
) )
840 tr_sessionSetSpeedLimit_KBps( session
, TR_UP
, i
);
841 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_USPEED_ENABLED
, &boolVal
) )
842 tr_sessionLimitSpeed( session
, TR_UP
, boolVal
);
844 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_DSPEED_KBps
, &i
) )
845 tr_sessionSetSpeedLimit_KBps( session
, TR_DOWN
, i
);
846 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_DSPEED_ENABLED
, &boolVal
) )
847 tr_sessionLimitSpeed( session
, TR_DOWN
, boolVal
);
849 if( tr_bencDictFindReal( settings
, TR_PREFS_KEY_RATIO
, &d
) )
850 tr_sessionSetRatioLimit( session
, d
);
851 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_RATIO_ENABLED
, &boolVal
) )
852 tr_sessionSetRatioLimited( session
, boolVal
);
854 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_IDLE_LIMIT
, &i
) )
855 tr_sessionSetIdleLimit( session
, i
);
856 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_IDLE_LIMIT_ENABLED
, &boolVal
) )
857 tr_sessionSetIdleLimited( session
, boolVal
);
863 /* update the turtle mode's fields */
864 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, &i
) )
865 turtle
->speedLimit_Bps
[TR_UP
] = toSpeedBytes( i
);
866 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, &i
) )
867 turtle
->speedLimit_Bps
[TR_DOWN
] = toSpeedBytes( i
);
868 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, &i
) )
869 turtle
->beginMinute
= i
;
870 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, &i
) )
871 turtle
->endMinute
= i
;
872 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, &i
) )
874 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, &boolVal
) )
875 turtle
->isClockEnabled
= boolVal
;
876 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, &boolVal
) )
877 turtle
->isEnabled
= boolVal
;
878 turtleBootstrap( session
, turtle
);
884 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, &boolVal
) )
885 tr_sessionSetTorrentDoneScriptEnabled( session
, boolVal
);
886 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, &str
) )
887 tr_sessionSetTorrentDoneScript( session
, str
);
893 tr_sessionSet( tr_session
* session
, struct tr_benc
* settings
)
895 struct init_data data
;
897 data
.session
= session
;
898 data
.clientSettings
= settings
;
900 /* run the rest in the libtransmission thread */
901 tr_runInEventThread( session
, sessionSetImpl
, &data
);
911 tr_sessionSetDownloadDir( tr_session
* session
, const char * dir
)
913 assert( tr_isSession( session
) );
915 if( session
->downloadDir
!= dir
)
917 tr_free( session
->downloadDir
);
918 session
->downloadDir
= tr_strdup( dir
);
923 tr_sessionGetDownloadDir( const tr_session
* session
)
925 assert( tr_isSession( session
) );
927 return session
->downloadDir
;
931 tr_sessionGetDownloadDirFreeSpace( const tr_session
* session
)
933 assert( tr_isSession( session
) );
935 return tr_getFreeSpace( session
->downloadDir
);
943 tr_sessionSetIncompleteFileNamingEnabled( tr_session
* session
, bool b
)
945 assert( tr_isSession( session
) );
946 assert( tr_isBool( b
) );
948 session
->isIncompleteFileNamingEnabled
= b
;
952 tr_sessionIsIncompleteFileNamingEnabled( const tr_session
* session
)
954 assert( tr_isSession( session
) );
956 return session
->isIncompleteFileNamingEnabled
;
965 tr_sessionSetIncompleteDir( tr_session
* session
, const char * dir
)
967 assert( tr_isSession( session
) );
969 if( session
->incompleteDir
!= dir
)
971 tr_free( session
->incompleteDir
);
973 session
->incompleteDir
= tr_strdup( dir
);
978 tr_sessionGetIncompleteDir( const tr_session
* session
)
980 assert( tr_isSession( session
) );
982 return session
->incompleteDir
;
986 tr_sessionSetIncompleteDirEnabled( tr_session
* session
, bool b
)
988 assert( tr_isSession( session
) );
989 assert( tr_isBool( b
) );
991 session
->isIncompleteDirEnabled
= b
;
995 tr_sessionIsIncompleteDirEnabled( const tr_session
* session
)
997 assert( tr_isSession( session
) );
999 return session
->isIncompleteDirEnabled
;
1007 tr_sessionLock( tr_session
* session
)
1009 assert( tr_isSession( session
) );
1011 tr_lockLock( session
->lock
);
1015 tr_sessionUnlock( tr_session
* session
)
1017 assert( tr_isSession( session
) );
1019 tr_lockUnlock( session
->lock
);
1023 tr_sessionIsLocked( const tr_session
* session
)
1025 return tr_isSession( session
) && tr_lockHave( session
->lock
);
1028 /***********************************************************************
1030 ***********************************************************************
1032 **********************************************************************/
1035 peerPortChanged( void * session
)
1037 tr_torrent
* tor
= NULL
;
1039 assert( tr_isSession( session
) );
1041 close_incoming_peer_port( session
);
1042 open_incoming_peer_port( session
);
1043 tr_sharedPortChanged( session
);
1045 while(( tor
= tr_torrentNext( session
, tor
)))
1046 tr_torrentChangeMyPort( tor
);
1050 setPeerPort( tr_session
* session
, tr_port port
)
1052 session
->private_peer_port
= port
;
1053 session
->public_peer_port
= port
;
1055 tr_runInEventThread( session
, peerPortChanged
, session
);
1059 tr_sessionSetPeerPort( tr_session
* session
, tr_port port
)
1061 if( tr_isSession( session
) && ( session
->private_peer_port
!= port
) )
1063 setPeerPort( session
, port
);
1068 tr_sessionGetPeerPort( const tr_session
* session
)
1070 return tr_isSession( session
) ? session
->private_peer_port
: 0;
1074 tr_sessionSetPeerPortRandom( tr_session
* session
)
1076 assert( tr_isSession( session
) );
1078 tr_sessionSetPeerPort( session
, getRandomPort( session
) );
1079 return session
->private_peer_port
;
1083 tr_sessionSetPeerPortRandomOnStart( tr_session
* session
,
1086 assert( tr_isSession( session
) );
1088 session
->isPortRandom
= random
;
1092 tr_sessionGetPeerPortRandomOnStart( tr_session
* session
)
1094 assert( tr_isSession( session
) );
1096 return session
->isPortRandom
;
1100 tr_sessionGetPortForwarding( const tr_session
* session
)
1102 assert( tr_isSession( session
) );
1104 return tr_sharedTraversalStatus( session
->shared
);
1112 tr_sessionSetRatioLimited( tr_session
* session
, bool isLimited
)
1114 assert( tr_isSession( session
) );
1116 session
->isRatioLimited
= isLimited
;
1120 tr_sessionSetRatioLimit( tr_session
* session
, double desiredRatio
)
1122 assert( tr_isSession( session
) );
1124 session
->desiredRatio
= desiredRatio
;
1128 tr_sessionIsRatioLimited( const tr_session
* session
)
1130 assert( tr_isSession( session
) );
1132 return session
->isRatioLimited
;
1136 tr_sessionGetRatioLimit( const tr_session
* session
)
1138 assert( tr_isSession( session
) );
1140 return session
->desiredRatio
;
1148 tr_sessionSetIdleLimited( tr_session
* session
, bool isLimited
)
1150 assert( tr_isSession( session
) );
1152 session
->isIdleLimited
= isLimited
;
1156 tr_sessionSetIdleLimit( tr_session
* session
, uint16_t idleMinutes
)
1158 assert( tr_isSession( session
) );
1160 session
->idleLimitMinutes
= idleMinutes
;
1164 tr_sessionIsIdleLimited( const tr_session
* session
)
1166 assert( tr_isSession( session
) );
1168 return session
->isIdleLimited
;
1172 tr_sessionGetIdleLimit( const tr_session
* session
)
1174 assert( tr_isSession( session
) );
1176 return session
->idleLimitMinutes
;
1186 tr_sessionGetActiveSpeedLimit_Bps( const tr_session
* session
, tr_direction dir
, int * setme_Bps
)
1188 int isLimited
= true;
1190 if( !tr_isSession( session
) )
1193 if( tr_sessionUsesAltSpeed( session
) )
1194 *setme_Bps
= tr_sessionGetAltSpeed_Bps( session
, dir
);
1195 else if( tr_sessionIsSpeedLimited( session
, dir
) )
1196 *setme_Bps
= tr_sessionGetSpeedLimit_Bps( session
, dir
);
1203 tr_sessionGetActiveSpeedLimit_KBps( const tr_session
* session
,
1205 double * setme_KBps
)
1208 const bool is_active
= tr_sessionGetActiveSpeedLimit_Bps( session
, dir
, &Bps
);
1209 *setme_KBps
= toSpeedKBps( Bps
);
1214 updateBandwidth( tr_session
* session
, tr_direction dir
)
1217 const bool isLimited
= tr_sessionGetActiveSpeedLimit_Bps( session
, dir
, &limit_Bps
);
1218 const bool zeroCase
= isLimited
&& !limit_Bps
;
1220 tr_bandwidthSetLimited( &session
->bandwidth
, dir
, isLimited
&& !zeroCase
);
1222 tr_bandwidthSetDesiredSpeed_Bps( &session
->bandwidth
, dir
, limit_Bps
);
1227 MINUTES_PER_HOUR
= 60,
1228 MINUTES_PER_DAY
= MINUTES_PER_HOUR
* 24,
1229 MINUTES_PER_WEEK
= MINUTES_PER_DAY
* 7
1233 turtleUpdateTable( struct tr_turtle_info
* t
)
1236 tr_bitfield
* b
= &t
->minutes
;
1238 tr_bitfieldSetHasNone( b
);
1240 for( day
=0; day
<7; ++day
)
1242 if( t
->days
& (1<<day
) )
1245 const time_t begin
= t
->beginMinute
;
1246 time_t end
= t
->endMinute
;
1249 end
+= MINUTES_PER_DAY
;
1251 for( i
=begin
; i
<end
; ++i
)
1252 tr_bitfieldAdd( b
, (i
+day
*MINUTES_PER_DAY
) % MINUTES_PER_WEEK
);
1258 altSpeedToggled( void * vsession
)
1260 tr_session
* session
= vsession
;
1261 struct tr_turtle_info
* t
= &session
->turtle
;
1263 assert( tr_isSession( session
) );
1265 updateBandwidth( session
, TR_UP
);
1266 updateBandwidth( session
, TR_DOWN
);
1268 if( t
->callback
!= NULL
)
1269 (*t
->callback
)( session
, t
->isEnabled
, t
->changedByUser
, t
->callbackUserData
);
1273 useAltSpeed( tr_session
* s
, struct tr_turtle_info
* t
,
1274 bool enabled
, bool byUser
)
1276 assert( tr_isSession( s
) );
1277 assert( t
!= NULL
);
1278 assert( tr_isBool( enabled
) );
1279 assert( tr_isBool( byUser
) );
1281 if( t
->isEnabled
!= enabled
)
1283 t
->isEnabled
= enabled
;
1284 t
->changedByUser
= byUser
;
1285 tr_runInEventThread( s
, altSpeedToggled
, s
);
1290 * @param enabled whether turtle should be on/off according to the scheduler
1291 * @param changed whether that's different from the previous minute
1294 testTurtleTime( const struct tr_turtle_info
* t
,
1300 size_t minute_of_the_week
;
1301 const time_t now
= tr_time( );
1303 tr_localtime_r( &now
, &tm
);
1305 minute_of_the_week
= tm
.tm_wday
* MINUTES_PER_DAY
1306 + tm
.tm_hour
* MINUTES_PER_HOUR
1308 if( minute_of_the_week
>= MINUTES_PER_WEEK
) /* leap minutes? */
1309 minute_of_the_week
= MINUTES_PER_WEEK
- 1;
1311 e
= tr_bitfieldHas( &t
->minutes
, minute_of_the_week
);
1312 if( enabled
!= NULL
)
1315 if( changed
!= NULL
)
1317 const size_t prev
= minute_of_the_week
> 0 ? minute_of_the_week
- 1
1318 : MINUTES_PER_WEEK
- 1;
1319 *changed
= e
!= tr_bitfieldHas( &t
->minutes
, prev
);
1324 turtleCheckClock( tr_session
* s
, struct tr_turtle_info
* t
)
1329 assert( t
->isClockEnabled
);
1331 testTurtleTime( t
, &enabled
, &changed
);
1335 tr_inf( "Time to turn %s turtle mode!", (enabled
?"on":"off") );
1336 useAltSpeed( s
, t
, enabled
, false );
1340 /* Called after the turtle's fields are loaded from an outside source.
1341 * It initializes the implementation fields
1342 * and turns on turtle mode if the clock settings say to. */
1344 turtleBootstrap( tr_session
* session
, struct tr_turtle_info
* turtle
)
1346 turtle
->changedByUser
= false;
1348 tr_bitfieldConstruct( &turtle
->minutes
, MINUTES_PER_WEEK
);
1350 turtleUpdateTable( turtle
);
1352 if( turtle
->isClockEnabled
)
1353 testTurtleTime( turtle
, &turtle
->isEnabled
, NULL
);
1355 altSpeedToggled( session
);
1359 **** Primary session speed limits
1363 tr_sessionSetSpeedLimit_Bps( tr_session
* s
, tr_direction d
, int Bps
)
1365 assert( tr_isSession( s
) );
1366 assert( tr_isDirection( d
) );
1369 s
->speedLimit_Bps
[d
] = Bps
;
1371 updateBandwidth( s
, d
);
1374 tr_sessionSetSpeedLimit_KBps( tr_session
* s
, tr_direction d
, int KBps
)
1376 tr_sessionSetSpeedLimit_Bps( s
, d
, toSpeedBytes( KBps
) );
1380 tr_sessionGetSpeedLimit_Bps( const tr_session
* s
, tr_direction d
)
1382 assert( tr_isSession( s
) );
1383 assert( tr_isDirection( d
) );
1385 return s
->speedLimit_Bps
[d
];
1388 tr_sessionGetSpeedLimit_KBps( const tr_session
* s
, tr_direction d
)
1390 return toSpeedKBps( tr_sessionGetSpeedLimit_Bps( s
, d
) );
1394 tr_sessionLimitSpeed( tr_session
* s
, tr_direction d
, bool b
)
1396 assert( tr_isSession( s
) );
1397 assert( tr_isDirection( d
) );
1398 assert( tr_isBool( b
) );
1400 s
->speedLimitEnabled
[d
] = b
;
1402 updateBandwidth( s
, d
);
1406 tr_sessionIsSpeedLimited( const tr_session
* s
, tr_direction d
)
1408 assert( tr_isSession( s
) );
1409 assert( tr_isDirection( d
) );
1411 return s
->speedLimitEnabled
[d
];
1415 **** Alternative speed limits that are used during scheduled times
1419 tr_sessionSetAltSpeed_Bps( tr_session
* s
, tr_direction d
, int Bps
)
1421 assert( tr_isSession( s
) );
1422 assert( tr_isDirection( d
) );
1425 s
->turtle
.speedLimit_Bps
[d
] = Bps
;
1427 updateBandwidth( s
, d
);
1431 tr_sessionSetAltSpeed_KBps( tr_session
* s
, tr_direction d
, int KBps
)
1433 tr_sessionSetAltSpeed_Bps( s
, d
, toSpeedBytes( KBps
) );
1437 tr_sessionGetAltSpeed_Bps( const tr_session
* s
, tr_direction d
)
1439 assert( tr_isSession( s
) );
1440 assert( tr_isDirection( d
) );
1442 return s
->turtle
.speedLimit_Bps
[d
];
1445 tr_sessionGetAltSpeed_KBps( const tr_session
* s
, tr_direction d
)
1447 return toSpeedKBps( tr_sessionGetAltSpeed_Bps( s
, d
) );
1451 userPokedTheClock( tr_session
* s
, struct tr_turtle_info
* t
)
1453 tr_dbg( "Refreshing the turtle mode clock due to user changes" );
1455 turtleUpdateTable( t
);
1457 if( t
->isClockEnabled
)
1459 bool enabled
, changed
;
1460 testTurtleTime( t
, &enabled
, &changed
);
1461 useAltSpeed( s
, t
, enabled
, true );
1466 tr_sessionUseAltSpeedTime( tr_session
* s
, bool b
)
1468 struct tr_turtle_info
* t
= &s
->turtle
;
1470 assert( tr_isSession( s
) );
1471 assert( tr_isBool ( b
) );
1473 if( t
->isClockEnabled
!= b
) {
1474 t
->isClockEnabled
= b
;
1475 userPokedTheClock( s
, t
);
1480 tr_sessionUsesAltSpeedTime( const tr_session
* s
)
1482 assert( tr_isSession( s
) );
1484 return s
->turtle
.isClockEnabled
;
1488 tr_sessionSetAltSpeedBegin( tr_session
* s
, int minute
)
1490 assert( tr_isSession( s
) );
1491 assert( 0<=minute
&& minute
<(60*24) );
1493 if( s
->turtle
.beginMinute
!= minute
) {
1494 s
->turtle
.beginMinute
= minute
;
1495 userPokedTheClock( s
, &s
->turtle
);
1500 tr_sessionGetAltSpeedBegin( const tr_session
* s
)
1502 assert( tr_isSession( s
) );
1504 return s
->turtle
.beginMinute
;
1508 tr_sessionSetAltSpeedEnd( tr_session
* s
, int minute
)
1510 assert( tr_isSession( s
) );
1511 assert( 0<=minute
&& minute
<(60*24) );
1513 if( s
->turtle
.endMinute
!= minute
) {
1514 s
->turtle
.endMinute
= minute
;
1515 userPokedTheClock( s
, &s
->turtle
);
1520 tr_sessionGetAltSpeedEnd( const tr_session
* s
)
1522 assert( tr_isSession( s
) );
1524 return s
->turtle
.endMinute
;
1528 tr_sessionSetAltSpeedDay( tr_session
* s
, tr_sched_day days
)
1530 assert( tr_isSession( s
) );
1532 if( s
->turtle
.days
!= days
) {
1533 s
->turtle
.days
= days
;
1534 userPokedTheClock( s
, &s
->turtle
);
1539 tr_sessionGetAltSpeedDay( const tr_session
* s
)
1541 assert( tr_isSession( s
) );
1543 return s
->turtle
.days
;
1547 tr_sessionUseAltSpeed( tr_session
* session
, bool enabled
)
1549 useAltSpeed( session
, &session
->turtle
, enabled
, true );
1553 tr_sessionUsesAltSpeed( const tr_session
* s
)
1555 assert( tr_isSession( s
) );
1557 return s
->turtle
.isEnabled
;
1561 tr_sessionSetAltSpeedFunc( tr_session
* session
,
1562 tr_altSpeedFunc func
,
1565 assert( tr_isSession( session
) );
1567 session
->turtle
.callback
= func
;
1568 session
->turtle
.callbackUserData
= userData
;
1572 tr_sessionClearAltSpeedFunc( tr_session
* session
)
1574 tr_sessionSetAltSpeedFunc( session
, NULL
, NULL
);
1582 tr_sessionSetPeerLimit( tr_session
* session
, uint16_t n
)
1584 assert( tr_isSession( session
) );
1586 session
->peerLimit
= n
;
1590 tr_sessionGetPeerLimit( const tr_session
* session
)
1592 assert( tr_isSession( session
) );
1594 return session
->peerLimit
;
1598 tr_sessionSetPeerLimitPerTorrent( tr_session
* session
, uint16_t n
)
1600 assert( tr_isSession( session
) );
1602 session
->peerLimitPerTorrent
= n
;
1606 tr_sessionGetPeerLimitPerTorrent( const tr_session
* session
)
1608 assert( tr_isSession( session
) );
1610 return session
->peerLimitPerTorrent
;
1618 tr_sessionSetPaused( tr_session
* session
, bool isPaused
)
1620 assert( tr_isSession( session
) );
1622 session
->pauseAddedTorrent
= isPaused
;
1626 tr_sessionGetPaused( const tr_session
* session
)
1628 assert( tr_isSession( session
) );
1630 return session
->pauseAddedTorrent
;
1634 tr_sessionSetDeleteSource( tr_session
* session
, bool deleteSource
)
1636 assert( tr_isSession( session
) );
1638 session
->deleteSourceTorrent
= deleteSource
;
1642 tr_sessionGetDeleteSource( const tr_session
* session
)
1644 assert( tr_isSession( session
) );
1646 return session
->deleteSourceTorrent
;
1654 tr_sessionGetPieceSpeed_Bps( const tr_session
* session
, tr_direction dir
)
1656 return tr_isSession( session
) ? tr_bandwidthGetPieceSpeed_Bps( &session
->bandwidth
, 0, dir
) : 0;
1660 tr_sessionGetRawSpeed_Bps( const tr_session
* session
, tr_direction dir
)
1662 return tr_isSession( session
) ? tr_bandwidthGetRawSpeed_Bps( &session
->bandwidth
, 0, dir
) : 0;
1665 tr_sessionGetRawSpeed_KBps( const tr_session
* session
, tr_direction dir
)
1667 return toSpeedKBps( tr_sessionGetRawSpeed_Bps( session
, dir
) );
1672 tr_sessionCountTorrents( const tr_session
* session
)
1674 return tr_isSession( session
) ? session
->torrentCount
: 0;
1678 compareTorrentByCur( const void * va
, const void * vb
)
1680 const tr_torrent
* a
= *(const tr_torrent
**)va
;
1681 const tr_torrent
* b
= *(const tr_torrent
**)vb
;
1682 const uint64_t aCur
= a
->downloadedCur
+ a
->uploadedCur
;
1683 const uint64_t bCur
= b
->downloadedCur
+ b
->uploadedCur
;
1686 return aCur
> bCur
? -1 : 1; /* close the biggest torrents first */
1691 static void closeBlocklists( tr_session
* );
1694 sessionCloseImpl( void * vsession
)
1696 tr_session
* session
= vsession
;
1699 tr_torrent
** torrents
;
1701 assert( tr_isSession( session
) );
1703 free_incoming_peer_port( session
);
1705 if( session
->isLPDEnabled
)
1706 tr_lpdUninit( session
);
1708 tr_utpClose( session
);
1709 tr_dhtUninit( session
);
1711 event_free( session
->saveTimer
);
1712 session
->saveTimer
= NULL
;
1714 event_free( session
->nowTimer
);
1715 session
->nowTimer
= NULL
;
1717 tr_verifyClose( session
);
1718 tr_sharedClose( session
);
1719 tr_rpcClose( &session
->rpcServer
);
1721 /* Close the torrents. Get the most active ones first so that
1722 * if we can't get them all closed in a reasonable amount of time,
1723 * at least we get the most important ones first. */
1725 n
= session
->torrentCount
;
1726 torrents
= tr_new( tr_torrent
*, session
->torrentCount
);
1727 for( i
= 0; i
< n
; ++i
)
1728 torrents
[i
] = tor
= tr_torrentNext( session
, tor
);
1729 qsort( torrents
, n
, sizeof( tr_torrent
* ), compareTorrentByCur
);
1730 for( i
= 0; i
< n
; ++i
)
1731 tr_torrentFree( torrents
[i
] );
1732 tr_free( torrents
);
1734 /* Close the announcer *after* closing the torrents
1735 so that all the &event=stopped messages will be
1736 queued to be sent by tr_announcerClose() */
1737 tr_announcerClose( session
);
1739 /* and this goes *after* announcer close so that
1740 it won't be idle until the announce events are sent... */
1741 tr_webClose( session
, TR_WEB_CLOSE_WHEN_IDLE
);
1743 tr_cacheFree( session
->cache
);
1744 session
->cache
= NULL
;
1746 /* gotta keep udp running long enough to send out all
1747 the &event=stopped UDP tracker messages */
1748 while( !tr_tracker_udp_is_idle( session
) ) {
1749 tr_tracker_udp_upkeep( session
);
1750 tr_wait_msec( 100 );
1753 /* we had to wait until UDP trackers were closed before closing these: */
1754 evdns_base_free( session
->evdns_base
, 0 );
1755 session
->evdns_base
= NULL
;
1756 tr_tracker_udp_close( session
);
1757 tr_udpUninit( session
);
1759 tr_statsClose( session
);
1760 tr_peerMgrFree( session
->peerMgr
);
1762 closeBlocklists( session
);
1764 tr_fdClose( session
);
1766 session
->isClosed
= true;
1770 deadlineReached( const time_t deadline
)
1772 return time( NULL
) >= deadline
;
1775 #define SHUTDOWN_MAX_SECONDS 20
1778 tr_sessionClose( tr_session
* session
)
1780 const time_t deadline
= time( NULL
) + SHUTDOWN_MAX_SECONDS
;
1782 assert( tr_isSession( session
) );
1784 dbgmsg( "shutting down transmission session %p... now is %zu, deadline is %zu", session
, (size_t)time(NULL
), (size_t)deadline
);
1786 /* close the session */
1787 tr_runInEventThread( session
, sessionCloseImpl
, session
);
1788 while( !session
->isClosed
&& !deadlineReached( deadline
) )
1790 dbgmsg( "waiting for the libtransmission thread to finish" );
1791 tr_wait_msec( 100 );
1794 /* "shared" and "tracker" have live sockets,
1795 * so we need to keep the transmission thread alive
1796 * for a bit while they tell the router & tracker
1797 * that we're closing now */
1798 while( ( session
->shared
|| session
->web
|| session
->announcer
|| session
->announcer_udp
)
1799 && !deadlineReached( deadline
) )
1801 dbgmsg( "waiting on port unmap (%p) or announcer (%p)... now %zu deadline %zu",
1802 session
->shared
, session
->announcer
, (size_t)time(NULL
), (size_t)deadline
);
1803 tr_wait_msec( 100 );
1806 tr_webClose( session
, TR_WEB_CLOSE_NOW
);
1808 /* close the libtransmission thread */
1809 tr_eventClose( session
);
1810 while( session
->events
!= NULL
)
1812 static bool forced
= false;
1813 dbgmsg( "waiting for libtransmission thread to finish... now %zu deadline %zu", (size_t)time(NULL
), (size_t)deadline
);
1814 tr_wait_msec( 500 );
1815 if( deadlineReached( deadline
) && !forced
)
1817 dbgmsg( "calling event_loopbreak()" );
1819 event_base_loopbreak( session
->event_base
);
1821 if( deadlineReached( deadline
+3 ) )
1823 dbgmsg( "deadline+3 reached... calling break...\n" );
1828 /* free the session memory */
1829 tr_bencFree( &session
->removedTorrents
);
1830 tr_bandwidthDestruct( &session
->bandwidth
);
1831 tr_bitfieldDestruct( &session
->turtle
.minutes
);
1832 tr_lockFree( session
->lock
);
1833 if( session
->metainfoLookup
) {
1834 tr_bencFree( session
->metainfoLookup
);
1835 tr_free( session
->metainfoLookup
);
1837 tr_free( session
->torrentDoneScript
);
1838 tr_free( session
->tag
);
1839 tr_free( session
->configDir
);
1840 tr_free( session
->resumeDir
);
1841 tr_free( session
->torrentDir
);
1842 tr_free( session
->downloadDir
);
1843 tr_free( session
->incompleteDir
);
1844 tr_free( session
->blocklist_url
);
1845 tr_free( session
->peer_congestion_algorithm
);
1849 struct sessionLoadTorrentsData
1851 tr_session
* session
;
1854 tr_torrent
** torrents
;
1859 sessionLoadTorrents( void * vdata
)
1866 tr_list
* list
= NULL
;
1867 struct sessionLoadTorrentsData
* data
= vdata
;
1868 const char * dirname
= tr_getTorrentDir( data
->session
);
1870 assert( tr_isSession( data
->session
) );
1872 tr_ctorSetSave( data
->ctor
, false ); /* since we already have them */
1874 if( !stat( dirname
, &sb
)
1875 && S_ISDIR( sb
.st_mode
)
1876 && ( ( odir
= opendir ( dirname
) ) ) )
1879 for( d
= readdir( odir
); d
!= NULL
; d
= readdir( odir
) )
1881 if( tr_str_has_suffix( d
->d_name
, ".torrent" ) )
1884 char * path
= tr_buildPath( dirname
, d
->d_name
, NULL
);
1885 tr_ctorSetMetainfoFromFile( data
->ctor
, path
);
1886 if(( tor
= tr_torrentNew( data
->ctor
, NULL
)))
1888 tr_list_prepend( &list
, tor
);
1897 data
->torrents
= tr_new( tr_torrent
*, n
);
1898 for( i
= 0, l
= list
; l
!= NULL
; l
= l
->next
)
1899 data
->torrents
[i
++] = (tr_torrent
*) l
->data
;
1902 tr_list_free( &list
, NULL
);
1905 tr_inf( _( "Loaded %d torrents" ), n
);
1907 if( data
->setmeCount
)
1908 *data
->setmeCount
= n
;
1914 tr_sessionLoadTorrents( tr_session
* session
,
1918 struct sessionLoadTorrentsData data
;
1920 data
.session
= session
;
1922 data
.setmeCount
= setmeCount
;
1923 data
.torrents
= NULL
;
1926 tr_runInEventThread( session
, sessionLoadTorrents
, &data
);
1928 tr_wait_msec( 100 );
1930 return data
.torrents
;
1938 tr_sessionSetPexEnabled( tr_session
* session
, bool enabled
)
1940 assert( tr_isSession( session
) );
1942 session
->isPexEnabled
= enabled
!= 0;
1946 tr_sessionIsPexEnabled( const tr_session
* session
)
1948 assert( tr_isSession( session
) );
1950 return session
->isPexEnabled
;
1954 tr_sessionAllowsDHT( const tr_session
* session
)
1956 return tr_sessionIsDHTEnabled( session
);
1960 tr_sessionIsDHTEnabled( const tr_session
* session
)
1962 assert( tr_isSession( session
) );
1964 return session
->isDHTEnabled
;
1968 toggleDHTImpl( void * data
)
1970 tr_session
* session
= data
;
1971 assert( tr_isSession( session
) );
1973 tr_udpUninit( session
);
1974 session
->isDHTEnabled
= !session
->isDHTEnabled
;
1975 tr_udpInit( session
);
1979 tr_sessionSetDHTEnabled( tr_session
* session
, bool enabled
)
1981 assert( tr_isSession( session
) );
1982 assert( tr_isBool( enabled
) );
1984 if( ( enabled
!= 0 ) != ( session
->isDHTEnabled
!= 0 ) )
1985 tr_runInEventThread( session
, toggleDHTImpl
, session
);
1993 tr_sessionIsUTPEnabled( const tr_session
* session
)
1995 assert( tr_isSession( session
) );
1998 return session
->isUTPEnabled
;
2005 toggle_utp( void * data
)
2007 tr_session
* session
= data
;
2008 assert( tr_isSession( session
) );
2010 session
->isUTPEnabled
= !session
->isUTPEnabled
;
2012 tr_udpSetSocketBuffers( session
);
2014 /* But don't call tr_utpClose -- see reset_timer in tr-utp.c for an
2019 tr_sessionSetUTPEnabled( tr_session
* session
, bool enabled
)
2021 assert( tr_isSession( session
) );
2022 assert( tr_isBool( enabled
) );
2024 if( ( enabled
!= 0 ) != ( session
->isUTPEnabled
!= 0 ) )
2025 tr_runInEventThread( session
, toggle_utp
, session
);
2033 toggleLPDImpl( void * data
)
2035 tr_session
* session
= data
;
2036 assert( tr_isSession( session
) );
2038 if( session
->isLPDEnabled
)
2039 tr_lpdUninit( session
);
2041 session
->isLPDEnabled
= !session
->isLPDEnabled
;
2043 if( session
->isLPDEnabled
)
2044 tr_lpdInit( session
, &session
->public_ipv4
->addr
);
2048 tr_sessionSetLPDEnabled( tr_session
* session
, bool enabled
)
2050 assert( tr_isSession( session
) );
2051 assert( tr_isBool( enabled
) );
2053 if( ( enabled
!= 0 ) != ( session
->isLPDEnabled
!= 0 ) )
2054 tr_runInEventThread( session
, toggleLPDImpl
, session
);
2058 tr_sessionIsLPDEnabled( const tr_session
* session
)
2060 assert( tr_isSession( session
) );
2062 return session
->isLPDEnabled
;
2066 tr_sessionAllowsLPD( const tr_session
* session
)
2068 return tr_sessionIsLPDEnabled( session
);
2076 tr_sessionSetCacheLimit_MB( tr_session
* session
, int max_bytes
)
2078 assert( tr_isSession( session
) );
2080 tr_cacheSetLimit( session
->cache
, toMemBytes( max_bytes
) );
2084 tr_sessionGetCacheLimit_MB( const tr_session
* session
)
2086 assert( tr_isSession( session
) );
2088 return toMemMB( tr_cacheGetLimit( session
->cache
) );
2095 struct port_forwarding_data
2098 struct tr_shared
* shared
;
2102 setPortForwardingEnabled( void * vdata
)
2104 struct port_forwarding_data
* data
= vdata
;
2105 tr_sharedTraversalEnable( data
->shared
, data
->enabled
);
2110 tr_sessionSetPortForwardingEnabled( tr_session
* session
, bool enabled
)
2112 struct port_forwarding_data
* d
;
2113 d
= tr_new0( struct port_forwarding_data
, 1 );
2114 d
->shared
= session
->shared
;
2115 d
->enabled
= enabled
;
2116 tr_runInEventThread( session
, setPortForwardingEnabled
, d
);
2120 tr_sessionIsPortForwardingEnabled( const tr_session
* session
)
2122 assert( tr_isSession( session
) );
2124 return tr_sharedTraversalIsEnabled( session
->shared
);
2132 tr_stringEndsWith( const char * str
, const char * end
)
2134 const size_t slen
= strlen( str
);
2135 const size_t elen
= strlen( end
);
2137 return slen
>= elen
&& !memcmp( &str
[slen
- elen
], end
, elen
);
2141 loadBlocklists( tr_session
* session
)
2148 tr_list
* list
= NULL
;
2149 const bool isEnabled
= session
->isBlocklistEnabled
;
2151 /* walk through the directory and find blocklists */
2152 dirname
= tr_buildPath( session
->configDir
, "blocklists", NULL
);
2154 &sb
) && S_ISDIR( sb
.st_mode
)
2155 && ( ( odir
= opendir( dirname
) ) ) )
2158 for( d
= readdir( odir
); d
; d
= readdir( odir
) )
2162 if( !d
->d_name
|| d
->d_name
[0] == '.' ) /* skip dotfiles, ., and ..
2166 filename
= tr_buildPath( dirname
, d
->d_name
, NULL
);
2168 if( tr_stringEndsWith( filename
, ".bin" ) )
2170 /* if we don't already have this blocklist, add it */
2171 if( !tr_list_find( list
, filename
,
2172 (TrListCompareFunc
)strcmp
) )
2174 tr_list_append( &list
,
2175 _tr_blocklistNew( filename
, isEnabled
) );
2181 /* strip out the file suffix, if there is one, and add ".bin"
2184 const char * dot
= strrchr( d
->d_name
, '.' );
2185 const int len
= dot
? dot
- d
->d_name
2186 : (int)strlen( d
->d_name
);
2187 char * tmp
= tr_strdup_printf(
2188 "%s" TR_PATH_DELIMITER_STR
"%*.*s.bin",
2189 dirname
, len
, len
, d
->d_name
);
2190 b
= _tr_blocklistNew( tmp
, isEnabled
);
2191 _tr_blocklistSetContent( b
, filename
);
2192 tr_list_append( &list
, b
);
2197 tr_free( filename
);
2203 session
->blocklists
= list
;
2206 tr_dbg( "Found %d blocklists in \"%s\"", binCount
, dirname
);
2208 tr_dbg( "Found %d new blocklists in \"%s\"", newCount
, dirname
);
2214 closeBlocklists( tr_session
* session
)
2216 tr_list_free( &session
->blocklists
,
2217 (TrListForeachFunc
)_tr_blocklistFree
);
2221 tr_sessionReloadBlocklists( tr_session
* session
)
2223 closeBlocklists( session
);
2224 loadBlocklists( session
);
2226 tr_peerMgrOnBlocklistChanged( session
->peerMgr
);
2230 tr_blocklistGetRuleCount( const tr_session
* session
)
2235 assert( tr_isSession( session
) );
2237 for( l
= session
->blocklists
; l
; l
= l
->next
)
2238 n
+= _tr_blocklistGetRuleCount( l
->data
);
2243 tr_blocklistIsEnabled( const tr_session
* session
)
2245 assert( tr_isSession( session
) );
2247 return session
->isBlocklistEnabled
;
2251 tr_blocklistSetEnabled( tr_session
* session
, bool isEnabled
)
2255 assert( tr_isSession( session
) );
2257 session
->isBlocklistEnabled
= isEnabled
!= 0;
2259 for( l
=session
->blocklists
; l
!=NULL
; l
=l
->next
)
2260 _tr_blocklistSetEnabled( l
->data
, isEnabled
);
2264 tr_blocklistExists( const tr_session
* session
)
2266 assert( tr_isSession( session
) );
2268 return session
->blocklists
!= NULL
;
2272 tr_blocklistSetContent( tr_session
* session
, const char * contentFilename
)
2277 const char * defaultName
= DEFAULT_BLOCKLIST_FILENAME
;
2278 tr_sessionLock( session
);
2280 for( b
= NULL
, l
= session
->blocklists
; !b
&& l
; l
= l
->next
)
2281 if( tr_stringEndsWith( _tr_blocklistGetFilename( l
->data
),
2287 char * path
= tr_buildPath( session
->configDir
, "blocklists", defaultName
, NULL
);
2288 b
= _tr_blocklistNew( path
, session
->isBlocklistEnabled
);
2289 tr_list_append( &session
->blocklists
, b
);
2293 ruleCount
= _tr_blocklistSetContent( b
, contentFilename
);
2294 tr_sessionUnlock( session
);
2299 tr_sessionIsAddressBlocked( const tr_session
* session
,
2300 const tr_address
* addr
)
2304 assert( tr_isSession( session
) );
2306 for( l
= session
->blocklists
; l
; l
= l
->next
)
2307 if( _tr_blocklistHasAddress( l
->data
, addr
) )
2313 tr_blocklistSetURL( tr_session
* session
, const char * url
)
2315 if( session
->blocklist_url
!= url
)
2317 tr_free( session
->blocklist_url
);
2318 session
->blocklist_url
= tr_strdup( url
);
2323 tr_blocklistGetURL ( const tr_session
* session
)
2325 return session
->blocklist_url
;
2334 metainfoLookupInit( tr_session
* session
)
2337 const char * dirname
= tr_getTorrentDir( session
);
2339 tr_ctor
* ctor
= NULL
;
2343 assert( tr_isSession( session
) );
2345 /* walk through the directory and find the mappings */
2346 lookup
= tr_new0( tr_benc
, 1 );
2347 tr_bencInitDict( lookup
, 0 );
2348 ctor
= tr_ctorNew( session
);
2349 tr_ctorSetSave( ctor
, false ); /* since we already have them */
2350 if( !stat( dirname
, &sb
) && S_ISDIR( sb
.st_mode
) && ( ( odir
= opendir( dirname
) ) ) )
2353 while(( d
= readdir( odir
)))
2355 if( tr_str_has_suffix( d
->d_name
, ".torrent" ) )
2358 char * path
= tr_buildPath( dirname
, d
->d_name
, NULL
);
2359 tr_ctorSetMetainfoFromFile( ctor
, path
);
2360 if( !tr_torrentParse( ctor
, &inf
) )
2363 tr_bencDictAddStr( lookup
, inf
.hashString
, path
);
2370 tr_ctorFree( ctor
);
2372 session
->metainfoLookup
= lookup
;
2373 tr_dbg( "Found %d torrents in \"%s\"", n
, dirname
);
2377 tr_sessionFindTorrentFile( const tr_session
* session
,
2378 const char * hashString
)
2380 const char * filename
= NULL
;
2381 if( !session
->metainfoLookup
)
2382 metainfoLookupInit( (tr_session
*)session
);
2383 tr_bencDictFindStr( session
->metainfoLookup
, hashString
, &filename
);
2388 tr_sessionSetTorrentFile( tr_session
* session
,
2389 const char * hashString
,
2390 const char * filename
)
2392 /* since we walk session->configDir/torrents/ to build the lookup table,
2393 * and tr_sessionSetTorrentFile() is just to tell us there's a new file
2394 * in that same directory, we don't need to do anything here if the
2395 * lookup table hasn't been built yet */
2396 if( session
->metainfoLookup
)
2397 tr_bencDictAddStr( session
->metainfoLookup
, hashString
, filename
);
2405 tr_sessionSetRPCEnabled( tr_session
* session
, bool isEnabled
)
2407 assert( tr_isSession( session
) );
2409 tr_rpcSetEnabled( session
->rpcServer
, isEnabled
);
2413 tr_sessionIsRPCEnabled( const tr_session
* session
)
2415 assert( tr_isSession( session
) );
2417 return tr_rpcIsEnabled( session
->rpcServer
);
2421 tr_sessionSetRPCPort( tr_session
* session
,
2424 assert( tr_isSession( session
) );
2426 tr_rpcSetPort( session
->rpcServer
, port
);
2430 tr_sessionGetRPCPort( const tr_session
* session
)
2432 assert( tr_isSession( session
) );
2434 return tr_rpcGetPort( session
->rpcServer
);
2438 tr_sessionSetRPCUrl( tr_session
* session
,
2441 assert( tr_isSession( session
) );
2443 tr_rpcSetUrl( session
->rpcServer
, url
);
2447 tr_sessionGetRPCUrl( const tr_session
* session
)
2449 assert( tr_isSession( session
) );
2451 return tr_rpcGetUrl( session
->rpcServer
);
2455 tr_sessionSetRPCCallback( tr_session
* session
,
2459 assert( tr_isSession( session
) );
2461 session
->rpc_func
= func
;
2462 session
->rpc_func_user_data
= user_data
;
2466 tr_sessionSetRPCWhitelist( tr_session
* session
,
2467 const char * whitelist
)
2469 assert( tr_isSession( session
) );
2471 tr_rpcSetWhitelist( session
->rpcServer
, whitelist
);
2475 tr_sessionGetRPCWhitelist( const tr_session
* session
)
2477 assert( tr_isSession( session
) );
2479 return tr_rpcGetWhitelist( session
->rpcServer
);
2483 tr_sessionSetRPCWhitelistEnabled( tr_session
* session
, bool isEnabled
)
2485 assert( tr_isSession( session
) );
2487 tr_rpcSetWhitelistEnabled( session
->rpcServer
, isEnabled
);
2491 tr_sessionGetRPCWhitelistEnabled( const tr_session
* session
)
2493 assert( tr_isSession( session
) );
2495 return tr_rpcGetWhitelistEnabled( session
->rpcServer
);
2500 tr_sessionSetRPCPassword( tr_session
* session
,
2501 const char * password
)
2503 assert( tr_isSession( session
) );
2505 tr_rpcSetPassword( session
->rpcServer
, password
);
2509 tr_sessionGetRPCPassword( const tr_session
* session
)
2511 assert( tr_isSession( session
) );
2513 return tr_rpcGetPassword( session
->rpcServer
);
2517 tr_sessionSetRPCUsername( tr_session
* session
,
2518 const char * username
)
2520 assert( tr_isSession( session
) );
2522 tr_rpcSetUsername( session
->rpcServer
, username
);
2526 tr_sessionGetRPCUsername( const tr_session
* session
)
2528 assert( tr_isSession( session
) );
2530 return tr_rpcGetUsername( session
->rpcServer
);
2534 tr_sessionSetRPCPasswordEnabled( tr_session
* session
, bool isEnabled
)
2536 assert( tr_isSession( session
) );
2538 tr_rpcSetPasswordEnabled( session
->rpcServer
, isEnabled
);
2542 tr_sessionIsRPCPasswordEnabled( const tr_session
* session
)
2544 assert( tr_isSession( session
) );
2546 return tr_rpcIsPasswordEnabled( session
->rpcServer
);
2550 tr_sessionGetRPCBindAddress( const tr_session
* session
)
2552 assert( tr_isSession( session
) );
2554 return tr_rpcGetBindAddress( session
->rpcServer
);
2562 tr_sessionIsTorrentDoneScriptEnabled( const tr_session
* session
)
2564 assert( tr_isSession( session
) );
2566 return session
->isTorrentDoneScriptEnabled
;
2570 tr_sessionSetTorrentDoneScriptEnabled( tr_session
* session
, bool isEnabled
)
2572 assert( tr_isSession( session
) );
2573 assert( tr_isBool( isEnabled
) );
2575 session
->isTorrentDoneScriptEnabled
= isEnabled
;
2579 tr_sessionGetTorrentDoneScript( const tr_session
* session
)
2581 assert( tr_isSession( session
) );
2583 return session
->torrentDoneScript
;
2587 tr_sessionSetTorrentDoneScript( tr_session
* session
, const char * scriptFilename
)
2589 assert( tr_isSession( session
) );
2591 if( session
->torrentDoneScript
!= scriptFilename
)
2593 tr_free( session
->torrentDoneScript
);
2594 session
->torrentDoneScript
= tr_strdup( scriptFilename
);