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