mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
udp: split out TTL and loop options
Split setting the TTL and loop parameters in 2 methods as they are not related. Fix setting the TTL correctly for multicast streams. See #588245
This commit is contained in:
parent
6a53d0a2c9
commit
e2518fedbe
3 changed files with 96 additions and 19 deletions
|
@ -723,14 +723,26 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
|
||||||
sink->bytes_to_serve = 0;
|
sink->bytes_to_serve = 0;
|
||||||
sink->bytes_served = 0;
|
sink->bytes_served = 0;
|
||||||
|
|
||||||
gst_udp_set_loop_ttl (sink->sock, sink->loop, sink->ttl);
|
|
||||||
gst_multiudpsink_setup_qos_dscp (sink);
|
gst_multiudpsink_setup_qos_dscp (sink);
|
||||||
|
|
||||||
/* look for multicast clients and join multicast groups appropriately */
|
/* look for multicast clients and join multicast groups appropriately
|
||||||
|
set also ttl and multicast loopback delivery appropriately */
|
||||||
for (clients = sink->clients; clients; clients = g_list_next (clients)) {
|
for (clients = sink->clients; clients; clients = g_list_next (clients)) {
|
||||||
client = (GstUDPClient *) clients->data;
|
client = (GstUDPClient *) clients->data;
|
||||||
if (sink->auto_multicast && gst_udp_is_multicast (&client->theiraddr))
|
if (gst_udp_is_multicast (&client->theiraddr)) {
|
||||||
gst_udp_join_group (*(client->sock), &client->theiraddr, NULL);
|
if (sink->auto_multicast) {
|
||||||
|
if (gst_udp_join_group (*(client->sock), &client->theiraddr, NULL)
|
||||||
|
!= 0)
|
||||||
|
goto join_group_failed;
|
||||||
|
}
|
||||||
|
if (gst_udp_set_loop (sink->sock, sink->loop) != 0)
|
||||||
|
goto loop_failed;
|
||||||
|
if (gst_udp_set_ttl (sink->sock, sink->ttl, TRUE) != 0)
|
||||||
|
goto ttl_failed;
|
||||||
|
} else {
|
||||||
|
if (gst_udp_set_ttl (sink->sock, sink->ttl, FALSE) != 0)
|
||||||
|
goto ttl_failed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -749,6 +761,29 @@ no_broadcast:
|
||||||
g_strerror (errno)));
|
g_strerror (errno)));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
join_group_failed:
|
||||||
|
{
|
||||||
|
CLOSE_IF_REQUESTED (sink);
|
||||||
|
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
|
||||||
|
("Could not join multicast group (%d): %s", errno, g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
ttl_failed:
|
||||||
|
{
|
||||||
|
CLOSE_IF_REQUESTED (sink);
|
||||||
|
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
|
||||||
|
("Could not set TTL socket option (%d): %s", errno,
|
||||||
|
g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
loop_failed:
|
||||||
|
{
|
||||||
|
CLOSE_IF_REQUESTED (sink);
|
||||||
|
GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL),
|
||||||
|
("Could not set loopback socket option (%d): %s", errno,
|
||||||
|
g_strerror (errno)));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -113,7 +113,7 @@ beach:
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
|
gst_udp_set_loop (int sockfd, gboolean loop)
|
||||||
{
|
{
|
||||||
socklen_t socklen;
|
socklen_t socklen;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
|
@ -128,29 +128,70 @@ gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
|
||||||
switch (addr.ss_family) {
|
switch (addr.ss_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
{
|
{
|
||||||
if ((ret =
|
ret = setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l, sizeof (l));
|
||||||
setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
|
if (ret < 0)
|
||||||
sizeof (l))) < 0)
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if ((ret =
|
break;
|
||||||
setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
|
}
|
||||||
sizeof (ttl))) < 0)
|
case AF_INET6:
|
||||||
|
{
|
||||||
|
ret =
|
||||||
|
setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
|
||||||
|
sizeof (l));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
WSASetLastError (WSAEAFNOSUPPORT);
|
||||||
|
#else
|
||||||
|
errno = EAFNOSUPPORT;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
gst_udp_set_ttl (int sockfd, int ttl, gboolean is_multicast)
|
||||||
|
{
|
||||||
|
socklen_t socklen;
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
int optname = -1;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
socklen = sizeof (addr);
|
||||||
|
if ((ret = getsockname (sockfd, (struct sockaddr *) &addr, &socklen)) < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (addr.ss_family) {
|
||||||
|
case AF_INET:
|
||||||
|
{
|
||||||
|
optname = (is_multicast == TRUE) ? IP_MULTICAST_TTL : IP_TTL;
|
||||||
|
ret = setsockopt (sockfd, IPPROTO_IP, optname, &ttl, sizeof (ttl));
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
{
|
{
|
||||||
if ((ret =
|
optname =
|
||||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
|
(is_multicast == TRUE) ? IPV6_MULTICAST_HOPS : IPV6_UNICAST_HOPS;
|
||||||
sizeof (l))) < 0)
|
ret = setsockopt (sockfd, IPPROTO_IPV6, optname, &ttl, sizeof (ttl));
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if ((ret =
|
/* When using IPV4 address with IPV6 socket, both TTL values
|
||||||
setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
|
must be set in order to actually use the given value.
|
||||||
sizeof (ttl))) < 0)
|
Has no effect when IPV6 address is used. */
|
||||||
|
optname = (is_multicast == TRUE) ? IP_MULTICAST_TTL : IP_TTL;
|
||||||
|
ret = setsockopt (sockfd, IPPROTO_IP, optname, &ttl, sizeof (ttl));
|
||||||
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -80,7 +80,8 @@ int gst_udp_get_sockaddr_length(struct sockaddr_storage *addr);
|
||||||
int gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr);
|
int gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr);
|
||||||
int gst_udp_is_multicast (struct sockaddr_storage *addr);
|
int gst_udp_is_multicast (struct sockaddr_storage *addr);
|
||||||
|
|
||||||
int gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl);
|
int gst_udp_set_loop (int sockfd, gboolean loop);
|
||||||
|
int gst_udp_set_ttl (int sockfd, int ttl, gboolean is_multicast);
|
||||||
|
|
||||||
int gst_udp_join_group (int sockfd, struct sockaddr_storage *addr,
|
int gst_udp_join_group (int sockfd, struct sockaddr_storage *addr,
|
||||||
gchar *iface);
|
gchar *iface);
|
||||||
|
|
Loading…
Reference in a new issue