24 #ifndef GOBY_MIDDLEWARE_IO_COBS_COMMON_H
25 #define GOBY_MIDDLEWARE_IO_COBS_COMMON_H
29 #include <boost/asio/read.hpp>
30 #include <boost/asio/write.hpp>
43 template <
class Thread>
45 std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg)
47 constexpr
static char cobs_eol{0};
50 auto input_size = io_msg->
data().size();
51 auto output_size_max = input_size + (input_size / 254) + 1;
52 std::string cobs_encoded(output_size_max,
'\0');
54 auto cobs_size =
cobs_encode(
reinterpret_cast<const uint8_t*
>(io_msg->
data().data()),
55 input_size,
reinterpret_cast<uint8_t*
>(&cobs_encoded[0]));
59 cobs_encoded.resize(cobs_size);
60 cobs_encoded += cobs_eol;
63 << cobs_encoded.size() <<
"B) <"
67 boost::asio::async_write(this_thread->mutable_socket(), boost::asio::buffer(cobs_encoded),
68 [this_thread, cobs_encoded](
const boost::system::error_code& ec,
69 std::size_t bytes_transferred) {
70 if (!ec && bytes_transferred > 0)
72 this_thread->handle_write_success(bytes_transferred);
76 this_thread->handle_write_error(ec);
83 <<
"Failed to encode COBS message: "
85 this_thread->handle_write_error(boost::system::error_code());
89 template <
class Thread,
class ThreadBase = Thread>
91 std::shared_ptr<ThreadBase>
self = std::shared_ptr<ThreadBase>())
93 constexpr
static char cobs_eol{0};
95 boost::asio::async_read_until(
96 this_thread->mutable_socket(), this_thread->buffer_, cobs_eol,
97 [this_thread,
self](
const boost::system::error_code& ec, std::size_t bytes_transferred) {
98 if (!ec && bytes_transferred > 0)
100 std::string bytes(bytes_transferred,
'\0');
101 std::istream is(&this_thread->buffer_);
102 is.read(&bytes[0], bytes_transferred);
104 goby::glog.is_debug2() && goby::glog << group(this_thread->glog_group()) <<
"COBS ("
105 << bytes.size() <<
"B) >"
106 <<
" " << goby::util::hex_encode(bytes)
109 auto io_msg = std::make_shared<goby::middleware::protobuf::IOData>();
110 auto& cobs_decoded = *io_msg->mutable_data();
111 cobs_decoded = std::string(bytes_transferred,
'\0');
114 cobs_decode(reinterpret_cast<const uint8_t*>(bytes.data()), bytes_transferred,
115 reinterpret_cast<uint8_t*>(&cobs_decoded[0]));
119 cobs_decoded.resize(decoded_size - 1);
120 this_thread->handle_read_success(bytes_transferred, io_msg);
121 this_thread->async_read();
125 goby::glog.is_warn() && goby::glog << group(this_thread->glog_group())
126 <<
"Failed to decode COBS message: "
127 << goby::util::hex_encode(bytes)
129 this_thread->handle_read_error(ec);
134 this_thread->handle_read_error(ec);