Various updates to initial server code.
Need to create user sessions and handle msgpack-encoded packets. The plan is to use a branch of oh::msgpack with tl::expected.
This commit is contained in:
parent
eab689909d
commit
ec3b953384
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|||||||
@ -77,14 +77,22 @@ struct fmt::formatter<parselink::logging::enum_name_only<E>>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<std::error_code> : fmt::formatter<std::string_view> {
|
||||||
|
template<typename FormatContext>
|
||||||
|
auto format(auto const& v, FormatContext& ctx) const {
|
||||||
|
return fmt::formatter<std::string_view>::format(v.message(), ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Support conversion of typical standard error codes into a human-readable
|
// Support conversion of typical standard error codes into a human-readable
|
||||||
// string.
|
// string.
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<std::errc> : fmt::formatter<std::string_view> {
|
struct fmt::formatter<std::errc> : fmt::formatter<std::error_code> {
|
||||||
template<typename FormatContext>
|
template<typename FormatContext>
|
||||||
auto format(std::errc const& v, FormatContext& ctx) const {
|
auto format(std::errc const& v, FormatContext& ctx) const {
|
||||||
return fmt::formatter<std::string_view>::format(
|
return fmt::formatter<std::error_code>::format(
|
||||||
std::make_error_code(v).message(), ctx);
|
std::make_error_code(v), ctx);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -84,12 +84,18 @@ template <typename E>
|
|||||||
requires std::is_enum_v<E>
|
requires std::is_enum_v<E>
|
||||||
struct theme<E> : static_theme<fmt::color::gray> {};
|
struct theme<E> : static_theme<fmt::color::gray> {};
|
||||||
|
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
template <>
|
||||||
|
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 <>
|
template <>
|
||||||
struct theme<error_str> : static_theme<fmt::color::fire_brick> {};
|
struct theme<error_str> : static_theme<fmt::color::fire_brick> {};
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct theme<enum_name_only<logging::level>> {
|
struct theme<enum_name_only<logging::level>> {
|
||||||
constexpr static fmt::color colors[] = {
|
constexpr static fmt::color colors[] = {
|
||||||
|
|||||||
@ -22,18 +22,75 @@
|
|||||||
#include <server.h>
|
#include <server.h>
|
||||||
|
|
||||||
#include <boost/asio/io_context.hpp>
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/signal_set.hpp>
|
||||||
|
#include <boost/asio/redirect_error.hpp>
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
|
|
||||||
#include <boost/asio/ip/address.hpp>
|
#include <boost/asio/ip/address.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
#include <boost/asio/signal_set.hpp>
|
|
||||||
|
#include <boost/asio/co_spawn.hpp>
|
||||||
|
#include <boost/asio/deferred.hpp>
|
||||||
|
#include <boost/asio/detached.hpp>
|
||||||
|
#include <boost/asio/as_tuple.hpp>
|
||||||
|
|
||||||
|
using namespace parselink;
|
||||||
|
|
||||||
namespace net = boost::asio;
|
namespace net = boost::asio;
|
||||||
using namespace parselink;
|
using net::co_spawn;
|
||||||
|
using net::awaitable;
|
||||||
|
using net::use_awaitable;
|
||||||
|
using net::deferred;
|
||||||
|
using net::detached;
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 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 <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
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
logging::logger logger("server");
|
logging::logger logger("server");
|
||||||
|
constexpr auto no_ex_coro = net::as_tuple(use_awaitable);
|
||||||
|
constexpr auto no_ex_defer = net::as_tuple(deferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class monolithic_server : public server {
|
class monolithic_server : public server {
|
||||||
public:
|
public:
|
||||||
monolithic_server(std::string_view address, std::uint16_t user_port,
|
monolithic_server(std::string_view address, std::uint16_t user_port,
|
||||||
@ -42,9 +99,14 @@ public:
|
|||||||
std::error_code run() noexcept override;
|
std::error_code run() noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
awaitable<void> echo(net::ip::tcp::socket socket);
|
||||||
|
awaitable<void> user_listen();
|
||||||
|
|
||||||
net::io_context io_context_;
|
net::io_context io_context_;
|
||||||
net::ip::address addr_;
|
net::ip::address addr_;
|
||||||
net::ip::tcp::acceptor user_acceptor_;
|
std::uint16_t user_port_;
|
||||||
|
std::uint16_t websocket_port_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -52,10 +114,36 @@ monolithic_server::monolithic_server(std::string_view address,
|
|||||||
std::uint16_t user_port, std::uint16_t websocket_port)
|
std::uint16_t user_port, std::uint16_t websocket_port)
|
||||||
: io_context_{1}
|
: io_context_{1}
|
||||||
, addr_(net::ip::address::from_string(std::string{address}))
|
, addr_(net::ip::address::from_string(std::string{address}))
|
||||||
, user_acceptor_{io_context_, {addr_, user_port}} {
|
, user_port_{user_port}
|
||||||
logger.debug("Creating monolithic_server with"
|
, websocket_port_{websocket_port} {
|
||||||
"\n\taddress {},\n\tuser_port {},\n\twebsocket_port {}",
|
logger.debug("Creating monolithic_server(address = {}, user_port = {}, "
|
||||||
address, user_port, websocket_port);
|
"websocket_port = {})", address, user_port_, websocket_port_);
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitable<void> monolithic_server::echo(net::ip::tcp::socket socket) {
|
||||||
|
std::array<std::byte, 4096> buffer;
|
||||||
|
while (true) {
|
||||||
|
auto [ec, n] = co_await socket.async_read_some(net::buffer(buffer), no_ex_coro);
|
||||||
|
if (ec) {
|
||||||
|
logger.error("Read from socket failed: {}", ec);
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
auto [ec2, x] = co_await net::async_write(socket, net::buffer(buffer, n), no_ex_coro);
|
||||||
|
if (ec2) {
|
||||||
|
logger.error("Write to socket failed: {}", ec);
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
awaitable<void> monolithic_server::user_listen() {
|
||||||
|
auto exec = co_await net::this_coro::executor;
|
||||||
|
net::ip::tcp::acceptor acceptor{exec, {addr_, user_port_}};
|
||||||
|
while (true) {
|
||||||
|
auto socket = co_await acceptor.async_accept(use_awaitable);
|
||||||
|
logger.debug("Accepted new connection from {}", socket.remote_endpoint());
|
||||||
|
co_spawn(exec, echo(std::move(socket)), detached);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code monolithic_server::run() noexcept {
|
std::error_code monolithic_server::run() noexcept {
|
||||||
@ -67,6 +155,8 @@ std::error_code monolithic_server::run() noexcept {
|
|||||||
io_context_.stop();
|
io_context_.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
co_spawn(io_context_, user_listen(), detached);
|
||||||
|
|
||||||
io_context_.run();
|
io_context_.run();
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user