Formatting
publish / publish (push) Successful in 27m34s

This commit is contained in:
khodowany
2026-09-14 23:54:56 -05:00
parent 6914712d20
commit 4170d3a003
26 changed files with 668 additions and 621 deletions
+4
View File
@@ -48,6 +48,10 @@ jobs:
restore-keys: conan-${{ runner.os }}-
- name: Configure native release
run: python3 modulus.py configure --target x86_64_gcc12_release
- name: Check code style
run: |
python3 -m pip install --no-cache-dir -r build/build_tools/docker/format-requirements.txt
python3 modulus.py format --check
- name: Build native release
run: python3 modulus.py build --target x86_64_gcc12_release
- name: Test native release
+2
View File
@@ -6,6 +6,8 @@ Ligo uses Modulus for shared build tooling, Boost.JSON, and OpenSSL integration.
## Build
Code style is managed by Modulus: run `./modulus.py format` or `./modulus.py format --check`. The generated Neovim integration uses the same pinned container formatter for C++ and Python, including existing format-on-save toggles. Configure first to prepare tooling; customize `tooling.editor.clang_format` and `tooling.format.exclude` in `modulus.json`, not generated editor files. See the shared Modulus README for the compact layout and no-alias policy.
Configure, build, and test the default target:
```sh
-8
View File
@@ -41,15 +41,12 @@ class ligo_conan(conan.ConanFile):
"tests/*.cpp",
"tests/*.hpp",
)
def config_options(self):
if self.settings.os == "Windows":
del self.options.fPIC
def configure(self):
if self.options.shared:
del self.options.fPIC
def requirements(self):
self.requires(
"modulus/latest",
@@ -59,7 +56,6 @@ class ligo_conan(conan.ConanFile):
"with_openssl": True,
},
)
def generate(self):
deps = conan.tools.cmake.CMakeDeps(self)
deps.generate()
@@ -69,14 +65,12 @@ class ligo_conan(conan.ConanFile):
toolchain.variables["BUILD_SHARED_LIBS"] = bool(self.options.shared)
toolchain.variables["BUILD_TESTING"] = bool(self.options.with_tests)
toolchain.generate()
def build(self):
cmake = conan.tools.cmake.CMake(self)
cmake.configure()
cmake.build()
if self.options.with_tests and conan.tools.build.can_run(self):
cmake.test(target="check")
def package_id(self):
self.info.options.rm_safe("with_tests")
for requirement in (
@@ -88,11 +82,9 @@ class ligo_conan(conan.ConanFile):
):
if requirement in self.info.requires.pkg_names:
self.info.requires.remove(requirement)
def package(self):
cmake = conan.tools.cmake.CMake(self)
cmake.install()
def package_info(self):
self.cpp_info.set_property(
"cmake_file_name",
+1
View File
@@ -12,6 +12,7 @@
#include <ligo/security.hpp>
namespace ligo {
enum class protocol {
+1
View File
@@ -8,6 +8,7 @@
#include <modulus.hpp>
namespace ligo::detail {
constexpr std::int32_t error_ok{0};
+1
View File
@@ -25,6 +25,7 @@
#include <ligo/detail/errors.hpp>
#include <ligo/detail/transport.hpp>
namespace ligo::detail {
auto cancel_session_stream(boost::beast::tcp_stream &stream) -> void;
+5 -2
View File
@@ -7,6 +7,7 @@
#include <modulus.hpp>
namespace ligo::detail {
class state_handle {
@@ -49,7 +50,8 @@ private:
}
template <typename STATE>
ligo::detail::state_handle::state_handle(std::shared_ptr<STATE> state) : state_{std::shared_ptr<void>{std::move(state)}} {}
ligo::detail::state_handle::state_handle(std::shared_ptr<STATE> state)
: state_{std::shared_ptr<void>{std::move(state)}} {}
template <typename STATE>
auto ligo::detail::state_handle::as() const -> std::shared_ptr<STATE> {
@@ -57,7 +59,8 @@ auto ligo::detail::state_handle::as() const -> std::shared_ptr<STATE> {
}
template <typename STATE>
ligo::detail::unique_state::unique_state(std::unique_ptr<STATE> state) : state_{state.release(), delete_state<STATE>} {}
ligo::detail::unique_state::unique_state(std::unique_ptr<STATE> state)
: state_{state.release(), delete_state<STATE>} {}
template <typename STATE>
auto ligo::detail::unique_state::as() const noexcept -> STATE * {
+1
View File
@@ -28,6 +28,7 @@
#include <ligo/detail/errors.hpp>
#include <ligo/service.hpp>
namespace ligo::detail {
struct endpoint_parts {
+1
View File
@@ -11,6 +11,7 @@
#include <modulus.hpp>
namespace ligo {
enum class security_mode {
+1
View File
@@ -13,6 +13,7 @@
#include <modulus.hpp>
namespace ligo {
struct request_context {
+2 -1
View File
@@ -123,6 +123,7 @@ auto connect(boost::asio::any_io_executor executor, ligo::endpoint_config const&
auto connect_tls_configured(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::tcp::client_options options = {}, ligo::security_config security = {.mode = ligo::security_mode::TLS}) -> boost::asio::awaitable<std::expected<ligo::tcp::tls_socket, modulus::error>>;
auto connect_tls_handshaken(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::tcp::client_options options = {}, ligo::security_config security = {.mode = ligo::security_mode::TLS}) -> boost::asio::awaitable<std::expected<ligo::tcp::tls_socket, modulus::error>>;
inline tls_socket::released_stream::released_stream(std::shared_ptr<boost::asio::ssl::context> context, boost::asio::ssl::stream<boost::asio::ip::tcp::socket> stream) : context{std::move(context)}, stream{std::move(stream)} {}
inline tls_socket::released_stream::released_stream(std::shared_ptr<boost::asio::ssl::context> context, boost::asio::ssl::stream<boost::asio::ip::tcp::socket> stream)
: context{std::move(context)}, stream{std::move(stream)} {}
}
+6 -2
View File
@@ -16,6 +16,7 @@ COMMANDS = (
"package",
"lsp",
"clangd",
"format",
)
COMMON_DIR = pathlib.Path("build") / "build_common"
TOOLS_DIR = pathlib.Path("build") / "build_tools"
@@ -60,6 +61,9 @@ def runtime_ready(root):
and (root / TOOLS_DIR / "clangd.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "cli.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "export.py").is_file()
and (root / TOOLS_DIR / "format.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "formatting.py").is_file()
and (root / RUNTIME_DIR / "modulus" / "format_layout.py").is_file()
)
def optional_credentials():
@@ -340,9 +344,9 @@ def ensure_runtime(root):
def delegate(command, argv):
root = repo_root()
if command == "clangd":
if command in {"clangd", "format"}:
if not runtime_ready(root):
print("Modulus clangd tooling is missing; run ./modulus.py configure first", file=sys.stderr)
print(f"Modulus {command} tooling is missing; run ./modulus.py configure first", file=sys.stderr)
return 1
else:
ensure_runtime(root)
+14 -8
View File
@@ -17,13 +17,13 @@
#include <ligo/detail/errors.hpp>
#include <ligo/security.hpp>
namespace {
constexpr auto json_options = modulus::json_config::options{
.category = "ligo",
.invalid_argument_code = ligo::detail::error_invalid_argument,
.not_found_code = ligo::detail::error_not_found
};
.not_found_code = ligo::detail::error_not_found};
auto protocol_name(ligo::protocol value) -> std::string_view {
switch (value) {
@@ -73,7 +73,8 @@ auto parse_security_config(boost::json::value const& value) -> std::expected<lig
"ca_file",
"certificate_chain_file",
"private_key_file",
}, "endpoint security", json_options);
},
"endpoint security", json_options);
if (!unknown) {
return ligo::detail::fail<ligo::security_config>(unknown.error());
}
@@ -91,7 +92,8 @@ auto parse_security_config(boost::json::value const& value) -> std::expected<lig
.name = "dtls",
.value = ligo::security_mode::DTLS,
},
}, "endpoint security mode must be none, tls, or dtls", json_options);
},
"endpoint security mode must be none, tls, or dtls", json_options);
if (!mode) {
return ligo::detail::fail<ligo::security_config>(mode.error());
}
@@ -108,7 +110,8 @@ auto parse_security_config(boost::json::value const& value) -> std::expected<lig
.name = "peer",
.value = ligo::verify_mode::PEER,
},
}, "endpoint security verify must be defaulted, none, or peer", json_options);
},
"endpoint security verify must be defaulted, none, or peer", json_options);
if (!verify) {
return ligo::detail::fail<ligo::security_config>(verify.error());
}
@@ -175,7 +178,8 @@ auto ligo::parse_endpoint_config(boost::json::value const& value) -> std::expect
"security",
"http",
"udp",
}, "endpoint", json_options);
},
"endpoint", json_options);
if (!unknown) {
return ligo::detail::fail<ligo::endpoint_config>(unknown.error());
}
@@ -197,7 +201,8 @@ auto ligo::parse_endpoint_config(boost::json::value const& value) -> std::expect
.name = "udp",
.value = ligo::protocol::UDP,
},
}, "endpoint protocol must be http, tcp, or udp", json_options);
},
"endpoint protocol must be http, tcp, or udp", json_options);
if (!protocol) {
return ligo::detail::fail<ligo::endpoint_config>(protocol.error());
}
@@ -249,7 +254,8 @@ auto ligo::parse_endpoint_config(boost::json::value const& value) -> std::expect
"resend_interval_ms",
"max_in_flight",
"session_timeout_ms",
}, "endpoint udp", json_options);
},
"endpoint udp", json_options);
if (!udp_unknown) {
return ligo::detail::fail<ligo::endpoint_config>(udp_unknown.error());
}
+1
View File
@@ -5,6 +5,7 @@
#include <modulus.hpp>
#include <cstdint>
auto ligo::detail::make_error(std::int32_t code, std::string message, modulus::source_location location) -> modulus::error {
return modulus::make_error("ligo", code, std::move(message), location);
}
+1
View File
@@ -3,6 +3,7 @@
#include <boost/beast/core.hpp>
#include <boost/system/error_code.hpp>
auto ligo::detail::cancel_session_stream(boost::beast::tcp_stream &stream) -> void {
auto ignored = boost::system::error_code{};
stream.socket().cancel(ignored);
+3 -1
View File
@@ -30,6 +30,7 @@
#include <ligo/detail/state.hpp>
#include <ligo/service.hpp>
namespace {
auto error_status_code(boost::system::error_code const &error) -> std::int32_t {
@@ -47,7 +48,8 @@ auto error_status_code(boost::system::error_code const& error) -> std::int32_t {
}
ligo::detail::state_handle::state_handle(ligo::detail::state_handle&& other) noexcept : state_{other.state_.exchange(nullptr)} {}
ligo::detail::state_handle::state_handle(ligo::detail::state_handle &&other) noexcept
: state_{other.state_.exchange(nullptr)} {}
auto ligo::detail::state_handle::operator=(ligo::detail::state_handle &&other) noexcept -> ligo::detail::state_handle & {
if (this != &other) {
+10 -6
View File
@@ -43,6 +43,7 @@
#include <ligo/security.hpp>
#include <ligo/service.hpp>
namespace {
struct http_server_state {
@@ -544,19 +545,23 @@ auto call_http_endpoint(ligo::http::endpoint endpoint, std::shared_ptr<ligo::htt
co_return co_await read_http_response(stream, options.timeout, options.max_body_size);
}
http_server_state::http_server_state(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options) : executor{std::move(executor)}, strand{boost::asio::make_strand(this->executor)}, acceptor{std::make_shared<boost::asio::ip::tcp::acceptor>(strand)}, endpoint{std::move(endpoint)}, options{options}, router{std::make_shared<ligo::service_router>(std::move(router))} {}
http_server_state::http_server_state(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options)
: executor{std::move(executor)}, strand{boost::asio::make_strand(this->executor)}, acceptor{std::make_shared<boost::asio::ip::tcp::acceptor>(strand)}, endpoint{std::move(endpoint)}, options{options}, router{std::make_shared<ligo::service_router>(std::move(router))} {}
}
ligo::http::client::client(ligo::http::endpoint endpoint, ligo::http::client_options options) : endpoint_{std::move(endpoint)}, options_{options} {}
ligo::http::client::client(ligo::http::endpoint endpoint, ligo::http::client_options options)
: endpoint_{std::move(endpoint)}, options_{options} {}
auto ligo::http::client::call(ligo::http::request const &request) const -> boost::asio::awaitable<std::expected<boost::json::value, modulus::error>> {
return call_http_endpoint(endpoint_, std::make_shared<ligo::http::request const>(request), options_);
}
ligo::http::server::server(boost::asio::io_context& io, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options) : ligo::http::server{io.get_executor(), std::move(endpoint), std::move(router), options} {}
ligo::http::server::server(boost::asio::io_context &io, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options)
: ligo::http::server{io.get_executor(), std::move(endpoint), std::move(router), options} {}
ligo::http::server::server(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options) : state_{ligo::detail::state_handle{std::make_shared<http_server_state>(std::move(executor), std::move(endpoint), std::move(router), options)}} {}
ligo::http::server::server(boost::asio::any_io_executor executor, ligo::http::endpoint endpoint, ligo::service_router router, ligo::http::server_options options)
: state_{ligo::detail::state_handle{std::make_shared<http_server_state>(std::move(executor), std::move(endpoint), std::move(router), options)}} {}
ligo::http::server::~server() {
if (auto state = http_state(state_)) {
@@ -599,8 +604,7 @@ auto ligo::http::client_endpoint_from_config(ligo::endpoint_config const& config
}
return modulus::success(ligo::http::endpoint{
.host = std::move(parsed->host),
.port = parsed->port
});
.port = parsed->port});
}
auto ligo::http::server_endpoint_from_config(ligo::endpoint_config const &config) -> std::expected<ligo::http::endpoint, modulus::error> {
+11 -6
View File
@@ -37,6 +37,7 @@
#include <ligo/tcp.hpp>
#include <cstdint>
class ligo::net::byte_stream_state {
public:
byte_stream_state() = default;
@@ -53,7 +54,6 @@ public:
virtual auto is_open() const -> std::bool_t = 0;
};
namespace {
struct net_listener_state {
@@ -227,9 +227,11 @@ auto make_server_tls_context(ligo::security_config const& security) -> std::expe
return context;
}
net_listener_state::net_listener_state(boost::asio::any_io_executor executor) : strand{boost::asio::make_strand(std::move(executor))}, acceptor{strand} {}
net_listener_state::net_listener_state(boost::asio::any_io_executor executor)
: strand{boost::asio::make_strand(std::move(executor))}, acceptor{strand} {}
tcp_byte_stream_state::tcp_byte_stream_state(boost::asio::ip::tcp::socket socket) : socket_{std::make_shared<boost::asio::ip::tcp::socket>(std::move(socket))} {}
tcp_byte_stream_state::tcp_byte_stream_state(boost::asio::ip::tcp::socket socket)
: socket_{std::make_shared<boost::asio::ip::tcp::socket>(std::move(socket))} {}
auto tcp_byte_stream_state::async_read_some(boost::asio::mutable_buffer buffer, std::chrono::milliseconds timeout) -> boost::asio::awaitable<std::expected<std::size_t, modulus::error>> {
if (!is_open()) {
@@ -282,7 +284,8 @@ auto tcp_byte_stream_state::is_open() const -> std::bool_t {
return socket_ && socket_->is_open();
}
tls_byte_stream_state::tls_byte_stream_state(ligo::tcp::tls_socket::released_stream released) : context_{std::move(released.context)}, stream_{std::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>(std::move(released.stream))} {}
tls_byte_stream_state::tls_byte_stream_state(ligo::tcp::tls_socket::released_stream released)
: context_{std::move(released.context)}, stream_{std::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>(std::move(released.stream))} {}
auto tls_byte_stream_state::async_read_some(boost::asio::mutable_buffer buffer, std::chrono::milliseconds timeout) -> boost::asio::awaitable<std::expected<std::size_t, modulus::error>> {
if (!is_open()) {
@@ -402,7 +405,8 @@ auto ligo::net::byte_stream::is_open() const -> std::bool_t {
return false;
}
ligo::net::byte_stream::byte_stream(std::shared_ptr<ligo::net::byte_stream_state> state) : state_{std::move(state)} {}
ligo::net::byte_stream::byte_stream(std::shared_ptr<ligo::net::byte_stream_state> state)
: state_{std::move(state)} {}
ligo::net::listener::~listener() {
close();
@@ -487,7 +491,8 @@ auto ligo::net::listener::close() -> void {
close_listener(listener_state(state_));
}
ligo::net::listener::listener(ligo::detail::state_handle state) : state_{std::move(state)} {}
ligo::net::listener::listener(ligo::detail::state_handle state)
: state_{std::move(state)} {}
auto ligo::net::connect_tcp(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::tcp::client_options options) -> boost::asio::awaitable<std::expected<ligo::tcp::socket_handle, modulus::error>> {
co_return co_await ligo::tcp::connect(std::move(executor), std::move(endpoint), options);
+1
View File
@@ -19,6 +19,7 @@
#include <ligo/detail/errors.hpp>
#include <cstdint>
namespace {
auto ssl_failure(std::int32_t code, std::string message) -> modulus::error {
+1
View File
@@ -18,6 +18,7 @@
#include <ligo/detail/errors.hpp>
#include <ligo/detail/transport.hpp>
namespace {
auto json_content_type(std::string const &value) -> std::bool_t {
+15 -7
View File
@@ -46,6 +46,7 @@
#include <ligo/security.hpp>
#include <ligo/service.hpp>
namespace {
struct tcp_server_state {
@@ -496,13 +497,16 @@ auto validate_tls_connect_security(ligo::security_config const& security) -> std
return ligo::detail::fail_void(ligo::detail::error_invalid_argument, "TLS connect requires TLS security mode");
}
tcp_server_state::tcp_server_state(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options) : executor{std::move(executor)}, strand{boost::asio::make_strand(this->executor)}, acceptor{std::make_shared<boost::asio::ip::tcp::acceptor>(strand)}, endpoint{std::move(endpoint)}, options{options}, router{std::make_shared<ligo::service_router>(std::move(router))} {}
tcp_server_state::tcp_server_state(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options)
: executor{std::move(executor)}, strand{boost::asio::make_strand(this->executor)}, acceptor{std::make_shared<boost::asio::ip::tcp::acceptor>(strand)}, endpoint{std::move(endpoint)}, options{options}, router{std::make_shared<ligo::service_router>(std::move(router))} {}
}
ligo::tcp::socket_handle::socket_handle(boost::asio::ip::tcp::socket socket) : socket_{std::make_shared<boost::asio::ip::tcp::socket>(std::move(socket))} {}
ligo::tcp::socket_handle::socket_handle(boost::asio::ip::tcp::socket socket)
: socket_{std::make_shared<boost::asio::ip::tcp::socket>(std::move(socket))} {}
ligo::tcp::socket_handle::socket_handle(std::shared_ptr<boost::asio::ip::tcp::socket> socket) : socket_{std::move(socket)} {}
ligo::tcp::socket_handle::socket_handle(std::shared_ptr<boost::asio::ip::tcp::socket> socket)
: socket_{std::move(socket)} {}
auto ligo::tcp::socket_handle::socket() -> std::expected<std::reference_wrapper<boost::asio::ip::tcp::socket>, modulus::error> {
if (!socket_) {
@@ -540,7 +544,8 @@ auto ligo::tcp::socket_handle::release_socket() -> std::expected<boost::asio::ip
};
}
ligo::tcp::tls_socket::tls_socket(std::shared_ptr<boost::asio::ssl::context> context, boost::asio::ip::tcp::socket socket) : context_{std::move(context)} {
ligo::tcp::tls_socket::tls_socket(std::shared_ptr<boost::asio::ssl::context> context, boost::asio::ip::tcp::socket socket)
: context_{std::move(context)} {
if (context_) {
stream_ = std::make_unique<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>(std::move(socket), *context_);
}
@@ -597,7 +602,8 @@ auto ligo::tcp::tls_socket::release_stream() -> std::expected<ligo::tcp::tls_soc
};
}
ligo::tcp::client::client(ligo::tcp::endpoint endpoint, ligo::tcp::client_options options) : endpoint_{std::move(endpoint)}, options_{options} {}
ligo::tcp::client::client(ligo::tcp::endpoint endpoint, ligo::tcp::client_options options)
: endpoint_{std::move(endpoint)}, options_{options} {}
auto ligo::tcp::client::call(ligo::tcp::request const &request) const -> boost::asio::awaitable<std::expected<boost::json::value, modulus::error>> {
auto body = serialize_tcp_request(request);
@@ -607,9 +613,11 @@ auto ligo::tcp::client::call(ligo::tcp::request const& request) const -> boost::
return call_tcp_endpoint(endpoint_, std::make_shared<std::string const>(std::move(*body)), options_);
}
ligo::tcp::server::server(boost::asio::io_context& io, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options) : ligo::tcp::server{io.get_executor(), std::move(endpoint), std::move(router), options} {}
ligo::tcp::server::server(boost::asio::io_context &io, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options)
: ligo::tcp::server{io.get_executor(), std::move(endpoint), std::move(router), options} {}
ligo::tcp::server::server(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options) : state_{ligo::detail::state_handle{std::make_shared<tcp_server_state>(std::move(executor), std::move(endpoint), std::move(router), options)}} {}
ligo::tcp::server::server(boost::asio::any_io_executor executor, ligo::tcp::endpoint endpoint, ligo::service_router router, ligo::tcp::server_options options)
: state_{ligo::detail::state_handle{std::make_shared<tcp_server_state>(std::move(executor), std::move(endpoint), std::move(router), options)}} {}
ligo::tcp::server::~server() {
if (auto state = tcp_state(state_)) {
+9 -5
View File
@@ -48,6 +48,7 @@
#include <ligo/config.hpp>
#include <ligo/security.hpp>
namespace {
struct ssl_ctx_deleter {
@@ -704,7 +705,6 @@ auto send_payload_on_strand(std::shared_ptr<reliable_channel_state> state, boost
finish_send(state, sequence);
co_return ligo::detail::fail_void(sent.error());
}
if (state->acked.erase(sequence) > 0) {
finish_send(state, sequence);
co_return std::expected<void, modulus::error>{};
@@ -911,7 +911,8 @@ auto bio_deleter::operator()(BIO* bio) const noexcept -> void {
BIO_free(bio);
}
reliable_channel_state::reliable_channel_state(std::unique_ptr<boost::asio::ip::udp::socket> socket, boost::asio::ip::udp::endpoint local_endpoint, boost::asio::ip::udp::endpoint peer, ligo::udp_reliability_config config, ligo::security_config security, std::uint64_t session_id, std::unique_ptr<dtls_state> dtls) : socket{std::move(socket)}, local_endpoint{std::move(local_endpoint)}, peer{std::move(peer)}, config{config}, security{std::move(security)}, dtls{std::move(dtls)}, session_id{session_id} {
reliable_channel_state::reliable_channel_state(std::unique_ptr<boost::asio::ip::udp::socket> socket, boost::asio::ip::udp::endpoint local_endpoint, boost::asio::ip::udp::endpoint peer, ligo::udp_reliability_config config, ligo::security_config security, std::uint64_t session_id, std::unique_ptr<dtls_state> dtls)
: socket{std::move(socket)}, local_endpoint{std::move(local_endpoint)}, peer{std::move(peer)}, config{config}, security{std::move(security)}, dtls{std::move(dtls)}, session_id{session_id} {
notify_timer.expires_at(std::chrono::steady_clock::time_point::max());
close_timer.expires_at(std::chrono::steady_clock::time_point::max());
}
@@ -937,7 +938,8 @@ auto ligo::udp::client::open(boost::asio::any_io_executor executor, boost::asio:
0,
},
.peer = std::move(peer),
}, options);
},
options);
}
auto ligo::udp::client::open(boost::asio::io_context &io, boost::asio::ip::udp::endpoint peer, ligo::udp::client_options options) -> std::expected<ligo::udp::client, modulus::error> {
@@ -992,7 +994,8 @@ auto ligo::udp::client::async_close(std::chrono::milliseconds timeout) -> boost:
co_return co_await async_close_channel(channel_state(state_), timeout);
}
ligo::udp::client::client(ligo::detail::state_handle state) : state_{std::move(state)} {}
ligo::udp::client::client(ligo::detail::state_handle state)
: state_{std::move(state)} {}
ligo::udp::server::~server() {
close();
@@ -1054,7 +1057,8 @@ auto ligo::udp::server::async_close(std::chrono::milliseconds timeout) -> boost:
co_return co_await async_close_channel(channel_state(state_), timeout);
}
ligo::udp::server::server(ligo::detail::state_handle state) : state_{std::move(state)} {}
ligo::udp::server::server(ligo::detail::state_handle state)
: state_{std::move(state)} {}
auto ligo::udp::client_endpoint_from_config(ligo::endpoint_config const &config) -> std::expected<ligo::udp::endpoint, modulus::error> {
return endpoint_from_config(config);
+58 -56
View File
@@ -45,6 +45,7 @@
#include <test.hpp>
BOOST_AUTO_TEST_CASE(ligo_asserts_follow_build_type) {
#if defined(LIGO_EXPECT_NDEBUG) && !defined(NDEBUG)
BOOST_FAIL("release-style builds must define NDEBUG");
@@ -54,7 +55,6 @@ BOOST_AUTO_TEST_CASE(ligo_asserts_follow_build_type) {
#endif
}
namespace {
auto test_network_failure(boost::system::error_code const &error) -> modulus::error {
@@ -423,7 +423,8 @@ auto udp_client_bind(boost::asio::io_context& io, boost::asio::ip::udp::endpoint
return ligo::udp::client::bind(io, {
.local = std::move(local),
.peer = std::move(peer),
}, {
},
{
.reliability = config,
.session_id = session_id,
});
@@ -472,7 +473,8 @@ BOOST_AUTO_TEST_CASE(ligo_config_drives_http_tcp_and_udp_setup) {
};
auto config_text = std::string{
"{\"endpoints\":[",
}+ "{\"name\":\"http\",\"protocol\":\"http\",\"bind\":\"127.0.0.1:0\",\"timeout_ms\":1000}," + "{\"name\":\"tcp\",\"protocol\":\"tcp\",\"bind\":\"127.0.0.1:0\",\"timeout_ms\":1000}," + "{\"name\":\"udp-client\",\"protocol\":\"udp\",\"bind\":\"127.0.0.1:" + std::to_string(udp_client_endpoint.port()) + "\",\"connect\":\"127.0.0.1:" + std::to_string(udp_server_endpoint.port()) + "\",\"udp\":{\"resend_interval_ms\":5,\"max_in_flight\":2,\"session_timeout_ms\":1000}}," + "{\"name\":\"udp-server\",\"protocol\":\"udp\",\"bind\":\"127.0.0.1:" + std::to_string(udp_server_endpoint.port()) + "\",\"connect\":\"127.0.0.1:" + std::to_string(udp_client_endpoint.port()) + "\",\"udp\":{\"resend_interval_ms\":5,\"max_in_flight\":2,\"session_timeout_ms\":1000}}" + "]}";
} +
"{\"name\":\"http\",\"protocol\":\"http\",\"bind\":\"127.0.0.1:0\",\"timeout_ms\":1000}," + "{\"name\":\"tcp\",\"protocol\":\"tcp\",\"bind\":\"127.0.0.1:0\",\"timeout_ms\":1000}," + "{\"name\":\"udp-client\",\"protocol\":\"udp\",\"bind\":\"127.0.0.1:" + std::to_string(udp_client_endpoint.port()) + "\",\"connect\":\"127.0.0.1:" + std::to_string(udp_server_endpoint.port()) + "\",\"udp\":{\"resend_interval_ms\":5,\"max_in_flight\":2,\"session_timeout_ms\":1000}}," + "{\"name\":\"udp-server\",\"protocol\":\"udp\",\"bind\":\"127.0.0.1:" + std::to_string(udp_server_endpoint.port()) + "\",\"connect\":\"127.0.0.1:" + std::to_string(udp_client_endpoint.port()) + "\",\"udp\":{\"resend_interval_ms\":5,\"max_in_flight\":2,\"session_timeout_ms\":1000}}" + "]}";
auto configs = ligo::parse_endpoint_configs(boost::json::parse(config_text));
BOOST_REQUIRE(configs);
BOOST_REQUIRE((configs->size()) == (4u));
@@ -625,8 +627,7 @@ BOOST_AUTO_TEST_CASE(ligo_http_post_round_trip_dispatches_json_handler) {
{
.target = "/echo",
.payload = boost::json::parse(R"json({"ok":true})json"),
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -690,8 +691,7 @@ BOOST_AUTO_TEST_CASE(ligo_http_tls_post_round_trip_dispatches_json_handler) {
{
.timeout = std::chrono::milliseconds{1000},
.security = test_tls_client_config(),
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -766,7 +766,8 @@ BOOST_AUTO_TEST_CASE(ligo_http_get_round_trip_dispatches_method_and_route) {
auto future = boost::asio::co_spawn(io, http_client_call_selected_and_stop(server, {
.method = ligo::http::method::GET,
.target = "/method",
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_REQUIRE(result);
@@ -788,7 +789,8 @@ BOOST_AUTO_TEST_CASE(ligo_http_missing_route_returns_status) {
auto future = boost::asio::co_spawn(io, http_client_call_selected_and_stop(server, {
.target = "/missing",
.payload = boost::json::object{},
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_CHECK(!(result));
@@ -813,7 +815,8 @@ BOOST_AUTO_TEST_CASE(ligo_http_handler_failure_returns_status) {
auto future = boost::asio::co_spawn(io, http_client_call_selected_and_stop(server, {
.target = "/boom",
.payload = boost::json::object{},
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_CHECK(!(result));
@@ -895,8 +898,7 @@ BOOST_AUTO_TEST_CASE(ligo_http_client_rejects_oversized_response_body) {
{
.timeout = std::chrono::milliseconds{1000},
.max_body_size = 32,
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -934,7 +936,8 @@ BOOST_AUTO_TEST_CASE(ligo_http_concurrent_client_calls_succeed) {
futures.push_back(boost::asio::co_spawn(io, client.call({
.target = "/echo",
.payload = std::move(payload),
}), boost::asio::use_future));
}),
boost::asio::use_future));
}
for (auto &future : futures) {
auto result = future.get();
@@ -971,8 +974,7 @@ BOOST_AUTO_TEST_CASE(ligo_http_async_stop_cancels_active_session) {
},
{
.timeout = std::chrono::milliseconds{200},
}
),
}),
boost::asio::use_future);
auto stopped = boost::asio::co_spawn(io, http_async_stop_after(server, std::chrono::milliseconds{5}, std::chrono::milliseconds{200}), boost::asio::use_future);
run_two_threads(io);
@@ -1002,8 +1004,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_round_trip_dispatches_json_handler) {
{
.route = "echo",
.payload = boost::json::parse(R"json({"ok":true})json"),
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -1043,8 +1044,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_tls_round_trip_dispatches_json_handler) {
{
.timeout = std::chrono::milliseconds{1000},
.security = test_tls_client_config(),
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -1085,8 +1085,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_tls_verified_peer_succeeds) {
{
.timeout = std::chrono::milliseconds{1000},
.security = test_tls_verified_client_config("localhost"),
}
),
}),
boost::asio::use_future);
auto stopper = boost::asio::steady_timer{io};
stopper.expires_after(std::chrono::milliseconds{200});
@@ -1132,8 +1131,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_tls_hostname_mismatch_fails) {
{
.timeout = std::chrono::milliseconds{1000},
.security = test_tls_verified_client_config("wrong.local"),
}
),
}),
boost::asio::use_future);
auto stopper = boost::asio::steady_timer{io};
stopper.expires_after(std::chrono::milliseconds{200});
@@ -1206,7 +1204,8 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_missing_route_returns_status) {
auto future = boost::asio::co_spawn(io, tcp_client_call_selected_and_stop(server, {
.route = "missing",
.payload = boost::json::object{},
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_CHECK(!(result));
@@ -1231,7 +1230,8 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_handler_failure_returns_status) {
auto future = boost::asio::co_spawn(io, tcp_client_call_selected_and_stop(server, {
.route = "boom",
.payload = boost::json::object{},
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_CHECK(!(result));
@@ -1243,7 +1243,8 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_connection_refused_returns_unavailable) {
auto future = boost::asio::co_spawn(io, tcp_client_call("127.0.0.1", 9, {
.route = "echo",
.payload = boost::json::object{},
}), boost::asio::use_future);
}),
boost::asio::use_future);
io.run();
auto result = future.get();
BOOST_CHECK(!(result));
@@ -1269,8 +1270,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_stalled_peer_times_out) {
},
{
.timeout = std::chrono::milliseconds{20},
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -1308,7 +1308,8 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_concurrent_client_calls_succeed) {
futures.push_back(boost::asio::co_spawn(io, client.call({
.route = "echo",
.payload = std::move(payload),
}), boost::asio::use_future));
}),
boost::asio::use_future));
}
for (auto &future : futures) {
auto result = future.get();
@@ -1345,8 +1346,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_async_stop_cancels_active_session) {
},
{
.timeout = std::chrono::milliseconds{200},
}
),
}),
boost::asio::use_future);
auto stopped = boost::asio::co_spawn(io, tcp_async_stop_after(server, std::chrono::milliseconds{5}, std::chrono::milliseconds{200}), boost::asio::use_future);
run_two_threads(io);
@@ -1372,8 +1372,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_connect_returns_connected_socket) {
},
{
.timeout = std::chrono::milliseconds{1000},
}
),
}),
boost::asio::use_future);
io.run();
auto socket = result.get();
@@ -1401,8 +1400,7 @@ BOOST_AUTO_TEST_CASE(ligo_net_connect_returns_connected_socket) {
},
{
.timeout = std::chrono::milliseconds{1000},
}
),
}),
boost::asio::use_future);
io.run();
auto socket = result.get();
@@ -1432,8 +1430,7 @@ BOOST_AUTO_TEST_CASE(ligo_net_listener_accept_returns_socket) {
},
{
.timeout = std::chrono::milliseconds{1000},
}
),
}),
boost::asio::use_future);
io.run();
auto accepted_socket = accepted.get();
@@ -1467,8 +1464,7 @@ BOOST_AUTO_TEST_CASE(ligo_net_byte_stream_round_trips_over_tcp) {
},
{
.timeout = std::chrono::milliseconds{1000},
}
),
}),
boost::asio::use_future);
io.run();
auto accepted_socket = accepted.get();
@@ -1506,7 +1502,9 @@ BOOST_AUTO_TEST_CASE(ligo_net_listener_tls_accept_rejects_non_tls_security_modes
auto listener = std::move(*listener_result);
auto none = boost::asio::co_spawn(io, listener.async_accept_tls_configured({
.mode = ligo::security_mode::NONE,
}, std::chrono::milliseconds{1000}), boost::asio::use_future);
},
std::chrono::milliseconds{1000}),
boost::asio::use_future);
io.run();
auto result = none.get();
BOOST_CHECK(!result);
@@ -1534,8 +1532,7 @@ BOOST_AUTO_TEST_CASE(ligo_net_listener_tls_handshake_succeeds) {
{
.timeout = std::chrono::milliseconds{1000},
},
test_tls_client_config()
),
test_tls_client_config()),
boost::asio::use_future);
io.run();
auto accepted_socket = accepted.get();
@@ -1565,8 +1562,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_raw_connect_rejects_secure_modes) {
.security = {
.mode = ligo::security_mode::TLS,
},
}
),
}),
boost::asio::use_future);
io.run();
auto result = future.get();
@@ -1589,8 +1585,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_tls_connect_rejects_non_tls_security_modes) {
},
{
.mode = ligo::security_mode::NONE,
}
),
}),
boost::asio::use_future);
auto dtls = boost::asio::co_spawn(
io,
@@ -1605,8 +1600,7 @@ BOOST_AUTO_TEST_CASE(ligo_tcp_tls_connect_rejects_non_tls_security_modes) {
},
{
.mode = ligo::security_mode::DTLS,
}
),
}),
boost::asio::use_future);
io.run();
auto none_result = none.get();
@@ -1898,7 +1892,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_dtls_server_requires_identity) {
0,
},
.peer = peer,
}, {
},
{
.security = {
.mode = ligo::security_mode::DTLS,
},
@@ -1998,7 +1993,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_wrong_session_times_out) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, receiver_endpoint, config, 7);
},
receiver_endpoint, config, 7);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto future = boost::asio::co_spawn(io, channel.send(boost::json::object{}), boost::asio::use_future);
@@ -2024,7 +2020,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_oversized_payload_returns_invalid_argument) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, receiver_endpoint);
},
receiver_endpoint);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto payload = boost::json::value{
@@ -2053,7 +2050,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_close_wakes_pending_receive) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, right_endpoint);
},
right_endpoint);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto received = boost::asio::co_spawn(io, channel.receive(), boost::asio::use_future);
@@ -2084,7 +2082,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_async_close_drains_pending_receive) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, right_endpoint);
},
right_endpoint);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto received = boost::asio::co_spawn(io, channel.receive(), boost::asio::use_future);
@@ -2117,7 +2116,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_async_close_drains_pending_send) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, receiver_endpoint, config, 171);
},
receiver_endpoint, config, 171);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto sent = boost::asio::co_spawn(io, channel.send(boost::json::object{}), boost::asio::use_future);
@@ -2145,7 +2145,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_async_close_moved_from_channel_is_ok) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, right_endpoint);
},
right_endpoint);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto moved = std::move(channel);
@@ -2171,7 +2172,8 @@ BOOST_AUTO_TEST_CASE(ligo_udp_async_close_rejects_invalid_timeout) {
auto channel_result = udp_client_bind(io, boost::asio::ip::udp::endpoint{
boost::asio::ip::udp::v4(),
0,
}, right_endpoint);
},
right_endpoint);
BOOST_REQUIRE(channel_result);
auto channel = std::move(*channel_result);
auto closed = boost::asio::co_spawn(io, channel.async_close(std::chrono::milliseconds{0}), boost::asio::use_future);