2#include <ossia/detail/pod_vector.hpp>
3#include <ossia/network/sockets/writers.hpp>
5#include <boost/asio/error.hpp>
6#include <boost/asio/read.hpp>
7#include <boost/asio/streambuf.hpp>
8#include <boost/asio/write.hpp>
14 static const constexpr uint8_t eot = 192;
15 static const constexpr uint8_t esc = 219;
16 static const constexpr uint8_t esc_end = 220;
17 static const constexpr uint8_t esc_esc = 221;
20template <
typename Socket>
24 boost::asio::streambuf m_data;
25 ossia::pod_vector<char> m_decoded;
33 explicit slip_decoder(Socket& socket)
41 socket.async_read_some(
42 boost::asio::mutable_buffer(m_data.prepare(1024)),
43 [
this, f = std::move(f)](boost::system::error_code ec, std::size_t sz)
mutable {
44 if(!f.validate_stream(ec))
52 receive(std::move(f));
57 void process_bytes(
const F& f, std::size_t sz)
59 auto begin = (
const uint8_t*)m_data.data().data();
60 for(std::size_t i = 0; i < sz; i++)
62 const uint8_t next_char = *begin;
63 process_byte(f, next_char);
70 void process_byte(
const F& f,
const uint8_t next_char)
79 m_status = reading_char;
96 if(m_decoded.size() > 0)
98 f((
const unsigned char*)m_decoded.data(), m_decoded.size());
105 m_status = reading_esc;
110 m_decoded.push_back(next_char);
120 m_status = reading_char;
121 m_decoded.push_back(slip::eot);
125 m_status = reading_char;
126 m_decoded.push_back(slip::esc);
142template <
typename Socket>
148 void write(
const char* data, std::size_t sz)
150 this->write(socket, boost::asio::buffer(&slip::eot, 1));
152 const uint8_t* begin =
reinterpret_cast<const uint8_t*
>(data);
153 const uint8_t* end = begin + sz;
156 std::size_t written = this->write(begin, end);
159 this->write(socket, boost::asio::buffer(&slip::eot, 1));
162 std::size_t write(
const uint8_t* begin,
const uint8_t* end)
164 const uint8_t
byte = *begin;
168 const uint8_t data[2] = {slip::esc, slip::esc_end};
169 this->write(socket, boost::asio::buffer(data, 2));
173 const uint8_t data[2] = {slip::esc, slip::esc_esc};
174 this->write(socket, boost::asio::buffer(data, 2));
178 auto sub_end = begin + 1;
179 while(sub_end != end && *sub_end != slip::eot && *sub_end != slip::esc)
182 this->write(socket, boost::asio::buffer(begin, sub_end - begin));
183 return sub_end - begin;
188 template <
typename T>
189 void write(T& sock,
const boost::asio::const_buffer& buf)
191 boost::asio::write(sock, buf);
194 template <
typename T>
195 void write(multi_socket_writer<T>& sock,
const boost::asio::const_buffer& buf)
203 template <
typename Socket>
204 using encoder = slip_encoder<Socket>;
205 template <
typename Socket>
206 using decoder = slip_decoder<Socket>;