diff --git a/PAM/ssh/bin/rublon_application.cpp b/PAM/ssh/bin/rublon_application.cpp index 579f879..8dfde4a 100644 --- a/PAM/ssh/bin/rublon_application.cpp +++ b/PAM/ssh/bin/rublon_application.cpp @@ -62,8 +62,7 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char ** argv) { auto finalizeTransaction = [&](const AuthenticationStatus & status) mutable -> tl::expected< AuthenticationStatus, Error > { if(status.userAuthorized()) { - auto tok = std::string{status.accessToken().data()}; - Finish finish{session, std::move(tok)}; + Finish finish{session, status.accessToken()}; finish.handle(CH); } return status; diff --git a/PAM/ssh/include/rublon/check_application.hpp b/PAM/ssh/include/rublon/check_application.hpp index 87590b4..6817702 100644 --- a/PAM/ssh/include/rublon/check_application.hpp +++ b/PAM/ssh/include/rublon/check_application.hpp @@ -171,8 +171,8 @@ class CheckApplication { public: tl::expected< int, Error > call(const CoreHandler_t & coreHandler, std::string_view systemToken) const { - memory::Monotonic_1k_Resource mr; - RapidJSONPMRStackAlloc< 2048 > alloc{}; + memory::MonotonicStack_1k_Resource mr; + RapidJSONPMRAlloc alloc{&mr}; constexpr std::string_view api = "/api/app/init"; Status status; diff --git a/PAM/ssh/include/rublon/configuration.hpp b/PAM/ssh/include/rublon/configuration.hpp index 32260b6..6c9765f 100644 --- a/PAM/ssh/include/rublon/configuration.hpp +++ b/PAM/ssh/include/rublon/configuration.hpp @@ -50,24 +50,22 @@ class Configuration { class ConfigurationReader { public: ConfigurationReader(std::pmr::memory_resource * memResource, std::string_view filepath) : memoryResource(memResource) { + keyValues.reserve(20); loadFromFile(filepath); } // Load config from file path void loadFromFile(std::string_view filepath) { using namespace memory::literals; - memory::MonotonicStackResource< 4_kB > stackResource; + memory::MonotonicStack_1k_Resource memoryResource; std::ifstream file(filepath.data()); if(not file.good()) return ; - std::pmr::string line{&stackResource}; - line.reserve(4000); // allocate full stack to line + std::pmr::string line{&memoryResource}; + line.reserve(300); while(std::getline(file, line)) { - std::pmr::string key{memoryResource}; - std::pmr::string value{memoryResource}; - details::trimInPlace(line); if(!line.length()) continue; @@ -76,8 +74,8 @@ class ConfigurationReader { continue; auto posEqual = line.find('='); - key = line.substr(0, posEqual); - value = line.substr(posEqual + 1); + std::pmr::string key {line.substr(0, posEqual),&memoryResource}; + std::pmr::string value{line.substr(posEqual + 1), &memoryResource}; keyValues[std::move(key)] = std::move(value); } diff --git a/PAM/ssh/include/rublon/core_handler.hpp b/PAM/ssh/include/rublon/core_handler.hpp index 4ebba2f..d252949 100755 --- a/PAM/ssh/include/rublon/core_handler.hpp +++ b/PAM/ssh/include/rublon/core_handler.hpp @@ -157,24 +157,23 @@ class CoreHandler : public CoreHandlerInterface< CoreHandler< HttpHandler > > { } tl::expected< Document, Error > request(RapidJSONPMRAlloc & mr, std::string_view path, const Document & body) const { - memory::Monotonic_8k_Resource memoryResource; + memory::Monotonic_4k_Resource memoryResource; const auto validateSignature = [&](const auto & arg) { return this->validateSignature(arg); }; const auto validateResponse = [&](const auto & arg) { return this->validateResponse(mr, arg); }; const auto handleError = [&](const auto & error) { return this->handleError(error); }; - const auto pmrs = [&](const auto & txt) { return std::pmr::string{txt, &memoryResource}; }; Request request{&memoryResource}; Response response{&memoryResource}; - request.headers["Content-Type"] = pmrs("application/json"); - request.headers["Accept"] = pmrs("application/json"); + request.headers["Content-Type"] = "application/json"; + request.headers["Accept"] = "application/json"; stringifyTo(body, request.body); signRequest(request); std::pmr::string uri{&memoryResource}; - uri.reserve(config().apiServer.size() + path.size() + 1); + uri.reserve(conservative_estimate(config().apiServer, path.size())); uri += config().apiServer; uri += path.data(); diff --git a/PAM/ssh/include/rublon/curl.hpp b/PAM/ssh/include/rublon/curl.hpp index e991f04..eb020a3 100644 --- a/PAM/ssh/include/rublon/curl.hpp +++ b/PAM/ssh/include/rublon/curl.hpp @@ -23,7 +23,7 @@ namespace { struct Request { std::pmr::memory_resource * _mr; - + std::pmr::map< std::pmr::string, std::pmr::string > headers; std::pmr::string body; diff --git a/PAM/ssh/include/rublon/json.hpp b/PAM/ssh/include/rublon/json.hpp index d566294..7207bde 100644 --- a/PAM/ssh/include/rublon/json.hpp +++ b/PAM/ssh/include/rublon/json.hpp @@ -122,8 +122,8 @@ struct FileWriter { template < typename T > static void stringifyTo(const Document & body, T & to) { - memory::Monotonic_1k_Resource tmpResource; - RapidJSONPMRAlloc alloc{&tmpResource}; + memory::MonotonicStack_1k_Resource memoryResource; + RapidJSONPMRAlloc alloc{&memoryResource}; StringWriter< T > s{to}; rapidjson::Writer< StringWriter< T >, rapidjson::UTF8<>, rapidjson::UTF8<>, RapidJSONPMRAlloc > writer{s, &alloc}; body.Accept(writer); diff --git a/PAM/ssh/include/rublon/memory.hpp b/PAM/ssh/include/rublon/memory.hpp index 29960ae..6d12ef7 100644 --- a/PAM/ssh/include/rublon/memory.hpp +++ b/PAM/ssh/include/rublon/memory.hpp @@ -1,15 +1,16 @@ #pragma once +#include #include namespace rublon { namespace memory { - namespace literals{ + namespace literals { constexpr std::uint64_t operator"" _kB(unsigned long long kilobytes) { return kilobytes * 1024ULL; } - } - + } // namespace literals + struct default_memory_resource { static inline std::pmr::memory_resource * _mr = std::pmr::get_default_resource(); }; @@ -22,14 +23,6 @@ namespace memory { return default_memory_resource{}._mr; } - template < std::size_t N > - class MonotonicStackResource : public std::pmr::monotonic_buffer_resource { - char _buffer[N]; - - public: - MonotonicStackResource() : std::pmr::monotonic_buffer_resource{_buffer, N, std::pmr::null_memory_resource()} {} - }; - class MonotonicResourceBase { public: std::pmr::memory_resource * _upstream{}; @@ -47,15 +40,31 @@ namespace memory { template < std::size_t N > class MonotonicResource : MonotonicResourceBase, public std::pmr::monotonic_buffer_resource { public: - MonotonicResource() - : MonotonicResourceBase{N}, std::pmr::monotonic_buffer_resource{this->_buffer, this->_size, default_resource()} {} + MonotonicResource(std::pmr::memory_resource * mr = default_resource()) + : MonotonicResourceBase{N}, std::pmr::monotonic_buffer_resource{this->_buffer, this->_size, mr} {} }; + template < std::size_t N > + class MonotonicStackResourceBase { + public: + char _buffer[N]; + }; + + template < std::size_t N > + class MonotonicStackResource : MonotonicStackResourceBase< N >, public std::pmr::monotonic_buffer_resource { + public: + MonotonicStackResource() + : MonotonicStackResourceBase< N >{}, std::pmr::monotonic_buffer_resource{this->_buffer, N, default_resource()} {} + }; + + using MonotonicStack_1k_Resource = MonotonicStackResource< 1 * 1024 >; + using MonotonicStack_2k_Resource = MonotonicStackResource< 2 * 1024 >; + + using Monotonic_1k_Resource = MonotonicResource< 1 * 1024 >; using Monotonic_2k_Resource = MonotonicResource< 2 * 1024 >; using Monotonic_4k_Resource = MonotonicResource< 4 * 1024 >; using Monotonic_8k_Resource = MonotonicResource< 8 * 1024 >; - using Monotonic_16k_Resource = MonotonicResource< 16 * 1024 >; } // namespace memory // class RublonMemory { diff --git a/PAM/ssh/include/rublon/method/passcode_based_auth.hpp b/PAM/ssh/include/rublon/method/passcode_based_auth.hpp index 36fdfc8..ce1c7a5 100644 --- a/PAM/ssh/include/rublon/method/passcode_based_auth.hpp +++ b/PAM/ssh/include/rublon/method/passcode_based_auth.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rublon/memory.hpp" #include #include @@ -59,8 +60,9 @@ class PasscodeBasedAuth : public AuthenticationStep { tl::expected< std::reference_wrapper< Document >, Error > readPasscode(Document & body, const Pam_t & pam) const { /// TODO assert in interactive mode - auto & alloc = body.GetAllocator(); - auto vericode = pam.scan([](const char * userInput) { return std::string{userInput}; }, _userMessage); + memory::MonotonicStackResource< 100 > memoryResource; + auto & alloc = body.GetAllocator(); + auto vericode = pam.scan([&](const char * userInput) { return std::pmr::string{userInput, &memoryResource}; }, _userMessage); if(hasValidLength(vericode) and hasValidCharacters(vericode)) { Value confirmFieldValue(_confirmField, alloc); diff --git a/PAM/ssh/include/rublon/rublon.hpp b/PAM/ssh/include/rublon/rublon.hpp index 4374abb..8632cc2 100755 --- a/PAM/ssh/include/rublon/rublon.hpp +++ b/PAM/ssh/include/rublon/rublon.hpp @@ -14,8 +14,8 @@ class RublonFactory { public: tl::expected< void, Error > initializeSession(Session & session) { log(LogLevel::Debug, "Configuration read start"); - memory::Monotonic_16k_Resource heap; - ConfigurationReader reader{&heap, "/etc/rublon.config"}; + memory::MonotonicStack_2k_Resource memory_resource; + ConfigurationReader reader{&memory_resource, "/etc/rublon.config"}; if(auto ok = reader.applyTo(session.config()); not ok.has_value()) { log(LogLevel::Warning, "Configuration contains errors"); diff --git a/PAM/ssh/include/rublon/session.hpp b/PAM/ssh/include/rublon/session.hpp index c5abac3..21bae4c 100644 --- a/PAM/ssh/include/rublon/session.hpp +++ b/PAM/ssh/include/rublon/session.hpp @@ -1,5 +1,6 @@ #pragma once +#include "rublon/memory.hpp" #include #include #include @@ -9,9 +10,91 @@ #include #include + namespace rublon { -class Session { + +// class LoggingMemoryResource : public std::pmr::memory_resource { +// public: +// LoggingMemoryResource(std::pmr::memory_resource* upstream = std::pmr::get_default_resource()) +// : upstream_(upstream), allocated_bytes_(0) +// { +// pid_t pid = getpid(); +// std::ostringstream filename; +// filename << "/tmp/memory" << pid << ".log"; +// log_file_.open(filename.str(), std::ios::out | std::ios::trunc); + +// if (!log_file_) { +// throw std::runtime_error("Failed to open log file"); +// } +// log("Memory logging started."); +// } + +// ~LoggingMemoryResource() override { +// log("Memory logging ended."); +// log_file_.close(); +// } + +// protected: +// void* do_allocate(std::size_t bytes, std::size_t alignment) override { +// std::lock_guard lock(mutex_); +// void* ptr = upstream_->allocate(bytes, alignment); +// allocated_bytes_ += bytes; +// active_allocations_[ptr] = bytes; + +// log("ALLOC", ptr, bytes, alignment); +// return ptr; +// } + +// void do_deallocate(void* ptr, std::size_t bytes, std::size_t alignment) override { +// std::lock_guard lock(mutex_); +// auto it = active_allocations_.find(ptr); +// if (it != active_allocations_.end()) { +// allocated_bytes_ -= it->second; +// active_allocations_.erase(it); +// } + +// log("FREE", ptr, bytes, alignment); +// upstream_->deallocate(ptr, bytes, alignment); +// } + +// bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override { +// return this == &other; +// } + +// private: +// std::pmr::memory_resource* upstream_; +// std::ofstream log_file_; +// std::mutex mutex_; +// std::size_t allocated_bytes_; +// std::map active_allocations_; + +// void log(const std::string& action, void* ptr = nullptr, std::size_t bytes = 0, std::size_t alignment = 0) { +// auto now = std::chrono::system_clock::now(); +// auto now_time = std::chrono::system_clock::to_time_t(now); +// log_file_ << std::put_time(std::localtime(&now_time), "%F %T") +// << " | " << std::setw(6) << action; + +// if (ptr) { +// log_file_ << " | ptr=" << ptr << " bytes=" << bytes << " align=" << alignment; +// } + +// log_file_ << " | total=" << allocated_bytes_ << " bytes\n"; +// log_file_.flush(); +// } +// }; + +// std::pmr::unsynchronized_pool_resource resource{}; +// LoggingMemoryResource mr{&resource}; + +class DefaultResource { + public: + DefaultResource() { + // memory::set_default_resource(&mr); + } +}; + +class Session :public DefaultResource { std::pmr::memory_resource * mr; const Pam_t & _pam; Configuration _config; @@ -22,8 +105,7 @@ class Session { CoreHandler_t _coreHandler; /// TODO log public: - Session(const Pam_t & pam) - : mr{memory::default_resource()}, _pam{pam}, _config{mr}, _coreHandler{_config} { + Session(const Pam_t & pam) : DefaultResource{}, mr{memory::default_resource()}, _pam{pam}, _config{mr}, _coreHandler{_config} { details::initLog(); } diff --git a/PAM/ssh/include/rublon/utils.hpp b/PAM/ssh/include/rublon/utils.hpp index 4886b2e..599f111 100755 --- a/PAM/ssh/include/rublon/utils.hpp +++ b/PAM/ssh/include/rublon/utils.hpp @@ -234,7 +234,7 @@ namespace details { } std::pmr::string osName(std::pmr::memory_resource * mr) { - memory::Monotonic_8k_Resource memoryResource; + memory::Monotonic_1k_Resource memoryResource; std::ifstream file(std::filesystem::path{"/etc/os-release"}); if(not file.good())