| /////////////////////////////////////////////////////////////////////////////// |
| // 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 |
| // Rev: <RnXnn> |
| // Prodnr: CNL 113 630 |
| // Updated: 2012-05-07 |
| // Contact: http://ttcn.ericsson.se |
| |
| 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 |