From 046de4118f7137ea53aa63204c78fc1c6b8cae21 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 20 Aug 2022 00:18:50 +0200 Subject: [PATCH] Rework curl helpers --- src/advanced-scene-switcher.cpp | 12 ---- src/legacy/switch-file.cpp | 25 +++---- src/macro-core/macro-action-http.cpp | 25 +++---- src/macro-core/macro-condition-file.cpp | 24 +++---- src/switcher-data-structs.hpp | 4 +- src/utils/curl-helper.cpp | 92 +++++++++++++++---------- src/utils/curl-helper.hpp | 45 +++++++----- 7 files changed, 120 insertions(+), 107 deletions(-) diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index 99868874..e02044a9 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -487,14 +487,6 @@ bool SwitcherData::anySceneTransitionStarted() ******************************************************************************/ extern "C" void FreeSceneSwitcher() { - if (loaded_curl_lib) { - if (switcher->curl && f_curl_cleanup) { - f_curl_cleanup(switcher->curl); - } - delete loaded_curl_lib; - loaded_curl_lib = nullptr; - } - PlatformCleanup(); delete switcher; @@ -691,10 +683,6 @@ extern "C" void InitSceneSwitcher(obs_module_t *m, translateFunc t) switcher->modulePtr = m; switcher->translate = t; - if (loadCurl() && f_curl_init) { - switcher->curl = f_curl_init(); - } - PlatformInit(); LoadPlugins(); SetupDock(); diff --git a/src/legacy/switch-file.cpp b/src/legacy/switch-file.cpp index c57ceb8d..a9ba1883 100644 --- a/src/legacy/switch-file.cpp +++ b/src/legacy/switch-file.cpp @@ -174,21 +174,18 @@ static std::string getRemoteData(std::string &url) { std::string readBuffer; - if (switcher->curl && f_curl_setopt && f_curl_perform) { - f_curl_setopt(switcher->curl, CURLOPT_URL, url.c_str()); - f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, - WriteCallback); - f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer); + switcher->curl.SetOpt(CURLOPT_URL, url.c_str()); + switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback); + switcher->curl.SetOpt(CURLOPT_WRITEDATA, &readBuffer); - // Set timeout to at least one second - int timeout = switcher->interval / 1000; - if (timeout == 0) { - timeout = 1; - } - f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT, 1); - - f_curl_perform(switcher->curl); + // Set timeout to at least one second + int timeout = switcher->interval / 1000; + if (timeout == 0) { + timeout = 1; } + switcher->curl.SetOpt(CURLOPT_TIMEOUT, 1); + switcher->curl.Perform(); + return readBuffer; } @@ -422,7 +419,7 @@ void AdvSceneSwitcher::setupFileTab() obs_module_text("AdvSceneSwitcher.fileTab.remoteFileWarning2")); ui->remoteFileWarningLabel->hide(); - if (switcher->curl) { + if (switcher->curl.Initialized()) { ui->libcurlWarning->setVisible(false); } diff --git a/src/macro-core/macro-action-http.cpp b/src/macro-core/macro-action-http.cpp index 7951cbb9..299b53fa 100644 --- a/src/macro-core/macro-action-http.cpp +++ b/src/macro-core/macro-action-http.cpp @@ -24,31 +24,28 @@ size_t WriteCB(void *, size_t size, size_t nmemb, std::string *) void MacroActionHttp::Get() { - - f_curl_setopt(switcher->curl, CURLOPT_URL, _url.c_str()); - f_curl_setopt(switcher->curl, CURLOPT_HTTPGET, 1L); - f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT_MS, - _timeout.seconds * 1000); + switcher->curl.SetOpt(CURLOPT_URL, _url.c_str()); + switcher->curl.SetOpt(CURLOPT_HTTPGET, 1L); + switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000); std::string response; - f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, WriteCB); - f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &response); + switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCB); + switcher->curl.SetOpt(CURLOPT_WRITEDATA, &response); - f_curl_perform(switcher->curl); + switcher->curl.Perform(); } void MacroActionHttp::Post() { - f_curl_setopt(switcher->curl, CURLOPT_URL, _url.c_str()); - f_curl_setopt(switcher->curl, CURLOPT_POSTFIELDS, _data.c_str()); - f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT_MS, - _timeout.seconds * 1000); - f_curl_perform(switcher->curl); + switcher->curl.SetOpt(CURLOPT_URL, _url.c_str()); + switcher->curl.SetOpt(CURLOPT_POSTFIELDS, _data.c_str()); + switcher->curl.SetOpt(CURLOPT_TIMEOUT_MS, _timeout.seconds * 1000); + switcher->curl.Perform(); } bool MacroActionHttp::PerformAction() { - if (!switcher->curl) { + if (!switcher->curl.Initialized()) { blog(LOG_WARNING, "cannot perform http action (curl not found)"); return true; diff --git a/src/macro-core/macro-condition-file.cpp b/src/macro-core/macro-condition-file.cpp index 77b02616..538929bb 100644 --- a/src/macro-core/macro-condition-file.cpp +++ b/src/macro-core/macro-condition-file.cpp @@ -27,22 +27,16 @@ static size_t WriteCallback(void *contents, size_t size, size_t nmemb, static std::string getRemoteData(std::string &url) { std::string readBuffer; - - if (switcher->curl && f_curl_setopt && f_curl_perform) { - f_curl_setopt(switcher->curl, CURLOPT_URL, url.c_str()); - f_curl_setopt(switcher->curl, CURLOPT_WRITEFUNCTION, - WriteCallback); - f_curl_setopt(switcher->curl, CURLOPT_WRITEDATA, &readBuffer); - - // Set timeout to at least one second - int timeout = switcher->interval / 1000; - if (timeout == 0) { - timeout = 1; - } - f_curl_setopt(switcher->curl, CURLOPT_TIMEOUT, 1); - - f_curl_perform(switcher->curl); + switcher->curl.SetOpt(CURLOPT_URL, url.c_str()); + switcher->curl.SetOpt(CURLOPT_WRITEFUNCTION, WriteCallback); + switcher->curl.SetOpt(CURLOPT_WRITEDATA, &readBuffer); + // Set timeout to at least one second + int timeout = switcher->interval / 1000; + if (timeout == 0) { + timeout = 1; } + switcher->curl.SetOpt(CURLOPT_TIMEOUT, 1); + switcher->curl.Perform(); return readBuffer; } diff --git a/src/switcher-data-structs.hpp b/src/switcher-data-structs.hpp index dd648886..f7c03d2c 100644 --- a/src/switcher-data-structs.hpp +++ b/src/switcher-data-structs.hpp @@ -29,6 +29,7 @@ #include #include #include +#include constexpr auto default_interval = 300; constexpr auto previous_scene_name = "Previous Scene"; @@ -135,6 +136,8 @@ struct SwitcherData { bool obsIsShuttingDown = false; int shutdownConditionCount = 0; + Curlhelper curl; + std::deque connections; std::vector websocketMessages; @@ -158,7 +161,6 @@ struct SwitcherData { FileIOData fileIO; std::deque fileSwitches; - CURL *curl = nullptr; std::deque executableSwitches; diff --git a/src/utils/curl-helper.cpp b/src/utils/curl-helper.cpp index 5699de36..452e4e9b 100644 --- a/src/utils/curl-helper.cpp +++ b/src/utils/curl-helper.cpp @@ -1,49 +1,57 @@ +#include "curl-helper.hpp" + #include #include #include #include -#include "curl-helper.hpp" +#if defined(WIN32) +constexpr auto curl_library_name = "libcurl.dll"; +#elif __APPLE__ +constexpr auto curl_library_name = "libcurl.4.dylib"; +#else +constexpr auto curl_library_name = "libcurl.so.4"; +#endif -initFunction f_curl_init = nullptr; -setOptFunction f_curl_setopt = nullptr; -performFunction f_curl_perform = nullptr; -cleanupFunction f_curl_cleanup = nullptr; - -QLibrary *loaded_curl_lib = nullptr; - -bool resolveCurl() +Curlhelper::Curlhelper() { - f_curl_init = (initFunction)loaded_curl_lib->resolve("curl_easy_init"); - f_curl_setopt = - (setOptFunction)loaded_curl_lib->resolve("curl_easy_setopt"); - f_curl_perform = - (performFunction)loaded_curl_lib->resolve("curl_easy_perform"); - f_curl_cleanup = - (cleanupFunction)loaded_curl_lib->resolve("curl_easy_cleanup"); - - if (f_curl_init && f_curl_setopt && f_curl_perform && f_curl_cleanup) { - blog(LOG_INFO, "[adv-ss] curl loaded successfully"); - return true; + if (LoadLib()) { + _curl = _init(); + _initialized = true; } - - blog(LOG_INFO, "[adv-ss] curl symbols not resolved"); - return false; } -bool loadCurl() +Curlhelper::~Curlhelper() { - loaded_curl_lib = new QLibrary(curl_library_name, nullptr); - if (resolveCurl()) { + if (_lib) { + if (_cleanup) { + _cleanup(_curl); + } + delete _lib; + _lib = nullptr; + } +} + +CURLcode Curlhelper::Perform() +{ + if (!_initialized) { + return CURLE_FAILED_INIT; + } + return _perform(_curl); +} + +bool Curlhelper::LoadLib() +{ + _lib = new QLibrary(curl_library_name, nullptr); + if (Resolve()) { blog(LOG_INFO, "[adv-ss] found curl library"); return true; } else { - delete loaded_curl_lib; - loaded_curl_lib = nullptr; + delete _lib; + _lib = nullptr; blog(LOG_WARNING, "[adv-ss] couldn't find the curl library in PATH"); } - QStringList locations; locations << QDir::currentPath(); #if defined(__linux__) || defined(__APPLE__) @@ -52,7 +60,6 @@ bool loadCurl() locations << "/usr/lib/x86_64-linux-gnu"; locations << "/usr/local/opt/curl/lib"; #endif - for (QString path : locations) { blog(LOG_INFO, "[adv-ss] trying '%s'", path.toUtf8().constData()); @@ -64,16 +71,31 @@ bool loadCurl() blog(LOG_INFO, "[adv-ss] found curl library at '%s'", libFilePath.toUtf8().constData()); - loaded_curl_lib = new QLibrary(libFilePath, nullptr); - if (resolveCurl()) { + _lib = new QLibrary(libFilePath, nullptr); + if (Resolve()) { return true; } else { - delete loaded_curl_lib; - loaded_curl_lib = nullptr; + delete _lib; + _lib = nullptr; } } } - blog(LOG_WARNING, "[adv-ss] can't find the curl library"); return false; } + +bool Curlhelper::Resolve() +{ + _init = (initFunction)_lib->resolve("curl_easy_init"); + _setopt = (setOptFunction)_lib->resolve("curl_easy_setopt"); + _perform = (performFunction)_lib->resolve("curl_easy_perform"); + _cleanup = (cleanupFunction)_lib->resolve("curl_easy_cleanup"); + + if (_init && _setopt && _perform && _cleanup) { + blog(LOG_INFO, "[adv-ss] curl loaded successfully"); + return true; + } + + blog(LOG_INFO, "[adv-ss] curl symbols not resolved"); + return false; +} diff --git a/src/utils/curl-helper.hpp b/src/utils/curl-helper.hpp index 461e81f3..4cd4ea1e 100644 --- a/src/utils/curl-helper.hpp +++ b/src/utils/curl-helper.hpp @@ -2,25 +2,38 @@ #include #include -#if defined(WIN32) -constexpr auto curl_library_name = "libcurl.dll"; -#elif __APPLE__ -constexpr auto curl_library_name = "libcurl.4.dylib"; -#else -constexpr auto curl_library_name = "libcurl.so.4"; -#endif - typedef CURL *(*initFunction)(void); +typedef void (*cleanupFunction)(CURL *); typedef CURLcode (*setOptFunction)(CURL *, CURLoption, ...); typedef CURLcode (*performFunction)(CURL *); -typedef void (*cleanupFunction)(CURL *); -extern initFunction f_curl_init; -extern setOptFunction f_curl_setopt; -extern performFunction f_curl_perform; -extern cleanupFunction f_curl_cleanup; +class Curlhelper { +public: + Curlhelper(); + ~Curlhelper(); -extern QLibrary *loaded_curl_lib; + template CURLcode SetOpt(CURLoption, Args...); + CURLcode Perform(); + bool Initialized() { return _initialized; } -bool resolveCurl(); -bool loadCurl(); +private: + bool LoadLib(); + bool Resolve(); + + initFunction _init = nullptr; + setOptFunction _setopt = nullptr; + performFunction _perform = nullptr; + cleanupFunction _cleanup = nullptr; + CURL *_curl = nullptr; + QLibrary *_lib; + bool _initialized = false; +}; + +template +inline CURLcode Curlhelper::SetOpt(CURLoption option, Args... args) +{ + if (!_initialized) { + return CURLE_FAILED_INIT; + } + return _setopt(_curl, option, args...); +}