📄 sip_parser.c
字号:
if (parsing_headers) { if (!pj_scan_is_eof(scanner)) { /* Skip until next line. * Watch for header continuation. */ do { pj_scan_skip_line(scanner); } while (IS_SPACE(*scanner->curptr)); } /* Restore flag. Flag may be set in int_parse_sip_url() */ scanner->skip_ws = PJ_SCAN_AUTOSKIP_WS_HEADER; /* Continue parse next header, if any. */ if (!pj_scan_is_eof(scanner) && !IS_NEWLINE(*scanner->curptr)) { goto parse_headers; } } msg = NULL; } PJ_END; return msg;}/* Parse parameter (pname ["=" pvalue]). */static void 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){ /* pname */ parser_get_and_unescape(scanner, pool, spec, esc_spec, pname); /* init pvalue */ pvalue->ptr = NULL; pvalue->slen = 0; /* pvalue, if any */ if (*scanner->curptr == '=') { pj_scan_get_char(scanner); if (!pj_scan_is_eof(scanner)) { /* pvalue can be a quoted string. */ if (*scanner->curptr == '"') { pj_scan_get_quote( scanner, '"', '"', pvalue); if (option & PJSIP_PARSE_REMOVE_QUOTE) { pvalue->ptr++; pvalue->slen -= 2; } } else if(pj_cis_match(spec, *scanner->curptr)) { parser_get_and_unescape(scanner, pool, spec, esc_spec, pvalue); } } }}/* Parse parameter (pname ["=" pvalue]) using token. */void pjsip_parse_param_imp( pj_scanner *scanner, pj_pool_t *pool, pj_str_t *pname, pj_str_t *pvalue, unsigned option){ parse_param_imp(scanner, pool, pname, pvalue, &pjsip_TOKEN_SPEC, &pjsip_TOKEN_SPEC_ESC, option);}/* Parse parameter (pname ["=" pvalue]) using paramchar. */void pjsip_parse_uri_param_imp(pj_scanner *scanner, pj_pool_t *pool, pj_str_t *pname, pj_str_t *pvalue, unsigned option){ parse_param_imp(scanner, pool, pname, pvalue, &pjsip_PARAM_CHAR_SPEC, &pjsip_PARAM_CHAR_SPEC_ESC, option);}/* Parse parameter (";" pname ["=" pvalue]) in header. */static void int_parse_param( pj_scanner *scanner, pj_pool_t *pool, pj_str_t *pname, pj_str_t *pvalue, unsigned option){ /* Get ';' character */ pj_scan_get_char(scanner); /* Get pname and optionally pvalue */ pjsip_parse_param_imp(scanner, pool, pname, pvalue, option);}/* Parse parameter (";" pname ["=" pvalue]) in URI. */static void int_parse_uri_param( pj_scanner *scanner, pj_pool_t *pool, pj_str_t *pname, pj_str_t *pvalue, unsigned option){ /* Get ';' character */ pj_scan_get_char(scanner); /* Get pname and optionally pvalue */ pjsip_parse_uri_param_imp(scanner, pool, pname, pvalue, option);}/* Parse header parameter. */static void int_parse_hparam( pj_scanner *scanner, pj_pool_t *pool, pj_str_t *hname, pj_str_t *hvalue ){ /* Get '?' or '&' character. */ pj_scan_get_char(scanner); /* hname */ parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC, &pjsip_HDR_CHAR_SPEC_ESC, hname); /* Init hvalue */ hvalue->ptr = NULL; hvalue->slen = 0; /* pvalue, if any */ if (*scanner->curptr == '=') { pj_scan_get_char(scanner); if (!pj_scan_is_eof(scanner) && pj_cis_match(&pjsip_HDR_CHAR_SPEC, *scanner->curptr)) { parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC, &pjsip_HDR_CHAR_SPEC_ESC, hvalue); } }}/* Parse host:port in URI. */static void int_parse_uri_host_port( pj_scanner *scanner, pj_str_t *host, int *p_port){ pj_scan_get( scanner, &pjsip_HOST_SPEC, host); /* RFC3261 section 19.1.2: host don't need to be unescaped */ if (*scanner->curptr == ':') { pj_str_t port; pj_scan_get_char(scanner); pj_scan_get(scanner, &pjsip_DIGIT_SPEC, &port); *p_port = pj_strtoul(&port); } else { *p_port = 0; }}/* Determine if the next token in an URI is a user specification. */static int int_is_next_user(pj_scanner *scanner){ pj_str_t dummy; int is_user; /* Find character '@'. If this character exist, then the token * must be a username. */ if (pj_scan_peek( scanner, &pjsip_PROBE_USER_HOST_SPEC, &dummy) == '@') is_user = 1; else is_user = 0; return is_user;}/* Parse user:pass tokens in an URI. */static void int_parse_user_pass( pj_scanner *scanner, pj_pool_t *pool, pj_str_t *user, pj_str_t *pass){ parser_get_and_unescape(scanner, pool, &pjsip_USER_SPEC, &pjsip_USER_SPEC_ESC, user); if ( *scanner->curptr == ':') { pj_scan_get_char( scanner ); parser_get_and_unescape(scanner, pool, &pjsip_PASSWD_SPEC, &pjsip_PASSWD_SPEC_ESC, pass); } else { pass->ptr = NULL; pass->slen = 0; } /* Get the '@' */ pj_scan_get_char( scanner );}/* Parse all types of URI. */static pjsip_uri *int_parse_uri_or_name_addr( pj_scanner *scanner, pj_pool_t *pool, unsigned opt){ pjsip_uri *uri; int is_name_addr = 0; /* Exhaust any whitespaces. */ pj_scan_skip_whitespace(scanner); if (*scanner->curptr=='"' || *scanner->curptr=='<') { uri = (pjsip_uri*)int_parse_name_addr( scanner, pool ); is_name_addr = 1; } else { pj_str_t scheme; int next_ch; next_ch = pj_scan_peek( scanner, &pjsip_DISPLAY_SPEC, &scheme); if (next_ch==':') { pjsip_parse_uri_func *func = find_uri_handler(&scheme); if (func == NULL) { /* Unsupported URI scheme */ PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } uri = (*func)( scanner, pool, (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0); } else { uri = (pjsip_uri*)int_parse_name_addr( scanner, pool ); is_name_addr = 1; } } /* Should we return the URI object as name address? */ if (opt & PJSIP_PARSE_URI_AS_NAMEADDR) { if (is_name_addr == 0) { pjsip_name_addr *name_addr; name_addr = pjsip_name_addr_create(pool); name_addr->uri = uri; uri = (pjsip_uri*)name_addr; } } return uri;}/* Parse URI. */static pjsip_uri *int_parse_uri(pj_scanner *scanner, pj_pool_t *pool, pj_bool_t parse_params){ /* Bug: * This function should not call back int_parse_name_addr() because * it is called by that function. This would cause stack overflow * with PROTOS test #1223. if (*scanner->curptr=='"' || *scanner->curptr=='<') { return (pjsip_uri*)int_parse_name_addr( scanner, pool ); } else { */ pj_str_t scheme; int colon; pjsip_parse_uri_func *func; /* Get scheme. */ colon = pj_scan_peek(scanner, &pjsip_TOKEN_SPEC, &scheme); if (colon != ':') { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } func = find_uri_handler(&scheme); if (func) { return (pjsip_uri*)(*func)(scanner, pool, parse_params); } else { /* Unsupported URI scheme */ PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); UNREACHED({ return NULL; /* Not reached. */ }) } /* } */}/* Parse "sip:" and "sips:" URI. * This actually returns (pjsip_sip_uri*) type, */static void* int_parse_sip_url( pj_scanner *scanner, pj_pool_t *pool, pj_bool_t parse_params){ pj_str_t scheme; pjsip_sip_uri *url = NULL; int colon; int skip_ws = scanner->skip_ws; scanner->skip_ws = 0; pj_scan_get(scanner, &pjsip_TOKEN_SPEC, &scheme); colon = pj_scan_get_char(scanner); if (colon != ':') { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); } if (parser_stricmp(scheme, pjsip_SIP_STR)==0) { url = pjsip_sip_uri_create(pool, 0); } else if (parser_stricmp(scheme, pjsip_SIPS_STR)==0) { url = pjsip_sip_uri_create(pool, 1); } else { PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); /* should not reach here */ UNREACHED({ pj_assert(0); return 0; }) } if (int_is_next_user(scanner)) { int_parse_user_pass(scanner, pool, &url->user, &url->passwd); } /* Get host:port */ int_parse_uri_host_port(scanner, &url->host, &url->port); /* Get URL parameters. */ if (parse_params) { while (*scanner->curptr == ';' ) { pj_str_t pname, pvalue; int_parse_uri_param( scanner, pool, &pname, &pvalue, 0); if (!parser_stricmp(pname, pjsip_USER_STR) && pvalue.slen) { url->user_param = pvalue; } else if (!parser_stricmp(pname, pjsip_METHOD_STR) && pvalue.slen) { url->method_param = pvalue; } else if (!parser_stricmp(pname,pjsip_TRANSPORT_STR) && pvalue.slen) { url->transport_param = pvalue; } else if (!parser_stricmp(pname, pjsip_TTL_STR) && pvalue.slen) { url->ttl_param = pj_strtoul(&pvalue); } else if (!parser_stricmp(pname, pjsip_MADDR_STR) && pvalue.slen) { url->maddr_param = pvalue; } else if (!parser_stricmp(pname, pjsip_LR_STR)) { url->lr_param = 1; } else { pjsip_param *p = pj_pool_alloc(pool, sizeof(pjsip_param)); p->name = pname; p->value = pvalue; pj_list_insert_before(&url->other_param, p); } } } /* Get header params. */ if (parse_params && *scanner->curptr == '?') { do { pjsip_param *param; param = pj_pool_alloc(pool, sizeof(pjsip_param)); int_parse_hparam(scanner, pool, ¶m->name, ¶m->value); pj_list_insert_before(&url->header_param, param); } while (*scanner->curptr == '&'); } scanner->skip_ws = skip_ws; pj_scan_skip_whitespace(scanner); return url;}/* Parse nameaddr. */static pjsip_name_addr *int_parse_name_addr( pj_scanner *scanner, pj_pool_t *pool ){ int has_bracket; pjsip_name_addr *name_addr; name_addr = pjsip_name_addr_create(pool); if (*scanner->curptr == '"') { pj_scan_get_quote( scanner, '"', '"', &name_addr->display); /* Trim the leading and ending quote */ name_addr->display.ptr++; name_addr->display.slen -= 2; } else if (*scanner->curptr != '<') { int next; pj_str_t dummy; /* This can be either the start of display name, * the start of URL ("sip:", "sips:", "tel:", etc.), or '<' char. * We're only interested in display name, because SIP URL * will be parser later. */ next = pj_scan_peek(scanner, &pjsip_DISPLAY_SPEC, &dummy); if (next == '<') { /* Ok, this is what we're looking for, a display name. */ pj_scan_get_until_ch( scanner, '<', &name_addr->display); pj_strtrim(&name_addr->display); } } /* Manually skip whitespace. */ pj_scan_skip_whitespace(scanner); /* Get the SIP-URL */ has_bracket = (*scanner->curptr == '<'); if (has_bracket) pj_scan_get_char(scanner); name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE ); if (has_bracket) { if (pj_scan_get_char(scanner) != '>') PJ_THROW( PJSIP_SYN_ERR_EXCEPTION); } return name_addr;}/* Parse SIP request line. */static void int_parse_req_line( pj_scanner *scanner, pj_pool_t *pool, pjsip_request_line *req_line){ pj_str_t token; pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &token); pjsip_method_init_np( &req_line->method, &token); req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE); if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0) PJ_THROW( PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n (scanner, 7, 1); pj_scan_get_newline( scanner );}/* Parse status line. */static void int_parse_status_line( pj_scanner *scanner, pjsip_status_line *status_line){ pj_str_t token; if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0) PJ_THROW(PJSIP_SYN_ERR_EXCEPTION); pj_scan_advance_n( scanner, 7, 1); pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &token); status_line->code = pj_strtoul(&token); pj_scan_get( scanner, &pjsip_NOT_NEWLINE, &status_line->reason); pj_scan_get_newline( scanner );}/* * Public API to parse SIP status line. */PJ_DEF(pj_status_t) pjsip_parse_status_line( char *buf, pj_size_t size, pjsip_status_line *status_line){ pj_scanner scanner; PJ_USE_EXCEPTION; pj_bzero(status_line, sizeof(*status_line)); pj_scan_init(&scanner, buf, size, 0, &on_syntax_error); PJ_TRY { int_parse_status_line(&scanner, status_line); } PJ_CATCH_ANY { /* Tolerate the error if it is caused only by missing newline */ if (status_line->code == 0 && status_line->reason.slen == 0) { pj_scan_fini(&scanner); return PJSIP_EINVALIDMSG; } } PJ_END; pj_scan_fini(&scanner); return PJ_SUCCESS;}/* Parse ending of header. */static void parse_hdr_end( pj_scanner *scanner ){ if (pj_scan_is_eof(scanner)) { ; /* Do nothing. */ } else if (*scanner->curptr == '&') { pj_scan_get_char(scanner); } else { pj_scan_get_newline(scanner); }}/* Parse ending of header. */void pjsip_parse_end_hdr_imp( pj_scanner *scanner ){ parse_hdr_end(scanner);}/* Parse generic array header. */static void parse_generic_array_hdr( pjsip_generic_array_hdr *hdr, pj_scanner *scanner){ /* Some header fields allow empty elements in the value: * Accept, Allow, Supported */ if (pj_scan_is_eof(scanner) || *scanner->curptr == '\r' || *scanner->curptr == '\n') { goto end; } pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[0]); hdr->count++; while (*scanner->curptr == ',') { pj_scan_get_char(scanner); pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[hdr->count]); hdr->count++; if (hdr->count >= PJSIP_GENERIC_ARRAY_MAX_COUNT) break; }end:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -