blob: ab33af713e41b65673f4ca40ddd6e95f0403703d [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;
Pau Espin Pedrolf3713752024-03-21 17:32:55 +010029import from SDP_Templates all;
Harald Welteafec4712018-03-19 22:52:17 +010030
31import from SIP_Emulation all;
32import from SIPmsg_Types all;
Harald Welteb0d93602018-03-20 18:09:34 +010033import from SIP_Templates all;
Harald Welteafec4712018-03-19 22:52:17 +010034
35modulepar {
Harald Welteb0d93602018-03-20 18:09:34 +010036 charstring mp_local_host := "127.0.0.2";
Harald Welteafec4712018-03-19 22:52:17 +010037 charstring mp_osmosip_host := "127.0.0.1";
38 integer mp_osmosip_port_ctrl := -1; /* RFU */
39 charstring mp_mncc := "/tmp/mncc";
40}
41
42type component test_CT extends CTRL_Adapter_CT {
43 var MNCC_Emulation_CT vc_MNCC;
44 var SIP_Emulation_CT vc_SIP;
45
46 port TELNETasp_PT SIPVTY;
47}
48
49type component ConnHdlr extends SIP_ConnHdlr, MNCC_ConnHdlr {
50 var ConnHdlrPars g_pars;
51 timer g_Tguard;
52}
53
54type record ConnHdlrPars {
Harald Welteb0d93602018-03-20 18:09:34 +010055 float t_guard,
56 CallPars g_cp optional
57}
58
59type record CallPars {
60 boolean is_mo,
61 charstring calling,
62 charstring called,
63
64 uint32_t mncc_call_id optional,
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020065 CallParsComputed comp optional,
Harald Welteb0d93602018-03-20 18:09:34 +010066
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020067 charstring sip_rtp_addr,
68 uint16_t sip_rtp_port,
69 charstring cn_rtp_addr,
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +020070 uint16_t cn_rtp_port,
71
72 /* Send SDP to MNCC, and expect to receive SDP from MNCC. mncc_with_sdp := false tests legacy compatibility to
73 * the time when we did not include SDP in MNCC messages. mncc_with_sdp := true expects SDP to pass through the
74 * SUT osmo-sip-connector unchanged. */
75 boolean mncc_with_sdp
Harald Welteb0d93602018-03-20 18:09:34 +010076}
77
78type record CallParsComputed {
79 CallidString sip_call_id,
80 SipAddr sip_url_ext,
81 SipAddr sip_url_gsm,
82 charstring sip_body,
83 integer sip_seq_nr
84}
85
Neels Hofmeyra0d015b2023-09-13 04:32:14 +020086private template (value) CallPars t_CallPars(boolean is_mo, boolean mncc_with_sdp := true) := {
Harald Welteb0d93602018-03-20 18:09:34 +010087 is_mo := is_mo,
88 calling := "12345",
89 called := "98766",
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020090
Harald Welteb0d93602018-03-20 18:09:34 +010091 mncc_call_id := omit,
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +020092 comp := omit,
93 sip_rtp_addr := "1.2.3.4",
94 sip_rtp_port := 1234,
95 cn_rtp_addr := "5.6.7.8",
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +020096 cn_rtp_port := 5678,
97 mncc_with_sdp := mncc_with_sdp
Harald Welteb0d93602018-03-20 18:09:34 +010098}
99
100private function f_CallPars_compute(inout CallPars cp) {
101 if (cp.is_mo) {
102 cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.called, mp_local_host, 5060));
103 cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.calling, mp_osmosip_host, 5060));
Pau Espin Pedrol6052a342024-03-28 20:20:46 +0100104 cp.mncc_call_id := f_sip_rand_seq_nr();
Harald Welteb0d93602018-03-20 18:09:34 +0100105 } else {
106 cp.comp.sip_url_ext := valueof(ts_SipAddr(cp.calling, mp_local_host, 5060));
107 cp.comp.sip_url_gsm := valueof(ts_SipAddr(cp.called, mp_osmosip_host, 5060));
108 cp.comp.sip_call_id := hex2str(f_rnd_hexstring(15));
109 }
Pau Espin Pedrol6052a342024-03-28 20:20:46 +0100110 cp.comp.sip_seq_nr := f_sip_rand_seq_nr();
Harald Welteb0d93602018-03-20 18:09:34 +0100111 cp.comp.sip_body := "";
Harald Welteafec4712018-03-19 22:52:17 +0100112}
113
Harald Welteafec4712018-03-19 22:52:17 +0100114function f_init_mncc(charstring id) runs on test_CT {
115 id := id & "-MNCC";
116 var MnccOps ops := {
117 create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
118 unitdata_cb := refers(MNCC_Emulation.DummyUnitdataCallback)
119 };
120
121 vc_MNCC := MNCC_Emulation_CT.create(id);
122 map(vc_MNCC:MNCC, system:MNCC_CODEC_PT);
123 vc_MNCC.start(MNCC_Emulation.main(ops, id, mp_mncc, true));
124}
125
126function f_init() runs on test_CT {
Pau Espin Pedrol9a5b8ff2021-01-04 19:01:31 +0100127 //f_ipa_ctrl_start_client(mp_osmosip_host, mp_osmosip_port_ctrl);
Harald Welteafec4712018-03-19 22:52:17 +0100128 f_init_mncc("SIP_Test");
129 log("end of f_init_mncc");
130 f_init_sip(vc_SIP, "SIP_Test");
131 log("end of f_init_sip");
132
133 map(self:SIPVTY, system:SIPVTY);
134 f_vty_set_prompts(SIPVTY);
135 f_vty_transceive(SIPVTY, "enable");
136 log("end of f_init");
137}
138
139type function void_fn(charstring id) runs on ConnHdlr;
140
141function f_start_handler(void_fn fn, ConnHdlrPars pars)
142runs on test_CT return ConnHdlr {
143 var ConnHdlr vc_conn;
144 var charstring id := testcasename();
145
146 vc_conn := ConnHdlr.create(id);
147
148 connect(vc_conn:SIP, vc_SIP:CLIENT);
149 connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);
150
151 connect(vc_conn:MNCC, vc_MNCC:MNCC_CLIENT);
152 connect(vc_conn:MNCC_PROC, vc_MNCC:MNCC_PROC);
153
154 vc_conn.start(f_handler_init(fn, id, pars));
155 return vc_conn;
156}
157
158private altstep as_Tguard() runs on ConnHdlr {
159 [] g_Tguard.timeout {
160 setverdict(fail, "Tguard timeout");
Daniel Willmannafce8662018-07-06 23:11:32 +0200161 mtc.stop;
Harald Welteafec4712018-03-19 22:52:17 +0100162 }
163}
164
165private function f_handler_init(void_fn fn, charstring id, ConnHdlrPars pars)
166runs on ConnHdlr {
167 g_pars := pars;
168 g_Tguard.start(pars.t_guard);
169 activate(as_Tguard());
170
171 /* call the user-supied test case function */
172 fn.apply(id);
173}
174
175
176template (value) ConnHdlrPars t_Pars := {
Harald Welteb0d93602018-03-20 18:09:34 +0100177 t_guard := 30.0,
178 g_cp := omit
Harald Welteafec4712018-03-19 22:52:17 +0100179}
180
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200181altstep as_SIP_expect_resp(template PDU_SIP_Response sip_expect) runs on ConnHdlr
182{
183 [] SIP.receive(sip_expect);
184 [] SIP.receive {
185 log("FAIL: expected SIP message ", sip_expect);
186 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
187 }
188}
189
190function f_SIP_expect_req(template PDU_SIP_Request sip_expect) runs on ConnHdlr return PDU_SIP_Request
191{
192 var PDU_SIP_Request rx;
193 alt {
194 [] SIP.receive(sip_expect) -> value rx;
195 [] SIP.receive {
196 log("FAIL: expected SIP message ", sip_expect);
197 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "Received unexpected SIP message");
198 }
199 }
200 return rx;
201}
202
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200203/* Update 'last_sdp', and match with expectation of what the current SDP should be.
204 * Useful to ensure that MNCC or SIP send and possibly resend only the expected SDP.
205 * last_sdp keeps the last non-empty rx_sdp, across multiple check_sdp() invocations.
206 * rx_sdp is the SDP charstring just received. If it is nonempty, update last_sdp to rx_sdp.
207 * After updating last_sdp as appropriate, match last_sdp with expect_sdp. */
208private function check_sdp(inout charstring last_sdp,
209 charstring rx_sdp,
210 template charstring expect_sdp)
211{
212 /* If there is new SDP, store it. */
213 if (lengthof(rx_sdp) > 0) {
214 if (last_sdp != rx_sdp) {
215 log("SDP update from ", last_sdp, " to ", rx_sdp);
216 }
217
218 /* If MNCC sent SDP data, remember it as the last valid SDP */
219 last_sdp := rx_sdp;
220 }
221 /* Validate expectations of the SDP data */
222 if (not match(last_sdp, expect_sdp)) {
223 log("FAIL: expected SDP ", expect_sdp, " but got ", last_sdp);
224 Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, "unexpected SDP");
225 }
226}
227
Harald Welteb0d93602018-03-20 18:09:34 +0100228/* Establish a mobile terminated call described in 'cp' */
229function f_establish_mt(inout CallPars cp) runs on ConnHdlr {
230 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
231 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
Harald Welteb0d93602018-03-20 18:09:34 +0100232 var MNCC_PDU mncc;
Harald Welteafec4712018-03-19 22:52:17 +0100233
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200234 /* The last SDP that the MSC received via MNCC from osmo-sip-connector */
235 var charstring sdp_to_msc := "";
236 /* At first, allow any empty and nonempty SDP. As the test progresses, this may expect specific SDP instead. */
237 var template charstring expect_sdp_to_msc := *;
238
239 /* If cp.mncc_with_sdp == true, expect SDP forwarding like this:
240 *
241 * SDP1: SIP agent's RTP and codec info
242 * SDP2: osmo-msc's RTP and codec info
243 *
244 * MNCC osmo-sip-connector SIP
245 * |<--SDP1----- SIP Invite
246 * |-----------> SIP (Invite) Trying
247 * <--SDP1-------| MNCC SETUP req
248 * ------------->| MNCC CALL CONF ind
249 * <-------------| MNCC RTP CREATE (SDP optional, still unchanged from SDP1)
250 * -------SDP2-->| MNCC RTP CREATE
251 * ------------->| MNCC ALERT ind
252 * |--------------> SIP (Invite) Ringing
253 * (MT picks up) |
254 * ------------->| MNCC SETUP CNF
255 * <-------------| MNCC RTP CONNECT (SDP optional, still unchanged from SDP1)
256 * |--------SDP2--> SIP (Invite) OK
257 * |<-------------- SIP ACK
258 * <-------------| MNCC SETUP COMPL (SDP optional, still unchanged from SDP1)
259 */
260
Harald Welteb0d93602018-03-20 18:09:34 +0100261 /* Ask MNCC_Emulation to "expect" a call to the given called number */
262 f_create_mncc_expect(cp.called);
Harald Welteafec4712018-03-19 22:52:17 +0100263
Harald Welteb0d93602018-03-20 18:09:34 +0100264 /* OSC <- SIP: A party sends SIP invite for a MT-call into OSC */
265 SIP.send(ts_SIP_INVITE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
266 cp.comp.sip_seq_nr, cp.comp.sip_body));
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200267 if (cp.mncc_with_sdp) {
268 /* We just sent SDP via SIP, now expect the same SDP in MNCC to the MSC */
269 expect_sdp_to_msc := cp.comp.sip_body;
270 }
271
Harald Welteb0d93602018-03-20 18:09:34 +0100272 /* OSC -> SIP */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200273 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
274 "INVITE", 100, ?, "Trying", *));
Harald Welteafec4712018-03-19 22:52:17 +0100275
Pau Espin Pedrol37cf4082020-09-23 16:59:16 +0200276 alt {
277 /* MSC <- OSC: OSC generates MNCC_SETUP_REQ from INVITE */
278 [] MNCC.receive(tr_MNCC_SETUP_req) -> value mncc {
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200279 cp.mncc_call_id := mncc.u.signal.callref;
280 /* Expect the SDP sent via SIP to arrive in MNCC */
281 check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
Pau Espin Pedrol37cf4082020-09-23 16:59:16 +0200282 }
283 [] SIP.receive {
Neels Hofmeyrbaf02722023-09-12 02:10:11 +0200284 setverdict(fail, "Received unexpected SIP response");
Pau Espin Pedrol37cf4082020-09-23 16:59:16 +0200285 SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
286 cp.comp.sip_seq_nr, omit));
287 mtc.stop;
288 }
289 }
290
Harald Welteb0d93602018-03-20 18:09:34 +0100291 /* MSC -> OSC: After MS sends CALL CONF in response to SETUP */
292 MNCC.send(ts_MNCC_CALL_CONF_ind(cp.mncc_call_id));
293 /* MSC <- OSC: OSC asks MSC to create RTP socket */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200294 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) -> value mncc {
295 check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
296 }
297
298 /* MSC -> OSC: SDP that the MSC will send via MNCC */
299 var charstring cn_sdp := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100300 f_sdp_addr2addrtype(cp.cn_rtp_addr) & " " & cp.cn_rtp_addr &
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200301 "\r\nt=0 0\r\nm=audio " & int2str(cp.cn_rtp_port) &
302 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
303 /* OSC -> SIP: what SDP to expect in SIP from osmo-sip-connector */
304 var template charstring expect_sdp_to_sip := pattern "*" & cp.cn_rtp_addr & "*";
305
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200306 mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
307 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
308 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
309 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200310 if (cp.mncc_with_sdp) {
311 /* MSC -> OSC: tell OSC our RTP info in SDP form */
312 mncc.u.rtp.sdp := cn_sdp;
313 /* OSC -> SIP: and expect it unchanged on SIP later, but allow osmo-sip-connector to append an
314 * "a=sendrecv;" */
315 expect_sdp_to_sip := pattern cn_sdp & "*";
316 }
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200317 MNCC.send(mncc);
Harald Welteafec4712018-03-19 22:52:17 +0100318
Harald Welteb0d93602018-03-20 18:09:34 +0100319 /* MSC -> OSC: After MS is ringing and sent CC ALERTING */
320 MNCC.send(ts_MNCC_ALERT_ind(cp.mncc_call_id));
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200321
322 /* Now expect SIP response "Ringing" back to MO, containing the same SDP information as in the MNCC RTP CREATE
323 * sent to OSC above */
Harald Welteb0d93602018-03-20 18:09:34 +0100324 SIP.clear;
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200325
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200326 /* 180 Ringing should not contain any SDP. */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200327 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200328 "INVITE", 180, ?, "Ringing", omit));
Harald Welteafec4712018-03-19 22:52:17 +0100329
Harald Welteb0d93602018-03-20 18:09:34 +0100330 /* MSC -> OSC: After MT user has picked up and sent CC CONNECT */
331 MNCC.send(ts_MNCC_SETUP_CNF(cp.mncc_call_id));
332
333 SIP.clear;
Harald Welteb0d93602018-03-20 18:09:34 +0100334 /* MSC <- OSC: OSC asks MSC to connect its RTP stream to remote end */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200335 MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id, f_addrstr2addr(cp.sip_rtp_addr), cp.sip_rtp_port))
336 -> value mncc {
337 check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
338 }
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200339
Harald Welteb0d93602018-03-20 18:09:34 +0100340 /* OSC -> SIP: OSC confirms call establishment to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200341 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, contact_addr := ?,
342 method := "INVITE", status_code := 200,
343 seq_nr := ?, reason := "OK",
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200344 body := expect_sdp_to_sip));
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200345
Harald Welteb0d93602018-03-20 18:09:34 +0100346 /* OSC <- SIP: SIP world acknowledges "200 OK" */
347 SIP.send(ts_SIP_ACK(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
348 cp.comp.sip_seq_nr, omit));
349 /* MSC <- OSC: OSC sends SETUP COMPL to MNCC (which triggers CC CONNECT ACK */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200350 MNCC.receive(tr_MNCC_SETUP_COMPL_req(cp.mncc_call_id)) -> value mncc {
351 check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
352 }
Harald Welteafec4712018-03-19 22:52:17 +0100353}
354
Harald Welteb0d93602018-03-20 18:09:34 +0100355/* Establish a mobile originated call described in 'cp' */
356function f_establish_mo(inout CallPars cp) runs on ConnHdlr {
357 var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN));
358 var MNCC_number src := valueof(ts_MNCC_number(cp.calling, GSM48_TON_UNKNOWN));
359 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
360 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
361 var PDU_SIP_Request sip_req;
362 var integer seq_nr;
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200363 var MNCC_PDU mncc;
364
365 /* The last SDP that the MSC received via MNCC from osmo-sip-connector */
366 var charstring sdp_to_msc := "";
367 /* At first, allow any empty and nonempty SDP. As the test progresses, this may expect specific SDP instead. */
368 var template charstring expect_sdp_to_msc := *;
369
370 /* If cp.mncc_with_sdp == true, expect SDP forwarding like this:
371 *
372 * SDP1: osmo-msc's RTP and codec info
373 * SDP2: SIP agent's RTP and codec info
374 *
375 * MNCC osmo-sip-connector SIP
376 * -------SDP1-->| MNCC SETUP ind
377 * <-------------| MNCC RTP CREATE (?)
378 * |-----SDP1--> SIP Invite
379 * |<----------- SIP (Invite) Trying
380 * <-------------| MNCC CALL PROC req
381 * |<----------- SIP (Invite) Ringing
382 * <-------------| MNCC ALERT req
383 * | (MT picks up)
384 * |<--SDP2----- SIP (Invite) OK
385 * <--SDP2-------| MNCC RTP CONNECT (SDP optional, still unchanged from SDP2)
386 * <-------------| MNCC SETUP rsp (SDP optional, still unchanged from SDP2)
387 * ------------->| MNCC SETUP COMPL ind (SDP optional, still unchanged from SDP1)
388 * |------------> SIP ACK
389 */
390
391 var charstring cn_sdp := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100392 f_sdp_addr2addrtype(cp.cn_rtp_addr) & " " & cp.cn_rtp_addr &
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200393 "\r\nt=0 0\r\nm=audio " & int2str(cp.cn_rtp_port) &
394 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100395
396 f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec);
397
398 /* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200399 mncc := valueof(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
400 if (cp.mncc_with_sdp) {
401 mncc.u.signal.sdp := cn_sdp;
402 }
403 MNCC.send(mncc);
404
Harald Welteb0d93602018-03-20 18:09:34 +0100405 /* MSC <- OSC: Create GSM side RTP socket */
406 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200407 mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
Harald Welteb0d93602018-03-20 18:09:34 +0100408 mncc.u.rtp.payload_msg_type := oct2int('0300'O);
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200409 /* FIXME: makes no sense to send cp.cn_rtp_addr back to the cn. */
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200410 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
411 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
412 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
413 MNCC.send(mncc);
Harald Welteb0d93602018-03-20 18:09:34 +0100414 }
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200415
Harald Welteb0d93602018-03-20 18:09:34 +0100416 /* OSC -> SIP: Send INVITE with GSM side IP/Port in SDP */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200417 var template charstring expect_sdp_to_sip := ?;
418 if (cp.mncc_with_sdp) {
419 /* Expect the same SDP as sent to osmo-sip-connector in MNCC, and allow osmo-sip-connector to append an
420 * "a=sendrecv;" */
421 expect_sdp_to_sip := pattern cn_sdp & "*";
422 }
423 sip_req := f_SIP_expect_req(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, expect_sdp_to_sip));
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200424 cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
425 cp.comp.sip_call_id := sip_req.msgHeader.callId.callid;
426 seq_nr := sip_req.msgHeader.cSeq.seqNumber;
427
Harald Welteb0d93602018-03-20 18:09:34 +0100428 /* OSC <- SIP: Notify call is proceeding */
429 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
430 "INVITE", 100, seq_nr, "Trying", sip_req.msgHeader.via));
431 /* MSC <- OSC: "100 Trying" translated to MNCC_CALL_PROC_REQ */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200432 MNCC.receive(tr_MNCC_CALL_PROC_req(cp.mncc_call_id)) -> value mncc {
433 check_sdp(sdp_to_msc, mncc.u.signal.sdp, "");
434 }
Harald Welteb0d93602018-03-20 18:09:34 +0100435
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200436 /* OSC <- SIP: SIP-terminated user is ringing now. 180 Ringing should not contain any SDP. */
Harald Welteb0d93602018-03-20 18:09:34 +0100437 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200438 "INVITE", 180, seq_nr, "Ringing", sip_req.msgHeader.via, omit));
Harald Welteb0d93602018-03-20 18:09:34 +0100439
440 /* MSC <- OSC: "180 Ringing" translated to MNCC_ALERT_REQ */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200441 MNCC.receive(tr_MNCC_ALERT_req(cp.mncc_call_id)) -> value mncc {
442 check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
443 }
Harald Welteb0d93602018-03-20 18:09:34 +0100444
445 /* OSC <- SIP: SIP-terminated user has accepted the call */
446 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
447 "INVITE", 200, seq_nr, "OK", sip_req.msgHeader.via,
448 cp.comp.sip_body));
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200449
450 if (cp.mncc_with_sdp) {
451 /* If we expect SDP forwarding, from now on expect MNCC to reflect the SDP that we just sent on SIP. */
452 expect_sdp_to_msc := cp.comp.sip_body;
453 }
454 /* If we don't expect SDP forwarding, just keep expect_sdp_to_msc := *. */
455
456 MNCC.receive(tr_MNCC_RTP_CONNECT(cp.mncc_call_id)) -> value mncc {
457 check_sdp(sdp_to_msc, mncc.u.rtp.sdp, expect_sdp_to_msc);
458 }
Harald Welteb0d93602018-03-20 18:09:34 +0100459 /* MSC <- OSC: "200 OK" translated to MNCC_SETUP_RSP */
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200460 MNCC.receive(tr_MNCC_SETUP_rsp(cp.mncc_call_id)) -> value mncc {
461 check_sdp(sdp_to_msc, mncc.u.signal.sdp, expect_sdp_to_msc);
462 }
Harald Welteb0d93602018-03-20 18:09:34 +0100463
464 /* MSC -> OSC: CC CONNECT ACK was received from MS */
465 MNCC.send(ts_MNCC_SETUP_COMPL_ind(cp.mncc_call_id));
466 /* OSC -> SIP: Acknowledge the call */
467 SIP.receive(tr_SIP_ACK(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, omit));
468}
469
470/* Release call from the mobile side */
471function f_release_mobile(inout CallPars cp) runs on ConnHdlr {
472 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
473 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
474 var PDU_SIP_Request sip_req;
475 SIP.clear;
476 /* MSC -> OSC: Simulate a CC DISCONNET from the MT user */
477 MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200478
Harald Welteb0d93602018-03-20 18:09:34 +0100479 /* OSC -> SIP: Expect BYE from OSC to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200480 sip_req := f_SIP_expect_req(tr_SIP_BYE(cp.comp.sip_call_id, sip_addr_gsm, sip_addr_ext, ?, *));
481 cp.comp.sip_url_gsm.params := sip_req.msgHeader.fromField.fromParams;
482
Harald Welteb0d93602018-03-20 18:09:34 +0100483 /* OSC <- SIP: Acknowledge the BYE */
484 SIP.send(ts_SIP_Response(cp.comp.sip_call_id, cp.comp.sip_url_gsm, cp.comp.sip_url_ext,
485 "BYE", 200, sip_req.msgHeader.cSeq.seqNumber, "OK",
486 sip_req.msgHeader.via));
487 /* MSC <- OSC: Send REL_REQ to MSC, triggers CC RELEASE REQ to MS */
488 MNCC.receive(tr_MNCC_REL_req(cp.mncc_call_id)); // CAUSE?
489 /* MSC -> OSC: MS has responded with CC CLEAR COMPL, triggers MNCC_REL_CNF */
490 MNCC.send(ts_MNCC_REL_cnf(cp.mncc_call_id, ts_MNCC_cause(0)));
491}
492
493/* Release call from the SIP side */
494function f_release_sip(inout CallPars cp) runs on ConnHdlr {
495 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
496 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
497 /* OSC <- SIP: SIP-side sends a BYE to OSC */
498 SIP.send(ts_SIP_BYE(cp.comp.sip_call_id, cp.comp.sip_url_ext, cp.comp.sip_url_gsm,
499 cp.comp.sip_seq_nr, omit));
500 /* MSC <- OSC: Expect OSC to cause MNCC Disconnect Request */
501 MNCC.receive(tr_MNCC_DISC_req(cp.mncc_call_id));
502 /* MSC -> OSC: Indicate GSM side release */
503 MNCC.send(ts_MNCC_REL_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
504 /* OSC -> SIP: Confirmation to SIP side */
Neels Hofmeyrc35b6572023-09-12 02:16:43 +0200505 as_SIP_expect_resp(tr_SIP_Response(cp.comp.sip_call_id, sip_addr_ext, sip_addr_gsm, *,
506 "BYE", 200, cp.comp.sip_seq_nr, "OK", omit));
Harald Welteb0d93602018-03-20 18:09:34 +0100507}
508
509/* Successful MT Call, which is subsequently released by GSM side */
510private function f_TC_mt_success_rel_gsm(charstring id) runs on ConnHdlr {
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200511 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100512 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200513 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100514 f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200515 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
516 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100517 f_sleep(3.0)
518
519 f_establish_mt(cp);
520 /* now call is fully established */
521 f_sleep(2.0);
522 f_release_mobile(cp);
523 setverdict(pass);
524}
525testcase TC_mt_success_rel_gsm() runs on test_CT {
Harald Welteafec4712018-03-19 22:52:17 +0100526 var ConnHdlrPars pars;
527 var ConnHdlr vc_conn;
Harald Welteafec4712018-03-19 22:52:17 +0100528 f_init();
Harald Welteafec4712018-03-19 22:52:17 +0100529 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200530 pars.g_cp := valueof(t_CallPars(false, false));
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200531 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
532 vc_conn.done;
533}
534testcase TC_mt_success_rel_gsm_ipv6() runs on test_CT {
535 var ConnHdlrPars pars;
536 var ConnHdlr vc_conn;
537 f_init();
538 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200539 pars.g_cp := valueof(t_CallPars(false, false));
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200540 pars.g_cp.sip_rtp_addr := "::1";
541 pars.g_cp.cn_rtp_addr := "::2";
Harald Welteb0d93602018-03-20 18:09:34 +0100542 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
543 vc_conn.done;
544}
545
546/* Successful MT Call, which is subsequently released by SIP side */
547private function f_TC_mt_success_rel_sip(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200548 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100549 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200550 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100551 f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200552 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
553 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100554 f_sleep(3.0)
555
556 f_establish_mt(cp);
557 /* now call is fully established */
558 f_sleep(2.0);
559 f_release_sip(cp);
560 setverdict(pass);
561}
562testcase TC_mt_success_rel_sip() runs on test_CT {
563 var ConnHdlrPars pars;
564 var ConnHdlr vc_conn;
565 f_init();
566 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200567 pars.g_cp := valueof(t_CallPars(false, false));
Harald Welteb0d93602018-03-20 18:09:34 +0100568 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_sip), pars);
Harald Welteafec4712018-03-19 22:52:17 +0100569 vc_conn.done;
570}
571
572
Harald Welteb0d93602018-03-20 18:09:34 +0100573/* Successful MO Call, which is subsequently released by GSM side */
574private function f_TC_mo_success_rel_gsm(charstring id) runs on ConnHdlr {
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200575 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100576 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200577 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100578 f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200579 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
580 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100581 f_sleep(3.0)
Harald Welteafec4712018-03-19 22:52:17 +0100582
Harald Welteb0d93602018-03-20 18:09:34 +0100583 f_establish_mo(cp);
584 /* now call is fully established */
585 f_sleep(2.0);
586 f_release_mobile(cp);
587 setverdict(pass);
588}
589testcase TC_mo_success_rel_gsm() runs on test_CT {
590 var ConnHdlrPars pars;
591 var ConnHdlr vc_conn;
592 f_init();
593 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200594 pars.g_cp := valueof(t_CallPars(true, false));
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200595 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
596 vc_conn.done;
597}
598testcase TC_mo_success_rel_gsm_ipv6() runs on test_CT {
599 var ConnHdlrPars pars;
600 var ConnHdlr vc_conn;
601 f_init();
602 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200603 pars.g_cp := valueof(t_CallPars(true, false));
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200604 pars.g_cp.sip_rtp_addr := "::1";
605 pars.g_cp.cn_rtp_addr := "::2";
Harald Welteb0d93602018-03-20 18:09:34 +0100606 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_gsm), pars);
607 vc_conn.done;
Harald Welteafec4712018-03-19 22:52:17 +0100608}
609
Harald Welteb0d93602018-03-20 18:09:34 +0100610/* Successful MO Call, which is subsequently released by SIP side */
611private function f_TC_mo_success_rel_sip(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200612 var CallPars cp := g_pars.g_cp;
Harald Welteb0d93602018-03-20 18:09:34 +0100613 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200614 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100615 f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200616 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
617 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteb0d93602018-03-20 18:09:34 +0100618 f_sleep(3.0)
Harald Welteafec4712018-03-19 22:52:17 +0100619
Harald Welteb0d93602018-03-20 18:09:34 +0100620 f_establish_mo(cp);
621 /* now call is fully established */
622 f_sleep(2.0);
623 f_release_sip(cp);
624 setverdict(pass);
625}
626testcase TC_mo_success_rel_sip() runs on test_CT {
627 var ConnHdlrPars pars;
628 var ConnHdlr vc_conn;
629 f_init();
630 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200631 pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := false));
Harald Welteb0d93602018-03-20 18:09:34 +0100632 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars);
633 vc_conn.done;
634}
Harald Welteafec4712018-03-19 22:52:17 +0100635
Harald Welteddf011e2019-04-19 09:39:35 +0200636/* SETUP followed by DISC results in lingering B-leg (OS#3518)*/
637private function f_TC_mo_setup_disc_late_rtp(charstring id) runs on ConnHdlr {
Neels Hofmeyrfb7f43b2023-09-13 05:42:41 +0200638 var CallPars cp := g_pars.g_cp;
Harald Welteddf011e2019-04-19 09:39:35 +0200639 f_CallPars_compute(cp);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200640 cp.comp.sip_body := "v=0\r\no=Osmocom 0 0 IN IP4 1.1.1.1\r\ns=GSM Call\r\nc=IN " &
Pau Espin Pedrolf3713752024-03-21 17:32:55 +0100641 f_sdp_addr2addrtype(cp.sip_rtp_addr) & " " & cp.sip_rtp_addr &
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200642 "\r\nt=0 0\r\nm=audio " & int2str(cp.sip_rtp_port) &
643 " RTP/AVP 0\r\na=rtpmap:0 GSM/8000\r\n";
Harald Welteddf011e2019-04-19 09:39:35 +0200644 f_sleep(3.0);
645
646 var MNCC_number dst := valueof(ts_MNCC_number(cp.called, GSM48_TON_UNKNOWN));
647 var MNCC_number src := valueof(ts_MNCC_number(cp.calling, GSM48_TON_UNKNOWN));
648 var template SipAddr sip_addr_gsm := tr_SipAddr_from_val(cp.comp.sip_url_gsm);
649 var template SipAddr sip_addr_ext := tr_SipAddr_from_val(cp.comp.sip_url_ext);
650
651 f_create_sip_expect(cp.comp.sip_url_ext.addr.nameAddr.addrSpec);
652
653 /* MSC -> OSC: MSC sends SETUP.ind after CC SETUP was received from MS */
654 MNCC.send(ts_MNCC_SETUP_ind(cp.mncc_call_id, dst, src, "262420123456789"));
655
656 /* MSC -> OSC: Simulate a CC DISCONNET from the MT user *before* responding to the RTP_CREATE */
657 MNCC.send(ts_MNCC_DISC_ind(cp.mncc_call_id, ts_MNCC_cause(0)));
658
659 /* MSC <- OSC: Create GSM side RTP socket (too late) */
660 MNCC.receive(tr_MNCC_RTP_CREATE(cp.mncc_call_id)) {
661 var MNCC_PDU mncc := valueof(ts_MNCC_RTP_CREATE(cp.mncc_call_id));
662 mncc.u.rtp.payload_msg_type := oct2int('0300'O);
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200663 mncc.u.rtp.is_ipv6 := f_addr_is_ipv6(cp.cn_rtp_addr);
664 mncc.u.rtp.ip := f_addrstr2addr(cp.cn_rtp_addr);
665 mncc.u.rtp.rtp_port := cp.cn_rtp_port;
666 MNCC.send(mncc);
Harald Welteddf011e2019-04-19 09:39:35 +0200667 }
668
669 /* OSC -> SIP: We should never receive INVITE */
670 timer T := 10.0;
671 T.start;
672 alt {
673 [] SIP.receive(tr_SIP_INVITE(?, sip_addr_gsm, sip_addr_ext, ?, ?)) {
674 setverdict(fail, "Received unexpected INVITE");
675 }
676 [] T.timeout {
677 setverdict(pass);
678 }
679 }
680}
681testcase TC_mo_setup_disc_late_rtp() runs on test_CT {
682 var ConnHdlrPars pars;
683 var ConnHdlr vc_conn;
684 f_init();
685 pars := valueof(t_Pars);
Neels Hofmeyra0d015b2023-09-13 04:32:14 +0200686 pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := false));
Harald Welteddf011e2019-04-19 09:39:35 +0200687 vc_conn := f_start_handler(refers(f_TC_mo_setup_disc_late_rtp), pars);
688 vc_conn.done;
689}
Harald Welteafec4712018-03-19 22:52:17 +0100690
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200691testcase TC_mt_with_sdp() runs on test_CT {
692 var ConnHdlrPars pars;
693 var ConnHdlr vc_conn;
694 f_init();
695 pars := valueof(t_Pars);
696 pars.g_cp := valueof(t_CallPars(is_mo := false, mncc_with_sdp := true));
697 vc_conn := f_start_handler(refers(f_TC_mt_success_rel_gsm), pars);
698 vc_conn.done;
699}
700
701testcase TC_mo_with_sdp() runs on test_CT {
702 var ConnHdlrPars pars;
703 var ConnHdlr vc_conn;
704 f_init();
705 pars := valueof(t_Pars);
706 pars.g_cp := valueof(t_CallPars(is_mo := true, mncc_with_sdp := true));
707 vc_conn := f_start_handler(refers(f_TC_mo_success_rel_sip), pars);
708 vc_conn.done;
709}
710
Harald Welteafec4712018-03-19 22:52:17 +0100711control {
Harald Welteb0d93602018-03-20 18:09:34 +0100712 execute( TC_mt_success_rel_gsm() );
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200713 execute( TC_mt_success_rel_gsm_ipv6() );
Harald Welteb0d93602018-03-20 18:09:34 +0100714 execute( TC_mt_success_rel_sip() );
715 execute( TC_mo_success_rel_gsm() );
Pau Espin Pedrolbdd874a2020-09-10 19:09:47 +0200716 execute( TC_mo_success_rel_gsm_ipv6() );
Harald Welteb0d93602018-03-20 18:09:34 +0100717 execute( TC_mo_success_rel_sip() );
Harald Welteddf011e2019-04-19 09:39:35 +0200718 execute( TC_mo_setup_disc_late_rtp() );
Neels Hofmeyr2e3a0e22023-09-12 02:09:48 +0200719 execute( TC_mt_with_sdp() );
720 execute( TC_mo_with_sdp() );
Harald Welteafec4712018-03-19 22:52:17 +0100721}
722
723
724
725}