diff --git a/cli/cli.cc b/cli/cli.cc index 86f5f6797..42ac7f52f 100644 --- a/cli/cli.cc +++ b/cli/cli.cc @@ -200,6 +200,8 @@ static std::string getConfigDir(int argc, char const** argv) int tr_main(int argc, char* argv[]) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); tr_variant settings; diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 6bf38dbd6..c963b0f2a 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -691,9 +692,6 @@ int tr_daemon::start([[maybe_unused]] bool foreground) sd_notifyf(0, "MAINPID=%d\n", (int)getpid()); - /* should go before libevent calls */ - tr_net_init(); - /* setup event state */ ev_base_ = event_base_new(); @@ -941,6 +939,8 @@ void tr_daemon::handle_error(tr_error* error) const int tr_main(int argc, char* argv[]) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); int ret; diff --git a/gtk/main.cc b/gtk/main.cc index b59fec441..0b6c94bb4 100644 --- a/gtk/main.cc +++ b/gtk/main.cc @@ -50,6 +50,9 @@ Glib::OptionEntry create_option_entry(Glib::ustring const& long_name, gchar shor int main(int argc, char** argv) { + /* init libtransmission */ + auto const init_mgr = tr_lib_init(); + /* init i18n */ tr_locale_set_global(""); bindtextdomain(AppTranslationDomainName, TRANSMISSIONLOCALEDIR); diff --git a/libtransmission/session-thread.cc b/libtransmission/session-thread.cc index b8303b728..4d08a3e56 100644 --- a/libtransmission/session-thread.cc +++ b/libtransmission/session-thread.cc @@ -113,8 +113,6 @@ unsigned long thread_current_id() void initEvthreadsOnce() { - tr_net_init(); - evthread_lock_callbacks constexpr LockCbs{ EVTHREAD_LOCK_API_VERSION, EVTHREAD_LOCKTYPE_RECURSIVE, lock_alloc, lock_free, lock_lock, lock_unlock }; diff --git a/libtransmission/tr-lpd.cc b/libtransmission/tr-lpd.cc index 97a8c6d41..97bae2d27 100644 --- a/libtransmission/tr-lpd.cc +++ b/libtransmission/tr-lpd.cc @@ -272,8 +272,6 @@ private: */ bool initImpl(struct event_base* event_base) { - tr_net_init(); - int const opt_on = 1; static_assert(AnnounceScope > 0); diff --git a/libtransmission/utils.cc b/libtransmission/utils.cc index 77f6be748..9637283dd 100644 --- a/libtransmission/utils.cc +++ b/libtransmission/utils.cc @@ -11,7 +11,6 @@ #include // SIZE_MAX #include // getenv() #include /* strerror() */ -#include // nanosleep() #include #include // for std::back_inserter #include @@ -19,14 +18,12 @@ #include #include #include -#include #include #ifdef _WIN32 #include /* Sleep(), GetEnvironmentVariable() */ #include /* CommandLineToArgv() */ -#include /* WSAStartup() */ #endif #ifndef _WIN32 @@ -36,6 +33,8 @@ #define UTF_CPP_CPLUSPLUS 201703L #include +#include + #include #include @@ -929,19 +928,36 @@ std::string tr_env_get_string(std::string_view key, std::string_view default_val // --- -void tr_net_init() +tr_net_init_mgr::tr_net_init_mgr() { -#ifdef _WIN32 - static bool initialized = false; - - if (!initialized) + // try to init curl with default settings (currently ssl support + win32 sockets) + // but if that fails, we need to init win32 sockets as a bare minimum + if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { - WSADATA wsaData; - WSAStartup(MAKEWORD(2, 2), &wsaData); - - initialized = true; + curl_global_init(CURL_GLOBAL_WIN32); } -#endif +} + +tr_net_init_mgr::~tr_net_init_mgr() +{ + curl_global_cleanup(); +} + +std::unique_ptr tr_net_init_mgr::create() +{ + if (!initialised) + { + initialised = true; + return std::unique_ptr{ new tr_net_init_mgr }; + } + return {}; +} + +bool tr_net_init_mgr::initialised = false; + +std::unique_ptr tr_lib_init() +{ + return tr_net_init_mgr::create(); } // --- mime-type diff --git a/libtransmission/utils.h b/libtransmission/utils.h index 52ee00a10..c2abdee1d 100644 --- a/libtransmission/utils.h +++ b/libtransmission/utils.h @@ -10,6 +10,7 @@ #include // uint8_t, uint32_t, uint64_t #include // size_t #include // time_t +#include #include #include #include @@ -340,4 +341,20 @@ void tr_formatter_get_units(void* dict); // --- -void tr_net_init(); +class tr_net_init_mgr +{ +private: + tr_net_init_mgr(); + TR_DISABLE_COPY_MOVE(tr_net_init_mgr) + +public: + ~tr_net_init_mgr(); + static std::unique_ptr create(); + +private: + static bool initialised; +}; + +/** @brief Initialise libtransmission for each app + * @return A manager object to be kept in scope of main() */ +std::unique_ptr tr_lib_init(); diff --git a/libtransmission/watchdir-win32.cc b/libtransmission/watchdir-win32.cc index 360f3148d..3b8cc0962 100644 --- a/libtransmission/watchdir-win32.cc +++ b/libtransmission/watchdir-win32.cc @@ -134,8 +134,6 @@ private: void init(struct event_base* event_base) { - tr_net_init(); - auto const path = dirname(); auto const wide_path = tr_win32_utf8_to_native(path); if (std::empty(wide_path)) diff --git a/libtransmission/web.cc b/libtransmission/web.cc index 38a1584b5..fdea4f8d6 100644 --- a/libtransmission/web.cc +++ b/libtransmission/web.cc @@ -160,8 +160,6 @@ public: explicit Impl(Mediator& mediator_in) : mediator{ mediator_in } { - std::call_once(curl_init_flag, curlInit); - if (auto bundle = tr_env_get_string("CURL_CA_BUNDLE"); !std::empty(bundle)) { curl_ca_bundle = std::move(bundle); @@ -778,19 +776,7 @@ public: } } - static inline auto curl_init_flag = std::once_flag{}; - std::map paused_easy_handles; - - static void curlInit() - { - // try to enable ssl for https support; - // but if that fails, try a plain vanilla init - if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) - { - curl_global_init(0); - } - } }; tr_web::tr_web(Mediator& mediator) diff --git a/macosx/main.mm b/macosx/main.mm index 17cfadb6f..e473e563f 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -10,6 +10,8 @@ int main(int argc, char** argv) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); return NSApplicationMain(argc, (char const**)argv); diff --git a/qt/Application.cc b/qt/Application.cc index 6b883a8fe..82f418d7d 100644 --- a/qt/Application.cc +++ b/qt/Application.cc @@ -662,6 +662,8 @@ void Application::onNotificationActionInvoked(quint32 /* notification_id */, QSt int tr_main(int argc, char** argv) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); InteropHelper::initialize(); diff --git a/tests/libtransmission/announcer-udp-test.cc b/tests/libtransmission/announcer-udp-test.cc index 06a543f17..277982ce8 100644 --- a/tests/libtransmission/announcer-udp-test.cc +++ b/tests/libtransmission/announcer-udp-test.cc @@ -32,9 +32,8 @@ class AnnouncerUdpTest : public ::testing::Test private: void SetUp() override { - tr_net_init(); - ::testing::Test::SetUp(); + init_mgr_ = tr_lib_init(); tr_timeUpdate(time(nullptr)); } @@ -288,6 +287,8 @@ protected: return timer; } + std::unique_ptr init_mgr_; + // https://www.bittorrent.org/beps/bep_0015.html static auto constexpr ProtocolId = uint64_t{ 0x41727101980ULL }; static auto constexpr ConnectAction = uint32_t{ 0 }; diff --git a/tests/libtransmission/dht-test.cc b/tests/libtransmission/dht-test.cc index 5460b375e..a54c39928 100644 --- a/tests/libtransmission/dht-test.cc +++ b/tests/libtransmission/dht-test.cc @@ -15,6 +15,7 @@ #include #include +#include #include // for tr_evthread_init(); #include "gtest/gtest.h" @@ -388,6 +389,8 @@ protected: { SandboxedTest::SetUp(); + init_mgr_ = tr_lib_init(); + tr_session_thread::tr_evthread_init(); event_base_ = event_base_new(); } @@ -402,6 +405,8 @@ protected: struct event_base* event_base_ = nullptr; + std::unique_ptr init_mgr_; + // Arbitrary values. Several tests requires socket/port values // to be provided but they aren't central to the tests, so they're // declared here with "Arbitrary" in the name to make that clear. diff --git a/tests/libtransmission/test-fixtures.h b/tests/libtransmission/test-fixtures.h index da65c7727..bdbed5447 100644 --- a/tests/libtransmission/test-fixtures.h +++ b/tests/libtransmission/test-fixtures.h @@ -530,6 +530,8 @@ protected: { SandboxedTest::SetUp(); + init_mgr_ = tr_lib_init(); + auto callback = [this](tr_torrent* tor, bool /*aborted*/) { auto verified_lock = std::scoped_lock(verified_mutex_); @@ -554,6 +556,8 @@ private: std::mutex verified_mutex_; std::condition_variable verified_cv_; std::vector verified_; + + std::unique_ptr init_mgr_; }; } // namespace test diff --git a/tests/libtransmission/watchdir-test.cc b/tests/libtransmission/watchdir-test.cc index 452d3f6e8..07192c166 100644 --- a/tests/libtransmission/watchdir-test.cc +++ b/tests/libtransmission/watchdir-test.cc @@ -53,10 +53,13 @@ private: std::shared_ptr ev_base_; std::unique_ptr timer_maker_; + std::unique_ptr init_mgr_; + protected: void SetUp() override { SandboxedTest::SetUp(); + init_mgr_ = tr_lib_init(); ev_base_.reset(event_base_new(), event_base_free); timer_maker_ = std::make_unique(ev_base_.get()); Watchdir::set_generic_rescan_interval(GenericRescanInterval); diff --git a/utils/remote.cc b/utils/remote.cc index a2c56396c..eb7e772d2 100644 --- a/utils/remote.cc +++ b/utils/remote.cc @@ -3290,6 +3290,8 @@ static void getHostAndPortAndRpcUrl(int* argc, char** argv, std::string* host, i int tr_main(int argc, char* argv[]) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); auto config = Config{}; diff --git a/utils/show.cc b/utils/show.cc index 0c2eaaa19..bfa2fec6c 100644 --- a/utils/show.cc +++ b/utils/show.cc @@ -398,6 +398,8 @@ void doScrape(tr_torrent_metainfo const& metainfo) int tr_main(int argc, char* argv[]) { + auto const init_mgr = tr_lib_init(); + tr_locale_set_global(""); tr_logSetQueueEnabled(false);