rtsp: Added support for parsing IPv6 addresses in RTSP URLs.
authorPeter Kjellerstedt <pkj@axis.com>
Tue, 9 Jun 2009 17:06:57 +0000 (19:06 +0200)
committerPeter Kjellerstedt <pkj@axis.com>
Wed, 17 Jun 2009 16:00:17 +0000 (18:00 +0200)
gst-libs/gst/rtsp/gstrtspurl.c

index 4a2ce5b..145018e 100644 (file)
@@ -85,7 +85,11 @@ gst_rtsp_url_get_type (void)
 #define RTSPH_PROTO     "rtsph://"
 #define RTSPH_PROTO_LEN 8
 
-/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] */
+/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] where host
+ * is a host name, an IPv4 dotted decimal address ("aaa.bbb.ccc.ddd") or an
+ * [IPv6] address ("[aabb:ccdd:eeff:gghh::sstt]" note the brackets around the
+ * address to allow the distinction between ':' as an IPv6 hexgroup separator
+ * and as a host/port separator) */
 
 /**
  * gst_rtsp_url_parse:
@@ -102,6 +106,7 @@ gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url)
 {
   GstRTSPUrl *res;
   gchar *p, *delim, *at, *col;
+  gchar *host_end = NULL;
 
   g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
@@ -147,39 +152,52 @@ gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url)
     p = at + 1;
   }
 
-  col = strchr (p, ':');
-  /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
-   * not really part of the hostname */
-  if (col && delim && col >= delim)
-    col = NULL;
-
-  if (col) {
-    res->host = g_strndup (p, col - p);
-    p = col + 1;
-    res->port = strtoul (p, (char **) &p, 10);
-    if (delim)
-      p = delim;
+  if (*p == '[') {
+    res->family = GST_RTSP_FAM_INET6;
+
+    /* we have an IPv6 address in the URL, find the ending ] which must be
+     * before any delimiter */
+    host_end = strchr (++p, ']');
+    if (!host_end || (delim && host_end >= delim))
+      goto invalid;
+
+    /* a port specifier must follow the address immediately */
+    col = host_end[1] == ':' ? host_end + 1 : NULL;
   } else {
-    /* no port specified, set to 0. _get_port() will return the default port. */
-    res->port = 0;
-    if (!delim) {
-      res->host = g_strdup (p);
-      p = NULL;
+    res->family = GST_RTSP_FAM_INET;
+
+    col = strchr (p, ':');
+
+    /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
+     * not really part of the hostname */
+    if (col && delim && col >= delim)
+      col = NULL;
+
+    host_end = col ? col : delim;
+  }
+
+  if (!host_end)
+    res->host = g_strdup (p);
+  else {
+    res->host = g_strndup (p, host_end - p);
+
+    if (col) {
+      res->port = strtoul (col + 1, NULL, 10);
     } else {
-      res->host = g_strndup (p, delim - p);
-      p = delim;
+      /* no port specified, set to 0. gst_rtsp_url_get_port() will return the
+       * default port */
+      res->port = 0;
     }
   }
+  p = delim;
 
   if (p && *p == '/') {
     delim = strchr (p, '?');
-    if (!delim) {
+    if (!delim)
       res->abspath = g_strdup (p);
-      p = NULL;
-    } else {
+    else
       res->abspath = g_strndup (p, delim - p);
-      p = delim;
-    }
+    p = delim;
   } else {
     res->abspath = g_strdup ("/");
   }
@@ -305,15 +323,24 @@ gchar *
 gst_rtsp_url_get_request_uri (const GstRTSPUrl * url)
 {
   gchar *uri;
+  gchar *pre_host;
+  gchar *post_host;
+  gchar *pre_query;
+  gchar *query;
 
   g_return_val_if_fail (url != NULL, NULL);
 
+  pre_host = url->family == GST_RTSP_FAM_INET6 ? "[" : "";
+  post_host = url->family == GST_RTSP_FAM_INET6 ? "]" : "";
+  pre_query = url->query ? "?" : "";
+  query = url->query ? url->query : "";
+
   if (url->port != 0) {
-    uri = g_strdup_printf ("rtsp://%s:%u%s%s%s", url->host, url->port,
-        url->abspath, url->query ? "?" : "", url->query ? url->query : "");
+    uri = g_strdup_printf ("rtsp://%s%s%s:%u%s%s%s", pre_host, url->host,
+        post_host, url->port, url->abspath, pre_query, query);
   } else {
-    uri = g_strdup_printf ("rtsp://%s%s%s%s", url->host, url->abspath,
-        url->query ? "?" : "", url->query ? url->query : "");
+    uri = g_strdup_printf ("rtsp://%s%s%s%s%s%s", pre_host, url->host,
+        post_host, url->abspath, pre_query, query);
   }
 
   return uri;