aboutsummaryrefslogtreecommitdiffstats
path: root/hlr/HLR_EUSE.ttcn
blob: 170bcd22a7baa84409a50eb6ced7c1a30d4b8c8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* 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 GSUP_Templates 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(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) { repeat; }
	[] EUSE.receive(tr_ASP_IPA_EV(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;
			}
		}
	}
}


}