Add base PROXY support implementation
This commit is contained in:
parent
af64f8e9e3
commit
cd65d742a5
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <rublon/bits.hpp>
|
||||
#include <rublon/core_handler.hpp>
|
||||
#include <rublon/curl.hpp>
|
||||
@ -13,10 +14,16 @@
|
||||
|
||||
namespace rublon {
|
||||
|
||||
struct closefile_deleter {
|
||||
void operator()(FILE * f) const {
|
||||
pclose(f);
|
||||
}
|
||||
};
|
||||
|
||||
std::string exec(const char * cmd) {
|
||||
std::array< char, 128 > buffer;
|
||||
std::string result;
|
||||
std::unique_ptr< FILE, decltype(&pclose) > pipe(popen(cmd, "r"), pclose);
|
||||
std::unique_ptr< FILE, closefile_deleter > pipe(popen(cmd, "r"));
|
||||
if(!pipe) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -28,6 +28,14 @@ class Configuration {
|
||||
bool autopushPrompt{};
|
||||
FailMode failMode{};
|
||||
bool nonInteractiveMode{};
|
||||
|
||||
StaticString< 8 > proxyType{};
|
||||
StaticString< 4096 > proxyServer{};
|
||||
StaticString< 256 > proxyUsername{};
|
||||
StaticString< 256 > proxyPass{};
|
||||
int proxyPort{};
|
||||
bool proxyAuthRequired{};
|
||||
bool proxyEnabled{};
|
||||
};
|
||||
|
||||
namespace {
|
||||
@ -139,7 +147,7 @@ constexpr auto make_entry(const char * name, const char * defaultValue) {
|
||||
return Entry{name, defaultValue, Entry::make_read_function< member >()};
|
||||
}
|
||||
|
||||
constexpr static inline std::array< Entry, 9 > configurationVariables = { //
|
||||
constexpr static inline std::array< Entry, 16 > configurationVariables = {
|
||||
make_entry< &Configuration::logging >("logging", "true"),
|
||||
make_entry< &Configuration::systemToken >("systemToken", nullptr),
|
||||
make_entry< &Configuration::secretKey >("secretKey", nullptr),
|
||||
@ -148,7 +156,15 @@ constexpr static inline std::array< Entry, 9 > configurationVariables = { //
|
||||
make_entry< &Configuration::enablePasswdEmail >("enablePasswdEmail", "true"),
|
||||
make_entry< &Configuration::autopushPrompt >("autopushPrompt", "false"),
|
||||
make_entry< &Configuration::failMode >("failMode", "deny"),
|
||||
make_entry< &Configuration::nonInteractiveMode >("nonInteractiveMode", "false")
|
||||
make_entry< &Configuration::nonInteractiveMode >("nonInteractiveMode", "false"),
|
||||
|
||||
make_entry< &Configuration::proxyType >("proxyType", nullptr),
|
||||
make_entry< &Configuration::proxyServer >("proxyServer", nullptr),
|
||||
make_entry< &Configuration::proxyUsername >("proxyUsername", nullptr),
|
||||
make_entry< &Configuration::proxyPass >("proxyPass", nullptr),
|
||||
make_entry< &Configuration::proxyPort >("proxyPort", "8080"),
|
||||
make_entry< &Configuration::proxyAuthRequired >("proxyAuthRequired", "false"),
|
||||
make_entry< &Configuration::proxyEnabled >("proxyEnabled", "false") //
|
||||
};
|
||||
|
||||
class ConfigurationFactory {
|
||||
@ -156,7 +172,7 @@ class ConfigurationFactory {
|
||||
ConfigurationFactory() = default;
|
||||
|
||||
std::optional< Configuration > systemConfig() {
|
||||
memory::MonotonicStackResource< 8 * 1024 > stackResource;
|
||||
memory::MonotonicStackResource< 16 * 1024 > stackResource;
|
||||
Configuration configuration{};
|
||||
|
||||
std::ifstream file(std::filesystem::path{"/etc/rublon.config"});
|
||||
|
||||
@ -73,7 +73,7 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > {
|
||||
|
||||
public:
|
||||
CoreHandler() = delete;
|
||||
CoreHandler(const Configuration & config) : _config{config}, _ws{std::make_unique<WebSocket>(_config.apiServer)}, http{} {
|
||||
CoreHandler(const Configuration & config) : _config{config}, _ws{std::make_unique<WebSocket>(_config.apiServer)}, http{_config} {
|
||||
log(LogLevel::Debug, "Core Handler apiServer: %s", _config.apiServer.c_str());
|
||||
}
|
||||
CoreHandler(CoreHandler &&) noexcept = default;
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "rublon/memory.hpp"
|
||||
#include <rublon/error.hpp>
|
||||
#include <rublon/utils.hpp>
|
||||
#include <rublon/configuration.hpp>
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
@ -51,22 +53,59 @@ struct Response {
|
||||
|
||||
class CURL {
|
||||
std::unique_ptr< ::CURL, void (*)(::CURL *) > curl;
|
||||
|
||||
const Configuration &_config;
|
||||
public:
|
||||
CURL() : curl{std::unique_ptr< ::CURL, void (*)(::CURL *) >(curl_easy_init(), curl_easy_cleanup)} {}
|
||||
CURL(const Configuration &config) : curl{std::unique_ptr< ::CURL, void (*)(::CURL *) >(curl_easy_init(), curl_easy_cleanup)}, _config{config} {}
|
||||
|
||||
tl::expected< std::reference_wrapper< Response >, ConnectionError >
|
||||
request(std::string_view uri, const Request & request, Response & response) const {
|
||||
memory::MonotonicStackResource< 4 * 1024 > stackResource;
|
||||
using namespace memory::literals;
|
||||
memory::Monotonic_16k_HeapResource memoryResource;
|
||||
|
||||
std::pmr::string response_data{&stackResource};
|
||||
response_data.reserve(3000);
|
||||
std::pmr::string response_data{&memoryResource};
|
||||
response_data.reserve(4_kB);
|
||||
|
||||
auto curl_headers = std::unique_ptr< curl_slist, void (*)(curl_slist *) >(nullptr, curl_slist_free_all);
|
||||
std::for_each(request.headers.begin(), request.headers.end(), [&](auto header) {
|
||||
log(LogLevel::Debug, "%s header: %s: %s", "CURL", header.first.c_str(), header.second.c_str());
|
||||
curl_headers.reset(curl_slist_append(curl_headers.release(), (header.first + ": " + header.second).c_str()));
|
||||
});
|
||||
|
||||
// Optional: Build full proxy URL if proxy is enabled
|
||||
if (_config.proxyEnabled) {
|
||||
std::pmr::string proxyUrl{&memoryResource};
|
||||
proxyUrl.reserve(4_kB);
|
||||
|
||||
if (_config.proxyType == "http" || _config.proxyType == "https" || _config.proxyType == "socks4" || _config.proxyType == "socks5") {
|
||||
proxyUrl = _config.proxyType.c_str();
|
||||
proxyUrl += "://";
|
||||
proxyUrl += _config.proxyServer.c_str();
|
||||
if (_config.proxyPort > 0) {
|
||||
proxyUrl += ":";
|
||||
proxyUrl += std::to_string(_config.proxyPort);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_PROXY, proxyUrl.c_str());
|
||||
|
||||
if (_config.proxyType == "socks4") {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
|
||||
} else if (_config.proxyType == "socks5") {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
|
||||
} else {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
}
|
||||
|
||||
if (_config.proxyAuthRequired) {
|
||||
std::pmr::string proxyAuth{&memoryResource};
|
||||
proxyAuth.reserve(1_kB);
|
||||
_config.proxyUsername.c_str();
|
||||
proxyAuth += ":";
|
||||
proxyAuth += _config.proxyPass.c_str();
|
||||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_PROXYUSERPWD, proxyAuth.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_VERBOSE, 0);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, uri.data());
|
||||
|
||||
@ -4,6 +4,13 @@
|
||||
|
||||
namespace rublon {
|
||||
namespace memory {
|
||||
|
||||
namespace literals{
|
||||
constexpr std::uint64_t operator"" _kB(unsigned long long kilobytes) {
|
||||
return kilobytes * 1024ULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct default_memory_resource {
|
||||
static inline std::pmr::memory_resource * _mr = std::pmr::get_default_resource();
|
||||
};
|
||||
@ -58,11 +65,15 @@ namespace memory {
|
||||
using StrictMonotonic_2k_HeapResource = StrictMonotonicHeapResource< 2 * 1024 >;
|
||||
using StrictMonotonic_4k_HeapResource = StrictMonotonicHeapResource< 4 * 1024 >;
|
||||
using StrictMonotonic_8k_HeapResource = StrictMonotonicHeapResource< 8 * 1024 >;
|
||||
using StrictMonotonic_16k_HeapResource = StrictMonotonicHeapResource< 16 * 1024 >;
|
||||
using StrictMonotonic_32k_HeapResource = StrictMonotonicHeapResource< 32 * 1024 >;
|
||||
|
||||
using Monotonic_1k_HeapResource = MonotonicHeapResource< 1 * 1024 >;
|
||||
using Monotonic_2k_HeapResource = MonotonicHeapResource< 2 * 1024 >;
|
||||
using Monotonic_4k_HeapResource = MonotonicHeapResource< 4 * 1024 >;
|
||||
using Monotonic_8k_HeapResource = MonotonicHeapResource< 8 * 1024 >;
|
||||
using Monotonic_16k_HeapResource = MonotonicHeapResource< 4 * 1024 >;
|
||||
using Monotonic_32k_HeapResource = MonotonicHeapResource< 8 * 1024 >;
|
||||
} // namespace memory
|
||||
|
||||
// class RublonMemory {
|
||||
|
||||
@ -89,4 +89,10 @@ class StaticString : public details::StaticStringBase {
|
||||
private:
|
||||
std::array< char, N + 1 > m_str{};
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
bool operator==(const StaticString<N> &lhs, const char* rhs){
|
||||
return strcmp(lhs.c_str(), rhs) == 0;
|
||||
}
|
||||
|
||||
} // namespace rublon
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "rublon/configuration.hpp"
|
||||
#include "rublon/json.hpp"
|
||||
#include "rublon/memory.hpp"
|
||||
#include "rublon/static_string.hpp"
|
||||
@ -7,6 +8,7 @@
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <rublon/error.hpp>
|
||||
#include <rublon/pam_action.hpp>
|
||||
#include <rublon/utils.hpp>
|
||||
@ -28,7 +30,7 @@ struct RublonEventData {
|
||||
};
|
||||
|
||||
class WebSocket {
|
||||
std::string url; /// TODO pmr
|
||||
std::reference_wrapper< const Configuration > _config;
|
||||
std::string_view urlv;
|
||||
|
||||
bool event_received = false;
|
||||
@ -42,7 +44,11 @@ class WebSocket {
|
||||
RublonEventData * currentEvent{nullptr};
|
||||
|
||||
public:
|
||||
WebSocket(std::string_view uri) : url{uri.data()}, urlv{url} {
|
||||
WebSocket(const Configuration & config) : _config{config}, urlv{_config.get().apiServer.c_str(), _config.get().apiServer.size()} {
|
||||
using namespace memory::literals;
|
||||
memory::Monotonic_8k_HeapResource memoryResource;
|
||||
const auto & cfg = _config.get();
|
||||
|
||||
auto lws_log_emit = [](int level, const char * line) {
|
||||
LogLevel rlevel{};
|
||||
if(level == LLL_ERR)
|
||||
@ -70,6 +76,30 @@ class WebSocket {
|
||||
|
||||
context = lws_create_context(&info);
|
||||
|
||||
if(cfg.proxyEnabled && (cfg.proxyType == "http" || cfg.proxyType == "https")) {
|
||||
std::pmr::string proxyUrl{&memoryResource};
|
||||
proxyUrl.reserve(4_kB);
|
||||
|
||||
proxyUrl += cfg.proxyType.data();
|
||||
proxyUrl += "://";
|
||||
|
||||
if(cfg.proxyAuthRequired) {
|
||||
proxyUrl += cfg.proxyUsername.c_str();
|
||||
proxyUrl += ":";
|
||||
proxyUrl += cfg.proxyPass.c_str();
|
||||
proxyUrl += "@";
|
||||
}
|
||||
|
||||
proxyUrl += cfg.proxyServer.c_str();
|
||||
if(cfg.proxyPort > 0) {
|
||||
proxyUrl += ":";
|
||||
proxyUrl += std::to_string(cfg.proxyPort);
|
||||
}
|
||||
|
||||
// Set environment variable for libwebsockets to pick up
|
||||
setenv((cfg.proxyType == "https" ? "https_proxy" : "http_proxy"), proxyUrl.c_str(), 1);
|
||||
}
|
||||
|
||||
const std::string_view prefix = "https://";
|
||||
|
||||
if(urlv.substr(0, prefix.size()) == prefix)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user