summaryrefslogtreecommitdiff
path: root/libavformat/udp.c
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2018-09-21 23:34:50 +0200
committerMarton Balint <cus@passwd.hu>2018-10-03 22:03:29 +0200
commitab0812c1a8925a95315354b88b41256faad5faa8 (patch)
tree4ecb5616ac66965e3746bc7694fc032352953cb7 /libavformat/udp.c
parentd3bda871f033be4825ecb69d444b3396bf2a2eb7 (diff)
avformat/udp: always use IP_ADD_SOURCE_MEMBERSHIP for subscribing to an UDP multicast source group in IPv4
That alone supports specifying the interface based on its address. Getting the interface index from the local address seems quite a bit of work in a platform independent way... Obviously for IPv6 we still always use MCAST_JOIN_SOURCE_GROUP. As a side effect this also fixes ticket #7459. Signed-off-by: Marton Balint <cus@passwd.hu>
Diffstat (limited to 'libavformat/udp.c')
-rw-r--r--libavformat/udp.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 4bfe4fd4e3..cf73d331e0 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -246,36 +246,40 @@ static int udp_set_multicast_sources(URLContext *h,
struct sockaddr_storage *sources,
int nb_sources, int include)
{
-#if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE) && !defined(_WIN32) && (!defined(TARGET_OS_TV) || !TARGET_OS_TV)
- /* These ones are available in the microsoft SDK, but don't seem to work
- * as on linux, so just prefer the v4-only approach there for now. */
- int i;
- for (i = 0; i < nb_sources; i++) {
- struct group_source_req mreqs;
- int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
-
- //TODO: Interface index should be looked up from local_addr
- mreqs.gsr_interface = 0;
- memcpy(&mreqs.gsr_group, addr, addr_len);
- memcpy(&mreqs.gsr_source, &sources[i], sizeof(*sources));
-
- if (setsockopt(sockfd, level,
- include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
- (const void *)&mreqs, sizeof(mreqs)) < 0) {
- if (include)
- ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)");
- else
- ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)");
- return ff_neterrno();
- }
- }
-#elif HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
int i;
if (addr->sa_family != AF_INET) {
+#if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE)
+ /* For IPv4 prefer the old approach, as that alone works reliably on
+ * Windows and it also supports supplying the interface based on its
+ * address. */
+ int i;
+ for (i = 0; i < nb_sources; i++) {
+ struct group_source_req mreqs;
+ int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+
+ //TODO: Interface index should be looked up from local_addr
+ mreqs.gsr_interface = 0;
+ memcpy(&mreqs.gsr_group, addr, addr_len);
+ memcpy(&mreqs.gsr_source, &sources[i], sizeof(*sources));
+
+ if (setsockopt(sockfd, level,
+ include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
+ (const void *)&mreqs, sizeof(mreqs)) < 0) {
+ if (include)
+ ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)");
+ else
+ ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)");
+ return ff_neterrno();
+ }
+ }
+ return 0;
+#else
av_log(NULL, AV_LOG_ERROR,
"Setting multicast sources only supported for IPv4\n");
return AVERROR(EINVAL);
+#endif
}
+#if HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
for (i = 0; i < nb_sources; i++) {
struct ip_mreq_source mreqs;
if (sources[i].ss_family != AF_INET) {