blob: 6173c874cb3f4bbe8e3904d14b5af4b5fd920546 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2019 Ericsson Telecom AB
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
///////////////////////////////////////////////////////////////////////////////
//
// File: SCTP_Daemon_Dynamic.ttcn
// Description: SDD behaviour
// Rev: <RnXnn>
// Prodnr: CNL 113 630
// Updated: 2012-01-23
// Contact: http://ttcn.ericsson.se
module SCTP_Daemon_Dynamic
{
//=========================================================================
// Import Part
//=========================================================================
import from SCTP_Daemon_Dynamic_Types all;
import from SCTP_Daemon_Dynamic_Interface_Definitions all;
import from TCCInterface_Functions all;
import from TCCConversion_Functions all;
import from IPL4asp_Types all;
import from IPL4asp_PortType all;
import from SCTP_Daemon_Dynamic_IPL4_CtrlFunct all;
//=========================================================================
// Module Parameters
//=========================================================================
modulepar {
// Host name where the SCTP Daemon listens for the testcases
charstring tsp_SDD_TCP_ListenInterface := "127.0.0.1";
// Port number where the SCTP Daemon listens for the testcases
integer tsp_SDD_TCP_ListenPort := 1314;
// Default set of SCTP connections which the SCTP Daemon initializes on startup
// for associations with autoReconnect == true and server associations
SDD_AssociationConfigList tsp_SDD_AssociationList := {};
float tsp_SDD_ReconnectTimer := 2.0;
// inactivity timer -> client associations get closed
float tsp_SDD_InactivityTimer := 60.0;
boolean tsp_debug := false;
}
//=========================================================================
// Altsteps
//=========================================================================
altstep as_Handle_SCTP_Events() runs on SDD_CT {
[] SCTP_PCO.receive(ASP_RecvFrom : ?) -> value vc_asp_SCTP_ReceivedMessage {
debuglog("INFO: ASP_SCTP");
f_RestartInactivityTimer();
var boolean vl_autoReplied := false;
var ASP_Send vl_sctpReply;
var integer index := 0;
for(index := 0; index < sizeof(vc_associationRuntimeAttributesList); index := index + 1) {
if(vc_associationRuntimeAttributesList[index].socket == vc_asp_SCTP_ReceivedMessage.connId) {
break;
}
}
for(var integer i := 0; not vl_autoReplied and (i < sizeof(vc_registeredAutoReplyFunctionList)); i := i + 1) {
vl_autoReplied := vc_registeredAutoReplyFunctionList[i].apply(index, vc_asp_SCTP_ReceivedMessage, vl_sctpReply);
if(vl_autoReplied) {
SCTP_PCO.send(vl_sctpReply);
}
}
if(not vl_autoReplied) {
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList); i := i + 1) {
if(vc_associationRuntimeAttributesList[i].socket == vc_asp_SCTP_ReceivedMessage.connId) {
if (v_Connection_Lookup!=null){
v_TCP_connections_List:=v_Connection_Lookup.apply(vc_asp_SCTP_ReceivedMessage.msg);
for(var integer k := 0; k < sizeof(v_TCP_connections_List); k := k + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
v_TCP_connections_List[k],
{
sctpData := {
messageType := 0, // encoder will replace
associationId := vc_associationList[i].associationId,
sinfo_stream := vc_asp_SCTP_ReceivedMessage.proto.sctp.sinfo_stream,
sinfo_ppid := vc_asp_SCTP_ReceivedMessage.proto.sctp.sinfo_ppid,
dataLength := 0, // encoder will replace
data := vc_asp_SCTP_ReceivedMessage.msg
}
}
});
}
}
else{
for(var integer j := 0; j < sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[i].subscribedTestcases[j],
{
sctpData := {
messageType := 0, // encoder will replace
associationId := vc_associationList[i].associationId,
sinfo_stream := vc_asp_SCTP_ReceivedMessage.proto.sctp.sinfo_stream,
sinfo_ppid := vc_asp_SCTP_ReceivedMessage.proto.sctp.sinfo_ppid,
dataLength := 0, // encoder will replace
data := vc_asp_SCTP_ReceivedMessage.msg
}
}
});
}
}
}
}
}
repeat;
}
[] SCTP_PCO.receive(tr_S_SCTP_AssocChange(?,?)) -> value vc_asp_SCTP_Event {
debuglog("INFO: ASSOC_CHANGE vc_associationRuntimeAttributesList: " & log2str(vc_associationRuntimeAttributesList));
f_RestartInactivityTimer();
var boolean vl_autoHandled := false;
var ASP_Send vl_sctpMsg;
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList); i := i + 1) {
if(vc_associationRuntimeAttributesList[i].socket == vc_asp_SCTP_Event.sctpEvent.sctpAssocChange.clientId) {
//debuglog(log2str(vc_associationList[i]) & " subscribedTestcases: " & log2str(vc_associationRuntimeAttributesList[i].subscribedTestcases));
vl_autoHandled := false;
for(var integer j := 0; not vl_autoHandled and (j < sizeof(vc_registeredAutoStateChangeHandlerFunctionList)); j := j + 1) {
vl_autoHandled := vc_registeredAutoStateChangeHandlerFunctionList[j].apply(i, vc_asp_SCTP_Event.sctpEvent.sctpAssocChange.sac_state, vl_sctpMsg);
if(vl_autoHandled) {
SCTP_PCO.send(vl_sctpMsg);
}
}
if(not vl_autoHandled) {
for(var integer j := 0; j < sizeof( vc_associationRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[i].subscribedTestcases[j],
{
associationChanged := {
messageType := 0,
associationId := vc_associationList[i].associationId,
state := vc_asp_SCTP_Event.sctpEvent.sctpAssocChange.sac_state
}
}
});
}
}
vc_associationRuntimeAttributesList[i].associationState := vc_asp_SCTP_Event.sctpEvent.sctpAssocChange.sac_state;
if(vc_associationRuntimeAttributesList[i].associationState == SCTP_COMM_LOST) {
if(vc_associationList[i].serverAssociation) {
vc_associationRuntimeAttributesList[i].socket := -1;
// initiate reconnect
f_ScheduleReconnect();
}
else{
f_removeAssociation(vc_associationList[i].associationId);
}
}
}
}
repeat;
}
[] SCTP_PCO.receive(tr_S_SCTP_ShutdownEvent) -> value vc_asp_SCTP_Event {
debuglog("INFO: SHUTDOWN");
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList); i := i + 1) {
if(vc_associationRuntimeAttributesList[i].socket == vc_asp_SCTP_Event.sctpEvent.sctpShutDownEvent.clientId) {
vc_associationRuntimeAttributesList[i].associationState := SCTP_COMM_LOST;
vc_associationRuntimeAttributesList[i].socket := -1;
for(var integer j := 0; j < sizeof( vc_associationRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[i].subscribedTestcases[j],
{
associationChanged := {
messageType := 0,
associationId := vc_associationList[i].associationId,
state := SCTP_COMM_LOST
}
}
});
}
f_ScheduleReconnect();
}
}
f_RestartInactivityTimer();
repeat;
}
[] SCTP_PCO.receive(tr_ASP_SCTP_Connected) -> value vc_asp_SCTP_Event {
if(tsp_debug) {
log("@before ASP_SCTP_Connected vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
f_RestartInactivityTimer();
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
if(ispresent(vc_associationList[i].localInterface)) {
if(vc_associationList[i].serverAssociation and
vc_asp_SCTP_Event.connOpened.locName == vc_associationList[i].localInterface.hostName and
vc_asp_SCTP_Event.connOpened.locPort == vc_associationList[i].localInterface.portNumber) {
// book the new association into the database
var integer newIndex := sizeof(vc_associationList);
vc_associationList[newIndex] := c_emptyAssociation;
vc_associationRuntimeAttributesList[newIndex] := c_emptyAssociationRuntimeAttribute;
vc_associationRuntimeAttributesList[newIndex].socket := vc_asp_SCTP_Event.connOpened.connId;
vc_associationRuntimeAttributesList[newIndex].endpointIndex := i;
vc_associationList[newIndex].associationId := f_getNextUniqueAssociationId();
vc_associationList[newIndex].localInterface.hostNameLength := 0;
vc_associationList[newIndex].localInterface.hostName := vc_asp_SCTP_Event.connOpened.locName;
vc_associationList[newIndex].localInterface.portNumber := vc_asp_SCTP_Event.connOpened.locPort;
vc_associationList[newIndex].remoteInterface.hostNameLength := 0;
vc_associationList[newIndex].remoteInterface.hostName := vc_asp_SCTP_Event.connOpened.remName;
vc_associationList[newIndex].remoteInterface.portNumber := vc_asp_SCTP_Event.connOpened.remPort;
vc_associationList[newIndex].autoReconnect := false;
// send notification to all subscribed testcases of the server
for(var integer j := 0; j < sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[i].subscribedTestcases[j],
{
sctpConnected := {
messageType := 0, // encoder will replace
associationId := vc_associationList[newIndex].associationId,
remoteInterface := {
hostNameLength := 0, // encoder will replace
hostName := vc_asp_SCTP_Event.connOpened.locName,
portNumber := vc_asp_SCTP_Event.connOpened.locPort
}
}
}
} );
}
// subscribe the connected association to the server's subscribed testcases
vc_associationRuntimeAttributesList[newIndex].subscribedTestcases := vc_associationRuntimeAttributesList[i].subscribedTestcases;
}
}
}
if(tsp_debug) {
log("@after ASP_SCTP_Connected vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
repeat;
}
[] SCTP_PCO.receive(tr_S_SCTP_PeerAddressChange) {
debuglog("INFO: ASP_SCTP_PEER_ADDR_CHANGE");
f_RestartInactivityTimer();
repeat;
}
[] SCTP_PCO.receive(tr_ASP_SCTP_Closed) {
debuglog("INFO: ASP_SCTP_Closed");
f_RestartInactivityTimer();
repeat;
}
[] SCTP_PCO.receive(tr_ASP_Result) -> value vc_sctpResult {
debuglog("INFO: ASP_SCTP_RESULT");
f_RestartInactivityTimer();
repeat;
}
[] SCTP_PCO.receive {
log("WARNING: unhandled SCTP message received!");
f_RestartInactivityTimer();
repeat;
}
}
altstep as_Handle_TCP_Events() runs on SDD_CT {
[] daemonPort.receive(tr_ASP_TCP_Connected) -> value vc_asp_TCP_Event {
debuglog("INFO: ASP_TCP_Connected");
var f_IPL4_getMsgLen sdd_msglen := refers(f_SDD_getMsgLen);
SCTP_Daemon_Dynamic_IPL4_CtrlFunct.f_IPL4_setGetMsgLen(daemonPort,vc_asp_TCP_Event.connOpened.connId,sdd_msglen,{});
repeat;
}
[] daemonPort.receive(tr_ASP_TCP_Close) -> value vc_tcpClose {
debuglog("INFO: ASP_TCP_Close");
var IntegerList vl_newSubsribedTestcases := {};
if (v_Connection_Delete!=null)
{
v_Connection_Delete.apply(vc_tcpClose.connClosed.connId)
}
else{
// remove subscrition belonging to this client from the vc_associationRuntimeAttributesList.subscribedTestcases
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList); i := i + 1) {
vl_newSubsribedTestcases := {};
for(var integer j := 0; j < sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
if(vc_associationRuntimeAttributesList[i].subscribedTestcases[j] != vc_tcpClose.connClosed.connId) {
vl_newSubsribedTestcases[sizeof(vl_newSubsribedTestcases)] := vc_associationRuntimeAttributesList[i].subscribedTestcases[j];
}
}
if(sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases) != sizeof(vl_newSubsribedTestcases)) {
vc_associationRuntimeAttributesList[i].subscribedTestcases := vl_newSubsribedTestcases;
}
}
}
repeat;
}
/* [] daemonPort.receive(tr_ASP_Result) {
log("*** ERROR: Could not send data on the TCP between the testcase and the SCTP Daemon!");
repeat;
}*/
[] daemonPort.receive(t_close) -> value vc_daemonMessage {
debuglog("INFO: t_close");
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
if(vc_associationList[i].associationId == vc_daemonMessage.msg.sctpClose.associationId) {
if(vc_associationRuntimeAttributesList[i].socket >= 0) {
var Result vl_result := IPL4asp_PortType.f_IPL4_close(SCTP_PCO, vc_associationRuntimeAttributesList[i].socket, {sctp := {omit,omit,omit,omit}});
log("Result of closing socket: ",vl_result);
} else {
log("ERROR: association ", vc_daemonMessage.msg.sctpClose.associationId, " is not alive, not sending ASP_SCTP_Close!");
}
}
}
f_removeAssociation(vc_daemonMessage.msg.sctpClose.associationId);
debuglog("INFO: ASP_SCTP_Close sent, returning to the main alt");
repeat;
}
[] daemonPort.receive(t_queryAssociations) -> value vc_daemonMessage {
daemonPort.send(SDD_Message_with_ClientId : { vc_daemonMessage.client_id, { associations := {
0, // encoder will replace
vc_associationList
} } });
repeat;
}
[] daemonPort.receive(t_connect) -> value vc_daemonMessage {
if(tsp_debug) {
log("@before sctpConnect vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
var integer newIndex := sizeof(vc_associationList);
vc_associationList[newIndex] := c_emptyAssociation;
vc_associationRuntimeAttributesList[newIndex] := c_emptyAssociationRuntimeAttribute;
vc_associationRuntimeAttributesList[newIndex].subscribedTestcases
[sizeof(vc_associationRuntimeAttributesList[newIndex].subscribedTestcases)] := vc_daemonMessage.client_id;
if(ispresent(vc_daemonMessage.msg.sctpConnect.localInterface)) {
vc_associationList[newIndex].localInterface := vc_daemonMessage.msg.sctpConnect.localInterface;
}
vc_associationList[newIndex].remoteInterface := vc_daemonMessage.msg.sctpConnect.remoteInterface;
vc_associationList[newIndex].autoReconnect := vc_daemonMessage.msg.sctpConnect.autoReconnect;
f_Reconnect_SCTP_Association(newIndex);
if(tsp_debug) {
log("@after defineClientAssociation vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
repeat;
}
[] daemonPort.receive(t_listen) -> value vc_daemonMessage {
if(tsp_debug) {
log("@before sctpListen vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
var integer newIndex := sizeof(vc_associationList);
vc_associationList[newIndex] := c_emptyAssociation;
vc_associationRuntimeAttributesList[newIndex] := c_emptyAssociationRuntimeAttribute;
vc_associationRuntimeAttributesList[newIndex].subscribedTestcases
[sizeof(vc_associationRuntimeAttributesList[newIndex].subscribedTestcases)] := vc_daemonMessage.client_id;
vc_associationList[newIndex].serverAssociation := true;
vc_associationList[newIndex].localInterface := {
hostNameLength := 0,
hostName := f_getIpAddr(vc_daemonMessage.msg.sctpListen.localInterface.hostName,f_addressType(vc_daemonMessage.msg.sctpListen.localInterface.hostName)),
portNumber := vc_daemonMessage.msg.sctpListen.localInterface.portNumber
};
f_Init_Server_SCTP_Association(newIndex);
if(tsp_debug) {
log("@after defineServerAssociation vc_associationList: ", vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
repeat;
}
[] daemonPort.receive(t_subscribeToAssociation) -> value vc_daemonMessage {
debuglog("INFO: t_subscribeToAssociation");
var boolean vl_subscribed := false, vl_found := false;
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
if(vc_associationList[i].associationId == vc_daemonMessage.msg.subscribeToAssociation.associationId) {
vl_found := false;
for(var integer j := 0; not vl_found and (j < sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases)); j := j + 1) {
if(vc_associationRuntimeAttributesList[i].subscribedTestcases[j] == vc_daemonMessage.client_id) {
vl_found := true
}
}
if(not vl_found) {
vc_associationRuntimeAttributesList[i].subscribedTestcases[sizeof(vc_associationRuntimeAttributesList[i].subscribedTestcases)] := vc_daemonMessage.client_id;
vl_subscribed := true;
} else {
log("*** WARNING: test case ", vc_daemonMessage.client_id, " is already subscribed to: ", vc_associationList[i]);
}
}
}
if(not vl_subscribed) {
log("*** WARNING: test case ", vc_daemonMessage.client_id, " was not subscribed to any association!");
}
repeat;
}
[] daemonPort.receive(t_sctpData) -> value vc_daemonMessage {
debuglog("INFO: t_sctpData");
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
if(vc_associationList[i].associationId == vc_daemonMessage.msg.sctpData.associationId) {
if (v_Connection_Insert!=null) {v_Connection_Insert.apply(vc_daemonMessage.msg.sctpData.data,vc_daemonMessage.client_id)}
SCTP_PCO.send(ASP_Send:{
connId := vc_associationRuntimeAttributesList[i].socket,
proto :=
{
sctp:=
{
sinfo_stream := vc_daemonMessage.msg.sctpData.sinfo_stream,
sinfo_ppid := vc_daemonMessage.msg.sctpData.sinfo_ppid,
// Multiple remote addresses can be given in case of one-to-many connections.
remSocks := omit,
// Association ID to identify one specific connection in case of one-to-many connections.
assocId := omit
}
},
msg := vc_daemonMessage.msg.sctpData.data
});
}
}
repeat;
}
}
altstep as_Handle_Reconnect() runs on SDD_CT {
[] vc_reconnectTimer.timeout {
if(tsp_debug) {
log("On vc_reconnectTimer.timeout vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList, " vc_associationList: ", vc_associationList);
}
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList); i := i + 1) {
if(vc_associationRuntimeAttributesList[i].socket < 0 and vc_associationList[i].autoReconnect) {
f_Reconnect_SCTP_Association(i);
}
}
repeat;
}
}
altstep as_Handle_Inactivity() runs on SDD_CT {
[] vc_inactivityTimer.timeout {
if(tsp_debug) {
log("On vc_inactivityTimer.timeout vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList, " vc_associationList: ", vc_associationList);
}
log("*** SDD QUIT due to ", tsp_SDD_InactivityTimer, " seconds of inactivity.");
log("*** Please restart SDD if you need it again.");
}
}
//=========================================================================
// Functions
//=========================================================================
function debuglog(in charstring str) {
if(tsp_debug) {
log(str);
}
}
function f_addressType(charstring ip_address)
return TCCInterface_IPAddressType
{
var integer v_index:=f_strstr(ip_address, ":");
log("v_index: ",v_index);
if(v_index == -1)
{
return IPv4;
}
return IPv6;
}
function f_getNextUniqueAssociationId() runs on SDD_CT return integer {
var integer newId := 0;
var boolean found := false;
var boolean exit := false;
while(not exit) {
found := false;
for(var integer i := 0; i < sizeof(vc_associationList) and (not found); i := i + 1) {
if(vc_associationList[i].associationId == newId) {
found := true;
}
}
if(not found) {
exit := true;
} else {
newId := newId + 1;
}
}
debuglog("returning new association id: " & int2str(newId));
return newId;
}
function f_InitTCPServer() runs on SDD_CT {
var Result vl_result := { errorCode := omit, connId := omit, os_error_code:=omit, os_error_text:= omit };
vl_result := SCTP_Daemon_Dynamic_IPL4_CtrlFunct.f_IPL4_listen(daemonPort, tsp_SDD_TCP_ListenInterface, tsp_SDD_TCP_ListenPort, {tcp := {}});
if ((vl_result.errorCode == omit) or (vl_result.errorCode == IPL4_ERROR_TEMPORARILY_UNAVAILABLE))
{
log("Listening on port (TCP)",tsp_SDD_TCP_ListenPort);
var f_IPL4_getMsgLen sdd_msglen := refers(f_SDD_getMsgLen);
SCTP_Daemon_Dynamic_IPL4_CtrlFunct.f_IPL4_setGetMsgLen(daemonPort,vl_result.connId,sdd_msglen,{});
}else{
log("Error during initialization of the TCP port: ",vl_result);
setverdict(fail);
stop;
}
alt{
[] daemonPort.receive(tr_ASP_Result){
log("Result received");
}
[] daemonPort.receive{
log("ERROR: unhandled daemon message received.");
setverdict(fail);
stop;
}
}
}
function f_Init_Server_SCTP_Association(in integer assoc_idx) runs on SDD_CT {
if(vc_associationList[assoc_idx].serverAssociation) {
if(ispresent(vc_associationList[assoc_idx].localInterface)) {
if(vc_associationRuntimeAttributesList[assoc_idx].socket < 0) {
log("Association of server: ",assoc_idx);
vc_associationRuntimeAttributesList[assoc_idx].endpointIndex := f_GetEndpointIndex(vc_associationList[assoc_idx].localInterface);
var Result vl_result := { errorCode := omit, connId := omit, os_error_code:=omit, os_error_text:= omit };
vl_result := IPL4asp_PortType.f_IPL4_listen(SCTP_PCO, vc_associationList[assoc_idx].localInterface.hostName, vc_associationList[assoc_idx].localInterface.portNumber, {sctp := {omit,omit,omit,omit}});
alt{
[] SCTP_PCO.receive(tr_ASP_Result){
log("Result received");
}
[] as_Handle_SCTP_Events();
}
if(vc_associationList[assoc_idx].associationId < 0) {
vc_associationList[assoc_idx].associationId := f_getNextUniqueAssociationId();
}
vc_associationRuntimeAttributesList[assoc_idx].socket := vl_result.connId;
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList[assoc_idx].subscribedTestcases); i := i + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[assoc_idx].subscribedTestcases[i],
{ sctpResult := {
messageType := 0, // encoder will replace
associationId := vc_associationList[assoc_idx].associationId,
errorStatus := not(vl_result.errorCode==omit),
errorMessage := vl_result.os_error_text
}}
} );
}
} else {
log("*** WARNING: SCTP server association ", vc_associationList[assoc_idx].localInterface, " is already listening!");
}
} else {
log("*** ERROR: SCTP server association #", assoc_idx, " is declared as server, but has no localInterface defined!");
}
} else {
if(tsp_debug) {
log("*** INFO: SCTP association ", vc_associationList[assoc_idx], " is not server.");
}
}
}
function f_Reconnect_SCTP_Association(in integer assoc_idx) runs on SDD_CT {
if(vc_associationRuntimeAttributesList[assoc_idx].socket < 0) {
if(ispresent(vc_associationList[assoc_idx].remoteInterface)) {
if(ispresent(vc_associationList[assoc_idx].localInterface)) {
if(not vc_associationList[assoc_idx].serverAssociation) {
vc_associationRuntimeAttributesList[assoc_idx].endpointIndex := f_GetEndpointIndex(vc_associationList[assoc_idx].localInterface);
var Result vl_result := { errorCode := omit, connId := omit, os_error_code:=omit, os_error_text:= omit };
vl_result := IPL4asp_PortType.f_IPL4_connect
(
SCTP_PCO,
vc_associationList[assoc_idx].remoteInterface.hostName,
vc_associationList[assoc_idx].remoteInterface.portNumber,
vc_associationList[assoc_idx].localInterface.hostName,
vc_associationList[assoc_idx].localInterface.portNumber,
connId := -1,
proto :=
{
sctp:=
{
sinfo_stream := omit,
sinfo_ppid := omit,
remSocks := omit,
assocId := omit
}
},
options := {}
);
} else {
if(vc_associationList[assoc_idx].serverAssociation) {
log("WARNING: association ", vc_associationList[assoc_idx].localInterface,
" is declared as server association, but also initiates client connection to ",
vc_associationList[assoc_idx].remoteInterface);}
}
}
else {
log("WARNING: association ", vc_associationList[assoc_idx].remoteInterface,
" localInterface is missing ");
}
timer t_wait := 10.0; t_wait.start;
alt {
[] SCTP_PCO.receive(tr_ASP_Result)-> value vc_sctpResult{
if ((vc_sctpResult.result.errorCode == omit) or (vc_sctpResult.result.errorCode == IPL4_ERROR_TEMPORARILY_UNAVAILABLE)) //if not error
{
vc_associationRuntimeAttributesList[assoc_idx].socket := vc_sctpResult.result.connId;
if(vc_associationList[assoc_idx].associationId < 0) {
vc_associationList[assoc_idx].associationId := f_getNextUniqueAssociationId();
}
}
else
{
f_ScheduleReconnect();
}
for(var integer i := 0; i < sizeof(vc_associationRuntimeAttributesList[assoc_idx].subscribedTestcases); i := i + 1) {
daemonPort.send(SDD_Message_with_ClientId : {
vc_associationRuntimeAttributesList[assoc_idx].subscribedTestcases[i],
{ sctpResult := {
messageType := 0, // encoder will replace
associationId := vc_associationList[assoc_idx].associationId,
errorStatus := not(vc_sctpResult.result.errorCode==omit),
errorMessage := vc_sctpResult.result.os_error_text
}}
} );
}
if(tsp_debug) {
log("@after ASP_SCTP_RESULT vc_associationList: ",vc_associationList, ", vc_associationRuntimeAttributesList: ", vc_associationRuntimeAttributesList);
}
}
[] as_Handle_SCTP_Events();
[] t_wait.timeout {
log("WARNING: SCTP association to " & log2str(vc_associationList[assoc_idx].remoteInterface) & " could not be established!");
f_ScheduleReconnect();
}
}
} else {
if(vc_associationList[assoc_idx].serverAssociation) {
if(tsp_debug) {
log("*** INFO: SCTP association ", vc_associationList[assoc_idx].localInterface, " is server only.");
}
} else {
log("*** ERROR: SCTP association ", vc_associationList[assoc_idx].localInterface, " is not a server association!");
}
}
} else if(ispresent(vc_associationList[assoc_idx].remoteInterface)) {
log("*** WARNING: SCTP association to " & log2str(vc_associationList[assoc_idx].remoteInterface) & " is already active!");
}
}
function f_removeAssociation(in integer pl_associationId) runs on SDD_CT {
var SDD_AssociationList newAssociationList := {};
var AssociationRuntimeAttributesList newAssociationRuntimeAttributesList := {};
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
if(vc_associationList[i].associationId != pl_associationId) {
newAssociationList[sizeof(newAssociationList)] := vc_associationList[i];
newAssociationRuntimeAttributesList[sizeof(newAssociationRuntimeAttributesList)] := vc_associationRuntimeAttributesList[i];
}
}
if(sizeof(newAssociationList) != sizeof(vc_associationList)) {
vc_associationList := newAssociationList;
vc_associationRuntimeAttributesList := newAssociationRuntimeAttributesList;
} else {
log("*** ERROR: SCTP association to delete: ", pl_associationId, " was not found in the database.");
}
}
function f_GetEndpointIndex(in SDD_Interface pl_interface) runs on SDD_CT return integer {
for(var integer vl_i := 0; vl_i < sizeof(v_localEndpointList); vl_i := vl_i + 1) {
if((v_localEndpointList[vl_i].hostName == pl_interface.hostName) and (v_localEndpointList[vl_i].portNumber == pl_interface.portNumber)) {
return vl_i;
}
}
v_localEndpointList[sizeof(v_localEndpointList)] := pl_interface;
return sizeof(v_localEndpointList) - 1;
}
function f_ScheduleReconnect() runs on SDD_CT {
if(not vc_reconnectTimer.running) {
vc_reconnectTimer.start(tsp_SDD_ReconnectTimer);
}
}
function f_RestartInactivityTimer() runs on SDD_CT {
if(tsp_SDD_InactivityTimer > 0.0) {
if(vc_inactivityTimer.running) {
vc_inactivityTimer.stop;
};
vc_inactivityTimer.start(tsp_SDD_InactivityTimer);
debuglog("### Inactivity timer restarted.");
}
}
function f_RegisterAutoReplyFunction(in f_SDD_AutoReplyFunction autoReplyFunction) runs on SDD_CT {
vc_registeredAutoReplyFunctionList[sizeof(vc_registeredAutoReplyFunctionList)] := autoReplyFunction;
}
function f_RegisterAutoStateChangeHandlerFunction(in f_SDD_AutoStateChangeHandlerFunction autoStateChangeHandlerFunction) runs on SDD_CT {
vc_registeredAutoStateChangeHandlerFunctionList[sizeof(vc_registeredAutoStateChangeHandlerFunctionList)] := autoStateChangeHandlerFunction;
}
function f_SDD() runs on SDD_CT {
map(mtc:daemonPort, system:daemonPort);
map(mtc:SCTP_PCO, system:SCTP_PCO);
f_InitTCPServer();
for(var integer i := 0; i < sizeof(tsp_SDD_AssociationList); i := i + 1) {
vc_associationList[i] := {
associationId := -1,
serverAssociation:= tsp_SDD_AssociationList[i].serverAssociation,
autoReconnect := tsp_SDD_AssociationList[i].autoReconnect,
localInterfacePresent := false, // enter always false
localInterface := {
hostNameLength := 0,
hostName := f_getIpAddr(tsp_SDD_AssociationList[i].localInterface.hostName,f_addressType(tsp_SDD_AssociationList[i].localInterface.hostName)),
portNumber := tsp_SDD_AssociationList[i].localInterface.portNumber
},
remoteInterfacePresent := false, // enter always false
remoteInterface := tsp_SDD_AssociationList[i].remoteInterface
};
// clientIds: empty, associationState: SCTP_COMM_LOST
vc_associationRuntimeAttributesList[i] := c_emptyAssociationRuntimeAttribute;
}
for(var integer i := 0; i < sizeof(vc_associationList); i := i + 1) {
f_Init_Server_SCTP_Association(i);
f_Reconnect_SCTP_Association(i);
}
alt {
[] as_Handle_TCP_Events()
[] as_Handle_Reconnect()
[] as_Handle_SCTP_Events()
[] as_Handle_Inactivity()
}
//timer t_wait := 500.0; t_wait.start; t_wait.timeout;
unmap(mtc:daemonPort, system:daemonPort);
unmap(mtc:SCTP_PCO, system:SCTP_PCO);
}
//=========================================================================
// Testcases
//=========================================================================
testcase tc_SDD() runs on SDD_CT {
f_SDD();
}
//=========================================================================
// Control
//=========================================================================
control {
execute(tc_SDD());
}
} // end of module