2
0

parse_hname2.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /*
  2. * $Id$
  3. *
  4. * Fast 32-bit Header Field Name Parser
  5. *
  6. * Copyright (C) 2001-2003 Fhg Fokus
  7. *
  8. * This file is part of ser, a free SIP server.
  9. *
  10. * ser is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version
  14. *
  15. * For a license to use the ser software under conditions
  16. * other than those described here, or to purchase support for this
  17. * software, please contact iptel.org by e-mail at the following addresses:
  18. * [email protected]
  19. *
  20. * ser is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. */
  29. #include "parse_hname2.h"
  30. #include "keys.h"
  31. #include "../ut.h" /* q_memchr */
  32. #define LOWER_BYTE(b) ((b) | 0x20)
  33. #define LOWER_DWORD(d) ((d) | 0x20202020)
  34. /*
  35. * Skip all whitechars and return position of the first
  36. * non-white char
  37. */
  38. static inline char* skip_ws(char* p, unsigned int size)
  39. {
  40. char* end;
  41. end = p + size;
  42. for(; p < end; p++) {
  43. if ((*p != ' ') && (*p != '\t')) return p;
  44. }
  45. return p;
  46. }
  47. /*
  48. * Parser macros
  49. */
  50. #include "case_via.h" /* Via */
  51. #include "case_from.h" /* From */
  52. #include "case_to.h" /* To */
  53. #include "case_cseq.h" /* CSeq */
  54. #include "case_call.h" /* Call-ID */
  55. #include "case_cont.h" /* Contact, Content-Type, Content-Length */
  56. #include "case_rout.h" /* Route */
  57. #include "case_max.h" /* Max-Forwards */
  58. #include "case_reco.h" /* Record-Route */
  59. #include "case_auth.h" /* Authorization */
  60. #include "case_expi.h" /* Expires */
  61. #include "case_prox.h" /* Proxy-Authorization, Proxy-Require */
  62. #include "case_allo.h" /* Allow */
  63. #include "case_unsu.h" /* Unsupported */
  64. #include "case_requ.h" /* Require */
  65. #include "case_supp.h" /* Supported */
  66. #include "case_www.h" /* WWW-Authenticate */
  67. #include "case_even.h" /* Event */
  68. #define READ(val) \
  69. (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
  70. #define FIRST_QUATERNIONS \
  71. case _via1_: via1_CASE; \
  72. case _from_: from_CASE; \
  73. case _to12_: to12_CASE; \
  74. case _cseq_: cseq_CASE; \
  75. case _call_: call_CASE; \
  76. case _cont_: cont_CASE; \
  77. case _rout_: rout_CASE; \
  78. case _max__: max_CASE; \
  79. case _reco_: reco_CASE; \
  80. case _via2_: via2_CASE; \
  81. case _auth_: auth_CASE; \
  82. case _expi_: expi_CASE; \
  83. case _prox_: prox_CASE; \
  84. case _allo_: allo_CASE; \
  85. case _unsu_: unsu_CASE; \
  86. case _requ_: requ_CASE; \
  87. case _supp_: supp_CASE; \
  88. case _www__: www_CASE; \
  89. case _even_: even_CASE;
  90. #define PARSE_COMPACT(id) \
  91. switch(*(p + 1)) { \
  92. case ' ': \
  93. hdr->type = id; \
  94. p += 2; \
  95. goto dc_end; \
  96. \
  97. case ':': \
  98. hdr->type = id; \
  99. hdr->name.len = 1; \
  100. *(p + 1) = '\0'; \
  101. return (p + 2); \
  102. }
  103. char* parse_hname2(char* begin, char* end, struct hdr_field* hdr)
  104. {
  105. register char* p;
  106. register unsigned int val;
  107. if ((end - begin) < 4) {
  108. hdr->type = HDR_ERROR;
  109. return begin;
  110. }
  111. p = begin;
  112. val = LOWER_DWORD(READ(p));
  113. hdr->name.s = begin;
  114. switch(val) {
  115. FIRST_QUATERNIONS;
  116. default:
  117. switch(LOWER_BYTE(*p)) {
  118. case 't':
  119. switch(LOWER_BYTE(*(p + 1))) {
  120. case 'o':
  121. case ' ':
  122. hdr->type = HDR_TO;
  123. p += 2;
  124. goto dc_end;
  125. case ':':
  126. hdr->type = HDR_TO;
  127. hdr->name.len = 1;
  128. *(p + 1) = '\0';
  129. return (p + 2);
  130. }
  131. break;
  132. case 'v': PARSE_COMPACT(HDR_VIA); break;
  133. case 'f': PARSE_COMPACT(HDR_FROM); break;
  134. case 'i': PARSE_COMPACT(HDR_CALLID); break;
  135. case 'm': PARSE_COMPACT(HDR_CONTACT); break;
  136. case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH); break;
  137. case 'c': PARSE_COMPACT(HDR_CONTENTTYPE); break;
  138. case 'k': PARSE_COMPACT(HDR_SUPPORTED); break;
  139. case 'o': PARSE_COMPACT(HDR_EVENT); break;
  140. }
  141. goto other;
  142. }
  143. /* Double colon hasn't been found yet */
  144. dc_end:
  145. p = skip_ws(p, end - p);
  146. if (*p != ':') {
  147. goto other;
  148. } else {
  149. hdr->name.len = p - hdr->name.s;
  150. *p = '\0';
  151. return (p + 1);
  152. }
  153. /* Unknown header type */
  154. other:
  155. p = q_memchr(p, ':', end - p);
  156. if (!p) { /* No double colon found, error.. */
  157. hdr->type = HDR_ERROR;
  158. hdr->name.s = 0;
  159. hdr->name.len = 0;
  160. return 0;
  161. } else {
  162. hdr->type = HDR_OTHER;
  163. *p = '\0';
  164. hdr->name.len = p - hdr->name.s;
  165. return (p + 1);
  166. }
  167. }