1
/* $Id: sip_parser.c 4537 2013-06-19 06:47:43Z riza $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
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.
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.
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
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>
34
#include <pj/string.h>
36
#include <pj/assert.h>
38
#define THIS_FILE "sip_parser.c"
41
#define RESERVED ";/?:@&=+$,"
42
#define MARK "-_.!~*'()"
43
#define UNRESERVED ALNUM MARK
45
#define USER_UNRESERVED "&=+$,;?/"
47
#define TOKEN "-.!%*_`'~+" /* '=' was removed for parsing
50
#define HEX_DIGIT "abcdefABCDEF"
51
#define PARAM_CHAR "[]/:&+$" UNRESERVED ESCAPED
52
#define HNV_UNRESERVED "[]/?:+$"
53
#define HDR_CHAR HNV_UNRESERVED UNRESERVED ESCAPED
55
/* A generic URI can consist of (For a complete BNF see RFC 2396):
58
#define GENERIC_URI_CHARS "#?;:@&=+-_.!~*'()%$,/" "%"
60
#define UNREACHED(expr)
62
#define IS_NEWLINE(c) ((c)=='\r' || (c)=='\n')
63
#define IS_SPACE(c) ((c)==' ' || (c)=='\t')
66
* Header parser records.
68
typedef struct handler_rec
70
char hname[PJSIP_MAX_HNAME_LEN+1];
72
pj_uint32_t hname_hash;
73
pjsip_parse_hdr_func *handler;
76
static handler_rec handler[PJSIP_MAX_HEADER_TYPES];
77
static unsigned handler_count;
78
static int parser_is_initialized;
83
typedef struct uri_parser_rec
86
pjsip_parse_uri_func *parse;
89
static uri_parser_rec uri_handler[PJSIP_MAX_URI_TYPES];
90
static unsigned uri_handler_count;
93
* Global vars (also extern).
95
int PJSIP_SYN_ERR_EXCEPTION = -1;
97
/* Parser constants */
98
static pjsip_parser_const_t pconst =
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 */
117
/* Character Input Specification buffer. */
118
static pj_cis_buf_t cis_buf;
124
static pjsip_msg * int_parse_msg( pjsip_parse_ctx *ctx,
125
pjsip_parser_err_report *err_list);
126
static void int_parse_param( pj_scanner *scanner,
131
static void int_parse_uri_param( pj_scanner *scanner,
136
static void int_parse_hparam( pj_scanner *scanner,
140
static void int_parse_req_line( pj_scanner *scanner,
142
pjsip_request_line *req_line);
143
static int int_is_next_user( pj_scanner *scanner);
144
static void int_parse_status_line( pj_scanner *scanner,
145
pjsip_status_line *line);
146
static void int_parse_user_pass( pj_scanner *scanner,
150
static void int_parse_uri_host_port( pj_scanner *scanner,
153
static pjsip_uri * int_parse_uri_or_name_addr( pj_scanner *scanner,
156
static void* int_parse_sip_url( pj_scanner *scanner,
158
pj_bool_t parse_params);
159
static pjsip_name_addr *
160
int_parse_name_addr( pj_scanner *scanner,
162
static void* int_parse_other_uri(pj_scanner *scanner,
164
pj_bool_t parse_params);
165
static void parse_hdr_end( pj_scanner *scanner );
167
static pjsip_hdr* parse_hdr_accept( pjsip_parse_ctx *ctx );
168
static pjsip_hdr* parse_hdr_allow( pjsip_parse_ctx *ctx );
169
static pjsip_hdr* parse_hdr_call_id( pjsip_parse_ctx *ctx);
170
static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx);
171
static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx );
172
static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx );
173
static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx );
174
static pjsip_hdr* parse_hdr_expires( pjsip_parse_ctx *ctx );
175
static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx );
176
static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx);
177
static pjsip_hdr* parse_hdr_min_expires( pjsip_parse_ctx *ctx );
178
static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx );
179
static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx );
180
static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx );
181
static pjsip_hdr* parse_hdr_retry_after( pjsip_parse_ctx *ctx );
182
static pjsip_hdr* parse_hdr_supported( pjsip_parse_ctx *ctx );
183
static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx );
184
static pjsip_hdr* parse_hdr_unsupported( pjsip_parse_ctx *ctx );
185
static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx );
186
static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx);
188
/* Convert non NULL terminated string to integer. */
189
static unsigned long pj_strtoul_mindigit(const pj_str_t *str,
196
for (i=0; i<(unsigned)str->slen; ++i) {
197
value = value * 10 + (str->ptr[i] - '0');
199
for (; i<mindig; ++i) {
205
/* Case insensitive comparison */
206
#define parser_stricmp(s1, s2) (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2))
209
/* Get a token and unescape */
210
PJ_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,
215
#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0
218
pj_scan_get_unescape(scanner, unesc_spec, token);
220
PJ_UNUSED_ARG(unesc_spec);
221
pj_scan_get(scanner, spec, token);
222
*token = pj_str_unescape(pool, token);
228
/* Syntax error handler for parser. */
229
static void on_syntax_error(pj_scanner *scanner)
231
PJ_UNUSED_ARG(scanner);
232
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
235
/* Get parser constants. */
236
PJ_DEF(const pjsip_parser_const_t*) pjsip_parser_const(void)
241
/* Concatenate unrecognized params into single string. */
242
PJ_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,
250
len = param->slen + pname->slen + pvalue->slen + 3;
251
p = new_param = (char*) pj_pool_alloc(pool, len);
254
pj_size_t old_len = param->slen;
255
pj_memcpy(p, param->ptr, old_len);
258
*p++ = (char)sepchar;
259
pj_memcpy(p, pname->ptr, pname->slen);
264
pj_memcpy(p, pvalue->ptr, pvalue->slen);
270
param->ptr = new_param;
271
param->slen = p - new_param;
274
/* Initialize static properties of the parser. */
275
static pj_status_t init_parser()
280
* Syntax error exception number.
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);
288
* Init character input spec (cis)
291
pj_cis_buf_init(&cis_buf);
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);
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 );
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 );
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);
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);
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);
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, "%");
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, ":");
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, ":");
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);
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);
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);
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);
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);
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);
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 );
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);
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, "#");
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, "#");
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);
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);
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 );
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);
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);
395
* Register URI parsers.
398
status = pjsip_register_uri_parser("sip", &int_parse_sip_url);
399
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
401
status = pjsip_register_uri_parser("sips", &int_parse_sip_url);
402
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
405
* Register header parsers.
408
status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
409
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
411
status = pjsip_register_hdr_parser( "Allow", NULL, &parse_hdr_allow);
412
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
414
status = pjsip_register_hdr_parser( "Call-ID", "i", &parse_hdr_call_id);
415
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
417
status = pjsip_register_hdr_parser( "Contact", "m", &parse_hdr_contact);
418
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
420
status = pjsip_register_hdr_parser( "Content-Length", "l",
421
&parse_hdr_content_len);
422
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
424
status = pjsip_register_hdr_parser( "Content-Type", "c",
425
&parse_hdr_content_type);
426
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
428
status = pjsip_register_hdr_parser( "CSeq", NULL, &parse_hdr_cseq);
429
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
431
status = pjsip_register_hdr_parser( "Expires", NULL, &parse_hdr_expires);
432
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
434
status = pjsip_register_hdr_parser( "From", "f", &parse_hdr_from);
435
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
437
status = pjsip_register_hdr_parser( "Max-Forwards", NULL,
438
&parse_hdr_max_forwards);
439
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
441
status = pjsip_register_hdr_parser( "Min-Expires", NULL,
442
&parse_hdr_min_expires);
443
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
445
status = pjsip_register_hdr_parser( "Record-Route", NULL, &parse_hdr_rr);
446
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
448
status = pjsip_register_hdr_parser( "Route", NULL, &parse_hdr_route);
449
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
451
status = pjsip_register_hdr_parser( "Require", NULL, &parse_hdr_require);
452
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
454
status = pjsip_register_hdr_parser( "Retry-After", NULL,
455
&parse_hdr_retry_after);
456
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
458
status = pjsip_register_hdr_parser( "Supported", "k",
459
&parse_hdr_supported);
460
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
462
status = pjsip_register_hdr_parser( "To", "t", &parse_hdr_to);
463
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
465
status = pjsip_register_hdr_parser( "Unsupported", NULL,
466
&parse_hdr_unsupported);
467
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
469
status = pjsip_register_hdr_parser( "Via", "v", &parse_hdr_via);
470
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
473
* Register auth parser.
476
status = pjsip_auth_init_parser();
481
void init_sip_parser(void)
483
pj_enter_critical_section();
484
if (++parser_is_initialized == 1) {
487
pj_leave_critical_section();
490
void deinit_sip_parser(void)
492
pj_enter_critical_section();
493
if (--parser_is_initialized == 0) {
494
/* Clear header handlers */
495
pj_bzero(handler, sizeof(handler));
498
/* Clear URI handlers */
499
pj_bzero(uri_handler, sizeof(uri_handler));
500
uri_handler_count = 0;
502
/* Deregister exception ID */
503
pj_exception_id_free(PJSIP_SYN_ERR_EXCEPTION);
504
PJSIP_SYN_ERR_EXCEPTION = -1;
506
pj_leave_critical_section();
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.
514
PJ_INLINE(int) compare_handler( const handler_rec *r1,
519
PJ_UNUSED_ARG(name_len);
521
/* Compare hashed value. */
522
if (r1->hname_hash < hash)
524
if (r1->hname_hash > hash)
527
/* Compare length. */
529
if (r1->hname_len < name_len)
531
if (r1->hname_len > name_len)
535
/* Equal length and equal hash. compare the strings. */
536
return pj_memcmp(r1->hname, name, name_len);
539
/* Register one handler for one header name. */
540
static pj_status_t int_register_parser( const char *name,
541
pjsip_parse_hdr_func *fptr )
546
if (handler_count >= PJ_ARRAY_SIZE(handler)) {
547
pj_assert(!"Too many handlers!");
551
/* Initialize temporary handler. */
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;
559
pj_memcpy(rec.hname, name, rec.hname_len);
560
rec.hname[rec.hname_len] = '\0';
562
/* Calculate hash value. */
563
rec.hname_hash = pj_hash_calc(0, rec.hname, (unsigned)rec.hname_len);
565
/* Get the pos to insert the new handler. */
566
for (pos=0; pos < handler_count; ++pos) {
568
d = compare_handler(&handler[pos], rec.hname, rec.hname_len,
579
/* Shift handlers. */
580
if (pos != handler_count) {
581
pj_memmove( &handler[pos+1], &handler[pos],
582
(handler_count-pos)*sizeof(handler_rec));
584
/* Add new handler. */
585
pj_memcpy( &handler[pos], &rec, sizeof(handler_rec));
591
/* Register parser handler. If both header name and short name are valid,
592
* then two instances of handler will be registered.
594
PJ_DEF(pj_status_t) pjsip_register_hdr_parser( const char *hname,
595
const char *hshortname,
596
pjsip_parse_hdr_func *fptr)
600
char hname_lcase[PJSIP_MAX_HNAME_LEN+1];
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;
610
/* Register the normal Mixed-Case name */
611
status = int_register_parser(hname, fptr);
612
if (status != PJ_SUCCESS) {
616
/* Get the lower-case name */
617
for (i=0; i<len; ++i) {
618
hname_lcase[i] = (char)pj_tolower(hname[i]);
620
hname_lcase[len] = '\0';
622
/* Register the lower-case version of the name */
623
status = int_register_parser(hname_lcase, fptr);
624
if (status != PJ_SUCCESS) {
629
/* Register the shortname version of the name */
631
status = int_register_parser(hshortname, fptr);
632
if (status != PJ_SUCCESS)
639
/* Find handler to parse the header name. */
640
static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t hash,
641
const pj_str_t *hname)
647
/* Binary search for the handler. */
652
unsigned half = n / 2;
653
handler_rec *mid = first + half;
655
comp = compare_handler(mid, hname->ptr, hname->slen, hash);
659
} else if (comp==0) {
667
return comp==0 ? first->handler : NULL;
671
/* Find handler to parse the header name. */
672
static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname)
675
char hname_copy[PJSIP_MAX_HNAME_LEN];
677
pjsip_parse_hdr_func *handler;
679
if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
680
/* Guaranteed not to be able to find handler. */
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);
691
/* If not found, try converting the header name to lowercase and
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);
701
/* Find URI handler. */
702
static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme)
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;
709
return &int_parse_other_uri;
712
/* Register URI parser. */
713
PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme,
714
pjsip_parse_uri_func *func)
716
if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler))
719
uri_handler[uri_handler_count].scheme = pj_str((char*)scheme);
720
uri_handler[uri_handler_count].parse = func;
726
/* Public function to parse SIP message. */
727
PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,
728
char *buf, pj_size_t size,
729
pjsip_parser_err_report *err_list)
731
pjsip_msg *msg = NULL;
733
pjsip_parse_ctx context;
735
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
738
context.scanner = &scanner;
740
context.rdata = NULL;
742
msg = int_parse_msg(&context, err_list);
744
pj_scan_fini(&scanner);
748
/* Public function to parse as rdata.*/
749
PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
750
pjsip_rx_data *rdata )
753
pjsip_parse_ctx context;
755
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
758
context.scanner = &scanner;
759
context.pool = rdata->tp_info.pool;
760
context.rdata = rdata;
762
rdata->msg_info.msg = int_parse_msg(&context, &rdata->msg_info.parse_err);
764
pj_scan_fini(&scanner);
765
return rdata->msg_info.msg;
768
/* Determine if a message has been received. */
769
PJ_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)
774
const char *body_start;
777
int content_length = -1;
779
const pj_str_t end_hdr = { "\n\r\n", 3};
783
/* For datagram, the whole datagram IS the message. */
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
793
cur_msg.ptr = (char*)buf; cur_msg.slen = size;
794
pos = pj_strstr(&cur_msg, &end_hdr);
796
return PJSIP_EPARTIALMSG;
802
/* Find "Content-Length" header the hard way. */
803
line = pj_strchr(&cur_msg, '\n');
804
while (line && line < hdr_end) {
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)==':')))
811
/* Try to parse the header. */
815
pj_scan_init(&scanner, (char*)line, hdr_end-line,
816
PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
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);
828
if (pj_scan_get_char(&scanner) != ':') {
829
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
833
pj_scan_get(&scanner, &pconst.pjsip_DIGIT_SPEC, &str_clen);
836
pj_scan_get_newline(&scanner);
838
/* Found a valid Content-Length header. */
839
content_length = pj_strtoul(&str_clen);
846
pj_scan_fini(&scanner);
849
/* Found valid Content-Length? */
850
if (content_length != -1)
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');
859
/* Found Content-Length? */
860
if (content_length == -1) {
861
return PJSIP_EMISSINGHDR;
864
/* Enough packet received? */
865
*msg_size = (body_start - buf) + content_length;
866
return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;
869
PJ_UNUSED_ARG(is_datagram);
875
/* Public function to parse URI */
876
PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
877
char *buf, pj_size_t size,
881
pjsip_uri *uri = NULL;
884
pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
888
uri = int_parse_uri_or_name_addr(&scanner, pool, option);
895
/* Must have exhausted all inputs. */
896
if (pj_scan_is_eof(&scanner) || IS_NEWLINE(*scanner.curptr)) {
898
pj_scan_fini(&scanner);
902
/* Still have some characters unparsed. */
903
pj_scan_fini(&scanner);
908
static void parse_sip_version(pj_scanner *scanner)
910
pj_str_t SIP = { "SIP", 3 };
911
pj_str_t V2 = { "2.0", 3 };
912
pj_str_t sip, version;
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);
922
static pj_bool_t is_next_sip_version(pj_scanner *scanner)
924
pj_str_t SIP = { "SIP", 3 };
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"!
934
return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0;
937
/* Internal function to parse SIP message */
938
static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
939
pjsip_parser_err_report *err_list)
941
pj_bool_t parsing_headers;
942
pjsip_msg *msg = NULL;
944
pjsip_ctype_hdr *ctype_hdr = NULL;
945
pj_scanner *scanner = ctx->scanner;
946
pj_pool_t *pool = ctx->pool;
949
parsing_headers = PJ_FALSE;
957
/* Skip leading newlines. */
958
while (IS_NEWLINE(*scanner->curptr)) {
959
pj_scan_get_newline(scanner);
962
/* Check if we still have valid packet.
963
* Sometimes endpoints just send blank (CRLF) packets just to keep
966
if (pj_scan_is_eof(scanner))
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 );
974
msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
975
int_parse_req_line(scanner, pool, &msg->line.req );
978
parsing_headers = PJ_TRUE;
983
pjsip_parse_hdr_func * handler;
984
pjsip_hdr *hdr = NULL;
986
/* Init hname just in case parsing fails.
992
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
993
if (pj_scan_get_char( scanner ) != ':') {
994
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
998
handler = find_handler(&hname);
1000
/* Call the handler if found.
1001
* If no handler is found, then treat the header as generic
1002
* hname/hvalue pair.
1005
hdr = (*handler)(ctx);
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
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
1017
if (hdr && hdr->type == PJSIP_H_CONTENT_TYPE) {
1018
ctype_hdr = (pjsip_ctype_hdr*)hdr;
1022
hdr = parse_hdr_generic_string(ctx);
1023
hdr->name = hdr->sname = hname;
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.
1034
pj_list_insert_nodes_before(&msg->hdr, hdr);
1036
/* Parse until EOF or an empty line is found. */
1037
} while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr));
1039
parsing_headers = PJ_FALSE;
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);
1048
/* If we have Content-Type header, treat the rest of the message
1051
if (ctype_hdr && scanner->curptr!=scanner->end) {
1052
/* New: if Content-Type indicates that this is a multipart
1053
* message body, parse it.
1055
const pj_str_t STR_MULTIPART = { "multipart", 9 };
1056
pjsip_msg_body *body;
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);
1063
body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body);
1064
pjsip_media_type_cp(pool, &body->content_type,
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;
1078
/* Exception was thrown during parsing.
1079
* Skip until newline, and parse next header.
1082
pjsip_parser_err_report *err_info;
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");
1096
err_info->hname.slen = 0;
1098
pj_list_insert_before(err_list, err_info);
1101
if (parsing_headers) {
1102
if (!pj_scan_is_eof(scanner)) {
1103
/* Skip until next line.
1104
* Watch for header continuation.
1107
pj_scan_skip_line(scanner);
1108
} while (IS_SPACE(*scanner->curptr));
1111
/* Restore flag. Flag may be set in int_parse_sip_url() */
1112
scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
1114
/* Continue parse next header, if any. */
1115
if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) {
1128
/* Parse parameter (pname ["=" pvalue]). */
1129
static 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,
1135
parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
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) {
1152
} else if (*scanner->curptr == '[') {
1153
/* pvalue can be a quoted IPv6; in this case, the
1154
* '[' and ']' quote characters are to be removed
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);
1167
/* Parse parameter (pname ["=" pvalue]) using token. */
1168
PJ_DEF(void) pjsip_parse_param_imp(pj_scanner *scanner, pj_pool_t *pool,
1169
pj_str_t *pname, pj_str_t *pvalue,
1172
parse_param_imp(scanner, pool, pname, pvalue, &pconst.pjsip_TOKEN_SPEC,
1173
&pconst.pjsip_TOKEN_SPEC_ESC, option);
1177
/* Parse parameter (pname ["=" pvalue]) using paramchar. */
1178
PJ_DEF(void) pjsip_parse_uri_param_imp( pj_scanner *scanner, pj_pool_t *pool,
1179
pj_str_t *pname, pj_str_t *pvalue,
1182
parse_param_imp(scanner,pool, pname, pvalue, &pconst.pjsip_PARAM_CHAR_SPEC,
1183
&pconst.pjsip_PARAM_CHAR_SPEC_ESC, option);
1187
/* Parse parameter (";" pname ["=" pvalue]) in SIP header. */
1188
static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool,
1189
pj_str_t *pname, pj_str_t *pvalue,
1192
/* Get ';' character */
1193
pj_scan_get_char(scanner);
1195
/* Get pname and optionally pvalue */
1196
pjsip_parse_param_imp(scanner, pool, pname, pvalue, option);
1199
/* Parse parameter (";" pname ["=" pvalue]) in URI. */
1200
static void int_parse_uri_param( pj_scanner *scanner, pj_pool_t *pool,
1201
pj_str_t *pname, pj_str_t *pvalue,
1204
/* Get ';' character */
1205
pj_scan_get_char(scanner);
1207
/* Get pname and optionally pvalue */
1208
pjsip_parse_uri_param_imp(scanner, pool, pname, pvalue,
1213
/* Parse header parameter. */
1214
static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool,
1215
pj_str_t *hname, pj_str_t *hvalue )
1217
/* Get '?' or '&' character. */
1218
pj_scan_get_char(scanner);
1221
parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1222
&pconst.pjsip_HDR_CHAR_SPEC_ESC, hname);
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))
1234
parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1235
&pconst.pjsip_HDR_CHAR_SPEC_ESC, hvalue);
1241
* host = hostname / IPv4address / IPv6reference
1243
static void int_parse_host(pj_scanner *scanner, pj_str_t *host)
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);
1251
pj_scan_get( scanner, &pconst.pjsip_HOST_SPEC, host);
1255
/* Parse host:port in URI. */
1256
static void int_parse_uri_host_port( pj_scanner *scanner,
1257
pj_str_t *host, int *p_port)
1259
int_parse_host(scanner, host);
1261
/* RFC3261 section 19.1.2: host don't need to be unescaped */
1262
if (*scanner->curptr == ':') {
1264
pj_scan_get_char(scanner);
1265
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &port);
1266
*p_port = pj_strtoul(&port);
1272
/* Determine if the next token in an URI is a user specification. */
1273
static int int_is_next_user(pj_scanner *scanner)
1278
/* Find character '@'. If this character exist, then the token
1279
* must be a username.
1281
if (pj_scan_peek( scanner, &pconst.pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
1289
/* Parse user:pass tokens in an URI. */
1290
static void int_parse_user_pass( pj_scanner *scanner, pj_pool_t *pool,
1291
pj_str_t *user, pj_str_t *pass)
1293
parser_get_and_unescape(scanner, pool, &pconst.pjsip_USER_SPEC_LENIENT,
1294
&pconst.pjsip_USER_SPEC_LENIENT_ESC, user);
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);
1306
pj_scan_get_char( scanner );
1309
/* Parse all types of URI. */
1310
static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool,
1314
int is_name_addr = 0;
1316
/* Exhaust any whitespaces. */
1317
pj_scan_skip_whitespace(scanner);
1319
if (*scanner->curptr=='"' || *scanner->curptr=='<') {
1320
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
1326
next_ch = pj_scan_peek( scanner, &pconst.pjsip_DISPLAY_SPEC, &scheme);
1329
pjsip_parse_uri_func *func = find_uri_handler(&scheme);
1332
/* Unsupported URI scheme */
1333
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1337
(*func)(scanner, pool,
1338
(opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)==0);
1342
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
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;
1352
name_addr = pjsip_name_addr_create(pool);
1353
name_addr->uri = uri;
1355
uri = (pjsip_uri*)name_addr;
1363
static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool,
1364
pj_bool_t parse_params)
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 );
1376
pjsip_parse_uri_func *func;
1379
colon = pj_scan_peek(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1381
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1384
func = find_uri_handler(&scheme);
1386
return (pjsip_uri*)(*func)(scanner, pool, parse_params);
1389
/* Unsupported URI scheme */
1390
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1391
UNREACHED({ return NULL; /* Not reached. */ })
1399
/* Parse "sip:" and "sips:" URI.
1400
* This actually returns (pjsip_sip_uri*) type,
1402
static void* int_parse_sip_url( pj_scanner *scanner,
1404
pj_bool_t parse_params)
1407
pjsip_sip_uri *url = NULL;
1409
int skip_ws = scanner->skip_ws;
1410
scanner->skip_ws = 0;
1412
pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1413
colon = pj_scan_get_char(scanner);
1415
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1418
if (parser_stricmp(scheme, pconst.pjsip_SIP_STR)==0) {
1419
url = pjsip_sip_uri_create(pool, 0);
1421
} else if (parser_stricmp(scheme, pconst.pjsip_SIPS_STR)==0) {
1422
url = pjsip_sip_uri_create(pool, 1);
1425
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1426
/* should not reach here */
1433
if (int_is_next_user(scanner)) {
1434
int_parse_user_pass(scanner, pool, &url->user, &url->passwd);
1438
int_parse_uri_host_port(scanner, &url->host, &url->port);
1440
/* Get URL parameters. */
1442
while (*scanner->curptr == ';' ) {
1443
pj_str_t pname, pvalue;
1445
int_parse_uri_param( scanner, pool, &pname, &pvalue, 0);
1447
if (!parser_stricmp(pname, pconst.pjsip_USER_STR) && pvalue.slen) {
1448
url->user_param = pvalue;
1450
} else if (!parser_stricmp(pname, pconst.pjsip_METHOD_STR) && pvalue.slen) {
1451
url->method_param = pvalue;
1453
} else if (!parser_stricmp(pname, pconst.pjsip_TRANSPORT_STR) && pvalue.slen) {
1454
url->transport_param = pvalue;
1456
} else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
1457
url->ttl_param = pj_strtoul(&pvalue);
1459
} else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
1460
url->maddr_param = pvalue;
1462
} else if (!parser_stricmp(pname, pconst.pjsip_LR_STR)) {
1466
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1469
pj_list_insert_before(&url->other_param, p);
1474
/* Get header params. */
1475
if (parse_params && *scanner->curptr == '?') {
1478
param = PJ_POOL_ALLOC_T(pool, pjsip_param);
1479
int_parse_hparam(scanner, pool, ¶m->name, ¶m->value);
1480
pj_list_insert_before(&url->header_param, param);
1481
} while (*scanner->curptr == '&');
1484
scanner->skip_ws = skip_ws;
1485
pj_scan_skip_whitespace(scanner);
1489
/* Parse nameaddr. */
1490
static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
1494
pjsip_name_addr *name_addr;
1496
name_addr = pjsip_name_addr_create(pool);
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;
1504
} else if (*scanner->curptr != '<') {
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.
1513
next = pj_scan_peek(scanner, &pconst.pjsip_DISPLAY_SPEC, &dummy);
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);
1521
/* Manually skip whitespace. */
1522
pj_scan_skip_whitespace(scanner);
1524
/* Get the SIP-URL */
1525
has_bracket = (*scanner->curptr == '<');
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.
1533
PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1535
name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
1537
if (pj_scan_get_char(scanner) != '>')
1538
PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1545
/* Parse other URI */
1546
static void* int_parse_other_uri(pj_scanner *scanner,
1548
pj_bool_t parse_params)
1550
pjsip_other_uri *uri = 0;
1551
const pjsip_parser_const_t *pc = pjsip_parser_const();
1552
int skip_ws = scanner->skip_ws;
1554
PJ_UNUSED_ARG(parse_params);
1556
scanner->skip_ws = 0;
1558
uri = pjsip_other_uri_create(pool);
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);
1565
pj_scan_get(scanner, &pc->pjsip_OTHER_URI_CONTENT, &uri->content);
1566
scanner->skip_ws = skip_ws;
1572
/* Parse SIP request line. */
1573
static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool,
1574
pjsip_request_line *req_line)
1578
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &token);
1579
pjsip_method_init_np( &req_line->method, &token);
1581
req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
1582
parse_sip_version(scanner);
1583
pj_scan_get_newline( scanner );
1586
/* Parse status line. */
1587
static void int_parse_status_line( pj_scanner *scanner,
1588
pjsip_status_line *status_line)
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);
1598
status_line->reason.slen=0, status_line->reason.ptr=NULL;
1599
pj_scan_get_newline( scanner );
1604
* Public API to parse SIP status line.
1606
PJ_DEF(pj_status_t) pjsip_parse_status_line( char *buf, pj_size_t size,
1607
pjsip_status_line *status_line)
1612
pj_bzero(status_line, sizeof(*status_line));
1613
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
1617
int_parse_status_line(&scanner, status_line);
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;
1628
pj_scan_fini(&scanner);
1633
/* Parse ending of header. */
1634
static void parse_hdr_end( pj_scanner *scanner )
1636
if (pj_scan_is_eof(scanner)) {
1638
} else if (*scanner->curptr == '&') {
1639
pj_scan_get_char(scanner);
1641
pj_scan_get_newline(scanner);
1645
/* Parse ending of header. */
1646
PJ_DEF(void) pjsip_parse_end_hdr_imp( pj_scanner *scanner )
1648
parse_hdr_end(scanner);
1651
/* Parse generic array header. */
1652
static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
1653
pj_scanner *scanner)
1655
/* Some header fields allow empty elements in the value:
1656
* Accept, Allow, Supported
1658
if (pj_scan_is_eof(scanner) ||
1659
*scanner->curptr == '\r' || *scanner->curptr == '\n')
1664
if (hdr->count >= PJ_ARRAY_SIZE(hdr->values)) {
1665
/* Too many elements */
1666
on_syntax_error(scanner);
1670
pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
1671
&hdr->values[hdr->count]);
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]);
1680
if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT)
1685
parse_hdr_end(scanner);
1688
/* Parse generic array header. */
1689
PJ_DEF(void) pjsip_parse_generic_array_hdr_imp( pjsip_generic_array_hdr *hdr,
1690
pj_scanner *scanner)
1692
parse_generic_array_hdr(hdr, scanner);
1696
/* Parse generic string header. */
1697
static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
1698
pjsip_parse_ctx *ctx)
1700
pj_scanner *scanner = ctx->scanner;
1702
hdr->hvalue.slen = 0;
1704
/* header may be mangled hence the loop */
1705
while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) {
1708
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue);
1709
if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr))
1711
/* mangled, get next fraction */
1712
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next);
1714
tmp.ptr = (char*)pj_pool_alloc(ctx->pool,
1715
hdr->hvalue.slen + next.slen + 2);
1717
pj_strcpy(&tmp, &hdr->hvalue);
1718
pj_strcat2(&tmp, " ");
1719
pj_strcat(&tmp, &next);
1720
tmp.ptr[tmp.slen] = '\0';
1725
parse_hdr_end(scanner);
1728
/* Parse generic integer header. */
1729
static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr,
1730
pj_scanner *scanner )
1733
pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
1734
hdr->ivalue = pj_strtoul(&tmp);
1735
parse_hdr_end(scanner);
1739
/* Parse Accept header. */
1740
static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx)
1742
pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool);
1743
parse_generic_array_hdr(accept, ctx->scanner);
1744
return (pjsip_hdr*)accept;
1747
/* Parse Allow header. */
1748
static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx)
1750
pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool);
1751
parse_generic_array_hdr(allow, ctx->scanner);
1752
return (pjsip_hdr*)allow;
1755
/* Parse Call-ID header. */
1756
static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx)
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);
1763
ctx->rdata->msg_info.cid = hdr;
1765
return (pjsip_hdr*)hdr;
1768
/* Parse and interpret Contact param. */
1769
static void int_parse_contact_param( pjsip_contact_hdr *hdr,
1770
pj_scanner *scanner,
1773
while ( *scanner->curptr == ';' ) {
1774
pj_str_t pname, pvalue;
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);
1780
hdr->q1000 = pj_strtoul(&pvalue) * 1000;
1782
pj_str_t tmp = pvalue;
1784
tmp.slen = dot_pos - pvalue.ptr;
1785
hdr->q1000 = pj_strtoul(&tmp) * 1000;
1787
pvalue.slen = (pvalue.ptr+pvalue.slen) - (dot_pos+1);
1788
pvalue.ptr = dot_pos + 1;
1789
hdr->q1000 += pj_strtoul_mindigit(&pvalue, 3);
1791
} else if (!parser_stricmp(pname, pconst.pjsip_EXPIRES_STR) && pvalue.slen) {
1792
hdr->expires = pj_strtoul(&pvalue);
1795
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1798
pj_list_insert_before(&hdr->other_param, p);
1803
/* Parse Contact header. */
1804
static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx )
1806
pjsip_contact_hdr *first = NULL;
1807
pj_scanner *scanner = ctx->scanner;
1810
pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool);
1814
pj_list_insert_before(first, hdr);
1816
if (*scanner->curptr == '*') {
1817
pj_scan_get_char(scanner);
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);
1826
int_parse_contact_param(hdr, scanner, ctx->pool);
1829
if (*scanner->curptr != ',')
1832
pj_scan_get_char(scanner);
1836
parse_hdr_end(scanner);
1838
return (pjsip_hdr*)first;
1841
/* Parse Content-Length header. */
1842
static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx )
1845
pjsip_clen_hdr *hdr;
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);
1853
ctx->rdata->msg_info.clen = hdr;
1855
return (pjsip_hdr*)hdr;
1858
/* Parse Content-Type header. */
1859
static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx )
1861
pjsip_ctype_hdr *hdr;
1862
pj_scanner *scanner = ctx->scanner;
1864
hdr = pjsip_ctype_hdr_create(ctx->pool);
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);
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, ¶m->name, ¶m->value, 0);
1875
pj_list_push_back(&hdr->media.param, param);
1878
parse_hdr_end(ctx->scanner);
1881
ctx->rdata->msg_info.ctype = hdr;
1883
return (pjsip_hdr*)hdr;
1886
/* Parse CSeq header. */
1887
static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx )
1889
pj_str_t cseq, method;
1890
pjsip_cseq_hdr *hdr;
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);
1896
pj_scan_get( ctx->scanner, &pconst.pjsip_TOKEN_SPEC, &method);
1897
pjsip_method_init_np(&hdr->method, &method);
1899
parse_hdr_end( ctx->scanner );
1902
ctx->rdata->msg_info.cseq = hdr;
1904
return (pjsip_hdr*)hdr;
1907
/* Parse Expires header. */
1908
static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx)
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;
1915
/* Parse From: or To: header. */
1916
static void parse_hdr_fromto( pj_scanner *scanner,
1918
pjsip_from_hdr *hdr)
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);
1924
while ( *scanner->curptr == ';' ) {
1925
pj_str_t pname, pvalue;
1927
int_parse_param( scanner, pool, &pname, &pvalue, 0);
1929
if (!parser_stricmp(pname, pconst.pjsip_TAG_STR)) {
1933
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1936
pj_list_insert_before(&hdr->other_param, p);
1940
parse_hdr_end(scanner);
1943
/* Parse From: header. */
1944
static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
1946
pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool);
1947
parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
1949
ctx->rdata->msg_info.from = hdr;
1951
return (pjsip_hdr*)hdr;
1954
/* Parse Require: header. */
1955
static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
1957
pjsip_require_hdr *hdr;
1958
pj_bool_t new_hdr = (ctx->rdata==NULL ||
1959
ctx->rdata->msg_info.require == NULL);
1961
if (ctx->rdata && ctx->rdata->msg_info.require) {
1962
hdr = ctx->rdata->msg_info.require;
1964
hdr = pjsip_require_hdr_create(ctx->pool);
1966
ctx->rdata->msg_info.require = hdr;
1969
parse_generic_array_hdr(hdr, ctx->scanner);
1971
return new_hdr ? (pjsip_hdr*)hdr : NULL;
1974
/* Parse Retry-After: header. */
1975
static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
1977
pjsip_retry_after_hdr *hdr;
1978
pj_scanner *scanner = ctx->scanner;
1981
hdr = pjsip_retry_after_hdr_create(ctx->pool, 0);
1983
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
1984
hdr->ivalue = pj_strtoul(&tmp);
1986
while (!pj_scan_is_eof(scanner) && *scanner->curptr!='\r' &&
1987
*scanner->curptr!='\n')
1989
if (*scanner->curptr=='(') {
1990
pj_scan_get_quote(scanner, '(', ')', &hdr->comment);
1991
/* Trim the leading and ending parens */
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);
2001
parse_hdr_end(scanner);
2002
return (pjsip_hdr*)hdr;
2005
/* Parse Supported: header. */
2006
static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
2008
pjsip_supported_hdr *hdr;
2009
pj_bool_t new_hdr = (ctx->rdata==NULL ||
2010
ctx->rdata->msg_info.supported == NULL);
2012
if (ctx->rdata && ctx->rdata->msg_info.supported) {
2013
hdr = ctx->rdata->msg_info.supported;
2015
hdr = pjsip_supported_hdr_create(ctx->pool);
2017
ctx->rdata->msg_info.supported = hdr;
2020
parse_generic_array_hdr(hdr, ctx->scanner);
2021
return new_hdr ? (pjsip_hdr*)hdr : NULL;
2024
/* Parse To: header. */
2025
static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
2027
pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool);
2028
parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
2031
ctx->rdata->msg_info.to = hdr;
2033
return (pjsip_hdr*)hdr;
2036
/* Parse Unsupported: header. */
2037
static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx)
2039
pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool);
2040
parse_generic_array_hdr(hdr, ctx->scanner);
2041
return (pjsip_hdr*)hdr;
2044
/* Parse and interpret Via parameters. */
2045
static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
2048
while ( *scanner->curptr == ';' ) {
2049
pj_str_t pname, pvalue;
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,
2067
if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
2068
hdr->branch_param = pvalue;
2070
} else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
2071
hdr->ttl_param = pj_strtoul(&pvalue);
2073
} else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
2074
hdr->maddr_param = pvalue;
2076
} else if (!parser_stricmp(pname, pconst.pjsip_RECEIVED_STR) && pvalue.slen) {
2077
hdr->recvd_param = pvalue;
2079
} else if (!parser_stricmp(pname, pconst.pjsip_RPORT_STR)) {
2081
hdr->rport_param = pj_strtoul(&pvalue);
2083
hdr->rport_param = 0;
2085
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2088
pj_list_insert_before(&hdr->other_param, p);
2093
/* Parse Max-Forwards header. */
2094
static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx )
2096
pjsip_max_fwd_hdr *hdr;
2097
hdr = pjsip_max_fwd_hdr_create(ctx->pool, 0);
2098
parse_generic_int_hdr(hdr, ctx->scanner);
2101
ctx->rdata->msg_info.max_fwd = hdr;
2103
return (pjsip_hdr*)hdr;
2106
/* Parse Min-Expires header. */
2107
static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx)
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;
2116
/* Parse Route: or Record-Route: header. */
2117
static void parse_hdr_rr_route( pj_scanner *scanner, pj_pool_t *pool,
2118
pjsip_routing_hdr *hdr )
2120
pjsip_name_addr *temp=int_parse_name_addr(scanner, pool);
2122
pj_memcpy(&hdr->name_addr, temp, sizeof(*temp));
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);
2131
/* Parse Record-Route header. */
2132
static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx)
2134
pjsip_rr_hdr *first = NULL;
2135
pj_scanner *scanner = ctx->scanner;
2138
pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool);
2142
pj_list_insert_before(first, hdr);
2144
parse_hdr_rr_route(scanner, ctx->pool, hdr);
2145
if (*scanner->curptr == ',') {
2146
pj_scan_get_char(scanner);
2151
parse_hdr_end(scanner);
2153
if (ctx->rdata && ctx->rdata->msg_info.record_route==NULL)
2154
ctx->rdata->msg_info.record_route = first;
2156
return (pjsip_hdr*)first;
2159
/* Parse Route: header. */
2160
static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx )
2162
pjsip_route_hdr *first = NULL;
2163
pj_scanner *scanner = ctx->scanner;
2166
pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool);
2170
pj_list_insert_before(first, hdr);
2172
parse_hdr_rr_route(scanner, ctx->pool, hdr);
2173
if (*scanner->curptr == ',') {
2174
pj_scan_get_char(scanner);
2179
parse_hdr_end(scanner);
2181
if (ctx->rdata && ctx->rdata->msg_info.route==NULL)
2182
ctx->rdata->msg_info.route = first;
2184
return (pjsip_hdr*)first;
2187
/* Parse Via: header. */
2188
static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
2190
pjsip_via_hdr *first = NULL;
2191
pj_scanner *scanner = ctx->scanner;
2194
pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool);
2198
pj_list_insert_before(first, hdr);
2200
parse_sip_version(scanner);
2201
if (pj_scan_get_char(scanner) != '/')
2202
on_syntax_error(scanner);
2204
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport);
2205
int_parse_host(scanner, &hdr->sent_by.host);
2207
if (*scanner->curptr==':') {
2209
pj_scan_get_char(scanner);
2210
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &digit);
2211
hdr->sent_by.port = pj_strtoul(&digit);
2214
int_parse_via_param(hdr, scanner, ctx->pool);
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 );
2222
if (*scanner->curptr != ',')
2225
pj_scan_get_char(scanner);
2229
parse_hdr_end(scanner);
2231
if (ctx->rdata && ctx->rdata->msg_info.via == NULL)
2232
ctx->rdata->msg_info.via = first;
2234
return (pjsip_hdr*)first;
2237
/* Parse generic header. */
2238
static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
2240
pjsip_generic_string_hdr *hdr;
2242
hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL);
2243
parse_generic_string_hdr(hdr, ctx);
2244
return (pjsip_hdr*)hdr;
2248
/* Public function to parse a header value. */
2249
PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
2250
char *buf, pj_size_t size, int *parsed_len )
2253
pjsip_hdr *hdr = NULL;
2254
pjsip_parse_ctx context;
2257
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2260
context.scanner = &scanner;
2261
context.pool = pool;
2262
context.rdata = NULL;
2265
pjsip_parse_hdr_func *handler = find_handler(hname);
2267
hdr = (*handler)(&context);
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;
2282
*parsed_len = (unsigned)(scanner.curptr - scanner.begin);
2285
pj_scan_fini(&scanner);
2290
/* Parse multiple header lines */
2291
PJ_DEF(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input,
2292
pj_size_t size, pjsip_hdr *hlist,
2295
enum { STOP_ON_ERROR = 1 };
2297
pjsip_parse_ctx ctx;
2301
pj_scan_init(&scanner, input, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2304
pj_bzero(&ctx, sizeof(ctx));
2305
ctx.scanner = &scanner;
2311
/* Parse headers. */
2313
pjsip_parse_hdr_func * handler;
2314
pjsip_hdr *hdr = NULL;
2316
/* Init hname just in case parsing fails.
2322
pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
2323
if (pj_scan_get_char( &scanner ) != ':') {
2324
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
2328
handler = find_handler(&hname);
2330
/* Call the handler if found.
2331
* If no handler is found, then treat the header as generic
2332
* hname/hvalue pair.
2335
hdr = (*handler)(&ctx);
2337
hdr = parse_hdr_generic_string(&ctx);
2338
hdr->name = hdr->sname = hname;
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.
2348
pj_list_insert_nodes_before(hlist, hdr);
2350
/* Parse until EOF or an empty line is found. */
2351
} while (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr));
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);
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)));
2366
/* Exception was thrown during parsing. */
2367
if ((options & STOP_ON_ERROR) == STOP_ON_ERROR) {
2368
pj_scan_fini(&scanner);
2369
return PJSIP_EINVALIDHDR;
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.
2378
pj_scan_skip_line(&scanner);
2379
} while (IS_SPACE(*scanner.curptr));
2382
/* Restore flag. Flag may be set in int_parse_sip_url() */
2383
scanner.skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
2385
/* Continue parse next header, if any. */
2386
if (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)) {