module TCAP_CodecPort {

/* Simple TCAP Codec Port, translating between raw SCCP primitives with
 * octetstring payload towards the SCCP provider, and TCAP-SCCP primitives
 * which carry the decoded TCAP data types as payload.
 *
 * (C) 2025 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 */

import from General_Types all;
import from Osmocom_Types all;

import from SCCPasp_Types all;
import from SCCP_Types all;

import from TCAPMessages language "ASN.1:1997" all;
import from TCAP_Types all;

const BIT8n RETURN_OPTION_DISCARD := '00000000'B;
const BIT8n RETURN_OPTION_ON_ERROR := '00000001'B;

type record TCAP_N_CONNECT_req
{
   SCCP_PAR_Address                 calledAddress,
   SCCP_PAR_Address                 callingAddress     optional,
   SCCP_PAR_Expedited_Data_Sel	    expeditedDataSel   optional,
   SCCP_PAR_Quality_Of_Service      qualityOfService   optional,
   TCMessage                        userData           optional,
   SCCP_PAR_Connection_Id           connectionId       optional,
   SCCP_PAR_Importance              importance         optional
}

template (value) TCAP_N_CONNECT_req ts_TCAP_CONNECT_req(SCCP_PAR_Address called,
						       SCCP_PAR_Address calling,
						       SCCP_PAR_Connection_Id conn_id,
						       template (omit) TCMessage ranap := omit) := {
	calledAddress := called,
	callingAddress := calling,
	expeditedDataSel := omit,
	qualityOfService := omit,
	userData := ranap,
	connectionId := conn_id,
	importance := omit
}

type record TCAP_N_CONNECT_ind
{
   SCCP_PAR_Address                 calledAddress,
   SCCP_PAR_Address                 callingAddress     optional,
   SCCP_PAR_Quality_Of_Service      qualityOfService   optional,
   TCMessage                        userData           optional,
   SCCP_PAR_Connection_Id           connectionId       optional,
   SCCP_PAR_Importance              importance         optional
}

template (present) TCAP_N_CONNECT_ind tr_TCAP_CONNECT_ind(template SCCP_PAR_Address called,
							  template SCCP_PAR_Address calling,
							  template TCMessage payload := *) := {
	calledAddress := called,
	callingAddress := calling,
	qualityOfService := *,
	userData := payload,
	connectionId := *,
	importance := *
}

type record TCAP_N_CONNECT_res
{
   SCCP_PAR_Address			respondingAddress optional,
   SCCP_PAR_Expedited_Data_Sel		expeditedDataSel  optional,
   SCCP_PAR_Quality_Of_Service		qualityOfService  optional,
   TCMessage				userData          optional,
   SCCP_PAR_Connection_Id		connectionId      optional,
   SCCP_PAR_Importance 			importance        optional
}

template (value) TCAP_N_CONNECT_res ts_TCAP_CONNECT_res(SCCP_PAR_Connection_Id conn_id,
							template (omit) TCMessage ranap := omit) := {
	respondingAddress := omit,
	expeditedDataSel := omit,
	qualityOfService := omit,
	userData := ranap,
	connectionId := conn_id,
	importance := omit
}

type record TCAP_N_CONNECT_cfm
{
  SCCP_PAR_Address              respondingAddress optional,
  SCCP_PAR_Quality_Of_Service   qualityOfService  optional,
  TCMessage                     userData           optional,
  SCCP_PAR_Connection_Id        connectionId      optional,
  SCCP_PAR_Importance           importance        optional
}

template (present) TCAP_N_CONNECT_cfm tr_TCAP_CONNECT_cfm(template SCCP_PAR_Connection_Id conn_id,
							  template TCMessage ranap := *) := {
	respondingAddress := *,
	qualityOfService := *,
	userData := ranap,
	connectionId := conn_id,
	importance := *
}

type record TCAP_N_DATA_req
{
  TCMessage               userData               ,
  SCCP_PAR_Connection_Id  connectionId  optional ,
  SCCP_PAR_Importance     importance    optional
}

template (value) TCAP_N_DATA_req ts_TCAP_DATA_req(SCCP_PAR_Connection_Id conn_id,
						  template (value) TCMessage ranap) := {
	userData := ranap,
	connectionId := conn_id,
	importance := omit
}


type record TCAP_N_DATA_ind
{
  TCMessage               userData               ,
  SCCP_PAR_Connection_Id  connectionId optional  ,
  SCCP_PAR_Importance     importance   optional
}

template (present) TCAP_N_DATA_ind tr_TCAP_DATA_ind(SCCP_PAR_Connection_Id conn_id,
						    template TCMessage ranap := *) := {
	userData := ranap,
	connectionId := conn_id,
	importance := *
}


type record TCAP_N_DISCONNECT_req
{
  SCCP_PAR_Address         respondingAddress  optional,
  SCCP_PAR_Reason          reason                      ,
  TCMessage                userData           optional ,
  SCCP_PAR_Connection_Id   connectionId       optional ,
  SCCP_PAR_Importance      importance         optional
}

template (value) TCAP_N_DISCONNECT_req ts_TCAP_DISC_req(SCCP_PAR_Connection_Id conn_id,
							template (value) SCCP_PAR_Reason reason,
							template (omit) TCMessage ranap := omit) := {
	respondingAddress := omit,
	reason := reason,
	userData := ranap,
	connectionId := conn_id,
	importance := omit
}


type record TCAP_N_DISCONNECT_ind
{
  SCCP_PAR_Originator     originator                  ,
  SCCP_PAR_Address        respondingAddress  optional ,
  SCCP_PAR_Reason         reason                      ,
  TCMessage               userData           optional ,
  SCCP_PAR_Connection_Id  connectionId       optional ,
  SCCP_PAR_Importance     importance         optional
}

template (present) TCAP_N_DISCONNECT_ind tr_TCAP_DISC_ind(template (present) SCCP_PAR_Connection_Id conn_id,
							  template (present) SCCP_PAR_Originator originator,
							  template (present) SCCP_PAR_Reason reason,
							  template TCMessage ranap := *) := {
	originator := originator,
	respondingAddress:= *,
	reason := reason,
	userData := ranap,
	connectionId := conn_id,
	importance := *
}

type record TCAP_N_UNITDATA_req
{
  SCCP_PAR_Address          calledAddress               ,
  SCCP_PAR_Address          callingAddress              ,
  SCCP_PAR_Sequence_Control sequenceControl    optional ,
  SCCP_PAR_Return_Option    returnOption       optional ,
  TCMessage                 userData                    ,
  SCCP_PAR_Importance       importance         optional
 }

template (value) TCAP_N_UNITDATA_req ts_TCAP_UNITDATA_req(SCCP_PAR_Address called,
							  SCCP_PAR_Address calling,
							  template (value) TCMessage payload,
							  template (omit) SCCP_PAR_Return_Option returns := omit) := {
	calledAddress := called,
	callingAddress := calling,
	sequenceControl := omit,
	returnOption := returns,
	userData := payload,
	importance := omit
}

type record TCAP_N_UNITDATA_ind
{
  SCCP_PAR_Address           calledAddress              ,
  SCCP_PAR_Address           callingAddress             ,
  SCCP_PAR_Sequence_Control  sequenceControl  optional  ,
  SCCP_PAR_Return_Option     returnOption     optional  ,
  TCMessage                  userData                   ,
  SCCP_PAR_Importance        importance       optional
}

template (present) TCAP_N_UNITDATA_ind tr_TCAP_UNITDATA_ind(template SCCP_PAR_Address called,
							    template SCCP_PAR_Address calling,
							    template TCMessage payload) := {
	calledAddress := called,
	callingAddress := calling,
	sequenceControl := *,
	returnOption := *,
	userData := payload,
	importance := *
}

type record TCAP_N_NOTICE_ind
{
  SCCP_PAR_Address               calledAddress            ,
  SCCP_PAR_Address               callingAddress           ,
  SCCP_PAR_Reason_For_Return     reasonForReturn          ,
  TCMessage                      userData                 ,
  SCCP_PAR_Importance            importance       optional
}

template (present) TCAP_N_NOTICE_ind tr_TCAP_N_NOTICE_ind(template SCCP_PAR_Address called,
							  template SCCP_PAR_Address calling,
							  template SCCP_PAR_Reason_For_Return reason,
							  template TCMessage payload) := {
	calledAddress := called,
	callingAddress := calling,
	reasonForReturn := reason,
	userData := payload,
	importance := *
}


private function f_dec_ConnectInd(in ASP_SCCP_N_CONNECT_ind pin, out TCAP_N_CONNECT_ind pout) {
	pout.calledAddress := pin.calledAddress;
	pout.callingAddress := pin.callingAddress;
	pout.qualityOfService := pin.qualityOfService;
	if (ispresent(pin.userData)) {
		pout.userData := dec_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_dec_ConnectCfm(in ASP_SCCP_N_CONNECT_cfm pin, out TCAP_N_CONNECT_cfm pout) {
	pout.respondingAddress := pin.respondingAddress;
	pout.qualityOfService := pin.qualityOfService;
	if (ispresent(pin.userData)) {
		pout.userData := dec_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_dec_DataInd(in ASP_SCCP_N_DATA_ind pin, out TCAP_N_DATA_ind pout) {
	pout.userData := dec_TCAP_TCMessage(pin.userData);
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_dec_DisconnectInd(in ASP_SCCP_N_DISCONNECT_ind pin, out TCAP_N_DISCONNECT_ind pout) {
	pout.originator := pin.originator;
	pout.respondingAddress := pin.respondingAddress;
	pout.reason := pin.reason;
	if (ispresent(pin.userData)) {
		pout.userData := dec_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_dec_UnitdataInd(in ASP_SCCP_N_UNITDATA_ind pin, out TCAP_N_UNITDATA_ind pout) {
	pout.calledAddress := pin.calledAddress;
	pout.callingAddress := pin.callingAddress;
	pout.sequenceControl := pin.sequenceControl;
	pout.returnOption := pin.returnOption;
	pout.userData := dec_TCAP_TCMessage(pin.userData);
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_dec_NoticeInd(in ASP_SCCP_N_NOTICE_ind pin, out TCAP_N_NOTICE_ind pout) {
	pout.calledAddress := pin.calledAddress;
	pout.callingAddress := pin.callingAddress;
	pout.reasonForReturn := pin.reasonForReturn;
	pout.userData := dec_TCAP_TCMessage(pin.userData);
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }



private function f_enc_ConnectReq(in TCAP_N_CONNECT_req pin, out ASP_SCCP_N_CONNECT_req pout) {
	pout.calledAddress := pin.calledAddress;
	pout.callingAddress := pin.callingAddress;
	pout.expeditedDataSel := pin.expeditedDataSel;
	pout.qualityOfService := pin.qualityOfService;
	if (ispresent(pin.userData)) {
		pout.userData := enc_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_enc_ConnectRes(in TCAP_N_CONNECT_res pin, out ASP_SCCP_N_CONNECT_res pout) {
	pout.respondingAddress := pin.respondingAddress;
	pout.expeditedDataSel := pin.expeditedDataSel;
	pout.qualityOfService := pin.qualityOfService;
	if (ispresent(pin.userData)) {
		pout.userData := enc_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_enc_DataReq(in TCAP_N_DATA_req pin, out ASP_SCCP_N_DATA_req pout) {
	pout.userData := enc_TCAP_TCMessage(pin.userData);
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_enc_DisconnectReq(in TCAP_N_DISCONNECT_req pin, out ASP_SCCP_N_DISCONNECT_req pout) {
	pout.respondingAddress := pin.respondingAddress;
	pout.reason := pin.reason;
	if (ispresent(pin.userData)) {
		pout.userData := enc_TCAP_TCMessage(pin.userData);
	} else {
		pout.userData := omit;
	}
	pout.connectionId := pin.connectionId;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

private function f_enc_UnitdataReq(in TCAP_N_UNITDATA_req pin, out ASP_SCCP_N_UNITDATA_req pout) {
	pout.calledAddress := pin.calledAddress;
	pout.callingAddress := pin.callingAddress;
	pout.userData := enc_TCAP_TCMessage(pin.userData);
	pout.sequenceControl := pin.sequenceControl;
	pout.returnOption := pin.returnOption;
	pout.importance := pin.importance;
	//port.setstate(0);
} with {extension "prototype(fast)" }

type port TCAP_CODEC_PT message {
	out	TCAP_N_CONNECT_req,
		TCAP_N_CONNECT_res,
		TCAP_N_DATA_req,
		TCAP_N_DISCONNECT_req,
		TCAP_N_UNITDATA_req,
		ASP_SCCP_N_RESET_req;
	in	TCAP_N_CONNECT_ind,
		TCAP_N_CONNECT_cfm,
		TCAP_N_DATA_ind,
		TCAP_N_DISCONNECT_ind,
		TCAP_N_UNITDATA_ind,
		TCAP_N_NOTICE_ind,
		ASP_SCCP_N_RESET_ind,
		ASP_SCCP_N_RESET_cfm,
		ASP_SCCP_N_STATE_ind,
		ASP_SCCP_N_PCSTATE_ind;
} with { extension "internal user SCCPasp_PT
	out(TCAP_N_CONNECT_req -> ASP_SCCP_N_CONNECT_req: function(f_enc_ConnectReq);
	    TCAP_N_CONNECT_res -> ASP_SCCP_N_CONNECT_res: function(f_enc_ConnectRes);
	    TCAP_N_DATA_req -> ASP_SCCP_N_DATA_req: function(f_enc_DataReq);
	    TCAP_N_DISCONNECT_req -> ASP_SCCP_N_DISCONNECT_req: function(f_enc_DisconnectReq);
	    TCAP_N_UNITDATA_req -> ASP_SCCP_N_UNITDATA_req: function(f_enc_UnitdataReq);
	    ASP_SCCP_N_RESET_req -> ASP_SCCP_N_RESET_req: simple)
	in(ASP_SCCP_N_CONNECT_ind -> TCAP_N_CONNECT_ind: function(f_dec_ConnectInd);
	   ASP_SCCP_N_CONNECT_cfm -> TCAP_N_CONNECT_cfm: function(f_dec_ConnectCfm);
	   ASP_SCCP_N_DATA_ind -> TCAP_N_DATA_ind: function(f_dec_DataInd);
	   ASP_SCCP_N_DISCONNECT_ind -> TCAP_N_DISCONNECT_ind: function(f_dec_DisconnectInd);
	   ASP_SCCP_N_UNITDATA_ind -> TCAP_N_UNITDATA_ind: function(f_dec_UnitdataInd);
	   ASP_SCCP_N_NOTICE_ind -> TCAP_N_NOTICE_ind: function(f_dec_NoticeInd);
	   ASP_SCCP_N_RESET_ind -> ASP_SCCP_N_RESET_ind: simple;
	   ASP_SCCP_N_RESET_cfm -> ASP_SCCP_N_RESET_cfm: simple;
	   ASP_SCCP_N_STATE_ind -> ASP_SCCP_N_STATE_ind: simple;
	   ASP_SCCP_N_PCSTATE_ind -> ASP_SCCP_N_PCSTATE_ind: simple)"
}


}
