Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snom patch: Last_ keywords extension #260

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 0 additions & 1 deletion include/call.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <std::string, int> file_line_map;
Expand Down
2 changes: 2 additions & 0 deletions include/sip_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 34 additions & 0 deletions regress/github-#0260/run
Original file line number Diff line number Diff line change
@@ -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: <sip:sipp@127.0.0.1:5060>' log.log; then
fail "[last_Contact] header not found"
elif ! grep -qF 'LAST Contact:|Contact: <sip:sipp@127.0.0.1:5060>' log.log; then
fail "[last_Contact:] header not found"
elif ! grep -qF 'LAST From:value|"Tom Jones" <sip:tom.jones@wales.uk>;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
Copy link
Member

@wdoekes wdoekes Oct 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be done without so much nesting with negative tests instead:

if test $status -ne 0; then
    fail "process failure"
elif ! grep -q '^LAST From: "Tom Jones" <sip:tom\.jones@wales.uk>;tag=SIPpTag001$' log.log; then
    fail "From header not found"
...


ok
54 changes: 54 additions & 0 deletions regress/github-#0260/uac.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario>
<send retrans="500" start_txn="invite">
<![CDATA[

INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=justafake
From: "Tom Jones" <sip:tom.jones@wales.uk>;tag=SIPpTag00[call_number]
To: "Fromage" <sip:cheese@paris.fr>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: <sip:sipp@[local_ip]:[local_port]>
Content-Length: 0

]]>
</send>

<recv response="200" response_txn="invite" rrs="true"/>

<send retrans="500" ack_txn="invite">
<![CDATA[

ACK [next_url] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=justafake
From: "Tom Jones" <sip:tom.jones@wales.uk>;tag=SIPpTag00[call_number]
To: "Fromage" <sip:cheese@paris.fr>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Content-Length: 0

]]>
</send>

<recv request="BYE"/>

<send>
<![CDATA[

SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0

]]>
</send>

<timewait milliseconds="500"/>
</scenario>
53 changes: 53 additions & 0 deletions regress/github-#0260/uas.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario>
<recv request="INVITE"/>

<send retrans="500">
<![CDATA[

SIP/2.0 200 OK
[last_Contact]
[last_via]
From: [last_From:value]
To: [last_To:value];tag=[pid]SIPpTag00[call_number]
Call-ID: [last_Call-ID:value]
CSeq: [last_CSeq:value]
Contact: sip:sipp@[local_ip]:[local_port]
Content-Length: 0

]]>
</send>

<recv request="ACK" rrs="true">
<action>
<log message="LAST Contact|[last_Contact]" />
<log message="LAST Contact:|[last_Contact:]" />
<log message="LAST Contact:uri|[last_Contact:uri]"/>
<log message="LAST Via:value[last_Via:value]"/>
<log message="LAST From:value|[last_From:value]"/>
<log message="LAST To:value|[last_To:value]"/>
<log message="LAST To:uri|[last_To:uri]"/>
<log message="LAST From:param.tag|[last_From:param.tag]"/>
</action>
</recv>

<send retrans="500">
<![CDATA[

BYE [next_url] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: [last_To:value]
To: [last_From:value]
Call-ID: [call_id]
CSeq: 2 BYE
Contact: sip:sipp@[local_ip]:[local_port]
Content-Length: 0

]]>
</send>

<recv response="200"/>

<timewait milliseconds="500"/>
</scenario>
66 changes: 20 additions & 46 deletions src/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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: {
Expand Down
76 changes: 68 additions & 8 deletions src/sip_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,72 @@ 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;
}

/* Skip past display-name */
/* 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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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: <abc@domain.com>;test=123\r\n\r\n", "Contact", ""));
}

TEST(Parser, get_param) {
EXPECT_STREQ("123", get_param("...\r\nContact: <abc@domain.com>;test=123\r\n\r\n", "test", "Contact", ""));
}

TEST(Parser, get_header) {
EXPECT_STREQ("Contact: <abc@domain.com>;test=123", get_header("...\r\nContact: <abc@domain.com>;test=123\r\n\r\n", "Contact:", false));
}

TEST(Parser, get_header_content) {
EXPECT_STREQ("<abc@domain.com>;test=123", get_header("...\r\nContact: <abc@domain.com>;test=123\r\n\r\n", "Contact:", true));
}
#endif //GTEST