diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c18074..2c1884b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,7 @@ pr_add_module(${PROJ_NAME} SHARED "modules/curl/") pr_add_dependency(${PROJ_NAME} ishared TARGET PUBLIC) -pr_add_headers(${PROJ_NAME} "include/") -pr_add_sources(${PROJ_NAME} "src/") +pr_init_module(${PROJ_NAME}) # Curl set(CURL_USE_LIBSSH2 OFF CACHE BOOL "Curl SSH2" FORCE) diff --git a/include/curl_handler.hpp b/include/curl_handler.hpp deleted file mode 100644 index 629e106..0000000 --- a/include/curl_handler.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-FileCopyrightText: (c) 2019 Silverlan -// SPDX-License-Identifier: MIT - -#ifndef __CURL_HANDLER_HPP__ -#define __CURL_HANDLER_HPP__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct RequestData { - RequestData() = default; - std::string postData; - std::vector headers; - std::optional timeoutMs {}; - std::function &)> onComplete; - std::function progressCallback; - - void SetPostKeyValues(const std::unordered_map &postValues); -}; - -class CurlHandler { - public: - enum class ResultCode : uint32_t { Ok = 0, BadHandle, BadEasyHandle, OutOfMemory, InternalError, BadSocket, UnknownOption, AddedAlready }; - CurlHandler(); - ~CurlHandler(); - void AddResource(const std::string &fname, const std::function &callback, const std::shared_ptr &userData = nullptr, const std::function &progressCallback = nullptr, - const std::function &onComplete = nullptr); - void AddRequest(const std::string &url, const RequestData &requestData = {}); - void StartDownload(); - void CancelDownload(); - bool IsComplete() const; - void SetErrorHandler(const std::function &f); - private: - void *m_multiCurl = nullptr; - - struct Request { - struct Header { - std::string fileName; - } header; - std::string url; - std::optional timeoutMs; - std::function writeCallback = nullptr; // Write Callback - std::function completeCallback = nullptr; - std::function progressCallback = nullptr; - std::shared_ptr userData = nullptr; - CurlHandler *curl = nullptr; - std::shared_ptr handle = nullptr; - std::shared_ptr headers = nullptr; - std::function request = nullptr; - }; - - std::queue> m_queuedRequests; - std::vector> m_activeRequests; - std::mutex m_resourceMutex; - std::mutex m_requestMutex; - std::unique_ptr m_thread = nullptr; - std::atomic m_bComplete = true; - std::atomic m_bCancel = false; - std::atomic m_bThreadActive = false; - std::function m_errorHandler = nullptr; - - void ProcessNextRequest(); - uint32_t ProcessAllRequests(); - - void AddRequest(const std::string &url, const std::function &writeCallback, const std::function &onComplete, const std::function &progressCallback, - const std::function &fRequest, std::optional timeout = {}); - static size_t ReceiveHeader(char *buffer, size_t size, size_t nitems, void *userdata); - static void InitializeCurl(void *curl, Request *request); - static size_t WriteData(void *ptr, size_t size, size_t nmemb, void *userData); - static int32_t UpdateProgress(void *clientp, int64_t dltotal, int64_t dlnow, int64_t ultotal, int64_t ulnow); - static std::string ResultCodeToString(ResultCode ec); -}; - -#endif diff --git a/include/wvmodule.hpp b/include/wvmodule.hpp deleted file mode 100644 index 6e47fa5..0000000 --- a/include/wvmodule.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: (c) 2019 Silverlan -// SPDX-License-Identifier: MIT - -#ifndef __WVMODULE_HPP__ -#define __WVMODULE_HPP__ - - - -#endif diff --git a/src/curl_handler.cpp b/src/implementation/curl_handler.cpp similarity index 87% rename from src/curl_handler.cpp rename to src/implementation/curl_handler.cpp index ac0a847..e45961f 100644 --- a/src/curl_handler.cpp +++ b/src/implementation/curl_handler.cpp @@ -1,10 +1,11 @@ // SPDX-FileCopyrightText: (c) 2019 Silverlan // SPDX-License-Identifier: MIT -#include "curl_handler.hpp" +module; + #include -#include -#include + +module pragma.modules.curl; CurlHandler::CurlHandler() {} @@ -296,18 +297,18 @@ void CurlHandler::AddRequest(const std::string &url, const RequestData &requestD } extern "C" { -PRAGMA_EXPORT void *mcd_create() { return new CurlHandler(); } -PRAGMA_EXPORT void mcd_release(void *cd) { delete static_cast(cd); } -PRAGMA_EXPORT void mcd_add_resource(void *cd, const std::string &fname, const std::function &callback, const std::shared_ptr &userData, const std::function &progressCallback, +PR_EXPORT void *mcd_create() { return new CurlHandler(); } +PR_EXPORT void mcd_release(void *cd) { delete static_cast(cd); } +PR_EXPORT void mcd_add_resource(void *cd, const std::string &fname, const std::function &callback, const std::shared_ptr &userData, const std::function &progressCallback, const std::function &onComplete) { static_cast(cd)->AddResource(fname, callback, userData, progressCallback, onComplete); } -PRAGMA_EXPORT void mcd_start_download(void *cd) { static_cast(cd)->StartDownload(); } -PRAGMA_EXPORT void mcd_cancel_download(void *cd) { static_cast(cd)->CancelDownload(); } -PRAGMA_EXPORT bool mcd_is_complete(void *cd) { return static_cast(cd)->IsComplete(); } -PRAGMA_EXPORT void mcd_set_error_handler(void *cd, const std::function &f) { static_cast(cd)->SetErrorHandler(reinterpret_cast &>(f)); } -PRAGMA_EXPORT void mcd_send_request(void *cd, const std::string &url, const std::unordered_map &post, const std::function &onComplete, const std::function &progressCallback) +PR_EXPORT void mcd_start_download(void *cd) { static_cast(cd)->StartDownload(); } +PR_EXPORT void mcd_cancel_download(void *cd) { static_cast(cd)->CancelDownload(); } +PR_EXPORT bool mcd_is_complete(void *cd) { return static_cast(cd)->IsComplete(); } +PR_EXPORT void mcd_set_error_handler(void *cd, const std::function &f) { static_cast(cd)->SetErrorHandler(reinterpret_cast &>(f)); } +PR_EXPORT void mcd_send_request(void *cd, const std::string &url, const std::unordered_map &post, const std::function &onComplete, const std::function &progressCallback) { RequestData requestData {}; requestData.SetPostKeyValues(post); @@ -320,6 +321,6 @@ PRAGMA_EXPORT void mcd_send_request(void *cd, const std::string &url, const std: requestData.progressCallback = progressCallback; static_cast(cd)->AddRequest(url, requestData); } -PRAGMA_EXPORT void mcd_code_to_string(int32_t code, std::string &outString) { outString = curl_easy_strerror(static_cast(code)); } -PRAGMA_EXPORT bool mcd_is_error_code(int32_t code) { return code != CURLE_OK; } +PR_EXPORT void mcd_code_to_string(int32_t code, std::string &outString) { outString = curl_easy_strerror(static_cast(code)); } +PR_EXPORT bool mcd_is_error_code(int32_t code) { return code != CURLE_OK; } }; diff --git a/src/lua_bindings.cpp b/src/implementation/lua_bindings.cpp similarity index 68% rename from src/lua_bindings.cpp rename to src/implementation/lua_bindings.cpp index 36057a1..7781a59 100644 --- a/src/lua_bindings.cpp +++ b/src/implementation/lua_bindings.cpp @@ -1,25 +1,17 @@ // SPDX-FileCopyrightText: (c) 2020 Silverlan // SPDX-License-Identifier: MIT -#include "curl_handler.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +module pragma.modules.curl; -class CurlRequest : public util::ParallelWorker { +import pragma.lua; + +class CurlRequest : public util::ParallelWorker { public: CurlRequest(const std::string &url, const RequestData &requestData); - virtual const DataStream &GetResult() override { return m_result; } + virtual const util::DataStream &GetResult() override { return m_result; } private: - DataStream m_result; + util::DataStream m_result; std::shared_ptr m_curlHandler = nullptr; }; @@ -29,7 +21,7 @@ CurlRequest::CurlRequest(const std::string &url, const RequestData &requestData) AddThread([this, url, requestData = std::move(requestData)]() mutable { std::atomic progress = 0.0; int32_t resultCode = -1; - DataStream result; + util::DataStream result; std::atomic complete = false; m_curlHandler->SetErrorHandler([](CurlHandler::ResultCode resultCode) { // TODO @@ -67,9 +59,7 @@ CurlRequest::CurlRequest(const std::string &url, const RequestData &requestData) }); } -#include - -static void add_request(lua_State *l, CurlHandler &curlHandler, const std::string &url, std::optional timeout) +static void add_request(lua::State *l, CurlHandler &curlHandler, const std::string &url, std::optional timeout) { std::unordered_map postValues {}; std::function &)> onComplete = [](int32_t code, const std::vector &result) mutable { @@ -94,19 +84,17 @@ static void add_request(lua_State *l, CurlHandler &curlHandler, const std::strin static void register_lua_library(Lua::Interface &l) { - /*{"create_instance",static_cast([](lua_State *l) -> int32_t { + /*{"create_instance",static_cast([](lua::State *l) -> int32_t { auto curlHandler = std::make_shared(); Lua::Push(l,curlHandler); return 1; })},*/ auto &modCurl = l.RegisterLibrary("curl"); - modCurl[luabind::def( - "request", +[](const std::string &url, const RequestData &requestData) -> util::ParallelJob { return util::create_parallel_job(url, std::move(requestData)); })]; + modCurl[luabind::def("request", +[](const std::string &url, const RequestData &requestData) -> util::ParallelJob { return util::create_parallel_job(url, std::move(requestData)); })]; auto classDefRequestData = luabind::class_("RequestData"); classDefRequestData.def(luabind::constructor<>()); - classDefRequestData.def( - "__tostring", +[]() -> std::string { return "RequestData"; }); + classDefRequestData.def("__tostring", +[]() -> std::string { return "RequestData"; }); classDefRequestData.def("SetPostKeyValues", &RequestData::SetPostKeyValues); classDefRequestData.def_readwrite("postData", &RequestData::postData); classDefRequestData.def_readwrite("headers", &RequestData::headers); @@ -115,8 +103,8 @@ static void register_lua_library(Lua::Interface &l) auto classDefCurl = luabind::class_("Instance"); #if 0 - classDefCurl.def("AddRequest",static_cast,luabind::function,luabind::function)>( - [](lua_State *l,CurlHandler &curlHandler,const std::string &url,luabind::table<> lPostValues,luabind::function lOnComplete,luabind::function lProgressCallback) { + classDefCurl.def("AddRequest",static_cast,luabind::function,luabind::function)>( + [](lua::State *l,CurlHandler &curlHandler,const std::string &url,luabind::table<> lPostValues,luabind::function lOnComplete,luabind::function lProgressCallback) { std::unordered_map postValues {}; for(auto it=luabind::iterator{lPostValues},end=luabind::iterator{};it!=end;++it) { @@ -140,14 +128,13 @@ static void register_lua_library(Lua::Interface &l) )); #endif classDefCurl.def("AddRequest", &add_request); - classDefCurl.def( - "AddRequest", +[](lua_State *l, CurlHandler &curlHandler, const std::string &url) { add_request(l, curlHandler, url, {}); }); - classDefCurl.def("StartDownload", static_cast([](lua_State *l, CurlHandler &curlHandler) { curlHandler.StartDownload(); })); - classDefCurl.def("CancelDownload", static_cast([](lua_State *l, CurlHandler &curlHandler) { curlHandler.CancelDownload(); })); - classDefCurl.def("CancelDownload", static_cast([](lua_State *l, CurlHandler &curlHandler) -> bool { return curlHandler.IsComplete(); })); + classDefCurl.def("AddRequest", +[](lua::State *l, CurlHandler &curlHandler, const std::string &url) { add_request(l, curlHandler, url, {}); }); + classDefCurl.def("StartDownload", static_cast([](lua::State *l, CurlHandler &curlHandler) { curlHandler.StartDownload(); })); + classDefCurl.def("CancelDownload", static_cast([](lua::State *l, CurlHandler &curlHandler) { curlHandler.CancelDownload(); })); + classDefCurl.def("CancelDownload", static_cast([](lua::State *l, CurlHandler &curlHandler) -> bool { return curlHandler.IsComplete(); })); modCurl[classDefCurl]; } extern "C" { -void PRAGMA_EXPORT pragma_initialize_lua(Lua::Interface &l) { register_lua_library(l); } +void PR_EXPORT pragma_initialize_lua(Lua::Interface &l) { register_lua_library(l); } }; diff --git a/src/implementation/module.cpp b/src/implementation/module.cpp new file mode 100644 index 0000000..a26ee02 --- /dev/null +++ b/src/implementation/module.cpp @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: (c) 2019 Silverlan +// SPDX-License-Identifier: MIT + +module; + +#include + +module pragma.modules.curl; + +extern "C" { + +PR_EXPORT bool wv_curl_download_file(const std::string &url, size_t (*fData)(void *, size_t, size_t, void *), void *userData, std::string &err) +{ + auto *curl = curl_easy_init(); + if(curl == nullptr) + return false; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fData); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, userData); + auto res = curl_easy_perform(curl); + if(res != CURLE_OK) + err = curl_easy_strerror(res); + curl_easy_cleanup(curl); + return true; +} +}; diff --git a/src/interface/curl_handler.cppm b/src/interface/curl_handler.cppm new file mode 100644 index 0000000..302393b --- /dev/null +++ b/src/interface/curl_handler.cppm @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: (c) 2019 Silverlan +// SPDX-License-Identifier: MIT + +export module pragma.modules.curl; + +export import std.compat; + +export { + struct RequestData { + RequestData() = default; + std::string postData; + std::vector headers; + std::optional timeoutMs {}; + std::function &)> onComplete; + std::function progressCallback; + + void SetPostKeyValues(const std::unordered_map &postValues); + }; + + class CurlHandler { + public: + enum class ResultCode : uint32_t { Ok = 0, BadHandle, BadEasyHandle, OutOfMemory, InternalError, BadSocket, UnknownOption, AddedAlready }; + CurlHandler(); + ~CurlHandler(); + void AddResource(const std::string &fname, const std::function &callback, const std::shared_ptr &userData = nullptr, const std::function &progressCallback = nullptr, + const std::function &onComplete = nullptr); + void AddRequest(const std::string &url, const RequestData &requestData = {}); + void StartDownload(); + void CancelDownload(); + bool IsComplete() const; + void SetErrorHandler(const std::function &f); + private: + void *m_multiCurl = nullptr; + + struct Request { + struct Header { + std::string fileName; + } header; + std::string url; + std::optional timeoutMs; + std::function writeCallback = nullptr; // Write Callback + std::function completeCallback = nullptr; + std::function progressCallback = nullptr; + std::shared_ptr userData = nullptr; + CurlHandler *curl = nullptr; + std::shared_ptr handle = nullptr; + std::shared_ptr headers = nullptr; + std::function request = nullptr; + }; + + std::queue> m_queuedRequests; + std::vector> m_activeRequests; + std::mutex m_resourceMutex; + std::mutex m_requestMutex; + std::unique_ptr m_thread = nullptr; + std::atomic m_bComplete = true; + std::atomic m_bCancel = false; + std::atomic m_bThreadActive = false; + std::function m_errorHandler = nullptr; + + void ProcessNextRequest(); + uint32_t ProcessAllRequests(); + + void AddRequest(const std::string &url, const std::function &writeCallback, const std::function &onComplete, const std::function &progressCallback, + const std::function &fRequest, std::optional timeout = {}); + static size_t ReceiveHeader(char *buffer, size_t size, size_t nitems, void *userdata); + static void InitializeCurl(void *curl, Request *request); + static size_t WriteData(void *ptr, size_t size, size_t nmemb, void *userData); + static int32_t UpdateProgress(void *clientp, int64_t dltotal, int64_t dlnow, int64_t ultotal, int64_t ulnow); + static std::string ResultCodeToString(ResultCode ec); + }; +} diff --git a/src/wvmodule.cpp b/src/wvmodule.cpp deleted file mode 100644 index 68e27fe..0000000 --- a/src/wvmodule.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: (c) 2019 Silverlan -// SPDX-License-Identifier: MIT - -#include -#include -#include -#include - - - -extern "C" { - -PRAGMA_EXPORT bool wv_curl_download_file(const std::string &url,size_t(*fData)(void*,size_t,size_t,void*),void *userData,std::string &err) -{ - auto *curl = curl_easy_init(); - if(curl == nullptr) - return false; - curl_easy_setopt(curl,CURLOPT_URL,url.c_str()); - curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,fData); - curl_easy_setopt(curl,CURLOPT_WRITEDATA,userData); - auto res = curl_easy_perform(curl); - if(res != CURLE_OK) - err = curl_easy_strerror(res); - curl_easy_cleanup(curl); - return true; -} - -};