Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
IPTV/RTP input: handle source specific multicast (SSM) URLs in Linux
  • Loading branch information
duncanthrax authored and perexg committed Mar 27, 2017
1 parent 88f6e66 commit 071badd
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 12 deletions.
4 changes: 3 additions & 1 deletion src/input/mpegts/iptv/iptv_udp.c
Expand Up @@ -40,7 +40,9 @@ iptv_udp_start ( iptv_mux_t *im, const char *raw, const url_t *url )

mpegts_mux_nice_name((mpegts_mux_t*)im, name, sizeof(name));

conn = udp_bind(LS_IPTV, name, url->host, url->port,
/* Note: url->user is used for specifying multicast source address (SSM)
here. The URL format is rtp://<srcaddr>@<grpaddr>:<port> */
conn = udp_bind(LS_IPTV, name, url->host, url->port, url->user,
im->mm_iptv_interface, IPTV_BUF_SIZE, 4*1024);
if (conn == UDP_FATAL_ERROR)
return SM_CODE_TUNING_FAILED;
Expand Down
53 changes: 45 additions & 8 deletions src/udp.c
Expand Up @@ -119,7 +119,7 @@ udp_get_ifindex( const char *ifname )
return r;
}

#if defined(PLATFORM_DARWIN)
#if defined(PLATFORM_LINUX) || defined(PLATFORM_DARWIN)
static int
udp_get_ifaddr( int fd, const char *ifname, struct in_addr *addr )
{
Expand Down Expand Up @@ -154,7 +154,7 @@ udp_get_solip( void )

udp_connection_t *
udp_bind ( int subsystem, const char *name,
const char *bindaddr, int port,
const char *bindaddr, int port, const char *multicast_src,
const char *ifname, int rxsize, int txsize )
{
int fd, ifindex, reuse = 1;
Expand Down Expand Up @@ -233,11 +233,48 @@ udp_bind ( int subsystem, const char *name,
}
#endif

if (setsockopt(fd, udp_get_solip(), IP_ADD_MEMBERSHIP, &m, sizeof(m))) {
inet_ntop(AF_INET, &m.imr_multiaddr, buf, sizeof(buf));
tvhwarn(subsystem, "%s - cannot join %s [%s]",
name, buf, strerror(errno));
#if defined(PLATFORM_LINUX)
if (multicast_src) {

struct ip_mreq_source ms;
memset(&ms, 0, sizeof(ms));

ms.imr_multiaddr = IP_AS_V4(uc->ip, addr);

/* Unfortunately, ip_mreq_source does not support the ifindex parameter,
so we have to resolve to the ip of the interface. */
if (udp_get_ifaddr(fd, ifname, &ms.imr_interface) == -1) {
tvherror(subsystem, "%s - cannot find ip address for interface %s [e=%s]",
name, ifname, strerror(errno));
goto error;
}

if (inet_pton(AF_INET, multicast_src, &ms.imr_sourceaddr) < 1) {
tvherror(subsystem, "%s - invalid ipv4 address '%s' specified as multicast source [e=%s]",
name, multicast_src, strerror(errno));
goto error;
}

if (setsockopt(fd, udp_get_solip(), IP_ADD_SOURCE_MEMBERSHIP,
&ms, sizeof(ms)) < 0) {
tvherror(subsystem, "%s - setsockopt IP_ADD_SOURCE_MEMBERSHIP failed [e=%s]",
name, strerror(errno));
goto error;
}

}
else {
#endif
if (setsockopt(fd, udp_get_solip(), IP_ADD_MEMBERSHIP, &m, sizeof(m))) {
inet_ntop(AF_INET, &m.imr_multiaddr, buf, sizeof(buf));
tvhwarn(subsystem, "%s - cannot join %s [%s]",
name, buf, strerror(errno));
}
#if defined(PLATFORM_LINUX)
}
#endif


}

/* Bind to IPv6 group */
Expand Down Expand Up @@ -309,13 +346,13 @@ udp_bind_double ( udp_connection_t **_u1, udp_connection_t **_u2,

memset(&ucs, 0, sizeof(ucs));
while (1) {
u1 = udp_bind(subsystem, name1, host, port, ifname, rxsize1, txsize1);
u1 = udp_bind(subsystem, name1, host, port, NULL, ifname, rxsize1, txsize1);
if (u1 == NULL || u1 == UDP_FATAL_ERROR)
goto fail;
port2 = ntohs(IP_PORT(u1->ip));
/* RTP port should be even, RTCP port should be odd */
if ((port2 % 2) == 0) {
u2 = udp_bind(subsystem, name2, host, port2 + 1, ifname, rxsize2, txsize2);
u2 = udp_bind(subsystem, name2, host, port2 + 1, NULL, ifname, rxsize2, txsize2);
if (u2 != NULL && u2 != UDP_FATAL_ERROR)
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/udp.h
Expand Up @@ -43,7 +43,7 @@ typedef struct udp_connection {

udp_connection_t *
udp_bind ( int subsystem, const char *name,
const char *bindaddr, int port,
const char *bindaddr, int port, const char *multicast_src,
const char *ifname, int rxsize, int txsize );
int
udp_bind_double ( udp_connection_t **_u1, udp_connection_t **_u2,
Expand Down
4 changes: 2 additions & 2 deletions src/upnp.c
Expand Up @@ -138,11 +138,11 @@ upnp_thread( void *aux )
int r, delay_ms;

multicast = udp_bind(LS_UPNP, "upnp_thread_multicast",
"239.255.255.250", 1900,
"239.255.255.250", 1900, NULL,
NULL, 32*1024, 32*1024);
if (multicast == NULL || multicast == UDP_FATAL_ERROR)
goto error;
unicast = udp_bind(LS_UPNP, "upnp_thread_unicast", bindaddr, 0,
unicast = udp_bind(LS_UPNP, "upnp_thread_unicast", bindaddr, 0, NULL,
NULL, 32*1024, 32*1024);
if (unicast == NULL || unicast == UDP_FATAL_ERROR)
goto error;
Expand Down

1 comment on commit 071badd

@SqTER-PL
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix causes an error.
Can not join multicast udp group

Please sign in to comment.