module Osmocom_CTRL_Functions {

/* Definition of helper functions for the Osmocom CTRL interface.
 *
 * As opposed to many other parts of the Osmocom TTCN-3 code base, this module
 * implements blocking functions, instead of asynchronous functions.  The
 * rationale for this is simple: One normally wants to inquire a value or set
 * a value and not continue the main program until that operation is complete.
 *
 * CTRL is a machine-type protocol on how external programs can interact with
 * an Osmocom program in a structured way.  It is intended for programmatic
 * access (by other software), as opposed to the VTY interface intended for
 * human consumption.
 *
 * (C) 2017 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.
 */


	import from Osmocom_CTRL_Types all;
	import from IPA_Emulation all;

	private function f_gen_rand_id() return CtrlId {
		return int2str(float2int(rnd()*999999999.0));
	}

	/* perform a given GET Operation */
	function f_ctrl_get(IPA_CTRL_PT pt, CtrlVariable variable) return CtrlValue {
		timer T := 2.0;
		var CtrlMessage rx;
		var CtrlId id := f_gen_rand_id();
		pt.send(ts_CtrlMsgGet(id, variable));
		T.start;
		alt {
		[] pt.receive(tr_CtrlMsgGetRepl(id, variable)) -> value rx {
			}
		[] pt.receive(tr_CtrlMsgTrap) { repeat; }
		[] pt.receive(tr_CtrlMsgError) -> value rx {
			setverdict(fail, "Error in CTRL GET ", variable, ": ", rx.err.reason);
			mtc.stop;
			}
		[] T.timeout {
			setverdict(fail, "Timeout waiting for CTRL GET REPLY ", variable);
			mtc.stop;
			}
		}
		return rx.resp.val;
	}

	/* perform a given SET Operation */
	function f_ctrl_set(IPA_CTRL_PT pt, CtrlVariable variable, CtrlValue val) {
		timer T := 2.0;
		var CtrlMessage rx;
		var CtrlId id := f_gen_rand_id();
		pt.send(ts_CtrlMsgSet(id, variable, val));
		T.start;
		alt {
		[] pt.receive(tr_CtrlMsgSetRepl(id, variable, val)) { }
		[] pt.receive(tr_CtrlMsgTrap) { repeat; }
		[] pt.receive(tr_CtrlMsgError) -> value rx {
			setverdict(fail, "Error in CTRL GET ", variable, ": ", rx.err.reason);
			mtc.stop;
			}
		[] T.timeout {
			setverdict(fail, "Timeout waiting for CTRL SET REPLY ", variable);
			mtc.stop;
			}
		}
	}

	/* send a TRAP */
	function f_ctrl_trap(IPA_CTRL_PT pt, CtrlVariable variable, CtrlValue val) {
		pt.send(ts_CtrlMsgTrap(variable, val));
	}

	/* Expect a matching TRAP */
	function f_ctrl_exp_trap(IPA_CTRL_PT pt, template CtrlVariable variable,
				 template CtrlValue val := ?, float timeout_val := 2.0)
	return CtrlValue {
		timer T := timeout_val;
		var CtrlMessage rx;
		T.start;
		alt {
		[] pt.receive(tr_CtrlMsgTrap(variable, val)) -> value rx {
			}
		[] T.timeout {
			setverdict(fail, "Timeout waiting for TRAP ", variable);
			mtc.stop;
			}
		}
		return rx.trap.val;
	}

	/* Expect a matching SET, optionally answer */
	function f_ctrl_exp_set(IPA_CTRL_PT pt, template CtrlVariable variable,
				 template CtrlValue val := ?,
				 template (omit) CtrlValue rsp := omit,
				 float timeout_val := 2.0)
	return CtrlValue {
		timer T := timeout_val;
		var CtrlMessage rx;
		T.start;
		alt {
		[] pt.receive(tr_CtrlMsgSet(?, variable, val)) -> value rx {
			if (ispresent(rsp)) {
				pt.send(ts_CtrlMsgSetRepl(rx.cmd.id, valueof(variable), valueof(rsp)));
			}
			}
		[] T.timeout {
			setverdict(fail, "Timeout waiting for SET ", variable);
			mtc.stop;
			}
		}
		return rx.cmd.val;
	}

	/* Expect a matching GET result */
	function f_ctrl_get_exp(IPA_CTRL_PT pt, CtrlVariable variable, template CtrlValue exp) {
		var charstring ctrl_resp;
		ctrl_resp := f_ctrl_get(pt, variable);
		if (not match(ctrl_resp, exp)) {
			setverdict(fail, "Unexpected " & variable & ":" & ctrl_resp);
			mtc.stop;
		}
	}

	template charstring ts_ctrl_ratectr(CtrlVariable grp, integer instance, CtrlVariable name,
					    CtrlVariable kind := "abs") :=
		"rate_ctr." & kind & "." & grp & "." & int2str(instance) & "." & name;

	function f_ctrl_get_ratectr_abs(IPA_CTRL_PT pt, CtrlVariable grp, integer instance,
					CtrlVariable name) return integer {
		return str2int(f_ctrl_get(pt, valueof(ts_ctrl_ratectr(grp, instance, name))));
	}

	function f_ctrl_get_exp_ratectr_abs(IPA_CTRL_PT pt, CtrlVariable grp, integer instance,
					    CtrlVariable name, template integer exp) {
		var charstring ctrl_resp;
		var CtrlVariable variable := valueof(ts_ctrl_ratectr(grp, instance, name));
		ctrl_resp := f_ctrl_get(pt, variable);
		if (not match(str2int(ctrl_resp), exp)) {
			setverdict(fail, variable & " value " & ctrl_resp & " didn't match ", exp);
			mtc.stop;
		}
	}


}
