transmission 2.83
[tomato.git] / release / src-rt-6.x.4708 / router / transmission / libtransmission / session.c
bloba11c2363f2021d2836361171ddad23dd9a17476c
1 /*
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 $
8 */
10 #include <assert.h>
11 #include <errno.h> /* ENOENT */
12 #include <limits.h> /* INT_MAX */
13 #include <stdlib.h>
14 #include <string.h> /* memcpy */
16 #include <signal.h>
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"
32 #include "cache.h"
33 #include "crypto.h"
34 #include "fdlimit.h"
35 #include "list.h"
36 #include "log.h"
37 #include "net.h"
38 #include "peer-io.h"
39 #include "peer-mgr.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"
44 #include "session.h"
45 #include "stats.h"
46 #include "torrent.h"
47 #include "tr-dht.h" /* tr_dhtUpkeep () */
48 #include "tr-udp.h"
49 #include "tr-utp.h"
50 #include "tr-lpd.h"
51 #include "trevent.h"
52 #include "utils.h"
53 #include "variant.h"
54 #include "verify.h"
55 #include "version.h"
56 #include "web.h"
58 enum
60 #ifdef TR_LIGHTWEIGHT
61 DEFAULT_CACHE_SIZE_MB = 2,
62 DEFAULT_PREFETCH_ENABLED = false,
63 #else
64 DEFAULT_CACHE_SIZE_MB = 4,
65 DEFAULT_PREFETCH_ENABLED = true,
66 #endif
67 SAVE_INTERVAL_SECS = 360
71 #define dbgmsg(...) \
72 do \
73 { \
74 if (tr_logGetDeepEnabled ()) \
75 tr_logAddDeep (__FILE__, __LINE__, NULL, __VA_ARGS__); \
76 } \
77 while (0)
79 static tr_port
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) */
89 void
90 tr_peerIdInit (uint8_t * buf)
92 int i;
93 int val;
94 int total = 0;
95 const char * pool = "0123456789abcdefghijklmnopqrstuvwxyz";
96 const int base = 36;
98 memcpy (buf, PEERID_PREFIX, 8);
100 tr_cryptoRandBuf (buf+8, 11);
101 for (i=8; i<19; ++i)
103 val = buf[i] % base;
104 total += val;
105 buf[i] = pool[val];
108 val = total % base ? base - (total % base) : 0;
109 buf[19] = pool[val];
110 buf[20] = '\0';
113 /***
114 ****
115 ***/
117 tr_encryption_mode
118 tr_sessionGetEncryption (tr_session * session)
120 assert (session);
122 return session->encryptionMode;
125 void
126 tr_sessionSetEncryption (tr_session * session,
127 tr_encryption_mode mode)
129 assert (session);
130 assert (mode == TR_ENCRYPTION_PREFERRED
131 || mode == TR_ENCRYPTION_REQUIRED
132 || mode == TR_CLEAR_PREFERRED);
134 session->encryptionMode = mode;
137 /***
138 ****
139 ***/
141 struct tr_bindinfo
143 int socket;
144 tr_address addr;
145 struct event * ev;
149 static void
150 close_bindinfo (struct tr_bindinfo * b)
152 if ((b != NULL) && (b->socket >=0))
154 event_free (b->ev);
155 b->ev = NULL;
156 tr_netCloseSocket (b->socket);
160 static void
161 close_incoming_peer_port (tr_session * session)
163 close_bindinfo (session->public_ipv4);
164 close_bindinfo (session->public_ipv6);
167 static void
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;
179 static void
180 accept_incoming_peer (evutil_socket_t fd, short what UNUSED, void * vsession)
182 int clientSocket;
183 tr_port clientPort;
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,
193 clientSocket, NULL);
197 static void
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);
205 if (b->socket >= 0)
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);
216 if (b->socket >= 0)
218 b->ev = event_new (session->event_base, b->socket, EV_READ | EV_PERSIST, accept_incoming_peer, session);
219 event_add (b->ev, NULL);
224 const tr_address*
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;
230 switch (tr_af_type)
232 case TR_AF_INET:
233 bindinfo = session->public_ipv4;
234 default_value = TR_DEFAULT_BIND_ADDRESS_IPV4;
235 break;
237 case TR_AF_INET6:
238 bindinfo = session->public_ipv6;
239 default_value = TR_DEFAULT_BIND_ADDRESS_IPV6;
240 break;
242 default:
243 bindinfo = NULL;
244 default_value = "";
245 break;
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;
254 /***
255 ****
256 ***/
258 #ifdef TR_LIGHTWEIGHT
259 #define TR_DEFAULT_ENCRYPTION TR_CLEAR_PREFERRED
260 #else
261 #define TR_DEFAULT_ENCRYPTION TR_ENCRYPTION_PREFERRED
262 #endif
264 static int
265 parse_tos (const char *str)
267 char *p;
268 int value;
270 if (!evutil_ascii_strcasecmp (str, ""))
271 return 0;
272 if (!evutil_ascii_strcasecmp (str, "default"))
273 return 0;
275 if (!evutil_ascii_strcasecmp (str, "lowcost"))
276 return 0x10;
277 if (!evutil_ascii_strcasecmp (str, "mincost"))
278 return 0x10;
280 if (!evutil_ascii_strcasecmp (str, "throughput"))
281 return 0x08;
282 if (!evutil_ascii_strcasecmp (str, "reliability"))
283 return 0x04;
284 if (!evutil_ascii_strcasecmp (str, "lowdelay"))
285 return 0x02;
287 value = strtol (str, &p, 0);
288 if (!p || (p == str))
289 return 0;
291 return value;
294 static const char *
295 format_tos (int value)
297 static char buf[8];
298 switch (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";
305 default:
306 tr_snprintf (buf, 8, "%d", value);
307 return buf;
311 void
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);
382 void
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));
454 bool
455 tr_sessionLoadSettings (tr_variant * dict, const char * configDir, const char * appName)
457 int err = 0;
458 char * filename;
459 tr_variant fileSettings;
460 tr_variant sessionDefaults;
461 tr_variant tmp;
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);
471 tmp = *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);
482 if (!err)
484 tr_variantMergeDicts (dict, &fileSettings);
485 tr_variantFree (&fileSettings);
488 /* cleanup */
489 tr_variantFree (&sessionDefaults);
490 tr_free (filename);
491 success = (err==0) || (err==ENOENT);
492 return success;
495 void
496 tr_sessionSaveSettings (tr_session * session,
497 const char * configDir,
498 const tr_variant * clientSettings)
500 tr_variant settings;
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);
511 if (!err)
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);
533 /* cleanup */
534 tr_free (filename);
535 tr_variantFree (&settings);
538 /***
539 ****
540 ***/
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.
547 static void
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);
564 /***
565 ****
566 ***/
568 static void tr_sessionInitImpl (void *);
570 struct init_data
572 bool done;
573 bool messageQueuingEnabled;
574 tr_session * session;
575 const char * configDir;
576 tr_variant * clientSettings;
579 tr_session *
580 tr_sessionInit (const char * tag,
581 const char * configDir,
582 bool messageQueuingEnabled,
583 tr_variant * clientSettings)
585 int64_t i;
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))
606 tr_logSetLevel (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 */
614 data.done = false;
615 data.session = session;
616 data.configDir = configDir;
617 data.messageQueuingEnabled = messageQueuingEnabled;
618 data.clientSettings = clientSettings;
619 tr_runInEventThread (session, tr_sessionInitImpl, &data);
620 while (!data.done)
621 tr_wait_msec (50);
623 return session;
626 static void turtleCheckClock (tr_session * s, struct tr_turtle_info * t);
628 static void
629 onNowTimer (evutil_socket_t foo UNUSED, short bar UNUSED, void * vsession)
631 int usec;
632 const int min = 100;
633 const int max = 999999;
634 struct timeval tv;
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
646 tr_timeUpdate (now);
648 tr_dhtUpkeep (session);
650 if (session->turtle.isClockEnabled)
651 turtleCheckClock (session, &session->turtle);
653 while ((tor = tr_torrentNext (session, tor)))
655 if (tor->isRunning)
657 if (tr_torrentIsSeed (tor))
658 ++tor->secondsSeeding;
659 else
660 ++tor->secondsDownloading;
665 *** Set the timer
668 /* schedule the next timer for right after the next second begins */
669 tr_gettimeofday (&tv);
670 usec = 1000000 - tv.tv_usec;
671 if (usec > max)
672 usec = max;
673 if (usec < min)
674 usec = min;
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);
681 static void
682 tr_sessionInitImpl (void * vdata)
684 tr_variant settings;
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);
703 #ifndef WIN32
704 /* Don't exit when writing on a broken socket */
705 signal (SIGPIPE, SIG_IGN);
706 #endif
708 tr_logSetQueueEnabled (data->messageQueuingEnabled);
710 tr_setConfigDir (session, data->configDir);
712 session->peerMgr = tr_peerMgrNew (session);
714 session->shared = tr_sharedInit (session);
717 *** Blocklist
721 char * filename = tr_buildPath (session->configDir, "blocklists", NULL);
722 tr_mkdirp (filename, 0777);
723 tr_free (filename);
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);
747 /* cleanup */
748 tr_variantFree (&settings);
749 data->done = true;
752 static void turtleBootstrap (tr_session *, struct tr_turtle_info *);
753 static void setPeerPort (tr_session * session, tr_port port);
755 static void
756 sessionSetImpl (void * vdata)
758 int64_t i;
759 double d;
760 bool boolVal;
761 const char * str;
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))
773 tr_logSetLevel (i);
775 if (tr_variantDictFindInt (settings, TR_KEY_umask, &i))
777 session->umask = (mode_t)i;
778 umask (session->umask);
781 /* misc features */
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);
800 else
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;
813 /* torrent queues */
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);
841 /* rpc server */
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;
853 b.socket = -1;
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;
859 b.socket = -1;
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);
905 *** Turtle Mode
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))
918 turtle->days = 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);
926 *** Scripts
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;
938 data->done = true;
941 void
942 tr_sessionSet (tr_session * session, tr_variant * settings)
944 struct init_data data;
945 data.done = false;
946 data.session = session;
947 data.clientSettings = settings;
949 /* run the rest in the libtransmission thread */
950 tr_runInEventThread (session, sessionSetImpl, &data);
951 while (!data.done)
952 tr_wait_msec (100);
955 /***
956 ****
957 ***/
959 void
960 tr_sessionSetDownloadDir (tr_session * session, const char * dir)
962 struct tr_device_info * info = NULL;
964 assert (tr_isSession (session));
966 if (dir != NULL)
967 info = tr_device_info_create (dir);
968 tr_device_info_free (session->downloadDir);
969 session->downloadDir = info;
972 const char *
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;
982 return dir;
985 int64_t
986 tr_sessionGetDirFreeSpace (tr_session * session, const char * dir)
988 int64_t free_space;
990 if (!tr_strcmp0 (dir, tr_sessionGetDownloadDir (session)))
991 free_space = tr_device_info_get_free_space (session->downloadDir);
992 else
993 free_space = tr_getDirFreeSpace (dir);
995 return free_space;
998 /***
999 ****
1000 ***/
1002 void
1003 tr_sessionSetIncompleteFileNamingEnabled (tr_session * session, bool b)
1005 assert (tr_isSession (session));
1006 assert (tr_isBool (b));
1008 session->isIncompleteFileNamingEnabled = b;
1011 bool
1012 tr_sessionIsIncompleteFileNamingEnabled (const tr_session * session)
1014 assert (tr_isSession (session));
1016 return session->isIncompleteFileNamingEnabled;
1019 /***
1020 ****
1021 ***/
1024 void
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);
1037 const char*
1038 tr_sessionGetIncompleteDir (const tr_session * session)
1040 assert (tr_isSession (session));
1042 return session->incompleteDir;
1045 void
1046 tr_sessionSetIncompleteDirEnabled (tr_session * session, bool b)
1048 assert (tr_isSession (session));
1049 assert (tr_isBool (b));
1051 session->isIncompleteDirEnabled = b;
1054 bool
1055 tr_sessionIsIncompleteDirEnabled (const tr_session * session)
1057 assert (tr_isSession (session));
1059 return session->isIncompleteDirEnabled;
1062 /***
1063 ****
1064 ***/
1066 void
1067 tr_sessionLock (tr_session * session)
1069 assert (tr_isSession (session));
1071 tr_lockLock (session->lock);
1074 void
1075 tr_sessionUnlock (tr_session * session)
1077 assert (tr_isSession (session));
1079 tr_lockUnlock (session->lock);
1082 bool
1083 tr_sessionIsLocked (const tr_session * session)
1085 return tr_isSession (session) && tr_lockHave (session->lock);
1088 /***
1089 **** Peer Port
1090 ***/
1092 static void
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);
1107 static void
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);
1116 void
1117 tr_sessionSetPeerPort (tr_session * session, tr_port port)
1119 if (tr_isSession (session) && (session->private_peer_port != port))
1121 setPeerPort (session, port);
1125 tr_port
1126 tr_sessionGetPeerPort (const tr_session * session)
1128 return tr_isSession (session) ? session->private_peer_port : 0;
1131 tr_port
1132 tr_sessionSetPeerPortRandom (tr_session * session)
1134 assert (tr_isSession (session));
1136 tr_sessionSetPeerPort (session, getRandomPort (session));
1137 return session->private_peer_port;
1140 void
1141 tr_sessionSetPeerPortRandomOnStart (tr_session * session,
1142 bool random)
1144 assert (tr_isSession (session));
1146 session->isPortRandom = random;
1149 bool
1150 tr_sessionGetPeerPortRandomOnStart (tr_session * session)
1152 assert (tr_isSession (session));
1154 return session->isPortRandom;
1157 tr_port_forwarding
1158 tr_sessionGetPortForwarding (const tr_session * session)
1160 assert (tr_isSession (session));
1162 return tr_sharedTraversalStatus (session->shared);
1165 /***
1166 ****
1167 ***/
1169 void
1170 tr_sessionSetRatioLimited (tr_session * session, bool isLimited)
1172 assert (tr_isSession (session));
1174 session->isRatioLimited = isLimited;
1177 void
1178 tr_sessionSetRatioLimit (tr_session * session, double desiredRatio)
1180 assert (tr_isSession (session));
1182 session->desiredRatio = desiredRatio;
1185 bool
1186 tr_sessionIsRatioLimited (const tr_session * session)
1188 assert (tr_isSession (session));
1190 return session->isRatioLimited;
1193 double
1194 tr_sessionGetRatioLimit (const tr_session * session)
1196 assert (tr_isSession (session));
1198 return session->desiredRatio;
1201 /***
1202 ****
1203 ***/
1205 void
1206 tr_sessionSetIdleLimited (tr_session * session, bool isLimited)
1208 assert (tr_isSession (session));
1210 session->isIdleLimited = isLimited;
1213 void
1214 tr_sessionSetIdleLimit (tr_session * session, uint16_t idleMinutes)
1216 assert (tr_isSession (session));
1218 session->idleLimitMinutes = idleMinutes;
1221 bool
1222 tr_sessionIsIdleLimited (const tr_session * session)
1224 assert (tr_isSession (session));
1226 return session->isIdleLimited;
1229 uint16_t
1230 tr_sessionGetIdleLimit (const tr_session * session)
1232 assert (tr_isSession (session));
1234 return session->idleLimitMinutes;
1237 /***
1238 ****
1239 **** SPEED LIMITS
1240 ****
1241 ***/
1243 bool
1244 tr_sessionGetActiveSpeedLimit_Bps (const tr_session * session, tr_direction dir, unsigned int * setme_Bps)
1246 bool isLimited = true;
1248 if (!tr_isSession (session))
1249 return false;
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);
1255 else
1256 isLimited = false;
1258 return isLimited;
1260 bool
1261 tr_sessionGetActiveSpeedLimit_KBps (const tr_session * session,
1262 tr_direction dir,
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);
1268 return is_active;
1271 static void
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);
1283 enum
1285 MINUTES_PER_HOUR = 60,
1286 MINUTES_PER_DAY = MINUTES_PER_HOUR * 24,
1287 MINUTES_PER_WEEK = MINUTES_PER_DAY * 7
1290 static void
1291 turtleUpdateTable (struct tr_turtle_info * t)
1293 int day;
1294 tr_bitfield * b = &t->minutes;
1296 tr_bitfieldSetHasNone (b);
1298 for (day=0; day<7; ++day)
1300 if (t->days & (1<<day))
1302 int i;
1303 const time_t begin = t->beginMinute;
1304 time_t end = t->endMinute;
1306 if (end <= begin)
1307 end += MINUTES_PER_DAY;
1309 for (i=begin; i<end; ++i)
1310 tr_bitfieldAdd (b, (i+day*MINUTES_PER_DAY) % MINUTES_PER_WEEK);
1315 static void
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);
1330 static void
1331 useAltSpeed (tr_session * s, struct tr_turtle_info * t,
1332 bool enabled, bool byUser)
1334 assert (tr_isSession (s));
1335 assert (t != NULL);
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
1350 static bool
1351 getInTurtleTime (const struct tr_turtle_info * t)
1353 struct tm tm;
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
1361 + tm.tm_min;
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;
1374 static void
1375 turtleCheckClock (tr_session * s, struct tr_turtle_info * t)
1377 bool enabled;
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. */
1398 static void
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);
1418 /***
1419 **** Primary session speed limits
1420 ***/
1422 void
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);
1432 void
1433 tr_sessionSetSpeedLimit_KBps (tr_session * s, tr_direction d, unsigned int KBps)
1435 tr_sessionSetSpeedLimit_Bps (s, d, toSpeedBytes (KBps));
1438 unsigned int
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];
1446 unsigned int
1447 tr_sessionGetSpeedLimit_KBps (const tr_session * s, tr_direction d)
1449 return toSpeedKBps (tr_sessionGetSpeedLimit_Bps (s, d));
1452 void
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);
1464 bool
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];
1473 /***
1474 **** Alternative speed limits that are used during scheduled times
1475 ***/
1477 void
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);
1488 void
1489 tr_sessionSetAltSpeed_KBps (tr_session * s, tr_direction d, unsigned int KBps)
1491 tr_sessionSetAltSpeed_Bps (s, d, toSpeedBytes (KBps));
1494 unsigned int
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];
1502 unsigned int
1503 tr_sessionGetAltSpeed_KBps (const tr_session * s, tr_direction d)
1505 return toSpeedKBps (tr_sessionGetAltSpeed_Bps (s, d));
1508 static void
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);
1525 void
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);
1540 bool
1541 tr_sessionUsesAltSpeedTime (const tr_session * s)
1543 assert (tr_isSession (s));
1545 return s->turtle.isClockEnabled;
1548 void
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;
1569 void
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;
1590 void
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);
1602 tr_sched_day
1603 tr_sessionGetAltSpeedDay (const tr_session * s)
1605 assert (tr_isSession (s));
1607 return s->turtle.days;
1610 void
1611 tr_sessionUseAltSpeed (tr_session * session, bool enabled)
1613 useAltSpeed (session, &session->turtle, enabled, true);
1616 bool
1617 tr_sessionUsesAltSpeed (const tr_session * s)
1619 assert (tr_isSession (s));
1621 return s->turtle.isEnabled;
1624 void
1625 tr_sessionSetAltSpeedFunc (tr_session * session,
1626 tr_altSpeedFunc func,
1627 void * userData)
1629 assert (tr_isSession (session));
1631 session->turtle.callback = func;
1632 session->turtle.callbackUserData = userData;
1635 void
1636 tr_sessionClearAltSpeedFunc (tr_session * session)
1638 tr_sessionSetAltSpeedFunc (session, NULL, NULL);
1641 /***
1642 ****
1643 ***/
1645 void
1646 tr_sessionSetPeerLimit (tr_session * session, uint16_t n)
1648 assert (tr_isSession (session));
1650 session->peerLimit = n;
1653 uint16_t
1654 tr_sessionGetPeerLimit (const tr_session * session)
1656 assert (tr_isSession (session));
1658 return session->peerLimit;
1661 void
1662 tr_sessionSetPeerLimitPerTorrent (tr_session * session, uint16_t n)
1664 assert (tr_isSession (session));
1666 session->peerLimitPerTorrent = n;
1669 uint16_t
1670 tr_sessionGetPeerLimitPerTorrent (const tr_session * session)
1672 assert (tr_isSession (session));
1674 return session->peerLimitPerTorrent;
1677 /***
1678 ****
1679 ***/
1681 void
1682 tr_sessionSetPaused (tr_session * session, bool isPaused)
1684 assert (tr_isSession (session));
1686 session->pauseAddedTorrent = isPaused;
1689 bool
1690 tr_sessionGetPaused (const tr_session * session)
1692 assert (tr_isSession (session));
1694 return session->pauseAddedTorrent;
1697 void
1698 tr_sessionSetDeleteSource (tr_session * session, bool deleteSource)
1700 assert (tr_isSession (session));
1702 session->deleteSourceTorrent = deleteSource;
1705 bool
1706 tr_sessionGetDeleteSource (const tr_session * session)
1708 assert (tr_isSession (session));
1710 return session->deleteSourceTorrent;
1713 /***
1714 ****
1715 ***/
1717 unsigned int
1718 tr_sessionGetPieceSpeed_Bps (const tr_session * session, tr_direction dir)
1720 return tr_isSession (session) ? tr_bandwidthGetPieceSpeed_Bps (&session->bandwidth, 0, dir) : 0;
1723 unsigned int
1724 tr_sessionGetRawSpeed_Bps (const tr_session * session, tr_direction dir)
1726 return tr_isSession (session) ? tr_bandwidthGetRawSpeed_Bps (&session->bandwidth, 0, dir) : 0;
1728 double
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;
1741 tr_torrent **
1742 tr_sessionGetTorrents (tr_session * session, int * setme_n)
1744 int i;
1745 int n;
1746 tr_torrent ** torrents;
1747 tr_torrent * tor;
1749 assert (tr_isSession (session));
1750 assert (setme_n != NULL);
1752 n = tr_sessionCountTorrents (session);
1753 *setme_n = n;
1755 torrents = tr_new (tr_torrent *, n);
1756 tor = NULL;
1757 for (i=0; i<n; ++i)
1758 torrents[i] = tor = tr_torrentNext (session, tor);
1760 return torrents;
1763 static int
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;
1771 if (aCur != bCur)
1772 return aCur > bCur ? -1 : 1; /* close the biggest torrents first */
1774 return 0;
1777 static void closeBlocklists (tr_session *);
1779 static void
1780 sessionCloseImpl (void * vsession)
1782 int i, n;
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);
1813 for (i=0; i<n; ++i)
1814 tr_torrentFree (torrents[i]);
1815 tr_free (torrents);
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);
1834 tr_wait_msec (100);
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;
1853 static int
1854 deadlineReached (const time_t deadline)
1856 return time (NULL) >= deadline;
1859 #define SHUTDOWN_MAX_SECONDS 20
1861 void
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");
1875 tr_wait_msec (100);
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);
1887 tr_wait_msec (50);
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);
1898 tr_wait_msec (100);
1900 if (deadlineReached (deadline) && !forced)
1902 dbgmsg ("calling event_loopbreak ()");
1903 forced = true;
1904 event_base_loopbreak (session->event_base);
1907 if (deadlineReached (deadline+3))
1909 dbgmsg ("deadline+3 reached... calling break...\n");
1910 break;
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);
1933 tr_free (session);
1936 struct sessionLoadTorrentsData
1938 tr_session * session;
1939 tr_ctor * ctor;
1940 int * setmeCount;
1941 tr_torrent ** torrents;
1942 bool done;
1945 static void
1946 sessionLoadTorrents (void * vdata)
1948 int i;
1949 int n = 0;
1950 struct stat sb;
1951 DIR * odir = NULL;
1952 tr_list * l = NULL;
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))))
1965 struct dirent *d;
1966 for (d = readdir (odir); d != NULL; d = readdir (odir))
1968 if (tr_str_has_suffix (d->d_name, ".torrent"))
1970 tr_torrent * tor;
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);
1976 ++n;
1978 tr_free (path);
1981 closedir (odir);
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;
1987 assert (i == n);
1989 tr_list_free (&list, NULL);
1991 if (n)
1992 tr_logAddInfo (_("Loaded %d torrents"), n);
1994 if (data->setmeCount)
1995 *data->setmeCount = n;
1997 data->done = true;
2000 tr_torrent **
2001 tr_sessionLoadTorrents (tr_session * session,
2002 tr_ctor * ctor,
2003 int * setmeCount)
2005 struct sessionLoadTorrentsData data;
2007 data.session = session;
2008 data.ctor = ctor;
2009 data.setmeCount = setmeCount;
2010 data.torrents = NULL;
2011 data.done = false;
2013 tr_runInEventThread (session, sessionLoadTorrents, &data);
2014 while (!data.done)
2015 tr_wait_msec (100);
2017 return data.torrents;
2020 /***
2021 ****
2022 ***/
2024 void
2025 tr_sessionSetPexEnabled (tr_session * session, bool enabled)
2027 assert (tr_isSession (session));
2028 assert (tr_isBool (enabled));
2030 session->isPexEnabled = enabled;
2033 bool
2034 tr_sessionIsPexEnabled (const tr_session * session)
2036 assert (tr_isSession (session));
2038 return session->isPexEnabled;
2041 bool
2042 tr_sessionAllowsDHT (const tr_session * session)
2044 return tr_sessionIsDHTEnabled (session);
2047 bool
2048 tr_sessionIsDHTEnabled (const tr_session * session)
2050 assert (tr_isSession (session));
2052 return session->isDHTEnabled;
2055 static void
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);
2066 void
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);
2076 /***
2077 ****
2078 ***/
2080 bool
2081 tr_sessionIsUTPEnabled (const tr_session * session)
2083 assert (tr_isSession (session));
2085 #ifdef WITH_UTP
2086 return session->isUTPEnabled;
2087 #else
2088 return false;
2089 #endif
2092 static void
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
2104 explanation. */
2107 void
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);
2117 /***
2118 ****
2119 ***/
2121 static void
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);
2136 void
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);
2146 bool
2147 tr_sessionIsLPDEnabled (const tr_session * session)
2149 assert (tr_isSession (session));
2151 return session->isLPDEnabled;
2154 bool
2155 tr_sessionAllowsLPD (const tr_session * session)
2157 return tr_sessionIsLPDEnabled (session);
2160 /***
2161 ****
2162 ***/
2164 void
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));
2180 /***
2181 ****
2182 ***/
2184 struct port_forwarding_data
2186 bool enabled;
2187 struct tr_shared * shared;
2190 static void
2191 setPortForwardingEnabled (void * vdata)
2193 struct port_forwarding_data * data = vdata;
2194 tr_sharedTraversalEnable (data->shared, data->enabled);
2195 tr_free (data);
2198 void
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);
2208 bool
2209 tr_sessionIsPortForwardingEnabled (const tr_session * session)
2211 assert (tr_isSession (session));
2213 return tr_sharedTraversalIsEnabled (session->shared);
2216 /***
2217 ****
2218 ***/
2220 static int
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);
2229 static void
2230 loadBlocklists (tr_session * session)
2232 DIR * odir;
2233 char * dirname;
2234 struct dirent * d;
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);
2242 if (odir == NULL)
2244 tr_free (dirname);
2245 return;
2248 while ((d = readdir (odir)))
2250 char * path;
2251 char * load = NULL;
2253 if (!d->d_name || (d->d_name[0]=='.')) /* ignore dotfiles */
2254 continue;
2256 path = tr_buildPath (dirname, d->d_name, NULL);
2258 if (tr_stringEndsWith (path, ".bin"))
2260 load = tr_strdup (path);
2262 else
2264 char * binname;
2265 char * basename;
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);
2276 if (n > 0)
2277 load = tr_strdup (binname);
2279 tr_blocklistFileFree (b);
2281 else if (tr_fileExists(path,&path_mtime) && (path_mtime>=binname_mtime)) /* update it */
2283 char * old;
2284 tr_blocklistFile * b;
2286 old = tr_strdup_printf ("%s.old", binname);
2287 tr_remove (old);
2288 tr_rename (binname, old);
2289 b = tr_blocklistFileNew (binname, isEnabled);
2290 if (tr_blocklistFileSetContent (b, path) > 0)
2292 tr_remove (old);
2294 else
2296 tr_remove (binname);
2297 tr_rename (old, binname);
2300 tr_blocklistFileFree (b);
2301 tr_free (old);
2304 tr_free (basename);
2305 tr_free (binname);
2308 if (load != NULL)
2310 if (tr_ptrArrayFindSorted (&loadme, load, (PtrArrayCompareFunc)strcmp) == NULL)
2311 tr_ptrArrayInsertSorted (&loadme, load, (PtrArrayCompareFunc)strcmp);
2312 else
2313 tr_free (load);
2316 tr_free (path);
2319 if (!tr_ptrArrayEmpty (&loadme))
2321 int i;
2322 const int n = tr_ptrArraySize (&loadme);
2323 const char ** paths = (const char **) tr_ptrArrayBase (&loadme);
2325 for (i=0; i<n; ++i)
2326 tr_list_append (&blocklists, tr_blocklistFileNew (paths[i], isEnabled));
2329 /* cleanup */
2330 closedir (odir);
2331 tr_free (dirname);
2332 tr_ptrArrayDestruct (&loadme, (PtrArrayForeachFunc)tr_free);
2333 session->blocklists = blocklists;
2336 static void
2337 closeBlocklists (tr_session * session)
2339 tr_list_free (&session->blocklists, (TrListForeachFunc)tr_blocklistFileFree);
2342 void
2343 tr_sessionReloadBlocklists (tr_session * session)
2345 closeBlocklists (session);
2346 loadBlocklists (session);
2348 tr_peerMgrOnBlocklistChanged (session->peerMgr);
2352 tr_blocklistGetRuleCount (const tr_session * session)
2354 tr_list * l;
2355 int n = 0;
2357 assert (tr_isSession (session));
2359 for (l = session->blocklists; l; l = l->next)
2360 n += tr_blocklistFileGetRuleCount (l->data);
2362 return n;
2365 bool
2366 tr_blocklistIsEnabled (const tr_session * session)
2368 assert (tr_isSession (session));
2370 return session->isBlocklistEnabled;
2373 void
2374 tr_blocklistSetEnabled (tr_session * session, bool isEnabled)
2376 tr_list * l;
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);
2387 bool
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)
2398 tr_list * l;
2399 int ruleCount;
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))
2406 b = l->data;
2408 if (!b)
2410 char * path = tr_buildPath (session->configDir, "blocklists", defaultName, NULL);
2411 b = tr_blocklistFileNew (path, session->isBlocklistEnabled);
2412 tr_list_append (&session->blocklists, b);
2413 tr_free (path);
2416 ruleCount = tr_blocklistFileSetContent (b, contentFilename);
2417 tr_sessionUnlock (session);
2418 return ruleCount;
2421 bool
2422 tr_sessionIsAddressBlocked (const tr_session * session,
2423 const tr_address * addr)
2425 tr_list * l;
2427 assert (tr_isSession (session));
2429 for (l = session->blocklists; l; l = l->next)
2430 if (tr_blocklistFileHasAddress (l->data, addr))
2431 return true;
2433 return false;
2436 void
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);
2446 const char *
2447 tr_blocklistGetURL (const tr_session * session)
2449 return session->blocklist_url;
2453 /***
2454 ****
2455 ***/
2457 static void
2458 metainfoLookupInit (tr_session * session)
2460 struct stat sb;
2461 const char * dirname = tr_getTorrentDir (session);
2462 DIR * odir = NULL;
2463 tr_ctor * ctor = NULL;
2464 tr_variant * lookup;
2465 int n = 0;
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))))
2476 struct dirent *d;
2477 while ((d = readdir (odir)))
2479 if (tr_str_has_suffix (d->d_name, ".torrent"))
2481 tr_info inf;
2482 char * path = tr_buildPath (dirname, d->d_name, NULL);
2483 tr_ctorSetMetainfoFromFile (ctor, path);
2484 if (!tr_torrentParse (ctor, &inf))
2486 ++n;
2487 tr_variantDictAddStr (lookup, tr_quark_new(inf.hashString,-1), path);
2489 tr_free (path);
2492 closedir (odir);
2494 tr_ctorFree (ctor);
2496 session->metainfoLookup = lookup;
2497 tr_logAddDebug ("Found %d torrents in \"%s\"", n, dirname);
2500 const char*
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);
2510 return filename;
2513 void
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);
2526 /***
2527 ****
2528 ***/
2530 void
2531 tr_sessionSetRPCEnabled (tr_session * session, bool isEnabled)
2533 assert (tr_isSession (session));
2535 tr_rpcSetEnabled (session->rpcServer, isEnabled);
2538 bool
2539 tr_sessionIsRPCEnabled (const tr_session * session)
2541 assert (tr_isSession (session));
2543 return tr_rpcIsEnabled (session->rpcServer);
2546 void
2547 tr_sessionSetRPCPort (tr_session * session,
2548 tr_port port)
2550 assert (tr_isSession (session));
2552 tr_rpcSetPort (session->rpcServer, port);
2555 tr_port
2556 tr_sessionGetRPCPort (const tr_session * session)
2558 assert (tr_isSession (session));
2560 return tr_rpcGetPort (session->rpcServer);
2563 void
2564 tr_sessionSetRPCUrl (tr_session * session,
2565 const char * url)
2567 assert (tr_isSession (session));
2569 tr_rpcSetUrl (session->rpcServer, url);
2572 const char*
2573 tr_sessionGetRPCUrl (const tr_session * session)
2575 assert (tr_isSession (session));
2577 return tr_rpcGetUrl (session->rpcServer);
2580 void
2581 tr_sessionSetRPCCallback (tr_session * session,
2582 tr_rpc_func func,
2583 void * user_data)
2585 assert (tr_isSession (session));
2587 session->rpc_func = func;
2588 session->rpc_func_user_data = user_data;
2591 void
2592 tr_sessionSetRPCWhitelist (tr_session * session,
2593 const char * whitelist)
2595 assert (tr_isSession (session));
2597 tr_rpcSetWhitelist (session->rpcServer, whitelist);
2600 const char*
2601 tr_sessionGetRPCWhitelist (const tr_session * session)
2603 assert (tr_isSession (session));
2605 return tr_rpcGetWhitelist (session->rpcServer);
2608 void
2609 tr_sessionSetRPCWhitelistEnabled (tr_session * session, bool isEnabled)
2611 assert (tr_isSession (session));
2613 tr_rpcSetWhitelistEnabled (session->rpcServer, isEnabled);
2616 bool
2617 tr_sessionGetRPCWhitelistEnabled (const tr_session * session)
2619 assert (tr_isSession (session));
2621 return tr_rpcGetWhitelistEnabled (session->rpcServer);
2625 void
2626 tr_sessionSetRPCPassword (tr_session * session,
2627 const char * password)
2629 assert (tr_isSession (session));
2631 tr_rpcSetPassword (session->rpcServer, password);
2634 const char*
2635 tr_sessionGetRPCPassword (const tr_session * session)
2637 assert (tr_isSession (session));
2639 return tr_rpcGetPassword (session->rpcServer);
2642 void
2643 tr_sessionSetRPCUsername (tr_session * session,
2644 const char * username)
2646 assert (tr_isSession (session));
2648 tr_rpcSetUsername (session->rpcServer, username);
2651 const char*
2652 tr_sessionGetRPCUsername (const tr_session * session)
2654 assert (tr_isSession (session));
2656 return tr_rpcGetUsername (session->rpcServer);
2659 void
2660 tr_sessionSetRPCPasswordEnabled (tr_session * session, bool isEnabled)
2662 assert (tr_isSession (session));
2664 tr_rpcSetPasswordEnabled (session->rpcServer, isEnabled);
2667 bool
2668 tr_sessionIsRPCPasswordEnabled (const tr_session * session)
2670 assert (tr_isSession (session));
2672 return tr_rpcIsPasswordEnabled (session->rpcServer);
2675 const char *
2676 tr_sessionGetRPCBindAddress (const tr_session * session)
2678 assert (tr_isSession (session));
2680 return tr_rpcGetBindAddress (session->rpcServer);
2683 /****
2684 *****
2685 ****/
2687 bool
2688 tr_sessionIsTorrentDoneScriptEnabled (const tr_session * session)
2690 assert (tr_isSession (session));
2692 return session->isTorrentDoneScriptEnabled;
2695 void
2696 tr_sessionSetTorrentDoneScriptEnabled (tr_session * session, bool isEnabled)
2698 assert (tr_isSession (session));
2699 assert (tr_isBool (isEnabled));
2701 session->isTorrentDoneScriptEnabled = isEnabled;
2704 const char *
2705 tr_sessionGetTorrentDoneScript (const tr_session * session)
2707 assert (tr_isSession (session));
2709 return session->torrentDoneScript;
2712 void
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);
2724 /***
2725 ****
2726 ***/
2728 void
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];
2746 void
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;
2756 bool
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];
2765 void
2766 tr_sessionSetQueueStalledMinutes (tr_session * session, int minutes)
2768 assert (tr_isSession (session));
2769 assert (minutes > 0);
2771 session->queueStalledMinutes = minutes;
2774 void
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;
2783 bool
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
2801 tr_torrent * tor;
2802 int position;
2805 static int
2806 compareTorrentAndPositions (const void * va, const void * vb)
2808 int ret;
2809 const struct TorrentAndPosition * a = va;
2810 const struct TorrentAndPosition * b = vb;
2812 if (a->position > b->position)
2813 ret = 1;
2814 else if (a->position < b->position)
2815 ret = -1;
2816 else
2817 ret = 0;
2819 return ret;
2823 void
2824 tr_sessionGetNextQueuedTorrents (tr_session * session,
2825 tr_direction direction,
2826 size_t num_wanted,
2827 tr_ptrArray * setme)
2829 size_t i;
2830 size_t n;
2831 tr_torrent * tor;
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);
2840 i = 0;
2841 tor = NULL;
2842 while ((tor = tr_torrentNext (session, tor)))
2844 if (!tr_torrentIsQueued (tor))
2845 continue;
2847 if (direction != tr_torrentGetQueueDirection (tor))
2848 continue;
2850 candidates[i].tor = tor;
2851 candidates[i].position = tr_torrentGetQueuePosition (tor);
2852 ++i;
2855 /* find the best n candidates */
2856 if (num_wanted > i)
2857 num_wanted = i;
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);
2867 /* cleanup */
2868 tr_free (candidates);
2872 tr_sessionCountQueueFreeSlots (tr_session * session, tr_direction dir)
2874 tr_torrent * tor;
2875 int active_count;
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))
2880 return INT_MAX;
2882 tor = NULL;
2883 active_count = 0;
2884 while ((tor = tr_torrentNext (session, tor)))
2885 if (!tr_torrentIsStalled (tor))
2886 if (tr_torrentGetActivity (tor) == activity)
2887 ++active_count;
2889 if (active_count >= max)
2890 return 0;
2892 return max - active_count;