diff --git a/libavformat/udp.c b/libavformat/udp.c index 4bfe4fd4e3535b22ac1edeb7e40159a33b745a81..cf73d331e0472f20ecbab9c6c873a3a0ac98bef4 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) {