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