module BSC_ConnectionHandler {

import from General_Types all;
import from Osmocom_Types all;
import from GSM_Types all;
import from SCCPasp_Types all;
import from BSSAP_Types all;
import from BSSMAP_Emulation all;
import from BSSMAP_Templates all;

import from GSUP_Types all;
import from GSUP_Emulation all;

import from MNCC_Types all;
import from MNCC_Emulation all;

import from MobileL3_Types all;
import from MobileL3_CommonIE_Types all;
import from MobileL3_MM_Types all;
import from L3_Templates all;

/* this component represents a single subscriber connection */
type component BSC_ConnHdlr extends BSSAP_ConnHdlr, MNCC_ConnHdlr, GSUP_ConnHdlr {
	var BSC_ConnHdlrPars g_pars;
}

type record BSC_ConnHdlrPars {
	SCCP_PAR_Address sccp_addr_own,
	SCCP_PAR_Address sccp_addr_peer,
	BSSMAP_IE_CellIdentifier cell_id,
	hexstring imei,
	hexstring imsi,
	hexstring msisdn,
	OCT4 tmsi optional,
	BSSMAP_IE_ClassmarkInformationType2 cm2,
	BSSMAP_IE_ClassmarkInformationType3 cm3 optional
};


/* Callback function from general BSSMAP_Emulation whenever a connectionless
 * BSSMAP message arrives. Canreturn a PDU_BSSAPthat should be sent in return */
private function BscUnitdataCallback(PDU_BSSAP bssap)
runs on BSSMAP_Emulation_CT return template PDU_BSSAP {
	var template PDU_BSSAP resp := omit;

	log("BSSMAP_BscUnitdataCallback");
	/* answer all RESET with RESET ACK */
	if (match(bssap, tr_BSSMAP_Reset)){
		log("BSSMAP_BscUnitdataCallback: Responding to RESET with RESET-ACK");
		resp := ts_BSSMAP_ResetAck;
	}

	/* FIXME: Handle paging, etc. */
	return resp;
}

const BssmapOps BSC_BssmapOps := {
	/* Create call-back for inbound connections from MSC (hand-over) */
	create_cb := refers(BSSMAP_Emulation.ExpectedCreateCallback),
	unitdata_cb := refers(BscUnitdataCallback),
	decode_dtap := true,
	role_ms := true
}


private function MnccUnitdataCallback(MNCC_PDU mncc)
runs on MNCC_Emulation_CT return template MNCC_PDU {
	log("Ignoring MNCC", mncc);
	return omit;
}

const MnccOps BCC_MnccOps := {
	create_cb := refers(MNCC_Emulation.ExpectedCreateCallback),
	unitdata_cb := refers(MnccUnitdataCallback)
}



template BSSAP_Conn_Req ts_BSSAP_Conn_Req(SCCP_PAR_Address peer, SCCP_PAR_Address own, PDU_BSSAP bssap) := {
	addr_peer := peer,
	addr_own := own,
	bssap := bssap
};

/* Encode 'l3' and ask BSSMAP_Emulation to create new connection with COMPL L3 INFO */
function f_bssap_compl_l3(PDU_ML3_MS_NW l3)
runs on BSC_ConnHdlr {
	log("Sending COMPL L3: ", l3);
	var octetstring l3_enc := enc_PDU_ML3_MS_NW(l3);
	BSSAP.send(ts_BSSAP_Conn_Req(g_pars.sccp_addr_peer, g_pars.sccp_addr_own,
				     valueof(ts_BSSMAP_ComplL3(g_pars.cell_id, l3_enc))));
	alt {
	[] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_CONF_IND) {}
	[] BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND) {
			setverdict(fail, "DISC.ind from SCCP");
			self.stop;
		}
	}
}

/* helper function to fully establish a dedicated channel */
function f_establish_fully(MobileIdentityLV mi, boolean expect_auth)
runs on BSC_ConnHdlr {
	var PDU_ML3_MS_NW l3_info := valueof(ts_CM_SERV_REQ(CM_TYPE_MO_CALL, mi));
	var PDU_DTAP_MT dtap_mt;

	/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
	f_bssap_compl_l3(l3_info);

	if (expect_auth) {
		/* FIXME */
	}
	BSSAP.receive(tr_PDU_DTAP_MT(tr_CM_SERV_ACC));
}

/* build a PDU_ML3_MS_NW containing a Location Update by IMSI */
function f_build_lu_imsi(hexstring imsi) return PDU_ML3_MS_NW
{
	var MobileIdentityLV mi := valueof(ts_MI_IMSI_LV(imsi));
	return f_build_lu(mi);
}
function f_build_lu_imei(hexstring imei) return PDU_ML3_MS_NW
{
	var MobileIdentityLV mi := valueof(ts_MI_IMEI_LV(imei));
	return f_build_lu(mi);
}
function f_build_lu_tmsi(OCT4 tmsi) return PDU_ML3_MS_NW
{
	var MobileIdentityLV mi := valueof(ts_MI_TMSI_LV(tmsi));
	return f_build_lu(mi);
}
private function f_build_lu(MobileIdentityLV mi) return PDU_ML3_MS_NW
{
	var LocationAreaIdentification_V old_lai := { '62F220'O, '9999'O };
	var PDU_ML3_MS_NW l3_info := valueof(ts_ML3_MO_LU_Req(valueof(ts_ML3_IE_LuType_Attach),
							      old_lai, mi, valueof(ts_CM1)));
	return l3_info;
}

type record AuthVector {
	OCT16 rand,
	OCT4 sres,
	OCT8 kc
	/* FIXME: 3G elements */
}

private function f_rnd_oct(integer len) return octetstring {
	var integer i;
	var octetstring res;
	for (i := 0; i < len; i := i + 1) {
		res[i] := int2oct(float2int(rnd()*256.0), 1);
	}
	return res;
}

function f_gen_auth_vec_2g() return AuthVector {
	var AuthVector vec;
	vec.rand := f_rnd_oct(16);
	vec.sres := f_rnd_oct(4);
	vec.kc := f_rnd_oct(8);
	return vec;
}

function f_perform_lu(boolean expect_auth, boolean expect_tmsi, boolean send_early_cm)
runs on BSC_ConnHdlr {
	var PDU_ML3_MS_NW l3_lu := f_build_lu_imsi(g_pars.imsi)
	var PDU_DTAP_MT dtap_mt;

	/* tell GSUP dispatcher to send this IMSI to us */
	f_create_gsup_expect(hex2str(g_pars.imsi));

	/* Send BSSAP_Conn_Req with COMPL L3 INFO to MSC */
	f_bssap_compl_l3(l3_lu);

	if (send_early_cm) {
		BSSAP.send(ts_BSSMAP_ClassmarkUpd(g_pars.cm2, g_pars.cm3));
	}

	if (expect_auth) {
		var AuthVector vec := f_gen_auth_vec_2g();
		var GSUP_IE auth_tuple := valueof(ts_GSUP_IE_AuthTuple2G(vec.rand, vec.sres, vec.kc));
		GSUP.receive(tr_GSUP_SAI_REQ(g_pars.imsi));
		GSUP.send(ts_GSUP_SAI_RES(g_pars.imsi, auth_tuple));

		BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_MM_AUTH_REQ(vec.rand)));
		BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MT_MM_AUTH_RESP_2G(vec.sres)));
	}

	/* Expect MSC to perform LU with HLR */
	GSUP.receive(tr_GSUP_UL_REQ(g_pars.imsi));
	GSUP.send(ts_GSUP_ISD_REQ(g_pars.imsi, g_pars.msisdn));
	GSUP.receive(tr_GSUP_ISD_RES(g_pars.imsi));
	GSUP.send(ts_GSUP_UL_RES(g_pars.imsi));

	alt {
	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Acc)) -> value dtap_mt {
		var PDU_ML3_LocationUpdateAccept lu_acc := dtap_mt.dtap.msgs.mm.locationUpdateAccept;
		if (expect_tmsi) {
			if (not ispresent(lu_acc.mobileIdentityTLV) or
			    not ischosen(lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi)) {
				setverdict(fail, "Expected TMSI but no TMSI was allocated");
				self.stop;
			} else {
				g_pars.tmsi := lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi.octets;
				BSSAP.send(ts_PDU_DTAP_MO(ts_ML3_MO_TmsiRealloc_Cmpl));
			}
		} else {
			if (ispresent(lu_acc.mobileIdentityTLV) and
			    ischosen(lu_acc.mobileIdentityTLV.mobileIdentityLV.mobileIdentityV.oddEvenInd_identity.tmsi_ptmsi)) {
				setverdict(fail, "Expected no TMSI but TMSI was allocated");
				self.stop;
			}
		}
		}
	[] BSSAP.receive(tr_PDU_DTAP_MT(tr_ML3_MT_LU_Rej)) {
		setverdict(fail, "Expected LU ACK, but received LU REJ");
		self.stop;
		}
	}
	/* FIXME: there could be pending SMS or other common procedures by the MSC, let's ignore them */
	BSSAP.receive(tr_BSSMAP_ClearCommand);
	BSSAP.send(ts_BSSMAP_ClearComplete);
	BSSAP.receive(BSSAP_Conn_Prim:MSC_CONN_PRIM_DISC_IND);
	setverdict(pass);
}

function f_foo() runs on BSC_ConnHdlr{
	/* SCCP CC handled by BSSMAP_Emulation_CT.main() */
	/* Expect auth, if enabled */

	/* TODO: ISD */
	/* Expect encr, if enabled */
	/* Expect encr, if enabled */
	/* Expect ASS CMD, if chan_type != requested */
	/* Send ASS CMPL in successful case */

	/* Expect AoIP port/ip information for RTP stream */
	/* Expect MSC-originated MGCP to our simulated MGW */
	/* Verify Counters via CTRL */
	/* re-configure MSC behaviour via VTY */
}





}


