Reputation: 1404
I have a host with two interfaces. In my specific case I am trying to join a multicast group using boost::asio::ip::multicast::join_group
which appears to only work if i use the constructor that includes the local address. However i do not know in advance the ip address of the local interface connected to the remote host that will do the multicasting. I do however know that it will be eth1. Of course, i could make it configurable but that seems like introducing a useless opportunity to misconfigure, seeing how the same address would have to be configured for the interface and my application.
Ideally there would be a glaringly obvious way to create a boost::asio::endpoint
or boost::asio::address
from an interface instead of an address that i somehow missed. Alternatively i would of course be just as happy with any other way to deduce an interfaces Ip that works both, with and without a DHCP-Server supplying the Ip.
Is there a proper way to do either or should i just trust users to never fumble with the configuration?
To make sure that this is not completely a XY Problem, here is the code i used while testing to join a multicast group:
m_socket.open(boost_ip::udp::v4());
m_socket.bind(boost_ip::udp::endpoint(boost_ip::udp::v4(), listeningPort));
m_socket.set_option(boost::asio::ip::udp::socket::reuse_address(true));
m_socket.set_option(boost::asio::ip::multicast::join_group(
boost::asio::ip::address::from_string("225.x.x.10").to_v4(), // remote
boost::asio::ip::address::from_string("192.x.x.3").to_v4())); // local
This does work but when i discard the last line to not be dependent on the current local address (that might be changed in deployment), i no longer receive any packets.
Upvotes: 1
Views: 1279
Reputation: 1404
I came up with an answer to my question myself. This works for me but I will leave the question open in case anyone has a more straightforward solution.
I settled with using <ifaddrs.h>
to just find my current ip for the interface and use that to join the multicast group. This is the code i ended up with to determine my ip:
#include <ifaddrs.h>
#include <boost/asio.hpp>
#include <cstring>
std::string getInterfaceAddress(const std::string & interfaceName)
{
ifaddrs* firstNetIf = 0;
getifaddrs(&firstNetIf);
ifaddrs* netIf = 0;
for(netIf = firstNetIf; netIf != 0; netIf = netIf->ifa_next)
{
if(netIf->ifa_addr->sa_family == AF_INET && std::strncmp(netIf->ifa_name, interfaceName.c_str(), interfaceName.length()) == 0)
{
break;
}
}
unsigned long address =
netIf != 0 ? reinterpret_cast<sockaddr_in*>(netIf->ifa_addr)->sin_addr.s_addr : 0;
if(firstNetIf != 0)
{
freeifaddrs(firstNetIf);
}
return boost::asio::ip::address_v4(htonl(address)).to_string();
}
Of course in my case i could compare with "eth1"
and return the boost::asio::ip::address
directly but it turns out that this code can be used at one other place as well this way.
Upvotes: 1
Reputation: 330
Multicast uses the IGMP protocol to form a multicast group. Since IGMP operates on the network layer, it requires the local ip address of the end-point that is joining the multicast group.
The application should wait for an event indicating an ip address has been assigned to the ethernet interface and then call the join_group method to join the multicast group.
Upvotes: 1