Compare commits
2 Commits
main
...
client_imp
| Author | SHA1 | Date | |
|---|---|---|---|
| 29d7ad94f1 | |||
| 2522bd5830 |
@ -27,12 +27,11 @@
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
// Simple wrapper for error strings to be formatted like any other string_view.
|
||||
template <>
|
||||
struct fmt::formatter<parselink::logging::error_str>
|
||||
: fmt::formatter<std::string_view> {
|
||||
template <error_code Err>
|
||||
struct fmt::formatter<Err> : 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.v, ctx);
|
||||
return fmt::formatter<std::string_view>::format(v.message(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@ -150,4 +149,13 @@ 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
|
||||
|
||||
@ -98,14 +98,14 @@ template <typename E>
|
||||
struct theme<E> : static_theme<fmt::color::gray> {};
|
||||
|
||||
// Errors
|
||||
template <>
|
||||
struct theme<std::error_code> : static_theme<fmt::color::fire_brick> {};
|
||||
template <error_code Err>
|
||||
struct theme<Err> : static_theme<fmt::color::fire_brick> {};
|
||||
|
||||
template <>
|
||||
struct theme<std::errc> : static_theme<fmt::color::fire_brick> {};
|
||||
|
||||
template <>
|
||||
struct theme<error_str> : static_theme<fmt::color::fire_brick> {};
|
||||
template <endpoint T>
|
||||
struct theme<T> : static_theme<fmt::color::coral> {};
|
||||
|
||||
template <>
|
||||
struct theme<bool> {
|
||||
|
||||
@ -22,6 +22,22 @@
|
||||
#include <memory>
|
||||
#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 logging {
|
||||
|
||||
@ -41,16 +57,6 @@ struct enum_name_only {
|
||||
template <typename 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 {
|
||||
|
||||
// The following concepts aim to describe both raw and smart pointers in a
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
||||
#define PARSELINK_MSGPACK_TOKEN_API
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace detail {
|
||||
|
||||
@ -36,6 +36,10 @@
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
||||
#define PARSELINK_MSGPACK_TOKEN_API
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
// This API is _currently_ optimizing on the fact that most desktop/server
|
||||
|
||||
@ -27,7 +27,9 @@
|
||||
#include <bits/iterator_concepts.h>
|
||||
#include <ranges>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
||||
#define PARSELINK_MSGPACK_TOKEN_API
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
@ -28,6 +28,10 @@
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef PARSELINK_MSGPACK_TOKEN_API
|
||||
#define PARSELINK_MSGPACK_TOKEN_API
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
enum class writer_error {
|
||||
|
||||
@ -33,6 +33,8 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <tl/expected.hpp>
|
||||
|
||||
// Simple command line parser for testing executables.
|
||||
|
||||
namespace argparse {
|
||||
@ -260,6 +262,15 @@ public:
|
||||
: 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>
|
||||
T const& opt(std::string_view opt_name) const {
|
||||
auto const* v = maybe_opt<T>(opt_name);
|
||||
@ -287,6 +298,15 @@ public:
|
||||
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) {
|
||||
return parse_inner(arglist);
|
||||
}
|
||||
|
||||
118
include/parselink/utility/ctstring.h
Normal file
118
include/parselink/utility/ctstring.h
Normal file
@ -0,0 +1,118 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// ___ __ _ _
|
||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
#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
|
||||
33
source/BUILD
33
source/BUILD
@ -1,24 +1,31 @@
|
||||
cc_library(
|
||||
name = "headers",
|
||||
hdrs = [
|
||||
"//include/parselink:server.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "parselinkd",
|
||||
cc_library(
|
||||
name = "client",
|
||||
srcs = [
|
||||
"main.cpp",
|
||||
"server.cpp",
|
||||
"client.h",
|
||||
"client.cpp",
|
||||
],
|
||||
deps = [
|
||||
"headers",
|
||||
"//include/parselink:msgpack",
|
||||
"//include/parselink:proto",
|
||||
"//include/parselink:utility",
|
||||
"//source/logging",
|
||||
"//source/proto",
|
||||
"//source/server",
|
||||
"@hydrogen",
|
||||
"@boost//:asio",
|
||||
"@boost//:beast",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:private"
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "parselink",
|
||||
srcs = [
|
||||
"main.cpp",
|
||||
],
|
||||
deps = [
|
||||
"client"
|
||||
],
|
||||
)
|
||||
|
||||
33
source/client/BUILD
Normal file
33
source/client/BUILD
Normal file
@ -0,0 +1,33 @@
|
||||
# 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"
|
||||
],
|
||||
)
|
||||
134
source/client/client.cpp
Normal file
134
source/client/client.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// ___ __ _ _
|
||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 <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/tcp.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;
|
||||
|
||||
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...");
|
||||
net::ip::tcp::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;
|
||||
}
|
||||
|
||||
net::ip::tcp::socket socket(io_context_);
|
||||
|
||||
logger.debug("Attempting connection with {}", results.begin()->endpoint());
|
||||
auto [ec2] = co_await socket.async_connect(*results.begin(), no_ex_coro);
|
||||
if (ec2) {
|
||||
logger.error("connection to {} failed: {}", results.begin()->endpoint(),
|
||||
ec2);
|
||||
co_return;
|
||||
}
|
||||
|
||||
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) {
|
||||
logger.info("Received signal: {}. Shutting down.", sig);
|
||||
});
|
||||
|
||||
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();
|
||||
}
|
||||
48
source/client/client.h
Normal file
48
source/client/client.h
Normal file
@ -0,0 +1,48 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// ___ __ _ _
|
||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
71
source/client/main.cpp
Normal file
71
source/client/main.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// ___ __ _ _
|
||||
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
|
||||
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
|
||||
// / ___/ (_| | | \__ \ __/ /__| | | | | <
|
||||
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 {
|
||||
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; }
|
||||
|
||||
|
||||
@ -6,8 +6,8 @@ cc_library(
|
||||
"memory_session_manager.cpp",
|
||||
],
|
||||
deps = [
|
||||
"//include/parselink:proto",
|
||||
"//include/parselink:msgpack",
|
||||
"//include/parselink:proto",
|
||||
"//include/parselink:server",
|
||||
"//source/logging",
|
||||
"@hydrogen",
|
||||
@ -18,3 +18,27 @@ cc_library(
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "headers",
|
||||
hdrs = [
|
||||
"//include/parselink:server.h",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "parselinkd",
|
||||
srcs = [
|
||||
"main.cpp",
|
||||
"monolithic_server.cpp",
|
||||
],
|
||||
deps = [
|
||||
"headers",
|
||||
"//include/parselink:utility",
|
||||
"//source/logging",
|
||||
"//source/proto",
|
||||
":server",
|
||||
"@boost//:beast",
|
||||
],
|
||||
)
|
||||
|
||||
@ -57,24 +57,6 @@ using net::deferred;
|
||||
using net::detached;
|
||||
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 <>
|
||||
struct fmt::formatter<tl::monostate> : fmt::formatter<std::string_view> {
|
||||
constexpr auto format(auto const&, auto& ctx) const {
|
||||
@ -82,77 +64,6 @@ 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
|
||||
//-----------------------------------------------------------------------------
|
||||
Loading…
Reference in New Issue
Block a user