--- a/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c Wed Mar 31 22:03:18 2010 +0300
+++ b/gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c Tue Aug 31 15:30:33 2010 +0300
@@ -58,14 +58,44 @@
#include "gstrtspurl.h"
-#define RTSP_PROTO "rtsp://"
-#define RTSP_PROTO_LEN 7
-#define RTSPU_PROTO "rtspu://"
-#define RTSPU_PROTO_LEN 8
-#define RTSPT_PROTO "rtspt://"
-#define RTSPT_PROTO_LEN 8
+static void
+register_rtsp_url_type (GType * id)
+{
+ *id = g_boxed_type_register_static ("GstRTSPUrl",
+ (GBoxedCopyFunc) gst_rtsp_url_copy, (GBoxedFreeFunc) gst_rtsp_url_free);
+}
+
+GType
+gst_rtsp_url_get_type (void)
+{
+ static GType id;
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, (GThreadFunc) register_rtsp_url_type, &id);
+ return id;
+}
-/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] */
+static const gchar *rtsp_url_schemes[] = {
+ "rtsp",
+ "rtspu",
+ "rtspt",
+ "rtsph",
+ NULL
+};
+
+static GstRTSPLowerTrans rtsp_url_transports[] = {
+ GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
+ GST_RTSP_LOWER_TRANS_UDP_MCAST,
+ GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST,
+ GST_RTSP_LOWER_TRANS_TCP,
+ GST_RTSP_LOWER_TRANS_HTTP | GST_RTSP_LOWER_TRANS_TCP,
+};
+
+/* 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:
@@ -82,6 +112,8 @@
{
GstRTSPUrl *res;
gchar *p, *delim, *at, *col;
+ gchar *host_end = NULL;
+ guint scheme;
g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
@@ -89,18 +121,20 @@
res = g_new0 (GstRTSPUrl, 1);
p = (gchar *) urlstr;
- if (g_str_has_prefix (p, RTSP_PROTO)) {
- res->transports =
- GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
- GST_RTSP_LOWER_TRANS_UDP_MCAST;
- p += RTSP_PROTO_LEN;
- } else if (g_str_has_prefix (p, RTSPU_PROTO)) {
- res->transports = GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST;
- p += RTSPU_PROTO_LEN;
- } else if (g_str_has_prefix (p, RTSPT_PROTO)) {
- res->transports = GST_RTSP_LOWER_TRANS_TCP;
- p += RTSPT_PROTO_LEN;
- } else
+
+ col = strstr (p, "://");
+ if (col == NULL)
+ goto invalid;
+
+ for (scheme = 0; rtsp_url_schemes[scheme] != NULL; scheme++) {
+ if (g_ascii_strncasecmp (rtsp_url_schemes[scheme], p, col - p) == 0) {
+ res->transports = rtsp_url_transports[scheme];
+ p = col + 3;
+ break;
+ }
+ }
+
+ if (res->transports == GST_RTSP_LOWER_TRANS_UNKNOWN)
goto invalid;
delim = strpbrk (p, "/?");
@@ -124,39 +158,52 @@
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;
+
+ /* 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 {
+ res->family = GST_RTSP_FAM_INET;
+
+ col = strchr (p, ':');
- if (col) {
- res->host = g_strndup (p, col - p);
- p = col + 1;
- res->port = strtoul (p, (char **) &p, 10);
- if (delim)
- p = delim;
- } 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;
+ /* 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 ("/");
}
@@ -177,6 +224,37 @@
}
/**
+ * gst_rtsp_url_copy:
+ * @url: a #GstRTSPUrl
+ *
+ * Make a copy of @url.
+ *
+ * Returns: a copy of @url. Free with gst_rtsp_url_free () after usage.
+ *
+ * Since: 0.10.22
+ */
+GstRTSPUrl *
+gst_rtsp_url_copy (const GstRTSPUrl * url)
+{
+ GstRTSPUrl *res;
+
+ g_return_val_if_fail (url != NULL, NULL);
+
+ res = g_new0 (GstRTSPUrl, 1);
+
+ res->transports = url->transports;
+ res->family = url->family;
+ res->user = g_strdup (url->user);
+ res->passwd = g_strdup (url->passwd);
+ res->host = g_strdup (url->host);
+ res->port = url->port;
+ res->abspath = g_strdup (url->abspath);
+ res->query = g_strdup (url->query);
+
+ return res;
+}
+
+/**
* gst_rtsp_url_free:
* @url: a #GstRTSPUrl
*
@@ -225,7 +303,7 @@
* Returns: #GST_RTSP_OK.
*/
GstRTSPResult
-gst_rtsp_url_get_port (GstRTSPUrl * url, guint16 * port)
+gst_rtsp_url_get_port (const GstRTSPUrl * url, guint16 * port)
{
g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL);
@@ -248,18 +326,27 @@
* Returns: a string with the request URI. g_free() after usage.
*/
gchar *
-gst_rtsp_url_get_request_uri (GstRTSPUrl * url)
+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;