2.0.0-rc (#9)
Some checks failed
BlockStorage/repertory_osx/pipeline/head This commit looks good
BlockStorage/repertory_windows/pipeline/head This commit looks good
BlockStorage/repertory/pipeline/head There was a failure building this commit
BlockStorage/repertory_linux_builds/pipeline/head This commit looks good
BlockStorage/repertory_osx_builds/pipeline/head There was a failure building this commit
Some checks failed
BlockStorage/repertory_osx/pipeline/head This commit looks good
BlockStorage/repertory_windows/pipeline/head This commit looks good
BlockStorage/repertory/pipeline/head There was a failure building this commit
BlockStorage/repertory_linux_builds/pipeline/head This commit looks good
BlockStorage/repertory_osx_builds/pipeline/head There was a failure building this commit
### Issues * \#1 \[bug\] Unable to mount S3 due to 'item_not_found' exception * \#2 Require bucket name for S3 mounts * \#3 \[bug\] File size is not being updated in S3 mount * \#4 Upgrade to libfuse-3.x.x * \#5 Switch to renterd for Sia support * \#6 Switch to cpp-httplib to further reduce dependencies * \#7 Remove global_data and calculate used disk space per provider * \#8 Switch to libcurl for S3 mount support ### Changes from v1.x.x * Added read-only encrypt provider * Pass-through mount point that transparently encrypts source data using `XChaCha20-Poly1305` * Added S3 encryption support via `XChaCha20-Poly1305` * Added replay protection to remote mounts * Added support base64 writes in remote FUSE * Created static linked Linux binaries for `amd64` and `aarch64` using `musl-libc` * Removed legacy Sia renter support * Removed Skynet support * Fixed multiple remote mount WinFSP API issues on \*NIX servers * Implemented chunked read and write * Writes for non-cached files are performed in chunks of 8Mib * Removed `repertory-ui` support * Removed `FreeBSD` support * Switched to `libsodium` over `CryptoPP` * Switched to `XChaCha20-Poly1305` for remote mounts * Updated `GoogleTest` to v1.14.0 * Updated `JSON for Modern C++` to v3.11.2 * Updated `OpenSSL` to v1.1.1w * Updated `RocksDB` to v8.5.3 * Updated `WinFSP` to 2023 * Updated `boost` to v1.78.0 * Updated `cURL` to v8.3.0 * Updated `zlib` to v1.3 * Use `upload_manager` for all providers * Adds a delay to uploads to prevent excessive API calls * Supports re-upload after mount restart for incomplete uploads * NOTE: Uploads for all providers are full file (no resume support) * Multipart upload support is planned for S3 Reviewed-on: #9
This commit is contained in:
@ -1,269 +1,231 @@
|
||||
/*
|
||||
Copyright <2018-2022> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_COMM_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_COMM_HPP_
|
||||
|
||||
#include "common.hpp"
|
||||
#include "comm/curl/multi_request.hpp"
|
||||
#include "comm/curl/session_manager.hpp"
|
||||
#include "comm/i_comm.hpp"
|
||||
#include "app_config.hpp"
|
||||
#include "comm/i_http_comm.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class curl_resolver;
|
||||
namespace utils::encryption {
|
||||
class encrypting_reader;
|
||||
}
|
||||
struct curl_setup;
|
||||
struct raw_write_data;
|
||||
|
||||
class curl_comm : public virtual i_comm {
|
||||
class curl_comm final : public i_http_comm {
|
||||
public:
|
||||
typedef size_t (*curl_read_callback)(char *, size_t, size_t, void *);
|
||||
typedef size_t (*curl_write_callback)(char *, size_t, size_t, void *);
|
||||
curl_comm() = delete;
|
||||
|
||||
static curl_read_callback read_data_callback_;
|
||||
static curl_write_callback write_data_callback_;
|
||||
static curl_write_callback write_header_callback_;
|
||||
static curl_write_callback write_null_callback_;
|
||||
static curl_write_callback write_string_callback_;
|
||||
explicit curl_comm(host_config hc);
|
||||
|
||||
public:
|
||||
explicit curl_comm(const app_config &config) : config_(config) {}
|
||||
|
||||
~curl_comm() override = default;
|
||||
explicit curl_comm(s3_config s3);
|
||||
|
||||
private:
|
||||
const app_config &config_;
|
||||
session_manager session_manager_;
|
||||
using write_callback = size_t (*)(char *, size_t, size_t, void *);
|
||||
|
||||
public:
|
||||
static std::string construct_url(CURL *curl_handle, const std::string &relative_path,
|
||||
const host_config &hc);
|
||||
struct read_write_info final {
|
||||
repertory::data_buffer data{};
|
||||
repertory::stop_type &stop_requested;
|
||||
};
|
||||
|
||||
static bool create_auth_session(CURL *&curl_handle, const app_config &config, host_config hc,
|
||||
std::string &session);
|
||||
|
||||
static std::string http_range_to_string(const http_range &range);
|
||||
|
||||
static void release_auth_session(const app_config &config, host_config hc,
|
||||
const std::string &session);
|
||||
|
||||
static void update_auth_session(CURL *curl_handle, const app_config &config,
|
||||
const std::string &session);
|
||||
static const write_callback write_data;
|
||||
static const write_callback write_headers;
|
||||
|
||||
private:
|
||||
CURL *common_curl_setup(const std::string &path, curl_setup &setup, std::string &url,
|
||||
std::string &fields);
|
||||
std::optional<host_config> host_config_;
|
||||
std::optional<s3_config> s3_config_;
|
||||
|
||||
CURL *common_curl_setup(CURL *curl_handle, const std::string &path, curl_setup &setup,
|
||||
std::string &url, std::string &fields);
|
||||
|
||||
template <typename begin, typename end>
|
||||
api_error execute_binary_operation(CURL *curl_handle, const std::string &url,
|
||||
std::vector<char> &data, json &error,
|
||||
const bool &stop_requested,
|
||||
const CURLcode &default_code = CURLE_OK) {
|
||||
auto curl_code = default_code;
|
||||
long http_code = 400;
|
||||
execute_operation<begin>(curl_handle, url, curl_code, http_code, stop_requested);
|
||||
|
||||
const auto ret = process_binary_response(url, curl_code, http_code, data, error);
|
||||
if (config_.get_event_level() >= end::level) {
|
||||
event_system::instance().raise<end>(url, curl_code, http_code,
|
||||
((ret == api_error::success) ? "" : error.dump(2)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename begin, typename end>
|
||||
api_error execute_json_operation(CURL *curl_handle, const std::string &url,
|
||||
const std::string &result, json &data, json &error,
|
||||
const bool &stop_requested,
|
||||
const CURLcode &default_code = CURLE_OK) {
|
||||
auto curl_code = default_code;
|
||||
long http_code = 400;
|
||||
execute_operation<begin>(curl_handle, url, curl_code, http_code, stop_requested);
|
||||
|
||||
const auto ret = process_json_response(url, curl_code, http_code, result, data, error);
|
||||
if (config_.get_event_level() >= end::level) {
|
||||
event_system::instance().raise<end>(url, curl_code, http_code,
|
||||
((ret == api_error::success) ? "" : error.dump(2)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename begin>
|
||||
void execute_operation(CURL *curl_handle, const std::string &url, CURLcode &curl_code,
|
||||
long &http_code, const bool &stop_requested) {
|
||||
if (config_.get_event_level() >= begin::level) {
|
||||
event_system::instance().raise<begin>(url);
|
||||
}
|
||||
|
||||
if (curl_code == CURLE_OK) {
|
||||
multi_request request(curl_handle, stop_requested);
|
||||
request.get_result(curl_code, http_code);
|
||||
}
|
||||
}
|
||||
|
||||
api_error get_or_post(const host_config &hc, const bool &post, const std::string &path,
|
||||
const http_parameters ¶meters, json &data, json &error,
|
||||
http_headers *headers = nullptr,
|
||||
std::function<void(CURL *curl_handle)> cb = nullptr);
|
||||
|
||||
api_error get_range(const host_config &hc, const std::string &path,
|
||||
const std::uint64_t &data_size, const http_parameters ¶meters,
|
||||
const std::string &encryption_token, std::vector<char> &data,
|
||||
const http_ranges &ranges, json &error, http_headers *headers,
|
||||
const bool &stop_requested);
|
||||
|
||||
api_error get_range_unencrypted(const host_config &hc, const std::string &path,
|
||||
const http_parameters ¶meters, std::vector<char> &data,
|
||||
const http_ranges &ranges, json &error, http_headers *headers,
|
||||
const bool &stop_requested);
|
||||
|
||||
api_error process_binary_response(const std::string &url, const CURLcode &res,
|
||||
const long &http_code, std::vector<char> data, json &error);
|
||||
|
||||
api_error process_json_response(const std::string &url, const CURLcode &res,
|
||||
const long &http_code, const std::string &result, json &data,
|
||||
json &error);
|
||||
|
||||
api_error process_response(const std::string &url, const CURLcode &res, const long &http_code,
|
||||
const std::size_t &data_size,
|
||||
const std::function<std::string()> &to_string_converter,
|
||||
const std::function<void()> &success_handler, json &error) const;
|
||||
|
||||
static std::string url_encode(CURL *curl_handle, const std::string &data,
|
||||
const bool &allow_slash = false);
|
||||
private:
|
||||
bool use_s3_path_style_{false};
|
||||
|
||||
public:
|
||||
api_error get(const std::string &path, json &data, json &error) override {
|
||||
return get_or_post(config_.get_host_config(), false, path, {}, data, error);
|
||||
[[nodiscard]] static auto construct_url(CURL *curl,
|
||||
const std::string &relative_path,
|
||||
const host_config &hc) -> std::string;
|
||||
|
||||
[[nodiscard]] static auto create_host_config(const s3_config &config,
|
||||
bool use_s3_path_style)
|
||||
-> host_config;
|
||||
|
||||
[[nodiscard]] static auto url_encode(CURL *curl, const std::string &data,
|
||||
bool allow_slash) -> std::string;
|
||||
|
||||
template <typename request_type>
|
||||
[[nodiscard]] static auto
|
||||
make_encrypted_request(const host_config &hc, const request_type &request,
|
||||
long &response_code, stop_type &stop_requested)
|
||||
-> bool {
|
||||
response_code = 0;
|
||||
|
||||
if (not request.decryption_token.has_value() ||
|
||||
request.decryption_token.value().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not request.range.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not request.total_size.has_value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data_buffer data{};
|
||||
const auto key =
|
||||
utils::encryption::generate_key(request.decryption_token.value());
|
||||
const auto result = utils::encryption::read_encrypted_range(
|
||||
request.range.value(), key,
|
||||
[&](std::vector<char> &ct, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> api_error {
|
||||
auto encrypted_request = request;
|
||||
encrypted_request.decryption_token = std::nullopt;
|
||||
encrypted_request.range = {{start_offset, end_offset}};
|
||||
encrypted_request.response_handler = [&ct](const auto &encrypted_data,
|
||||
long /*response_code*/) {
|
||||
ct = encrypted_data;
|
||||
};
|
||||
encrypted_request.total_size = std::nullopt;
|
||||
|
||||
if (not make_request(hc, encrypted_request, response_code,
|
||||
stop_requested)) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
if (response_code != 200) {
|
||||
return api_error::comm_error;
|
||||
}
|
||||
|
||||
return api_error::success;
|
||||
},
|
||||
request.total_size.value(), data);
|
||||
if (result != api_error::success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.response_handler.has_value()) {
|
||||
request.response_handler.value()(data, response_code);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
api_error get(const host_config &hc, const std::string &path, json &data, json &error) override {
|
||||
return get_or_post(hc, false, path, {}, data, error);
|
||||
template <typename request_type>
|
||||
[[nodiscard]] static auto
|
||||
make_request(const host_config &hc, const request_type &request,
|
||||
long &response_code, stop_type &stop_requested) -> bool {
|
||||
if (request.decryption_token.has_value() &&
|
||||
not request.decryption_token.value().empty()) {
|
||||
return make_encrypted_request(hc, request, response_code, stop_requested);
|
||||
}
|
||||
|
||||
response_code = 0;
|
||||
|
||||
auto *curl = utils::create_curl();
|
||||
if (not request.set_method(curl, stop_requested)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not hc.agent_string.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, hc.agent_string.c_str());
|
||||
}
|
||||
|
||||
if (request.allow_timeout && hc.timeout_ms) {
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, hc.timeout_ms);
|
||||
}
|
||||
|
||||
std::string range_list{};
|
||||
if (request.range.has_value()) {
|
||||
range_list = std::to_string(request.range.value().begin) + '-' +
|
||||
std::to_string(request.range.value().end);
|
||||
curl_easy_setopt(curl, CURLOPT_RANGE, range_list.c_str());
|
||||
}
|
||||
|
||||
if (request.response_headers.has_value()) {
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERDATA,
|
||||
&request.response_headers.value());
|
||||
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_headers);
|
||||
}
|
||||
|
||||
read_write_info write_info{{}, stop_requested};
|
||||
if (request.response_handler.has_value()) {
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_info);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
|
||||
}
|
||||
|
||||
std::string parameters{};
|
||||
for (const auto &kv : request.query) {
|
||||
parameters += (parameters.empty() ? '?' : '&') + kv.first + '=' +
|
||||
url_encode(curl, kv.second, false);
|
||||
}
|
||||
|
||||
if (not hc.api_password.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, hc.api_user.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_PASSWORD, hc.api_password.c_str());
|
||||
} else if (not hc.api_user.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_USERNAME, hc.api_user.c_str());
|
||||
}
|
||||
|
||||
if (request.aws_service.has_value()) {
|
||||
curl_easy_setopt(curl, CURLOPT_AWS_SIGV4,
|
||||
request.aws_service.value().c_str());
|
||||
}
|
||||
|
||||
auto url = construct_url(curl, request.get_path(), hc) + parameters;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
|
||||
multi_request curl_request(curl, stop_requested);
|
||||
|
||||
CURLcode curl_code{};
|
||||
curl_request.get_result(curl_code, response_code);
|
||||
if (curl_code != CURLE_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.response_handler.has_value()) {
|
||||
request.response_handler.value()(write_info.data, response_code);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
api_error get(const std::string &path, const http_parameters ¶meters, json &data,
|
||||
json &error) override {
|
||||
return get_or_post(config_.get_host_config(), false, path, parameters, data, error);
|
||||
}
|
||||
public:
|
||||
void enable_s3_path_style(bool enable) override;
|
||||
|
||||
api_error get(const host_config &hc, const std::string &path, const http_parameters ¶meters,
|
||||
json &data, json &error) override {
|
||||
return get_or_post(hc, false, path, parameters, data, error);
|
||||
}
|
||||
[[nodiscard]] auto make_request(const curl::requests::http_delete &del,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
|
||||
api_error get_range(const std::string &path, const std::uint64_t &data_size,
|
||||
const http_parameters ¶meters, const std::string &encryption_token,
|
||||
std::vector<char> &data, const http_ranges &ranges, json &error,
|
||||
const bool &stop_requested) override {
|
||||
return get_range(config_.get_host_config(), path, data_size, parameters, encryption_token, data,
|
||||
ranges, error, nullptr, stop_requested);
|
||||
}
|
||||
[[nodiscard]] auto make_request(const curl::requests::http_get &get,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
|
||||
api_error get_range(const host_config &hc, const std::string &path,
|
||||
const std::uint64_t &data_size, const http_parameters ¶meters,
|
||||
const std::string &encryption_token, std::vector<char> &data,
|
||||
const http_ranges &ranges, json &error, const bool &stop_requested) override {
|
||||
return get_range(hc, path, data_size, parameters, encryption_token, data, ranges, error,
|
||||
nullptr, stop_requested);
|
||||
}
|
||||
[[nodiscard]] auto make_request(const curl::requests::http_head &head,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
|
||||
api_error get_range_and_headers(const std::string &path, const std::uint64_t &dataSize,
|
||||
const http_parameters ¶meters,
|
||||
const std::string &encryption_token, std::vector<char> &data,
|
||||
const http_ranges &ranges, json &error, http_headers &headers,
|
||||
const bool &stop_requested) override {
|
||||
return get_range(config_.get_host_config(), path, dataSize, parameters, encryption_token, data,
|
||||
ranges, error, &headers, stop_requested);
|
||||
}
|
||||
|
||||
api_error get_range_and_headers(const host_config &hc, const std::string &path,
|
||||
const std::uint64_t &dataSize, const http_parameters ¶meters,
|
||||
const std::string &encryption_token, std::vector<char> &data,
|
||||
const http_ranges &ranges, json &error, http_headers &headers,
|
||||
const bool &stop_requested) override {
|
||||
return get_range(hc, path, dataSize, parameters, encryption_token, data, ranges, error,
|
||||
&headers, stop_requested);
|
||||
}
|
||||
|
||||
api_error get_raw(const std::string &path, const http_parameters ¶meters,
|
||||
std::vector<char> &data, json &error, const bool &stop_requested) override {
|
||||
return get_raw(config_.get_host_config(), path, parameters, data, error, stop_requested);
|
||||
}
|
||||
|
||||
api_error get_raw(const host_config &hc, const std::string &path,
|
||||
const http_parameters ¶meters, std::vector<char> &data, json &error,
|
||||
const bool &stop_requested) override;
|
||||
|
||||
api_error post(const std::string &path, json &data, json &error) override {
|
||||
return get_or_post(config_.get_host_config(), true, path, {}, data, error);
|
||||
}
|
||||
|
||||
api_error post(const host_config &hc, const std::string &path, json &data, json &error) override {
|
||||
return get_or_post(hc, true, path, {}, data, error);
|
||||
}
|
||||
|
||||
api_error post(const std::string &path, const http_parameters ¶meters, json &data,
|
||||
json &error) override {
|
||||
return get_or_post(config_.get_host_config(), true, path, parameters, data, error);
|
||||
}
|
||||
|
||||
api_error post(const host_config &hc, const std::string &path, const http_parameters ¶meters,
|
||||
json &data, json &error) override {
|
||||
return get_or_post(hc, true, path, parameters, data, error);
|
||||
}
|
||||
|
||||
api_error post_file(const std::string &path, const std::string &source_path,
|
||||
const http_parameters ¶meters, json &data, json &error,
|
||||
const bool &stop_requested) override {
|
||||
return post_file(config_.get_host_config(), path, source_path, parameters, data, error,
|
||||
stop_requested);
|
||||
}
|
||||
|
||||
api_error post_file(const host_config &hc, const std::string &path,
|
||||
const std::string &source_path, const http_parameters ¶meters, json &data,
|
||||
json &error, const bool &stop_requested) override;
|
||||
|
||||
api_error post_multipart_file(const std::string &path, const std::string &file_name,
|
||||
const std::string &source_path, const std::string &encryption_token,
|
||||
json &data, json &error, const bool &stop_requested) override {
|
||||
return post_multipart_file(config_.get_host_config(), path, file_name, source_path,
|
||||
encryption_token, data, error, stop_requested);
|
||||
}
|
||||
|
||||
api_error post_multipart_file(const host_config &hc, const std::string &path,
|
||||
const std::string &file_name, const std::string &source_path,
|
||||
const std::string &encryption_token, json &data, json &error,
|
||||
const bool &stop_requested) override;
|
||||
|
||||
bool tus_upload(host_config hc, const std::string &source_path, const std::string &file_name,
|
||||
std::uint64_t file_size, const std::string &location, std::string &skylink,
|
||||
const bool &stop_requested, utils::encryption::encrypting_reader *reader);
|
||||
|
||||
bool tus_upload_create(host_config hc, const std::string &file_name,
|
||||
const std::uint64_t &file_size, std::string &location);
|
||||
[[nodiscard]] auto make_request(const curl::requests::http_put_file &put_file,
|
||||
long &response_code,
|
||||
stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2022> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_RESOLVER_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_RESOLVER_HPP_
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class curl_resolver final {
|
||||
public:
|
||||
curl_resolver() = delete;
|
||||
curl_resolver(const curl_resolver &) noexcept = delete;
|
||||
curl_resolver(curl_resolver &&) noexcept = delete;
|
||||
curl_resolver &operator=(const curl_resolver &) noexcept = delete;
|
||||
curl_resolver &operator=(curl_resolver &&) noexcept = delete;
|
||||
|
||||
public:
|
||||
curl_resolver(CURL *handle, std::vector<std::string> items, const bool &ignore_root = false);
|
||||
|
||||
~curl_resolver();
|
||||
|
||||
private:
|
||||
std::vector<std::string> items_;
|
||||
|
||||
struct curl_slist *host_list_ = nullptr;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_RESOLVER_HPP_
|
@ -1,36 +1,39 @@
|
||||
/*
|
||||
Copyright <2018-2022> <scott.e.graves@protonmail.com>
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_MULTI_REQUEST_HPP_
|
||||
#define INCLUDE_COMM_CURL_MULTI_REQUEST_HPP_
|
||||
|
||||
#include "common.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class multi_request final {
|
||||
public:
|
||||
multi_request(CURL *curl_handle, const bool &stop_requested);
|
||||
multi_request(CURL *curl_handle, stop_type &stop_requested);
|
||||
|
||||
~multi_request();
|
||||
|
||||
private:
|
||||
CURL *curl_handle_;
|
||||
const bool &stop_requested_;
|
||||
stop_type &stop_requested_;
|
||||
CURLM *multi_handle_;
|
||||
|
||||
public:
|
||||
|
40
include/comm/curl/requests/http_delete.hpp
Normal file
40
include/comm/curl/requests/http_delete.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_DELETE_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_DELETE_HPP_
|
||||
|
||||
#include "comm/curl/requests/http_request_base.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_delete final : http_request_base {
|
||||
~http_delete() override = default;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl,
|
||||
stop_type & /* stop_requested */) const
|
||||
-> bool override {
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace repertory::curl::requests
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_DELETE_HPP_
|
40
include/comm/curl/requests/http_get.hpp
Normal file
40
include/comm/curl/requests/http_get.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_GET_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_GET_HPP_
|
||||
|
||||
#include "comm/curl/requests/http_request_base.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_get final : http_request_base {
|
||||
~http_get() override = default;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl,
|
||||
stop_type & /*stop_requested*/) const
|
||||
-> bool override {
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace repertory::curl::requests
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_GET_HPP_
|
41
include/comm/curl/requests/http_head.hpp
Normal file
41
include/comm/curl/requests/http_head.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_HEAD_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_HEAD_HPP_
|
||||
|
||||
#include "comm/curl/requests/http_request_base.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_head final : http_request_base {
|
||||
~http_head() override = default;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl,
|
||||
stop_type & /* stop_requested */) const
|
||||
-> bool override {
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace repertory::curl::requests
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_HEAD_HPP_
|
47
include/comm/curl/requests/http_put_file.hpp
Normal file
47
include/comm/curl/requests/http_put_file.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_PUT_FILE_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_PUT_FILE_HPP_
|
||||
|
||||
#include "comm/curl/requests/http_request_base.hpp"
|
||||
#include "utils/encrypting_reader.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
struct http_put_file final : http_request_base {
|
||||
~http_put_file() override = default;
|
||||
|
||||
std::optional<std::string> encryption_token{};
|
||||
std::string file_name{};
|
||||
mutable std::shared_ptr<utils::encryption::encrypting_reader> reader{};
|
||||
std::string source_path{};
|
||||
|
||||
[[nodiscard]] auto get_path() const -> std::string override;
|
||||
|
||||
[[nodiscard]] auto set_method(CURL *curl, stop_type &stop_requested) const
|
||||
-> bool override;
|
||||
|
||||
private:
|
||||
mutable std::shared_ptr<read_file_info> read_info{};
|
||||
};
|
||||
} // namespace repertory::curl::requests
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_PUT_FILE_HPP_
|
74
include/comm/curl/requests/http_request_base.hpp
Normal file
74
include/comm/curl/requests/http_request_base.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright <2018-2023> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_
|
||||
#define INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/native_file.hpp"
|
||||
|
||||
namespace repertory::curl::requests {
|
||||
using read_callback = size_t (*)(char *, size_t, size_t, void *);
|
||||
|
||||
using response_callback =
|
||||
std::function<void(const data_buffer &data, long response_code)>;
|
||||
|
||||
struct read_file_info final {
|
||||
stop_type &stop_requested;
|
||||
native_file::native_file_ptr nf{};
|
||||
std::uint64_t offset{};
|
||||
};
|
||||
|
||||
inline const auto read_file_data = static_cast<read_callback>(
|
||||
[](char *buffer, size_t size, size_t nitems, void *instream) -> size_t {
|
||||
auto *rd = reinterpret_cast<read_file_info *>(instream);
|
||||
std::size_t bytes_read{};
|
||||
auto ret =
|
||||
rd->nf->read_bytes(buffer, size * nitems, rd->offset, bytes_read);
|
||||
if (ret) {
|
||||
rd->offset += bytes_read;
|
||||
}
|
||||
return ret && not rd->stop_requested ? bytes_read : CURL_READFUNC_ABORT;
|
||||
});
|
||||
|
||||
struct http_request_base {
|
||||
virtual ~http_request_base() = default;
|
||||
|
||||
bool allow_timeout{};
|
||||
std::optional<std::string> aws_service;
|
||||
std::optional<std::string> decryption_token{};
|
||||
http_headers headers{};
|
||||
std::string path{};
|
||||
query_parameters query{};
|
||||
std::optional<http_range> range{};
|
||||
std::optional<response_callback> response_handler;
|
||||
std::optional<http_headers> response_headers;
|
||||
std::optional<std::uint64_t> total_size{};
|
||||
|
||||
[[nodiscard]] virtual auto get_path() const -> std::string { return path; }
|
||||
|
||||
[[nodiscard]] virtual auto set_method(CURL *curl,
|
||||
stop_type &stop_requested) const
|
||||
-> bool = 0;
|
||||
};
|
||||
} // namespace repertory::curl::requests
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_CURL_REQUESTS_HTTP_REQUEST_BASE_HPP_
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2022> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef INCLUDE_COMM_CURL_SESSION_MANAGER_HPP_
|
||||
#define INCLUDE_COMM_CURL_SESSION_MANAGER_HPP_
|
||||
|
||||
#include "common.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
class session_manager final {
|
||||
private:
|
||||
std::string session_;
|
||||
std::uint64_t session_count_ = 0u;
|
||||
std::mutex session_mutex_;
|
||||
|
||||
public:
|
||||
bool create_auth_session(CURL *&curl_handle, const app_config &config, host_config hc,
|
||||
std::string &session);
|
||||
|
||||
void release_auth_session(const app_config &config, host_config hc, const std::string &session);
|
||||
|
||||
void update_auth_session(CURL *curl_handle, const app_config &config, const host_config &hc);
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // INCLUDE_COMM_CURL_SESSION_MANAGER_HPP_
|
Reference in New Issue
Block a user