gst/rtsp/: Fix for new API.
authorPeter Kjellerstedt <pkj@axis.com>
Thu, 24 May 2007 08:10:42 +0000 (08:10 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 24 May 2007 08:10:42 +0000 (08:10 +0000)
Original commit message from CVS:
Patch by: Peter Kjellerstedt  <pkj at axis com>
* gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_setup_auth),
(gst_rtspsrc_try_send), (gst_rtspsrc_parse_methods),
(gst_rtspsrc_setup_streams), (gst_rtspsrc_open),
(gst_rtspsrc_play):
(rtsp_connection_send), (rtsp_connection_receive):
* gst/rtsp/rtspextwms.c: (rtsp_ext_wms_after_send):
Fix for new API.
* gst/rtsp/rtspconnection.c: (add_auth_header),
Only add authorisation and session headers when sending messages.
* gst/rtsp/rtspmessage.c: (key_value_foreach), (rtsp_message_init),
(rtsp_message_init_request), (rtsp_message_init_response),
(rtsp_message_unset), (rtsp_message_add_header),
(rtsp_message_remove_header), (rtsp_message_get_header),
(rtsp_message_append_headers), (dump_key_value),
(rtsp_message_dump):
* gst/rtsp/rtspmessage.h:
Add support for multiple headers of the same type by storing the parsed
headers in a GArray instaed of a hashtable.

ChangeLog
gst/rtsp/gstrtspsrc.c
gst/rtsp/rtspconnection.c
gst/rtsp/rtspextwms.c
gst/rtsp/rtspmessage.c
gst/rtsp/rtspmessage.h

index 1707265..29f16e5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2007-05-24  Wim Taymans  <wim@fluendo.com>
+
+       Patch by: Peter Kjellerstedt  <pkj at axis com>
+
+       * gst/rtsp/gstrtspsrc.c: (gst_rtspsrc_setup_auth),
+       (gst_rtspsrc_try_send), (gst_rtspsrc_parse_methods),
+       (gst_rtspsrc_setup_streams), (gst_rtspsrc_open),
+       (gst_rtspsrc_play):
+       (rtsp_connection_send), (rtsp_connection_receive):
+       * gst/rtsp/rtspextwms.c: (rtsp_ext_wms_after_send):
+       Fix for new API.
+
+       * gst/rtsp/rtspconnection.c: (add_auth_header),
+       Only add authorisation and session headers when sending messages.
+
+       * gst/rtsp/rtspmessage.c: (key_value_foreach), (rtsp_message_init),
+       (rtsp_message_init_request), (rtsp_message_init_response),
+       (rtsp_message_unset), (rtsp_message_add_header),
+       (rtsp_message_remove_header), (rtsp_message_get_header),
+       (rtsp_message_append_headers), (dump_key_value),
+       (rtsp_message_dump):
+       * gst/rtsp/rtspmessage.h:
+       Add support for multiple headers of the same type by storing the parsed
+       headers in a GArray instaed of a hashtable.
+
 2007-05-21  Wim Taymans  <wim@fluendo.com>
 
        * gst/udp/gstudpsrc.c: (gst_udpsrc_class_init),
index 18c0421..5b6a35a 100644 (file)
@@ -2640,7 +2640,7 @@ gst_rtspsrc_setup_auth (GstRTSPSrc * src, RTSPMessage * response)
   gchar *hdr;
 
   /* Identify the available auth methods and see if any are supported */
-  if (rtsp_message_get_header (response, RTSP_HDR_WWW_AUTHENTICATE, &hdr) ==
+  if (rtsp_message_get_header (response, RTSP_HDR_WWW_AUTHENTICATE, &hdr, 0) ==
       RTSP_OK) {
     gst_rtspsrc_parse_auth_hdr (hdr, &avail_methods);
   }
@@ -2772,7 +2772,7 @@ next:
     return RTSP_OK;
 
   /* store new content base if any */
-  rtsp_message_get_header (response, RTSP_HDR_CONTENT_BASE, &content_base);
+  rtsp_message_get_header (response, RTSP_HDR_CONTENT_BASE, &content_base, 0);
   g_free (src->content_base);
   src->content_base = g_strdup (content_base);
 
@@ -2905,45 +2905,56 @@ error_response:
 static gboolean
 gst_rtspsrc_parse_methods (GstRTSPSrc * src, RTSPMessage * response)
 {
+  RTSPHeaderField field;
   gchar *respoptions = NULL;
   gchar **options;
+  gint indx = 0;
   gint i;
 
   /* clear supported methods */
   src->methods = 0;
 
-  /* Try Allow Header first */
-  rtsp_message_get_header (response, RTSP_HDR_ALLOW, &respoptions);
-  if (!respoptions)
-    /* Then maybe Public Header... */
-    rtsp_message_get_header (response, RTSP_HDR_PUBLIC, &respoptions);
-  if (!respoptions) {
-    /* this field is not required, assume the server supports
-     * DESCRIBE, SETUP and PLAY */
-    GST_DEBUG_OBJECT (src, "could not get OPTIONS");
-    src->methods = RTSP_DESCRIBE | RTSP_SETUP | RTSP_PLAY | RTSP_PAUSE;
-    goto done;
-  }
+  /* try the Allow header first */
+  field = RTSP_HDR_ALLOW;
+  while (TRUE) {
+    rtsp_message_get_header (response, field, &respoptions, indx);
+    if (indx == 0 && !respoptions) {
+      /* if no Allow header was found then try the Public header... */
+      field = RTSP_HDR_PUBLIC;
+      rtsp_message_get_header (response, field, &respoptions, indx);
+    }
+    if (!respoptions)
+      break;
 
-  /* If we get here, the server gave a list of supported methods, parse
-   * them here. The string is like: 
-   *
-   * OPTIONS, DESCRIBE, ANNOUNCE, PLAY, SETUP, ...
-   */
-  options = g_strsplit (respoptions, ",", 0);
+    /* If we get here, the server gave a list of supported methods, parse
+     * them here. The string is like:
+     *
+     * OPTIONS, DESCRIBE, ANNOUNCE, PLAY, SETUP, ...
+     */
+    options = g_strsplit (respoptions, ",", 0);
 
-  for (i = 0; options[i]; i++) {
-    gchar *stripped;
-    gint method;
+    for (i = 0; options[i]; i++) {
+      gchar *stripped;
+      gint method;
 
-    stripped = g_strstrip (options[i]);
-    method = rtsp_find_method (stripped);
+      stripped = g_strstrip (options[i]);
+      method = rtsp_find_method (stripped);
 
-    /* keep bitfield of supported methods */
-    if (method != RTSP_INVALID)
-      src->methods |= method;
+      /* keep bitfield of supported methods */
+      if (method != RTSP_INVALID)
+        src->methods |= method;
+    }
+    g_strfreev (options);
+
+    indx++;
+  }
+
+  if (src->methods == 0) {
+    /* neither Allow nor Public are required, assume the server supports
+     * DESCRIBE, SETUP, PLAY and PAUSE */
+    GST_DEBUG_OBJECT (src, "could not get OPTIONS");
+    src->methods = RTSP_DESCRIBE | RTSP_SETUP | RTSP_PLAY | RTSP_PAUSE;
   }
-  g_strfreev (options);
 
   /* we need describe and setup */
   if (!(src->methods & RTSP_DESCRIBE))
@@ -2951,7 +2962,6 @@ gst_rtspsrc_parse_methods (GstRTSPSrc * src, RTSPMessage * response)
   if (!(src->methods & RTSP_SETUP))
     goto no_setup;
 
-done:
   return TRUE;
 
   /* ERRORS */
@@ -3219,7 +3229,7 @@ gst_rtspsrc_setup_streams (GstRTSPSrc * src)
       gchar *resptrans = NULL;
       RTSPTransport transport = { 0 };
 
-      rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans);
+      rtsp_message_get_header (&response, RTSP_HDR_TRANSPORT, &resptrans, 0);
       if (!resptrans)
         goto no_transport;
 
@@ -3425,7 +3435,7 @@ gst_rtspsrc_open (GstRTSPSrc * src)
     goto send_error;
 
   /* check if reply is SDP */
-  rtsp_message_get_header (&response, RTSP_HDR_CONTENT_TYPE, &respcont);
+  rtsp_message_get_header (&response, RTSP_HDR_CONTENT_TYPE, &respcont, 0);
   /* could not be set but since the request returned OK, we assume it
    * was SDP, else check it. */
   if (respcont) {
@@ -3756,14 +3766,14 @@ gst_rtspsrc_play (GstRTSPSrc * src)
 
   /* parse RTP npt field. This is the current position in the stream (Normal
    * Play Time) and should be put in the NEWSEGMENT position field. */
-  if (rtsp_message_get_header (&response, RTSP_HDR_RANGE, &range) == RTSP_OK)
+  if (rtsp_message_get_header (&response, RTSP_HDR_RANGE, &range, 0) == RTSP_OK)
     gst_rtspsrc_parse_range (src, range);
 
   /* parse the RTP-Info header field (if ANY) to get the base seqnum and timestamp
    * for the RTP packets. If this is not present, we assume all starts from 0... 
    * This is info for the RTP session manager that we pass to it in caps. */
   if (rtsp_message_get_header (&response, RTSP_HDR_RTP_INFO,
-          &rtpinfo) == RTSP_OK)
+          &rtpinfo, 0) == RTSP_OK)
     gst_rtspsrc_parse_rtpinfo (src, rtpinfo);
 
   rtsp_message_unset (&response);
index 086dddc..e20de23 100644 (file)
@@ -273,15 +273,7 @@ timeout:
 }
 
 static void
-append_header (gint key, gchar * value, GString * str)
-{
-  const gchar *keystr = rtsp_header_as_text (key);
-
-  g_string_append_printf (str, "%s: %s\r\n", keystr, value);
-}
-
-static void
-append_auth_header (RTSPConnection * conn, RTSPMessage * message, GString * str)
+add_auth_header (RTSPConnection * conn, RTSPMessage * message)
 {
   switch (conn->auth_method) {
     case RTSP_AUTH_BASIC:{
@@ -290,7 +282,7 @@ append_auth_header (RTSPConnection * conn, RTSPMessage * message, GString * str)
       gchar *user_pass64 = util_base64_encode (user_pass, strlen (user_pass));
       gchar *auth_string = g_strdup_printf ("Basic %s", user_pass64);
 
-      append_header (RTSP_HDR_AUTHORIZATION, auth_string, str);
+      rtsp_message_add_header (message, RTSP_HDR_AUTHORIZATION, auth_string);
 
       g_free (user_pass);
       g_free (user_pass64);
@@ -427,6 +419,12 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
           "CSeq: %d\r\n",
           rtsp_method_as_text (message->type_data.request.method),
           message->type_data.request.uri, conn->cseq++);
+      /* add session id if we have one */
+      if (conn->session_id[0] != '\0') {
+        rtsp_message_add_header (message, RTSP_HDR_SESSION, conn->session_id);
+      }
+      /* add any authentication headers */
+      add_auth_header (conn, message);
       break;
     case RTSP_MESSAGE_RESPONSE:
       /* create response string */
@@ -455,39 +453,28 @@ rtsp_connection_send (RTSPConnection * conn, RTSPMessage * message,
       break;
   }
 
-  /* append specific headers and body */
-  switch (message->type) {
-    case RTSP_MESSAGE_REQUEST:
-    case RTSP_MESSAGE_RESPONSE:
-      /* append session id if we have one */
-      if (conn->session_id[0] != '\0') {
-        append_header (RTSP_HDR_SESSION, conn->session_id, str);
-      }
-      /* append headers */
-      g_hash_table_foreach (message->hdr_fields, (GHFunc) append_header, str);
-
-      /* Append any authentication headers */
-      append_auth_header (conn, message, str);
-
-      /* append Content-Length and body if needed */
-      if (message->body != NULL && message->body_size > 0) {
-        gchar *len;
-
-        len = g_strdup_printf ("%d", message->body_size);
-        append_header (RTSP_HDR_CONTENT_LENGTH, len, str);
-        g_free (len);
-        /* header ends here */
-        g_string_append (str, "\r\n");
-        str =
-            g_string_append_len (str, (gchar *) message->body,
-            message->body_size);
-      } else {
-        /* just end headers */
-        g_string_append (str, "\r\n");
-      }
-      break;
-    default:
-      break;
+  /* append headers and body */
+  if (message->type != RTSP_MESSAGE_DATA) {
+    /* append headers */
+    rtsp_message_append_headers (message, str);
+
+    /* append Content-Length and body if needed */
+    if (message->body != NULL && message->body_size > 0) {
+      gchar *len;
+
+      len = g_strdup_printf ("%d", message->body_size);
+      g_string_append_printf (str, "%s: %s\r\n",
+          rtsp_header_as_text (RTSP_HDR_CONTENT_LENGTH), len);
+      g_free (len);
+      /* header ends here */
+      g_string_append (str, "\r\n");
+      str =
+          g_string_append_len (str, (gchar *) message->body,
+          message->body_size);
+    } else {
+      /* just end headers */
+      g_string_append (str, "\r\n");
+    }
   }
 
   /* write request */
@@ -914,7 +901,7 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg,
   if (need_body) {
     /* see if there is a Content-Length header */
     if (rtsp_message_get_header (msg, RTSP_HDR_CONTENT_LENGTH,
-            &hdrval) == RTSP_OK) {
+            &hdrval, 0) == RTSP_OK) {
       /* there is, read the body */
       content_length = atol (hdrval);
       RTSP_CHECK (read_body (conn, content_length, msg, timeout), read_error);
@@ -925,7 +912,7 @@ rtsp_connection_receive (RTSPConnection * conn, RTSPMessage * msg,
       gchar *session_id;
 
       if (rtsp_message_get_header (msg, RTSP_HDR_SESSION,
-              &session_id) == RTSP_OK) {
+              &session_id, 0) == RTSP_OK) {
         gint sesslen, maxlen, i;
 
         /* default session timeout */
index b79a458..e336176 100644 (file)
@@ -86,7 +86,7 @@ rtsp_ext_wms_after_send (RTSPExtensionCtx * ctx, RTSPMessage * req,
     {
       gchar *server = NULL;
 
-      rtsp_message_get_header (resp, RTSP_HDR_SERVER, &server);
+      rtsp_message_get_header (resp, RTSP_HDR_SERVER, &server, 0);
       if (server && g_str_has_prefix (server, SERVER_PREFIX))
         rext->active = TRUE;
       else
index ed622c3..2cb12bf 100644 (file)
 
 #include "rtspmessage.h"
 
+typedef struct _RTSPKeyValue
+{
+  RTSPHeaderField field;
+  gchar *value;
+} RTSPKeyValue;
+
+static void
+key_value_foreach (GArray * array, GFunc func, gpointer user_data)
+{
+  guint i;
+
+  g_return_if_fail (array != NULL);
+
+  for (i = 0; i < array->len; i++) {
+    (*func) (&g_array_index (array, RTSPKeyValue, i), user_data);
+  }
+}
+
 RTSPResult
 rtsp_message_new (RTSPMessage ** msg)
 {
@@ -67,8 +85,7 @@ rtsp_message_init (RTSPMessage * msg)
   rtsp_message_unset (msg);
 
   msg->type = RTSP_MESSAGE_INVALID;
-  msg->hdr_fields =
-      g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+  msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue));
 
   return RTSP_OK;
 }
@@ -101,8 +118,7 @@ rtsp_message_init_request (RTSPMessage * msg, RTSPMethod method,
   msg->type = RTSP_MESSAGE_REQUEST;
   msg->type_data.request.method = method;
   msg->type_data.request.uri = g_strdup (uri);
-  msg->hdr_fields =
-      g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+  msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue));
 
   return RTSP_OK;
 }
@@ -136,19 +152,19 @@ rtsp_message_init_response (RTSPMessage * msg, RTSPStatusCode code,
   msg->type = RTSP_MESSAGE_RESPONSE;
   msg->type_data.response.code = code;
   msg->type_data.response.reason = g_strdup (reason);
-  msg->hdr_fields =
-      g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+  msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue));
 
   if (request) {
     gchar *header;
 
     /* copy CSEQ */
-    if (rtsp_message_get_header (request, RTSP_HDR_CSEQ, &header) == RTSP_OK) {
+    if (rtsp_message_get_header (request, RTSP_HDR_CSEQ, &header, 0) == RTSP_OK) {
       rtsp_message_add_header (msg, RTSP_HDR_CSEQ, header);
     }
 
     /* copy session id */
-    if (rtsp_message_get_header (request, RTSP_HDR_SESSION, &header) == RTSP_OK) {
+    if (rtsp_message_get_header (request, RTSP_HDR_SESSION, &header,
+            0) == RTSP_OK) {
       char *pos;
 
       header = g_strdup (header);
@@ -201,7 +217,7 @@ rtsp_message_unset (RTSPMessage * msg)
   }
 
   if (msg->hdr_fields != NULL)
-    g_hash_table_destroy (msg->hdr_fields);
+    g_array_free (msg->hdr_fields, TRUE);
 
   g_free (msg->body);
 
@@ -228,44 +244,80 @@ RTSPResult
 rtsp_message_add_header (RTSPMessage * msg, RTSPHeaderField field,
     const gchar * value)
 {
+  RTSPKeyValue key_value;
+
   g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
   g_return_val_if_fail (value != NULL, RTSP_EINVAL);
 
-  g_hash_table_insert (msg->hdr_fields, GINT_TO_POINTER (field),
-      g_strdup (value));
+  key_value.field = field;
+  key_value.value = g_strdup (value);
+
+  g_array_append_val (msg->hdr_fields, key_value);
 
   return RTSP_OK;
 }
 
 RTSPResult
-rtsp_message_remove_header (RTSPMessage * msg, RTSPHeaderField field)
+rtsp_message_remove_header (RTSPMessage * msg, RTSPHeaderField field, gint indx)
 {
+  RTSPResult res = RTSP_ENOTIMPL;
+  guint i = 0;
+  gint cnt = 0;
+
   g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
 
-  g_hash_table_remove (msg->hdr_fields, GINT_TO_POINTER (field));
+  while (i < msg->hdr_fields->len) {
+    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
 
-  return RTSP_ENOTIMPL;
+    if (key_value.field == field && (indx == -1 || cnt++ == indx)) {
+      g_array_remove_index (msg->hdr_fields, i);
+      res = RTSP_OK;
+      if (indx != -1)
+        break;
+    } else {
+      i++;
+    }
+  }
+
+  return res;
 }
 
 RTSPResult
 rtsp_message_get_header (const RTSPMessage * msg, RTSPHeaderField field,
-    gchar ** value)
+    gchar ** value, gint indx)
 {
-  gchar *val;
+  guint i;
+  gint cnt = 0;
 
   g_return_val_if_fail (msg != NULL, RTSP_EINVAL);
 
-  if (msg->type == RTSP_MESSAGE_INVALID || msg->type == RTSP_MESSAGE_DATA)
-    return RTSP_ENOTIMPL;
+  for (i = 0; i < msg->hdr_fields->len; i++) {
+    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
 
-  val = g_hash_table_lookup (msg->hdr_fields, GINT_TO_POINTER (field));
-  if (val == NULL)
-    return RTSP_ENOTIMPL;
+    if (key_value.field == field && cnt++ == indx) {
+      if (value)
+        *value = key_value.value;
+      return RTSP_OK;
+    }
+  }
 
-  if (value)
-    *value = val;
+  return RTSP_ENOTIMPL;
+}
 
-  return RTSP_OK;
+void
+rtsp_message_append_headers (const RTSPMessage * msg, GString * str)
+{
+  guint i;
+
+  g_return_if_fail (msg != NULL);
+  g_return_if_fail (str != NULL);
+
+  for (i = 0; i < msg->hdr_fields->len; i++) {
+    RTSPKeyValue key_value = g_array_index (msg->hdr_fields, RTSPKeyValue, i);
+    const gchar *keystr = rtsp_header_as_text (key_value.field);
+
+    g_string_append_printf (str, "%s: %s\r\n", keystr, key_value.value);
+  }
 }
 
 RTSPResult
@@ -352,12 +404,12 @@ dump_mem (guint8 * mem, guint size)
 }
 
 static void
-dump_key_value (gpointer key, gpointer value, gpointer data)
+dump_key_value (gpointer data, gpointer user_data)
 {
-  RTSPHeaderField field = GPOINTER_TO_INT (key);
+  RTSPKeyValue *key_value = (RTSPKeyValue *) data;
 
-  g_print ("   key: '%s', value: '%s'\n", rtsp_header_as_text (field),
-      (gchar *) value);
+  g_print ("   key: '%s', value: '%s'\n",
+      rtsp_header_as_text (key_value->field), key_value->value);
 }
 
 RTSPResult
@@ -376,7 +428,7 @@ rtsp_message_dump (RTSPMessage * msg)
           rtsp_method_as_text (msg->type_data.request.method));
       g_print ("   uri:    '%s'\n", msg->type_data.request.uri);
       g_print (" headers:\n");
-      g_hash_table_foreach (msg->hdr_fields, dump_key_value, NULL);
+      key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
       g_print (" body:\n");
       rtsp_message_get_body (msg, &data, &size);
       dump_mem (data, size);
@@ -387,7 +439,7 @@ rtsp_message_dump (RTSPMessage * msg)
       g_print ("   code:   '%d'\n", msg->type_data.response.code);
       g_print ("   reason: '%s'\n", msg->type_data.response.reason);
       g_print (" headers:\n");
-      g_hash_table_foreach (msg->hdr_fields, dump_key_value, NULL);
+      key_value_foreach (msg->hdr_fields, dump_key_value, NULL);
       rtsp_message_get_body (msg, &data, &size);
       g_print (" body: length %d\n", size);
       dump_mem (data, size);
index 089676c..2c099f1 100644 (file)
@@ -75,7 +75,7 @@ typedef struct _RTSPMessage
     } data;
   } type_data;
 
-  GHashTable    *hdr_fields;
+  GArray        *hdr_fields;
 
   guint8        *body;
   guint          body_size;
@@ -112,10 +112,15 @@ RTSPResult      rtsp_message_add_header         (RTSPMessage *msg,
                                                  RTSPHeaderField field,
                                                  const gchar *value);
 RTSPResult      rtsp_message_remove_header      (RTSPMessage *msg,
-                                                 RTSPHeaderField field);
+                                                 RTSPHeaderField field,
+                                                 gint indx);
 RTSPResult      rtsp_message_get_header         (const RTSPMessage *msg,
                                                  RTSPHeaderField field,
-                                                 gchar **value);
+                                                 gchar **value,
+                                                 gint indx);
+
+void            rtsp_message_append_headers     (const RTSPMessage *msg,
+                                                 GString *str);
 
 RTSPResult      rtsp_message_set_body           (RTSPMessage *msg,
                                                  const guint8 *data,