blob: 57edb0080b266bedf81e9a2762d40b1493dd5b1b [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
10/*
11modulepar {
12}
13*/
14
Harald Welteb3414b22017-11-23 18:22:10 +010015type enumerated IpaMode {
16 IPA_MODE_CLIENT,
17 IPA_MODE_SERVER
18}
19
Harald Weltec76f29f2017-11-22 12:46:46 +010020type record ASP_IPA_Unitdata {
21 IpaStreamId streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +010022 IpaStreamIdExt streamIdExt optional,
Harald Weltec76f29f2017-11-22 12:46:46 +010023 octetstring payload
24}
25
26type port IPA_SP_PT message {
27 inout ASP_IPA_Unitdata;
28} with { extension "internal" }
29
Harald Welted86cdc62017-11-22 00:45:07 +010030type component IPA_Emulation_CT {
31 /* down-facing port to IPA codec port */
32 port IPA_CODEC_PT IPA_PORT;
33 /* up-facing port to SCCP */
34 port MTP3asp_SP_PT MTP3_SP_PORT;
Harald Weltec76f29f2017-11-22 12:46:46 +010035 /* up-facing port for other streams */
36 port IPA_SP_PT IPA_SP_PORT;
Harald Welted86cdc62017-11-22 00:45:07 +010037
38 var boolean g_initialized := false;
39 var ConnectionId g_ipa_conn_id := -1;
Harald Welteb3414b22017-11-23 18:22:10 +010040
41 var IpaMode g_mode;
Harald Welted86cdc62017-11-22 00:45:07 +010042}
43
44function f_connect(charstring remote_host, PortNumber remote_port,
45 charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
46 var Result res;
47 res := IPA_CodecPort_CtrlFunct.f_IPL4_connect(IPA_PORT, remote_host, remote_port,
48 local_host, local_port, 0, { tcp:={} });
49 g_ipa_conn_id := res.connId;
50}
51
Harald Welteb3414b22017-11-23 18:22:10 +010052function f_bind(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
53 var Result res;
54 res := IPA_CodecPort_CtrlFunct.f_IPL4_listen(IPA_PORT,
55 local_host, local_port, { tcp:={} });
56 g_ipa_conn_id := res.connId;
57}
58
Harald Welted86cdc62017-11-22 00:45:07 +010059template ASP_MTP3_TRANSFERind ts_MTP3_XFER_ind(integer opc, octetstring data) := {
60 sio := { '10'B, '00'B, '0011'B },
61 opc := opc,
62 dpc := 0,
63 sls := 0,
64 data := data
65}
66
67
68private template IpaCcmRespPart t_IdRespPart(IpaCcmIdTag tag, charstring payload) := {
69 len := 0, /* overwritten by codec */
70 tag := tag,
71 data := payload
72}
73
74/* build IPA CCM ID RESP response from IPA CCM GET */
75private function f_ccm_make_id_resp(PDU_IPA_CCM get) return PDU_IPA_CCM {
76 var integer i;
77 var PDU_IPA_CCM resp := {
78 msg_type := IPAC_MSGT_ID_RESP,
79 u := {
80 resp := {}
81 }
82 }
83
84 for (i := 0; i < sizeof(get.u.get); i := i + 1) {
85 var IpaCcmIdTag tag := get.u.get[i].tag;
86 var charstring foo;
87 select (tag) {
88 case (IPAC_IDTAG_UNIT) {
89 foo := "0/1/2";
90 }
91 case (IPAC_IDTAG_UNITNAME) {
92 foo := "mahlzeit";
93 }
94 case else {
95 foo := "foo";
96 }
97 }
98 resp.u.resp[sizeof(resp.u.resp)] := valueof(t_IdRespPart(tag, foo));
99 }
100
101 return resp;
102}
103
104/* transmit IPA CCM message */
105private function f_ccm_tx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
106 var IPA_Send ipa_tx := {
107 connId := g_ipa_conn_id,
108 streamId := IPAC_PROTO_CCM,
Harald Welte2a8f8472017-11-23 21:11:34 +0100109 streamIdExt := omit,
Harald Welted86cdc62017-11-22 00:45:07 +0100110 msg := enc_PDU_IPA_CCM(ccm)
111 }
112 log("CCM Tx:", ccm);
113 IPA_PORT.send(ipa_tx);
114}
115
116template PDU_IPA_CCM ts_IPA_PONG := {
117 msg_type := IPAC_MSGT_PONG,
118 u := omit
119}
120
121template PDU_IPA_CCM ts_IPA_ACK := {
122 msg_type := IPAC_MSGT_ID_ACK,
123 u := omit
124}
125
Harald Welteb3414b22017-11-23 18:22:10 +0100126template PDU_IPA_CCM ts_IPA_ID_GET := {
127 msg_type := IPAC_MSGT_ID_GET,
128 u := {
129 get := {
130 { 1, IPAC_IDTAG_UNITNAME }
131 }
132 }
133}
134
Harald Welted86cdc62017-11-22 00:45:07 +0100135/* receive IPA CCM message */
136private function f_ccm_rx(PDU_IPA_CCM ccm) runs on IPA_Emulation_CT {
137 select (ccm.msg_type) {
138 case (IPAC_MSGT_PING) {
139 f_ccm_tx(valueof(ts_IPA_PONG));
140 }
141 case (IPAC_MSGT_ID_ACK) {
142 f_ccm_tx(valueof(ts_IPA_ACK));
143 }
144 case (IPAC_MSGT_ID_GET) {
145 f_ccm_tx(f_ccm_make_id_resp(ccm));
146 }
147 case else {
148 log("Unknown/unsupported IPA CCM message type", ccm);
149 }
150 }
151}
152
Harald Weltec76f29f2017-11-22 12:46:46 +0100153private function f_to_asp(IPA_RecvFrom ipa_rx) return ASP_IPA_Unitdata {
154 var ASP_IPA_Unitdata ret := {
155 streamId := ipa_rx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100156 streamIdExt := ipa_rx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100157 payload := ipa_rx.msg
158 }
159 return ret;
160}
161
162private function f_from_asp(ConnectionId connId, ASP_IPA_Unitdata ipa_tx) return IPA_Send {
163 var IPA_Send ret := {
164 connId := connId,
165 streamId := ipa_tx.streamId,
Harald Welte2a8f8472017-11-23 21:11:34 +0100166 streamIdExt := ipa_tx.streamIdExt,
Harald Weltec76f29f2017-11-22 12:46:46 +0100167 msg := ipa_tx.payload
168 }
169 return ret;
170}
Harald Welted86cdc62017-11-22 00:45:07 +0100171
Harald Welteb3414b22017-11-23 18:22:10 +0100172function main_client(charstring remote_host, PortNumber remote_port,
173 charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
174 g_mode := IPA_MODE_CLIENT;
175 f_connect(remote_host, remote_port, local_host, local_port);
176 ScanEvents();
177}
178
179function main_server(charstring local_host, PortNumber local_port) runs on IPA_Emulation_CT {
180 g_mode := IPA_MODE_SERVER;
181 f_bind(local_host, local_port);
182 ScanEvents();
183}
184
185private function ScanEvents() runs on IPA_Emulation_CT {
Harald Welted86cdc62017-11-22 00:45:07 +0100186 var IPA_RecvFrom ipa_rx;
Harald Weltec76f29f2017-11-22 12:46:46 +0100187 var ASP_IPA_Unitdata ipa_ud;
Harald Welted86cdc62017-11-22 00:45:07 +0100188 var ASP_MTP3_TRANSFERreq mtp_req;
Harald Welteb3414b22017-11-23 18:22:10 +0100189 var ASP_Event asp_evt;
Harald Welted86cdc62017-11-22 00:45:07 +0100190
191 while (true) {
192 alt {
193 /* Received IPA -> up into SCCP stack */
194 [] IPA_PORT.receive(IPA_RecvFrom: ?) -> value ipa_rx {
195 select (ipa_rx.streamId) {
196 case (IPAC_PROTO_CCM) {
197 var PDU_IPA_CCM ccm := dec_PDU_IPA_CCM(ipa_rx.msg);
198 log("CCM Rx:", ccm);
199 f_ccm_rx(ccm);
200 }
201 case (IPAC_PROTO_SCCP) {
202 var ASP_MTP3_TRANSFERind mtp;
203 mtp := valueof(ts_MTP3_XFER_ind(0, ipa_rx.msg));
204 MTP3_SP_PORT.send(mtp);
205 }
206 case else {
Harald Weltec76f29f2017-11-22 12:46:46 +0100207 IPA_SP_PORT.send(f_to_asp(ipa_rx));
Harald Welted86cdc62017-11-22 00:45:07 +0100208 }
209 }
210 }
211
Harald Welteb3414b22017-11-23 18:22:10 +0100212 /* server only */
213 [] IPA_PORT.receive(ASP_Event:{connOpened:=?}) -> value asp_evt {
214 log("IPA: Connected");
215 g_ipa_conn_id := asp_evt.connOpened.connId;
216 if (g_mode == IPA_MODE_SERVER) {
217 f_ccm_tx(valueof(ts_IPA_ID_GET));
218 }
219 }
220
221 [] IPA_PORT.receive(ASP_Event:{connClosed:=?}) -> value asp_evt {
222 log("IPA: Closed");
223 g_ipa_conn_id := -1;
224 self.stop;
225 }
226
Harald Welted86cdc62017-11-22 00:45:07 +0100227 /* Received SCCP -> down into IPA */
228 [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq: ?) -> value mtp_req {
229 var IPA_Send ipa_tx := {
230 connId := g_ipa_conn_id,
231 streamId := IPAC_PROTO_SCCP,
232 msg := mtp_req.data
233 }
234 IPA_PORT.send(ipa_tx);
235 }
Harald Weltec76f29f2017-11-22 12:46:46 +0100236
237 /* Received MISC (RSL/OML/CTRL/MGCP) -> down into IPA */
238 [] IPA_SP_PORT.receive(ASP_IPA_Unitdata: ?) -> value ipa_ud {
239 IPA_PORT.send(f_from_asp(g_ipa_conn_id, ipa_ud));
240 }
241
242
Harald Welted86cdc62017-11-22 00:45:07 +0100243 }
244 }
245}
246
247}