From 65c7bd7a2ced2c3c82f6bb4663217c9afdb9faad Mon Sep 17 00:00:00 2001 From: Evan Callaway Date: Mon, 14 Dec 2015 09:10:16 -0500 Subject: [PATCH] rtspconnection: Support authentication during tunneling setup gst_rtsp_connection_connect_with_response accepts a response pointer which it fills with the response from setup_tunneling if the connection is configured to be tunneled. The motivation for this is to allow the caller to inspect the response header to determine if additional authentication is required so that the connection can be retried with the appropriate authentication headers. The function prototype of gst_rtsp_connection_connect has been preserved for compatability with existing code and wraps gst_rtsp_connection_connect_with_response. https://bugzilla.gnome.org/show_bug.cgi?id=749596 --- docs/libs/gst-plugins-base-libs-sections.txt | 1 + gst-libs/gst/rtsp/gstrtspconnection.c | 66 +++++++++++++++++++++------- gst-libs/gst/rtsp/gstrtspconnection.h | 10 +++-- win32/common/libgstrtsp.def | 1 + 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index fd1e381..fd3afdd 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -1491,6 +1491,7 @@ gst_rtsp_connection_create gst_rtsp_connection_create_from_socket gst_rtsp_connection_accept gst_rtsp_connection_connect +gst_rtsp_connection_connect_with_response gst_rtsp_connection_close gst_rtsp_connection_free diff --git a/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-libs/gst/rtsp/gstrtspconnection.c index 786dbcc..f48a4bd 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.c +++ b/gst-libs/gst/rtsp/gstrtspconnection.c @@ -196,6 +196,10 @@ typedef struct glong body_len; } GstRTSPBuilder; +/* function prototypes */ +static void add_auth_header (GstRTSPConnection * conn, + GstRTSPMessage * message); + static void build_reset (GstRTSPBuilder * builder) { @@ -681,14 +685,14 @@ gst_rtsp_connection_get_tls_interaction (GstRTSPConnection * conn) } static GstRTSPResult -setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) +setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri, + GstRTSPMessage * response) { gint i; GstRTSPResult res; gchar *value; guint16 url_port; GstRTSPMessage *msg; - GstRTSPMessage response; gboolean old_http; GstRTSPUrl *url; GError *error = NULL; @@ -696,9 +700,6 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) GSocket *socket; gchar *luri = NULL; - memset (&response, 0, sizeof (response)); - gst_rtsp_message_init (&response); - url = conn->url; /* create a random sessionid */ @@ -717,6 +718,7 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) "application/x-rtsp-tunnelled"); gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CACHE_CONTROL, "no-cache"); gst_rtsp_message_add_header (msg, GST_RTSP_HDR_PRAGMA, "no-cache"); + add_auth_header (conn, msg); /* we need to temporarily set conn->tunneled to FALSE to prevent the HTTP * request from being base64 encoded */ @@ -731,15 +733,15 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) * failure otherwise */ old_http = conn->manual_http; conn->manual_http = TRUE; - GST_RTSP_CHECK (gst_rtsp_connection_receive (conn, &response, timeout), + GST_RTSP_CHECK (gst_rtsp_connection_receive (conn, response, timeout), read_failed); conn->manual_http = old_http; - if (response.type != GST_RTSP_MESSAGE_HTTP_RESPONSE || - response.type_data.response.code != GST_RTSP_STS_OK) + if (response->type != GST_RTSP_MESSAGE_HTTP_RESPONSE || + response->type_data.response.code != GST_RTSP_STS_OK) goto wrong_result; - if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_X_SERVER_IP_ADDRESS, + if (gst_rtsp_message_get_header (response, GST_RTSP_HDR_X_SERVER_IP_ADDRESS, &value, 0) == GST_RTSP_OK) { g_free (url->host); url->host = g_strdup (value); @@ -792,6 +794,7 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) gst_rtsp_message_add_header (msg, GST_RTSP_HDR_EXPIRES, "Sun, 9 Jan 1972 00:00:00 GMT"); gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONTENT_LENGTH, "32767"); + add_auth_header (conn, msg); /* we need to temporarily set conn->tunneled to FALSE to prevent the HTTP * request from being base64 encoded */ @@ -801,7 +804,6 @@ setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout, gchar * uri) conn->tunneled = TRUE; exit: - gst_rtsp_message_unset (&response); g_free (luri); return res; @@ -827,8 +829,8 @@ read_failed: } wrong_result: { - GST_ERROR ("got failure response %d %s", response.type_data.response.code, - response.type_data.response.reason); + GST_ERROR ("got failure response %d %s", + response->type_data.response.code, response->type_data.response.reason); res = GST_RTSP_ERROR; goto exit; } @@ -849,21 +851,26 @@ remote_address_failed: } /** - * gst_rtsp_connection_connect: + * gst_rtsp_connection_connect_with_response: * @conn: a #GstRTSPConnection * @timeout: a #GTimeVal timeout + * @response: a #GstRTSPMessage * * Attempt to connect to the url of @conn made with * gst_rtsp_connection_create(). If @timeout is #NULL this function can block * forever. If @timeout contains a valid timeout, this function will return - * #GST_RTSP_ETIMEOUT after the timeout expired. + * #GST_RTSP_ETIMEOUT after the timeout expired. If @conn is set to tunneled, + * @response will contain a response to the tunneling request messages. * * This function can be cancelled with gst_rtsp_connection_flush(). * * Returns: #GST_RTSP_OK when a connection could be made. + * + * Since 1.8 */ GstRTSPResult -gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) +gst_rtsp_connection_connect_with_response (GstRTSPConnection * conn, + GTimeVal * timeout, GstRTSPMessage * response) { GstRTSPResult res; GSocketConnection *connection; @@ -921,7 +928,7 @@ gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) conn->control_stream = NULL; if (conn->tunneled) { - res = setup_tunneling (conn, timeout, uri); + res = setup_tunneling (conn, timeout, uri, response); if (res != GST_RTSP_OK) goto tunneling_failed; } @@ -1077,6 +1084,33 @@ add_auth_header (GstRTSPConnection * conn, GstRTSPMessage * message) } } +/** + * gst_rtsp_connection_connect: + * @conn: a #GstRTSPConnection + * @timeout: a #GTimeVal timeout + * + * Attempt to connect to the url of @conn made with + * gst_rtsp_connection_create(). If @timeout is #NULL this function can block + * forever. If @timeout contains a valid timeout, this function will return + * #GST_RTSP_ETIMEOUT after the timeout expired. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK when a connection could be made. + */ +GstRTSPResult +gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) +{ + GstRTSPResult result; + GstRTSPMessage response; + gst_rtsp_message_init (&response); + + result = gst_rtsp_connection_connect_with_response (conn, timeout, &response); + + gst_rtsp_message_unset (&response); + return result; +} + static void gen_date_string (gchar * date_string, guint len) { diff --git a/gst-libs/gst/rtsp/gstrtspconnection.h b/gst-libs/gst/rtsp/gstrtspconnection.h index 464764b..43479ae 100644 --- a/gst-libs/gst/rtsp/gstrtspconnection.h +++ b/gst-libs/gst/rtsp/gstrtspconnection.h @@ -67,10 +67,12 @@ GstRTSPResult gst_rtsp_connection_create_from_socket (GSocket * socket, guint16 port, const gchar * initial_buffer, GstRTSPConnection ** conn); -GstRTSPResult gst_rtsp_connection_accept (GSocket *socket, GstRTSPConnection **conn, GCancellable *cancellable); -GstRTSPResult gst_rtsp_connection_connect (GstRTSPConnection *conn, GTimeVal *timeout); -GstRTSPResult gst_rtsp_connection_close (GstRTSPConnection *conn); -GstRTSPResult gst_rtsp_connection_free (GstRTSPConnection *conn); + +GstRTSPResult gst_rtsp_connection_accept (GSocket * socket, GstRTSPConnection ** conn, GCancellable * cancellable); +GstRTSPResult gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout); +GstRTSPResult gst_rtsp_connection_connect_with_response (GstRTSPConnection * conn, GTimeVal * timeout, GstRTSPMessage * response); +GstRTSPResult gst_rtsp_connection_close (GstRTSPConnection *conn); +GstRTSPResult gst_rtsp_connection_free (GstRTSPConnection *conn); /* TLS connections */ GTlsConnection * gst_rtsp_connection_get_tls (GstRTSPConnection * conn, GError ** error); diff --git a/win32/common/libgstrtsp.def b/win32/common/libgstrtsp.def index aa307cc..355a9ef 100644 --- a/win32/common/libgstrtsp.def +++ b/win32/common/libgstrtsp.def @@ -4,6 +4,7 @@ EXPORTS gst_rtsp_connection_clear_auth_params gst_rtsp_connection_close gst_rtsp_connection_connect + gst_rtsp_connection_connect_with_response gst_rtsp_connection_create gst_rtsp_connection_create_from_socket gst_rtsp_connection_do_tunnel -- 2.7.4