rtsp-server: use an existing socket to establish HTTP tunnel

Make it possible to transfer a socket from an HTTP server to be used as
an RTSP over HTTP tunnel.
This commit is contained in:
Ognyan Tonchev 2012-07-03 18:06:00 +02:00 committed by Wim Taymans
parent 86e53af34a
commit ed66f974dd
4 changed files with 145 additions and 31 deletions

View 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;
}
}

View 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__ */

View file

@ -779,6 +779,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

View 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);