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