OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
fixed_length_framing.hpp
1#pragma once
2#include <ossia/detail/pod_vector.hpp>
3#include <ossia/network/sockets/writers.hpp>
4
5#include <boost/asio/buffer.hpp>
6#include <boost/asio/error.hpp>
7#include <boost/asio/read.hpp>
8#include <boost/asio/write.hpp>
9
10namespace ossia::net
11{
12
13template <typename Socket>
14struct fixed_length_decoder
15{
16 Socket& socket;
17 std::size_t frame_size{64};
18 ossia::pod_vector<char> m_data;
19 lifetime_token m_lifetime;
20
21 explicit fixed_length_decoder(Socket& socket)
22 : socket{socket}
23 {
24 }
25
26 template <typename F>
27 void receive(F f)
28 {
29 m_data.resize(frame_size, boost::container::default_init);
30 boost::asio::async_read(
31 socket, boost::asio::mutable_buffer(m_data.data(), frame_size),
32 boost::asio::transfer_exactly(frame_size),
33 [this, alive = m_lifetime.watch(),
34 f = std::move(f)](boost::system::error_code ec, std::size_t sz) mutable {
35 // The socket may be gone since this read was armed; see lifetime_token.
36 if(alive.expired())
37 return;
38
39 if(!f.validate_stream(ec))
40 return;
41
42 if(!ec && sz > 0)
43 {
44 try
45 {
46 f((const unsigned char*)m_data.data(), sz);
47 }
48 catch(...)
49 {
50 }
51 }
52
53 this->receive(std::move(f));
54 });
55 }
56};
57
58template <typename Socket>
59struct fixed_length_encoder
60{
61 Socket& socket;
62
63 void write(const char* data, std::size_t sz)
64 {
65 this->do_write(socket, boost::asio::buffer(data, sz));
66 }
67
68 template <typename T>
69 void do_write(T& sock, const boost::asio::const_buffer& buf)
70 {
71 boost::asio::write(sock, buf);
72 }
73
74 template <typename T>
75 void do_write(multi_socket_writer<T>& sock, const boost::asio::const_buffer& buf)
76 {
77 sock.write(buf);
78 }
79};
80
81struct fixed_length_framing
82{
83 template <typename Socket>
84 using encoder = fixed_length_encoder<Socket>;
85 template <typename Socket>
86 using decoder = fixed_length_decoder<Socket>;
87};
88
89}