/ src / multicast_tx_socket.cpp
multicast_tx_socket.cpp
 1  // SPDX-FileCopyrightText: Copyright (C) 2025 Marek Küthe <m.k@mk16.de>
 2  //
 3  // SPDX-License-Identifier: GPL-3.0-or-later
 4  
 5  #include "multicast_tx_socket.hpp"
 6  
 7  using namespace MPingSender;
 8  
 9  MPingSender::MulticastTxSocket::MulticastTxSocket(
10      boost::asio::any_io_executor ex,
11      std::function<void(boost::system::error_code)> error_handler,
12      const boost::asio::ip::udp::endpoint& endpoint,
13      const boost::asio::ip::multicast::hops hops,
14      const std::string& interface) :
15      _socket(ex, endpoint.protocol()),
16      _error_handler(std::move(error_handler))
17  {
18      this->_socket.set_option(boost::asio::socket_base::reuse_address(true));
19      this->_socket.set_option(boost::asio::ip::multicast::outbound_interface(
20          PosixWrapper::if_nametoindex(interface)));
21      this->_socket.set_option(boost::asio::ip::multicast::enable_loopback(true));
22      this->_socket.set_option(hops);
23      this->_socket.set_option(boost::asio::socket_base::receive_buffer_size(0));
24  
25      BOOST_LOG_TRIVIAL(info) << "Bind on address " << endpoint.address()
26                              << " port " << endpoint.port();
27      this->_socket.bind(endpoint);
28  }
29  
30  void MPingSender::MulticastTxSocket::send_packet(
31      const std::string& message, const boost::asio::ip::udp::endpoint endpoint)
32  {
33      BOOST_LOG_TRIVIAL(trace)
34          << "Sending packet to address " << endpoint.address() << " port "
35          << endpoint.port();
36  
37      const auto sdata = std::make_shared<const std::string>(message);
38      this->_socket.async_send_to(
39          boost::asio::buffer(*sdata),
40          endpoint,
41          [this, sdata](const boost::system::error_code ec,
42                        [[maybe_unused]] const std::size_t bytes_transferred)
43          {
44              if (ec) [[unlikely]]
45              {
46                  BOOST_LOG_TRIVIAL(fatal)
47                      << "Failed to send packet." << ec.message();
48                  this->_error_handler(ec);
49              }
50              else [[likely]]
51              {
52                  BOOST_LOG_TRIVIAL(trace) << "Packet sendet.";
53              }
54          });
55  }