blob: 3b8d931f696450bd5872846ccf215e9e1735581c [file] [log] [blame]
Harald Welted86cdc62017-11-22 00:45:07 +01001module IPA_Emulation {
2
3import from IPA_Types all;
4import from IPA_CodecPort all;
5import from IPA_CodecPort_CtrlFunct all;
6import from IPL4asp_Types all;
7import from MTP3asp_Types all;
8import from MTP3asp_PortType all;
9
Harald Weltec82eef42017-11-24 20:40:12 +010010import from MGCP_Types all;
11
Harald Welted86cdc62017-11-22 00:45:07 +010012/*
13modulepar {
14}
15*/
16
Harald Welteb3414b22017-11-23 18:22:10 +010017type enumerated IpaMode {
18 IPA_MODE_CLIENT,
19 IPA_MODE_SERVER
20}
21
Harald Weltec76f29f2017-11-22 12:46:46 +010022type record ASP_IPA_Unitdata {
23 IpaStreamId streamId,
Harald Weltec82eef42017-11-24 20:40:12 +010024 IpaExtStreamId streamIdExt optional,
Harald Weltec76f29f2017-11-22 12:46:46 +010025 octetstring payload
26}
27
28type port IPA_SP_PT message {
29 inout ASP_IPA_Unitdata;
30} with { extension "internal" }
31
Harald Weltec82eef42017-11-24 20:40:12 +010032type port IPA_MGCP_PT message {
33 inout MgcpCommand, MgcpResponse;
34} with { extension "internal" }
35
Harald Welted86cdc62017-11-22 00:45:07 +010036type component IPA_Emulation_CT {
37 /* down-facing port to IPA codec port */
38 port IPA_CODEC_PT IPA_PORT;
39 /* up-facing port to SCCP */
40 port MTP3asp_SP_PT MTP3_SP_PORT;
Harald Weltec82eef42017-11-24 20:40:12 +010041 /* up-facing port for MGCP */
42 port IPA_MGCP_PT IPA_MGCP_PORT;
Harald Weltec76f29f2017-11-22 12:46:46 +010043 /* up-facing port for other streams */
44 port IPA_SP_PT IPA_SP_PORT;
Harald Welted86cdc62017-11-22 00:45:07 +010045
46 var boolean g_initialized := false;
47 var ConnectionId g_ipa_conn_id := -1;
Harald Weltec82eef42017-11-24 20:40:12 +010048 /* Are we a BSC/MGW (truel) or MSC (false) */
49 var boolean g_is_bsc_mgw;
Harald Welteb3414b22017-11-23 18:22:10 +010050
51 var IpaMode g_mode;
Harald Welted86cdc62017-11-22 00:45:07 +010052}
53
54function f_connect(charstring remote_host, PortNumber remote_port,
55 charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
56 var Result res;
57 res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
58 local_host, local_port, 0, { tcp:={} });
59 g_ipa_conn_id := res.connId;
Harald Weltec82eef42017-11-24 20:40:12 +010060 g_is_bsc_mgw := true;
Harald Welted86cdc62017-11-22 00:45:07 +010061}
62
Harald Welteb3414b22017-11-23 18:22:10 +010063function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
64 var Result res;
65 res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
66 local_host, local_port, { tcp:={} });
67 g_ipa_conn_id := res.connId;
Harald Weltec82eef42017-11-24 20:40:12 +010068 g_is_bsc_mgw := false;
Harald Welteb3414b22017-11-23 18:22:10 +010069}
70
Harald Welted86cdc62017-11-22 00:45:07 +010071template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
72 sio := { '10'B, '00'B, '0011'B },
73 opc := opc,
74 dpc := 0,
75 sls := 0,
76 data := data
77}
78
79
80private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
81 len := 0, /* overwritten by codec */
82 tag := tag,
83 data := payload
84}
85
86/* build IPA CCM ID RESP response from IPA CCM GET */
87private function f_ccm_make_id_resp(PDU_IPA_CCM get) return PDU_IPA_CCM {
88 var integer i;
89 var PDU_IPA_CCM resp := {
90 msg_type := IPAC_MSGT_ID_RESP,
91 u := {
92 resp := {}
93 }
94 }
95
96 for (i := 0; i < sizeof(get.u.get); i := i + 1) {
97 var IpaCcmIdTag tag := get.u.get[i].tag;
98 var charstring foo;
99 select (tag) {
100 case (IPAC_IDTAG_UNIT) {
101 foo := "0/1/2";
102 }
103 case (IPAC_IDTAG_UNITNAME) {
104 foo := "mahlzeit";
105 }
106 case else {
107 foo := "foo";
108 }
109 }
110 resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
111 }
112
113 return resp;
114}
115
116/* transmit IPA CCM message */
117private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
Harald Weltec82eef42017-11-24 20:40:12 +0100118 var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_CCM, enc_PDU_IPA_CCM(ccm)));
Harald Welted86cdc62017-11-22 00:45:07 +0100119 log("CCM Tx:", ccm);
120 IPA_PORT.send(ipa_tx);
121}
122
123template PDU_IPA_CCM ts_IPA_PONG := {
124 msg_type := IPAC_MSGT_PONG,
125 u := omit
126}
127
128template PDU_IPA_CCM ts_IPA_ACK := {
129 msg_type := IPAC_MSGT_ID_ACK,
130 u := omit
131}
132
Harald Welteb3414b22017-11-23 18:22:10 +0100133template PDU_IPA_CCM ts_IPA_ID_GET := {
134 msg_type := IPAC_MSGT_ID_GET,
135 u := {
136 get := {
137 { 1, IPAC_IDTAG_UNITNAME }
138 }
139 }
140}
141
Harald Welted86cdc62017-11-22 00:45:07 +0100142/* receive IPA CCM message */
143private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
144 select (ccm.msg_type) {
145 case (IPAC_MSGT_PING) {
146 f_ccm_tx(valueof(ts_IPA_PONG));
147 }
148 case (IPAC_MSGT_ID_ACK) {
149 f_ccm_tx(valueof(ts_IPA_ACK));
150 }
151 case (IPAC_MSGT_ID_GET) {
152 f_ccm_tx(f_ccm_make_id_resp(ccm));
153 }
154 case else {
155 log("Unknown/unsupported IPA CCM message type", ccm);
156 }
157 }
158}
159
Harald Weltec76f29f2017-11-22 12:46:46 +0100160private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
161 var ASP_IPA_Unitdata ret := {
162 streamId := ipa_rx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100163 streamIdExt := ipa_rx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100164 payload := ipa_rx.msg
165 }
166 return ret;
167}
168
169private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
Harald Weltec82eef42017-11-24 20:40:12 +0100170 var IPA_Send ret := valueof(t_IPA_Send(connId, ipa_tx.streamId, ipa_tx.payload,
171 ipa_tx.streamIdExt));
Harald Weltec76f29f2017-11-22 12:46:46 +0100172 return ret;
173}
Harald Welted86cdc62017-11-22 00:45:07 +0100174
Harald Welteb3414b22017-11-23 18:22:10 +0100175function main_client(charstring remote_host, PortNumber remote_port,
176 charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
177 g_mode := IPA_MODE_CLIENT;
178 f_connect(remote_host, remote_port, local_host, local_port);
179 ScanEvents();
180}
181
182function main_server(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
183 g_mode := IPA_MODE_SERVER;
184 f_bind(local_host, local_port);
185 ScanEvents();
186}
187
Harald Weltec82eef42017-11-24 20:40:12 +0100188private function f_mgcp_to_user(octetstring msg) runs on IPA_Emulation_CT {
189 var charstring msg_ch := oct2char(msg);
190 if (g_is_bsc_mgw) {
191 log("============");
192 log(msg_ch);
193 IPA_MGCP_PORT.send(dec_MgcpCommand(msg_ch));
194 } else {
195 IPA_MGCP_PORT.send(dec_MgcpResponse(msg_ch));
196 }
197}
198
Harald Welteb3414b22017-11-23 18:22:10 +0100199private function ScanEvents() runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100200 var IPA_RecvFrom ipa_rx;
Harald Weltec76f29f2017-11-22 12:46:46 +0100201 var ASP_IPA_Unitdata ipa_ud;
Harald Welted86cdc62017-11-22 00:45:07 +0100202 var ASP_MTP3_TRANSFERreq mtp_req;
Harald Welteb3414b22017-11-23 18:22:10 +0100203 var ASP_Event asp_evt;
Harald Weltec82eef42017-11-24 20:40:12 +0100204 var MgcpCommand mgcp_cmd;
205 var MgcpResponse mgcp_rsp;
Harald Welted86cdc62017-11-22 00:45:07 +0100206
207 while (true) {
208 alt {
209 /* Received IPA -> up into SCCP stack */
210 [] IPA_PORT.receive(IPA_RecvFrom: ?) -> value ipa_rx {
211 select (ipa_rx.streamId) {
212 case (IPAC_PROTO_CCM) {
213 var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
214 log("CCM Rx:", ccm);
215 f_ccm_rx(ccm);
Harald Weltec82eef42017-11-24 20:40:12 +0100216 } case (IPAC_PROTO_SCCP) {
Harald Welted86cdc62017-11-22 00:45:07 +0100217 var ASP_MTP3_TRANSFERind mtp;
218 mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
219 MTP3_SP_PORT.send(mtp);
Harald Weltec82eef42017-11-24 20:40:12 +0100220 } case (IPAC_PROTO_MGCP_OLD) {
221 f_mgcp_to_user(ipa_rx.msg);
222 } case (IPAC_PROTO_OSMO) {
223 select (ipa_rx.streamIdExt) {
224 case (IPAC_PROTO_EXT_MGCP) {
225 f_mgcp_to_user(ipa_rx.msg);
226 } case else {
227 IPA_SP_PORT.send(f_to_asp(ipa_rx));
228 }
Harald Welted86cdc62017-11-22 00:45:07 +0100229 }
Harald Weltec82eef42017-11-24 20:40:12 +0100230 } case else {
Harald Weltec76f29f2017-11-22 12:46:46 +0100231 IPA_SP_PORT.send(f_to_asp(ipa_rx));
Harald Welted86cdc62017-11-22 00:45:07 +0100232 }
233 }
234 }
235
Harald Welteb3414b22017-11-23 18:22:10 +0100236 /* server only */
237 [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
238 log("IPA: Connected");
239 g_ipa_conn_id := asp_evt.connOpened.connId;
240 if (g_mode == IPA_MODE_SERVER) {
241 f_ccm_tx(valueof(ts_IPA_ID_GET));
242 }
243 }
244
245 [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
246 log("IPA: Closed");
247 g_ipa_conn_id := -1;
248 self.stop;
249 }
250
Harald Welted86cdc62017-11-22 00:45:07 +0100251 /* Received SCCP -> down into IPA */
252 [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
Harald Weltec82eef42017-11-24 20:40:12 +0100253 var IPA_Send ipa_tx := valueof(t_IPA_Send(g_ipa_conn_id, IPAC_PROTO_SCCP,
254 mtp_req.data));
Harald Welted86cdc62017-11-22 00:45:07 +0100255 IPA_PORT.send(ipa_tx);
256 }
Harald Weltec76f29f2017-11-22 12:46:46 +0100257
Harald Weltec82eef42017-11-24 20:40:12 +0100258 /* Received MGCP -> down into IPA */
259 [] IPA_MGCP_PORT.receive(MgcpCommand:?) -> value mgcp_cmd {
260 ipa_ud := {
261 streamId := IPAC_PROTO_OSMO,
262 streamIdExt := IPAC_PROTO_EXT_MGCP,
263 payload := char2oct(enc_MgcpCommand(mgcp_cmd))
264 }
265 IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
266 }
267 [] IPA_MGCP_PORT.receive(MgcpResponse:?) -> value mgcp_rsp {
268 ipa_ud := {
269 streamId := IPAC_PROTO_OSMO,
270 streamIdExt := IPAC_PROTO_EXT_MGCP,
271 payload := char2oct(enc_MgcpResponse(mgcp_rsp))
272 }
273 IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
274 }
275
276
277 /* Received MISC (RSL/OML/CTRL) -> down into IPA */
Harald Weltec76f29f2017-11-22 12:46:46 +0100278 [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
279 IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
280 }
281
282
Harald Welted86cdc62017-11-22 00:45:07 +0100283 }
284 }
285}
286
287}