GNOME Bugzilla – Bug 771530
Clarify that a multicast interface *name* is required, not an IP or anything else
Last modified: 2016-10-31 14:31:26 UTC
Using gst-rtsp-server git master as of commit 74c8a9f4cff34c99fe8e2dc1c7aec4749f9a1fcf against gstreamer and plugins 1.9.2 release tarballs. I was getting ENODEV from the multicast group join setsockopt call unless I have a default route on the machine. This seems to be known behaviour in Linux when the imr_interface is "Any". I added a call to gst_rtsp_media_factory_set_multicast_iface so my code basically does this... gst_rtsp_address_pool_add_range(pool, "239.255.7.0", "239.255.7.1", 5000, 5001, 16); gst_rtsp_media_factory_set_address_pool(factory, pool); gst_rtsp_media_factory_set_protocols(factory, GST_RTSP_LOWER_TRANS_UDP_MCAST); gst_rtsp_media_factory_set_multicast_iface(factory, ipaddr); (here ipaddr is the string "192.168.9.102", which is the local interface IP addr) But it seems like the multicast_iface address specified is not making it through to the setsockopt call. Using strace I see this... [pid 723] setsockopt(19, SOL_IP, IP_ADD_MEMBERSHIP, {imr_multiaddr=inet_addr("239.255.7.0"), imr_interface=inet_addr("0.0.0.0")}, 12) = -1 ENODEV (No such device) But if I do "ip route add default dev eth0", then I get this... [pid 676] setsockopt(19, SOL_IP, IP_ADD_MEMBERSHIP, {imr_multiaddr=inet_addr("239.255.7.0"), imr_interface=inet_addr("0.0.0.0")}, 12) = 0 and streaming works. I'd have expected the string I specified in gst_rtsp_media_factory_set_multicast_iface to show up in imr_interface.
I added a little debug to gstmultiudpsink.c where it calls the group join... GST_DEBUG_OBJECT (sink, "autojoining group on iface %s", sink->multi_iface); if (!g_socket_join_multicast_group (socket, addr, FALSE, sink->multi_iface, &err)) And get this... 0:00:21.526560977 532 0xb5215a00 DEBUG multiudpsink gstmultiudpsink.c:1256:gst_multiudpsink_configure_client:<multiudpsink1> autojoining group on iface 192.168.9.102 [pid 544] setsockopt(20, SOL_IP, IP_ADD_MEMBERSHIP, {imr_multiaddr=inet_addr("239.255.7.0"), imr_interface=inet_addr("0.0.0.0")}, 12) = -1 ENODEV (No such device) 0:00:21.896296692 532 0xb5215a00 WARN multiudpsink gstmultiudpsink.c:1277:gst_multiudpsink_configure_client:<multiudpsink1> error: Could not join multicast group: Error joining multicast group: No such device So it looks like the multi_iface property is set OK and it's the underlying glib call that's broken. :-(
Further digging shows this in Glib/Gio's gsocket.c #ifdef HAVE_IP_MREQN if (iface) mc_req.imr_ifindex = if_nametoindex (iface); else mc_req.imr_ifindex = 0; /* Pick any. */ The imr_interface field is not used, and if_nametoindex looks up the interface name, not the interface's ip addr. I changed my rtsp server code to have this instead: gst_rtsp_media_factory_set_multicast_iface(factory, "eth0"); And now the multicast join works without a default route. So, this bug isn't really a bug at all, except maybe to note that some documentation for gst_rtsp_media_factory_set_multicast_iface with info on what was expected for the parameters would be nice.
Perhaps you could suggest a suitable addition for the documentation? :)
Created attachment 335759 [details] [review] Patch to add the word "name" to the iface parameter description.
Well, the entry for g_socket_join_multicast_group says this... iface Name of the interface to use, or NULL. which of course I'm only noticing now. So maybe just putting the word "name" on the end of the parameter is enough? Possible patch attached.
commit 34389831cb18e41be002314c524e4010e2ab8e8f Author: Ian Jamison <ian.dev@arkver.com> Date: Sat Sep 17 13:17:19 2016 +0100 rtsp-server: Hint that set_multicast_iface expects the name of the interface To prevent any possibly confusion with IPs or anything else. https://bugzilla.gnome.org/show_bug.cgi?id=771530
Using a IP would also not be unambiguous, it must be a name.