and added files
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_port.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14   
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #ifdef _WIN32_WCE
21 #define _INC_TIME               /* for wce.h */
22 #include <windows.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28
29 #include <osipparser2/osip_port.h>
30
31 #ifdef HAVE_CTYPE_H
32 #include <ctype.h>
33 #endif
34
35 #include <time.h>
36
37 #if defined(__VXWORKS_OS__)
38 #include <selectLib.h>
39 #elif (!defined(WIN32) && !defined(_WIN32_WCE))
40 #include <sys/time.h>
41 #elif defined(WIN32)
42 #include <windows.h>
43 #ifdef WIN32_USE_CRYPTO
44 #include <Wincrypt.h>
45 #endif
46 #endif
47
48 #if defined (HAVE_SYS_UNISTD_H)
49 #  include <sys/unistd.h>
50 #endif
51
52 #if defined (HAVE_UNISTD_H)
53 #  include <unistd.h>
54 #endif
55
56 #if defined (HAVE_SYSLOG_H)
57 #  include <syslog.h>
58 #endif
59
60 #if defined (HAVE_SYS_SELECT_H)
61 #  include <sys/select.h>
62 #endif
63
64 #ifdef HAVE_PTH_PTHREAD_H
65 #include <pthread.h>
66 #endif
67
68 FILE *logfile = NULL;
69 int tracing_table[END_TRACE_LEVEL];
70 static int use_syslog = 0;
71
72 static unsigned int random_seed_set = 0;
73
74 #ifndef WIN32_USE_CRYPTO
75 unsigned int
76 osip_build_random_number ()
77 #else
78 static unsigned int
79 osip_fallback_random_number ()
80 #endif
81 {
82   if (!random_seed_set)
83     {
84 #ifndef WIN32
85       struct timeval tv;
86
87       gettimeofday (&tv, NULL);
88       srand (tv.tv_usec);
89 #else
90       srand (time (NULL));
91 #endif
92       random_seed_set = 1;
93     }
94
95   return rand ();
96 }
97
98 #ifdef WIN32_USE_CRYPTO
99
100 unsigned int
101 osip_build_random_number ()
102 {
103   HCRYPTPROV crypto;
104   BOOL err;
105   unsigned int num;
106
107   err =
108     CryptAcquireContext (&crypto, NULL, NULL, PROV_RSA_FULL,
109                          CRYPT_VERIFYCONTEXT);
110   if (err)
111     {
112       err = CryptGenRandom (crypto, sizeof (num), (BYTE *) & num);
113       CryptReleaseContext (crypto, 0);
114     }
115   if (!err)
116     {
117       num = osip_fallback_random_number ();
118     }
119   return num;
120 }
121
122 #endif
123
124 #if defined(__linux)
125 #include <limits.h>
126 #endif
127
128 int
129 osip_atoi (const char *number)
130 {
131 #if defined(__linux) || defined(HAVE_STRTOL)
132   int i;
133   if (number == NULL)
134     return -1;
135   i = strtol (number, (char **) NULL, 10);
136   if (i == LONG_MIN || i == LONG_MAX)
137     return -1;
138   return i;
139 #endif
140
141   return atoi (number);
142 }
143
144 char *
145 osip_strncpy (char *dest, const char *src, size_t length)
146 {
147 #ifdef WIN32
148   strncpy (dest, src, length);
149 #else
150   strncpy (dest, src, length);
151 #endif
152   dest[length] = '\0';
153   return dest;
154 }
155
156 /* append string_osip_to_append to string at position cur
157    size is the current allocated size of the element
158 */
159 char *
160 __osip_sdp_append_string (char *string, size_t size, char *cur,
161                           char *string_osip_to_append)
162 {
163   size_t length = strlen (string_osip_to_append);
164
165   if (cur - string + length > size)
166     {
167       size_t length2;
168
169       length2 = cur - string;
170       string = realloc (string, size + length + 10);
171       cur = string + length2;   /* the initial allocation may have changed! */
172     }
173   osip_strncpy (cur, string_osip_to_append, length);
174   return cur + strlen (cur);
175 }
176
177 void
178 osip_usleep (int useconds)
179 {
180 #ifdef WIN32
181   Sleep (useconds / 1000);
182 #else
183   struct timeval delay;
184   int sec;
185
186   sec = (int) useconds / 1000000;
187   if (sec > 0)
188     {
189       delay.tv_sec = sec;
190       delay.tv_usec = 0;
191     }
192   else
193     {
194       delay.tv_sec = 0;
195       delay.tv_usec = useconds;
196     }
197   select (0, 0, 0, 0, &delay);
198 #endif
199 }
200
201
202 char *
203 osip_strdup (const char *ch)
204 {
205   char *copy;
206   size_t length;
207   if (ch == NULL)
208     return NULL;
209   length = strlen (ch);
210   copy = (char *) osip_malloc (length + 1);
211   osip_strncpy (copy, ch, length);
212   return copy;
213 }
214
215 char *
216 osip_strdup_without_quote (const char *ch)
217 {
218   char *copy = (char *) osip_malloc (strlen (ch) + 1);
219
220   /* remove leading and trailing " */
221   if ((*ch == '\"'))
222     {
223       osip_strncpy (copy, ch + 1, strlen (ch + 1));
224       osip_strncpy (copy + strlen (copy) - 1, "\0", 1);
225     }
226   else
227     osip_strncpy (copy, ch, strlen (ch));
228   return copy;
229 }
230
231 int
232 osip_tolower (char *word)
233 {
234 #ifdef HAVE_CTYPE_H
235   for (; *word; word++)
236     *word = (char) tolower (*word);
237 #else
238   int i;
239   size_t len = strlen (word);
240
241   for (i = 0; i <= len - 1; i++)
242     {
243       if ('A' <= word[i] && word[i] <= 'Z')
244         word[i] = word[i] + 32;
245     }
246 #endif
247   return 0;
248 }
249
250 int
251 osip_strcasecmp (const char *s1, const char *s2)
252 {
253 #if (!defined WIN32 && !defined _WIN32_WCE)
254   return strcasecmp (s1, s2);
255 #else
256   return _stricmp (s1, s2);
257 #endif
258 }
259
260 int
261 osip_strncasecmp (const char *s1, const char *s2, size_t len)
262 {
263 #if (!defined WIN32 && !defined _WIN32_WCE)
264   return strncasecmp (s1, s2, len);
265 #else
266   return _strnicmp (s1, s2, len);
267 #endif
268 }
269
270 /* remove SPACE before and after the content */
271 int
272 osip_clrspace (char *word)
273 {
274   char *pbeg;
275   char *pend;
276   size_t len;
277
278   if (word == NULL)
279     return -1;
280   if (*word == '\0')
281     return 0;
282   len = strlen (word);
283
284   pbeg = word;
285   while ((' ' == *pbeg) || ('\r' == *pbeg) || ('\n' == *pbeg)
286          || ('\t' == *pbeg))
287     pbeg++;
288
289   pend = word + len - 1;
290   while ((' ' == *pend) || ('\r' == *pend) || ('\n' == *pend)
291          || ('\t' == *pend))
292     {
293       pend--;
294       if (pend < pbeg)
295         {
296           *word = '\0';
297           return 0;
298         }
299     }
300
301   /* Add terminating NULL only if we've cleared room for it */
302   if (pend + 1 <= word + (len - 1))
303     pend[1] = '\0';
304
305   if (pbeg != word)
306     memmove (word, pbeg, pend - pbeg + 2);
307
308   return 0;
309 }
310
311 /* __osip_set_next_token:
312    dest is the place where the value will be allocated
313    buf is the string where the value is searched
314    end_separator is the character that MUST be found at the end of the value
315    next is the final location of the separator + 1
316
317    the element MUST be found before any "\r" "\n" "\0" and
318    end_separator
319
320    return -1 on error
321    return 1 on success
322 */
323 int
324 __osip_set_next_token (char **dest, char *buf, int end_separator, char **next)
325 {
326   char *sep;                    /* separator */
327
328   *next = NULL;
329
330   sep = buf;
331   while ((*sep != end_separator) && (*sep != '\0') && (*sep != '\r')
332          && (*sep != '\n'))
333     sep++;
334   if ((*sep == '\r') || (*sep == '\n'))
335     {                           /* we should continue normally only if this is the separator asked! */
336       if (*sep != end_separator)
337         return -1;
338     }
339   if (*sep == '\0')
340     return -1;                  /* value must not end with this separator! */
341   if (sep == buf)
342     return -1;                  /* empty value (or several space!) */
343
344   *dest = osip_malloc (sep - (buf) + 1);
345   osip_strncpy (*dest, buf, sep - buf);
346
347   *next = sep + 1;              /* return the position right after the separator */
348   return 0;
349 }
350
351 #if 0
352 /*  not yet done!!! :-)
353  */
354 int
355 __osip_set_next_token_better (char **dest, char *buf, int end_separator,
356                               int *forbidden_tab[], int size_tab, char **next)
357 {
358   char *sep;                    /* separator */
359
360   *next = NULL;
361
362   sep = buf;
363   while ((*sep != end_separator) && (*sep != '\0') && (*sep != '\r')
364          && (*sep != '\n'))
365     sep++;
366   if ((*sep == '\r') && (*sep == '\n'))
367     {                           /* we should continue normally only if this is the separator asked! */
368       if (*sep != end_separator)
369         return -1;
370     }
371   if (*sep == '\0')
372     return -1;                  /* value must not end with this separator! */
373   if (sep == buf)
374     return -1;                  /* empty value (or several space!) */
375
376   *dest = osip_malloc (sep - (buf) + 1);
377   osip_strncpy (*dest, buf, sep - buf);
378
379   *next = sep + 1;              /* return the position right after the separator */
380   return 1;
381 }
382 #endif
383
384 /* in quoted-string, many characters can be escaped...   */
385 /* __osip_quote_find returns the next quote that is not escaped */
386 char *
387 __osip_quote_find (const char *qstring)
388 {
389   char *quote;
390
391   quote = strchr (qstring, '"');
392   if (quote == qstring)         /* the first char matches and is not escaped... */
393     return quote;
394
395   if (quote == NULL)
396     return NULL;                /* no quote at all... */
397
398   /* this is now the nasty cases where '"' is escaped
399      '" jonathan ros \\\""'
400      |                  |
401      '" jonathan ros \\"'
402      |                |
403      '" jonathan ros \""'
404      |                |
405      we must count the number of preceeding '\' */
406   {
407     int i = 1;
408
409     for (;;)
410       {
411         if (0 == strncmp (quote - i, "\\", 1))
412           i++;
413         else
414           {
415             if (i % 2 == 1)     /* the '"' was not escaped */
416               return quote;
417
418             /* else continue with the next '"' */
419             quote = strchr (quote + 1, '"');
420             if (quote == NULL)
421               return NULL;
422             i = 1;
423           }
424         if (quote - i == qstring - 1)
425           /* example: "\"john"  */
426           /* example: "\\"jack" */
427           {
428             /* special case where the string start with '\' */
429             if (*qstring == '\\')
430               i++;              /* an escape char was not counted */
431             if (i % 2 == 0)     /* the '"' was not escaped */
432               return quote;
433             else
434               {                 /* else continue with the next '"' */
435                 qstring = quote + 1;    /* reset qstring because
436                                            (*quote+1) may be also == to '\\' */
437                 quote = strchr (quote + 1, '"');
438                 if (quote == NULL)
439                   return NULL;
440                 i = 1;
441               }
442
443           }
444       }
445     return NULL;
446   }
447 }
448
449 char *
450 osip_enquote (const char *s)
451 {
452   char *rtn;
453   char *t;
454
455   t = rtn = osip_malloc (strlen (s) * 2 + 3);
456   *t++ = '"';
457   for (; *s != '\0'; s++)
458     {
459       switch (*s)
460         {
461         case '"':
462         case '\\':
463         case 0x7f:
464           *t++ = '\\';
465           *t++ = *s;
466           break;
467         case '\n':
468         case '\r':
469           *t++ = ' ';
470           break;
471         default:
472           *t++ = *s;
473           break;
474         }
475     }
476   *t++ = '"';
477   *t++ = '\0';
478   return rtn;
479 }
480
481 void
482 osip_dequote (char *s)
483 {
484   size_t len;
485
486   if (*s == '\0')
487     return;
488   if (*s != '"')
489     return;
490   len = strlen (s);
491   memmove (s, s + 1, len--);
492   if (len > 0 && s[len - 1] == '"')
493     s[--len] = '\0';
494   for (; *s != '\0'; s++, len--)
495     {
496       if (*s == '\\')
497         memmove (s, s + 1, len--);
498     }
499 }
500
501 /**********************************************************/
502 /* only MACROS from osip/trace.h should be used by others */
503 /* TRACE_INITIALIZE(level,file))                          */
504 /* TRACE_ENABLE_LEVEL(level)                              */
505 /* TRACE_DISABLE_LEVEL(level)                             */
506 /* IS_TRACE_LEVEL_ACTIVATE(level)                         */
507 /**********************************************************/
508 #ifndef ENABLE_TRACE
509 void
510 osip_trace_initialize_syslog (osip_trace_level_t level, char *ident)
511 {
512 }
513 void
514 osip_trace_initialize (osip_trace_level_t level, FILE * file)
515 {
516 }
517 void
518 osip_trace_enable_level (osip_trace_level_t level)
519 {
520 }
521 void
522 osip_trace_disable_level (osip_trace_level_t level)
523 {
524 }
525
526 int
527 osip_is_trace_level_activate (osip_trace_level_t level)
528 {
529   return LOG_FALSE;
530 }
531
532 #else
533
534 /* initialize log */
535 /* all lower levels of level are logged in file. */
536 void
537 osip_trace_initialize (osip_trace_level_t level, FILE * file)
538 {
539   int i = 0;
540
541   /* enable trace in log file by default */
542   logfile = NULL;
543   if (file != NULL)
544     logfile = file;
545 #ifndef SYSTEM_LOGGER_ENABLED
546   else
547     logfile = stdout;
548 #endif
549
550   /* enable all lower levels */
551   while (i < END_TRACE_LEVEL)
552     {
553       if (i < level)
554         tracing_table[i] = LOG_TRUE;
555       else
556         tracing_table[i] = LOG_FALSE;
557       i++;
558     }
559 }
560
561 void
562 osip_trace_initialize_syslog (osip_trace_level_t level, char *ident)
563 {
564   int i = 0;
565 #if defined (HAVE_SYSLOG_H)
566   openlog (ident, LOG_CONS | LOG_PID, LOG_DAEMON);
567   use_syslog = 1;
568 #endif
569   /* enable all lower levels */
570   while (i < END_TRACE_LEVEL)
571     {
572       if (i < level)
573         tracing_table[i] = LOG_TRUE;
574       else
575         tracing_table[i] = LOG_FALSE;
576       i++;
577     }
578 }
579
580 /* enable a special debugging level! */
581 void
582 osip_trace_enable_level (osip_trace_level_t level)
583 {
584   tracing_table[level] = LOG_TRUE;
585 }
586
587 /* disable a special debugging level! */
588 void
589 osip_trace_disable_level (osip_trace_level_t level)
590 {
591   tracing_table[level] = LOG_FALSE;
592 }
593
594 /* not so usefull? */
595 int
596 osip_is_trace_level_activate (osip_trace_level_t level)
597 {
598   return tracing_table[level];
599 }
600 #endif
601
602 int
603 osip_trace (char *fi, int li, osip_trace_level_t level, FILE * f, char *chfr,
604             ...)
605 {
606   va_list ap;
607 #ifdef ENABLE_TRACE
608
609 #if !defined(WIN32) && !defined(SYSTEM_LOGGER_ENABLED)
610   if (logfile == NULL && use_syslog == 0)
611     {                           /* user did not initialize logger.. */
612       return 1;
613     }
614 #endif
615
616   if (f == NULL)
617     f = logfile;
618
619   if (tracing_table[level] == LOG_FALSE)
620     return 0;
621
622   VA_START (ap, chfr);
623
624 #ifdef __VXWORKS_OS__
625   /* vxworks can't have a local file */
626   f = stdout;
627 #endif
628
629   if (f && use_syslog == 0)
630     {
631       if (level == OSIP_FATAL)
632         fprintf (f, "| FATAL | <%s: %i> ", fi, li);
633       else if (level == OSIP_BUG)
634         fprintf (f, "|  BUG  | <%s: %i> ", fi, li);
635       else if (level == OSIP_ERROR)
636         fprintf (f, "| ERROR | <%s: %i> ", fi, li);
637       else if (level == OSIP_WARNING)
638         fprintf (f, "|WARNING| <%s: %i> ", fi, li);
639       else if (level == OSIP_INFO1)
640         fprintf (f, "| INFO1 | <%s: %i> ", fi, li);
641       else if (level == OSIP_INFO2)
642         fprintf (f, "| INFO2 | <%s: %i> ", fi, li);
643       else if (level == OSIP_INFO3)
644         fprintf (f, "| INFO3 | <%s: %i> ", fi, li);
645       else if (level == OSIP_INFO4)
646         fprintf (f, "| INFO4 | <%s: %i> ", fi, li);
647
648       vfprintf (f, chfr, ap);
649
650       fflush (f);
651     }
652 #if defined (HAVE_SYSLOG_H)
653   else if (use_syslog == 1)
654     {
655       char buffer[512];
656       int in = 0;
657       memset (buffer, 0, sizeof (buffer));
658       if (level == OSIP_FATAL)
659         in = snprintf (buffer, 511, "| FATAL | <%s: %i> ", fi, li);
660       else if (level == OSIP_BUG)
661         in = snprintf (buffer, 511, "|  BUG  | <%s: %i> ", fi, li);
662       else if (level == OSIP_ERROR)
663         in = snprintf (buffer, 511, "| ERROR | <%s: %i> ", fi, li);
664       else if (level == OSIP_WARNING)
665         in = snprintf (buffer, 511, "|WARNING| <%s: %i> ", fi, li);
666       else if (level == OSIP_INFO1)
667         in = snprintf (buffer, 511, "| INFO1 | <%s: %i> ", fi, li);
668       else if (level == OSIP_INFO2)
669         in = snprintf (buffer, 511, "| INFO2 | <%s: %i> ", fi, li);
670       else if (level == OSIP_INFO3)
671         in = snprintf (buffer, 511, "| INFO3 | <%s: %i> ", fi, li);
672       else if (level == OSIP_INFO4)
673         in = snprintf (buffer, 511, "| INFO4 | <%s: %i> ", fi, li);
674
675       vsnprintf (buffer + in, 511 - in, chfr, ap);
676       if (level == OSIP_FATAL)
677         syslog (LOG_ERR, "%s", buffer);
678       else if (level == OSIP_BUG)
679         syslog (LOG_ERR, "%s", buffer);
680       else if (level == OSIP_ERROR)
681         syslog (LOG_ERR, "%s", buffer);
682       else if (level == OSIP_WARNING)
683         syslog (LOG_WARNING, "%s", buffer);
684       else if (level == OSIP_INFO1)
685         syslog (LOG_INFO, "%s", buffer);
686       else if (level == OSIP_INFO2)
687         syslog (LOG_INFO, "%s", buffer);
688       else if (level == OSIP_INFO3)
689         syslog (LOG_DEBUG, "%s", buffer);
690       else if (level == OSIP_INFO4)
691         syslog (LOG_DEBUG, "%s", buffer);
692     }
693 #endif
694 #ifdef SYSTEM_LOGGER_ENABLED
695   else
696     {
697       char buffer[512];
698       int in = 0;
699       memset (buffer, 0, sizeof (buffer));
700       if (level == OSIP_FATAL)
701         in = _snprintf (buffer, 511, "| FATAL | <%s: %i> ", fi, li);
702       else if (level == OSIP_BUG)
703         in = _snprintf (buffer, 511, "|  BUG  | <%s: %i> ", fi, li);
704       else if (level == OSIP_ERROR)
705         in = _snprintf (buffer, 511, "| ERROR | <%s: %i> ", fi, li);
706       else if (level == OSIP_WARNING)
707         in = _snprintf (buffer, 511, "|WARNING| <%s: %i> ", fi, li);
708       else if (level == OSIP_INFO1)
709         in = _snprintf (buffer, 511, "| INFO1 | <%s: %i> ", fi, li);
710       else if (level == OSIP_INFO2)
711         in = _snprintf (buffer, 511, "| INFO2 | <%s: %i> ", fi, li);
712       else if (level == OSIP_INFO3)
713         in = _snprintf (buffer, 511, "| INFO3 | <%s: %i> ", fi, li);
714       else if (level == OSIP_INFO4)
715         in = _snprintf (buffer, 511, "| INFO4 | <%s: %i> ", fi, li);
716
717       _vsnprintf (buffer + in, 511 - in, chfr, ap);
718       OutputDebugString (buffer);
719     }
720 #endif
721
722   va_end (ap);
723 #endif
724   return 0;
725 }
726
727 #ifdef WIN32
728
729 void *osip_malloc(size_t size)
730 {
731   void *ptr = malloc(size);
732   if(ptr!=NULL)
733     memset(ptr,0,size);
734   return ptr;
735 }
736
737 void osip_free(void *ptr)
738 {
739   if (ptr==NULL) return;
740   free(ptr);
741 }
742
743 #endif
744