JayBeams  0.1
Another project to have fun coding.
make_socket_udp_send.hpp
Go to the documentation of this file.
1 #ifndef jb_itch5_make_socket_udp_send_hpp
2 #define jb_itch5_make_socket_udp_send_hpp
3 
6 #include <jb/strtonum.hpp>
7 
8 #include <boost/asio/ip/multicast.hpp>
9 #include <boost/asio/ip/udp.hpp>
10 #include <boost/asio/ip/unicast.hpp>
11 
12 namespace jb {
13 namespace itch5 {
14 
15 namespace detail {
16 template <typename socket_t>
17 void setup_socket_udp_send(socket_t& s, udp_sender_config const& cfg) {
18  // Some type aliases to shorten the code inside the function ...
19  namespace ip = boost::asio::ip;
20  using socket_base = boost::asio::socket_base;
21 
22  // ... this is the address we want to send to, we need to figure out
23  // what is its protocol so we can then open the socket ...
24  auto const r_address = ip::address::from_string(cfg.address());
25  // ... depending on the address we need to pick the right ADDRANY
26  // format ...
27  ip::address local_address = ip::address_v4();
28  if (r_address.is_v6()) {
29  local_address = ip::address_v6();
30  }
31  // ... create a socket bound to the right ADDRANY and an ephemeral
32  // port ...
33  ip::udp::endpoint endpoint(local_address, 0);
34 
35  s.open(endpoint.protocol());
36  s.set_option(socket_base::reuse_address(cfg.reuse_address()));
37  s.bind(endpoint);
38 
39  // ... now apply all the socket options, some only make sense if the
40  // destination is a multicast socket, apply those first ...
41  if (r_address.is_multicast()) {
42  s.set_option(ip::multicast::enable_loopback(cfg.enable_loopback()));
43  if (cfg.hops() != -1) {
44  s.set_option(ip::multicast::hops(ip::multicast::hops(cfg.hops())));
45  }
46  if (cfg.outbound_interface() != "") {
47  if (r_address.is_v4()) {
48  auto const local_if =
49  ip::address_v4::from_string(cfg.outbound_interface());
50  s.set_option(ip::multicast::outbound_interface(local_if));
51  } else {
52  int if_index;
53  if (not jb::strtonum(cfg.outbound_interface(), if_index)) {
54  std::ostringstream os;
55  os << "Cannot convert outbound-interface value ("
56  << cfg.outbound_interface() << ") to a IPv6 interface index";
57  throw std::runtime_error(os.str());
58  }
59  s.set_option(ip::multicast::outbound_interface(if_index));
60  }
61  }
62  } else {
63  if (cfg.hops() != -1) {
64  s.set_option(ip::unicast::hops(ip::unicast::hops(cfg.hops())));
65  }
66  s.set_option(socket_base::broadcast(cfg.broadcast()));
67  }
68 }
69 } // namespace detail
70 
71 /**
72  * Create a socket to send UDP messages given the configuration parameters.
73  *
74  * This is a function to create (open) sockets to send UDP
75  * messages, either unicast or multicast and either IPv4 or IPv6. The
76  * socket is bound to ADDRANY, and uses an ephemeral port selected by
77  * the operating system. The address family (v4 vs. v6) is selected
78  * based on the destination address.
79  *
80  * @tparam socket_t the type of socket to create. The main reason to
81  * change this type is for dependency injection during testing.
82  *
83  * @param io the Boost.ASIO io_service object that the socket is
84  * managed by.
85  *
86  * @param cfg the socket configuration.
87  */
88 template <class socket_t = boost::asio::ip::udp::socket>
90  boost::asio::io_service& io, udp_sender_config const& cfg) {
91  socket_t s(io);
93  make_socket_udp_common(s, cfg);
94  return s;
95 }
96 
97 } // namespace itch5
98 } // namespace jb
99 
100 #endif // jb_itch5_make_socket_udp_send_hpp
jb::config_attribute< udp_config_common, bool > reuse_address
socket_t make_socket_udp_send(boost::asio::io_service &io, udp_sender_config const &cfg)
Create a socket to send UDP messages given the configuration parameters.
jb::config_attribute< udp_sender_config, std::string > outbound_interface
jb::config_attribute< udp_sender_config, std::string > address
bool strtonum(std::string const &s, T &r)
Generic string to number conversion with validation.
Definition: strtonum.hpp:40
void make_socket_udp_common(socket_t &s, udp_config_common const &cfg)
Configure a UDP socket.
jb::config_attribute< udp_sender_config, int > hops
jb::config_attribute< udp_sender_config, bool > enable_loopback
A configuration object for UDP senders.
void setup_socket_udp_send(socket_t &s, udp_sender_config const &cfg)
jb::config_attribute< udp_sender_config, bool > broadcast
The top-level namespace for the JayBeams library.
Definition: as_hhmmss.hpp:7