Skip to content

Commit 03d7c04

Browse files
Petr Cisarorgads
Petr Cisar
authored andcommitted
Added regexp support for response codes
Now the regexp_match attribute should also work for response codes. Example: <recv response="^18" regexp_match="true" optional="true">
1 parent 73c4cfe commit 03d7c04

File tree

8 files changed

+140
-25
lines changed

8 files changed

+140
-25
lines changed

include/scenario.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class message
9393
char * peer_src;
9494

9595
/* If this is a recv */
96-
int recv_response;
96+
char * recv_response;
9797
char * recv_request;
9898
int optional;
9999
bool advance_state;

regress/github-#0769/run

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
# This regression test is a part of SIPp.
3+
# Author: Petr Cisar
4+
. "`dirname "$0"`/../functions"; init
5+
6+
# uac.xml checks reception of regex-based responses
7+
sippbg -sn uas -i 127.0.0.1 -p 5070 -m 1
8+
sippbg -sf uac.xml -i 127.0.0.1 -m 1 127.0.0.1:5070
9+
job2=$!
10+
11+
# If job2 did not finish, we have failure.
12+
if /bin/kill -0 $job2 2>/dev/null; then
13+
fail
14+
else
15+
ok
16+
fi

regress/github-#0769/uac.xml

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?xml version="1.0" encoding="ISO-8859-1"?>
2+
<!DOCTYPE scenario SYSTEM "sipp.dtd">
3+
<scenario>
4+
<send retrans="500">
5+
<![CDATA[
6+
7+
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
8+
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
9+
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
10+
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
11+
Call-ID: [call_id]
12+
CSeq: 1 INVITE
13+
Contact: sip:sipp@[local_ip]:[local_port]
14+
Max-Forwards: 70
15+
Content-Type: application/sdp
16+
Content-Length: [len]
17+
18+
v=0
19+
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
20+
s=-
21+
c=IN IP[media_ip_type] [media_ip]
22+
t=0 0
23+
m=audio [media_port] RTP/AVP 0
24+
a=rtpmap:0 PCMU/8000
25+
26+
]]>
27+
</send>
28+
29+
<!-- Test regular response code (no wildcard) -->
30+
<recv response="100" optional="true"/>
31+
32+
<!-- Test regex 18x response code -->
33+
<recv response="^18.$" regexp_match="true" optional="true"/>
34+
35+
<!-- Make sure that no match also works -->
36+
<recv response="^6" regexp_match="true" optional="true"/>
37+
38+
<!-- Test a simple prefix match on response code, it should also work -->
39+
<recv response="^2" regexp_match="true" rtd="true"></recv>
40+
41+
<send>
42+
<![CDATA[
43+
44+
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
45+
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
46+
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
47+
To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
48+
Call-ID: [call_id]
49+
CSeq: 1 ACK
50+
Contact: sip:sipp@[local_ip]:[local_port]
51+
Max-Forwards: 70
52+
Content-Length: 0
53+
54+
]]>
55+
</send>
56+
57+
<pause/>
58+
59+
<send retrans="500">
60+
<![CDATA[
61+
62+
BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
63+
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
64+
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
65+
To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
66+
Call-ID: [call_id]
67+
CSeq: 4 BYE
68+
Contact: sip:sipp@[local_ip]:[local_port]
69+
Max-Forwards: 70
70+
Content-Length: 0
71+
72+
]]>
73+
</send>
74+
75+
<recv response="200" crlf="true"/>
76+
77+
</scenario>

sipp.dtd

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
<!ELEMENT recv ( action? ) >
2727
<!ATTLIST recv %messageCmdCommon; >
28-
<!ATTLIST recv response NMTOKEN #IMPLIED >
28+
<!ATTLIST recv response CDATA #IMPLIED >
2929
<!ATTLIST recv request CDATA #IMPLIED >
3030
<!ATTLIST recv optional (true|false) #IMPLIED >
3131
<!ATTLIST recv ignosesdp (true|false) #IMPLIED >

src/call.cpp

+39-18
Original file line numberDiff line numberDiff line change
@@ -2348,7 +2348,7 @@ bool call::process_unexpected(const char* msg)
23482348
if (curmsg -> recv_request) {
23492349
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_request);
23502350
} else {
2351-
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%d' ", curmsg -> recv_response);
2351+
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while expecting '%s' ", curmsg -> recv_response);
23522352
}
23532353
} else if (curmsg -> M_type == MSG_TYPE_SEND) {
23542354
desc += snprintf(desc, MAX_HEADER_LEN - (desc - buffer), "while sending ");
@@ -4451,24 +4451,45 @@ bool call::matches_scenario(unsigned int index, int reply_code, char * request,
44514451
} else {
44524452
return !strcmp(curmsg->recv_request, request);
44534453
}
4454-
} else if (curmsg->recv_response && (curmsg->recv_response == reply_code)) {
4455-
/* This is a potential candidate, we need to match transactions. */
4456-
if (curmsg->response_txn) {
4457-
if (transactions[curmsg->response_txn - 1].txnID && !strcmp(transactions[curmsg->response_txn - 1].txnID, txn)) {
4458-
return true;
4459-
} else {
4460-
return false;
4454+
} else if (curmsg->recv_response) {
4455+
if (curmsg->regexp_match) { // Match response code using regex
4456+
char reply_code_str[8];
4457+
snprintf(reply_code_str, 8, "%u", reply_code); // Convert the response code to string
4458+
if (curmsg->regexp_compile == nullptr) {
4459+
regex_t *re = new regex_t;
4460+
/* No regex match position needed (NOSUB), we're simply
4461+
* looking for the <request method="INVITE|REGISTER"../>
4462+
* regex. */
4463+
if (regcomp(re, curmsg->recv_response, REGCOMP_PARAMS|REG_NOSUB)) {
4464+
ERROR("Invalid regular expression for index %d: %s", index, curmsg->recv_response);
4465+
}
4466+
curmsg->regexp_compile = re;
44614467
}
4462-
} else if (index == 0) {
4463-
/* Always true for the first message. */
4464-
return true;
4465-
} else if (curmsg->recv_response_for_cseq_method_list &&
4466-
strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
4467-
/* If we do not have a transaction defined, we just check the CSEQ method. */
4468-
return true;
4469-
} else {
4470-
return false;
4471-
}
4468+
if (regexec(curmsg->regexp_compile, reply_code_str, (size_t)0, nullptr, REGEXEC_PARAMS)) {
4469+
return false;
4470+
}
4471+
} else { // Exact numerical match
4472+
if (atoi(curmsg->recv_response) != reply_code) {
4473+
return false;
4474+
}
4475+
}
4476+
/* This is a potential candidate, we need to match transactions. */
4477+
if (curmsg->response_txn) {
4478+
if (transactions[curmsg->response_txn - 1].txnID && !strcmp(transactions[curmsg->response_txn - 1].txnID, txn)) {
4479+
return true;
4480+
} else {
4481+
return false;
4482+
}
4483+
} else if (index == 0) {
4484+
/* Always true for the first message. */
4485+
return true;
4486+
} else if (curmsg->recv_response_for_cseq_method_list &&
4487+
strstr(curmsg->recv_response_for_cseq_method_list, responsecseqmethod)) {
4488+
/* If we do not have a transaction defined, we just check the CSEQ method. */
4489+
return true;
4490+
} else {
4491+
return false;
4492+
}
44724493
}
44734494

44744495
return false;

src/logger.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void print_count_file(FILE* f, int header)
114114
}
115115
} else if (curmsg->recv_response) {
116116
if (header) {
117-
sprintf(temp_str, "%u_%d_", index, curmsg->recv_response);
117+
sprintf(temp_str, "%u_%s_", index, curmsg->recv_response);
118118

119119
fprintf(f, "%sRecv%s", temp_str, stat_delimiter);
120120
fprintf(f, "%sRetrans%s", temp_str, stat_delimiter);

src/scenario.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ message::message(int index, const char *desc)
5353
retrans_delay = 0;
5454
timeout = 0;
5555

56-
recv_response = 0;
56+
recv_response = nullptr; // free on exit
5757
recv_request = nullptr; // free on exit
5858
optional = 0;
5959
advance_state = true;
@@ -116,6 +116,7 @@ message::~message()
116116
free(pause_desc);
117117
delete send_scheme;
118118
free(recv_request);
119+
free(recv_response);
119120
if (regexp_compile != nullptr) {
120121
regfree(regexp_compile);
121122
}
@@ -891,7 +892,7 @@ scenario::scenario(char * filename, int deflt)
891892
curmsg->M_type = MSG_TYPE_RECV;
892893
/* Received messages descriptions */
893894
if((cptr = xp_get_value("response"))) {
894-
curmsg ->recv_response = get_long(cptr, "response code");
895+
curmsg ->recv_response = strdup(cptr);
895896
if (method_list) {
896897
curmsg->recv_response_for_cseq_method_list = strdup(method_list);
897898
}

src/screen.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,10 @@ void ScreenPrinter::draw_scenario_screen()
529529
} else if (curmsg->recv_response) {
530530
if (creationMode == MODE_SERVER) {
531531
buf_len += snprintf(buf + buf_len, bufsiz - buf_len,
532-
" ----------> %-10d ", curmsg->recv_response);
532+
" ----------> %-10s ", curmsg->recv_response);
533533
} else {
534534
buf_len += snprintf(buf + buf_len, bufsiz - buf_len,
535-
" %10d <---------- ", curmsg->recv_response);
535+
" %10s <---------- ", curmsg->recv_response);
536536
}
537537

538538
if (curmsg->start_rtd) {

0 commit comments

Comments
 (0)