gst_plugins_base/gst-libs/gst/rtsp/gstrtspurl.c
changeset 16 8e837d1bf446
parent 0 0e761a78d257
child 30 7e817e7e631c
equal deleted inserted replaced
15:4b0c6ed43234 16:8e837d1bf446
    56 #include <stdlib.h>
    56 #include <stdlib.h>
    57 #include <string.h>
    57 #include <string.h>
    58 
    58 
    59 #include "gstrtspurl.h"
    59 #include "gstrtspurl.h"
    60 
    60 
    61 #define RTSP_PROTO      "rtsp://"
    61 static void
    62 #define RTSP_PROTO_LEN  7
    62 register_rtsp_url_type (GType * id)
    63 #define RTSPU_PROTO     "rtspu://"
    63 {
    64 #define RTSPU_PROTO_LEN 8
    64   *id = g_boxed_type_register_static ("GstRTSPUrl",
    65 #define RTSPT_PROTO     "rtspt://"
    65       (GBoxedCopyFunc) gst_rtsp_url_copy, (GBoxedFreeFunc) gst_rtsp_url_free);
    66 #define RTSPT_PROTO_LEN 8
    66 }
    67 
    67 
    68 /* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] */
    68 GType
       
    69 gst_rtsp_url_get_type (void)
       
    70 {
       
    71   static GType id;
       
    72   static GOnce once = G_ONCE_INIT;
       
    73 
       
    74   g_once (&once, (GThreadFunc) register_rtsp_url_type, &id);
       
    75   return id;
       
    76 }
       
    77 
       
    78 static const gchar *rtsp_url_schemes[] = {
       
    79   "rtsp",
       
    80   "rtspu",
       
    81   "rtspt",
       
    82   "rtsph",
       
    83   NULL
       
    84 };
       
    85 
       
    86 static GstRTSPLowerTrans rtsp_url_transports[] = {
       
    87   GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
       
    88       GST_RTSP_LOWER_TRANS_UDP_MCAST,
       
    89   GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST,
       
    90   GST_RTSP_LOWER_TRANS_TCP,
       
    91   GST_RTSP_LOWER_TRANS_HTTP | GST_RTSP_LOWER_TRANS_TCP,
       
    92 };
       
    93 
       
    94 /* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] where host
       
    95  * is a host name, an IPv4 dotted decimal address ("aaa.bbb.ccc.ddd") or an
       
    96  * [IPv6] address ("[aabb:ccdd:eeff:gghh::sstt]" note the brackets around the
       
    97  * address to allow the distinction between ':' as an IPv6 hexgroup separator
       
    98  * and as a host/port separator) */
    69 
    99 
    70 /**
   100 /**
    71  * gst_rtsp_url_parse:
   101  * gst_rtsp_url_parse:
    72  * @urlstr: the url string to parse
   102  * @urlstr: the url string to parse
    73  * @url: location to hold the result.
   103  * @url: location to hold the result.
    80 GstRTSPResult
   110 GstRTSPResult
    81 gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url)
   111 gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url)
    82 {
   112 {
    83   GstRTSPUrl *res;
   113   GstRTSPUrl *res;
    84   gchar *p, *delim, *at, *col;
   114   gchar *p, *delim, *at, *col;
       
   115   gchar *host_end = NULL;
       
   116   guint scheme;
    85 
   117 
    86   g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
   118   g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
    87   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
   119   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
    88 
   120 
    89   res = g_new0 (GstRTSPUrl, 1);
   121   res = g_new0 (GstRTSPUrl, 1);
    90 
   122 
    91   p = (gchar *) urlstr;
   123   p = (gchar *) urlstr;
    92   if (g_str_has_prefix (p, RTSP_PROTO)) {
   124 
    93     res->transports =
   125   col = strstr (p, "://");
    94         GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
   126   if (col == NULL)
    95         GST_RTSP_LOWER_TRANS_UDP_MCAST;
   127     goto invalid;
    96     p += RTSP_PROTO_LEN;
   128 
    97   } else if (g_str_has_prefix (p, RTSPU_PROTO)) {
   129   for (scheme = 0; rtsp_url_schemes[scheme] != NULL; scheme++) {
    98     res->transports = GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST;
   130     if (g_ascii_strncasecmp (rtsp_url_schemes[scheme], p, col - p) == 0) {
    99     p += RTSPU_PROTO_LEN;
   131       res->transports = rtsp_url_transports[scheme];
   100   } else if (g_str_has_prefix (p, RTSPT_PROTO)) {
   132       p = col + 3;
   101     res->transports = GST_RTSP_LOWER_TRANS_TCP;
   133       break;
   102     p += RTSPT_PROTO_LEN;
   134     }
   103   } else
   135   }
       
   136 
       
   137   if (res->transports == GST_RTSP_LOWER_TRANS_UNKNOWN)
   104     goto invalid;
   138     goto invalid;
   105 
   139 
   106   delim = strpbrk (p, "/?");
   140   delim = strpbrk (p, "/?");
   107   at = strchr (p, '@');
   141   at = strchr (p, '@');
   108 
   142 
   122 
   156 
   123     /* move to host */
   157     /* move to host */
   124     p = at + 1;
   158     p = at + 1;
   125   }
   159   }
   126 
   160 
   127   col = strchr (p, ':');
   161   if (*p == '[') {
   128   /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
   162     res->family = GST_RTSP_FAM_INET6;
   129    * not really part of the hostname */
   163 
   130   if (col && delim && col >= delim)
   164     /* we have an IPv6 address in the URL, find the ending ] which must be
   131     col = NULL;
   165      * before any delimiter */
   132 
   166     host_end = strchr (++p, ']');
   133   if (col) {
   167     if (!host_end || (delim && host_end >= delim))
   134     res->host = g_strndup (p, col - p);
   168       goto invalid;
   135     p = col + 1;
   169 
   136     res->port = strtoul (p, (char **) &p, 10);
   170     /* a port specifier must follow the address immediately */
   137     if (delim)
   171     col = host_end[1] == ':' ? host_end + 1 : NULL;
   138       p = delim;
       
   139   } else {
   172   } else {
   140     /* no port specified, set to 0. _get_port() will return the default port. */
   173     res->family = GST_RTSP_FAM_INET;
   141     res->port = 0;
   174 
   142     if (!delim) {
   175     col = strchr (p, ':');
   143       res->host = g_strdup (p);
   176 
   144       p = NULL;
   177     /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
       
   178      * not really part of the hostname */
       
   179     if (col && delim && col >= delim)
       
   180       col = NULL;
       
   181 
       
   182     host_end = col ? col : delim;
       
   183   }
       
   184 
       
   185   if (!host_end)
       
   186     res->host = g_strdup (p);
       
   187   else {
       
   188     res->host = g_strndup (p, host_end - p);
       
   189 
       
   190     if (col) {
       
   191       res->port = strtoul (col + 1, NULL, 10);
   145     } else {
   192     } else {
   146       res->host = g_strndup (p, delim - p);
   193       /* no port specified, set to 0. gst_rtsp_url_get_port() will return the
   147       p = delim;
   194        * default port */
       
   195       res->port = 0;
   148     }
   196     }
   149   }
   197   }
       
   198   p = delim;
   150 
   199 
   151   if (p && *p == '/') {
   200   if (p && *p == '/') {
   152     delim = strchr (p, '?');
   201     delim = strchr (p, '?');
   153     if (!delim) {
   202     if (!delim)
   154       res->abspath = g_strdup (p);
   203       res->abspath = g_strdup (p);
   155       p = NULL;
   204     else
   156     } else {
       
   157       res->abspath = g_strndup (p, delim - p);
   205       res->abspath = g_strndup (p, delim - p);
   158       p = delim;
   206     p = delim;
   159     }
       
   160   } else {
   207   } else {
   161     res->abspath = g_strdup ("/");
   208     res->abspath = g_strdup ("/");
   162   }
   209   }
   163 
   210 
   164   if (p && *p == '?')
   211   if (p && *p == '?')
   172 invalid:
   219 invalid:
   173   {
   220   {
   174     gst_rtsp_url_free (res);
   221     gst_rtsp_url_free (res);
   175     return GST_RTSP_EINVAL;
   222     return GST_RTSP_EINVAL;
   176   }
   223   }
       
   224 }
       
   225 
       
   226 /**
       
   227  * gst_rtsp_url_copy:
       
   228  * @url: a #GstRTSPUrl
       
   229  *
       
   230  * Make a copy of @url.
       
   231  *
       
   232  * Returns: a copy of @url. Free with gst_rtsp_url_free () after usage.
       
   233  *
       
   234  * Since: 0.10.22
       
   235  */
       
   236 GstRTSPUrl *
       
   237 gst_rtsp_url_copy (const GstRTSPUrl * url)
       
   238 {
       
   239   GstRTSPUrl *res;
       
   240 
       
   241   g_return_val_if_fail (url != NULL, NULL);
       
   242 
       
   243   res = g_new0 (GstRTSPUrl, 1);
       
   244 
       
   245   res->transports = url->transports;
       
   246   res->family = url->family;
       
   247   res->user = g_strdup (url->user);
       
   248   res->passwd = g_strdup (url->passwd);
       
   249   res->host = g_strdup (url->host);
       
   250   res->port = url->port;
       
   251   res->abspath = g_strdup (url->abspath);
       
   252   res->query = g_strdup (url->query);
       
   253 
       
   254   return res;
   177 }
   255 }
   178 
   256 
   179 /**
   257 /**
   180  * gst_rtsp_url_free:
   258  * gst_rtsp_url_free:
   181  * @url: a #GstRTSPUrl
   259  * @url: a #GstRTSPUrl
   223  * Get the port number of @url.
   301  * Get the port number of @url.
   224  *
   302  *
   225  * Returns: #GST_RTSP_OK.
   303  * Returns: #GST_RTSP_OK.
   226  */
   304  */
   227 GstRTSPResult
   305 GstRTSPResult
   228 gst_rtsp_url_get_port (GstRTSPUrl * url, guint16 * port)
   306 gst_rtsp_url_get_port (const GstRTSPUrl * url, guint16 * port)
   229 {
   307 {
   230   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
   308   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
   231   g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL);
   309   g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL);
   232 
   310 
   233   /* if a port was specified, use that else use the default port. */
   311   /* if a port was specified, use that else use the default port. */
   246  * Get a newly allocated string describing the request URI for @url. 
   324  * Get a newly allocated string describing the request URI for @url. 
   247  *
   325  *
   248  * Returns: a string with the request URI. g_free() after usage.
   326  * Returns: a string with the request URI. g_free() after usage.
   249  */
   327  */
   250 gchar *
   328 gchar *
   251 gst_rtsp_url_get_request_uri (GstRTSPUrl * url)
   329 gst_rtsp_url_get_request_uri (const GstRTSPUrl * url)
   252 {
   330 {
   253   gchar *uri;
   331   gchar *uri;
       
   332   gchar *pre_host;
       
   333   gchar *post_host;
       
   334   gchar *pre_query;
       
   335   gchar *query;
   254 
   336 
   255   g_return_val_if_fail (url != NULL, NULL);
   337   g_return_val_if_fail (url != NULL, NULL);
   256 
   338 
       
   339   pre_host = url->family == GST_RTSP_FAM_INET6 ? "[" : "";
       
   340   post_host = url->family == GST_RTSP_FAM_INET6 ? "]" : "";
       
   341   pre_query = url->query ? "?" : "";
       
   342   query = url->query ? url->query : "";
       
   343 
   257   if (url->port != 0) {
   344   if (url->port != 0) {
   258     uri = g_strdup_printf ("rtsp://%s:%u%s%s%s", url->host, url->port,
   345     uri = g_strdup_printf ("rtsp://%s%s%s:%u%s%s%s", pre_host, url->host,
   259         url->abspath, url->query ? "?" : "", url->query ? url->query : "");
   346         post_host, url->port, url->abspath, pre_query, query);
   260   } else {
   347   } else {
   261     uri = g_strdup_printf ("rtsp://%s%s%s%s", url->host, url->abspath,
   348     uri = g_strdup_printf ("rtsp://%s%s%s%s%s%s", pre_host, url->host,
   262         url->query ? "?" : "", url->query ? url->query : "");
   349         post_host, url->abspath, pre_query, query);
   263   }
   350   }
   264 
   351 
   265   return uri;
   352   return uri;
   266 }
   353 }