forked from transmission/transmission
-
Notifications
You must be signed in to change notification settings - Fork 0
/
transmission.h
1694 lines (1365 loc) · 57.4 KB
/
transmission.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* This file Copyright © Transmission authors and contributors.
*
* It may be used under the 3-Clause BSD License, the GNU Public License v2,
* or v3, or any future license endorsed by Mnemosyne LLC.
*
*/
/*
* This file defines the public API for the libtransmission library.
* The other public API headers are variant.h and utils.h.
* Most of the remaining headers in libtransmission are private.
*/
#pragma once
/***
**** Basic Types
***/
#include <stdbool.h> /* bool */
#include <stddef.h> /* size_t */
#include <stdint.h> /* uintN_t */
#include <time.h> /* time_t */
#ifdef __cplusplus
#include <string>
#include <string_view>
#endif
#include "tr-macros.h"
using tr_file_index_t = uint32_t;
using tr_piece_index_t = uint32_t;
/* Assuming a 16 KiB block (tr_block_info::BlockSize), a 32-bit block index gives us a maximum torrent size of 64 TiB.
* When we ever need to grow past that, change tr_block_index_t and tr_piece_index_t to uint64_t. */
using tr_block_index_t = uint32_t;
using tr_tracker_tier_t = uint32_t;
using tr_tracker_id_t = uint32_t;
using tr_byte_index_t = uint64_t;
using tr_torrent_id_t = int;
struct tr_block_span_t
{
tr_block_index_t begin;
tr_block_index_t end;
};
struct tr_byte_span_t
{
uint64_t begin;
uint64_t end;
};
struct tr_ctor;
struct tr_error;
struct tr_session;
struct tr_torrent;
struct tr_torrent_metainfo;
struct tr_variant;
using tr_priority_t = int8_t;
#define TR_RPC_SESSION_ID_HEADER "X-Transmission-Session-Id"
enum tr_preallocation_mode
{
TR_PREALLOCATE_NONE = 0,
TR_PREALLOCATE_SPARSE = 1,
TR_PREALLOCATE_FULL = 2
};
enum tr_encryption_mode
{
TR_CLEAR_PREFERRED,
TR_ENCRYPTION_PREFERRED,
TR_ENCRYPTION_REQUIRED
};
#define TR_RATIO_NA -1
#define TR_RATIO_INF -2
/***
****
**** Startup & Shutdown
****
***/
/**
* @addtogroup tr_session Session
*
* A libtransmission session is created by calling tr_sessionInit().
* libtransmission creates a thread for itself so that it can operate
* independently of the caller's event loop. The session will continue
* until tr_sessionClose() is called.
*
* @{
*/
/**
* @brief get Transmission's default configuration file directory.
*
* The default configuration directory is determined this way:
* -# If the TRANSMISSION_HOME environment variable is set, its value is used.
* -# On Darwin, "${HOME}/Library/Application Support/${appname}" is used.
* -# On Windows, "${CSIDL_APPDATA}/${appname}" is used.
* -# If XDG_CONFIG_HOME is set, "${XDG_CONFIG_HOME}/${appname}" is used.
* -# ${HOME}/.config/${appname}" is used as a last resort.
*/
#ifdef __cplusplus
[[nodiscard]] std::string tr_getDefaultConfigDir(std::string_view appname);
#endif
/** @brief buffer variant of tr_getDefaultConfigDir(). See tr_strvToBuf(). */
size_t tr_getDefaultConfigDirToBuf(char const* appname, char* buf, size_t buflen);
/**
* @brief returns Transmisson's default download directory.
*
* The default download directory is determined this way:
* -# If the HOME environment variable is set, "${HOME}/Downloads" is used.
* -# On Windows, "${CSIDL_MYDOCUMENTS}/Downloads" is used.
* -# Otherwise, getpwuid(getuid())->pw_dir + "/Downloads" is used.
*/
#ifdef __cplusplus
[[nodiscard]] std::string tr_getDefaultDownloadDir();
#endif
/** @brief buffer variant of tr_getDefaultDownloadDir(). See tr_strvToBuf(). */
size_t tr_getDefaultDownloadDirToBuf(char* buf, size_t buflen);
#define TR_DEFAULT_RPC_WHITELIST "127.0.0.1,::1"
#define TR_DEFAULT_RPC_PORT_STR "9091"
#define TR_DEFAULT_RPC_PORT 9091
#define TR_DEFAULT_RPC_URL_STR "/transmission/"
#define TR_DEFAULT_PEER_PORT_STR "51413"
#define TR_DEFAULT_PEER_SOCKET_TOS_STR "le"
#define TR_DEFAULT_PEER_LIMIT_GLOBAL_STR "200"
#define TR_DEFAULT_PEER_LIMIT_TORRENT_STR "50"
#define TR_DEFAULT_PEER_LIMIT_TORRENT 50
/**
* Add libtransmission's default settings to the benc dictionary.
*
* Example:
* @code
* tr_variant settings;
* int64_t i;
*
* tr_variantInitDict(&settings, 0);
* tr_sessionGetDefaultSettings(&settings);
* if (tr_variantDictFindInt(&settings, TR_PREFS_KEY_PEER_PORT, &i))
* fprintf(stderr, "the default peer port is %d\n", (int)i);
* tr_variantClear(&settings);
* @endcode
*
* @param setme_dictionary pointer to a tr_variant dictionary
* @see tr_sessionLoadSettings()
* @see tr_sessionInit()
* @see tr_getDefaultConfigDir()
*/
void tr_sessionGetDefaultSettings(struct tr_variant* setme_dictionary);
/**
* Add the session's current configuration settings to the benc dictionary.
*
* TODO: if we ever make libtransmissionapp, this would go there.
*
* @param session the session to query
* @param setme_dictionary the dictionary to populate
* @see tr_sessionGetDefaultSettings()
*/
void tr_sessionGetSettings(tr_session const* session, struct tr_variant* setme_dictionary);
/**
* Load settings from the configuration directory's settings.json file,
* using libtransmission's default settings as fallbacks for missing keys.
*
* TODO: if we ever make libtransmissionapp, this would go there.
*
* @param dictionary pointer to an uninitialized tr_variant
* @param configDir the configuration directory to find settings.json
* @param appName if configDir is empty, appName is used to find the default dir.
* @return success true if the settings were loaded, false otherwise
* @see tr_sessionGetDefaultSettings()
* @see tr_sessionInit()
* @see tr_sessionSaveSettings()
*/
bool tr_sessionLoadSettings(struct tr_variant* dictionary, char const* config_dir, char const* appName);
/**
* Add the session's configuration settings to the benc dictionary
* and save it to the configuration directory's settings.json file.
*
* TODO: if we ever make libtransmissionapp, this would go there.
*
* @param session the session to save
* @param configDir the directory to write to
* @param dictionary the dictionary to save
* @see tr_sessionLoadSettings()
*/
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, struct tr_variant const* client_settings);
/**
* @brief Initialize a libtransmission session.
*
* For example, this will instantiate a session with all the default values:
* @code
* tr_variant settings;
* tr_session* session;
* char const* configDir;
*
* tr_variantInitDict(&settings, 0);
* tr_sessionGetDefaultSettings(&settings);
* configDir = tr_getDefaultConfigDir("Transmission");
* session = tr_sessionInit(configDir, true, &settings);
*
* tr_variantClear(&settings);
* @endcode
*
* @param configDir where Transmission will look for resume files, blocklists, etc.
* @param messageQueueingEnabled if false, messages will be dumped to stderr
* @param settings libtransmission settings
* @see tr_sessionGetDefaultSettings()
* @see tr_sessionLoadSettings()
* @see tr_getDefaultConfigDir()
*/
tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, struct tr_variant* settings);
/** @brief Update a session's settings from a benc dictionary
like to the one used in tr_sessionInit() */
void tr_sessionSet(tr_session* session, struct tr_variant* settings);
/** @brief Rescan the blocklists directory and
reload whatever blocklist files are found there */
void tr_sessionReloadBlocklists(tr_session* session);
/** @brief End a libtransmission session
@see tr_sessionInit() */
void tr_sessionClose(tr_session*);
/**
* @brief Return the session's configuration directory.
*
* This is where transmission stores its torrent files, .resume files,
* blocklists, etc. It's set in tr_transmissionInit() and is immutable
* during the session.
*/
char const* tr_sessionGetConfigDir(tr_session const*);
/**
* @brief Set the per-session default download folder for new torrents.
* @see tr_sessionInit()
* @see tr_sessionGetDownloadDir()
* @see tr_ctorSetDownloadDir()
*/
void tr_sessionSetDownloadDir(tr_session* session, char const* downloadDir);
/**
* @brief Get the default download folder for new torrents.
*
* This is set by tr_sessionInit() or tr_sessionSetDownloadDir(),
* and can be overridden on a per-torrent basis by tr_ctorSetDownloadDir().
*/
char const* tr_sessionGetDownloadDir(tr_session const* session);
/**
* @brief Set the torrent's bandwidth priority.
*/
void tr_ctorSetBandwidthPriority(tr_ctor* ctor, tr_priority_t priority);
/**
* @brief Get the torrent's bandwidth priority.
*/
tr_priority_t tr_ctorGetBandwidthPriority(tr_ctor const* ctor);
/**
* @brief set the per-session incomplete download folder.
*
* When you add a new torrent and the session's incomplete directory is enabled,
* the new torrent will start downloading into that directory, and then be moved
* to tr_torrent.downloadDir when the torrent is finished downloading.
*
* Torrents aren't moved as a result of changing the session's incomplete dir --
* it's applied to new torrents, not existing ones.
*
* tr_torrentSetLocation() overrules the incomplete dir: when a user specifies
* a new location, that becomes the torrent's new downloadDir and the torrent
* is moved there immediately regardless of whether or not it's complete.
*
* @see tr_sessionInit()
* @see tr_sessionGetIncompleteDir()
* @see tr_sessionSetIncompleteDirEnabled()
* @see tr_sessionGetIncompleteDirEnabled()
*/
void tr_sessionSetIncompleteDir(tr_session* session, char const* dir);
/** @brief get the per-session incomplete download folder */
char const* tr_sessionGetIncompleteDir(tr_session const* session);
/** @brief enable or disable use of the incomplete download folder */
void tr_sessionSetIncompleteDirEnabled(tr_session* session, bool);
/** @brief get whether or not the incomplete download folder is enabled */
bool tr_sessionIsIncompleteDirEnabled(tr_session const* session);
/**
* @brief When enabled, newly-created files will have ".part" appended
* to their filename until the file is fully downloaded
*
* This is not retroactive -- toggling this will not rename existing files.
* It only applies to new files created by Transmission after this API call.
*
* @see tr_sessionIsIncompleteFileNamingEnabled()
*/
void tr_sessionSetIncompleteFileNamingEnabled(tr_session* session, bool enabled);
/** @brief return true if files will end in ".part" until they're complete */
bool tr_sessionIsIncompleteFileNamingEnabled(tr_session const* session);
/**
* @brief Set whether or not RPC calls are allowed in this session.
*
* @details If true, libtransmission will open a server socket to listen
* for incoming http RPC requests as described in docs/rpc-spec.md.
*
* This is intially set by tr_sessionInit() and can be
* queried by tr_sessionIsRPCEnabled().
*/
void tr_sessionSetRPCEnabled(tr_session* session, bool is_enabled);
/** @brief Get whether or not RPC calls are allowed in this session.
@see tr_sessionInit()
@see tr_sessionSetRPCEnabled() */
bool tr_sessionIsRPCEnabled(tr_session const* session);
/** @brief Specify which port to listen for RPC requests on.
@see tr_sessionInit()
@see tr_sessionGetRPCPort */
void tr_sessionSetRPCPort(tr_session* session, uint16_t port);
/** @brief Get which port to listen for RPC requests on.
@see tr_sessionInit()
@see tr_sessionSetRPCPort */
uint16_t tr_sessionGetRPCPort(tr_session const* session);
/**
* @brief Specify a whitelist for remote RPC access
*
* The whitelist is a comma-separated list of dotted-quad IP addresses
* to be allowed. Wildmat notation is supported, meaning that
* '?' is interpreted as a single-character wildcard and
* '*' is interprted as a multi-character wildcard.
*/
void tr_sessionSetRPCWhitelist(tr_session* session, char const* whitelist);
/** @brief get the Access Control List for allowing/denying RPC requests.
@return a comma-separated string of whitelist domains.
@see tr_sessionInit
@see tr_sessionSetRPCWhitelist */
char const* tr_sessionGetRPCWhitelist(tr_session const*);
void tr_sessionSetRPCWhitelistEnabled(tr_session* session, bool isEnabled);
bool tr_sessionGetRPCWhitelistEnabled(tr_session const* session);
void tr_sessionSetRPCPassword(tr_session* session, char const* password);
void tr_sessionSetRPCUsername(tr_session* session, char const* username);
// TODO(ckerr): rename function to indicate it returns the salted value
/** @brief get the salted version of the password used to restrict RPC requests.
@return the password string.
@see tr_sessionInit()
@see tr_sessionSetRPCPassword() */
char const* tr_sessionGetRPCPassword(tr_session const* session);
char const* tr_sessionGetRPCUsername(tr_session const* session);
void tr_sessionSetRPCPasswordEnabled(tr_session* session, bool isEnabled);
bool tr_sessionIsRPCPasswordEnabled(tr_session const* session);
void tr_sessionSetDefaultTrackers(tr_session* session, char const* trackers);
enum tr_rpc_callback_type
{
TR_RPC_TORRENT_ADDED,
TR_RPC_TORRENT_STARTED,
TR_RPC_TORRENT_STOPPED,
TR_RPC_TORRENT_REMOVING,
TR_RPC_TORRENT_TRASHING, /* _REMOVING + delete local data */
TR_RPC_TORRENT_CHANGED, /* catch-all for the "torrent-set" rpc method */
TR_RPC_TORRENT_MOVED,
TR_RPC_SESSION_CHANGED,
TR_RPC_SESSION_QUEUE_POSITIONS_CHANGED, /* catch potentially multiple torrents being moved in the queue */
TR_RPC_SESSION_CLOSE
};
enum tr_rpc_callback_status
{
/* no special handling is needed by the caller */
TR_RPC_OK = 0,
/* indicates to the caller that the client will take care of
* removing the torrent itself. For example the client may
* need to keep the torrent alive long enough to cleanly close
* some resources in another thread. */
TR_RPC_NOREMOVE = (1 << 1)
};
using tr_rpc_func = tr_rpc_callback_status (*)( //
tr_session* session,
tr_rpc_callback_type type,
struct tr_torrent* tor_or_null,
void* user_data);
/**
* Register to be notified whenever something is changed via RPC,
* such as a torrent being added, removed, started, stopped, etc.
*
* func is invoked FROM LIBTRANSMISSION'S THREAD!
* This means func must be fast (to avoid blocking peers),
* shouldn't call libtransmission functions (to avoid deadlock),
* and shouldn't modify client-level memory without using a mutex!
*/
void tr_sessionSetRPCCallback(tr_session* session, tr_rpc_func func, void* user_data);
/**
***
**/
/** @brief Used by tr_sessionGetStats() and tr_sessionGetCumulativeStats() */
struct tr_session_stats
{
float ratio; /* TR_RATIO_INF, TR_RATIO_NA, or total up/down */
uint64_t uploadedBytes; /* total up */
uint64_t downloadedBytes; /* total down */
uint64_t filesAdded; /* number of files added */
uint64_t sessionCount; /* program started N times */
uint64_t secondsActive; /* how long Transmisson's been running */
};
/** @brief Get bandwidth use statistics for the current session */
tr_session_stats tr_sessionGetStats(tr_session const* session);
/** @brief Get cumulative bandwidth statistics for current and past sessions */
tr_session_stats tr_sessionGetCumulativeStats(tr_session const* session);
void tr_sessionClearStats(tr_session* session);
/**
* @brief Set whether or not torrents are allowed to do peer exchanges.
*
* PEX is always disabled in private torrents regardless of this.
* In public torrents, PEX is enabled by default.
*/
void tr_sessionSetPexEnabled(tr_session* session, bool isEnabled);
bool tr_sessionIsPexEnabled(tr_session const* session);
bool tr_sessionIsDHTEnabled(tr_session const* session);
void tr_sessionSetDHTEnabled(tr_session* session, bool);
bool tr_sessionIsUTPEnabled(tr_session const* session);
void tr_sessionSetUTPEnabled(tr_session* session, bool);
bool tr_sessionIsLPDEnabled(tr_session const* session);
void tr_sessionSetLPDEnabled(tr_session* session, bool enabled);
void tr_sessionSetCacheLimit_MB(tr_session* session, int mb);
int tr_sessionGetCacheLimit_MB(tr_session const* session);
tr_encryption_mode tr_sessionGetEncryption(tr_session const* session);
void tr_sessionSetEncryption(tr_session* session, tr_encryption_mode mode);
/***********************************************************************
** Incoming Peer Connections Port
*/
void tr_sessionSetPortForwardingEnabled(tr_session* session, bool enabled);
bool tr_sessionIsPortForwardingEnabled(tr_session const* session);
void tr_sessionSetPeerPort(tr_session* session, uint16_t port);
uint16_t tr_sessionGetPeerPort(tr_session const* session);
uint16_t tr_sessionSetPeerPortRandom(tr_session* session);
void tr_sessionSetPeerPortRandomOnStart(tr_session* session, bool random);
bool tr_sessionGetPeerPortRandomOnStart(tr_session const* session);
enum tr_port_forwarding
{
TR_PORT_ERROR,
TR_PORT_UNMAPPED,
TR_PORT_UNMAPPING,
TR_PORT_MAPPING,
TR_PORT_MAPPED
};
tr_port_forwarding tr_sessionGetPortForwarding(tr_session const* session);
enum tr_direction
{
TR_CLIENT_TO_PEER = 0,
TR_UP = 0,
TR_PEER_TO_CLIENT = 1,
TR_DOWN = 1
};
/***
****
***/
/***
**** Primary session speed limits
***/
void tr_sessionSetSpeedLimit_Bps(tr_session*, tr_direction, unsigned int Bps);
void tr_sessionSetSpeedLimit_KBps(tr_session*, tr_direction, unsigned int KBps);
unsigned int tr_sessionGetSpeedLimit_KBps(tr_session const*, tr_direction);
void tr_sessionLimitSpeed(tr_session*, tr_direction, bool);
bool tr_sessionIsSpeedLimited(tr_session const*, tr_direction);
/***
**** Alternative speed limits that are used during scheduled times
***/
void tr_sessionSetAltSpeed_KBps(tr_session*, tr_direction, unsigned int Bps);
unsigned int tr_sessionGetAltSpeed_KBps(tr_session const*, tr_direction);
void tr_sessionUseAltSpeed(tr_session*, bool);
bool tr_sessionUsesAltSpeed(tr_session const*);
void tr_sessionUseAltSpeedTime(tr_session*, bool);
bool tr_sessionUsesAltSpeedTime(tr_session const*);
void tr_sessionSetAltSpeedBegin(tr_session*, int minutes_since_midnight);
int tr_sessionGetAltSpeedBegin(tr_session const*);
void tr_sessionSetAltSpeedEnd(tr_session*, int minutes_since_midnight);
int tr_sessionGetAltSpeedEnd(tr_session const*);
enum tr_sched_day
{
TR_SCHED_SUN = (1 << 0),
TR_SCHED_MON = (1 << 1),
TR_SCHED_TUES = (1 << 2),
TR_SCHED_WED = (1 << 3),
TR_SCHED_THURS = (1 << 4),
TR_SCHED_FRI = (1 << 5),
TR_SCHED_SAT = (1 << 6),
TR_SCHED_WEEKDAY = (TR_SCHED_MON | TR_SCHED_TUES | TR_SCHED_WED | TR_SCHED_THURS | TR_SCHED_FRI),
TR_SCHED_WEEKEND = (TR_SCHED_SUN | TR_SCHED_SAT),
TR_SCHED_ALL = (TR_SCHED_WEEKDAY | TR_SCHED_WEEKEND)
};
void tr_sessionSetAltSpeedDay(tr_session*, tr_sched_day day);
tr_sched_day tr_sessionGetAltSpeedDay(tr_session const*);
using tr_altSpeedFunc = void (*)(tr_session*, bool active, bool userDriven, void*);
void tr_sessionSetAltSpeedFunc(tr_session*, tr_altSpeedFunc, void*);
/***
****
***/
double tr_sessionGetRawSpeed_KBps(tr_session const*, tr_direction);
void tr_sessionSetRatioLimited(tr_session*, bool is_limited);
bool tr_sessionIsRatioLimited(tr_session const*);
void tr_sessionSetRatioLimit(tr_session*, double desired_ratio);
double tr_sessionGetRatioLimit(tr_session const*);
void tr_sessionSetIdleLimited(tr_session*, bool is_limited);
bool tr_sessionIsIdleLimited(tr_session const*);
void tr_sessionSetIdleLimit(tr_session*, uint16_t idle_minutes);
uint16_t tr_sessionGetIdleLimit(tr_session const*);
void tr_sessionSetPeerLimit(tr_session*, uint16_t max_global_peers);
uint16_t tr_sessionGetPeerLimit(tr_session const*);
void tr_sessionSetPeerLimitPerTorrent(tr_session*, uint16_t max_peers);
uint16_t tr_sessionGetPeerLimitPerTorrent(tr_session const*);
void tr_sessionSetPaused(tr_session*, bool is_paused);
bool tr_sessionGetPaused(tr_session const*);
void tr_sessionSetDeleteSource(tr_session*, bool delete_source);
bool tr_sessionGetDeleteSource(tr_session const*);
tr_priority_t tr_torrentGetPriority(tr_torrent const*);
void tr_torrentSetPriority(tr_torrent*, tr_priority_t);
void tr_sessionSetAntiBruteForceThreshold(tr_session*, int max_bad_requests);
int tr_sessionGetAntiBruteForceThreshold(tr_session const*);
void tr_sessionSetAntiBruteForceEnabled(tr_session*, bool enabled);
bool tr_sessionGetAntiBruteForceEnabled(tr_session const*);
/**
**/
/***
****
**** Torrent Queueing
****
**** There are independent queues for seeding (TR_UP) and leeching (TR_DOWN).
****
**** If the session already has enough non-stalled seeds/leeches when
**** tr_torrentStart() is called, the torrent will be moved into the
**** appropriate queue and its state will be TR_STATUS_{DOWNLOAD,SEED}_WAIT.
****
**** To bypass the queue and unconditionally start the torrent use
**** tr_torrentStartNow().
****
**** Torrents can be moved in the queue using the simple functions
**** tr_torrentQueueMove{Top,Up,Down,Bottom}. They can be moved to
**** arbitrary points in the queue with tr_torrentSetQueuePosition().
****
***/
/** @brief Like tr_torrentStart(), but resumes right away regardless of the queues. */
void tr_torrentStartNow(tr_torrent*);
/** @brief Return the queued torrent's position in the queue it's in. [0...n) */
int tr_torrentGetQueuePosition(tr_torrent const*);
/** @brief Set the queued torrent's position in the queue it's in.
* Special cases: pos <= 0 moves to the front; pos >= queue length moves to the back */
void tr_torrentSetQueuePosition(tr_torrent*, int queue_position);
/**
**/
/** @brief Convenience function for moving a batch of torrents to the front of their queue(s) */
void tr_torrentsQueueMoveTop(tr_torrent* const* torrents, size_t torrent_count);
/** @brief Convenience function for moving a batch of torrents ahead one step in their queue(s) */
void tr_torrentsQueueMoveUp(tr_torrent* const* torrents, size_t torrent_count);
/** @brief Convenience function for moving a batch of torrents back one step in their queue(s) */
void tr_torrentsQueueMoveDown(tr_torrent* const* torrents, size_t torrent_count);
/** @brief Convenience function for moving a batch of torrents to the back of their queue(s) */
void tr_torrentsQueueMoveBottom(tr_torrent* const* torrents, size_t torrent_count);
/**
**/
/** @brief Set the number of torrents allowed to download (if direction is TR_DOWN) or seed (if direction is TR_UP) at the same time */
void tr_sessionSetQueueSize(tr_session*, tr_direction, int max_simultaneous_seed_torrents);
/** @brief Return the number of torrents allowed to download (if direction is TR_DOWN) or seed (if direction is TR_UP) at the same time */
int tr_sessionGetQueueSize(tr_session const*, tr_direction);
/** @brief Set whether or not to limit how many torrents can download (TR_DOWN) or seed (TR_UP) at the same time */
void tr_sessionSetQueueEnabled(tr_session*, tr_direction, bool do_limit_simultaneous_seed_torrents);
/** @brief Return true if we're limiting how many torrents can concurrently download (TR_DOWN) or seed (TR_UP) at the same time */
bool tr_sessionGetQueueEnabled(tr_session const*, tr_direction);
/**
**/
/** @brief Consider torrent as 'stalled' when it's been inactive for N minutes.
Stalled torrents are left running but are not counted by tr_sessionGetQueueSize(). */
void tr_sessionSetQueueStalledMinutes(tr_session*, int minutes);
/** @return the number of minutes a torrent can be idle before being considered as stalled */
int tr_sessionGetQueueStalledMinutes(tr_session const*);
/** @brief Set whether or not to count torrents idle for over N minutes as 'stalled' */
void tr_sessionSetQueueStalledEnabled(tr_session*, bool);
/** @return true if we're torrents idle for over N minutes will be flagged as 'stalled' */
bool tr_sessionGetQueueStalledEnabled(tr_session const*);
/** @brief Set a callback that is invoked when the queue starts a torrent */
void tr_sessionSetQueueStartCallback(tr_session*, void (*callback)(tr_session*, tr_torrent*, void*), void* user_data);
/***
****
****
***/
/**
* Load all the torrents in the session's torrent folder.
* This can be used at startup to kickstart all the torrents
* from the previous session.
*
* @return the number of torrents in the session
*/
size_t tr_sessionLoadTorrents(tr_session* session, tr_ctor* ctor);
/**
* Get pointers to all the torrents in a session.
*
* Iff `buflen` is large enough to hold the torrents pointers,
* then all of them are copied into `buf`.
*
* @return the number of torrents in the session
*/
size_t tr_sessionGetAllTorrents(tr_session* session, tr_torrent** buf, size_t buflen);
/**
***
**/
enum TrScript
{
TR_SCRIPT_ON_TORRENT_ADDED,
TR_SCRIPT_ON_TORRENT_DONE,
TR_SCRIPT_ON_TORRENT_DONE_SEEDING,
TR_SCRIPT_N_TYPES
};
void tr_sessionSetScript(tr_session*, TrScript, char const* script_filename);
char const* tr_sessionGetScript(tr_session const*, TrScript);
void tr_sessionSetScriptEnabled(tr_session*, TrScript, bool enabled);
bool tr_sessionIsScriptEnabled(tr_session const*, TrScript);
/** @} */
/**
***
**/
/** @addtogroup Blocklists
@{ */
/**
* Specify a range of IPs for Transmission to block.
*
* Filename must be an uncompressed ascii file.
*
* libtransmission does not keep a handle to `filename'
* after this call returns, so the caller is free to
* keep or delete `filename' as it wishes.
* libtransmission makes its own copy of the file
* massaged into a binary format easier to search.
*
* The caller only needs to invoke this when the blocklist
* has changed.
*
* Passing nullptr for a filename will clear the blocklist.
*/
size_t tr_blocklistSetContent(tr_session* session, char const* content_filename);
size_t tr_blocklistGetRuleCount(tr_session const* session);
bool tr_blocklistExists(tr_session const* session);
bool tr_blocklistIsEnabled(tr_session const* session);
void tr_blocklistSetEnabled(tr_session* session, bool isEnabled);
/** @brief The blocklist that ges updated when an RPC client
invokes the "blocklist-update" method */
void tr_blocklistSetURL(tr_session*, char const* url);
char const* tr_blocklistGetURL(tr_session const*);
/** @brief the file in the $config/blocklists/ directory that's
used by tr_blocklistSetContent() and "blocklist-update" */
#define DEFAULT_BLOCKLIST_FILENAME "blocklist.bin"
/** @} */
/**
* Instantiating tr_torrents and wrangling torrent file metadata
*
* 1. Torrent metadata is handled in the tr_torrent_metadata class.
*
* 2. Torrents should be instantiated using a torrent builder (tr_ctor).
* Calling one of the tr_ctorSetMetainfo*() functions is required.
* Other settings, e.g. torrent priority, are optional.
* When ready, pass the builder object to tr_torrentNew().
*/
enum tr_ctorMode
{
TR_FALLBACK, /* indicates the ctor value should be used only in case of missing resume settings */
TR_FORCE /* indicates the ctor value should be used regardless of what's in the resume settings */
};
/** @brief Create a torrent constructor object used to instantiate a tr_torrent
@param session the tr_session. */
tr_ctor* tr_ctorNew(tr_session const* session);
/** @brief Free a torrent constructor object */
void tr_ctorFree(tr_ctor* ctor);
/** @brief Set whether or not to delete the source torrent file
when the torrent is added. (Default: False) */
void tr_ctorSetDeleteSource(tr_ctor* ctor, bool delete_source);
/** @brief Set the constructor's metainfo from a magnet link */
bool tr_ctorSetMetainfoFromMagnetLink(tr_ctor* ctor, char const* magnet, tr_error** error);
/** @brief Set the constructor's metainfo from a raw benc already in memory */
bool tr_ctorSetMetainfo(tr_ctor* ctor, char const* metainfo, size_t len, tr_error** error);
/** @brief Set the constructor's metainfo from a local torrent file */
bool tr_ctorSetMetainfoFromFile(tr_ctor* ctor, char const* filename, tr_error** error);
tr_torrent_metainfo const* tr_ctorGetMetainfo(tr_ctor const* ctor);
/** @brief Set how many peers this torrent can connect to. (Default: 50) */
void tr_ctorSetPeerLimit(tr_ctor* ctor, tr_ctorMode mode, uint16_t limit);
/** @brief Set the download folder for the torrent being added with this ctor.
@see tr_ctorSetDownloadDir()
@see tr_sessionInit() */
void tr_ctorSetDownloadDir(tr_ctor* ctor, tr_ctorMode mode, char const* directory);
/**
* @brief Set the incompleteDir for this torrent.
*
* This is not a supported API call.
* It only exists so the mac client can migrate
* its older incompleteDir settings, and that's
* the only place where it should be used.
*/
void tr_ctorSetIncompleteDir(tr_ctor* ctor, char const* directory);
/** Set whether or not the torrent begins downloading/seeding when created.
(Default: not paused) */
void tr_ctorSetPaused(tr_ctor* ctor, tr_ctorMode mode, bool isPaused);
/** @brief Set the priorities for files in a torrent */
void tr_ctorSetFilePriorities(tr_ctor* ctor, tr_file_index_t const* files, tr_file_index_t fileCount, tr_priority_t priority);
/** @brief Set the download flag for files in a torrent */
void tr_ctorSetFilesWanted(tr_ctor* ctor, tr_file_index_t const* files, tr_file_index_t fileCount, bool wanted);
/** @brief Get this peer constructor's peer limit */
bool tr_ctorGetPeerLimit(tr_ctor const* ctor, tr_ctorMode mode, uint16_t* setmeCount);
/** @brief Get the "isPaused" flag from this peer constructor */
bool tr_ctorGetPaused(tr_ctor const* ctor, tr_ctorMode mode, bool* setmeIsPaused);
/** @brief Get the download path from this peer constructor */
bool tr_ctorGetDownloadDir(tr_ctor const* ctor, tr_ctorMode mode, char const** setmeDownloadDir);
/** @brief Get the "delete torrent file" flag from this peer constructor */
bool tr_ctorGetDeleteSource(tr_ctor const* ctor, bool* setmeDoDelete);
/** @brief Get the torrent file that this ctor's metainfo came from,
or nullptr if tr_ctorSetMetainfoFromFile() wasn't used */
char const* tr_ctorGetSourceFile(tr_ctor const* ctor);
// TODO(ckerr) remove
enum tr_parse_result
{
TR_PARSE_OK,
TR_PARSE_ERR,
TR_PARSE_DUPLICATE
};
/**
* Instantiate a single torrent.
*
* Returns a pointer to the torrent on success, or nullptr on failure.
*
* @param ctor the builder struct
* @param setme_duplicate_of If the torrent couldn't be created because it's a duplicate,
* this is set to point to the original torrent.
*/
tr_torrent* tr_torrentNew(tr_ctor* ctor, tr_torrent** setme_duplicate_of);
/** @} */
/***********************************************************************
***
*** TORRENTS
**/
/** @addtogroup tr_torrent Torrents
@{ */
using tr_fileFunc = bool (*)(char const* filename, struct tr_error** error);
/** @brief Removes our torrent and .resume files for this torrent */
void tr_torrentRemove(tr_torrent* torrent, bool delete_flag, tr_fileFunc delete_func);
/** @brief Start a torrent */
void tr_torrentStart(tr_torrent* torrent);
/** @brief Stop (pause) a torrent */
void tr_torrentStop(tr_torrent* torrent);
using tr_torrent_rename_done_func = void (*)( //
tr_torrent* torrent,
char const* oldpath,
char const* newname,
int error,
void* user_data);
/**
* @brief Rename a file or directory in a torrent.
*
* @param tor the torrent whose path will be renamed
* @param oldpath the path to the file or folder that will be renamed
* @param newname the file or folder's new name
* @param callback the callback invoked when the renaming finishes, or nullptr
* @param callback_data the pointer to pass in the callback's user_data arg
*
* As a special case, renaming the root file in a torrent will also
* update tr_torrentName().
*
* EXAMPLES
*
* Consider a tr_torrent where its
* tr_torrentFile(tor, 0).name is "frobnitz-linux/checksum" and
* tr_torrentFile(tor, 1).name is "frobnitz-linux/frobnitz.iso".
*
* 1. tr_torrentRenamePath(tor, "frobnitz-linux", "foo") will rename
* the "frotbnitz-linux" folder as "foo", and update both
* tr_torrentName(tor) and tr_torrentFile(tor, *).name.
*
* 2. tr_torrentRenamePath(tor, "frobnitz-linux/checksum", "foo") will
* rename the "frobnitz-linux/checksum" file as "foo" and update
* files[0].name to "frobnitz-linux/foo".
*
* RETURN
*
* Changing the torrent's internal fields requires a session thread lock,
* so this function returns asynchronously to avoid blocking. If you don't
* want to be notified when the function has finished, you can pass nullptr
* as the callback arg.
*
* On success, the callback's error argument will be 0.
*
* If oldpath can't be found in files[*].name, or if newname is already
* in files[*].name, or contains a directory separator, or is nullptr, "",
* ".", or "..", the error argument will be EINVAL.
*
* If the path exists on disk but can't be renamed, the error argument
* will be the errno set by rename().
*/
void tr_torrentRenamePath(
tr_torrent* tor,
char const* oldpath,
char const* newname,
tr_torrent_rename_done_func callback,
void* callback_user_data);
enum
{
TR_LOC_MOVING,
TR_LOC_DONE,
TR_LOC_ERROR
};
/**
* @brief Tell transmission where to find this torrent's local data.
*
* if move_from_previous_location is `true', the torrent's incompleteDir
* will be clobbered s.t. additional files being added will be saved
* to the torrent's downloadDir.
*/
void tr_torrentSetLocation(
tr_torrent* torrent,
char const* location,
bool move_from_old_path,
double volatile* setme_progress,
int volatile* setme_state);
uint64_t tr_torrentGetBytesLeftToAllocate(tr_torrent const* torrent);
/**
* @brief Returns this torrent's unique ID.
*
* IDs are fast lookup keys, but are not persistent between sessions.
* If you need that, use tr_torrentView().hash_string.
*/
tr_torrent_id_t tr_torrentId(tr_torrent const* torrent);
tr_torrent* tr_torrentFindFromId(tr_session* session, int id);
tr_torrent* tr_torrentFindFromMetainfo(tr_session*, tr_torrent_metainfo const*);
tr_torrent* tr_torrentFindFromMagnetLink(tr_session* session, char const* link);
/**
* @brief Set metainfo if possible.
* @return True if given metainfo was set.
*
*/
bool tr_torrentSetMetainfoFromFile(tr_torrent* torrent, tr_torrent_metainfo* metainfo, char const* filename);