2#include <ossia/detail/pod_vector.hpp>
3#include <ossia/network/sockets/writers.hpp>
5#include <boost/asio/buffer.hpp>
6#include <boost/asio/error.hpp>
7#include <boost/asio/write.hpp>
13 static const constexpr uint8_t eot = 192;
14 static const constexpr uint8_t esc = 219;
15 static const constexpr uint8_t esc_end = 220;
16 static const constexpr uint8_t esc_esc = 221;
19template <
typename Socket>
23 alignas(64) uint8_t m_readbuf[4096];
24 ossia::pod_vector<char> m_decoded;
32 explicit slip_decoder(Socket& socket)
35 m_decoded.reserve(1024);
41 socket.async_read_some(
42 boost::asio::buffer(m_readbuf),
43 [
this, f = std::move(f)](boost::system::error_code ec, std::size_t sz)
mutable {
44 if(!f.validate_stream(ec))
48 process_bytes(f, m_readbuf, sz);
50 receive(std::move(f));
55 void process_bytes(
const F& f,
const uint8_t* data, std::size_t sz)
57 const uint8_t* ptr = data;
58 const uint8_t* end = data + sz;
62 if(m_status == reading_char)
65 const uint8_t* run_end = ptr;
66 while(run_end < end && *run_end != slip::eot && *run_end != slip::esc)
73 m_decoded.end(),
reinterpret_cast<const char*
>(ptr),
74 reinterpret_cast<const char*
>(run_end));
80 process_byte(f, *ptr++);
85 process_byte(f, *ptr++);
91 void process_byte(
const F& f,
const uint8_t next_char)
100 m_status = reading_char;
117 if(m_decoded.size() > 0)
119 f((
const unsigned char*)m_decoded.data(), m_decoded.size());
126 m_status = reading_esc;
131 m_decoded.push_back(next_char);
141 m_status = reading_char;
142 m_decoded.push_back(slip::eot);
146 m_status = reading_char;
147 m_decoded.push_back(slip::esc);
163template <
typename Socket>
167 ossia::pod_vector<uint8_t> m_buf;
170 void write(
const char* data, std::size_t sz)
173 m_buf.reserve(sz * 2 + 2);
174 m_buf.push_back(slip::eot);
176 auto* src =
reinterpret_cast<const uint8_t*
>(data);
177 for(std::size_t i = 0; i < sz; ++i)
182 m_buf.push_back(slip::esc);
183 m_buf.push_back(slip::esc_end);
186 m_buf.push_back(slip::esc);
187 m_buf.push_back(slip::esc_esc);
190 m_buf.push_back(src[i]);
194 m_buf.push_back(slip::eot);
196 this->do_write(socket, boost::asio::buffer(m_buf.data(), m_buf.size()));
199 template <
typename T>
200 void do_write(T& sock,
const boost::asio::const_buffer& buf)
202 boost::asio::write(sock, buf);
205 template <
typename T>
206 void do_write(multi_socket_writer<T>& sock,
const boost::asio::const_buffer& buf)
214 template <
typename Socket>
215 using encoder = slip_encoder<Socket>;
216 template <
typename Socket>
217 using decoder = slip_decoder<Socket>;