From 969622b439cc7232e8889cd5c7a5579cba6b665f Mon Sep 17 00:00:00 2001 From: Aurelien Grimaud Date: Mon, 23 Feb 2009 20:49:37 +0100 Subject: Read ICMP error messages instead of looping When we are dealing with connected sockets shared between a udpsrc and a udpsink we might receive ICMP connection refused error messages in udpsrc that will cause it to go into a bursty loop because the poll returns right away without a message to read. Instead of looping, read the error message from the error queue in udpsrc. Fixes #567857. --- gst/udp/gstudpsrc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'gst/udp/gstudpsrc.c') diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index bcdbc359..58980b9e 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -357,6 +357,35 @@ gst_udpsrc_getcaps (GstBaseSrc * src) return gst_caps_new_any (); } +/* read a message from the error queue */ +static void +clear_error (GstUDPSrc * udpsrc) +{ + struct msghdr cmsg; + char cbuf[128]; + char msgbuf[CMSG_SPACE (128)]; + struct iovec iov; + + /* Flush ERRORS from fd so next poll will not return at once */ + /* No need for address : We look for local error */ + cmsg.msg_name = NULL; + cmsg.msg_namelen = 0; + + /* IOV */ + memset (&cbuf, 0, sizeof (cbuf)); + iov.iov_base = cbuf; + iov.iov_len = sizeof (cbuf); + cmsg.msg_iov = &iov; + cmsg.msg_iovlen = 1; + + /* msg_control */ + memset (&msgbuf, 0, sizeof (msgbuf)); + cmsg.msg_control = &msgbuf; + cmsg.msg_controllen = sizeof (msgbuf); + + recvmsg (udpsrc->sock.fd, &cmsg, MSG_ERRQUEUE); +} + static GstFlowReturn gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) { @@ -434,8 +463,10 @@ retry: * woken up by activity on the socket but it was not a read. We know someone * will also do something with the socket so that we don't go into an infinite * loop in the select(). */ - if (G_UNLIKELY (!readsize)) + if (G_UNLIKELY (!readsize)) { + clear_error (udpsrc); goto retry; + } no_select: GST_LOG_OBJECT (udpsrc, "ioctl says %d bytes available", (int) readsize); @@ -447,10 +478,11 @@ no_select: len = sizeof (struct sockaddr); #ifdef G_OS_WIN32 ret = recvfrom (udpsrc->sock.fd, (char *) pktdata, pktsize, + 0, (struct sockaddr *) &tmpaddr, &len); #else ret = recvfrom (udpsrc->sock.fd, pktdata, pktsize, -#endif 0, (struct sockaddr *) &tmpaddr, &len); +#endif if (G_UNLIKELY (ret < 0)) { #ifdef G_OS_WIN32 /* WSAECONNRESET for a UDP socket means that a packet sent with udpsink @@ -730,6 +762,7 @@ static gboolean gst_udpsrc_start (GstBaseSrc * bsrc) { guint bc_val; + guint err_val; gint reuse; int port; GstUDPSrc *src; @@ -821,6 +854,15 @@ gst_udpsrc_start (GstBaseSrc * bsrc) g_strerror (errno), errno)); } + /* Accept ERRQUEUE to get and flush icmp errors */ + err_val = 1; + if ((ret = setsockopt (src->sock.fd, IPPROTO_IP, IP_RECVERR, &err_val, + sizeof (err_val))) < 0) { + GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), + ("could not configure socket for IP_RECVERR %d: %s (%d)", ret, + g_strerror (errno), errno)); + } + if (src->auto_multicast && gst_udp_is_multicast (&src->myaddr)) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->multi_group); ret = gst_udp_join_group (src->sock.fd, &src->myaddr); -- cgit From 8588ebd22a07c5f994b3410db6e73676b38550fd Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 24 Feb 2009 17:58:32 +0000 Subject: udp: Fix strict-aliasing warnings from gcc 4.4.0 Fix strict aliasing warnings by defining a union on the different sockaddr structs that we need. --- gst/udp/gstudpsrc.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'gst/udp/gstudpsrc.c') diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index 58980b9e..690bc068 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -391,7 +391,13 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) { GstUDPSrc *udpsrc; GstNetBuffer *outbuf; - struct sockaddr_storage tmpaddr; + union gst_sockaddr + { + struct sockaddr_storage sa_stor; + struct sockaddr sa; + struct sockaddr_in sa_in; + struct sockaddr_in6 sa_in6; + } sa; socklen_t len; guint8 *pktdata; gint pktsize; @@ -478,10 +484,10 @@ no_select: len = sizeof (struct sockaddr); #ifdef G_OS_WIN32 ret = recvfrom (udpsrc->sock.fd, (char *) pktdata, pktsize, - 0, (struct sockaddr *) &tmpaddr, &len); + 0, &sa.sa, &len); #else ret = recvfrom (udpsrc->sock.fd, pktdata, pktsize, - 0, (struct sockaddr *) &tmpaddr, &len); + 0, &sa.sa, &len); #endif if (G_UNLIKELY (ret < 0)) { #ifdef G_OS_WIN32 @@ -518,22 +524,19 @@ no_select: GST_BUFFER_DATA (outbuf) = pktdata; GST_BUFFER_SIZE (outbuf) = ret; - switch (tmpaddr.ss_family) { + switch (sa.sa_stor.ss_family) { case AF_INET: { - gst_netaddress_set_ip4_address (&outbuf->from, - ((struct sockaddr_in *) &tmpaddr)->sin_addr.s_addr, - ((struct sockaddr_in *) &tmpaddr)->sin_port); + gst_netaddress_set_ip4_address (&outbuf->from, sa.sa_in.sin_addr.s_addr, + sa.sa_in.sin_port); } break; case AF_INET6: { guint8 ip6[16]; - memcpy (ip6, &((struct sockaddr_in6 *) &tmpaddr)->sin6_addr, - sizeof (ip6)); - gst_netaddress_set_ip6_address (&outbuf->from, ip6, - ((struct sockaddr_in *) &tmpaddr)->sin_port); + memcpy (ip6, &sa.sa_in6.sin6_addr, sizeof (ip6)); + gst_netaddress_set_ip6_address (&outbuf->from, ip6, sa.sa_in6.sin6_port); } break; default: -- cgit From 6e5e9edabfc34f0486f7befcae9d5860fe76427b Mon Sep 17 00:00:00 2001 From: Peter Kjellerstedt Date: Wed, 25 Feb 2009 11:32:28 +0100 Subject: udpsrc: Unify the use of union gst_sockaddr. --- gst/udp/gstudpsrc.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'gst/udp/gstudpsrc.c') diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index 690bc068..586f7c57 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -393,12 +393,12 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf) GstNetBuffer *outbuf; union gst_sockaddr { - struct sockaddr_storage sa_stor; struct sockaddr sa; struct sockaddr_in sa_in; struct sockaddr_in6 sa_in6; + struct sockaddr_storage sa_stor; } sa; - socklen_t len; + socklen_t slen; guint8 *pktdata; gint pktsize; #ifdef G_OS_UNIX @@ -481,13 +481,12 @@ no_select: pktsize = readsize; while (TRUE) { - len = sizeof (struct sockaddr); + slen = sizeof (struct sockaddr); #ifdef G_OS_WIN32 - ret = recvfrom (udpsrc->sock.fd, (char *) pktdata, pktsize, - 0, &sa.sa, &len); + ret = recvfrom (udpsrc->sock.fd, (char *) pktdata, pktsize, 0, &sa.sa, + &slen); #else - ret = recvfrom (udpsrc->sock.fd, pktdata, pktsize, - 0, &sa.sa, &len); + ret = recvfrom (udpsrc->sock.fd, pktdata, pktsize, 0, &sa.sa, &slen); #endif if (G_UNLIKELY (ret < 0)) { #ifdef G_OS_WIN32 @@ -524,7 +523,7 @@ no_select: GST_BUFFER_DATA (outbuf) = pktdata; GST_BUFFER_SIZE (outbuf) = ret; - switch (sa.sa_stor.ss_family) { + switch (sa.sa.sa_family) { case AF_INET: { gst_netaddress_set_ip4_address (&outbuf->from, sa.sa_in.sin_addr.s_addr, -- cgit From 7c56695160cd522f3998812dc796f3af34cb3465 Mon Sep 17 00:00:00 2001 From: Peter Kjellerstedt Date: Wed, 25 Feb 2009 11:35:31 +0100 Subject: udpsrc: Make sure the sockaddr length used for recvfrom() is big enough. Previously the sockaddr length used for recvfrom() was calculated as sizeof (struct sockaddr). However, this is too little to hold an IPv6 address, so the full size of the gst_sockaddr union should be used instead. --- gst/udp/gstudpsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gst/udp/gstudpsrc.c') diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index 586f7c57..5b4f6a3e 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -481,7 +481,7 @@ no_select: pktsize = readsize; while (TRUE) { - slen = sizeof (struct sockaddr); + slen = sizeof (sa); #ifdef G_OS_WIN32 ret = recvfrom (udpsrc->sock.fd, (char *) pktdata, pktsize, 0, &sa.sa, &slen); -- cgit From 40bc0400640d356aa008e2dd1821eb885e41adc3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 25 Feb 2009 14:01:26 +0100 Subject: udpsrc: fix compilation Fix compilation on systems MSG_ERRQUEUE and IP_RECVERR. --- gst/udp/gstudpsrc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'gst/udp/gstudpsrc.c') diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index 5b4f6a3e..8d92241e 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -361,6 +361,7 @@ gst_udpsrc_getcaps (GstBaseSrc * src) static void clear_error (GstUDPSrc * udpsrc) { +#if defined (MSG_ERRQUEUE) struct msghdr cmsg; char cbuf[128]; char msgbuf[CMSG_SPACE (128)]; @@ -384,6 +385,7 @@ clear_error (GstUDPSrc * udpsrc) cmsg.msg_controllen = sizeof (msgbuf); recvmsg (udpsrc->sock.fd, &cmsg, MSG_ERRQUEUE); +#endif } static GstFlowReturn @@ -858,12 +860,14 @@ gst_udpsrc_start (GstBaseSrc * bsrc) /* Accept ERRQUEUE to get and flush icmp errors */ err_val = 1; +#if defined (IP_RECVERR) if ((ret = setsockopt (src->sock.fd, IPPROTO_IP, IP_RECVERR, &err_val, sizeof (err_val))) < 0) { GST_ELEMENT_WARNING (src, RESOURCE, SETTINGS, (NULL), ("could not configure socket for IP_RECVERR %d: %s (%d)", ret, g_strerror (errno), errno)); } +#endif if (src->auto_multicast && gst_udp_is_multicast (&src->myaddr)) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->multi_group); -- cgit