fpagliughi / sockpp

Modern C++ socket library.
BSD 3-Clause "New" or "Revised" License
792 stars 126 forks source link

Is there or will there be a way to join a multicast group? #80

Closed fwr-ml closed 1 year ago

fwr-ml commented 1 year ago

I looked through the source, but couldn't find it being implemented (, which doesn't necessarily mean much).

fpagliughi commented 1 year ago

No, sorry, there's nothing particular implemented for this, and I don't have any experience with multicast groups. There is no direct IGMP support.

I don't know enough about it to determine if it would be appropriate for this library - or something that would be better suited to be implemented on top of it. But if you know how it can be implemented, I'd be interested to hear about it.

fwr-ml commented 1 year ago

I don't think, handling IGMP is needed. From what I've seen, on the sending side nothing special is needed. On the receiving end a struct ip_mreq would have to be used (with IPv4 on Linux that is) like

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(<multicast group address>);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
               &mreq, sizeof(mreq)) < 0)

I'd love to be more complete, but I'm new to the socket business.

For now I use Arthur Brainville's kissnet, but I'd prefer your project, for there are release tags and your API lets me use dynamically sized buffers for reception. kissnet's a one header library. It's sockets provide a method "join", that does what's needed.

It seems the only distinction Arthur makes is IPv4 vs IPv6. The rest is checking and pre-processing the given addresses.

fpagliughi commented 1 year ago

This library is just a thin wrapper over the base C sockets, just made a little easier for C++. So you should be able to do most low-level things using the library. (And where there isn't coverage, you can always get the OS socket handle and make the C calls yourself).

But there is coverage for getting and setting socket options from the base socket class. So assuming your socket is something derived from that, like a udp_socket (IPv4) or udp6_socket (IPv6), you can just do this:

struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(<multicast group address>);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

if (sock.set_option(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq) < 0) {
    ...
}

The sock::set_option() has a template definition that figures out the size of the struct from the pointer type and makes the call a little simpler.

fwr-ml commented 1 year ago

Thanks, I'll do that then. I must admit, I didn't quite realize how little opaque your API is.

fpagliughi commented 1 year ago

Definitely let us know how you make out, and if there's anything that could be added to the library that would help (keeping in mind the low-level nature of it). Or if there's anything you do that would be a good addition to the library, PR's are always welcome!

fpagliughi commented 1 year ago

I'll close this now, but feel free to re-open if there's anything new to report.