blob: 67e78188e5480a73e228125cd087516c3a4af0b7 [file] [log] [blame]
Harald Welteafec4712018-03-19 22:52:17 +01001module SIP_Tests {
2
Harald Welte34b5a952019-05-27 11:54:11 +02003/* osmo-sip-connector test suite in TTCN-3
4 * (C) 2018-2019 Harald Welte <laforge@gnumonks.org>
5 * All rights reserved.
6 *
7 * Released under the terms of GNU General Public License, Version 2 or
8 * (at your option) any later version.
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
Harald Welteafec4712018-03-19 22:52:17 +010013import from General_Types all;
14import from Osmocom_Types all;
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020015import from Native_Functions all;
16import from Misc_Helpers all;
Harald Welteafec4712018-03-19 22:52:17 +010017
18import from Osmocom_CTRL_Functions all;
19import from Osmocom_CTRL_Types all;
20import from Osmocom_CTRL_Adapter all;
21
22import from TELNETasp_PortType all;
23import from Osmocom_VTY_Functions all;
24
25import from MNCC_Emulation all;
26import from MNCC_Types all;
27
28import from SDP_Types all;
29
30import from SIP_Emulation all;
31import from SIPmsg_Types all;
Harald Welteb0d93602018-03-20 18:09:34 +010032import from SIP_Templates all;
Harald Welteafec4712018-03-19 22:52:17 +010033
34modulepar {
Harald Welteb0d93602018-03-20 18:09:34 +010035 charstring mp_local_host := "127.0.0.2";
Harald Welteafec4712018-03-19 22:52:17 +010036 charstring mp_osmosip_host := "127.0.0.1";
37 integer mp_osmosip_port_ctrl := -1; /* RFU */
38 charstring mp_mncc := "/tmp/mncc";
39}
40
41type component test_CT extends CTRL_Adapter_CT {
42 var MNCC_Emulation_CT vc_MNCC;
43 var SIP_Emulation_CT vc_SIP;
44
45 port TELNETasp_PT SIPVTY;
46}
47
48type component ConnHdlr extends SIP_ConnHdlr, MNCC_ConnHdlr {
49 var ConnHdlrPars g_pars;
50 timer g_Tguard;
51}
52
53type record ConnHdlrPars {
Harald Welteb0d93602018-03-20 18:09:34 +010054 float t_guard,
55 CallPars g_cp optional
56}
57
58type record CallPars {
59 boolean is_mo,
60 charstring calling,
61 charstring called,
62
63 uint32_t mncc_call_id optional,
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020064 CallParsComputed comp optional,
Harald Welteb0d93602018-03-20 18:09:34 +010065
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020066 charstring sip_rtp_addr,
67 uint16_t sip_rtp_port,
68 charstring cn_rtp_addr,
69 uint16_t cn_rtp_port
Harald Welteb0d93602018-03-20 18:09:34 +010070}
71
72type record CallParsComputed {
73 CallidString sip_call_id,
74 SipAddr sip_url_ext,
75 SipAddr sip_url_gsm,
76 charstring sip_body,
77 integer sip_seq_nr
78}
79
80private template (value) CallPars t_CallPars(boolean is_mo) := {
81 is_mo := is_mo,
82 calling := "12345",
83 called := "98766",
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020084
Harald Welteb0d93602018-03-20 18:09:34 +010085 mncc_call_id := omit,
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020086 comp := omit,
87 sip_rtp_addr := "1.2.3.4",
88 sip_rtp_port := 1234,
89 cn_rtp_addr := "5.6.7.8",
90 cn_rtp_port := 5678
Harald Welteb0d93602018-03-20 18:09:34 +010091}
92
93private function f_CallPars_compute(inout CallPars cp) {
94 if (cp.is_mo) {
95 cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.called, mp_local_host, 5060));
96 cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.calling, mp_osmosip_host, 5060));
97 cp.mncc_call_id := f_rnd_int(429496725);
98 } else {
99 cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.calling, mp_local_host, 5060));
100 cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.called, mp_osmosip_host, 5060));
101 cp.comp.sip_call_id := hex2str(f_rnd_hexstring(15));
102 }
103 cp.comp.sip_seq_nr := f_rnd_int(4294967295);
104 cp.comp.sip_body := "";
Harald Welteafec4712018-03-19 22:52:17 +0100105}
106
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200107private function f_mgcp_addr2addrtype(charstring addr) return charstring {
108 for (var integer i := 0; i < lengthof(addr); i := i + 1) {
109 if (addr[i] == ":") {
110 return "IP6";
111 }
112 }
113 return "IP4";
114}
115
116private function f_addrstr2addr(charstring addr) return octetstring {
117 if (f_addr_is_ipv6(addr)) {
118 return f_inet6_addr(addr);
119 } else {
120 return f_inet_addr(addr);
121 }
122}
Harald Welteafec4712018-03-19 22:52:17 +0100123
124function f_init_mncc(charstring id) runs on test_CT {
125 id := id & "-MNCC";
126 var MnccOps ops := {
127 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
128 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
129 };
130
131 vc_MNCC := MNCC_Emulation_CT.create(id);
132 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
133 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_mncc, true));
134}
135
136function f_init() runs on test_CT {
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +0100137 //f_ipa_ctrl_start_client(mp_osmosip_host, mp_osmosip_port_ctrl);
Harald Welteafec4712018-03-19 22:52:17 +0100138 f_init_mncc("SIP_Test");
139 log("end of f_init_mncc");
140 f_init_sip(vc_SIP, "SIP_Test");
141 log("end of f_init_sip");
142
143 map(self:SIPVTY, system:SIPVTY);
144 f_vty_set_prompts(SIPVTY);
145 f_vty_transceive(SIPVTY, "enable");
146 log("end of f_init");
147}
148
149type function void_fn(charstring id) runs on ConnHdlr;
150
151function f_start_handler(void_fn fn, ConnHdlrPars pars)
152runs on test_CT return ConnHdlr {
153 var ConnHdlr vc_conn;
154 var charstring id := testcasename();
155
156 vc_conn := ConnHdlr.create(id);
157
158 connect(vc_conn:SIP, vc_SIP:CLIENT);
159 connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
160
161 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
162 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
163
164 vc_conn.start(f_handler_init(fn, id, pars));
165 return vc_conn;
166}
167
168private altstep as_Tguard() runs on ConnHdlr {
169 [] g_Tguard.timeout {
170 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200171 mtc.stop;
Harald Welteafec4712018-03-19 22:52:17 +0100172 }
173}
174
175private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
176runs on ConnHdlr {
177 g_pars := pars;
178 g_Tguard.start(pars.t_guard);
179 activate(as_Tguard());
180
181 /* call the user-supied test case function */
182 fn.apply(id);
183}
184
185
186template (value) ConnHdlrPars t_Pars := {
Harald Welteb0d93602018-03-20 18:09:34 +0100187 t_guard := 30.0,
188 g_cp := omit
Harald Welteafec4712018-03-19 22:52:17 +0100189}
190
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200191altstep as_SIP_expect_resp(template PDU_SIP_Response sip_expect) runs on ConnHdlr
192{
193 [] SIP.receive(sip_expect);
194 [] SIP.receive {
195 log("FAIL: expected SIP message ", sip_expect);
196 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
197 }
198}
199
200function f_SIP_expect_req(template PDU_SIP_Request sip_expect) runs on ConnHdlr return PDU_SIP_Request
201{
202 var PDU_SIP_Request rx;
203 alt {
204 [] SIP.receive(sip_expect) -> value rx;
205 [] SIP.receive {
206 log("FAIL: expected SIP message ", sip_expect);
207 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
208 }
209 }
210 return rx;
211}
212
Harald Welteb0d93602018-03-20 18:09:34 +0100213/* Establish a mobile terminated call described in 'cp' */
214function f_establish_mt(inout CallPars cp) runs on ConnHdlr {
215 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
216 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
Harald Welteb0d93602018-03-20 18:09:34 +0100217 var MNCC_PDU mncc;
Harald Welteafec4712018-03-19 22:52:17 +0100218
Harald Welteb0d93602018-03-20 18:09:34 +0100219 /* Ask MNCC_Emulation to "expect" a call to the given called number */
220 f_create_mncc_expect(cp.called);
Harald Welteafec4712018-03-19 22:52:17 +0100221
Harald Welteb0d93602018-03-20 18:09:34 +0100222 /* OSC <- SIP: A party sends SIP invite for a MT-call into OSC */
223 SIP.send(ts_SIP_INVITE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
224 cp.comp.sip_seq_nr, cp.comp.sip_body));
Harald Welteb0d93602018-03-20 18:09:34 +0100225 /* OSC -> SIP */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200226 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
227 "INVITE", 100, ?, "Trying", *));
Harald Welteafec4712018-03-19 22:52:17 +0100228
Pau Espin Pedrol37cf4082020-09-23 16:59:16 +0200229 alt {
230 /* MSC <- OSC: OSC generates MNCC_SETUP_REQ from INVITE */
231 [] MNCC.receive(tr_MNCC_SETUP_req) -> value mncc {
232 cp.mncc_call_id := mncc.u.signal.callref;
233 }
234 [] SIP.receive {
Neels Hofmeyrbaf02722023-09-12 02:10:11 +0200235 setverdict(fail, "Received unexpected SIP response");
Pau Espin Pedrol37cf4082020-09-23 16:59:16 +0200236 SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
237 cp.comp.sip_seq_nr, omit));
238 mtc.stop;
239 }
240 }
241
Harald Welteb0d93602018-03-20 18:09:34 +0100242 /* MSC -> OSC: After MS sends CALL CONF in response to SETUP */
243 MNCC.send(ts_MNCC_CALL_CONF_ind(cp.mncc_call_id));
244 /* MSC <- OSC: OSC asks MSC to create RTP socket */
245 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id));
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200246 mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
247 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
248 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
249 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
250 MNCC.send(mncc);
Harald Welteafec4712018-03-19 22:52:17 +0100251
Harald Welteb0d93602018-03-20 18:09:34 +0100252 /* MSC -> OSC: After MS is ringing and sent CC ALERTING */
253 MNCC.send(ts_MNCC_ALERT_ind(cp.mncc_call_id));
254 SIP.clear;
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200255
256 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
257 "INVITE", 180, ?, "Ringing", *));
Harald Welteafec4712018-03-19 22:52:17 +0100258
Harald Welteb0d93602018-03-20 18:09:34 +0100259 /* MSC -> OSC: After MT user has picked up and sent CC CONNECT */
260 MNCC.send(ts_MNCC_SETUP_CNF(cp.mncc_call_id));
261
262 SIP.clear;
Harald Welteb0d93602018-03-20 18:09:34 +0100263 /* MSC <- OSC: OSC asks MSC to connect its RTP stream to remote end */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200264 MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id, f_addrstr2addr(cp.sip_rtp_addr), cp.sip_rtp_port));
265
Harald Welteb0d93602018-03-20 18:09:34 +0100266 /* OSC -> SIP: OSC confirms call establishment to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200267 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, contact_addr := ?,
268 method := "INVITE", status_code := 200,
269 seq_nr := ?, reason := "OK",
270 body := pattern "*" & cp.cn_rtp_addr & "*"));
271
Harald Welteb0d93602018-03-20 18:09:34 +0100272 /* OSC <- SIP: SIP world acknowledges "200 OK" */
273 SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
274 cp.comp.sip_seq_nr, omit));
275 /* MSC <- OSC: OSC sends SETUP COMPL to MNCC (which triggers CC CONNECT ACK */
276 MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id));
Harald Welteafec4712018-03-19 22:52:17 +0100277}
278
Harald Welteb0d93602018-03-20 18:09:34 +0100279/* Establish a mobile originated call described in 'cp' */
280function f_establish_mo(inout CallPars cp) runs on ConnHdlr {
281 var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN));
282 var MNCC_number src := valueof(ts_MNCC_number(cp.calling, GSM48_TON_UNKNOWN));
283 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
284 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
285 var PDU_SIP_Request sip_req;
286 var integer seq_nr;
287
288 f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec);
289
290 /* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */
291 MNCC.send(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
292 /* MSC <- OSC: Create GSM side RTP socket */
293 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
294 var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
295 mncc.u.rtp.payload_msg_type := oct2int('0300'O);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200296 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
297 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
298 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
299 MNCC.send(mncc);
Harald Welteb0d93602018-03-20 18:09:34 +0100300 }
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200301
Harald Welteb0d93602018-03-20 18:09:34 +0100302 /* OSC -> SIP: Send INVITE with GSM side IP/Port in SDP */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200303 sip_req := f_SIP_expect_req(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?));
304 cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
305 cp.comp.sip_call_id := sip_req.msgHeader.callId.callid;
306 seq_nr := sip_req.msgHeader.cSeq.seqNumber;
307
Harald Welteb0d93602018-03-20 18:09:34 +0100308 /* OSC <- SIP: Notify call is proceeding */
309 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
310 "INVITE", 100, seq_nr, "Trying", sip_req.msgHeader.via));
311 /* MSC <- OSC: "100 Trying" translated to MNCC_CALL_PROC_REQ */
312 MNCC.receive(tr_MNCC_CALL_PROC_req(cp.mncc_call_id));
313
314 /* OSC <- SIP: SIP-terminated user is ringing now */
315 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
316 "INVITE", 180, seq_nr, "Ringing", sip_req.msgHeader.via));
317
318 /* MSC <- OSC: "180 Ringing" translated to MNCC_ALERT_REQ */
319 MNCC.receive(tr_MNCC_ALERT_req(cp.mncc_call_id)) {}
320
321 /* OSC <- SIP: SIP-terminated user has accepted the call */
322 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
323 "INVITE", 200, seq_nr, "OK", sip_req.msgHeader.via,
324 cp.comp.sip_body));
325 MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id));
326 /* MSC <- OSC: "200 OK" translated to MNCC_SETUP_RSP */
327 MNCC.receive(tr_MNCC_SETUP_rsp(cp.mncc_call_id));
328
329 /* MSC -> OSC: CC CONNECT ACK was received from MS */
330 MNCC.send(ts_MNCC_SETUP_COMPL_ind(cp.mncc_call_id));
331 /* OSC -> SIP: Acknowledge the call */
332 SIP.receive(tr_SIP_ACK(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, omit));
333}
334
335/* Release call from the mobile side */
336function f_release_mobile(inout CallPars cp) runs on ConnHdlr {
337 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
338 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
339 var PDU_SIP_Request sip_req;
340 SIP.clear;
341 /* MSC -> OSC: Simulate a CC DISCONNET from the MT user */
342 MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200343
Harald Welteb0d93602018-03-20 18:09:34 +0100344 /* OSC -> SIP: Expect BYE from OSC to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200345 sip_req := f_SIP_expect_req(tr_SIP_BYE(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, *));
346 cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
347
Harald Welteb0d93602018-03-20 18:09:34 +0100348 /* OSC <- SIP: Acknowledge the BYE */
349 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
350 "BYE", 200, sip_req.msgHeader.cSeq.seqNumber, "OK",
351 sip_req.msgHeader.via));
352 /* MSC <- OSC: Send REL_REQ to MSC, triggers CC RELEASE REQ to MS */
353 MNCC.receive(tr_MNCC_REL_req(cp.mncc_call_id)); // CAUSE?
354 /* MSC -> OSC: MS has responded with CC CLEAR COMPL, triggers MNCC_REL_CNF */
355 MNCC.send(ts_MNCC_REL_cnf(cp.mncc_call_id, ts_MNCC_cause(0)));
356}
357
358/* Release call from the SIP side */
359function f_release_sip(inout CallPars cp) runs on ConnHdlr {
360 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
361 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
362 /* OSC <- SIP: SIP-side sends a BYE to OSC */
363 SIP.send(ts_SIP_BYE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
364 cp.comp.sip_seq_nr, omit));
365 /* MSC <- OSC: Expect OSC to cause MNCC Disconnect Request */
366 MNCC.receive(tr_MNCC_DISC_req(cp.mncc_call_id));
367 /* MSC -> OSC: Indicate GSM side release */
368 MNCC.send(ts_MNCC_REL_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
369 /* OSC -> SIP: Confirmation to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200370 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
371 "BYE", 200, cp.comp.sip_seq_nr, "OK", omit));
Harald Welteb0d93602018-03-20 18:09:34 +0100372}
373
374/* Successful MT Call, which is subsequently released by GSM side */
375private function f_TC_mt_success_rel_gsm(charstring id) runs on ConnHdlr {
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200376 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100377 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200378 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
379 f_mgcp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
380 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
381 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100382 f_sleep(3.0)
383
384 f_establish_mt(cp);
385 /* now call is fully established */
386 f_sleep(2.0);
387 f_release_mobile(cp);
388 setverdict(pass);
389}
390testcase TC_mt_success_rel_gsm() runs on test_CT {
Harald Welteafec4712018-03-19 22:52:17 +0100391 var ConnHdlrPars pars;
392 var ConnHdlr vc_conn;
Harald Welteafec4712018-03-19 22:52:17 +0100393 f_init();
Harald Welteafec4712018-03-19 22:52:17 +0100394 pars := valueof(t_Pars);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200395 pars.g_cp := valueof(t_CallPars(false));
396 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
397 vc_conn.done;
398}
399testcase TC_mt_success_rel_gsm_ipv6() runs on test_CT {
400 var ConnHdlrPars pars;
401 var ConnHdlr vc_conn;
402 f_init();
403 pars := valueof(t_Pars);
404 pars.g_cp := valueof(t_CallPars(false));
405 pars.g_cp.sip_rtp_addr := "::1";
406 pars.g_cp.cn_rtp_addr := "::2";
Harald Welteb0d93602018-03-20 18:09:34 +0100407 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
408 vc_conn.done;
409}
410
411/* Successful MT Call, which is subsequently released by SIP side */
412private function f_TC_mt_success_rel_sip(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200413 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100414 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200415 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
416 f_mgcp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
417 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
418 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100419 f_sleep(3.0)
420
421 f_establish_mt(cp);
422 /* now call is fully established */
423 f_sleep(2.0);
424 f_release_sip(cp);
425 setverdict(pass);
426}
427testcase TC_mt_success_rel_sip() runs on test_CT {
428 var ConnHdlrPars pars;
429 var ConnHdlr vc_conn;
430 f_init();
431 pars := valueof(t_Pars);
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200432 pars.g_cp := valueof(t_CallPars(false));
Harald Welteb0d93602018-03-20 18:09:34 +0100433 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_sip), pars);
Harald Welteafec4712018-03-19 22:52:17 +0100434 vc_conn.done;
435}
436
437
Harald Welteb0d93602018-03-20 18:09:34 +0100438/* Successful MO Call, which is subsequently released by GSM side */
439private function f_TC_mo_success_rel_gsm(charstring id) runs on ConnHdlr {
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200440 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100441 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200442 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
443 f_mgcp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
444 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
445 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100446 f_sleep(3.0)
Harald Welteafec4712018-03-19 22:52:17 +0100447
Harald Welteb0d93602018-03-20 18:09:34 +0100448 f_establish_mo(cp);
449 /* now call is fully established */
450 f_sleep(2.0);
451 f_release_mobile(cp);
452 setverdict(pass);
453}
454testcase TC_mo_success_rel_gsm() runs on test_CT {
455 var ConnHdlrPars pars;
456 var ConnHdlr vc_conn;
457 f_init();
458 pars := valueof(t_Pars);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200459 pars.g_cp := valueof(t_CallPars(true));
460 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
461 vc_conn.done;
462}
463testcase TC_mo_success_rel_gsm_ipv6() runs on test_CT {
464 var ConnHdlrPars pars;
465 var ConnHdlr vc_conn;
466 f_init();
467 pars := valueof(t_Pars);
468 pars.g_cp := valueof(t_CallPars(true));
469 pars.g_cp.sip_rtp_addr := "::1";
470 pars.g_cp.cn_rtp_addr := "::2";
Harald Welteb0d93602018-03-20 18:09:34 +0100471 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
472 vc_conn.done;
Harald Welteafec4712018-03-19 22:52:17 +0100473}
474
Harald Welteb0d93602018-03-20 18:09:34 +0100475/* Successful MO Call, which is subsequently released by SIP side */
476private function f_TC_mo_success_rel_sip(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200477 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100478 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200479 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
480 f_mgcp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
481 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
482 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100483 f_sleep(3.0)
Harald Welteafec4712018-03-19 22:52:17 +0100484
Harald Welteb0d93602018-03-20 18:09:34 +0100485 f_establish_mo(cp);
486 /* now call is fully established */
487 f_sleep(2.0);
488 f_release_sip(cp);
489 setverdict(pass);
490}
491testcase TC_mo_success_rel_sip() runs on test_CT {
492 var ConnHdlrPars pars;
493 var ConnHdlr vc_conn;
494 f_init();
495 pars := valueof(t_Pars);
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200496 pars.g_cp := valueof(t_CallPars(is_mo := true));
Harald Welteb0d93602018-03-20 18:09:34 +0100497 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars);
498 vc_conn.done;
499}
Harald Welteafec4712018-03-19 22:52:17 +0100500
Harald Welteddf011e2019-04-19 09:39:35 +0200501/* SETUP followed by DISC results in lingering B-leg (OS#3518)*/
502private function f_TC_mo_setup_disc_late_rtp(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200503 var CallPars cp := g_pars.g_cp;
Harald Welteddf011e2019-04-19 09:39:35 +0200504 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200505 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
506 f_mgcp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
507 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
508 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteddf011e2019-04-19 09:39:35 +0200509 f_sleep(3.0);
510
511 var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN));
512 var MNCC_number src := valueof(ts_MNCC_number(cp.calling, GSM48_TON_UNKNOWN));
513 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
514 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
515
516 f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec);
517
518 /* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */
519 MNCC.send(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
520
521 /* MSC -> OSC: Simulate a CC DISCONNET from the MT user *before* responding to the RTP_CREATE */
522 MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
523
524 /* MSC <- OSC: Create GSM side RTP socket (too late) */
525 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
526 var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
527 mncc.u.rtp.payload_msg_type := oct2int('0300'O);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200528 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
529 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
530 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
531 MNCC.send(mncc);
Harald Welteddf011e2019-04-19 09:39:35 +0200532 }
533
534 /* OSC -> SIP: We should never receive INVITE */
535 timer T := 10.0;
536 T.start;
537 alt {
538 [] SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) {
539 setverdict(fail, "Received unexpected INVITE");
540 }
541 [] T.timeout {
542 setverdict(pass);
543 }
544 }
545}
546testcase TC_mo_setup_disc_late_rtp() runs on test_CT {
547 var ConnHdlrPars pars;
548 var ConnHdlr vc_conn;
549 f_init();
550 pars := valueof(t_Pars);
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200551 pars.g_cp := valueof(t_CallPars(is_mo := true));
Harald Welteddf011e2019-04-19 09:39:35 +0200552 vc_conn := f_start_handler(refers(f_TC_mo_setup_disc_late_rtp), pars);
553 vc_conn.done;
554}
Harald Welteafec4712018-03-19 22:52:17 +0100555
556control {
Harald Welteb0d93602018-03-20 18:09:34 +0100557 execute( TC_mt_success_rel_gsm() );
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200558 execute( TC_mt_success_rel_gsm_ipv6() );
Harald Welteb0d93602018-03-20 18:09:34 +0100559 execute( TC_mt_success_rel_sip() );
560 execute( TC_mo_success_rel_gsm() );
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200561 execute( TC_mo_success_rel_gsm_ipv6() );
Harald Welteb0d93602018-03-20 18:09:34 +0100562 execute( TC_mo_success_rel_sip() );
Harald Welteddf011e2019-04-19 09:39:35 +0200563 execute( TC_mo_setup_disc_late_rtp() );
Harald Welteafec4712018-03-19 22:52:17 +0100564}
565
566
567
568}