rtsp: Include gst/gstconfig.h to make sure GST_PADDING is defined.
[platform/upstream/gstreamer.git] / gst-libs / gst / rtsp / gstrtspurl.c
1 /* GStreamer
2  * Copyright (C) <2005,2006> Wim Taymans <wim@fluendo.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 /*
20  * Unless otherwise indicated, Source Code is licensed under MIT license.
21  * See further explanation attached in License Statement (distributed in the file
22  * LICENSE).
23  *
24  * Permission is hereby granted, free of charge, to any person obtaining a copy of
25  * this software and associated documentation files (the "Software"), to deal in
26  * the Software without restriction, including without limitation the rights to
27  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
28  * of the Software, and to permit persons to whom the Software is furnished to do
29  * so, subject to the following conditions:
30  *
31  * The above copyright notice and this permission notice shall be included in all
32  * copies or substantial portions of the Software.
33  *
34  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40  * SOFTWARE.
41  */
42
43 /**
44  * SECTION:gstrtspurl
45  * @short_description: handling RTSP urls
46  *  
47  * <refsect2>
48  * <para>
49  * Provides helper functions to handle RTSP urls.
50  * </para>
51  * </refsect2>
52  *  
53  * Last reviewed on 2007-07-25 (0.10.14)
54  */
55
56 #include <stdlib.h>
57 #include <string.h>
58
59 #include "gstrtspurl.h"
60
61 static void
62 register_rtsp_url_type (GType * id)
63 {
64   *id = g_boxed_type_register_static ("GstRTSPUrl",
65       (GBoxedCopyFunc) gst_rtsp_url_copy, (GBoxedFreeFunc) gst_rtsp_url_free);
66 }
67
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
79 #define RTSP_PROTO      "rtsp://"
80 #define RTSP_PROTO_LEN  7
81 #define RTSPU_PROTO     "rtspu://"
82 #define RTSPU_PROTO_LEN 8
83 #define RTSPT_PROTO     "rtspt://"
84 #define RTSPT_PROTO_LEN 8
85 #define RTSPH_PROTO     "rtsph://"
86 #define RTSPH_PROTO_LEN 8
87
88 /* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] */
89
90 /**
91  * gst_rtsp_url_parse:
92  * @urlstr: the url string to parse
93  * @url: location to hold the result.
94  *
95  * Parse the RTSP @urlstr into a newly allocated #GstRTSPUrl. Free after usage
96  * with gst_rtsp_url_free().
97  *
98  * Returns: a #GstRTSPResult.
99  */
100 GstRTSPResult
101 gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url)
102 {
103   GstRTSPUrl *res;
104   gchar *p, *delim, *at, *col;
105
106   g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL);
107   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
108
109   res = g_new0 (GstRTSPUrl, 1);
110
111   p = (gchar *) urlstr;
112   if (g_str_has_prefix (p, RTSP_PROTO)) {
113     res->transports =
114         GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP |
115         GST_RTSP_LOWER_TRANS_UDP_MCAST;
116     p += RTSP_PROTO_LEN;
117   } else if (g_str_has_prefix (p, RTSPU_PROTO)) {
118     res->transports = GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST;
119     p += RTSPU_PROTO_LEN;
120   } else if (g_str_has_prefix (p, RTSPT_PROTO)) {
121     res->transports = GST_RTSP_LOWER_TRANS_TCP;
122     p += RTSPT_PROTO_LEN;
123   } else if (g_str_has_prefix (p, RTSPH_PROTO)) {
124     res->transports = GST_RTSP_LOWER_TRANS_HTTP | GST_RTSP_LOWER_TRANS_TCP;
125     p += RTSPH_PROTO_LEN;
126   } else
127     goto invalid;
128
129   delim = strpbrk (p, "/?");
130   at = strchr (p, '@');
131
132   if (at && delim && at > delim)
133     at = NULL;
134
135   if (at) {
136     col = strchr (p, ':');
137
138     /* must have a ':' and it must be before the '@' */
139     if (col == NULL || col > at)
140       goto invalid;
141
142     res->user = g_strndup (p, col - p);
143     col++;
144     res->passwd = g_strndup (col, at - col);
145
146     /* move to host */
147     p = at + 1;
148   }
149
150   col = strchr (p, ':');
151   /* we have a ':' and a delimiter but the ':' is after the delimiter, it's
152    * not really part of the hostname */
153   if (col && delim && col >= delim)
154     col = NULL;
155
156   if (col) {
157     res->host = g_strndup (p, col - p);
158     p = col + 1;
159     res->port = strtoul (p, (char **) &p, 10);
160     if (delim)
161       p = delim;
162   } else {
163     /* no port specified, set to 0. _get_port() will return the default port. */
164     res->port = 0;
165     if (!delim) {
166       res->host = g_strdup (p);
167       p = NULL;
168     } else {
169       res->host = g_strndup (p, delim - p);
170       p = delim;
171     }
172   }
173
174   if (p && *p == '/') {
175     delim = strchr (p, '?');
176     if (!delim) {
177       res->abspath = g_strdup (p);
178       p = NULL;
179     } else {
180       res->abspath = g_strndup (p, delim - p);
181       p = delim;
182     }
183   } else {
184     res->abspath = g_strdup ("/");
185   }
186
187   if (p && *p == '?')
188     res->query = g_strdup (p + 1);
189
190   *url = res;
191
192   return GST_RTSP_OK;
193
194   /* ERRORS */
195 invalid:
196   {
197     gst_rtsp_url_free (res);
198     return GST_RTSP_EINVAL;
199   }
200 }
201
202 /**
203  * gst_rtsp_url_copy:
204  * @url: a #GstRTSPUrl
205  *
206  * Make a copy of @url.
207  *
208  * Returns: a copy of @url. Free with gst_rtsp_url_free () after usage.
209  *
210  * Since: 0.10.22
211  */
212 GstRTSPUrl *
213 gst_rtsp_url_copy (const GstRTSPUrl * url)
214 {
215   GstRTSPUrl *res;
216
217   g_return_val_if_fail (url != NULL, NULL);
218
219   res = g_new0 (GstRTSPUrl, 1);
220
221   res->transports = url->transports;
222   res->family = url->family;
223   res->user = g_strdup (url->user);
224   res->passwd = g_strdup (url->passwd);
225   res->host = g_strdup (url->host);
226   res->port = url->port;
227   res->abspath = g_strdup (url->abspath);
228   res->query = g_strdup (url->query);
229
230   return res;
231 }
232
233 /**
234  * gst_rtsp_url_free:
235  * @url: a #GstRTSPUrl
236  *
237  * Free the memory used by @url.
238  */
239 void
240 gst_rtsp_url_free (GstRTSPUrl * url)
241 {
242   if (url == NULL)
243     return;
244
245   g_free (url->user);
246   g_free (url->passwd);
247   g_free (url->host);
248   g_free (url->abspath);
249   g_free (url->query);
250   g_free (url);
251 }
252
253 /**
254  * gst_rtsp_url_set_port:
255  * @url: a #GstRTSPUrl
256  * @port: the port
257  *
258  * Set the port number in @url to @port.
259  *
260  * Returns: #GST_RTSP_OK.
261  */
262 GstRTSPResult
263 gst_rtsp_url_set_port (GstRTSPUrl * url, guint16 port)
264 {
265   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
266
267   url->port = port;
268
269   return GST_RTSP_OK;
270 }
271
272 /**
273  * gst_rtsp_url_get_port:
274  * @url: a #GstRTSPUrl
275  * @port: location to hold the port
276  *
277  * Get the port number of @url.
278  *
279  * Returns: #GST_RTSP_OK.
280  */
281 GstRTSPResult
282 gst_rtsp_url_get_port (const GstRTSPUrl * url, guint16 * port)
283 {
284   g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL);
285   g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL);
286
287   /* if a port was specified, use that else use the default port. */
288   if (url->port != 0)
289     *port = url->port;
290   else
291     *port = GST_RTSP_DEFAULT_PORT;
292
293   return GST_RTSP_OK;
294 }
295
296 /**
297  * gst_rtsp_url_get_request_uri:
298  * @url: a #GstRTSPUrl
299  *
300  * Get a newly allocated string describing the request URI for @url. 
301  *
302  * Returns: a string with the request URI. g_free() after usage.
303  */
304 gchar *
305 gst_rtsp_url_get_request_uri (const GstRTSPUrl * url)
306 {
307   gchar *uri;
308
309   g_return_val_if_fail (url != NULL, NULL);
310
311   if (url->port != 0) {
312     uri = g_strdup_printf ("rtsp://%s:%u%s%s%s", url->host, url->port,
313         url->abspath, url->query ? "?" : "", url->query ? url->query : "");
314   } else {
315     uri = g_strdup_printf ("rtsp://%s%s%s%s", url->host, url->abspath,
316         url->query ? "?" : "", url->query ? url->query : "");
317   }
318
319   return uri;
320 }