1 #include <pichi/common/config.hpp>
2 // Include config.hpp first
3 #include <array>
4 #include <boost/asio/ip/tcp.hpp>
5 #include <iostream>
6 #include <pichi/api/session.hpp>
7 #include <pichi/common/adapter.hpp>
8 #include <pichi/common/constants.hpp>
9 #include <pichi/common/endpoint.hpp>
10 #include <pichi/common/exception.hpp>
11 #include <pichi/net/spawn.hpp>
12
13 using namespace std;
14 namespace asio = boost::asio;
15 namespace sys = boost::system;
16
17 using asio::ip::tcp;
18
19 namespace pichi::api {
20
bridge(Adapter & from,Adapter & to,asio::yield_context yield)21 static void bridge(Adapter& from, Adapter& to, asio::yield_context yield)
22 {
23 auto buf = array<uint8_t, MAX_FRAME_SIZE>{};
24 while (from.readable() && to.writable()) to.send({buf, from.recv(buf, yield)}, yield);
25 }
26
27 Session::~Session() = default;
28
Session(asio::io_context & io,Session::IngressPtr && ingress,Session::EgressPtr && egress)29 Session::Session(asio::io_context& io, Session::IngressPtr&& ingress, Session::EgressPtr&& egress)
30 : strand_{io}, ingress_{move(ingress)}, egress_{move(egress)}
31 {
32 }
33
start(Endpoint const & remote,ResolveResults const & next)34 void Session::start(Endpoint const& remote, ResolveResults const& next)
35 {
36 // FIXME Not copying for self because net::spawn ensures that
37 // Function and ExceptionHandler share the same scope.
38 net::spawn(
39 strand_,
40 [=, self = shared_from_this()](auto yield) {
41 egress_->connect(remote, next, yield);
42 ingress_->confirm(yield);
43 net::spawn(
44 strand_, [self, this](auto yield) { bridge(*ingress_, *egress_, yield); },
45 [this](auto, auto yield) noexcept { this->close(yield); });
46 net::spawn(
47 strand_, [self, this](auto yield) { bridge(*egress_, *ingress_, yield); },
48 [this](auto, auto yield) noexcept { this->close(yield); });
49 },
50 [this](auto eptr, auto yield) noexcept { ingress_->disconnect(eptr, yield); });
51 }
52
start()53 void Session::start() { start({}, {}); }
54
close(Yield yield)55 template <typename Yield> void Session::close(Yield yield)
56 {
57 ingress_->close(yield);
58 egress_->close(yield);
59 }
60
61 } // namespace pichi::api
62