Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
84 changes: 0 additions & 84 deletions include/curl_handler.hpp

This file was deleted.

9 changes: 0 additions & 9 deletions include/wvmodule.hpp

This file was deleted.

27 changes: 14 additions & 13 deletions src/curl_handler.cpp → src/implementation/curl_handler.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// SPDX-FileCopyrightText: (c) 2019 Silverlan <opensource@pragma-engine.com>
// SPDX-License-Identifier: MIT

#include "curl_handler.hpp"
module;

#include <curl/curl.h>
#include <pragma/pragma_module.hpp>
#include <cstring>

module pragma.modules.curl;

CurlHandler::CurlHandler() {}

Expand Down Expand Up @@ -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<CurlHandler *>(cd); }
PRAGMA_EXPORT void mcd_add_resource(void *cd, const std::string &fname, const std::function<size_t(void *, size_t, size_t)> &callback, const std::shared_ptr<void> &userData, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback,
PR_EXPORT void *mcd_create() { return new CurlHandler(); }
PR_EXPORT void mcd_release(void *cd) { delete static_cast<CurlHandler *>(cd); }
PR_EXPORT void mcd_add_resource(void *cd, const std::string &fname, const std::function<size_t(void *, size_t, size_t)> &callback, const std::shared_ptr<void> &userData, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback,
const std::function<void(int32_t)> &onComplete)
{
static_cast<CurlHandler *>(cd)->AddResource(fname, callback, userData, progressCallback, onComplete);
}
PRAGMA_EXPORT void mcd_start_download(void *cd) { static_cast<CurlHandler *>(cd)->StartDownload(); }
PRAGMA_EXPORT void mcd_cancel_download(void *cd) { static_cast<CurlHandler *>(cd)->CancelDownload(); }
PRAGMA_EXPORT bool mcd_is_complete(void *cd) { return static_cast<CurlHandler *>(cd)->IsComplete(); }
PRAGMA_EXPORT void mcd_set_error_handler(void *cd, const std::function<void(uint32_t)> &f) { static_cast<CurlHandler *>(cd)->SetErrorHandler(reinterpret_cast<const std::function<void(CurlHandler::ResultCode)> &>(f)); }
PRAGMA_EXPORT void mcd_send_request(void *cd, const std::string &url, const std::unordered_map<std::string, std::string> &post, const std::function<void(int32_t, const std::string &)> &onComplete, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback)
PR_EXPORT void mcd_start_download(void *cd) { static_cast<CurlHandler *>(cd)->StartDownload(); }
PR_EXPORT void mcd_cancel_download(void *cd) { static_cast<CurlHandler *>(cd)->CancelDownload(); }
PR_EXPORT bool mcd_is_complete(void *cd) { return static_cast<CurlHandler *>(cd)->IsComplete(); }
PR_EXPORT void mcd_set_error_handler(void *cd, const std::function<void(uint32_t)> &f) { static_cast<CurlHandler *>(cd)->SetErrorHandler(reinterpret_cast<const std::function<void(CurlHandler::ResultCode)> &>(f)); }
PR_EXPORT void mcd_send_request(void *cd, const std::string &url, const std::unordered_map<std::string, std::string> &post, const std::function<void(int32_t, const std::string &)> &onComplete, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback)
{
RequestData requestData {};
requestData.SetPostKeyValues(post);
Expand All @@ -320,6 +321,6 @@ PRAGMA_EXPORT void mcd_send_request(void *cd, const std::string &url, const std:
requestData.progressCallback = progressCallback;
static_cast<CurlHandler *>(cd)->AddRequest(url, requestData);
}
PRAGMA_EXPORT void mcd_code_to_string(int32_t code, std::string &outString) { outString = curl_easy_strerror(static_cast<CURLcode>(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<CURLcode>(code)); }
PR_EXPORT bool mcd_is_error_code(int32_t code) { return code != CURLE_OK; }
};
49 changes: 18 additions & 31 deletions src/lua_bindings.cpp → src/implementation/lua_bindings.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
// SPDX-FileCopyrightText: (c) 2020 Silverlan <opensource@pragma-engine.com>
// SPDX-License-Identifier: MIT

#include "curl_handler.hpp"
#include <luainterface.hpp>
#include <luasystem.h>
#include <pragma/engine.h>
#include <pragma/pragma_module.hpp>
#include <pragma/lua/ldefinitions.h>
#include <pragma/lua/libraries/lfile.h>
#include <pragma/lua/converters/vector_converter_t.hpp>
#include <pragma/lua/converters/optional_converter_t.hpp>
#include <sharedutils/util_parallel_job.hpp>
#include <sharedutils/datastream.h>
module pragma.modules.curl;

class CurlRequest : public util::ParallelWorker<const DataStream &> {
import pragma.lua;

class CurlRequest : public util::ParallelWorker<const util::DataStream &> {
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<CurlHandler> m_curlHandler = nullptr;
};

Expand All @@ -29,7 +21,7 @@ CurlRequest::CurlRequest(const std::string &url, const RequestData &requestData)
AddThread([this, url, requestData = std::move(requestData)]() mutable {
std::atomic<double> progress = 0.0;
int32_t resultCode = -1;
DataStream result;
util::DataStream result;
std::atomic<bool> complete = false;
m_curlHandler->SetErrorHandler([](CurlHandler::ResultCode resultCode) {
// TODO
Expand Down Expand Up @@ -67,9 +59,7 @@ CurlRequest::CurlRequest(const std::string &url, const RequestData &requestData)
});
}

#include <iostream>

static void add_request(lua_State *l, CurlHandler &curlHandler, const std::string &url, std::optional<size_t> timeout)
static void add_request(lua::State *l, CurlHandler &curlHandler, const std::string &url, std::optional<size_t> timeout)
{
std::unordered_map<std::string, std::string> postValues {};
std::function<void(int32_t, const std::vector<uint8_t> &)> onComplete = [](int32_t code, const std::vector<uint8_t> &result) mutable {
Expand All @@ -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<int32_t(*)(lua_State*)>([](lua_State *l) -> int32_t {
/*{"create_instance",static_cast<int32_t(*)(lua::State*)>([](lua::State *l) -> int32_t {
auto curlHandler = std::make_shared<CurlHandler>();
Lua::Push(l,curlHandler);
return 1;
})},*/
auto &modCurl = l.RegisterLibrary("curl");
modCurl[luabind::def(
"request", +[](const std::string &url, const RequestData &requestData) -> util::ParallelJob<const DataStream &> { return util::create_parallel_job<CurlRequest>(url, std::move(requestData)); })];
modCurl[luabind::def("request", +[](const std::string &url, const RequestData &requestData) -> util::ParallelJob<const util::DataStream &> { return util::create_parallel_job<CurlRequest>(url, std::move(requestData)); })];

auto classDefRequestData = luabind::class_<RequestData>("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);
Expand All @@ -115,8 +103,8 @@ static void register_lua_library(Lua::Interface &l)

auto classDefCurl = luabind::class_<CurlHandler>("Instance");
#if 0
classDefCurl.def("AddRequest",static_cast<void(*)(lua_State*,CurlHandler&,const std::string&,luabind::table<>,luabind::function<void>,luabind::function<void>)>(
[](lua_State *l,CurlHandler &curlHandler,const std::string &url,luabind::table<> lPostValues,luabind::function<void> lOnComplete,luabind::function<void> lProgressCallback) {
classDefCurl.def("AddRequest",static_cast<void(*)(lua::State*,CurlHandler&,const std::string&,luabind::table<>,luabind::function<void>,luabind::function<void>)>(
[](lua::State *l,CurlHandler &curlHandler,const std::string &url,luabind::table<> lPostValues,luabind::function<void> lOnComplete,luabind::function<void> lProgressCallback) {
std::unordered_map<std::string,std::string> postValues {};
for(auto it=luabind::iterator{lPostValues},end=luabind::iterator{};it!=end;++it)
{
Expand All @@ -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<void (*)(lua_State *, CurlHandler &)>([](lua_State *l, CurlHandler &curlHandler) { curlHandler.StartDownload(); }));
classDefCurl.def("CancelDownload", static_cast<void (*)(lua_State *, CurlHandler &)>([](lua_State *l, CurlHandler &curlHandler) { curlHandler.CancelDownload(); }));
classDefCurl.def("CancelDownload", static_cast<bool (*)(lua_State *, CurlHandler &)>([](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<void (*)(lua::State *, CurlHandler &)>([](lua::State *l, CurlHandler &curlHandler) { curlHandler.StartDownload(); }));
classDefCurl.def("CancelDownload", static_cast<void (*)(lua::State *, CurlHandler &)>([](lua::State *l, CurlHandler &curlHandler) { curlHandler.CancelDownload(); }));
classDefCurl.def("CancelDownload", static_cast<bool (*)(lua::State *, CurlHandler &)>([](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); }
};
26 changes: 26 additions & 0 deletions src/implementation/module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-FileCopyrightText: (c) 2019 Silverlan <opensource@pragma-engine.com>
// SPDX-License-Identifier: MIT

module;

#include <curl/curl.h>

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;
}
};
72 changes: 72 additions & 0 deletions src/interface/curl_handler.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: (c) 2019 Silverlan <opensource@pragma-engine.com>
// SPDX-License-Identifier: MIT

export module pragma.modules.curl;

export import std.compat;

export {
struct RequestData {
RequestData() = default;
std::string postData;
std::vector<std::string> headers;
std::optional<size_t> timeoutMs {};
std::function<void(int32_t, const std::vector<uint8_t> &)> onComplete;
std::function<void(int64_t, int64_t, int64_t, int64_t)> progressCallback;

void SetPostKeyValues(const std::unordered_map<std::string, std::string> &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<size_t(void *, size_t, size_t)> &callback, const std::shared_ptr<void> &userData = nullptr, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback = nullptr,
const std::function<void(int32_t)> &onComplete = nullptr);
void AddRequest(const std::string &url, const RequestData &requestData = {});
void StartDownload();
void CancelDownload();
bool IsComplete() const;
void SetErrorHandler(const std::function<void(ResultCode)> &f);
private:
void *m_multiCurl = nullptr;

struct Request {
struct Header {
std::string fileName;
} header;
std::string url;
std::optional<std::chrono::milliseconds> timeoutMs;
std::function<size_t(void *, size_t, size_t)> writeCallback = nullptr; // Write Callback
std::function<void(Request &, int32_t)> completeCallback = nullptr;
std::function<void(int64_t, int64_t, int64_t, int64_t)> progressCallback = nullptr;
std::shared_ptr<void> userData = nullptr;
CurlHandler *curl = nullptr;
std::shared_ptr<void> handle = nullptr;
std::shared_ptr<void> headers = nullptr;
std::function<void(void *)> request = nullptr;
};

std::queue<std::shared_ptr<Request>> m_queuedRequests;
std::vector<std::shared_ptr<Request>> m_activeRequests;
std::mutex m_resourceMutex;
std::mutex m_requestMutex;
std::unique_ptr<std::thread> m_thread = nullptr;
std::atomic<bool> m_bComplete = true;
std::atomic<bool> m_bCancel = false;
std::atomic<bool> m_bThreadActive = false;
std::function<void(ResultCode)> m_errorHandler = nullptr;

void ProcessNextRequest();
uint32_t ProcessAllRequests();

void AddRequest(const std::string &url, const std::function<size_t(void *, size_t, size_t)> &writeCallback, const std::function<void(int32_t, const std::string &)> &onComplete, const std::function<void(int64_t, int64_t, int64_t, int64_t)> &progressCallback,
const std::function<void(Request *, void *)> &fRequest, std::optional<std::chrono::milliseconds> 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);
};
}
28 changes: 0 additions & 28 deletions src/wvmodule.cpp

This file was deleted.

Loading