2 * This file Copyright (C) 2008-2014 Mnemosyne LLC
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
7 * $Id: session.c 14266 2014-04-27 23:10:01Z jordan $
11 #include <errno.h> /* ENOENT */
12 #include <limits.h> /* INT_MAX */
14 #include <string.h> /* memcpy */
17 #include <sys/types.h> /* stat (), umask () */
18 #include <sys/stat.h> /* stat (), umask () */
19 #include <unistd.h> /* stat */
20 #include <dirent.h> /* opendir */
22 #include <event2/dns.h> /* evdns_base_free () */
23 #include <event2/event.h>
25 #include <libutp/utp.h>
27 //#define TR_SHOW_DEPRECATED
28 #include "transmission.h"
29 #include "announcer.h"
30 #include "bandwidth.h"
31 #include "blocklist.h"
40 #include "platform.h" /* tr_lock, tr_getTorrentDir () */
41 #include "platform-quota.h" /* tr_device_info_free() */
42 #include "port-forwarding.h"
43 #include "rpc-server.h"
47 #include "tr-dht.h" /* tr_dhtUpkeep () */
61 DEFAULT_CACHE_SIZE_MB
= 2,
62 DEFAULT_PREFETCH_ENABLED
= false,
64 DEFAULT_CACHE_SIZE_MB
= 4,
65 DEFAULT_PREFETCH_ENABLED
= true,
67 SAVE_INTERVAL_SECS
= 360
74 if (tr_logGetDeepEnabled ()) \
75 tr_logAddDeep (__FILE__, __LINE__, NULL, __VA_ARGS__); \
80 getRandomPort (tr_session
* s
)
82 return tr_cryptoWeakRandInt (s
->randomPortHigh
- s
->randomPortLow
+ 1) + s
->randomPortLow
;
85 /* Generate a peer id : "-TRxyzb-" + 12 random alphanumeric
86 characters, where x is the major version number, y is the
87 minor version number, z is the maintenance number, and b
88 designates beta (Azureus-style) */
90 tr_peerIdInit (uint8_t * buf
)
95 const char * pool
= "0123456789abcdefghijklmnopqrstuvwxyz";
98 memcpy (buf
, PEERID_PREFIX
, 8);
100 tr_cryptoRandBuf (buf
+8, 11);
108 val
= total
% base
? base
- (total
% base
) : 0;
118 tr_sessionGetEncryption (tr_session
* session
)
122 return session
->encryptionMode
;
126 tr_sessionSetEncryption (tr_session
* session
,
127 tr_encryption_mode mode
)
130 assert (mode
== TR_ENCRYPTION_PREFERRED
131 || mode
== TR_ENCRYPTION_REQUIRED
132 || mode
== TR_CLEAR_PREFERRED
);
134 session
->encryptionMode
= mode
;
150 close_bindinfo (struct tr_bindinfo
* b
)
152 if ((b
!= NULL
) && (b
->socket
>=0))
156 tr_netCloseSocket (b
->socket
);
161 close_incoming_peer_port (tr_session
* session
)
163 close_bindinfo (session
->public_ipv4
);
164 close_bindinfo (session
->public_ipv6
);
168 free_incoming_peer_port (tr_session
* session
)
170 close_bindinfo (session
->public_ipv4
);
171 tr_free (session
->public_ipv4
);
172 session
->public_ipv4
= NULL
;
174 close_bindinfo (session
->public_ipv6
);
175 tr_free (session
->public_ipv6
);
176 session
->public_ipv6
= NULL
;
180 accept_incoming_peer (evutil_socket_t fd
, short what UNUSED
, void * vsession
)
184 tr_address clientAddr
;
185 tr_session
* session
= vsession
;
187 clientSocket
= tr_netAccept (session
, fd
, &clientAddr
, &clientPort
);
188 if (clientSocket
> 0)
190 tr_logAddDeep (__FILE__
, __LINE__
, NULL
, "new incoming connection %d (%s)",
191 clientSocket
, tr_peerIoAddrStr (&clientAddr
, clientPort
));
192 tr_peerMgrAddIncoming (session
->peerMgr
, &clientAddr
, clientPort
,
198 open_incoming_peer_port (tr_session
* session
)
200 struct tr_bindinfo
* b
;
202 /* bind an ipv4 port to listen for incoming peers... */
203 b
= session
->public_ipv4
;
204 b
->socket
= tr_netBindTCP (&b
->addr
, session
->private_peer_port
, false);
207 b
->ev
= event_new (session
->event_base
, b
->socket
, EV_READ
| EV_PERSIST
, accept_incoming_peer
, session
);
208 event_add (b
->ev
, NULL
);
211 /* and do the exact same thing for ipv6, if it's supported... */
212 if (tr_net_hasIPv6 (session
->private_peer_port
))
214 b
= session
->public_ipv6
;
215 b
->socket
= tr_netBindTCP (&b
->addr
, session
->private_peer_port
, false);
218 b
->ev
= event_new (session
->event_base
, b
->socket
, EV_READ
| EV_PERSIST
, accept_incoming_peer
, session
);
219 event_add (b
->ev
, NULL
);
225 tr_sessionGetPublicAddress (const tr_session
* session
, int tr_af_type
, bool * is_default_value
)
227 const char * default_value
;
228 const struct tr_bindinfo
* bindinfo
;
233 bindinfo
= session
->public_ipv4
;
234 default_value
= TR_DEFAULT_BIND_ADDRESS_IPV4
;
238 bindinfo
= session
->public_ipv6
;
239 default_value
= TR_DEFAULT_BIND_ADDRESS_IPV6
;
248 if (is_default_value
&& bindinfo
)
249 *is_default_value
= !tr_strcmp0 (default_value
, tr_address_to_string (&bindinfo
->addr
));
251 return bindinfo
? &bindinfo
->addr
: NULL
;
258 #ifdef TR_LIGHTWEIGHT
259 #define TR_DEFAULT_ENCRYPTION TR_CLEAR_PREFERRED
261 #define TR_DEFAULT_ENCRYPTION TR_ENCRYPTION_PREFERRED
265 parse_tos (const char *str
)
270 if (!evutil_ascii_strcasecmp (str
, ""))
272 if (!evutil_ascii_strcasecmp (str
, "default"))
275 if (!evutil_ascii_strcasecmp (str
, "lowcost"))
277 if (!evutil_ascii_strcasecmp (str
, "mincost"))
280 if (!evutil_ascii_strcasecmp (str
, "throughput"))
282 if (!evutil_ascii_strcasecmp (str
, "reliability"))
284 if (!evutil_ascii_strcasecmp (str
, "lowdelay"))
287 value
= strtol (str
, &p
, 0);
288 if (!p
|| (p
== str
))
295 format_tos (int value
)
300 case 0: return "default";
301 case 0x10: return "lowcost";
302 case 0x08: return "throughput";
303 case 0x04: return "reliability";
304 case 0x02: return "lowdelay";
306 tr_snprintf (buf
, 8, "%d", value
);
312 tr_sessionGetDefaultSettings (tr_variant
* d
)
314 assert (tr_variantIsDict (d
));
316 tr_variantDictReserve (d
, 63);
317 tr_variantDictAddBool (d
, TR_KEY_blocklist_enabled
, false);
318 tr_variantDictAddStr (d
, TR_KEY_blocklist_url
, "http://www.example.com/blocklist");
319 tr_variantDictAddInt (d
, TR_KEY_cache_size_mb
, DEFAULT_CACHE_SIZE_MB
);
320 tr_variantDictAddBool (d
, TR_KEY_dht_enabled
, true);
321 tr_variantDictAddBool (d
, TR_KEY_utp_enabled
, true);
322 tr_variantDictAddBool (d
, TR_KEY_lpd_enabled
, false);
323 tr_variantDictAddStr (d
, TR_KEY_download_dir
, tr_getDefaultDownloadDir ());
324 tr_variantDictAddInt (d
, TR_KEY_speed_limit_down
, 100);
325 tr_variantDictAddBool (d
, TR_KEY_speed_limit_down_enabled
, false);
326 tr_variantDictAddInt (d
, TR_KEY_encryption
, TR_DEFAULT_ENCRYPTION
);
327 tr_variantDictAddInt (d
, TR_KEY_idle_seeding_limit
, 30);
328 tr_variantDictAddBool (d
, TR_KEY_idle_seeding_limit_enabled
, false);
329 tr_variantDictAddStr (d
, TR_KEY_incomplete_dir
, tr_getDefaultDownloadDir ());
330 tr_variantDictAddBool (d
, TR_KEY_incomplete_dir_enabled
, false);
331 tr_variantDictAddInt (d
, TR_KEY_message_level
, TR_LOG_INFO
);
332 tr_variantDictAddInt (d
, TR_KEY_download_queue_size
, 5);
333 tr_variantDictAddBool (d
, TR_KEY_download_queue_enabled
, true);
334 tr_variantDictAddInt (d
, TR_KEY_peer_limit_global
, atoi (TR_DEFAULT_PEER_LIMIT_GLOBAL_STR
));
335 tr_variantDictAddInt (d
, TR_KEY_peer_limit_per_torrent
, atoi (TR_DEFAULT_PEER_LIMIT_TORRENT_STR
));
336 tr_variantDictAddInt (d
, TR_KEY_peer_port
, atoi (TR_DEFAULT_PEER_PORT_STR
));
337 tr_variantDictAddBool (d
, TR_KEY_peer_port_random_on_start
, false);
338 tr_variantDictAddInt (d
, TR_KEY_peer_port_random_low
, 49152);
339 tr_variantDictAddInt (d
, TR_KEY_peer_port_random_high
, 65535);
340 tr_variantDictAddStr (d
, TR_KEY_peer_socket_tos
, TR_DEFAULT_PEER_SOCKET_TOS_STR
);
341 tr_variantDictAddBool (d
, TR_KEY_pex_enabled
, true);
342 tr_variantDictAddBool (d
, TR_KEY_port_forwarding_enabled
, true);
343 tr_variantDictAddInt (d
, TR_KEY_preallocation
, TR_PREALLOCATE_SPARSE
);
344 tr_variantDictAddBool (d
, TR_KEY_prefetch_enabled
, DEFAULT_PREFETCH_ENABLED
);
345 tr_variantDictAddInt (d
, TR_KEY_peer_id_ttl_hours
, 6);
346 tr_variantDictAddBool (d
, TR_KEY_queue_stalled_enabled
, true);
347 tr_variantDictAddInt (d
, TR_KEY_queue_stalled_minutes
, 30);
348 tr_variantDictAddReal (d
, TR_KEY_ratio_limit
, 2.0);
349 tr_variantDictAddBool (d
, TR_KEY_ratio_limit_enabled
, false);
350 tr_variantDictAddBool (d
, TR_KEY_rename_partial_files
, true);
351 tr_variantDictAddBool (d
, TR_KEY_rpc_authentication_required
, false);
352 tr_variantDictAddStr (d
, TR_KEY_rpc_bind_address
, "0.0.0.0");
353 tr_variantDictAddBool (d
, TR_KEY_rpc_enabled
, false);
354 tr_variantDictAddStr (d
, TR_KEY_rpc_password
, "");
355 tr_variantDictAddStr (d
, TR_KEY_rpc_username
, "");
356 tr_variantDictAddStr (d
, TR_KEY_rpc_whitelist
, TR_DEFAULT_RPC_WHITELIST
);
357 tr_variantDictAddBool (d
, TR_KEY_rpc_whitelist_enabled
, true);
358 tr_variantDictAddInt (d
, TR_KEY_rpc_port
, atoi (TR_DEFAULT_RPC_PORT_STR
));
359 tr_variantDictAddStr (d
, TR_KEY_rpc_url
, TR_DEFAULT_RPC_URL_STR
);
360 tr_variantDictAddBool (d
, TR_KEY_scrape_paused_torrents_enabled
, true);
361 tr_variantDictAddStr (d
, TR_KEY_script_torrent_done_filename
, "");
362 tr_variantDictAddBool (d
, TR_KEY_script_torrent_done_enabled
, false);
363 tr_variantDictAddInt (d
, TR_KEY_seed_queue_size
, 10);
364 tr_variantDictAddBool (d
, TR_KEY_seed_queue_enabled
, false);
365 tr_variantDictAddBool (d
, TR_KEY_alt_speed_enabled
, false);
366 tr_variantDictAddInt (d
, TR_KEY_alt_speed_up
, 50); /* half the regular */
367 tr_variantDictAddInt (d
, TR_KEY_alt_speed_down
, 50); /* half the regular */
368 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_begin
, 540); /* 9am */
369 tr_variantDictAddBool (d
, TR_KEY_alt_speed_time_enabled
, false);
370 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_end
, 1020); /* 5pm */
371 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_day
, TR_SCHED_ALL
);
372 tr_variantDictAddInt (d
, TR_KEY_speed_limit_up
, 100);
373 tr_variantDictAddBool (d
, TR_KEY_speed_limit_up_enabled
, false);
374 tr_variantDictAddInt (d
, TR_KEY_umask
, 022);
375 tr_variantDictAddInt (d
, TR_KEY_upload_slots_per_torrent
, 14);
376 tr_variantDictAddStr (d
, TR_KEY_bind_address_ipv4
, TR_DEFAULT_BIND_ADDRESS_IPV4
);
377 tr_variantDictAddStr (d
, TR_KEY_bind_address_ipv6
, TR_DEFAULT_BIND_ADDRESS_IPV6
);
378 tr_variantDictAddBool (d
, TR_KEY_start_added_torrents
, true);
379 tr_variantDictAddBool (d
, TR_KEY_trash_original_torrent_files
, false);
383 tr_sessionGetSettings (tr_session
* s
, tr_variant
* d
)
385 assert (tr_variantIsDict (d
));
387 tr_variantDictReserve (d
, 63);
388 tr_variantDictAddBool (d
, TR_KEY_blocklist_enabled
, tr_blocklistIsEnabled (s
));
389 tr_variantDictAddStr (d
, TR_KEY_blocklist_url
, tr_blocklistGetURL (s
));
390 tr_variantDictAddInt (d
, TR_KEY_cache_size_mb
, tr_sessionGetCacheLimit_MB (s
));
391 tr_variantDictAddBool (d
, TR_KEY_dht_enabled
, s
->isDHTEnabled
);
392 tr_variantDictAddBool (d
, TR_KEY_utp_enabled
, s
->isUTPEnabled
);
393 tr_variantDictAddBool (d
, TR_KEY_lpd_enabled
, s
->isLPDEnabled
);
394 tr_variantDictAddStr (d
, TR_KEY_download_dir
, tr_sessionGetDownloadDir (s
));
395 tr_variantDictAddInt (d
, TR_KEY_download_queue_size
, tr_sessionGetQueueSize (s
, TR_DOWN
));
396 tr_variantDictAddBool (d
, TR_KEY_download_queue_enabled
, tr_sessionGetQueueEnabled (s
, TR_DOWN
));
397 tr_variantDictAddInt (d
, TR_KEY_speed_limit_down
, tr_sessionGetSpeedLimit_KBps (s
, TR_DOWN
));
398 tr_variantDictAddBool (d
, TR_KEY_speed_limit_down_enabled
, tr_sessionIsSpeedLimited (s
, TR_DOWN
));
399 tr_variantDictAddInt (d
, TR_KEY_encryption
, s
->encryptionMode
);
400 tr_variantDictAddInt (d
, TR_KEY_idle_seeding_limit
, tr_sessionGetIdleLimit (s
));
401 tr_variantDictAddBool (d
, TR_KEY_idle_seeding_limit_enabled
, tr_sessionIsIdleLimited (s
));
402 tr_variantDictAddStr (d
, TR_KEY_incomplete_dir
, tr_sessionGetIncompleteDir (s
));
403 tr_variantDictAddBool (d
, TR_KEY_incomplete_dir_enabled
, tr_sessionIsIncompleteDirEnabled (s
));
404 tr_variantDictAddInt (d
, TR_KEY_message_level
, tr_logGetLevel ());
405 tr_variantDictAddInt (d
, TR_KEY_peer_limit_global
, s
->peerLimit
);
406 tr_variantDictAddInt (d
, TR_KEY_peer_limit_per_torrent
, s
->peerLimitPerTorrent
);
407 tr_variantDictAddInt (d
, TR_KEY_peer_port
, tr_sessionGetPeerPort (s
));
408 tr_variantDictAddBool (d
, TR_KEY_peer_port_random_on_start
, s
->isPortRandom
);
409 tr_variantDictAddInt (d
, TR_KEY_peer_port_random_low
, s
->randomPortLow
);
410 tr_variantDictAddInt (d
, TR_KEY_peer_port_random_high
, s
->randomPortHigh
);
411 tr_variantDictAddStr (d
, TR_KEY_peer_socket_tos
, format_tos (s
->peerSocketTOS
));
412 tr_variantDictAddStr (d
, TR_KEY_peer_congestion_algorithm
, s
->peer_congestion_algorithm
);
413 tr_variantDictAddBool (d
, TR_KEY_pex_enabled
, s
->isPexEnabled
);
414 tr_variantDictAddBool (d
, TR_KEY_port_forwarding_enabled
, tr_sessionIsPortForwardingEnabled (s
));
415 tr_variantDictAddInt (d
, TR_KEY_preallocation
, s
->preallocationMode
);
416 tr_variantDictAddInt (d
, TR_KEY_prefetch_enabled
, s
->isPrefetchEnabled
);
417 tr_variantDictAddInt (d
, TR_KEY_peer_id_ttl_hours
, s
->peer_id_ttl_hours
);
418 tr_variantDictAddBool (d
, TR_KEY_queue_stalled_enabled
, tr_sessionGetQueueStalledEnabled (s
));
419 tr_variantDictAddInt (d
, TR_KEY_queue_stalled_minutes
, tr_sessionGetQueueStalledMinutes (s
));
420 tr_variantDictAddReal (d
, TR_KEY_ratio_limit
, s
->desiredRatio
);
421 tr_variantDictAddBool (d
, TR_KEY_ratio_limit_enabled
, s
->isRatioLimited
);
422 tr_variantDictAddBool (d
, TR_KEY_rename_partial_files
, tr_sessionIsIncompleteFileNamingEnabled (s
));
423 tr_variantDictAddBool (d
, TR_KEY_rpc_authentication_required
, tr_sessionIsRPCPasswordEnabled (s
));
424 tr_variantDictAddStr (d
, TR_KEY_rpc_bind_address
, tr_sessionGetRPCBindAddress (s
));
425 tr_variantDictAddBool (d
, TR_KEY_rpc_enabled
, tr_sessionIsRPCEnabled (s
));
426 tr_variantDictAddStr (d
, TR_KEY_rpc_password
, tr_sessionGetRPCPassword (s
));
427 tr_variantDictAddInt (d
, TR_KEY_rpc_port
, tr_sessionGetRPCPort (s
));
428 tr_variantDictAddStr (d
, TR_KEY_rpc_url
, tr_sessionGetRPCUrl (s
));
429 tr_variantDictAddStr (d
, TR_KEY_rpc_username
, tr_sessionGetRPCUsername (s
));
430 tr_variantDictAddStr (d
, TR_KEY_rpc_whitelist
, tr_sessionGetRPCWhitelist (s
));
431 tr_variantDictAddBool (d
, TR_KEY_rpc_whitelist_enabled
, tr_sessionGetRPCWhitelistEnabled (s
));
432 tr_variantDictAddBool (d
, TR_KEY_scrape_paused_torrents_enabled
, s
->scrapePausedTorrents
);
433 tr_variantDictAddBool (d
, TR_KEY_script_torrent_done_enabled
, tr_sessionIsTorrentDoneScriptEnabled (s
));
434 tr_variantDictAddStr (d
, TR_KEY_script_torrent_done_filename
, tr_sessionGetTorrentDoneScript (s
));
435 tr_variantDictAddInt (d
, TR_KEY_seed_queue_size
, tr_sessionGetQueueSize (s
, TR_UP
));
436 tr_variantDictAddBool (d
, TR_KEY_seed_queue_enabled
, tr_sessionGetQueueEnabled (s
, TR_UP
));
437 tr_variantDictAddBool (d
, TR_KEY_alt_speed_enabled
, tr_sessionUsesAltSpeed (s
));
438 tr_variantDictAddInt (d
, TR_KEY_alt_speed_up
, tr_sessionGetAltSpeed_KBps (s
, TR_UP
));
439 tr_variantDictAddInt (d
, TR_KEY_alt_speed_down
, tr_sessionGetAltSpeed_KBps (s
, TR_DOWN
));
440 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_begin
, tr_sessionGetAltSpeedBegin (s
));
441 tr_variantDictAddBool (d
, TR_KEY_alt_speed_time_enabled
, tr_sessionUsesAltSpeedTime (s
));
442 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_end
, tr_sessionGetAltSpeedEnd (s
));
443 tr_variantDictAddInt (d
, TR_KEY_alt_speed_time_day
, tr_sessionGetAltSpeedDay (s
));
444 tr_variantDictAddInt (d
, TR_KEY_speed_limit_up
, tr_sessionGetSpeedLimit_KBps (s
, TR_UP
));
445 tr_variantDictAddBool (d
, TR_KEY_speed_limit_up_enabled
, tr_sessionIsSpeedLimited (s
, TR_UP
));
446 tr_variantDictAddInt (d
, TR_KEY_umask
, s
->umask
);
447 tr_variantDictAddInt (d
, TR_KEY_upload_slots_per_torrent
, s
->uploadSlotsPerTorrent
);
448 tr_variantDictAddStr (d
, TR_KEY_bind_address_ipv4
, tr_address_to_string (&s
->public_ipv4
->addr
));
449 tr_variantDictAddStr (d
, TR_KEY_bind_address_ipv6
, tr_address_to_string (&s
->public_ipv6
->addr
));
450 tr_variantDictAddBool (d
, TR_KEY_start_added_torrents
, !tr_sessionGetPaused (s
));
451 tr_variantDictAddBool (d
, TR_KEY_trash_original_torrent_files
, tr_sessionGetDeleteSource (s
));
455 tr_sessionLoadSettings (tr_variant
* dict
, const char * configDir
, const char * appName
)
459 tr_variant fileSettings
;
460 tr_variant sessionDefaults
;
462 bool success
= false;
464 assert (tr_variantIsDict (dict
));
466 /* initializing the defaults: caller may have passed in some app-level defaults.
467 * preserve those and use the session defaults to fill in any missing gaps. */
468 tr_variantInitDict (&sessionDefaults
, 0);
469 tr_sessionGetDefaultSettings (&sessionDefaults
);
470 tr_variantMergeDicts (&sessionDefaults
, dict
);
472 *dict
= sessionDefaults
;
473 sessionDefaults
= tmp
;
475 /* if caller didn't specify a config dir, use the default */
476 if (!configDir
|| !*configDir
)
477 configDir
= tr_getDefaultConfigDir (appName
);
479 /* file settings override the defaults */
480 filename
= tr_buildPath (configDir
, "settings.json", NULL
);
481 err
= tr_variantFromFile (&fileSettings
, TR_VARIANT_FMT_JSON
, filename
);
484 tr_variantMergeDicts (dict
, &fileSettings
);
485 tr_variantFree (&fileSettings
);
489 tr_variantFree (&sessionDefaults
);
491 success
= (err
==0) || (err
==ENOENT
);
496 tr_sessionSaveSettings (tr_session
* session
,
497 const char * configDir
,
498 const tr_variant
* clientSettings
)
501 char * filename
= tr_buildPath (configDir
, "settings.json", NULL
);
503 assert (tr_variantIsDict (clientSettings
));
505 tr_variantInitDict (&settings
, 0);
507 /* the existing file settings are the fallback values */
509 tr_variant fileSettings
;
510 const int err
= tr_variantFromFile (&fileSettings
, TR_VARIANT_FMT_JSON
, filename
);
513 tr_variantMergeDicts (&settings
, &fileSettings
);
514 tr_variantFree (&fileSettings
);
518 /* the client's settings override the file settings */
519 tr_variantMergeDicts (&settings
, clientSettings
);
521 /* the session's true values override the file & client settings */
523 tr_variant sessionSettings
;
524 tr_variantInitDict (&sessionSettings
, 0);
525 tr_sessionGetSettings (session
, &sessionSettings
);
526 tr_variantMergeDicts (&settings
, &sessionSettings
);
527 tr_variantFree (&sessionSettings
);
530 /* save the result */
531 tr_variantToFile (&settings
, TR_VARIANT_FMT_JSON
, filename
);
535 tr_variantFree (&settings
);
543 * Periodically save the .resume files of any torrents whose
544 * status has recently changed. This prevents loss of metadata
545 * in the case of a crash, unclean shutdown, clumsy user, etc.
548 onSaveTimer (evutil_socket_t foo UNUSED
, short bar UNUSED
, void * vsession
)
550 tr_torrent
* tor
= NULL
;
551 tr_session
* session
= vsession
;
553 if (tr_cacheFlushDone (session
->cache
))
554 tr_logAddError ("Error while flushing completed pieces from cache");
556 while ((tor
= tr_torrentNext (session
, tor
)))
557 tr_torrentSave (tor
);
559 tr_statsSaveDirty (session
);
561 tr_timerAdd (session
->saveTimer
, SAVE_INTERVAL_SECS
, 0);
568 static void tr_sessionInitImpl (void *);
573 bool messageQueuingEnabled
;
574 tr_session
* session
;
575 const char * configDir
;
576 tr_variant
* clientSettings
;
580 tr_sessionInit (const char * tag
,
581 const char * configDir
,
582 bool messageQueuingEnabled
,
583 tr_variant
* clientSettings
)
586 tr_session
* session
;
587 struct init_data data
;
589 assert (tr_variantIsDict (clientSettings
));
591 tr_timeUpdate (time (NULL
));
593 /* initialize the bare skeleton of the session object */
594 session
= tr_new0 (tr_session
, 1);
595 session
->udp_socket
= -1;
596 session
->udp6_socket
= -1;
597 session
->lock
= tr_lockNew ();
598 session
->cache
= tr_cacheNew (1024*1024*2);
599 session
->tag
= tr_strdup (tag
);
600 session
->magicNumber
= SESSION_MAGIC_NUMBER
;
601 tr_bandwidthConstruct (&session
->bandwidth
, session
, NULL
);
602 tr_variantInitList (&session
->removedTorrents
, 0);
604 /* nice to start logging at the very beginning */
605 if (tr_variantDictFindInt (clientSettings
, TR_KEY_message_level
, &i
))
608 /* start the libtransmission thread */
609 tr_netInit (); /* must go before tr_eventInit */
610 tr_eventInit (session
);
611 assert (session
->events
!= NULL
);
613 /* run the rest in the libtransmission thread */
615 data
.session
= session
;
616 data
.configDir
= configDir
;
617 data
.messageQueuingEnabled
= messageQueuingEnabled
;
618 data
.clientSettings
= clientSettings
;
619 tr_runInEventThread (session
, tr_sessionInitImpl
, &data
);
626 static void turtleCheckClock (tr_session
* s
, struct tr_turtle_info
* t
);
629 onNowTimer (evutil_socket_t foo UNUSED
, short bar UNUSED
, void * vsession
)
633 const int max
= 999999;
635 tr_torrent
* tor
= NULL
;
636 tr_session
* session
= vsession
;
637 const time_t now
= time (NULL
);
639 assert (tr_isSession (session
));
640 assert (session
->nowTimer
!= NULL
);
643 *** tr_session things to do once per second
648 tr_dhtUpkeep (session
);
650 if (session
->turtle
.isClockEnabled
)
651 turtleCheckClock (session
, &session
->turtle
);
653 while ((tor
= tr_torrentNext (session
, tor
)))
657 if (tr_torrentIsSeed (tor
))
658 ++tor
->secondsSeeding
;
660 ++tor
->secondsDownloading
;
668 /* schedule the next timer for right after the next second begins */
669 tr_gettimeofday (&tv
);
670 usec
= 1000000 - tv
.tv_usec
;
675 tr_timerAdd (session
->nowTimer
, 0, usec
);
676 /* fprintf (stderr, "time %"TR_PRIuSIZE" sec, %"TR_PRIuSIZE" microsec\n", (size_t)tr_time (), (size_t)tv.tv_usec); */
679 static void loadBlocklists (tr_session
* session
);
682 tr_sessionInitImpl (void * vdata
)
685 struct init_data
* data
= vdata
;
686 tr_variant
* clientSettings
= data
->clientSettings
;
687 tr_session
* session
= data
->session
;
689 assert (tr_amInEventThread (session
));
690 assert (tr_variantIsDict (clientSettings
));
692 dbgmsg ("tr_sessionInit: the session's top-level bandwidth object is %p",
693 (void*)&session
->bandwidth
);
695 tr_variantInitDict (&settings
, 0);
696 tr_sessionGetDefaultSettings (&settings
);
697 tr_variantMergeDicts (&settings
, clientSettings
);
699 assert (session
->event_base
!= NULL
);
700 session
->nowTimer
= evtimer_new (session
->event_base
, onNowTimer
, session
);
701 onNowTimer (0, 0, session
);
704 /* Don't exit when writing on a broken socket */
705 signal (SIGPIPE
, SIG_IGN
);
708 tr_logSetQueueEnabled (data
->messageQueuingEnabled
);
710 tr_setConfigDir (session
, data
->configDir
);
712 session
->peerMgr
= tr_peerMgrNew (session
);
714 session
->shared
= tr_sharedInit (session
);
721 char * filename
= tr_buildPath (session
->configDir
, "blocklists", NULL
);
722 tr_mkdirp (filename
, 0777);
724 loadBlocklists (session
);
727 assert (tr_isSession (session
));
729 session
->saveTimer
= evtimer_new (session
->event_base
, onSaveTimer
, session
);
730 tr_timerAdd (session
->saveTimer
, SAVE_INTERVAL_SECS
, 0);
732 tr_announcerInit (session
);
734 /* first %s is the application name
735 second %s is the version number */
736 tr_logAddInfo (_("%s %s started"), TR_NAME
, LONG_VERSION_STRING
);
738 tr_statsInit (session
);
740 tr_sessionSet (session
, &settings
);
742 tr_udpInit (session
);
744 if (session
->isLPDEnabled
)
745 tr_lpdInit (session
, &session
->public_ipv4
->addr
);
748 tr_variantFree (&settings
);
752 static void turtleBootstrap (tr_session
*, struct tr_turtle_info
*);
753 static void setPeerPort (tr_session
* session
, tr_port port
);
756 sessionSetImpl (void * vdata
)
762 struct tr_bindinfo b
;
763 struct init_data
* data
= vdata
;
764 tr_session
* session
= data
->session
;
765 tr_variant
* settings
= data
->clientSettings
;
766 struct tr_turtle_info
* turtle
= &session
->turtle
;
768 assert (tr_isSession (session
));
769 assert (tr_variantIsDict (settings
));
770 assert (tr_amInEventThread (session
));
772 if (tr_variantDictFindInt (settings
, TR_KEY_message_level
, &i
))
775 if (tr_variantDictFindInt (settings
, TR_KEY_umask
, &i
))
777 session
->umask
= (mode_t
)i
;
778 umask (session
->umask
);
782 if (tr_variantDictFindInt (settings
, TR_KEY_cache_size_mb
, &i
))
783 tr_sessionSetCacheLimit_MB (session
, i
);
784 if (tr_variantDictFindInt (settings
, TR_KEY_peer_limit_per_torrent
, &i
))
785 tr_sessionSetPeerLimitPerTorrent (session
, i
);
786 if (tr_variantDictFindBool (settings
, TR_KEY_pex_enabled
, &boolVal
))
787 tr_sessionSetPexEnabled (session
, boolVal
);
788 if (tr_variantDictFindBool (settings
, TR_KEY_dht_enabled
, &boolVal
))
789 tr_sessionSetDHTEnabled (session
, boolVal
);
790 if (tr_variantDictFindBool (settings
, TR_KEY_utp_enabled
, &boolVal
))
791 tr_sessionSetUTPEnabled (session
, boolVal
);
792 if (tr_variantDictFindBool (settings
, TR_KEY_lpd_enabled
, &boolVal
))
793 tr_sessionSetLPDEnabled (session
, boolVal
);
794 if (tr_variantDictFindInt (settings
, TR_KEY_encryption
, &i
))
795 tr_sessionSetEncryption (session
, i
);
796 if (tr_variantDictFindStr (settings
, TR_KEY_peer_socket_tos
, &str
, NULL
))
797 session
->peerSocketTOS
= parse_tos (str
);
798 if (tr_variantDictFindStr (settings
, TR_KEY_peer_congestion_algorithm
, &str
, NULL
))
799 session
->peer_congestion_algorithm
= tr_strdup (str
);
801 session
->peer_congestion_algorithm
= tr_strdup ("");
802 if (tr_variantDictFindBool (settings
, TR_KEY_blocklist_enabled
, &boolVal
))
803 tr_blocklistSetEnabled (session
, boolVal
);
804 if (tr_variantDictFindStr (settings
, TR_KEY_blocklist_url
, &str
, NULL
))
805 tr_blocklistSetURL (session
, str
);
806 if (tr_variantDictFindBool (settings
, TR_KEY_start_added_torrents
, &boolVal
))
807 tr_sessionSetPaused (session
, !boolVal
);
808 if (tr_variantDictFindBool (settings
, TR_KEY_trash_original_torrent_files
, &boolVal
))
809 tr_sessionSetDeleteSource (session
, boolVal
);
810 if (tr_variantDictFindInt (settings
, TR_KEY_peer_id_ttl_hours
, &i
))
811 session
->peer_id_ttl_hours
= i
;
814 if (tr_variantDictFindInt (settings
, TR_KEY_queue_stalled_minutes
, &i
))
815 tr_sessionSetQueueStalledMinutes (session
, i
);
816 if (tr_variantDictFindBool (settings
, TR_KEY_queue_stalled_enabled
, &boolVal
))
817 tr_sessionSetQueueStalledEnabled (session
, boolVal
);
818 if (tr_variantDictFindInt (settings
, TR_KEY_download_queue_size
, &i
))
819 tr_sessionSetQueueSize (session
, TR_DOWN
, i
);
820 if (tr_variantDictFindBool (settings
, TR_KEY_download_queue_enabled
, &boolVal
))
821 tr_sessionSetQueueEnabled (session
, TR_DOWN
, boolVal
);
822 if (tr_variantDictFindInt (settings
, TR_KEY_seed_queue_size
, &i
))
823 tr_sessionSetQueueSize (session
, TR_UP
, i
);
824 if (tr_variantDictFindBool (settings
, TR_KEY_seed_queue_enabled
, &boolVal
))
825 tr_sessionSetQueueEnabled (session
, TR_UP
, boolVal
);
827 /* files and directories */
828 if (tr_variantDictFindBool (settings
, TR_KEY_prefetch_enabled
, &boolVal
))
829 session
->isPrefetchEnabled
= boolVal
;
830 if (tr_variantDictFindInt (settings
, TR_KEY_preallocation
, &i
))
831 session
->preallocationMode
= i
;
832 if (tr_variantDictFindStr (settings
, TR_KEY_download_dir
, &str
, NULL
))
833 tr_sessionSetDownloadDir (session
, str
);
834 if (tr_variantDictFindStr (settings
, TR_KEY_incomplete_dir
, &str
, NULL
))
835 tr_sessionSetIncompleteDir (session
, str
);
836 if (tr_variantDictFindBool (settings
, TR_KEY_incomplete_dir_enabled
, &boolVal
))
837 tr_sessionSetIncompleteDirEnabled (session
, boolVal
);
838 if (tr_variantDictFindBool (settings
, TR_KEY_rename_partial_files
, &boolVal
))
839 tr_sessionSetIncompleteFileNamingEnabled (session
, boolVal
);
842 if (session
->rpcServer
!= NULL
) /* close the old one */
843 tr_rpcClose (&session
->rpcServer
);
844 session
->rpcServer
= tr_rpcInit (session
, settings
);
846 /* public addresses */
848 free_incoming_peer_port (session
);
850 tr_variantDictFindStr (settings
, TR_KEY_bind_address_ipv4
, &str
, NULL
);
851 if (!tr_address_from_string (&b
.addr
, str
) || (b
.addr
.type
!= TR_AF_INET
))
852 b
.addr
= tr_inaddr_any
;
854 session
->public_ipv4
= tr_memdup (&b
, sizeof (struct tr_bindinfo
));
856 tr_variantDictFindStr (settings
, TR_KEY_bind_address_ipv6
, &str
, NULL
);
857 if (!tr_address_from_string (&b
.addr
, str
) || (b
.addr
.type
!= TR_AF_INET6
))
858 b
.addr
= tr_in6addr_any
;
860 session
->public_ipv6
= tr_memdup (&b
, sizeof (struct tr_bindinfo
));
862 /* incoming peer port */
863 if (tr_variantDictFindInt (settings
, TR_KEY_peer_port_random_low
, &i
))
864 session
->randomPortLow
= i
;
865 if (tr_variantDictFindInt (settings
, TR_KEY_peer_port_random_high
, &i
))
866 session
->randomPortHigh
= i
;
867 if (tr_variantDictFindBool (settings
, TR_KEY_peer_port_random_on_start
, &boolVal
))
868 tr_sessionSetPeerPortRandomOnStart (session
, boolVal
);
869 if (!tr_variantDictFindInt (settings
, TR_KEY_peer_port
, &i
))
870 i
= session
->private_peer_port
;
871 setPeerPort (session
, boolVal
? getRandomPort (session
) : i
);
872 if (tr_variantDictFindBool (settings
, TR_KEY_port_forwarding_enabled
, &boolVal
))
873 tr_sessionSetPortForwardingEnabled (session
, boolVal
);
875 if (tr_variantDictFindInt (settings
, TR_KEY_peer_limit_global
, &i
))
876 session
->peerLimit
= i
;
881 if (tr_variantDictFindInt (settings
, TR_KEY_upload_slots_per_torrent
, &i
))
882 session
->uploadSlotsPerTorrent
= i
;
884 if (tr_variantDictFindInt (settings
, TR_KEY_speed_limit_up
, &i
))
885 tr_sessionSetSpeedLimit_KBps (session
, TR_UP
, i
);
886 if (tr_variantDictFindBool (settings
, TR_KEY_speed_limit_up_enabled
, &boolVal
))
887 tr_sessionLimitSpeed (session
, TR_UP
, boolVal
);
889 if (tr_variantDictFindInt (settings
, TR_KEY_speed_limit_down
, &i
))
890 tr_sessionSetSpeedLimit_KBps (session
, TR_DOWN
, i
);
891 if (tr_variantDictFindBool (settings
, TR_KEY_speed_limit_down_enabled
, &boolVal
))
892 tr_sessionLimitSpeed (session
, TR_DOWN
, boolVal
);
894 if (tr_variantDictFindReal (settings
, TR_KEY_ratio_limit
, &d
))
895 tr_sessionSetRatioLimit (session
, d
);
896 if (tr_variantDictFindBool (settings
, TR_KEY_ratio_limit_enabled
, &boolVal
))
897 tr_sessionSetRatioLimited (session
, boolVal
);
899 if (tr_variantDictFindInt (settings
, TR_KEY_idle_seeding_limit
, &i
))
900 tr_sessionSetIdleLimit (session
, i
);
901 if (tr_variantDictFindBool (settings
, TR_KEY_idle_seeding_limit_enabled
, &boolVal
))
902 tr_sessionSetIdleLimited (session
, boolVal
);
908 /* update the turtle mode's fields */
909 if (tr_variantDictFindInt (settings
, TR_KEY_alt_speed_up
, &i
))
910 turtle
->speedLimit_Bps
[TR_UP
] = toSpeedBytes (i
);
911 if (tr_variantDictFindInt (settings
, TR_KEY_alt_speed_down
, &i
))
912 turtle
->speedLimit_Bps
[TR_DOWN
] = toSpeedBytes (i
);
913 if (tr_variantDictFindInt (settings
, TR_KEY_alt_speed_time_begin
, &i
))
914 turtle
->beginMinute
= i
;
915 if (tr_variantDictFindInt (settings
, TR_KEY_alt_speed_time_end
, &i
))
916 turtle
->endMinute
= i
;
917 if (tr_variantDictFindInt (settings
, TR_KEY_alt_speed_time_day
, &i
))
919 if (tr_variantDictFindBool (settings
, TR_KEY_alt_speed_time_enabled
, &boolVal
))
920 turtle
->isClockEnabled
= boolVal
;
921 if (tr_variantDictFindBool (settings
, TR_KEY_alt_speed_enabled
, &boolVal
))
922 turtle
->isEnabled
= boolVal
;
923 turtleBootstrap (session
, turtle
);
929 if (tr_variantDictFindBool (settings
, TR_KEY_script_torrent_done_enabled
, &boolVal
))
930 tr_sessionSetTorrentDoneScriptEnabled (session
, boolVal
);
931 if (tr_variantDictFindStr (settings
, TR_KEY_script_torrent_done_filename
, &str
, NULL
))
932 tr_sessionSetTorrentDoneScript (session
, str
);
935 if (tr_variantDictFindBool (settings
, TR_KEY_scrape_paused_torrents_enabled
, &boolVal
))
936 session
->scrapePausedTorrents
= boolVal
;
942 tr_sessionSet (tr_session
* session
, tr_variant
* settings
)
944 struct init_data data
;
946 data
.session
= session
;
947 data
.clientSettings
= settings
;
949 /* run the rest in the libtransmission thread */
950 tr_runInEventThread (session
, sessionSetImpl
, &data
);
960 tr_sessionSetDownloadDir (tr_session
* session
, const char * dir
)
962 struct tr_device_info
* info
= NULL
;
964 assert (tr_isSession (session
));
967 info
= tr_device_info_create (dir
);
968 tr_device_info_free (session
->downloadDir
);
969 session
->downloadDir
= info
;
973 tr_sessionGetDownloadDir (const tr_session
* session
)
975 const char * dir
= NULL
;
977 assert (tr_isSession (session
));
979 if ((session
!= NULL
) && (session
->downloadDir
!= NULL
))
980 dir
= session
->downloadDir
->path
;
986 tr_sessionGetDirFreeSpace (tr_session
* session
, const char * dir
)
990 if (!tr_strcmp0 (dir
, tr_sessionGetDownloadDir (session
)))
991 free_space
= tr_device_info_get_free_space (session
->downloadDir
);
993 free_space
= tr_getDirFreeSpace (dir
);
1003 tr_sessionSetIncompleteFileNamingEnabled (tr_session
* session
, bool b
)
1005 assert (tr_isSession (session
));
1006 assert (tr_isBool (b
));
1008 session
->isIncompleteFileNamingEnabled
= b
;
1012 tr_sessionIsIncompleteFileNamingEnabled (const tr_session
* session
)
1014 assert (tr_isSession (session
));
1016 return session
->isIncompleteFileNamingEnabled
;
1025 tr_sessionSetIncompleteDir (tr_session
* session
, const char * dir
)
1027 assert (tr_isSession (session
));
1029 if (session
->incompleteDir
!= dir
)
1031 tr_free (session
->incompleteDir
);
1033 session
->incompleteDir
= tr_strdup (dir
);
1038 tr_sessionGetIncompleteDir (const tr_session
* session
)
1040 assert (tr_isSession (session
));
1042 return session
->incompleteDir
;
1046 tr_sessionSetIncompleteDirEnabled (tr_session
* session
, bool b
)
1048 assert (tr_isSession (session
));
1049 assert (tr_isBool (b
));
1051 session
->isIncompleteDirEnabled
= b
;
1055 tr_sessionIsIncompleteDirEnabled (const tr_session
* session
)
1057 assert (tr_isSession (session
));
1059 return session
->isIncompleteDirEnabled
;
1067 tr_sessionLock (tr_session
* session
)
1069 assert (tr_isSession (session
));
1071 tr_lockLock (session
->lock
);
1075 tr_sessionUnlock (tr_session
* session
)
1077 assert (tr_isSession (session
));
1079 tr_lockUnlock (session
->lock
);
1083 tr_sessionIsLocked (const tr_session
* session
)
1085 return tr_isSession (session
) && tr_lockHave (session
->lock
);
1093 peerPortChanged (void * session
)
1095 tr_torrent
* tor
= NULL
;
1097 assert (tr_isSession (session
));
1099 close_incoming_peer_port (session
);
1100 open_incoming_peer_port (session
);
1101 tr_sharedPortChanged (session
);
1103 while ((tor
= tr_torrentNext (session
, tor
)))
1104 tr_torrentChangeMyPort (tor
);
1108 setPeerPort (tr_session
* session
, tr_port port
)
1110 session
->private_peer_port
= port
;
1111 session
->public_peer_port
= port
;
1113 tr_runInEventThread (session
, peerPortChanged
, session
);
1117 tr_sessionSetPeerPort (tr_session
* session
, tr_port port
)
1119 if (tr_isSession (session
) && (session
->private_peer_port
!= port
))
1121 setPeerPort (session
, port
);
1126 tr_sessionGetPeerPort (const tr_session
* session
)
1128 return tr_isSession (session
) ? session
->private_peer_port
: 0;
1132 tr_sessionSetPeerPortRandom (tr_session
* session
)
1134 assert (tr_isSession (session
));
1136 tr_sessionSetPeerPort (session
, getRandomPort (session
));
1137 return session
->private_peer_port
;
1141 tr_sessionSetPeerPortRandomOnStart (tr_session
* session
,
1144 assert (tr_isSession (session
));
1146 session
->isPortRandom
= random
;
1150 tr_sessionGetPeerPortRandomOnStart (tr_session
* session
)
1152 assert (tr_isSession (session
));
1154 return session
->isPortRandom
;
1158 tr_sessionGetPortForwarding (const tr_session
* session
)
1160 assert (tr_isSession (session
));
1162 return tr_sharedTraversalStatus (session
->shared
);
1170 tr_sessionSetRatioLimited (tr_session
* session
, bool isLimited
)
1172 assert (tr_isSession (session
));
1174 session
->isRatioLimited
= isLimited
;
1178 tr_sessionSetRatioLimit (tr_session
* session
, double desiredRatio
)
1180 assert (tr_isSession (session
));
1182 session
->desiredRatio
= desiredRatio
;
1186 tr_sessionIsRatioLimited (const tr_session
* session
)
1188 assert (tr_isSession (session
));
1190 return session
->isRatioLimited
;
1194 tr_sessionGetRatioLimit (const tr_session
* session
)
1196 assert (tr_isSession (session
));
1198 return session
->desiredRatio
;
1206 tr_sessionSetIdleLimited (tr_session
* session
, bool isLimited
)
1208 assert (tr_isSession (session
));
1210 session
->isIdleLimited
= isLimited
;
1214 tr_sessionSetIdleLimit (tr_session
* session
, uint16_t idleMinutes
)
1216 assert (tr_isSession (session
));
1218 session
->idleLimitMinutes
= idleMinutes
;
1222 tr_sessionIsIdleLimited (const tr_session
* session
)
1224 assert (tr_isSession (session
));
1226 return session
->isIdleLimited
;
1230 tr_sessionGetIdleLimit (const tr_session
* session
)
1232 assert (tr_isSession (session
));
1234 return session
->idleLimitMinutes
;
1244 tr_sessionGetActiveSpeedLimit_Bps (const tr_session
* session
, tr_direction dir
, unsigned int * setme_Bps
)
1246 bool isLimited
= true;
1248 if (!tr_isSession (session
))
1251 if (tr_sessionUsesAltSpeed (session
))
1252 *setme_Bps
= tr_sessionGetAltSpeed_Bps (session
, dir
);
1253 else if (tr_sessionIsSpeedLimited (session
, dir
))
1254 *setme_Bps
= tr_sessionGetSpeedLimit_Bps (session
, dir
);
1261 tr_sessionGetActiveSpeedLimit_KBps (const tr_session
* session
,
1263 double * setme_KBps
)
1265 unsigned int Bps
= 0;
1266 const bool is_active
= tr_sessionGetActiveSpeedLimit_Bps (session
, dir
, &Bps
);
1267 *setme_KBps
= toSpeedKBps (Bps
);
1272 updateBandwidth (tr_session
* session
, tr_direction dir
)
1274 unsigned int limit_Bps
= 0;
1275 const bool isLimited
= tr_sessionGetActiveSpeedLimit_Bps (session
, dir
, &limit_Bps
);
1276 const bool zeroCase
= isLimited
&& !limit_Bps
;
1278 tr_bandwidthSetLimited (&session
->bandwidth
, dir
, isLimited
&& !zeroCase
);
1280 tr_bandwidthSetDesiredSpeed_Bps (&session
->bandwidth
, dir
, limit_Bps
);
1285 MINUTES_PER_HOUR
= 60,
1286 MINUTES_PER_DAY
= MINUTES_PER_HOUR
* 24,
1287 MINUTES_PER_WEEK
= MINUTES_PER_DAY
* 7
1291 turtleUpdateTable (struct tr_turtle_info
* t
)
1294 tr_bitfield
* b
= &t
->minutes
;
1296 tr_bitfieldSetHasNone (b
);
1298 for (day
=0; day
<7; ++day
)
1300 if (t
->days
& (1<<day
))
1303 const time_t begin
= t
->beginMinute
;
1304 time_t end
= t
->endMinute
;
1307 end
+= MINUTES_PER_DAY
;
1309 for (i
=begin
; i
<end
; ++i
)
1310 tr_bitfieldAdd (b
, (i
+day
*MINUTES_PER_DAY
) % MINUTES_PER_WEEK
);
1316 altSpeedToggled (void * vsession
)
1318 tr_session
* session
= vsession
;
1319 struct tr_turtle_info
* t
= &session
->turtle
;
1321 assert (tr_isSession (session
));
1323 updateBandwidth (session
, TR_UP
);
1324 updateBandwidth (session
, TR_DOWN
);
1326 if (t
->callback
!= NULL
)
1327 (*t
->callback
)(session
, t
->isEnabled
, t
->changedByUser
, t
->callbackUserData
);
1331 useAltSpeed (tr_session
* s
, struct tr_turtle_info
* t
,
1332 bool enabled
, bool byUser
)
1334 assert (tr_isSession (s
));
1336 assert (tr_isBool (enabled
));
1337 assert (tr_isBool (byUser
));
1339 if (t
->isEnabled
!= enabled
)
1341 t
->isEnabled
= enabled
;
1342 t
->changedByUser
= byUser
;
1343 tr_runInEventThread (s
, altSpeedToggled
, s
);
1348 * @return whether turtle should be on/off according to the scheduler
1351 getInTurtleTime (const struct tr_turtle_info
* t
)
1354 size_t minute_of_the_week
;
1355 const time_t now
= tr_time ();
1357 tr_localtime_r (&now
, &tm
);
1359 minute_of_the_week
= tm
.tm_wday
* MINUTES_PER_DAY
1360 + tm
.tm_hour
* MINUTES_PER_HOUR
1362 if (minute_of_the_week
>= MINUTES_PER_WEEK
) /* leap minutes? */
1363 minute_of_the_week
= MINUTES_PER_WEEK
- 1;
1365 return tr_bitfieldHas (&t
->minutes
, minute_of_the_week
);
1368 static inline tr_auto_switch_state_t
1369 autoSwitchState (bool enabled
)
1371 return enabled
? TR_AUTO_SWITCH_ON
: TR_AUTO_SWITCH_OFF
;
1375 turtleCheckClock (tr_session
* s
, struct tr_turtle_info
* t
)
1378 bool alreadySwitched
;
1379 tr_auto_switch_state_t newAutoTurtleState
;
1381 assert (t
->isClockEnabled
);
1383 enabled
= getInTurtleTime (t
);
1384 newAutoTurtleState
= autoSwitchState (enabled
);
1385 alreadySwitched
= (t
->autoTurtleState
== newAutoTurtleState
);
1387 if (!alreadySwitched
)
1389 tr_logAddInfo ("Time to turn %s turtle mode!", (enabled
?"on":"off"));
1390 t
->autoTurtleState
= newAutoTurtleState
;
1391 useAltSpeed (s
, t
, enabled
, false);
1395 /* Called after the turtle's fields are loaded from an outside source.
1396 * It initializes the implementation fields
1397 * and turns on turtle mode if the clock settings say to. */
1399 turtleBootstrap (tr_session
* session
, struct tr_turtle_info
* turtle
)
1401 turtle
->changedByUser
= false;
1402 turtle
->autoTurtleState
= TR_AUTO_SWITCH_UNUSED
;
1404 tr_bitfieldConstruct (&turtle
->minutes
, MINUTES_PER_WEEK
);
1406 turtleUpdateTable (turtle
);
1408 if (turtle
->isClockEnabled
)
1410 turtle
->isEnabled
= getInTurtleTime (turtle
);
1411 turtle
->autoTurtleState
= autoSwitchState (turtle
->isEnabled
);
1414 altSpeedToggled (session
);
1419 **** Primary session speed limits
1423 tr_sessionSetSpeedLimit_Bps (tr_session
* s
, tr_direction d
, unsigned int Bps
)
1425 assert (tr_isSession (s
));
1426 assert (tr_isDirection (d
));
1428 s
->speedLimit_Bps
[d
] = Bps
;
1430 updateBandwidth (s
, d
);
1433 tr_sessionSetSpeedLimit_KBps (tr_session
* s
, tr_direction d
, unsigned int KBps
)
1435 tr_sessionSetSpeedLimit_Bps (s
, d
, toSpeedBytes (KBps
));
1439 tr_sessionGetSpeedLimit_Bps (const tr_session
* s
, tr_direction d
)
1441 assert (tr_isSession (s
));
1442 assert (tr_isDirection (d
));
1444 return s
->speedLimit_Bps
[d
];
1447 tr_sessionGetSpeedLimit_KBps (const tr_session
* s
, tr_direction d
)
1449 return toSpeedKBps (tr_sessionGetSpeedLimit_Bps (s
, d
));
1453 tr_sessionLimitSpeed (tr_session
* s
, tr_direction d
, bool b
)
1455 assert (tr_isSession (s
));
1456 assert (tr_isDirection (d
));
1457 assert (tr_isBool (b
));
1459 s
->speedLimitEnabled
[d
] = b
;
1461 updateBandwidth (s
, d
);
1465 tr_sessionIsSpeedLimited (const tr_session
* s
, tr_direction d
)
1467 assert (tr_isSession (s
));
1468 assert (tr_isDirection (d
));
1470 return s
->speedLimitEnabled
[d
];
1474 **** Alternative speed limits that are used during scheduled times
1478 tr_sessionSetAltSpeed_Bps (tr_session
* s
, tr_direction d
, unsigned int Bps
)
1480 assert (tr_isSession (s
));
1481 assert (tr_isDirection (d
));
1483 s
->turtle
.speedLimit_Bps
[d
] = Bps
;
1485 updateBandwidth (s
, d
);
1489 tr_sessionSetAltSpeed_KBps (tr_session
* s
, tr_direction d
, unsigned int KBps
)
1491 tr_sessionSetAltSpeed_Bps (s
, d
, toSpeedBytes (KBps
));
1495 tr_sessionGetAltSpeed_Bps (const tr_session
* s
, tr_direction d
)
1497 assert (tr_isSession (s
));
1498 assert (tr_isDirection (d
));
1500 return s
->turtle
.speedLimit_Bps
[d
];
1503 tr_sessionGetAltSpeed_KBps (const tr_session
* s
, tr_direction d
)
1505 return toSpeedKBps (tr_sessionGetAltSpeed_Bps (s
, d
));
1509 userPokedTheClock (tr_session
* s
, struct tr_turtle_info
* t
)
1511 tr_logAddDebug ("Refreshing the turtle mode clock due to user changes");
1513 t
->autoTurtleState
= TR_AUTO_SWITCH_UNUSED
;
1515 turtleUpdateTable (t
);
1517 if (t
->isClockEnabled
)
1519 const bool enabled
= getInTurtleTime (t
);
1520 useAltSpeed (s
, t
, enabled
, true);
1521 t
->autoTurtleState
= autoSwitchState (enabled
);
1526 tr_sessionUseAltSpeedTime (tr_session
* s
, bool b
)
1528 struct tr_turtle_info
* t
= &s
->turtle
;
1530 assert (tr_isSession (s
));
1531 assert (tr_isBool (b
));
1533 if (t
->isClockEnabled
!= b
)
1535 t
->isClockEnabled
= b
;
1536 userPokedTheClock (s
, t
);
1541 tr_sessionUsesAltSpeedTime (const tr_session
* s
)
1543 assert (tr_isSession (s
));
1545 return s
->turtle
.isClockEnabled
;
1549 tr_sessionSetAltSpeedBegin (tr_session
* s
, int minute
)
1551 assert (tr_isSession (s
));
1552 assert (0<=minute
&& minute
< (60*24));
1554 if (s
->turtle
.beginMinute
!= minute
)
1556 s
->turtle
.beginMinute
= minute
;
1557 userPokedTheClock (s
, &s
->turtle
);
1562 tr_sessionGetAltSpeedBegin (const tr_session
* s
)
1564 assert (tr_isSession (s
));
1566 return s
->turtle
.beginMinute
;
1570 tr_sessionSetAltSpeedEnd (tr_session
* s
, int minute
)
1572 assert (tr_isSession (s
));
1573 assert (0<=minute
&& minute
< (60*24));
1575 if (s
->turtle
.endMinute
!= minute
)
1577 s
->turtle
.endMinute
= minute
;
1578 userPokedTheClock (s
, &s
->turtle
);
1583 tr_sessionGetAltSpeedEnd (const tr_session
* s
)
1585 assert (tr_isSession (s
));
1587 return s
->turtle
.endMinute
;
1591 tr_sessionSetAltSpeedDay (tr_session
* s
, tr_sched_day days
)
1593 assert (tr_isSession (s
));
1595 if (s
->turtle
.days
!= days
)
1597 s
->turtle
.days
= days
;
1598 userPokedTheClock (s
, &s
->turtle
);
1603 tr_sessionGetAltSpeedDay (const tr_session
* s
)
1605 assert (tr_isSession (s
));
1607 return s
->turtle
.days
;
1611 tr_sessionUseAltSpeed (tr_session
* session
, bool enabled
)
1613 useAltSpeed (session
, &session
->turtle
, enabled
, true);
1617 tr_sessionUsesAltSpeed (const tr_session
* s
)
1619 assert (tr_isSession (s
));
1621 return s
->turtle
.isEnabled
;
1625 tr_sessionSetAltSpeedFunc (tr_session
* session
,
1626 tr_altSpeedFunc func
,
1629 assert (tr_isSession (session
));
1631 session
->turtle
.callback
= func
;
1632 session
->turtle
.callbackUserData
= userData
;
1636 tr_sessionClearAltSpeedFunc (tr_session
* session
)
1638 tr_sessionSetAltSpeedFunc (session
, NULL
, NULL
);
1646 tr_sessionSetPeerLimit (tr_session
* session
, uint16_t n
)
1648 assert (tr_isSession (session
));
1650 session
->peerLimit
= n
;
1654 tr_sessionGetPeerLimit (const tr_session
* session
)
1656 assert (tr_isSession (session
));
1658 return session
->peerLimit
;
1662 tr_sessionSetPeerLimitPerTorrent (tr_session
* session
, uint16_t n
)
1664 assert (tr_isSession (session
));
1666 session
->peerLimitPerTorrent
= n
;
1670 tr_sessionGetPeerLimitPerTorrent (const tr_session
* session
)
1672 assert (tr_isSession (session
));
1674 return session
->peerLimitPerTorrent
;
1682 tr_sessionSetPaused (tr_session
* session
, bool isPaused
)
1684 assert (tr_isSession (session
));
1686 session
->pauseAddedTorrent
= isPaused
;
1690 tr_sessionGetPaused (const tr_session
* session
)
1692 assert (tr_isSession (session
));
1694 return session
->pauseAddedTorrent
;
1698 tr_sessionSetDeleteSource (tr_session
* session
, bool deleteSource
)
1700 assert (tr_isSession (session
));
1702 session
->deleteSourceTorrent
= deleteSource
;
1706 tr_sessionGetDeleteSource (const tr_session
* session
)
1708 assert (tr_isSession (session
));
1710 return session
->deleteSourceTorrent
;
1718 tr_sessionGetPieceSpeed_Bps (const tr_session
* session
, tr_direction dir
)
1720 return tr_isSession (session
) ? tr_bandwidthGetPieceSpeed_Bps (&session
->bandwidth
, 0, dir
) : 0;
1724 tr_sessionGetRawSpeed_Bps (const tr_session
* session
, tr_direction dir
)
1726 return tr_isSession (session
) ? tr_bandwidthGetRawSpeed_Bps (&session
->bandwidth
, 0, dir
) : 0;
1729 tr_sessionGetRawSpeed_KBps (const tr_session
* session
, tr_direction dir
)
1731 return toSpeedKBps (tr_sessionGetRawSpeed_Bps (session
, dir
));
1736 tr_sessionCountTorrents (const tr_session
* session
)
1738 return tr_isSession (session
) ? session
->torrentCount
: 0;
1742 tr_sessionGetTorrents (tr_session
* session
, int * setme_n
)
1746 tr_torrent
** torrents
;
1749 assert (tr_isSession (session
));
1750 assert (setme_n
!= NULL
);
1752 n
= tr_sessionCountTorrents (session
);
1755 torrents
= tr_new (tr_torrent
*, n
);
1758 torrents
[i
] = tor
= tr_torrentNext (session
, tor
);
1764 compareTorrentByCur (const void * va
, const void * vb
)
1766 const tr_torrent
* a
= * (const tr_torrent
**)va
;
1767 const tr_torrent
* b
= * (const tr_torrent
**)vb
;
1768 const uint64_t aCur
= a
->downloadedCur
+ a
->uploadedCur
;
1769 const uint64_t bCur
= b
->downloadedCur
+ b
->uploadedCur
;
1772 return aCur
> bCur
? -1 : 1; /* close the biggest torrents first */
1777 static void closeBlocklists (tr_session
*);
1780 sessionCloseImpl (void * vsession
)
1783 tr_torrent
** torrents
;
1784 tr_session
* session
= vsession
;
1786 assert (tr_isSession (session
));
1788 session
->isClosing
= true;
1790 free_incoming_peer_port (session
);
1792 if (session
->isLPDEnabled
)
1793 tr_lpdUninit (session
);
1795 tr_utpClose (session
);
1796 tr_dhtUninit (session
);
1798 event_free (session
->saveTimer
);
1799 session
->saveTimer
= NULL
;
1801 event_free (session
->nowTimer
);
1802 session
->nowTimer
= NULL
;
1804 tr_verifyClose (session
);
1805 tr_sharedClose (session
);
1806 tr_rpcClose (&session
->rpcServer
);
1808 /* Close the torrents. Get the most active ones first so that
1809 * if we can't get them all closed in a reasonable amount of time,
1810 * at least we get the most important ones first. */
1811 torrents
= tr_sessionGetTorrents (session
, &n
);
1812 qsort (torrents
, n
, sizeof (tr_torrent
*), compareTorrentByCur
);
1814 tr_torrentFree (torrents
[i
]);
1817 /* Close the announcer *after* closing the torrents
1818 so that all the &event=stopped messages will be
1819 queued to be sent by tr_announcerClose () */
1820 tr_announcerClose (session
);
1822 /* and this goes *after* announcer close so that
1823 it won't be idle until the announce events are sent... */
1824 tr_webClose (session
, TR_WEB_CLOSE_WHEN_IDLE
);
1826 tr_cacheFree (session
->cache
);
1827 session
->cache
= NULL
;
1829 /* gotta keep udp running long enough to send out all
1830 the &event=stopped UDP tracker messages */
1831 while (!tr_tracker_udp_is_idle (session
))
1833 tr_tracker_udp_upkeep (session
);
1837 /* we had to wait until UDP trackers were closed before closing these: */
1838 evdns_base_free (session
->evdns_base
, 0);
1839 session
->evdns_base
= NULL
;
1840 tr_tracker_udp_close (session
);
1841 tr_udpUninit (session
);
1843 tr_statsClose (session
);
1844 tr_peerMgrFree (session
->peerMgr
);
1846 closeBlocklists (session
);
1848 tr_fdClose (session
);
1850 session
->isClosed
= true;
1854 deadlineReached (const time_t deadline
)
1856 return time (NULL
) >= deadline
;
1859 #define SHUTDOWN_MAX_SECONDS 20
1862 tr_sessionClose (tr_session
* session
)
1864 const time_t deadline
= time (NULL
) + SHUTDOWN_MAX_SECONDS
;
1866 assert (tr_isSession (session
));
1868 dbgmsg ("shutting down transmission session %p... now is %"TR_PRIuSIZE
", deadline is %"TR_PRIuSIZE
, (void*)session
, (size_t)time (NULL
), (size_t)deadline
);
1870 /* close the session */
1871 tr_runInEventThread (session
, sessionCloseImpl
, session
);
1872 while (!session
->isClosed
&& !deadlineReached (deadline
))
1874 dbgmsg ("waiting for the libtransmission thread to finish");
1878 /* "shared" and "tracker" have live sockets,
1879 * so we need to keep the transmission thread alive
1880 * for a bit while they tell the router & tracker
1881 * that we're closing now */
1882 while ((session
->shared
|| session
->web
|| session
->announcer
|| session
->announcer_udp
)
1883 && !deadlineReached (deadline
))
1885 dbgmsg ("waiting on port unmap (%p) or announcer (%p)... now %"TR_PRIuSIZE
" deadline %"TR_PRIuSIZE
,
1886 (void*)session
->shared
, (void*)session
->announcer
, (size_t)time (NULL
), (size_t)deadline
);
1890 tr_webClose (session
, TR_WEB_CLOSE_NOW
);
1892 /* close the libtransmission thread */
1893 tr_eventClose (session
);
1894 while (session
->events
!= NULL
)
1896 static bool forced
= false;
1897 dbgmsg ("waiting for libtransmission thread to finish... now %"TR_PRIuSIZE
" deadline %"TR_PRIuSIZE
, (size_t)time (NULL
), (size_t)deadline
);
1900 if (deadlineReached (deadline
) && !forced
)
1902 dbgmsg ("calling event_loopbreak ()");
1904 event_base_loopbreak (session
->event_base
);
1907 if (deadlineReached (deadline
+3))
1909 dbgmsg ("deadline+3 reached... calling break...\n");
1914 /* free the session memory */
1915 tr_variantFree (&session
->removedTorrents
);
1916 tr_bandwidthDestruct (&session
->bandwidth
);
1917 tr_bitfieldDestruct (&session
->turtle
.minutes
);
1918 tr_lockFree (session
->lock
);
1919 if (session
->metainfoLookup
)
1921 tr_variantFree (session
->metainfoLookup
);
1922 tr_free (session
->metainfoLookup
);
1924 tr_device_info_free (session
->downloadDir
);
1925 tr_free (session
->torrentDoneScript
);
1926 tr_free (session
->tag
);
1927 tr_free (session
->configDir
);
1928 tr_free (session
->resumeDir
);
1929 tr_free (session
->torrentDir
);
1930 tr_free (session
->incompleteDir
);
1931 tr_free (session
->blocklist_url
);
1932 tr_free (session
->peer_congestion_algorithm
);
1936 struct sessionLoadTorrentsData
1938 tr_session
* session
;
1941 tr_torrent
** torrents
;
1946 sessionLoadTorrents (void * vdata
)
1953 tr_list
* list
= NULL
;
1954 struct sessionLoadTorrentsData
* data
= vdata
;
1955 const char * dirname
= tr_getTorrentDir (data
->session
);
1957 assert (tr_isSession (data
->session
));
1959 tr_ctorSetSave (data
->ctor
, false); /* since we already have them */
1961 if (!stat (dirname
, &sb
)
1962 && S_ISDIR (sb
.st_mode
)
1963 && ((odir
= opendir (dirname
))))
1966 for (d
= readdir (odir
); d
!= NULL
; d
= readdir (odir
))
1968 if (tr_str_has_suffix (d
->d_name
, ".torrent"))
1971 char * path
= tr_buildPath (dirname
, d
->d_name
, NULL
);
1972 tr_ctorSetMetainfoFromFile (data
->ctor
, path
);
1973 if ((tor
= tr_torrentNew (data
->ctor
, NULL
, NULL
)))
1975 tr_list_prepend (&list
, tor
);
1984 data
->torrents
= tr_new (tr_torrent
*, n
);
1985 for (i
=0, l
=list
; l
!=NULL
; l
=l
->next
)
1986 data
->torrents
[i
++] = (tr_torrent
*) l
->data
;
1989 tr_list_free (&list
, NULL
);
1992 tr_logAddInfo (_("Loaded %d torrents"), n
);
1994 if (data
->setmeCount
)
1995 *data
->setmeCount
= n
;
2001 tr_sessionLoadTorrents (tr_session
* session
,
2005 struct sessionLoadTorrentsData data
;
2007 data
.session
= session
;
2009 data
.setmeCount
= setmeCount
;
2010 data
.torrents
= NULL
;
2013 tr_runInEventThread (session
, sessionLoadTorrents
, &data
);
2017 return data
.torrents
;
2025 tr_sessionSetPexEnabled (tr_session
* session
, bool enabled
)
2027 assert (tr_isSession (session
));
2028 assert (tr_isBool (enabled
));
2030 session
->isPexEnabled
= enabled
;
2034 tr_sessionIsPexEnabled (const tr_session
* session
)
2036 assert (tr_isSession (session
));
2038 return session
->isPexEnabled
;
2042 tr_sessionAllowsDHT (const tr_session
* session
)
2044 return tr_sessionIsDHTEnabled (session
);
2048 tr_sessionIsDHTEnabled (const tr_session
* session
)
2050 assert (tr_isSession (session
));
2052 return session
->isDHTEnabled
;
2056 toggleDHTImpl (void * data
)
2058 tr_session
* session
= data
;
2059 assert (tr_isSession (session
));
2061 tr_udpUninit (session
);
2062 session
->isDHTEnabled
= !session
->isDHTEnabled
;
2063 tr_udpInit (session
);
2067 tr_sessionSetDHTEnabled (tr_session
* session
, bool enabled
)
2069 assert (tr_isSession (session
));
2070 assert (tr_isBool (enabled
));
2072 if (enabled
!= session
->isDHTEnabled
)
2073 tr_runInEventThread (session
, toggleDHTImpl
, session
);
2081 tr_sessionIsUTPEnabled (const tr_session
* session
)
2083 assert (tr_isSession (session
));
2086 return session
->isUTPEnabled
;
2093 toggle_utp (void * data
)
2095 tr_session
* session
= data
;
2097 assert (tr_isSession (session
));
2099 session
->isUTPEnabled
= !session
->isUTPEnabled
;
2101 tr_udpSetSocketBuffers (session
);
2103 /* But don't call tr_utpClose -- see reset_timer in tr-utp.c for an
2108 tr_sessionSetUTPEnabled (tr_session
* session
, bool enabled
)
2110 assert (tr_isSession (session
));
2111 assert (tr_isBool (enabled
));
2113 if (enabled
!= session
->isUTPEnabled
)
2114 tr_runInEventThread (session
, toggle_utp
, session
);
2122 toggleLPDImpl (void * data
)
2124 tr_session
* session
= data
;
2125 assert (tr_isSession (session
));
2127 if (session
->isLPDEnabled
)
2128 tr_lpdUninit (session
);
2130 session
->isLPDEnabled
= !session
->isLPDEnabled
;
2132 if (session
->isLPDEnabled
)
2133 tr_lpdInit (session
, &session
->public_ipv4
->addr
);
2137 tr_sessionSetLPDEnabled (tr_session
* session
, bool enabled
)
2139 assert (tr_isSession (session
));
2140 assert (tr_isBool (enabled
));
2142 if (enabled
!= session
->isLPDEnabled
)
2143 tr_runInEventThread (session
, toggleLPDImpl
, session
);
2147 tr_sessionIsLPDEnabled (const tr_session
* session
)
2149 assert (tr_isSession (session
));
2151 return session
->isLPDEnabled
;
2155 tr_sessionAllowsLPD (const tr_session
* session
)
2157 return tr_sessionIsLPDEnabled (session
);
2165 tr_sessionSetCacheLimit_MB (tr_session
* session
, int max_bytes
)
2167 assert (tr_isSession (session
));
2169 tr_cacheSetLimit (session
->cache
, toMemBytes (max_bytes
));
2173 tr_sessionGetCacheLimit_MB (const tr_session
* session
)
2175 assert (tr_isSession (session
));
2177 return toMemMB (tr_cacheGetLimit (session
->cache
));
2184 struct port_forwarding_data
2187 struct tr_shared
* shared
;
2191 setPortForwardingEnabled (void * vdata
)
2193 struct port_forwarding_data
* data
= vdata
;
2194 tr_sharedTraversalEnable (data
->shared
, data
->enabled
);
2199 tr_sessionSetPortForwardingEnabled (tr_session
* session
, bool enabled
)
2201 struct port_forwarding_data
* d
;
2202 d
= tr_new0 (struct port_forwarding_data
, 1);
2203 d
->shared
= session
->shared
;
2204 d
->enabled
= enabled
;
2205 tr_runInEventThread (session
, setPortForwardingEnabled
, d
);
2209 tr_sessionIsPortForwardingEnabled (const tr_session
* session
)
2211 assert (tr_isSession (session
));
2213 return tr_sharedTraversalIsEnabled (session
->shared
);
2221 tr_stringEndsWith (const char * str
, const char * end
)
2223 const size_t slen
= strlen (str
);
2224 const size_t elen
= strlen (end
);
2226 return slen
>= elen
&& !memcmp (&str
[slen
- elen
], end
, elen
);
2230 loadBlocklists (tr_session
* session
)
2235 tr_list
* blocklists
= NULL
;
2236 tr_ptrArray loadme
= TR_PTR_ARRAY_INIT
;
2237 const bool isEnabled
= session
->isBlocklistEnabled
;
2239 /* walk the blocklist directory... */
2240 dirname
= tr_buildPath (session
->configDir
, "blocklists", NULL
);
2241 odir
= opendir (dirname
);
2248 while ((d
= readdir (odir
)))
2253 if (!d
->d_name
|| (d
->d_name
[0]=='.')) /* ignore dotfiles */
2256 path
= tr_buildPath (dirname
, d
->d_name
, NULL
);
2258 if (tr_stringEndsWith (path
, ".bin"))
2260 load
= tr_strdup (path
);
2266 time_t path_mtime
= 0;
2267 time_t binname_mtime
= 0;
2269 basename
= tr_basename (d
->d_name
);
2270 binname
= tr_strdup_printf ("%s" TR_PATH_DELIMITER_STR
"%s.bin", dirname
, basename
);
2272 if (!tr_fileExists (binname
, &binname_mtime
)) /* create it */
2274 tr_blocklistFile
* b
= tr_blocklistFileNew (binname
, isEnabled
);
2275 const int n
= tr_blocklistFileSetContent (b
, path
);
2277 load
= tr_strdup (binname
);
2279 tr_blocklistFileFree (b
);
2281 else if (tr_fileExists(path
,&path_mtime
) && (path_mtime
>=binname_mtime
)) /* update it */
2284 tr_blocklistFile
* b
;
2286 old
= tr_strdup_printf ("%s.old", binname
);
2288 tr_rename (binname
, old
);
2289 b
= tr_blocklistFileNew (binname
, isEnabled
);
2290 if (tr_blocklistFileSetContent (b
, path
) > 0)
2296 tr_remove (binname
);
2297 tr_rename (old
, binname
);
2300 tr_blocklistFileFree (b
);
2310 if (tr_ptrArrayFindSorted (&loadme
, load
, (PtrArrayCompareFunc
)strcmp
) == NULL
)
2311 tr_ptrArrayInsertSorted (&loadme
, load
, (PtrArrayCompareFunc
)strcmp
);
2319 if (!tr_ptrArrayEmpty (&loadme
))
2322 const int n
= tr_ptrArraySize (&loadme
);
2323 const char ** paths
= (const char **) tr_ptrArrayBase (&loadme
);
2326 tr_list_append (&blocklists
, tr_blocklistFileNew (paths
[i
], isEnabled
));
2332 tr_ptrArrayDestruct (&loadme
, (PtrArrayForeachFunc
)tr_free
);
2333 session
->blocklists
= blocklists
;
2337 closeBlocklists (tr_session
* session
)
2339 tr_list_free (&session
->blocklists
, (TrListForeachFunc
)tr_blocklistFileFree
);
2343 tr_sessionReloadBlocklists (tr_session
* session
)
2345 closeBlocklists (session
);
2346 loadBlocklists (session
);
2348 tr_peerMgrOnBlocklistChanged (session
->peerMgr
);
2352 tr_blocklistGetRuleCount (const tr_session
* session
)
2357 assert (tr_isSession (session
));
2359 for (l
= session
->blocklists
; l
; l
= l
->next
)
2360 n
+= tr_blocklistFileGetRuleCount (l
->data
);
2366 tr_blocklistIsEnabled (const tr_session
* session
)
2368 assert (tr_isSession (session
));
2370 return session
->isBlocklistEnabled
;
2374 tr_blocklistSetEnabled (tr_session
* session
, bool isEnabled
)
2378 assert (tr_isSession (session
));
2379 assert (tr_isBool (isEnabled
));
2381 session
->isBlocklistEnabled
= isEnabled
;
2383 for (l
=session
->blocklists
; l
!=NULL
; l
=l
->next
)
2384 tr_blocklistFileSetEnabled (l
->data
, isEnabled
);
2388 tr_blocklistExists (const tr_session
* session
)
2390 assert (tr_isSession (session
));
2392 return session
->blocklists
!= NULL
;
2396 tr_blocklistSetContent (tr_session
* session
, const char * contentFilename
)
2400 tr_blocklistFile
* b
;
2401 const char * defaultName
= DEFAULT_BLOCKLIST_FILENAME
;
2402 tr_sessionLock (session
);
2404 for (b
=NULL
, l
=session
->blocklists
; !b
&& l
; l
=l
->next
)
2405 if (tr_stringEndsWith (tr_blocklistFileGetFilename (l
->data
), defaultName
))
2410 char * path
= tr_buildPath (session
->configDir
, "blocklists", defaultName
, NULL
);
2411 b
= tr_blocklistFileNew (path
, session
->isBlocklistEnabled
);
2412 tr_list_append (&session
->blocklists
, b
);
2416 ruleCount
= tr_blocklistFileSetContent (b
, contentFilename
);
2417 tr_sessionUnlock (session
);
2422 tr_sessionIsAddressBlocked (const tr_session
* session
,
2423 const tr_address
* addr
)
2427 assert (tr_isSession (session
));
2429 for (l
= session
->blocklists
; l
; l
= l
->next
)
2430 if (tr_blocklistFileHasAddress (l
->data
, addr
))
2437 tr_blocklistSetURL (tr_session
* session
, const char * url
)
2439 if (session
->blocklist_url
!= url
)
2441 tr_free (session
->blocklist_url
);
2442 session
->blocklist_url
= tr_strdup (url
);
2447 tr_blocklistGetURL (const tr_session
* session
)
2449 return session
->blocklist_url
;
2458 metainfoLookupInit (tr_session
* session
)
2461 const char * dirname
= tr_getTorrentDir (session
);
2463 tr_ctor
* ctor
= NULL
;
2464 tr_variant
* lookup
;
2467 assert (tr_isSession (session
));
2469 /* walk through the directory and find the mappings */
2470 lookup
= tr_new0 (tr_variant
, 1);
2471 tr_variantInitDict (lookup
, 0);
2472 ctor
= tr_ctorNew (session
);
2473 tr_ctorSetSave (ctor
, false); /* since we already have them */
2474 if (!stat (dirname
, &sb
) && S_ISDIR (sb
.st_mode
) && ((odir
= opendir (dirname
))))
2477 while ((d
= readdir (odir
)))
2479 if (tr_str_has_suffix (d
->d_name
, ".torrent"))
2482 char * path
= tr_buildPath (dirname
, d
->d_name
, NULL
);
2483 tr_ctorSetMetainfoFromFile (ctor
, path
);
2484 if (!tr_torrentParse (ctor
, &inf
))
2487 tr_variantDictAddStr (lookup
, tr_quark_new(inf
.hashString
,-1), path
);
2496 session
->metainfoLookup
= lookup
;
2497 tr_logAddDebug ("Found %d torrents in \"%s\"", n
, dirname
);
2501 tr_sessionFindTorrentFile (const tr_session
* session
,
2502 const char * hashString
)
2504 const char * filename
= NULL
;
2506 if (!session
->metainfoLookup
)
2507 metainfoLookupInit ((tr_session
*)session
);
2508 tr_variantDictFindStr (session
->metainfoLookup
, tr_quark_new(hashString
,-1), &filename
, NULL
);
2514 tr_sessionSetTorrentFile (tr_session
* session
,
2515 const char * hashString
,
2516 const char * filename
)
2518 /* since we walk session->configDir/torrents/ to build the lookup table,
2519 * and tr_sessionSetTorrentFile () is just to tell us there's a new file
2520 * in that same directory, we don't need to do anything here if the
2521 * lookup table hasn't been built yet */
2522 if (session
->metainfoLookup
)
2523 tr_variantDictAddStr (session
->metainfoLookup
, tr_quark_new(hashString
,-1), filename
);
2531 tr_sessionSetRPCEnabled (tr_session
* session
, bool isEnabled
)
2533 assert (tr_isSession (session
));
2535 tr_rpcSetEnabled (session
->rpcServer
, isEnabled
);
2539 tr_sessionIsRPCEnabled (const tr_session
* session
)
2541 assert (tr_isSession (session
));
2543 return tr_rpcIsEnabled (session
->rpcServer
);
2547 tr_sessionSetRPCPort (tr_session
* session
,
2550 assert (tr_isSession (session
));
2552 tr_rpcSetPort (session
->rpcServer
, port
);
2556 tr_sessionGetRPCPort (const tr_session
* session
)
2558 assert (tr_isSession (session
));
2560 return tr_rpcGetPort (session
->rpcServer
);
2564 tr_sessionSetRPCUrl (tr_session
* session
,
2567 assert (tr_isSession (session
));
2569 tr_rpcSetUrl (session
->rpcServer
, url
);
2573 tr_sessionGetRPCUrl (const tr_session
* session
)
2575 assert (tr_isSession (session
));
2577 return tr_rpcGetUrl (session
->rpcServer
);
2581 tr_sessionSetRPCCallback (tr_session
* session
,
2585 assert (tr_isSession (session
));
2587 session
->rpc_func
= func
;
2588 session
->rpc_func_user_data
= user_data
;
2592 tr_sessionSetRPCWhitelist (tr_session
* session
,
2593 const char * whitelist
)
2595 assert (tr_isSession (session
));
2597 tr_rpcSetWhitelist (session
->rpcServer
, whitelist
);
2601 tr_sessionGetRPCWhitelist (const tr_session
* session
)
2603 assert (tr_isSession (session
));
2605 return tr_rpcGetWhitelist (session
->rpcServer
);
2609 tr_sessionSetRPCWhitelistEnabled (tr_session
* session
, bool isEnabled
)
2611 assert (tr_isSession (session
));
2613 tr_rpcSetWhitelistEnabled (session
->rpcServer
, isEnabled
);
2617 tr_sessionGetRPCWhitelistEnabled (const tr_session
* session
)
2619 assert (tr_isSession (session
));
2621 return tr_rpcGetWhitelistEnabled (session
->rpcServer
);
2626 tr_sessionSetRPCPassword (tr_session
* session
,
2627 const char * password
)
2629 assert (tr_isSession (session
));
2631 tr_rpcSetPassword (session
->rpcServer
, password
);
2635 tr_sessionGetRPCPassword (const tr_session
* session
)
2637 assert (tr_isSession (session
));
2639 return tr_rpcGetPassword (session
->rpcServer
);
2643 tr_sessionSetRPCUsername (tr_session
* session
,
2644 const char * username
)
2646 assert (tr_isSession (session
));
2648 tr_rpcSetUsername (session
->rpcServer
, username
);
2652 tr_sessionGetRPCUsername (const tr_session
* session
)
2654 assert (tr_isSession (session
));
2656 return tr_rpcGetUsername (session
->rpcServer
);
2660 tr_sessionSetRPCPasswordEnabled (tr_session
* session
, bool isEnabled
)
2662 assert (tr_isSession (session
));
2664 tr_rpcSetPasswordEnabled (session
->rpcServer
, isEnabled
);
2668 tr_sessionIsRPCPasswordEnabled (const tr_session
* session
)
2670 assert (tr_isSession (session
));
2672 return tr_rpcIsPasswordEnabled (session
->rpcServer
);
2676 tr_sessionGetRPCBindAddress (const tr_session
* session
)
2678 assert (tr_isSession (session
));
2680 return tr_rpcGetBindAddress (session
->rpcServer
);
2688 tr_sessionIsTorrentDoneScriptEnabled (const tr_session
* session
)
2690 assert (tr_isSession (session
));
2692 return session
->isTorrentDoneScriptEnabled
;
2696 tr_sessionSetTorrentDoneScriptEnabled (tr_session
* session
, bool isEnabled
)
2698 assert (tr_isSession (session
));
2699 assert (tr_isBool (isEnabled
));
2701 session
->isTorrentDoneScriptEnabled
= isEnabled
;
2705 tr_sessionGetTorrentDoneScript (const tr_session
* session
)
2707 assert (tr_isSession (session
));
2709 return session
->torrentDoneScript
;
2713 tr_sessionSetTorrentDoneScript (tr_session
* session
, const char * scriptFilename
)
2715 assert (tr_isSession (session
));
2717 if (session
->torrentDoneScript
!= scriptFilename
)
2719 tr_free (session
->torrentDoneScript
);
2720 session
->torrentDoneScript
= tr_strdup (scriptFilename
);
2729 tr_sessionSetQueueSize (tr_session
* session
, tr_direction dir
, int n
)
2731 assert (tr_isSession (session
));
2732 assert (tr_isDirection (dir
));
2734 session
->queueSize
[dir
] = n
;
2738 tr_sessionGetQueueSize (const tr_session
* session
, tr_direction dir
)
2740 assert (tr_isSession (session
));
2741 assert (tr_isDirection (dir
));
2743 return session
->queueSize
[dir
];
2747 tr_sessionSetQueueEnabled (tr_session
* session
, tr_direction dir
, bool is_enabled
)
2749 assert (tr_isSession (session
));
2750 assert (tr_isDirection (dir
));
2751 assert (tr_isBool (is_enabled
));
2753 session
->queueEnabled
[dir
] = is_enabled
;
2757 tr_sessionGetQueueEnabled (const tr_session
* session
, tr_direction dir
)
2759 assert (tr_isSession (session
));
2760 assert (tr_isDirection (dir
));
2762 return session
->queueEnabled
[dir
];
2766 tr_sessionSetQueueStalledMinutes (tr_session
* session
, int minutes
)
2768 assert (tr_isSession (session
));
2769 assert (minutes
> 0);
2771 session
->queueStalledMinutes
= minutes
;
2775 tr_sessionSetQueueStalledEnabled (tr_session
* session
, bool is_enabled
)
2777 assert (tr_isSession (session
));
2778 assert (tr_isBool (is_enabled
));
2780 session
->stalledEnabled
= is_enabled
;
2784 tr_sessionGetQueueStalledEnabled (const tr_session
* session
)
2786 assert (tr_isSession (session
));
2788 return session
->stalledEnabled
;
2792 tr_sessionGetQueueStalledMinutes (const tr_session
* session
)
2794 assert (tr_isSession (session
));
2796 return session
->queueStalledMinutes
;
2799 struct TorrentAndPosition
2806 compareTorrentAndPositions (const void * va
, const void * vb
)
2809 const struct TorrentAndPosition
* a
= va
;
2810 const struct TorrentAndPosition
* b
= vb
;
2812 if (a
->position
> b
->position
)
2814 else if (a
->position
< b
->position
)
2824 tr_sessionGetNextQueuedTorrents (tr_session
* session
,
2825 tr_direction direction
,
2827 tr_ptrArray
* setme
)
2832 struct TorrentAndPosition
* candidates
;
2834 assert (tr_isSession (session
));
2835 assert (tr_isDirection (direction
));
2837 /* build an array of the candidates */
2838 n
= tr_sessionCountTorrents (session
);
2839 candidates
= tr_new (struct TorrentAndPosition
, n
);
2842 while ((tor
= tr_torrentNext (session
, tor
)))
2844 if (!tr_torrentIsQueued (tor
))
2847 if (direction
!= tr_torrentGetQueueDirection (tor
))
2850 candidates
[i
].tor
= tor
;
2851 candidates
[i
].position
= tr_torrentGetQueuePosition (tor
);
2855 /* find the best n candidates */
2858 else if (num_wanted
< i
)
2859 tr_quickfindFirstK (candidates
, i
,
2860 sizeof(struct TorrentAndPosition
),
2861 compareTorrentAndPositions
, num_wanted
);
2863 /* add them to the return array */
2864 for (i
=0; i
<num_wanted
; ++i
)
2865 tr_ptrArrayAppend (setme
, candidates
[i
].tor
);
2868 tr_free (candidates
);
2872 tr_sessionCountQueueFreeSlots (tr_session
* session
, tr_direction dir
)
2876 const int max
= tr_sessionGetQueueSize (session
, dir
);
2877 const tr_torrent_activity activity
= dir
== TR_UP
? TR_STATUS_SEED
: TR_STATUS_DOWNLOAD
;
2879 if (!tr_sessionGetQueueEnabled (session
, dir
))
2884 while ((tor
= tr_torrentNext (session
, tor
)))
2885 if (!tr_torrentIsStalled (tor
))
2886 if (tr_torrentGetActivity (tor
) == activity
)
2889 if (active_count
>= max
)
2892 return max
- active_count
;