8756db651846c0f367f27cb3dded249220b06213
[sip-router] / modules / tm / lw_parser.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2007 iptelorg GmbH
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser 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  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * 2007-05-28   lightweight parser implemented for build_local_reparse()
28  *              function. Basically copy-pasted from the core parser (Miklos)
29  */
30
31 #include "../../parser/keys.h"
32 #include "../../parser/hf.h"
33 #include "../../parser/parser_f.h"
34 #include "lw_parser.h"
35
36 /* macros from the core parser */
37 #define LOWER_BYTE(b) ((b) | 0x20)
38 #define LOWER_DWORD(d) ((d) | 0x20202020)
39
40 #define READ(val) \
41 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
42
43 /*
44  * lightweight header field name parser
45  * used by build_local_reparse() function in order to construct ACK or CANCEL request
46  * from the INVITE buffer
47  * this parser supports only the header fields which are needed by build_local_reparse()
48  */
49 char *lw_get_hf_name(char *begin, char *end,
50                         enum _hdr_types_t *type)
51 {
52
53         char            *p;
54         unsigned int    val;
55
56         if (end - begin < 4) {
57                 *type = HDR_ERROR_T;
58                 return begin;
59         }
60
61         p = begin;
62         val = LOWER_DWORD(READ(p));
63
64         switch(val) {
65
66         case _cseq_:    /* Cseq */
67                 *type = HDR_CSEQ_T;
68                 p += 4;
69                 break;
70
71         case _via1_:    /* Via */
72         case _via2_:
73                 *type = HDR_VIA_T;
74                 p += 3;
75                 break;
76
77         case _from_:    /* From */
78                 *type = HDR_FROM_T;
79                 p += 4;
80                 break;
81
82         case _to12_:    /* To */
83                 *type = HDR_TO_T;
84                 p += 2;
85                 break;
86
87         case _requ_:    /* Require */
88                 p += 4;
89                 val = LOWER_DWORD(READ(p));
90
91                 switch(val) {
92
93                 case _ire1_:
94                 case _ire2_:
95                         p += 3;
96                         *type = HDR_REQUIRE_T;
97                         break;
98
99                 default:
100                         p -= 4;
101                         *type = HDR_OTHER_T;
102                         break;
103                 }
104                 break;
105
106         case _prox_:    /* Proxy-Require */
107
108                 if ((LOWER_DWORD(READ(p+4)) == _y_re_)
109                 && (LOWER_DWORD(READ(p+8)) == _quir_)
110                 && (LOWER_BYTE(*(p+12)) == 'e')) {
111
112                         p += 13;
113                         *type = HDR_PROXYREQUIRE_T;
114                         break;
115
116                 } else {
117                         *type = HDR_OTHER_T;
118                         break;
119                 }
120
121         case _cont_:    /* Content-Length */
122
123                 if ((LOWER_DWORD(READ(p+4)) == _ent__)
124                 && (LOWER_DWORD(READ(p+8)) == _leng_)
125                 && (LOWER_BYTE(*(p+12)) == 't')
126                 && (LOWER_BYTE(*(p+13)) == 'h')) {
127
128                         p += 14;
129                         *type = HDR_CONTENTLENGTH_T;
130                         break;
131                 } else {
132                         *type = HDR_OTHER_T;
133                         break;
134                 }
135
136         case _call_:    /* Call-Id */
137
138                 p += 4;
139                 val = LOWER_DWORD(READ(p));
140
141                 switch(val) {
142
143                 case __id1_:
144                 case __id2_:
145                         p += 7;
146                         *type = HDR_CALLID_T;
147                         break;
148
149                 default:
150                         p -= 4;
151                         *type = HDR_OTHER_T;
152                         break;
153                 }
154                 break;
155
156         case _rout_:    /* Route */
157
158                 if (LOWER_BYTE(*(p+4)) == 'e') {
159                         p += 5;
160                         *type = HDR_ROUTE_T;
161                         break;
162                 } else {
163                         *type = HDR_OTHER_T;
164                         break;
165                 }
166
167         case _max__:    /* Max-Forwards */
168
169                 if ((LOWER_DWORD(READ(p+4)) == _forw_)
170                 && (LOWER_DWORD(READ(p+8)) == _ards_)) {
171
172                         p += 12;
173                         *type = HDR_MAXFORWARDS_T;
174                         break;
175                 } else {
176                         *type = HDR_OTHER_T;
177                         break;
178                 }
179
180         default:
181                 /* compact headers */
182                 switch(LOWER_BYTE(*p)) {
183
184                 case 'v':       /* Via */
185                         if ((*(p+1) == ' ') || (*(p+1) == ':')) {
186                                 p++;
187                                 *type = HDR_VIA_T;
188                                 break;
189                         }
190                         *type = HDR_OTHER_T;
191                         break;
192
193                 case 'f':       /* From */
194                         if ((*(p+1) == ' ') || (*(p+1) == ':')) {
195                                 p++;
196                                 *type = HDR_FROM_T;
197                                 break;
198                         }
199                         *type = HDR_OTHER_T;
200                         break;
201
202                 case 't':       /* To */
203                         if (LOWER_BYTE(*(p+1)) == 'o') {
204                                 p += 2;
205                                 *type = HDR_TO_T;
206                                 break;
207                         }
208                         if ((*(p+1) == ' ') || (*(p+1) == ':')) {
209                                 p++;
210                                 *type = HDR_TO_T;
211                                 break;
212                         }
213                         *type = HDR_OTHER_T;
214                         break;
215
216                 case 'l':       /* Content-Length */
217                         if ((*(p+1) == ' ') || (*(p+1) == ':')) {
218                                 p++;
219                                 *type = HDR_CONTENTLENGTH_T;
220                                 break;
221                         }
222                         *type = HDR_OTHER_T;
223                         break;
224
225                 case 'i':       /* Call-Id */
226                         if ((*(p+1) == ' ') || (*(p+1) == ':')) {
227                                 p++;
228                                 *type = HDR_CALLID_T;
229                                 break;
230                         }
231                         *type = HDR_OTHER_T;
232                         break;
233
234                 default:
235                         *type = HDR_OTHER_T;
236                         break;
237                 }
238         }
239
240         return p;
241 }
242
243 /* returns a pointer to the next line */
244 char *lw_next_line(char *buf, char *buf_end)
245 {
246         char    *c;
247
248         c = buf;
249         do {
250                 while ((c < buf_end) && (*c != '\n')) c++;
251                 if (c < buf_end) c++;
252
253         } while ((c < buf_end) &&
254                 ((*c == ' ') || (*c == '\t'))); /* next line begins with whitespace line folding */
255
256         return c;
257 }