128 lines
3.5 KiB
C++
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
|