udpsrc: receive control messages only in multicast

Control messages are used only in multicast mode - to detect if the destination
address is not ours and possibly drop the packet. However in non-multicast
modes the messages are still allocated and freed even if not used. Therefore
request control messages from g_socket_receive_message() only in multicast
mode.

https://bugzilla.gnome.org/show_bug.cgi?id=772841
This commit is contained in:
Petr Kulhavy 2016-11-12 23:34:23 +01:00 committed by Sebastian Dröge
parent 55297bdbad
commit 1fc572d740

View file

@ -847,6 +847,7 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
gssize res; gssize res;
gsize offset; gsize offset;
GSocketControlMessage **msgs = NULL; GSocketControlMessage **msgs = NULL;
GSocketControlMessage ***p_msgs;
gint n_msgs = 0, i; gint n_msgs = 0, i;
udpsrc = GST_UDPSRC_CAST (psrc); udpsrc = GST_UDPSRC_CAST (psrc);
@ -854,6 +855,11 @@ gst_udpsrc_create (GstPushSrc * psrc, GstBuffer ** buf)
if (!gst_udpsrc_ensure_mem (udpsrc)) if (!gst_udpsrc_ensure_mem (udpsrc))
goto memory_alloc_error; goto memory_alloc_error;
/* optimization: use messages only in multicast mode */
p_msgs =
(g_inet_address_get_is_multicast (g_inet_socket_address_get_address
(udpsrc->addr))) ? &msgs : NULL;
/* Retrieve sender address unless we've been configured not to do so */ /* Retrieve sender address unless we've been configured not to do so */
p_saddr = (udpsrc->retrieve_sender_address) ? &saddr : NULL; p_saddr = (udpsrc->retrieve_sender_address) ? &saddr : NULL;
@ -898,7 +904,7 @@ retry:
res = res =
g_socket_receive_message (udpsrc->used_socket, p_saddr, udpsrc->vec, 2, g_socket_receive_message (udpsrc->used_socket, p_saddr, udpsrc->vec, 2,
&msgs, &n_msgs, &flags, udpsrc->cancellable, &err); p_msgs, &n_msgs, &flags, udpsrc->cancellable, &err);
if (G_UNLIKELY (res < 0)) { if (G_UNLIKELY (res < 0)) {
/* G_IO_ERROR_HOST_UNREACHABLE for a UDP socket means that a packet sent /* G_IO_ERROR_HOST_UNREACHABLE for a UDP socket means that a packet sent
@ -923,44 +929,40 @@ retry:
/* Retry if multicast and the destination address is not ours. We don't want /* Retry if multicast and the destination address is not ours. We don't want
* to receive arbitrary packets */ * to receive arbitrary packets */
{ if (p_msgs) {
GInetAddress *iaddr = g_inet_socket_address_get_address (udpsrc->addr); GInetAddress *iaddr = g_inet_socket_address_get_address (udpsrc->addr);
gboolean skip_packet = FALSE; gboolean skip_packet = FALSE;
gsize iaddr_size = g_inet_address_get_native_size (iaddr); gsize iaddr_size = g_inet_address_get_native_size (iaddr);
const guint8 *iaddr_bytes = g_inet_address_to_bytes (iaddr); const guint8 *iaddr_bytes = g_inet_address_to_bytes (iaddr);
if (g_inet_address_get_is_multicast (iaddr)) { for (i = 0; i < n_msgs && !skip_packet; i++) {
for (i = 0; i < n_msgs && !skip_packet; i++) {
#ifdef IP_PKTINFO #ifdef IP_PKTINFO
if (GST_IS_IP_PKTINFO_MESSAGE (msgs[i])) { if (GST_IS_IP_PKTINFO_MESSAGE (msgs[i])) {
GstIPPktinfoMessage *msg = GST_IP_PKTINFO_MESSAGE (msgs[i]); GstIPPktinfoMessage *msg = GST_IP_PKTINFO_MESSAGE (msgs[i]);
if (sizeof (msg->addr) == iaddr_size if (sizeof (msg->addr) == iaddr_size
&& memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr))) && memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr)))
skip_packet = TRUE; skip_packet = TRUE;
} }
#endif #endif
#ifdef IPV6_PKTINFO #ifdef IPV6_PKTINFO
if (GST_IS_IPV6_PKTINFO_MESSAGE (msgs[i])) { if (GST_IS_IPV6_PKTINFO_MESSAGE (msgs[i])) {
GstIPV6PktinfoMessage *msg = GST_IPV6_PKTINFO_MESSAGE (msgs[i]); GstIPV6PktinfoMessage *msg = GST_IPV6_PKTINFO_MESSAGE (msgs[i]);
if (sizeof (msg->addr) == iaddr_size if (sizeof (msg->addr) == iaddr_size
&& memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr))) && memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr)))
skip_packet = TRUE; skip_packet = TRUE;
} }
#endif #endif
#ifdef IP_RECVDSTADDR #ifdef IP_RECVDSTADDR
if (GST_IS_IP_RECVDSTADDR_MESSAGE (msgs[i])) { if (GST_IS_IP_RECVDSTADDR_MESSAGE (msgs[i])) {
GstIPRecvdstaddrMessage *msg = GST_IP_RECVDSTADDR_MESSAGE (msgs[i]); GstIPRecvdstaddrMessage *msg = GST_IP_RECVDSTADDR_MESSAGE (msgs[i]);
if (sizeof (msg->addr) == iaddr_size if (sizeof (msg->addr) == iaddr_size
&& memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr))) && memcmp (iaddr_bytes, &msg->addr, sizeof (msg->addr)))
skip_packet = TRUE; skip_packet = TRUE;
}
#endif
} }
#endif
} }
for (i = 0; i < n_msgs; i++) { for (i = 0; i < n_msgs; i++) {