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.
27 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include "sip_miscdefs.h"
38 #include "sip_parse_uri.h"
41 * atoi function from a header
44 sip_atoi(_sip_header_t
*sip_header
, int *num
)
46 boolean_t num_found
= B_FALSE
;
49 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
50 if (isspace(*sip_header
->sip_hdr_current
)) {
51 sip_header
->sip_hdr_current
++;
54 } else if (isdigit(*sip_header
->sip_hdr_current
)) {
56 (*sip_header
->sip_hdr_current
- '0');
58 sip_header
->sip_hdr_current
++;
72 sip_find_token(_sip_header_t
*sip_header
, char token
)
74 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
75 if (token
!= SIP_COMMA
&&
76 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
77 sip_header
->sip_hdr_current
--;
80 if (*sip_header
->sip_hdr_current
++ == token
) {
82 * sip_hdr_current points to the char
92 * Find a carriage-return
95 sip_find_cr(_sip_header_t
*sip_header
)
97 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_end
;
98 while (*sip_header
->sip_hdr_current
-- != '\n') {
99 if (sip_header
->sip_hdr_current
== sip_header
->sip_hdr_start
)
106 * Find one of the separator provided, i.e. separator_1st or separator_2nd or
110 sip_find_separator(_sip_header_t
*sip_header
, char separator_1st
,
111 char separator_2nd
, char separator_3rd
, boolean_t ignore_space
)
113 assert(separator_1st
!= (char)NULL
|| separator_2nd
!= (char)NULL
);
114 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
115 if (ignore_space
&& (*sip_header
->sip_hdr_current
== SIP_SP
)) {
116 sip_header
->sip_hdr_current
++;
119 if (isspace(*sip_header
->sip_hdr_current
) ||
120 (separator_1st
!= (char)NULL
&&
121 (*sip_header
->sip_hdr_current
== separator_1st
)) ||
122 (separator_2nd
!= (char)NULL
&&
123 (*sip_header
->sip_hdr_current
== separator_2nd
)) ||
124 (separator_3rd
!= (char)NULL
&&
125 (*sip_header
->sip_hdr_current
== separator_3rd
))) {
129 * If we have escape character, go to the next char
131 if (*sip_header
->sip_hdr_current
== '\\')
132 sip_header
->sip_hdr_current
++;
133 sip_header
->sip_hdr_current
++;
139 * Return when we hit a white space
142 sip_find_white_space(_sip_header_t
*sip_header
)
144 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
145 if (isspace(*sip_header
->sip_hdr_current
))
147 sip_header
->sip_hdr_current
++;
153 * Skip to the next non-whitespace
156 sip_skip_white_space(_sip_header_t
*sip_header
)
158 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
159 if (!isspace(*sip_header
->sip_hdr_current
))
161 sip_header
->sip_hdr_current
++;
168 * Skip to the non-white space in the reverse direction
171 sip_reverse_skip_white_space(_sip_header_t
*sip_header
)
173 while (sip_header
->sip_hdr_current
>= sip_header
->sip_hdr_start
) {
174 if (!isspace(*sip_header
->sip_hdr_current
))
176 sip_header
->sip_hdr_current
--;
182 * get to the first non space after ':'
185 sip_parse_goto_values(_sip_header_t
*sip_header
)
187 if (sip_find_token(sip_header
, SIP_HCOLON
) != 0)
189 if (sip_skip_white_space(sip_header
) != 0)
196 * Skip the current value.
199 sip_goto_next_value(_sip_header_t
*sip_header
)
201 boolean_t quoted
= B_FALSE
;
203 while (sip_header
->sip_hdr_current
< sip_header
->sip_hdr_end
) {
204 if (*sip_header
->sip_hdr_current
== SIP_QUOTE
) {
209 } else if (!quoted
&&
210 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
212 * value ends before the COMMA
214 sip_header
->sip_hdr_current
--;
217 sip_header
->sip_hdr_current
++;
225 * Parse the header into parameter list. Parameters start with a ';'
228 sip_parse_params(_sip_header_t
*sip_header
, sip_param_t
**parsed_list
)
230 sip_param_t
*param
= NULL
;
231 sip_param_t
*new_param
;
234 if (parsed_list
== NULL
)
239 boolean_t quoted_name
= B_FALSE
;
242 * First check if there are any params
244 if (sip_skip_white_space(sip_header
) != 0)
246 if (*sip_header
->sip_hdr_current
!= SIP_SEMI
)
249 sip_header
->sip_hdr_current
++;
251 new_param
= calloc(1, sizeof (sip_param_t
));
252 if (new_param
== NULL
)
256 param
->param_next
= new_param
;
258 *parsed_list
= new_param
;
263 * Let's get to the start of the param name
265 if (sip_skip_white_space(sip_header
) != 0)
268 * start of param name
270 tmp_ptr
= sip_header
->sip_hdr_current
;
271 param
->param_name
.sip_str_ptr
= tmp_ptr
;
273 if (sip_find_separator(sip_header
, SIP_EQUAL
, SIP_SEMI
,
274 SIP_COMMA
, B_FALSE
) != 0) {
275 param
->param_name
.sip_str_len
=
276 sip_header
->sip_hdr_current
- tmp_ptr
;
277 param
->param_value
.sip_str_ptr
= NULL
;
278 param
->param_value
.sip_str_len
= 0;
285 param
->param_name
.sip_str_len
=
286 sip_header
->sip_hdr_current
- tmp_ptr
;
288 if (sip_skip_white_space(sip_header
) != 0 ||
289 *sip_header
->sip_hdr_current
== SIP_COMMA
) {
290 param
->param_value
.sip_str_ptr
= NULL
;
291 param
->param_value
.sip_str_len
= 0;
294 if (*sip_header
->sip_hdr_current
== SIP_SEMI
) {
295 param
->param_value
.sip_str_ptr
= NULL
;
296 param
->param_value
.sip_str_len
= 0;
299 assert(*sip_header
->sip_hdr_current
== SIP_EQUAL
);
302 * We are at EQUAL, lets go beyond that
304 sip_header
->sip_hdr_current
++;
306 if (sip_skip_white_space(sip_header
) != 0)
309 if (*sip_header
->sip_hdr_current
== SIP_QUOTE
) {
310 sip_header
->sip_hdr_current
++;
311 quoted_name
= B_TRUE
;
315 * start of param value
317 param
->param_value
.sip_str_ptr
= sip_header
->sip_hdr_current
;
318 tmp_ptr
= sip_header
->sip_hdr_current
;
320 if (quoted_name
&& sip_find_token(sip_header
, SIP_QUOTE
) != 0) {
322 } else if (sip_find_separator(sip_header
, SIP_SEMI
, SIP_COMMA
,
323 (char)NULL
, B_FALSE
) != 0) {
326 param
->param_value
.sip_str_len
= sip_header
->sip_hdr_current
-
329 param
->param_value
.sip_str_len
--;
334 * a header that only has "header_name : " is an empty header
336 * sip_hdr_current resets to sip_hdr_start before exit
339 sip_is_empty_hdr(_sip_header_t
*sip_header
)
341 if (sip_find_token(sip_header
, SIP_HCOLON
) != 0) {
342 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
346 if (sip_skip_white_space(sip_header
) == 0) {
347 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
351 sip_header
->sip_hdr_current
= sip_header
->sip_hdr_start
;
356 * Parsing an empty header, i.e. only has a ":"
359 sip_parse_hdr_empty(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
)
361 sip_parsed_header_t
*parsed_header
;
363 if (hdr
== NULL
|| phdr
== NULL
)
367 * check if already parsed
369 if (hdr
->sip_hdr_parsed
!= NULL
) {
370 *phdr
= hdr
->sip_hdr_parsed
;
376 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
377 if (parsed_header
== NULL
)
379 parsed_header
->sip_header
= hdr
;
381 parsed_header
->value
= NULL
;
383 *phdr
= parsed_header
;
388 * validate uri str and parse uri using uri_parse()
391 sip_parse_uri_str(sip_str_t
*sip_str
, sip_hdr_value_t
*value
)
398 if (sip_str
->sip_str_len
> 0) {
399 value
->sip_value_parsed_uri
= sip_parse_uri(sip_str
, &error
);
400 if (value
->sip_value_parsed_uri
== NULL
)
403 value
->sip_value_parsed_uri
->sip_uri_errflags
!= 0) {
404 value
->sip_value_state
= SIP_VALUE_BAD
;
410 * Some basic common checks before parsing the headers
413 sip_prim_parsers(_sip_header_t
*sip_header
, sip_parsed_header_t
**header
)
415 if (sip_header
== NULL
|| header
== NULL
)
419 * check if already parsed
421 if (sip_header
->sip_hdr_parsed
!= NULL
) {
422 *header
= sip_header
->sip_hdr_parsed
;
427 assert(sip_header
->sip_hdr_start
== sip_header
->sip_hdr_current
);
429 if (sip_parse_goto_values(sip_header
) != 0)
436 * Parse SIP/2.0 string
439 sip_get_protocol_version(_sip_header_t
*sip_header
,
440 sip_proto_version_t
*sip_proto_version
)
442 if (sip_skip_white_space(sip_header
) != 0)
445 if (strncasecmp(sip_header
->sip_hdr_current
, SIP
, strlen(SIP
)) == 0) {
446 sip_proto_version
->name
.sip_str_ptr
=
447 sip_header
->sip_hdr_current
;
448 sip_proto_version
->name
.sip_str_len
= strlen(SIP
);
450 if (sip_find_token(sip_header
, SIP_SLASH
) != 0)
452 if (sip_skip_white_space(sip_header
) != 0)
455 sip_proto_version
->version
.sip_str_ptr
=
456 sip_header
->sip_hdr_current
;
457 while (isdigit(*sip_header
->sip_hdr_current
)) {
458 sip_header
->sip_hdr_current
++;
459 if (sip_header
->sip_hdr_current
>=
460 sip_header
->sip_hdr_end
) {
464 if (*sip_header
->sip_hdr_current
!= SIP_PERIOD
)
466 sip_header
->sip_hdr_current
++;
468 if (!isdigit(*sip_header
->sip_hdr_current
))
470 while (isdigit(*sip_header
->sip_hdr_current
)) {
471 sip_header
->sip_hdr_current
++;
472 if (sip_header
->sip_hdr_current
>=
473 sip_header
->sip_hdr_end
) {
478 sip_proto_version
->version
.sip_str_len
=
479 sip_header
->sip_hdr_current
-
480 sip_proto_version
->version
.sip_str_ptr
;
487 * parser1 parses hdr format
488 * header_name: val1[; par1=pval1;par2=pval2 ..][, val2[;parlist..] ]
489 * val can be str1/str2 or str
490 * headers: Accept, Accept-Encode, Accept-lang, Allow, Content-disp,
491 * Content-Encode, Content-Lang, In-reply-to,
492 * Priority, Require, Supported, Unsupported
493 * Allow-Events, Event, Subscription-State
496 sip_parse_hdr_parser1(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
, char sep
)
498 sip_parsed_header_t
*parsed_header
;
500 sip_hdr_value_t
*value
= NULL
;
501 sip_hdr_value_t
*last_value
= NULL
;
503 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
507 * check if previously parsed
510 hdr
->sip_hdr_parsed
= *phdr
;
514 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
515 if (parsed_header
== NULL
)
517 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
518 parsed_header
->sip_header
= hdr
;
520 while (hdr
->sip_hdr_current
< hdr
->sip_hdr_end
) {
521 value
= calloc(1, sizeof (sip_hdr_value_t
));
523 sip_free_phdr(parsed_header
);
526 if (last_value
!= NULL
)
527 last_value
->sip_next_value
= value
;
529 parsed_header
->value
= (sip_value_t
*)value
;
531 value
->sip_value_start
= hdr
->sip_hdr_current
;
532 value
->sip_value_header
= parsed_header
;
534 if (sip_find_separator(hdr
, sep
, SIP_COMMA
, SIP_SEMI
,
536 char c
= *hdr
->sip_hdr_current
;
538 if (isspace(c
) && sep
== (char)NULL
) {
539 value
->str_val_ptr
= value
->sip_value_start
;
540 value
->str_val_len
= hdr
->sip_hdr_current
-
541 value
->sip_value_start
;
543 * nothing at the end except space
545 if (sip_skip_white_space(hdr
) != 0) {
546 value
->sip_value_end
=
547 hdr
->sip_hdr_current
;
551 * white space skipped
553 c
= *(hdr
->sip_hdr_current
);
557 * only one string until COMMA, use sip_str_t
559 if (c
== SIP_COMMA
) {
560 char *t
= hdr
->sip_hdr_current
;
562 hdr
->sip_hdr_current
--;
563 (void) sip_reverse_skip_white_space(hdr
);
564 value
->str_val_ptr
= value
->sip_value_start
;
565 value
->str_val_len
= hdr
->sip_hdr_current
-
566 value
->sip_value_start
+ 1;
567 hdr
->sip_hdr_current
= t
;
572 * two strings, use sip_2strs_t
574 if ((sep
!= (char)NULL
) && (c
== sep
)) {
575 value
->strs1_val_ptr
= value
->sip_value_start
;
576 value
->strs1_val_len
= hdr
->sip_hdr_current
-
577 value
->sip_value_start
;
579 value
->strs2_val_ptr
=
580 (++hdr
->sip_hdr_current
);
581 if (sip_find_separator(hdr
, SIP_SEMI
, SIP_COMMA
,
582 (char)NULL
, B_FALSE
) == 0) {
583 char t
= *(hdr
->sip_hdr_current
);
584 value
->strs2_val_len
=
585 hdr
->sip_hdr_current
-
586 value
->strs2_val_ptr
;
588 * if COMMA, no param list, get next val
589 * if SEMI, need to set params list
593 } else { /* the last part */
594 value
->strs2_val_len
=
595 hdr
->sip_hdr_current
-
596 value
->strs2_val_ptr
;
597 value
->sip_value_end
=
598 hdr
->sip_hdr_current
;
601 } else if (sep
!= (char)NULL
) {
602 value
->sip_value_state
= SIP_VALUE_BAD
;
607 * c == SEMI, value contains single string
608 * only one string until SEMI, use sip_str_t
611 char *t
= hdr
->sip_hdr_current
;
613 hdr
->sip_hdr_current
--;
615 * get rid of SP at end of value field
617 (void) sip_reverse_skip_white_space(hdr
);
618 value
->str_val_ptr
= value
->sip_value_start
;
619 value
->str_val_len
= hdr
->sip_hdr_current
-
620 value
->str_val_ptr
+ 1;
621 hdr
->sip_hdr_current
= t
;
625 * if SEMI exists in the value, set params list
626 * two situations, there is or not SLASH before SEMI
628 ret
= sip_parse_params(hdr
, &value
->sip_param_list
);
630 value
->sip_value_state
= SIP_VALUE_BAD
;
631 } else if (ret
!= 0) {
632 sip_free_phdr(parsed_header
);
637 value
->str_val_ptr
= value
->sip_value_start
;
638 value
->str_val_len
= hdr
->sip_hdr_current
-
639 value
->sip_value_start
;
640 value
->sip_value_end
= hdr
->sip_hdr_current
;
644 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
645 value
->sip_value_end
= hdr
->sip_hdr_current
;
648 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
650 (void) sip_skip_white_space(hdr
);
654 *phdr
= parsed_header
;
655 hdr
->sip_hdr_parsed
= *phdr
;
661 * headers: Expires, Min-Expires
665 sip_parse_hdr_parser2(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
,
668 sip_parsed_header_t
*parsed_header
;
670 sip_hdr_value_t
*value
= NULL
;
672 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
676 * check if previously parsed
679 hdr
->sip_hdr_parsed
= *phdr
;
682 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
683 if (parsed_header
== NULL
)
685 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
686 parsed_header
->sip_header
= hdr
;
688 value
= calloc(1, sizeof (sip_hdr_value_t
));
690 sip_free_phdr(parsed_header
);
694 parsed_header
->value
= (sip_value_t
*)value
;
696 value
->sip_value_start
= hdr
->sip_hdr_current
;
697 value
->sip_value_header
= parsed_header
;
699 ret
= sip_atoi(hdr
, &value
->int_val
);
702 value
->sip_value_state
= SIP_VALUE_BAD
;
705 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
707 *phdr
= parsed_header
;
708 hdr
->sip_hdr_parsed
= *phdr
;
713 * parser3 parses hdr format
714 * header_name: <val1>[, <val2>]
715 * Alert-Info, Call-Info, Error-Info, reply-to
718 sip_parse_hdr_parser3(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
, int type
,
721 sip_parsed_header_t
*parsed_header
;
722 sip_hdr_value_t
*value
= NULL
;
723 sip_hdr_value_t
*last_value
= NULL
;
726 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
730 * check if previously parsed
733 hdr
->sip_hdr_parsed
= *phdr
;
736 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
737 if (parsed_header
== NULL
)
739 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
740 parsed_header
->sip_header
= hdr
;
741 while (hdr
->sip_hdr_current
< hdr
->sip_hdr_end
) {
744 value
= calloc(1, sizeof (sip_hdr_value_t
));
746 sip_free_phdr(parsed_header
);
750 if (last_value
!= NULL
)
751 last_value
->sip_next_value
= value
;
753 parsed_header
->value
= (sip_value_t
*)value
;
755 value
->sip_value_start
= hdr
->sip_hdr_current
;
756 value
->sip_value_header
= parsed_header
;
758 if (type
== SIP_STRS_VAL
) {
759 if (sip_find_token(hdr
, SIP_LAQUOT
) == 0) {
763 * record the position after LAQUOT
765 cur
= hdr
->sip_hdr_current
;
767 * get display name and store in str1
769 hdr
->sip_hdr_current
= value
->sip_value_start
;
770 if (*(hdr
->sip_hdr_current
) != SIP_LAQUOT
) {
772 * record start pos of display name
774 char *tmp
= hdr
->sip_hdr_current
;
776 if (*hdr
->sip_hdr_current
==
778 hdr
->sip_hdr_current
++;
780 if (sip_find_token(hdr
,
782 value
->sip_value_state
=
786 hdr
->sip_hdr_current
-= 2;
788 hdr
->sip_hdr_current
= cur
- 2;
790 sip_reverse_skip_white_space
793 value
->strs1_val_ptr
= tmp
;
794 value
->strs1_val_len
=
795 hdr
->sip_hdr_current
- tmp
+ 1;
797 value
->strs1_val_ptr
= NULL
;
798 value
->strs1_val_len
= 0;
802 * set current to the char after LAQUOT
804 hdr
->sip_hdr_current
= cur
;
805 value
->strs2_val_ptr
= hdr
->sip_hdr_current
;
806 if (sip_find_token(hdr
, SIP_RAQUOT
)) {
810 value
->strs1_val_ptr
= NULL
;
811 value
->strs1_val_len
= 0;
812 value
->strs2_val_ptr
= NULL
;
813 value
->strs2_val_len
= 0;
814 value
->sip_value_state
= SIP_VALUE_BAD
;
817 value
->strs2_val_len
= hdr
->sip_hdr_current
-
818 value
->strs2_val_ptr
- 1;
823 * No display name - Only URI.
825 value
->strs1_val_ptr
= NULL
;
826 value
->strs1_val_len
= 0;
827 cur
= value
->sip_value_start
;
828 hdr
->sip_hdr_current
= cur
;
829 if (sip_find_separator(hdr
, SIP_COMMA
,
830 (char)NULL
, (char)NULL
, B_FALSE
) != 0) {
831 value
->strs2_val_ptr
= cur
;
832 value
->strs2_val_len
=
833 hdr
->sip_hdr_current
-
834 value
->strs2_val_ptr
- 1;
835 } else if (*hdr
->sip_hdr_current
== SIP_SP
) {
836 value
->strs2_val_ptr
= cur
;
837 cur
= hdr
->sip_hdr_current
- 1;
838 if (sip_skip_white_space(hdr
) != 0) {
839 value
->strs2_val_len
= cur
-
840 value
->strs2_val_ptr
- 1;
841 } else if (*hdr
->sip_hdr_current
==
843 value
->strs2_val_len
= cur
-
844 value
->strs2_val_ptr
- 1;
846 value
->sip_value_state
=
851 value
->strs2_val_ptr
= cur
;
852 value
->strs2_val_len
=
853 hdr
->sip_hdr_current
-
854 value
->strs2_val_ptr
;
858 sip_parse_uri_str(&value
->strs_s2
, value
);
861 if (type
== SIP_STR_VAL
) {
863 * alert-info, error-info, call-info
865 if (sip_find_token(hdr
, SIP_LAQUOT
) == 0) {
866 value
->str_val_ptr
= hdr
->sip_hdr_current
;
867 if (sip_find_token(hdr
, SIP_RAQUOT
) == 0) {
869 hdr
->sip_hdr_current
-
870 value
->str_val_ptr
- 1;
872 value
->str_val_ptr
= NULL
;
873 value
->str_val_len
= 0;
874 value
->sip_value_state
= SIP_VALUE_BAD
;
877 hdr
->sip_hdr_current
--;
879 value
->str_val_ptr
= NULL
;
880 value
->str_val_len
= 0;
881 value
->sip_value_state
= SIP_VALUE_BAD
;
885 sip_parse_uri_str(&value
->str_val
, value
);
888 r
= sip_find_separator(hdr
, SIP_COMMA
, SIP_SEMI
, (char)NULL
,
891 value
->sip_value_end
= hdr
->sip_hdr_current
;
894 if (*hdr
->sip_hdr_current
== SIP_SEMI
) {
895 (void) sip_parse_params(hdr
,
896 &(value
->sip_param_list
));
900 if (*hdr
->sip_hdr_current
== SIP_COMMA
) {
901 hdr
->sip_hdr_current
--;
905 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
906 value
->sip_value_end
= hdr
->sip_hdr_current
;
909 value
->sip_value_end
= hdr
->sip_hdr_current
- 1;
911 (void) sip_skip_white_space(hdr
);
915 *phdr
= parsed_header
;
916 hdr
->sip_hdr_parsed
= *phdr
;
921 * parser4 parses hdr format, the whole field is one single str
922 * header: Subject, MIME-Version, Organization, Server, User-Agent
925 sip_parse_hdr_parser4(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
)
927 sip_parsed_header_t
*parsed_header
;
928 sip_hdr_value_t
*value
= NULL
;
931 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
935 * check if previously parsed
938 hdr
->sip_hdr_parsed
= *phdr
;
941 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
942 if (parsed_header
== NULL
)
944 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
945 parsed_header
->sip_header
= hdr
;
947 value
= calloc(1, sizeof (sip_hdr_value_t
));
949 sip_free_phdr(parsed_header
);
953 parsed_header
->value
= (sip_value_t
*)value
;
955 value
->sip_value_start
= hdr
->sip_hdr_current
;
956 value
->sip_value_header
= parsed_header
;
958 value
->str_val_ptr
= hdr
->sip_hdr_current
;
960 * get rid of CRLF at end
962 value
->str_val_len
= hdr
->sip_hdr_end
- value
->str_val_ptr
- 2;
963 value
->sip_value_end
= hdr
->sip_hdr_end
;
965 *phdr
= parsed_header
;
966 hdr
->sip_hdr_parsed
= *phdr
;
971 sip_parse_hdr_parser5(_sip_header_t
*hdr
, sip_parsed_header_t
**phdr
,
974 sip_parsed_header_t
*parsed_header
;
975 sip_hdr_value_t
*value
= NULL
;
976 sip_param_t
*tmp_param
;
977 boolean_t first_param
= B_TRUE
;
980 if ((ret
= sip_prim_parsers(hdr
, phdr
)) != 0)
984 * check if previously parsed
987 hdr
->sip_hdr_parsed
= *phdr
;
990 parsed_header
= calloc(1, sizeof (sip_parsed_header_t
));
991 if (parsed_header
== NULL
)
993 parsed_header
->sip_parsed_header_version
= SIP_PARSED_HEADER_VERSION_1
;
994 parsed_header
->sip_header
= hdr
;
996 value
= calloc(1, sizeof (sip_hdr_value_t
));
998 sip_free_phdr(parsed_header
);
1002 parsed_header
->value
= (sip_value_t
*)value
;
1004 value
->sip_value_start
= hdr
->sip_hdr_current
;
1005 value
->auth_scheme_ptr
= value
->sip_value_start
;
1006 value
->sip_value_header
= parsed_header
;
1010 if (sip_find_white_space(hdr
)) {
1011 value
->sip_value_state
= SIP_VALUE_BAD
;
1014 value
->auth_scheme_len
= hdr
->sip_hdr_current
- value
->auth_scheme_ptr
;
1016 tmp_param
= value
->auth_param
;
1023 boolean_t quoted_name
= B_FALSE
;
1024 char quoted_char
= (char)0;
1025 sip_param_t
*new_param
;
1026 boolean_t pval_is_uri
= B_FALSE
;
1028 if (sip_skip_white_space(hdr
) != 0) {
1029 value
->sip_value_state
= SIP_VALUE_BAD
;
1032 tmp_cur
= hdr
->sip_hdr_current
;
1034 new_param
= calloc(1, sizeof (sip_param_t
));
1035 if (new_param
== NULL
)
1038 if (first_param
== B_FALSE
)
1039 tmp_param
->param_next
= new_param
;
1041 value
->auth_param
= new_param
;
1043 tmp_param
= new_param
;
1044 tmp_param
->param_name
.sip_str_ptr
= tmp_cur
;
1046 if (sip_find_separator(hdr
, SIP_EQUAL
, SIP_COMMA
, (char)NULL
,
1048 tmp_param
->param_name
.sip_str_len
=
1049 hdr
->sip_hdr_current
- tmp_cur
;
1050 tmp_param
->param_value
.sip_str_ptr
= NULL
;
1051 tmp_param
->param_value
.sip_str_len
= 0;
1052 value
->sip_value_end
= hdr
->sip_hdr_current
;
1059 tmp_param
->param_name
.sip_str_len
= hdr
->sip_hdr_current
-
1062 if (sip_skip_white_space(hdr
) != 0 ||
1063 *hdr
->sip_hdr_current
== SIP_COMMA
) {
1064 tmp_param
->param_value
.sip_str_ptr
= NULL
;
1065 tmp_param
->param_value
.sip_str_len
= 0;
1072 hdr
->sip_hdr_current
++;
1074 if (sip_skip_white_space(hdr
) != 0) {
1075 value
->sip_value_state
= SIP_VALUE_BAD
;
1080 if (*hdr
->sip_hdr_current
== SIP_QUOTE
||
1081 *hdr
->sip_hdr_current
== SIP_LAQUOT
) {
1082 if (*hdr
->sip_hdr_current
== SIP_QUOTE
)
1083 quoted_char
= SIP_QUOTE
;
1085 quoted_char
= SIP_RAQUOT
;
1086 pval_is_uri
= B_TRUE
;
1088 hdr
->sip_hdr_current
++;
1089 quoted_name
= B_TRUE
;
1093 * start of param value
1095 tmp_cur
= hdr
->sip_hdr_current
;
1096 tmp_param
->param_value
.sip_str_ptr
= tmp_cur
;
1098 if (sip_find_token(hdr
, quoted_char
) != 0) {
1099 value
->sip_value_state
= SIP_VALUE_BAD
;
1103 tmp_param
->param_value
.sip_str_len
=
1104 hdr
->sip_hdr_current
- tmp_cur
- 1;
1107 if (sip_find_token(hdr
, SIP_COMMA
) != 0) {
1108 value
->sip_value_end
= hdr
->sip_hdr_current
;
1112 char *t
= hdr
->sip_hdr_current
;
1113 hdr
->sip_hdr_current
--;
1114 (void) sip_reverse_skip_white_space(hdr
);
1115 tmp_param
->param_value
.sip_str_len
=
1116 hdr
->sip_hdr_current
- tmp_cur
;
1117 hdr
->sip_hdr_current
= t
;
1121 if (first_param
== B_TRUE
)
1122 first_param
= B_FALSE
;
1127 if (pval_is_uri
&& parse_uri
)
1128 sip_parse_uri_str(&tmp_param
->param_value
, value
);
1133 *phdr
= parsed_header
;
1134 hdr
->sip_hdr_parsed
= *phdr
;
1139 * Return the URI in the request startline
1142 _sip_get_request_uri(_sip_header_t
*sip_header
, sip_message_type_t
*msg_info
)
1147 if (sip_skip_white_space(sip_header
) != 0)
1149 start_ptr
= sip_header
->sip_hdr_current
;
1151 while (!isspace(*sip_header
->sip_hdr_current
)) {
1152 if (sip_header
->sip_hdr_current
>= sip_header
->sip_hdr_end
)
1154 sip_header
->sip_hdr_current
++;
1157 size
= sip_header
->sip_hdr_current
- start_ptr
;
1159 msg_info
->U
.sip_request
.sip_request_uri
.sip_str_ptr
= start_ptr
;
1160 msg_info
->U
.sip_request
.sip_request_uri
.sip_str_len
= size
;
1161 if (size
> 0) { /* Parse uri */
1164 msg_info
->U
.sip_request
.sip_parse_uri
= sip_parse_uri(
1165 &msg_info
->U
.sip_request
.sip_request_uri
, &error
);
1166 if (msg_info
->U
.sip_request
.sip_parse_uri
== NULL
)
1173 * Parse the start line into request/response
1176 sip_parse_first_line(_sip_header_t
*sip_header
, sip_message_type_t
**msg_info
)
1178 sip_message_type_t
*sip_msg_info
;
1179 boolean_t sip_is_request
= B_TRUE
;
1182 if (sip_header
== NULL
|| msg_info
== NULL
)
1185 if (sip_skip_white_space(sip_header
) != 0)
1189 * There is nothing, return
1191 if (sip_header
->sip_hdr_current
+ strlen(SIP_VERSION
) >=
1192 sip_header
->sip_hdr_end
) {
1196 assert(mutex_held(&sip_header
->sip_hdr_sipmsg
->sip_msg_mutex
));
1198 sip_msg_info
= malloc(sizeof (sip_message_type_t
));
1199 if (sip_msg_info
== NULL
)
1203 * let's see if it's a request or a response
1205 ret
= sip_get_protocol_version(sip_header
,
1206 &sip_msg_info
->sip_proto_version
);
1208 sip_is_request
= B_FALSE
;
1209 } else if (ret
== 2) {
1214 if (sip_skip_white_space(sip_header
) != 0) {
1219 if (!sip_is_request
) {
1221 * check for status code.
1223 if (sip_skip_white_space(sip_header
) != 0) {
1227 if (sip_header
->sip_hdr_current
+ SIP_SIZE_OF_STATUS_CODE
>=
1228 sip_header
->sip_hdr_end
) {
1233 if (sip_atoi(sip_header
,
1234 &sip_msg_info
->U
.sip_response
.sip_response_code
)) {
1239 if (sip_msg_info
->U
.sip_response
.sip_response_code
< 100 ||
1240 sip_msg_info
->U
.sip_response
.sip_response_code
> 700) {
1246 * get reason phrase.
1248 if (sip_skip_white_space(sip_header
) != 0) {
1249 sip_msg_info
->sip_resp_phrase_len
= 0;
1250 sip_msg_info
->sip_resp_phrase_ptr
= NULL
;
1252 sip_msg_info
->sip_resp_phrase_ptr
=
1253 sip_header
->sip_hdr_current
;
1254 if (sip_find_cr(sip_header
) != 0) {
1258 sip_msg_info
->sip_resp_phrase_len
=
1259 sip_header
->sip_hdr_current
-
1260 sip_msg_info
->sip_resp_phrase_ptr
;
1262 sip_msg_info
->is_request
= B_FALSE
;
1268 sip_msg_info
->is_request
= B_TRUE
;
1269 for (i
= 1; i
< MAX_SIP_METHODS
; i
++) {
1270 if (strncmp(sip_methods
[i
].name
,
1271 sip_header
->sip_hdr_current
,
1272 sip_methods
[i
].len
) == 0) {
1273 sip_msg_info
->sip_req_method
= i
;
1274 sip_header
->sip_hdr_current
+=
1276 if (!isspace(*sip_header
->sip_hdr_current
++) ||
1277 !isalpha(*sip_header
->sip_hdr_current
)) {
1282 if ((ret
= _sip_get_request_uri(sip_header
,
1283 sip_msg_info
)) != 0) {
1291 ret
= sip_get_protocol_version(sip_header
,
1292 &sip_msg_info
->sip_proto_version
);
1304 sip_msg_info
->sip_next
= *msg_info
;
1305 *msg_info
= sip_msg_info
;