rtspconnection: Support authentication during tunneling setup
authorEvan Callaway <evan.callaway@ipconfigure.com>
Mon, 14 Dec 2015 14:10:16 +0000 (09:10 -0500)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 14 Dec 2015 15:00:45 +0000 (16:00 +0100)
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
gst-libs/gst/rtsp/gstrtspconnection.c
gst-libs/gst/rtsp/gstrtspconnection.h
win32/common/libgstrtsp.def

index fd1e381..fd3afdd 100644 (file)
@@ -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
 
index 786dbcc..f48a4bd 100644 (file)
@@ -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)
 {
index 464764b..43479ae 100644 (file)
@@ -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);
index aa307cc..355a9ef 100644 (file)
@@ -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