25#ifndef GOBY_MIDDLEWARE_IO_UDP_ONE_TO_MANY_H
26#define GOBY_MIDDLEWARE_IO_UDP_ONE_TO_MANY_H
29#include <boost/asio/buffer.hpp>
30#include <boost/asio/ip/udp.hpp>
31#include <boost/asio/socket_base.hpp>
32#include <boost/system/error_code.hpp>
57template <
const goby::middleware::Group& line_in_group,
58 const goby::middleware::Group& line_out_group,
63 typename Config = goby::middleware::protobuf::UDPOneToManyConfig,
65 bool use_indexed_groups =
false>
67 :
public detail::IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, Config,
68 boost::asio::ip::udp::socket, ThreadType, use_indexed_groups>
71 detail::IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer, Config,
72 boost::asio::ip::udp::socket, ThreadType, use_indexed_groups>;
83 this->
interthread().template publish<line_in_group>(ready);
95 async_write(std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg)
override;
102 static constexpr int max_udp_size{65507};
103 std::array<char, max_udp_size> rx_message_;
104 boost::asio::ip::udp::endpoint sender_endpoint_;
105 boost::asio::ip::udp::endpoint local_endpoint_;
115 template <
class>
class ThreadType,
bool use_indexed_groups>
117 subscribe_layer, Config, ThreadType,
118 use_indexed_groups>::open_socket()
120 auto protocol = this->cfg().ipv6() ? boost::asio::ip::udp::v6() :
boost::asio::ip::udp::v4();
121 this->mutable_socket().open(protocol);
123 if (this->cfg().set_reuseaddr())
126 boost::asio::socket_base::reuse_address option(
true);
127 this->mutable_socket().set_option(option);
130 if (this->cfg().set_broadcast())
133 this->mutable_socket().set_option(boost::asio::socket_base::broadcast(
true));
136 this->mutable_socket().bind(boost::asio::ip::udp::endpoint(protocol, this->cfg().bind_port()));
137 local_endpoint_ = this->mutable_socket().local_endpoint();
144 template <
class>
class ThreadType,
bool use_indexed_groups>
146 subscribe_layer, Config, ThreadType,
150 boost::asio::buffer(rx_message_), sender_endpoint_,
151 [
this](
const boost::system::error_code& ec,
size_t bytes_transferred)
153 if (!ec && bytes_transferred > 0)
155 auto io_msg = std::make_shared<goby::middleware::protobuf::IOData>();
156 *io_msg->mutable_data() =
157 std::string(rx_message_.begin(), rx_message_.begin() + bytes_transferred);
159 *io_msg->mutable_udp_src() =
161 *io_msg->mutable_udp_dest() =
178 template <
class>
class ThreadType,
bool use_indexed_groups>
180 line_in_group, line_out_group, publish_layer, subscribe_layer, Config, ThreadType,
181 use_indexed_groups>
::async_write(std::shared_ptr<const goby::middleware::protobuf::IOData>
184 if (!io_msg->has_udp_dest())
185 throw(
goby::Exception(
"UDPOneToManyThread requires 'udp_dest' field to be set in IOData"));
187 boost::asio::ip::udp::resolver resolver(this->
mutable_io());
188 boost::asio::ip::udp::endpoint remote_endpoint =
190 .resolve(io_msg->udp_dest().addr(), std::to_string(io_msg->udp_dest().port()),
191 boost::asio::ip::resolver_base::numeric_service)
196 boost::asio::buffer(io_msg->data()), remote_endpoint,
197 [
this, io_msg](
const boost::system::error_code& ec, std::size_t bytes_transferred)
199 if (!ec && bytes_transferred > 0)
201 this->handle_write_success(bytes_transferred);
205 this->handle_write_error(ec);
simple exception class for goby applications
Class for grouping publications in the Goby middleware. Analogous to "topics" in ROS,...
InterThreadTransporter & interthread()
virtual void async_read() override
Starts an asynchronous read on the udp socket.
~UDPOneToManyThread() override
UDPOneToManyThread(const Config &config, int index=-1, bool is_final=true)
Constructs the thread.
virtual void async_write(std::shared_ptr< const goby::middleware::protobuf::IOData > io_msg) override
Starts an asynchronous write from data published.
void handle_read_success(std::size_t bytes_transferred, const std::string &bytes)
void handle_read_error(const boost::system::error_code &ec)
boost::asio::ip::udp::socket & mutable_socket()
virtual void open_socket()=0
boost::asio::io_context & mutable_io()
ProtobufEndpoint endpoint_convert(const ASIOEndpoint &asio_ep)
Objects implementing the Goby nested middleware.
std::string to_string(goby::middleware::protobuf::Layer layer)
middleware::SimpleThread< Config, detail::InterProcessTag > SimpleThread
Zeromq-backed SimpleThread. Derives from middleware::SimpleThread using InterProcessTag.
The global namespace for the Goby project.