1 /* $Id$ */
2 /*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #include <pjsip/sip_parser.h>
21 #include <pjsip/sip_uri.h>
22 #include <pjsip/sip_msg.h>
23 #include <pjsip/sip_multipart.h>
24 #include <pjsip/sip_auth_parser.h>
25 #include <pjsip/sip_errno.h>
26 #include <pjsip/sip_transport.h> /* rdata structure */
27 #include <pjlib-util/scanner.h>
28 #include <pjlib-util/string.h>
29 #include <pj/except.h>
30 #include <pj/log.h>
31 #include <pj/hash.h>
32 #include <pj/os.h>
33 #include <pj/pool.h>
34 #include <pj/string.h>
35 #include <pj/ctype.h>
36 #include <pj/assert.h>
37 #include <pj/limits.h>
38
39 #define THIS_FILE "sip_parser.c"
40
41 #define ALNUM
42 #define RESERVED ";/?:@&=+$,"
43 #define MARK "-_.!~*'()"
44 #define UNRESERVED ALNUM MARK
45 #define ESCAPED "%"
46 #define USER_UNRESERVED "&=+$,;?/"
47 #define PASS "&=+$,"
48 #define TOKEN "-.!%*_`'~+" /* '=' was removed for parsing
49 * param */
50 #define HOST "_-."
51 #define HEX_DIGIT "abcdefABCDEF"
52 #define PARAM_CHAR "[]/:&+$" UNRESERVED ESCAPED
53 #define HNV_UNRESERVED "[]/?:+$"
54 #define HDR_CHAR HNV_UNRESERVED UNRESERVED ESCAPED
55
56 /* A generic URI can consist of (For a complete BNF see RFC 2396):
57 #?;:@&=+-_.!~*'()%$,/
58 */
59 #define GENERIC_URI_CHARS "#?;:@&=+-_.!~*'()%$,/" "%"
60
61 #define UNREACHED(expr)
62
63 #define IS_NEWLINE(c) ((c)=='\r' || (c)=='\n')
64 #define IS_SPACE(c) ((c)==' ' || (c)=='\t')
65
66 /*
67 * Header parser records.
68 */
69 typedef struct handler_rec
70 {
71 char hname[PJSIP_MAX_HNAME_LEN+1];
72 pj_size_t hname_len;
73 pj_uint32_t hname_hash;
74 pjsip_parse_hdr_func *handler;
75 } handler_rec;
76
77 static handler_rec handler[PJSIP_MAX_HEADER_TYPES];
78 static unsigned handler_count;
79 static int parser_is_initialized;
80
81 /*
82 * URI parser records.
83 */
84 typedef struct uri_parser_rec
85 {
86 pj_str_t scheme;
87 pjsip_parse_uri_func *parse;
88 } uri_parser_rec;
89
90 static uri_parser_rec uri_handler[PJSIP_MAX_URI_TYPES];
91 static unsigned uri_handler_count;
92
93 /*
94 * Global vars (also extern).
95 */
96 int PJSIP_SYN_ERR_EXCEPTION = -1;
97 int PJSIP_EINVAL_ERR_EXCEPTION = -2;
98
99 /* Parser constants */
100 static pjsip_parser_const_t pconst =
101 {
102 { "user", 4}, /* pjsip_USER_STR */
103 { "method", 6}, /* pjsip_METHOD_STR */
104 { "transport", 9}, /* pjsip_TRANSPORT_STR */
105 { "maddr", 5 }, /* pjsip_MADDR_STR */
106 { "lr", 2 }, /* pjsip_LR_STR */
107 { "sip", 3 }, /* pjsip_SIP_STR */
108 { "sips", 4 }, /* pjsip_SIPS_STR */
109 { "tel", 3 }, /* pjsip_TEL_STR */
110 { "branch", 6 }, /* pjsip_BRANCH_STR */
111 { "ttl", 3 }, /* pjsip_TTL_STR */
112 { "received", 8 }, /* pjsip_RECEIVED_STR */
113 { "q", 1 }, /* pjsip_Q_STR */
114 { "expires", 7 }, /* pjsip_EXPIRES_STR */
115 { "tag", 3 }, /* pjsip_TAG_STR */
116 { "rport", 5} /* pjsip_RPORT_STR */
117 };
118
119 /* Character Input Specification buffer. */
120 static pj_cis_buf_t cis_buf;
121
122
123 /*
124 * Forward decl.
125 */
126 static pjsip_msg * int_parse_msg( pjsip_parse_ctx *ctx,
127 pjsip_parser_err_report *err_list);
128 static void int_parse_param( pj_scanner *scanner,
129 pj_pool_t *pool,
130 pj_str_t *pname,
131 pj_str_t *pvalue,
132 unsigned option);
133 static void int_parse_uri_param( pj_scanner *scanner,
134 pj_pool_t *pool,
135 pj_str_t *pname,
136 pj_str_t *pvalue,
137 unsigned option);
138 static void int_parse_hparam( pj_scanner *scanner,
139 pj_pool_t *pool,
140 pj_str_t *hname,
141 pj_str_t *hvalue );
142 static void int_parse_req_line( pj_scanner *scanner,
143 pj_pool_t *pool,
144 pjsip_request_line *req_line);
145 static int int_is_next_user( pj_scanner *scanner);
146 static void int_parse_status_line( pj_scanner *scanner,
147 pjsip_status_line *line);
148 static void int_parse_user_pass( pj_scanner *scanner,
149 pj_pool_t *pool,
150 pj_str_t *user,
151 pj_str_t *pass);
152 static void int_parse_uri_host_port( pj_scanner *scanner,
153 pj_str_t *p_host,
154 int *p_port);
155 static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner,
156 pj_pool_t *pool,
157 unsigned option);
158 static void* int_parse_sip_url( pj_scanner *scanner,
159 pj_pool_t *pool,
160 pj_bool_t parse_params);
161 static pjsip_name_addr *
162 int_parse_name_addr( pj_scanner *scanner,
163 pj_pool_t *pool );
164 static void* int_parse_other_uri(pj_scanner *scanner,
165 pj_pool_t *pool,
166 pj_bool_t parse_params);
167 static void parse_hdr_end( pj_scanner *scanner );
168
169 static pjsip_hdr* parse_hdr_accept( pjsip_parse_ctx *ctx );
170 static pjsip_hdr* parse_hdr_allow( pjsip_parse_ctx *ctx );
171 static pjsip_hdr* parse_hdr_call_id( pjsip_parse_ctx *ctx);
172 static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx);
173 static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx );
174 static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx );
175 static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx );
176 static pjsip_hdr* parse_hdr_expires( pjsip_parse_ctx *ctx );
177 static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx );
178 static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx);
179 static pjsip_hdr* parse_hdr_min_expires( pjsip_parse_ctx *ctx );
180 static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx );
181 static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx );
182 static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx );
183 static pjsip_hdr* parse_hdr_retry_after( pjsip_parse_ctx *ctx );
184 static pjsip_hdr* parse_hdr_supported( pjsip_parse_ctx *ctx );
185 static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx );
186 static pjsip_hdr* parse_hdr_unsupported( pjsip_parse_ctx *ctx );
187 static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx );
188 static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx);
189
190 /* Convert non NULL terminated string to integer. */
pj_strtoul_mindigit(const pj_str_t * str,unsigned mindig)191 static unsigned long pj_strtoul_mindigit(const pj_str_t *str,
192 unsigned mindig)
193 {
194 unsigned long value;
195 unsigned i;
196
197 value = 0;
198 for (i=0; i<(unsigned)str->slen; ++i) {
199 value = value * 10 + (str->ptr[i] - '0');
200 }
201 for (; i<mindig; ++i) {
202 value = value * 10;
203 }
204 return value;
205 }
206
207 /* Case insensitive comparison */
208 #define parser_stricmp(s1, s2) (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2))
209
210 /* Get a token and unescape */
parser_get_and_unescape(pj_scanner * scanner,pj_pool_t * pool,const pj_cis_t * spec,const pj_cis_t * unesc_spec,pj_str_t * token)211 PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool,
212 const pj_cis_t *spec,
213 const pj_cis_t *unesc_spec,
214 pj_str_t *token)
215 {
216 #if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
217 PJ_UNUSED_ARG(pool);
218 PJ_UNUSED_ARG(spec);
219 pj_scan_get_unescape(scanner, unesc_spec, token);
220 #else
221 PJ_UNUSED_ARG(unesc_spec);
222 pj_scan_get(scanner, spec, token);
223 *token = pj_str_unescape(pool, token);
224 #endif
225 }
226
227 /* Syntax error handler for parser. */
on_syntax_error(pj_scanner * scanner)228 static void on_syntax_error(pj_scanner *scanner)
229 {
230 PJ_UNUSED_ARG(scanner);
231 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
232 }
233
234 /* Syntax error handler for parser. */
on_str_parse_error(const pj_str_t * str,int rc)235 static void on_str_parse_error(const pj_str_t *str, int rc)
236 {
237 char *s;
238
239 switch(rc) {
240 case PJ_EINVAL:
241 s = "NULL input string, invalid input string, or NULL return "\
242 "value pointer";
243 break;
244 case PJ_ETOOSMALL:
245 s = "String value was less than the minimum allowed value.";
246 break;
247 case PJ_ETOOBIG:
248 s = "String value was greater than the maximum allowed value.";
249 break;
250 default:
251 s = "Unknown error";
252 }
253
254 if (str) {
255 PJ_LOG(1, (THIS_FILE, "Error parsing '%.*s': %s",
256 (int)str->slen, str->ptr, s));
257 } else {
258 PJ_LOG(1, (THIS_FILE, "Can't parse input string: %s", s));
259 }
260 PJ_THROW(PJSIP_EINVAL_ERR_EXCEPTION);
261 }
262
strtoi_validate(const pj_str_t * str,int min_val,int max_val,int * value)263 static void strtoi_validate(const pj_str_t *str, int min_val,
264 int max_val, int *value)
265 {
266 long retval;
267 pj_status_t status;
268
269 if (!str || !value) {
270 on_str_parse_error(str, PJ_EINVAL);
271 }
272 status = pj_strtol2(str, &retval);
273 if (status != PJ_EINVAL) {
274 if (min_val > retval) {
275 *value = min_val;
276 status = PJ_ETOOSMALL;
277 } else if (retval > max_val) {
278 *value = max_val;
279 status = PJ_ETOOBIG;
280 } else
281 *value = (int)retval;
282 }
283
284 if (status != PJ_SUCCESS)
285 on_str_parse_error(str, status);
286 }
287
288 /* Get parser constants. */
pjsip_parser_const(void)289 PJ_DEF(const pjsip_parser_const_t*) pjsip_parser_const(void)
290 {
291 return &pconst;
292 }
293
294 /* Concatenate unrecognized params into single string. */
pjsip_concat_param_imp(pj_str_t * param,pj_pool_t * pool,const pj_str_t * pname,const pj_str_t * pvalue,int sepchar)295 PJ_DEF(void) pjsip_concat_param_imp(pj_str_t *param, pj_pool_t *pool,
296 const pj_str_t *pname,
297 const pj_str_t *pvalue,
298 int sepchar)
299 {
300 char *new_param, *p;
301 pj_size_t len;
302
303 len = param->slen + pname->slen + pvalue->slen + 3;
304 p = new_param = (char*) pj_pool_alloc(pool, len);
305
306 if (param->slen) {
307 pj_size_t old_len = param->slen;
308 pj_memcpy(p, param->ptr, old_len);
309 p += old_len;
310 }
311 *p++ = (char)sepchar;
312 pj_memcpy(p, pname->ptr, pname->slen);
313 p += pname->slen;
314
315 if (pvalue->slen) {
316 *p++ = '=';
317 pj_memcpy(p, pvalue->ptr, pvalue->slen);
318 p += pvalue->slen;
319 }
320
321 *p = '\0';
322
323 param->ptr = new_param;
324 param->slen = p - new_param;
325 }
326
327 /* Initialize static properties of the parser. */
init_parser()328 static pj_status_t init_parser()
329 {
330 pj_status_t status;
331
332 /*
333 * Syntax error exception number.
334 */
335 pj_assert (PJSIP_SYN_ERR_EXCEPTION == -1);
336 status = pj_exception_id_alloc("PJSIP syntax error",
337 &PJSIP_SYN_ERR_EXCEPTION);
338 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
339
340 /*
341 * Invalid value exception.
342 */
343 pj_assert (PJSIP_EINVAL_ERR_EXCEPTION == -2);
344 status = pj_exception_id_alloc("PJSIP invalid value error",
345 &PJSIP_EINVAL_ERR_EXCEPTION);
346 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
347
348 /*
349 * Init character input spec (cis)
350 */
351
352 pj_cis_buf_init(&cis_buf);
353
354 status = pj_cis_init(&cis_buf, &pconst.pjsip_DIGIT_SPEC);
355 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
356 pj_cis_add_num(&pconst.pjsip_DIGIT_SPEC);
357
358 status = pj_cis_init(&cis_buf, &pconst.pjsip_ALPHA_SPEC);
359 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
360 pj_cis_add_alpha( &pconst.pjsip_ALPHA_SPEC );
361
362 status = pj_cis_init(&cis_buf, &pconst.pjsip_ALNUM_SPEC);
363 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
364 pj_cis_add_alpha( &pconst.pjsip_ALNUM_SPEC );
365 pj_cis_add_num( &pconst.pjsip_ALNUM_SPEC );
366
367 status = pj_cis_init(&cis_buf, &pconst.pjsip_NOT_NEWLINE);
368 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
369 pj_cis_add_str(&pconst.pjsip_NOT_NEWLINE, "\r\n");
370 pj_cis_invert(&pconst.pjsip_NOT_NEWLINE);
371
372 status = pj_cis_init(&cis_buf, &pconst.pjsip_NOT_COMMA_OR_NEWLINE);
373 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
374 pj_cis_add_str( &pconst.pjsip_NOT_COMMA_OR_NEWLINE, ",\r\n");
375 pj_cis_invert(&pconst.pjsip_NOT_COMMA_OR_NEWLINE);
376
377 status = pj_cis_dup(&pconst.pjsip_TOKEN_SPEC, &pconst.pjsip_ALNUM_SPEC);
378 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
379 pj_cis_add_str( &pconst.pjsip_TOKEN_SPEC, TOKEN);
380
381 status = pj_cis_dup(&pconst.pjsip_TOKEN_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC);
382 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
383 pj_cis_del_str(&pconst.pjsip_TOKEN_SPEC_ESC, "%");
384
385 status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC, &pconst.pjsip_TOKEN_SPEC);
386 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
387 pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC, "[:]");
388
389 status = pj_cis_dup(&pconst.pjsip_VIA_PARAM_SPEC_ESC, &pconst.pjsip_TOKEN_SPEC_ESC);
390 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
391 pj_cis_add_str(&pconst.pjsip_VIA_PARAM_SPEC_ESC, "[:]");
392
393 status = pj_cis_dup(&pconst.pjsip_HOST_SPEC, &pconst.pjsip_ALNUM_SPEC);
394 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
395 pj_cis_add_str( &pconst.pjsip_HOST_SPEC, HOST);
396
397 status = pj_cis_dup(&pconst.pjsip_HEX_SPEC, &pconst.pjsip_DIGIT_SPEC);
398 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
399 pj_cis_add_str( &pconst.pjsip_HEX_SPEC, HEX_DIGIT);
400
401 status = pj_cis_dup(&pconst.pjsip_PARAM_CHAR_SPEC, &pconst.pjsip_ALNUM_SPEC);
402 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
403 pj_cis_add_str(&pconst.pjsip_PARAM_CHAR_SPEC, PARAM_CHAR);
404
405 status = pj_cis_dup(&pconst.pjsip_PARAM_CHAR_SPEC_ESC, &pconst.pjsip_PARAM_CHAR_SPEC);
406 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
407 pj_cis_del_str(&pconst.pjsip_PARAM_CHAR_SPEC_ESC, ESCAPED);
408
409 status = pj_cis_dup(&pconst.pjsip_HDR_CHAR_SPEC, &pconst.pjsip_ALNUM_SPEC);
410 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
411 pj_cis_add_str(&pconst.pjsip_HDR_CHAR_SPEC, HDR_CHAR);
412
413 status = pj_cis_dup(&pconst.pjsip_HDR_CHAR_SPEC_ESC, &pconst.pjsip_HDR_CHAR_SPEC);
414 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
415 pj_cis_del_str(&pconst.pjsip_HDR_CHAR_SPEC_ESC, ESCAPED);
416
417 status = pj_cis_dup(&pconst.pjsip_USER_SPEC, &pconst.pjsip_ALNUM_SPEC);
418 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
419 pj_cis_add_str( &pconst.pjsip_USER_SPEC, UNRESERVED ESCAPED USER_UNRESERVED );
420
421 status = pj_cis_dup(&pconst.pjsip_USER_SPEC_ESC, &pconst.pjsip_USER_SPEC);
422 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
423 pj_cis_del_str( &pconst.pjsip_USER_SPEC_ESC, ESCAPED);
424
425 status = pj_cis_dup(&pconst.pjsip_USER_SPEC_LENIENT, &pconst.pjsip_USER_SPEC);
426 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
427 pj_cis_add_str(&pconst.pjsip_USER_SPEC_LENIENT, "#");
428
429 status = pj_cis_dup(&pconst.pjsip_USER_SPEC_LENIENT_ESC, &pconst.pjsip_USER_SPEC_ESC);
430 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
431 pj_cis_add_str(&pconst.pjsip_USER_SPEC_LENIENT_ESC, "#");
432
433 status = pj_cis_dup(&pconst.pjsip_PASSWD_SPEC, &pconst.pjsip_ALNUM_SPEC);
434 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
435 pj_cis_add_str( &pconst.pjsip_PASSWD_SPEC, UNRESERVED ESCAPED PASS);
436
437 status = pj_cis_dup(&pconst.pjsip_PASSWD_SPEC_ESC, &pconst.pjsip_PASSWD_SPEC);
438 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
439 pj_cis_del_str( &pconst.pjsip_PASSWD_SPEC_ESC, ESCAPED);
440
441 status = pj_cis_init(&cis_buf, &pconst.pjsip_PROBE_USER_HOST_SPEC);
442 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
443 pj_cis_add_str( &pconst.pjsip_PROBE_USER_HOST_SPEC, "@ \n>");
444 pj_cis_invert( &pconst.pjsip_PROBE_USER_HOST_SPEC );
445
446 status = pj_cis_init(&cis_buf, &pconst.pjsip_DISPLAY_SPEC);
447 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
448 pj_cis_add_str( &pconst.pjsip_DISPLAY_SPEC, ":\r\n<");
449 pj_cis_invert(&pconst.pjsip_DISPLAY_SPEC);
450
451 status = pj_cis_dup(&pconst.pjsip_OTHER_URI_CONTENT, &pconst.pjsip_ALNUM_SPEC);
452 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
453 pj_cis_add_str( &pconst.pjsip_OTHER_URI_CONTENT, GENERIC_URI_CHARS);
454
455 /*
456 * Register URI parsers.
457 */
458
459 status = pjsip_register_uri_parser("sip", &int_parse_sip_url);
460 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
461
462 status = pjsip_register_uri_parser("sips", &int_parse_sip_url);
463 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
464
465 /*
466 * Register header parsers.
467 */
468
469 status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
470 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
471
472 status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);
473 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
474
475 status = pjsip_register_hdr_parser( "Call-ID", "i", &parse_hdr_call_id);
476 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
477
478 status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);
479 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
480
481 status = pjsip_register_hdr_parser( "Content-Length", "l",
482 &parse_hdr_content_len);
483 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
484
485 status = pjsip_register_hdr_parser( "Content-Type", "c",
486 &parse_hdr_content_type);
487 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
488
489 status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);
490 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
491
492 status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);
493 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
494
495 status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);
496 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
497
498 status = pjsip_register_hdr_parser( "Max-Forwards", NULL,
499 &parse_hdr_max_forwards);
500 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
501
502 status = pjsip_register_hdr_parser( "Min-Expires", NULL,
503 &parse_hdr_min_expires);
504 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
505
506 status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);
507 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
508
509 status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);
510 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
511
512 status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);
513 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
514
515 status = pjsip_register_hdr_parser( "Retry-After", NULL,
516 &parse_hdr_retry_after);
517 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
518
519 status = pjsip_register_hdr_parser( "Supported", "k",
520 &parse_hdr_supported);
521 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
522
523 status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);
524 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
525
526 status = pjsip_register_hdr_parser( "Unsupported", NULL,
527 &parse_hdr_unsupported);
528 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
529
530 status = pjsip_register_hdr_parser( "Via", "v", &parse_hdr_via);
531 PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
532
533 /*
534 * Register auth parser.
535 */
536
537 status = pjsip_auth_init_parser();
538
539 return status;
540 }
541
init_sip_parser(void)542 void init_sip_parser(void)
543 {
544 pj_enter_critical_section();
545 if (++parser_is_initialized == 1) {
546 init_parser();
547 }
548 pj_leave_critical_section();
549 }
550
deinit_sip_parser(void)551 void deinit_sip_parser(void)
552 {
553 pj_enter_critical_section();
554 if (--parser_is_initialized == 0) {
555 /* Clear header handlers */
556 pj_bzero(handler, sizeof(handler));
557 handler_count = 0;
558
559 /* Clear URI handlers */
560 pj_bzero(uri_handler, sizeof(uri_handler));
561 uri_handler_count = 0;
562
563 /* Deregister exception ID */
564 pj_exception_id_free(PJSIP_SYN_ERR_EXCEPTION);
565 PJSIP_SYN_ERR_EXCEPTION = -1;
566
567 pj_exception_id_free(PJSIP_EINVAL_ERR_EXCEPTION);
568 PJSIP_EINVAL_ERR_EXCEPTION = -2;
569 }
570 pj_leave_critical_section();
571 }
572
573 /* Compare the handler record with header name, and return:
574 * - 0 if handler match.
575 * - <0 if handler is 'less' than the header name.
576 * - >0 if handler is 'greater' than header name.
577 */
compare_handler(const handler_rec * r1,const char * name,pj_size_t name_len,pj_uint32_t hash)578 PJ_INLINE(int) compare_handler( const handler_rec *r1,
579 const char *name,
580 pj_size_t name_len,
581 pj_uint32_t hash )
582 {
583 PJ_UNUSED_ARG(name_len);
584
585 /* Compare hashed value. */
586 if (r1->hname_hash < hash)
587 return -1;
588 if (r1->hname_hash > hash)
589 return 1;
590
591 /* Compare length. */
592 /*
593 if (r1->hname_len < name_len)
594 return -1;
595 if (r1->hname_len > name_len)
596 return 1;
597 */
598
599 /* Equal length and equal hash. compare the strings. */
600 return pj_memcmp(r1->hname, name, name_len);
601 }
602
603 /* Register one handler for one header name. */
int_register_parser(const char * name,pjsip_parse_hdr_func * fptr)604 static pj_status_t int_register_parser( const char *name,
605 pjsip_parse_hdr_func *fptr )
606 {
607 unsigned pos;
608 handler_rec rec;
609
610 if (handler_count >= PJ_ARRAY_SIZE(handler)) {
611 pj_assert(!"Too many handlers!");
612 return PJ_ETOOMANY;
613 }
614
615 /* Initialize temporary handler. */
616 rec.handler = fptr;
617 rec.hname_len = strlen(name);
618 if (rec.hname_len >= sizeof(rec.hname)) {
619 pj_assert(!"Header name is too long!");
620 return PJ_ENAMETOOLONG;
621 }
622 /* Copy name. */
623 pj_memcpy(rec.hname, name, rec.hname_len);
624 rec.hname[rec.hname_len] = '\0';
625
626 /* Calculate hash value. */
627 rec.hname_hash = pj_hash_calc(0, rec.hname, (unsigned)rec.hname_len);
628
629 /* Get the pos to insert the new handler. */
630 for (pos=0; pos < handler_count; ++pos) {
631 int d;
632 d = compare_handler(&handler[pos], rec.hname, rec.hname_len,
633 rec.hname_hash);
634 if (d == 0) {
635 pj_assert(0);
636 return PJ_EEXISTS;
637 }
638 if (d > 0) {
639 break;
640 }
641 }
642
643 /* Shift handlers. */
644 if (pos != handler_count) {
645 pj_memmove( &handler[pos+1], &handler[pos],
646 (handler_count-pos)*sizeof(handler_rec));
647 }
648 /* Add new handler. */
649 pj_memcpy( &handler[pos], &rec, sizeof(handler_rec));
650 ++handler_count;
651
652 return PJ_SUCCESS;
653 }
654
655 /* Register parser handler. If both header name and short name are valid,
656 * then two instances of handler will be registered.
657 */
pjsip_register_hdr_parser(const char * hname,const char * hshortname,pjsip_parse_hdr_func * fptr)658 PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,
659 const char *hshortname,
660 pjsip_parse_hdr_func *fptr)
661 {
662 unsigned i;
663 pj_size_t len;
664 char hname_lcase[PJSIP_MAX_HNAME_LEN+1];
665 pj_status_t status;
666
667 /* Check that name is not too long */
668 len = pj_ansi_strlen(hname);
669 if (len > PJSIP_MAX_HNAME_LEN) {
670 pj_assert(!"Header name is too long!");
671 return PJ_ENAMETOOLONG;
672 }
673
674 /* Register the normal Mixed-Case name */
675 status = int_register_parser(hname, fptr);
676 if (status != PJ_SUCCESS) {
677 return status;
678 }
679
680 /* Get the lower-case name */
681 for (i=0; i<len; ++i) {
682 hname_lcase[i] = (char)pj_tolower(hname[i]);
683 }
684 hname_lcase[len] = '\0';
685
686 /* Register the lower-case version of the name */
687 status = int_register_parser(hname_lcase, fptr);
688 if (status != PJ_SUCCESS) {
689 return status;
690 }
691
692
693 /* Register the shortname version of the name */
694 if (hshortname) {
695 status = int_register_parser(hshortname, fptr);
696 if (status != PJ_SUCCESS)
697 return status;
698 }
699 return PJ_SUCCESS;
700 }
701
702
703 /* Find handler to parse the header name. */
find_handler_imp(pj_uint32_t hash,const pj_str_t * hname)704 static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t hash,
705 const pj_str_t *hname)
706 {
707 handler_rec *first;
708 int comp;
709 unsigned n;
710
711 /* Binary search for the handler. */
712 comp = -1;
713 first = &handler[0];
714 n = handler_count;
715 for (; n > 0; ) {
716 unsigned half = n / 2;
717 handler_rec *mid = first + half;
718
719 comp = compare_handler(mid, hname->ptr, hname->slen, hash);
720 if (comp < 0) {
721 first = ++mid;
722 n -= half + 1;
723 } else if (comp==0) {
724 first = mid;
725 break;
726 } else {
727 n = half;
728 }
729 }
730
731 return comp==0 ? first->handler : NULL;
732 }
733
734
735 /* Find handler to parse the header name. */
find_handler(const pj_str_t * hname)736 static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname)
737 {
738 pj_uint32_t hash;
739 char hname_copy[PJSIP_MAX_HNAME_LEN];
740 pj_str_t tmp;
741 pjsip_parse_hdr_func *func;
742
743 if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
744 /* Guaranteed not to be able to find handler. */
745 return NULL;
746 }
747
748 /* First, common case, try to find handler with exact name */
749 hash = pj_hash_calc(0, hname->ptr, (unsigned)hname->slen);
750 func = find_handler_imp(hash, hname);
751 if (func)
752 return func;
753
754
755 /* If not found, try converting the header name to lowercase and
756 * search again.
757 */
758 hash = pj_hash_calc_tolower(0, hname_copy, hname);
759 tmp.ptr = hname_copy;
760 tmp.slen = hname->slen;
761 return find_handler_imp(hash, &tmp);
762 }
763
764
765 /* Find URI handler. */
find_uri_handler(const pj_str_t * scheme)766 static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme)
767 {
768 unsigned i;
769 for (i=0; i<uri_handler_count; ++i) {
770 if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0)
771 return uri_handler[i].parse;
772 }
773 return &int_parse_other_uri;
774 }
775
776 /* Register URI parser. */
pjsip_register_uri_parser(char * scheme,pjsip_parse_uri_func * func)777 PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme,
778 pjsip_parse_uri_func *func)
779 {
780 if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler))
781 return PJ_ETOOMANY;
782
783 uri_handler[uri_handler_count].scheme = pj_str((char*)scheme);
784 uri_handler[uri_handler_count].parse = func;
785 ++uri_handler_count;
786
787 return PJ_SUCCESS;
788 }
789
790 /* Public function to parse SIP message. */
pjsip_parse_msg(pj_pool_t * pool,char * buf,pj_size_t size,pjsip_parser_err_report * err_list)791 PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,
792 char *buf, pj_size_t size,
793 pjsip_parser_err_report *err_list)
794 {
795 pjsip_msg *msg = NULL;
796 pj_scanner scanner;
797 pjsip_parse_ctx context;
798
799 pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
800 &on_syntax_error);
801
802 context.scanner = &scanner;
803 context.pool = pool;
804 context.rdata = NULL;
805
806 msg = int_parse_msg(&context, err_list);
807
808 pj_scan_fini(&scanner);
809 return msg;
810 }
811
812 /* Public function to parse as rdata.*/
pjsip_parse_rdata(char * buf,pj_size_t size,pjsip_rx_data * rdata)813 PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
814 pjsip_rx_data *rdata )
815 {
816 pj_scanner scanner;
817 pjsip_parse_ctx context;
818
819 pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
820 &on_syntax_error);
821
822 context.scanner = &scanner;
823 context.pool = rdata->tp_info.pool;
824 context.rdata = rdata;
825
826 rdata->msg_info.msg = int_parse_msg(&context, &rdata->msg_info.parse_err);
827
828 pj_scan_fini(&scanner);
829 return rdata->msg_info.msg;
830 }
831
832 /* Determine if a message has been received. */
pjsip_find_msg(const char * buf,pj_size_t size,pj_bool_t is_datagram,pj_size_t * msg_size)833 PJ_DEF(pj_status_t) pjsip_find_msg( const char *buf, pj_size_t size,
834 pj_bool_t is_datagram, pj_size_t *msg_size)
835 {
836 #if PJ_HAS_TCP
837 const char *volatile hdr_end;
838 const char *volatile body_start;
839 const char *pos;
840 const char *volatile line;
841 int content_length = -1;
842 pj_str_t cur_msg;
843 pj_status_t status = PJSIP_EMISSINGHDR;
844 const pj_str_t end_hdr = { "\n\r\n", 3};
845
846 *msg_size = size;
847
848 /* For datagram, the whole datagram IS the message. */
849 if (is_datagram) {
850 return PJ_SUCCESS;
851 }
852
853
854 /* Find the end of header area by finding an empty line.
855 * Don't use plain strstr() since we want to be able to handle
856 * NULL character in the message
857 */
858 cur_msg.ptr = (char*)buf; cur_msg.slen = size;
859 pos = pj_strstr(&cur_msg, &end_hdr);
860 if (pos == NULL) {
861 return PJSIP_EPARTIALMSG;
862 }
863
864 hdr_end = pos+1;
865 body_start = pos+3;
866
867 /* Find "Content-Length" header the hard way. */
868 line = pj_strchr(&cur_msg, '\n');
869 while (line && line < hdr_end) {
870 ++line;
871 if ( ((*line=='C' || *line=='c') &&
872 strnicmp_alnum(line, "Content-Length", 14) == 0) ||
873 ((*line=='l' || *line=='L') &&
874 (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
875 {
876 /* Try to parse the header. */
877 pj_scanner scanner;
878 PJ_USE_EXCEPTION;
879
880 /* The buffer passed to the scanner is not NULL terminated,
881 * but should be safe. See ticket #2063.
882 */
883 pj_scan_init(&scanner, (char*)line, hdr_end-line,
884 PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
885
886 PJ_TRY {
887 pj_str_t str_clen;
888
889 /* Get "Content-Length" or "L" name */
890 if (*line=='C' || *line=='c')
891 pj_scan_advance_n(&scanner, 14, PJ_TRUE);
892 else if (*line=='l' || *line=='L')
893 pj_scan_advance_n(&scanner, 1, PJ_TRUE);
894
895 /* Get colon */
896 if (pj_scan_get_char(&scanner) != ':') {
897 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
898 }
899
900 /* Get number */
901 pj_scan_get(&scanner, &pconst.pjsip_DIGIT_SPEC, &str_clen);
902
903 /* Get newline. */
904 pj_scan_get_newline(&scanner);
905
906 /* Found a valid Content-Length header. */
907 strtoi_validate(&str_clen, PJSIP_MIN_CONTENT_LENGTH,
908 PJSIP_MAX_CONTENT_LENGTH, &content_length);
909 }
910 PJ_CATCH_ANY {
911 int eid = PJ_GET_EXCEPTION();
912 if (eid == PJSIP_SYN_ERR_EXCEPTION) {
913 status = PJSIP_EMISSINGHDR;
914 } else if (eid == PJSIP_EINVAL_ERR_EXCEPTION) {
915 status = PJSIP_EINVALIDHDR;
916 }
917 content_length = -1;
918 }
919 PJ_END
920
921 pj_scan_fini(&scanner);
922 }
923
924 /* Found valid Content-Length? */
925 if (content_length != -1)
926 break;
927
928 /* Go to next line. */
929 cur_msg.slen -= (line - cur_msg.ptr);
930 cur_msg.ptr = (char*)line;
931 line = pj_strchr(&cur_msg, '\n');
932 }
933
934 /* Found Content-Length? */
935 if (content_length == -1) {
936 return status;
937 }
938
939 /* Enough packet received? */
940 *msg_size = (body_start - buf) + content_length;
941 return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;
942 #else
943 PJ_UNUSED_ARG(buf);
944 PJ_UNUSED_ARG(is_datagram);
945 *msg_size = size;
946 return PJ_SUCCESS;
947 #endif
948 }
949
950 /* Public function to parse URI */
pjsip_parse_uri(pj_pool_t * pool,char * buf,pj_size_t size,unsigned option)951 PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
952 char *buf, pj_size_t size,
953 unsigned option)
954 {
955 pj_scanner scanner;
956 pjsip_uri *uri = NULL;
957 PJ_USE_EXCEPTION;
958
959 pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
960
961
962 PJ_TRY {
963 uri = int_parse_uri_or_name_addr(&scanner, pool, option);
964 }
965 PJ_CATCH_ANY {
966 uri = NULL;
967 }
968 PJ_END;
969
970 /* Must have exhausted all inputs. */
971 if (pj_scan_is_eof(&scanner) || IS_NEWLINE(*scanner.curptr)) {
972 /* Success. */
973 pj_scan_fini(&scanner);
974 return uri;
975 }
976
977 /* Still have some characters unparsed. */
978 pj_scan_fini(&scanner);
979 return NULL;
980 }
981
982 /* SIP version */
parse_sip_version(pj_scanner * scanner)983 static void parse_sip_version(pj_scanner *scanner)
984 {
985 pj_str_t SIP = { "SIP", 3 };
986 pj_str_t V2 = { "2.0", 3 };
987 pj_str_t sip, version;
988
989 pj_scan_get( scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
990 if (pj_scan_get_char(scanner) != '/')
991 on_syntax_error(scanner);
992 pj_scan_get_n( scanner, 3, &version);
993 if (pj_stricmp(&sip, &SIP) || pj_stricmp(&version, &V2))
994 on_syntax_error(scanner);
995 }
996
is_next_sip_version(pj_scanner * scanner)997 static pj_bool_t is_next_sip_version(pj_scanner *scanner)
998 {
999 pj_str_t SIP = { "SIP", 3 };
1000 pj_str_t sip;
1001 int c;
1002
1003 c = pj_scan_peek(scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
1004 /* return TRUE if it is "SIP" followed by "/" or space.
1005 * we include space since the "/" may be separated by space,
1006 * although this would mean it would return TRUE if it is a
1007 * request and the method is "SIP"!
1008 */
1009 return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0;
1010 }
1011
1012 /* Internal function to parse SIP message */
int_parse_msg(pjsip_parse_ctx * ctx,pjsip_parser_err_report * err_list)1013 static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
1014 pjsip_parser_err_report *err_list)
1015 {
1016 /* These variables require "volatile" so their values get
1017 * preserved when re-entering the PJ_TRY block after an error.
1018 */
1019 volatile pj_bool_t parsing_headers;
1020 pjsip_msg *volatile msg = NULL;
1021 pjsip_ctype_hdr *volatile ctype_hdr = NULL;
1022
1023 pj_str_t hname;
1024 pj_scanner *scanner = ctx->scanner;
1025 pj_pool_t *pool = ctx->pool;
1026 PJ_USE_EXCEPTION;
1027
1028 parsing_headers = PJ_FALSE;
1029
1030 retry_parse:
1031 PJ_TRY
1032 {
1033 if (parsing_headers)
1034 goto parse_headers;
1035
1036 /* Skip leading newlines. */
1037 while (IS_NEWLINE(*scanner->curptr)) {
1038 pj_scan_get_newline(scanner);
1039 }
1040
1041 /* Check if we still have valid packet.
1042 * Sometimes endpoints just send blank (CRLF) packets just to keep
1043 * NAT bindings open.
1044 */
1045 if (pj_scan_is_eof(scanner))
1046 return NULL;
1047
1048 /* Parse request or status line */
1049 if (is_next_sip_version(scanner)) {
1050 msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
1051 int_parse_status_line( scanner, &msg->line.status );
1052 } else {
1053 msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
1054 int_parse_req_line(scanner, pool, &msg->line.req );
1055 }
1056
1057 parsing_headers = PJ_TRUE;
1058
1059 parse_headers:
1060 /* Parse headers. */
1061 do {
1062 pjsip_parse_hdr_func * func;
1063 pjsip_hdr *hdr = NULL;
1064
1065 /* Init hname just in case parsing fails.
1066 * Ref: PROTOS #2412
1067 */
1068 hname.slen = 0;
1069
1070 /* Get hname. */
1071 pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
1072 if (pj_scan_get_char( scanner ) != ':') {
1073 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1074 }
1075
1076 /* Find handler. */
1077 func = find_handler(&hname);
1078
1079 /* Call the handler if found.
1080 * If no handler is found, then treat the header as generic
1081 * hname/hvalue pair.
1082 */
1083 if (func) {
1084 hdr = (*func)(ctx);
1085
1086 /* Note:
1087 * hdr MAY BE NULL, if parsing does not yield a new header
1088 * instance, e.g. the values have been added to existing
1089 * header. See http://trac.pjsip.org/repos/ticket/940
1090 */
1091
1092 /* Check if we've just parsed a Content-Type header.
1093 * We will check for a message body if we've got Content-Type
1094 * header.
1095 */
1096 if (hdr && hdr->type == PJSIP_H_CONTENT_TYPE) {
1097 ctype_hdr = (pjsip_ctype_hdr*)hdr;
1098 }
1099
1100 } else {
1101 hdr = parse_hdr_generic_string(ctx);
1102 hdr->name = hdr->sname = hname;
1103 }
1104
1105 /* Single parse of header line can produce multiple headers.
1106 * For example, if one Contact: header contains Contact list
1107 * separated by comma, then these Contacts will be split into
1108 * different Contact headers.
1109 * So here we must insert list instead of just insert one header.
1110 */
1111 if (hdr)
1112 pj_list_insert_nodes_before(&msg->hdr, hdr);
1113
1114 /* Parse until EOF or an empty line is found. */
1115 } while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr));
1116
1117 parsing_headers = PJ_FALSE;
1118
1119 /* If empty line is found, eat it. */
1120 if (!pj_scan_is_eof(scanner)) {
1121 if (IS_NEWLINE(*scanner->curptr)) {
1122 pj_scan_get_newline(scanner);
1123 }
1124 }
1125
1126 /* If we have Content-Type header, treat the rest of the message
1127 * as body.
1128 */
1129 if (ctype_hdr && scanner->curptr!=scanner->end) {
1130 /* New: if Content-Type indicates that this is a multipart
1131 * message body, parse it.
1132 */
1133 const pj_str_t STR_MULTIPART = { "multipart", 9 };
1134 pjsip_msg_body *body;
1135
1136 if (pj_stricmp(&ctype_hdr->media.type, &STR_MULTIPART)==0) {
1137 body = pjsip_multipart_parse(pool, scanner->curptr,
1138 scanner->end - scanner->curptr,
1139 &ctype_hdr->media, 0);
1140 } else {
1141 body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body);
1142 pjsip_media_type_cp(pool, &body->content_type,
1143 &ctype_hdr->media);
1144
1145 body->data = scanner->curptr;
1146 body->len = (unsigned)(scanner->end - scanner->curptr);
1147 body->print_body = &pjsip_print_text_body;
1148 body->clone_data = &pjsip_clone_text_data;
1149 }
1150
1151 msg->body = body;
1152 }
1153 }
1154 PJ_CATCH_ANY
1155 {
1156 /* Exception was thrown during parsing.
1157 * Skip until newline, and parse next header.
1158 */
1159 if (err_list) {
1160 pjsip_parser_err_report *err_info;
1161
1162 err_info = PJ_POOL_ALLOC_T(pool, pjsip_parser_err_report);
1163 err_info->except_code = PJ_GET_EXCEPTION();
1164 err_info->line = scanner->line;
1165 /* Scanner's column is zero based, so add 1 */
1166 err_info->col = pj_scan_get_col(scanner) + 1;
1167 if (parsing_headers)
1168 err_info->hname = hname;
1169 else if (msg && msg->type == PJSIP_REQUEST_MSG)
1170 err_info->hname = pj_str("Request Line");
1171 else if (msg && msg->type == PJSIP_RESPONSE_MSG)
1172 err_info->hname = pj_str("Status Line");
1173 else
1174 err_info->hname.slen = 0;
1175
1176 pj_list_insert_before(err_list, err_info);
1177 }
1178
1179 if (parsing_headers) {
1180 if (!pj_scan_is_eof(scanner)) {
1181 /* Skip until next line.
1182 * Watch for header continuation.
1183 */
1184 do {
1185 pj_scan_skip_line(scanner);
1186 } while (IS_SPACE(*scanner->curptr));
1187 }
1188
1189 /* Restore flag. Flag may be set in int_parse_sip_url() */
1190 scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
1191
1192 /* Continue parse next header, if any. */
1193 if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) {
1194 goto retry_parse;
1195 }
1196 }
1197
1198 msg = NULL;
1199 }
1200 PJ_END;
1201
1202 return msg;
1203 }
1204
1205
1206 /* Parse parameter (pname ["=" pvalue]). */
parse_param_imp(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * pname,pj_str_t * pvalue,const pj_cis_t * spec,const pj_cis_t * esc_spec,unsigned option)1207 static void parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
1208 pj_str_t *pname, pj_str_t *pvalue,
1209 const pj_cis_t *spec, const pj_cis_t *esc_spec,
1210 unsigned option)
1211 {
1212 /* pname */
1213 parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
1214
1215 /* init pvalue */
1216 pvalue->ptr = NULL;
1217 pvalue->slen = 0;
1218
1219 /* pvalue, if any */
1220 if (*scanner->curptr == '=') {
1221 pj_scan_get_char(scanner);
1222 if (!pj_scan_is_eof(scanner)) {
1223 /* pvalue can be a quoted string. */
1224 if (*scanner->curptr == '"') {
1225 pj_scan_get_quote( scanner, '"', '"', pvalue);
1226 if (option & PJSIP_PARSE_REMOVE_QUOTE) {
1227 pvalue->ptr++;
1228 pvalue->slen -= 2;
1229 }
1230 // } else if (*scanner->curptr == '[') {
1231 /* pvalue can be a quoted IPv6; in this case, the
1232 * '[' and ']' quote characters are to be removed
1233 * from the pvalue.
1234 *
1235 * Update: this seems to be unnecessary and may cause
1236 * parsing error for cases such as IPv6 reference with
1237 * port number.
1238 */
1239 // pj_scan_get_char(scanner);
1240 // pj_scan_get_until_ch(scanner, ']', pvalue);
1241 // pj_scan_get_char(scanner);
1242 } else if(pj_cis_match(spec, *scanner->curptr)) {
1243 parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue);
1244 }
1245 }
1246 }
1247 }
1248
1249 /* Parse parameter (pname ["=" pvalue]) using token. */
pjsip_parse_param_imp(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * pname,pj_str_t * pvalue,unsigned option)1250 PJ_DEF(void) pjsip_parse_param_imp(pj_scanner *scanner, pj_pool_t *pool,
1251 pj_str_t *pname, pj_str_t *pvalue,
1252 unsigned option)
1253 {
1254 parse_param_imp(scanner, pool, pname, pvalue, &pconst.pjsip_TOKEN_SPEC,
1255 &pconst.pjsip_TOKEN_SPEC_ESC, option);
1256 }
1257
1258
1259 /* Parse parameter (pname ["=" pvalue]) using paramchar. */
pjsip_parse_uri_param_imp(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * pname,pj_str_t * pvalue,unsigned option)1260 PJ_DEF(void) pjsip_parse_uri_param_imp( pj_scanner *scanner, pj_pool_t *pool,
1261 pj_str_t *pname, pj_str_t *pvalue,
1262 unsigned option)
1263 {
1264 parse_param_imp(scanner,pool, pname, pvalue, &pconst.pjsip_PARAM_CHAR_SPEC,
1265 &pconst.pjsip_PARAM_CHAR_SPEC_ESC, option);
1266 }
1267
1268
1269 /* Parse parameter (";" pname ["=" pvalue]) in SIP header. */
int_parse_param(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * pname,pj_str_t * pvalue,unsigned option)1270 static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool,
1271 pj_str_t *pname, pj_str_t *pvalue,
1272 unsigned option)
1273 {
1274 /* Get ';' character */
1275 pj_scan_get_char(scanner);
1276
1277 /* Get pname and optionally pvalue */
1278 pjsip_parse_param_imp(scanner, pool, pname, pvalue, option);
1279 }
1280
1281 /* Parse parameter (";" pname ["=" pvalue]) in URI. */
int_parse_uri_param(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * pname,pj_str_t * pvalue,unsigned option)1282 static void int_parse_uri_param( pj_scanner *scanner, pj_pool_t *pool,
1283 pj_str_t *pname, pj_str_t *pvalue,
1284 unsigned option)
1285 {
1286 /* Get ';' character */
1287 pj_scan_get_char(scanner);
1288
1289 /* Get pname and optionally pvalue */
1290 pjsip_parse_uri_param_imp(scanner, pool, pname, pvalue,
1291 option);
1292 }
1293
1294
1295 /* Parse header parameter. */
int_parse_hparam(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * hname,pj_str_t * hvalue)1296 static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool,
1297 pj_str_t *hname, pj_str_t *hvalue )
1298 {
1299 /* Get '?' or '&' character. */
1300 pj_scan_get_char(scanner);
1301
1302 /* hname */
1303 parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1304 &pconst.pjsip_HDR_CHAR_SPEC_ESC, hname);
1305
1306 /* Init hvalue */
1307 hvalue->ptr = NULL;
1308 hvalue->slen = 0;
1309
1310 /* pvalue, if any */
1311 if (*scanner->curptr == '=') {
1312 pj_scan_get_char(scanner);
1313 if (!pj_scan_is_eof(scanner) &&
1314 pj_cis_match(&pconst.pjsip_HDR_CHAR_SPEC, *scanner->curptr))
1315 {
1316 parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1317 &pconst.pjsip_HDR_CHAR_SPEC_ESC, hvalue);
1318 }
1319 }
1320 }
1321
1322 /* Parse host part:
1323 * host = hostname / IPv4address / IPv6reference
1324 */
int_parse_host(pj_scanner * scanner,pj_str_t * host)1325 static void int_parse_host(pj_scanner *scanner, pj_str_t *host)
1326 {
1327 if (*scanner->curptr == '[') {
1328 /* Note: the '[' and ']' characters are removed from the host */
1329 pj_scan_get_char(scanner);
1330 pj_scan_get_until_ch(scanner, ']', host);
1331 pj_scan_get_char(scanner);
1332 } else {
1333 pj_scan_get( scanner, &pconst.pjsip_HOST_SPEC, host);
1334 }
1335 }
1336
1337 /* Parse host:port in URI. */
int_parse_uri_host_port(pj_scanner * scanner,pj_str_t * host,int * p_port)1338 static void int_parse_uri_host_port( pj_scanner *scanner,
1339 pj_str_t *host, int *p_port)
1340 {
1341 int_parse_host(scanner, host);
1342
1343 /* RFC3261 section 19.1.2: host don't need to be unescaped */
1344 if (*scanner->curptr == ':') {
1345 pj_str_t port;
1346 pj_scan_get_char(scanner);
1347 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &port);
1348 strtoi_validate(&port, PJSIP_MIN_PORT, PJSIP_MAX_PORT, p_port);
1349 } else {
1350 *p_port = 0;
1351 }
1352 }
1353
1354 /* Determine if the next token in an URI is a user specification. */
int_is_next_user(pj_scanner * scanner)1355 static int int_is_next_user(pj_scanner *scanner)
1356 {
1357 pj_str_t dummy;
1358 int is_user;
1359
1360 /* Find character '@'. If this character exist, then the token
1361 * must be a username.
1362 */
1363 if (pj_scan_peek( scanner, &pconst.pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
1364 is_user = 1;
1365 else
1366 is_user = 0;
1367
1368 return is_user;
1369 }
1370
1371 /* Parse user:pass tokens in an URI. */
int_parse_user_pass(pj_scanner * scanner,pj_pool_t * pool,pj_str_t * user,pj_str_t * pass)1372 static void int_parse_user_pass( pj_scanner *scanner, pj_pool_t *pool,
1373 pj_str_t *user, pj_str_t *pass)
1374 {
1375 parser_get_and_unescape(scanner, pool, &pconst.pjsip_USER_SPEC_LENIENT,
1376 &pconst.pjsip_USER_SPEC_LENIENT_ESC, user);
1377
1378 if ( *scanner->curptr == ':') {
1379 pj_scan_get_char( scanner );
1380 parser_get_and_unescape(scanner, pool, &pconst.pjsip_PASSWD_SPEC,
1381 &pconst.pjsip_PASSWD_SPEC_ESC, pass);
1382 } else {
1383 pass->ptr = NULL;
1384 pass->slen = 0;
1385 }
1386
1387 /* Get the '@' */
1388 pj_scan_get_char( scanner );
1389 }
1390
1391 /* Parse all types of URI. */
int_parse_uri_or_name_addr(pj_scanner * scanner,pj_pool_t * pool,unsigned opt)1392 static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool,
1393 unsigned opt)
1394 {
1395 pjsip_uri *uri;
1396 int is_name_addr = 0;
1397
1398 /* Exhaust any whitespaces. */
1399 pj_scan_skip_whitespace(scanner);
1400
1401 if (*scanner->curptr=='"' || *scanner->curptr=='<') {
1402 uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
1403 is_name_addr = 1;
1404 } else {
1405 pj_str_t scheme;
1406 int next_ch;
1407
1408 next_ch = pj_scan_peek( scanner, &pconst.pjsip_DISPLAY_SPEC, &scheme);
1409
1410 if (next_ch==':') {
1411 pjsip_parse_uri_func *func = find_uri_handler(&scheme);
1412
1413 if (func == NULL) {
1414 /* Unsupported URI scheme */
1415 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1416 }
1417
1418 uri = (pjsip_uri*)
1419 (*func)(scanner, pool,
1420 (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)==0);
1421
1422
1423 } else {
1424 uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
1425 is_name_addr = 1;
1426 }
1427 }
1428
1429 /* Should we return the URI object as name address? */
1430 if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) {
1431 if (is_name_addr == 0) {
1432 pjsip_name_addr *name_addr;
1433
1434 name_addr = pjsip_name_addr_create(pool);
1435 name_addr->uri = uri;
1436
1437 uri = (pjsip_uri*)name_addr;
1438 }
1439 }
1440
1441 return uri;
1442 }
1443
1444 /* Parse URI. */
int_parse_uri(pj_scanner * scanner,pj_pool_t * pool,pj_bool_t parse_params)1445 static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool,
1446 pj_bool_t parse_params)
1447 {
1448 /* Bug:
1449 * This function should not call back int_parse_name_addr() because
1450 * it is called by that function. This would cause stack overflow
1451 * with PROTOS test #1223.
1452 if (*scanner->curptr=='"' || *scanner->curptr=='<') {
1453 return (pjsip_uri*)int_parse_name_addr( scanner, pool );
1454 } else {
1455 */
1456 pj_str_t scheme;
1457 int colon;
1458 pjsip_parse_uri_func *func;
1459
1460 /* Get scheme. */
1461 colon = pj_scan_peek(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1462 if (colon != ':') {
1463 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1464 }
1465
1466 func = find_uri_handler(&scheme);
1467 if (func) {
1468 return (pjsip_uri*)(*func)(scanner, pool, parse_params);
1469
1470 } else {
1471 /* Unsupported URI scheme */
1472 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1473 UNREACHED({ return NULL; /* Not reached. */ })
1474 }
1475
1476 /*
1477 }
1478 */
1479 }
1480
1481 /* Parse "sip:" and "sips:" URI.
1482 * This actually returns (pjsip_sip_uri*) type,
1483 */
int_parse_sip_url(pj_scanner * scanner,pj_pool_t * pool,pj_bool_t parse_params)1484 static void* int_parse_sip_url( pj_scanner *scanner,
1485 pj_pool_t *pool,
1486 pj_bool_t parse_params)
1487 {
1488 pj_str_t scheme;
1489 pjsip_sip_uri *url = NULL;
1490 int colon;
1491 int skip_ws = scanner->skip_ws;
1492 scanner->skip_ws = 0;
1493
1494 pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1495 colon = pj_scan_get_char(scanner);
1496 if (colon != ':') {
1497 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1498 }
1499
1500 if (parser_stricmp(scheme, pconst.pjsip_SIP_STR)==0) {
1501 url = pjsip_sip_uri_create(pool, 0);
1502
1503 } else if (parser_stricmp(scheme, pconst.pjsip_SIPS_STR)==0) {
1504 url = pjsip_sip_uri_create(pool, 1);
1505
1506 } else {
1507 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1508 /* should not reach here */
1509 UNREACHED({
1510 pj_assert(0);
1511 return 0;
1512 })
1513 }
1514
1515 if (int_is_next_user(scanner)) {
1516 int_parse_user_pass(scanner, pool, &url->user, &url->passwd);
1517 }
1518
1519 /* Get host:port */
1520 int_parse_uri_host_port(scanner, &url->host, &url->port);
1521
1522 /* Get URL parameters. */
1523 if (parse_params) {
1524 while (*scanner->curptr == ';' ) {
1525 pj_str_t pname, pvalue;
1526
1527 int_parse_uri_param( scanner, pool, &pname, &pvalue, 0);
1528
1529 if (!parser_stricmp(pname, pconst.pjsip_USER_STR) && pvalue.slen) {
1530 url->user_param = pvalue;
1531
1532 } else if (!parser_stricmp(pname, pconst.pjsip_METHOD_STR) && pvalue.slen) {
1533 url->method_param = pvalue;
1534
1535 } else if (!parser_stricmp(pname, pconst.pjsip_TRANSPORT_STR) && pvalue.slen) {
1536 url->transport_param = pvalue;
1537
1538 } else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
1539 strtoi_validate(&pvalue, PJSIP_MIN_TTL, PJSIP_MAX_TTL,
1540 &url->ttl_param);
1541 } else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
1542 url->maddr_param = pvalue;
1543
1544 } else if (!parser_stricmp(pname, pconst.pjsip_LR_STR)) {
1545 url->lr_param = 1;
1546
1547 } else {
1548 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1549 p->name = pname;
1550 p->value = pvalue;
1551 pj_list_insert_before(&url->other_param, p);
1552 }
1553 }
1554 }
1555
1556 /* Get header params. */
1557 if (parse_params && *scanner->curptr == '?') {
1558 do {
1559 pjsip_param *param;
1560 param = PJ_POOL_ALLOC_T(pool, pjsip_param);
1561 int_parse_hparam(scanner, pool, ¶m->name, ¶m->value);
1562 pj_list_insert_before(&url->header_param, param);
1563 } while (*scanner->curptr == '&');
1564 }
1565
1566 scanner->skip_ws = skip_ws;
1567 pj_scan_skip_whitespace(scanner);
1568 return url;
1569 }
1570
1571 /* Parse nameaddr. */
int_parse_name_addr(pj_scanner * scanner,pj_pool_t * pool)1572 static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
1573 pj_pool_t *pool )
1574 {
1575 int has_bracket;
1576 pjsip_name_addr *name_addr;
1577
1578 name_addr = pjsip_name_addr_create(pool);
1579
1580 if (*scanner->curptr == '"') {
1581 pj_scan_get_quote( scanner, '"', '"', &name_addr->display);
1582 /* Trim the leading and ending quote */
1583 name_addr->display.ptr++;
1584 name_addr->display.slen -= 2;
1585
1586 } else if (*scanner->curptr != '<') {
1587 int next;
1588 pj_str_t dummy;
1589
1590 /* This can be either the start of display name,
1591 * the start of URL ("sip:", "sips:", "tel:", etc.), or '<' char.
1592 * We're only interested in display name, because SIP URL
1593 * will be parser later.
1594 */
1595 next = pj_scan_peek(scanner, &pconst.pjsip_DISPLAY_SPEC, &dummy);
1596 if (next == '<') {
1597 /* Ok, this is what we're looking for, a display name. */
1598 pj_scan_get_until_ch( scanner, '<', &name_addr->display);
1599 pj_strtrim(&name_addr->display);
1600 }
1601 }
1602
1603 /* Manually skip whitespace. */
1604 pj_scan_skip_whitespace(scanner);
1605
1606 /* Get the SIP-URL */
1607 has_bracket = (*scanner->curptr == '<');
1608 if (has_bracket) {
1609 pj_scan_get_char(scanner);
1610 } else if (name_addr->display.slen) {
1611 /* Must have bracket now (2012-10-26).
1612 * Allowing (invalid) name-addr to pass URI verification will
1613 * cause us to send invalid URI to the wire.
1614 */
1615 PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1616 }
1617 name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
1618 if (has_bracket) {
1619 if (pj_scan_get_char(scanner) != '>')
1620 PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1621 }
1622
1623 return name_addr;
1624 }
1625
1626
1627 /* Parse other URI */
int_parse_other_uri(pj_scanner * scanner,pj_pool_t * pool,pj_bool_t parse_params)1628 static void* int_parse_other_uri(pj_scanner *scanner,
1629 pj_pool_t *pool,
1630 pj_bool_t parse_params)
1631 {
1632 pjsip_other_uri *uri = 0;
1633 const pjsip_parser_const_t *pc = pjsip_parser_const();
1634 int skip_ws = scanner->skip_ws;
1635
1636 PJ_UNUSED_ARG(parse_params);
1637
1638 scanner->skip_ws = 0;
1639
1640 uri = pjsip_other_uri_create(pool);
1641
1642 pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &uri->scheme);
1643 if (pj_scan_get_char(scanner) != ':') {
1644 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1645 }
1646
1647 pj_scan_get(scanner, &pc->pjsip_OTHER_URI_CONTENT, &uri->content);
1648 scanner->skip_ws = skip_ws;
1649
1650 return uri;
1651 }
1652
1653
1654 /* Parse SIP request line. */
int_parse_req_line(pj_scanner * scanner,pj_pool_t * pool,pjsip_request_line * req_line)1655 static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool,
1656 pjsip_request_line *req_line)
1657 {
1658 pj_str_t token;
1659
1660 pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &token);
1661 pjsip_method_init_np( &req_line->method, &token);
1662
1663 req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
1664 parse_sip_version(scanner);
1665 pj_scan_get_newline( scanner );
1666 }
1667
1668 /* Parse status line. */
int_parse_status_line(pj_scanner * scanner,pjsip_status_line * status_line)1669 static void int_parse_status_line( pj_scanner *scanner,
1670 pjsip_status_line *status_line)
1671 {
1672 pj_str_t token;
1673
1674 parse_sip_version(scanner);
1675 pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token);
1676 strtoi_validate(&token, PJSIP_MIN_STATUS_CODE, PJSIP_MAX_STATUS_CODE,
1677 &status_line->code);
1678 if (*scanner->curptr != '\r' && *scanner->curptr != '\n')
1679 pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &status_line->reason);
1680 else
1681 status_line->reason.slen=0, status_line->reason.ptr=NULL;
1682 pj_scan_get_newline( scanner );
1683 }
1684
1685
1686 /*
1687 * Public API to parse SIP status line.
1688 */
pjsip_parse_status_line(char * buf,pj_size_t size,pjsip_status_line * status_line)1689 PJ_DEF(pj_status_t) pjsip_parse_status_line( char *buf, pj_size_t size,
1690 pjsip_status_line *status_line)
1691 {
1692 pj_scanner scanner;
1693 PJ_USE_EXCEPTION;
1694
1695 pj_bzero(status_line, sizeof(*status_line));
1696 pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
1697 &on_syntax_error);
1698
1699 PJ_TRY {
1700 int_parse_status_line(&scanner, status_line);
1701 }
1702 PJ_CATCH_ANY {
1703 /* Tolerate the error if it is caused only by missing newline */
1704 if (status_line->code == 0 && status_line->reason.slen == 0) {
1705 pj_scan_fini(&scanner);
1706 return PJSIP_EINVALIDMSG;
1707 }
1708 }
1709 PJ_END;
1710
1711 pj_scan_fini(&scanner);
1712 return PJ_SUCCESS;
1713 }
1714
1715
1716 /* Parse ending of header. */
parse_hdr_end(pj_scanner * scanner)1717 static void parse_hdr_end( pj_scanner *scanner )
1718 {
1719 if (pj_scan_is_eof(scanner)) {
1720 ; /* Do nothing. */
1721 } else if (*scanner->curptr == '&') {
1722 pj_scan_get_char(scanner);
1723 } else {
1724 pj_scan_get_newline(scanner);
1725 }
1726 }
1727
1728 /* Parse ending of header. */
pjsip_parse_end_hdr_imp(pj_scanner * scanner)1729 PJ_DEF(void) pjsip_parse_end_hdr_imp( pj_scanner *scanner )
1730 {
1731 parse_hdr_end(scanner);
1732 }
1733
1734 /* Parse generic array header. */
parse_generic_array_hdr(pjsip_generic_array_hdr * hdr,pj_scanner * scanner)1735 static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
1736 pj_scanner *scanner)
1737 {
1738 /* Some header fields allow empty elements in the value:
1739 * Accept, Allow, Supported
1740 */
1741 if (pj_scan_is_eof(scanner) ||
1742 *scanner->curptr == '\r' || *scanner->curptr == '\n')
1743 {
1744 goto end;
1745 }
1746
1747 if (hdr->count >= PJ_ARRAY_SIZE(hdr->values)) {
1748 /* Too many elements */
1749 on_syntax_error(scanner);
1750 return;
1751 }
1752
1753 pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
1754 &hdr->values[hdr->count]);
1755 hdr->count++;
1756
1757 while ((hdr->count < PJSIP_GENERIC_ARRAY_MAX_COUNT) &&
1758 (*scanner->curptr == ','))
1759 {
1760 pj_scan_get_char(scanner);
1761 pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
1762 &hdr->values[hdr->count]);
1763 hdr->count++;
1764 }
1765
1766 end:
1767 parse_hdr_end(scanner);
1768 }
1769
1770 /* Parse generic array header. */
pjsip_parse_generic_array_hdr_imp(pjsip_generic_array_hdr * hdr,pj_scanner * scanner)1771 PJ_DEF(void) pjsip_parse_generic_array_hdr_imp( pjsip_generic_array_hdr *hdr,
1772 pj_scanner *scanner)
1773 {
1774 parse_generic_array_hdr(hdr, scanner);
1775 }
1776
1777
1778 /* Parse generic string header. */
parse_generic_string_hdr(pjsip_generic_string_hdr * hdr,pjsip_parse_ctx * ctx)1779 static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
1780 pjsip_parse_ctx *ctx)
1781 {
1782 pj_scanner *scanner = ctx->scanner;
1783
1784 hdr->hvalue.slen = 0;
1785
1786 /* header may be mangled hence the loop */
1787 while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) {
1788 pj_str_t next, tmp;
1789
1790 pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue);
1791 if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr))
1792 break;
1793 /* mangled, get next fraction */
1794 pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next);
1795 /* concatenate */
1796 tmp.ptr = (char*)pj_pool_alloc(ctx->pool,
1797 hdr->hvalue.slen + next.slen + 2);
1798 tmp.slen = 0;
1799 pj_strcpy(&tmp, &hdr->hvalue);
1800 pj_strcat2(&tmp, " ");
1801 pj_strcat(&tmp, &next);
1802 tmp.ptr[tmp.slen] = '\0';
1803
1804 hdr->hvalue = tmp;
1805 }
1806
1807 parse_hdr_end(scanner);
1808 }
1809
1810 /* Parse generic integer header. */
parse_generic_int_hdr(pjsip_generic_int_hdr * hdr,pj_scanner * scanner)1811 static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr,
1812 pj_scanner *scanner )
1813 {
1814 pj_str_t tmp;
1815 pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
1816 hdr->ivalue = pj_strtoul(&tmp);
1817 parse_hdr_end(scanner);
1818 }
1819
1820
1821 /* Parse Accept header. */
parse_hdr_accept(pjsip_parse_ctx * ctx)1822 static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx)
1823 {
1824 pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool);
1825 parse_generic_array_hdr(accept, ctx->scanner);
1826 return (pjsip_hdr*)accept;
1827 }
1828
1829 /* Parse Allow header. */
parse_hdr_allow(pjsip_parse_ctx * ctx)1830 static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx)
1831 {
1832 pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool);
1833 parse_generic_array_hdr(allow, ctx->scanner);
1834 return (pjsip_hdr*)allow;
1835 }
1836
1837 /* Parse Call-ID header. */
parse_hdr_call_id(pjsip_parse_ctx * ctx)1838 static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx)
1839 {
1840 pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool);
1841 pj_scan_get( ctx->scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->id);
1842 parse_hdr_end(ctx->scanner);
1843
1844 if (ctx->rdata)
1845 ctx->rdata->msg_info.cid = hdr;
1846
1847 return (pjsip_hdr*)hdr;
1848 }
1849
1850 /* Parse and interpret Contact param. */
int_parse_contact_param(pjsip_contact_hdr * hdr,pj_scanner * scanner,pj_pool_t * pool)1851 static void int_parse_contact_param( pjsip_contact_hdr *hdr,
1852 pj_scanner *scanner,
1853 pj_pool_t *pool)
1854 {
1855 while ( *scanner->curptr == ';' ) {
1856 pj_str_t pname, pvalue;
1857
1858 int_parse_param( scanner, pool, &pname, &pvalue, 0);
1859 if (!parser_stricmp(pname, pconst.pjsip_Q_STR) && pvalue.slen) {
1860 char *dot_pos = (char*) pj_memchr(pvalue.ptr, '.', pvalue.slen);
1861 if (!dot_pos) {
1862 strtoi_validate(&pvalue, PJSIP_MIN_Q1000, PJSIP_MAX_Q1000,
1863 &hdr->q1000);
1864 hdr->q1000 *= 1000;
1865 } else {
1866 pj_str_t tmp = pvalue;
1867 unsigned long qval_frac;
1868
1869 tmp.slen = dot_pos - pvalue.ptr;
1870 strtoi_validate(&tmp, PJSIP_MIN_Q1000, PJSIP_MAX_Q1000,
1871 &hdr->q1000);
1872 hdr->q1000 *= 1000;
1873
1874 pvalue.slen = (pvalue.ptr+pvalue.slen) - (dot_pos+1);
1875 pvalue.ptr = dot_pos + 1;
1876 if (pvalue.slen > 3) {
1877 pvalue.slen = 3;
1878 }
1879 qval_frac = pj_strtoul_mindigit(&pvalue, 3);
1880 if ((unsigned)hdr->q1000 > (PJ_MAXINT32 - qval_frac)) {
1881 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1882 }
1883 hdr->q1000 += qval_frac;
1884 }
1885 } else if (!parser_stricmp(pname, pconst.pjsip_EXPIRES_STR) &&
1886 pvalue.slen)
1887 {
1888 hdr->expires = pj_strtoul(&pvalue);
1889 if (hdr->expires == PJSIP_EXPIRES_NOT_SPECIFIED)
1890 hdr->expires--;
1891 if (hdr->expires > PJSIP_MAX_EXPIRES)
1892 hdr->expires = PJSIP_MAX_EXPIRES;
1893 if (hdr->expires < PJSIP_MIN_EXPIRES)
1894 hdr->expires = PJSIP_MIN_EXPIRES;
1895 } else {
1896 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1897 p->name = pname;
1898 p->value = pvalue;
1899 pj_list_insert_before(&hdr->other_param, p);
1900 }
1901 }
1902 }
1903
1904 /* Parse Contact header. */
parse_hdr_contact(pjsip_parse_ctx * ctx)1905 static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx )
1906 {
1907 pjsip_contact_hdr *first = NULL;
1908 pj_scanner *scanner = ctx->scanner;
1909
1910 do {
1911 pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool);
1912 if (first == NULL)
1913 first = hdr;
1914 else
1915 pj_list_insert_before(first, hdr);
1916
1917 if (*scanner->curptr == '*') {
1918 pj_scan_get_char(scanner);
1919 hdr->star = 1;
1920
1921 } else {
1922 hdr->star = 0;
1923 hdr->uri = int_parse_uri_or_name_addr(scanner, ctx->pool,
1924 PJSIP_PARSE_URI_AS_NAMEADDR |
1925 PJSIP_PARSE_URI_IN_FROM_TO_HDR);
1926
1927 int_parse_contact_param(hdr, scanner, ctx->pool);
1928 }
1929
1930 if (*scanner->curptr != ',')
1931 break;
1932
1933 pj_scan_get_char(scanner);
1934
1935 } while (1);
1936
1937 parse_hdr_end(scanner);
1938
1939 return (pjsip_hdr*)first;
1940 }
1941
1942 /* Parse Content-Length header. */
parse_hdr_content_len(pjsip_parse_ctx * ctx)1943 static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx )
1944 {
1945 pj_str_t digit;
1946 pjsip_clen_hdr *hdr;
1947
1948 hdr = pjsip_clen_hdr_create(ctx->pool);
1949 pj_scan_get(ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &digit);
1950 hdr->len = pj_strtoul(&digit);
1951 parse_hdr_end(ctx->scanner);
1952
1953 if (ctx->rdata)
1954 ctx->rdata->msg_info.clen = hdr;
1955
1956 return (pjsip_hdr*)hdr;
1957 }
1958
1959 /* Parse Content-Type header. */
parse_hdr_content_type(pjsip_parse_ctx * ctx)1960 static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx )
1961 {
1962 pjsip_ctype_hdr *hdr;
1963 pj_scanner *scanner = ctx->scanner;
1964
1965 hdr = pjsip_ctype_hdr_create(ctx->pool);
1966
1967 /* Parse media type and subtype. */
1968 pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->media.type);
1969 pj_scan_get_char(scanner);
1970 pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->media.subtype);
1971
1972 /* Parse media parameters */
1973 while (*scanner->curptr == ';') {
1974 pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
1975 int_parse_param(scanner, ctx->pool, ¶m->name, ¶m->value, 0);
1976 pj_list_push_back(&hdr->media.param, param);
1977 }
1978
1979 parse_hdr_end(ctx->scanner);
1980
1981 if (ctx->rdata)
1982 ctx->rdata->msg_info.ctype = hdr;
1983
1984 return (pjsip_hdr*)hdr;
1985 }
1986
1987 /* Parse CSeq header. */
parse_hdr_cseq(pjsip_parse_ctx * ctx)1988 static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx )
1989 {
1990 pj_str_t cseq, method;
1991 pjsip_cseq_hdr *hdr = NULL;
1992 int cseq_val = 0;
1993
1994 pj_scan_get( ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &cseq);
1995 strtoi_validate(&cseq, PJSIP_MIN_CSEQ, PJSIP_MAX_CSEQ, &cseq_val);
1996
1997 hdr = pjsip_cseq_hdr_create(ctx->pool);
1998 hdr->cseq = cseq_val;
1999
2000 pj_scan_get( ctx->scanner, &pconst.pjsip_TOKEN_SPEC, &method);
2001 parse_hdr_end( ctx->scanner );
2002
2003 pjsip_method_init_np(&hdr->method, &method);
2004 if (ctx->rdata) {
2005 ctx->rdata->msg_info.cseq = hdr;
2006 }
2007
2008 return (pjsip_hdr*)hdr;
2009 }
2010
2011 /* Parse Expires header. */
parse_hdr_expires(pjsip_parse_ctx * ctx)2012 static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx)
2013 {
2014 pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(ctx->pool, 0);
2015 parse_generic_int_hdr(hdr, ctx->scanner);
2016 return (pjsip_hdr*)hdr;
2017 }
2018
2019 /* Parse From: or To: header. */
parse_hdr_fromto(pj_scanner * scanner,pj_pool_t * pool,pjsip_from_hdr * hdr)2020 static void parse_hdr_fromto( pj_scanner *scanner,
2021 pj_pool_t *pool,
2022 pjsip_from_hdr *hdr)
2023 {
2024 hdr->uri = int_parse_uri_or_name_addr(scanner, pool,
2025 PJSIP_PARSE_URI_AS_NAMEADDR |
2026 PJSIP_PARSE_URI_IN_FROM_TO_HDR);
2027
2028 while ( *scanner->curptr == ';' ) {
2029 pj_str_t pname, pvalue;
2030
2031 int_parse_param( scanner, pool, &pname, &pvalue, 0);
2032
2033 if (!parser_stricmp(pname, pconst.pjsip_TAG_STR)) {
2034 hdr->tag = pvalue;
2035
2036 } else {
2037 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2038 p->name = pname;
2039 p->value = pvalue;
2040 pj_list_insert_before(&hdr->other_param, p);
2041 }
2042 }
2043
2044 parse_hdr_end(scanner);
2045 }
2046
2047 /* Parse From: header. */
parse_hdr_from(pjsip_parse_ctx * ctx)2048 static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
2049 {
2050 pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool);
2051 parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
2052 if (ctx->rdata)
2053 ctx->rdata->msg_info.from = hdr;
2054
2055 return (pjsip_hdr*)hdr;
2056 }
2057
2058 /* Parse Require: header. */
parse_hdr_require(pjsip_parse_ctx * ctx)2059 static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
2060 {
2061 pjsip_require_hdr *hdr;
2062 pj_bool_t new_hdr = (ctx->rdata==NULL ||
2063 ctx->rdata->msg_info.require == NULL);
2064
2065 if (ctx->rdata && ctx->rdata->msg_info.require) {
2066 hdr = ctx->rdata->msg_info.require;
2067 } else {
2068 hdr = pjsip_require_hdr_create(ctx->pool);
2069 if (ctx->rdata)
2070 ctx->rdata->msg_info.require = hdr;
2071 }
2072
2073 parse_generic_array_hdr(hdr, ctx->scanner);
2074
2075 return new_hdr ? (pjsip_hdr*)hdr : NULL;
2076 }
2077
2078 /* Parse Retry-After: header. */
parse_hdr_retry_after(pjsip_parse_ctx * ctx)2079 static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
2080 {
2081 pjsip_retry_after_hdr *hdr;
2082 pj_scanner *scanner = ctx->scanner;
2083 pj_str_t tmp;
2084
2085 hdr = pjsip_retry_after_hdr_create(ctx->pool, 0);
2086
2087 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
2088 strtoi_validate(&tmp, PJSIP_MIN_RETRY_AFTER, PJSIP_MAX_RETRY_AFTER,
2089 &hdr->ivalue);
2090
2091 while (!pj_scan_is_eof(scanner) && *scanner->curptr!='\r' &&
2092 *scanner->curptr!='\n')
2093 {
2094 if (*scanner->curptr=='(') {
2095 pj_scan_get_quote(scanner, '(', ')', &hdr->comment);
2096 /* Trim the leading and ending parens */
2097 hdr->comment.ptr++;
2098 hdr->comment.slen -= 2;
2099 } else if (*scanner->curptr==';') {
2100 pjsip_param *prm = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
2101 int_parse_param(scanner, ctx->pool, &prm->name, &prm->value, 0);
2102 pj_list_push_back(&hdr->param, prm);
2103 } else {
2104 on_syntax_error(scanner);
2105 }
2106 }
2107
2108 parse_hdr_end(scanner);
2109 return (pjsip_hdr*)hdr;
2110 }
2111
2112 /* Parse Supported: header. */
parse_hdr_supported(pjsip_parse_ctx * ctx)2113 static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
2114 {
2115 pjsip_supported_hdr *hdr;
2116 pj_bool_t new_hdr = (ctx->rdata==NULL ||
2117 ctx->rdata->msg_info.supported == NULL);
2118
2119 if (ctx->rdata && ctx->rdata->msg_info.supported) {
2120 hdr = ctx->rdata->msg_info.supported;
2121 } else {
2122 hdr = pjsip_supported_hdr_create(ctx->pool);
2123 if (ctx->rdata)
2124 ctx->rdata->msg_info.supported = hdr;
2125 }
2126
2127 parse_generic_array_hdr(hdr, ctx->scanner);
2128 return new_hdr ? (pjsip_hdr*)hdr : NULL;
2129 }
2130
2131 /* Parse To: header. */
parse_hdr_to(pjsip_parse_ctx * ctx)2132 static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
2133 {
2134 pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool);
2135 parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
2136
2137 if (ctx->rdata)
2138 ctx->rdata->msg_info.to = hdr;
2139
2140 return (pjsip_hdr*)hdr;
2141 }
2142
2143 /* Parse Unsupported: header. */
parse_hdr_unsupported(pjsip_parse_ctx * ctx)2144 static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx)
2145 {
2146 pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool);
2147 parse_generic_array_hdr(hdr, ctx->scanner);
2148 return (pjsip_hdr*)hdr;
2149 }
2150
2151 /* Parse and interpret Via parameters. */
int_parse_via_param(pjsip_via_hdr * hdr,pj_scanner * scanner,pj_pool_t * pool)2152 static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
2153 pj_pool_t *pool)
2154 {
2155 while ( *scanner->curptr == ';' ) {
2156 pj_str_t pname, pvalue;
2157
2158 //Parse with PARAM_CHAR instead, to allow IPv6
2159 //No, back to using int_parse_param() for the "`" character!
2160 //int_parse_param( scanner, pool, &pname, &pvalue, 0);
2161 //parse_param_imp(scanner, pool, &pname, &pvalue,
2162 // &pconst.pjsip_TOKEN_SPEC,
2163 // &pconst.pjsip_TOKEN_SPEC_ESC, 0);
2164 //int_parse_param(scanner, pool, &pname, &pvalue, 0);
2165 // This should be the correct one:
2166 // added special spec for Via parameter, basically token plus
2167 // ":" to allow IPv6 address in the received param.
2168 pj_scan_get_char(scanner);
2169 parse_param_imp(scanner, pool, &pname, &pvalue,
2170 &pconst.pjsip_VIA_PARAM_SPEC,
2171 &pconst.pjsip_VIA_PARAM_SPEC_ESC,
2172 0);
2173
2174 if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
2175 hdr->branch_param = pvalue;
2176
2177 } else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
2178 strtoi_validate(&pvalue, PJSIP_MIN_TTL, PJSIP_MAX_TTL,
2179 &hdr->ttl_param);
2180
2181 } else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
2182 hdr->maddr_param = pvalue;
2183
2184 } else if (!parser_stricmp(pname, pconst.pjsip_RECEIVED_STR) && pvalue.slen) {
2185 hdr->recvd_param = pvalue;
2186
2187 } else if (!parser_stricmp(pname, pconst.pjsip_RPORT_STR)) {
2188 if (pvalue.slen) {
2189 strtoi_validate(&pvalue, PJSIP_MIN_PORT, PJSIP_MAX_PORT,
2190 &hdr->rport_param);
2191 } else
2192 hdr->rport_param = 0;
2193 } else {
2194 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2195 p->name = pname;
2196 p->value = pvalue;
2197 pj_list_insert_before(&hdr->other_param, p);
2198 }
2199 }
2200 }
2201
2202 /* Parse Max-Forwards header. */
parse_hdr_max_forwards(pjsip_parse_ctx * ctx)2203 static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx )
2204 {
2205 pjsip_max_fwd_hdr *hdr;
2206 hdr = pjsip_max_fwd_hdr_create(ctx->pool, 0);
2207 parse_generic_int_hdr(hdr, ctx->scanner);
2208
2209 if (ctx->rdata)
2210 ctx->rdata->msg_info.max_fwd = hdr;
2211
2212 return (pjsip_hdr*)hdr;
2213 }
2214
2215 /* Parse Min-Expires header. */
parse_hdr_min_expires(pjsip_parse_ctx * ctx)2216 static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx)
2217 {
2218 pjsip_min_expires_hdr *hdr;
2219 hdr = pjsip_min_expires_hdr_create(ctx->pool, 0);
2220 parse_generic_int_hdr(hdr, ctx->scanner);
2221 return (pjsip_hdr*)hdr;
2222 }
2223
2224
2225 /* Parse Route: or Record-Route: header. */
parse_hdr_rr_route(pj_scanner * scanner,pj_pool_t * pool,pjsip_routing_hdr * hdr)2226 static void parse_hdr_rr_route( pj_scanner *scanner, pj_pool_t *pool,
2227 pjsip_routing_hdr *hdr )
2228 {
2229 pjsip_name_addr *temp=int_parse_name_addr(scanner, pool);
2230
2231 pj_memcpy(&hdr->name_addr, temp, sizeof(*temp));
2232
2233 while (*scanner->curptr == ';') {
2234 pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2235 int_parse_param(scanner, pool, &p->name, &p->value, 0);
2236 pj_list_insert_before(&hdr->other_param, p);
2237 }
2238 }
2239
2240 /* Parse Record-Route header. */
parse_hdr_rr(pjsip_parse_ctx * ctx)2241 static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx)
2242 {
2243 pjsip_rr_hdr *first = NULL;
2244 pj_scanner *scanner = ctx->scanner;
2245
2246 do {
2247 pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool);
2248 if (!first) {
2249 first = hdr;
2250 } else {
2251 pj_list_insert_before(first, hdr);
2252 }
2253 parse_hdr_rr_route(scanner, ctx->pool, hdr);
2254 if (*scanner->curptr == ',') {
2255 pj_scan_get_char(scanner);
2256 } else {
2257 break;
2258 }
2259 } while (1);
2260 parse_hdr_end(scanner);
2261
2262 if (ctx->rdata && ctx->rdata->msg_info.record_route==NULL)
2263 ctx->rdata->msg_info.record_route = first;
2264
2265 return (pjsip_hdr*)first;
2266 }
2267
2268 /* Parse Route: header. */
parse_hdr_route(pjsip_parse_ctx * ctx)2269 static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx )
2270 {
2271 pjsip_route_hdr *first = NULL;
2272 pj_scanner *scanner = ctx->scanner;
2273
2274 do {
2275 pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool);
2276 if (!first) {
2277 first = hdr;
2278 } else {
2279 pj_list_insert_before(first, hdr);
2280 }
2281 parse_hdr_rr_route(scanner, ctx->pool, hdr);
2282 if (*scanner->curptr == ',') {
2283 pj_scan_get_char(scanner);
2284 } else {
2285 break;
2286 }
2287 } while (1);
2288 parse_hdr_end(scanner);
2289
2290 if (ctx->rdata && ctx->rdata->msg_info.route==NULL)
2291 ctx->rdata->msg_info.route = first;
2292
2293 return (pjsip_hdr*)first;
2294 }
2295
2296 /* Parse Via: header. */
parse_hdr_via(pjsip_parse_ctx * ctx)2297 static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
2298 {
2299 pjsip_via_hdr *first = NULL;
2300 pj_scanner *scanner = ctx->scanner;
2301
2302 do {
2303 pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool);
2304 if (!first)
2305 first = hdr;
2306 else
2307 pj_list_insert_before(first, hdr);
2308
2309 parse_sip_version(scanner);
2310 if (pj_scan_get_char(scanner) != '/')
2311 on_syntax_error(scanner);
2312
2313 pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport);
2314 int_parse_host(scanner, &hdr->sent_by.host);
2315
2316 if (*scanner->curptr==':') {
2317 pj_str_t digit;
2318 pj_scan_get_char(scanner);
2319 pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &digit);
2320 strtoi_validate(&digit, PJSIP_MIN_PORT, PJSIP_MAX_PORT,
2321 &hdr->sent_by.port);
2322 }
2323
2324 int_parse_via_param(hdr, scanner, ctx->pool);
2325
2326 if (*scanner->curptr == '(') {
2327 pj_scan_get_char(scanner);
2328 pj_scan_get_until_ch( scanner, ')', &hdr->comment);
2329 pj_scan_get_char( scanner );
2330 }
2331
2332 if (*scanner->curptr != ',')
2333 break;
2334
2335 pj_scan_get_char(scanner);
2336
2337 } while (1);
2338
2339 parse_hdr_end(scanner);
2340
2341 if (ctx->rdata && ctx->rdata->msg_info.via == NULL)
2342 ctx->rdata->msg_info.via = first;
2343
2344 return (pjsip_hdr*)first;
2345 }
2346
2347 /* Parse generic header. */
parse_hdr_generic_string(pjsip_parse_ctx * ctx)2348 static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
2349 {
2350 pjsip_generic_string_hdr *hdr;
2351
2352 hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL);
2353 parse_generic_string_hdr(hdr, ctx);
2354 return (pjsip_hdr*)hdr;
2355
2356 }
2357
2358 /* Public function to parse a header value. */
pjsip_parse_hdr(pj_pool_t * pool,const pj_str_t * hname,char * buf,pj_size_t size,int * parsed_len)2359 PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
2360 char *buf, pj_size_t size, int *parsed_len )
2361 {
2362 pj_scanner scanner;
2363 pjsip_hdr *hdr = NULL;
2364 pjsip_parse_ctx context;
2365 PJ_USE_EXCEPTION;
2366
2367 pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2368 &on_syntax_error);
2369
2370 context.scanner = &scanner;
2371 context.pool = pool;
2372 context.rdata = NULL;
2373
2374 PJ_TRY {
2375 pjsip_parse_hdr_func *func = find_handler(hname);
2376 if (func) {
2377 hdr = (*func)(&context);
2378 } else {
2379 hdr = parse_hdr_generic_string(&context);
2380 hdr->type = PJSIP_H_OTHER;
2381 pj_strdup(pool, &hdr->name, hname);
2382 hdr->sname = hdr->name;
2383 }
2384
2385 }
2386 PJ_CATCH_ANY {
2387 hdr = NULL;
2388 }
2389 PJ_END
2390
2391 if (parsed_len) {
2392 *parsed_len = (unsigned)(scanner.curptr - scanner.begin);
2393 }
2394
2395 pj_scan_fini(&scanner);
2396
2397 return hdr;
2398 }
2399
2400 /* Parse multiple header lines */
pjsip_parse_headers(pj_pool_t * pool,char * input,pj_size_t size,pjsip_hdr * hlist,unsigned options)2401 PJ_DEF(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input,
2402 pj_size_t size, pjsip_hdr *hlist,
2403 unsigned options)
2404 {
2405 enum { STOP_ON_ERROR = 1 };
2406 pj_str_t hname;
2407 pj_scanner scanner;
2408 pjsip_parse_ctx ctx;
2409
2410 PJ_USE_EXCEPTION;
2411
2412 pj_scan_init(&scanner, input, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2413 &on_syntax_error);
2414
2415 pj_bzero(&ctx, sizeof(ctx));
2416 ctx.scanner = &scanner;
2417 ctx.pool = pool;
2418
2419 retry_parse:
2420 PJ_TRY
2421 {
2422 /* Parse headers. */
2423 do {
2424 pjsip_parse_hdr_func * func;
2425 pjsip_hdr *hdr = NULL;
2426
2427 /* Init hname just in case parsing fails.
2428 * Ref: PROTOS #2412
2429 */
2430 hname.slen = 0;
2431
2432 /* Get hname. */
2433 pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
2434 if (pj_scan_get_char( &scanner ) != ':') {
2435 PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
2436 }
2437
2438 /* Find handler. */
2439 func = find_handler(&hname);
2440
2441 /* Call the handler if found.
2442 * If no handler is found, then treat the header as generic
2443 * hname/hvalue pair.
2444 */
2445 if (func) {
2446 hdr = (*func)(&ctx);
2447 } else {
2448 hdr = parse_hdr_generic_string(&ctx);
2449 hdr->name = hdr->sname = hname;
2450 }
2451
2452 /* Single parse of header line can produce multiple headers.
2453 * For example, if one Contact: header contains Contact list
2454 * separated by comma, then these Contacts will be split into
2455 * different Contact headers.
2456 * So here we must insert list instead of just insert one header.
2457 */
2458 if (hdr)
2459 pj_list_insert_nodes_before(hlist, hdr);
2460
2461 /* Parse until EOF or an empty line is found. */
2462 } while (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr));
2463
2464 /* If empty line is found, eat it. */
2465 if (!pj_scan_is_eof(&scanner)) {
2466 if (IS_NEWLINE(*scanner.curptr)) {
2467 pj_scan_get_newline(&scanner);
2468 }
2469 }
2470 }
2471 PJ_CATCH_ANY
2472 {
2473 PJ_LOG(4,(THIS_FILE, "Error parsing header: '%.*s' line %d col %d",
2474 (int)hname.slen, hname.ptr, scanner.line,
2475 pj_scan_get_col(&scanner)));
2476
2477 /* Exception was thrown during parsing. */
2478 if ((options & STOP_ON_ERROR) == STOP_ON_ERROR) {
2479 pj_scan_fini(&scanner);
2480 return PJSIP_EINVALIDHDR;
2481 }
2482
2483 /* Skip until newline, and parse next header. */
2484 if (!pj_scan_is_eof(&scanner)) {
2485 /* Skip until next line.
2486 * Watch for header continuation.
2487 */
2488 do {
2489 pj_scan_skip_line(&scanner);
2490 } while (IS_SPACE(*scanner.curptr));
2491 }
2492
2493 /* Restore flag. Flag may be set in int_parse_sip_url() */
2494 scanner.skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
2495
2496 /* Continue parse next header, if any. */
2497 if (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)) {
2498 goto retry_parse;
2499 }
2500
2501 }
2502 PJ_END;
2503
2504 return PJ_SUCCESS;
2505 }
2506
2507