parse_supported.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2006 Andreas Granig <[email protected]>
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. /*!
  23. * \file
  24. * \brief Supported parser
  25. * \ingroup parser
  26. */
  27. #include "../../mem/mem.h"
  28. #include "../../parser/keys.h"
  29. #include "parse_supported.h"
  30. #define _100r_ 0x72303031 /* "100r" for "100rel" */
  31. #define _time_ 0x656d6974 /*!< "time" */
  32. #define IS_DELIM(c) (*(c) == ' ' || *(c) == '\t' || *(c) == '\r' || *(c) == '\n' || *(c) == ',')
  33. /* from parser/parse_hname2.c: */
  34. #define LOWER_BYTE(b) ((b) | 0x20)
  35. #define LOWER_DWORD(d) ((d) | 0x20202020)
  36. #define READ(val) \
  37. (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
  38. /*!
  39. * Parse Supported HF body.
  40. */
  41. static inline int parse_supported_body(str *body, unsigned int *sup)
  42. {
  43. register char* p;
  44. register unsigned int val;
  45. int len, pos = 0;
  46. *sup = 0;
  47. p = body->s;
  48. len = body->len;
  49. while (pos < len) {
  50. /* skip spaces and commas */
  51. for (; pos < len && IS_DELIM(p); ++pos, ++p);
  52. val = LOWER_DWORD(READ(p));
  53. switch (val) {
  54. /* "path" */
  55. case _path_:
  56. if(pos + 4 <= len && IS_DELIM(p+4)) {
  57. *sup |= F_SUPPORTED_PATH;
  58. pos += 5; p += 5;
  59. }
  60. break;
  61. /* "100rel" */
  62. case _100r_:
  63. if ( pos+6 <= len
  64. && LOWER_BYTE(*(p+4))=='e' && LOWER_BYTE(*(p+5))=='l'
  65. && IS_DELIM(p+6)) {
  66. *sup |= F_SUPPORTED_100REL;
  67. pos += SUPPORTED_100REL_LEN + 1;
  68. p += SUPPORTED_100REL_LEN + 1;
  69. }
  70. break;
  71. /* "timer" */
  72. case _time_:
  73. if ( pos+5 <= len && LOWER_BYTE(*(p+4))=='r'
  74. && IS_DELIM(p+5) ) {
  75. *sup |= F_SUPPORTED_TIMER;
  76. pos += SUPPORTED_TIMER_LEN + 1;
  77. p += SUPPORTED_TIMER_LEN + 1;
  78. }
  79. break;
  80. /* extra supported or unknown */
  81. default:
  82. if(pos+SUPPORTED_EVENTLIST_LEN<=len
  83. && strncasecmp(p, SUPPORTED_EVENTLIST_STR,
  84. SUPPORTED_EVENTLIST_LEN)==0
  85. && IS_DELIM(p+SUPPORTED_EVENTLIST_LEN) ) {
  86. *sup |= F_SUPPORTED_EVENTLIST;
  87. pos += SUPPORTED_EVENTLIST_LEN + 1;
  88. p += SUPPORTED_EVENTLIST_LEN + 1;
  89. } else if(pos+SUPPORTED_GRUU_LEN<=len
  90. && strncasecmp(p, SUPPORTED_GRUU_STR,
  91. SUPPORTED_GRUU_LEN)==0
  92. && IS_DELIM(p+SUPPORTED_GRUU_LEN)) {
  93. *sup |= F_SUPPORTED_GRUU;
  94. pos += SUPPORTED_GRUU_LEN + 1;
  95. p += SUPPORTED_GRUU_LEN + 1;
  96. } else if(pos+SUPPORTED_OUTBOUND_LEN<=len
  97. && strncasecmp(p, SUPPORTED_OUTBOUND_STR,
  98. SUPPORTED_OUTBOUND_LEN)==0
  99. && IS_DELIM(p+SUPPORTED_OUTBOUND_LEN)) {
  100. *sup |= F_SUPPORTED_OUTBOUND;
  101. pos += SUPPORTED_OUTBOUND_LEN + 1;
  102. p += SUPPORTED_OUTBOUND_LEN + 1;
  103. } else {
  104. /* skip element */
  105. for (; pos < len && !IS_DELIM(p); ++pos, ++p);
  106. }
  107. break;
  108. }
  109. }
  110. return 0;
  111. }
  112. /**
  113. * wrapper to free the content of parsed supported header
  114. */
  115. void hf_free_supported(void *parsed)
  116. {
  117. struct supported_body *sb;
  118. sb = (struct supported_body*)parsed;
  119. free_supported(&sb);
  120. }
  121. /*!
  122. * Parse all Supported headers
  123. */
  124. int parse_supported( struct sip_msg *msg)
  125. {
  126. unsigned int supported;
  127. struct hdr_field *hdr;
  128. struct supported_body *sb;
  129. /* maybe the header is already parsed! */
  130. if (msg->supported && msg->supported->parsed)
  131. return 0;
  132. /* parse to the end in order to get all SUPPORTED headers */
  133. if (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->supported)
  134. return -1;
  135. /* bad luck! :-( - we have to parse them */
  136. supported = 0;
  137. for( hdr=msg->supported ; hdr ; hdr=next_sibling_hdr(hdr)) {
  138. if (hdr->parsed) {
  139. supported |= ((struct supported_body*)hdr->parsed)->supported;
  140. continue;
  141. }
  142. sb = (struct supported_body*)pkg_malloc(sizeof(struct supported_body));
  143. if (sb == 0) {
  144. LM_ERR("out of pkg_memory\n");
  145. return -1;
  146. }
  147. parse_supported_body(&(hdr->body), &(sb->supported));
  148. sb->hfree = hf_free_supported;
  149. sb->supported_all = 0;
  150. hdr->parsed = (void*)sb;
  151. supported |= sb->supported;
  152. }
  153. ((struct supported_body*)msg->supported->parsed)->supported_all =
  154. supported;
  155. return 0;
  156. }
  157. /* free supported header structure */
  158. void free_supported(struct supported_body **sb)
  159. {
  160. if (sb && *sb) {
  161. pkg_free(*sb);
  162. *sb = 0;
  163. }
  164. }