/* OsmoHNodeB Lower Layer Socket Interface codec port in TTCN-3
 * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
 *
 * 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 HNBLLIF_CodecPort {

import from Osmocom_Types all;
import from HNBLLIF_Types all;
import from UD_PortType all;
import from UD_Types all;

type record HNBLLIF_send_data {
	HNBLLIF_Message	data,
	integer		id
};

private function HNBLLIF_to_UD(in HNBLLIF_send_data pin, out UD_send_data pout) {
	pout.id := pin.id;
	pout.data := enc_HNBLLIF_Message(pin.data);
} with { extension "prototype(fast)" };

private function UD_to_HNBLLIF(in UD_send_data pin, out HNBLLIF_send_data pout) {
	pout.id := pin.id;
	pout.data := dec_HNBLLIF_Message(pin.data);
} with { extension "prototype(fast)" };

type port HNBLLIF_CODEC_PT message {
	out	UD_close, UD_listen, UD_shutdown, UD_connect, HNBLLIF_send_data;
	in	UD_listen_result, UD_connect_result, UD_connected, HNBLLIF_send_data;
} with { extension "user UD_PT
	out (
		UD_close -> UD_close:simple;
		UD_listen -> UD_listen:simple;
		UD_shutdown -> UD_shutdown:simple;
		UD_connect -> UD_connect:simple;
		HNBLLIF_send_data -> UD_send_data: function(HNBLLIF_to_UD)
		)
	in (
		UD_listen_result -> UD_listen_result:simple;
		UD_connect_result -> UD_connect_result:simple;
		UD_send_data -> HNBLLIF_send_data: function(UD_to_HNBLLIF);
		UD_connected -> UD_connected:simple
		)"
};

template HNBLLIF_send_data t_SD_HNBLLIF(integer id, template HNBLLIF_Message pdu) := {
	data := pdu,
	id := id
}
template (value) HNBLLIF_send_data ts_SD_HNBLLIF(integer id, template (value) HNBLLIF_Message pdu) := {
	data := pdu,
	id := id
}

function f_hnbllif_connect(HNBLLIF_CODEC_PT pt, charstring sock) return integer {
	var UD_connect_result res;
	timer T := 5.0;

	T.start;
	pt.send(UD_connect:{sock, -1});
	alt {
	[] pt.receive(UD_connect_result:?) -> value res {
		if (ispresent(res.result) and ispresent(res.result.result_code) and
		    res.result.result_code == ERROR) {
			if (ispresent(res.result.err)) {
				setverdict(fail, "Error connecting to HNBLL socket ", sock, ": ", res.result.err);
			} else {
				setverdict(fail, "Error connecting to HNBLL socket ", sock);
			}
			mtc.stop;
		} else {
			return res.id;
		}
		}
	[] T.timeout {
		setverdict(fail, "Timeout connecting to HNBLL socket ", sock);
		mtc.stop;
		}
	}
	return -23;
}

function f_hnbllif_close(HNBLLIF_CODEC_PT pt, integer id)
{
	pt.send(UD_close:{id := id});
}

}
