blob: 1e7574b67caf1bf4494a7a178df3aca0e2aa3dbe [file] [log] [blame]
Harald Weltef9d449e2018-06-24 22:27:47 +02001/* Simple / General implementation of an External USSD Entity using OsmoHLR's GSUP Protocol
2 *
3 * The idea is that a test case can simply start an instance of this component in parallel to its
4 * normal test components. HLR_EUSE_CT will then connect via GSUP to the HLR as the specified EUSE
5 * name. Any USSD related GSUP message received will be passed to a user-provided call-back
6 * function, which will return whatever PDU to send in response back to the HLR.
7 */
8
9/* (C) 2018 by Harald Welte <laforge@gnumonks.org> */
10
11module HLR_EUSE {
12
13import from GSUP_Types all;
14import from IPA_Emulation all;
15
16import from General_Types all;
17import from Osmocom_Types all;
18import from SS_Types all;
19import from SS_Templates all;
20
21/* emulating an external USSD Entity towards OsmoHLR */
22type component HLR_EUSE_CT {
23 /* Component reference + config of underlying IPA emulation */
24 var IPA_Emulation_CT vc_IPA_EUSE;
25 var IPA_CCM_Parameters ccm_pars;
26 /* port towards the underlying IPA emulation */
27 port IPA_GSUP_PT EUSE;
28}
29
30private function f_init(charstring hlr_ip, uint16_t hlr_gsup_port, charstring name) runs on HLR_EUSE_CT {
31 var charstring id := "EUSE-" & name;
32 ccm_pars := c_IPA_default_ccm_pars;
33 ccm_pars.name := "Osmocom TTCN-3 EUSE Simulator";
34 ccm_pars.ser_nr := id;
35
36 vc_IPA_EUSE := IPA_Emulation_CT.create("IPA-" & id);
37 map(vc_IPA_EUSE:IPA_PORT, system:IPA_CODEC_PT);
38 connect(vc_IPA_EUSE:IPA_GSUP_PORT, self:EUSE);
39 vc_IPA_EUSE.start(IPA_Emulation.main_client(hlr_ip, hlr_gsup_port, "", 0, ccm_pars));
40
41 timer T := 10.0;
42 T.start;
43 alt {
44 [] EUSE.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { repeat; }
45 [] EUSE.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_ID_ACK}) { }
46 [] T.timeout {
47 setverdict(fail, "EUSE: Timeout waiting for GSUP IPA Link to come up");
48 self.stop;
49 }
50 }
51}
52
53type function f_euse_cb(GSUP_SessionState ss_state, GSUP_PDU rx_pdu) return GSUP_PDU;
54
55function f_ss_echo_continue(GSUP_SessionState ss_state, GSUP_PDU rx_pdu) return GSUP_PDU {
56 var GSUP_SessionState ss_next_state;
57 var GSUP_IeValue ss_ie;
58 var SS_FacilityInformation dec_fac, rsp_fac;
59 var octetstring ss_rsp;
60
61 f_gsup_find_ie(rx_pdu, OSMO_GSUP_SS_INFO_IE, ss_ie);
62 dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
63 log("dec_fac: ", dec_fac);
64 rsp_fac := valueof(ts_SS_USSD_FACILITY_RETURN_RESULT(dec_fac[0].invoke.invokeId.present_,
65 SS_OP_CODE_PROCESS_USS_REQ,
66 dec_fac[0].invoke.argument.uSSD_Arg.ussd_DataCodingScheme,
67 dec_fac[0].invoke.argument.uSSD_Arg.ussd_String));
68 ss_rsp := enc_SS_FacilityInformation(rsp_fac);
69 select (ss_state) {
70 case (OSMO_GSUP_SESSION_STATE_BEGIN) { ss_next_state := OSMO_GSUP_SESSION_STATE_CONTINUE; }
71 case (OSMO_GSUP_SESSION_STATE_CONTINUE) { ss_next_state := OSMO_GSUP_SESSION_STATE_END; }
72 }
73 return valueof(ts_GSUP_PROC_SS_RES(rx_pdu.ies[0].val.imsi, rx_pdu.ies[1].val.session_id,
74 ss_next_state, ss_rsp));
75}
76
77function f_ss_echo(GSUP_SessionState ss_state, GSUP_PDU rx_pdu) return GSUP_PDU {
78 var GSUP_IeValue ss_ie;
79 var SS_FacilityInformation dec_fac, rsp_fac;
80 var octetstring ss_rsp;
81
82 f_gsup_find_ie(rx_pdu, OSMO_GSUP_SS_INFO_IE, ss_ie);
83 dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
84 log("dec_fac: ", dec_fac);
85 rsp_fac := valueof(ts_SS_USSD_FACILITY_RETURN_RESULT(dec_fac[0].invoke.invokeId.present_,
86 SS_OP_CODE_PROCESS_USS_REQ,
87 dec_fac[0].invoke.argument.uSSD_Arg.ussd_DataCodingScheme,
88 dec_fac[0].invoke.argument.uSSD_Arg.ussd_String));
89 ss_rsp := enc_SS_FacilityInformation(rsp_fac);
90 return valueof(ts_GSUP_PROC_SS_RES(rx_pdu.ies[0].val.imsi, rx_pdu.ies[1].val.session_id,
91 OSMO_GSUP_SESSION_STATE_END, ss_rsp));
92}
93
94/* main function for handling mobile-originated USSD via GSUP */
95function f_main_mo(charstring hlr_ip, uint16_t hlr_gsup_port, charstring name, f_euse_cb cb_fn)
96runs on HLR_EUSE_CT {
97 var GSUP_PDU rx_pdu, tx_pdu;
98
99 f_init(hlr_ip, hlr_gsup_port, name);
100
101 while (true) {
102 alt {
103 [] EUSE.receive(tr_GSUP_PROC_SS_REQ(?, ?, OSMO_GSUP_SESSION_STATE_BEGIN)) -> value rx_pdu {
104 EUSE.send(cb_fn.apply(OSMO_GSUP_SESSION_STATE_BEGIN, rx_pdu));
105 }
106 [] EUSE.receive(tr_GSUP_PROC_SS_REQ(?, ?, OSMO_GSUP_SESSION_STATE_CONTINUE)) -> value rx_pdu {
107 EUSE.send(cb_fn.apply(OSMO_GSUP_SESSION_STATE_CONTINUE, rx_pdu));
108 }
109
110 [] EUSE.receive(tr_GSUP_PROC_SS_REQ(?, ?, OSMO_GSUP_SESSION_STATE_END)) -> value rx_pdu {
111 EUSE.send(cb_fn.apply(OSMO_GSUP_SESSION_STATE_END, rx_pdu));
112 }
113
114
115 [] EUSE.receive {
116 setverdict(fail, "EUSE: Unexpected Rx from HLR");
117 self.stop;
118 }
119 }
120 }
121}
122
123
124}