rtsp-server: use an existing socket to establish HTTP tunnel
authorOgnyan Tonchev <ognyan@axis.com>
Tue, 3 Jul 2012 16:06:00 +0000 (18:06 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Tue, 10 Jul 2012 09:38:05 +0000 (11:38 +0200)
Make it possible to transfer a socket from an HTTP server to be used as
an RTSP over HTTP tunnel.

gst/rtsp-server/rtsp-client.c
gst/rtsp-server/rtsp-client.h
gst/rtsp-server/rtsp-server.c
gst/rtsp-server/rtsp-server.h

index 57d1441..adc8924 100644 (file)
@@ -1904,26 +1904,10 @@ client_watch_notify (GstRTSPClient * client)
   g_object_unref (client);
 }
 
-/**
- * gst_rtsp_client_attach:
- * @client: a #GstRTSPClient
- * @socket: a #GSocket
- * @cancellable: a #GCancellable
- * @error: a #GError
- *
- * Accept a new connection for @client on @socket.
- *
- * This function should be called when the client properties and urls are fully
- * configured and the client is ready to start.
- *
- * Returns: %TRUE if the client could be accepted.
- */
-gboolean
-gst_rtsp_client_accept (GstRTSPClient * client, GSocket * socket,
-    GCancellable * cancellable, GError ** error)
+static gboolean
+attach_client (GstRTSPClient * client, GSocket * socket,
+    GstRTSPConnection *conn, GError ** error)
 {
-  GstRTSPConnection *conn;
-  GstRTSPResult res;
   GSocket *read_socket;
   GSocketAddress *addres;
   GSource *source;
@@ -1933,10 +1917,6 @@ gst_rtsp_client_accept (GstRTSPClient * client, GSocket * socket,
   socklen_t addrlen;
   gchar ip[INET6_ADDRSTRLEN];
 
-  /* a new client connected. */
-  GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, cancellable),
-      accept_failed);
-
   read_socket = gst_rtsp_connection_get_read_socket (conn);
   client->is_ipv6 = g_socket_get_family (socket) == G_SOCKET_FAMILY_IPV6;
 
@@ -1982,14 +1962,6 @@ gst_rtsp_client_accept (GstRTSPClient * client, GSocket * socket,
   return TRUE;
 
   /* ERRORS */
-accept_failed:
-  {
-    gchar *str = gst_rtsp_strresult (res);
-
-    GST_ERROR ("Could not accept client on server socket %p: %s", socket, str);
-    g_free (str);
-    return FALSE;
-  }
 no_address:
   {
     GST_ERROR ("could not get remote address %s", (*error)->message);
@@ -2007,3 +1979,77 @@ getnameinfo_failed:
     return FALSE;
   }
 }
+
+/**
+ * gst_rtsp_client_create_from_socket:
+ * @client: a #GstRTSPClient
+ * @socket: a #GSocket
+ * @ip: the IP address of the remote client
+ * @port: the port used by the other end
+ * @initial_buffer: any initial data that was already read from the socket
+ * @error: a #GError
+ *
+ * Take an existing network socket and use it for an RTSP connection.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gst_rtsp_client_create_from_socket (GstRTSPClient * client, GSocket * socket,
+    const gchar * ip, gint port, const gchar * initial_buffer, GError ** error)
+{
+  GstRTSPConnection *conn;
+  GstRTSPResult res;
+
+  GST_RTSP_CHECK (gst_rtsp_connection_create_from_socket (socket, ip, port,
+      initial_buffer, &conn), no_connection);
+
+  return attach_client (client, socket, conn, error);
+
+  /* ERRORS */
+no_connection:
+  {
+    gchar *str = gst_rtsp_strresult (res);
+
+    GST_ERROR ("could not create connection from socket %p: %s", socket, str);
+    g_free (str);
+    return FALSE;
+  }
+}
+
+/**
+ * gst_rtsp_client_attach:
+ * @client: a #GstRTSPClient
+ * @socket: a #GSocket
+ * @cancellable: a #GCancellable
+ * @error: a #GError
+ *
+ * Accept a new connection for @client on @socket.
+ *
+ * This function should be called when the client properties and urls are fully
+ * configured and the client is ready to start.
+ *
+ * Returns: %TRUE if the client could be accepted.
+ */
+gboolean
+gst_rtsp_client_accept (GstRTSPClient * client, GSocket * socket,
+    GCancellable * cancellable, GError ** error)
+{
+  GstRTSPConnection *conn;
+  GstRTSPResult res;
+
+  /* a new client connected. */
+  GST_RTSP_CHECK (gst_rtsp_connection_accept (socket, &conn, cancellable),
+      accept_failed);
+
+  return attach_client (client, socket, conn, error);
+
+  /* ERRORS */
+accept_failed:
+  {
+    gchar *str = gst_rtsp_strresult (res);
+
+    GST_ERROR ("Could not accept client on server socket %p: %s", socket, str);
+    g_free (str);
+    return FALSE;
+  }
+}
index bc56cc7..97bb0c2 100644 (file)
@@ -136,6 +136,13 @@ gboolean              gst_rtsp_client_accept            (GstRTSPClient *client,
                                                          GCancellable *cancellable,
                                                          GError **error);
 
+gboolean              gst_rtsp_client_create_from_socket(GstRTSPClient * client,
+                                                         GSocket *socket,
+                                                         const gchar * ip,
+                                                         gint port,
+                                                         const gchar *initial_buffer,
+                                                         GError **error);
+
 G_END_DECLS
 
 #endif /* __GST_RTSP_CLIENT_H__ */
index c4b951e..9c4594a 100644 (file)
@@ -780,6 +780,65 @@ accept_failed:
 }
 
 /**
+ * gst_rtsp_server_transfer_connection:
+ * @server: a #GstRTSPServer
+ * @socket: a network socket
+ * @ip: the IP address of the remote client
+ * @port: the port used by the other end
+ * @initial_buffer: any initial data that was already read from the socket
+ *
+ * Take an existing network socket and use it for an RTSP connection. This
+ * is used when transferring a socket from an HTTP server which should be used
+ * as an RTSP over HTTP tunnel. The @initial_buffer contains any remaining data
+ * that the HTTP server read from the socket while parsing the HTTP header.
+ *
+ * Returns: TRUE if all was ok, FALSE if an error occured.
+ */
+gboolean
+gst_rtsp_server_transfer_connection (GstRTSPServer * server, GSocket * socket,
+    const gchar * ip, gint port, const gchar *initial_buffer)
+{
+  GstRTSPClient *client = NULL;
+  GstRTSPServerClass *klass;
+  GError *error = NULL;
+
+  klass = GST_RTSP_SERVER_GET_CLASS (server);
+
+  if (klass->create_client)
+    client = klass->create_client (server);
+  if (client == NULL)
+    goto client_failed;
+
+  /* a new client connected, create a client object to handle the client. */
+  if (!gst_rtsp_client_create_from_socket (client, socket, ip, port,
+      initial_buffer, &error)) {
+    goto transfer_failed;
+  }
+
+  /* manage the client connection */
+  manage_client (server, client);
+
+  g_signal_emit (server, gst_rtsp_server_signals[SIGNAL_CLIENT_CONNECTED], 0,
+      client);
+
+  return TRUE;
+
+  /* ERRORS */
+client_failed:
+  {
+    GST_ERROR_OBJECT (server, "failed to create a client");
+    return FALSE;
+  }
+transfer_failed:
+  {
+    GST_ERROR_OBJECT (server, "failed to accept client: %s", error->message);
+    g_error_free (error);
+    gst_object_unref (client);
+    return FALSE;
+  }
+}
+
+/**
  * gst_rtsp_server_io_func:
  * @socket: a #GSocket
  * @condition: the condition on @source
index 1c5cb0c..595f2f1 100644 (file)
@@ -116,6 +116,8 @@ GstRTSPMediaMapping * gst_rtsp_server_get_media_mapping    (GstRTSPServer *serve
 void                  gst_rtsp_server_set_auth             (GstRTSPServer *server, GstRTSPAuth *auth);
 GstRTSPAuth *         gst_rtsp_server_get_auth             (GstRTSPServer *server);
 
+gboolean              gst_rtsp_server_transfer_connection  (GstRTSPServer * server, GSocket *socket, const gchar * ip, gint port, const gchar *initial_buffer);
+
 gboolean              gst_rtsp_server_io_func              (GSocket *socket, GIOCondition condition,
                                                             GstRTSPServer *server);