From ddbeb44f14ab53c41a4f79a34f06b501f27f10c9 Mon Sep 17 00:00:00 2001 From: Peter Kjellerstedt Date: Tue, 9 Jun 2009 19:06:57 +0200 Subject: [PATCH] rtsp: Added support for parsing IPv6 addresses in RTSP URLs. --- gst-libs/gst/rtsp/gstrtspurl.c | 83 ++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/gst-libs/gst/rtsp/gstrtspurl.c b/gst-libs/gst/rtsp/gstrtspurl.c index 4a2ce5bcbf..145018e126 100644 --- a/gst-libs/gst/rtsp/gstrtspurl.c +++ b/gst-libs/gst/rtsp/gstrtspurl.c @@ -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 (*p == '[') { + res->family = GST_RTSP_FAM_INET6; - if (col) { - res->host = g_strndup (p, col - p); - p = col + 1; - res->port = strtoul (p, (char **) &p, 10); - if (delim) - p = delim; + /* 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;