sdp: add methods to convert between uri and message
authorWim Taymans <wim.taymans@collabora.co.uk>
Fri, 10 Sep 2010 15:55:46 +0000 (17:55 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Fri, 10 Sep 2010 15:58:53 +0000 (17:58 +0200)
Add methods to convert between uri and sdpmessages, loosly based on
http://tools.ietf.org/html/draft-fujikawa-sdp-url-01

API: GstSDPMessage::gst_sdp_message_parse_uri
API: GstSDPMessage::gst_sdp_message_as_uri

docs/libs/gst-plugins-base-libs-sections.txt
gst-libs/gst/sdp/gstsdpmessage.c
gst-libs/gst/sdp/gstsdpmessage.h

index f9d0990..6bd3207 100644 (file)
@@ -1543,7 +1543,13 @@ gst_sdp_message_new
 gst_sdp_message_init
 gst_sdp_message_uninit
 gst_sdp_message_free
+
 gst_sdp_message_parse_buffer
+gst_sdp_message_as_text
+
+gst_sdp_message_parse_uri
+gst_sdp_message_as_uri
+
 gst_sdp_message_get_version
 gst_sdp_message_set_version
 gst_sdp_message_get_origin
@@ -1582,7 +1588,6 @@ gst_sdp_message_medias_len
 gst_sdp_message_get_media
 gst_sdp_message_add_media
 gst_sdp_message_dump
-gst_sdp_message_as_text
 
 gst_sdp_media_new
 gst_sdp_media_init
index 7784bce..7b0023d 100644 (file)
@@ -341,12 +341,12 @@ is_multicast_address (const gchar * host_name, guint * family)
   for (ai = res; !ret && ai; ai = ai->ai_next) {
     if (ai->ai_family == AF_INET)
       ret =
-          IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->
-              sin_addr.s_addr));
+          IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)->sin_addr.
+              s_addr));
     else
       ret =
-          IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->
-              ai_addr)->sin6_addr);
+          IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai->ai_addr)->
+          sin6_addr);
     if (ret && family)
       *family = ai->ai_family;
   }
@@ -486,6 +486,185 @@ gst_sdp_message_as_text (const GstSDPMessage * msg)
   return g_string_free (lines, FALSE);
 }
 
+static int
+hex_to_int (gchar c)
+{
+  return c >= '0' && c <= '9' ? c - '0'
+      : c >= 'A' && c <= 'F' ? c - 'A' + 10
+      : c >= 'a' && c <= 'f' ? c - 'a' + 10 : 0;
+}
+
+/**
+ * gst_sdp_message_parse_uri:
+ * @uri: the start of the uri
+ * @msg: the result #GstSDPMessage
+ *
+ * Parse the null-terminated @uri and store the result in @msg.
+ *
+ * The uri should be of the form:
+ *
+ *  scheme://[address[:ttl=ttl][:noa=noa]]/[sessionname]
+ *               [#type=value *[&type=value]]
+ *
+ *  where value is url encoded. This looslely resembles
+ *  http://tools.ietf.org/html/draft-fujikawa-sdp-url-01
+ *
+ * Returns: #GST_SDP_OK on success.
+ *
+ * Since: 0.10.31
+ */
+GstSDPResult
+gst_sdp_message_parse_uri (const gchar * uri, GstSDPMessage * msg)
+{
+  GstSDPResult res;
+  gchar *message;
+  const gchar *colon, *slash, *hash, *p;
+  GString *lines;
+
+  g_return_val_if_fail (uri != NULL, GST_SDP_EINVAL);
+  g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL);
+
+  g_print ("uri %s\n", uri);
+
+  colon = strstr (uri, "://");
+  if (!colon)
+    goto no_colon;
+
+  /* FIXME connection info goes here */
+
+  slash = strstr (colon + 3, "/");
+  if (!slash)
+    goto no_slash;
+
+  /* FIXME session name goes here */
+
+  hash = strstr (slash + 1, "#");
+  if (!hash)
+    goto no_hash;
+
+  lines = g_string_new ("");
+
+  /* unescape */
+  for (p = hash + 1; *p; p++) {
+    if (*p == '&')
+      g_string_append_printf (lines, "\r\n");
+    else if (*p == '+')
+      g_string_append_c (lines, ' ');
+    else if (*p == '%') {
+      gchar a, b;
+
+      if ((a = p[1])) {
+        if ((b = p[2])) {
+          g_string_append_c (lines, (hex_to_int (a) << 4) | hex_to_int (b));
+          p += 2;
+        }
+      } else {
+        p++;
+      }
+    } else
+      g_string_append_c (lines, *p);
+  }
+
+  message = g_string_free (lines, FALSE);
+  res =
+      gst_sdp_message_parse_buffer ((const guint8 *) message, strlen (message),
+      msg);
+  g_free (message);
+
+  return res;
+
+  /* ERRORS */
+no_colon:
+  {
+    return GST_SDP_EINVAL;
+  }
+no_slash:
+  {
+    return GST_SDP_EINVAL;
+  }
+no_hash:
+  {
+    return GST_SDP_EINVAL;
+  }
+}
+
+static const guchar acceptable[96] = {
+  /* X0   X1    X2    X3    X4    X5    X6    X7    X8    X9    XA    XB    XC    XD    XE    XF */
+  0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,       /* 2X  !"#$%&'()*+,-./   */
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,       /* 3X 0123456789:;<=>?   */
+  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,       /* 4X @ABCDEFGHIJKLMNO   */
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,       /* 5X PQRSTUVWXYZ[\]^_   */
+  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,       /* 6X `abcdefghijklmno   */
+  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00        /* 7X pqrstuvwxyz{|}~DEL */
+};
+
+static const gchar hex[16] = "0123456789ABCDEF";
+
+#define ACCEPTABLE_CHAR(a) ((a)>=32 && (a)<128 && acceptable[(a)-32])
+
+/**
+ * gst_sdp_message_as_uri:
+ * @scheme: the uri scheme
+ * @msg: the #GstSDPMessage
+ *
+ * Creates a uri from @msg with the given @scheme. The uri has the format:
+ *
+ *  @scheme:///[#type=value *[&type=value]]
+ *
+ *  Where each value is url encoded.
+ *
+ * Returns: a uri for @msg.
+ *
+ * Since: 0.10.31
+ */
+gchar *
+gst_sdp_message_as_uri (const gchar * scheme, const GstSDPMessage * msg)
+{
+  gchar *serialized, *p;
+  gchar *res;
+  GString *lines;
+  gboolean first;
+
+  g_return_val_if_fail (scheme != NULL, NULL);
+  g_return_val_if_fail (msg != NULL, NULL);
+
+  p = serialized = gst_sdp_message_as_text (msg);
+
+  lines = g_string_new ("");
+  g_string_append_printf (lines, "%s:///#", scheme);
+
+  /* now escape */
+  first = TRUE;
+  for (p = serialized; *p; p++) {
+    if (first) {
+      g_string_append_printf (lines, "%c=", *p);
+      if (*(p + 1))
+        p++;
+      first = FALSE;
+      continue;
+    }
+    if (*p == '\r')
+      continue;
+    else if (*p == '\n') {
+      if (*(p + 1))
+        g_string_append_c (lines, '&');
+      first = TRUE;
+    } else if (*p == ' ')
+      g_string_append_c (lines, '+');
+    else if (ACCEPTABLE_CHAR (*p))
+      g_string_append_c (lines, *p);
+    else {
+      /* escape */
+      g_string_append_printf (lines, "%%%c%c", hex[*p >> 4], hex[*p & 0xf]);
+    }
+  }
+
+  res = g_string_free (lines, FALSE);
+  g_free (serialized);
+
+  return res;
+}
+
 /**
  * gst_sdp_message_set_version:
  * @msg: a #GstSDPMessage
index 5e6a3f5..bd61b15 100644 (file)
@@ -280,9 +280,12 @@ GstSDPResult            gst_sdp_message_uninit              (GstSDPMessage *msg)
 GstSDPResult            gst_sdp_message_free                (GstSDPMessage *msg);
 
 GstSDPResult            gst_sdp_message_parse_buffer        (const guint8 *data, guint size, GstSDPMessage *msg);
-
 gchar*                  gst_sdp_message_as_text             (const GstSDPMessage *msg);
 
+/* convert from/to uri */
+GstSDPResult            gst_sdp_message_parse_uri           (const gchar *uri, GstSDPMessage *msg);
+gchar*                  gst_sdp_message_as_uri              (const gchar *scheme, const GstSDPMessage *msg);
+
 /* v=.. */
 const gchar*            gst_sdp_message_get_version         (const GstSDPMessage *msg);
 GstSDPResult            gst_sdp_message_set_version         (GstSDPMessage *msg, const gchar *version);