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