/* * This file Copyright (C) 2008-2014 Mnemosyne LLC * * It may be used under the GNU GPL versions 2 or 3 * or any future license endorsed by Mnemosyne LLC. * */ #pragma once #ifndef __TRANSMISSION__ #error only libtransmission should #include this header. #endif #define TR_NAME "Transmission" #include #include // memcmp() #include #include #include #include #include #include #include // evutil_ascii_strncasecmp() #include "bandwidth.h" #include "net.h" #include "tr-macros.h" #include "utils.h" // tr_speed_K enum tr_auto_switch_state_t { TR_AUTO_SWITCH_UNUSED, TR_AUTO_SWITCH_ON, TR_AUTO_SWITCH_OFF, }; tr_peer_id_t tr_peerIdInit(); struct event_base; struct evdns_base; class tr_bitfield; struct tr_address; struct tr_announcer; struct tr_announcer_udp; struct tr_bindsockets; struct tr_blocklistFile; struct tr_cache; struct tr_device_info; struct tr_fdInfo; struct tr_turtle_info { /* TR_UP and TR_DOWN speed limits */ unsigned int speedLimit_Bps[2]; /* is turtle mode on right now? */ bool isEnabled; /* does turtle mode turn itself on and off at given times? */ bool isClockEnabled; /* when clock mode is on, minutes after midnight to turn on turtle mode */ int beginMinute; /* when clock mode is on, minutes after midnight to turn off turtle mode */ int endMinute; /* only use clock mode on these days of the week */ tr_sched_day days; /* called when isEnabled changes */ tr_altSpeedFunc callback; /* the callback's user_data argument */ void* callbackUserData; /* the callback's changedByUser argument. * indicates whether the change came from the user or from the clock. */ bool changedByUser; /* bitfield of all the minutes in a week. * Each bit's value indicates whether the scheduler wants turtle * limits on or off at that given minute in the week. */ // Changed to non-owning pointer temporarily till tr_turtle_info becomes C++-constructible and destructible // TODO: remove * and own the value tr_bitfield* minutes = nullptr; /* recent action that was done by turtle's automatic switch */ tr_auto_switch_state_t autoTurtleState; }; struct CompareHash { bool operator()(uint8_t const* const a, uint8_t const* const b) const { return std::memcmp(a, b, SHA_DIGEST_LENGTH) < 0; } }; struct CaseInsensitiveStringCompare // case-insensitive string compare { int compare(std::string_view a, std::string_view b) const // <=> { auto const alen = std::size(a); auto const blen = std::size(b); auto i = evutil_ascii_strncasecmp(std::data(a), std::data(b), std::min(alen, blen)); if (i != 0) { return i; } if (alen != blen) { return alen < blen ? -1 : 1; } return 0; } bool operator()(std::string_view a, std::string_view b) const // less than { return compare(a, b) < 0; } }; /** @brief handle to an active libtransmission session */ struct tr_session { bool isPortRandom; bool isPexEnabled; bool isDHTEnabled; bool isUTPEnabled; bool isLPDEnabled; bool isBlocklistEnabled; bool isPrefetchEnabled; bool isClosing; bool isClosed; bool isIncompleteFileNamingEnabled; bool isRatioLimited; bool isIdleLimited; bool isIncompleteDirEnabled; bool pauseAddedTorrent; bool deleteSourceTorrent; bool scrapePausedTorrents; std::array scripts_enabled; uint8_t peer_id_ttl_hours; // torrent id, time removed std::vector> removed_torrents; bool stalledEnabled; bool queueEnabled[2]; int queueSize[2]; int queueStalledMinutes; int umask; unsigned int speedLimit_Bps[2]; bool speedLimitEnabled[2]; struct tr_turtle_info turtle; struct tr_fdInfo* fdInfo; int magicNumber; tr_encryption_mode encryptionMode; tr_preallocation_mode preallocationMode; struct event_base* event_base; struct evdns_base* evdns_base; struct tr_event_handle* events; uint16_t peerLimit; uint16_t peerLimitPerTorrent; int uploadSlotsPerTorrent; /* The UDP sockets used for the DHT and uTP. */ tr_port udp_port; tr_socket_t udp_socket; tr_socket_t udp6_socket; unsigned char* udp6_bound; struct event* udp_event; struct event* udp6_event; struct event* utp_timer; /* The open port on the local machine for incoming peer requests */ tr_port private_peer_port; /** * The open port on the public device for incoming peer requests. * This is usually the same as private_peer_port but can differ * if the public device is a router and it decides to use a different * port than the one requested by Transmission. */ tr_port public_peer_port; tr_port randomPortLow; tr_port randomPortHigh; int peerSocketTOS; char* peer_congestion_algorithm; std::unordered_set torrents; std::map torrentsById; std::map torrentsByHash; std::map torrentsByHashString; std::array scripts; char* configDir; char* resumeDir; char* torrentDir; char* incompleteDir; char* blocklist_url; struct tr_device_info* downloadDir; std::list blocklists; struct tr_peerMgr* peerMgr; struct tr_shared* shared; struct tr_cache* cache; struct tr_lock* lock; struct tr_web* web; struct tr_session_id* session_id; struct tr_rpc_server* rpcServer; tr_rpc_func rpc_func; void* rpc_func_user_data; struct tr_stats_handle* sessionStats; struct tr_announcer* announcer; struct tr_announcer_udp* announcer_udp; struct event* nowTimer; struct event* saveTimer; /* monitors the "global pool" speeds */ // Changed to non-owning pointer temporarily till tr_session becomes C++-constructible and destructible // TODO: change tr_bandwidth* to owning pointer to the bandwidth, or remove * and own the value Bandwidth* bandwidth; float desiredRatio; uint16_t idleLimitMinutes; struct tr_bindinfo* bind_ipv4; struct tr_bindinfo* bind_ipv6; }; constexpr tr_port tr_sessionGetPublicPeerPort(tr_session const* session) { return session->public_peer_port; } bool tr_sessionAllowsDHT(tr_session const* session); bool tr_sessionAllowsLPD(tr_session const* session); bool tr_sessionIsAddressBlocked(tr_session const* session, struct tr_address const* addr); void tr_sessionLock(tr_session*); void tr_sessionUnlock(tr_session*); bool tr_sessionIsLocked(tr_session const*); struct tr_address const* tr_sessionGetPublicAddress(tr_session const* session, int tr_af_type, bool* is_default_value); struct tr_bindsockets* tr_sessionGetBindSockets(tr_session*); int tr_sessionCountTorrents(tr_session const* session); std::vector tr_sessionGetTorrents(tr_session* session); enum { SESSION_MAGIC_NUMBER = 3845, }; constexpr bool tr_isSession(tr_session const* session) { return session != nullptr && session->magicNumber == SESSION_MAGIC_NUMBER; } constexpr bool tr_isPreallocationMode(tr_preallocation_mode m) { return m == TR_PREALLOCATE_NONE || m == TR_PREALLOCATE_SPARSE || m == TR_PREALLOCATE_FULL; } constexpr bool tr_isEncryptionMode(tr_encryption_mode m) { return m == TR_CLEAR_PREFERRED || m == TR_ENCRYPTION_PREFERRED || m == TR_ENCRYPTION_REQUIRED; } constexpr bool tr_isPriority(tr_priority_t p) { return p == TR_PRI_LOW || p == TR_PRI_NORMAL || p == TR_PRI_HIGH; } /*** **** ***/ static inline unsigned int toSpeedBytes(unsigned int KBps) { return KBps * tr_speed_K; } static inline double toSpeedKBps(unsigned int Bps) { return Bps / (double)tr_speed_K; } static inline uint64_t toMemBytes(unsigned int MB) { uint64_t B = (uint64_t)tr_mem_K * tr_mem_K; B *= MB; return B; } static inline int toMemMB(uint64_t B) { return (int)(B / (tr_mem_K * tr_mem_K)); } /** **/ unsigned int tr_sessionGetSpeedLimit_Bps(tr_session const*, tr_direction); unsigned int tr_sessionGetPieceSpeed_Bps(tr_session const*, tr_direction); bool tr_sessionGetActiveSpeedLimit_Bps(tr_session const* session, tr_direction dir, unsigned int* setme); std::vector tr_sessionGetNextQueuedTorrents(tr_session* session, tr_direction dir, size_t numwanted); int tr_sessionCountQueueFreeSlots(tr_session* session, tr_direction); void tr_sessionAddTorrent(tr_session* session, tr_torrent* tor); void tr_sessionRemoveTorrent(tr_session* session, tr_torrent* tor);