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

Added regexp support for response codes #769

Merged
merged 1 commit into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/scenario.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class message
char * peer_src;

/* If this is a recv */
int recv_response;
char * recv_response;
char * recv_request;
int optional;
bool advance_state;
Expand Down
16 changes: 16 additions & 0 deletions regress/github-#0769/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/sh
# This regression test is a part of SIPp.
# Author: Petr Cisar
. "`dirname "$0"`/../functions"; init

# uac.xml checks reception of regex-based responses
sippbg -sn uas -i 127.0.0.1 -p 5070 -m 1
sippbg -sf uac.xml -i 127.0.0.1 -m 1 127.0.0.1:5070
job2=$!

# If job2 did not finish, we have failure.
if /bin/kill -0 $job2 2>/dev/null; then
fail
else
ok
fi
77 changes: 77 additions & 0 deletions regress/github-#0769/uac.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario>
<send retrans="500">
<![CDATA[

INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Content-Type: application/sdp
Content-Length: [len]

v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000

]]>
</send>

<!-- Test regular response code (no wildcard) -->
<recv response="100" optional="true"/>

<!-- Test regex 18x response code -->
<recv response="^18.$" regexp_match="true" optional="true"/>

<!-- Make sure that no match also works -->
<recv response="^6" regexp_match="true" optional="true"/>

<!-- Test a simple prefix match on response code, it should also work -->
<recv response="^2" regexp_match="true" rtd="true"></recv>

<send>
<![CDATA[

ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Content-Length: 0

]]>
</send>

<pause/>

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

BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 4 BYE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Content-Length: 0

]]>
</send>

<recv response="200" crlf="true"/>

</scenario>
2 changes: 1 addition & 1 deletion sipp.dtd
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

<!ELEMENT recv ( action? ) >
<!ATTLIST recv %messageCmdCommon; >
<!ATTLIST recv response NMTOKEN #IMPLIED >
<!ATTLIST recv response CDATA #IMPLIED >
<!ATTLIST recv request CDATA #IMPLIED >
<!ATTLIST recv optional (true|false) #IMPLIED >
<!ATTLIST recv ignosesdp (true|false) #IMPLIED >
Expand Down
57 changes: 39 additions & 18 deletions src/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2348,7 +2348,7 @@ bool call::process_unexpected(const char* msg)
if (curmsg -> recv_request) {
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_request);
} else {
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", curmsg -> recv_response);
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_response);
}
} else if (curmsg -> M_type == MSG_TYPE_SEND) {
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending ");
Expand Down Expand Up @@ -4451,24 +4451,45 @@ bool call::matches_scenario(unsigned int index, int reply_code, char * request,
} else {
return !strcmp(curmsg->recv_request, request);
}
} else if (curmsg->recv_response && (curmsg->recv_response == reply_code)) {
/* This is a potential candidate, we need to match transactions. */
if (curmsg->response_txn) {
if (transactions[curmsg->response_txn - 1].txnID && !strcmp(transactions[curmsg->response_txn - 1].txnID, txn)) {
return true;
} else {
return false;
} else if (curmsg->recv_response) {
if (curmsg->regexp_match) { // Match response code using regex
char reply_code_str[8];
snprintf(reply_code_str, 8, "%u", reply_code); // Convert the response code to string
if (curmsg->regexp_compile == nullptr) {
regex_t *re = new regex_t;
/* No regex match position needed (NOSUB), we're simply
* looking for the <request method="INVITE|REGISTER"../>
* regex. */
if (regcomp(re, curmsg->recv_response, REGCOMP_PARAMS|REG_NOSUB)) {
ERROR("Invalid regular expression for index %d: %s", index, curmsg->recv_response);
}
curmsg->regexp_compile = re;
}
} else if (index == 0) {
/* Always true for the first message. */
return true;
} else if (curmsg->recv_response_for_cseq_method_list &&
strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
/* If we do not have a transaction defined, we just check the CSEQ method. */
return true;
} else {
return false;
}
if (regexec(curmsg->regexp_compile, reply_code_str, (size_t)0, nullptr, REGEXEC_PARAMS)) {
orgads marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
} else { // Exact numerical match
if (atoi(curmsg->recv_response) != reply_code) {
return false;
}
}
/* This is a potential candidate, we need to match transactions. */
if (curmsg->response_txn) {
if (transactions[curmsg->response_txn - 1].txnID && !strcmp(transactions[curmsg->response_txn - 1].txnID, txn)) {
return true;
} else {
return false;
}
} else if (index == 0) {
/* Always true for the first message. */
return true;
} else if (curmsg->recv_response_for_cseq_method_list &&
strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
/* If we do not have a transaction defined, we just check the CSEQ method. */
return true;
} else {
return false;
}
}

return false;
Expand Down
2 changes: 1 addition & 1 deletion src/logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void print_count_file(FILE* f, int header)
}
} else if (curmsg->recv_response) {
if (header) {
sprintf(temp_str, "%u_%d_", index, curmsg->recv_response);
sprintf(temp_str, "%u_%s_", index, curmsg->recv_response);

fprintf(f, "%sRecv%s", temp_str, stat_delimiter);
fprintf(f, "%sRetrans%s", temp_str, stat_delimiter);
Expand Down
5 changes: 3 additions & 2 deletions src/scenario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ message::message(int index, const char *desc)
retrans_delay = 0;
timeout = 0;

recv_response = 0;
recv_response = nullptr; // free on exit
recv_request = nullptr; // free on exit
optional = 0;
advance_state = true;
Expand Down Expand Up @@ -116,6 +116,7 @@ message::~message()
free(pause_desc);
delete send_scheme;
free(recv_request);
free(recv_response);
if (regexp_compile != nullptr) {
regfree(regexp_compile);
}
Expand Down Expand Up @@ -891,7 +892,7 @@ scenario::scenario(char * filename, int deflt)
curmsg->M_type = MSG_TYPE_RECV;
/* Received messages descriptions */
if((cptr = xp_get_value("response"))) {
curmsg ->recv_response = get_long(cptr, "response code");
curmsg ->recv_response = strdup(cptr);
if (method_list) {
curmsg->recv_response_for_cseq_method_list = strdup(method_list);
}
Expand Down
4 changes: 2 additions & 2 deletions src/screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,10 +529,10 @@ void ScreenPrinter::draw_scenario_screen()
} else if (curmsg->recv_response) {
if (creationMode == MODE_SERVER) {
buf_len += snprintf(buf + buf_len, bufsiz - buf_len,
" ----------> %-10d ", curmsg->recv_response);
" ----------> %-10s ", curmsg->recv_response);
} else {
buf_len += snprintf(buf + buf_len, bufsiz - buf_len,
" %10d <---------- ", curmsg->recv_response);
" %10s <---------- ", curmsg->recv_response);
}

if (curmsg->start_rtd) {
Expand Down