initial chekin of code received by Ericsson on 20170410
diff --git a/M3UA_CNL113537/src/M3UA_Emulation.ttcn b/M3UA_CNL113537/src/M3UA_Emulation.ttcn
new file mode 100644
index 0000000..7a4a7e9
--- /dev/null
+++ b/M3UA_CNL113537/src/M3UA_Emulation.ttcn
@@ -0,0 +1,1307 @@
+///////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright Test Competence Center (TCC) ETH 2009 //
+// //
+// The copyright to the computer program(s) herein is the property of TCC. //
+// The program(s) may be used and/or copied only with the written permission //
+// of TCC or in accordance with the terms and conditions stipulated in the //
+// agreement/contract under which the program(s) have been supplied //
+// //
+///////////////////////////////////////////////////////////////////////////////
+//
+// File: M3UA_Emulation.ttcn
+// Reference: M3UA Protocol Emulation
+// Rev: R1B01
+// Prodnr: CNL 113 537
+// Updated: 2009-01-06
+// Contact: http://ttcn.ericsson.se
+
+module M3UA_Emulation
+{
+
+modulepar
+{
+ boolean tsp_logVerbose := false;
+ float tsp_Timer := 2.0; // General timer used in M3UA emulation.
+ float tsp_ASPUP_Resend_Timer := 2.0;
+ float tsp_ASPAC_Resend_Timer := 2.0;
+ float tsp_Assoc_Restart_Timer := 60.0;
+ float tsp_Heartbeat_Timer := 30.0;
+ integer tsp_SCTP_PayloadProtocolID := 3; // 3 for M3UA.
+ boolean tsp_Enable_M3UA_Heartbeat := false; // Send SCTP packets periodically.
+ boolean tsp_SCTP_Server_Mode := false;
+ boolean tsp_M3UA_Server_Mode := false;
+}
+
+import from General_Types all;
+import from M3UA_Types all;
+import from SCTPasp_Types all;
+import from SCTPasp_PortType all;
+import from MTP3asp_Types all;
+
+type record of ASP_MTP3_TRANSFERreq TRANSFERreq_Buffer;
+
+type record SCTP_Association_Address
+{
+ integer local_sctp_port,
+ charstring local_ip_addr,
+ integer remote_sctp_port,
+ charstring remote_ip_addr
+}
+
+// Definition of M3UA_Entity which contains M3UA entity data.
+type record M3UA_Entity
+{
+ M3UA_CommStatus commStatus optional,
+ integer sCTP_Assoc_ID optional,
+ SCTP_Association_Address assoc
+}
+
+// Type for status of SCTP communication for an M3UA entity.
+type enumerated M3UA_CommStatus
+{
+ aSP_Down_initial_State (0),
+ aSP_Down_sCTP_Initialize_Done (1),
+ aSP_Down_sCTP_Associate_done (2),
+ aSP_Down_commUP_Received (3),
+ aSP_Down_ASPUP_Sent (4),
+ aSP_Inactive (5),
+ aSP_Inact_ASPAC_Sent (6),
+ aSP_Active (7) // aSPAC_Ack_Received
+}
+
+// We need an internal port to communicate with the MTP3 side.
+// internal in name
+type port MTP3asp_SP_PT_Int message
+{
+ in ASP_MTP3_TRANSFERreq;
+ out ASP_MTP3_TRANSFERind;
+ // out ASP_MTP3_PAUSE;
+ // out ASP_MTP3_RESUME;
+ // out ASP_MTP3_STATUS;
+} with {
+ extension "internal"
+}
+
+// M3UA emulation component.
+type component M3UA_CT
+{
+ var M3UA_Entity v_Entity;
+ var TRANSFERreq_Buffer v_TRANSFERreq_Buffer := {};
+
+ var ASP_SCTP v_ASP_SCTP;
+ var ASP_SCTP_SEND_FAILED v_ASP_SCTP_SEND_FAILED;
+ var ASP_SCTP_RESULT v_ASP_SCTP_RESULT;
+ var ASP_SCTP_Connected v_ASP_SCTP_Connected;
+ var ASP_SCTP_ASSOC_CHANGE v_ASP_SCTP_ASSOC_CHANGE;
+ var ASP_SCTP_SHUTDOWN_EVENT v_ASP_SCTP_SHUTDOWN_EVENT;
+
+ var PDU_M3UA v_PDU_M3UA;
+
+ // Component timers.
+ timer T_Timer := tsp_Timer;
+ timer T_ASPUP_resend := tsp_ASPUP_Resend_Timer;
+ timer T_ASPAC_resend := tsp_ASPAC_Resend_Timer;
+ timer T_Heartbeat := tsp_Heartbeat_Timer;
+ timer T_Assoc_restart := tsp_Assoc_Restart_Timer;
+
+ // Port declarations.
+ port MTP3asp_SP_PT_Int MTP3_SP_PORT; // Port towards MTP3/M3UA.
+ port SCTPasp_PT SCTP_PORT; // Port towards target through SCTP.
+}
+
+//********************************
+// Start of SCTP related templates
+//********************************
+template ASP_SCTP t_S_SCTP_Send
+ (in template integer pl_associationID,
+ in template integer pl_streamID,
+ in template octetstring pl_userData,
+ in template integer pl_protocolID) :=
+{
+ client_id := pl_associationID,
+ sinfo_stream := pl_streamID,
+ sinfo_ppid := pl_protocolID,
+ data := pl_userData
+}
+
+template ASP_SCTP_SEND_FAILED t_ASP_SCTP_SEND_FAILED
+ (in template integer pl_streamID) :=
+{
+ client_id := pl_streamID
+}
+
+template ASP_SCTP_Listen t_ASP_SCTP_Listen
+ (template charstring pl_local_hostname,
+ template integer pl_local_portnumber) :=
+{
+ local_hostname := pl_local_hostname,
+ local_portnumber := pl_local_portnumber
+}
+
+template ASP_SCTP_Connected tr_ASP_SCTP_Connected
+ (template integer pl_client_id,
+ template charstring pl_local_hostname,
+ template integer pl_local_portnumber,
+ template charstring pl_peer_hostname,
+ template integer pl_peer_portnumber) :=
+{
+ client_id := pl_client_id,
+ local_hostname := pl_local_hostname,
+ local_portnumber := pl_local_portnumber,
+ peer_hostname := pl_peer_hostname,
+ peer_portnumber := pl_peer_portnumber
+}
+
+template ASP_SCTP_ConnectFrom t_ASP_SCTP_ConnectFrom
+ (template charstring pl_local_hostname,
+ template integer pl_local_portnumber,
+ template charstring pl_peer_hostname,
+ template integer pl_peer_portnumber) :=
+{
+ local_hostname := pl_local_hostname,
+ local_portnumber := pl_local_portnumber,
+ peer_hostname := pl_peer_hostname,
+ peer_portnumber := pl_peer_portnumber
+}
+
+template ASP_SCTP_RESULT t_ASP_SCTP_RESULT
+ (template integer pl_client_id,
+ template boolean pl_error_status,
+ template charstring pl_error_message) :=
+{
+ client_id := pl_client_id,
+ error_status := pl_error_status,
+ error_message := pl_error_message
+}
+
+template ASP_SCTP_ASSOC_CHANGE tr_S_SCTP_CommunicationUp
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID,
+ sac_state := SCTP_COMM_UP
+}
+
+template ASP_SCTP_ASSOC_CHANGE tr_S_SCTP_CommunicationLost
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID,
+ sac_state := SCTP_COMM_LOST
+}
+
+template ASP_SCTP_ASSOC_CHANGE tr_S_SCTP_ShutdownComplete
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID,
+ sac_state := SCTP_SHUTDOWN_COMP
+}
+
+template ASP_SCTP_SHUTDOWN_EVENT tr_S_SCTP_ShutdownEvent
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID
+}
+
+template ASP_SCTP_ASSOC_CHANGE tr_S_SCTP_Restart
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID,
+ sac_state := SCTP_RESTART
+}
+
+template ASP_SCTP_ASSOC_CHANGE tr_S_SCTP_CANT_STR_ASSOC
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID,
+ sac_state := SCTP_CANT_STR_ASSOC
+}
+
+template ASP_SCTP tr_S_SCTP_DataArrive
+ (in template integer pl_associationID,
+ in template integer pl_streamID,
+ in template integer pl_protocolID,
+ in template PDU_SCTP pl_data) :=
+{
+ client_id := pl_associationID,
+ sinfo_stream := pl_streamID,
+ sinfo_ppid := pl_protocolID,
+ data := pl_data
+}
+
+template ASP_SCTP_Close t_ASP_SCTP_Close
+ (in template integer pl_associationID) :=
+{
+ client_id := pl_associationID
+}
+//******************************
+// End of SCTP related templates
+//******************************
+
+//*****************************
+// Start of M3UA PDU templates.
+//*****************************
+template PDU_M3UA t_PDU_M3UA_ASPUP
+ (in template M3UA_ASP_Identifier pl_aSP_Identifier,
+ in template M3UA_Info_String pl_info_String) :=
+{
+ m3UA_ASPUP := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0301'O,
+ messageLength := 0,
+ messageParameters := {
+ aSP_Identifier := pl_aSP_Identifier,
+ info_String := pl_info_String
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPUP_Ack :=
+{
+ m3UA_ASPUP_Ack := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0304'O,
+ messageLength := 0,
+ messageParameters := {
+ info_String := omit
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPDN :=
+{
+ m3UA_ASPDN := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0302'O,
+ messageLength := 0,
+ messageParameters := {
+ info_String := omit
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPDN_Ack :=
+{
+ m3UA_ASPDN_Ack := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0305'O,
+ messageLength := 0,
+ messageParameters := {
+ info_String := omit
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPAC
+ (in template M3UA_Traffic_Mode_Type pl_traffic_Mode_Type,
+ in template M3UA_Routing_Context pl_routing_Context,
+ in template M3UA_Info_String pl_info_String) :=
+{
+ m3UA_ASPAC := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0401'O,
+ messageLength := 0,
+ messageParameters := {
+ traffic_Mode_Type := pl_traffic_Mode_Type,
+ routing_Context := pl_routing_Context,
+ info_String := pl_info_String
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPAC_Ack
+ (in template M3UA_Traffic_Mode_Type pl_traffic_mode_type,
+ in template M3UA_Routing_Context pl_routing_Context) :=
+{
+ m3UA_ASPAC_Ack := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0403'O,
+ messageLength := 0,
+ messageParameters := {
+ traffic_Mode_Type := pl_traffic_mode_type,
+ routing_Context := pl_routing_Context,
+ info_String := omit
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPIA
+ (in template M3UA_Routing_Context pl_routing_Context,
+ in template M3UA_Info_String pl_info_String) :=
+{
+ m3UA_ASPIA := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0402'O,
+ messageLength := 0,
+ messageParameters := {
+ routing_Context := pl_routing_Context,
+ info_String := pl_info_String
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_ASPIA_Ack
+ (in template M3UA_Routing_Context pl_routing_Context) :=
+{
+ m3UA_ASPIA_Ack := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0404'O,
+ messageLength := 0,
+ messageParameters := {
+ routing_Context := pl_routing_Context,
+ info_String := omit
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_Heartbeat
+ (in template M3UA_Heartbeat_Data pl_heartbeat_Data) :=
+{
+ m3UA_BEAT := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0303'O,
+ messageLength := 0,
+ messageParameters := {
+ heartbeat_Data := pl_heartbeat_Data
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_Beat_Ack
+ (in template M3UA_Heartbeat_Data pl_heartbeat_Data) :=
+{
+ m3UA_BEAT_Ack := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0306'O,
+ messageLength := 0,
+ messageParameters := {
+ heartbeat_Data := pl_heartbeat_Data
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_DATA
+ (in template M3UA_Network_Appearance pl_network_Appearance,
+ in template M3UA_Routing_Context pl_routing_Context,
+ in template M3UA_Protocol_Data pl_protocol_Data,
+ in template M3UA_Correlation_ID pl_correlation_ID) :=
+{
+ m3UA_DATA := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0101'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := pl_network_Appearance,
+ routing_Context := pl_routing_Context,
+ protocol_Data := pl_protocol_Data,
+ correlation_ID := pl_correlation_ID
+ }
+ }
+}
+
+template PDU_M3UA t_PDU_M3UA_DAVA
+ (in template M3UA_Network_Appearance pl_network_Appearance,
+ in template M3UA_Routing_Context pl_routing_Context,
+ in template M3UA_Affected_Point_Codes pl_affected_Point_Codes,
+ in template M3UA_Info_String pl_info_String) :=
+{
+ m3UA_DAVA := {
+ version := '01'O,
+ reserved := '00'O,
+ messageClassAndType := '0202'O,
+ messageLength := 0,
+ messageParameters := {
+ network_Appearance := pl_network_Appearance,
+ routing_Context := pl_routing_Context,
+ affected_Point_Codes := pl_affected_Point_Codes,
+ info_String := pl_info_String
+ }
+ }
+}
+//**************************
+// End of M3UA PDU templates
+//**************************
+
+//**********************************
+// Start of M3UA parameter templates
+//**********************************
+template M3UA_Protocol_Data t_M3UA_Protocol_Data
+ (template OCT4 pl_oPC,
+ template OCT4 pl_dPC,
+ template OCT1 pl_sI,
+ template OCT1 pl_nI,
+ template OCT1 pl_mP,
+ template OCT1 pl_sLS,
+ template octetstring pl_userProtocolData) :=
+{
+ tag := '0210'O,
+ lengthInd := 0,
+ oPC := pl_oPC,
+ dPC := pl_dPC,
+ sI := pl_sI,
+ nI := pl_nI,
+ mP := pl_mP,
+ sLS := pl_sLS,
+ userProtocolData := pl_userProtocolData
+}
+//********************************
+// End of M3UA parameter templates
+//********************************
+
+//***********************************
+// Dynamic part of the M3UA emulation
+//***********************************
+
+function f_M3UA_Emulation(SCTP_Association_Address pl_Boot) runs on M3UA_CT
+{
+ // Initialize parameters from the test case.
+ v_Entity.assoc := pl_Boot;
+ v_Entity.commStatus := aSP_Down_initial_State;
+
+ // At this point, we assume that the ports are already connected and mapped
+ // properly by the user.
+ log("*************************************************");
+ log("M3UA emulation initiated, the test can be started");
+ log("*************************************************");
+
+ f_Initialize_SCTP();
+
+ // Start the main function in an infinte loop.
+ f_M3UA_ScanEvents();
+}
+
+// Initialize the SCTP layer with parameters read from the configuration file.
+// We have only a single association.
+function f_Initialize_SCTP() runs on M3UA_CT
+{
+ v_Entity.commStatus := aSP_Down_sCTP_Initialize_Done;
+ if (tsp_SCTP_Server_Mode) {
+ // Send out a LISTEN message. The communication status doesn't change
+ // here.
+ SCTP_PORT.send
+ (t_ASP_SCTP_Listen(v_Entity.assoc.local_ip_addr,
+ v_Entity.assoc.local_sctp_port));
+ }
+ else {
+ // Send ConnectFrom sequentially, wait for RESULT messages.
+ f_Associate();
+ T_Assoc_restart.start;
+ }
+
+ if (tsp_SCTP_PayloadProtocolID == 3) {
+ if (not tsp_M3UA_Server_Mode) {
+ T_ASPUP_resend.start;
+ T_ASPAC_resend.start;
+ }
+ if (tsp_Enable_M3UA_Heartbeat) {
+ T_Heartbeat.start;
+ }
+ }
+}
+
+// Associate SCTP connection for a M3UA entity.
+function f_Associate() runs on M3UA_CT
+{
+ SCTP_PORT.send(t_ASP_SCTP_ConnectFrom
+ (v_Entity.assoc.local_ip_addr,
+ v_Entity.assoc.local_sctp_port,
+ v_Entity.assoc.remote_ip_addr,
+ v_Entity.assoc.remote_sctp_port));
+
+ T_Timer.start;
+ alt {
+ [] SCTP_PORT.receive(t_ASP_SCTP_RESULT(*, ?, *)) -> value v_ASP_SCTP_RESULT {
+ if (v_ASP_SCTP_RESULT.error_status) {
+ log("Connect failed: ", v_ASP_SCTP_RESULT.error_message);
+ }
+ else {
+ v_Entity.sCTP_Assoc_ID := v_ASP_SCTP_RESULT.client_id;
+ v_Entity.commStatus := aSP_Down_sCTP_Associate_done;
+ log("SCTP_ConnectResult -> connection established from: ",
+ v_Entity.assoc.local_ip_addr, ":", v_Entity.assoc.local_sctp_port,
+ " to server: ", v_Entity.assoc.remote_ip_addr, ":",
+ v_Entity.assoc.remote_sctp_port, " association #",
+ v_Entity.sCTP_Assoc_ID);
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to ",
+ v_Entity.commStatus);
+ }
+ }
+ T_Timer.stop;
+ }
+ [] T_Timer.timeout {
+ log("----------------------------------------------");
+ log("No response received to t_ASP_SCTP_ConnectFrom");
+ log("----------------------------------------------");
+ setverdict(fail);
+ // mtc.stop;
+ }
+ }
+}
+
+// Starts M3UA emulation execution.
+function f_M3UA_ScanEvents() runs on M3UA_CT
+{
+ var ASP_MTP3_TRANSFERreq vl_ASP_MTP3_TRANSFERreq;
+
+ alt {
+ [] MTP3_SP_PORT.receive(ASP_MTP3_TRANSFERreq : ?)
+ -> value vl_ASP_MTP3_TRANSFERreq {
+ f_Send_MTP3_TRANSFERreq(vl_ASP_MTP3_TRANSFERreq);
+ repeat;
+ }
+ [] as_SCTP_CommunicationUp()
+ [] as_SCTP_DataArrive()
+ [] as_SCTP_Connected()
+ [] as_Unexpected_SCTP_Events()
+ [] as_handleM3UA_timers()
+ [] as_handleSCTP_timers()
+ }
+}
+
+function f_Send_MTP3_TRANSFERreq(ASP_MTP3_TRANSFERreq pl_ASP_MTP3_TRANSFERreq)
+ runs on M3UA_CT
+{
+ if (v_Entity.commStatus == aSP_Active) {
+ if (tsp_SCTP_PayloadProtocolID == 3) { // M3UA
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 1,
+ enc_PDU_M3UA
+ (valueof
+ (t_PDU_M3UA_DATA
+ (omit,
+ omit,
+ t_M3UA_Protocol_Data
+ (int2oct(pl_ASP_MTP3_TRANSFERreq.opc, 4), // OPC
+ int2oct(pl_ASP_MTP3_TRANSFERreq.dpc, 4), // DPC
+ bit2oct('0000'B & pl_ASP_MTP3_TRANSFERreq.sio.si), // SIO
+ bit2oct('000000'B & pl_ASP_MTP3_TRANSFERreq.sio.ni),
+ bit2oct('000000'B & pl_ASP_MTP3_TRANSFERreq.sio.prio),
+ int2oct(pl_ASP_MTP3_TRANSFERreq.sls, 1), // SLS
+ pl_ASP_MTP3_TRANSFERreq.data),
+ omit))),
+ tsp_SCTP_PayloadProtocolID));
+ }
+ else { // Non-M3UA
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 1,
+ pl_ASP_MTP3_TRANSFERreq.data,
+ tsp_SCTP_PayloadProtocolID));
+ }
+ if (tsp_logVerbose) {
+ log("MTP3_SP_PORT: ASP_MTP3_TRANSFERreq received -> message sent " &
+ "via SCTP");
+ }
+ }
+ else {
+ // If the SCTP association is not yet running, we have to buffer the data
+ // messages arrived from the MTP3 side. Sending of buffered data messages
+ // should occure when the SCTP association is up and before sending the
+ // data message in reply for a new ASP_MTP3_TRANSFERreq data message. The
+ // buffer should be checked before sending.
+ v_TRANSFERreq_Buffer[sizeof(v_TRANSFERreq_Buffer)] :=
+ pl_ASP_MTP3_TRANSFERreq;
+ if (tsp_logVerbose) {
+ log("MTP3_SP_PORT: ASP_MTP3_TRANSFERreq received in an inactive state " &
+ "-> message was buffered");
+ }
+ }
+}
+
+// Handle communication up messages of users which performed associate earlier.
+// We have only one association.
+altstep as_SCTP_CommunicationUp() runs on M3UA_CT
+{
+ [] SCTP_PORT.receive(tr_S_SCTP_CommunicationUp(?))
+ -> value v_ASP_SCTP_ASSOC_CHANGE {
+ if (v_Entity.sCTP_Assoc_ID == v_ASP_SCTP_ASSOC_CHANGE.client_id) {
+ if (v_Entity.commStatus == aSP_Down_sCTP_Associate_done) {
+ v_Entity.commStatus := aSP_Down_commUP_Received;
+ if (tsp_SCTP_PayloadProtocolID != 3) { // Non-M3UA
+ v_Entity.commStatus := aSP_Active;
+ var integer v_i;
+ for (v_i := 0; v_i < sizeof(v_TRANSFERreq_Buffer); v_i := v_i + 1) {
+ log("Sending buffered message #", v_i);
+ f_Send_MTP3_TRANSFERreq(v_TRANSFERreq_Buffer[v_i]);
+ }
+ v_TRANSFERreq_Buffer := {};
+ // MTP3_SP_PORT.send(ASP_MTP3_RESUME : {});
+ }
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ if ((not tsp_M3UA_Server_Mode) and
+ (tsp_SCTP_PayloadProtocolID == 3)) { // M3UA
+ f_ASPUP_Sending();
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("SCTP_CommunicationUp received in wrong state (i.e. not after " &
+ "SCTP_Associate is done) in state: ", v_Entity.commStatus);
+ }
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association does not exists, received in CommunicationUp");
+ }
+ }
+ repeat;
+ }
+}
+
+// This altstep handles the data received from SCTP.
+altstep as_SCTP_DataArrive() runs on M3UA_CT
+{
+ [] SCTP_PORT.receive(tr_S_SCTP_DataArrive
+ (?, // associationID
+ ?, // streamID
+ ?, // protocolID
+ ? // data
+ )) -> value v_ASP_SCTP {
+ // Checking the identifier for the association is not necessary, because we
+ // have only only one association.
+ if (f_Assoc_Exists(v_ASP_SCTP.client_id)) {
+ if (tsp_logVerbose) {
+ log("Message received on association #", v_Entity.sCTP_Assoc_ID);
+ }
+ if (tsp_SCTP_PayloadProtocolID == 3) { // M3UA
+ v_PDU_M3UA := dec_PDU_M3UA(v_ASP_SCTP.data);
+ f_handle_M3UA_msg(v_PDU_M3UA);
+ }
+ else { // Non-M3UA
+ f_handle_nonM3UA_msg(v_ASP_SCTP.data);
+ }
+ }
+ else{
+ log("Message received on unknown association #", v_Entity.sCTP_Assoc_ID,
+ " -> closing connection");
+ SCTP_PORT.send(t_ASP_SCTP_Close(v_Entity.sCTP_Assoc_ID));
+ log("SCTP connection closed");
+ }
+ repeat;
+ }
+}
+
+// Handle the SCTP connected messages. It is sent from the SCTP side and it
+// signals, that we're on the right track to create the association. This is
+// for server mode.
+altstep as_SCTP_Connected() runs on M3UA_CT
+{
+ [tsp_SCTP_Server_Mode] SCTP_PORT.receive(tr_ASP_SCTP_Connected(?, ?, ?, ?, ?))
+ -> value v_ASP_SCTP_Connected {
+ // Message from the configured endpoint.
+ if ((v_ASP_SCTP_Connected.local_portnumber ==
+ v_Entity.assoc.local_sctp_port) and
+ (v_ASP_SCTP_Connected.local_hostname ==
+ v_Entity.assoc.local_ip_addr) and
+ (v_ASP_SCTP_Connected.peer_portnumber ==
+ v_Entity.assoc.remote_sctp_port) and
+ (v_ASP_SCTP_Connected.peer_hostname ==
+ v_Entity.assoc.remote_ip_addr)) {
+ v_Entity.sCTP_Assoc_ID := v_ASP_SCTP_Connected.client_id;
+ v_Entity.commStatus := aSP_Down_sCTP_Associate_done;
+ log("ASP_SCTP_Connected -> accepted connection from client: ",
+ v_ASP_SCTP_Connected.peer_hostname, ":",
+ v_ASP_SCTP_Connected.peer_portnumber, " on server: ",
+ v_ASP_SCTP_Connected.local_hostname, ":",
+ v_ASP_SCTP_Connected.local_portnumber, " with association #",
+ v_Entity.sCTP_Assoc_ID);
+ }
+ else {
+ log("ASP_SCTP_Connected -> connection from unknown client: ",
+ v_ASP_SCTP_Connected.peer_hostname, ":",
+ v_ASP_SCTP_Connected.peer_portnumber);
+ }
+ repeat;
+ }
+}
+
+// Handle error messages of users.
+altstep as_Unexpected_SCTP_Events() runs on M3UA_CT
+{
+ // Handle communications lost message. State of user with given index jumps
+ // back to initial state and stays there. That user will not be able to
+ // communicate anymore.
+ [] SCTP_PORT.receive(tr_S_SCTP_CommunicationLost(?))
+ -> value v_ASP_SCTP_ASSOC_CHANGE {
+ if (f_Assoc_Exists(v_ASP_SCTP_ASSOC_CHANGE.client_id)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ }
+ v_Entity.commStatus := aSP_Down_sCTP_Initialize_Done;
+ v_Entity.sCTP_Assoc_ID := omit;
+ if (tsp_logVerbose) {
+ log("SCTP_CommunicationLost received");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " cleared, state " &
+ "changed to: ", v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association does not exist, received in CommunicationLost");
+ }
+ }
+ repeat;
+ }
+ [] SCTP_PORT.receive(tr_S_SCTP_ShutdownComplete(?))
+ -> value v_ASP_SCTP_ASSOC_CHANGE {
+ if (f_Assoc_Exists(v_ASP_SCTP_ASSOC_CHANGE.client_id)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ }
+ v_Entity.commStatus := aSP_Down_sCTP_Initialize_Done;
+ if (tsp_logVerbose) {
+ log("SCTP_ShutdownComplete received");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association does not exist, received in ShutdownComplete");
+ }
+ }
+ repeat;
+ }
+ [] SCTP_PORT.receive(tr_S_SCTP_ShutdownEvent(?))
+ -> value v_ASP_SCTP_SHUTDOWN_EVENT {
+ if (f_Assoc_Exists(v_ASP_SCTP_SHUTDOWN_EVENT.client_id)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ }
+ v_Entity.commStatus := aSP_Down_sCTP_Initialize_Done;
+ if (tsp_logVerbose) {
+ log("SCTP_ShutdownEvent received");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association does not exist, received in ShutdownEvent");
+ }
+ }
+ repeat;
+ }
+ [] SCTP_PORT.receive(tr_ASP_SCTP_Connected(?, ?, ?, ?, ?))
+ -> value v_ASP_SCTP_Connected {
+ log("Unexpected ASP_SCTP_Connected");
+ repeat;
+ }
+ [] SCTP_PORT.receive(tr_S_SCTP_Restart(?)) -> value v_ASP_SCTP_ASSOC_CHANGE {
+ if (f_Assoc_Exists(v_ASP_SCTP_ASSOC_CHANGE.client_id)) {
+ log("SCTP_Restart received");
+ v_Entity.commStatus := aSP_Down_commUP_Received;
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association does not exist, received in SCTP_Restart");
+ }
+ }
+ repeat;
+ }
+ [] SCTP_PORT.receive(t_ASP_SCTP_SEND_FAILED(?))
+ -> value v_ASP_SCTP_SEND_FAILED {
+ log("SCTP_Send failed for association #", v_Entity.sCTP_Assoc_ID);
+ if (f_Assoc_Exists(v_ASP_SCTP_SEND_FAILED.client_id)) {
+ // Daemon sends an error status message here.
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ }
+ else {
+ log("Send error received for association that doesn't exist");
+ }
+ repeat;
+ }
+ [] SCTP_PORT.receive(tr_S_SCTP_CANT_STR_ASSOC(?)) {
+ repeat;
+ }
+ [] SCTP_PORT.receive {
+ repeat;
+ }
+}
+
+// After reception of SCTP_CommunicationUp M3UA ASPUP/ASPAC is resent by the
+// entity if it didn't receive ASPUP_Ack/ASPAC_Ack.
+altstep as_handleM3UA_timers() runs on M3UA_CT
+{
+ [] T_ASPUP_resend.timeout {
+ if ((v_Entity.commStatus == aSP_Down_commUP_Received) or
+ (v_Entity.commStatus == aSP_Down_ASPUP_Sent)) {
+ // Try to send ASPUP again.
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPUP(omit, omit))),
+ tsp_SCTP_PayloadProtocolID));
+ v_Entity.commStatus := aSP_Down_ASPUP_Sent;
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ T_ASPUP_resend.start;
+ repeat;
+ }
+
+ [] T_ASPAC_resend.timeout {
+ if ((v_Entity.commStatus == aSP_Inactive) or
+ (v_Entity.commStatus == aSP_Inact_ASPAC_Sent)) {
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPAC(omit, omit, omit))),
+ tsp_SCTP_PayloadProtocolID));
+ v_Entity.commStatus := aSP_Inact_ASPAC_Sent;
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ T_ASPAC_resend.start;
+ repeat;
+ }
+
+ [tsp_Enable_M3UA_Heartbeat] T_Heartbeat.timeout {
+ if (v_Entity.commStatus == aSP_Active) {
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_Heartbeat(omit))),
+ tsp_SCTP_PayloadProtocolID));
+ if (tsp_logVerbose) {
+ log("Heartbeat sent to association #", v_Entity.sCTP_Assoc_ID);
+ }
+ }
+ T_Heartbeat.start;
+ repeat;
+ }
+}
+
+// Handles SCTP timer events. In server mode we don't associate.
+altstep as_handleSCTP_timers() runs on M3UA_CT
+{
+ [not tsp_SCTP_Server_Mode] T_Assoc_restart.timeout {
+ if (v_Entity.commStatus == aSP_Down_sCTP_Initialize_Done) {
+ f_Associate();
+ }
+ T_Assoc_restart.start;
+ repeat;
+ }
+}
+
+// After reception of SCTP CommunicationUp messages M3UA ASPUP is sent by
+// every entity and the M3UA ASPUP_Ack is received by every entity.
+function f_ASPUP_Sending() runs on M3UA_CT
+{
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0, // streamID
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPUP(omit, omit))),
+ tsp_SCTP_PayloadProtocolID));
+ v_Entity.commStatus := aSP_Down_ASPUP_Sent;
+ if (tsp_logVerbose) {
+ log("M3UA_ASPUP sent");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+}
+
+
+// Test if an association with assocID exists or not. We have only one
+// association at the moment, we just check if the given assocID is the same,
+// that is associated with our single entity. If we would have more entities
+// in a table, the index of it should be returned instead of a boolean value.
+function f_Assoc_Exists(integer pl_assocID) runs on M3UA_CT return boolean
+{
+ if (v_Entity.sCTP_Assoc_ID == pl_assocID) {
+ return true;
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " not found");
+ }
+ }
+ return false;
+}
+
+function f_handle_M3UA_msg(PDU_M3UA pl_PDU_M3UA) runs on M3UA_CT
+{
+ if (ischosen(pl_PDU_M3UA.m3UA_DATA)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ // Send ASP_MTP3_TRANSFERind message.
+ MTP3_SP_PORT.send
+ (valueof
+ (tr_ASP_MTP3_TRANSFERind_sio
+ (substr(oct2bit(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.nI), 6, 2),
+ substr(oct2bit(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.mP), 6, 2),
+ substr(oct2bit(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.sI), 4, 4),
+ oct2int(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.oPC),
+ oct2int(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.dPC),
+ oct2int(pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.sLS),
+ pl_PDU_M3UA.m3UA_DATA.messageParameters.protocol_Data.userProtocolData)));
+ if (tsp_logVerbose) {
+ log("MTP3_SP_PORT: Data received -> TRANSFERind sent");
+ }
+ }
+ else {
+ // Buffering indication messages?
+ if (tsp_logVerbose) {
+ log("MTP3_SP_PORT: Data received, no user connected -> discard");
+ }
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_BEAT)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA
+ (valueof
+ (t_PDU_M3UA_Beat_Ack
+ (pl_PDU_M3UA.m3UA_BEAT.messageParameters.heartbeat_Data))),
+ tsp_SCTP_PayloadProtocolID));
+ if (tsp_logVerbose) {
+ log("M3UA_BEAT received -> M3UA_BEAT_Ack sent");
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_BEAT received in wrong state");
+ }
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_BEAT_Ack)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_BEAT_Ack -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_ERR)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_ERR -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_NOTIFY)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_NOTIFY -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DUNA)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DUNA -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DAVA)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DAVA -> discard");
+ }
+ }
+ // In server mode ASP_M3UA_DAUD messages can be received. In response the
+ // server must send ASP_M3UA_DAVA messages. It's not checked if we're
+ // servers or not.
+ else if (ischosen(pl_PDU_M3UA.m3UA_DAUD)) {
+ if ((v_Entity.commStatus == aSP_Inactive) or
+ (v_Entity.commStatus == aSP_Inact_ASPAC_Sent) or
+ (v_Entity.commStatus == aSP_Active)) {
+ // Send ASP_M3UA_DAVA message.
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA
+ (valueof
+ (t_PDU_M3UA_DAVA
+ (pl_PDU_M3UA.m3UA_DAUD.messageParameters.network_Appearance,
+ pl_PDU_M3UA.m3UA_DAUD.messageParameters.routing_Context,
+ pl_PDU_M3UA.m3UA_DAUD.messageParameters.affected_Point_Codes,
+ pl_PDU_M3UA.m3UA_DAUD.messageParameters.info_String))),
+ tsp_SCTP_PayloadProtocolID));
+ if (tsp_logVerbose) {
+ log("M3UA_DAUD received -> DAVA sent");
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_DAUD received in wrong state");
+ }
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_SCON)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_SCON -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DUPU)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DUPU -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DRST)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DRST -> discard");
+ }
+ }
+ // In server mode we can receive M3UA_ASPUP messages. The answer will be a
+ // M3UA_ASPUP_Ack message to the client.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPUP)) {
+ if (((v_Entity.commStatus == aSP_Down_commUP_Received) or
+ (v_Entity.commStatus == aSP_Down_ASPUP_Sent)) and
+ tsp_M3UA_Server_Mode) {
+ v_Entity.commStatus := aSP_Inactive;
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPUP_Ack)),
+ tsp_SCTP_PayloadProtocolID));
+ if (tsp_logVerbose) {
+ log("M3UA_ASPUP received -> M3UA_ASPUP_Ack sent");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_ASPUP received in wrong state or the emulation is not in " &
+ "M3UA server mode");
+ }
+ }
+ }
+ // Receives a M3UA_ASPDN message and sends a M3UA_ASPDN_Ack message in
+ // response.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPDN)) {
+ if ((v_Entity.commStatus == aSP_Inactive) or
+ (v_Entity.commStatus == aSP_Inact_ASPAC_Sent) or
+ (v_Entity.commStatus == aSP_Active)) {
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPDN_Ack)),
+ tsp_SCTP_PayloadProtocolID));
+ if (v_Entity.commStatus == aSP_Active) {
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ }
+ v_Entity.commStatus := aSP_Down_commUP_Received;
+ if (tsp_logVerbose) {
+ log("M3UA_ASPDN received -> ASPDN_Ack sent");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("ASPDN received in wrong state or the emulation is not in M3UA " &
+ "server mode");
+ }
+ }
+ }
+ // The M3UA client receives M3UA_ASPUP_Ack messages from the server. In
+ // response of a M3UA_ASPUP message sent by the client.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPUP_Ack)) {
+ if (((v_Entity.commStatus == aSP_Down_ASPUP_Sent) or
+ (v_Entity.commStatus == aSP_Inactive)) and
+ not tsp_M3UA_Server_Mode) {
+ v_Entity.commStatus := aSP_Inactive;
+ if (tsp_logVerbose) {
+ log("M3UA_ASPUP_Ack received -> send M3UA_ASPAC");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA(valueof(t_PDU_M3UA_ASPAC(omit, omit, omit))),
+ tsp_SCTP_PayloadProtocolID));
+ // The state changes again after sending the M3UA_ASPAC message.
+ v_Entity.commStatus := aSP_Inact_ASPAC_Sent;
+ if (tsp_logVerbose) {
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_ASPUP_Ack received in wrong state or the emulation is not " &
+ "in M3UA client mode");
+ }
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPDN_Ack)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_ASPDN_Ack -> discard");
+ }
+ }
+ // M3UA_ASPAC messages are received on the server side. The server sends a
+ // M3UA_ASPAC_Ack message back to the client. This step makes the
+ // association active on both sides.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPAC)) {
+ if (((v_Entity.commStatus == aSP_Inactive) or
+ (v_Entity.commStatus == aSP_Inact_ASPAC_Sent)) and
+ tsp_M3UA_Server_Mode) {
+ v_Entity.commStatus := aSP_Active;
+ if (tsp_logVerbose) {
+ log("M3UA_ASPAC received -> M3UA_ASPAC_Ack sent");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ var integer v_i;
+ for (v_i := 0; v_i < sizeof(v_TRANSFERreq_Buffer); v_i := v_i + 1) {
+ log("Sending buffered message #", v_i);
+ f_Send_MTP3_TRANSFERreq(v_TRANSFERreq_Buffer[v_i]);
+ }
+ v_TRANSFERreq_Buffer := {};
+ // Send M3UA_ASPAC_Ack.
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA
+ (valueof
+ (t_PDU_M3UA_ASPAC_Ack
+ (pl_PDU_M3UA.m3UA_ASPAC.messageParameters.traffic_Mode_Type,
+ pl_PDU_M3UA.m3UA_ASPAC.messageParameters.routing_Context))),
+ tsp_SCTP_PayloadProtocolID));
+ // MTP3_SP_PORT.send(ASP_MTP3_RESUME : {});
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_ASPAC received in wrong state or the emulation is not in " &
+ "M3UA server mode");
+ }
+ }
+ }
+ // The client receives M3UA_ASPAC_Ack messages from the server. The
+ // association will be activated. The buffered messages should be send here.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPAC_Ack)) {
+ if (((v_Entity.commStatus == aSP_Inact_ASPAC_Sent) or
+ (v_Entity.commStatus == aSP_Active)) and
+ not tsp_M3UA_Server_Mode) {
+ // MTP3_SP_PORT.send(ASP_MTP3_RESUME : {});
+ v_Entity.commStatus := aSP_Active;
+ if (tsp_logVerbose) {
+ log("ASPAC_Ack received for association #", v_Entity.sCTP_Assoc_ID);
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ var integer v_i;
+ for (v_i := 0; v_i < sizeof(v_TRANSFERreq_Buffer); v_i := v_i + 1) {
+ log("Sending buffered message #", v_i);
+ f_Send_MTP3_TRANSFERreq(v_TRANSFERreq_Buffer[v_i]);
+ }
+ v_TRANSFERreq_Buffer := {};
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_ASPAC_Ack received in wrong state on association #",
+ v_Entity.sCTP_Assoc_ID, " or the emulation is not in M3UA " &
+ "client mode");
+ }
+ }
+ }
+ // Receives a M3UA_ASPIA message and sends back a M3UA_ASPIA_Ack message in
+ // response.
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPIA)) {
+ if (v_Entity.commStatus == aSP_Active) {
+ SCTP_PORT.send
+ (t_S_SCTP_Send
+ (v_Entity.sCTP_Assoc_ID,
+ 0,
+ enc_PDU_M3UA
+ (valueof
+ (t_PDU_M3UA_ASPIA_Ack
+ (pl_PDU_M3UA.m3UA_ASPIA.messageParameters.routing_Context))),
+ tsp_SCTP_PayloadProtocolID));
+ // MTP3_SP_PORT.send(ASP_MTP3_PAUSE : {});
+ v_Entity.commStatus := aSP_Inactive;
+ if (tsp_logVerbose) {
+ log("M3UA_ASPIA received -> M3UA_ASPIA_Ack sent");
+ log("Association #", v_Entity.sCTP_Assoc_ID, " state changed to: ",
+ v_Entity.commStatus);
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("M3UA_ASPIA received in wrong state or the emulation is not " &
+ "running in M3UA server mode");
+ }
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_ASPIA_Ack)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_ASPIA_Ack -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_REG_REQ)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_REG_REQ -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_REG_RSP)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_REG_RSP -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DEREG_REQ)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DEREG_REQ -> discard");
+ }
+ }
+ else if (ischosen(pl_PDU_M3UA.m3UA_DEREG_RSP)) {
+ if (tsp_logVerbose) {
+ log("Received M3UA_DEREG_RSP -> discard");
+ }
+ }
+}
+
+function f_handle_nonM3UA_msg(octetstring pl_PDU) runs on M3UA_CT
+{
+ if (v_Entity.commStatus == aSP_Active) {
+ // Send TRANSFERind message.
+ MTP3_SP_PORT.send(valueof
+ (tr_ASP_MTP3_TRANSFERind_sio
+ ('00'B,
+ '00'B,
+ '0000'B,
+ 0,
+ 0,
+ 0,
+ pl_PDU)));
+ if (tsp_logVerbose) {
+ log("Non-M3UA DATA received -> TRANSFERind sent");
+ }
+ }
+ else {
+ if (tsp_logVerbose) {
+ log("DATA received, but no user connected -> discard");
+ }
+ }
+}
+
+}