📄 sip_parse.c
字号:
* Timestamp = "Timestamp" HCOLON 1*DIGIT ["." *(DIGIT)] [LWS delay] */intsip_parse_timestamp_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ sip_parsed_header_t *parsed_header; sip_hdr_value_t *value = NULL; if (sip_header == NULL || header == NULL) return (EINVAL); /* check if already parsed */ if (sip_header->sip_hdr_parsed != NULL) { *header = sip_header->sip_hdr_parsed; return (0); } *header = NULL; assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); if (sip_parse_goto_values(sip_header)) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_header = sip_header; value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_phdr(parsed_header); return (ENOMEM); } parsed_header->value = (sip_value_t *)value; value->sip_value_start = sip_header->sip_hdr_current; value->sip_value_header = parsed_header; if (sip_skip_white_space(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } value->strs1_val_ptr = sip_header->sip_hdr_current; if (sip_find_white_space(sip_header) == 0) { /* timestamp and delay, timestamp in str1, delay in str2 */ value->strs1_val_len = sip_header->sip_hdr_current - value->strs1_val_ptr; (void) sip_skip_white_space(sip_header); value->strs2_val_ptr = sip_header->sip_hdr_current; if (sip_find_cr(sip_header) != 0) { value->sip_value_state = SIP_VALUE_BAD; return (EPROTO); } if (sip_header->sip_hdr_current < value->strs2_val_ptr) { value->strs2_val_ptr = NULL; value->strs2_val_len = 0; } else { value->strs2_val_len = sip_header->sip_hdr_current - value->strs2_val_ptr; } } else { /* no delay information */ value->strs1_val_len = sip_header->sip_hdr_current - value->strs1_val_ptr; value->strs2_val_ptr = NULL; value->strs2_val_len = 0; } *header = parsed_header; sip_header->sip_hdr_parsed = *header; return (0);}/* * Unsupported = "Unsupported" HCOLON option-tag * (COMMA option-tag) */intsip_parse_usupport_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser1(sip_header, header, (char)NULL); sip_header->sip_hdr_parsed = *header; return (r);}/* * User-Agent = "User-Agent" HCOLON server-val * (LWS server-val) * servel-val = product |comment * product = token [SLASH version] * version = token */intsip_parse_useragt_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ int r; r = sip_parse_hdr_parser4(sip_header, header); sip_header->sip_hdr_parsed = *header; return (r);}/* * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm) * via-parm = sent-protocol LWS sent-by *( SEMI via-params ) * via-params = via-ttl / via-maddr * / via-received / via-branch * / via-extension * via-ttl = "ttl" EQUAL ttl * via-maddr = "maddr" EQUAL host * via-received = "received" EQUAL (IPv4address / IPv6address) * via-branch = "branch" EQUAL token * via-extension = generic-param * sent-protocol = protocol-name SLASH protocol-version * SLASH transport * protocol-name = "SIP" / token * protocol-version = token * transport = "UDP" / "TCP" / "TLS" / "SCTP" * / other-transport * sent-by = host [ COLON port ] * ttl = 1*3DIGIT ; 0 to 255 * * There can be multiple via headers we always append the header. */intsip_parse_via_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ sip_parsed_header_t *parsed_header; int ret; sip_hdr_value_t *value = NULL; sip_hdr_value_t *last_value = NULL; if (sip_header == NULL || header == NULL) return (EINVAL); /* check if already parsed */ if (sip_header->sip_hdr_parsed != NULL) { *header = sip_header->sip_hdr_parsed; return (0); } *header = NULL; assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); if (sip_parse_goto_values(sip_header) != 0) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; parsed_header->sip_header = sip_header; while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_phdr(parsed_header); return (ENOMEM); } if (last_value != NULL) last_value->sip_next_value = value; else parsed_header->value = (sip_value_t *)value; value->sip_value_version = SIP_VALUE_VERSION_1; value->sip_value_start = sip_header->sip_hdr_current; value->sip_value_header = parsed_header; value->via_protocol_name.sip_str_ptr = sip_header->sip_hdr_current; /* * Check to see if there is a version number */ if (sip_get_protocol_version(sip_header, &value->via_protocol) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } if (sip_find_token(sip_header, SIP_SLASH) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } if (sip_skip_white_space(sip_header) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } value->via_protocol_transport.sip_str_ptr = sip_header->sip_hdr_current; if (sip_find_white_space(sip_header) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } value->via_protocol_transport.sip_str_len = sip_header->sip_hdr_current - value->via_protocol_transport.sip_str_ptr; if (sip_skip_white_space(sip_header) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } value->via_sent_by_host.sip_str_ptr = sip_header->sip_hdr_current; if (*sip_header->sip_hdr_current == '[') { if (sip_find_token(sip_header, ']')) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_COMMA, SIP_HCOLON)) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } value->via_sent_by_host.sip_str_len = sip_header->sip_hdr_current - value->via_sent_by_host.sip_str_ptr; if (sip_skip_white_space(sip_header) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } if (*sip_header->sip_hdr_current == SIP_HCOLON) { sip_header->sip_hdr_current++; /* * We have a port number */ if (sip_atoi(sip_header, &value->via_sent_by_port) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } } /* * Do some sanity checking. * This should be replaced by a v4/v6 address check. */ if (value->via_sent_by_host.sip_str_len == 0 || (!isalnum(*value->via_sent_by_host.sip_str_ptr) && *value->via_sent_by_host.sip_str_ptr != '[')) { if (sip_goto_next_value(sip_header) != 0) { sip_free_phdr(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_via_value; } ret = sip_parse_params(sip_header, &value->sip_param_list); if (ret == EPROTO) { value->sip_value_state = SIP_VALUE_BAD; } else if (ret != 0) { sip_free_phdr(parsed_header); return (ret); }get_next_via_value: value->sip_value_end = sip_header->sip_hdr_current; if (sip_find_token(sip_header, SIP_COMMA) != 0) break; last_value = value; (void) sip_skip_white_space(sip_header); } sip_header->sip_hdr_parsed = parsed_header; *header = parsed_header; return (0);}/* Generic parser for Contact, From, To, Route and Record-Route headers */intsip_parse_cftr_header(_sip_header_t *sip_header, sip_parsed_header_t **header){ sip_parsed_header_t *parsed_header; char *tmp_ptr; char *tmp_ptr_2; int ret; sip_hdr_value_t *value = NULL; sip_hdr_value_t *last_value = NULL; if (sip_header == NULL || header == NULL) return (EINVAL); /* check if already parsed */ if (sip_header->sip_hdr_parsed != NULL) { *header = sip_header->sip_hdr_parsed; return (0); } *header = NULL; assert(sip_header->sip_hdr_start == sip_header->sip_hdr_current); if (sip_parse_goto_values(sip_header) != 0) return (EPROTO); parsed_header = calloc(1, sizeof (sip_parsed_header_t)); if (parsed_header == NULL) return (ENOMEM); parsed_header->sip_parsed_header_version = SIP_PARSED_HEADER_VERSION_1; parsed_header->sip_header = sip_header; while (sip_header->sip_hdr_current < sip_header->sip_hdr_end) { boolean_t quoted_name = B_FALSE; value = calloc(1, sizeof (sip_hdr_value_t)); if (value == NULL) { sip_free_cftr_header(parsed_header); return (ENOMEM); } if (last_value != NULL) last_value->sip_next_value = value; else parsed_header->value = (sip_value_t *)value; if (*sip_header->sip_hdr_current == SIP_QUOTE) { sip_header->sip_hdr_current++; quoted_name = B_TRUE; } value->sip_value_version = SIP_VALUE_VERSION_1; value->sip_value_start = sip_header->sip_hdr_current; value->sip_value_header = parsed_header; /* * lets see if there is a display name */ if (*sip_header->sip_hdr_current != '<') { tmp_ptr = sip_header->sip_hdr_current; /* * According to 20.10 '<' may not have a leading * space. */ if (quoted_name && sip_find_token(sip_header, SIP_QUOTE)) { if (sip_goto_next_value(sip_header) != 0) { sip_free_cftr_header(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } else if (sip_find_separator(sip_header, SIP_SEMI, SIP_LAQUOT, SIP_COMMA)) { /* * only a uri. */ value->cftr_uri.sip_str_ptr = tmp_ptr; value->cftr_uri.sip_str_len = sip_header->sip_hdr_current - tmp_ptr; /* * It's an error not to have a uri. */ if (value->cftr_uri.sip_str_len == 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_cftr_header( parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } continue; } tmp_ptr_2 = sip_header->sip_hdr_current; if (*sip_header->sip_hdr_current == SIP_SP) { if (sip_skip_white_space(sip_header) != 0) { /* * only a uri. */ value->cftr_uri.sip_str_ptr = tmp_ptr; value->cftr_uri.sip_str_len = tmp_ptr_2 - tmp_ptr; /* * It's an error not to have a uri. */ if (value->cftr_uri.sip_str_len == 0) { if (sip_goto_next_value( sip_header) != 0) { sip_free_cftr_header( parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } continue; } } if (*sip_header->sip_hdr_current != SIP_LAQUOT) { /* * No display name here. */ value->cftr_uri.sip_str_ptr = tmp_ptr; value->cftr_uri.sip_str_len = tmp_ptr_2 - tmp_ptr; /* * It's an error not to have a uri. */ if (value->cftr_uri.sip_str_len == 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_cftr_header( parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } goto get_params; } value->cftr_name = malloc(sizeof (sip_str_t)); if (value->cftr_name == NULL) { sip_free_cftr_header(parsed_header); return (ENOMEM); } value->cftr_name->sip_str_ptr = tmp_ptr; value->cftr_name->sip_str_len = tmp_ptr_2 - tmp_ptr; if (quoted_name) value->cftr_name->sip_str_len--; } if (sip_find_token(sip_header, SIP_LAQUOT) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_cftr_header(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } if (*sip_header->sip_hdr_current == SIP_SP) { if (sip_skip_white_space(sip_header) != 0) { if (sip_goto_next_value(sip_header) != 0) { sip_free_cftr_header(parsed_header); return (EPROTO); } value->sip_value_state = SIP_VALUE_BAD; goto get_next_cftr_value; } } tmp_ptr = sip_header->sip_hdr_current; if (sip_find_separator(sip_header, SIP_RAQUOT, (char)NULL, (char)NULL)) { if (sip_goto_next_value(sip_header) != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -