Transmission: update from 2.42 to 2.50
[tomato.git] / release / src / router / transmission / libtransmission / session.c
blob8fa0e3ac4ba7cfd174037386cc823deb2955cc76
1 /*
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 $
13 #include <assert.h>
14 #include <errno.h> /* ENOENT */
15 #include <stdlib.h>
16 #include <string.h> /* memcpy */
18 #include <signal.h>
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"
31 #include "bencode.h"
32 #include "blocklist.h"
33 #include "cache.h"
34 #include "crypto.h"
35 #include "fdlimit.h"
36 #include "list.h"
37 #include "net.h"
38 #include "peer-io.h"
39 #include "peer-mgr.h"
40 #include "platform.h" /* tr_lock, tr_getTorrentDir(), tr_getFreeSpace() */
41 #include "port-forwarding.h"
42 #include "rpc-server.h"
43 #include "session.h"
44 #include "stats.h"
45 #include "torrent.h"
46 #include "tr-dht.h" /* tr_dhtUpkeep() */
47 #include "tr-udp.h"
48 #include "tr-utp.h"
49 #include "tr-lpd.h"
50 #include "trevent.h"
51 #include "utils.h"
52 #include "verify.h"
53 #include "version.h"
54 #include "web.h"
56 enum
58 #ifdef TR_LIGHTWEIGHT
59 DEFAULT_CACHE_SIZE_MB = 2,
60 DEFAULT_PREFETCH_ENABLED = false,
61 #else
62 DEFAULT_CACHE_SIZE_MB = 4,
63 DEFAULT_PREFETCH_ENABLED = true,
64 #endif
65 SAVE_INTERVAL_SECS = 360
69 #define dbgmsg( ... ) \
70 do { \
71 if( tr_deepLoggingIsActive( ) ) \
72 tr_deepLog( __FILE__, __LINE__, NULL, __VA_ARGS__ ); \
73 } while( 0 )
75 static tr_port
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) */
85 void
86 tr_peerIdInit( uint8_t * buf )
88 int i;
89 int val;
90 int total = 0;
91 const char * pool = "0123456789abcdefghijklmnopqrstuvwxyz";
92 const int base = 36;
94 memcpy( buf, PEERID_PREFIX, 8 );
96 tr_cryptoRandBuf( buf+8, 11 );
97 for( i=8; i<19; ++i ) {
98 val = buf[i] % base;
99 total += val;
100 buf[i] = pool[val];
103 val = total % base ? base - ( total % base ) : 0;
104 buf[19] = pool[val];
105 buf[20] = '\0';
108 /***
109 ****
110 ***/
112 tr_encryption_mode
113 tr_sessionGetEncryption( tr_session * session )
115 assert( session );
117 return session->encryptionMode;
120 void
121 tr_sessionSetEncryption( tr_session * session,
122 tr_encryption_mode mode )
124 assert( session );
125 assert( mode == TR_ENCRYPTION_PREFERRED
126 || mode == TR_ENCRYPTION_REQUIRED
127 || mode == TR_CLEAR_PREFERRED );
129 session->encryptionMode = mode;
132 /***
133 ****
134 ***/
136 struct tr_bindinfo
138 int socket;
139 tr_address addr;
140 struct event * ev;
144 static void
145 close_bindinfo( struct tr_bindinfo * b )
147 if( ( b != NULL ) && ( b->socket >=0 ) )
149 event_free( b->ev );
150 b->ev = NULL;
151 tr_netCloseSocket( b->socket );
155 static void
156 close_incoming_peer_port( tr_session * session )
158 close_bindinfo( session->public_ipv4 );
159 close_bindinfo( session->public_ipv6 );
162 static void
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;
174 static void
175 accept_incoming_peer( int fd, short what UNUSED, void * vsession )
177 int clientSocket;
178 tr_port clientPort;
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 );
191 static void
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 );
215 const tr_address*
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;
221 switch( tr_af_type )
223 case TR_AF_INET:
224 bindinfo = session->public_ipv4;
225 default_value = TR_DEFAULT_BIND_ADDRESS_IPV4;
226 break;
228 case TR_AF_INET6:
229 bindinfo = session->public_ipv6;
230 default_value = TR_DEFAULT_BIND_ADDRESS_IPV6;
231 break;
233 default:
234 bindinfo = NULL;
235 default_value = "";
236 break;
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;
245 /***
246 ****
247 ***/
249 #ifdef TR_LIGHTWEIGHT
250 #define TR_DEFAULT_ENCRYPTION TR_CLEAR_PREFERRED
251 #else
252 #define TR_DEFAULT_ENCRYPTION TR_ENCRYPTION_PREFERRED
253 #endif
255 static int
256 parse_tos( const char *str )
258 char *p;
259 int value;
261 if( !evutil_ascii_strcasecmp( str, "" ) )
262 return 0;
263 if( !evutil_ascii_strcasecmp( str, "default" ) )
264 return 0;
266 if( !evutil_ascii_strcasecmp( str, "lowcost" ) )
267 return 0x10;
268 if( !evutil_ascii_strcasecmp( str, "mincost" ) )
269 return 0x10;
271 if( !evutil_ascii_strcasecmp( str, "throughput" ) )
272 return 0x08;
273 if( !evutil_ascii_strcasecmp( str, "reliability" ) )
274 return 0x04;
275 if( !evutil_ascii_strcasecmp( str, "lowdelay" ) )
276 return 0x02;
278 value = strtol( str, &p, 0 );
279 if( !p || ( p == str ) )
280 return 0;
282 return value;
285 static const char *
286 format_tos(int value)
288 static char buf[8];
289 switch(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";
295 default:
296 snprintf(buf, 8, "%d", value);
297 return buf;
301 void
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 );
371 void
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 ) );
442 bool
443 tr_sessionLoadSettings( tr_benc * d, const char * configDir, const char * appName )
445 int err = 0;
446 char * filename;
447 tr_benc fileSettings;
448 tr_benc sessionDefaults;
449 tr_benc tmp;
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 );
468 if( !err ) {
469 tr_bencMergeDicts( d, &fileSettings );
470 tr_bencFree( &fileSettings );
473 /* cleanup */
474 tr_bencFree( &sessionDefaults );
475 tr_free( filename );
476 success = (err==0) || (err==ENOENT);
477 return success;
480 void
481 tr_sessionSaveSettings( tr_session * session,
482 const char * configDir,
483 const tr_benc * clientSettings )
485 tr_benc settings;
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 );
496 if( !err )
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 );
518 /* cleanup */
519 tr_free( filename );
520 tr_bencFree( &settings );
523 /***
524 ****
525 ***/
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.
532 static void
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 );
549 /***
550 ****
551 ***/
553 static void tr_sessionInitImpl( void * );
555 struct init_data
557 tr_session * session;
558 const char * configDir;
559 bool done;
560 bool messageQueuingEnabled;
561 tr_benc * clientSettings;
564 tr_session *
565 tr_sessionInit( const char * tag,
566 const char * configDir,
567 bool messageQueuingEnabled,
568 tr_benc * clientSettings )
570 int64_t i;
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 */
600 data.done = false;
601 data.session = session;
602 data.configDir = configDir;
603 data.messageQueuingEnabled = messageQueuingEnabled;
604 data.clientSettings = clientSettings;
605 tr_runInEventThread( session, tr_sessionInitImpl, &data );
606 while( !data.done )
607 tr_wait_msec( 100 );
609 return session;
612 static void turtleCheckClock( tr_session * s, struct tr_turtle_info * t );
614 static void
615 onNowTimer( int foo UNUSED, short bar UNUSED, void * vsession )
617 int usec;
618 const int min = 100;
619 const int max = 999999;
620 struct timeval tv;
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;
643 else
644 ++tor->secondsDownloading;
649 *** Set the timer
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 );
663 static void
664 tr_sessionInitImpl( void * vdata )
666 tr_benc settings;
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 );
685 #ifndef WIN32
686 /* Don't exit when writing on a broken socket */
687 signal( SIGPIPE, SIG_IGN );
688 #endif
690 tr_setMessageQueuing( data->messageQueuingEnabled );
692 tr_setConfigDir( session, data->configDir );
694 session->peerMgr = tr_peerMgrNew( session );
696 session->shared = tr_sharedInit( session );
699 *** Blocklist
703 char * filename = tr_buildPath( session->configDir, "blocklists", NULL );
704 tr_mkdirp( filename, 0777 );
705 tr_free( filename );
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 );
731 /* cleanup */
732 tr_bencFree( &settings );
733 data->done = true;
736 static void turtleBootstrap( tr_session *, struct tr_turtle_info * );
737 static void setPeerPort( tr_session * session, tr_port port );
739 static void
740 sessionSetImpl( void * vdata )
742 int64_t i;
743 double d;
744 bool boolVal;
745 const char * str;
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 );
764 /* misc features */
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);
783 else
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 );
794 /* torrent queues */
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 );
822 /* rpc server */
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;
835 b.socket = -1;
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;
842 b.socket = -1;
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 );
888 *** Turtle Mode
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 ) )
901 turtle->days = 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 );
909 *** Scripts
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;
921 data->done = true;
924 void
925 tr_sessionSet( tr_session * session, struct tr_benc * settings )
927 struct init_data data;
928 data.done = false;
929 data.session = session;
930 data.clientSettings = settings;
932 /* run the rest in the libtransmission thread */
933 tr_runInEventThread( session, sessionSetImpl, &data );
934 while( !data.done )
935 tr_wait_msec( 100 );
938 /***
939 ****
940 ***/
942 void
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 );
954 const char *
955 tr_sessionGetDownloadDir( const tr_session * session )
957 assert( tr_isSession( session ) );
959 return session->downloadDir;
962 int64_t
963 tr_sessionGetDownloadDirFreeSpace( const tr_session * session )
965 assert( tr_isSession( session ) );
967 return tr_getFreeSpace( session->downloadDir );
970 /***
971 ****
972 ***/
974 void
975 tr_sessionSetIncompleteFileNamingEnabled( tr_session * session, bool b )
977 assert( tr_isSession( session ) );
978 assert( tr_isBool( b ) );
980 session->isIncompleteFileNamingEnabled = b;
983 bool
984 tr_sessionIsIncompleteFileNamingEnabled( const tr_session * session )
986 assert( tr_isSession( session ) );
988 return session->isIncompleteFileNamingEnabled;
991 /***
992 ****
993 ***/
996 void
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 );
1009 const char*
1010 tr_sessionGetIncompleteDir( const tr_session * session )
1012 assert( tr_isSession( session ) );
1014 return session->incompleteDir;
1017 void
1018 tr_sessionSetIncompleteDirEnabled( tr_session * session, bool b )
1020 assert( tr_isSession( session ) );
1021 assert( tr_isBool( b ) );
1023 session->isIncompleteDirEnabled = b;
1026 bool
1027 tr_sessionIsIncompleteDirEnabled( const tr_session * session )
1029 assert( tr_isSession( session ) );
1031 return session->isIncompleteDirEnabled;
1034 /***
1035 ****
1036 ***/
1038 void
1039 tr_sessionLock( tr_session * session )
1041 assert( tr_isSession( session ) );
1043 tr_lockLock( session->lock );
1046 void
1047 tr_sessionUnlock( tr_session * session )
1049 assert( tr_isSession( session ) );
1051 tr_lockUnlock( session->lock );
1054 bool
1055 tr_sessionIsLocked( const tr_session * session )
1057 return tr_isSession( session ) && tr_lockHave( session->lock );
1060 /***********************************************************************
1061 * tr_setBindPort
1062 ***********************************************************************
1064 **********************************************************************/
1066 static void
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 );
1081 static void
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 );
1090 void
1091 tr_sessionSetPeerPort( tr_session * session, tr_port port )
1093 if( tr_isSession( session ) && ( session->private_peer_port != port ) )
1095 setPeerPort( session, port );
1099 tr_port
1100 tr_sessionGetPeerPort( const tr_session * session )
1102 return tr_isSession( session ) ? session->private_peer_port : 0;
1105 tr_port
1106 tr_sessionSetPeerPortRandom( tr_session * session )
1108 assert( tr_isSession( session ) );
1110 tr_sessionSetPeerPort( session, getRandomPort( session ) );
1111 return session->private_peer_port;
1114 void
1115 tr_sessionSetPeerPortRandomOnStart( tr_session * session,
1116 bool random )
1118 assert( tr_isSession( session ) );
1120 session->isPortRandom = random;
1123 bool
1124 tr_sessionGetPeerPortRandomOnStart( tr_session * session )
1126 assert( tr_isSession( session ) );
1128 return session->isPortRandom;
1131 tr_port_forwarding
1132 tr_sessionGetPortForwarding( const tr_session * session )
1134 assert( tr_isSession( session ) );
1136 return tr_sharedTraversalStatus( session->shared );
1139 /***
1140 ****
1141 ***/
1143 void
1144 tr_sessionSetRatioLimited( tr_session * session, bool isLimited )
1146 assert( tr_isSession( session ) );
1148 session->isRatioLimited = isLimited;
1151 void
1152 tr_sessionSetRatioLimit( tr_session * session, double desiredRatio )
1154 assert( tr_isSession( session ) );
1156 session->desiredRatio = desiredRatio;
1159 bool
1160 tr_sessionIsRatioLimited( const tr_session * session )
1162 assert( tr_isSession( session ) );
1164 return session->isRatioLimited;
1167 double
1168 tr_sessionGetRatioLimit( const tr_session * session )
1170 assert( tr_isSession( session ) );
1172 return session->desiredRatio;
1175 /***
1176 ****
1177 ***/
1179 void
1180 tr_sessionSetIdleLimited( tr_session * session, bool isLimited )
1182 assert( tr_isSession( session ) );
1184 session->isIdleLimited = isLimited;
1187 void
1188 tr_sessionSetIdleLimit( tr_session * session, uint16_t idleMinutes )
1190 assert( tr_isSession( session ) );
1192 session->idleLimitMinutes = idleMinutes;
1195 bool
1196 tr_sessionIsIdleLimited( const tr_session * session )
1198 assert( tr_isSession( session ) );
1200 return session->isIdleLimited;
1203 uint16_t
1204 tr_sessionGetIdleLimit( const tr_session * session )
1206 assert( tr_isSession( session ) );
1208 return session->idleLimitMinutes;
1211 /***
1212 ****
1213 **** SPEED LIMITS
1214 ****
1215 ***/
1217 bool
1218 tr_sessionGetActiveSpeedLimit_Bps( const tr_session * session, tr_direction dir, int * setme_Bps )
1220 int isLimited = true;
1222 if( !tr_isSession( session ) )
1223 return false;
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 );
1229 else
1230 isLimited = false;
1232 return isLimited;
1234 bool
1235 tr_sessionGetActiveSpeedLimit_KBps( const tr_session * session,
1236 tr_direction dir,
1237 double * setme_KBps )
1239 int Bps = 0;
1240 const bool is_active = tr_sessionGetActiveSpeedLimit_Bps( session, dir, &Bps );
1241 *setme_KBps = toSpeedKBps( Bps );
1242 return is_active;
1245 static void
1246 updateBandwidth( tr_session * session, tr_direction dir )
1248 int limit_Bps = 0;
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 );
1257 enum
1259 MINUTES_PER_HOUR = 60,
1260 MINUTES_PER_DAY = MINUTES_PER_HOUR * 24,
1261 MINUTES_PER_WEEK = MINUTES_PER_DAY * 7
1264 static void
1265 turtleUpdateTable( struct tr_turtle_info * t )
1267 int day;
1268 tr_bitfield * b = &t->minutes;
1270 tr_bitfieldSetHasNone( b );
1272 for( day=0; day<7; ++day )
1274 if( t->days & (1<<day) )
1276 int i;
1277 const time_t begin = t->beginMinute;
1278 time_t end = t->endMinute;
1280 if( end <= begin )
1281 end += MINUTES_PER_DAY;
1283 for( i=begin; i<end; ++i )
1284 tr_bitfieldAdd( b, (i+day*MINUTES_PER_DAY) % MINUTES_PER_WEEK );
1289 static void
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 );
1304 static void
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
1325 static void
1326 testTurtleTime( const struct tr_turtle_info * t,
1327 bool * enabled,
1328 bool * changed )
1330 bool e;
1331 struct tm tm;
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
1339 + tm.tm_min;
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 )
1345 *enabled = e;
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 );
1355 static void
1356 turtleCheckClock( tr_session * s, struct tr_turtle_info * t )
1358 bool enabled;
1359 bool changed;
1361 assert( t->isClockEnabled );
1363 testTurtleTime( t, &enabled, &changed );
1365 if( 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. */
1375 static void
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 );
1390 /***
1391 **** Primary session speed limits
1392 ***/
1394 void
1395 tr_sessionSetSpeedLimit_Bps( tr_session * s, tr_direction d, int Bps )
1397 assert( tr_isSession( s ) );
1398 assert( tr_isDirection( d ) );
1399 assert( Bps >= 0 );
1401 s->speedLimit_Bps[d] = Bps;
1403 updateBandwidth( s, d );
1405 void
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 ) );
1425 void
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 );
1437 bool
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];
1446 /***
1447 **** Alternative speed limits that are used during scheduled times
1448 ***/
1450 void
1451 tr_sessionSetAltSpeed_Bps( tr_session * s, tr_direction d, int Bps )
1453 assert( tr_isSession( s ) );
1454 assert( tr_isDirection( d ) );
1455 assert( Bps >= 0 );
1457 s->turtle.speedLimit_Bps[d] = Bps;
1459 updateBandwidth( s, d );
1462 void
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 ) );
1482 static void
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 );
1497 void
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 );
1511 bool
1512 tr_sessionUsesAltSpeedTime( const tr_session * s )
1514 assert( tr_isSession( s ) );
1516 return s->turtle.isClockEnabled;
1519 void
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;
1539 void
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;
1559 void
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 );
1570 tr_sched_day
1571 tr_sessionGetAltSpeedDay( const tr_session * s )
1573 assert( tr_isSession( s ) );
1575 return s->turtle.days;
1578 void
1579 tr_sessionUseAltSpeed( tr_session * session, bool enabled )
1581 useAltSpeed( session, &session->turtle, enabled, true );
1584 bool
1585 tr_sessionUsesAltSpeed( const tr_session * s )
1587 assert( tr_isSession( s ) );
1589 return s->turtle.isEnabled;
1592 void
1593 tr_sessionSetAltSpeedFunc( tr_session * session,
1594 tr_altSpeedFunc func,
1595 void * userData )
1597 assert( tr_isSession( session ) );
1599 session->turtle.callback = func;
1600 session->turtle.callbackUserData = userData;
1603 void
1604 tr_sessionClearAltSpeedFunc( tr_session * session )
1606 tr_sessionSetAltSpeedFunc( session, NULL, NULL );
1609 /***
1610 ****
1611 ***/
1613 void
1614 tr_sessionSetPeerLimit( tr_session * session, uint16_t n )
1616 assert( tr_isSession( session ) );
1618 session->peerLimit = n;
1621 uint16_t
1622 tr_sessionGetPeerLimit( const tr_session * session )
1624 assert( tr_isSession( session ) );
1626 return session->peerLimit;
1629 void
1630 tr_sessionSetPeerLimitPerTorrent( tr_session * session, uint16_t n )
1632 assert( tr_isSession( session ) );
1634 session->peerLimitPerTorrent = n;
1637 uint16_t
1638 tr_sessionGetPeerLimitPerTorrent( const tr_session * session )
1640 assert( tr_isSession( session ) );
1642 return session->peerLimitPerTorrent;
1645 /***
1646 ****
1647 ***/
1649 void
1650 tr_sessionSetPaused( tr_session * session, bool isPaused )
1652 assert( tr_isSession( session ) );
1654 session->pauseAddedTorrent = isPaused;
1657 bool
1658 tr_sessionGetPaused( const tr_session * session )
1660 assert( tr_isSession( session ) );
1662 return session->pauseAddedTorrent;
1665 void
1666 tr_sessionSetDeleteSource( tr_session * session, bool deleteSource )
1668 assert( tr_isSession( session ) );
1670 session->deleteSourceTorrent = deleteSource;
1673 bool
1674 tr_sessionGetDeleteSource( const tr_session * session )
1676 assert( tr_isSession( session ) );
1678 return session->deleteSourceTorrent;
1681 /***
1682 ****
1683 ***/
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;
1696 double
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;
1709 static int
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;
1717 if( aCur != bCur )
1718 return aCur > bCur ? -1 : 1; /* close the biggest torrents first */
1720 return 0;
1723 static void closeBlocklists( tr_session * );
1725 static void
1726 sessionCloseImpl( void * vsession )
1728 tr_session * session = vsession;
1729 tr_torrent * tor;
1730 int i, n;
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. */
1756 tor = NULL;
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;
1801 static int
1802 deadlineReached( const time_t deadline )
1804 return time( NULL ) >= deadline;
1807 #define SHUTDOWN_MAX_SECONDS 20
1809 void
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()" );
1850 forced = true;
1851 event_base_loopbreak( session->event_base );
1853 if( deadlineReached( deadline+3 ) )
1855 dbgmsg( "deadline+3 reached... calling break...\n" );
1856 break;
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 );
1878 tr_free( session );
1881 struct sessionLoadTorrentsData
1883 tr_session * session;
1884 tr_ctor * ctor;
1885 int * setmeCount;
1886 tr_torrent ** torrents;
1887 bool done;
1890 static void
1891 sessionLoadTorrents( void * vdata )
1893 int i;
1894 int n = 0;
1895 struct stat sb;
1896 DIR * odir = NULL;
1897 tr_list * l = NULL;
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 ) ) ) )
1910 struct dirent *d;
1911 for( d = readdir( odir ); d != NULL; d = readdir( odir ) )
1913 if( tr_str_has_suffix( d->d_name, ".torrent" ) )
1915 tr_torrent * tor;
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 );
1921 ++n;
1923 tr_free( path );
1926 closedir( odir );
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;
1932 assert( i == n );
1934 tr_list_free( &list, NULL );
1936 if( n )
1937 tr_inf( _( "Loaded %d torrents" ), n );
1939 if( data->setmeCount )
1940 *data->setmeCount = n;
1942 data->done = true;
1945 tr_torrent **
1946 tr_sessionLoadTorrents( tr_session * session,
1947 tr_ctor * ctor,
1948 int * setmeCount )
1950 struct sessionLoadTorrentsData data;
1952 data.session = session;
1953 data.ctor = ctor;
1954 data.setmeCount = setmeCount;
1955 data.torrents = NULL;
1956 data.done = false;
1958 tr_runInEventThread( session, sessionLoadTorrents, &data );
1959 while( !data.done )
1960 tr_wait_msec( 100 );
1962 return data.torrents;
1965 /***
1966 ****
1967 ***/
1969 void
1970 tr_sessionSetPexEnabled( tr_session * session, bool enabled )
1972 assert( tr_isSession( session ) );
1974 session->isPexEnabled = enabled != 0;
1977 bool
1978 tr_sessionIsPexEnabled( const tr_session * session )
1980 assert( tr_isSession( session ) );
1982 return session->isPexEnabled;
1985 bool
1986 tr_sessionAllowsDHT( const tr_session * session )
1988 return tr_sessionIsDHTEnabled( session );
1991 bool
1992 tr_sessionIsDHTEnabled( const tr_session * session )
1994 assert( tr_isSession( session ) );
1996 return session->isDHTEnabled;
1999 static void
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 );
2010 void
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 );
2020 /***
2021 ****
2022 ***/
2024 bool
2025 tr_sessionIsUTPEnabled( const tr_session * session )
2027 assert( tr_isSession( session ) );
2029 #ifdef WITH_UTP
2030 return session->isUTPEnabled;
2031 #else
2032 return false;
2033 #endif
2036 static void
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
2047 explanation. */
2050 void
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 );
2060 /***
2061 ****
2062 ***/
2064 static void
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 );
2079 void
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 );
2089 bool
2090 tr_sessionIsLPDEnabled( const tr_session * session )
2092 assert( tr_isSession( session ) );
2094 return session->isLPDEnabled;
2097 bool
2098 tr_sessionAllowsLPD( const tr_session * session )
2100 return tr_sessionIsLPDEnabled( session );
2103 /***
2104 ****
2105 ***/
2107 void
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 ) );
2123 /***
2124 ****
2125 ***/
2127 struct port_forwarding_data
2129 bool enabled;
2130 struct tr_shared * shared;
2133 static void
2134 setPortForwardingEnabled( void * vdata )
2136 struct port_forwarding_data * data = vdata;
2137 tr_sharedTraversalEnable( data->shared, data->enabled );
2138 tr_free( data );
2141 void
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 );
2151 bool
2152 tr_sessionIsPortForwardingEnabled( const tr_session * session )
2154 assert( tr_isSession( session ) );
2156 return tr_sharedTraversalIsEnabled( session->shared );
2159 /***
2160 ****
2161 ***/
2163 static int
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 );
2172 static void
2173 loadBlocklists( tr_session * session )
2175 int binCount = 0;
2176 int newCount = 0;
2177 struct stat sb;
2178 char * dirname;
2179 DIR * odir = NULL;
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 );
2185 if( !stat( dirname,
2186 &sb ) && S_ISDIR( sb.st_mode )
2187 && ( ( odir = opendir( dirname ) ) ) )
2189 struct dirent *d;
2190 for( d = readdir( odir ); d; d = readdir( odir ) )
2192 char * filename;
2194 if( !d->d_name || d->d_name[0] == '.' ) /* skip dotfiles, ., and ..
2196 continue;
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 ) );
2208 ++binCount;
2211 else
2213 /* strip out the file suffix, if there is one, and add ".bin"
2214 instead */
2215 tr_blocklist * b;
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 );
2225 ++newCount;
2226 tr_free( tmp );
2229 tr_free( filename );
2232 closedir( odir );
2235 session->blocklists = list;
2237 if( binCount )
2238 tr_dbg( "Found %d blocklists in \"%s\"", binCount, dirname );
2239 if( newCount )
2240 tr_dbg( "Found %d new blocklists in \"%s\"", newCount, dirname );
2242 tr_free( dirname );
2245 static void
2246 closeBlocklists( tr_session * session )
2248 tr_list_free( &session->blocklists,
2249 (TrListForeachFunc)_tr_blocklistFree );
2252 void
2253 tr_sessionReloadBlocklists( tr_session * session )
2255 closeBlocklists( session );
2256 loadBlocklists( session );
2258 tr_peerMgrOnBlocklistChanged( session->peerMgr );
2262 tr_blocklistGetRuleCount( const tr_session * session )
2264 int n = 0;
2265 tr_list * l;
2267 assert( tr_isSession( session ) );
2269 for( l = session->blocklists; l; l = l->next )
2270 n += _tr_blocklistGetRuleCount( l->data );
2271 return n;
2274 bool
2275 tr_blocklistIsEnabled( const tr_session * session )
2277 assert( tr_isSession( session ) );
2279 return session->isBlocklistEnabled;
2282 void
2283 tr_blocklistSetEnabled( tr_session * session, bool isEnabled )
2285 tr_list * l;
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 );
2295 bool
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 )
2306 tr_list * l;
2307 int ruleCount;
2308 tr_blocklist * b;
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 ),
2314 defaultName ) )
2315 b = l->data;
2317 if( !b )
2319 char * path = tr_buildPath( session->configDir, "blocklists", defaultName, NULL );
2320 b = _tr_blocklistNew( path, session->isBlocklistEnabled );
2321 tr_list_append( &session->blocklists, b );
2322 tr_free( path );
2325 ruleCount = _tr_blocklistSetContent( b, contentFilename );
2326 tr_sessionUnlock( session );
2327 return ruleCount;
2330 bool
2331 tr_sessionIsAddressBlocked( const tr_session * session,
2332 const tr_address * addr )
2334 tr_list * l;
2336 assert( tr_isSession( session ) );
2338 for( l = session->blocklists; l; l = l->next )
2339 if( _tr_blocklistHasAddress( l->data, addr ) )
2340 return true;
2341 return false;
2344 void
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 );
2354 const char *
2355 tr_blocklistGetURL ( const tr_session * session )
2357 return session->blocklist_url;
2361 /***
2362 ****
2363 ***/
2365 static void
2366 metainfoLookupInit( tr_session * session )
2368 struct stat sb;
2369 const char * dirname = tr_getTorrentDir( session );
2370 DIR * odir = NULL;
2371 tr_ctor * ctor = NULL;
2372 tr_benc * lookup;
2373 int n = 0;
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 ) ) ) )
2384 struct dirent *d;
2385 while(( d = readdir( odir )))
2387 if( tr_str_has_suffix( d->d_name, ".torrent" ) )
2389 tr_info inf;
2390 char * path = tr_buildPath( dirname, d->d_name, NULL );
2391 tr_ctorSetMetainfoFromFile( ctor, path );
2392 if( !tr_torrentParse( ctor, &inf ) )
2394 ++n;
2395 tr_bencDictAddStr( lookup, inf.hashString, path );
2397 tr_free( path );
2400 closedir( odir );
2402 tr_ctorFree( ctor );
2404 session->metainfoLookup = lookup;
2405 tr_dbg( "Found %d torrents in \"%s\"", n, dirname );
2408 const char*
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 );
2416 return filename;
2419 void
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 );
2432 /***
2433 ****
2434 ***/
2436 void
2437 tr_sessionSetRPCEnabled( tr_session * session, bool isEnabled )
2439 assert( tr_isSession( session ) );
2441 tr_rpcSetEnabled( session->rpcServer, isEnabled );
2444 bool
2445 tr_sessionIsRPCEnabled( const tr_session * session )
2447 assert( tr_isSession( session ) );
2449 return tr_rpcIsEnabled( session->rpcServer );
2452 void
2453 tr_sessionSetRPCPort( tr_session * session,
2454 tr_port port )
2456 assert( tr_isSession( session ) );
2458 tr_rpcSetPort( session->rpcServer, port );
2461 tr_port
2462 tr_sessionGetRPCPort( const tr_session * session )
2464 assert( tr_isSession( session ) );
2466 return tr_rpcGetPort( session->rpcServer );
2469 void
2470 tr_sessionSetRPCUrl( tr_session * session,
2471 const char * url )
2473 assert( tr_isSession( session ) );
2475 tr_rpcSetUrl( session->rpcServer, url );
2478 const char*
2479 tr_sessionGetRPCUrl( const tr_session * session )
2481 assert( tr_isSession( session ) );
2483 return tr_rpcGetUrl( session->rpcServer );
2486 void
2487 tr_sessionSetRPCCallback( tr_session * session,
2488 tr_rpc_func func,
2489 void * user_data )
2491 assert( tr_isSession( session ) );
2493 session->rpc_func = func;
2494 session->rpc_func_user_data = user_data;
2497 void
2498 tr_sessionSetRPCWhitelist( tr_session * session,
2499 const char * whitelist )
2501 assert( tr_isSession( session ) );
2503 tr_rpcSetWhitelist( session->rpcServer, whitelist );
2506 const char*
2507 tr_sessionGetRPCWhitelist( const tr_session * session )
2509 assert( tr_isSession( session ) );
2511 return tr_rpcGetWhitelist( session->rpcServer );
2514 void
2515 tr_sessionSetRPCWhitelistEnabled( tr_session * session, bool isEnabled )
2517 assert( tr_isSession( session ) );
2519 tr_rpcSetWhitelistEnabled( session->rpcServer, isEnabled );
2522 bool
2523 tr_sessionGetRPCWhitelistEnabled( const tr_session * session )
2525 assert( tr_isSession( session ) );
2527 return tr_rpcGetWhitelistEnabled( session->rpcServer );
2531 void
2532 tr_sessionSetRPCPassword( tr_session * session,
2533 const char * password )
2535 assert( tr_isSession( session ) );
2537 tr_rpcSetPassword( session->rpcServer, password );
2540 const char*
2541 tr_sessionGetRPCPassword( const tr_session * session )
2543 assert( tr_isSession( session ) );
2545 return tr_rpcGetPassword( session->rpcServer );
2548 void
2549 tr_sessionSetRPCUsername( tr_session * session,
2550 const char * username )
2552 assert( tr_isSession( session ) );
2554 tr_rpcSetUsername( session->rpcServer, username );
2557 const char*
2558 tr_sessionGetRPCUsername( const tr_session * session )
2560 assert( tr_isSession( session ) );
2562 return tr_rpcGetUsername( session->rpcServer );
2565 void
2566 tr_sessionSetRPCPasswordEnabled( tr_session * session, bool isEnabled )
2568 assert( tr_isSession( session ) );
2570 tr_rpcSetPasswordEnabled( session->rpcServer, isEnabled );
2573 bool
2574 tr_sessionIsRPCPasswordEnabled( const tr_session * session )
2576 assert( tr_isSession( session ) );
2578 return tr_rpcIsPasswordEnabled( session->rpcServer );
2581 const char *
2582 tr_sessionGetRPCBindAddress( const tr_session * session )
2584 assert( tr_isSession( session ) );
2586 return tr_rpcGetBindAddress( session->rpcServer );
2589 /****
2590 *****
2591 ****/
2593 bool
2594 tr_sessionIsTorrentDoneScriptEnabled( const tr_session * session )
2596 assert( tr_isSession( session ) );
2598 return session->isTorrentDoneScriptEnabled;
2601 void
2602 tr_sessionSetTorrentDoneScriptEnabled( tr_session * session, bool isEnabled )
2604 assert( tr_isSession( session ) );
2605 assert( tr_isBool( isEnabled ) );
2607 session->isTorrentDoneScriptEnabled = isEnabled;
2610 const char *
2611 tr_sessionGetTorrentDoneScript( const tr_session * session )
2613 assert( tr_isSession( session ) );
2615 return session->torrentDoneScript;
2618 void
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 );
2630 /***
2631 ****
2632 ***/
2634 void
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];
2652 void
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;
2662 bool
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];
2671 void
2672 tr_sessionSetQueueStalledMinutes( tr_session * session, int minutes )
2674 assert( tr_isSession( session ) );
2675 assert( minutes > 0 );
2677 session->queueStalledMinutes = minutes;
2680 void
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;
2689 bool
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;
2705 tr_torrent *
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 )))
2717 int position;
2719 if( !tr_torrentIsQueued( tor ) )
2720 continue;
2721 if( direction != tr_torrentGetQueueDirection( tor ) )
2722 continue;
2724 position = tr_torrentGetQueuePosition( tor );
2725 if( best_position > position ) {
2726 best_position = position;
2727 best_tor = tor;
2731 return best_tor;
2735 tr_sessionCountQueueFreeSlots( tr_session * session, tr_direction dir )
2737 tr_torrent * tor;
2738 int active_count;
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 ) )
2743 return INT_MAX;
2745 tor = NULL;
2746 active_count = 0;
2747 while(( tor = tr_torrentNext( session, tor )))
2748 if( !tr_torrentIsStalled( tor ) )
2749 if( tr_torrentGetActivity( tor ) == activity )
2750 ++active_count;
2752 if( active_count >= max )
2753 return 0;
2755 return max - active_count;