thespian/test/endpoint_tcp.cpp
2024-02-08 23:04:55 +01:00

93 lines
2.2 KiB
C++

#include "tests.hpp"
#include "cbor/cbor.hpp"
#include "thespian/env.hpp"
#include "thespian/handle.hpp"
#include <thespian/endpoint.hpp>
#include <thespian/instance.hpp>
#include <thespian/socket.hpp>
#include <thespian/tcp.hpp>
#include <cstring>
#include <map>
#include <utility>
using cbor::any;
using cbor::buffer;
using cbor::extract;
using std::make_shared;
using std::move;
using std::string;
using std::string_view;
using std::stringstream;
using thespian::context;
using thespian::env;
using thespian::env_t;
using thespian::exit;
using thespian::handle;
using thespian::link;
using thespian::ok;
using thespian::receive;
using thespian::result;
using thespian::unexpected;
using thespian::endpoint::tcp::listen;
namespace {
struct controller {
handle ep_listen;
handle ep_connect;
size_t ping_count{};
size_t pong_count{};
bool success_{false};
explicit controller(handle ep_l) : ep_listen{move(ep_l)} {}
auto receive(const handle &from, const buffer &m) {
port_t port{0};
if (m("port", extract(port))) {
ep_connect =
thespian::endpoint::tcp::connect(in6addr_loopback, port).value();
return ok();
}
if (m("connected")) {
ping_count++;
return ep_connect.send("ping", ping_count);
}
if (m("ping", any)) {
pong_count++;
return from.send("pong", pong_count);
}
if (m("pong", any)) {
if (ping_count > 10) {
return exit(ping_count == pong_count ? "success" : "closed");
}
ping_count++;
return from.send("ping", ping_count);
}
return unexpected(m);
}
}; // namespace
} // namespace
auto endpoint_tcp(context &ctx, bool &result, env_t env_) -> ::result {
return to_result(ctx.spawn_link(
[=]() {
link(env().proc("log"));
handle ep_listen = listen(in6addr_loopback, 0).value();
auto ret = ep_listen.send("get", "port");
if (not ret)
return ret;
receive([p{make_shared<controller>(ep_listen)}](auto from, auto m) {
return p->receive(move(from), move(m));
});
return ok();
},
[&](auto s) {
if (s == "success")
result = true;
},
"endpoint_tcp", move(env_)));
}