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