OSSIA
Open Scenario System for Interactive Application
tcp_socket.hpp
1 #pragma once
2 #include <ossia/network/sockets/configuration.hpp>
3 
4 #include <boost/asio/io_context.hpp>
5 #include <boost/asio/ip/tcp.hpp>
6 #include <boost/asio/ip/udp.hpp>
7 #include <boost/asio/local/datagram_protocol.hpp>
8 #include <boost/asio/placeholders.hpp>
9 #include <boost/asio/strand.hpp>
10 #include <boost/asio/write.hpp>
11 
12 #include <nano_signal_slot.hpp>
13 
14 namespace ossia::net
15 {
16 class tcp_listener
17 {
18 public:
19  using proto = boost::asio::ip::tcp;
20  using socket = typename proto::socket;
21 
22  tcp_listener() = delete;
23  tcp_listener(const tcp_listener&) = delete;
24  tcp_listener& operator=(const tcp_listener&) = delete;
25  tcp_listener(tcp_listener&&) = default;
26  tcp_listener& operator=(tcp_listener&&) = default;
27  explicit tcp_listener(proto::socket sock)
28  : m_socket{std::move(sock)}
29  {
30  }
31 
32  void close() { m_socket.close(); }
33 
34  void write(const boost::asio::const_buffer& buf) { boost::asio::write(m_socket, buf); }
35 
36  void on_close() { }
37 
38  void on_fail() { }
39 
40  proto::socket m_socket;
41 };
42 
43 class tcp_server
44 {
45 public:
46  using proto = boost::asio::ip::tcp;
47  using socket = typename proto::socket;
48  using listener = tcp_listener;
49 
50  tcp_server(const socket_configuration& conf, boost::asio::io_context& ctx)
51  : m_context{ctx}
52  , m_acceptor{
53  boost::asio::make_strand(ctx),
54  proto::endpoint{boost::asio::ip::make_address(conf.host), conf.port}}
55  {
56  }
57 
58  boost::asio::io_context& m_context;
59  proto::acceptor m_acceptor;
60 };
61 
62 class tcp_client
63 {
64 public:
65  using proto = boost::asio::ip::tcp;
66  using socket = typename proto::socket;
67 
68  tcp_client(const socket_configuration& conf, boost::asio::io_context& ctx)
69  : m_context{ctx}
70  , m_endpoint{boost::asio::ip::make_address(conf.host), conf.port}
71  , m_socket{boost::asio::make_strand(ctx)}
72  {
73  }
74 
75  void connect()
76  {
77  m_socket.connect(m_endpoint);
78  on_open();
79  }
80 
81  bool connected() const { return m_connected; }
82 
83  void close()
84  {
85  m_context.post([this] {
86  m_socket.close();
87  on_close();
88  });
89  }
90 
91  void write(const char* data, std::size_t sz)
92  {
93  boost::asio::write(m_socket, boost::asio::buffer(data, sz));
94  }
95 
96  Nano::Signal<void()> on_open;
97  Nano::Signal<void()> on_close;
98  Nano::Signal<void()> on_fail;
99 
100  boost::asio::io_context& m_context;
101  proto::endpoint m_endpoint;
102  proto::socket m_socket;
103  bool m_connected{false};
104 };
105 }