parse_sst.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (c) 2006 SOMA Networks, Inc. <http://www.somanetworks.com/>
  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * History:
  23. * --------
  24. * 2006-02-17 Initial revision ([email protected])
  25. */
  26. /*!
  27. * \file
  28. * \brief SST parser
  29. * \ingroup parser
  30. */
  31. #include "parse_sst.h"
  32. #include "../../error.h"
  33. #include "../../dprint.h"
  34. #include "../../mem/mem.h"
  35. static inline int/*bool*/ is_space( char c ) { return (c == ' ' || c == '\t'); }
  36. static inline int/*bool*/ is_num( char c ) { return (c >= '0' && c <= '9'); }
  37. static inline unsigned lower_byte( char b ) { return b | 0x20; }
  38. static inline unsigned lower_4bytes( unsigned d ) { return d | 0x20202020; }
  39. static inline unsigned lower_3bytes( unsigned d ) { return d | 0x202020; }
  40. static inline unsigned read_4bytes( char *val ) {
  41. return (*(val + 0) + (*(val + 1) << 8)
  42. + (*(val + 2) << 16) + (*(val + 3) << 24));
  43. }
  44. static inline unsigned read_3bytes( char *val ) {
  45. return (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16));
  46. }
  47. /* compile-time constants if called with constants */
  48. #define MAKE_4BYTES( a, b, c, d ) \
  49. ( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) | (((d)&0xFF)<<24) )
  50. #define MAKE_3BYTES( a, b, c ) \
  51. ( ((a)&0xFF) | (((b)&0xFF)<<8) | (((c)&0xFF)<<16) )
  52. struct session_expires *
  53. malloc_session_expires( void )
  54. {
  55. struct session_expires *se = (struct session_expires *)
  56. pkg_malloc( sizeof(struct session_expires) );
  57. if ( se )
  58. memset( se, 0, sizeof(struct session_expires) );
  59. return se;
  60. }
  61. /**
  62. * wrapper to free the content of parsed session-expires header
  63. */
  64. void hf_free_session_expires(void *parsed)
  65. {
  66. struct session_expires *se;
  67. se = (struct session_expires*)parsed;
  68. free_session_expires(se);
  69. }
  70. void
  71. free_session_expires( struct session_expires *se )
  72. {
  73. if ( se )
  74. pkg_free( se );
  75. }
  76. enum parse_sst_result
  77. parse_session_expires_body( struct hdr_field *hf )
  78. {
  79. register char *p = hf->body.s;
  80. int pos = 0;
  81. int len = hf->body.len;
  82. char *q;
  83. struct session_expires se = { 0, 0, sst_refresher_unspecified };
  84. unsigned tok;
  85. if ( !p || len <= 0 ) {
  86. LM_ERR(" no body for header field\n" );
  87. return parse_sst_header_not_found;
  88. }
  89. /* skip whitespace */
  90. for ( ; pos < len && is_space(*p); ++pos, ++p )
  91. /*nothing*/;
  92. /* collect a number */
  93. for ( q = p; pos < len && is_num(*q); ++pos, ++q )
  94. se.interval = se.interval*10/*radix*/ + (*q - '0');
  95. if ( q == p ) /*nothing parsed */ {
  96. LM_ERR(" no expiry interval\n" );
  97. return parse_sst_no_value;
  98. }
  99. p = q;
  100. /* continue on with params */
  101. while ( pos < len ) {
  102. if ( *p == ';' ) {
  103. ++p; ++pos;
  104. if ( pos + 4 < len ) {
  105. switch ( lower_4bytes(read_4bytes(p)) ) {
  106. case /*refr*/MAKE_4BYTES('r','e','f','r'):
  107. if ( pos + 9 <= len
  108. && lower_4bytes(read_4bytes(p+4))
  109. == /*eshe*/MAKE_4BYTES('e','s','h','e')
  110. && lower_byte(*(p+8)) == 'r'
  111. && *(p+9) == '=' ) {
  112. tok = lower_3bytes( read_3bytes(p+10) );
  113. if ( tok == MAKE_3BYTES('u','a','c') ) {
  114. se.refresher = sst_refresher_uac;
  115. p += 13; pos += 13;
  116. }
  117. else if ( tok == MAKE_3BYTES('u','a','s') ) {
  118. se.refresher = sst_refresher_uas;
  119. p += 13; pos += 13;
  120. }
  121. else /* unrecognized refresher-param */ {
  122. LM_ERR(" unrecognized refresher\n" );
  123. return parse_sst_parse_error;
  124. }
  125. }
  126. else /* not "esher=" */ {
  127. /* there are no other se-params
  128. that start with "refr" */
  129. for ( ; pos < len && *p != ';'; ++pos, ++p )
  130. /*skip to ';'*/;
  131. }
  132. break;
  133. default:
  134. /* unrecognized se-param */
  135. for ( ; pos < len && *p != ';'; ++pos, ++p )
  136. /*skip to ';'*/;
  137. break;
  138. } /*switch*/
  139. } /* exist 4 bytes to check */
  140. else /* less than 4 bytes left */ {
  141. /* not enough text left for any of the recognized se-params */
  142. /* no other recognized se-param */
  143. for ( ; pos < len && *p != ';'; ++pos, ++p ) /*skip to ';'*/;
  144. }
  145. }
  146. else /* not ';' */ {
  147. LM_ERR("no semicolon separating se-params\n");
  148. return parse_sst_parse_error;
  149. } /* if ';' */
  150. } /* while */
  151. hf->parsed = malloc_session_expires();
  152. if ( !hf->parsed ) {
  153. LM_ERR(" out of pkg memory\n" );
  154. return parse_sst_out_of_mem;
  155. }
  156. se.hfree = hf_free_session_expires;
  157. *((struct session_expires *)hf->parsed) = se;
  158. return parse_sst_success;
  159. }
  160. enum parse_sst_result
  161. parse_session_expires( struct sip_msg *msg, struct session_expires *se )
  162. {
  163. enum parse_sst_result result;
  164. if ( msg->session_expires ) {
  165. if ( msg->session_expires->parsed == 0
  166. && (result = parse_session_expires_body(msg->session_expires))
  167. != parse_sst_success ) {
  168. return result;
  169. }
  170. if ( se ) {
  171. *se = *((struct session_expires *)msg->session_expires->parsed);
  172. }
  173. return parse_sst_success;
  174. }
  175. else {
  176. return parse_sst_header_not_found;
  177. }
  178. }
  179. enum parse_sst_result
  180. parse_min_se_body( struct hdr_field *hf )
  181. {
  182. int len = hf->body.len;
  183. char *p = hf->body.s;
  184. int pos = 0;
  185. unsigned int interval = 0;
  186. /* skip whitespace */
  187. for ( ; pos < len && is_space(*p); ++pos, ++p )
  188. /*nothing*/;
  189. if ( pos == len )
  190. return parse_sst_no_value;
  191. /* collect a number */
  192. for ( ; pos < len && is_num(*p); ++pos, ++p )
  193. interval = interval*10/*radix*/ + (*p - '0');
  194. /* skip whitespace */
  195. for ( ; pos < len && is_space(*p); ++pos, ++p )
  196. /*nothing*/;
  197. if ( pos != len ) /* shouldn't be any more junk */
  198. return parse_sst_parse_error;
  199. hf->parsed=(void*)(long)interval;
  200. return parse_sst_success;
  201. }
  202. enum parse_sst_result
  203. parse_min_se( struct sip_msg *msg, unsigned int *min_se )
  204. {
  205. enum parse_sst_result result;
  206. if ( msg->min_se ) {
  207. if ( msg->min_se->parsed == 0
  208. && (result = parse_min_se_body(msg->min_se))
  209. != parse_sst_success ) {
  210. return result;
  211. }
  212. if ( min_se ) {
  213. *min_se = (unsigned int)(long)msg->min_se->parsed;
  214. }
  215. return parse_sst_success;
  216. }
  217. else {
  218. return parse_sst_header_not_found;
  219. }
  220. }