blob: 906664fbc6ca39896d880b5fbc778234d322b6a7 [file] [log] [blame]
Harald Welted86cdc62017-11-22 00:45:07 +01001module IPA_Emulation {
2
Harald Weltebdb63702017-12-09 01:15:44 +01003/* This module implements the IPA multiplex protocol on top of TCP, using the IPL4asp
4 * test-port as provider. It implements both client and server roles, as well was the CCM
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +02005 * handshake for establishing the identity of the client to the server.
Harald Welte35bb7162018-01-03 21:07:52 +01006 *
7 * It already knows certain well-known sub-protocols such as A-bis RSL, MGCP and SCCP and
8 * GSUP. IT hence transcodes messages so the user can work with abstract data types rather
9 * than binary messages. It handles multiple packets inside one TCP segment.
10 *
Harald Welte34b5a952019-05-27 11:54:11 +020011 * (C) 2017-2019 by Harald Welte <laforge@gnumonks.org>
12 * contributions by sysmocom - s.f.m.c. GmbH
Harald Welte35bb7162018-01-03 21:07:52 +010013 * All rights reserved.
14 *
15 * Released under the terms of GNU General Public License, Version 2 or
16 * (at your option) any later version.
Harald Welte34b5a952019-05-27 11:54:11 +020017 *
18 * SPDX-License-Identifier: GPL-2.0-or-later
Harald Welte35bb7162018-01-03 21:07:52 +010019 */
Harald Weltebdb63702017-12-09 01:15:44 +010020
Harald Welted86cdc62017-11-22 00:45:07 +010021import from IPA_Types all;
22import from IPA_CodecPort all;
23import from IPA_CodecPort_CtrlFunct all;
24import from IPL4asp_Types all;
Harald Welte12188832017-11-29 11:47:13 +010025import from IPL4asp_PortType all;
Stefan Sperling830dc9d2018-02-12 21:08:28 +010026import from Socket_API_Definitions all;
Harald Welted86cdc62017-11-22 00:45:07 +010027
Harald Weltedf277252018-02-20 15:49:30 +010028#ifdef IPA_EMULATION_SCCP
29import from MTP3asp_Types all;
30import from MTP3asp_PortType all;
31#endif
32
33#ifdef IPA_EMULATION_RSL
34import from RSL_Types all;
35#endif
36
Harald Weltec6826662019-02-06 22:26:46 +010037#ifdef IPA_EMULATION_OML
38import from AbisOML_Types all;
39#endif
40
Harald Weltedf277252018-02-20 15:49:30 +010041#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +010042import from MGCP_Types all;
Harald Weltedf277252018-02-20 15:49:30 +010043#endif
44
45#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +010046import from GSUP_Types all;
Harald Weltedf277252018-02-20 15:49:30 +010047#endif
Harald Weltec82eef42017-11-24 20:40:12 +010048
Harald Welte7460a722018-10-10 12:28:27 +020049#ifdef IPA_EMULATION_RSPRO
50import from RSPRO all;
51import from RSPRO_Types all;
52#endif
53
Harald Welte3286eb32019-08-18 19:36:10 +020054#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +010055import from Osmocom_CTRL_Types all;
Harald Welte3286eb32019-08-18 19:36:10 +020056#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +010057
Harald Welted86cdc62017-11-22 00:45:07 +010058modulepar {
Harald Welte92632e12017-11-25 02:31:20 +010059 /* Use Osmocom extended IPA mux header */
60 boolean mp_ipa_mgcp_uses_osmo_ext := true;
Harald Welted86cdc62017-11-22 00:45:07 +010061}
Harald Welted86cdc62017-11-22 00:45:07 +010062
Harald Welteb3414b22017-11-23 18:22:10 +010063type enumerated IpaMode {
64 IPA_MODE_CLIENT,
65 IPA_MODE_SERVER
66}
67
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +020068type enumerated IpaInitBehavior {
69 IPA_INIT_SEND_IPA_ID_GET,
70 IPA_INIT_SEND_IPA_ID_ACK
71}
72
Harald Weltec76f29f2017-11-22 12:46:46 +010073type record ASP_IPA_Unitdata {
74 IpaStreamId streamId,
Harald Weltec82eef42017-11-24 20:40:12 +010075 IpaExtStreamId streamIdExt optional,
Harald Weltec76f29f2017-11-22 12:46:46 +010076 octetstring payload
77}
78
Vadim Yanitskiy8701b272020-05-18 20:17:25 +070079type enumerated ASP_IPA_EventType {
Harald Welte0d846a72017-12-07 17:58:28 +010080 ASP_IPA_EVENT_DOWN,
81 ASP_IPA_EVENT_UP,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070082 ASP_IPA_EVENT_ID_RESP,
Harald Welte0d846a72017-12-07 17:58:28 +010083 ASP_IPA_EVENT_ID_ACK
84}
85
Harald Weltebdb63702017-12-09 01:15:44 +010086/* an event indicating us whether or not a connection is physically up or down,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070087 * and whether we have received an ID_RESP or ID_ACK */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +070088type record ASP_IPA_Event {
89 ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070090 integer conn_id,
91
92 /* Presence of these fields depends on event type */
93 IpaCcmIdResp id_resp optional // ASP_IPA_EVENT_ID_RESP
Harald Welte0d846a72017-12-07 17:58:28 +010094}
95
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070096template (value) ASP_IPA_Event ts_ASP_IPA_EV(ASP_IPA_EventType ev_type, integer conn_id,
97 template (omit) IpaCcmIdResp id_resp := omit) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +070098 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +070099 conn_id := conn_id,
100 id_resp := id_resp
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700101}
102
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700103template ASP_IPA_Event tr_ASP_IPA_EV(template ASP_IPA_EventType ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700104 template integer conn_id := ?,
105 template IpaCcmIdResp id_resp := *) := {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700106 ev_type := ev_type,
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700107 conn_id := conn_id,
108 id_resp := id_resp
Harald Welte0d846a72017-12-07 17:58:28 +0100109}
110
Harald Welte1dd8f372017-11-25 02:25:27 +0100111template ASP_IPA_Unitdata t_ASP_IPA_UD(IpaStreamId sid, octetstring pl,
112 template IpaExtStreamId esid := omit) := {
113 streamId := sid,
114 streamIdExt := esid,
115 payload := pl
116}
117
Harald Weltedf277252018-02-20 15:49:30 +0100118#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100119/* like ASP_IPA_Unitdata, but with RSL_Message abstract type instead of octetstring */
Harald Welte0d846a72017-12-07 17:58:28 +0100120type record ASP_RSL_Unitdata {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700121 integer conn_id optional,
Harald Welte0d846a72017-12-07 17:58:28 +0100122 IpaStreamId streamId,
123 RSL_Message rsl
124};
125
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700126template (value) ASP_RSL_Unitdata ts_ASP_RSL_UD(template (value) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700127 IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
128 template (omit) integer conn_id := omit) := {
129 conn_id := conn_id,
Harald Welte0d846a72017-12-07 17:58:28 +0100130 streamId := sid,
Vadim Yanitskiy6b4856d2020-05-25 21:23:46 +0700131 rsl := rsl
Harald Welte0d846a72017-12-07 17:58:28 +0100132}
133
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700134template ASP_RSL_Unitdata tr_ASP_RSL_UD(template (present) RSL_Message rsl,
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700135 template IpaStreamId sid := IPAC_PROTO_RSL_TRX0,
136 template integer conn_id := *) := {
137 conn_id := conn_id,
Harald Welte7ae019e2017-12-09 00:54:15 +0100138 streamId := sid,
139 rsl := rsl
140}
141
Harald Welte0d846a72017-12-07 17:58:28 +0100142template IpaStreamId t_IpaSidRSL := ( IPAC_PROTO_RSL_TRX0, IPAC_PROTO_RSL_TRX1,
143 IPAC_PROTO_RSL_TRX2, IPAC_PROTO_RSL_TRX3 );
Harald Weltedf277252018-02-20 15:49:30 +0100144#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100145
Harald Weltec6826662019-02-06 22:26:46 +0100146
Harald Weltebdb63702017-12-09 01:15:44 +0100147/* Client port for general IPA messages, not further decoded */
Harald Weltec76f29f2017-11-22 12:46:46 +0100148type port IPA_SP_PT message {
Harald Welte0d846a72017-12-07 17:58:28 +0100149 inout ASP_IPA_Unitdata, ASP_IPA_Event;
Harald Weltec76f29f2017-11-22 12:46:46 +0100150} with { extension "internal" }
151
Harald Weltedf277252018-02-20 15:49:30 +0100152#ifdef IPA_EMULATION_MGCP
Harald Weltebdb63702017-12-09 01:15:44 +0100153/* Client port for MGCP inside IPA */
Harald Weltec82eef42017-11-24 20:40:12 +0100154type port IPA_MGCP_PT message {
155 inout MgcpCommand, MgcpResponse;
156} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100157#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100158
Harald Weltedf277252018-02-20 15:49:30 +0100159#ifdef IPA_EMULATION_RSL
Harald Weltebdb63702017-12-09 01:15:44 +0100160/* Client port for A-bis RSL inside IPA */
Harald Welte0d846a72017-12-07 17:58:28 +0100161type port IPA_RSL_PT message {
162 inout ASP_RSL_Unitdata, ASP_IPA_Event;
163} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100164#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100165
Harald Weltec6826662019-02-06 22:26:46 +0100166#ifdef IPA_EMULATION_OML
167/* Client port for A-bis OML inside IPA */
168type port IPA_OML_PT message {
169 inout OML_PDU, octetstring, ASP_IPA_Event;
170} with { extension "internal" }
171#endif
172
Harald Welte3286eb32019-08-18 19:36:10 +0200173#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100174/* Client port for CTRL inside IPA */
175type port IPA_CTRL_PT message {
176 inout CtrlMessage, ASP_IPA_Event;
177} with { extension "internal" }
Harald Welte3286eb32019-08-18 19:36:10 +0200178#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100179
Harald Weltedf277252018-02-20 15:49:30 +0100180#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100181/* Client port for CTRL inside IPA */
182type port IPA_GSUP_PT message {
183 inout GSUP_PDU, ASP_IPA_Event;
184} with { extension "internal" }
Harald Weltedf277252018-02-20 15:49:30 +0100185#endif
Harald Weltedf327232017-12-28 22:51:51 +0100186
Harald Welte7460a722018-10-10 12:28:27 +0200187#ifdef IPA_EMULATION_RSPRO
188type port IPA_RSPRO_PT message {
189 inout RsproPDU, ASP_IPA_Event;
190} with { extension "internal" }
191#endif
192
193
194
Harald Weltedf327232017-12-28 22:51:51 +0100195
Harald Welted86cdc62017-11-22 00:45:07 +0100196type component IPA_Emulation_CT {
197 /* down-facing port to IPA codec port */
198 port IPA_CODEC_PT IPA_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100199#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100200 /* up-facing port to SCCP */
201 port MTP3asp_SP_PT MTP3_SP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100202#endif
203#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100204 /* up-facing port for MGCP */
205 port IPA_MGCP_PT IPA_MGCP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100206#endif
207#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100208 /* up-facing port for RSL */
209 port IPA_RSL_PT IPA_RSL_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100210#endif
Harald Weltec6826662019-02-06 22:26:46 +0100211#ifdef IPA_EMULATION_OML
212 /* up-facing port for OML */
213 port IPA_OML_PT IPA_OML_PORT;
214#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200215#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100216 /* up-facing port for CTRL */
217 port IPA_CTRL_PT IPA_CTRL_PORT;
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200218#endif
Harald Weltedf277252018-02-20 15:49:30 +0100219#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100220 /* up-facing port for GSUP */
221 port IPA_GSUP_PT IPA_GSUP_PORT;
Harald Weltedf277252018-02-20 15:49:30 +0100222#endif
Harald Welte7460a722018-10-10 12:28:27 +0200223#ifdef IPA_EMULATION_RSPRO
224 /* up-facing port for RSPRO */
225 port IPA_RSPRO_PT IPA_RSPRO_PORT;
226#endif
Harald Weltedf327232017-12-28 22:51:51 +0100227
Harald Weltec76f29f2017-11-22 12:46:46 +0100228 /* up-facing port for other streams */
229 port IPA_SP_PT IPA_SP_PORT;
Harald Welted86cdc62017-11-22 00:45:07 +0100230
231 var boolean g_initialized := false;
Harald Weltec82eef42017-11-24 20:40:12 +0100232 /* Are we a BSC/MGW (truel) or MSC (false) */
233 var boolean g_is_bsc_mgw;
Harald Welteb3414b22017-11-23 18:22:10 +0100234
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700235 /* Connection identifier of the client / server itself */
236 var IPL4asp_Types.ConnectionId g_self_conn_id := -1;
237 /* Connection identifier of the last connected client (server only) */
238 var IPL4asp_Types.ConnectionId g_last_conn_id := -1;
239
Harald Welteb3414b22017-11-23 18:22:10 +0100240 var IpaMode g_mode;
Harald Welte2d86aff2018-04-17 11:23:04 +0200241 var boolean g_ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200242 var IpaInitBehavior g_init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100243 /* Shall we stop the component once the client disconnects, or keep
244 * running to let next user in ? */
245 var boolean g_server_stop_on_ipa_ev_down := true;
Harald Weltee09921f2017-12-07 17:49:00 +0100246 var IPA_CCM_Parameters g_ccm_pars := c_IPA_default_ccm_pars;
Harald Welted86cdc62017-11-22 00:45:07 +0100247}
248
Harald Weltee21096d2017-12-04 20:45:12 +0100249type record IPA_CCM_Parameters {
250 charstring ser_nr optional,
251 charstring name optional,
252 charstring location1 optional,
253 charstring location2 optional,
254 charstring equip_version optional,
255 charstring sw_version optional,
256 charstring ip_addr optional,
257 charstring mac_addr optional,
258 charstring unit_id optional,
259 charstring osmo_rand optional
260}
261
Harald Weltee09921f2017-12-07 17:49:00 +0100262const IPA_CCM_Parameters c_IPA_default_ccm_pars := {
263 ser_nr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100264 name := "mahlzeit",
Harald Weltee09921f2017-12-07 17:49:00 +0100265 location1 := "",
266 location2 := "",
267 equip_version := "",
268 sw_version := "",
269 ip_addr := "",
270 mac_addr := "",
Harald Weltee21096d2017-12-04 20:45:12 +0100271 unit_id := "0/1/2",
Harald Weltee09921f2017-12-07 17:49:00 +0100272 osmo_rand := ""
Harald Weltee21096d2017-12-04 20:45:12 +0100273};
274
Harald Weltebdb63702017-12-09 01:15:44 +0100275/* Function to use to connect as client to a remote IPA Server */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100276function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
277 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100278 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100279 var IPL4asp_Types.Result res;
Harald Welted86cdc62017-11-22 00:45:07 +0100280 res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
281 local_host, local_port, 0, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200282 if (not ispresent(res.connId)) {
Stefan Sperling6a90be42018-08-31 15:05:39 +0200283 setverdict(fail, "Could not connect IPA socket from ", local_host, " port ", local_port,
284 " to ", remote_host, " port ", remote_port, "; check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200285 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200286 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700287 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100288 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100289 g_is_bsc_mgw := true;
Harald Welted86cdc62017-11-22 00:45:07 +0100290}
291
Harald Weltebdb63702017-12-09 01:15:44 +0100292/* Function to use to bind to a local port as IPA server, accepting remote clients */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100293function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Weltee09921f2017-12-07 17:49:00 +0100294 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars) runs on IPA_Emulation_CT {
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100295 var IPL4asp_Types.Result res;
Pau Espin Pedrol76ba5412019-06-10 11:00:33 +0200296 res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
Harald Welteb3414b22017-11-23 18:22:10 +0100297 local_host, local_port, { tcp:={} });
Harald Welte9220f632018-05-23 20:27:02 +0200298 if (not ispresent(res.connId)) {
Maxb7aae8b2019-03-11 15:22:02 +0100299 setverdict(fail, "Could not listen IPA socket ", local_host, ":", local_port, ", check your configuration");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200300 mtc.stop;
Harald Welte9220f632018-05-23 20:27:02 +0200301 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700302 g_self_conn_id := res.connId;
Harald Weltee21096d2017-12-04 20:45:12 +0100303 g_ccm_pars := ccm_pars;
Harald Weltec82eef42017-11-24 20:40:12 +0100304 g_is_bsc_mgw := false;
Harald Welteb3414b22017-11-23 18:22:10 +0100305}
306
Harald Weltedf277252018-02-20 15:49:30 +0100307#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100308template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
309 sio := { '10'B, '00'B, '0011'B },
310 opc := opc,
311 dpc := 0,
312 sls := 0,
313 data := data
314}
Harald Weltedf277252018-02-20 15:49:30 +0100315#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100316
317
318private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
319 len := 0, /* overwritten by codec */
320 tag := tag,
Harald Welte95686e02018-08-02 15:05:43 +0200321 data := char2oct(payload) & '00'O
Harald Welted86cdc62017-11-22 00:45:07 +0100322}
323
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700324private function f_send_IPA_EVT(template (value) ASP_IPA_Event evt) runs on IPA_Emulation_CT {
Harald Welte2e32e432018-05-24 20:00:00 +0200325 if (IPA_SP_PORT.checkstate("Connected")) {
326 IPA_SP_PORT.send(evt);
327 }
Harald Weltedf277252018-02-20 15:49:30 +0100328#ifdef IPA_EMULATION_RSL
Harald Welte5819b552017-12-09 02:55:46 +0100329 if (IPA_RSL_PORT.checkstate("Connected")) {
330 IPA_RSL_PORT.send(evt);
331 }
Harald Weltedf277252018-02-20 15:49:30 +0100332#endif
Harald Weltec6826662019-02-06 22:26:46 +0100333#ifdef IPA_EMULATION_OML
334 if (IPA_OML_PORT.checkstate("Connected")) {
335 IPA_OML_PORT.send(evt);
336 }
337#endif
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200338#ifdef IPA_EMULATION_CTRL
Harald Welte5819b552017-12-09 02:55:46 +0100339 if (IPA_CTRL_PORT.checkstate("Connected")) {
340 IPA_CTRL_PORT.send(evt);
341 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200342#endif
Harald Weltedf277252018-02-20 15:49:30 +0100343#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100344 if (IPA_GSUP_PORT.checkstate("Connected")) {
345 IPA_GSUP_PORT.send(evt);
346 }
Harald Weltedf277252018-02-20 15:49:30 +0100347#endif
Harald Welte7460a722018-10-10 12:28:27 +0200348#ifdef IPA_EMULATION_RSPRO
349 if (IPA_RSPRO_PORT.checkstate("Connected")) {
350 IPA_RSPRO_PORT.send(evt);
351 }
352#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100353 /* FIXME: to other ports */
354}
355
Harald Welted86cdc62017-11-22 00:45:07 +0100356/* build IPA CCM ID RESP response from IPA CCM GET */
Harald Weltee21096d2017-12-04 20:45:12 +0100357private function f_ccm_make_id_resp(PDU_IPA_CCM get) runs on IPA_Emulation_CT return PDU_IPA_CCM {
Harald Welted86cdc62017-11-22 00:45:07 +0100358 var integer i;
359 var PDU_IPA_CCM resp := {
360 msg_type := IPAC_MSGT_ID_RESP,
361 u := {
362 resp := {}
363 }
364 }
365
366 for (i := 0; i < sizeof(get.u.get); i := i + 1) {
367 var IpaCcmIdTag tag := get.u.get[i].tag;
368 var charstring foo;
369 select (tag) {
Harald Weltee21096d2017-12-04 20:45:12 +0100370 case (IPAC_IDTAG_SERNR) {
371 foo := g_ccm_pars.ser_nr;
Harald Welted86cdc62017-11-22 00:45:07 +0100372 }
373 case (IPAC_IDTAG_UNITNAME) {
Harald Weltee21096d2017-12-04 20:45:12 +0100374 foo := g_ccm_pars.name;
375 }
376 case (IPAC_IDTAG_LOCATION1) {
377 foo := g_ccm_pars.location1;
378 }
379 case (IPAC_IDTAG_LOCATION2) {
380 foo := g_ccm_pars.location2;
381 }
382 case (IPAC_IDTAG_EQUIPVERS) {
383 foo := g_ccm_pars.equip_version;
384 }
385 case (IPAC_IDTAG_SWVERSION) {
386 foo := g_ccm_pars.sw_version;
387 }
388 case (IPAC_IDTAG_IPADDR) {
389 foo := g_ccm_pars.ip_addr;
390 }
391 case (IPAC_IDTAG_MACADDR) {
392 foo := g_ccm_pars.mac_addr;
393 }
Vadim Yanitskiy44f0c482020-05-24 20:49:29 +0700394 case (IPAC_IDTAG_UNITID) {
Harald Weltee21096d2017-12-04 20:45:12 +0100395 foo := g_ccm_pars.unit_id;
396 }
397 case (IPAC_IDTAG_OSMO_RAND) {
398 foo := g_ccm_pars.osmo_rand;
Harald Welted86cdc62017-11-22 00:45:07 +0100399 }
400 case else {
Harald Weltee21096d2017-12-04 20:45:12 +0100401 foo := "unknown";
Harald Welted86cdc62017-11-22 00:45:07 +0100402 }
403 }
404 resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
405 }
406
407 return resp;
408}
409
410/* transmit IPA CCM message */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700411private function f_ccm_tx(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
412runs on IPA_Emulation_CT {
413 var IPA_Send ipa_tx := valueof(t_IPA_Send(conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm)));
Harald Welted86cdc62017-11-22 00:45:07 +0100414 log("CCM Tx:", ccm);
415 IPA_PORT.send(ipa_tx);
416}
417
418template PDU_IPA_CCM ts_IPA_PONG := {
419 msg_type := IPAC_MSGT_PONG,
420 u := omit
421}
422
423template PDU_IPA_CCM ts_IPA_ACK := {
424 msg_type := IPAC_MSGT_ID_ACK,
425 u := omit
426}
427
Harald Welteb3414b22017-11-23 18:22:10 +0100428template PDU_IPA_CCM ts_IPA_ID_GET := {
429 msg_type := IPAC_MSGT_ID_GET,
430 u := {
431 get := {
Vadim Yanitskiy40ee56c2020-05-24 20:51:24 +0700432 { 1, IPAC_IDTAG_UNITNAME },
433 { 1, IPAC_IDTAG_UNITID }
Harald Welteb3414b22017-11-23 18:22:10 +0100434 }
435 }
436}
437
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700438template PDU_IPA_CCM tr_IPA_ID_RESP := {
439 msg_type := IPAC_MSGT_ID_RESP,
440 u := {
441 resp := {
442 { ?, IPAC_IDTAG_UNITNAME, ? },
443 { ?, IPAC_IDTAG_UNITID, ? }
444 }
445 }
446}
447
Harald Welted86cdc62017-11-22 00:45:07 +0100448/* receive IPA CCM message */
Harald Welte2d86aff2018-04-17 11:23:04 +0200449private function f_ccm_rx_client(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100450 select (ccm.msg_type) {
451 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700452 f_ccm_tx(valueof(ts_IPA_PONG), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100453 }
454 case (IPAC_MSGT_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700455 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, g_self_conn_id));
Harald Welted86cdc62017-11-22 00:45:07 +0100456 }
457 case (IPAC_MSGT_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700458 f_ccm_tx(f_ccm_make_id_resp(ccm), g_self_conn_id);
Harald Welted86cdc62017-11-22 00:45:07 +0100459 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200460 case else {
461 log("Unknown/unsupported IPA CCM message type", ccm);
462 }
463 }
464}
465
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700466private function f_ccm_rx_server(PDU_IPA_CCM ccm, IPL4asp_Types.ConnectionId conn_id)
467runs on IPA_Emulation_CT {
Harald Welte2d86aff2018-04-17 11:23:04 +0200468 select (ccm.msg_type) {
469 case (IPAC_MSGT_PING) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700470 f_ccm_tx(valueof(ts_IPA_PONG), conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200471 }
472 case (IPAC_MSGT_ID_ACK) {
473 /* the IPA server should at some point receive an ID_ACK from the client,
474 * in case of RSL/OML from nanoBTS, this is actually the first message after
475 * the TCP connection is established. Other implementations may differ.
476 * We currently ignore it completely - but actually we should make sure that
477 * one ID_ACK is received by the server at some point */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700478 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK, conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200479 }
Harald Welte3bc387f2018-02-21 12:18:46 +0100480 case (IPAC_MSGT_ID_RESP) {
481 log("IPA ID RESP: ", ccm.u.resp);
Vadim Yanitskiy11edf3c2020-05-24 22:26:54 +0700482
483 /* make sure that the response contains all fields we requested */
484 if (not match(ccm, tr_IPA_ID_RESP)) {
485 log("IPA identity response ", ccm.u.resp, " mismatch");
486 return;
487 }
488
489 /* forward to the upper layers, so they can map conn_id with unit_id */
490 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP, conn_id, ccm.u.resp));
Harald Welte2d86aff2018-04-17 11:23:04 +0200491 /* acknowledge any identity that the client may have sent */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700492 f_ccm_tx(valueof(ts_IPA_ACK), conn_id);
Harald Welte3bc387f2018-02-21 12:18:46 +0100493 }
Harald Welted86cdc62017-11-22 00:45:07 +0100494 case else {
495 log("Unknown/unsupported IPA CCM message type", ccm);
496 }
497 }
498}
499
Harald Weltec76f29f2017-11-22 12:46:46 +0100500private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
501 var ASP_IPA_Unitdata ret := {
502 streamId := ipa_rx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100503 streamIdExt := ipa_rx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100504 payload := ipa_rx.msg
505 }
506 return ret;
507}
508
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100509private function f_from_asp(IPL4asp_Types.ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
Harald Weltec82eef42017-11-24 20:40:12 +0100510 var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
511 ipa_tx.streamIdExt));
Harald Weltec76f29f2017-11-22 12:46:46 +0100512 return ret;
513}
Harald Welted86cdc62017-11-22 00:45:07 +0100514
Harald Weltedf277252018-02-20 15:49:30 +0100515#ifdef IPA_EMULATION_RSL
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100516private function f_from_rsl(IPL4asp_Types.ConnectionId connId, ASP_RSL_Unitdata rsl_tx) return IPA_Send {
Harald Welte0d846a72017-12-07 17:58:28 +0100517 var octetstring payload := enc_RSL_Message(rsl_tx.rsl);
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700518
519 /* ASP_RSL_Unitdata may (optionally) contain TCP/IP connection ID */
520 if (rsl_tx.conn_id != omit) {
521 connId := rsl_tx.conn_id;
522 }
523
524 return valueof(t_IPA_Send(connId, rsl_tx.streamId, payload));
Harald Welte0d846a72017-12-07 17:58:28 +0100525}
Harald Weltedf277252018-02-20 15:49:30 +0100526#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100527
Harald Weltec6826662019-02-06 22:26:46 +0100528#ifdef IPA_EMULATION_OML
529private function f_from_oml(IPL4asp_Types.ConnectionId connId, OML_PDU oml_tx) return IPA_Send {
530 var octetstring payload := enc_OML_PDU(oml_tx);
531 var IPA_Send ret := valueof(t_IPA_Send(connId, IPAC_PROTO_OML, payload));
532 return ret;
533}
534#endif
535
Harald Weltebdb63702017-12-09 01:15:44 +0100536/* main function to use for a client-side IPA implementation */
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100537function main_client(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
538 charstring local_host, IPL4asp_Types.PortNumber local_port,
Harald Welte2d86aff2018-04-17 11:23:04 +0200539 IPA_CCM_Parameters ccm_pars := c_IPA_default_ccm_pars,
540 boolean ccm_enabled := true) runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100541 g_mode := IPA_MODE_CLIENT;
Harald Welte2d86aff2018-04-17 11:23:04 +0200542 g_ccm_enabled := ccm_enabled;
Harald Weltee09921f2017-12-07 17:49:00 +0100543 f_connect(remote_host, remote_port, local_host, local_port, ccm_pars);
Harald Welte2d86aff2018-04-17 11:23:04 +0200544 if (g_ccm_enabled) {
545 /* we're a client: Send ID_ACK immediately after connect */
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700546 f_ccm_tx(valueof(ts_IPA_ACK), g_self_conn_id);
Harald Welte2d86aff2018-04-17 11:23:04 +0200547 }
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700548 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_self_conn_id));
Harald Welteb3414b22017-11-23 18:22:10 +0100549 ScanEvents();
550}
551
Harald Weltebdb63702017-12-09 01:15:44 +0100552/* main function to use for a server-side IPA implementation */
Harald Welte2d86aff2018-04-17 11:23:04 +0200553function main_server(charstring local_host, IPL4asp_Types.PortNumber local_port,
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200554 boolean ccm_enabled := true,
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100555 IpaInitBehavior init_behavior := IPA_INIT_SEND_IPA_ID_GET,
556 boolean server_stop_on_ipa_ev_down := true)
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200557runs on IPA_Emulation_CT {
Harald Welteb3414b22017-11-23 18:22:10 +0100558 g_mode := IPA_MODE_SERVER;
Harald Welte2d86aff2018-04-17 11:23:04 +0200559 g_ccm_enabled := ccm_enabled;
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200560 g_init_behavior := init_behavior;
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100561 g_server_stop_on_ipa_ev_down := server_stop_on_ipa_ev_down;
Harald Welteb3414b22017-11-23 18:22:10 +0100562 f_bind(local_host, local_port);
563 ScanEvents();
564}
565
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200566#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100567private function f_ctrl_to_user(octetstring msg) runs on IPA_Emulation_CT {
568 var charstring msg_ch := oct2char(msg);
569 IPA_CTRL_PORT.send(dec_CtrlMessage(msg_ch));
570}
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200571#endif
Harald Weltedf277252018-02-20 15:49:30 +0100572
573#ifdef IPA_EMULATION_GSUP
574private function f_gsup_to_user(octetstring msg) runs on IPA_Emulation_CT {
575 var GSUP_PDU gsup := dec_GSUP_PDU(msg);
576 f_gsup_postprocess_decoded(gsup);
577 IPA_GSUP_PORT.send(gsup);
578}
579#endif
580
Harald Welte7460a722018-10-10 12:28:27 +0200581#ifdef IPA_EMULATION_RSPRO
582private function f_rspro_to_user(octetstring msg) runs on IPA_Emulation_CT {
583 var RsproPDU rspro := dec_RsproPDU(msg);
584 IPA_RSPRO_PORT.send(rspro);
585}
586#endif
587
Harald Weltedf277252018-02-20 15:49:30 +0100588#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100589private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
590 var charstring msg_ch := oct2char(msg);
591 if (g_is_bsc_mgw) {
592 log("============");
593 log(msg_ch);
594 IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
595 } else {
596 IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
597 }
598}
599
Harald Welte92632e12017-11-25 02:31:20 +0100600private function f_mgcp_to_ud(octetstring payload) runs on IPA_Emulation_CT return ASP_IPA_Unitdata {
601 if (mp_ipa_mgcp_uses_osmo_ext) {
602 return valueof(t_ASP_IPA_UD(IPAC_PROTO_MGCP_OLD, payload));
603 } else {
604 return valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_MGCP));
605 }
606}
Harald Weltedf277252018-02-20 15:49:30 +0100607#endif
Harald Welte92632e12017-11-25 02:31:20 +0100608
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700609/* Resolve TCP/IP connection identifier depending on g_mode */
610private function f_ipa_conn_id() runs on IPA_Emulation_CT
611return IPL4asp_Types.ConnectionId {
612 var IPL4asp_Types.ConnectionId conn_id;
613
614 select (g_mode) {
615 case (IPA_MODE_CLIENT) { conn_id := g_self_conn_id; }
616 case (IPA_MODE_SERVER) { conn_id := g_last_conn_id; }
617 case else {
618 setverdict(fail, "Unknown mode");
619 mtc.stop;
620 }
621 }
622
623 if (conn_id == -1) { /* Just to be sure */
624 setverdict(fail, "Connection is not established");
625 mtc.stop;
626 }
627
628 return conn_id;
629}
630
Harald Weltebdb63702017-12-09 01:15:44 +0100631/* main loop function for both client and server. 'thread' of the component */
Harald Welteb3414b22017-11-23 18:22:10 +0100632private function ScanEvents() runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100633 var IPA_RecvFrom ipa_rx;
Harald Welteb3414b22017-11-23 18:22:10 +0100634 var ASP_Event asp_evt;
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100635 var Socket_API_Definitions.PortEvent port_evt;
Harald Weltedf277252018-02-20 15:49:30 +0100636 var octetstring payload;
Harald Weltedf277252018-02-20 15:49:30 +0100637 var ASP_IPA_Unitdata ipa_ud;
Harald Welte3286eb32019-08-18 19:36:10 +0200638#ifdef IPA_EMULATION_CTRL
639 var CtrlMessage ctrl_msg;
640#endif
Harald Weltedf277252018-02-20 15:49:30 +0100641#ifdef IPA_EMULATION_SCCP
642 var ASP_MTP3_TRANSFERreq mtp_req;
643#endif
644#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100645 var MgcpCommand mgcp_cmd;
646 var MgcpResponse mgcp_rsp;
Harald Weltedf277252018-02-20 15:49:30 +0100647#endif
648#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100649 var GSUP_PDU gsup_msg;
Harald Weltedf277252018-02-20 15:49:30 +0100650#endif
651#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100652 var ASP_RSL_Unitdata rsl;
Harald Weltedf277252018-02-20 15:49:30 +0100653#endif
Harald Weltec6826662019-02-06 22:26:46 +0100654#ifdef IPA_EMULATION_OML
655 var OML_PDU oml;
656#endif
Harald Welte7460a722018-10-10 12:28:27 +0200657#ifdef IPA_EMULATION_RSPRO
658 var RsproPDU rspro;
659#endif
Harald Welted86cdc62017-11-22 00:45:07 +0100660
Harald Welte3e6ad892017-12-12 14:39:46 +0100661 /* Set function for dissecting the binary */
662 var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700663 IPA_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(IPA_PORT, g_self_conn_id, vl_f, {0, 2, 3, 1, 0});
Harald Welte3e6ad892017-12-12 14:39:46 +0100664
Harald Welted86cdc62017-11-22 00:45:07 +0100665 while (true) {
666 alt {
667 /* Received IPA -> up into SCCP stack */
Harald Welte2d86aff2018-04-17 11:23:04 +0200668 [g_ccm_enabled] IPA_PORT.receive(IPA_RecvFrom:{?,IPAC_PROTO_CCM,omit,?}) -> value ipa_rx {
669 var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
670 log("CCM Rx:", ccm);
671 select (g_mode) {
672 case (IPA_MODE_CLIENT) {
673 f_ccm_rx_client(ccm);
674 }
675 case (IPA_MODE_SERVER) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700676 f_ccm_rx_server(ccm, ipa_rx.connId);
Harald Welte2d86aff2018-04-17 11:23:04 +0200677 }
678 case else {
679 setverdict(fail, "Unknown mode");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200680 mtc.stop;
Harald Welte2d86aff2018-04-17 11:23:04 +0200681 }
Harald Weltedf277252018-02-20 15:49:30 +0100682 }
Harald Welte2d86aff2018-04-17 11:23:04 +0200683 }
684 [] IPA_PORT.receive(IPA_RecvFrom:?) -> value ipa_rx {
685 select (ipa_rx.streamId) {
Harald Weltedf277252018-02-20 15:49:30 +0100686#ifdef IPA_EMULATION_SCCP
687 case (IPAC_PROTO_SCCP) {
Harald Welted86cdc62017-11-22 00:45:07 +0100688 var ASP_MTP3_TRANSFERind mtp;
689 mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
690 MTP3_SP_PORT.send(mtp);
Harald Weltedf277252018-02-20 15:49:30 +0100691 }
692#endif
693#ifdef IPA_EMULATION_MGCP
694 case (IPAC_PROTO_MGCP_OLD) {
Harald Weltec82eef42017-11-24 20:40:12 +0100695 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100696 }
697#endif
698#ifdef IPA_EMULATION_RSL
699 case (t_IpaSidRSL) {
Vadim Yanitskiyef9bcd22020-05-25 19:01:04 +0700700 rsl := valueof(ts_ASP_RSL_UD(
701 rsl := dec_RSL_Message(ipa_rx.msg),
702 sid := ipa_rx.streamId,
703 conn_id := ipa_rx.connId
704 ));
Harald Welte0d846a72017-12-07 17:58:28 +0100705 IPA_RSL_PORT.send(rsl);
Harald Weltedf277252018-02-20 15:49:30 +0100706 }
707#endif
Harald Weltec6826662019-02-06 22:26:46 +0100708#ifdef IPA_EMULATION_OML
709 case (IPAC_PROTO_OML) {
710 oml := dec_OML_PDU(ipa_rx.msg)
711 IPA_OML_PORT.send(oml);
712 }
713#endif
Harald Weltedf277252018-02-20 15:49:30 +0100714 case (IPAC_PROTO_OSMO) {
Harald Weltec82eef42017-11-24 20:40:12 +0100715 select (ipa_rx.streamIdExt) {
Harald Weltedf277252018-02-20 15:49:30 +0100716#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100717 case (IPAC_PROTO_EXT_MGCP) {
718 f_mgcp_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100719 }
720#endif
Harald Welte3286eb32019-08-18 19:36:10 +0200721#ifdef IPA_EMULATION_CTRL
Harald Weltedf277252018-02-20 15:49:30 +0100722 case (IPAC_PROTO_EXT_CTRL) {
Harald Weltea76c4bb2017-12-09 02:06:07 +0100723 f_ctrl_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100724 }
Harald Welte3286eb32019-08-18 19:36:10 +0200725#endif
Harald Weltedf277252018-02-20 15:49:30 +0100726#ifdef IPA_EMULATION_GSUP
727 case (IPAC_PROTO_EXT_GSUP) {
Harald Weltedf327232017-12-28 22:51:51 +0100728 f_gsup_to_user(ipa_rx.msg);
Harald Weltedf277252018-02-20 15:49:30 +0100729 }
730#endif
Harald Welte7460a722018-10-10 12:28:27 +0200731#ifdef IPA_EMULATION_RSPRO
732 case (IPAC_PROTO_EXT_RSPRO) {
733 f_rspro_to_user(ipa_rx.msg);
734 }
735#endif
Harald Weltedf277252018-02-20 15:49:30 +0100736 case else {
Harald Weltec82eef42017-11-24 20:40:12 +0100737 IPA_SP_PORT.send(f_to_asp(ipa_rx));
738 }
Harald Welted86cdc62017-11-22 00:45:07 +0100739 }
Harald Weltedf277252018-02-20 15:49:30 +0100740 }
741 case else {
Harald Weltec76f29f2017-11-22 12:46:46 +0100742 IPA_SP_PORT.send(f_to_asp(ipa_rx));
Harald Welted86cdc62017-11-22 00:45:07 +0100743 }
744 }
745 }
746
Harald Welteb3414b22017-11-23 18:22:10 +0100747 /* server only */
748 [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700749 g_last_conn_id := asp_evt.connOpened.connId;
750 log("Established a new IPA connection (conn_id=", g_last_conn_id, ")");
751
752 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_UP, g_last_conn_id));
Harald Welte2d86aff2018-04-17 11:23:04 +0200753 if (g_mode == IPA_MODE_SERVER and g_ccm_enabled) {
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200754 select (g_init_behavior) {
755 case (IPA_INIT_SEND_IPA_ID_GET) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700756 f_ccm_tx(valueof(ts_IPA_ID_GET), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200757 }
758 case (IPA_INIT_SEND_IPA_ID_ACK) {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700759 f_ccm_tx(valueof(ts_IPA_ACK), g_last_conn_id);
Neels Hofmeyr3bf31d22018-08-24 14:44:32 +0200760 }
761 }
Harald Welteb3414b22017-11-23 18:22:10 +0100762 }
763 }
764
765 [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
766 log("IPA: Closed");
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700767 g_self_conn_id := -1;
768 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, asp_evt.connClosed.connId));
Pau Espin Pedrol2dc137c2021-01-28 19:53:21 +0100769 if (g_mode != IPA_MODE_SERVER or g_server_stop_on_ipa_ev_down) {
770 self.stop;
771 }
Harald Welteb3414b22017-11-23 18:22:10 +0100772 }
773
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100774 [] IPA_PORT.receive(Socket_API_Definitions.PortEvent:{result:={errorCode:=ERROR_SOCKET, connId:=?, os_error_code:=?, os_error_text:=?}}) -> value port_evt {
775 log("PortEvent: ERROR_SOCKET: ", port_evt);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700776 g_self_conn_id := -1;
777 f_send_IPA_EVT(ts_ASP_IPA_EV(ASP_IPA_EVENT_DOWN, port_evt.result.connId));
Stefan Sperling830dc9d2018-02-12 21:08:28 +0100778 self.stop;
779 }
780
Harald Weltedf277252018-02-20 15:49:30 +0100781#ifdef IPA_EMULATION_SCCP
Harald Welted86cdc62017-11-22 00:45:07 +0100782 /* Received SCCP -> down into IPA */
783 [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700784 var IPA_Send ipa_tx := valueof(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_SCCP,
Harald Weltec82eef42017-11-24 20:40:12 +0100785 mtp_req.data));
Harald Welted86cdc62017-11-22 00:45:07 +0100786 IPA_PORT.send(ipa_tx);
787 }
Harald Weltedf277252018-02-20 15:49:30 +0100788#endif
Harald Weltec76f29f2017-11-22 12:46:46 +0100789
Harald Weltedf277252018-02-20 15:49:30 +0100790#ifdef IPA_EMULATION_MGCP
Harald Weltec82eef42017-11-24 20:40:12 +0100791 /* Received MGCP -> down into IPA */
792 [] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
Harald Welte92632e12017-11-25 02:31:20 +0100793 payload := char2oct(enc_MgcpCommand(mgcp_cmd));
794 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700795 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100796 }
797 [] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
Harald Welte1dd8f372017-11-25 02:25:27 +0100798 payload := char2oct(enc_MgcpResponse(mgcp_rsp));
Harald Welte92632e12017-11-25 02:31:20 +0100799 ipa_ud := f_mgcp_to_ud(payload);
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700800 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec82eef42017-11-24 20:40:12 +0100801 }
Harald Weltedf277252018-02-20 15:49:30 +0100802#endif
Harald Weltec82eef42017-11-24 20:40:12 +0100803
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200804#ifdef IPA_EMULATION_CTRL
Harald Weltea76c4bb2017-12-09 02:06:07 +0100805 [] IPA_CTRL_PORT.receive(CtrlMessage:?) -> value ctrl_msg {
806 payload := char2oct(enc_CtrlMessage(ctrl_msg));
807 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_CTRL));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700808 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltea76c4bb2017-12-09 02:06:07 +0100809 }
Pau Espin Pedrolacc51192019-06-11 15:35:19 +0200810#endif
Harald Weltea76c4bb2017-12-09 02:06:07 +0100811
Harald Weltedf277252018-02-20 15:49:30 +0100812#ifdef IPA_EMULATION_GSUP
Harald Weltedf327232017-12-28 22:51:51 +0100813 [] IPA_GSUP_PORT.receive(GSUP_PDU:?) -> value gsup_msg {
Harald Welte2f562b12018-01-24 20:52:38 +0100814 f_gsup_preprocess_encoded(gsup_msg);
Harald Weltedf327232017-12-28 22:51:51 +0100815 payload := enc_GSUP_PDU(gsup_msg);
816 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_GSUP));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700817 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltedf327232017-12-28 22:51:51 +0100818 }
Harald Weltedf277252018-02-20 15:49:30 +0100819#endif
Harald Weltedf327232017-12-28 22:51:51 +0100820
Harald Welte7460a722018-10-10 12:28:27 +0200821#ifdef IPA_EMULATION_RSPRO
822 [] IPA_RSPRO_PORT.receive(RsproPDU:?) -> value rspro {
823 payload := enc_RsproPDU(rspro);
824 ipa_ud := valueof(t_ASP_IPA_UD(IPAC_PROTO_OSMO, payload, IPAC_PROTO_EXT_RSPRO));
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700825 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Welte7460a722018-10-10 12:28:27 +0200826 }
827#endif
828
Harald Weltedf277252018-02-20 15:49:30 +0100829#ifdef IPA_EMULATION_RSL
Harald Welte0d846a72017-12-07 17:58:28 +0100830 /* Received RSL -> down into IPA */
831 [] IPA_RSL_PORT.receive(ASP_RSL_Unitdata:?) -> value rsl {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700832 IPA_PORT.send(f_from_rsl(f_ipa_conn_id(), rsl));
Harald Welte0d846a72017-12-07 17:58:28 +0100833 }
Harald Weltedf277252018-02-20 15:49:30 +0100834#endif
Harald Weltec6826662019-02-06 22:26:46 +0100835#ifdef IPA_EMULATION_OML
836 /* Received OML -> down into IPA */
837 [] IPA_OML_PORT.receive(OML_PDU:?) -> value oml {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700838 IPA_PORT.send(f_from_oml(f_ipa_conn_id(), oml));
Harald Weltec6826662019-02-06 22:26:46 +0100839 }
840 [] IPA_OML_PORT.receive(octetstring:?) -> value payload {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700841 IPA_PORT.send(t_IPA_Send(f_ipa_conn_id(), IPAC_PROTO_OML, payload));
Harald Weltec6826662019-02-06 22:26:46 +0100842 }
843#endif
Harald Welte0d846a72017-12-07 17:58:28 +0100844 /* Received MISC (OML/CTRL) -> down into IPA */
Harald Weltec76f29f2017-11-22 12:46:46 +0100845 [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
Vadim Yanitskiy6643e8d2020-05-18 21:50:12 +0700846 IPA_PORT.send(f_from_asp(f_ipa_conn_id(), ipa_ud));
Harald Weltec76f29f2017-11-22 12:46:46 +0100847 }
848
849
Harald Welted86cdc62017-11-22 00:45:07 +0100850 }
851 }
852}
853
Harald Welte2e32e432018-05-24 20:00:00 +0200854/***********************************************************************
855 * IPA Event waiter component. Wait for ASP_IPA_EVENT_ID_ACK
856 ***********************************************************************/
857
858type component IPA_EventWaiter_CT {
859 port IPA_SP_PT IPA_SP_PORT;
860}
861
Vadim Yanitskiy61564be2020-05-18 20:44:14 +0700862function waiter_main(template ASP_IPA_Event wait_for := tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK))
Harald Welte2e32e432018-05-24 20:00:00 +0200863runs on IPA_EventWaiter_CT {
864
865 alt {
866 [] IPA_SP_PORT.receive(wait_for) {
867 setverdict(pass);
868 }
869 [] IPA_SP_PORT.receive { repeat; }
870 }
871}
872
873
Harald Welted86cdc62017-11-22 00:45:07 +0100874}