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