how to use an already open and bound socket for gst_rstp_server

Philippe De Muyter phdm at macq.eu
Mon May 28 13:18:31 UTC 2018


On Mon, May 28, 2018 at 09:14:46AM +0200, Philippe De Muyter wrote:
> 
> Would it be OK to add a 'gst_rtsp_server_set_fd' function and modify the
> behaviour of 'gst_rtsp_server_create_socket' to use 'g_socket_new_from_fd'
> instead of 'g_socket_new' + 'g_socket_bind' if 'gst_rtsp_server_set_fd'
> has been called before ?
> 
> Philippe

Here is the implementation :

>From 64394c110b026796283c44451a74aedf74188f06 Mon Sep 17 00:00:00 2001
From: Philippe De Muyter <phdm at macqel.be>
Date: Mon, 28 May 2018 12:45:47 +0200
Subject: [PATCH] Add 'gst_rtsp_server_set_fd' function.

---
 gst/rtsp-server/rtsp-server.c | 177 +++++++++++++++++++++++++-----------------
 gst/rtsp-server/rtsp-server.h |   2 +
 2 files changed, 109 insertions(+), 70 deletions(-)

diff --git a/gst/rtsp-server/rtsp-server.c b/gst/rtsp-server/rtsp-server.c
index 686ba03..54755a2 100644
--- a/gst/rtsp-server/rtsp-server.c
+++ b/gst/rtsp-server/rtsp-server.c
@@ -73,6 +73,7 @@ struct _GstRTSPServerPrivate
   gchar *address;
   gchar *service;
   gint backlog;
+  gint fd;
 
   GSocket *socket;
 
@@ -244,6 +245,7 @@ gst_rtsp_server_init (GstRTSPServer * server)
   g_mutex_init (&priv->lock);
   priv->address = g_strdup (DEFAULT_ADDRESS);
   priv->service = g_strdup (DEFAULT_SERVICE);
+  priv->fd = -1;
   priv->socket = NULL;
   priv->backlog = DEFAULT_BACKLOG;
   priv->session_pool = gst_rtsp_session_pool_new ();
@@ -381,6 +383,34 @@ out:
 }
 
 /**
+ * gst_rtsp_server_set_fd:
+ * @server: a #GstRTSPServer
+ * @fd: the fd
+ *
+ * Configure @server to accept connections on the given fd.
+ * @fd should be the file descriptor of a already bound socket
+ *
+ * If this function is not used, gst_rtsp_server_create_socket will
+ * create and bind the socket itself.
+ *
+ * This function must be called before the server is bound.
+ */
+void
+gst_rtsp_server_set_fd (GstRTSPServer * server, gint fd)
+{
+  GstRTSPServerPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_SERVER (server));
+  g_return_if_fail (fd >= 0);
+
+  priv = server->priv;
+
+  GST_RTSP_SERVER_LOCK (server);
+  priv->fd = fd;
+  GST_RTSP_SERVER_UNLOCK (server);
+}
+
+/**
  * gst_rtsp_server_set_service:
  * @server: a #GstRTSPServer
  * @service: the service
@@ -803,84 +833,91 @@ gst_rtsp_server_create_socket (GstRTSPServer * server,
   priv = server->priv;
 
   GST_RTSP_SERVER_LOCK (server);
-  GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address,
-      priv->service);
-
-  /* resolve the server IP address */
-  port = atoi (priv->service);
-  if (port != 0 || !strcmp (priv->service, "0"))
-    conn = g_network_address_new (priv->address, port);
-  else
-    conn = g_network_service_new (priv->service, "tcp", priv->address);
-
-  enumerator = g_socket_connectable_enumerate (conn);
-  g_object_unref (conn);
-
-  /* create server socket, we loop through all the addresses until we manage to
-   * create a socket and bind. */
-  while (TRUE) {
-    GSocketAddress *sockaddr;
-
-    sockaddr =
-        g_socket_address_enumerator_next (enumerator, cancellable, error);
-    if (!sockaddr) {
-      if (!*error)
-        GST_DEBUG_OBJECT (server, "no more addresses %s",
-            *error ? (*error)->message : "");
-      else
-        GST_DEBUG_OBJECT (server, "failed to retrieve next address %s",
-            (*error)->message);
-      break;
-    }
-
-    /* only keep the first error */
-    socket = g_socket_new (g_socket_address_get_family (sockaddr),
-        G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP,
-        sock_error ? NULL : &sock_error);
-
-    if (socket == NULL) {
-      GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next",
-          sock_error->message);
-      g_object_unref (sockaddr);
-      continue;
-    }
+  if (priv->fd >= 0) {
+    GST_DEBUG_OBJECT (server, "using user-provided fd %d", priv->fd);
+    socket = g_socket_new_from_fd (priv->fd, error);
+  } else {
+    GST_DEBUG_OBJECT (server, "getting address info of %s/%s", priv->address,
+        priv->service);
+
+    /* resolve the server IP address */
+    port = atoi (priv->service);
+    if (port != 0 || !strcmp (priv->service, "0"))
+      conn = g_network_address_new (priv->address, port);
+    else
+      conn = g_network_service_new (priv->service, "tcp", priv->address);
+
+    enumerator = g_socket_connectable_enumerate (conn);
+    g_object_unref (conn);
+
+    /* create server socket, we loop through all the addresses until we manage to
+     * create a socket and bind. */
+    while (TRUE) {
+      GSocketAddress *sockaddr;
+
+      sockaddr =
+          g_socket_address_enumerator_next (enumerator, cancellable, error);
+      if (!sockaddr) {
+        if (!*error)
+          GST_DEBUG_OBJECT (server, "no more addresses %s",
+              *error ? (*error)->message : "");
+        else
+          GST_DEBUG_OBJECT (server, "failed to retrieve next address %s",
+              (*error)->message);
+        break;
+      }
 
-    if (g_socket_bind (socket, sockaddr, TRUE, bind_error ? NULL : &bind_error)) {
-      /* ask what port the socket has been bound to */
-      if (port == 0 || !strcmp (priv->service, "0")) {
-        GError *addr_error = NULL;
+      /* only keep the first error */
+      socket = g_socket_new (g_socket_address_get_family (sockaddr),
+          G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP,
+          sock_error ? NULL : &sock_error);
 
+      if (socket == NULL) {
+        GST_DEBUG_OBJECT (server, "failed to make socket (%s), try next",
+            sock_error->message);
         g_object_unref (sockaddr);
-        sockaddr = g_socket_get_local_address (socket, &addr_error);
-
-        if (addr_error != NULL) {
-          GST_DEBUG_OBJECT (server,
-              "failed to get the local address of a bound socket %s",
-              addr_error->message);
-          g_clear_error (&addr_error);
-          break;
-        }
-        port =
-            g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr));
-
-        if (port != 0) {
-          g_free (priv->service);
-          priv->service = g_strdup_printf ("%d", port);
-        } else {
-          GST_DEBUG_OBJECT (server, "failed to get the port of a bound socket");
+        continue;
+      }
+
+      if (g_socket_bind (socket, sockaddr, TRUE,
+              bind_error ? NULL : &bind_error)) {
+        /* ask what port the socket has been bound to */
+        if (port == 0 || !strcmp (priv->service, "0")) {
+          GError *addr_error = NULL;
+
+          g_object_unref (sockaddr);
+          sockaddr = g_socket_get_local_address (socket, &addr_error);
+
+          if (addr_error != NULL) {
+            GST_DEBUG_OBJECT (server,
+                "failed to get the local address of a bound socket %s",
+                addr_error->message);
+            g_clear_error (&addr_error);
+            break;
+          }
+          port =
+              g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (sockaddr));
+
+          if (port != 0) {
+            g_free (priv->service);
+            priv->service = g_strdup_printf ("%d", port);
+          } else {
+            GST_DEBUG_OBJECT (server,
+                "failed to get the port of a bound socket");
+          }
         }
+        g_object_unref (sockaddr);
+        break;
       }
+
+      GST_DEBUG_OBJECT (server, "failed to bind socket (%s), try next",
+          bind_error->message);
       g_object_unref (sockaddr);
-      break;
+      g_object_unref (socket);
+      socket = NULL;
     }
-
-    GST_DEBUG_OBJECT (server, "failed to bind socket (%s), try next",
-        bind_error->message);
-    g_object_unref (sockaddr);
-    g_object_unref (socket);
-    socket = NULL;
+    g_object_unref (enumerator);
   }
-  g_object_unref (enumerator);
 
   if (socket == NULL)
     goto no_socket;
diff --git a/gst/rtsp-server/rtsp-server.h b/gst/rtsp-server/rtsp-server.h
index 9a6f9d4..ab89e51 100644
--- a/gst/rtsp-server/rtsp-server.h
+++ b/gst/rtsp-server/rtsp-server.h
@@ -136,6 +136,8 @@ GSource *             gst_rtsp_server_create_source        (GstRTSPServer *serve
 guint                 gst_rtsp_server_attach               (GstRTSPServer *server,
                                                             GMainContext *context);
 
+void                  gst_rtsp_server_set_fd               (GstRTSPServer *server, gint fd);
+
 /**
  * GstRTSPServerClientFilterFunc:
  * @server: a #GstRTSPServer object
-- 
1.8.4.5



More information about the gstreamer-devel mailing list