| /////////////////////////////////////////////////////////////////////////////// |
| // Copyright (c) 2000-2018 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 |