blob: 3cf6bfd511d87cefbd97509810acf9ab108e04fd [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: IP_Daemon_Dynamic.ttcn
// Description: IPDD behaviour
module IP_Daemon_Dynamic
{
//=========================================================================
// Import Part
//=========================================================================
import from IP_Daemon_Dynamic_Types all;
import from IP_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 IP_Daemon_Dynamic_IPL4_CtrlFunct all;
//=========================================================================
// Module Parameters
//=========================================================================
modulepar {
// Host name where the IP Daemon listens for the testcases
charstring tsp_IPDD_TCP_ListenInterface := "127.0.0.1";
// Port number where the IP Daemon listens for the testcases
integer tsp_IPDD_TCP_ListenPort := 1314;
// Default set of IP connections which the IP Daemon initializes on startup
// for connections with autoReconnect == true and server connections
IPDD_ConnectionConfigList tsp_IPDD_ConnectionList := {};
float tsp_IPDD_ReconnectTimer := 2.0;
// inactivity timer -> client connections get closed
float tsp_IPDD_InactivityTimer := 60.0;
boolean tsp_debug := false;
}
//=========================================================================
// Altsteps
//=========================================================================
altstep as_Handle_IP_Events() runs on IPDD_CT {
[] IP_PCO.receive(ASP_RecvFrom : ?) -> value vc_asp_IP_ReceivedMessage {
debuglog("INFO: ASP_IP");
f_RestartInactivityTimer();
var boolean vl_autoReplied := false;
var ASP_Send vl_ipReply;
var integer index := 0;
for(index := 0; index < sizeof(vc_connectionRuntimeAttributesList); index := index + 1) {
if(vc_connectionRuntimeAttributesList[index].socket == vc_asp_IP_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_IP_ReceivedMessage, vl_ipReply);
if(vl_autoReplied and vl_ipReply.connId > 0)
{
if(ischosen(vc_asp_IP_ReceivedMessage.proto.udp))
{
var ASP_SendTo vl_udpReply :=
{
connId := vl_ipReply.connId,
remName := vc_asp_IP_ReceivedMessage.remName,
remPort := vc_asp_IP_ReceivedMessage.remPort,
proto := vl_ipReply.proto,
msg := vl_ipReply.msg
};
IP_PCO.send(vl_udpReply);
}
else
{
IP_PCO.send(vl_ipReply);
}
}
}
if(not vl_autoReplied) {
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket == vc_asp_IP_ReceivedMessage.connId) {
if(ischosen(vc_asp_IP_ReceivedMessage.proto.sctp)) {
if(v_Connection_Lookup != null) {
v_TCP_connections_List:=v_Connection_Lookup.apply(vc_asp_IP_ReceivedMessage.msg);
for(var integer k := 0; k < sizeof(v_TCP_connections_List); k := k + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
v_TCP_connections_List[k],
{
ipdd_data := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId,
sctpAttributesPresent := true,
sctpAttributes := {
sinfo_stream := vc_asp_IP_ReceivedMessage.proto.sctp.sinfo_stream,
sinfo_ppid := vc_asp_IP_ReceivedMessage.proto.sctp.sinfo_ppid
},
dataLength := 0, // encoder will replace
data := vc_asp_IP_ReceivedMessage.msg
}
}
});
}
}
else {
for(var integer j := 0; j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_data := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId,
sctpAttributesPresent := true,
sctpAttributes := {
sinfo_stream := vc_asp_IP_ReceivedMessage.proto.sctp.sinfo_stream,
sinfo_ppid := vc_asp_IP_ReceivedMessage.proto.sctp.sinfo_ppid
},
dataLength := 0, // encoder will replace
data := vc_asp_IP_ReceivedMessage.msg
}
}
});
}
}
}
if(ischosen(vc_asp_IP_ReceivedMessage.proto.tcp) or ischosen(vc_asp_IP_ReceivedMessage.proto.udp)) {
if(v_Connection_Lookup != null) {
v_TCP_connections_List:=v_Connection_Lookup.apply(vc_asp_IP_ReceivedMessage.msg);
for(var integer k := 0; k < sizeof(v_TCP_connections_List); k := k + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
v_TCP_connections_List[k],
{
ipdd_data := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId,
sctpAttributesPresent := false,
sctpAttributes := omit,
dataLength := 0, // encoder will replace
data := vc_asp_IP_ReceivedMessage.msg
}
}
});
}
}
else {
for(var integer j := 0; j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_data := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId,
sctpAttributesPresent := false,
sctpAttributes := omit,
dataLength := 0, // encoder will replace
data := vc_asp_IP_ReceivedMessage.msg
}
}
});
}
}
}
if(ischosen(vc_asp_IP_ReceivedMessage.proto.udp))
{
vc_connectionList[i].remoteInterface :=
{
hostNameLength := 0,
hostName := vc_asp_IP_ReceivedMessage.remName,
portNumber := vc_asp_IP_ReceivedMessage.remPort
}
}
}
}
}
repeat;
}
[] IP_PCO.receive(ASP_Event : { result := ? } ) -> value vc_asp_IP_Event {
debuglog("INFO: ASSOC_CHANGE vc_connectionRuntimeAttributesList: " & log2str(vc_connectionRuntimeAttributesList));
f_RestartInactivityTimer();
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket == vc_asp_IP_Event.result.connId) {
//debuglog(log2str(vc_connectionList[i]) & " subscribedTestcases: " & log2str(vc_connectionRuntimeAttributesList[i].subscribedTestcases));
for(var integer j := 0; j < sizeof( vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_connectionChanged := {
messageType := 0,
connectionId := vc_connectionList[i].connectionId,
eventPresent := true,
event := {
errorCodePresent := true,
errorCode := vc_asp_IP_Event.result.errorCode,
os_error_codePresent := true,
os_error_code := vc_asp_IP_Event.result.os_error_code,
os_error_textLength := 0,
os_error_text := vc_asp_IP_Event.result.os_error_text
},
sctpStatePresent := false,
sctpState := omit
}
}
});
}
}
}
repeat;
}
[] IP_PCO.receive(tr_sctpEvent(?, ?)) -> value vc_asp_IP_Event {
debuglog("INFO: ASSOC_CHANGE vc_connectionRuntimeAttributesList: " & log2str(vc_connectionRuntimeAttributesList));
f_RestartInactivityTimer();
var boolean vl_autoHandled := false;
var ASP_Send vl_ipMsg;
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket == vc_asp_IP_Event.sctpEvent.sctpAssocChange.clientId) {
//debuglog(log2str(vc_connectionList[i]) & " subscribedTestcases: " & log2str(vc_connectionRuntimeAttributesList[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_IP_Event.sctpEvent.sctpAssocChange.sac_state, vl_ipMsg);
if(vl_autoHandled) {
IP_PCO.send(vl_ipMsg);
}
}
if(not vl_autoHandled) {
for(var integer j := 0; j < sizeof( vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_connectionChanged := {
messageType := 0,
connectionId := vc_connectionList[i].connectionId,
eventPresent := false,
event := omit,
sctpStatePresent := true,
sctpState := vc_asp_IP_Event.sctpEvent.sctpAssocChange.sac_state
}
}
});
}
}
vc_connectionRuntimeAttributesList[i].sctpState := vc_asp_IP_Event.sctpEvent.sctpAssocChange.sac_state;
if(vc_connectionRuntimeAttributesList[i].sctpState == SCTP_COMM_LOST) {
if(vc_connectionList[i].serverConnection) {
vc_connectionRuntimeAttributesList[i].socket := -1;
// initiate reconnect
f_ScheduleReconnect();
}
else{
f_removeConnection(vc_connectionList[i].connectionId);
}
}
}
}
repeat;
}
[] IP_PCO.receive(tr_S_SCTP_ShutdownEvent) -> value vc_asp_IP_Event {
debuglog("INFO: SHUTDOWN");
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket == vc_asp_IP_Event.sctpEvent.sctpShutDownEvent.clientId) {
vc_connectionRuntimeAttributesList[i].sctpState := SCTP_COMM_LOST;
for(var integer j := 0; j < sizeof( vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_connectionChanged := {
messageType := 0,
connectionId := vc_connectionList[i].connectionId,
eventPresent := false,
event := omit,
sctpStatePresent := true,
sctpState := vc_connectionRuntimeAttributesList[i].sctpState
}
}
});
}
f_ScheduleReconnect();
}
}
f_RestartInactivityTimer();
repeat;
}
[] IP_PCO.receive(tr_ASP_IP_Connected) -> value vc_asp_IP_Event {
if(tsp_debug) {
log("@before ASP_IP_Connected vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
f_RestartInactivityTimer();
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(ispresent(vc_connectionList[i].localInterface)) {
if(vc_connectionList[i].serverConnection and
vc_asp_IP_Event.connOpened.locName == vc_connectionList[i].localInterface.hostName and
vc_asp_IP_Event.connOpened.locPort == vc_connectionList[i].localInterface.portNumber and
f_IPDD_ProtoMatches(vc_asp_IP_Event.connOpened.proto, vc_connectionList[i].proto)) {
// book the new connection into the database
var integer newIndex := sizeof(vc_connectionList);
vc_connectionList[newIndex] := c_emptyConnection;
vc_connectionRuntimeAttributesList[newIndex] := c_emptyConnectionRuntimeAttribute;
vc_connectionRuntimeAttributesList[newIndex].socket := vc_asp_IP_Event.connOpened.connId;
vc_connectionRuntimeAttributesList[newIndex].endpointIndex := i;
vc_connectionList[newIndex].connectionId := f_getNextUniqueConnectionId();
vc_connectionList[newIndex].localInterface.hostNameLength := 0;
vc_connectionList[newIndex].localInterface.hostName := vc_asp_IP_Event.connOpened.locName;
vc_connectionList[newIndex].localInterface.portNumber := vc_asp_IP_Event.connOpened.locPort;
vc_connectionList[newIndex].remoteInterface.hostNameLength := 0;
vc_connectionList[newIndex].remoteInterface.hostName := vc_asp_IP_Event.connOpened.remName;
vc_connectionList[newIndex].remoteInterface.portNumber := vc_asp_IP_Event.connOpened.remPort;
vc_connectionList[newIndex].autoReconnect := false;
vc_connectionList[newIndex].proto := vc_connectionList[i].proto;
// send notification to all subscribed testcases of the server
for(var integer j := 0; j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_connected := {
messageType := 0, // encoder will replace
serverId := vc_connectionList[i].connectionId,
connectionId := vc_connectionList[newIndex].connectionId,
remoteInterface := {
hostNameLength := 0, // encoder will replace
hostName := vc_asp_IP_Event.connOpened.locName,
portNumber := vc_asp_IP_Event.connOpened.locPort
}
}
}
} );
}
// subscribe the connected connection to the server's subscribed testcases
vc_connectionRuntimeAttributesList[newIndex].subscribedTestcases := vc_connectionRuntimeAttributesList[i].subscribedTestcases;
}
}
}
if(tsp_debug) {
log("@after ASP_IP_Connected vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
repeat;
}
[] IP_PCO.receive(tr_S_SCTP_PeerAddressChange) {
debuglog("INFO: ASP_IP_PEER_ADDR_CHANGE");
f_RestartInactivityTimer();
repeat;
}
[] IP_PCO.receive(tr_ASP_IP_Closed) -> value vc_asp_IP_Event {
debuglog("INFO: ASP_IP_Closed");
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket == vc_asp_IP_Event.connClosed.connId) {
for(var integer j := 0; j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[j],
{
ipdd_closed := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId
}
}
});
}
vc_connectionRuntimeAttributesList[i].socket := -1;
}
}
f_RestartInactivityTimer();
repeat;
}
[] IP_PCO.receive(tr_ASP_Result) -> value vc_ipResult {
debuglog("INFO: ASP_IP_RESULT");
f_RestartInactivityTimer();
repeat;
}
[] IP_PCO.receive {
log("*** WARNING: unhandled IP message received!");
f_RestartInactivityTimer();
repeat;
}
}
altstep as_Handle_TCP_Events() runs on IPDD_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_IPDD_getMsgLen);
IP_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_connectionRuntimeAttributesList.subscribedTestcases
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
vl_newSubsribedTestcases := {};
for(var integer j := 0; j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases); j := j + 1) {
if(vc_connectionRuntimeAttributesList[i].subscribedTestcases[j] != vc_tcpClose.connClosed.connId) {
vl_newSubsribedTestcases[sizeof(vl_newSubsribedTestcases)] := vc_connectionRuntimeAttributesList[i].subscribedTestcases[j];
}
}
if(sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases) != sizeof(vl_newSubsribedTestcases)) {
vc_connectionRuntimeAttributesList[i].subscribedTestcases := vl_newSubsribedTestcases;
}
}
}
repeat;
}
[] daemonPort.receive(t_close) -> value vc_daemonMessage {
debuglog("INFO: t_close");
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(vc_connectionList[i].connectionId == vc_daemonMessage.msg.ipdd_close.connectionId) {
if(vc_connectionRuntimeAttributesList[i].socket >= 0) {
var Result vl_result := IPL4asp_PortType.f_IPL4_close(IP_PCO, vc_connectionRuntimeAttributesList[i].socket, f_IPDD_getIPL4_Proto(i));
log("*** INFO: result of closing socket: ", vl_result);
daemonPort.send(IPDD_Message_with_ClientId : {
vc_daemonMessage.client_id,
{ ipdd_result := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[i].connectionId,
errorStatus := not(vl_result.errorCode==omit),
errorMessage := vl_result.os_error_text
}}
} );
} else {
log("*** ERROR: connection ", vc_daemonMessage.msg.ipdd_close.connectionId, " is not alive, not sending ASP_IP_Close!");
}
}
}
f_removeConnection(vc_daemonMessage.msg.ipdd_close.connectionId);
debuglog("INFO: ASP_IP_Close sent, returning to the main alt");
repeat;
}
[] daemonPort.receive(t_queryConnections) -> value vc_daemonMessage {
daemonPort.send(IPDD_Message_with_ClientId : { vc_daemonMessage.client_id, { ipdd_connections := {
0, // encoder will replace
vc_connectionList
} } });
repeat;
}
[] daemonPort.receive(t_connect) -> value vc_daemonMessage {
if(tsp_debug) {
log("@before ipdd_connect vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
var integer newIndex := sizeof(vc_connectionList);
vc_connectionList[newIndex] := c_emptyConnection;
vc_connectionRuntimeAttributesList[newIndex] := c_emptyConnectionRuntimeAttribute;
vc_connectionRuntimeAttributesList[newIndex].subscribedTestcases
[sizeof(vc_connectionRuntimeAttributesList[newIndex].subscribedTestcases)] := vc_daemonMessage.client_id;
if(ispresent(vc_daemonMessage.msg.ipdd_connect.localInterface)) {
vc_connectionList[newIndex].localInterface := vc_daemonMessage.msg.ipdd_connect.localInterface;
}
vc_connectionList[newIndex].remoteInterface := vc_daemonMessage.msg.ipdd_connect.remoteInterface;
vc_connectionList[newIndex].autoReconnect := vc_daemonMessage.msg.ipdd_connect.autoReconnect;
vc_connectionList[newIndex].proto := vc_daemonMessage.msg.ipdd_connect.proto;
f_Reconnect_IP_Connection(newIndex);
f_RunAutoStartupFunctions(newIndex);
if(tsp_debug) {
log("@after defineClientConnection vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
repeat;
}
[] daemonPort.receive(t_listen) -> value vc_daemonMessage {
if(tsp_debug) {
log("@before sctpListen vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
var integer newIndex := sizeof(vc_connectionList);
vc_connectionList[newIndex] := c_emptyConnection;
vc_connectionRuntimeAttributesList[newIndex] := c_emptyConnectionRuntimeAttribute;
vc_connectionRuntimeAttributesList[newIndex].subscribedTestcases
[sizeof(vc_connectionRuntimeAttributesList[newIndex].subscribedTestcases)] := vc_daemonMessage.client_id;
vc_connectionList[newIndex].serverConnection := true;
vc_connectionList[newIndex].localInterface := {
hostNameLength := 0,
hostName := f_getIpAddr(vc_daemonMessage.msg.ipdd_listen.localInterface.hostName,f_addressType(vc_daemonMessage.msg.ipdd_listen.localInterface.hostName)),
portNumber := vc_daemonMessage.msg.ipdd_listen.localInterface.portNumber
};
vc_connectionList[newIndex].proto := vc_daemonMessage.msg.ipdd_listen.proto;
f_Init_Server_IP_Connection(newIndex);
f_RunAutoStartupFunctions(newIndex);
if(tsp_debug) {
log("@after defineServerConnection vc_connectionList: ", vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
repeat;
}
[] daemonPort.receive(t_subscribeToConnection) -> value vc_daemonMessage {
debuglog("INFO: t_subscribeToConnection");
var boolean vl_subscribed := false, vl_found := false;
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(vc_connectionList[i].connectionId == vc_daemonMessage.msg.ipdd_subscribeToConnection.connectionId) {
vl_found := false;
for(var integer j := 0; not vl_found and (j < sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases)); j := j + 1) {
if(vc_connectionRuntimeAttributesList[i].subscribedTestcases[j] == vc_daemonMessage.client_id) {
vl_found := true
}
}
if(not vl_found) {
vc_connectionRuntimeAttributesList[i].subscribedTestcases[sizeof(vc_connectionRuntimeAttributesList[i].subscribedTestcases)] := vc_daemonMessage.client_id;
vl_subscribed := true;
} else {
log("*** WARNING: test case ", vc_daemonMessage.client_id, " is already subscribed to: ", vc_connectionList[i]);
}
}
}
if(not vl_subscribed) {
log("*** WARNING: test case ", vc_daemonMessage.client_id, " was not subscribed to any connection!");
}
repeat;
}
[] daemonPort.receive(t_ipData) -> value vc_daemonMessage {
debuglog("INFO: t_sctpData");
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(vc_connectionList[i].connectionId == vc_daemonMessage.msg.ipdd_data.connectionId) {
if (v_Connection_Insert!=null) {v_Connection_Insert.apply(vc_daemonMessage.msg.ipdd_data.data,vc_daemonMessage.client_id)}
if(vc_connectionList[i].proto != udp)
{
var ASP_Send vl_send := {
connId := vc_connectionRuntimeAttributesList[i].socket,
proto := { tcp := {} },
msg := vc_daemonMessage.msg.ipdd_data.data
}
vl_send.proto := f_IPDD_getIPL4_Proto(i);
if (vc_connectionList[i].proto == sctp and vc_daemonMessage.msg.ipdd_data.sctpAttributesPresent) {
vl_send.proto.sctp.sinfo_stream := vc_daemonMessage.msg.ipdd_data.sctpAttributes.sinfo_stream;
vl_send.proto.sctp.sinfo_ppid := vc_daemonMessage.msg.ipdd_data.sctpAttributes.sinfo_ppid;
}
IP_PCO.send(vl_send);
}
else
{
var ASP_SendTo vl_send := {
connId := vc_connectionRuntimeAttributesList[i].socket,
remName := vc_connectionList[i].remoteInterface.hostName,
remPort := vc_connectionList[i].remoteInterface.portNumber,
proto := { udp := { } },
msg := vc_daemonMessage.msg.ipdd_data.data
}
IP_PCO.send(vl_send);
}
}
}
repeat;
}
[] daemonPort.receive(PortEvent : { result := ? }) -> value vc_asp_TCP_Event {
log("*** INFO: ignoring result.");
repeat;
}
}
altstep as_Handle_Reconnect() runs on IPDD_CT {
[] vc_reconnectTimer.timeout {
if(tsp_debug) {
log("On vc_reconnectTimer.timeout vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList, " vc_connectionList: ", vc_connectionList);
}
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList); i := i + 1) {
if(vc_connectionRuntimeAttributesList[i].socket < 0 and vc_connectionList[i].autoReconnect) {
f_Reconnect_IP_Connection(i);
f_RunAutoStartupFunctions(i);
}
}
repeat;
}
}
altstep as_Handle_Inactivity() runs on IPDD_CT {
[] vc_inactivityTimer.timeout {
if(tsp_debug) {
log("On vc_inactivityTimer.timeout vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList, " vc_connectionList: ", vc_connectionList);
}
log("*** IPDD QUIT due to ", tsp_IPDD_InactivityTimer, " seconds of inactivity.");
log("*** Please restart IPDD if you need it again.");
}
}
//=========================================================================
// Functions
//=========================================================================
function debuglog(in charstring str) {
if(tsp_debug) {
log(str);
}
}
function f_IPDD_ProtoMatches(in ProtoTuple pl_protoTuple, in ProtoTupleEnum pl_protoTupleEnum) return boolean {
select (pl_protoTupleEnum) {
case (udp) {
if(ischosen(pl_protoTuple.udp)) {
return true;
}
}
case (tcp) {
if(ischosen(pl_protoTuple.tcp)) {
return true;
}
}
case (sctp) {
if(ischosen(pl_protoTuple.sctp)) {
return true;
}
}
case (ssl) {
if(ischosen(pl_protoTuple.ssl)) {
return true;
}
}
case (unspecified) {
if(ischosen(pl_protoTuple.unspecified)) {
return true;
}
}
case else {
log("*** WARNING: unhandled protoTuple type!");
}
}
return false;
}
function f_IPDD_getIPL4_Proto(in integer pl_idx) runs on IPDD_CT return ProtoTuple {
var ProtoTuple vl_ret := { sctp := { omit, omit, omit, omit} };
select (vc_connectionList[pl_idx].proto) {
case (sctp) {
vl_ret := { sctp := { omit, omit, omit, omit} }
}
case (tcp) {
vl_ret := { tcp := { } };
}
case (udp) {
vl_ret := { udp := { } };
}
case (ssl) {
vl_ret := { ssl := { } };
}
case (unspecified) {
vl_ret := { unspecified := { } };
}
case else {
log("*** WARNING: unhandled protoTuple type!!!");
}
}
return vl_ret;
}
function f_addressType(charstring ip_address) return TCCInterface_IPAddressType {
var integer v_index := f_strstr(ip_address, ":");
if(v_index == -1) {
return IPv4;
}
return IPv6;
}
function f_getNextUniqueConnectionId() runs on IPDD_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_connectionList) and (not found); i := i + 1) {
if(vc_connectionList[i].connectionId == newId) {
found := true;
}
}
if(not found) {
exit := true;
} else {
newId := newId + 1;
}
}
debuglog("returning new connection id: " & int2str(newId));
return newId;
}
function f_InitTCPServer() runs on IPDD_CT {
var Result vl_result := { errorCode := omit, connId := omit, os_error_code:=omit, os_error_text:= omit };
vl_result := IP_Daemon_Dynamic_IPL4_CtrlFunct.f_IPL4_listen(daemonPort, tsp_IPDD_TCP_ListenInterface, tsp_IPDD_TCP_ListenPort, {tcp := {}});
if ((vl_result.errorCode == omit) or (vl_result.errorCode == IPL4_ERROR_TEMPORARILY_UNAVAILABLE)) {
log("*** INFO: listening on port (TCP): ", tsp_IPDD_TCP_ListenPort, "; result: ", vl_result);
var f_IPL4_getMsgLen ipdd_msglen := refers(f_IPDD_getMsgLen);
IP_Daemon_Dynamic_IPL4_CtrlFunct.f_IPL4_setGetMsgLen(daemonPort,vl_result.connId,ipdd_msglen,{});
} else {
log("*** ERROR: error during initialization of the TCP port: ",vl_result);
setverdict(fail);
stop;
}
}
function f_Init_Server_IP_Connection(in integer conn_idx) runs on IPDD_CT {
if(vc_connectionList[conn_idx].serverConnection) {
if(ispresent(vc_connectionList[conn_idx].localInterface)) {
if(vc_connectionRuntimeAttributesList[conn_idx].socket < 0) {
log("init server: #", conn_idx);
vc_connectionRuntimeAttributesList[conn_idx].endpointIndex := f_GetEndpointIndex(vc_connectionList[conn_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(
IP_PCO,
vc_connectionList[conn_idx].localInterface.hostName,
vc_connectionList[conn_idx].localInterface.portNumber,
f_IPDD_getIPL4_Proto(conn_idx)
);
if(vc_connectionList[conn_idx].connectionId < 0) {
vc_connectionList[conn_idx].connectionId := f_getNextUniqueConnectionId();
}
vc_connectionRuntimeAttributesList[conn_idx].socket := vl_result.connId;
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList[conn_idx].subscribedTestcases); i := i + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[conn_idx].subscribedTestcases[i],
{ ipdd_result := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[conn_idx].connectionId,
errorStatus := not(vl_result.errorCode==omit),
errorMessage := vl_result.os_error_text
}}
} );
}
} else {
log("*** WARNING: IP server connection ", vc_connectionList[conn_idx].localInterface, " is already listening!");
}
} else {
log("*** ERROR: IP server connection #", conn_idx, " is declared as server, but has no localInterface defined!");
}
} else {
if(tsp_debug) {
log("*** INFO: IP connection ", vc_connectionList[conn_idx], " is not server.");
}
}
}
function f_Reconnect_IP_Connection(in integer conn_idx) runs on IPDD_CT {
if(vc_connectionRuntimeAttributesList[conn_idx].socket < 0) {
if(ispresent(vc_connectionList[conn_idx].remoteInterface)) {
if(ispresent(vc_connectionList[conn_idx].localInterface)) {
if(not vc_connectionList[conn_idx].serverConnection) {
vc_connectionRuntimeAttributesList[conn_idx].endpointIndex := f_GetEndpointIndex(vc_connectionList[conn_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
(
IP_PCO,
vc_connectionList[conn_idx].remoteInterface.hostName,
vc_connectionList[conn_idx].remoteInterface.portNumber,
vc_connectionList[conn_idx].localInterface.hostName,
vc_connectionList[conn_idx].localInterface.portNumber,
connId := -1,
proto := f_IPDD_getIPL4_Proto(conn_idx),
options := {}
);
if ((vl_result.errorCode == omit) or (vl_result.errorCode == IPL4_ERROR_TEMPORARILY_UNAVAILABLE)) //if not error
{
vc_connectionRuntimeAttributesList[conn_idx].socket := vl_result.connId;
log("**** INFO: New client socket: ", vc_connectionRuntimeAttributesList[conn_idx].socket);
if(vc_connectionList[conn_idx].connectionId < 0) {
vc_connectionList[conn_idx].connectionId := f_getNextUniqueConnectionId();
}
}
else
{
f_ScheduleReconnect();
}
for(var integer i := 0; i < sizeof(vc_connectionRuntimeAttributesList[conn_idx].subscribedTestcases); i := i + 1) {
daemonPort.send(IPDD_Message_with_ClientId : {
vc_connectionRuntimeAttributesList[conn_idx].subscribedTestcases[i],
{ ipdd_result := {
messageType := 0, // encoder will replace
connectionId := vc_connectionList[conn_idx].connectionId,
errorStatus := not(vl_result.errorCode==omit),
errorMessage := vl_result.os_error_text
}}
} );
}
} else {
if(vc_connectionList[conn_idx].serverConnection) {
log("*** WARNING: connection ", vc_connectionList[conn_idx].localInterface,
" is declared as server connection, but also initiates client connection to ",
vc_connectionList[conn_idx].remoteInterface, ".");}
}
}
else {
log("*** WARNING: connection ", vc_connectionList[conn_idx].remoteInterface, " localInterface is missing.");
}
if(tsp_debug) {
log("@after ASP_IP_RESULT vc_connectionList: ",vc_connectionList, ", vc_connectionRuntimeAttributesList: ", vc_connectionRuntimeAttributesList);
}
} else {
if(vc_connectionList[conn_idx].serverConnection) {
if(tsp_debug) {
log("*** INFO: IP connection ", vc_connectionList[conn_idx].localInterface, " is server only.");
}
} else {
log("*** ERROR: IP connection ", vc_connectionList[conn_idx].localInterface, " is not a server connection!");
}
}
} else if(ispresent(vc_connectionList[conn_idx].remoteInterface)) {
log("*** WARNING: IP connection to " & log2str(vc_connectionList[conn_idx].remoteInterface) & " is already active!");
}
}
function f_removeConnection(in integer pl_connectionId) runs on IPDD_CT {
var IPDD_ConnectionList newConnectionList := {};
var ConnectionRuntimeAttributesList newConnectionRuntimeAttributesList := {};
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
if(vc_connectionList[i].connectionId != pl_connectionId) {
newConnectionList[sizeof(newConnectionList)] := vc_connectionList[i];
newConnectionRuntimeAttributesList[sizeof(newConnectionRuntimeAttributesList)] := vc_connectionRuntimeAttributesList[i];
}
}
if(sizeof(newConnectionList) != sizeof(vc_connectionList)) {
vc_connectionList := newConnectionList;
vc_connectionRuntimeAttributesList := newConnectionRuntimeAttributesList;
} else {
log("*** WARNING: IP connection to delete: ", pl_connectionId, " was not found in the database.");
}
}
function f_GetEndpointIndex(in IPDD_Interface pl_interface) runs on IPDD_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_RunAutoStartupFunctions(in integer conn_idx) runs on IPDD_CT {
var boolean vl_send;
var ASP_Send vl_ipMsg;
for(var integer i := 0; i < sizeof(vc_registeredAutoStartupFunctionList); i := i + 1) {
vl_send := vc_registeredAutoStartupFunctionList[i].apply(conn_idx, vl_ipMsg);
if(vl_send and vl_ipMsg.connId > 0) {
if(ischosen(vl_ipMsg.proto.udp)) {
var ASP_SendTo vl_udpMsg :=
{
connId := vl_ipMsg.connId,
remName := vc_connectionList[conn_idx].remoteInterface.hostName,
remPort := vc_connectionList[conn_idx].remoteInterface.portNumber,
proto := vl_ipMsg.proto,
msg := vl_ipMsg.msg
};
IP_PCO.send(vl_udpMsg);
}
else
{
IP_PCO.send(vl_ipMsg);
}
}
}
}
function f_ScheduleReconnect() runs on IPDD_CT {
if(not vc_reconnectTimer.running) {
vc_reconnectTimer.start(tsp_IPDD_ReconnectTimer);
}
}
function f_RestartInactivityTimer() runs on IPDD_CT {
if(tsp_IPDD_InactivityTimer > 0.0) {
if(vc_inactivityTimer.running) {
vc_inactivityTimer.stop;
};
vc_inactivityTimer.start(tsp_IPDD_InactivityTimer);
debuglog("*** INFO: Inactivity timer restarted.");
}
}
function f_RegisterAutoReplyFunction(in f_IPDD_AutoReplyFunction autoReplyFunction) runs on IPDD_CT {
vc_registeredAutoReplyFunctionList[sizeof(vc_registeredAutoReplyFunctionList)] := autoReplyFunction;
}
function f_RegisterAutoStateChangeHandlerFunction(in f_IPDD_AutoStateChangeHandlerFunction autoStateChangeHandlerFunction) runs on IPDD_CT {
vc_registeredAutoStateChangeHandlerFunctionList[sizeof(vc_registeredAutoStateChangeHandlerFunctionList)] := autoStateChangeHandlerFunction;
}
function f_RegisterAutoStartupFunction(in f_IPDD_AutoStartupFunction autoStartupFunction) runs on IPDD_CT {
vc_registeredAutoStartupFunctionList[sizeof(vc_registeredAutoStartupFunctionList)] := autoStartupFunction;
}
function f_IPDD() runs on IPDD_CT {
map(mtc:daemonPort, system:daemonPort);
map(mtc:IP_PCO, system:IP_PCO);
f_InitTCPServer();
for(var integer i := 0; i < sizeof(tsp_IPDD_ConnectionList); i := i + 1) {
vc_connectionList[i] := {
connectionId := -1,
serverConnection:= tsp_IPDD_ConnectionList[i].serverConnection,
autoReconnect := tsp_IPDD_ConnectionList[i].autoReconnect,
localInterfacePresent := false, // enter always false
localInterface := {
hostNameLength := 0,
hostName := f_getIpAddr(tsp_IPDD_ConnectionList[i].localInterface.hostName, f_addressType(tsp_IPDD_ConnectionList[i].localInterface.hostName)),
portNumber := tsp_IPDD_ConnectionList[i].localInterface.portNumber
},
remoteInterfacePresent := false, // enter always false
remoteInterface := tsp_IPDD_ConnectionList[i].remoteInterface,
proto := tsp_IPDD_ConnectionList[i].proto,
sctpProtoAttributesPresent := false,
sctpProtoAttributes := omit
};
// clientIds: empty, sctpState: SCTP_COMM_LOST
vc_connectionRuntimeAttributesList[i] := c_emptyConnectionRuntimeAttribute;
}
log("*** INFO: initial config: ", vc_connectionList);
for(var integer i := 0; i < sizeof(vc_connectionList); i := i + 1) {
f_Init_Server_IP_Connection(i);
f_Reconnect_IP_Connection(i);
f_RunAutoStartupFunctions(i);
}
alt {
[] as_Handle_TCP_Events()
[] as_Handle_Reconnect()
[] as_Handle_IP_Events()
[] as_Handle_Inactivity()
}
unmap(mtc:daemonPort, system:daemonPort);
unmap(mtc:IP_PCO, system:IP_PCO);
}
//=========================================================================
// Testcases
//=========================================================================
testcase tc_IPDD() runs on IPDD_CT {
f_IPDD();
}
//=========================================================================
// Control
//=========================================================================
control {
execute(tc_IPDD());
}
} //end of module