4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
34 #include "sip_miscdefs.h"
36 #include "sip_parse_uri.h"
39 * atoi function from a header
42 sip_atoi(_sip_header_t
*sip_header
, int *num
)
44 boolean_t num_found
= B_FALSE
;
47 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
48 if (isspace(*sip_header
->sip_hdr_current
)) {
49 sip_header
->sip_hdr_current
++;
52 } else if (isdigit(*sip_header
->sip_hdr_current
)) {
54 (*sip_header
->sip_hdr_current
- '0');
56 sip_header
->sip_hdr_current
++;
70 sip_find_token(_sip_header_t
*sip_header
, char token
)
72 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
73 if (token
!= SIP_COMMA
&&
74 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
75 sip_header
->sip_hdr_current
--;
78 if (*sip_header
->sip_hdr_current
++ == token
) {
80 * sip_hdr_current points to the char
90 * Find a carriage-return
93 sip_find_cr(_sip_header_t
*sip_header
)
95 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_end
;
96 while (*sip_header
->sip_hdr_current
-- != '\n') {
97 if (sip_header
->sip_hdr_current
== sip_header
->sip_hdr_start
)
104 * Find one of the separator provided, i.e. separator_1st or separator_2nd or
108 sip_find_separator(_sip_header_t
*sip_header
, char separator_1st
,
109 char separator_2nd
, char separator_3rd
, boolean_t ignore_space
)
111 assert(separator_1st
!= SIP_NUL
|| separator_2nd
!= SIP_NUL
);
112 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
113 if (ignore_space
&& (*sip_header
->sip_hdr_current
== SIP_SP
)) {
114 sip_header
->sip_hdr_current
++;
117 if (isspace(*sip_header
->sip_hdr_current
) ||
118 (separator_1st
!= SIP_NUL
&&
119 (*sip_header
->sip_hdr_current
== separator_1st
)) ||
120 (separator_2nd
!= SIP_NUL
&&
121 (*sip_header
->sip_hdr_current
== separator_2nd
)) ||
122 (separator_3rd
!= SIP_NUL
&&
123 (*sip_header
->sip_hdr_current
== separator_3rd
))) {
127 * If we have escape character, go to the next char
129 if (*sip_header
->sip_hdr_current
== '\\')
130 sip_header
->sip_hdr_current
++;
131 sip_header
->sip_hdr_current
++;
137 * Return when we hit a white space
140 sip_find_white_space(_sip_header_t
*sip_header
)
142 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
143 if (isspace(*sip_header
->sip_hdr_current
))
145 sip_header
->sip_hdr_current
++;
151 * Skip to the next non-whitespace
154 sip_skip_white_space(_sip_header_t
*sip_header
)
156 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
157 if (!isspace(*sip_header
->sip_hdr_current
))
159 sip_header
->sip_hdr_current
++;
166 * Skip to the non-white space in the reverse direction
169 sip_reverse_skip_white_space(_sip_header_t
*sip_header
)
171 while (sip_header
->sip_hdr_current
>= sip_header
->sip_hdr_start
) {
172 if (!isspace(*sip_header
->sip_hdr_current
))
174 sip_header
->sip_hdr_current
--;
180 * get to the first non space after ':'
183 sip_parse_goto_values(_sip_header_t
*sip_header
)
185 if (sip_find_token(sip_header
, SIP_HCOLON
) != 0)
187 if (sip_skip_white_space(sip_header
) != 0)
194 * Skip the current value.
197 sip_goto_next_value(_sip_header_t
*sip_header
)
199 boolean_t quoted
= B_FALSE
;
201 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
202 if (*sip_header
->sip_hdr_current
== SIP_QUOTE
) {
207 } else if (!quoted
&&
208 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
210 * value ends before the COMMA
212 sip_header
->sip_hdr_current
--;
215 sip_header
->sip_hdr_current
++;
223 * Parse the header into parameter list. Parameters start with a ';'
226 sip_parse_params(_sip_header_t
*sip_header
, sip_param_t
**parsed_list
)
228 sip_param_t
*param
= NULL
;
229 sip_param_t
*new_param
;
232 if (parsed_list
== NULL
)
237 boolean_t quoted_name
= B_FALSE
;
240 * First check if there are any params
242 if (sip_skip_white_space(sip_header
) != 0)
244 if (*sip_header
->sip_hdr_current
!= SIP_SEMI
)
247 sip_header
->sip_hdr_current
++;
249 new_param
= calloc(1, sizeof (sip_param_t
));
250 if (new_param
== NULL
)
254 param
->param_next
= new_param
;
256 *parsed_list
= new_param
;
261 * Let's get to the start of the param name
263 if (sip_skip_white_space(sip_header
) != 0)
266 * start of param name
268 tmp_ptr
= sip_header
->sip_hdr_current
;
269 param
->param_name
.sip_str_ptr
= tmp_ptr
;
271 if (sip_find_separator(sip_header
, SIP_EQUAL
, SIP_SEMI
,
272 SIP_COMMA
, B_FALSE
) != 0) {
273 param
->param_name
.sip_str_len
=
274 sip_header
->sip_hdr_current
- tmp_ptr
;
275 param
->param_value
.sip_str_ptr
= NULL
;
276 param
->param_value
.sip_str_len
= 0;
283 param
->param_name
.sip_str_len
=
284 sip_header
->sip_hdr_current
- tmp_ptr
;
286 if (sip_skip_white_space(sip_header
) != 0 ||
287 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
288 param
->param_value
.sip_str_ptr
= NULL
;
289 param
->param_value
.sip_str_len
= 0;
292 if (*sip_header
->sip_hdr_current
== SIP_SEMI
) {
293 param
->param_value
.sip_str_ptr
= NULL
;
294 param
->param_value
.sip_str_len
= 0;
297 assert(*sip_header
->sip_hdr_current
== SIP_EQUAL
);
300 * We are at EQUAL, lets go beyond that
302 sip_header
->sip_hdr_current
++;
304 if (sip_skip_white_space(sip_header
) != 0)
307 if (*sip_header
->sip_hdr_current
== SIP_QUOTE
) {
308 sip_header
->sip_hdr_current
++;
309 quoted_name
= B_TRUE
;
313 * start of param value
315 param
->param_value
.sip_str_ptr
= sip_header
->sip_hdr_current
;
316 tmp_ptr
= sip_header
->sip_hdr_current
;
318 if (quoted_name
&& sip_find_token(sip_header
, SIP_QUOTE
) != 0) {
320 } else if (sip_find_separator(sip_header
, SIP_SEMI
, SIP_COMMA
,
321 SIP_NUL
, B_FALSE
) != 0) {
324 param
->param_value
.sip_str_len
= sip_header
->sip_hdr_current
-
327 param
->param_value
.sip_str_len
--;
332 * a header that only has "header_name : " is an empty header
334 * sip_hdr_current resets to sip_hdr_start before exit
337 sip_is_empty_hdr(_sip_header_t
*sip_header
)
339 if (sip_find_token(sip_header
, SIP_HCOLON
) != 0) {
340 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
344 if (sip_skip_white_space(sip_header
) == 0) {
345 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
349 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
354 * Parsing an empty header, i.e. only has a ":"
357 sip_parse_hdr_empty(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
)
359 sip_parsed_header_t
*parsed_header
;
361 if (hdr
== NULL
|| phdr
== NULL
)
365 * check if already parsed
367 if (hdr
->sip_hdr_parsed
!= NULL
) {
368 *phdr
= hdr
->sip_hdr_parsed
;
374 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
375 if (parsed_header
== NULL
)
377 parsed_header
->sip_header
= hdr
;
379 parsed_header
->value
= NULL
;
381 *phdr
= parsed_header
;
386 * validate uri str and parse uri using uri_parse()
389 sip_parse_uri_str(sip_str_t
*sip_str
, sip_hdr_value_t
*value
)
396 if (sip_str
->sip_str_len
> 0) {
397 value
->sip_value_parsed_uri
= sip_parse_uri(sip_str
, &error
);
398 if (value
->sip_value_parsed_uri
== NULL
)
401 value
->sip_value_parsed_uri
->sip_uri_errflags
!= 0) {
402 value
->sip_value_state
= SIP_VALUE_BAD
;
408 * Some basic common checks before parsing the headers
411 sip_prim_parsers(_sip_header_t
*sip_header
, sip_parsed_header_t
**header
)
413 if (sip_header
== NULL
|| header
== NULL
)
417 * check if already parsed
419 if (sip_header
->sip_hdr_parsed
!= NULL
) {
420 *header
= sip_header
->sip_hdr_parsed
;
425 assert(sip_header
->sip_hdr_start
== sip_header
->sip_hdr_current
);
427 if (sip_parse_goto_values(sip_header
) != 0)
434 * Parse SIP/2.0 string
437 sip_get_protocol_version(_sip_header_t
*sip_header
,
438 sip_proto_version_t
*sip_proto_version
)
440 if (sip_skip_white_space(sip_header
) != 0)
443 if (strncasecmp(sip_header
->sip_hdr_current
, SIP
, strlen(SIP
)) == 0) {
444 sip_proto_version
->name
.sip_str_ptr
=
445 sip_header
->sip_hdr_current
;
446 sip_proto_version
->name
.sip_str_len
= strlen(SIP
);
448 if (sip_find_token(sip_header
, SIP_SLASH
) != 0)
450 if (sip_skip_white_space(sip_header
) != 0)
453 sip_proto_version
->version
.sip_str_ptr
=
454 sip_header
->sip_hdr_current
;
455 while (isdigit(*sip_header
->sip_hdr_current
)) {
456 sip_header
->sip_hdr_current
++;
457 if (sip_header
->sip_hdr_current
>=
458 sip_header
->sip_hdr_end
) {
462 if (*sip_header
->sip_hdr_current
!= SIP_PERIOD
)
464 sip_header
->sip_hdr_current
++;
466 if (!isdigit(*sip_header
->sip_hdr_current
))
468 while (isdigit(*sip_header
->sip_hdr_current
)) {
469 sip_header
->sip_hdr_current
++;
470 if (sip_header
->sip_hdr_current
>=
471 sip_header
->sip_hdr_end
) {
476 sip_proto_version
->version
.sip_str_len
=
477 sip_header
->sip_hdr_current
-
478 sip_proto_version
->version
.sip_str_ptr
;
485 * parser1 parses hdr format
486 * header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
487 * val can be str1/str2 or str
488 * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
489 * Content-Encode, Content-Lang, In-reply-to,
490 * Priority, Require, Supported, Unsupported
491 * Allow-Events, Event, Subscription-State
494 sip_parse_hdr_parser1(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
, char sep
)
496 sip_parsed_header_t
*parsed_header
;
498 sip_hdr_value_t
*value
= NULL
;
499 sip_hdr_value_t
*last_value
= NULL
;
501 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
505 * check if previously parsed
508 hdr
->sip_hdr_parsed
= *phdr
;
512 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
513 if (parsed_header
== NULL
)
515 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
516 parsed_header
->sip_header
= hdr
;
518 while (hdr
->sip_hdr_current
< hdr
->sip_hdr_end
) {
519 value
= calloc(1, sizeof (sip_hdr_value_t
));
521 sip_free_phdr(parsed_header
);
524 if (last_value
!= NULL
)
525 last_value
->sip_next_value
= value
;
527 parsed_header
->value
= (sip_value_t
*)value
;
529 value
->sip_value_start
= hdr
->sip_hdr_current
;
530 value
->sip_value_header
= parsed_header
;
532 if (sip_find_separator(hdr
, sep
, SIP_COMMA
, SIP_SEMI
,
534 char c
= *hdr
->sip_hdr_current
;
536 if (isspace(c
) && sep
== SIP_NUL
) {
537 value
->str_val_ptr
= value
->sip_value_start
;
538 value
->str_val_len
= hdr
->sip_hdr_current
-
539 value
->sip_value_start
;
541 * nothing at the end except space
543 if (sip_skip_white_space(hdr
) != 0) {
544 value
->sip_value_end
=
545 hdr
->sip_hdr_current
;
549 * white space skipped
551 c
= *(hdr
->sip_hdr_current
);
555 * only one string until COMMA, use sip_str_t
557 if (c
== SIP_COMMA
) {
558 char *t
= hdr
->sip_hdr_current
;
560 hdr
->sip_hdr_current
--;
561 (void) sip_reverse_skip_white_space(hdr
);
562 value
->str_val_ptr
= value
->sip_value_start
;
563 value
->str_val_len
= hdr
->sip_hdr_current
-
564 value
->sip_value_start
+ 1;
565 hdr
->sip_hdr_current
= t
;
570 * two strings, use sip_2strs_t
572 if ((sep
!= SIP_NUL
) && (c
== sep
)) {
573 value
->strs1_val_ptr
= value
->sip_value_start
;
574 value
->strs1_val_len
= hdr
->sip_hdr_current
-
575 value
->sip_value_start
;
577 value
->strs2_val_ptr
=
578 (++hdr
->sip_hdr_current
);
579 if (sip_find_separator(hdr
, SIP_SEMI
, SIP_COMMA
,
580 SIP_NUL
, B_FALSE
) == 0) {
581 char t
= *(hdr
->sip_hdr_current
);
582 value
->strs2_val_len
=
583 hdr
->sip_hdr_current
-
584 value
->strs2_val_ptr
;
586 * if COMMA, no param list, get next val
587 * if SEMI, need to set params list
591 } else { /* the last part */
592 value
->strs2_val_len
=
593 hdr
->sip_hdr_current
-
594 value
->strs2_val_ptr
;
595 value
->sip_value_end
=
596 hdr
->sip_hdr_current
;
599 } else if (sep
!= SIP_NUL
) {
600 value
->sip_value_state
= SIP_VALUE_BAD
;
605 * c == SEMI, value contains single string
606 * only one string until SEMI, use sip_str_t
609 char *t
= hdr
->sip_hdr_current
;
611 hdr
->sip_hdr_current
--;
613 * get rid of SP at end of value field
615 (void) sip_reverse_skip_white_space(hdr
);
616 value
->str_val_ptr
= value
->sip_value_start
;
617 value
->str_val_len
= hdr
->sip_hdr_current
-
618 value
->str_val_ptr
+ 1;
619 hdr
->sip_hdr_current
= t
;
623 * if SEMI exists in the value, set params list
624 * two situations, there is or not SLASH before SEMI
626 ret
= sip_parse_params(hdr
, &value
->sip_param_list
);
628 value
->sip_value_state
= SIP_VALUE_BAD
;
629 } else if (ret
!= 0) {
630 sip_free_phdr(parsed_header
);
635 value
->str_val_ptr
= value
->sip_value_start
;
636 value
->str_val_len
= hdr
->sip_hdr_current
-
637 value
->sip_value_start
;
638 value
->sip_value_end
= hdr
->sip_hdr_current
;
642 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
643 value
->sip_value_end
= hdr
->sip_hdr_current
;
646 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
648 (void) sip_skip_white_space(hdr
);
652 *phdr
= parsed_header
;
653 hdr
->sip_hdr_parsed
= *phdr
;
659 * headers: Expires, Min-Expires
663 sip_parse_hdr_parser2(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
,
666 sip_parsed_header_t
*parsed_header
;
668 sip_hdr_value_t
*value
= NULL
;
670 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
674 * check if previously parsed
677 hdr
->sip_hdr_parsed
= *phdr
;
680 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
681 if (parsed_header
== NULL
)
683 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
684 parsed_header
->sip_header
= hdr
;
686 value
= calloc(1, sizeof (sip_hdr_value_t
));
688 sip_free_phdr(parsed_header
);
692 parsed_header
->value
= (sip_value_t
*)value
;
694 value
->sip_value_start
= hdr
->sip_hdr_current
;
695 value
->sip_value_header
= parsed_header
;
697 ret
= sip_atoi(hdr
, &value
->int_val
);
700 value
->sip_value_state
= SIP_VALUE_BAD
;
703 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
705 *phdr
= parsed_header
;
706 hdr
->sip_hdr_parsed
= *phdr
;
711 * parser3 parses hdr format
712 * header_name: <val1>[, <val2>]
713 * Alert-Info, Call-Info, Error-Info, reply-to
716 sip_parse_hdr_parser3(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
, int type
,
719 sip_parsed_header_t
*parsed_header
;
720 sip_hdr_value_t
*value
= NULL
;
721 sip_hdr_value_t
*last_value
= NULL
;
724 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
728 * check if previously parsed
731 hdr
->sip_hdr_parsed
= *phdr
;
734 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
735 if (parsed_header
== NULL
)
737 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
738 parsed_header
->sip_header
= hdr
;
739 while (hdr
->sip_hdr_current
< hdr
->sip_hdr_end
) {
742 value
= calloc(1, sizeof (sip_hdr_value_t
));
744 sip_free_phdr(parsed_header
);
748 if (last_value
!= NULL
)
749 last_value
->sip_next_value
= value
;
751 parsed_header
->value
= (sip_value_t
*)value
;
753 value
->sip_value_start
= hdr
->sip_hdr_current
;
754 value
->sip_value_header
= parsed_header
;
756 if (type
== SIP_STRS_VAL
) {
757 if (sip_find_token(hdr
, SIP_LAQUOT
) == 0) {
761 * record the position after LAQUOT
763 cur
= hdr
->sip_hdr_current
;
765 * get display name and store in str1
767 hdr
->sip_hdr_current
= value
->sip_value_start
;
768 if (*(hdr
->sip_hdr_current
) != SIP_LAQUOT
) {
770 * record start pos of display name
772 char *tmp
= hdr
->sip_hdr_current
;
774 if (*hdr
->sip_hdr_current
==
776 hdr
->sip_hdr_current
++;
778 if (sip_find_token(hdr
,
780 value
->sip_value_state
=
784 hdr
->sip_hdr_current
-= 2;
786 hdr
->sip_hdr_current
= cur
- 2;
788 sip_reverse_skip_white_space
791 value
->strs1_val_ptr
= tmp
;
792 value
->strs1_val_len
=
793 hdr
->sip_hdr_current
- tmp
+ 1;
795 value
->strs1_val_ptr
= NULL
;
796 value
->strs1_val_len
= 0;
800 * set current to the char after LAQUOT
802 hdr
->sip_hdr_current
= cur
;
803 value
->strs2_val_ptr
= hdr
->sip_hdr_current
;
804 if (sip_find_token(hdr
, SIP_RAQUOT
)) {
808 value
->strs1_val_ptr
= NULL
;
809 value
->strs1_val_len
= 0;
810 value
->strs2_val_ptr
= NULL
;
811 value
->strs2_val_len
= 0;
812 value
->sip_value_state
= SIP_VALUE_BAD
;
815 value
->strs2_val_len
= hdr
->sip_hdr_current
-
816 value
->strs2_val_ptr
- 1;
821 * No display name - Only URI.
823 value
->strs1_val_ptr
= NULL
;
824 value
->strs1_val_len
= 0;
825 cur
= value
->sip_value_start
;
826 hdr
->sip_hdr_current
= cur
;
827 if (sip_find_separator(hdr
, SIP_COMMA
,
828 SIP_NUL
, SIP_NUL
, B_FALSE
) != 0) {
829 value
->strs2_val_ptr
= cur
;
830 value
->strs2_val_len
=
831 hdr
->sip_hdr_current
-
832 value
->strs2_val_ptr
- 1;
833 } else if (*hdr
->sip_hdr_current
== SIP_SP
) {
834 value
->strs2_val_ptr
= cur
;
835 cur
= hdr
->sip_hdr_current
- 1;
836 if (sip_skip_white_space(hdr
) != 0) {
837 value
->strs2_val_len
= cur
-
838 value
->strs2_val_ptr
- 1;
839 } else if (*hdr
->sip_hdr_current
==
841 value
->strs2_val_len
= cur
-
842 value
->strs2_val_ptr
- 1;
844 value
->sip_value_state
=
849 value
->strs2_val_ptr
= cur
;
850 value
->strs2_val_len
=
851 hdr
->sip_hdr_current
-
852 value
->strs2_val_ptr
;
856 sip_parse_uri_str(&value
->strs_s2
, value
);
859 if (type
== SIP_STR_VAL
) {
861 * alert-info, error-info, call-info
863 if (sip_find_token(hdr
, SIP_LAQUOT
) == 0) {
864 value
->str_val_ptr
= hdr
->sip_hdr_current
;
865 if (sip_find_token(hdr
, SIP_RAQUOT
) == 0) {
867 hdr
->sip_hdr_current
-
868 value
->str_val_ptr
- 1;
870 value
->str_val_ptr
= NULL
;
871 value
->str_val_len
= 0;
872 value
->sip_value_state
= SIP_VALUE_BAD
;
875 hdr
->sip_hdr_current
--;
877 value
->str_val_ptr
= NULL
;
878 value
->str_val_len
= 0;
879 value
->sip_value_state
= SIP_VALUE_BAD
;
883 sip_parse_uri_str(&value
->str_val
, value
);
886 r
= sip_find_separator(hdr
, SIP_COMMA
, SIP_SEMI
, SIP_NUL
,
889 value
->sip_value_end
= hdr
->sip_hdr_current
;
892 if (*hdr
->sip_hdr_current
== SIP_SEMI
) {
893 (void) sip_parse_params(hdr
,
894 &(value
->sip_param_list
));
898 if (*hdr
->sip_hdr_current
== SIP_COMMA
) {
899 hdr
->sip_hdr_current
--;
903 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
904 value
->sip_value_end
= hdr
->sip_hdr_current
;
907 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
909 (void) sip_skip_white_space(hdr
);
913 *phdr
= parsed_header
;
914 hdr
->sip_hdr_parsed
= *phdr
;
919 * parser4 parses hdr format, the whole field is one single str
920 * header: Subject, MIME-Version, Organization, Server, User-Agent
923 sip_parse_hdr_parser4(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
)
925 sip_parsed_header_t
*parsed_header
;
926 sip_hdr_value_t
*value
= NULL
;
929 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
933 * check if previously parsed
936 hdr
->sip_hdr_parsed
= *phdr
;
939 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
940 if (parsed_header
== NULL
)
942 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
943 parsed_header
->sip_header
= hdr
;
945 value
= calloc(1, sizeof (sip_hdr_value_t
));
947 sip_free_phdr(parsed_header
);
951 parsed_header
->value
= (sip_value_t
*)value
;
953 value
->sip_value_start
= hdr
->sip_hdr_current
;
954 value
->sip_value_header
= parsed_header
;
956 value
->str_val_ptr
= hdr
->sip_hdr_current
;
958 * get rid of CRLF at end
960 value
->str_val_len
= hdr
->sip_hdr_end
- value
->str_val_ptr
- 2;
961 value
->sip_value_end
= hdr
->sip_hdr_end
;
963 *phdr
= parsed_header
;
964 hdr
->sip_hdr_parsed
= *phdr
;
969 sip_parse_hdr_parser5(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
,
972 sip_parsed_header_t
*parsed_header
;
973 sip_hdr_value_t
*value
= NULL
;
974 sip_param_t
*tmp_param
;
975 boolean_t first_param
= B_TRUE
;
978 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
982 * check if previously parsed
985 hdr
->sip_hdr_parsed
= *phdr
;
988 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
989 if (parsed_header
== NULL
)
991 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
992 parsed_header
->sip_header
= hdr
;
994 value
= calloc(1, sizeof (sip_hdr_value_t
));
996 sip_free_phdr(parsed_header
);
1000 parsed_header
->value
= (sip_value_t
*)value
;
1002 value
->sip_value_start
= hdr
->sip_hdr_current
;
1003 value
->auth_scheme_ptr
= value
->sip_value_start
;
1004 value
->sip_value_header
= parsed_header
;
1008 if (sip_find_white_space(hdr
)) {
1009 value
->sip_value_state
= SIP_VALUE_BAD
;
1012 value
->auth_scheme_len
= hdr
->sip_hdr_current
- value
->auth_scheme_ptr
;
1014 tmp_param
= value
->auth_param
;
1021 boolean_t quoted_name
= B_FALSE
;
1022 char quoted_char
= '\0';
1023 sip_param_t
*new_param
;
1024 boolean_t pval_is_uri
= B_FALSE
;
1026 if (sip_skip_white_space(hdr
) != 0) {
1027 value
->sip_value_state
= SIP_VALUE_BAD
;
1030 tmp_cur
= hdr
->sip_hdr_current
;
1032 new_param
= calloc(1, sizeof (sip_param_t
));
1033 if (new_param
== NULL
)
1036 if (first_param
== B_FALSE
)
1037 tmp_param
->param_next
= new_param
;
1039 value
->auth_param
= new_param
;
1041 tmp_param
= new_param
;
1042 tmp_param
->param_name
.sip_str_ptr
= tmp_cur
;
1044 if (sip_find_separator(hdr
, SIP_EQUAL
, SIP_COMMA
, SIP_NUL
,
1046 tmp_param
->param_name
.sip_str_len
=
1047 hdr
->sip_hdr_current
- tmp_cur
;
1048 tmp_param
->param_value
.sip_str_ptr
= NULL
;
1049 tmp_param
->param_value
.sip_str_len
= 0;
1050 value
->sip_value_end
= hdr
->sip_hdr_current
;
1057 tmp_param
->param_name
.sip_str_len
= hdr
->sip_hdr_current
-
1060 if (sip_skip_white_space(hdr
) != 0 ||
1061 *hdr
->sip_hdr_current
== SIP_COMMA
) {
1062 tmp_param
->param_value
.sip_str_ptr
= NULL
;
1063 tmp_param
->param_value
.sip_str_len
= 0;
1070 hdr
->sip_hdr_current
++;
1072 if (sip_skip_white_space(hdr
) != 0) {
1073 value
->sip_value_state
= SIP_VALUE_BAD
;
1078 if (*hdr
->sip_hdr_current
== SIP_QUOTE
||
1079 *hdr
->sip_hdr_current
== SIP_LAQUOT
) {
1080 if (*hdr
->sip_hdr_current
== SIP_QUOTE
)
1081 quoted_char
= SIP_QUOTE
;
1083 quoted_char
= SIP_RAQUOT
;
1084 pval_is_uri
= B_TRUE
;
1086 hdr
->sip_hdr_current
++;
1087 quoted_name
= B_TRUE
;
1091 * start of param value
1093 tmp_cur
= hdr
->sip_hdr_current
;
1094 tmp_param
->param_value
.sip_str_ptr
= tmp_cur
;
1096 if (sip_find_token(hdr
, quoted_char
) != 0) {
1097 value
->sip_value_state
= SIP_VALUE_BAD
;
1101 tmp_param
->param_value
.sip_str_len
=
1102 hdr
->sip_hdr_current
- tmp_cur
- 1;
1105 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
1106 value
->sip_value_end
= hdr
->sip_hdr_current
;
1110 char *t
= hdr
->sip_hdr_current
;
1111 hdr
->sip_hdr_current
--;
1112 (void) sip_reverse_skip_white_space(hdr
);
1113 tmp_param
->param_value
.sip_str_len
=
1114 hdr
->sip_hdr_current
- tmp_cur
;
1115 hdr
->sip_hdr_current
= t
;
1119 if (first_param
== B_TRUE
)
1120 first_param
= B_FALSE
;
1125 if (pval_is_uri
&& parse_uri
)
1126 sip_parse_uri_str(&tmp_param
->param_value
, value
);
1131 *phdr
= parsed_header
;
1132 hdr
->sip_hdr_parsed
= *phdr
;
1137 * Return the URI in the request startline
1140 _sip_get_request_uri(_sip_header_t
*sip_header
, sip_message_type_t
*msg_info
)
1145 if (sip_skip_white_space(sip_header
) != 0)
1147 start_ptr
= sip_header
->sip_hdr_current
;
1149 while (!isspace(*sip_header
->sip_hdr_current
)) {
1150 if (sip_header
->sip_hdr_current
>= sip_header
->sip_hdr_end
)
1152 sip_header
->sip_hdr_current
++;
1155 size
= sip_header
->sip_hdr_current
- start_ptr
;
1157 msg_info
->U
.sip_request
.sip_request_uri
.sip_str_ptr
= start_ptr
;
1158 msg_info
->U
.sip_request
.sip_request_uri
.sip_str_len
= size
;
1159 if (size
> 0) { /* Parse uri */
1162 msg_info
->U
.sip_request
.sip_parse_uri
= sip_parse_uri(
1163 &msg_info
->U
.sip_request
.sip_request_uri
, &error
);
1164 if (msg_info
->U
.sip_request
.sip_parse_uri
== NULL
)
1171 * Parse the start line into request/response
1174 sip_parse_first_line(_sip_header_t
*sip_header
, sip_message_type_t
**msg_info
)
1176 sip_message_type_t
*sip_msg_info
;
1177 boolean_t sip_is_request
= B_TRUE
;
1180 if (sip_header
== NULL
|| msg_info
== NULL
)
1183 if (sip_skip_white_space(sip_header
) != 0)
1187 * There is nothing, return
1189 if (sip_header
->sip_hdr_current
+ strlen(SIP_VERSION
) >=
1190 sip_header
->sip_hdr_end
) {
1194 assert(mutex_held(&sip_header
->sip_hdr_sipmsg
->sip_msg_mutex
));
1196 sip_msg_info
= malloc(sizeof (sip_message_type_t
));
1197 if (sip_msg_info
== NULL
)
1201 * let's see if it's a request or a response
1203 ret
= sip_get_protocol_version(sip_header
,
1204 &sip_msg_info
->sip_proto_version
);
1206 sip_is_request
= B_FALSE
;
1207 } else if (ret
== 2) {
1212 if (sip_skip_white_space(sip_header
) != 0) {
1217 if (!sip_is_request
) {
1219 * check for status code.
1221 if (sip_skip_white_space(sip_header
) != 0) {
1225 if (sip_header
->sip_hdr_current
+ SIP_SIZE_OF_STATUS_CODE
>=
1226 sip_header
->sip_hdr_end
) {
1231 if (sip_atoi(sip_header
,
1232 &sip_msg_info
->U
.sip_response
.sip_response_code
)) {
1237 if (sip_msg_info
->U
.sip_response
.sip_response_code
< 100 ||
1238 sip_msg_info
->U
.sip_response
.sip_response_code
> 700) {
1244 * get reason phrase.
1246 if (sip_skip_white_space(sip_header
) != 0) {
1247 sip_msg_info
->sip_resp_phrase_len
= 0;
1248 sip_msg_info
->sip_resp_phrase_ptr
= NULL
;
1250 sip_msg_info
->sip_resp_phrase_ptr
=
1251 sip_header
->sip_hdr_current
;
1252 if (sip_find_cr(sip_header
) != 0) {
1256 sip_msg_info
->sip_resp_phrase_len
=
1257 sip_header
->sip_hdr_current
-
1258 sip_msg_info
->sip_resp_phrase_ptr
;
1260 sip_msg_info
->is_request
= B_FALSE
;
1266 sip_msg_info
->is_request
= B_TRUE
;
1267 for (i
= 1; i
< MAX_SIP_METHODS
; i
++) {
1268 if (strncmp(sip_methods
[i
].name
,
1269 sip_header
->sip_hdr_current
,
1270 sip_methods
[i
].len
) == 0) {
1271 sip_msg_info
->sip_req_method
= i
;
1272 sip_header
->sip_hdr_current
+=
1274 if (!isspace(*sip_header
->sip_hdr_current
++) ||
1275 !isalpha(*sip_header
->sip_hdr_current
)) {
1280 if ((ret
= _sip_get_request_uri(sip_header
,
1281 sip_msg_info
)) != 0) {
1289 ret
= sip_get_protocol_version(sip_header
,
1290 &sip_msg_info
->sip_proto_version
);
1302 sip_msg_info
->sip_next
= *msg_info
;
1303 *msg_info
= sip_msg_info
;