blob: c3d09b93a772c5a1a50b6a10d5968fa1b6d09749 [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.
28 */
29
Daniel Willmannfa870f52018-01-17 12:37:14 +010030import from MGCP_CodecPort all;
31import from MGCP_CodecPort_CtrlFunct all;
32import from MGCP_Types all;
33import from MGCP_Templates all;
34import from Osmocom_Types all;
35import from IPL4asp_Types all;
36
37type component MGCP_ConnHdlr {
38 port MGCP_Conn_PT MGCP;
Harald Weltebb5a1212018-01-26 10:34:44 +010039 /* procedure based port to register for incoming connections */
40 port MGCPEM_PROC_PT MGCP_PROC;
Daniel Willmannfa870f52018-01-17 12:37:14 +010041}
42
43/* port between individual per-connection components and this dispatcher */
44type port MGCP_Conn_PT message {
45 inout MgcpCommand, MgcpResponse;
46} with { extension "internal" };
47
Harald Welte9601c812018-01-26 18:58:20 +010048/* represents a single MGCP Endpoint */
49type record EndpointData {
Harald Weltebb5a1212018-01-26 10:34:44 +010050 MGCP_ConnHdlr comp_ref,
Harald Welte9601c812018-01-26 18:58:20 +010051 MgcpEndpoint endpoint optional
Harald Weltebb5a1212018-01-26 10:34:44 +010052};
Daniel Willmannfa870f52018-01-17 12:37:14 +010053
Harald Welte9601c812018-01-26 18:58:20 +010054/* pending CRCX with their transaction ID */
55type set of MgcpTransId MgcpTransIds;
56
Daniel Willmannfa870f52018-01-17 12:37:14 +010057type component MGCP_Emulation_CT {
58 /* Port facing to the UDP SUT */
59 port MGCP_CODEC_PT MGCP;
60 /* All MGCP_ConnHdlr MGCP ports connect here
61 * MGCP_Emulation_CT.main needs to figure out what messages
62 * to send where with CLIENT.send() to vc_conn */
Harald Weltebb5a1212018-01-26 10:34:44 +010063 port MGCP_Conn_PT MGCP_CLIENT;
Daniel Willmannfa870f52018-01-17 12:37:14 +010064 /* currently tracked connections */
Harald Welte9601c812018-01-26 18:58:20 +010065 var EndpointData MgcpEndpointTable[16];
66 var MgcpTransIds MgcpPendingTrans := {};
Daniel Willmannfa870f52018-01-17 12:37:14 +010067 /* pending expected CRCX */
Harald Weltebb5a1212018-01-26 10:34:44 +010068 var ExpectData MgcpExpectTable[8];
Daniel Willmannfa870f52018-01-17 12:37:14 +010069 /* procedure based port to register for incoming connections */
Harald Weltebb5a1212018-01-26 10:34:44 +010070 port MGCPEM_PROC_PT MGCP_PROC;
Daniel Willmannfa870f52018-01-17 12:37:14 +010071
72 var charstring g_mgcp_id;
Daniel Willmann166bbb32018-01-17 15:28:04 +010073 var integer g_mgcp_conn_id := -1;
Daniel Willmannfa870f52018-01-17 12:37:14 +010074}
75
76type function MGCPCreateCallback(MgcpCommand cmd, charstring id)
77runs on MGCP_Emulation_CT return MGCP_ConnHdlr;
78
Harald Weltebb5a1212018-01-26 10:34:44 +010079type function MGCPUnitdataCallback(MgcpMessage msg)
80runs on MGCP_Emulation_CT return template MgcpMessage;
81
Daniel Willmannfa870f52018-01-17 12:37:14 +010082type record MGCPOps {
Harald Weltebb5a1212018-01-26 10:34:44 +010083 MGCPCreateCallback create_cb,
84 MGCPUnitdataCallback unitdata_cb
Daniel Willmannfa870f52018-01-17 12:37:14 +010085}
86
87type record MGCP_conn_parameters {
Harald Weltebb5a1212018-01-26 10:34:44 +010088 HostName callagent_ip,
89 PortNumber callagent_udp_port,
90 HostName mgw_ip,
91 PortNumber mgw_udp_port
Daniel Willmannfa870f52018-01-17 12:37:14 +010092}
93
Daniel Willmann166bbb32018-01-17 15:28:04 +010094function tr_MGCP_RecvFrom_R(template MgcpMessage msg)
95runs on MGCP_Emulation_CT return template MGCP_RecvFrom {
96 var template MGCP_RecvFrom mrf := {
97 connId := g_mgcp_conn_id,
98 remName := ?,
99 remPort := ?,
100 locName := ?,
101 locPort := ?,
102 msg := msg
103 }
104 return mrf;
105}
106
Harald Welte9601c812018-01-26 18:58:20 +0100107private function f_ep_known(MgcpEndpoint ep)
Harald Weltebb5a1212018-01-26 10:34:44 +0100108runs on MGCP_Emulation_CT return boolean {
109 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100110 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
111 if (MgcpEndpointTable[i].endpoint == ep) {
Harald Weltebb5a1212018-01-26 10:34:44 +0100112 return true;
113 }
114 }
115 return false;
116}
117
118private function f_comp_known(MGCP_ConnHdlr client)
119runs on MGCP_Emulation_CT return boolean {
120 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100121 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
122 if (MgcpEndpointTable[i].comp_ref == client) {
Harald Weltebb5a1212018-01-26 10:34:44 +0100123 return true;
124 }
125 }
126 return false;
127}
128
Harald Welte9601c812018-01-26 18:58:20 +0100129private function f_comp_by_ep(MgcpEndpoint ep)
Harald Weltebb5a1212018-01-26 10:34:44 +0100130runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
131 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100132 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
133 if (MgcpEndpointTable[i].endpoint == ep) {
134 return MgcpEndpointTable[i].comp_ref;
Harald Weltebb5a1212018-01-26 10:34:44 +0100135 }
136 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200137 setverdict(fail, "MGCP Endpoint Table not found by Endpoint", ep);
138 mtc.stop;
Harald Weltebb5a1212018-01-26 10:34:44 +0100139}
140
Harald Welte9601c812018-01-26 18:58:20 +0100141private function f_ep_by_comp(MGCP_ConnHdlr client)
142runs on MGCP_Emulation_CT return MgcpEndpoint {
Harald Weltebb5a1212018-01-26 10:34:44 +0100143 var integer i;
Harald Welte9601c812018-01-26 18:58:20 +0100144 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
145 if (MgcpEndpointTable[i].comp_ref == client) {
146 return MgcpEndpointTable[i].endpoint;
Harald Weltebb5a1212018-01-26 10:34:44 +0100147 }
148 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200149 setverdict(fail, "MGCP Endpoint Table not found by component ", client);
150 mtc.stop;
Harald Weltebb5a1212018-01-26 10:34:44 +0100151}
152
Harald Welte9601c812018-01-26 18:58:20 +0100153private function f_ep_table_add(MGCP_ConnHdlr comp_ref, MgcpEndpoint ep)
154runs on MGCP_Emulation_CT {
155 var integer i;
156 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
157 if (not isvalue(MgcpEndpointTable[i].endpoint)) {
158 MgcpEndpointTable[i].endpoint := ep;
159 MgcpEndpointTable[i].comp_ref := comp_ref;
160 return;
161 }
162 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200163 testcase.stop("MGCP Endpoint Table full!");
Harald Welte9601c812018-01-26 18:58:20 +0100164}
165
166private function f_ep_table_del(MGCP_ConnHdlr comp_ref, MgcpEndpoint ep)
167runs on MGCP_Emulation_CT {
168 var integer i;
169 for (i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
170 if (MgcpEndpointTable[i].comp_ref == comp_ref and
171 MgcpEndpointTable[i].endpoint == ep) {
172 MgcpEndpointTable[i].endpoint := omit;
173 MgcpEndpointTable[i].comp_ref := null;
174 return;
175 }
176 }
177 setverdict(fail, "MGCP Endpoint Table: Couldn't find to-be-deleted entry!");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200178 mtc.stop;
Harald Welte9601c812018-01-26 18:58:20 +0100179}
180
181
182/* Check if the given transaction ID is a pending CRCX. If yes, return true + remove */
183private function f_trans_id_was_pending(MgcpTransId trans_id)
184runs on MGCP_Emulation_CT return boolean {
185 for (var integer i := 0; i < lengthof(MgcpPendingTrans); i := i+1) {
186 if (MgcpPendingTrans[i] == trans_id) {
187 /* Remove from list */
188 var MgcpTransIds OldPendingTrans := MgcpPendingTrans;
189 MgcpPendingTrans := {}
190 for (var integer j := 0; j < lengthof(OldPendingTrans); j := j+1) {
191 if (j != i) {
192 MgcpPendingTrans := MgcpPendingTrans & {OldPendingTrans[j]};
193 }
194 }
195 return true;
196 }
197 }
198 return false;
199}
200
Harald Weltebb5a1212018-01-26 10:34:44 +0100201/* TODO: move this to MGCP_Types? */
Harald Welte9601c812018-01-26 18:58:20 +0100202function f_mgcp_ep(MgcpMessage msg) return MgcpEndpoint {
Harald Weltebb5a1212018-01-26 10:34:44 +0100203 var MgcpParameterList params;
204 var integer i;
205 if (ischosen(msg.command)) {
Harald Welte9601c812018-01-26 18:58:20 +0100206 return msg.command.line.ep;
Harald Weltebb5a1212018-01-26 10:34:44 +0100207 } else {
Harald Welte363cb0a2018-01-30 19:35:53 +0100208 var MgcpEndpoint ep;
209 if (f_mgcp_find_param(msg, "Z", ep) == false) {
210 setverdict(fail, "No SpecificEndpointName in MGCP response", msg);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200211 mtc.stop;
Harald Welte363cb0a2018-01-30 19:35:53 +0100212 }
213 return ep;
Harald Weltebb5a1212018-01-26 10:34:44 +0100214 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100215}
216
Harald Welte9601c812018-01-26 18:58:20 +0100217private function f_ep_table_init()
Harald Weltebb5a1212018-01-26 10:34:44 +0100218runs on MGCP_Emulation_CT {
Harald Welte9601c812018-01-26 18:58:20 +0100219 for (var integer i := 0; i < sizeof(MgcpEndpointTable); i := i+1) {
220 MgcpEndpointTable[i].comp_ref := null;
221 MgcpEndpointTable[i].endpoint := omit;
Harald Weltebb5a1212018-01-26 10:34:44 +0100222 }
223}
224
Daniel Willmann955627a2018-01-17 15:22:32 +0100225function main(MGCPOps ops, MGCP_conn_parameters p, charstring id) runs on MGCP_Emulation_CT {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100226 var Result res;
227 g_mgcp_id := id;
Harald Welte9601c812018-01-26 18:58:20 +0100228 f_ep_table_init();
Daniel Willmann955627a2018-01-17 15:22:32 +0100229 f_expect_table_init();
Daniel Willmannfa870f52018-01-17 12:37:14 +0100230
231 map(self:MGCP, system:MGCP_CODEC_PT);
Harald Weltebb5a1212018-01-26 10:34:44 +0100232 if (p.callagent_udp_port == -1) {
233 res := MGCP_CodecPort_CtrlFunct.f_IPL4_listen(MGCP, p.mgw_ip, p.mgw_udp_port, { udp:={} });
234 } else {
235 res := MGCP_CodecPort_CtrlFunct.f_IPL4_connect(MGCP, p.callagent_ip, p.callagent_udp_port, p.mgw_ip, p.mgw_udp_port, -1, { udp:={} });
236 }
Harald Welte9220f632018-05-23 20:27:02 +0200237 if (not ispresent(res.connId)) {
238 setverdict(fail, "Could not connect MGCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200239 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200240 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100241 g_mgcp_conn_id := res.connId;
Harald Weltebb5a1212018-01-26 10:34:44 +0100242
Daniel Willmannfa870f52018-01-17 12:37:14 +0100243 while (true) {
Daniel Willmann166bbb32018-01-17 15:28:04 +0100244 var MGCP_ConnHdlr vc_conn;
245 var ExpectCriteria crit;
246 var MGCP_RecvFrom mrf;
247 var MgcpMessage msg;
248 var MgcpCommand cmd;
249 var MgcpResponse resp;
Harald Welte9601c812018-01-26 18:58:20 +0100250 var MgcpEndpoint ep;
Daniel Willmann166bbb32018-01-17 15:28:04 +0100251
Daniel Willmannfa870f52018-01-17 12:37:14 +0100252 alt {
Daniel Willmann166bbb32018-01-17 15:28:04 +0100253 /* MGCP from client */
Harald Weltebb5a1212018-01-26 10:34:44 +0100254 [] MGCP_CLIENT.receive(MgcpResponse:?) -> value resp sender vc_conn {
Harald Welte9601c812018-01-26 18:58:20 +0100255 msg := {
256 response := resp
257 };
258 /* If this is the resposne to a pending CRCX, extract Endpoint and store in table */
259 if (f_trans_id_was_pending(resp.line.trans_id)) {
260 f_ep_table_add(vc_conn, f_mgcp_ep(msg));
261 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100262 /* Pass message through */
Harald Weltebb5a1212018-01-26 10:34:44 +0100263 /* TODO: check which ConnectionID client has allocated + store in table? */
Daniel Willmann166bbb32018-01-17 15:28:04 +0100264 MGCP.send(t_MGCP_Send(g_mgcp_conn_id, msg));
Daniel Willmannfa870f52018-01-17 12:37:14 +0100265 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100266 [] MGCP.receive(tr_MGCP_RecvFrom_R(?)) -> value mrf {
Harald Weltebb5a1212018-01-26 10:34:44 +0100267 if (p.callagent_udp_port == -1) {
268 /* we aren't yet connected to the remote side port, let's fix this */
269 p.callagent_udp_port := mrf.remPort;
Harald Welte930d0a72018-03-22 22:08:40 +0100270 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 +0200271 if (not ispresent(res.connId)) {
272 setverdict(fail, "Could not connect MGCP socket, check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200273 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200274 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100275 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100276 if (ischosen(mrf.msg.command)) {
277 cmd := mrf.msg.command;
Harald Welte9601c812018-01-26 18:58:20 +0100278 if (f_ep_known(cmd.line.ep)) {
279 vc_conn := f_comp_by_ep(cmd.line.ep);
Harald Weltebb5a1212018-01-26 10:34:44 +0100280 MGCP_CLIENT.send(cmd) to vc_conn;
281 } else {
Harald Welte9601c812018-01-26 18:58:20 +0100282 if (cmd.line.verb == "CRCX") {
283 vc_conn := ops.create_cb.apply(cmd, id);
Harald Welte363cb0a2018-01-30 19:35:53 +0100284 if (not match(cmd.line.ep, t_MGCP_EP_wildcard)) {
285 /* non-wildcard EP, use directly */
Harald Welte9601c812018-01-26 18:58:20 +0100286 f_ep_table_add(vc_conn, cmd.line.ep);
287 } else {
288 /* add this transaction to list of pending transactions */
289 MgcpPendingTrans := MgcpPendingTrans & {cmd.line.trans_id};
290 }
291 MGCP_CLIENT.send(cmd) to vc_conn;
292 } else {
293 /* connectionless MGCP, i.e. messages without ConnectionId */
294 var template MgcpMessage r := ops.unitdata_cb.apply(mrf.msg);
295 if (isvalue(r)) {
296 MGCP.send(t_MGCP_Send(g_mgcp_conn_id, r));
297 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100298 }
299 }
Daniel Willmann166bbb32018-01-17 15:28:04 +0100300 } else {
301 setverdict(fail, "Received unexpected MGCP response: ", mrf.msg.response);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200302 mtc.stop;
Daniel Willmann166bbb32018-01-17 15:28:04 +0100303 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100304 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100305 [] MGCP_PROC.getcall(MGCPEM_register:{?,?}) -> param(crit, vc_conn) {
Daniel Willmann955627a2018-01-17 15:22:32 +0100306 f_create_expect(crit, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200307 MGCP_PROC.reply(MGCPEM_register:{crit, vc_conn}) to vc_conn;
Daniel Willmann955627a2018-01-17 15:22:32 +0100308 }
Harald Welte9601c812018-01-26 18:58:20 +0100309 [] MGCP_PROC.getcall(MGCPEM_delete_ep:{?,?}) -> param(ep, vc_conn) {
310 f_ep_table_del(vc_conn, ep);
Harald Weltee32ad992018-05-31 22:17:46 +0200311 MGCP_PROC.reply(MGCPEM_delete_ep:{ep, vc_conn}) to vc_conn;
Harald Welte9601c812018-01-26 18:58:20 +0100312 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100313 }
Harald Welte9601c812018-01-26 18:58:20 +0100314
Daniel Willmannfa870f52018-01-17 12:37:14 +0100315 }
316}
317
318/* "Expect" Handling */
319
320/* */
Daniel Willmann955627a2018-01-17 15:22:32 +0100321type record ExpectCriteria {
322 MgcpConnectionId connid optional,
323 MgcpEndpoint endpoint optional,
324 MgcpTransId transid optional
Daniel Willmannfa870f52018-01-17 12:37:14 +0100325}
326
327type record ExpectData {
328 ExpectCriteria crit optional,
Daniel Willmann955627a2018-01-17 15:22:32 +0100329 MGCP_ConnHdlr vc_conn
Daniel Willmannfa870f52018-01-17 12:37:14 +0100330}
331
Daniel Willmann955627a2018-01-17 15:22:32 +0100332signature MGCPEM_register(in ExpectCriteria cmd, in MGCP_ConnHdlr hdlr);
Harald Welte9601c812018-01-26 18:58:20 +0100333signature MGCPEM_delete_ep(in MgcpEndpoint ep, in MGCP_ConnHdlr hdlr);
Daniel Willmannfa870f52018-01-17 12:37:14 +0100334
335type port MGCPEM_PROC_PT procedure {
Harald Welte9601c812018-01-26 18:58:20 +0100336 inout MGCPEM_register, MGCPEM_delete_ep;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100337} with { extension "internal" };
338
339function f_get_mgcp_by_crit(ExpectCriteria crit)
340return template MgcpCommand {
Harald Weltebb5a1212018-01-26 10:34:44 +0100341 var template MgcpCommand ret := {
342 line := {
343 verb := ?,
344 trans_id := ?,
345 ep := ?,
346 ver := ?
347 },
348 params := *,
349 sdp := *
350 }
351 if (ispresent(crit.connid)) {
352 ret.params := { *, ts_MgcpParConnectionId(crit.connid), * };
353 }
354 if (ispresent(crit.endpoint)) {
355 ret.line.ep := crit.endpoint;
356 }
357 if (ispresent(crit.transid)) {
358 ret.line.trans_id := crit.transid;
359 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100360
361 return ret;
362}
363
364/* Function that can be used as create_cb and will usse the expect table */
365function ExpectedCreateCallback(MgcpCommand cmd, charstring id)
366runs on MGCP_Emulation_CT return MGCP_ConnHdlr {
367 var MGCP_ConnHdlr ret := null;
368 var template MgcpCommand mgcpcmd;
369 var integer i;
370
Harald Weltebb5a1212018-01-26 10:34:44 +0100371 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
372 if (not ispresent(MgcpExpectTable[i].crit)) {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100373 continue;
374 }
Daniel Willmann955627a2018-01-17 15:22:32 +0100375 /* FIXME: Ignore criteria for now */
Harald Weltebb5a1212018-01-26 10:34:44 +0100376 mgcpcmd := f_get_mgcp_by_crit(MgcpExpectTable[i].crit);
377 if (match(cmd, mgcpcmd)) {
378 ret := MgcpExpectTable[i].vc_conn;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100379 /* Release this entry */
Harald Weltebb5a1212018-01-26 10:34:44 +0100380 MgcpExpectTable[i].crit := omit;
381 MgcpExpectTable[i].vc_conn := null;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100382 log("Found Expect[", i, "] for ", cmd, " handled at ", ret);
383 return ret;
Harald Weltebb5a1212018-01-26 10:34:44 +0100384 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100385 }
386 setverdict(fail, "Couldn't find Expect for CRCX", cmd);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200387 mtc.stop;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100388 return ret;
389}
390
391private function f_create_expect(ExpectCriteria crit, MGCP_ConnHdlr hdlr)
392runs on MGCP_Emulation_CT {
393 var integer i;
394
395 /* Check an entry like this is not already presnt */
Harald Weltebb5a1212018-01-26 10:34:44 +0100396 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
397 if (crit == MgcpExpectTable[i].crit) {
Daniel Willmannfa870f52018-01-17 12:37:14 +0100398 setverdict(fail, "Crit already present", crit);
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200399 mtc.stop;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100400 }
401 }
Harald Weltebb5a1212018-01-26 10:34:44 +0100402 for (i := 0; i < sizeof(MgcpExpectTable); i := i+1) {
403 if (not ispresent(MgcpExpectTable[i].crit)) {
404 MgcpExpectTable[i].crit := crit;
405 MgcpExpectTable[i].vc_conn := hdlr;
Daniel Willmannfa870f52018-01-17 12:37:14 +0100406 log("Created Expect[", i, "] for ", crit, " to be handled at ", hdlr);
407 return;
408 }
409 }
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200410 testcase.stop("No space left in MgcpExpectTable")
Harald Weltebb5a1212018-01-26 10:34:44 +0100411}
412
413/* client/conn_hdlr side function to use procedure port to create expect in emulation */
414function f_create_mgcp_expect(ExpectCriteria dest_number) runs on MGCP_ConnHdlr {
415 MGCP_PROC.call(MGCPEM_register:{dest_number, self}) {
416 [] MGCP_PROC.getreply(MGCPEM_register:{?,?}) {};
417 }
Daniel Willmannfa870f52018-01-17 12:37:14 +0100418}
419
Harald Welte9601c812018-01-26 18:58:20 +0100420/* client/conn_hdlr side function to use procedure port to create expect in emulation */
421function f_create_mgcp_delete_ep(MgcpEndpoint ep) runs on MGCP_ConnHdlr {
422 MGCP_PROC.call(MGCPEM_delete_ep:{ep, self}) {
423 [] MGCP_PROC.getreply(MGCPEM_delete_ep:{?,?}) {};
424 }
425}
426
427
Daniel Willmann955627a2018-01-17 15:22:32 +0100428private function f_expect_table_init()
429runs on MGCP_Emulation_CT {
430 var integer i;
Harald Weltebb5a1212018-01-26 10:34:44 +0100431 for (i := 0; i < sizeof(MgcpExpectTable); i := i + 1) {
432 MgcpExpectTable[i].crit := omit;
Daniel Willmann955627a2018-01-17 15:22:32 +0100433 }
434}
435
Harald Weltebb5a1212018-01-26 10:34:44 +0100436function DummyUnitdataCallback(MgcpMessage msg)
437runs on MGCP_Emulation_CT return template MgcpMessage {
438 log("Ignoring MGCP ", msg);
439 return omit;
440}
441
Philipp Maier11a58942018-06-25 16:40:48 +0200442/* Determine encoding name for a specified payload type number */
443function f_encoding_name_from_pt(SDP_FIELD_PayloadType pt) return charstring {
444 if (pt == PT_PCMU) {
445 return "PCMU";
446 } else if (pt == PT_GSM) {
447 return "GSM";
448 } else if (pt == PT_PCMA) {
449 return "PCMA";
450 } else if (pt == PT_GSMEFR) {
451 return "GSM-EFR";
452 } else if (pt == PT_GSMHR) {
453 return "GSM-HR-08";
454 } else if (pt == PT_AMR) {
455 return "AMR";
456 } else if (pt == PT_AMRWB) {
457 return "AMR-WB";
458 }
459
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200460 setverdict(fail, "Unknown payload type ", pt);
461 mtc.stop;
Philipp Maier11a58942018-06-25 16:40:48 +0200462 return "";
463}
Harald Weltebb5a1212018-01-26 10:34:44 +0100464
Daniel Willmannfa870f52018-01-17 12:37:14 +0100465}