OSSIA
Open Scenario System for Interactive Application
framing.hpp
1 #pragma once
2 #include <ossia/network/sockets/size_prefix_framing.hpp>
3 #include <ossia/network/sockets/slip_framing.hpp>
4 #include <ossia/network/sockets/tcp_socket.hpp>
5 #include <ossia/network/sockets/udp_socket.hpp>
6 #include <ossia/network/sockets/unix_socket.hpp>
7 #include <ossia/network/sockets/writers.hpp>
8 
9 namespace ossia::net
10 {
11 
12 template <typename Base, typename Framing>
13 struct framed_listener : public Base
14 {
15  using proto = typename Base::proto;
16  using socket = typename proto::socket;
17  using decoder = typename Framing::template decoder<socket>;
18 
19  template <typename F>
20  framed_listener(socket&& sock, F f)
21  : Base{std::move(sock)}
22  , m_decoder{this->m_socket}
23  {
24  m_decoder.receive(stream_processor<framed_listener, F>{*this, std::move(f)});
25  }
26 
27  decoder m_decoder;
28 };
29 
30 template <typename Base, typename Framing>
31 struct framed_server : Base
32 {
33 public:
34  using proto = typename Base::proto;
35  using socket = typename proto::socket;
36  using listener = framed_listener<typename Base::listener, Framing>;
37  using encoder =
38  typename Framing::template encoder<multi_socket_writer<std::unique_ptr<listener>>>;
39  using decoder = typename Framing::template decoder<socket>;
40 
41  template <typename... Args>
42  framed_server(Args&&... args)
43  : Base{std::forward<Args>(args)...}
44  {
45  }
46 
47  template <typename F>
48  void close(F f)
49  {
50  this->m_context.post([this, f] {
51  for(auto& sock : m_sockets)
52  {
53  sock.close();
54  }
55  f();
56  });
57  }
58 
59  template <typename F>
60  void listen(F f)
61  {
62  this->m_acceptor.async_accept(
63  [this, f = std::move(f)](std::error_code ec, socket socket) {
64  if(!ec)
65  {
66  m_sockets.push_back(std::make_unique<listener>(std::move(socket), f));
67  }
68 
69  listen(std::move(f));
70  });
71  }
72 
73  void write(const char* data, std::size_t sz)
74  {
75  multi_socket_writer<std::unique_ptr<listener>> wr{this->m_sockets};
76  encoder{wr}.write(data, sz);
77  }
78 
79  std::vector<std::unique_ptr<listener>> m_sockets;
80 };
81 
82 template <typename Base, typename Framing>
83 struct framed_client : Base
84 {
85  using socket = typename Base::socket;
86  using encoder = typename Framing::template encoder<socket>;
87  using decoder = typename Framing::template decoder<socket>;
88 
89  template <typename... Args>
90  framed_client(Args&&... args)
91  : Base{std::forward<Args>(args)...}
92  , m_decoder{this->m_socket}
93  {
94  }
95 
96  template <typename F>
97  void receive(F f)
98  {
99  m_decoder.receive(stream_processor<framed_client, F>{*this, std::move(f)});
100  }
101 
102  void write(const char* data, std::size_t sz)
103  {
104  encoder{this->m_socket}.write(data, sz);
105  }
106 
107  decoder m_decoder;
108 };
109 
110 template <typename Base, typename Framing>
111 struct framed_socket : Base
112 {
113  using socket = typename Base::socket;
114  using encoder = typename Framing::template encoder<socket>;
115  using decoder = typename Framing::template decoder<socket>;
116 
117  template <typename... Args>
118  framed_socket(Args&&... args)
119  : Base{std::forward<Args>(args)...}
120  , m_decoder{this->m_socket}
121  {
122  }
123 
124  template <typename F>
125  void listen(F f)
126  {
127  Base::open();
128  m_decoder.receive(stream_processor<framed_socket, F>{*this, std::move(f)});
129  }
130 
131  template <typename F>
132  void receive(F f)
133  {
134  m_decoder.receive(stream_processor<framed_socket, F>{*this, std::move(f)});
135  }
136 
137  void write(const char* data, std::size_t sz)
138  {
139  encoder{this->m_socket}.write(data, sz);
140  }
141 
142  decoder m_decoder;
143 };
144 
145 struct tcp_size_prefix_server : framed_server<tcp_server, size_prefix_framing>
146 {
147  using framed_server::framed_server;
148 };
149 struct tcp_slip_server : framed_server<tcp_server, slip_framing>
150 {
151  using framed_server::framed_server;
152 };
153 
154 struct tcp_size_prefix_client : framed_client<tcp_client, size_prefix_framing>
155 {
156  using framed_client::framed_client;
157 };
158 struct tcp_slip_client : framed_client<tcp_client, slip_framing>
159 {
160  using framed_client::framed_client;
161 };
162 
163 #if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
164 struct unix_stream_size_prefix_server
165  : framed_server<unix_stream_server, size_prefix_framing>
166 {
167  using framed_server::framed_server;
168 };
169 struct unix_stream_slip_server : framed_server<unix_stream_server, slip_framing>
170 {
171  using framed_server::framed_server;
172 };
173 
174 struct unix_stream_size_prefix_client
175  : framed_socket<unix_stream_client, size_prefix_framing>
176 {
177  using framed_socket::framed_socket;
178 };
179 struct unix_stream_slip_client : framed_socket<unix_stream_client, slip_framing>
180 {
181  using framed_socket::framed_socket;
182 };
183 #endif
184 
185 }