/* Osmocom VTY interface functions in TTCN-3
 * (C) 2017-2018 Harald Welte <laforge@gnumonks.org>
 * contributions by sysmocom - s.f.m.c. GmbH
 * 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 Osmocom_VTY_Functions {
	import from TELNETasp_PortType all;
	import from Osmocom_Types all;

	modulepar {
		charstring mp_prompt_prefix := "OpenBSC";
	}

	const charstring VTY_VIEW_SUFFIX := "> ";
	const charstring VTY_ENABLE_SUFFIX := "# ";
	const charstring VTY_CFG_SUFFIX := "(*)";

	template charstring t_vty_unknown := pattern "*% Unknown command.";

	/* configure prompts in TELNETasp module */
	function f_vty_set_prompts(TELNETasp_PT pt, charstring prompt_prefix := mp_prompt_prefix) {
		var ASP_TelnetDynamicConfig vty_prompt[3] := {
			{
				prompt := {
					id := 1,
					prompt := prompt_prefix & VTY_VIEW_SUFFIX,
					has_wildcards := false
				}
			}, {
				prompt := {
					id := 2,
					prompt := prompt_prefix & VTY_ENABLE_SUFFIX,
					has_wildcards := false
				}
			}, {
				prompt := {
					id := 3,
					prompt := prompt_prefix & VTY_CFG_SUFFIX,
					has_wildcards := true
				}
			}
		};

		/* set some configuration that isn't possible to express
		 * in the config file due to syntactic restrictions (Who invents config
		 * files that don't permit regular expressions? */
		for (var integer i := 0; i < sizeof(vty_prompt); i:= i + 1) {
			pt.send(vty_prompt[i]);
		}
	}

	/* wait for any of the permitted prompts; buffer + return all intermediate output */
	function f_vty_wait_for_prompt(TELNETasp_PT pt, boolean strict := true, charstring log_label := "(?)") return charstring {
		var charstring rx, buf := "";
		var integer fd;
		timer T := 2.0;

		T.start;
		alt {
			[] pt.receive(pattern "[\w-]+" & VTY_VIEW_SUFFIX) { };
			[] pt.receive(pattern "[\w-]+\# ") { };
			[] pt.receive(pattern "[\w-]+\(*\)\# ") { };
			[] pt.receive(t_vty_unknown) -> value rx {
				if (strict) {
					setverdict(fail, "VTY: Unknown Command: " & log_label);
					mtc.stop;
				} else {
					log("VTY: Unknown Command (ignored): " & log_label);
					buf := buf & rx;
					repeat;
				}
				};
			[] pt.receive(charstring:?) -> value rx { buf := buf & rx; repeat };
			[] pt.receive(integer:?) -> value fd {
				if (fd == -1) {
					setverdict(fail, "VTY Telnet Connection Failure: " & log_label);
					mtc.stop;
				} else {
					repeat; /* telnet connection succeeded */
				}
			}
			[] T.timeout {
				setverdict(fail, "VTY Timeout for prompt: " & log_label);
				mtc.stop;
				};
		}
		T.stop;
		return buf;
	}

	/* send a VTY command and obtain response until prompt is received */
	function f_vty_transceive_ret(TELNETasp_PT pt, charstring tx, boolean strict := true) return charstring {
		pt.send(tx);
		return f_vty_wait_for_prompt(pt, strict, tx);
	}

	/* send a VTY command and obtain response until prompt is received */
	function f_vty_transceive(TELNETasp_PT pt, charstring tx, boolean strict := true) {
		var charstring unused := f_vty_transceive_ret(pt, tx, strict);
	}

	type integer BtsNr (0..255);
	type integer BtsTrxNr (0..255);
	type integer BtsTimeslotNr (0..7);
	type integer MscNr (0..255);
	type integer Cs7Nr (0..255);

	type charstring BtsGprsMode ("none", "gprs", "egrps");

	/* enter the'confiugration' mode of the VTY */
	function f_vty_enter_config(TELNETasp_PT pt) {
		f_vty_transceive(pt, "configure terminal")
	}

	function f_vty_enter_cfg_network(TELNETasp_PT pt) {
		f_vty_enter_config(pt);
		f_vty_transceive(pt, "network")
	}

	function f_vty_enter_cfg_bts(TELNETasp_PT pt, BtsNr bts := 0) {
		f_vty_enter_cfg_network(pt);
		f_vty_transceive(pt, "bts " & int2str(bts));
	}

	function f_vty_enter_cfg_trx(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0) {
		f_vty_enter_cfg_bts(pt, bts);
		f_vty_transceive(pt, "trx " & int2str(trx));
	}

	function f_vty_enter_cfg_ts(TELNETasp_PT pt, BtsNr bts := 0, BtsTrxNr trx := 0, BtsTimeslotNr ts) {
		f_vty_enter_cfg_trx(pt, bts, trx);
		f_vty_transceive(pt, "timeslot " & int2str(ts));
	}

	function f_vty_enter_cfg_msc(TELNETasp_PT pt, MscNr msc := 0) {
		f_vty_enter_config(pt);
		f_vty_transceive(pt, "msc " & int2str(msc));
	}

	function f_vty_enter_cfg_cs7_inst(TELNETasp_PT pt, Cs7Nr cs7_inst := 0) {
		f_vty_enter_config(pt);
		f_vty_transceive(pt, "cs7 instance " & int2str(cs7_inst));
	}

type record of charstring rof_charstring;
function f_vty_config2(TELNETasp_PT pt, rof_charstring config_nodes, charstring cmd)
{
	/* enter config mode; enter node */
	f_vty_enter_config(pt);
	for (var integer i := 0; i < sizeof(config_nodes); i := i+1) {
		f_vty_transceive(pt, config_nodes[i]);
	}
	/* execute command */
	f_vty_transceive(pt, cmd);
	/* leave config mode */
	f_vty_transceive(pt, "end");
}


function f_vty_config(TELNETasp_PT pt, charstring config_node, charstring cmd)
{
	f_vty_config2(pt, {config_node}, cmd);
}

function f_vty_transceive_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
	var charstring ret := f_vty_transceive_ret(pt, cmd);
	if (not match(ret, exp_ret)) {
		setverdict(fail, "Non-matching VTY response: ", ret);
		mtc.stop;
	}
}

function f_vty_transceive_not_match(TELNETasp_PT pt, charstring cmd, template charstring exp_ret) {
	var charstring ret := f_vty_transceive_ret(pt, cmd);
	if (match(ret, exp_ret)) {
		setverdict(fail, "Unexpected matching VTY response: ", ret);
		mtc.stop;
	}
}

function f_vty_transceive_match_regex(TELNETasp_PT pt, charstring cmd, charstring regex, integer groupno) return charstring
{
	var charstring resp := f_vty_transceive_ret(pt, cmd);
	return regexp(resp, regex, groupno);
}

function f_vty_transceive_match_regexp_retry(TELNETasp_PT pt, charstring cmd, charstring regex,
					     integer groupno, integer num_attempts, float retry_delay) return charstring
{
	 while (num_attempts > 0) {
		var charstring ret := f_vty_transceive_match_regex(pt, cmd, regex, groupno);
		if (ret != "") {
			return ret;
		}
		f_sleep(retry_delay);
		num_attempts := num_attempts - 1;
	}

	setverdict(fail, "No matching VTY response for regular expression '", regex,
		   "' after ", num_attempts, " attempts." );
	mtc.stop;
}

}
