Skip to content

Commit 3f49675

Browse files
author
Petr Cisar
committed
Added regexp support for response codes
Style fixed, DTD updated, test added Updated the style. updated the DTD to allow regex Fixed author in the test run
1 parent 0240350 commit 3f49675

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)