stream: handle failed port allocation
authorWim Taymans <wim.taymans@collabora.co.uk>
Mon, 1 Jul 2013 12:45:49 +0000 (14:45 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Mon, 1 Jul 2013 12:47:33 +0000 (14:47 +0200)
Allow for ipv4 or ipv6 socket allocations to fail. Only report failure if we
can't allocate any family at all. Also keep track of what port families we
allocated.

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=703175

gst/rtsp-server/rtsp-stream.c

index 920a87f..a9d7037 100644 (file)
@@ -68,10 +68,12 @@ struct _GstRTSPStreamPrivate
   /* server ports for sending/receiving over ipv4 */
   GstRTSPRange server_port_v4;
   GstRTSPAddress *server_addr_v4;
+  gboolean have_ipv4;
 
   /* server ports for sending/receiving over ipv6 */
   GstRTSPRange server_port_v6;
   GstRTSPAddress *server_addr_v6;
+  gboolean have_ipv6;
 
   /* multicast addresses */
   GstRTSPAddressPool *pool;
@@ -536,11 +538,12 @@ alloc_ports_one_family (GstRTSPAddressPool * pool, gint buffer_size,
   GInetAddress *inetaddr = NULL;
   GSocketAddress *rtp_sockaddr = NULL;
   GSocketAddress *rtcp_sockaddr = NULL;
-  const gchar *multisink_socket = "socket";
+  const gchar *multisink_socket;
 
-  if (family == G_SOCKET_FAMILY_IPV6) {
+  if (family == G_SOCKET_FAMILY_IPV6)
     multisink_socket = "socket-v6";
-  }
+  else
+    multisink_socket = "socket";
 
   udpsrc0 = NULL;
   udpsrc1 = NULL;
@@ -772,12 +775,15 @@ alloc_ports (GstRTSPStream * stream)
 {
   GstRTSPStreamPrivate *priv = stream->priv;
 
-  return alloc_ports_one_family (priv->pool, priv->buffer_size,
+  priv->have_ipv4 = alloc_ports_one_family (priv->pool, priv->buffer_size,
       G_SOCKET_FAMILY_IPV4, priv->udpsrc_v4, priv->udpsink,
-      &priv->server_port_v4, &priv->server_addr_v4) &&
-      alloc_ports_one_family (priv->pool, priv->buffer_size,
+      &priv->server_port_v4, &priv->server_addr_v4);
+
+  priv->have_ipv6 = alloc_ports_one_family (priv->pool, priv->buffer_size,
       G_SOCKET_FAMILY_IPV6, priv->udpsrc_v6, priv->udpsink,
       &priv->server_port_v6, &priv->server_addr_v6);
+
+  return priv->have_ipv4 || priv->have_ipv6;
 }
 
 /**
@@ -1246,28 +1252,34 @@ gst_rtsp_stream_join_bin (GstRTSPStream * stream, GstBin * bin,
     gst_pad_link (pad, priv->recv_sink[i]);
     gst_object_unref (pad);
 
-    /* we set and keep these to playing so that they don't cause NO_PREROLL return
-     * values */
-    gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_PLAYING);
-    gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_PLAYING);
-    gst_element_set_locked_state (priv->udpsrc_v4[i], TRUE);
-    gst_element_set_locked_state (priv->udpsrc_v6[i], TRUE);
-    /* add udpsrc */
-    gst_bin_add (bin, priv->udpsrc_v4[i]);
-    gst_bin_add (bin, priv->udpsrc_v6[i]);
-    /* and link to the funnel v4 */
-    selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
-    pad = gst_element_get_static_pad (priv->udpsrc_v4[i], "src");
-    gst_pad_link (pad, selpad);
-    gst_object_unref (pad);
-    gst_object_unref (selpad);
+    if (priv->udpsrc_v4[i]) {
+      /* we set and keep these to playing so that they don't cause NO_PREROLL return
+       * values */
+      gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_PLAYING);
+      gst_element_set_locked_state (priv->udpsrc_v4[i], TRUE);
+      /* add udpsrc */
+      gst_bin_add (bin, priv->udpsrc_v4[i]);
+
+      /* and link to the funnel v4 */
+      selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
+      pad = gst_element_get_static_pad (priv->udpsrc_v4[i], "src");
+      gst_pad_link (pad, selpad);
+      gst_object_unref (pad);
+      gst_object_unref (selpad);
+    }
 
-    /* and link to the funnel v6 */
-    selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
-    pad = gst_element_get_static_pad (priv->udpsrc_v6[i], "src");
-    gst_pad_link (pad, selpad);
-    gst_object_unref (pad);
-    gst_object_unref (selpad);
+    if (priv->udpsrc_v6[i]) {
+      gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_PLAYING);
+      gst_element_set_locked_state (priv->udpsrc_v6[i], TRUE);
+      gst_bin_add (bin, priv->udpsrc_v6[i]);
+
+      /* and link to the funnel v6 */
+      selpad = gst_element_get_request_pad (priv->funnel[i], "sink_%u");
+      pad = gst_element_get_static_pad (priv->udpsrc_v6[i], "src");
+      gst_pad_link (pad, selpad);
+      gst_object_unref (pad);
+      gst_object_unref (selpad);
+    }
 
     /* make and add appsrc */
     priv->appsrc[i] = gst_element_factory_make ("appsrc", NULL);
@@ -1366,16 +1378,19 @@ gst_rtsp_stream_leave_bin (GstRTSPStream * stream, GstBin * bin,
     gst_element_set_state (priv->tee[i], GST_STATE_NULL);
     gst_element_set_state (priv->funnel[i], GST_STATE_NULL);
     gst_element_set_state (priv->appsrc[i], GST_STATE_NULL);
-    /* and set udpsrc to NULL now before removing */
-    gst_element_set_locked_state (priv->udpsrc_v4[i], FALSE);
-    gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_NULL);
-    gst_element_set_locked_state (priv->udpsrc_v6[i], FALSE);
-    gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_NULL);
-
-    /* removing them should also nicely release the request
-     * pads when they finalize */
-    gst_bin_remove (bin, priv->udpsrc_v4[i]);
-    gst_bin_remove (bin, priv->udpsrc_v6[i]);
+    if (priv->udpsrc_v4[i]) {
+      /* and set udpsrc to NULL now before removing */
+      gst_element_set_locked_state (priv->udpsrc_v4[i], FALSE);
+      gst_element_set_state (priv->udpsrc_v4[i], GST_STATE_NULL);
+      /* removing them should also nicely release the request
+       * pads when they finalize */
+      gst_bin_remove (bin, priv->udpsrc_v4[i]);
+    }
+    if (priv->udpsrc_v6[i]) {
+      gst_element_set_locked_state (priv->udpsrc_v6[i], FALSE);
+      gst_element_set_state (priv->udpsrc_v6[i], GST_STATE_NULL);
+      gst_bin_remove (bin, priv->udpsrc_v6[i]);
+    }
     gst_bin_remove (bin, priv->udpsink[i]);
     gst_bin_remove (bin, priv->appsrc[i]);
     gst_bin_remove (bin, priv->appsink[i]);