diff --git a/include/call.hpp b/include/call.hpp index 2861dbda..6963f578 100644 --- a/include/call.hpp +++ b/include/call.hpp @@ -291,7 +291,6 @@ class call : virtual public task, virtual public listener, public virtual socket char * get_header_field_code(const char * msg, const char * code); char * get_last_header(const char * name); - char * get_last_request_uri(); unsigned long hash(const char * msg); typedef std::map file_line_map; diff --git a/include/sip_parser.hpp b/include/sip_parser.hpp index c059815e..402372d4 100644 --- a/include/sip_parser.hpp +++ b/include/sip_parser.hpp @@ -26,6 +26,8 @@ #define MAX_HEADER_LEN 2049 char *get_call_id(const char *msg); +char *get_header_uri(const char *msg, const char *name, const char *shortname); +char *get_param(const char *msg, const char *param, const char *name, const char *shortname); char *get_peer_tag(const char *msg); int get_method(char *msg); diff --git a/regress/github-#0260/run b/regress/github-#0260/run new file mode 100755 index 00000000..3fd8d2c1 --- /dev/null +++ b/regress/github-#0260/run @@ -0,0 +1,34 @@ +#!/bin/sh +# This regression test is a part of SIPp. +# Author: Pietro Bertera, Snom Technology AG, 2016 + +. "`dirname "$0"`/../functions"; init + +sippbg -m 1 -sf uas.xml -p 5070 -i 127.0.0.1 \ + -timeout 4 -timeout_error -trace_logs \ + -log_file log.log >/dev/null 2>&1 + +job=$! + +sippfg -m 1 -sf uac.xml -i 127.0.0.1 -p 5060 127.0.0.1:5070 \ + -timeout 4 -timeout_error >/dev/null 2>&1 + +status=$? +wait $job || status=1 + + +if test $status -ne 0; then + fail "process failure" +elif ! grep -qF 'LAST Contact|Contact: ' log.log; then + fail "[last_Contact] header not found" +elif ! grep -qF 'LAST Contact:|Contact: ' log.log; then + fail "[last_Contact:] header not found" +elif ! grep -qF 'LAST From:value|"Tom Jones" ;tag=SIPpTag001' log.log; then + fail "[last_From:value] not found" +elif ! grep -qF 'LAST To:uri|sip:cheese@paris.fr' log.log; then + fail "[last_To:uri] not found" +elif ! grep -qF 'LAST From:param.tag|SIPpTag001' log.log; then + fail "[last_From:param.tag] not found" +fi + +ok diff --git a/regress/github-#0260/uac.xml b/regress/github-#0260/uac.xml new file mode 100644 index 00000000..f06d2430 --- /dev/null +++ b/regress/github-#0260/uac.xml @@ -0,0 +1,54 @@ + + + + + ;tag=SIPpTag00[call_number] + To: "Fromage" + Call-ID: [call_id] + CSeq: 1 INVITE + Contact: + Content-Length: 0 + + ]]> + + + + + + ;tag=SIPpTag00[call_number] + To: "Fromage" [peer_tag_param] + Call-ID: [call_id] + CSeq: 1 ACK + Contact: sip:sipp@[local_ip]:[local_port] + Content-Length: 0 + + ]]> + + + + + + + Content-Length: 0 + + ]]> + + + + diff --git a/regress/github-#0260/uas.xml b/regress/github-#0260/uas.xml new file mode 100644 index 00000000..ffcc1331 --- /dev/null +++ b/regress/github-#0260/uas.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/call.cpp b/src/call.cpp index 457d3559..beda2495 100644 --- a/src/call.cpp +++ b/src/call.cpp @@ -920,56 +920,32 @@ char * call::get_last_header(const char * name) ERROR("call::get_last_header: Header to parse bigger than %d (%zu)", MAX_HEADER_LEN, strlen(name)); } - if (name[len - 1] == ':') { - return get_header(last_recv_msg, name, false); - } else { - char with_colon[MAX_HEADER_LEN]; - sprintf(with_colon, "%s:", name); - return get_header(last_recv_msg, with_colon, false); - } -} - -/* Return the last request URI from the To header. On any error returns the - * empty string. The caller must free the result. */ -char * call::get_last_request_uri() -{ - char * tmp; - char * tmp2; - char * last_request_uri; - int tmp_len; - - char * last_To = get_last_header("To:"); - if (!last_To) { - return strdup(""); - } - - tmp = strchr(last_To, '<'); - if (!tmp) { - return strdup(""); - } - tmp++; + char header_name[MAX_HEADER_LEN]; + const char *sep = strrchr(name, ':'); - tmp2 = strchr(last_To, '>'); - if (!tmp2) { - return strdup(""); + if (!sep){ /* [last_Header] */ + sprintf(header_name, "%s:", name); + return get_header(last_recv_msg, header_name, false); } - tmp_len = strlen(tmp) - strlen(tmp2); - if (tmp_len < 0) { - return strdup(""); - } + snprintf(header_name, len - strlen(sep) + 2, name); - if (!(last_request_uri = (char *)malloc(tmp_len + 1))) { - ERROR("Cannot allocate !\n"); + /* [last_Header:] */ + if (name[len - 1] == ':') { + return get_header(last_recv_msg, name, false); } - last_request_uri[0] = '\0'; - if (tmp && (tmp_len > 0)) { - strncpy(last_request_uri, tmp, tmp_len); + if (!strcmp(sep, ":value")) { /* [last_Header:value] */ + return get_header(last_recv_msg, header_name, true); + } else if (!strcmp(sep, ":uri")) { /* [last_Header:uri] */ + snprintf(header_name, len - 3, "%s", name); + return get_header_uri(last_recv_msg, header_name, ""); + } else if (!strcmp(sep, ":param.tag")) { /* [last_Header:param.tag] */ + snprintf(header_name, len - 9, "%s", name); + return get_param(last_recv_msg, "tag", header_name, ""); + } else { + ERROR("Token %s not valid in %s", sep, name); } - last_request_uri[tmp_len] = '\0'; - - return last_request_uri; } char * call::send_scene(int index, int *send_status, int *len) @@ -2201,9 +2177,7 @@ char* call::createSendingMessage(SendingMessage *src, int P_index, char *msg_buf } break; case E_Message_Last_Request_URI: { - char * last_request_uri = get_last_request_uri(); - dest += sprintf(dest, "%s", last_request_uri); - free(last_request_uri); + dest += sprintf(dest, "%s", get_last_header("To:uri")); break; } case E_Message_Last_CSeq_Number: { diff --git a/src/sip_parser.cpp b/src/sip_parser.cpp index ebc00241..719a55fa 100644 --- a/src/sip_parser.cpp +++ b/src/sip_parser.cpp @@ -70,17 +70,57 @@ static const char *internal_hdrend(const char *ptr); /*************************** Mini SIP parser (externals) ***************/ -char * get_peer_tag(const char *msg) +char * get_header_uri(const char *msg, const char *name, const char *shortname) +{ + char * start; + char * end; + const char * hdr; + static char last_request_uri[MAX_HEADER_LEN]; + int uri_len; + + /* Find start of header */ + hdr = internal_find_header(msg, name, shortname, true); + if (!hdr) { + WARNING("No valid %s: header found", name); + return NULL; + } + + start = strchr((char*)hdr, '<'); + if (!start) { + return NULL; + } + start++; + + end = strchr((char*)hdr, '>'); + if (!end) { + return NULL; + } + + uri_len = strlen(start) - strlen(end); + if (uri_len < 0) { + return NULL; + } + + last_request_uri[0] = '\0'; + if (start && (uri_len > 0)) { + strncpy(last_request_uri, start, uri_len); + } + last_request_uri[uri_len] = '\0'; + + return last_request_uri; +} + +char * get_param(const char *msg, const char * param, const char *name, const char *shortname) { static char tag[MAX_HEADER_LEN]; - const char * to_hdr; + const char * hdr; const char * ptr; int tag_i = 0; /* Find start of header */ - to_hdr = internal_find_header(msg, "To", "t", true); - if (!to_hdr) { - WARNING("No valid To: header in reply"); + hdr = internal_find_header(msg, name, shortname, true); + if (!hdr) { + WARNING("No valid %s: header in reply", name); return NULL; } @@ -88,14 +128,14 @@ char * get_peer_tag(const char *msg) /* FIXME */ /* Skip past LA/RA-quoted addr-spec if any */ - ptr = internal_hdrchr(to_hdr, '>'); + ptr = internal_hdrchr(hdr, '>'); if (!ptr) { /* Maybe an addr-spec without quotes */ - ptr = to_hdr; + ptr = hdr; } /* Find tag in this header */ - ptr = internal_find_param(ptr, "tag"); + ptr = internal_find_param(ptr, param); if (!ptr) { return NULL; } @@ -109,6 +149,11 @@ char * get_peer_tag(const char *msg) return tag; } +char * get_peer_tag(const char *msg) +{ + return get_param(msg, "tag", "To", "t"); +} + char * get_header_content(const char* message, const char * name) { return get_header(message, name, true); @@ -575,4 +620,19 @@ TEST(Parser, get_call_id_github_0101) { // github-#0101 EXPECT_STREQ("1-18220@127.0.0.1", get_call_id(input)); } +TEST(Parser, get_header_uri) { + EXPECT_STREQ("abc@domain.com", get_header_uri("...\r\nContact: ;test=123\r\n\r\n", "Contact", "")); +} + +TEST(Parser, get_param) { + EXPECT_STREQ("123", get_param("...\r\nContact: ;test=123\r\n\r\n", "test", "Contact", "")); +} + +TEST(Parser, get_header) { + EXPECT_STREQ("Contact: ;test=123", get_header("...\r\nContact: ;test=123\r\n\r\n", "Contact:", false)); +} + +TEST(Parser, get_header_content) { + EXPECT_STREQ(";test=123", get_header("...\r\nContact: ;test=123\r\n\r\n", "Contact:", true)); +} #endif //GTEST