forked from ttcn3/osmo-ttcn3-hacks
1308 lines
40 KiB
Plaintext
1308 lines
40 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// 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");
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|