PageRenderTime 24ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/parser/parse_hname2.c

https://gitlab.com/oded/kamailio
C | 293 lines | 218 code | 29 blank | 46 comment | 18 complexity | 7cbc837b0c1564d83d5d5d62f4126440 MD5 | raw file
  1. /*
  2. * Fast 32-bit Header Field Name Parser
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  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. */
  23. /** Parser :: Fast 32-bit Header Field Name Parser.
  24. * @file
  25. * @ingroup parser
  26. */
  27. #include "../comp_defs.h"
  28. #include "parse_hname2.h"
  29. #include "keys.h"
  30. #include "../ut.h" /* q_memchr */
  31. #define LOWER_BYTE(b) ((b) | 0x20)
  32. #define LOWER_DWORD(d) ((d) | 0x20202020)
  33. /** Skip all white-chars and return position of the first non-white char.
  34. */
  35. static inline char* skip_ws(char* p, unsigned int size)
  36. {
  37. char* end;
  38. end = p + size;
  39. for(; p < end; p++) {
  40. if ((*p != ' ') && (*p != '\t')) return p;
  41. }
  42. return p;
  43. }
  44. /*! \name
  45. * Parser macros
  46. */
  47. /*@{ */
  48. #include "case_via.h" /* Via */
  49. #include "case_from.h" /* From */
  50. #include "case_to.h" /* To */
  51. #include "case_cseq.h" /* CSeq */
  52. #include "case_call.h" /* Call-ID */
  53. #include "case_cont.h" /* Contact, Content-Type, Content-Length, Content-Purpose,
  54. * Content-Action, Content-Disposition */
  55. #include "case_rout.h" /* Route */
  56. #include "case_max.h" /* Max-Forwards */
  57. #include "case_reco.h" /* Record-Route */
  58. #include "case_auth.h" /* Authorization */
  59. #include "case_expi.h" /* Expires */
  60. #include "case_prox.h" /* Proxy-Authorization, Proxy-Require */
  61. #include "case_allo.h" /* Allow */
  62. #include "case_unsu.h" /* Unsupported */
  63. #include "case_even.h" /* Event */
  64. #include "case_sip.h" /* Sip-If-Match */
  65. #include "case_acce.h" /* Accept, Accept-Language */
  66. #include "case_orga.h" /* Organization */
  67. #include "case_prio.h" /* Priority */
  68. #include "case_subj.h" /* Subject */
  69. #include "case_user.h" /* User-Agent */
  70. #include "case_serv.h" /* Server */
  71. #include "case_supp.h" /* Supported */
  72. #include "case_dive.h" /* Diversion */
  73. #include "case_remo.h" /* Remote-Party-ID */
  74. #include "case_refe.h" /* Refer-To */
  75. #include "case_sess.h" /* Session-Expires */
  76. #include "case_reje.h" /* Reject-Contact */
  77. #include "case_min.h" /* Min-SE */
  78. #include "case_subs.h" /* Subscription-State */
  79. #include "case_requ.h" /* Require */
  80. #include "case_www.h" /* WWW-Authenticate */
  81. #include "case_date.h" /* Date */
  82. #include "case_iden.h" /* Identity, Identity-info */
  83. #include "case_retr.h" /* Retry-After */
  84. #include "case_path.h" /* Path */
  85. #include "case_priv.h"
  86. #include "case_reas.h" /* Reason */
  87. #include "case_p_as.h" /* P-Asserted-Identity */
  88. #include "case_p_pr.h" /* P-Preferred-Identity */
  89. /*@} */
  90. #define SAFE_READ(val, len) \
  91. ((len) == 1 ? READ1(val) : ((len) == 2 ? READ2(val) : ((len) == 3 ? READ3(val) : ((len) > 3 ? READ4(val) : READ0(val)))))
  92. #define READ(val) \
  93. READ4(val)
  94. #define READ4(val) \
  95. (*((val) + 0) + (*((val) + 1) << 8) + (*((val) + 2) << 16) + (*((val) + 3) << 24))
  96. #define READ3(val) \
  97. (*((val) + 0) + (*((val) + 1) << 8) + (*((val) + 2) << 16))
  98. #define READ2(val) \
  99. (*((val) + 0) + (*((val) + 1) << 8))
  100. #define READ1(val) \
  101. (*((val) + 0))
  102. #define READ0(val) \
  103. (0)
  104. #define FIRST_QUATERNIONS \
  105. case _via1_: via1_CASE; \
  106. case _from_: from_CASE; \
  107. case _to12_: to12_CASE; \
  108. case _cseq_: cseq_CASE; \
  109. case _call_: call_CASE; \
  110. case _cont_: cont_CASE; \
  111. case _rout_: rout_CASE; \
  112. case _max__: max_CASE; \
  113. case _reco_: reco_CASE; \
  114. case _via2_: via2_CASE; \
  115. case _auth_: auth_CASE; \
  116. case _supp_: supp_CASE; \
  117. case _expi_: expi_CASE; \
  118. case _prox_: prox_CASE; \
  119. case _allo_: allo_CASE; \
  120. case _unsu_: unsu_CASE; \
  121. case _even_: even_CASE; \
  122. case _sip_ : sip_CASE; \
  123. case _acce_: acce_CASE; \
  124. case _orga_: orga_CASE; \
  125. case _prio_: prio_CASE; \
  126. case _subj_: subj_CASE; \
  127. case _subs_: subs_CASE; \
  128. case _user_: user_CASE; \
  129. case _serv_: serv_CASE; \
  130. case _dive_: dive_CASE; \
  131. case _remo_: remo_CASE; \
  132. case _refe_: refe_CASE; \
  133. case _sess_: sess_CASE; \
  134. case _reje_: reje_CASE; \
  135. case _min__: min_CASE; \
  136. case _requ_: requ_CASE; \
  137. case _www__: www_CASE; \
  138. case _date_: date_CASE; \
  139. case _iden_: iden_CASE; \
  140. case _retr_: retr_CASE; \
  141. case _path_: path_CASE; \
  142. case _priv_: priv_CASE; \
  143. case _reas_: reas_CASE; \
  144. case _p_as_: p_as_CASE; \
  145. case _p_pr_: p_pr_CASE;
  146. #define PARSE_COMPACT(id) \
  147. switch(*(p + 1)) { \
  148. case ' ': \
  149. hdr->type = id; \
  150. p += 2; \
  151. goto dc_end; \
  152. \
  153. case ':': \
  154. hdr->type = id; \
  155. hdr->name.len = 1; \
  156. return (p + 2); \
  157. }
  158. char* parse_hname2(char* const begin, const char* const end, struct hdr_field* const hdr)
  159. {
  160. register char* p;
  161. register unsigned int val;
  162. if ((end - begin) < 4) {
  163. hdr->type = HDR_ERROR_T;
  164. return begin;
  165. }
  166. p = begin;
  167. val = LOWER_DWORD(READ(p));
  168. hdr->name.s = begin;
  169. switch(val) {
  170. FIRST_QUATERNIONS;
  171. default:
  172. switch(LOWER_BYTE(*p)) {
  173. case 't':
  174. switch(LOWER_BYTE(*(p + 1))) {
  175. case 'o':
  176. case ' ':
  177. hdr->type = HDR_TO_T;
  178. p += 2;
  179. goto dc_end;
  180. case ':':
  181. hdr->type = HDR_TO_T;
  182. hdr->name.len = 1;
  183. return (p + 2);
  184. }
  185. break;
  186. case 'v': PARSE_COMPACT(HDR_VIA_T); break;
  187. case 'f': PARSE_COMPACT(HDR_FROM_T); break;
  188. case 'i': PARSE_COMPACT(HDR_CALLID_T); break;
  189. case 'm': PARSE_COMPACT(HDR_CONTACT_T); break;
  190. case 'l': PARSE_COMPACT(HDR_CONTENTLENGTH_T); break;
  191. case 'k': PARSE_COMPACT(HDR_SUPPORTED_T); break;
  192. case 'c': PARSE_COMPACT(HDR_CONTENTTYPE_T); break;
  193. case 'o': PARSE_COMPACT(HDR_EVENT_T); break;
  194. case 'x': PARSE_COMPACT(HDR_SESSIONEXPIRES_T);break;
  195. case 'a': PARSE_COMPACT(HDR_ACCEPTCONTACT_T); break;
  196. case 'u': PARSE_COMPACT(HDR_ALLOWEVENTS_T); break;
  197. case 'e': PARSE_COMPACT(HDR_CONTENTENCODING_T); break;
  198. case 'b': PARSE_COMPACT(HDR_REFERREDBY_T); break;
  199. case 'j': PARSE_COMPACT(HDR_REJECTCONTACT_T); break;
  200. case 'd': PARSE_COMPACT(HDR_REQUESTDISPOSITION_T); break;
  201. case 's': PARSE_COMPACT(HDR_SUBJECT_T); break;
  202. case 'r': PARSE_COMPACT(HDR_REFER_TO_T); break;
  203. case 'y': PARSE_COMPACT(HDR_IDENTITY_T); break;
  204. case 'n': PARSE_COMPACT(HDR_IDENTITY_INFO_T); break;
  205. }
  206. goto other;
  207. }
  208. /* Double colon hasn't been found yet */
  209. dc_end:
  210. p = skip_ws(p, end - p);
  211. if (*p != ':') {
  212. goto other;
  213. } else {
  214. hdr->name.len = p - hdr->name.s;
  215. return (p + 1);
  216. }
  217. /* Unknown header type */
  218. other:
  219. p = q_memchr(p, ':', end - p);
  220. if (!p) { /* No double colon found, error.. */
  221. hdr->type = HDR_ERROR_T;
  222. hdr->name.s = 0;
  223. hdr->name.len = 0;
  224. return 0;
  225. } else {
  226. hdr->type = HDR_OTHER_T;
  227. hdr->name.len = p - hdr->name.s;
  228. /*hdr_update_type(hdr);*/
  229. return (p + 1);
  230. }
  231. }
  232. /**
  233. * parse_hname2_short() - safer version to parse header name stored in short buffers
  234. * - parse_hanem2() reads 4 bytes at once, expecting to walk through a buffer
  235. * that contains more than the header name (e.g., sip msg buf, full header buf
  236. * with name and body)
  237. */
  238. char* parse_hname2_short(char* const begin, const char* const end, struct hdr_field* const hdr)
  239. {
  240. #define HBUF_MAX_SIZE 256
  241. char hbuf[HBUF_MAX_SIZE];
  242. char *p;
  243. if(end-begin>=HBUF_MAX_SIZE-4) {
  244. p = q_memchr(begin, ':', end - begin);
  245. if(p && p-4> begin) {
  246. /* header name termination char found and enough space in buffer after it */
  247. return parse_hname2(begin, end, hdr);
  248. }
  249. /* not enough space */
  250. LM_ERR("not enough space to parse the header name in [%.*s] (%d)\n",
  251. (int)(end-begin), begin, (int)(end-begin));
  252. return NULL;
  253. }
  254. /* pad with whitespace - tipycal char after the ':' of the header name */
  255. memset(hbuf, ' ', HBUF_MAX_SIZE);
  256. memcpy(hbuf, begin, end-begin);
  257. p = parse_hname2(hbuf, hbuf + 4 + (end-begin), hdr);
  258. if(!p) {
  259. LM_ERR("failed to parse the header name in [%.*s] (%d)\n",
  260. (int)(end-begin), begin, (int)(end-begin));
  261. return NULL;
  262. }
  263. return begin + (p-hbuf);
  264. }