parselink-old/include/parselink/proto/session.h

128 lines
3.5 KiB
C++

//-----------------------------------------------------------------------------
// ___ __ _ _
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
// / ___/ (_| | | \__ \ __/ /__| | | | | <
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
//
//-----------------------------------------------------------------------------
// Author: Kurt Sassenrath
// Module: Proto
//
// Session management for the "user" protocol.
//
// Copyright (c) 2023 Kurt Sassenrath.
//
// License TBD.
//-----------------------------------------------------------------------------
#ifndef session_07eae057feface79
#define session_07eae057feface79
#include "parselink/msgpack/token.h"
#include <chrono>
#include <cstdint>
#include <functional>
#include <span>
#include <string>
#include <tl/expected.hpp>
template <>
struct std::hash<std::span<std::byte const>> {
constexpr static std::uint32_t seed_var = 0x811c9dc5;
constexpr static std::uint32_t factor = 0x01000193;
constexpr auto operator()(std::span<std::byte const> data) const noexcept {
std::uint32_t digest = seed_var * factor;
for (auto byte : data) {
digest = (digest ^ static_cast<std::uint32_t>(byte)) * factor;
}
return digest >> 8;
}
};
namespace parselink {
namespace proto {
enum class error {
system_error,
incomplete,
unsupported,
bad_data,
too_large,
};
// Structure containing header information parsed from a buffer.
struct header_info {
std::uint32_t message_size; // Size of the message, minus the header.
std::uint32_t bytes_read; // How many bytes of the buffer were used.
std::uint32_t bytes_parsed; // How many bytes were parsed as part of the
// header.
};
struct connect_info {
std::uint32_t version;
std::string_view user_id;
std::span<std::byte const> session_id;
};
template <typename T>
struct transparent_hash {
using is_transparent = void;
using type = T;
using hash_type = std::hash<type>;
template <typename Arg>
[[nodiscard]] constexpr auto operator()(Arg&& arg) const {
return hash_type{}(std::forward<Arg>(arg));
}
};
class session {
public:
using close_handle = std::function<void(std::string_view)>;
session(std::string_view user_id, close_handle hdl) noexcept;
~session();
std::span<std::byte const> id() const noexcept { return id_; }
std::string_view user_id() const noexcept { return user_id_; }
auto last_activity() const noexcept { return last_activity_; }
void update_last_activity(
std::chrono::steady_clock::time_point =
std::chrono::steady_clock::now()) noexcept {}
constexpr bool operator==(std::span<std::byte const> id) const noexcept {
return std::ranges::equal(id, id_);
}
private:
std::array<std::byte, 32> id_;
std::string user_id_;
close_handle closer_;
std::chrono::steady_clock::time_point last_activity_;
};
template <>
struct transparent_hash<session>
: transparent_hash<std::span<std::byte const>> {
[[nodiscard]] auto operator()(session const& s) const {
return std::hash<std::span<std::byte const>>{}(s.id());
}
};
// Parse the protocol header out of a buffer.
tl::expected<header_info, error> parse_header(
std::span<std::byte const> buffer) noexcept;
tl::expected<connect_info, error> parse_connect(
std::span<msgpack::token> tokens) noexcept;
} // namespace proto
} // namespace parselink
#endif // session_0c61530748b9f966