129 lines
4.3 KiB
Plaintext
129 lines
4.3 KiB
Plaintext
/* Simple / General implementation of an External USSD Entity using OsmoHLR's GSUP Protocol
|
|
*
|
|
* The idea is that a test case can simply start an instance of this component in parallel to its
|
|
* normal test components. HLR_EUSE_CT will then connect via GSUP to the HLR as the specified EUSE
|
|
* name. Any USSD related GSUP message received will be passed to a user-provided call-back
|
|
* function, which will return whatever PDU to send in response back to the HLR.
|
|
*/
|
|
|
|
|
|
/* (C) 2018 Harald Welte <laforge@gnumonks.org>
|
|
* All rights reserved.
|
|
*
|
|
* Released under the terms of GNU General Public License, Version 2 or
|
|
* (at your option) any later version.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
module HLR_EUSE {
|
|
|
|
import from GSUP_Types all;
|
|
import from IPA_Emulation all;
|
|
|
|
import from General_Types all;
|
|
import from Osmocom_Types all;
|
|
import from SS_Types all;
|
|
import from SS_Templates all;
|
|
|
|
/* emulating an external USSD Entity towards OsmoHLR */
|
|
type component HLR_EUSE_CT {
|
|
/* Component reference + config of underlying IPA emulation */
|
|
var IPA_Emulation_CT vc_IPA_EUSE;
|
|
var IPA_CCM_Parameters ccm_pars;
|
|
/* port towards the underlying IPA emulation */
|
|
port IPA_GSUP_PT EUSE;
|
|
}
|
|
|
|
private function f_init(charstring hlr_ip, uint16_t hlr_gsup_port, charstring name) runs on HLR_EUSE_CT {
|
|
var charstring id := "EUSE-" & name;
|
|
ccm_pars := c_IPA_default_ccm_pars;
|
|
ccm_pars.name := "Osmocom TTCN-3 EUSE Simulator";
|
|
ccm_pars.ser_nr := id;
|
|
|
|
vc_IPA_EUSE := IPA_Emulation_CT.create("IPA-" & id);
|
|
map(vc_IPA_EUSE:IPA_PORT, system:IPA_CODEC_PT);
|
|
connect(vc_IPA_EUSE:IPA_GSUP_PORT, self:EUSE);
|
|
vc_IPA_EUSE.start(IPA_Emulation.main_client(hlr_ip, hlr_gsup_port, "", 0, ccm_pars));
|
|
|
|
timer T := 10.0;
|
|
T.start;
|
|
alt {
|
|
[] EUSE.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { repeat; }
|
|
[] EUSE.receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_ID_ACK}) { }
|
|
[] T.timeout {
|
|
setverdict(fail, "EUSE: Timeout waiting for GSUP IPA Link to come up");
|
|
self.stop;
|
|
}
|
|
}
|
|
}
|
|
|
|
type function f_euse_cb(GSUP_PDU rx_pdu) return GSUP_PDU;
|
|
|
|
function f_ss_echo_continue(GSUP_PDU rx_pdu) return GSUP_PDU {
|
|
var GSUP_SessionState ss_next_state;
|
|
var GSUP_IeValue ss_ie, state_ie;
|
|
var SS_FacilityInformation dec_fac, rsp_fac;
|
|
var octetstring ss_rsp;
|
|
|
|
f_gsup_find_ie(rx_pdu, OSMO_GSUP_SESSION_STATE_IE, state_ie);
|
|
var GSUP_SessionState ss_state := state_ie.session_state;
|
|
|
|
f_gsup_find_ie(rx_pdu, OSMO_GSUP_SS_INFO_IE, ss_ie);
|
|
dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
|
|
log("dec_fac: ", dec_fac);
|
|
rsp_fac := valueof(ts_SS_USSD_FACILITY_RETURN_RESULT(dec_fac[0].invoke.invokeId.present_,
|
|
SS_OP_CODE_PROCESS_USS_REQ,
|
|
dec_fac[0].invoke.argument.uSSD_Arg.ussd_DataCodingScheme,
|
|
dec_fac[0].invoke.argument.uSSD_Arg.ussd_String));
|
|
ss_rsp := enc_SS_FacilityInformation(rsp_fac);
|
|
select (ss_state) {
|
|
case (OSMO_GSUP_SESSION_STATE_BEGIN) { ss_next_state := OSMO_GSUP_SESSION_STATE_CONTINUE; }
|
|
case (OSMO_GSUP_SESSION_STATE_CONTINUE) { ss_next_state := OSMO_GSUP_SESSION_STATE_END; }
|
|
}
|
|
return valueof(ts_GSUP_PROC_SS_RES(rx_pdu.ies[0].val.imsi, rx_pdu.ies[1].val.session_id,
|
|
ss_next_state, ss_rsp));
|
|
}
|
|
|
|
function f_ss_echo(GSUP_PDU rx_pdu) return GSUP_PDU {
|
|
var GSUP_IeValue ss_ie;
|
|
var SS_FacilityInformation dec_fac, rsp_fac;
|
|
var octetstring ss_rsp;
|
|
|
|
f_gsup_find_ie(rx_pdu, OSMO_GSUP_SS_INFO_IE, ss_ie);
|
|
dec_fac := dec_SS_FacilityInformation(ss_ie.ss_info);
|
|
log("dec_fac: ", dec_fac);
|
|
rsp_fac := valueof(ts_SS_USSD_FACILITY_RETURN_RESULT(dec_fac[0].invoke.invokeId.present_,
|
|
SS_OP_CODE_PROCESS_USS_REQ,
|
|
dec_fac[0].invoke.argument.uSSD_Arg.ussd_DataCodingScheme,
|
|
dec_fac[0].invoke.argument.uSSD_Arg.ussd_String));
|
|
ss_rsp := enc_SS_FacilityInformation(rsp_fac);
|
|
return valueof(ts_GSUP_PROC_SS_RES(rx_pdu.ies[0].val.imsi, rx_pdu.ies[1].val.session_id,
|
|
OSMO_GSUP_SESSION_STATE_END, ss_rsp));
|
|
}
|
|
|
|
/* main function for handling mobile-originated USSD via GSUP */
|
|
function f_main_mo(charstring hlr_ip, uint16_t hlr_gsup_port, charstring name, f_euse_cb cb_fn)
|
|
runs on HLR_EUSE_CT {
|
|
var GSUP_PDU rx_pdu, tx_pdu;
|
|
|
|
f_init(hlr_ip, hlr_gsup_port, name);
|
|
|
|
while (true) {
|
|
alt {
|
|
[] EUSE.receive(tr_GSUP_PROC_SS_REQ(?, ?, ?)) -> value rx_pdu {
|
|
EUSE.send(cb_fn.apply(rx_pdu));
|
|
}
|
|
|
|
|
|
[] EUSE.receive {
|
|
setverdict(fail, "EUSE: Unexpected Rx from HLR");
|
|
self.stop;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|