blob: 23cfeb4aaad6716ac69d708253c4926d80529a6e [file] [log] [blame]
Daniel Willmannfa870f52018-01-17 12:37:14 +01001module MGCP_Emulation {
2
Harald Weltea02515f2018-01-26 10:33:23 +01003/* MGCP Emulation, runs on top of MGCP_CodecPort. It multiplexes/demultiplexes
4 * the individual connections, so there can be separate TTCN-3 components handling
5 * each of the connections.
6 *
7 * The MGCP_Emulation.main() function processes MGCP primitives from the MGCP
8 * socket via the MGCP_CodecPort, and dispatches them to the per-connection components.
9 *
10 * For each new inbound connection, the MgcpOps.create_cb() is called. It can create
11 * or resolve a TTCN-3 component, and returns a component reference to which that inbound
12 * connection is routed/dispatched.
13 *
14 * If a pre-existing component wants to register to handle a future inbound call, it can
15 * do so by registering an "expect" with the expected destination phone number. This is e.g. useful
16 * if you are simulating BSC + MGCP, and first trigger a connection from BSC side in a
17 * component which then subsequently should also handle the MGCP emulation.
18 *
19 * Inbound Unit Data messages (such as are dispatched to the MgcpOps.unitdata_cb() callback,
20 * which is registered with an argument to the main() function below.
21 *
22 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
23 * (C) 2018 by sysmocom - s.f.m.c. GmbH, Author: Daniel Willmann
24 * All rights reserved.
25 *
26 * Released under the terms of GNU General Public License, Version 2 or
27 * (at your option) any later version.
Harald Welte34b5a952019-05-27 11:54:11 +020028 *
29 * SPDX-License-Identifier: GPL-2.0-or-later
Harald Weltea02515f2018-01-26 10:33:23 +010030 */
31
Daniel Willmannfa870f52018-01-17 12:37:14 +010032import from MGCP_CodecPort all;
33import from MGCP_CodecPort_CtrlFunct all;
34import from MGCP_Types all;
35import from MGCP_Templates all;
36import from Osmocom_Types all;
37import from IPL4asp_Types all;
38
39type component MGCP_ConnHdlr {
40 port MGCP_Conn_PT MGCP;
Harald Weltebb5a1212018-01-26 10:34:44 +010041 /* procedure based port to register for incoming connections */
42 port MGCPEM_PROC_PT MGCP_PROC;
Daniel Willmannfa870f52018-01-17 12:37:14 +010043}
44
45/* port between individual per-connection components and this dispatcher */
46type port MGCP_Conn_PT message {
47 inout MgcpCommand, MgcpResponse;
48} with { extension "internal" };
49
Harald Welte9601c812018-01-26 18:58:20 +010050/* represents a single MGCP Endpoint */
51type record EndpointData {
Harald Weltebb5a1212018-01-26 10:34:44 +010052 MGCP_ConnHdlr comp_ref,
Harald Welte9601c812018-01-26 18:58:20 +010053 MgcpEndpoint endpoint optional
Harald Weltebb5a1212018-01-26 10:34:44 +010054};
Daniel Willmannfa870f52018-01-17 12:37:14 +010055
Harald Welte9601c812018-01-26 18:58:20 +010056/* pending CRCX with their transaction ID */
57type set of MgcpTransId MgcpTransIds;
58
Daniel Willmannfa870f52018-01-17 12:37:14 +010059type component MGCP_Emulation_CT {
60 /* Port facing to the UDP SUT */
61 port MGCP_CODEC_PT MGCP;
62 /* All MGCP_ConnHdlr MGCP ports connect here
63 * MGCP_Emulation_CT.main needs to figure out what messages
64 * to send where with CLIENT.send() to vc_conn */
Harald Weltebb5a1212018-01-26 10:34:44 +010065 port MGCP_Conn_PT MGCP_CLIENT;
Daniel Willmannfa870f52018-01-17 12:37:14 +010066 /* currently tracked connections */
Harald Welte9601c812018-01-26 18:58:20 +010067 var EndpointData MgcpEndpointTable[16];
68 var MgcpTransIds MgcpPendingTrans := {};
Daniel Willmannfa870f52018-01-17 12:37:14 +010069 /* pending expected CRCX */
Harald Weltebb5a1212018-01-26 10:34:44 +010070 var ExpectData MgcpExpectTable[8];
Daniel Willmannfa870f52018-01-17 12:37:14 +010071 /* procedure based port to register for incoming connections */
Harald Weltebb5a1212018-01-26 10:34:44 +010072 port MGCPEM_PROC_PT MGCP_PROC;
Daniel Willmannfa870f52018-01-17 12:37:14 +010073
74 var charstring g_mgcp_id;
Daniel Willmann166bbb32018-01-17 15:28:04 +010075 var integer g_mgcp_conn_id := -1;
Daniel Willmannfa870f52018-01-17 12:37:14 +010076}
77
78type function MGCPCreateCallback(MgcpCommand cmd, charstring id)
79runs on MGCP_Emulation_CT return MGCP_ConnHdlr;
80
Harald Weltebb5a1212018-01-26 10:34:44 +010081type function MGCPUnitdataCallback(MgcpMessage msg)
82runs on MGCP_Emulation_CT return template MgcpMessage;
83
Daniel Willmannfa870f52018-01-17 12:37:14 +010084type record MGCPOps {
Harald Weltebb5a1212018-01-26 10:34:44 +010085 MGCPCreateCallback create_cb,
86 MGCPUnitdataCallback unitdata_cb
Daniel Willmannfa870f52018-01-17 12:37:14 +010087}
88
89type record MGCP_conn_parameters {
Harald Weltebb5a1212018-01-26 10:34:44 +010090 HostName callagent_ip,
91 PortNumber callagent_udp_port,
92 HostName mgw_ip,
93 PortNumber mgw_udp_port
Daniel Willmannfa870f52018-01-17 12:37:14 +010094}
95
Daniel Willmann166bbb32018-01-17 15:28:04 +010096function tr_MGCP_RecvFrom_R(template MgcpMessage msg)
97runs on MGCP_Emulation_CT return template MGCP_RecvFrom {
98 var template MGCP_RecvFrom mrf := {
99 connId := g_mgcp_conn_id,
100 remName := ?,
101 remPort := ?,
102 locName := ?,
103 locPort := ?,
104 msg := msg
105 }
106 return mrf;
107}
108
Harald Welte9601c812018-01-26 18:58:20 +0100109private function f_ep_known(MgcpEndpoint ep)
Harald Weltebb5a1212018-01-26 10:34:44 +0100110runs on MGCP_Emulation_CT return boolean {
111 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100112 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
113 if (MgcpEndpointTable[i].endpoint == ep) {
Harald Weltebb5a1212018-01-26 10:34:44 +0100114 return true;
115 }
116 }
117 return false;
118}
119
120private function f_comp_known(MGCP_ConnHdlr client)
121runs on MGCP_Emulation_CT return boolean {
122 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100123 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
124 if (MgcpEndpointTable[i].comp_ref == client) {
Harald Weltebb5a1212018-01-26 10:34:44 +0100125 return true;
126 }
127 }
128 return false;
129}
130
Harald Welte9601c812018-01-26 18:58:20 +0100131private function f_comp_by_ep(MgcpEndpoint ep)
Harald Weltebb5a1212018-01-26 10:34:44 +0100132runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
133 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100134 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
135 if (MgcpEndpointTable[i].endpoint == ep) {
136 return MgcpEndpointTable[i].comp_ref;
Harald Weltebb5a1212018-01-26 10:34:44 +0100137 }
138 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200139 setverdict(fail, "MGCP Endpoint Table not found by Endpoint", ep);
140 mtc.stop;
Harald Weltebb5a1212018-01-26 10:34:44 +0100141}
142
Harald Welte9601c812018-01-26 18:58:20 +0100143private function f_ep_by_comp(MGCP_ConnHdlr client)
144runs on MGCP_Emulation_CT return MgcpEndpoint {
Harald Weltebb5a1212018-01-26 10:34:44 +0100145 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100146 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
147 if (MgcpEndpointTable[i].comp_ref == client) {
148 return MgcpEndpointTable[i].endpoint;
Harald Weltebb5a1212018-01-26 10:34:44 +0100149 }
150 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200151 setverdict(fail, "MGCP Endpoint Table not found by component ", client);
152 mtc.stop;
Harald Weltebb5a1212018-01-26 10:34:44 +0100153}
154
Harald Welte9601c812018-01-26 18:58:20 +0100155private function f_ep_table_add(MGCP_ConnHdlr comp_ref, MgcpEndpoint ep)
156runs on MGCP_Emulation_CT {
157 var integer i;
158 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
159 if (not isvalue(MgcpEndpointTable[i].endpoint)) {
160 MgcpEndpointTable[i].endpoint := ep;
161 MgcpEndpointTable[i].comp_ref := comp_ref;
162 return;
163 }
164 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200165 testcase.stop("MGCP Endpoint Table full!");
Harald Welte9601c812018-01-26 18:58:20 +0100166}
167
168private function f_ep_table_del(MGCP_ConnHdlr comp_ref, MgcpEndpoint ep)
169runs on MGCP_Emulation_CT {
170 var integer i;
171 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
172 if (MgcpEndpointTable[i].comp_ref == comp_ref and
173 MgcpEndpointTable[i].endpoint == ep) {
174 MgcpEndpointTable[i].endpoint := omit;
175 MgcpEndpointTable[i].comp_ref := null;
176 return;
177 }
178 }
179 setverdict(fail, "MGCP Endpoint Table: Couldn't find to-be-deleted entry!");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200180 mtc.stop;
Harald Welte9601c812018-01-26 18:58:20 +0100181}
182
183
184/* Check if the given transaction ID is a pending CRCX. If yes, return true + remove */
185private function f_trans_id_was_pending(MgcpTransId trans_id)
186runs on MGCP_Emulation_CT return boolean {
187 for (var integer i := 0; i < lengthof(MgcpPendingTrans); i := i+1) {
188 if (MgcpPendingTrans[i] == trans_id) {
189 /* Remove from list */
190 var MgcpTransIds OldPendingTrans := MgcpPendingTrans;
191 MgcpPendingTrans := {}
192 for (var integer j := 0; j < lengthof(OldPendingTrans); j := j+1) {
193 if (j != i) {
194 MgcpPendingTrans := MgcpPendingTrans & {OldPendingTrans[j]};
195 }
196 }
197 return true;
198 }
199 }
200 return false;
201}
202
Harald Weltebb5a1212018-01-26 10:34:44 +0100203/* TODO: move this to MGCP_Types? */
Harald Welte9601c812018-01-26 18:58:20 +0100204function f_mgcp_ep(MgcpMessage msg) return MgcpEndpoint {
Harald Weltebb5a1212018-01-26 10:34:44 +0100205 var MgcpParameterList params;
206 var integer i;
207 if (ischosen(msg.command)) {
Harald Welte9601c812018-01-26 18:58:20 +0100208 return msg.command.line.ep;
Harald Weltebb5a1212018-01-26 10:34:44 +0100209 } else {
Harald Welte363cb0a2018-01-30 19:35:53 +0100210 var MgcpEndpoint ep;
211 if (f_mgcp_find_param(msg, "Z", ep) == false) {
212 setverdict(fail, "No SpecificEndpointName in MGCP response", msg);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200213 mtc.stop;
Harald Welte363cb0a2018-01-30 19:35:53 +0100214 }
215 return ep;
Harald Weltebb5a1212018-01-26 10:34:44 +0100216 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100217}
218
Harald Welte9601c812018-01-26 18:58:20 +0100219private function f_ep_table_init()
Harald Weltebb5a1212018-01-26 10:34:44 +0100220runs on MGCP_Emulation_CT {
Harald Welte9601c812018-01-26 18:58:20 +0100221 for (var integer i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
222 MgcpEndpointTable[i].comp_ref := null;
223 MgcpEndpointTable[i].endpoint := omit;
Harald Weltebb5a1212018-01-26 10:34:44 +0100224 }
225}
226
Daniel Willmann955627a2018-01-17 15:22:32 +0100227function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_Emulation_CT {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100228 var Result res;
229 g_mgcp_id := id;
Harald Welte9601c812018-01-26 18:58:20 +0100230 f_ep_table_init();
Daniel Willmann955627a2018-01-17 15:22:32 +0100231 f_expect_table_init();
Daniel Willmannfa870f52018-01-17 12:37:14 +0100232
233 map(self:MGCP, system:MGCP_CODEC_PT);
Harald Weltebb5a1212018-01-26 10:34:44 +0100234 if (p.callagent_udp_port == -1) {
235 res := MGCP_CodecPort_CtrlFunct.f_IPL4_listen(MGCP, p.mgw_ip, p.mgw_udp_port, { udp:={} });
236 } else {
237 res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, -1, { udp:={} });
238 }
Harald Welte9220f632018-05-23 20:27:02 +0200239 if (not ispresent(res.connId)) {
240 setverdict(fail, "Could not connect MGCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200241 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200242 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100243 g_mgcp_conn_id := res.connId;
Harald Weltebb5a1212018-01-26 10:34:44 +0100244
Daniel Willmannfa870f52018-01-17 12:37:14 +0100245 while (true) {
Daniel Willmann166bbb32018-01-17 15:28:04 +0100246 var MGCP_ConnHdlr vc_conn;
247 var ExpectCriteria crit;
248 var MGCP_RecvFrom mrf;
249 var MgcpMessage msg;
250 var MgcpCommand cmd;
251 var MgcpResponse resp;
Harald Welte9601c812018-01-26 18:58:20 +0100252 var MgcpEndpoint ep;
Daniel Willmann166bbb32018-01-17 15:28:04 +0100253
Daniel Willmannfa870f52018-01-17 12:37:14 +0100254 alt {
Daniel Willmann166bbb32018-01-17 15:28:04 +0100255 /* MGCP from client */
Harald Weltebb5a1212018-01-26 10:34:44 +0100256 [] MGCP_CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
Harald Welte9601c812018-01-26 18:58:20 +0100257 msg := {
258 response := resp
259 };
260 /* If this is the resposne to a pending CRCX, extract Endpoint and store in table */
261 if (f_trans_id_was_pending(resp.line.trans_id)) {
262 f_ep_table_add(vc_conn, f_mgcp_ep(msg));
263 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100264 /* Pass message through */
Harald Weltebb5a1212018-01-26 10:34:44 +0100265 /* TODO: check which ConnectionID client has allocated + store in table? */
Daniel Willmann166bbb32018-01-17 15:28:04 +0100266 MGCP.send(t_MGCP_Send(g_mgcp_conn_id, msg));
Daniel Willmannfa870f52018-01-17 12:37:14 +0100267 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100268 [] MGCP.receive(tr_MGCP_RecvFrom_R(?)) -> value mrf {
Harald Weltebb5a1212018-01-26 10:34:44 +0100269 if (p.callagent_udp_port == -1) {
270 /* we aren't yet connected to the remote side port, let's fix this */
271 p.callagent_udp_port := mrf.remPort;
Harald Welte930d0a72018-03-22 22:08:40 +0100272 res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, g_mgcp_conn_id, { udp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200273 if (not ispresent(res.connId)) {
274 setverdict(fail, "Could not connect MGCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200275 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200276 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100277 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100278 if (ischosen(mrf.msg.command)) {
279 cmd := mrf.msg.command;
Harald Welte9601c812018-01-26 18:58:20 +0100280 if (f_ep_known(cmd.line.ep)) {
281 vc_conn := f_comp_by_ep(cmd.line.ep);
Harald Weltebb5a1212018-01-26 10:34:44 +0100282 MGCP_CLIENT.send(cmd) to vc_conn;
283 } else {
Harald Welte9601c812018-01-26 18:58:20 +0100284 if (cmd.line.verb == "CRCX") {
285 vc_conn := ops.create_cb.apply(cmd, id);
Harald Welte363cb0a2018-01-30 19:35:53 +0100286 if (not match(cmd.line.ep, t_MGCP_EP_wildcard)) {
287 /* non-wildcard EP, use directly */
Harald Welte9601c812018-01-26 18:58:20 +0100288 f_ep_table_add(vc_conn, cmd.line.ep);
289 } else {
290 /* add this transaction to list of pending transactions */
291 MgcpPendingTrans := MgcpPendingTrans & {cmd.line.trans_id};
292 }
293 MGCP_CLIENT.send(cmd) to vc_conn;
294 } else {
295 /* connectionless MGCP, i.e. messages without ConnectionId */
296 var template MgcpMessage r := ops.unitdata_cb.apply(mrf.msg);
297 if (isvalue(r)) {
298 MGCP.send(t_MGCP_Send(g_mgcp_conn_id, r));
299 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100300 }
301 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100302 } else {
303 setverdict(fail, "Received unexpected MGCP response: ", mrf.msg.response);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200304 mtc.stop;
Daniel Willmann166bbb32018-01-17 15:28:04 +0100305 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100306 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100307 [] MGCP_PROC.getcall(MGCPEM_register:{?,?}) -> param(crit, vc_conn) {
Daniel Willmann955627a2018-01-17 15:22:32 +0100308 f_create_expect(crit, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200309 MGCP_PROC.reply(MGCPEM_register:{crit, vc_conn}) to vc_conn;
Daniel Willmann955627a2018-01-17 15:22:32 +0100310 }
Harald Welte9601c812018-01-26 18:58:20 +0100311 [] MGCP_PROC.getcall(MGCPEM_delete_ep:{?,?}) -> param(ep, vc_conn) {
312 f_ep_table_del(vc_conn, ep);
Harald Weltee32ad992018-05-31 22:17:46 +0200313 MGCP_PROC.reply(MGCPEM_delete_ep:{ep, vc_conn}) to vc_conn;
Harald Welte9601c812018-01-26 18:58:20 +0100314 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100315 }
Harald Welte9601c812018-01-26 18:58:20 +0100316
Daniel Willmannfa870f52018-01-17 12:37:14 +0100317 }
318}
319
320/* "Expect" Handling */
321
322/* */
Daniel Willmann955627a2018-01-17 15:22:32 +0100323type record ExpectCriteria {
324 MgcpConnectionId connid optional,
325 MgcpEndpoint endpoint optional,
326 MgcpTransId transid optional
Daniel Willmannfa870f52018-01-17 12:37:14 +0100327}
328
329type record ExpectData {
330 ExpectCriteria crit optional,
Daniel Willmann955627a2018-01-17 15:22:32 +0100331 MGCP_ConnHdlr vc_conn
Daniel Willmannfa870f52018-01-17 12:37:14 +0100332}
333
Daniel Willmann955627a2018-01-17 15:22:32 +0100334signature MGCPEM_register(in ExpectCriteria cmd, in MGCP_ConnHdlr hdlr);
Harald Welte9601c812018-01-26 18:58:20 +0100335signature MGCPEM_delete_ep(in MgcpEndpoint ep, in MGCP_ConnHdlr hdlr);
Daniel Willmannfa870f52018-01-17 12:37:14 +0100336
337type port MGCPEM_PROC_PT procedure {
Harald Welte9601c812018-01-26 18:58:20 +0100338 inout MGCPEM_register, MGCPEM_delete_ep;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100339} with { extension "internal" };
340
341function f_get_mgcp_by_crit(ExpectCriteria crit)
342return template MgcpCommand {
Harald Weltebb5a1212018-01-26 10:34:44 +0100343 var template MgcpCommand ret := {
344 line := {
345 verb := ?,
346 trans_id := ?,
347 ep := ?,
348 ver := ?
349 },
350 params := *,
351 sdp := *
352 }
353 if (ispresent(crit.connid)) {
354 ret.params := { *, ts_MgcpParConnectionId(crit.connid), * };
355 }
356 if (ispresent(crit.endpoint)) {
357 ret.line.ep := crit.endpoint;
358 }
359 if (ispresent(crit.transid)) {
360 ret.line.trans_id := crit.transid;
361 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100362
363 return ret;
364}
365
366/* Function that can be used as create_cb and will usse the expect table */
367function ExpectedCreateCallback(MgcpCommand cmd, charstring id)
368runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
369 var MGCP_ConnHdlr ret := null;
370 var template MgcpCommand mgcpcmd;
371 var integer i;
372
Harald Weltebb5a1212018-01-26 10:34:44 +0100373 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
374 if (not ispresent(MgcpExpectTable[i].crit)) {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100375 continue;
376 }
Daniel Willmann955627a2018-01-17 15:22:32 +0100377 /* FIXME: Ignore criteria for now */
Harald Weltebb5a1212018-01-26 10:34:44 +0100378 mgcpcmd := f_get_mgcp_by_crit(MgcpExpectTable[i].crit);
379 if (match(cmd, mgcpcmd)) {
380 ret := MgcpExpectTable[i].vc_conn;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100381 /* Release this entry */
Harald Weltebb5a1212018-01-26 10:34:44 +0100382 MgcpExpectTable[i].crit := omit;
383 MgcpExpectTable[i].vc_conn := null;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100384 log("Found Expect[", i, "] for ", cmd, " handled at ", ret);
385 return ret;
Harald Weltebb5a1212018-01-26 10:34:44 +0100386 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100387 }
388 setverdict(fail, "Couldn't find Expect for CRCX", cmd);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200389 mtc.stop;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100390}
391
392private function f_create_expect(ExpectCriteria crit, MGCP_ConnHdlr hdlr)
393runs on MGCP_Emulation_CT {
394 var integer i;
395
396 /* Check an entry like this is not already presnt */
Harald Weltebb5a1212018-01-26 10:34:44 +0100397 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
398 if (crit == MgcpExpectTable[i].crit) {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100399 setverdict(fail, "Crit already present", crit);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200400 mtc.stop;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100401 }
402 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100403 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
404 if (not ispresent(MgcpExpectTable[i].crit)) {
405 MgcpExpectTable[i].crit := crit;
406 MgcpExpectTable[i].vc_conn := hdlr;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100407 log("Created Expect[", i, "] for ", crit, " to be handled at ", hdlr);
408 return;
409 }
410 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200411 testcase.stop("No space left in MgcpExpectTable")
Harald Weltebb5a1212018-01-26 10:34:44 +0100412}
413
414/* client/conn_hdlr side function to use procedure port to create expect in emulation */
415function f_create_mgcp_expect(ExpectCriteria dest_number) runs on MGCP_ConnHdlr {
416 MGCP_PROC.call(MGCPEM_register:{dest_number, self}) {
417 [] MGCP_PROC.getreply(MGCPEM_register:{?,?}) {};
418 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100419}
420
Harald Welte9601c812018-01-26 18:58:20 +0100421/* client/conn_hdlr side function to use procedure port to create expect in emulation */
422function f_create_mgcp_delete_ep(MgcpEndpoint ep) runs on MGCP_ConnHdlr {
423 MGCP_PROC.call(MGCPEM_delete_ep:{ep, self}) {
424 [] MGCP_PROC.getreply(MGCPEM_delete_ep:{?,?}) {};
425 }
426}
427
428
Daniel Willmann955627a2018-01-17 15:22:32 +0100429private function f_expect_table_init()
430runs on MGCP_Emulation_CT {
431 var integer i;
Harald Weltebb5a1212018-01-26 10:34:44 +0100432 for (i := 0; i < sizeof(MgcpExpectTable); i := i + 1) {
433 MgcpExpectTable[i].crit := omit;
Daniel Willmann955627a2018-01-17 15:22:32 +0100434 }
435}
436
Harald Weltebb5a1212018-01-26 10:34:44 +0100437function DummyUnitdataCallback(MgcpMessage msg)
438runs on MGCP_Emulation_CT return template MgcpMessage {
439 log("Ignoring MGCP ", msg);
440 return omit;
441}
442
Philipp Maier11a58942018-06-25 16:40:48 +0200443/* Determine encoding name for a specified payload type number */
444function f_encoding_name_from_pt(SDP_FIELD_PayloadType pt) return charstring {
445 if (pt == PT_PCMU) {
446 return "PCMU";
447 } else if (pt == PT_GSM) {
448 return "GSM";
449 } else if (pt == PT_PCMA) {
450 return "PCMA";
451 } else if (pt == PT_GSMEFR) {
452 return "GSM-EFR";
453 } else if (pt == PT_GSMHR) {
454 return "GSM-HR-08";
455 } else if (pt == PT_AMR) {
456 return "AMR";
457 } else if (pt == PT_AMRWB) {
458 return "AMR-WB";
459 }
460
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200461 setverdict(fail, "Unknown payload type ", pt);
462 mtc.stop;
Philipp Maier11a58942018-06-25 16:40:48 +0200463}
Harald Weltebb5a1212018-01-26 10:34:44 +0100464
Daniel Willmannfa870f52018-01-17 12:37:14 +0100465}