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 13191 2012-02-03 16:44:07Z 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_DOWNLOAD_QUEUE_SIZE
, 5 );
323 tr_bencDictAddBool( d
, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED
, true );
324 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR
) );
325 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR
) );
326 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT
, atoi( TR_DEFAULT_PEER_PORT_STR
) );
327 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, false );
328 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, 49152 );
329 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, 65535 );
330 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_SOCKET_TOS
, TR_DEFAULT_PEER_SOCKET_TOS_STR
);
331 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEX_ENABLED
, true );
332 tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, true );
333 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREALLOCATION
, TR_PREALLOCATE_SPARSE
);
334 tr_bencDictAddBool( d
, TR_PREFS_KEY_PREFETCH_ENABLED
, DEFAULT_PREFETCH_ENABLED
);
335 tr_bencDictAddBool( d
, TR_PREFS_KEY_QUEUE_STALLED_ENABLED
, true );
336 tr_bencDictAddInt ( d
, TR_PREFS_KEY_QUEUE_STALLED_MINUTES
, 30 );
337 tr_bencDictAddReal( d
, TR_PREFS_KEY_RATIO
, 2.0 );
338 tr_bencDictAddBool( d
, TR_PREFS_KEY_RATIO_ENABLED
, false );
339 tr_bencDictAddBool( d
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, true );
340 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_AUTH_REQUIRED
, false );
341 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_BIND_ADDRESS
, "0.0.0.0" );
342 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_ENABLED
, false );
343 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_PASSWORD
, "" );
344 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_USERNAME
, "" );
345 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_WHITELIST
, TR_DEFAULT_RPC_WHITELIST
);
346 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_WHITELIST_ENABLED
, true );
347 tr_bencDictAddInt ( d
, TR_PREFS_KEY_RPC_PORT
, atoi( TR_DEFAULT_RPC_PORT_STR
) );
348 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_URL
, TR_DEFAULT_RPC_URL_STR
);
349 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS
, true );
350 tr_bencDictAddStr ( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, "" );
351 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, false );
352 tr_bencDictAddInt ( d
, TR_PREFS_KEY_SEED_QUEUE_SIZE
, 10 );
353 tr_bencDictAddBool( d
, TR_PREFS_KEY_SEED_QUEUE_ENABLED
, false );
354 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, false );
355 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, 50 ); /* half the regular */
356 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, 50 ); /* half the regular */
357 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, 540 ); /* 9am */
358 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, false );
359 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, 1020 ); /* 5pm */
360 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, TR_SCHED_ALL
);
361 tr_bencDictAddInt ( d
, TR_PREFS_KEY_USPEED_KBps
, 100 );
362 tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, false );
363 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UMASK
, 022 );
364 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, 14 );
365 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, TR_DEFAULT_BIND_ADDRESS_IPV4
);
366 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, TR_DEFAULT_BIND_ADDRESS_IPV6
);
367 tr_bencDictAddBool( d
, TR_PREFS_KEY_START
, true );
368 tr_bencDictAddBool( d
, TR_PREFS_KEY_TRASH_ORIGINAL
, false );
372 tr_sessionGetSettings( tr_session
* s
, struct tr_benc
* d
)
374 assert( tr_bencIsDict( d
) );
376 tr_bencDictReserve( d
, 60 );
377 tr_bencDictAddBool( d
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, tr_blocklistIsEnabled( s
) );
378 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BLOCKLIST_URL
, tr_blocklistGetURL( s
) );
379 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MAX_CACHE_SIZE_MB
, tr_sessionGetCacheLimit_MB( s
) );
380 tr_bencDictAddBool( d
, TR_PREFS_KEY_DHT_ENABLED
, s
->isDHTEnabled
);
381 tr_bencDictAddBool( d
, TR_PREFS_KEY_UTP_ENABLED
, s
->isUTPEnabled
);
382 tr_bencDictAddBool( d
, TR_PREFS_KEY_LPD_ENABLED
, s
->isLPDEnabled
);
383 tr_bencDictAddStr ( d
, TR_PREFS_KEY_DOWNLOAD_DIR
, s
->downloadDir
);
384 tr_bencDictAddInt ( d
, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE
, tr_sessionGetQueueSize( s
, TR_DOWN
) );
385 tr_bencDictAddBool( d
, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED
, tr_sessionGetQueueEnabled( s
, TR_DOWN
) );
386 tr_bencDictAddInt ( d
, TR_PREFS_KEY_DSPEED_KBps
, tr_sessionGetSpeedLimit_KBps( s
, TR_DOWN
) );
387 tr_bencDictAddBool( d
, TR_PREFS_KEY_DSPEED_ENABLED
, tr_sessionIsSpeedLimited( s
, TR_DOWN
) );
388 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ENCRYPTION
, s
->encryptionMode
);
389 tr_bencDictAddInt ( d
, TR_PREFS_KEY_IDLE_LIMIT
, tr_sessionGetIdleLimit( s
) );
390 tr_bencDictAddBool( d
, TR_PREFS_KEY_IDLE_LIMIT_ENABLED
, tr_sessionIsIdleLimited( s
) );
391 tr_bencDictAddStr ( d
, TR_PREFS_KEY_INCOMPLETE_DIR
, tr_sessionGetIncompleteDir( s
) );
392 tr_bencDictAddBool( d
, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED
, tr_sessionIsIncompleteDirEnabled( s
) );
393 tr_bencDictAddInt ( d
, TR_PREFS_KEY_MSGLEVEL
, tr_getMessageLevel( ) );
394 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, s
->peerLimit
);
395 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, s
->peerLimitPerTorrent
);
396 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT
, tr_sessionGetPeerPort( s
) );
397 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, s
->isPortRandom
);
398 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, s
->randomPortLow
);
399 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, s
->randomPortHigh
);
400 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_SOCKET_TOS
, format_tos(s
->peerSocketTOS
) );
401 tr_bencDictAddStr ( d
, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM
, s
->peer_congestion_algorithm
);
402 tr_bencDictAddBool( d
, TR_PREFS_KEY_PEX_ENABLED
, s
->isPexEnabled
);
403 tr_bencDictAddBool( d
, TR_PREFS_KEY_PORT_FORWARDING
, tr_sessionIsPortForwardingEnabled( s
) );
404 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREALLOCATION
, s
->preallocationMode
);
405 tr_bencDictAddInt ( d
, TR_PREFS_KEY_PREFETCH_ENABLED
, s
->isPrefetchEnabled
);
406 tr_bencDictAddBool( d
, TR_PREFS_KEY_QUEUE_STALLED_ENABLED
, tr_sessionGetQueueStalledEnabled( s
) );
407 tr_bencDictAddInt ( d
, TR_PREFS_KEY_QUEUE_STALLED_MINUTES
, tr_sessionGetQueueStalledMinutes( s
) );
408 tr_bencDictAddReal( d
, TR_PREFS_KEY_RATIO
, s
->desiredRatio
);
409 tr_bencDictAddBool( d
, TR_PREFS_KEY_RATIO_ENABLED
, s
->isRatioLimited
);
410 tr_bencDictAddBool( d
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, tr_sessionIsIncompleteFileNamingEnabled( s
) );
411 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_AUTH_REQUIRED
, tr_sessionIsRPCPasswordEnabled( s
) );
412 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_BIND_ADDRESS
, tr_sessionGetRPCBindAddress( s
) );
413 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_ENABLED
, tr_sessionIsRPCEnabled( s
) );
414 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_PASSWORD
, tr_sessionGetRPCPassword( s
) );
415 tr_bencDictAddInt ( d
, TR_PREFS_KEY_RPC_PORT
, tr_sessionGetRPCPort( s
) );
416 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_URL
, tr_sessionGetRPCUrl( s
) );
417 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_USERNAME
, tr_sessionGetRPCUsername( s
) );
418 tr_bencDictAddStr ( d
, TR_PREFS_KEY_RPC_WHITELIST
, tr_sessionGetRPCWhitelist( s
) );
419 tr_bencDictAddBool( d
, TR_PREFS_KEY_RPC_WHITELIST_ENABLED
, tr_sessionGetRPCWhitelistEnabled( s
) );
420 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS
, s
->scrapePausedTorrents
);
421 tr_bencDictAddBool( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, tr_sessionIsTorrentDoneScriptEnabled( s
) );
422 tr_bencDictAddStr ( d
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, tr_sessionGetTorrentDoneScript( s
) );
423 tr_bencDictAddInt ( d
, TR_PREFS_KEY_SEED_QUEUE_SIZE
, tr_sessionGetQueueSize( s
, TR_UP
) );
424 tr_bencDictAddBool( d
, TR_PREFS_KEY_SEED_QUEUE_ENABLED
, tr_sessionGetQueueEnabled( s
, TR_UP
) );
425 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, tr_sessionUsesAltSpeed( s
) );
426 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, tr_sessionGetAltSpeed_KBps( s
, TR_UP
) );
427 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, tr_sessionGetAltSpeed_KBps( s
, TR_DOWN
) );
428 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, tr_sessionGetAltSpeedBegin( s
) );
429 tr_bencDictAddBool( d
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, tr_sessionUsesAltSpeedTime( s
) );
430 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, tr_sessionGetAltSpeedEnd( s
) );
431 tr_bencDictAddInt ( d
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, tr_sessionGetAltSpeedDay( s
) );
432 tr_bencDictAddInt ( d
, TR_PREFS_KEY_USPEED_KBps
, tr_sessionGetSpeedLimit_KBps( s
, TR_UP
) );
433 tr_bencDictAddBool( d
, TR_PREFS_KEY_USPEED_ENABLED
, tr_sessionIsSpeedLimited( s
, TR_UP
) );
434 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UMASK
, s
->umask
);
435 tr_bencDictAddInt ( d
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, s
->uploadSlotsPerTorrent
);
436 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, tr_address_to_string( &s
->public_ipv4
->addr
) );
437 tr_bencDictAddStr ( d
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, tr_address_to_string( &s
->public_ipv6
->addr
) );
438 tr_bencDictAddBool( d
, TR_PREFS_KEY_START
, !tr_sessionGetPaused( s
) );
439 tr_bencDictAddBool( d
, TR_PREFS_KEY_TRASH_ORIGINAL
, tr_sessionGetDeleteSource( s
) );
443 tr_sessionLoadSettings( tr_benc
* d
, const char * configDir
, const char * appName
)
447 tr_benc fileSettings
;
448 tr_benc sessionDefaults
;
450 bool success
= false;
452 assert( tr_bencIsDict( d
) );
454 /* initializing the defaults: caller may have passed in some app-level defaults.
455 * preserve those and use the session defaults to fill in any missing gaps. */
456 tr_bencInitDict( &sessionDefaults
, 0 );
457 tr_sessionGetDefaultSettings( &sessionDefaults
);
458 tr_bencMergeDicts( &sessionDefaults
, d
);
459 tmp
= *d
; *d
= sessionDefaults
; sessionDefaults
= tmp
;
461 /* if caller didn't specify a config dir, use the default */
462 if( !configDir
|| !*configDir
)
463 configDir
= tr_getDefaultConfigDir( appName
);
465 /* file settings override the defaults */
466 filename
= tr_buildPath( configDir
, "settings.json", NULL
);
467 err
= tr_bencLoadFile( &fileSettings
, TR_FMT_JSON
, filename
);
469 tr_bencMergeDicts( d
, &fileSettings
);
470 tr_bencFree( &fileSettings
);
474 tr_bencFree( &sessionDefaults
);
476 success
= (err
==0) || (err
==ENOENT
);
481 tr_sessionSaveSettings( tr_session
* session
,
482 const char * configDir
,
483 const tr_benc
* clientSettings
)
486 char * filename
= tr_buildPath( configDir
, "settings.json", NULL
);
488 assert( tr_bencIsDict( clientSettings
) );
490 tr_bencInitDict( &settings
, 0 );
492 /* the existing file settings are the fallback values */
494 tr_benc fileSettings
;
495 const int err
= tr_bencLoadFile( &fileSettings
, TR_FMT_JSON
, filename
);
498 tr_bencMergeDicts( &settings
, &fileSettings
);
499 tr_bencFree( &fileSettings
);
503 /* the client's settings override the file settings */
504 tr_bencMergeDicts( &settings
, clientSettings
);
506 /* the session's true values override the file & client settings */
508 tr_benc sessionSettings
;
509 tr_bencInitDict( &sessionSettings
, 0 );
510 tr_sessionGetSettings( session
, &sessionSettings
);
511 tr_bencMergeDicts( &settings
, &sessionSettings
);
512 tr_bencFree( &sessionSettings
);
515 /* save the result */
516 tr_bencToFile( &settings
, TR_FMT_JSON
, filename
);
520 tr_bencFree( &settings
);
528 * Periodically save the .resume files of any torrents whose
529 * status has recently changed. This prevents loss of metadata
530 * in the case of a crash, unclean shutdown, clumsy user, etc.
533 onSaveTimer( int foo UNUSED
, short bar UNUSED
, void * vsession
)
535 tr_torrent
* tor
= NULL
;
536 tr_session
* session
= vsession
;
538 if( tr_cacheFlushDone( session
->cache
) )
539 tr_err( "Error while flushing completed pieces from cache" );
541 while(( tor
= tr_torrentNext( session
, tor
)))
542 tr_torrentSave( tor
);
544 tr_statsSaveDirty( session
);
546 tr_timerAdd( session
->saveTimer
, SAVE_INTERVAL_SECS
, 0 );
553 static void tr_sessionInitImpl( void * );
557 tr_session
* session
;
558 const char * configDir
;
560 bool messageQueuingEnabled
;
561 tr_benc
* clientSettings
;
565 tr_sessionInit( const char * tag
,
566 const char * configDir
,
567 bool messageQueuingEnabled
,
568 tr_benc
* clientSettings
)
571 tr_session
* session
;
572 struct init_data data
;
574 assert( tr_bencIsDict( clientSettings
) );
576 tr_timeUpdate( time( NULL
) );
578 /* initialize the bare skeleton of the session object */
579 session
= tr_new0( tr_session
, 1 );
580 session
->udp_socket
= -1;
581 session
->udp6_socket
= -1;
582 session
->lock
= tr_lockNew( );
583 session
->cache
= tr_cacheNew( 1024*1024*2 );
584 session
->tag
= tr_strdup( tag
);
585 session
->magicNumber
= SESSION_MAGIC_NUMBER
;
586 tr_bandwidthConstruct( &session
->bandwidth
, session
, NULL
);
587 tr_peerIdInit( session
->peer_id
);
588 tr_bencInitList( &session
->removedTorrents
, 0 );
590 /* nice to start logging at the very beginning */
591 if( tr_bencDictFindInt( clientSettings
, TR_PREFS_KEY_MSGLEVEL
, &i
) )
592 tr_setMessageLevel( i
);
594 /* start the libtransmission thread */
595 tr_netInit( ); /* must go before tr_eventInit */
596 tr_eventInit( session
);
597 assert( session
->events
!= NULL
);
599 /* run the rest in the libtransmission thread */
601 data
.session
= session
;
602 data
.configDir
= configDir
;
603 data
.messageQueuingEnabled
= messageQueuingEnabled
;
604 data
.clientSettings
= clientSettings
;
605 tr_runInEventThread( session
, tr_sessionInitImpl
, &data
);
612 static void turtleCheckClock( tr_session
* s
, struct tr_turtle_info
* t
);
615 onNowTimer( int foo UNUSED
, short bar UNUSED
, void * vsession
)
619 const int max
= 999999;
621 tr_torrent
* tor
= NULL
;
622 tr_session
* session
= vsession
;
623 const time_t now
= time( NULL
);
625 assert( tr_isSession( session
) );
626 assert( session
->nowTimer
!= NULL
);
629 *** tr_session things to do once per second
632 tr_timeUpdate( now
);
634 tr_dhtUpkeep( session
);
636 if( session
->turtle
.isClockEnabled
)
637 turtleCheckClock( session
, &session
->turtle
);
639 while(( tor
= tr_torrentNext( session
, tor
))) {
640 if( tor
->isRunning
) {
641 if( tr_torrentIsSeed( tor
) )
642 ++tor
->secondsSeeding
;
644 ++tor
->secondsDownloading
;
652 /* schedule the next timer for right after the next second begins */
653 gettimeofday( &tv
, NULL
);
654 usec
= 1000000 - tv
.tv_usec
;
655 if( usec
> max
) usec
= max
;
656 if( usec
< min
) usec
= min
;
657 tr_timerAdd( session
->nowTimer
, 0, usec
);
658 /* fprintf( stderr, "time %zu sec, %zu microsec\n", (size_t)tr_time(), (size_t)tv.tv_usec ); */
661 static void loadBlocklists( tr_session
* session
);
664 tr_sessionInitImpl( void * vdata
)
667 struct init_data
* data
= vdata
;
668 tr_benc
* clientSettings
= data
->clientSettings
;
669 tr_session
* session
= data
->session
;
671 assert( tr_amInEventThread( session
) );
672 assert( tr_bencIsDict( clientSettings
) );
674 dbgmsg( "tr_sessionInit: the session's top-level bandwidth object is %p",
675 &session
->bandwidth
);
677 tr_bencInitDict( &settings
, 0 );
678 tr_sessionGetDefaultSettings( &settings
);
679 tr_bencMergeDicts( &settings
, clientSettings
);
681 assert( session
->event_base
!= NULL
);
682 session
->nowTimer
= evtimer_new( session
->event_base
, onNowTimer
, session
);
683 onNowTimer( 0, 0, session
);
686 /* Don't exit when writing on a broken socket */
687 signal( SIGPIPE
, SIG_IGN
);
690 tr_setMessageQueuing( data
->messageQueuingEnabled
);
692 tr_setConfigDir( session
, data
->configDir
);
694 session
->peerMgr
= tr_peerMgrNew( session
);
696 session
->shared
= tr_sharedInit( session
);
703 char * filename
= tr_buildPath( session
->configDir
, "blocklists", NULL
);
704 tr_mkdirp( filename
, 0777 );
706 loadBlocklists( session
);
709 assert( tr_isSession( session
) );
711 session
->saveTimer
= evtimer_new( session
->event_base
, onSaveTimer
, session
);
712 tr_timerAdd( session
->saveTimer
, SAVE_INTERVAL_SECS
, 0 );
714 tr_announcerInit( session
);
716 /* first %s is the application name
717 second %s is the version number */
718 tr_inf( _( "%s %s started" ), TR_NAME
, LONG_VERSION_STRING
);
720 tr_statsInit( session
);
722 tr_webInit( session
);
724 tr_sessionSet( session
, &settings
);
726 tr_udpInit( session
);
728 if( session
->isLPDEnabled
)
729 tr_lpdInit( session
, &session
->public_ipv4
->addr
);
732 tr_bencFree( &settings
);
736 static void turtleBootstrap( tr_session
*, struct tr_turtle_info
* );
737 static void setPeerPort( tr_session
* session
, tr_port port
);
740 sessionSetImpl( void * vdata
)
746 struct tr_bindinfo b
;
747 struct init_data
* data
= vdata
;
748 tr_session
* session
= data
->session
;
749 tr_benc
* settings
= data
->clientSettings
;
750 struct tr_turtle_info
* turtle
= &session
->turtle
;
752 assert( tr_isSession( session
) );
753 assert( tr_bencIsDict( settings
) );
754 assert( tr_amInEventThread( session
) );
756 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_MSGLEVEL
, &i
) )
757 tr_setMessageLevel( i
);
759 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_UMASK
, &i
) ) {
760 session
->umask
= (mode_t
)i
;
761 umask( session
->umask
);
765 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_MAX_CACHE_SIZE_MB
, &i
) )
766 tr_sessionSetCacheLimit_MB( session
, i
);
767 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_LIMIT_TORRENT
, &i
) )
768 tr_sessionSetPeerLimitPerTorrent( session
, i
);
769 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PEX_ENABLED
, &boolVal
) )
770 tr_sessionSetPexEnabled( session
, boolVal
);
771 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_DHT_ENABLED
, &boolVal
) )
772 tr_sessionSetDHTEnabled( session
, boolVal
);
773 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_UTP_ENABLED
, &boolVal
) )
774 tr_sessionSetUTPEnabled( session
, boolVal
);
775 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_LPD_ENABLED
, &boolVal
) )
776 tr_sessionSetLPDEnabled( session
, boolVal
);
777 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ENCRYPTION
, &i
) )
778 tr_sessionSetEncryption( session
, i
);
779 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_PEER_SOCKET_TOS
, &str
) )
780 session
->peerSocketTOS
= parse_tos( str
);
781 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_PEER_CONGESTION_ALGORITHM
, &str
) )
782 session
->peer_congestion_algorithm
= tr_strdup(str
);
784 session
->peer_congestion_algorithm
= tr_strdup("");
785 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_BLOCKLIST_ENABLED
, &boolVal
) )
786 tr_blocklistSetEnabled( session
, boolVal
);
787 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_BLOCKLIST_URL
, &str
) )
788 tr_blocklistSetURL( session
, str
);
789 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_START
, &boolVal
) )
790 tr_sessionSetPaused( session
, !boolVal
);
791 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_TRASH_ORIGINAL
, &boolVal
) )
792 tr_sessionSetDeleteSource( session
, boolVal
);
795 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_QUEUE_STALLED_MINUTES
, &i
) )
796 tr_sessionSetQueueStalledMinutes( session
, i
);
797 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_QUEUE_STALLED_ENABLED
, &boolVal
) )
798 tr_sessionSetQueueStalledEnabled( session
, boolVal
);
799 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_DOWNLOAD_QUEUE_SIZE
, &i
) )
800 tr_sessionSetQueueSize( session
, TR_DOWN
, i
);
801 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_DOWNLOAD_QUEUE_ENABLED
, &boolVal
) )
802 tr_sessionSetQueueEnabled( session
, TR_DOWN
, boolVal
);
803 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_SEED_QUEUE_SIZE
, &i
) )
804 tr_sessionSetQueueSize( session
, TR_UP
, i
);
805 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_SEED_QUEUE_ENABLED
, &boolVal
) )
806 tr_sessionSetQueueEnabled( session
, TR_UP
, boolVal
);
808 /* files and directories */
809 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PREFETCH_ENABLED
, &boolVal
) )
810 session
->isPrefetchEnabled
= boolVal
;
811 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PREALLOCATION
, &i
) )
812 session
->preallocationMode
= i
;
813 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_DOWNLOAD_DIR
, &str
) )
814 tr_sessionSetDownloadDir( session
, str
);
815 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_INCOMPLETE_DIR
, &str
) )
816 tr_sessionSetIncompleteDir( session
, str
);
817 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED
, &boolVal
) )
818 tr_sessionSetIncompleteDirEnabled( session
, boolVal
);
819 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_RENAME_PARTIAL_FILES
, &boolVal
) )
820 tr_sessionSetIncompleteFileNamingEnabled( session
, boolVal
);
823 if( session
->rpcServer
!= NULL
) /* close the old one */
824 tr_rpcClose( &session
->rpcServer
);
825 session
->rpcServer
= tr_rpcInit( session
, settings
);
827 /* public addresses */
829 free_incoming_peer_port( session
);
831 str
= TR_PREFS_KEY_BIND_ADDRESS_IPV4
;
832 tr_bencDictFindStr( settings
, TR_PREFS_KEY_BIND_ADDRESS_IPV4
, &str
);
833 if( !tr_address_from_string( &b
.addr
, str
) || ( b
.addr
.type
!= TR_AF_INET
) )
834 b
.addr
= tr_inaddr_any
;
836 session
->public_ipv4
= tr_memdup( &b
, sizeof( struct tr_bindinfo
) );
838 str
= TR_PREFS_KEY_BIND_ADDRESS_IPV6
;
839 tr_bencDictFindStr( settings
, TR_PREFS_KEY_BIND_ADDRESS_IPV6
, &str
);
840 if( !tr_address_from_string( &b
.addr
, str
) || ( b
.addr
.type
!= TR_AF_INET6
) )
841 b
.addr
= tr_in6addr_any
;
843 session
->public_ipv6
= tr_memdup( &b
, sizeof( struct tr_bindinfo
) );
845 /* incoming peer port */
846 if( tr_bencDictFindInt ( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_LOW
, &i
) )
847 session
->randomPortLow
= i
;
848 if( tr_bencDictFindInt ( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_HIGH
, &i
) )
849 session
->randomPortHigh
= i
;
850 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START
, &boolVal
) )
851 tr_sessionSetPeerPortRandomOnStart( session
, boolVal
);
852 if( !tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_PORT
, &i
) )
853 i
= session
->private_peer_port
;
854 setPeerPort( session
, boolVal
? getRandomPort( session
) : i
);
855 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_PORT_FORWARDING
, &boolVal
) )
856 tr_sessionSetPortForwardingEnabled( session
, boolVal
);
858 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_PEER_LIMIT_GLOBAL
, &i
) )
859 session
->peerLimit
= i
;
864 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_UPLOAD_SLOTS_PER_TORRENT
, &i
) )
865 session
->uploadSlotsPerTorrent
= i
;
867 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_USPEED_KBps
, &i
) )
868 tr_sessionSetSpeedLimit_KBps( session
, TR_UP
, i
);
869 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_USPEED_ENABLED
, &boolVal
) )
870 tr_sessionLimitSpeed( session
, TR_UP
, boolVal
);
872 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_DSPEED_KBps
, &i
) )
873 tr_sessionSetSpeedLimit_KBps( session
, TR_DOWN
, i
);
874 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_DSPEED_ENABLED
, &boolVal
) )
875 tr_sessionLimitSpeed( session
, TR_DOWN
, boolVal
);
877 if( tr_bencDictFindReal( settings
, TR_PREFS_KEY_RATIO
, &d
) )
878 tr_sessionSetRatioLimit( session
, d
);
879 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_RATIO_ENABLED
, &boolVal
) )
880 tr_sessionSetRatioLimited( session
, boolVal
);
882 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_IDLE_LIMIT
, &i
) )
883 tr_sessionSetIdleLimit( session
, i
);
884 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_IDLE_LIMIT_ENABLED
, &boolVal
) )
885 tr_sessionSetIdleLimited( session
, boolVal
);
891 /* update the turtle mode's fields */
892 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_UP_KBps
, &i
) )
893 turtle
->speedLimit_Bps
[TR_UP
] = toSpeedBytes( i
);
894 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_DOWN_KBps
, &i
) )
895 turtle
->speedLimit_Bps
[TR_DOWN
] = toSpeedBytes( i
);
896 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_BEGIN
, &i
) )
897 turtle
->beginMinute
= i
;
898 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_END
, &i
) )
899 turtle
->endMinute
= i
;
900 if( tr_bencDictFindInt( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_DAY
, &i
) )
902 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_ALT_SPEED_TIME_ENABLED
, &boolVal
) )
903 turtle
->isClockEnabled
= boolVal
;
904 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_ALT_SPEED_ENABLED
, &boolVal
) )
905 turtle
->isEnabled
= boolVal
;
906 turtleBootstrap( session
, turtle
);
912 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_ENABLED
, &boolVal
) )
913 tr_sessionSetTorrentDoneScriptEnabled( session
, boolVal
);
914 if( tr_bencDictFindStr( settings
, TR_PREFS_KEY_SCRIPT_TORRENT_DONE_FILENAME
, &str
) )
915 tr_sessionSetTorrentDoneScript( session
, str
);
918 if( tr_bencDictFindBool( settings
, TR_PREFS_KEY_SCRAPE_PAUSED_TORRENTS
, &boolVal
) )
919 session
->scrapePausedTorrents
= boolVal
;
925 tr_sessionSet( tr_session
* session
, struct tr_benc
* settings
)
927 struct init_data data
;
929 data
.session
= session
;
930 data
.clientSettings
= settings
;
932 /* run the rest in the libtransmission thread */
933 tr_runInEventThread( session
, sessionSetImpl
, &data
);
943 tr_sessionSetDownloadDir( tr_session
* session
, const char * dir
)
945 assert( tr_isSession( session
) );
947 if( session
->downloadDir
!= dir
)
949 tr_free( session
->downloadDir
);
950 session
->downloadDir
= tr_strdup( dir
);
955 tr_sessionGetDownloadDir( const tr_session
* session
)
957 assert( tr_isSession( session
) );
959 return session
->downloadDir
;
963 tr_sessionGetDownloadDirFreeSpace( const tr_session
* session
)
965 assert( tr_isSession( session
) );
967 return tr_getFreeSpace( session
->downloadDir
);
975 tr_sessionSetIncompleteFileNamingEnabled( tr_session
* session
, bool b
)
977 assert( tr_isSession( session
) );
978 assert( tr_isBool( b
) );
980 session
->isIncompleteFileNamingEnabled
= b
;
984 tr_sessionIsIncompleteFileNamingEnabled( const tr_session
* session
)
986 assert( tr_isSession( session
) );
988 return session
->isIncompleteFileNamingEnabled
;
997 tr_sessionSetIncompleteDir( tr_session
* session
, const char * dir
)
999 assert( tr_isSession( session
) );
1001 if( session
->incompleteDir
!= dir
)
1003 tr_free( session
->incompleteDir
);
1005 session
->incompleteDir
= tr_strdup( dir
);
1010 tr_sessionGetIncompleteDir( const tr_session
* session
)
1012 assert( tr_isSession( session
) );
1014 return session
->incompleteDir
;
1018 tr_sessionSetIncompleteDirEnabled( tr_session
* session
, bool b
)
1020 assert( tr_isSession( session
) );
1021 assert( tr_isBool( b
) );
1023 session
->isIncompleteDirEnabled
= b
;
1027 tr_sessionIsIncompleteDirEnabled( const tr_session
* session
)
1029 assert( tr_isSession( session
) );
1031 return session
->isIncompleteDirEnabled
;
1039 tr_sessionLock( tr_session
* session
)
1041 assert( tr_isSession( session
) );
1043 tr_lockLock( session
->lock
);
1047 tr_sessionUnlock( tr_session
* session
)
1049 assert( tr_isSession( session
) );
1051 tr_lockUnlock( session
->lock
);
1055 tr_sessionIsLocked( const tr_session
* session
)
1057 return tr_isSession( session
) && tr_lockHave( session
->lock
);
1060 /***********************************************************************
1062 ***********************************************************************
1064 **********************************************************************/
1067 peerPortChanged( void * session
)
1069 tr_torrent
* tor
= NULL
;
1071 assert( tr_isSession( session
) );
1073 close_incoming_peer_port( session
);
1074 open_incoming_peer_port( session
);
1075 tr_sharedPortChanged( session
);
1077 while(( tor
= tr_torrentNext( session
, tor
)))
1078 tr_torrentChangeMyPort( tor
);
1082 setPeerPort( tr_session
* session
, tr_port port
)
1084 session
->private_peer_port
= port
;
1085 session
->public_peer_port
= port
;
1087 tr_runInEventThread( session
, peerPortChanged
, session
);
1091 tr_sessionSetPeerPort( tr_session
* session
, tr_port port
)
1093 if( tr_isSession( session
) && ( session
->private_peer_port
!= port
) )
1095 setPeerPort( session
, port
);
1100 tr_sessionGetPeerPort( const tr_session
* session
)
1102 return tr_isSession( session
) ? session
->private_peer_port
: 0;
1106 tr_sessionSetPeerPortRandom( tr_session
* session
)
1108 assert( tr_isSession( session
) );
1110 tr_sessionSetPeerPort( session
, getRandomPort( session
) );
1111 return session
->private_peer_port
;
1115 tr_sessionSetPeerPortRandomOnStart( tr_session
* session
,
1118 assert( tr_isSession( session
) );
1120 session
->isPortRandom
= random
;
1124 tr_sessionGetPeerPortRandomOnStart( tr_session
* session
)
1126 assert( tr_isSession( session
) );
1128 return session
->isPortRandom
;
1132 tr_sessionGetPortForwarding( const tr_session
* session
)
1134 assert( tr_isSession( session
) );
1136 return tr_sharedTraversalStatus( session
->shared
);
1144 tr_sessionSetRatioLimited( tr_session
* session
, bool isLimited
)
1146 assert( tr_isSession( session
) );
1148 session
->isRatioLimited
= isLimited
;
1152 tr_sessionSetRatioLimit( tr_session
* session
, double desiredRatio
)
1154 assert( tr_isSession( session
) );
1156 session
->desiredRatio
= desiredRatio
;
1160 tr_sessionIsRatioLimited( const tr_session
* session
)
1162 assert( tr_isSession( session
) );
1164 return session
->isRatioLimited
;
1168 tr_sessionGetRatioLimit( const tr_session
* session
)
1170 assert( tr_isSession( session
) );
1172 return session
->desiredRatio
;
1180 tr_sessionSetIdleLimited( tr_session
* session
, bool isLimited
)
1182 assert( tr_isSession( session
) );
1184 session
->isIdleLimited
= isLimited
;
1188 tr_sessionSetIdleLimit( tr_session
* session
, uint16_t idleMinutes
)
1190 assert( tr_isSession( session
) );
1192 session
->idleLimitMinutes
= idleMinutes
;
1196 tr_sessionIsIdleLimited( const tr_session
* session
)
1198 assert( tr_isSession( session
) );
1200 return session
->isIdleLimited
;
1204 tr_sessionGetIdleLimit( const tr_session
* session
)
1206 assert( tr_isSession( session
) );
1208 return session
->idleLimitMinutes
;
1218 tr_sessionGetActiveSpeedLimit_Bps( const tr_session
* session
, tr_direction dir
, int * setme_Bps
)
1220 int isLimited
= true;
1222 if( !tr_isSession( session
) )
1225 if( tr_sessionUsesAltSpeed( session
) )
1226 *setme_Bps
= tr_sessionGetAltSpeed_Bps( session
, dir
);
1227 else if( tr_sessionIsSpeedLimited( session
, dir
) )
1228 *setme_Bps
= tr_sessionGetSpeedLimit_Bps( session
, dir
);
1235 tr_sessionGetActiveSpeedLimit_KBps( const tr_session
* session
,
1237 double * setme_KBps
)
1240 const bool is_active
= tr_sessionGetActiveSpeedLimit_Bps( session
, dir
, &Bps
);
1241 *setme_KBps
= toSpeedKBps( Bps
);
1246 updateBandwidth( tr_session
* session
, tr_direction dir
)
1249 const bool isLimited
= tr_sessionGetActiveSpeedLimit_Bps( session
, dir
, &limit_Bps
);
1250 const bool zeroCase
= isLimited
&& !limit_Bps
;
1252 tr_bandwidthSetLimited( &session
->bandwidth
, dir
, isLimited
&& !zeroCase
);
1254 tr_bandwidthSetDesiredSpeed_Bps( &session
->bandwidth
, dir
, limit_Bps
);
1259 MINUTES_PER_HOUR
= 60,
1260 MINUTES_PER_DAY
= MINUTES_PER_HOUR
* 24,
1261 MINUTES_PER_WEEK
= MINUTES_PER_DAY
* 7
1265 turtleUpdateTable( struct tr_turtle_info
* t
)
1268 tr_bitfield
* b
= &t
->minutes
;
1270 tr_bitfieldSetHasNone( b
);
1272 for( day
=0; day
<7; ++day
)
1274 if( t
->days
& (1<<day
) )
1277 const time_t begin
= t
->beginMinute
;
1278 time_t end
= t
->endMinute
;
1281 end
+= MINUTES_PER_DAY
;
1283 for( i
=begin
; i
<end
; ++i
)
1284 tr_bitfieldAdd( b
, (i
+day
*MINUTES_PER_DAY
) % MINUTES_PER_WEEK
);
1290 altSpeedToggled( void * vsession
)
1292 tr_session
* session
= vsession
;
1293 struct tr_turtle_info
* t
= &session
->turtle
;
1295 assert( tr_isSession( session
) );
1297 updateBandwidth( session
, TR_UP
);
1298 updateBandwidth( session
, TR_DOWN
);
1300 if( t
->callback
!= NULL
)
1301 (*t
->callback
)( session
, t
->isEnabled
, t
->changedByUser
, t
->callbackUserData
);
1305 useAltSpeed( tr_session
* s
, struct tr_turtle_info
* t
,
1306 bool enabled
, bool byUser
)
1308 assert( tr_isSession( s
) );
1309 assert( t
!= NULL
);
1310 assert( tr_isBool( enabled
) );
1311 assert( tr_isBool( byUser
) );
1313 if( t
->isEnabled
!= enabled
)
1315 t
->isEnabled
= enabled
;
1316 t
->changedByUser
= byUser
;
1317 tr_runInEventThread( s
, altSpeedToggled
, s
);
1322 * @param enabled whether turtle should be on/off according to the scheduler
1323 * @param changed whether that's different from the previous minute
1326 testTurtleTime( const struct tr_turtle_info
* t
,
1332 size_t minute_of_the_week
;
1333 const time_t now
= tr_time( );
1335 tr_localtime_r( &now
, &tm
);
1337 minute_of_the_week
= tm
.tm_wday
* MINUTES_PER_DAY
1338 + tm
.tm_hour
* MINUTES_PER_HOUR
1340 if( minute_of_the_week
>= MINUTES_PER_WEEK
) /* leap minutes? */
1341 minute_of_the_week
= MINUTES_PER_WEEK
- 1;
1343 e
= tr_bitfieldHas( &t
->minutes
, minute_of_the_week
);
1344 if( enabled
!= NULL
)
1347 if( changed
!= NULL
)
1349 const size_t prev
= minute_of_the_week
> 0 ? minute_of_the_week
- 1
1350 : MINUTES_PER_WEEK
- 1;
1351 *changed
= e
!= tr_bitfieldHas( &t
->minutes
, prev
);
1356 turtleCheckClock( tr_session
* s
, struct tr_turtle_info
* t
)
1361 assert( t
->isClockEnabled
);
1363 testTurtleTime( t
, &enabled
, &changed
);
1367 tr_inf( "Time to turn %s turtle mode!", (enabled
?"on":"off") );
1368 useAltSpeed( s
, t
, enabled
, false );
1372 /* Called after the turtle's fields are loaded from an outside source.
1373 * It initializes the implementation fields
1374 * and turns on turtle mode if the clock settings say to. */
1376 turtleBootstrap( tr_session
* session
, struct tr_turtle_info
* turtle
)
1378 turtle
->changedByUser
= false;
1380 tr_bitfieldConstruct( &turtle
->minutes
, MINUTES_PER_WEEK
);
1382 turtleUpdateTable( turtle
);
1384 if( turtle
->isClockEnabled
)
1385 testTurtleTime( turtle
, &turtle
->isEnabled
, NULL
);
1387 altSpeedToggled( session
);
1391 **** Primary session speed limits
1395 tr_sessionSetSpeedLimit_Bps( tr_session
* s
, tr_direction d
, int Bps
)
1397 assert( tr_isSession( s
) );
1398 assert( tr_isDirection( d
) );
1401 s
->speedLimit_Bps
[d
] = Bps
;
1403 updateBandwidth( s
, d
);
1406 tr_sessionSetSpeedLimit_KBps( tr_session
* s
, tr_direction d
, int KBps
)
1408 tr_sessionSetSpeedLimit_Bps( s
, d
, toSpeedBytes( KBps
) );
1412 tr_sessionGetSpeedLimit_Bps( const tr_session
* s
, tr_direction d
)
1414 assert( tr_isSession( s
) );
1415 assert( tr_isDirection( d
) );
1417 return s
->speedLimit_Bps
[d
];
1420 tr_sessionGetSpeedLimit_KBps( const tr_session
* s
, tr_direction d
)
1422 return toSpeedKBps( tr_sessionGetSpeedLimit_Bps( s
, d
) );
1426 tr_sessionLimitSpeed( tr_session
* s
, tr_direction d
, bool b
)
1428 assert( tr_isSession( s
) );
1429 assert( tr_isDirection( d
) );
1430 assert( tr_isBool( b
) );
1432 s
->speedLimitEnabled
[d
] = b
;
1434 updateBandwidth( s
, d
);
1438 tr_sessionIsSpeedLimited( const tr_session
* s
, tr_direction d
)
1440 assert( tr_isSession( s
) );
1441 assert( tr_isDirection( d
) );
1443 return s
->speedLimitEnabled
[d
];
1447 **** Alternative speed limits that are used during scheduled times
1451 tr_sessionSetAltSpeed_Bps( tr_session
* s
, tr_direction d
, int Bps
)
1453 assert( tr_isSession( s
) );
1454 assert( tr_isDirection( d
) );
1457 s
->turtle
.speedLimit_Bps
[d
] = Bps
;
1459 updateBandwidth( s
, d
);
1463 tr_sessionSetAltSpeed_KBps( tr_session
* s
, tr_direction d
, int KBps
)
1465 tr_sessionSetAltSpeed_Bps( s
, d
, toSpeedBytes( KBps
) );
1469 tr_sessionGetAltSpeed_Bps( const tr_session
* s
, tr_direction d
)
1471 assert( tr_isSession( s
) );
1472 assert( tr_isDirection( d
) );
1474 return s
->turtle
.speedLimit_Bps
[d
];
1477 tr_sessionGetAltSpeed_KBps( const tr_session
* s
, tr_direction d
)
1479 return toSpeedKBps( tr_sessionGetAltSpeed_Bps( s
, d
) );
1483 userPokedTheClock( tr_session
* s
, struct tr_turtle_info
* t
)
1485 tr_dbg( "Refreshing the turtle mode clock due to user changes" );
1487 turtleUpdateTable( t
);
1489 if( t
->isClockEnabled
)
1491 bool enabled
, changed
;
1492 testTurtleTime( t
, &enabled
, &changed
);
1493 useAltSpeed( s
, t
, enabled
, true );
1498 tr_sessionUseAltSpeedTime( tr_session
* s
, bool b
)
1500 struct tr_turtle_info
* t
= &s
->turtle
;
1502 assert( tr_isSession( s
) );
1503 assert( tr_isBool ( b
) );
1505 if( t
->isClockEnabled
!= b
) {
1506 t
->isClockEnabled
= b
;
1507 userPokedTheClock( s
, t
);
1512 tr_sessionUsesAltSpeedTime( const tr_session
* s
)
1514 assert( tr_isSession( s
) );
1516 return s
->turtle
.isClockEnabled
;
1520 tr_sessionSetAltSpeedBegin( tr_session
* s
, int minute
)
1522 assert( tr_isSession( s
) );
1523 assert( 0<=minute
&& minute
<(60*24) );
1525 if( s
->turtle
.beginMinute
!= minute
) {
1526 s
->turtle
.beginMinute
= minute
;
1527 userPokedTheClock( s
, &s
->turtle
);
1532 tr_sessionGetAltSpeedBegin( const tr_session
* s
)
1534 assert( tr_isSession( s
) );
1536 return s
->turtle
.beginMinute
;
1540 tr_sessionSetAltSpeedEnd( tr_session
* s
, int minute
)
1542 assert( tr_isSession( s
) );
1543 assert( 0<=minute
&& minute
<(60*24) );
1545 if( s
->turtle
.endMinute
!= minute
) {
1546 s
->turtle
.endMinute
= minute
;
1547 userPokedTheClock( s
, &s
->turtle
);
1552 tr_sessionGetAltSpeedEnd( const tr_session
* s
)
1554 assert( tr_isSession( s
) );
1556 return s
->turtle
.endMinute
;
1560 tr_sessionSetAltSpeedDay( tr_session
* s
, tr_sched_day days
)
1562 assert( tr_isSession( s
) );
1564 if( s
->turtle
.days
!= days
) {
1565 s
->turtle
.days
= days
;
1566 userPokedTheClock( s
, &s
->turtle
);
1571 tr_sessionGetAltSpeedDay( const tr_session
* s
)
1573 assert( tr_isSession( s
) );
1575 return s
->turtle
.days
;
1579 tr_sessionUseAltSpeed( tr_session
* session
, bool enabled
)
1581 useAltSpeed( session
, &session
->turtle
, enabled
, true );
1585 tr_sessionUsesAltSpeed( const tr_session
* s
)
1587 assert( tr_isSession( s
) );
1589 return s
->turtle
.isEnabled
;
1593 tr_sessionSetAltSpeedFunc( tr_session
* session
,
1594 tr_altSpeedFunc func
,
1597 assert( tr_isSession( session
) );
1599 session
->turtle
.callback
= func
;
1600 session
->turtle
.callbackUserData
= userData
;
1604 tr_sessionClearAltSpeedFunc( tr_session
* session
)
1606 tr_sessionSetAltSpeedFunc( session
, NULL
, NULL
);
1614 tr_sessionSetPeerLimit( tr_session
* session
, uint16_t n
)
1616 assert( tr_isSession( session
) );
1618 session
->peerLimit
= n
;
1622 tr_sessionGetPeerLimit( const tr_session
* session
)
1624 assert( tr_isSession( session
) );
1626 return session
->peerLimit
;
1630 tr_sessionSetPeerLimitPerTorrent( tr_session
* session
, uint16_t n
)
1632 assert( tr_isSession( session
) );
1634 session
->peerLimitPerTorrent
= n
;
1638 tr_sessionGetPeerLimitPerTorrent( const tr_session
* session
)
1640 assert( tr_isSession( session
) );
1642 return session
->peerLimitPerTorrent
;
1650 tr_sessionSetPaused( tr_session
* session
, bool isPaused
)
1652 assert( tr_isSession( session
) );
1654 session
->pauseAddedTorrent
= isPaused
;
1658 tr_sessionGetPaused( const tr_session
* session
)
1660 assert( tr_isSession( session
) );
1662 return session
->pauseAddedTorrent
;
1666 tr_sessionSetDeleteSource( tr_session
* session
, bool deleteSource
)
1668 assert( tr_isSession( session
) );
1670 session
->deleteSourceTorrent
= deleteSource
;
1674 tr_sessionGetDeleteSource( const tr_session
* session
)
1676 assert( tr_isSession( session
) );
1678 return session
->deleteSourceTorrent
;
1686 tr_sessionGetPieceSpeed_Bps( const tr_session
* session
, tr_direction dir
)
1688 return tr_isSession( session
) ? tr_bandwidthGetPieceSpeed_Bps( &session
->bandwidth
, 0, dir
) : 0;
1692 tr_sessionGetRawSpeed_Bps( const tr_session
* session
, tr_direction dir
)
1694 return tr_isSession( session
) ? tr_bandwidthGetRawSpeed_Bps( &session
->bandwidth
, 0, dir
) : 0;
1697 tr_sessionGetRawSpeed_KBps( const tr_session
* session
, tr_direction dir
)
1699 return toSpeedKBps( tr_sessionGetRawSpeed_Bps( session
, dir
) );
1704 tr_sessionCountTorrents( const tr_session
* session
)
1706 return tr_isSession( session
) ? session
->torrentCount
: 0;
1710 compareTorrentByCur( const void * va
, const void * vb
)
1712 const tr_torrent
* a
= *(const tr_torrent
**)va
;
1713 const tr_torrent
* b
= *(const tr_torrent
**)vb
;
1714 const uint64_t aCur
= a
->downloadedCur
+ a
->uploadedCur
;
1715 const uint64_t bCur
= b
->downloadedCur
+ b
->uploadedCur
;
1718 return aCur
> bCur
? -1 : 1; /* close the biggest torrents first */
1723 static void closeBlocklists( tr_session
* );
1726 sessionCloseImpl( void * vsession
)
1728 tr_session
* session
= vsession
;
1731 tr_torrent
** torrents
;
1733 assert( tr_isSession( session
) );
1735 free_incoming_peer_port( session
);
1737 if( session
->isLPDEnabled
)
1738 tr_lpdUninit( session
);
1740 tr_utpClose( session
);
1741 tr_dhtUninit( session
);
1743 event_free( session
->saveTimer
);
1744 session
->saveTimer
= NULL
;
1746 event_free( session
->nowTimer
);
1747 session
->nowTimer
= NULL
;
1749 tr_verifyClose( session
);
1750 tr_sharedClose( session
);
1751 tr_rpcClose( &session
->rpcServer
);
1753 /* Close the torrents. Get the most active ones first so that
1754 * if we can't get them all closed in a reasonable amount of time,
1755 * at least we get the most important ones first. */
1757 n
= session
->torrentCount
;
1758 torrents
= tr_new( tr_torrent
*, session
->torrentCount
);
1759 for( i
= 0; i
< n
; ++i
)
1760 torrents
[i
] = tor
= tr_torrentNext( session
, tor
);
1761 qsort( torrents
, n
, sizeof( tr_torrent
* ), compareTorrentByCur
);
1762 for( i
= 0; i
< n
; ++i
)
1763 tr_torrentFree( torrents
[i
] );
1764 tr_free( torrents
);
1766 /* Close the announcer *after* closing the torrents
1767 so that all the &event=stopped messages will be
1768 queued to be sent by tr_announcerClose() */
1769 tr_announcerClose( session
);
1771 /* and this goes *after* announcer close so that
1772 it won't be idle until the announce events are sent... */
1773 tr_webClose( session
, TR_WEB_CLOSE_WHEN_IDLE
);
1775 tr_cacheFree( session
->cache
);
1776 session
->cache
= NULL
;
1778 /* gotta keep udp running long enough to send out all
1779 the &event=stopped UDP tracker messages */
1780 while( !tr_tracker_udp_is_idle( session
) ) {
1781 tr_tracker_udp_upkeep( session
);
1782 tr_wait_msec( 100 );
1785 /* we had to wait until UDP trackers were closed before closing these: */
1786 evdns_base_free( session
->evdns_base
, 0 );
1787 session
->evdns_base
= NULL
;
1788 tr_tracker_udp_close( session
);
1789 tr_udpUninit( session
);
1791 tr_statsClose( session
);
1792 tr_peerMgrFree( session
->peerMgr
);
1794 closeBlocklists( session
);
1796 tr_fdClose( session
);
1798 session
->isClosed
= true;
1802 deadlineReached( const time_t deadline
)
1804 return time( NULL
) >= deadline
;
1807 #define SHUTDOWN_MAX_SECONDS 20
1810 tr_sessionClose( tr_session
* session
)
1812 const time_t deadline
= time( NULL
) + SHUTDOWN_MAX_SECONDS
;
1814 assert( tr_isSession( session
) );
1816 dbgmsg( "shutting down transmission session %p... now is %zu, deadline is %zu", session
, (size_t)time(NULL
), (size_t)deadline
);
1818 /* close the session */
1819 tr_runInEventThread( session
, sessionCloseImpl
, session
);
1820 while( !session
->isClosed
&& !deadlineReached( deadline
) )
1822 dbgmsg( "waiting for the libtransmission thread to finish" );
1823 tr_wait_msec( 100 );
1826 /* "shared" and "tracker" have live sockets,
1827 * so we need to keep the transmission thread alive
1828 * for a bit while they tell the router & tracker
1829 * that we're closing now */
1830 while( ( session
->shared
|| session
->web
|| session
->announcer
|| session
->announcer_udp
)
1831 && !deadlineReached( deadline
) )
1833 dbgmsg( "waiting on port unmap (%p) or announcer (%p)... now %zu deadline %zu",
1834 session
->shared
, session
->announcer
, (size_t)time(NULL
), (size_t)deadline
);
1835 tr_wait_msec( 100 );
1838 tr_webClose( session
, TR_WEB_CLOSE_NOW
);
1840 /* close the libtransmission thread */
1841 tr_eventClose( session
);
1842 while( session
->events
!= NULL
)
1844 static bool forced
= false;
1845 dbgmsg( "waiting for libtransmission thread to finish... now %zu deadline %zu", (size_t)time(NULL
), (size_t)deadline
);
1846 tr_wait_msec( 500 );
1847 if( deadlineReached( deadline
) && !forced
)
1849 dbgmsg( "calling event_loopbreak()" );
1851 event_base_loopbreak( session
->event_base
);
1853 if( deadlineReached( deadline
+3 ) )
1855 dbgmsg( "deadline+3 reached... calling break...\n" );
1860 /* free the session memory */
1861 tr_bencFree( &session
->removedTorrents
);
1862 tr_bandwidthDestruct( &session
->bandwidth
);
1863 tr_bitfieldDestruct( &session
->turtle
.minutes
);
1864 tr_lockFree( session
->lock
);
1865 if( session
->metainfoLookup
) {
1866 tr_bencFree( session
->metainfoLookup
);
1867 tr_free( session
->metainfoLookup
);
1869 tr_free( session
->torrentDoneScript
);
1870 tr_free( session
->tag
);
1871 tr_free( session
->configDir
);
1872 tr_free( session
->resumeDir
);
1873 tr_free( session
->torrentDir
);
1874 tr_free( session
->downloadDir
);
1875 tr_free( session
->incompleteDir
);
1876 tr_free( session
->blocklist_url
);
1877 tr_free( session
->peer_congestion_algorithm
);
1881 struct sessionLoadTorrentsData
1883 tr_session
* session
;
1886 tr_torrent
** torrents
;
1891 sessionLoadTorrents( void * vdata
)
1898 tr_list
* list
= NULL
;
1899 struct sessionLoadTorrentsData
* data
= vdata
;
1900 const char * dirname
= tr_getTorrentDir( data
->session
);
1902 assert( tr_isSession( data
->session
) );
1904 tr_ctorSetSave( data
->ctor
, false ); /* since we already have them */
1906 if( !stat( dirname
, &sb
)
1907 && S_ISDIR( sb
.st_mode
)
1908 && ( ( odir
= opendir ( dirname
) ) ) )
1911 for( d
= readdir( odir
); d
!= NULL
; d
= readdir( odir
) )
1913 if( tr_str_has_suffix( d
->d_name
, ".torrent" ) )
1916 char * path
= tr_buildPath( dirname
, d
->d_name
, NULL
);
1917 tr_ctorSetMetainfoFromFile( data
->ctor
, path
);
1918 if(( tor
= tr_torrentNew( data
->ctor
, NULL
)))
1920 tr_list_prepend( &list
, tor
);
1929 data
->torrents
= tr_new( tr_torrent
*, n
);
1930 for( i
= 0, l
= list
; l
!= NULL
; l
= l
->next
)
1931 data
->torrents
[i
++] = (tr_torrent
*) l
->data
;
1934 tr_list_free( &list
, NULL
);
1937 tr_inf( _( "Loaded %d torrents" ), n
);
1939 if( data
->setmeCount
)
1940 *data
->setmeCount
= n
;
1946 tr_sessionLoadTorrents( tr_session
* session
,
1950 struct sessionLoadTorrentsData data
;
1952 data
.session
= session
;
1954 data
.setmeCount
= setmeCount
;
1955 data
.torrents
= NULL
;
1958 tr_runInEventThread( session
, sessionLoadTorrents
, &data
);
1960 tr_wait_msec( 100 );
1962 return data
.torrents
;
1970 tr_sessionSetPexEnabled( tr_session
* session
, bool enabled
)
1972 assert( tr_isSession( session
) );
1974 session
->isPexEnabled
= enabled
!= 0;
1978 tr_sessionIsPexEnabled( const tr_session
* session
)
1980 assert( tr_isSession( session
) );
1982 return session
->isPexEnabled
;
1986 tr_sessionAllowsDHT( const tr_session
* session
)
1988 return tr_sessionIsDHTEnabled( session
);
1992 tr_sessionIsDHTEnabled( const tr_session
* session
)
1994 assert( tr_isSession( session
) );
1996 return session
->isDHTEnabled
;
2000 toggleDHTImpl( void * data
)
2002 tr_session
* session
= data
;
2003 assert( tr_isSession( session
) );
2005 tr_udpUninit( session
);
2006 session
->isDHTEnabled
= !session
->isDHTEnabled
;
2007 tr_udpInit( session
);
2011 tr_sessionSetDHTEnabled( tr_session
* session
, bool enabled
)
2013 assert( tr_isSession( session
) );
2014 assert( tr_isBool( enabled
) );
2016 if( ( enabled
!= 0 ) != ( session
->isDHTEnabled
!= 0 ) )
2017 tr_runInEventThread( session
, toggleDHTImpl
, session
);
2025 tr_sessionIsUTPEnabled( const tr_session
* session
)
2027 assert( tr_isSession( session
) );
2030 return session
->isUTPEnabled
;
2037 toggle_utp( void * data
)
2039 tr_session
* session
= data
;
2040 assert( tr_isSession( session
) );
2042 session
->isUTPEnabled
= !session
->isUTPEnabled
;
2044 tr_udpSetSocketBuffers( session
);
2046 /* But don't call tr_utpClose -- see reset_timer in tr-utp.c for an
2051 tr_sessionSetUTPEnabled( tr_session
* session
, bool enabled
)
2053 assert( tr_isSession( session
) );
2054 assert( tr_isBool( enabled
) );
2056 if( ( enabled
!= 0 ) != ( session
->isUTPEnabled
!= 0 ) )
2057 tr_runInEventThread( session
, toggle_utp
, session
);
2065 toggleLPDImpl( void * data
)
2067 tr_session
* session
= data
;
2068 assert( tr_isSession( session
) );
2070 if( session
->isLPDEnabled
)
2071 tr_lpdUninit( session
);
2073 session
->isLPDEnabled
= !session
->isLPDEnabled
;
2075 if( session
->isLPDEnabled
)
2076 tr_lpdInit( session
, &session
->public_ipv4
->addr
);
2080 tr_sessionSetLPDEnabled( tr_session
* session
, bool enabled
)
2082 assert( tr_isSession( session
) );
2083 assert( tr_isBool( enabled
) );
2085 if( ( enabled
!= 0 ) != ( session
->isLPDEnabled
!= 0 ) )
2086 tr_runInEventThread( session
, toggleLPDImpl
, session
);
2090 tr_sessionIsLPDEnabled( const tr_session
* session
)
2092 assert( tr_isSession( session
) );
2094 return session
->isLPDEnabled
;
2098 tr_sessionAllowsLPD( const tr_session
* session
)
2100 return tr_sessionIsLPDEnabled( session
);
2108 tr_sessionSetCacheLimit_MB( tr_session
* session
, int max_bytes
)
2110 assert( tr_isSession( session
) );
2112 tr_cacheSetLimit( session
->cache
, toMemBytes( max_bytes
) );
2116 tr_sessionGetCacheLimit_MB( const tr_session
* session
)
2118 assert( tr_isSession( session
) );
2120 return toMemMB( tr_cacheGetLimit( session
->cache
) );
2127 struct port_forwarding_data
2130 struct tr_shared
* shared
;
2134 setPortForwardingEnabled( void * vdata
)
2136 struct port_forwarding_data
* data
= vdata
;
2137 tr_sharedTraversalEnable( data
->shared
, data
->enabled
);
2142 tr_sessionSetPortForwardingEnabled( tr_session
* session
, bool enabled
)
2144 struct port_forwarding_data
* d
;
2145 d
= tr_new0( struct port_forwarding_data
, 1 );
2146 d
->shared
= session
->shared
;
2147 d
->enabled
= enabled
;
2148 tr_runInEventThread( session
, setPortForwardingEnabled
, d
);
2152 tr_sessionIsPortForwardingEnabled( const tr_session
* session
)
2154 assert( tr_isSession( session
) );
2156 return tr_sharedTraversalIsEnabled( session
->shared
);
2164 tr_stringEndsWith( const char * str
, const char * end
)
2166 const size_t slen
= strlen( str
);
2167 const size_t elen
= strlen( end
);
2169 return slen
>= elen
&& !memcmp( &str
[slen
- elen
], end
, elen
);
2173 loadBlocklists( tr_session
* session
)
2180 tr_list
* list
= NULL
;
2181 const bool isEnabled
= session
->isBlocklistEnabled
;
2183 /* walk through the directory and find blocklists */
2184 dirname
= tr_buildPath( session
->configDir
, "blocklists", NULL
);
2186 &sb
) && S_ISDIR( sb
.st_mode
)
2187 && ( ( odir
= opendir( dirname
) ) ) )
2190 for( d
= readdir( odir
); d
; d
= readdir( odir
) )
2194 if( !d
->d_name
|| d
->d_name
[0] == '.' ) /* skip dotfiles, ., and ..
2198 filename
= tr_buildPath( dirname
, d
->d_name
, NULL
);
2200 if( tr_stringEndsWith( filename
, ".bin" ) )
2202 /* if we don't already have this blocklist, add it */
2203 if( !tr_list_find( list
, filename
,
2204 (TrListCompareFunc
)strcmp
) )
2206 tr_list_append( &list
,
2207 _tr_blocklistNew( filename
, isEnabled
) );
2213 /* strip out the file suffix, if there is one, and add ".bin"
2216 const char * dot
= strrchr( d
->d_name
, '.' );
2217 const int len
= dot
? dot
- d
->d_name
2218 : (int)strlen( d
->d_name
);
2219 char * tmp
= tr_strdup_printf(
2220 "%s" TR_PATH_DELIMITER_STR
"%*.*s.bin",
2221 dirname
, len
, len
, d
->d_name
);
2222 b
= _tr_blocklistNew( tmp
, isEnabled
);
2223 _tr_blocklistSetContent( b
, filename
);
2224 tr_list_append( &list
, b
);
2229 tr_free( filename
);
2235 session
->blocklists
= list
;
2238 tr_dbg( "Found %d blocklists in \"%s\"", binCount
, dirname
);
2240 tr_dbg( "Found %d new blocklists in \"%s\"", newCount
, dirname
);
2246 closeBlocklists( tr_session
* session
)
2248 tr_list_free( &session
->blocklists
,
2249 (TrListForeachFunc
)_tr_blocklistFree
);
2253 tr_sessionReloadBlocklists( tr_session
* session
)
2255 closeBlocklists( session
);
2256 loadBlocklists( session
);
2258 tr_peerMgrOnBlocklistChanged( session
->peerMgr
);
2262 tr_blocklistGetRuleCount( const tr_session
* session
)
2267 assert( tr_isSession( session
) );
2269 for( l
= session
->blocklists
; l
; l
= l
->next
)
2270 n
+= _tr_blocklistGetRuleCount( l
->data
);
2275 tr_blocklistIsEnabled( const tr_session
* session
)
2277 assert( tr_isSession( session
) );
2279 return session
->isBlocklistEnabled
;
2283 tr_blocklistSetEnabled( tr_session
* session
, bool isEnabled
)
2287 assert( tr_isSession( session
) );
2289 session
->isBlocklistEnabled
= isEnabled
!= 0;
2291 for( l
=session
->blocklists
; l
!=NULL
; l
=l
->next
)
2292 _tr_blocklistSetEnabled( l
->data
, isEnabled
);
2296 tr_blocklistExists( const tr_session
* session
)
2298 assert( tr_isSession( session
) );
2300 return session
->blocklists
!= NULL
;
2304 tr_blocklistSetContent( tr_session
* session
, const char * contentFilename
)
2309 const char * defaultName
= DEFAULT_BLOCKLIST_FILENAME
;
2310 tr_sessionLock( session
);
2312 for( b
= NULL
, l
= session
->blocklists
; !b
&& l
; l
= l
->next
)
2313 if( tr_stringEndsWith( _tr_blocklistGetFilename( l
->data
),
2319 char * path
= tr_buildPath( session
->configDir
, "blocklists", defaultName
, NULL
);
2320 b
= _tr_blocklistNew( path
, session
->isBlocklistEnabled
);
2321 tr_list_append( &session
->blocklists
, b
);
2325 ruleCount
= _tr_blocklistSetContent( b
, contentFilename
);
2326 tr_sessionUnlock( session
);
2331 tr_sessionIsAddressBlocked( const tr_session
* session
,
2332 const tr_address
* addr
)
2336 assert( tr_isSession( session
) );
2338 for( l
= session
->blocklists
; l
; l
= l
->next
)
2339 if( _tr_blocklistHasAddress( l
->data
, addr
) )
2345 tr_blocklistSetURL( tr_session
* session
, const char * url
)
2347 if( session
->blocklist_url
!= url
)
2349 tr_free( session
->blocklist_url
);
2350 session
->blocklist_url
= tr_strdup( url
);
2355 tr_blocklistGetURL ( const tr_session
* session
)
2357 return session
->blocklist_url
;
2366 metainfoLookupInit( tr_session
* session
)
2369 const char * dirname
= tr_getTorrentDir( session
);
2371 tr_ctor
* ctor
= NULL
;
2375 assert( tr_isSession( session
) );
2377 /* walk through the directory and find the mappings */
2378 lookup
= tr_new0( tr_benc
, 1 );
2379 tr_bencInitDict( lookup
, 0 );
2380 ctor
= tr_ctorNew( session
);
2381 tr_ctorSetSave( ctor
, false ); /* since we already have them */
2382 if( !stat( dirname
, &sb
) && S_ISDIR( sb
.st_mode
) && ( ( odir
= opendir( dirname
) ) ) )
2385 while(( d
= readdir( odir
)))
2387 if( tr_str_has_suffix( d
->d_name
, ".torrent" ) )
2390 char * path
= tr_buildPath( dirname
, d
->d_name
, NULL
);
2391 tr_ctorSetMetainfoFromFile( ctor
, path
);
2392 if( !tr_torrentParse( ctor
, &inf
) )
2395 tr_bencDictAddStr( lookup
, inf
.hashString
, path
);
2402 tr_ctorFree( ctor
);
2404 session
->metainfoLookup
= lookup
;
2405 tr_dbg( "Found %d torrents in \"%s\"", n
, dirname
);
2409 tr_sessionFindTorrentFile( const tr_session
* session
,
2410 const char * hashString
)
2412 const char * filename
= NULL
;
2413 if( !session
->metainfoLookup
)
2414 metainfoLookupInit( (tr_session
*)session
);
2415 tr_bencDictFindStr( session
->metainfoLookup
, hashString
, &filename
);
2420 tr_sessionSetTorrentFile( tr_session
* session
,
2421 const char * hashString
,
2422 const char * filename
)
2424 /* since we walk session->configDir/torrents/ to build the lookup table,
2425 * and tr_sessionSetTorrentFile() is just to tell us there's a new file
2426 * in that same directory, we don't need to do anything here if the
2427 * lookup table hasn't been built yet */
2428 if( session
->metainfoLookup
)
2429 tr_bencDictAddStr( session
->metainfoLookup
, hashString
, filename
);
2437 tr_sessionSetRPCEnabled( tr_session
* session
, bool isEnabled
)
2439 assert( tr_isSession( session
) );
2441 tr_rpcSetEnabled( session
->rpcServer
, isEnabled
);
2445 tr_sessionIsRPCEnabled( const tr_session
* session
)
2447 assert( tr_isSession( session
) );
2449 return tr_rpcIsEnabled( session
->rpcServer
);
2453 tr_sessionSetRPCPort( tr_session
* session
,
2456 assert( tr_isSession( session
) );
2458 tr_rpcSetPort( session
->rpcServer
, port
);
2462 tr_sessionGetRPCPort( const tr_session
* session
)
2464 assert( tr_isSession( session
) );
2466 return tr_rpcGetPort( session
->rpcServer
);
2470 tr_sessionSetRPCUrl( tr_session
* session
,
2473 assert( tr_isSession( session
) );
2475 tr_rpcSetUrl( session
->rpcServer
, url
);
2479 tr_sessionGetRPCUrl( const tr_session
* session
)
2481 assert( tr_isSession( session
) );
2483 return tr_rpcGetUrl( session
->rpcServer
);
2487 tr_sessionSetRPCCallback( tr_session
* session
,
2491 assert( tr_isSession( session
) );
2493 session
->rpc_func
= func
;
2494 session
->rpc_func_user_data
= user_data
;
2498 tr_sessionSetRPCWhitelist( tr_session
* session
,
2499 const char * whitelist
)
2501 assert( tr_isSession( session
) );
2503 tr_rpcSetWhitelist( session
->rpcServer
, whitelist
);
2507 tr_sessionGetRPCWhitelist( const tr_session
* session
)
2509 assert( tr_isSession( session
) );
2511 return tr_rpcGetWhitelist( session
->rpcServer
);
2515 tr_sessionSetRPCWhitelistEnabled( tr_session
* session
, bool isEnabled
)
2517 assert( tr_isSession( session
) );
2519 tr_rpcSetWhitelistEnabled( session
->rpcServer
, isEnabled
);
2523 tr_sessionGetRPCWhitelistEnabled( const tr_session
* session
)
2525 assert( tr_isSession( session
) );
2527 return tr_rpcGetWhitelistEnabled( session
->rpcServer
);
2532 tr_sessionSetRPCPassword( tr_session
* session
,
2533 const char * password
)
2535 assert( tr_isSession( session
) );
2537 tr_rpcSetPassword( session
->rpcServer
, password
);
2541 tr_sessionGetRPCPassword( const tr_session
* session
)
2543 assert( tr_isSession( session
) );
2545 return tr_rpcGetPassword( session
->rpcServer
);
2549 tr_sessionSetRPCUsername( tr_session
* session
,
2550 const char * username
)
2552 assert( tr_isSession( session
) );
2554 tr_rpcSetUsername( session
->rpcServer
, username
);
2558 tr_sessionGetRPCUsername( const tr_session
* session
)
2560 assert( tr_isSession( session
) );
2562 return tr_rpcGetUsername( session
->rpcServer
);
2566 tr_sessionSetRPCPasswordEnabled( tr_session
* session
, bool isEnabled
)
2568 assert( tr_isSession( session
) );
2570 tr_rpcSetPasswordEnabled( session
->rpcServer
, isEnabled
);
2574 tr_sessionIsRPCPasswordEnabled( const tr_session
* session
)
2576 assert( tr_isSession( session
) );
2578 return tr_rpcIsPasswordEnabled( session
->rpcServer
);
2582 tr_sessionGetRPCBindAddress( const tr_session
* session
)
2584 assert( tr_isSession( session
) );
2586 return tr_rpcGetBindAddress( session
->rpcServer
);
2594 tr_sessionIsTorrentDoneScriptEnabled( const tr_session
* session
)
2596 assert( tr_isSession( session
) );
2598 return session
->isTorrentDoneScriptEnabled
;
2602 tr_sessionSetTorrentDoneScriptEnabled( tr_session
* session
, bool isEnabled
)
2604 assert( tr_isSession( session
) );
2605 assert( tr_isBool( isEnabled
) );
2607 session
->isTorrentDoneScriptEnabled
= isEnabled
;
2611 tr_sessionGetTorrentDoneScript( const tr_session
* session
)
2613 assert( tr_isSession( session
) );
2615 return session
->torrentDoneScript
;
2619 tr_sessionSetTorrentDoneScript( tr_session
* session
, const char * scriptFilename
)
2621 assert( tr_isSession( session
) );
2623 if( session
->torrentDoneScript
!= scriptFilename
)
2625 tr_free( session
->torrentDoneScript
);
2626 session
->torrentDoneScript
= tr_strdup( scriptFilename
);
2635 tr_sessionSetQueueSize( tr_session
* session
, tr_direction dir
, int n
)
2637 assert( tr_isSession( session
) );
2638 assert( tr_isDirection( dir
) );
2640 session
->queueSize
[dir
] = n
;
2644 tr_sessionGetQueueSize( const tr_session
* session
, tr_direction dir
)
2646 assert( tr_isSession( session
) );
2647 assert( tr_isDirection( dir
) );
2649 return session
->queueSize
[dir
];
2653 tr_sessionSetQueueEnabled( tr_session
* session
, tr_direction dir
, bool is_enabled
)
2655 assert( tr_isSession( session
) );
2656 assert( tr_isDirection( dir
) );
2657 assert( tr_isBool( is_enabled
) );
2659 session
->queueEnabled
[dir
] = is_enabled
;
2663 tr_sessionGetQueueEnabled( const tr_session
* session
, tr_direction dir
)
2665 assert( tr_isSession( session
) );
2666 assert( tr_isDirection( dir
) );
2668 return session
->queueEnabled
[dir
];
2672 tr_sessionSetQueueStalledMinutes( tr_session
* session
, int minutes
)
2674 assert( tr_isSession( session
) );
2675 assert( minutes
> 0 );
2677 session
->queueStalledMinutes
= minutes
;
2681 tr_sessionSetQueueStalledEnabled( tr_session
* session
, bool is_enabled
)
2683 assert( tr_isSession( session
) );
2684 assert( tr_isBool( is_enabled
) );
2686 session
->stalledEnabled
= is_enabled
;
2690 tr_sessionGetQueueStalledEnabled( const tr_session
* session
)
2692 assert( tr_isSession( session
) );
2694 return session
->stalledEnabled
;
2698 tr_sessionGetQueueStalledMinutes( const tr_session
* session
)
2700 assert( tr_isSession( session
) );
2702 return session
->queueStalledMinutes
;
2706 tr_sessionGetNextQueuedTorrent( tr_session
* session
, tr_direction direction
)
2708 tr_torrent
* tor
= NULL
;
2709 tr_torrent
* best_tor
= NULL
;
2710 int best_position
= INT_MAX
;
2712 assert( tr_isSession( session
) );
2713 assert( tr_isDirection( direction
) );
2715 while(( tor
= tr_torrentNext( session
, tor
)))
2719 if( !tr_torrentIsQueued( tor
) )
2721 if( direction
!= tr_torrentGetQueueDirection( tor
) )
2724 position
= tr_torrentGetQueuePosition( tor
);
2725 if( best_position
> position
) {
2726 best_position
= position
;
2735 tr_sessionCountQueueFreeSlots( tr_session
* session
, tr_direction dir
)
2739 const int max
= tr_sessionGetQueueSize( session
, dir
);
2740 const tr_torrent_activity activity
= dir
== TR_UP
? TR_STATUS_SEED
: TR_STATUS_DOWNLOAD
;
2742 if( !tr_sessionGetQueueEnabled( session
, dir
) )
2747 while(( tor
= tr_torrentNext( session
, tor
)))
2748 if( !tr_torrentIsStalled( tor
) )
2749 if( tr_torrentGetActivity( tor
) == activity
)
2752 if( active_count
>= max
)
2755 return max
- active_count
;