From 64394c110b026796283c44451a74aedf74188f06 Mon Sep 17 00:00:00 2001 From: Philippe De Muyter 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