module RSPRO_Types {

/* Templates and utility functions for the RSPRO protocol.
 * (C) 2019 by 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
 */

import from RSPRO all;
import from Native_Functions all;

template ResultCode tr_Status_ok_or_nocard := (ok, cardNotPresent);

external function dec_RsproPDU(in octetstring stream) return RsproPDU;
external function enc_RsproPDU(in RsproPDU pdu) return octetstring;

type integer RsproVersion (0..32);

template (value) BankSlot ts_BankSlot(template (value) BankId bid,
				      template (value) SlotNumber slot) := {
	bankId := bid,
	slotNr := slot
}

template (value) ClientSlot ts_ClientSlot(template (value) ClientId cid,
					  template (value) SlotNumber slot) := {
	clientId := cid,
	slotNr := slot
}

template (value) ComponentIdentity ts_CompId(template (value) ComponentType ctype,
					     template (value) ComponentName name,
					     template (value) ComponentName sw := "TTCN3",
					     template (value) ComponentName sw_version := "0.1") := {
	type_ := ctype,
	name := name,
	software := sw,
	swVersion := sw_version,
	hwManufacturer := "sysmocom",
	hwModel	:= omit,
	hwSerialNr := omit,
	hwVersion := omit,
	fwVersion := omit
}
template ComponentIdentity tr_CompId(template ComponentType ctype,
				     template ComponentName name,
				     template ComponentName sw := "TTCN3",
				     template ComponentName sw_version := "0.1") := {
	type_ := ctype,
	name := name,
	software := sw,
	swVersion := sw_version,
	hwManufacturer := *,
	hwModel	:= *,
	hwSerialNr := *,
	hwVersion := *,
	fwVersion := *
}

template (value) IpPort ts_IpPort(template (value) IpAddress ip,
				  template (value) PortNumber port_nr) := {
	ip := ip,
	port_ := port_nr
}
template IpPort tr_IpPort(template IpAddress ip, template PortNumber port_nr) := {
	ip := ip,
	port_ := port_nr
}

template (value) IpAddress ts_IPv4(charstring ip_str) := {
	ipv4 := f_inet_addr(ip_str)
}




template (value) RsproPDU ts_RSPRO(template (value) RsproPDUchoice msg,
				   template (value) RsproVersion version := 2,
				   template (value) OperationTag tag := 0) := {
	version := version,
	tag := tag,
	msg := msg
}

template RsproPDU tr_RSPRO(template RsproPDUchoice msg,
			   template RsproVersion version := 2,
			   template OperationTag tag := ?) := {
	version := version,
	tag := tag,
	msg := msg
}


template (value) RsproPDU ts_RSPRO_ConnectClientReq(template (value) ComponentIdentity id,
						    template (omit) ClientSlot clslot) :=
	ts_RSPRO(RsproPDUchoice:{
			connectClientReq := {
				identity := id,
				clientSlot := clslot
			}
		});
template RsproPDU tr_RSPRO_ConnectClientReq(template ComponentIdentity id,
					    template ClientSlot clslot) :=
	tr_RSPRO(RsproPDUchoice:{
			connectClientReq := {
				identity := id,
				clientSlot := clslot
			}
		});


template (value) RsproPDU ts_RSPRO_ConnectClientRes(template (value) ComponentIdentity id,
						    template (value) ResultCode res) := 
	ts_RSPRO(RsproPDUchoice:{
			connectClientRes := {
				identity := id,
				result := res
			}
		});
template RsproPDU tr_RSPRO_ConnectClientRes(template ComponentIdentity id := ?,
					    template ResultCode res := ?) := 
	tr_RSPRO(RsproPDUchoice:{
			connectClientRes := {
				identity := id,
				result := res
			}
		});

template (value) RsproPDU ts_RSPRO_ConnectBankReq(template (value) ComponentIdentity id,
						  template (value) BankId bid,
						  template (value) SlotNumber nslots,
						  template (omit) IpPort bound) :=
	ts_RSPRO(RsproPDUchoice:{
			connectBankReq := {
				identity := id,
				bankId := bid,
				numberOfSlots := nslots,
				bound := bound
			}
		});
template RsproPDU tr_RSPRO_ConnectBankReq(template ComponentIdentity id,
					  template BankId bid,
					  template SlotNumber nslots,
					  template IpPort bound := *) :=
	tr_RSPRO(RsproPDUchoice:{
			connectBankReq := {
				identity := id,
				bankId := bid,
				numberOfSlots := nslots,
				bound := *
			}
		});


template (value) RsproPDU ts_RSPRO_ConnectBankRes(template (value) ComponentIdentity id,
						  template (value) ResultCode res) := 
	ts_RSPRO(RsproPDUchoice:{
			connectBankRes := {
				identity := id,
				result := res
			}
		});
template RsproPDU tr_RSPRO_ConnectBankRes(template ComponentIdentity id := ?,
					  template ResultCode res := ?) := 
	tr_RSPRO(RsproPDUchoice:{
			connectBankRes := {
				identity := id,
				result := res
			}
		});


template (value) RsproPDU ts_RSPRO_SetAtrReq(template (value) ClientSlot clslot,
					     template (value) ATR atr) :=
	ts_RSPRO(RsproPDUchoice:{
			setAtrReq := {
				slot := clslot,
				atr := atr
			}
		});
template RsproPDU tr_RSPRO_SetAtrReq(template ClientSlot clslot := ?,
				     template ATR atr := ?) :=
	tr_RSPRO(RsproPDUchoice:{
			setAtrReq := {
				slot := clslot,
				atr := atr
			}
		});

template (value) RsproPDU ts_RSPRO_SetAtrRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			setAtrRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_SetAtrRes(template ResultCode res := ?) :=
	tr_RSPRO(RsproPDUchoice:{
			setAtrRes := {
				result := res
			}
		});

template (value) RsproPDU ts_RSPRO_TpduModemToCard(template (value) ClientSlot from_clslot,
						   template (value) BankSlot to_bslot,
						   template (value) TpduFlags flags,
						   template (value) octetstring data) :=
	ts_RSPRO(RsproPDUchoice:{
			tpduModemToCard := {
				fromClientSlot := from_clslot,
				toBankSlot := to_bslot,
				flags := flags,
				data := data
			}
		});
template RsproPDU tr_RSPRO_TpduModemToCard(template ClientSlot from_clslot := ?,
					   template BankSlot to_bslot := ?,
					   template TpduFlags flags := ?,
					   template octetstring data := ?) :=
	tr_RSPRO(RsproPDUchoice:{
			tpduModemToCard := {
				fromClientSlot := from_clslot,
				toBankSlot := to_bslot,
				flags := flags,
				data := data
			}
		});

template (value) RsproPDU ts_RSPRO_TpduCardToModem(template (value) BankSlot from_bslot,
						   template (value) ClientSlot to_clslot,
						   template (value) TpduFlags flags,
						   template (value) octetstring data) :=
	ts_RSPRO(RsproPDUchoice:{
			tpduCardToModem := {
				fromBankSlot := from_bslot,
				toClientSlot := to_clslot,
				flags := flags,
				data := data
			}
		});
template RsproPDU tr_RSPRO_TpduCardToModem(template BankSlot from_bslot := ?,
					   template ClientSlot to_clslot := ?,
					   template TpduFlags flags := ?,
					   template octetstring data := ?) :=
	tr_RSPRO(RsproPDUchoice:{
			tpduCardToModem := {
				fromBankSlot := from_bslot,
				toClientSlot := to_clslot,
				flags := flags,
				data := data
			}
		});

template (value) RsproPDU ts_RSPRO_CreateMappingReq(template (value) ClientSlot cslot,
						    template (value) BankSlot bslot) :=
	ts_RSPRO(RsproPDUchoice:{
			createMappingReq := {
				client := cslot,
				bank := bslot
			}
		});
template RsproPDU tr_RSPRO_CreateMappingReq(template ClientSlot cslot,
					    template BankSlot bslot) :=
	tr_RSPRO(RsproPDUchoice:{
			createMappingReq := {
				client := cslot,
				bank := bslot
			}
		});

template (value) RsproPDU ts_RSPRO_CreateMappingRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			createMappingRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_CreateMappingRes(template ResultCode res) :=
	tr_RSPRO(RsproPDUchoice:{
			createMappingRes := {
				result := res
			}
		});

template (value) RsproPDU ts_RSPRO_RemoveMappingReq(template (value) ClientSlot cslot,
						    template (value) BankSlot bslot) :=
	ts_RSPRO(RsproPDUchoice:{
			removeMappingReq := {
				client := cslot,
				bank := bslot
			}
		});
template RsproPDU tr_RSPRO_RemoveMappingReq(template ClientSlot cslot,
					    template BankSlot bslot) :=
	tr_RSPRO(RsproPDUchoice:{
			removeMappingReq := {
				client := cslot,
				bank := bslot
			}
		});

template (value) RsproPDU ts_RSPRO_RemoveMappingRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			removeMappingRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_RemoveMappingRes(template ResultCode res) :=
	tr_RSPRO(RsproPDUchoice:{
			removeMappingRes := {
				result := res
			}
		});


template (value) RsproPDU ts_RSPRO_ConfigClientIdReq(template (value) ClientSlot cslot) :=
	ts_RSPRO(RsproPDUchoice: {
			configClientIdReq := {
				clientSlot := cslot
			}
		});
template RsproPDU tr_RSPRO_ConfigClientIdReq(template ClientSlot cslot) :=
	tr_RSPRO(RsproPDUchoice: {
			configClientIdReq := {
				clientSlot := cslot
			}
		});

template (value) RsproPDU ts_RSPRO_ConfigClientIdRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			configClientIdRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_ConfigClientIdRes(template ResultCode res) :=
	tr_RSPRO(RsproPDUchoice:{
			configClientIdRes := {
				result := res
			}
		});

template (value) RsproPDU ts_RSPRO_ConfigClientBankReq(template (value) BankSlot bslot,
							template (value) IpPort ip_port) :=
	ts_RSPRO(RsproPDUchoice: {
			configClientBankReq := {
				bankSlot := bslot,
				bankd := ip_port
			}
		});
template RsproPDU tr_RSPRO_ConfigClientBankReq(template BankSlot bslot,
						template IpPort ip_port) :=
	tr_RSPRO(RsproPDUchoice: {
			configClientBankReq := {
				bankSlot := bslot,
				bankd := ip_port
			}
		});

template (value) RsproPDU ts_RSPRO_ConfigClientBankRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			configClientBankRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_ConfigClientBankRes(template ResultCode res) :=
	tr_RSPRO(RsproPDUchoice:{
			configClientBankRes := {
				result := res
			}
		});

template (value) RsproPDU ts_RSPRO_ResetStateReq :=
	ts_RSPRO(RsproPDUchoice: {
			resetStateReq := {}
		});
template RsproPDU tr_RSPRO_ResetStateReq :=
	tr_RSPRO(RsproPDUchoice: {
			resetStateReq := {}
		});

template (value) RsproPDU ts_RSPRO_ResetStateRes(template (value) ResultCode res) :=
	ts_RSPRO(RsproPDUchoice:{
			resetStateRes := {
				result := res
			}
		});
template RsproPDU tr_RSPRO_ResetStateRes(template ResultCode res) :=
	tr_RSPRO(RsproPDUchoice:{
			resetStateRes := {
				result := res
			}
		});



}
