Compare commits
No commits in common. "udp_poc" and "main" have entirely different histories.
36
MODULE.bazel.lock
generated
36
MODULE.bazel.lock
generated
@ -641,13 +641,12 @@
|
|||||||
"name": "apple_support~1.5.0~apple_cc_configure_extension~local_config_apple_cc_toolchains"
|
"name": "apple_support~1.5.0~apple_cc_configure_extension~local_config_apple_cc_toolchains"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"recordedRepoMappingEntries": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@@bazel_tools//tools/cpp:cc_configure.bzl%cc_configure_extension": {
|
"@@bazel_tools//tools/cpp:cc_configure.bzl%cc_configure_extension": {
|
||||||
"general": {
|
"general": {
|
||||||
"bzlTransitiveDigest": "mcsWHq3xORJexV5/4eCvNOLxFOQKV6eli3fkr+tEaqE=",
|
"bzlTransitiveDigest": "O9sf6ilKWU9Veed02jG9o2HM/xgV/UAyciuFBuxrFRY=",
|
||||||
"accumulatedFileDigests": {},
|
"accumulatedFileDigests": {},
|
||||||
"envVariables": {},
|
"envVariables": {},
|
||||||
"generatedRepoSpecs": {
|
"generatedRepoSpecs": {
|
||||||
@ -665,14 +664,7 @@
|
|||||||
"name": "bazel_tools~cc_configure_extension~local_config_cc_toolchains"
|
"name": "bazel_tools~cc_configure_extension~local_config_cc_toolchains"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"recordedRepoMappingEntries": [
|
|
||||||
[
|
|
||||||
"bazel_tools",
|
|
||||||
"bazel_tools",
|
|
||||||
"bazel_tools"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@@bazel_tools//tools/osx:xcode_configure.bzl%xcode_configure_extension": {
|
"@@bazel_tools//tools/osx:xcode_configure.bzl%xcode_configure_extension": {
|
||||||
@ -690,8 +682,7 @@
|
|||||||
"remote_xcode": ""
|
"remote_xcode": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"recordedRepoMappingEntries": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@@bazel_tools//tools/sh:sh_configure.bzl%sh_configure_extension": {
|
"@@bazel_tools//tools/sh:sh_configure.bzl%sh_configure_extension": {
|
||||||
@ -707,13 +698,12 @@
|
|||||||
"name": "bazel_tools~sh_configure_extension~local_config_sh"
|
"name": "bazel_tools~sh_configure_extension~local_config_sh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"recordedRepoMappingEntries": []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@@rules_java~7.1.0//java:extensions.bzl%toolchains": {
|
"@@rules_java~7.1.0//java:extensions.bzl%toolchains": {
|
||||||
"general": {
|
"general": {
|
||||||
"bzlTransitiveDigest": "D02GmifxnV/IhYgspsJMDZ/aE8HxAjXgek5gi6FSto4=",
|
"bzlTransitiveDigest": "iUIRqCK7tkhvcDJCAfPPqSd06IHG0a8HQD0xeQyVAqw=",
|
||||||
"accumulatedFileDigests": {},
|
"accumulatedFileDigests": {},
|
||||||
"envVariables": {},
|
"envVariables": {},
|
||||||
"generatedRepoSpecs": {
|
"generatedRepoSpecs": {
|
||||||
@ -1248,19 +1238,7 @@
|
|||||||
"build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\n"
|
"build_file": "\nconfig_setting(\n name = \"prefix_version_setting\",\n values = {\"java_runtime_version\": \"remotejdk_21\"},\n visibility = [\"//visibility:private\"],\n)\nconfig_setting(\n name = \"version_setting\",\n values = {\"java_runtime_version\": \"21\"},\n visibility = [\"//visibility:private\"],\n)\nalias(\n name = \"version_or_prefix_version_setting\",\n actual = select({\n \":version_setting\": \":version_setting\",\n \"//conditions:default\": \":prefix_version_setting\",\n }),\n visibility = [\"//visibility:private\"],\n)\ntoolchain(\n name = \"toolchain\",\n target_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\ntoolchain(\n name = \"bootstrap_runtime_toolchain\",\n # These constraints are not required for correctness, but prevent fetches of remote JDK for\n # different architectures. As every Java compilation toolchain depends on a bootstrap runtime in\n # the same configuration, this constraint will not result in toolchain resolution failures.\n exec_compatible_with = [\"@platforms//os:windows\", \"@platforms//cpu:x86_64\"],\n target_settings = [\":version_or_prefix_version_setting\"],\n toolchain_type = \"@bazel_tools//tools/jdk:bootstrap_runtime_toolchain_type\",\n toolchain = \"@remotejdk21_win//:jdk\",\n)\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"recordedRepoMappingEntries": [
|
|
||||||
[
|
|
||||||
"rules_java~7.1.0",
|
|
||||||
"bazel_tools",
|
|
||||||
"bazel_tools"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"rules_java~7.1.0",
|
|
||||||
"remote_java_tools",
|
|
||||||
"rules_java~7.1.0~toolchains~remote_java_tools"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ cc_library(
|
|||||||
name = "msgpack",
|
name = "msgpack",
|
||||||
hdrs = glob(["msgpack/**/*.h"]),
|
hdrs = glob(["msgpack/**/*.h"]),
|
||||||
includes = ["."],
|
includes = ["."],
|
||||||
deps = ["@expected", "//include:path", "utility"],
|
deps = ["@expected", "//include:path"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,6 +23,14 @@ cc_library(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "proto",
|
||||||
|
hdrs = glob(["proto/**/*.h"]),
|
||||||
|
includes = ["."],
|
||||||
|
deps = ["@expected", "//include:path"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "utility",
|
name = "utility",
|
||||||
hdrs = glob(["utility/**/*.h"]),
|
hdrs = glob(["utility/**/*.h"]),
|
||||||
@ -31,14 +39,6 @@ cc_library(
|
|||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "proto",
|
|
||||||
hdrs = glob(["proto/**/*.h"]),
|
|
||||||
includes = ["."],
|
|
||||||
deps = ["@expected", "//include:path", "utility"],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
exports_files(
|
exports_files(
|
||||||
["server.h"],
|
["server.h"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
|
|||||||
@ -27,11 +27,12 @@
|
|||||||
#include <tl/expected.hpp>
|
#include <tl/expected.hpp>
|
||||||
|
|
||||||
// Simple wrapper for error strings to be formatted like any other string_view.
|
// Simple wrapper for error strings to be formatted like any other string_view.
|
||||||
template <error_code Err>
|
template <>
|
||||||
struct fmt::formatter<Err> : fmt::formatter<std::string_view> {
|
struct fmt::formatter<parselink::logging::error_str>
|
||||||
|
: fmt::formatter<std::string_view> {
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
constexpr auto format(auto const& v, FormatContext& ctx) const {
|
constexpr auto format(auto const& v, FormatContext& ctx) const {
|
||||||
return fmt::formatter<std::string_view>::format(v.message(), ctx);
|
return fmt::formatter<std::string_view>::format(v.v, ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -149,13 +150,4 @@ struct fmt::formatter<parselink::logging::format_arg<T>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <endpoint T>
|
|
||||||
struct fmt::formatter<T> : fmt::formatter<std::string_view> {
|
|
||||||
template <typename FormatContext>
|
|
||||||
constexpr auto format(auto const& v, FormatContext& ctx) const {
|
|
||||||
return fmt::format_to(
|
|
||||||
ctx.out(), "{}:{}", v.address().to_string(), v.port());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // logging_formatters_d22a64b1645a8134
|
#endif // logging_formatters_d22a64b1645a8134
|
||||||
|
|||||||
@ -62,16 +62,6 @@ struct format_arg<T> {
|
|||||||
type v;
|
type v;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct format_arg<std::string_view> {
|
|
||||||
using type = std::string_view;
|
|
||||||
|
|
||||||
constexpr format_arg(std::string_view const& t) noexcept
|
|
||||||
: v(t) {}
|
|
||||||
|
|
||||||
std::string_view v;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <detail::smart_pointer T>
|
template <detail::smart_pointer T>
|
||||||
struct format_arg<T> {
|
struct format_arg<T> {
|
||||||
using type = void const*;
|
using type = void const*;
|
||||||
@ -108,14 +98,14 @@ template <typename E>
|
|||||||
struct theme<E> : static_theme<fmt::color::gray> {};
|
struct theme<E> : static_theme<fmt::color::gray> {};
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
template <error_code Err>
|
template <>
|
||||||
struct theme<Err> : static_theme<fmt::color::fire_brick> {};
|
struct theme<std::error_code> : static_theme<fmt::color::fire_brick> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct theme<std::errc> : static_theme<fmt::color::fire_brick> {};
|
struct theme<std::errc> : static_theme<fmt::color::fire_brick> {};
|
||||||
|
|
||||||
template <endpoint T>
|
template <>
|
||||||
struct theme<T> : static_theme<fmt::color::coral> {};
|
struct theme<error_str> : static_theme<fmt::color::fire_brick> {};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct theme<bool> {
|
struct theme<bool> {
|
||||||
|
|||||||
@ -22,22 +22,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept endpoint = requires(T const& t) {
|
|
||||||
{ t.address() };
|
|
||||||
{ t.port() };
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept error_code = requires(T const& t) {
|
|
||||||
{ t.message() } -> std::convertible_to<std::string_view>;
|
|
||||||
{ t.category() };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
namespace parselink {
|
namespace parselink {
|
||||||
namespace logging {
|
namespace logging {
|
||||||
|
|
||||||
@ -57,6 +41,16 @@ struct enum_name_only {
|
|||||||
template <typename E>
|
template <typename E>
|
||||||
enum_name_only(E) -> enum_name_only<E>;
|
enum_name_only(E) -> enum_name_only<E>;
|
||||||
|
|
||||||
|
// Wrapper for a string that will be colorized as if it's an error, instead of
|
||||||
|
// a normal string.
|
||||||
|
struct error_str {
|
||||||
|
template <std::convertible_to<std::string_view> T>
|
||||||
|
error_str(T&& t)
|
||||||
|
: v(std::forward<T>(t)) {}
|
||||||
|
|
||||||
|
std::string_view v;
|
||||||
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// The following concepts aim to describe both raw and smart pointers in a
|
// The following concepts aim to describe both raw and smart pointers in a
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: msgpack
|
|
||||||
//
|
|
||||||
// Support for unpacking maps with known structure.
|
|
||||||
//
|
|
||||||
// Maps contain key, value pairs. These pairs may arrive in an
|
|
||||||
// implementation-defined order; this code aims to provide the user of the
|
|
||||||
// interface with a means to pass a set of handlers for each key.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifndef msgpack_core_detail_unpack_map_9f12af74a689aa51
|
|
||||||
#define msgpack_core_detail_unpack_map_9f12af74a689aa51
|
|
||||||
|
|
||||||
#include "parselink/utility/ctstring.h"
|
|
||||||
#include <algorithm>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace msgpack {
|
|
||||||
namespace map {
|
|
||||||
|
|
||||||
struct key_base {};
|
|
||||||
|
|
||||||
template <auto key_value, typename callable>
|
|
||||||
struct key : key_base {
|
|
||||||
static constexpr auto const& value = key_value;
|
|
||||||
callable handler;
|
|
||||||
|
|
||||||
constexpr key(callable fn) noexcept
|
|
||||||
: handler(std::move(fn)) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <auto key_value>
|
|
||||||
constexpr auto on_key(auto callable) noexcept {
|
|
||||||
return key<key_value, decltype(callable)>(std::move(callable));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <parselink::ct::string key_value>
|
|
||||||
constexpr auto on_key(auto callable) noexcept {
|
|
||||||
return key<key_value, decltype(callable)>(std::move(callable));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept is_key = std::is_base_of_v<key_base, T>;
|
|
||||||
|
|
||||||
consteval auto get_key(is_key auto const& key) {
|
|
||||||
return std::decay_t<decltype(key)>::value;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct policy_type {};
|
|
||||||
|
|
||||||
struct required : policy_type {};
|
|
||||||
|
|
||||||
template <is_key... Keys>
|
|
||||||
struct key_group {
|
|
||||||
constexpr key_group(Keys&&... keys) noexcept
|
|
||||||
: keys_(std::make_tuple(std::forward<Keys>(keys)...)){};
|
|
||||||
|
|
||||||
std::tuple<Keys...> keys_;
|
|
||||||
constexpr static std::size_t size = sizeof...(Keys);
|
|
||||||
}; // namespace map
|
|
||||||
|
|
||||||
} // namespace map
|
|
||||||
} // namespace msgpack
|
|
||||||
|
|
||||||
#endif // msgpack_core_detail_unpack_map_9f12af74a689aa51
|
|
||||||
@ -28,10 +28,6 @@
|
|||||||
|
|
||||||
#include <tl/expected.hpp>
|
#include <tl/expected.hpp>
|
||||||
|
|
||||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#define PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|||||||
@ -36,10 +36,6 @@
|
|||||||
|
|
||||||
#include <tl/expected.hpp>
|
#include <tl/expected.hpp>
|
||||||
|
|
||||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#define PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
// This API is _currently_ optimizing on the fact that most desktop/server
|
// This API is _currently_ optimizing on the fact that most desktop/server
|
||||||
|
|||||||
@ -27,9 +27,7 @@
|
|||||||
#include <bits/iterator_concepts.h>
|
#include <bits/iterator_concepts.h>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
#include <fmt/format.h>
|
||||||
#define PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
|
|||||||
@ -28,10 +28,6 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#define PARSELINK_MSGPACK_TOKEN_API
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace msgpack {
|
namespace msgpack {
|
||||||
|
|
||||||
enum class writer_error {
|
enum class writer_error {
|
||||||
|
|||||||
@ -18,8 +18,6 @@
|
|||||||
#ifndef message_0c61530748b9f966
|
#ifndef message_0c61530748b9f966
|
||||||
#define message_0c61530748b9f966
|
#define message_0c61530748b9f966
|
||||||
|
|
||||||
#include "parselink/utility/ctstring.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@ -38,23 +36,16 @@ namespace proto {
|
|||||||
|
|
||||||
struct base_message {};
|
struct base_message {};
|
||||||
|
|
||||||
template <ct::string Str>
|
|
||||||
struct message : base_message {
|
|
||||||
static constexpr auto name() noexcept { return Str; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept message_type = requires { T::message_name(); };
|
concept message_type = std::is_base_of_v<base_message, T>;
|
||||||
|
|
||||||
struct error_message {
|
|
||||||
static constexpr auto message_name() noexcept { return "error"; }
|
|
||||||
|
|
||||||
|
struct error_message : base_message {
|
||||||
std::uint32_t code; // An error code
|
std::uint32_t code; // An error code
|
||||||
std::string_view what; // A string
|
std::string_view what; // A string
|
||||||
};
|
};
|
||||||
|
|
||||||
// C->S: Request to (re)connect.
|
// C->S: Request to (re)connect.
|
||||||
struct connect_message : message<"connect"> {
|
struct connect_message : base_message {
|
||||||
std::uint32_t version; // The version of the client.
|
std::uint32_t version; // The version of the client.
|
||||||
std::string_view user_id; // The user id.
|
std::string_view user_id; // The user id.
|
||||||
std::span<std::byte> session_token; // An optional existing session token.
|
std::span<std::byte> session_token; // An optional existing session token.
|
||||||
|
|||||||
@ -21,45 +21,10 @@
|
|||||||
#ifndef parselink_proto_parser_ad351d41fe4c72dd
|
#ifndef parselink_proto_parser_ad351d41fe4c72dd
|
||||||
#define parselink_proto_parser_ad351d41fe4c72dd
|
#define parselink_proto_parser_ad351d41fe4c72dd
|
||||||
|
|
||||||
#include "parselink/logging.h"
|
|
||||||
#include "parselink/proto/error.h"
|
#include "parselink/proto/error.h"
|
||||||
#include "parselink/proto/message.h"
|
#include "parselink/proto/message.h"
|
||||||
|
|
||||||
#include "parselink/msgpack/core/unpacker.h"
|
|
||||||
|
|
||||||
#include <tl/expected.hpp>
|
#include <tl/expected.hpp>
|
||||||
#include <boost/pfr.hpp>
|
|
||||||
|
|
||||||
namespace parselink {
|
|
||||||
logging::logger& get_logger();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace msgpack {
|
|
||||||
|
|
||||||
template <parselink::proto::message_type M>
|
|
||||||
struct unpacker_adapter<M> {
|
|
||||||
static constexpr auto unpack(auto& unpacker) noexcept
|
|
||||||
-> tl::expected<M, error> {
|
|
||||||
auto verify_name = unpacker.template unpack<std::string_view>();
|
|
||||||
|
|
||||||
if (!verify_name || verify_name != M::message_name()) {
|
|
||||||
fmt::print("{} {}\n", verify_name, M::message_name());
|
|
||||||
return tl::make_unexpected(error::wrong_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto mapsize = unpacker.template unpack<msgpack::map_desc>();
|
|
||||||
|
|
||||||
if (!mapsize) {
|
|
||||||
return tl::make_unexpected(error::wrong_type);
|
|
||||||
} else if (mapsize->count != boost::pfr::tuple_size_v<M>) {
|
|
||||||
return tl::make_unexpected(error::wrong_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return M{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace msgpack
|
|
||||||
|
|
||||||
namespace parselink {
|
namespace parselink {
|
||||||
namespace proto {
|
namespace proto {
|
||||||
|
|||||||
@ -33,8 +33,6 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <tl/expected.hpp>
|
|
||||||
|
|
||||||
// Simple command line parser for testing executables.
|
// Simple command line parser for testing executables.
|
||||||
|
|
||||||
namespace argparse {
|
namespace argparse {
|
||||||
@ -262,15 +260,6 @@ public:
|
|||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T const& opt_or(std::string_view opt_name, T fallback = {}) const {
|
|
||||||
if (auto const* v = maybe_opt<T>(opt_name)) {
|
|
||||||
return *v;
|
|
||||||
} else {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T const& opt(std::string_view opt_name) const {
|
T const& opt(std::string_view opt_name) const {
|
||||||
auto const* v = maybe_opt<T>(opt_name);
|
auto const* v = maybe_opt<T>(opt_name);
|
||||||
@ -298,15 +287,6 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tl::expected<result, result::result::code> try_parse(
|
|
||||||
std::span<std::string_view> arglist) {
|
|
||||||
auto res = parse_inner(arglist);
|
|
||||||
if (res.ec != result::code::no_error) {
|
|
||||||
return tl::make_unexpected(res.ec);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
result parse(std::span<std::string_view> arglist) {
|
result parse(std::span<std::string_view> arglist) {
|
||||||
return parse_inner(arglist);
|
return parse_inner(arglist);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,174 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: Utility
|
|
||||||
//
|
|
||||||
// Compile-time reflection for structures.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifndef parselink_ct_reflect_080596cd36d52770
|
|
||||||
#define parselink_ct_reflect_080596cd36d52770
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <source_location>
|
|
||||||
#include <string_view>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace parselink {
|
|
||||||
namespace ct {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
// This allows us to reference a type instance without ever instantiating it.
|
|
||||||
template <typename T>
|
|
||||||
extern T const phantom;
|
|
||||||
|
|
||||||
// This type binds to anything, allowing us to sus out the number of data
|
|
||||||
// members in an aggregate.
|
|
||||||
struct any_type {
|
|
||||||
template <typename T>
|
|
||||||
constexpr operator T();
|
|
||||||
};
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
// This template takes a wrapped pointer to a data member of a theoretical
|
|
||||||
// instance of that type, in order to retrieve the name at compile time.
|
|
||||||
// Examples:
|
|
||||||
// gcc:
|
|
||||||
// constexpr auto parselink::ct::detail::src_string() [with auto Member = const_ptr<int>{(& phantom<structure>.structure::field)}]
|
|
||||||
//
|
|
||||||
// clang:
|
|
||||||
// auto parselink::ct::detail::src_string() [Member = const_ptr<member_ptr>{&phantom.field}]
|
|
||||||
// clang-format on
|
|
||||||
template <auto Member>
|
|
||||||
constexpr auto src_string() {
|
|
||||||
return std::source_location::current().function_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <char StartDelim, char EndDelim>
|
|
||||||
struct base_parse_traits {
|
|
||||||
static constexpr char start_delim = StartDelim;
|
|
||||||
static constexpr char end_delim = EndDelim;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
struct parse : base_parse_traits<'.', '}'> {};
|
|
||||||
#elif defined(__GNUC__)
|
|
||||||
struct parse : base_parse_traits<':', ')'> {};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static constexpr std::size_t max_members = 8;
|
|
||||||
|
|
||||||
// TODO: Logarithmic approach
|
|
||||||
// This needs to be limited to max_members, otherwise clang will go off into
|
|
||||||
// the weeds.
|
|
||||||
template <typename T, typename... Members>
|
|
||||||
requires(sizeof...(Members) <= max_members)
|
|
||||||
consteval std::size_t count_members(Members&&... members) {
|
|
||||||
if constexpr (requires { T{any_type{}, members...}; } == false) {
|
|
||||||
return sizeof...(members);
|
|
||||||
} else if constexpr (sizeof...(members) <= max_members) {
|
|
||||||
return count_members<T>(members..., any_type{});
|
|
||||||
} else {
|
|
||||||
throw "Too many members / something went wrong!";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This function takes an aggregate and attempts to bind it into a tuple.
|
|
||||||
// Unfortunately, without variadic packs for structured bindings, this will
|
|
||||||
// rely on some heavy boilerplate.
|
|
||||||
template <typename T, std::size_t MemberCount = count_members<T>()>
|
|
||||||
requires(MemberCount <= 8)
|
|
||||||
consteval decltype(auto) as_tuple(T&& t) {
|
|
||||||
if constexpr (MemberCount == 0) {
|
|
||||||
return std::tuple{};
|
|
||||||
} else if constexpr (MemberCount == 1) {
|
|
||||||
auto&& [a0] = t;
|
|
||||||
return std::tie(a0);
|
|
||||||
} else if constexpr (MemberCount == 2) {
|
|
||||||
auto&& [a0, a1] = t;
|
|
||||||
return std::tie(a0, a1);
|
|
||||||
} else if constexpr (MemberCount == 3) {
|
|
||||||
auto&& [a0, a1, a2] = t;
|
|
||||||
return std::tie(a0, a1, a2);
|
|
||||||
} else if constexpr (MemberCount == 4) {
|
|
||||||
auto&& [a0, a1, a2, a3] = t;
|
|
||||||
return std::tie(a0, a1, a2, a3);
|
|
||||||
} else if constexpr (MemberCount == 5) {
|
|
||||||
auto&& [a0, a1, a2, a3, a4] = t;
|
|
||||||
return std::tie(a0, a1, a2, a3, a4);
|
|
||||||
} else if constexpr (MemberCount == 6) {
|
|
||||||
auto&& [a0, a1, a2, a3, a4, a5] = t;
|
|
||||||
return std::tie(a0, a1, a2, a3, a4, a5);
|
|
||||||
} else if constexpr (MemberCount == 7) {
|
|
||||||
auto&& [a0, a1, a2, a3, a4, a5, a6] = t;
|
|
||||||
return std::tie(a0, a1, a2, a3, a4, a5, a6);
|
|
||||||
} else if constexpr (MemberCount == 8) {
|
|
||||||
auto&& [a0, a1, a2, a3, a4, a5, a6, a7] = t;
|
|
||||||
return std::tie(a0, a1, a2, a3, a4, a5, a6, a7);
|
|
||||||
} else {
|
|
||||||
throw "Too many members!";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
struct const_ptr {
|
|
||||||
T const* ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t I, typename T>
|
|
||||||
consteval decltype(auto) as_ptr(T&& t) noexcept {
|
|
||||||
auto&& member = std::get<I>(as_tuple(t));
|
|
||||||
using member_ptr = std::decay_t<decltype(member)>;
|
|
||||||
return const_ptr<member_ptr>(&member);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, std::size_t I>
|
|
||||||
consteval decltype(auto) raw_member_name() noexcept {
|
|
||||||
return src_string<as_ptr<I>(phantom<T>)>();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, std::size_t I>
|
|
||||||
consteval decltype(auto) get_member_name() noexcept {
|
|
||||||
std::string_view raw = raw_member_name<T, I>();
|
|
||||||
auto s = raw.rfind(parse::start_delim);
|
|
||||||
auto e = raw.rfind(parse::end_delim);
|
|
||||||
if (s == raw.npos || e == raw.npos) throw "name parsing is broken!";
|
|
||||||
return raw.substr(s + 1, e - (s + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, std::size_t... Is>
|
|
||||||
consteval decltype(auto) get_member_names(std::index_sequence<Is...>) noexcept {
|
|
||||||
return std::array{get_member_name<T, Is>()...};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename T, std::size_t I>
|
|
||||||
consteval decltype(auto) member_name() noexcept {
|
|
||||||
std::string_view raw = detail::raw_member_name<T, I>();
|
|
||||||
auto s = raw.rfind(detail::parse::start_delim);
|
|
||||||
auto e = raw.rfind(detail::parse::end_delim);
|
|
||||||
if (s == raw.npos || e == raw.npos) throw "name_of is broken!";
|
|
||||||
return raw.substr(s + 1, e - (s + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
consteval decltype(auto) member_names() noexcept {
|
|
||||||
return detail::get_member_names<T>(
|
|
||||||
std::make_index_sequence<detail::count_members<T>()>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ct
|
|
||||||
} // namespace parselink
|
|
||||||
|
|
||||||
#endif // parselink_ct_reflect_080596cd36d52770
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: Utility
|
|
||||||
//
|
|
||||||
// Compile-time string class, which can be used as template parameters and
|
|
||||||
// enable compile-time hashing/lookup of literals and so forth.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef ct_string_4fab12ca46f0d931
|
|
||||||
#define ct_string_4fab12ca46f0d931
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace parselink {
|
|
||||||
namespace ct {
|
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
struct string {
|
|
||||||
using char_type = char; // Maybe allow templatization in the future?
|
|
||||||
using storage_type = std::array<char, N + 1>;
|
|
||||||
storage_type data_ = {};
|
|
||||||
|
|
||||||
static constexpr auto npos = std::string_view::npos;
|
|
||||||
|
|
||||||
constexpr string() noexcept = default;
|
|
||||||
|
|
||||||
constexpr string(storage_type const& str) noexcept {
|
|
||||||
std::copy(std::begin(str), std::end(str), std::begin(data_));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr string(char const (&str)[N + 1]) noexcept {
|
|
||||||
std::copy(std::begin(str), std::end(str), std::begin(data_));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr string(string const& other) noexcept {
|
|
||||||
std::copy(std::begin(other), std::end(other), std::begin(data_));
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr string& operator=(string const& other) noexcept {
|
|
||||||
std::copy(std::begin(other), std::end(other), std::begin(data_));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr operator std::string_view() const noexcept {
|
|
||||||
return std::string_view{data_.data(), N};
|
|
||||||
}
|
|
||||||
|
|
||||||
// We save ourselves some headache by forwarding std::array's methods here.
|
|
||||||
constexpr auto data() noexcept { return data_.data(); }
|
|
||||||
|
|
||||||
constexpr auto data() const noexcept { return data_.data(); }
|
|
||||||
|
|
||||||
constexpr auto size() const noexcept { return N; }
|
|
||||||
|
|
||||||
constexpr auto begin() noexcept { return data_.begin(); }
|
|
||||||
|
|
||||||
constexpr auto begin() const noexcept { return data_.begin(); }
|
|
||||||
|
|
||||||
constexpr auto end() noexcept { return data_.end() - 1; }
|
|
||||||
|
|
||||||
constexpr auto end() const noexcept { return data_.end() - 1; }
|
|
||||||
|
|
||||||
constexpr auto cbegin() const noexcept { return data_.cbegin(); }
|
|
||||||
|
|
||||||
constexpr auto cend() const noexcept { return data_.cend() - 1; }
|
|
||||||
|
|
||||||
constexpr auto find(char_type c) noexcept {
|
|
||||||
return std::string_view{*this}.find(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr auto find(char_type c) const noexcept {
|
|
||||||
return std::string_view{*this}.find(c);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
string(char const (&)[N]) -> string<N - 1>;
|
|
||||||
|
|
||||||
template <std::size_t N1, std::size_t N2>
|
|
||||||
constexpr bool operator==(string<N1> const& a, string<N2> const& b) noexcept {
|
|
||||||
if constexpr (N1 != N2) return false;
|
|
||||||
return std::string_view{a} == std::string_view{b};
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
constexpr bool operator==(string<N> const& a, std::string_view b) noexcept {
|
|
||||||
return std::string_view{a} == b;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
constexpr bool operator==(std::string_view a, string<N> const& b) noexcept {
|
|
||||||
return b == a;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <std::size_t N1, std::size_t N2>
|
|
||||||
consteval string<N1 + N2> operator+(
|
|
||||||
string<N1> const& a, string<N2> const& b) noexcept {
|
|
||||||
using char_type = typename std::decay_t<decltype(a)>::char_type;
|
|
||||||
char_type buff[N1 + N2 + 1]{};
|
|
||||||
std::copy(std::begin(a), std::end(a), std::begin(buff));
|
|
||||||
std::copy(
|
|
||||||
std::begin(b), std::end(b), std::next(std::begin(buff), a.size()));
|
|
||||||
return string<N1 + N2>(buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity test for construction and concatenation at compile time.
|
|
||||||
static_assert(string("hello") + string(" world") == string("hello world"));
|
|
||||||
|
|
||||||
} // namespace ct
|
|
||||||
} // namespace parselink
|
|
||||||
|
|
||||||
#endif // ct_string_4fab12ca46f0d931
|
|
||||||
33
source/BUILD
33
source/BUILD
@ -1,31 +1,24 @@
|
|||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "client",
|
name = "headers",
|
||||||
srcs = [
|
hdrs = [
|
||||||
"client.h",
|
"//include/parselink:server.h",
|
||||||
"client.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"//include/parselink:msgpack",
|
|
||||||
"//include/parselink:proto",
|
|
||||||
"//include/parselink:utility",
|
|
||||||
"//source/logging",
|
|
||||||
"//source/proto",
|
|
||||||
"@hydrogen",
|
|
||||||
"@boost//:asio",
|
|
||||||
"@boost//:beast",
|
|
||||||
],
|
|
||||||
visibility = [
|
|
||||||
"//visibility:private"
|
|
||||||
],
|
],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_binary(
|
cc_binary(
|
||||||
name = "parselink",
|
name = "parselinkd",
|
||||||
srcs = [
|
srcs = [
|
||||||
"main.cpp",
|
"main.cpp",
|
||||||
|
"server.cpp",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"client"
|
"headers",
|
||||||
|
"//include/parselink:msgpack",
|
||||||
|
"//include/parselink:utility",
|
||||||
|
"//source/logging",
|
||||||
|
"//source/proto",
|
||||||
|
"//source/server",
|
||||||
|
"@boost//:beast",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,33 +0,0 @@
|
|||||||
# parselink
|
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "client",
|
|
||||||
srcs = [
|
|
||||||
"client.h",
|
|
||||||
"client.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"//include/parselink:msgpack",
|
|
||||||
"//include/parselink:utility",
|
|
||||||
"//source/logging",
|
|
||||||
"//source/proto",
|
|
||||||
"@hydrogen",
|
|
||||||
"@boost//:asio",
|
|
||||||
"@boost//:beast",
|
|
||||||
],
|
|
||||||
visibility = [
|
|
||||||
# TODO: Fix visibility
|
|
||||||
"//visibility:public",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_binary(
|
|
||||||
name = "parselink",
|
|
||||||
srcs = [
|
|
||||||
"client.h",
|
|
||||||
"main.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"client"
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: Client
|
|
||||||
//
|
|
||||||
// Client implementation. Most of this should be agnostic to the targeted
|
|
||||||
// platform (e.g. Linux vs Windows).
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#include "client.h"
|
|
||||||
#include "parselink/logging.h"
|
|
||||||
#include "parselink/utility/ctstring.h"
|
|
||||||
|
|
||||||
#include "parselink/msgpack/core/packer.h"
|
|
||||||
|
|
||||||
#include <boost/asio/as_tuple.hpp>
|
|
||||||
#include <boost/asio/co_spawn.hpp>
|
|
||||||
#include <boost/asio/detached.hpp>
|
|
||||||
#include <boost/asio/ip/address.hpp>
|
|
||||||
#include <boost/asio/ip/udp.hpp>
|
|
||||||
#include <boost/asio/signal_set.hpp>
|
|
||||||
#include <boost/beast.hpp>
|
|
||||||
|
|
||||||
using namespace parselink;
|
|
||||||
using namespace parselink::client;
|
|
||||||
|
|
||||||
namespace net = boost::asio;
|
|
||||||
using net::awaitable;
|
|
||||||
using net::co_spawn;
|
|
||||||
using net::detached;
|
|
||||||
using net::use_awaitable;
|
|
||||||
using udp = net::ip::udp;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
logging::logger logger{"client"};
|
|
||||||
|
|
||||||
constexpr auto no_ex_coro = net::as_tuple(use_awaitable);
|
|
||||||
|
|
||||||
class simple_client {
|
|
||||||
public:
|
|
||||||
simple_client(config const& cfg) noexcept;
|
|
||||||
std::error_code run() noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
awaitable<void> connect_to_server() noexcept;
|
|
||||||
awaitable<void> connect_to_websocket() noexcept;
|
|
||||||
|
|
||||||
net::io_context io_context_;
|
|
||||||
std::string server_address_;
|
|
||||||
std::uint16_t server_port_;
|
|
||||||
std::string websocket_address_;
|
|
||||||
std::uint16_t websocket_port_;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(interface<simple_client>);
|
|
||||||
|
|
||||||
simple_client::simple_client(config const& cfg) noexcept
|
|
||||||
: io_context_{1} {
|
|
||||||
server_address_ =
|
|
||||||
cfg.server_address.empty() ? "localhost" : cfg.server_address;
|
|
||||||
server_port_ = !cfg.server_port ? 9001 : cfg.server_port;
|
|
||||||
websocket_address_ =
|
|
||||||
cfg.websocket_address.empty() ? "localhost" : cfg.websocket_address;
|
|
||||||
websocket_port_ = !cfg.websocket_port ? 10501 : cfg.websocket_port;
|
|
||||||
|
|
||||||
logger.debug("Creating parselink client. Configured server: {}:{}, "
|
|
||||||
"websocket: {}:{}.",
|
|
||||||
server_address_, server_port_, websocket_address_, websocket_port_);
|
|
||||||
};
|
|
||||||
|
|
||||||
awaitable<void> simple_client::connect_to_server() noexcept {
|
|
||||||
logger.debug("Connecting to parselink server...");
|
|
||||||
udp::resolver resolver(io_context_);
|
|
||||||
auto [ec, results] = co_await resolver.async_resolve(
|
|
||||||
{server_address_, std::to_string(server_port_)}, no_ex_coro);
|
|
||||||
|
|
||||||
if (ec) {
|
|
||||||
logger.error("Unable to resolve {}:{}: {}", server_address_,
|
|
||||||
server_port_, ec);
|
|
||||||
co_return;
|
|
||||||
} else if (results.empty()) {
|
|
||||||
logger.error("Unable to resolve {}:{} to an endpoint.", server_address_,
|
|
||||||
server_port_);
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& r : results) {
|
|
||||||
udp::socket socket(io_context_);
|
|
||||||
socket.open(r.endpoint().protocol());
|
|
||||||
logger.debug("Connecting to {}", r.endpoint());
|
|
||||||
std::array<std::byte, 4096> buff;
|
|
||||||
msgpack::packer packer(buff);
|
|
||||||
packer.pack("error");
|
|
||||||
packer.pack(msgpack::map_desc{2});
|
|
||||||
auto span = packer.subspan();
|
|
||||||
auto [ec, bw] = co_await socket.async_send_to(
|
|
||||||
net::buffer(span.data(), span.size()), r.endpoint(),
|
|
||||||
no_ex_coro);
|
|
||||||
if (ec) {
|
|
||||||
logger.error("connection to {} failed: {}",
|
|
||||||
results.begin()->endpoint(), ec);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.error("Unable to connect to any resolved endpoints.");
|
|
||||||
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
awaitable<void> simple_client::connect_to_websocket() noexcept {
|
|
||||||
logger.debug("Connecting to websocket server...");
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::error_code simple_client::run() noexcept {
|
|
||||||
logger.debug("Starting client.");
|
|
||||||
|
|
||||||
net::signal_set signals(io_context_, SIGINT, SIGTERM);
|
|
||||||
signals.async_wait([&](auto sig, auto g) {
|
|
||||||
logger.info("Received signal: {} {}. Shutting down.", sig, g);
|
|
||||||
});
|
|
||||||
|
|
||||||
co_spawn(io_context_, connect_to_websocket(), detached);
|
|
||||||
co_spawn(io_context_, connect_to_server(), detached);
|
|
||||||
|
|
||||||
io_context_.run();
|
|
||||||
|
|
||||||
return std::make_error_code(std::errc::no_link);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
std::error_code parselink::client::create_and_run(config const& cfg) noexcept {
|
|
||||||
simple_client client(cfg);
|
|
||||||
return client.run();
|
|
||||||
}
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: Client
|
|
||||||
//
|
|
||||||
// Client interface.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#ifndef client_d7b353c402e38bfe
|
|
||||||
#define client_d7b353c402e38bfe
|
|
||||||
|
|
||||||
#include <concepts>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <system_error>
|
|
||||||
|
|
||||||
namespace parselink {
|
|
||||||
|
|
||||||
namespace client {
|
|
||||||
|
|
||||||
struct config {
|
|
||||||
std::string server_address;
|
|
||||||
std::uint16_t server_port;
|
|
||||||
std::string websocket_address;
|
|
||||||
std::uint16_t websocket_port;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
concept interface =
|
|
||||||
std::is_constructible_v<T, config const&> && requires(T& client) {
|
|
||||||
{ client.run() } -> std::same_as<std::error_code>;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::error_code create_and_run(config const& cfg) noexcept;
|
|
||||||
|
|
||||||
} // namespace client
|
|
||||||
} // namespace parselink
|
|
||||||
|
|
||||||
#endif // client_d7b353c402e38bfe
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: Client
|
|
||||||
//
|
|
||||||
// Client entrypoint. Should load config.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#include "client.h"
|
|
||||||
|
|
||||||
#include "parselink/logging.h"
|
|
||||||
#include "parselink/utility/argparse.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
parselink::logging::logger logger("main");
|
|
||||||
|
|
||||||
using level = parselink::logging::level;
|
|
||||||
|
|
||||||
int run(std::span<std::string_view> arg_list) {
|
|
||||||
argparse::command_line_parser parser({
|
|
||||||
{"server", {std::string{"localhost"}}},
|
|
||||||
{"server_port", {std::uint16_t{9001}}},
|
|
||||||
{"websocket_port", {std::uint16_t{10501}}},
|
|
||||||
{"websocket_server", {std::string{"localhost"}}},
|
|
||||||
{"verbose", {false}},
|
|
||||||
});
|
|
||||||
|
|
||||||
auto v = parser.try_parse(arg_list)
|
|
||||||
.map([](decltype(parser)::result args) {
|
|
||||||
if (args.opt<bool>("verbose")) {
|
|
||||||
logger.set_threshold(level::trace);
|
|
||||||
}
|
|
||||||
|
|
||||||
parselink::client::config cfg;
|
|
||||||
cfg.server_address = args.opt<std::string>("server");
|
|
||||||
cfg.server_port =
|
|
||||||
args.opt<std::uint16_t>("server_port");
|
|
||||||
cfg.websocket_port =
|
|
||||||
args.opt<std::uint16_t>("websocket_port");
|
|
||||||
cfg.websocket_address =
|
|
||||||
args.opt<std::string>("websocket_server");
|
|
||||||
return parselink::client::create_and_run(cfg);
|
|
||||||
})
|
|
||||||
.map([](auto err) { return err.value(); })
|
|
||||||
.map_error([](auto ec) {
|
|
||||||
return int(std::errc::invalid_argument);
|
|
||||||
});
|
|
||||||
return v ? *v : v.error();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
// TODO(ksassenrath): Add configuration file to the mix.
|
|
||||||
|
|
||||||
std::vector<std::string_view> args;
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
|
||||||
args.emplace_back(argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return run(args);
|
|
||||||
}
|
|
||||||
@ -26,7 +26,7 @@ namespace {
|
|||||||
|
|
||||||
struct console_endpoint : public endpoint {
|
struct console_endpoint : public endpoint {
|
||||||
static constexpr std::string_view format_string =
|
static constexpr std::string_view format_string =
|
||||||
"{:%Y-%m-%d %H:%M:%S}.{:03} [{:^8}] {:>20} | {}\n";
|
"{:%Y-%m-%d %H:%M:%S}.{:03} [{:<8}] {:>20} | {}\n";
|
||||||
|
|
||||||
bool colored() const noexcept override { return true; }
|
bool colored() const noexcept override { return true; }
|
||||||
|
|
||||||
|
|||||||
@ -22,15 +22,12 @@
|
|||||||
#include "parselink/msgpack/core/unpacker.h"
|
#include "parselink/msgpack/core/unpacker.h"
|
||||||
|
|
||||||
namespace parselink {
|
namespace parselink {
|
||||||
|
|
||||||
namespace {
|
|
||||||
logging::logger logger{"parser"};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace proto {
|
namespace proto {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
logging::logger logger{"parser"};
|
||||||
|
|
||||||
constexpr auto assign(auto& param, msgpack::unpacker& unpacker) noexcept
|
constexpr auto assign(auto& param, msgpack::unpacker& unpacker) noexcept
|
||||||
-> tl::expected<void, error> {
|
-> tl::expected<void, error> {
|
||||||
auto do_assign = [¶m](auto&& v) { param = v; };
|
auto do_assign = [¶m](auto&& v) { param = v; };
|
||||||
@ -49,7 +46,7 @@ tl::expected<connect_message, error> parse_connect_message(
|
|||||||
constexpr static tl::unexpected<error> bad_data(error::bad_data);
|
constexpr static tl::unexpected<error> bad_data(error::bad_data);
|
||||||
|
|
||||||
auto type = unpacker.unpack<std::string_view>();
|
auto type = unpacker.unpack<std::string_view>();
|
||||||
if (!type || type != connect_message::name()) return bad_data;
|
if (!type || type != "connect") return bad_data;
|
||||||
|
|
||||||
auto entries = unpacker.unpack<msgpack::map_desc>();
|
auto entries = unpacker.unpack<msgpack::map_desc>();
|
||||||
if (!entries) return bad_data;
|
if (!entries) return bad_data;
|
||||||
@ -71,5 +68,3 @@ tl::expected<connect_message, error> parse_connect_message(
|
|||||||
|
|
||||||
} // namespace proto
|
} // namespace proto
|
||||||
} // namespace parselink
|
} // namespace parselink
|
||||||
|
|
||||||
parselink::logging::logger& parselink::get_logger() { return logger; }
|
|
||||||
|
|||||||
@ -57,6 +57,24 @@ using net::deferred;
|
|||||||
using net::detached;
|
using net::detached;
|
||||||
using net::use_awaitable;
|
using net::use_awaitable;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// TODO(ksassenrath): These are logging formatters for various boost/asio types.
|
||||||
|
// Not all code is exposed to them, so they cannot be defined inside the
|
||||||
|
// generic logging/formatters.h header. They should go somewhere else.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <>
|
||||||
|
struct parselink::logging::theme<boost::system::error_code>
|
||||||
|
: parselink::logging::static_theme<fmt::color::fire_brick> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<boost::system::error_code>
|
||||||
|
: fmt::formatter<std::string_view> {
|
||||||
|
template <typename FormatContext>
|
||||||
|
constexpr auto format(auto const& v, FormatContext& ctx) const {
|
||||||
|
return fmt::formatter<std::string_view>::format(v.message(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<tl::monostate> : fmt::formatter<std::string_view> {
|
struct fmt::formatter<tl::monostate> : fmt::formatter<std::string_view> {
|
||||||
constexpr auto format(auto const&, auto& ctx) const {
|
constexpr auto format(auto const&, auto& ctx) const {
|
||||||
@ -64,6 +82,77 @@ struct fmt::formatter<tl::monostate> : fmt::formatter<std::string_view> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<msgpack::token> {
|
||||||
|
template <typename ParseContext>
|
||||||
|
constexpr auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(msgpack::token const& v, FormatContext& ctx) const {
|
||||||
|
using parselink::logging::themed_arg;
|
||||||
|
auto out = fmt::format_to(
|
||||||
|
ctx.out(), "<msgpack {} = ", themed_arg(v.type()));
|
||||||
|
switch (v.type()) {
|
||||||
|
case msgpack::format::type::unsigned_int:
|
||||||
|
fmt::format_to(
|
||||||
|
out, "{}", themed_arg(*(v.get<std::uint64_t>())));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::signed_int:
|
||||||
|
out = fmt::format_to(
|
||||||
|
out, "{}", themed_arg(*(v.get<std::uint64_t>())));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::boolean:
|
||||||
|
out = fmt::format_to(out, "{}", themed_arg(*(v.get<bool>())));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::string:
|
||||||
|
out = fmt::format_to(
|
||||||
|
out, "{}", themed_arg(*(v.get<std::string_view>())));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::binary:
|
||||||
|
out = fmt::format_to(out, "{}",
|
||||||
|
themed_arg(*(v.get<std::span<std::byte const>>())));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::map:
|
||||||
|
out = fmt::format_to(out, "(arity: {})",
|
||||||
|
themed_arg(v.get<msgpack::map_desc>()->count));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::array:
|
||||||
|
out = fmt::format_to(out, "(arity: {})",
|
||||||
|
themed_arg(v.get<msgpack::array_desc>()->count));
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::nil:
|
||||||
|
out = fmt::format_to(out, "(nil)");
|
||||||
|
break;
|
||||||
|
case msgpack::format::type::invalid:
|
||||||
|
out = fmt::format_to(out, "(invalid)");
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return fmt::format_to(out, ">");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept endpoint = requires(T const& t) {
|
||||||
|
{ t.address() };
|
||||||
|
{ t.port() };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <endpoint T>
|
||||||
|
struct parselink::logging::theme<T>
|
||||||
|
: parselink::logging::static_theme<fmt::color::coral> {};
|
||||||
|
|
||||||
|
template <endpoint T>
|
||||||
|
struct fmt::formatter<T> : fmt::formatter<std::string_view> {
|
||||||
|
template <typename FormatContext>
|
||||||
|
constexpr auto format(auto const& v, FormatContext& ctx) const {
|
||||||
|
return fmt::format_to(
|
||||||
|
ctx.out(), "{}:{}", v.address().to_string(), v.port());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// End formatters
|
// End formatters
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1,21 +1,13 @@
|
|||||||
# parselink
|
# parselink
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "headers",
|
|
||||||
hdrs = [
|
|
||||||
"//include/parselink:server.h",
|
|
||||||
],
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "server",
|
name = "server",
|
||||||
srcs = [
|
srcs = [
|
||||||
"memory_session_manager.cpp",
|
"memory_session_manager.cpp",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//include/parselink:msgpack",
|
|
||||||
"//include/parselink:proto",
|
"//include/parselink:proto",
|
||||||
|
"//include/parselink:msgpack",
|
||||||
"//include/parselink:server",
|
"//include/parselink:server",
|
||||||
"//source/logging",
|
"//source/logging",
|
||||||
"@hydrogen",
|
"@hydrogen",
|
||||||
@ -26,53 +18,3 @@ cc_library(
|
|||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
|
||||||
name = "udp_server",
|
|
||||||
srcs = [
|
|
||||||
"udp_server.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"headers",
|
|
||||||
"//include/parselink:msgpack",
|
|
||||||
"//include/parselink:proto",
|
|
||||||
"//include/parselink:server",
|
|
||||||
"//include/parselink:utility",
|
|
||||||
"//source/logging",
|
|
||||||
"@hydrogen",
|
|
||||||
"@boost//:asio",
|
|
||||||
],
|
|
||||||
visibility = [
|
|
||||||
# TODO: Fix visibility
|
|
||||||
"//visibility:public",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_binary(
|
|
||||||
name = "udp_parselinkd",
|
|
||||||
srcs = [
|
|
||||||
"main.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"//source/logging",
|
|
||||||
"//source/proto",
|
|
||||||
":udp_server",
|
|
||||||
"@boost//:beast",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
cc_binary(
|
|
||||||
name = "parselinkd",
|
|
||||||
srcs = [
|
|
||||||
"main.cpp",
|
|
||||||
"monolithic_server.cpp",
|
|
||||||
],
|
|
||||||
deps = [
|
|
||||||
"headers",
|
|
||||||
"//include/parselink:utility",
|
|
||||||
"//source/logging",
|
|
||||||
"//source/proto",
|
|
||||||
":server",
|
|
||||||
"@boost//:beast",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|||||||
@ -1,93 +0,0 @@
|
|||||||
#include "parselink/server.h"
|
|
||||||
|
|
||||||
#include "parselink/logging.h"
|
|
||||||
#include "parselink/msgpack/core/packer.h"
|
|
||||||
#include "parselink/msgpack/core/unpacker.h"
|
|
||||||
#include "parselink/proto/parser.h"
|
|
||||||
#include "parselink/proto/session.h"
|
|
||||||
#include "parselink/utility/file.h"
|
|
||||||
|
|
||||||
#include <boost/asio/as_tuple.hpp>
|
|
||||||
#include <boost/asio/co_spawn.hpp>
|
|
||||||
#include <boost/asio/deferred.hpp>
|
|
||||||
#include <boost/asio/detached.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp>
|
|
||||||
#include <boost/asio/ip/address.hpp>
|
|
||||||
#include <boost/asio/ip/udp.hpp>
|
|
||||||
#include <boost/asio/signal_set.hpp>
|
|
||||||
|
|
||||||
#include <fmt/ranges.h>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
using namespace parselink;
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
|
||||||
|
|
||||||
namespace net = boost::asio;
|
|
||||||
using udp = net::ip::udp;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
logging::logger logger{"udp.server"};
|
|
||||||
constexpr auto no_ex_coro = net::as_tuple(net::use_awaitable);
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class udp_server : public server {
|
|
||||||
public:
|
|
||||||
udp_server(std::string_view address, std::uint16_t port) noexcept;
|
|
||||||
|
|
||||||
std::error_code run() noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
net::awaitable<void> listen() noexcept;
|
|
||||||
|
|
||||||
net::io_context io_context_;
|
|
||||||
udp::endpoint local_endpoint_;
|
|
||||||
std::map<udp::endpoint, int> remotes_;
|
|
||||||
};
|
|
||||||
|
|
||||||
udp_server::udp_server(std::string_view address, std::uint16_t port) noexcept
|
|
||||||
: io_context_{1}
|
|
||||||
, local_endpoint_{
|
|
||||||
net::ip::address::from_string(std::string{address}), port} {
|
|
||||||
// Load keys, config data from file.
|
|
||||||
logger.debug("Creating server.");
|
|
||||||
}
|
|
||||||
|
|
||||||
net::awaitable<void> udp_server::listen() noexcept {
|
|
||||||
auto exec = co_await net::this_coro::executor;
|
|
||||||
logger.debug("Binding listener socket to {}.", local_endpoint_);
|
|
||||||
udp::socket listener{exec, local_endpoint_};
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
udp::endpoint remote;
|
|
||||||
std::array<std::byte, 4096> buff;
|
|
||||||
auto [ec, br] = co_await listener.async_receive_from(
|
|
||||||
net::buffer(buff), remote, no_ex_coro);
|
|
||||||
if (!ec) {
|
|
||||||
auto sp = std::span(buff.begin(), br);
|
|
||||||
logger.debug("From {}: {}", remote, std::span(buff.begin(), br));
|
|
||||||
msgpack::unpacker unpacker(sp);
|
|
||||||
unpacker.unpack<proto::error_message>()
|
|
||||||
.map([](auto msg) { logger.debug("Got error message"); })
|
|
||||||
.map_error([](auto err) {
|
|
||||||
logger.error("Error getting msg: {}", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
co_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::error_code udp_server::run() noexcept {
|
|
||||||
co_spawn(io_context_, listen(), net::detached);
|
|
||||||
|
|
||||||
io_context_.run();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<server> parselink::make_server(
|
|
||||||
std::string_view address, std::uint16_t user_port, std::uint16_t) {
|
|
||||||
using impl = udp_server;
|
|
||||||
return std::make_unique<impl>(address, user_port);
|
|
||||||
}
|
|
||||||
@ -5,9 +5,5 @@ cc_test(
|
|||||||
"*.cpp",
|
"*.cpp",
|
||||||
"*.h",
|
"*.h",
|
||||||
]),
|
]),
|
||||||
deps = [
|
deps = ["//tests/msgpack:common", "@rapidcheck"],
|
||||||
"//tests/msgpack:common",
|
|
||||||
"@rapidcheck",
|
|
||||||
"@boost//:pfr",
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
//-----------------------------------------------------------------------------
|
|
||||||
// ___ __ _ _
|
|
||||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
|
||||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
|
||||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
|
||||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Author: Kurt Sassenrath
|
|
||||||
// Module: msgpack
|
|
||||||
//
|
|
||||||
// Unpacker tests for maps.
|
|
||||||
//
|
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
|
||||||
//
|
|
||||||
// License TBD.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#include "parselink/msgpack/core/detail/unpack_map.h"
|
|
||||||
#include "parselink/utility/ctstring.h"
|
|
||||||
#include "test_unpacker.h"
|
|
||||||
|
|
||||||
#include "parselink/utility/ctreflect.h"
|
|
||||||
|
|
||||||
#include <fmt/ranges.h>
|
|
||||||
|
|
||||||
using namespace boost::ut;
|
|
||||||
|
|
||||||
struct S {
|
|
||||||
int abra;
|
|
||||||
int bar;
|
|
||||||
int cat;
|
|
||||||
int dog;
|
|
||||||
int lbue;
|
|
||||||
int bue;
|
|
||||||
int ue;
|
|
||||||
};
|
|
||||||
|
|
||||||
suite test_on_key = [] {
|
|
||||||
"on_key<int>"_test = [] {
|
|
||||||
bool expected = false;
|
|
||||||
auto key = msgpack::map::on_key<5>([&] { expected = true; });
|
|
||||||
expect(!expected);
|
|
||||||
key.handler();
|
|
||||||
expect(expected);
|
|
||||||
};
|
|
||||||
"on_key<string>"_test = [] {
|
|
||||||
bool expected = false;
|
|
||||||
auto key = msgpack::map::on_key<"hello">([&] { expected = true; });
|
|
||||||
expect(!expected);
|
|
||||||
key.handler();
|
|
||||||
expect(expected);
|
|
||||||
};
|
|
||||||
|
|
||||||
"key_group<int>"_test = [] {
|
|
||||||
auto keys = msgpack::map::key_group(
|
|
||||||
msgpack::map::on_key<5>([] {}), msgpack::map::on_key<1>([] {}));
|
|
||||||
constexpr auto size = decltype(keys)::size;
|
|
||||||
constexpr auto first_key = get_key(std::get<0>(keys.keys_));
|
|
||||||
constexpr auto second_key = get_key(std::get<1>(keys.keys_));
|
|
||||||
static_assert(size == 2);
|
|
||||||
expect(first_key == 5);
|
|
||||||
expect(second_key == 1);
|
|
||||||
};
|
|
||||||
"key_group<string>"_test = [] {
|
|
||||||
auto keys =
|
|
||||||
msgpack::map::key_group(msgpack::map::on_key<"hello">([] {}),
|
|
||||||
msgpack::map::on_key<"world">([] {}));
|
|
||||||
constexpr auto size = decltype(keys)::size;
|
|
||||||
constexpr auto first_key = get_key(std::get<0>(keys.keys_));
|
|
||||||
constexpr auto second_key = get_key(std::get<1>(keys.keys_));
|
|
||||||
static_assert(size == 2);
|
|
||||||
expect(first_key == "hello");
|
|
||||||
expect(second_key == "world");
|
|
||||||
};
|
|
||||||
"key_group_from_struct_names"_test = [] {
|
|
||||||
constexpr auto namefn = parselink::ct::member_name<S, 1>();
|
|
||||||
static_assert(parselink::ct::member_name<S, 1>() == "bar");
|
|
||||||
fmt::print("{}\n", namefn);
|
|
||||||
constexpr auto names = parselink::ct::member_names<S>();
|
|
||||||
fmt::print("{}\n", names);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -9,7 +9,7 @@
|
|||||||
// Author: Kurt Sassenrath
|
// Author: Kurt Sassenrath
|
||||||
// Module: msgpack
|
// Module: msgpack
|
||||||
//
|
//
|
||||||
// Unpacker tests for unsigned integers.
|
// Default packer tests.
|
||||||
//
|
//
|
||||||
// Copyright (c) 2023 Kurt Sassenrath.
|
// Copyright (c) 2023 Kurt Sassenrath.
|
||||||
//
|
//
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user