Skip to content

Commit

Permalink
Added regexp support for response codes
Browse files Browse the repository at this point in the history
Style fixed, DTD updated, test added

Updated the style. updated the DTD to allow regex

Fixed author in the test run
  • Loading branch information
Petr Cisar committed Nov 7, 2024
1 parent 0240350 commit 3f49675
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 25 deletions.
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)) {
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

0 comments on commit 3f49675

Please sign in to comment.