Merge remote-tracking branch 'origin/0.10'
[platform/upstream/gstreamer.git] / gst-libs / gst / rtsp / gstrtspdefs.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:gstrtspdefs
45  * @short_description: common RTSP defines
46  * @see_also: gstrtspurl, gstrtspconnection
47  *  
48  * Provides common defines for the RTSP library. 
49  *  
50  * Last reviewed on 2007-07-24 (0.10.14)
51  */
52
53 #include <errno.h>
54
55 #include "gstrtspdefs.h"
56
57 struct rtsp_header
58 {
59   const gchar *name;
60   gboolean multiple;
61 };
62
63 static const gchar *rtsp_methods[] = {
64   "DESCRIBE",
65   "ANNOUNCE",
66   "GET_PARAMETER",
67   "OPTIONS",
68   "PAUSE",
69   "PLAY",
70   "RECORD",
71   "REDIRECT",
72   "SETUP",
73   "SET_PARAMETER",
74   "TEARDOWN",
75   "GET",
76   "POST",
77   NULL
78 };
79
80 static struct rtsp_header rtsp_headers[] = {
81   {"Accept", TRUE},
82   {"Accept-Encoding", TRUE},
83   {"Accept-Language", TRUE},
84   {"Allow", TRUE},
85   {"Authorization", FALSE},
86   {"Bandwidth", FALSE},
87   {"Blocksize", FALSE},
88   {"Cache-Control", TRUE},
89   {"Conference", FALSE},
90   {"Connection", TRUE},
91   {"Content-Base", FALSE},
92   {"Content-Encoding", TRUE},
93   {"Content-Language", TRUE},
94   {"Content-Length", FALSE},
95   {"Content-Location", FALSE},
96   {"Content-Type", FALSE},
97   {"CSeq", FALSE},
98   {"Date", FALSE},
99   {"Expires", FALSE},
100   {"From", FALSE},
101   {"If-Modified-Since", FALSE},
102   {"Last-Modified", FALSE},
103   {"Proxy-Authenticate", TRUE},
104   {"Proxy-Require", TRUE},
105   {"Public", TRUE},
106   {"Range", FALSE},
107   {"Referer", FALSE},
108   {"Require", TRUE},
109   {"Retry-After", FALSE},
110   {"RTP-Info", TRUE},
111   {"Scale", FALSE},
112   {"Session", FALSE},
113   {"Server", FALSE},
114   {"Speed", FALSE},
115   {"Transport", TRUE},
116   {"Unsupported", FALSE},
117   {"User-Agent", FALSE},
118   {"Via", TRUE},
119   {"WWW-Authenticate", TRUE},
120
121   /* Real extensions */
122   {"ClientChallenge", FALSE},
123   {"RealChallenge1", FALSE},
124   {"RealChallenge2", FALSE},
125   {"RealChallenge3", FALSE},
126   {"Subscribe", FALSE},
127   {"Alert", FALSE},
128   {"ClientID", FALSE},
129   {"CompanyID", FALSE},
130   {"GUID", FALSE},
131   {"RegionData", FALSE},
132   {"SupportsMaximumASMBandwidth", FALSE},
133   {"Language", FALSE},
134   {"PlayerStarttime", FALSE},
135
136   /* Since 0.10.16 */
137   {"Location", FALSE},
138
139   /* Since 0.10.23 */
140   {"ETag", FALSE},
141   {"If-Match", TRUE},
142
143   /* WM extensions [MS-RTSP] Since 0.10.23 */
144   {"Accept-Charset", TRUE},
145   {"Supported", TRUE},
146   {"Vary", TRUE},
147   {"X-Accelerate-Streaming", FALSE},
148   {"X-Accept-Authentication", FALSE},
149   {"X-Accept-Proxy-Authentication", FALSE},
150   {"X-Broadcast-Id", FALSE},
151   {"X-Burst-Streaming", FALSE},
152   {"X-Notice", FALSE},
153   {"X-Player-Lag-Time", FALSE},
154   {"X-Playlist", FALSE},
155   {"X-Playlist-Change-Notice", FALSE},
156   {"X-Playlist-Gen-Id", FALSE},
157   {"X-Playlist-Seek-Id", FALSE},
158   {"X-Proxy-Client-Agent", FALSE},
159   {"X-Proxy-Client-Verb", FALSE},
160   {"X-Receding-PlaylistChange", FALSE},
161   {"X-RTP-Info", FALSE},
162   {"X-StartupProfile", FALSE},
163
164   /* Since 0.10.24 */
165   {"Timestamp", FALSE},
166
167   /* Since 0.10.25 */
168   {"Authentication-Info", FALSE},
169   {"Host", FALSE},
170   {"Pragma", TRUE},
171   {"X-Server-IP-Address", FALSE},
172   {"X-Sessioncookie", FALSE},
173
174   /* Since 0.10.36 */
175   {"RTCP-Interval", FALSE},
176
177   {NULL, FALSE}
178 };
179
180 #define DEF_STATUS(c, t) \
181   g_hash_table_insert (statuses, GUINT_TO_POINTER(c), (gpointer) t)
182
183 static GHashTable *
184 rtsp_init_status (void)
185 {
186   GHashTable *statuses = g_hash_table_new (NULL, NULL);
187
188   DEF_STATUS (GST_RTSP_STS_CONTINUE, "Continue");
189   DEF_STATUS (GST_RTSP_STS_OK, "OK");
190   DEF_STATUS (GST_RTSP_STS_CREATED, "Created");
191   DEF_STATUS (GST_RTSP_STS_LOW_ON_STORAGE, "Low on Storage Space");
192   DEF_STATUS (GST_RTSP_STS_MULTIPLE_CHOICES, "Multiple Choices");
193   DEF_STATUS (GST_RTSP_STS_MOVED_PERMANENTLY, "Moved Permanently");
194   DEF_STATUS (GST_RTSP_STS_MOVE_TEMPORARILY, "Move Temporarily");
195   DEF_STATUS (GST_RTSP_STS_SEE_OTHER, "See Other");
196   DEF_STATUS (GST_RTSP_STS_NOT_MODIFIED, "Not Modified");
197   DEF_STATUS (GST_RTSP_STS_USE_PROXY, "Use Proxy");
198   DEF_STATUS (GST_RTSP_STS_BAD_REQUEST, "Bad Request");
199   DEF_STATUS (GST_RTSP_STS_UNAUTHORIZED, "Unauthorized");
200   DEF_STATUS (GST_RTSP_STS_PAYMENT_REQUIRED, "Payment Required");
201   DEF_STATUS (GST_RTSP_STS_FORBIDDEN, "Forbidden");
202   DEF_STATUS (GST_RTSP_STS_NOT_FOUND, "Not Found");
203   DEF_STATUS (GST_RTSP_STS_METHOD_NOT_ALLOWED, "Method Not Allowed");
204   DEF_STATUS (GST_RTSP_STS_NOT_ACCEPTABLE, "Not Acceptable");
205   DEF_STATUS (GST_RTSP_STS_PROXY_AUTH_REQUIRED,
206       "Proxy Authentication Required");
207   DEF_STATUS (GST_RTSP_STS_REQUEST_TIMEOUT, "Request Time-out");
208   DEF_STATUS (GST_RTSP_STS_GONE, "Gone");
209   DEF_STATUS (GST_RTSP_STS_LENGTH_REQUIRED, "Length Required");
210   DEF_STATUS (GST_RTSP_STS_PRECONDITION_FAILED, "Precondition Failed");
211   DEF_STATUS (GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE,
212       "Request Entity Too Large");
213   DEF_STATUS (GST_RTSP_STS_REQUEST_URI_TOO_LARGE, "Request-URI Too Large");
214   DEF_STATUS (GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
215   DEF_STATUS (GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD,
216       "Parameter Not Understood");
217   DEF_STATUS (GST_RTSP_STS_CONFERENCE_NOT_FOUND, "Conference Not Found");
218   DEF_STATUS (GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH, "Not Enough Bandwidth");
219   DEF_STATUS (GST_RTSP_STS_SESSION_NOT_FOUND, "Session Not Found");
220   DEF_STATUS (GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE,
221       "Method Not Valid in This State");
222   DEF_STATUS (GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE,
223       "Header Field Not Valid for Resource");
224   DEF_STATUS (GST_RTSP_STS_INVALID_RANGE, "Invalid Range");
225   DEF_STATUS (GST_RTSP_STS_PARAMETER_IS_READONLY, "Parameter Is Read-Only");
226   DEF_STATUS (GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED,
227       "Aggregate operation not allowed");
228   DEF_STATUS (GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED,
229       "Only aggregate operation allowed");
230   DEF_STATUS (GST_RTSP_STS_UNSUPPORTED_TRANSPORT, "Unsupported transport");
231   DEF_STATUS (GST_RTSP_STS_DESTINATION_UNREACHABLE, "Destination unreachable");
232   DEF_STATUS (GST_RTSP_STS_INTERNAL_SERVER_ERROR, "Internal Server Error");
233   DEF_STATUS (GST_RTSP_STS_NOT_IMPLEMENTED, "Not Implemented");
234   DEF_STATUS (GST_RTSP_STS_BAD_GATEWAY, "Bad Gateway");
235   DEF_STATUS (GST_RTSP_STS_SERVICE_UNAVAILABLE, "Service Unavailable");
236   DEF_STATUS (GST_RTSP_STS_GATEWAY_TIMEOUT, "Gateway Time-out");
237   DEF_STATUS (GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED,
238       "RTSP Version not supported");
239   DEF_STATUS (GST_RTSP_STS_OPTION_NOT_SUPPORTED, "Option not supported");
240
241   return statuses;
242 }
243
244 /**
245  * gst_rtsp_strresult:
246  * @result: a #GstRTSPResult
247  *
248  * Convert @result in a human readable string.
249  *
250  * Returns: a newly allocated string. g_free() after usage.
251  */
252 gchar *
253 gst_rtsp_strresult (GstRTSPResult result)
254 {
255   switch (result) {
256     case GST_RTSP_OK:
257       return g_strdup ("OK");
258     case GST_RTSP_ESYS:
259       return g_strdup ("System error");
260     case GST_RTSP_ENET:
261       return g_strdup ("Network error");
262     case GST_RTSP_ERROR:
263       return g_strdup ("Generic error");
264     case GST_RTSP_EINVAL:
265       return g_strdup ("Invalid parameter specified");
266     case GST_RTSP_EINTR:
267       return g_strdup ("Operation interrupted");
268     case GST_RTSP_ENOMEM:
269       return g_strdup ("Out of memory");
270     case GST_RTSP_ERESOLV:
271       return g_strdup ("Cannot resolve host");
272     case GST_RTSP_ENOTIMPL:
273       return g_strdup ("Function not implemented");
274     case GST_RTSP_EPARSE:
275       return g_strdup ("Parse error");
276     case GST_RTSP_EWSASTART:
277       return g_strdup ("Error on WSAStartup");
278     case GST_RTSP_EWSAVERSION:
279       return g_strdup ("Windows sockets are not version 0x202");
280     case GST_RTSP_EEOF:
281       return g_strdup ("Received end-of-file");
282     case GST_RTSP_ENOTIP:
283       return g_strdup ("Host is not a valid IP address");
284     case GST_RTSP_ETIMEOUT:
285       return g_strdup ("Timeout while waiting for server response");
286     case GST_RTSP_ETGET:
287       return g_strdup ("Tunnel GET request received");
288     case GST_RTSP_ETPOST:
289       return g_strdup ("Tunnel POST request received");
290     case GST_RTSP_ELAST:
291     default:
292       return g_strdup_printf ("Unknown error (%d)", result);
293   }
294 }
295
296 /**
297  * gst_rtsp_method_as_text:
298  * @method: a #GstRTSPMethod
299  *
300  * Convert @method to a string.
301  *
302  * Returns: a string representation of @method.
303  */
304 const gchar *
305 gst_rtsp_method_as_text (GstRTSPMethod method)
306 {
307   gint i;
308
309   if (method == GST_RTSP_INVALID)
310     return NULL;
311
312   i = 0;
313   while ((method & 1) == 0) {
314     i++;
315     method >>= 1;
316   }
317   return rtsp_methods[i];
318 }
319
320 /**
321  * gst_rtsp_version_as_text:
322  * @version: a #GstRTSPVersion
323  *
324  * Convert @version to a string.
325  *
326  * Returns: a string representation of @version.
327  */
328 const gchar *
329 gst_rtsp_version_as_text (GstRTSPVersion version)
330 {
331   switch (version) {
332     case GST_RTSP_VERSION_1_0:
333       return "1.0";
334
335     case GST_RTSP_VERSION_1_1:
336       return "1.1";
337
338     default:
339       return "0.0";
340   }
341 }
342
343 /**
344  * gst_rtsp_header_as_text:
345  * @field: a #GstRTSPHeaderField
346  *
347  * Convert @field to a string.
348  *
349  * Returns: a string representation of @field.
350  */
351 const gchar *
352 gst_rtsp_header_as_text (GstRTSPHeaderField field)
353 {
354   if (field == GST_RTSP_HDR_INVALID)
355     return NULL;
356   else
357     return rtsp_headers[field - 1].name;
358 }
359
360 /**
361  * gst_rtsp_status_as_text:
362  * @code: a #GstRTSPStatusCode
363  *
364  * Convert @code to a string.
365  *
366  * Returns: a string representation of @code.
367  */
368 const gchar *
369 gst_rtsp_status_as_text (GstRTSPStatusCode code)
370 {
371   static GHashTable *statuses;
372
373   if (G_UNLIKELY (statuses == NULL))
374     statuses = rtsp_init_status ();
375
376   return g_hash_table_lookup (statuses, GUINT_TO_POINTER (code));
377 }
378
379 /**
380  * gst_rtsp_find_header_field:
381  * @header: a header string
382  *
383  * Convert @header to a #GstRTSPHeaderField.
384  *
385  * Returns: a #GstRTSPHeaderField for @header or #GST_RTSP_HDR_INVALID if the
386  * header field is unknown.
387  */
388 GstRTSPHeaderField
389 gst_rtsp_find_header_field (const gchar * header)
390 {
391   gint idx;
392
393   for (idx = 0; rtsp_headers[idx].name; idx++) {
394     if (g_ascii_strcasecmp (rtsp_headers[idx].name, header) == 0) {
395       return idx + 1;
396     }
397   }
398   return GST_RTSP_HDR_INVALID;
399 }
400
401 /**
402  * gst_rtsp_find_method:
403  * @method: a method
404  *
405  * Convert @method to a #GstRTSPMethod.
406  *
407  * Returns: a #GstRTSPMethod for @method or #GST_RTSP_INVALID if the
408  * method is unknown.
409  */
410 GstRTSPMethod
411 gst_rtsp_find_method (const gchar * method)
412 {
413   gint idx;
414
415   for (idx = 0; rtsp_methods[idx]; idx++) {
416     if (g_ascii_strcasecmp (rtsp_methods[idx], method) == 0) {
417       return (1 << idx);
418     }
419   }
420   return GST_RTSP_INVALID;
421 }
422
423 /**
424  * gst_rtsp_options_as_text:
425  * @options: one or more #GstRTSPMethod
426  *
427  * Convert @options to a string.
428  *
429  * Returns: a new string of @options. g_free() after usage.
430  *
431  * Since: 0.10.23
432  */
433 gchar *
434 gst_rtsp_options_as_text (GstRTSPMethod options)
435 {
436   GString *str;
437
438   str = g_string_new ("");
439
440   if (options & GST_RTSP_OPTIONS)
441     g_string_append (str, "OPTIONS, ");
442   if (options & GST_RTSP_DESCRIBE)
443     g_string_append (str, "DESCRIBE, ");
444   if (options & GST_RTSP_ANNOUNCE)
445     g_string_append (str, "ANNOUNCE, ");
446   if (options & GST_RTSP_GET_PARAMETER)
447     g_string_append (str, "GET_PARAMETER, ");
448   if (options & GST_RTSP_PAUSE)
449     g_string_append (str, "PAUSE, ");
450   if (options & GST_RTSP_PLAY)
451     g_string_append (str, "PLAY, ");
452   if (options & GST_RTSP_RECORD)
453     g_string_append (str, "RECORD, ");
454   if (options & GST_RTSP_REDIRECT)
455     g_string_append (str, "REDIRECT, ");
456   if (options & GST_RTSP_SETUP)
457     g_string_append (str, "SETUP, ");
458   if (options & GST_RTSP_SET_PARAMETER)
459     g_string_append (str, "SET_PARAMETER, ");
460   if (options & GST_RTSP_TEARDOWN)
461     g_string_append (str, "TEARDOWN, ");
462
463   /* remove trailing ", " if there is one */
464   if (str->len > 2)
465     str = g_string_truncate (str, str->len - 2);
466
467   return g_string_free (str, FALSE);
468 }
469
470 /**
471  * gst_rtsp_header_allow_multiple:
472  * @field: a #GstRTSPHeaderField
473  *
474  * Check whether @field may appear multiple times in a message.
475  *
476  * Returns: %TRUE if multiple headers are allowed.
477  *
478  * Since: 0.10.25
479  */
480 gboolean
481 gst_rtsp_header_allow_multiple (GstRTSPHeaderField field)
482 {
483   if (field == GST_RTSP_HDR_INVALID)
484     return FALSE;
485   else
486     return rtsp_headers[field - 1].multiple;
487 }