1
/* $Id: sip_parser.c 4288 2012-10-26 09:30:37Z bennylp $ */
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
int 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, 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)
599
char hname_lcase[PJSIP_MAX_HNAME_LEN+1];
602
/* Check that name is not too long */
603
len = pj_ansi_strlen(hname);
604
if (len > PJSIP_MAX_HNAME_LEN) {
605
pj_assert(!"Header name is too long!");
606
return PJ_ENAMETOOLONG;
609
/* Register the normal Mixed-Case name */
610
status = int_register_parser(hname, fptr);
611
if (status != PJ_SUCCESS) {
615
/* Get the lower-case name */
616
for (i=0; i<len; ++i) {
617
hname_lcase[i] = (char)pj_tolower(hname[i]);
619
hname_lcase[len] = '\0';
621
/* Register the lower-case version of the name */
622
status = int_register_parser(hname_lcase, fptr);
623
if (status != PJ_SUCCESS) {
628
/* Register the shortname version of the name */
630
status = int_register_parser(hshortname, fptr);
631
if (status != PJ_SUCCESS)
638
/* Find handler to parse the header name. */
639
static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t hash,
640
const pj_str_t *hname)
646
/* Binary search for the handler. */
651
unsigned half = n / 2;
652
handler_rec *mid = first + half;
654
comp = compare_handler(mid, hname->ptr, hname->slen, hash);
658
} else if (comp==0) {
666
return comp==0 ? first->handler : NULL;
670
/* Find handler to parse the header name. */
671
static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname)
674
char hname_copy[PJSIP_MAX_HNAME_LEN];
676
pjsip_parse_hdr_func *handler;
678
if (hname->slen >= PJSIP_MAX_HNAME_LEN) {
679
/* Guaranteed not to be able to find handler. */
683
/* First, common case, try to find handler with exact name */
684
hash = pj_hash_calc(0, hname->ptr, hname->slen);
685
handler = find_handler_imp(hash, hname);
690
/* If not found, try converting the header name to lowercase and
693
hash = pj_hash_calc_tolower(0, hname_copy, hname);
694
tmp.ptr = hname_copy;
695
tmp.slen = hname->slen;
696
return find_handler_imp(hash, &tmp);
700
/* Find URI handler. */
701
static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme)
704
for (i=0; i<uri_handler_count; ++i) {
705
if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0)
706
return uri_handler[i].parse;
708
return &int_parse_other_uri;
711
/* Register URI parser. */
712
PJ_DEF(pj_status_t) pjsip_register_uri_parser( char *scheme,
713
pjsip_parse_uri_func *func)
715
if (uri_handler_count >= PJ_ARRAY_SIZE(uri_handler))
718
uri_handler[uri_handler_count].scheme = pj_str((char*)scheme);
719
uri_handler[uri_handler_count].parse = func;
725
/* Public function to parse SIP message. */
726
PJ_DEF(pjsip_msg*) pjsip_parse_msg( pj_pool_t *pool,
727
char *buf, pj_size_t size,
728
pjsip_parser_err_report *err_list)
730
pjsip_msg *msg = NULL;
732
pjsip_parse_ctx context;
734
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
737
context.scanner = &scanner;
739
context.rdata = NULL;
741
msg = int_parse_msg(&context, err_list);
743
pj_scan_fini(&scanner);
747
/* Public function to parse as rdata.*/
748
PJ_DEF(pjsip_msg *) pjsip_parse_rdata( char *buf, pj_size_t size,
749
pjsip_rx_data *rdata )
752
pjsip_parse_ctx context;
754
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
757
context.scanner = &scanner;
758
context.pool = rdata->tp_info.pool;
759
context.rdata = rdata;
761
rdata->msg_info.msg = int_parse_msg(&context, &rdata->msg_info.parse_err);
763
pj_scan_fini(&scanner);
764
return rdata->msg_info.msg;
767
/* Determine if a message has been received. */
768
PJ_DEF(pj_bool_t) pjsip_find_msg( const char *buf, pj_size_t size,
769
pj_bool_t is_datagram, pj_size_t *msg_size)
773
const char *body_start;
776
int content_length = -1;
778
const pj_str_t end_hdr = { "\n\r\n", 3};
782
/* For datagram, the whole datagram IS the message. */
788
/* Find the end of header area by finding an empty line.
789
* Don't use plain strstr() since we want to be able to handle
790
* NULL character in the message
792
cur_msg.ptr = (char*)buf; cur_msg.slen = size;
793
pos = pj_strstr(&cur_msg, &end_hdr);
795
return PJSIP_EPARTIALMSG;
801
/* Find "Content-Length" header the hard way. */
802
line = pj_strchr(&cur_msg, '\n');
803
while (line && line < hdr_end) {
805
if ( ((*line=='C' || *line=='c') &&
806
strnicmp_alnum(line, "Content-Length", 14) == 0) ||
807
((*line=='l' || *line=='L') &&
808
(*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
810
/* Try to parse the header. */
814
pj_scan_init(&scanner, (char*)line, hdr_end-line,
815
PJ_SCAN_AUTOSKIP_WS_HEADER, &on_syntax_error);
820
/* Get "Content-Length" or "L" name */
821
if (*line=='C' || *line=='c')
822
pj_scan_advance_n(&scanner, 14, PJ_TRUE);
823
else if (*line=='l' || *line=='L')
824
pj_scan_advance_n(&scanner, 1, PJ_TRUE);
827
if (pj_scan_get_char(&scanner) != ':') {
828
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
832
pj_scan_get(&scanner, &pconst.pjsip_DIGIT_SPEC, &str_clen);
835
pj_scan_get_newline(&scanner);
837
/* Found a valid Content-Length header. */
838
content_length = pj_strtoul(&str_clen);
845
pj_scan_fini(&scanner);
848
/* Found valid Content-Length? */
849
if (content_length != -1)
852
/* Go to next line. */
853
cur_msg.slen -= (line - cur_msg.ptr);
854
cur_msg.ptr = (char*)line;
855
line = pj_strchr(&cur_msg, '\n');
858
/* Found Content-Length? */
859
if (content_length == -1) {
860
return PJSIP_EMISSINGHDR;
863
/* Enough packet received? */
864
*msg_size = (body_start - buf) + content_length;
865
return (*msg_size) <= size ? PJ_SUCCESS : PJSIP_EPARTIALMSG;
868
PJ_UNUSED_ARG(is_datagram);
874
/* Public function to parse URI */
875
PJ_DEF(pjsip_uri*) pjsip_parse_uri( pj_pool_t *pool,
876
char *buf, pj_size_t size,
880
pjsip_uri *uri = NULL;
883
pj_scan_init(&scanner, buf, size, 0, &on_syntax_error);
887
uri = int_parse_uri_or_name_addr(&scanner, pool, option);
894
/* Must have exhausted all inputs. */
895
if (pj_scan_is_eof(&scanner) || IS_NEWLINE(*scanner.curptr)) {
897
pj_scan_fini(&scanner);
901
/* Still have some characters unparsed. */
902
pj_scan_fini(&scanner);
907
static void parse_sip_version(pj_scanner *scanner)
909
pj_str_t SIP = { "SIP", 3 };
910
pj_str_t V2 = { "2.0", 3 };
911
pj_str_t sip, version;
913
pj_scan_get( scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
914
if (pj_scan_get_char(scanner) != '/')
915
on_syntax_error(scanner);
916
pj_scan_get_n( scanner, 3, &version);
917
if (pj_stricmp(&sip, &SIP) || pj_stricmp(&version, &V2))
918
on_syntax_error(scanner);
921
static pj_bool_t is_next_sip_version(pj_scanner *scanner)
923
pj_str_t SIP = { "SIP", 3 };
927
c = pj_scan_peek(scanner, &pconst.pjsip_ALPHA_SPEC, &sip);
928
/* return TRUE if it is "SIP" followed by "/" or space.
929
* we include space since the "/" may be separated by space,
930
* although this would mean it would return TRUE if it is a
931
* request and the method is "SIP"!
933
return c && (c=='/' || c==' ' || c=='\t') && pj_stricmp(&sip, &SIP)==0;
936
/* Internal function to parse SIP message */
937
static pjsip_msg *int_parse_msg( pjsip_parse_ctx *ctx,
938
pjsip_parser_err_report *err_list)
940
pj_bool_t parsing_headers;
941
pjsip_msg *msg = NULL;
943
pjsip_ctype_hdr *ctype_hdr = NULL;
944
pj_scanner *scanner = ctx->scanner;
945
pj_pool_t *pool = ctx->pool;
948
parsing_headers = PJ_FALSE;
956
/* Skip leading newlines. */
957
while (IS_NEWLINE(*scanner->curptr)) {
958
pj_scan_get_newline(scanner);
961
/* Check if we still have valid packet.
962
* Sometimes endpoints just send blank (CRLF) packets just to keep
965
if (pj_scan_is_eof(scanner))
968
/* Parse request or status line */
969
if (is_next_sip_version(scanner)) {
970
msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
971
int_parse_status_line( scanner, &msg->line.status );
973
msg = pjsip_msg_create(pool, PJSIP_REQUEST_MSG);
974
int_parse_req_line(scanner, pool, &msg->line.req );
977
parsing_headers = PJ_TRUE;
982
pjsip_parse_hdr_func * handler;
983
pjsip_hdr *hdr = NULL;
985
/* Init hname just in case parsing fails.
991
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
992
if (pj_scan_get_char( scanner ) != ':') {
993
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
997
handler = find_handler(&hname);
999
/* Call the handler if found.
1000
* If no handler is found, then treat the header as generic
1001
* hname/hvalue pair.
1004
hdr = (*handler)(ctx);
1007
* hdr MAY BE NULL, if parsing does not yield a new header
1008
* instance, e.g. the values have been added to existing
1009
* header. See http://trac.pjsip.org/repos/ticket/940
1012
/* Check if we've just parsed a Content-Type header.
1013
* We will check for a message body if we've got Content-Type
1016
if (hdr && hdr->type == PJSIP_H_CONTENT_TYPE) {
1017
ctype_hdr = (pjsip_ctype_hdr*)hdr;
1021
hdr = parse_hdr_generic_string(ctx);
1022
hdr->name = hdr->sname = hname;
1026
/* Single parse of header line can produce multiple headers.
1027
* For example, if one Contact: header contains Contact list
1028
* separated by comma, then these Contacts will be split into
1029
* different Contact headers.
1030
* So here we must insert list instead of just insert one header.
1033
pj_list_insert_nodes_before(&msg->hdr, hdr);
1035
/* Parse until EOF or an empty line is found. */
1036
} while (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr));
1038
parsing_headers = PJ_FALSE;
1040
/* If empty line is found, eat it. */
1041
if (!pj_scan_is_eof(scanner)) {
1042
if (IS_NEWLINE(*scanner->curptr)) {
1043
pj_scan_get_newline(scanner);
1047
/* If we have Content-Type header, treat the rest of the message
1050
if (ctype_hdr && scanner->curptr!=scanner->end) {
1051
/* New: if Content-Type indicates that this is a multipart
1052
* message body, parse it.
1054
const pj_str_t STR_MULTIPART = { "multipart", 9 };
1055
pjsip_msg_body *body;
1057
if (pj_stricmp(&ctype_hdr->media.type, &STR_MULTIPART)==0) {
1058
body = pjsip_multipart_parse(pool, scanner->curptr,
1059
scanner->end - scanner->curptr,
1060
&ctype_hdr->media, 0);
1062
body = PJ_POOL_ALLOC_T(pool, pjsip_msg_body);
1063
pjsip_media_type_cp(pool, &body->content_type,
1066
body->data = scanner->curptr;
1067
body->len = scanner->end - scanner->curptr;
1068
body->print_body = &pjsip_print_text_body;
1069
body->clone_data = &pjsip_clone_text_data;
1077
/* Exception was thrown during parsing.
1078
* Skip until newline, and parse next header.
1081
pjsip_parser_err_report *err_info;
1083
err_info = PJ_POOL_ALLOC_T(pool, pjsip_parser_err_report);
1084
err_info->except_code = PJ_GET_EXCEPTION();
1085
err_info->line = scanner->line;
1086
/* Scanner's column is zero based, so add 1 */
1087
err_info->col = pj_scan_get_col(scanner) + 1;
1088
if (parsing_headers)
1089
err_info->hname = hname;
1090
else if (msg && msg->type == PJSIP_REQUEST_MSG)
1091
err_info->hname = pj_str("Request Line");
1092
else if (msg && msg->type == PJSIP_RESPONSE_MSG)
1093
err_info->hname = pj_str("Status Line");
1095
err_info->hname.slen = 0;
1097
pj_list_insert_before(err_list, err_info);
1100
if (parsing_headers) {
1101
if (!pj_scan_is_eof(scanner)) {
1102
/* Skip until next line.
1103
* Watch for header continuation.
1106
pj_scan_skip_line(scanner);
1107
} while (IS_SPACE(*scanner->curptr));
1110
/* Restore flag. Flag may be set in int_parse_sip_url() */
1111
scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
1113
/* Continue parse next header, if any. */
1114
if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) {
1127
/* Parse parameter (pname ["=" pvalue]). */
1128
static void parse_param_imp( pj_scanner *scanner, pj_pool_t *pool,
1129
pj_str_t *pname, pj_str_t *pvalue,
1130
const pj_cis_t *spec, const pj_cis_t *esc_spec,
1134
parser_get_and_unescape(scanner, pool, spec, esc_spec, pname);
1140
/* pvalue, if any */
1141
if (*scanner->curptr == '=') {
1142
pj_scan_get_char(scanner);
1143
if (!pj_scan_is_eof(scanner)) {
1144
/* pvalue can be a quoted string. */
1145
if (*scanner->curptr == '"') {
1146
pj_scan_get_quote( scanner, '"', '"', pvalue);
1147
if (option & PJSIP_PARSE_REMOVE_QUOTE) {
1151
} else if (*scanner->curptr == '[') {
1152
/* pvalue can be a quoted IPv6; in this case, the
1153
* '[' and ']' quote characters are to be removed
1156
pj_scan_get_char(scanner);
1157
pj_scan_get_until_ch(scanner, ']', pvalue);
1158
pj_scan_get_char(scanner);
1159
} else if(pj_cis_match(spec, *scanner->curptr)) {
1160
parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue);
1166
/* Parse parameter (pname ["=" pvalue]) using token. */
1167
PJ_DEF(void) pjsip_parse_param_imp(pj_scanner *scanner, pj_pool_t *pool,
1168
pj_str_t *pname, pj_str_t *pvalue,
1171
parse_param_imp(scanner, pool, pname, pvalue, &pconst.pjsip_TOKEN_SPEC,
1172
&pconst.pjsip_TOKEN_SPEC_ESC, option);
1176
/* Parse parameter (pname ["=" pvalue]) using paramchar. */
1177
PJ_DEF(void) pjsip_parse_uri_param_imp( pj_scanner *scanner, pj_pool_t *pool,
1178
pj_str_t *pname, pj_str_t *pvalue,
1181
parse_param_imp(scanner,pool, pname, pvalue, &pconst.pjsip_PARAM_CHAR_SPEC,
1182
&pconst.pjsip_PARAM_CHAR_SPEC_ESC, option);
1186
/* Parse parameter (";" pname ["=" pvalue]) in SIP header. */
1187
static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool,
1188
pj_str_t *pname, pj_str_t *pvalue,
1191
/* Get ';' character */
1192
pj_scan_get_char(scanner);
1194
/* Get pname and optionally pvalue */
1195
pjsip_parse_param_imp(scanner, pool, pname, pvalue, option);
1198
/* Parse parameter (";" pname ["=" pvalue]) in URI. */
1199
static void int_parse_uri_param( pj_scanner *scanner, pj_pool_t *pool,
1200
pj_str_t *pname, pj_str_t *pvalue,
1203
/* Get ';' character */
1204
pj_scan_get_char(scanner);
1206
/* Get pname and optionally pvalue */
1207
pjsip_parse_uri_param_imp(scanner, pool, pname, pvalue,
1212
/* Parse header parameter. */
1213
static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool,
1214
pj_str_t *hname, pj_str_t *hvalue )
1216
/* Get '?' or '&' character. */
1217
pj_scan_get_char(scanner);
1220
parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1221
&pconst.pjsip_HDR_CHAR_SPEC_ESC, hname);
1227
/* pvalue, if any */
1228
if (*scanner->curptr == '=') {
1229
pj_scan_get_char(scanner);
1230
if (!pj_scan_is_eof(scanner) &&
1231
pj_cis_match(&pconst.pjsip_HDR_CHAR_SPEC, *scanner->curptr))
1233
parser_get_and_unescape(scanner, pool, &pconst.pjsip_HDR_CHAR_SPEC,
1234
&pconst.pjsip_HDR_CHAR_SPEC_ESC, hvalue);
1240
* host = hostname / IPv4address / IPv6reference
1242
static void int_parse_host(pj_scanner *scanner, pj_str_t *host)
1244
if (*scanner->curptr == '[') {
1245
/* Note: the '[' and ']' characters are removed from the host */
1246
pj_scan_get_char(scanner);
1247
pj_scan_get_until_ch(scanner, ']', host);
1248
pj_scan_get_char(scanner);
1250
pj_scan_get( scanner, &pconst.pjsip_HOST_SPEC, host);
1254
/* Parse host:port in URI. */
1255
static void int_parse_uri_host_port( pj_scanner *scanner,
1256
pj_str_t *host, int *p_port)
1258
int_parse_host(scanner, host);
1260
/* RFC3261 section 19.1.2: host don't need to be unescaped */
1261
if (*scanner->curptr == ':') {
1263
pj_scan_get_char(scanner);
1264
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &port);
1265
*p_port = pj_strtoul(&port);
1271
/* Determine if the next token in an URI is a user specification. */
1272
static int int_is_next_user(pj_scanner *scanner)
1277
/* Find character '@'. If this character exist, then the token
1278
* must be a username.
1280
if (pj_scan_peek( scanner, &pconst.pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@')
1288
/* Parse user:pass tokens in an URI. */
1289
static void int_parse_user_pass( pj_scanner *scanner, pj_pool_t *pool,
1290
pj_str_t *user, pj_str_t *pass)
1292
parser_get_and_unescape(scanner, pool, &pconst.pjsip_USER_SPEC_LENIENT,
1293
&pconst.pjsip_USER_SPEC_LENIENT_ESC, user);
1295
if ( *scanner->curptr == ':') {
1296
pj_scan_get_char( scanner );
1297
parser_get_and_unescape(scanner, pool, &pconst.pjsip_PASSWD_SPEC,
1298
&pconst.pjsip_PASSWD_SPEC_ESC, pass);
1305
pj_scan_get_char( scanner );
1308
/* Parse all types of URI. */
1309
static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool,
1313
int is_name_addr = 0;
1315
/* Exhaust any whitespaces. */
1316
pj_scan_skip_whitespace(scanner);
1318
if (*scanner->curptr=='"' || *scanner->curptr=='<') {
1319
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
1325
next_ch = pj_scan_peek( scanner, &pconst.pjsip_DISPLAY_SPEC, &scheme);
1328
pjsip_parse_uri_func *func = find_uri_handler(&scheme);
1331
/* Unsupported URI scheme */
1332
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1336
(*func)(scanner, pool,
1337
(opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)==0);
1341
uri = (pjsip_uri*)int_parse_name_addr( scanner, pool );
1346
/* Should we return the URI object as name address? */
1347
if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) {
1348
if (is_name_addr == 0) {
1349
pjsip_name_addr *name_addr;
1351
name_addr = pjsip_name_addr_create(pool);
1352
name_addr->uri = uri;
1354
uri = (pjsip_uri*)name_addr;
1362
static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool,
1363
pj_bool_t parse_params)
1366
* This function should not call back int_parse_name_addr() because
1367
* it is called by that function. This would cause stack overflow
1368
* with PROTOS test #1223.
1369
if (*scanner->curptr=='"' || *scanner->curptr=='<') {
1370
return (pjsip_uri*)int_parse_name_addr( scanner, pool );
1375
pjsip_parse_uri_func *func;
1378
colon = pj_scan_peek(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1380
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1383
func = find_uri_handler(&scheme);
1385
return (pjsip_uri*)(*func)(scanner, pool, parse_params);
1388
/* Unsupported URI scheme */
1389
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1390
UNREACHED({ return NULL; /* Not reached. */ })
1398
/* Parse "sip:" and "sips:" URI.
1399
* This actually returns (pjsip_sip_uri*) type,
1401
static void* int_parse_sip_url( pj_scanner *scanner,
1403
pj_bool_t parse_params)
1406
pjsip_sip_uri *url = NULL;
1408
int skip_ws = scanner->skip_ws;
1409
scanner->skip_ws = 0;
1411
pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &scheme);
1412
colon = pj_scan_get_char(scanner);
1414
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1417
if (parser_stricmp(scheme, pconst.pjsip_SIP_STR)==0) {
1418
url = pjsip_sip_uri_create(pool, 0);
1420
} else if (parser_stricmp(scheme, pconst.pjsip_SIPS_STR)==0) {
1421
url = pjsip_sip_uri_create(pool, 1);
1424
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1425
/* should not reach here */
1432
if (int_is_next_user(scanner)) {
1433
int_parse_user_pass(scanner, pool, &url->user, &url->passwd);
1437
int_parse_uri_host_port(scanner, &url->host, &url->port);
1439
/* Get URL parameters. */
1441
while (*scanner->curptr == ';' ) {
1442
pj_str_t pname, pvalue;
1444
int_parse_uri_param( scanner, pool, &pname, &pvalue, 0);
1446
if (!parser_stricmp(pname, pconst.pjsip_USER_STR) && pvalue.slen) {
1447
url->user_param = pvalue;
1449
} else if (!parser_stricmp(pname, pconst.pjsip_METHOD_STR) && pvalue.slen) {
1450
url->method_param = pvalue;
1452
} else if (!parser_stricmp(pname, pconst.pjsip_TRANSPORT_STR) && pvalue.slen) {
1453
url->transport_param = pvalue;
1455
} else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
1456
url->ttl_param = pj_strtoul(&pvalue);
1458
} else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
1459
url->maddr_param = pvalue;
1461
} else if (!parser_stricmp(pname, pconst.pjsip_LR_STR)) {
1465
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1468
pj_list_insert_before(&url->other_param, p);
1473
/* Get header params. */
1474
if (parse_params && *scanner->curptr == '?') {
1477
param = PJ_POOL_ALLOC_T(pool, pjsip_param);
1478
int_parse_hparam(scanner, pool, ¶m->name, ¶m->value);
1479
pj_list_insert_before(&url->header_param, param);
1480
} while (*scanner->curptr == '&');
1483
scanner->skip_ws = skip_ws;
1484
pj_scan_skip_whitespace(scanner);
1488
/* Parse nameaddr. */
1489
static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner,
1493
pjsip_name_addr *name_addr;
1495
name_addr = pjsip_name_addr_create(pool);
1497
if (*scanner->curptr == '"') {
1498
pj_scan_get_quote( scanner, '"', '"', &name_addr->display);
1499
/* Trim the leading and ending quote */
1500
name_addr->display.ptr++;
1501
name_addr->display.slen -= 2;
1503
} else if (*scanner->curptr != '<') {
1507
/* This can be either the start of display name,
1508
* the start of URL ("sip:", "sips:", "tel:", etc.), or '<' char.
1509
* We're only interested in display name, because SIP URL
1510
* will be parser later.
1512
next = pj_scan_peek(scanner, &pconst.pjsip_DISPLAY_SPEC, &dummy);
1514
/* Ok, this is what we're looking for, a display name. */
1515
pj_scan_get_until_ch( scanner, '<', &name_addr->display);
1516
pj_strtrim(&name_addr->display);
1520
/* Manually skip whitespace. */
1521
pj_scan_skip_whitespace(scanner);
1523
/* Get the SIP-URL */
1524
has_bracket = (*scanner->curptr == '<');
1526
pj_scan_get_char(scanner);
1527
} else if (name_addr->display.slen) {
1528
/* Must have bracket now (2012-10-26).
1529
* Allowing (invalid) name-addr to pass URI verification will
1530
* cause us to send invalid URI to the wire.
1532
PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1534
name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
1536
if (pj_scan_get_char(scanner) != '>')
1537
PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
1544
/* Parse other URI */
1545
static void* int_parse_other_uri(pj_scanner *scanner,
1547
pj_bool_t parse_params)
1549
pjsip_other_uri *uri = 0;
1550
const pjsip_parser_const_t *pc = pjsip_parser_const();
1551
int skip_ws = scanner->skip_ws;
1553
PJ_UNUSED_ARG(parse_params);
1555
scanner->skip_ws = 0;
1557
uri = pjsip_other_uri_create(pool);
1559
pj_scan_get(scanner, &pc->pjsip_TOKEN_SPEC, &uri->scheme);
1560
if (pj_scan_get_char(scanner) != ':') {
1561
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
1564
pj_scan_get(scanner, &pc->pjsip_OTHER_URI_CONTENT, &uri->content);
1565
scanner->skip_ws = skip_ws;
1571
/* Parse SIP request line. */
1572
static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool,
1573
pjsip_request_line *req_line)
1577
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &token);
1578
pjsip_method_init_np( &req_line->method, &token);
1580
req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
1581
parse_sip_version(scanner);
1582
pj_scan_get_newline( scanner );
1585
/* Parse status line. */
1586
static void int_parse_status_line( pj_scanner *scanner,
1587
pjsip_status_line *status_line)
1591
parse_sip_version(scanner);
1592
pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &token);
1593
status_line->code = pj_strtoul(&token);
1594
if (*scanner->curptr != '\r' && *scanner->curptr != '\n')
1595
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &status_line->reason);
1597
status_line->reason.slen=0, status_line->reason.ptr=NULL;
1598
pj_scan_get_newline( scanner );
1603
* Public API to parse SIP status line.
1605
PJ_DEF(pj_status_t) pjsip_parse_status_line( char *buf, pj_size_t size,
1606
pjsip_status_line *status_line)
1611
pj_bzero(status_line, sizeof(*status_line));
1612
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
1616
int_parse_status_line(&scanner, status_line);
1619
/* Tolerate the error if it is caused only by missing newline */
1620
if (status_line->code == 0 && status_line->reason.slen == 0) {
1621
pj_scan_fini(&scanner);
1622
return PJSIP_EINVALIDMSG;
1627
pj_scan_fini(&scanner);
1632
/* Parse ending of header. */
1633
static void parse_hdr_end( pj_scanner *scanner )
1635
if (pj_scan_is_eof(scanner)) {
1637
} else if (*scanner->curptr == '&') {
1638
pj_scan_get_char(scanner);
1640
pj_scan_get_newline(scanner);
1644
/* Parse ending of header. */
1645
PJ_DEF(void) pjsip_parse_end_hdr_imp( pj_scanner *scanner )
1647
parse_hdr_end(scanner);
1650
/* Parse generic array header. */
1651
static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr,
1652
pj_scanner *scanner)
1654
/* Some header fields allow empty elements in the value:
1655
* Accept, Allow, Supported
1657
if (pj_scan_is_eof(scanner) ||
1658
*scanner->curptr == '\r' || *scanner->curptr == '\n')
1663
if (hdr->count >= PJ_ARRAY_SIZE(hdr->values)) {
1664
/* Too many elements */
1665
on_syntax_error(scanner);
1669
pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
1670
&hdr->values[hdr->count]);
1673
while (*scanner->curptr == ',') {
1674
pj_scan_get_char(scanner);
1675
pj_scan_get( scanner, &pconst.pjsip_NOT_COMMA_OR_NEWLINE,
1676
&hdr->values[hdr->count]);
1679
if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT)
1684
parse_hdr_end(scanner);
1687
/* Parse generic string header. */
1688
static void parse_generic_string_hdr( pjsip_generic_string_hdr *hdr,
1689
pjsip_parse_ctx *ctx)
1691
pj_scanner *scanner = ctx->scanner;
1693
hdr->hvalue.slen = 0;
1695
/* header may be mangled hence the loop */
1696
while (pj_cis_match(&pconst.pjsip_NOT_NEWLINE, *scanner->curptr)) {
1699
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->hvalue);
1700
if (pj_scan_is_eof(scanner) || IS_NEWLINE(*scanner->curptr))
1702
/* mangled, get next fraction */
1703
pj_scan_get( scanner, &pconst.pjsip_NOT_NEWLINE, &next);
1705
tmp.ptr = (char*)pj_pool_alloc(ctx->pool,
1706
hdr->hvalue.slen + next.slen + 2);
1708
pj_strcpy(&tmp, &hdr->hvalue);
1709
pj_strcat2(&tmp, " ");
1710
pj_strcat(&tmp, &next);
1711
tmp.ptr[tmp.slen] = '\0';
1716
parse_hdr_end(scanner);
1719
/* Parse generic integer header. */
1720
static void parse_generic_int_hdr( pjsip_generic_int_hdr *hdr,
1721
pj_scanner *scanner )
1724
pj_scan_get( scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
1725
hdr->ivalue = pj_strtoul(&tmp);
1726
parse_hdr_end(scanner);
1730
/* Parse Accept header. */
1731
static pjsip_hdr* parse_hdr_accept(pjsip_parse_ctx *ctx)
1733
pjsip_accept_hdr *accept = pjsip_accept_hdr_create(ctx->pool);
1734
parse_generic_array_hdr(accept, ctx->scanner);
1735
return (pjsip_hdr*)accept;
1738
/* Parse Allow header. */
1739
static pjsip_hdr* parse_hdr_allow(pjsip_parse_ctx *ctx)
1741
pjsip_allow_hdr *allow = pjsip_allow_hdr_create(ctx->pool);
1742
parse_generic_array_hdr(allow, ctx->scanner);
1743
return (pjsip_hdr*)allow;
1746
/* Parse Call-ID header. */
1747
static pjsip_hdr* parse_hdr_call_id(pjsip_parse_ctx *ctx)
1749
pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool);
1750
pj_scan_get( ctx->scanner, &pconst.pjsip_NOT_NEWLINE, &hdr->id);
1751
parse_hdr_end(ctx->scanner);
1754
ctx->rdata->msg_info.cid = hdr;
1756
return (pjsip_hdr*)hdr;
1759
/* Parse and interpret Contact param. */
1760
static void int_parse_contact_param( pjsip_contact_hdr *hdr,
1761
pj_scanner *scanner,
1764
while ( *scanner->curptr == ';' ) {
1765
pj_str_t pname, pvalue;
1767
int_parse_param( scanner, pool, &pname, &pvalue, 0);
1768
if (!parser_stricmp(pname, pconst.pjsip_Q_STR) && pvalue.slen) {
1769
char *dot_pos = (char*) pj_memchr(pvalue.ptr, '.', pvalue.slen);
1771
hdr->q1000 = pj_strtoul(&pvalue) * 1000;
1773
pj_str_t tmp = pvalue;
1775
tmp.slen = dot_pos - pvalue.ptr;
1776
hdr->q1000 = pj_strtoul(&tmp) * 1000;
1778
pvalue.slen = (pvalue.ptr+pvalue.slen) - (dot_pos+1);
1779
pvalue.ptr = dot_pos + 1;
1780
hdr->q1000 += pj_strtoul_mindigit(&pvalue, 3);
1782
} else if (!parser_stricmp(pname, pconst.pjsip_EXPIRES_STR) && pvalue.slen) {
1783
hdr->expires = pj_strtoul(&pvalue);
1786
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1789
pj_list_insert_before(&hdr->other_param, p);
1794
/* Parse Contact header. */
1795
static pjsip_hdr* parse_hdr_contact( pjsip_parse_ctx *ctx )
1797
pjsip_contact_hdr *first = NULL;
1798
pj_scanner *scanner = ctx->scanner;
1801
pjsip_contact_hdr *hdr = pjsip_contact_hdr_create(ctx->pool);
1805
pj_list_insert_before(first, hdr);
1807
if (*scanner->curptr == '*') {
1808
pj_scan_get_char(scanner);
1813
hdr->uri = int_parse_uri_or_name_addr(scanner, ctx->pool,
1814
PJSIP_PARSE_URI_AS_NAMEADDR |
1815
PJSIP_PARSE_URI_IN_FROM_TO_HDR);
1817
int_parse_contact_param(hdr, scanner, ctx->pool);
1820
if (*scanner->curptr != ',')
1823
pj_scan_get_char(scanner);
1827
parse_hdr_end(scanner);
1829
return (pjsip_hdr*)first;
1832
/* Parse Content-Length header. */
1833
static pjsip_hdr* parse_hdr_content_len( pjsip_parse_ctx *ctx )
1836
pjsip_clen_hdr *hdr;
1838
hdr = pjsip_clen_hdr_create(ctx->pool);
1839
pj_scan_get(ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &digit);
1840
hdr->len = pj_strtoul(&digit);
1841
parse_hdr_end(ctx->scanner);
1844
ctx->rdata->msg_info.clen = hdr;
1846
return (pjsip_hdr*)hdr;
1849
/* Parse Content-Type header. */
1850
static pjsip_hdr* parse_hdr_content_type( pjsip_parse_ctx *ctx )
1852
pjsip_ctype_hdr *hdr;
1853
pj_scanner *scanner = ctx->scanner;
1855
hdr = pjsip_ctype_hdr_create(ctx->pool);
1857
/* Parse media type and subtype. */
1858
pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->media.type);
1859
pj_scan_get_char(scanner);
1860
pj_scan_get(scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->media.subtype);
1862
/* Parse media parameters */
1863
while (*scanner->curptr == ';') {
1864
pjsip_param *param = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
1865
int_parse_param(scanner, ctx->pool, ¶m->name, ¶m->value, 0);
1866
pj_list_push_back(&hdr->media.param, param);
1869
parse_hdr_end(ctx->scanner);
1872
ctx->rdata->msg_info.ctype = hdr;
1874
return (pjsip_hdr*)hdr;
1877
/* Parse CSeq header. */
1878
static pjsip_hdr* parse_hdr_cseq( pjsip_parse_ctx *ctx )
1880
pj_str_t cseq, method;
1881
pjsip_cseq_hdr *hdr;
1883
hdr = pjsip_cseq_hdr_create(ctx->pool);
1884
pj_scan_get( ctx->scanner, &pconst.pjsip_DIGIT_SPEC, &cseq);
1885
hdr->cseq = pj_strtoul(&cseq);
1887
pj_scan_get( ctx->scanner, &pconst.pjsip_TOKEN_SPEC, &method);
1888
pjsip_method_init_np(&hdr->method, &method);
1890
parse_hdr_end( ctx->scanner );
1893
ctx->rdata->msg_info.cseq = hdr;
1895
return (pjsip_hdr*)hdr;
1898
/* Parse Expires header. */
1899
static pjsip_hdr* parse_hdr_expires(pjsip_parse_ctx *ctx)
1901
pjsip_expires_hdr *hdr = pjsip_expires_hdr_create(ctx->pool, 0);
1902
parse_generic_int_hdr(hdr, ctx->scanner);
1903
return (pjsip_hdr*)hdr;
1906
/* Parse From: or To: header. */
1907
static void parse_hdr_fromto( pj_scanner *scanner,
1909
pjsip_from_hdr *hdr)
1911
hdr->uri = int_parse_uri_or_name_addr(scanner, pool,
1912
PJSIP_PARSE_URI_AS_NAMEADDR |
1913
PJSIP_PARSE_URI_IN_FROM_TO_HDR);
1915
while ( *scanner->curptr == ';' ) {
1916
pj_str_t pname, pvalue;
1918
int_parse_param( scanner, pool, &pname, &pvalue, 0);
1920
if (!parser_stricmp(pname, pconst.pjsip_TAG_STR)) {
1924
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
1927
pj_list_insert_before(&hdr->other_param, p);
1931
parse_hdr_end(scanner);
1934
/* Parse From: header. */
1935
static pjsip_hdr* parse_hdr_from( pjsip_parse_ctx *ctx )
1937
pjsip_from_hdr *hdr = pjsip_from_hdr_create(ctx->pool);
1938
parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
1940
ctx->rdata->msg_info.from = hdr;
1942
return (pjsip_hdr*)hdr;
1945
/* Parse Require: header. */
1946
static pjsip_hdr* parse_hdr_require( pjsip_parse_ctx *ctx )
1948
pjsip_require_hdr *hdr;
1949
pj_bool_t new_hdr = (ctx->rdata==NULL ||
1950
ctx->rdata->msg_info.require == NULL);
1952
if (ctx->rdata && ctx->rdata->msg_info.require) {
1953
hdr = ctx->rdata->msg_info.require;
1955
hdr = pjsip_require_hdr_create(ctx->pool);
1957
ctx->rdata->msg_info.require = hdr;
1960
parse_generic_array_hdr(hdr, ctx->scanner);
1962
return new_hdr ? (pjsip_hdr*)hdr : NULL;
1965
/* Parse Retry-After: header. */
1966
static pjsip_hdr* parse_hdr_retry_after(pjsip_parse_ctx *ctx)
1968
pjsip_retry_after_hdr *hdr;
1969
pj_scanner *scanner = ctx->scanner;
1972
hdr = pjsip_retry_after_hdr_create(ctx->pool, 0);
1974
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &tmp);
1975
hdr->ivalue = pj_strtoul(&tmp);
1977
while (!pj_scan_is_eof(scanner) && *scanner->curptr!='\r' &&
1978
*scanner->curptr!='\n')
1980
if (*scanner->curptr=='(') {
1981
pj_scan_get_quote(scanner, '(', ')', &hdr->comment);
1982
/* Trim the leading and ending parens */
1984
hdr->comment.slen -= 2;
1985
} else if (*scanner->curptr==';') {
1986
pjsip_param *prm = PJ_POOL_ALLOC_T(ctx->pool, pjsip_param);
1987
int_parse_param(scanner, ctx->pool, &prm->name, &prm->value, 0);
1988
pj_list_push_back(&hdr->param, prm);
1992
parse_hdr_end(scanner);
1993
return (pjsip_hdr*)hdr;
1996
/* Parse Supported: header. */
1997
static pjsip_hdr* parse_hdr_supported(pjsip_parse_ctx *ctx)
1999
pjsip_supported_hdr *hdr;
2000
pj_bool_t new_hdr = (ctx->rdata==NULL ||
2001
ctx->rdata->msg_info.supported == NULL);
2003
if (ctx->rdata && ctx->rdata->msg_info.supported) {
2004
hdr = ctx->rdata->msg_info.supported;
2006
hdr = pjsip_supported_hdr_create(ctx->pool);
2008
ctx->rdata->msg_info.supported = hdr;
2011
parse_generic_array_hdr(hdr, ctx->scanner);
2012
return new_hdr ? (pjsip_hdr*)hdr : NULL;
2015
/* Parse To: header. */
2016
static pjsip_hdr* parse_hdr_to( pjsip_parse_ctx *ctx )
2018
pjsip_to_hdr *hdr = pjsip_to_hdr_create(ctx->pool);
2019
parse_hdr_fromto(ctx->scanner, ctx->pool, hdr);
2022
ctx->rdata->msg_info.to = hdr;
2024
return (pjsip_hdr*)hdr;
2027
/* Parse Unsupported: header. */
2028
static pjsip_hdr* parse_hdr_unsupported(pjsip_parse_ctx *ctx)
2030
pjsip_unsupported_hdr *hdr = pjsip_unsupported_hdr_create(ctx->pool);
2031
parse_generic_array_hdr(hdr, ctx->scanner);
2032
return (pjsip_hdr*)hdr;
2035
/* Parse and interpret Via parameters. */
2036
static void int_parse_via_param( pjsip_via_hdr *hdr, pj_scanner *scanner,
2039
while ( *scanner->curptr == ';' ) {
2040
pj_str_t pname, pvalue;
2042
//Parse with PARAM_CHAR instead, to allow IPv6
2043
//No, back to using int_parse_param() for the "`" character!
2044
//int_parse_param( scanner, pool, &pname, &pvalue, 0);
2045
//parse_param_imp(scanner, pool, &pname, &pvalue,
2046
// &pconst.pjsip_TOKEN_SPEC,
2047
// &pconst.pjsip_TOKEN_SPEC_ESC, 0);
2048
//int_parse_param(scanner, pool, &pname, &pvalue, 0);
2049
// This should be the correct one:
2050
// added special spec for Via parameter, basically token plus
2051
// ":" to allow IPv6 address in the received param.
2052
pj_scan_get_char(scanner);
2053
parse_param_imp(scanner, pool, &pname, &pvalue,
2054
&pconst.pjsip_VIA_PARAM_SPEC,
2055
&pconst.pjsip_VIA_PARAM_SPEC_ESC,
2058
if (!parser_stricmp(pname, pconst.pjsip_BRANCH_STR) && pvalue.slen) {
2059
hdr->branch_param = pvalue;
2061
} else if (!parser_stricmp(pname, pconst.pjsip_TTL_STR) && pvalue.slen) {
2062
hdr->ttl_param = pj_strtoul(&pvalue);
2064
} else if (!parser_stricmp(pname, pconst.pjsip_MADDR_STR) && pvalue.slen) {
2065
hdr->maddr_param = pvalue;
2067
} else if (!parser_stricmp(pname, pconst.pjsip_RECEIVED_STR) && pvalue.slen) {
2068
hdr->recvd_param = pvalue;
2070
} else if (!parser_stricmp(pname, pconst.pjsip_RPORT_STR)) {
2072
hdr->rport_param = pj_strtoul(&pvalue);
2074
hdr->rport_param = 0;
2076
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2079
pj_list_insert_before(&hdr->other_param, p);
2084
/* Parse Max-Forwards header. */
2085
static pjsip_hdr* parse_hdr_max_forwards( pjsip_parse_ctx *ctx )
2087
pjsip_max_fwd_hdr *hdr;
2088
hdr = pjsip_max_fwd_hdr_create(ctx->pool, 0);
2089
parse_generic_int_hdr(hdr, ctx->scanner);
2092
ctx->rdata->msg_info.max_fwd = hdr;
2094
return (pjsip_hdr*)hdr;
2097
/* Parse Min-Expires header. */
2098
static pjsip_hdr* parse_hdr_min_expires(pjsip_parse_ctx *ctx)
2100
pjsip_min_expires_hdr *hdr;
2101
hdr = pjsip_min_expires_hdr_create(ctx->pool, 0);
2102
parse_generic_int_hdr(hdr, ctx->scanner);
2103
return (pjsip_hdr*)hdr;
2107
/* Parse Route: or Record-Route: header. */
2108
static void parse_hdr_rr_route( pj_scanner *scanner, pj_pool_t *pool,
2109
pjsip_routing_hdr *hdr )
2111
pjsip_name_addr *temp=int_parse_name_addr(scanner, pool);
2113
pj_memcpy(&hdr->name_addr, temp, sizeof(*temp));
2115
while (*scanner->curptr == ';') {
2116
pjsip_param *p = PJ_POOL_ALLOC_T(pool, pjsip_param);
2117
int_parse_param(scanner, pool, &p->name, &p->value, 0);
2118
pj_list_insert_before(&hdr->other_param, p);
2122
/* Parse Record-Route header. */
2123
static pjsip_hdr* parse_hdr_rr( pjsip_parse_ctx *ctx)
2125
pjsip_rr_hdr *first = NULL;
2126
pj_scanner *scanner = ctx->scanner;
2129
pjsip_rr_hdr *hdr = pjsip_rr_hdr_create(ctx->pool);
2133
pj_list_insert_before(first, hdr);
2135
parse_hdr_rr_route(scanner, ctx->pool, hdr);
2136
if (*scanner->curptr == ',') {
2137
pj_scan_get_char(scanner);
2142
parse_hdr_end(scanner);
2144
if (ctx->rdata && ctx->rdata->msg_info.record_route==NULL)
2145
ctx->rdata->msg_info.record_route = first;
2147
return (pjsip_hdr*)first;
2150
/* Parse Route: header. */
2151
static pjsip_hdr* parse_hdr_route( pjsip_parse_ctx *ctx )
2153
pjsip_route_hdr *first = NULL;
2154
pj_scanner *scanner = ctx->scanner;
2157
pjsip_route_hdr *hdr = pjsip_route_hdr_create(ctx->pool);
2161
pj_list_insert_before(first, hdr);
2163
parse_hdr_rr_route(scanner, ctx->pool, hdr);
2164
if (*scanner->curptr == ',') {
2165
pj_scan_get_char(scanner);
2170
parse_hdr_end(scanner);
2172
if (ctx->rdata && ctx->rdata->msg_info.route==NULL)
2173
ctx->rdata->msg_info.route = first;
2175
return (pjsip_hdr*)first;
2178
/* Parse Via: header. */
2179
static pjsip_hdr* parse_hdr_via( pjsip_parse_ctx *ctx )
2181
pjsip_via_hdr *first = NULL;
2182
pj_scanner *scanner = ctx->scanner;
2185
pjsip_via_hdr *hdr = pjsip_via_hdr_create(ctx->pool);
2189
pj_list_insert_before(first, hdr);
2191
parse_sip_version(scanner);
2192
if (pj_scan_get_char(scanner) != '/')
2193
on_syntax_error(scanner);
2195
pj_scan_get( scanner, &pconst.pjsip_TOKEN_SPEC, &hdr->transport);
2196
int_parse_host(scanner, &hdr->sent_by.host);
2198
if (*scanner->curptr==':') {
2200
pj_scan_get_char(scanner);
2201
pj_scan_get(scanner, &pconst.pjsip_DIGIT_SPEC, &digit);
2202
hdr->sent_by.port = pj_strtoul(&digit);
2205
int_parse_via_param(hdr, scanner, ctx->pool);
2207
if (*scanner->curptr == '(') {
2208
pj_scan_get_char(scanner);
2209
pj_scan_get_until_ch( scanner, ')', &hdr->comment);
2210
pj_scan_get_char( scanner );
2213
if (*scanner->curptr != ',')
2216
pj_scan_get_char(scanner);
2220
parse_hdr_end(scanner);
2222
if (ctx->rdata && ctx->rdata->msg_info.via == NULL)
2223
ctx->rdata->msg_info.via = first;
2225
return (pjsip_hdr*)first;
2228
/* Parse generic header. */
2229
static pjsip_hdr* parse_hdr_generic_string( pjsip_parse_ctx *ctx )
2231
pjsip_generic_string_hdr *hdr;
2233
hdr = pjsip_generic_string_hdr_create(ctx->pool, NULL, NULL);
2234
parse_generic_string_hdr(hdr, ctx);
2235
return (pjsip_hdr*)hdr;
2239
/* Public function to parse a header value. */
2240
PJ_DEF(void*) pjsip_parse_hdr( pj_pool_t *pool, const pj_str_t *hname,
2241
char *buf, pj_size_t size, int *parsed_len )
2244
pjsip_hdr *hdr = NULL;
2245
pjsip_parse_ctx context;
2248
pj_scan_init(&scanner, buf, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2251
context.scanner = &scanner;
2252
context.pool = pool;
2253
context.rdata = NULL;
2256
pjsip_parse_hdr_func *handler = find_handler(hname);
2258
hdr = (*handler)(&context);
2260
hdr = parse_hdr_generic_string(&context);
2261
hdr->type = PJSIP_H_OTHER;
2262
pj_strdup(pool, &hdr->name, hname);
2263
hdr->sname = hdr->name;
2273
*parsed_len = (scanner.curptr - scanner.begin);
2276
pj_scan_fini(&scanner);
2281
/* Parse multiple header lines */
2282
PJ_DEF(pj_status_t) pjsip_parse_headers( pj_pool_t *pool, char *input,
2283
pj_size_t size, pjsip_hdr *hlist,
2286
enum { STOP_ON_ERROR = 1 };
2288
pjsip_parse_ctx ctx;
2292
pj_scan_init(&scanner, input, size, PJ_SCAN_AUTOSKIP_WS_HEADER,
2295
pj_bzero(&ctx, sizeof(ctx));
2296
ctx.scanner = &scanner;
2302
/* Parse headers. */
2304
pjsip_parse_hdr_func * handler;
2305
pjsip_hdr *hdr = NULL;
2307
/* Init hname just in case parsing fails.
2313
pj_scan_get( &scanner, &pconst.pjsip_TOKEN_SPEC, &hname);
2314
if (pj_scan_get_char( &scanner ) != ':') {
2315
PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
2319
handler = find_handler(&hname);
2321
/* Call the handler if found.
2322
* If no handler is found, then treat the header as generic
2323
* hname/hvalue pair.
2326
hdr = (*handler)(&ctx);
2328
hdr = parse_hdr_generic_string(&ctx);
2329
hdr->name = hdr->sname = hname;
2332
/* Single parse of header line can produce multiple headers.
2333
* For example, if one Contact: header contains Contact list
2334
* separated by comma, then these Contacts will be split into
2335
* different Contact headers.
2336
* So here we must insert list instead of just insert one header.
2339
pj_list_insert_nodes_before(hlist, hdr);
2341
/* Parse until EOF or an empty line is found. */
2342
} while (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr));
2344
/* If empty line is found, eat it. */
2345
if (!pj_scan_is_eof(&scanner)) {
2346
if (IS_NEWLINE(*scanner.curptr)) {
2347
pj_scan_get_newline(&scanner);
2353
PJ_LOG(4,(THIS_FILE, "Error parsing header: '%.*s' line %d col %d",
2354
(int)hname.slen, hname.ptr, scanner.line,
2355
pj_scan_get_col(&scanner)));
2357
/* Exception was thrown during parsing. */
2358
if ((options & STOP_ON_ERROR) == STOP_ON_ERROR) {
2359
pj_scan_fini(&scanner);
2360
return PJSIP_EINVALIDHDR;
2363
/* Skip until newline, and parse next header. */
2364
if (!pj_scan_is_eof(&scanner)) {
2365
/* Skip until next line.
2366
* Watch for header continuation.
2369
pj_scan_skip_line(&scanner);
2370
} while (IS_SPACE(*scanner.curptr));
2373
/* Restore flag. Flag may be set in int_parse_sip_url() */
2374
scanner.skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER;
2376
/* Continue parse next header, if any. */
2377
if (!pj_scan_is_eof(&scanner) && !IS_NEWLINE(*scanner.curptr)) {