Просмотр исходного кода

Fixes timeout handling, fixes forward open and close for POSIX and Win32

CapXilinx 9 лет назад
Родитель
Сommit
0bb238a504

+ 11 - 11
source/contrib/msinttypes/inttypes.h

@@ -45,8 +45,8 @@
 // 7.8 Format conversion of integer types
 
 typedef struct {
-   intmax_t quot;
-   intmax_t rem;
+  intmax_t quot;
+  intmax_t rem;
 } imaxdiv_t;
 
 // 7.8.1 Macros for format specifiers
@@ -279,18 +279,18 @@ __inline
 #endif // STATIC_IMAXDIV ]
 imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
 {
-   imaxdiv_t result;
+  imaxdiv_t result;
 
-   result.quot = numer / denom;
-   result.rem = numer % denom;
+  result.quot = numer / denom;
+  result.rem = numer % denom;
 
-   if (numer < 0 && result.rem > 0) {
-      // did division wrong; must fix up
-      ++result.quot;
-      result.rem -= denom;
-   }
+  if (numer < 0 && result.rem > 0) {
+    // did division wrong; must fix up
+    ++result.quot;
+    result.rem -= denom;
+  }
 
-   return result;
+  return result;
 }
 
 // 7.8.2.3 The strtoimax and strtoumax functions

+ 2 - 2
source/src/cip/cipconnectionmanager.c

@@ -789,14 +789,14 @@ EipStatus GetConnectionOwner(CipInstance *instance,
 }
 
 EipStatus ManageConnections(MilliSeconds elapsed_time) {
-
+  //OPENER_TRACE_INFO("Entering ManageConnections\n");
   /*Inform application that it can execute */
   HandleApplication();
   ManageEncapsulationMessages(elapsed_time);
 
   ConnectionObject *connection_object = g_active_connection_list;
   while (NULL != connection_object) {
-    OPENER_TRACE_INFO("Entering Connection Object loop\n");
+    //OPENER_TRACE_INFO("Entering Connection Object loop\n");
     if (kConnectionStateEstablished == connection_object->state) {
       if ( (0 != connection_object->consuming_instance) ||                  /* we have a consuming connection check inactivity watchdog timer */
            (connection_object->transport_type_class_trigger & 0x80) )             /* all sever connections have to maintain an inactivity watchdog timer */

+ 1 - 1
source/src/cip/ciperror.h

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #ifndef OPENER_CIPERROR_H_

+ 5 - 4
source/src/cip/cipethernetlink.c

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #include <string.h>
@@ -28,8 +28,8 @@ CipEthernetLinkObject g_ethernet_link;
  *  @param mac_address The MAC address of the Ethernet Link
  */
 void ConfigureMacAddress(const EipUint8 *const mac_address) {
-  memcpy(&g_ethernet_link.physical_address, mac_address,
-         sizeof(g_ethernet_link.physical_address));
+  memcpy( &g_ethernet_link.physical_address, mac_address,
+          sizeof(g_ethernet_link.physical_address) );
 
 }
 
@@ -49,7 +49,8 @@ EipStatus CipEthernetLinkInit() {
 
   if (ethernet_link_class != NULL) {
 
-    CipInstance *ethernet_link_instance = GetCipInstance(ethernet_link_class, 1);
+    CipInstance *ethernet_link_instance =
+      GetCipInstance(ethernet_link_class, 1);
     InsertAttribute(ethernet_link_instance, 1, kCipUdint,
                     &g_ethernet_link.interface_speed, kGetableSingleAndAll); /* bind attributes to the instance*/
     InsertAttribute(ethernet_link_instance, 2, kCipDword,

+ 1 - 1
source/src/cip/cipethernetlink.h

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #ifndef OPENER_CIPETHERNETLINK_H_

+ 1 - 1
source/src/cip/cipidentity.c

@@ -73,7 +73,7 @@ static EipStatus Reset(CipInstance *instance,
                        CipMessageRouterRequest *message_router_request,
                        /* pointer to message router request*/
                        CipMessageRouterResponse *message_router_response,
-                       struct sockaddr_in *originator_address) {                      /* pointer to message router response*/
+                       struct sockaddr *originator_address) {                      /* pointer to message router response*/
   (void) instance;
 
   EipStatus eip_status = kEipStatusOkSend;

+ 10 - 10
source/src/cip/cipidentity.h

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #ifndef OPENER_CIPIDENTITY_H_
@@ -15,19 +15,19 @@ static const int kIdentityClassCode = 0x01;
 typedef enum {
   kOwned = 0x0001, /**< Indicates that the device has an owner */
   kConfigured = 0x0004, /**< Indicates that the device is configured to do
-   something different, than the out-of-the-box default. */
+                           something different, than the out-of-the-box default. */
   kMinorRecoverableFault = 0x0100, /**< Indicates that the device detected a
-   fault with itself, which was thought to be recoverable. The device did not
-   switch to a faulted state. */
+                                      fault with itself, which was thought to be recoverable. The device did not
+                                      switch to a faulted state. */
   kMinorUncoverableFault = 0x0200, /**< Indicates that the device detected a
-   fault with itself, which was thought to be recoverable. The device did not
-   switch to a faulted state. */
+                                      fault with itself, which was thought to be recoverable. The device did not
+                                      switch to a faulted state. */
   kMajorRecoveralbeFault = 0x0400, /**< Indicates that the device detected a
-   fault with itself,which was thought to be recoverable. The device changed
-   to the "Major Recoverable Fault" state */
+                                      fault with itself,which was thought to be recoverable. The device changed
+                                      to the "Major Recoverable Fault" state */
   kMajorUnrecoverableFault = 0x0800 /**< Indicates that the device detected a
-   fault with itself,which was thought to be recoverable. The device changed
-   to the "Major Unrecoverable Fault" state */
+                                       fault with itself,which was thought to be recoverable. The device changed
+                                       to the "Major Unrecoverable Fault" state */
 } CipIdentityStatus;
 
 typedef enum {

+ 7 - 3
source/src/enet_encap/encap.c

@@ -17,6 +17,7 @@
 #include "cipconnectionmanager.h"
 #include "cipidentity.h"
 #include "generic_networkhandler.h"
+#include "trace.h"
 
 /*Identity data from cipidentity.c*/
 extern EipUint16 vendor_id_;
@@ -488,6 +489,8 @@ void HandleReceivedRegisterSessionCommand(int socket,
 EipStatus HandleReceivedUnregisterSessionCommand(
   EncapsulationData *receive_data) {
 
+  OPENER_TRACE_INFO("encap.c: Unregister Session Command\n");
+
   if ( (0 < receive_data->session_handle)
        && (receive_data->session_handle <=
            OPENER_NUMBER_OF_SUPPORTED_SESSIONS) ) {
@@ -642,8 +645,8 @@ SessionStatus CheckRegisteredSessions(EncapsulationData *receive_data) {
 }
 
 void CloseSession(int socket) {
-  int i;
-  for (i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
+  OPENER_TRACE_INFO("encap.c: Close session\n");
+  for (size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
     if (g_registered_sessions[i] == socket) {
       IApp_CloseSocket_tcp(socket);
       g_registered_sessions[i] = kEipInvalidSocket;
@@ -653,7 +656,8 @@ void CloseSession(int socket) {
 }
 
 void EncapsulationShutDown(void) {
-  for (int i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
+  OPENER_TRACE_INFO("encap.c: Encapsulation shutdown\n");
+  for (size_t i = 0; i < OPENER_NUMBER_OF_SUPPORTED_SESSIONS; ++i) {
     if (kEipInvalidSocket != g_registered_sessions[i]) {
       IApp_CloseSocket_tcp(g_registered_sessions[i]);
       g_registered_sessions[i] = kEipInvalidSocket;

+ 2 - 2
source/src/enet_encap/encap.h

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #ifndef OPENER_ENCAP_H_
@@ -18,7 +18,7 @@
 
 /*** defines ***/
 
-#define ENCAPSULATION_HEADER_LENGTH	24
+#define ENCAPSULATION_HEADER_LENGTH     24
 
 /** @brief Ethernet/IP standard port */
 static const int kOpenerEthernetPort = 0xAF12;

+ 1 - 1
source/src/ports/CMakeLists.txt

@@ -14,6 +14,6 @@ opener_common_includes()
 #######################################
 opener_platform_support("INCLUDES")
 
-set( PLATFORM_GENERIC_SRC generic_networkhandler.c)
+set( PLATFORM_GENERIC_SRC generic_networkhandler.c socket_timer.c )
 
 add_library( PLATFORM_GENERIC ${PLATFORM_GENERIC_SRC})

+ 2 - 0
source/src/ports/POSIX/networkhandler.h

@@ -11,6 +11,8 @@
 
 #include "typedefs.h"
 
+#define OPENER_SOCKET_WOULD_BLOCK EWOULDBLOCK
+
 /** @brief Executes platform dependent network handler initialization code
  *
  *      @return EipStatusOk if initialization was successful, otherwise EipStatusError

+ 5 - 5
source/src/ports/WIN32/main.c

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #include <stdio.h>
@@ -36,9 +36,9 @@ int main(int argc, char *arg[]) {
     printf("Wrong number of command line parameters!\n");
     printf("The correct command line parameters are:\n");
     printf(
-        "./OpENer ipaddress subnetmask gateway domainname hostaddress macaddress\n");
+      "./OpENer ipaddress subnetmask gateway domainname hostaddress macaddress\n");
     printf(
-        "    e.g. ./OpENer 192.168.0.2 255.255.255.0 192.168.0.1 test.com testdevice 00 15 C5 BF D0 87\n");
+      "    e.g. ./OpENer 192.168.0.2 255.255.255.0 192.168.0.1 test.com testdevice 00 15 C5 BF D0 87\n");
     exit(0);
   } else {
     /* fetch Internet address info from the platform */
@@ -67,7 +67,7 @@ int main(int argc, char *arg[]) {
   CipStackInit(nUniqueConnectionID);
 
   /* Setup Network Handles */
-  if (kEipStatusOk == NetworkHandlerInitialize()) {
+  if ( kEipStatusOk == NetworkHandlerInitialize() ) {
     g_end_stack = 0;
 #ifndef WIN32
     /* register for closing signals so that we can trigger the stack to end */
@@ -76,7 +76,7 @@ int main(int argc, char *arg[]) {
 
     /* The event loop. Put other processing you need done continually in here */
     while (1 != g_end_stack) {
-      if (kEipStatusOk != NetworkHandlerProcessOnce()) {
+      if ( kEipStatusOk != NetworkHandlerProcessOnce() ) {
         break;
       }
     }

+ 2 - 2
source/src/ports/WIN32/networkhandler.c

@@ -46,6 +46,6 @@ void CloseSocketPlatform(int socket_handle) {
 }
 
 int SetSocketToNonBlocking(int socket_handle) {
-  u_long iMode = 0;
-  ioctlsocket(m_socket, FIONBIO, &iMode);
+  u_long iMode = 1;
+  return ioctlsocket(socket_handle, FIONBIO, &iMode);
 }

+ 2 - 0
source/src/ports/WIN32/networkhandler.h

@@ -8,6 +8,8 @@
 
 #include "typedefs.h"
 
+#define OPENER_SOCKET_WOULD_BLOCK WSAEWOULDBLOCK
+
 typedef unsigned long socklen_t;
 
 EipStatus NetworkHandlerInitializePlatform(void);

+ 18 - 15
source/src/ports/WIN32/sample_application/opener_user_conf.h

@@ -1,6 +1,6 @@
 /*******************************************************************************
  * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved. 
+ * All rights reserved.
  *
  ******************************************************************************/
 #ifndef OPENER_USER_CONF_H_
@@ -8,9 +8,9 @@
 
 /** @file
  * @brief OpENer configuration setup
- * 
+ *
  * This file contains the general application specific configuration for OpENer.
- * 
+ *
  * Furthermore you have to specific platform specific network include files.
  * OpENer needs definitions for the following data-types
  * and functions:
@@ -85,18 +85,18 @@ typedef unsigned short in_port_t;
  */
 #define OPENER_NUMBER_OF_SUPPORTED_SESSIONS 20
 
- /** @brief  The time in ms of the timer used in this implementations
+/** @brief  The time in ms of the timer used in this implementations
  */
 static const int kOpenerTimerTickInMilliSeconds = 10;
 
 /** @brief Define if RUN IDLE data is sent with consumed data
-*/
+ */
 static const int kOpenerConsumedDataHasRunIdleHeader = 1;
 
 /** @brief Define if RUN IDLE data is to be sent with produced data
-*
-* Per default we don't send run idle headers with produced data
-*/
+ *
+ * Per default we don't send run idle headers with produced data
+ */
 static const int kOpenerProducedDataHasRunIdleHeader = 0;
 
 #ifdef OPENER_WITH_TRACES
@@ -111,12 +111,15 @@ static const int kOpenerProducedDataHasRunIdleHeader = 0;
  *  further execution in an while(1) loop.
  */
 #define OPENER_ASSERT(assertion) \
-    do { \
-      if(!(assertion)) { \
-        LOG_TRACE("Assertion \"%s\" failed: file \"%s\", line %d\n", #assertion, __FILE__, __LINE__); \
-        while(1){;} \
-      } \
-    } while(0)
+  do { \
+    if( !(assertion) ) { \
+      LOG_TRACE("Assertion \"%s\" failed: file \"%s\", line %d\n", \
+                # assertion, \
+                __FILE__, \
+                __LINE__); \
+      while(1) {;} \
+    } \
+  } while(0)
 
 /* else use standard assert() */
 //#include <assert.h>
@@ -142,7 +145,7 @@ static const int kOpenerProducedDataHasRunIdleHeader = 0;
 #endif
 
 /** @brief The number of bytes used for the Ethernet message buffer on
- * the pc port. For different platforms it may makes sense to 
+ * the pc port. For different platforms it may makes sense to
  * have more than one buffer.
  *
  *  This buffer size will be used for any received message.

+ 16 - 15
source/src/ports/WIN32/sample_application/sampleapplication.c

@@ -25,16 +25,16 @@ EipUint8 g_assembly_data09A[32]; /* Explicit */
 EipStatus ApplicationInitialization(void) {
   /* create 3 assembly object instances*/
   /*INPUT*/
-  CreateAssemblyObject(DEMO_APP_INPUT_ASSEMBLY_NUM, &g_assembly_data064[0],
-                       sizeof(g_assembly_data064));
+  CreateAssemblyObject( DEMO_APP_INPUT_ASSEMBLY_NUM, &g_assembly_data064[0],
+                        sizeof(g_assembly_data064) );
 
   /*OUTPUT*/
-  CreateAssemblyObject(DEMO_APP_OUTPUT_ASSEMBLY_NUM, &g_assembly_data096[0],
-                       sizeof(g_assembly_data096));
+  CreateAssemblyObject( DEMO_APP_OUTPUT_ASSEMBLY_NUM, &g_assembly_data096[0],
+                        sizeof(g_assembly_data096) );
 
   /*CONFIG*/
-  CreateAssemblyObject(DEMO_APP_CONFIG_ASSEMBLY_NUM, &g_assembly_data097[0],
-                       sizeof(g_assembly_data097));
+  CreateAssemblyObject( DEMO_APP_CONFIG_ASSEMBLY_NUM, &g_assembly_data097[0],
+                        sizeof(g_assembly_data097) );
 
   /*Heart-beat output assembly for Input only connections */
   CreateAssemblyObject(DEMO_APP_HEARTBEAT_INPUT_ONLY_ASSEMBLY_NUM, 0, 0);
@@ -43,18 +43,18 @@ EipStatus ApplicationInitialization(void) {
   CreateAssemblyObject(DEMO_APP_HEARTBEAT_LISTEN_ONLY_ASSEMBLY_NUM, 0, 0);
 
   /* assembly for explicit messaging */
-  CreateAssemblyObject(DEMO_APP_EXPLICT_ASSEMBLY_NUM, &g_assembly_data09A[0],
-                       sizeof(g_assembly_data09A));
+  CreateAssemblyObject( DEMO_APP_EXPLICT_ASSEMBLY_NUM, &g_assembly_data09A[0],
+                        sizeof(g_assembly_data09A) );
 
   ConfigureExclusiveOwnerConnectionPoint(0, DEMO_APP_OUTPUT_ASSEMBLY_NUM,
-  DEMO_APP_INPUT_ASSEMBLY_NUM,
+                                         DEMO_APP_INPUT_ASSEMBLY_NUM,
                                          DEMO_APP_CONFIG_ASSEMBLY_NUM);
   ConfigureInputOnlyConnectionPoint(0,
-  DEMO_APP_HEARTBEAT_INPUT_ONLY_ASSEMBLY_NUM,
+                                    DEMO_APP_HEARTBEAT_INPUT_ONLY_ASSEMBLY_NUM,
                                     DEMO_APP_INPUT_ASSEMBLY_NUM,
                                     DEMO_APP_CONFIG_ASSEMBLY_NUM);
   ConfigureListenOnlyConnectionPoint(0,
-  DEMO_APP_HEARTBEAT_LISTEN_ONLY_ASSEMBLY_NUM,
+                                     DEMO_APP_HEARTBEAT_LISTEN_ONLY_ASSEMBLY_NUM,
                                      DEMO_APP_INPUT_ASSEMBLY_NUM,
                                      DEMO_APP_CONFIG_ASSEMBLY_NUM);
 
@@ -66,8 +66,8 @@ void HandleApplication(void) {
 }
 
 void CheckIoConnectionEvent(unsigned int pa_unOutputAssembly,
-                       unsigned int pa_unInputAssembly,
-                       IoConnectionEvent pa_eIOConnectionEvent) {
+                            unsigned int pa_unInputAssembly,
+                            IoConnectionEvent pa_eIOConnectionEvent) {
   /* maintain a correct output state according to the connection state*/
 
   (void) pa_unOutputAssembly; /* suppress compiler warning */
@@ -83,8 +83,8 @@ EipStatus AfterAssemblyDataReceived(CipInstance *pa_pstInstance) {
     case DEMO_APP_OUTPUT_ASSEMBLY_NUM:
       /* Data for the output assembly has been received.
        * Mirror it to the inputs */
-      memcpy(&g_assembly_data064[0], &g_assembly_data096[0],
-             sizeof(g_assembly_data064));
+      memcpy( &g_assembly_data064[0], &g_assembly_data096[0],
+              sizeof(g_assembly_data064) );
       break;
     case DEMO_APP_EXPLICT_ASSEMBLY_NUM:
       /* do something interesting with the new data from
@@ -118,6 +118,7 @@ EipBool8 BeforeAssemblyDataSend(CipInstance *pa_pstInstance) {
 
 EipStatus ResetDevice(void) {
   /* add reset code here*/
+  CloseAllConnections();
   return kEipStatusOk;
 }
 

+ 88 - 46
source/src/ports/generic_networkhandler.c

@@ -13,16 +13,18 @@
 
 #include <assert.h>
 #include <stdbool.h>
-#include <unistd.h>
 
 #include "generic_networkhandler.h"
 
 #include "typedefs.h"
 #include "trace.h"
 #include "opener_error.h"
+#include "socket_timer.h"
 #include "encap.h"
 #include "ciptcpipinterface.h"
 
+SocketTimer g_timestamps[MAX_NO_OF_TCP_SOCKETS];
+
 /** @brief handle any connection request coming in the TCP server socket.
  *
  */
@@ -62,6 +64,8 @@ EipStatus NetworkHandlerInitialize(void) {
     return kEipStatusError;
   }
 
+  SocketTimerArrayInitialize(g_timestamps, MAX_NO_OF_TCP_SOCKETS);
+
   /* clear the master an temp sets */
   FD_ZERO(&master_socket);
   FD_ZERO(&read_socket);
@@ -75,7 +79,7 @@ EipStatus NetworkHandlerInitialize(void) {
     OPENER_TRACE_ERR("error allocating socket stream listener, %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -102,7 +106,7 @@ EipStatus NetworkHandlerInitialize(void) {
       "error allocating UDP global broadcast listener socket, %d - %s\n",
       error_code,
       error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -113,7 +117,7 @@ EipStatus NetworkHandlerInitialize(void) {
     char *error_message = GetErrorMessage(error_code);
     OPENER_TRACE_ERR("error allocating UDP unicast listener socket, %d - %s\n",
                      error_code, error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -153,7 +157,7 @@ EipStatus NetworkHandlerInitialize(void) {
     char *error_message = GetErrorMessage(error_code);
     OPENER_TRACE_ERR("error with TCP bind: %d - %s\n", error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -164,7 +168,7 @@ EipStatus NetworkHandlerInitialize(void) {
     char *error_message = GetErrorMessage(error_code);
     OPENER_TRACE_ERR( "error with UDP unicast bind: %d - %s\n", error_code, GetErrorMessage(
                         error_code) );
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -184,7 +188,7 @@ EipStatus NetworkHandlerInitialize(void) {
     OPENER_TRACE_ERR(
       "error with setting broadcast receive for UDP socket: %d - %s\n",
       error_code, error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -196,7 +200,7 @@ EipStatus NetworkHandlerInitialize(void) {
     OPENER_TRACE_ERR("error with global broadcast UDP bind: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -208,7 +212,7 @@ EipStatus NetworkHandlerInitialize(void) {
     OPENER_TRACE_ERR("networkhandler: error with listen: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -227,13 +231,6 @@ EipStatus NetworkHandlerInitialize(void) {
   g_last_time = GetMilliSeconds(); /* initialize time keeping */
   g_network_status.elapsed_time = 0;
 
-  g_timestamps = calloc( MAX_NO_OF_TCP_SOCKETS,sizeof(MilliSeconds) );
-
-  for(int i = 0; i<highest_socket_handle; i++)
-  {
-    g_timestamps[i] = g_actual_time;
-  }
-
   return kEipStatusOk;
 }
 
@@ -242,6 +239,12 @@ void IApp_CloseSocket_udp(int socket_handle) {
 }
 
 void IApp_CloseSocket_tcp(int socket_handle) {
+  SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                             MAX_NO_OF_TCP_SOCKETS,
+                                             socket_handle);
+  if(NULL != socket_timer) {
+    DeleteSocketTimer(socket_timer);
+  }
   CloseSocket(socket_handle);
 }
 
@@ -271,7 +274,7 @@ void CheckAndHandleTcpListenerSocket(void) {
       char *error_message = GetErrorMessage(error_code);
       OPENER_TRACE_ERR("networkhandler: error on accept: %d - %s\n",
                        error_code, error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return;
     }
 
@@ -280,7 +283,11 @@ void CheckAndHandleTcpListenerSocket(void) {
     if (new_socket > highest_socket_handle) {
       highest_socket_handle = new_socket;
     }
-    g_timestamps[new_socket] = g_actual_time;
+    //g_timestamps[new_socket] = g_actual_time;
+    SocketTimer *socket_timer = GetEmptySocketTimer(g_timestamps,
+                                                    MAX_NO_OF_TCP_SOCKETS);
+    SocketTimerSetSocket(socket_timer, new_socket);
+    SocketTimerSetLastUpdate(socket_timer, g_actual_time);
 
     OPENER_TRACE_STATE("networkhandler: opened new TCP connection on fd %d\n",
                        new_socket);
@@ -310,7 +317,7 @@ EipStatus NetworkHandlerProcessOnce(void) {
       OPENER_TRACE_ERR("networkhandler: error with select: %d - %s\n",
                        error_code,
                        error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return kEipStatusError;
     }
   }
@@ -336,6 +343,8 @@ EipStatus NetworkHandlerProcessOnce(void) {
     }
   }
 
+  //OPENER_TRACE_INFO("Socket Loop done\n");
+
   g_actual_time = GetMilliSeconds();
   g_network_status.elapsed_time += g_actual_time - g_last_time;
   g_last_time = g_actual_time;
@@ -386,7 +395,7 @@ void CheckAndHandleUdpGlobalBroadcastSocket(void) {
         "networkhandler: error on recvfrom UDP global broadcast port: %d - %s\n",
         error_code,
         error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return;
     }
 
@@ -445,7 +454,7 @@ void CheckAndHandleUdpUnicastSocket(void) {
         "networkhandler: error on recvfrom UDP unicast port: %d - %s\n",
         error_code,
         error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return;
     }
 
@@ -492,7 +501,7 @@ EipStatus SendUdpData(struct sockaddr_in *address,
       "networkhandler: error with sendto in sendUDPData: %d - %s\n",
       error_code,
       error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -508,6 +517,7 @@ EipStatus SendUdpData(struct sockaddr_in *address,
 }
 
 EipStatus HandleDataOnTcpSocket(int socket) {
+  //OPENER_TRACE_INFO("Entering HandleDataOnTcpSocket\n");
   int remaining_bytes = 0;
   long data_sent = PC_OPENER_ETHERNET_BUFFER_SIZE;
 
@@ -521,23 +531,29 @@ EipStatus HandleDataOnTcpSocket(int socket) {
   long number_of_read_bytes = recv(socket, g_ethernet_communication_buffer, 4,
                                    0); /*TODO we may have to set the socket to a non blocking socket */
 
-  g_timestamps[socket] = g_actual_time;
+  SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                             MAX_NO_OF_TCP_SOCKETS,
+                                             socket);
+  SocketTimerSetLastUpdate(socket_timer, g_actual_time);
   if (number_of_read_bytes == 0) {
     int error_code = GetSocketErrorNumber();
     char *error_message = GetErrorMessage(error_code);
     OPENER_TRACE_ERR("networkhandler: connection closed by client: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
   if (number_of_read_bytes < 0) {
     int error_code = GetSocketErrorNumber();
+    if (OPENER_SOCKET_WOULD_BLOCK == error_code) {
+      return kEipStatusOk;
+    }
     char *error_message = GetErrorMessage(error_code);
     OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -556,7 +572,10 @@ EipStatus HandleDataOnTcpSocket(int socket) {
         data_sent);
       number_of_read_bytes = recv(socket, &g_ethernet_communication_buffer[0],
                                   data_sent, 0);
-      g_timestamps[socket] = g_actual_time;
+      SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                                 MAX_NO_OF_TCP_SOCKETS,
+                                                 socket);
+      SocketTimerSetLastUpdate(socket_timer, g_actual_time);
       if (number_of_read_bytes == 0) /* got error or connection closed by client */
       {
         int error_code = GetSocketErrorNumber();
@@ -565,16 +584,19 @@ EipStatus HandleDataOnTcpSocket(int socket) {
           "networkhandler: connection closed by client: %d - %s\n",
           error_code,
           error_message);
-        free(error_message);
+        FreeErrorMessage(error_message);
         return kEipStatusError;
       }
       if (number_of_read_bytes < 0) {
         int error_code = GetSocketErrorNumber();
         char *error_message = GetErrorMessage(error_code);
+        if (OPENER_SOCKET_WOULD_BLOCK == error_code) {
+          return kEipStatusOk;
+        }
         OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n",
                          error_code,
                          error_message);
-        free(error_message);
+        FreeErrorMessage(error_message);
         return kEipStatusError;
       }
       data_size -= number_of_read_bytes;
@@ -588,7 +610,8 @@ EipStatus HandleDataOnTcpSocket(int socket) {
 
   number_of_read_bytes = recv(socket, &g_ethernet_communication_buffer[4],
                               data_size, 0);
-  g_timestamps[socket] = g_actual_time;
+//  SocketTimer *socket_timer = GetSocketTimer(g_timestamps, MAX_NO_OF_TCP_SOCKETS, socket);
+  SocketTimerSetLastUpdate(socket_timer, g_actual_time);
   if (number_of_read_bytes == 0) /* got error or connection closed by client */
   {
     int error_code = GetSocketErrorNumber();
@@ -596,16 +619,19 @@ EipStatus HandleDataOnTcpSocket(int socket) {
     OPENER_TRACE_ERR("networkhandler: connection closed by client: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
   if (number_of_read_bytes < 0) {
     int error_code = GetSocketErrorNumber();
     char *error_message = GetErrorMessage(error_code);
+    if (OPENER_SOCKET_WOULD_BLOCK == error_code) {
+      return kEipStatusOk;
+    }
     OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipStatusError;
   }
 
@@ -625,9 +651,14 @@ EipStatus HandleDataOnTcpSocket(int socket) {
     number_of_read_bytes = HandleReceivedExplictTcpData(
       socket, g_ethernet_communication_buffer, data_size, &remaining_bytes,
       &sender_address);
-    g_timestamps[socket] = g_actual_time;
+    SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                               MAX_NO_OF_TCP_SOCKETS,
+                                               socket);
+    if(NULL != socket_timer) {
+      SocketTimerSetLastUpdate(socket_timer, g_actual_time);
+    }
 
-    g_current_active_tcp_socket = -1;
+    g_current_active_tcp_socket = kEipInvalidSocket;
 
     if (remaining_bytes != 0) {
       OPENER_TRACE_WARN(
@@ -640,7 +671,10 @@ EipStatus HandleDataOnTcpSocket(int socket) {
 
       data_sent = send(socket, (char *) &g_ethernet_communication_buffer[0],
                        number_of_read_bytes, 0);
-      g_timestamps[socket] = g_actual_time;
+      SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                                 MAX_NO_OF_TCP_SOCKETS,
+                                                 socket);
+      SocketTimerSetLastUpdate(socket_timer, g_actual_time);
       if (data_sent != number_of_read_bytes) {
         OPENER_TRACE_WARN("TCP response was not fully sent\n");
       }
@@ -679,7 +713,7 @@ int CreateUdpSocket(UdpCommuncationDirection communication_direction,
     OPENER_TRACE_ERR("networkhandler: cannot create UDP socket: %d- %s\n",
                      error_code,
                      error_message);
-    free(error_message);
+    FreeErrorMessage(error_message);
     return kEipInvalidSocket;
   }
 
@@ -706,7 +740,7 @@ int CreateUdpSocket(UdpCommuncationDirection communication_direction,
       char *error_message = GetErrorMessage(error_code);
       OPENER_TRACE_ERR("error on bind udp: %d - %s\n", error_code,
                        error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return kEipInvalidSocket;
     }
 
@@ -724,7 +758,7 @@ int CreateUdpSocket(UdpCommuncationDirection communication_direction,
           OPENER_TRACE_ERR(
             "networkhandler: could not set the TTL to: %d, error: %d - %s\n",
             g_time_to_live_value, error_code, error_message);
-          free(error_message);
+          FreeErrorMessage(error_message);
           return kEipInvalidSocket;
         }
       }
@@ -742,7 +776,7 @@ int CreateUdpSocket(UdpCommuncationDirection communication_direction,
       OPENER_TRACE_ERR("networkhandler: could not get peername: %d - %s\n",
                        error_code,
                        error_message);
-      free(error_message);
+      FreeErrorMessage(error_message);
       return kEipInvalidSocket;
     }
     /* store the originators address */
@@ -792,10 +826,13 @@ void CheckAndHandleConsumingUdpSockets(void) {
       if (0 > received_size) {
         int error_code = GetSocketErrorNumber();
         char *error_message = GetErrorMessage(error_code);
+        if (OPENER_SOCKET_WOULD_BLOCK == error_code) {
+          return;       // No fatal error, resume execution
+        }
         OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n",
                          error_code,
                          error_message);
-        free(error_message);
+        FreeErrorMessage(error_message);
         current_connection_object->connection_close_function(
           current_connection_object);
         continue;
@@ -816,6 +853,7 @@ void CloseSocket(int socket_handle) {
     FD_CLR(socket_handle, &master_socket);
     CloseSocketPlatform(socket_handle);
   }
+  OPENER_TRACE_INFO("networkhandler: closing socket done %d\n", socket_handle);
 }
 
 int GetMaxSocket(int socket1, int socket2, int socket3, int socket4) {
@@ -837,14 +875,18 @@ int GetMaxSocket(int socket1, int socket2, int socket3, int socket4) {
 void CheckEncapsulationInactivity(int socket_handle) {
 
   if (0 < g_encapsulation_inactivity_timeout) {
-    MilliSeconds diffms = g_actual_time - g_timestamps[socket_handle];
-    if (diffms < 0) {
-      diffms = 0;
-    }
+    SocketTimer *socket_timer = GetSocketTimer(g_timestamps,
+                                               MAX_NO_OF_TCP_SOCKETS,
+                                               socket_handle);
 
-    if (diffms >= g_encapsulation_inactivity_timeout) {
-      CloseSocket(socket_handle);
-      CloseSession(socket_handle);
+    if(NULL != socket_timer) {
+      MilliSeconds diffms = g_actual_time - GetSocketTimerLastUpdate(
+        socket_timer);
+
+      if (diffms >= g_encapsulation_inactivity_timeout) {
+        CloseSocket(socket_handle);
+        CloseSession(socket_handle);
+      }
     }
   }
 }

+ 0 - 2
source/src/ports/generic_networkhandler.h

@@ -47,8 +47,6 @@ int g_current_active_tcp_socket;
 struct timeval g_time_value;
 MilliSeconds g_actual_time;
 MilliSeconds g_last_time;
-MilliSeconds g_encap_timestamp;
-MilliSeconds* g_timestamps;
 /** @brief Struct representing the current network status
  *
  */

+ 7 - 0
source/src/ports/socket_timer.c

@@ -0,0 +1,7 @@
+/*******************************************************************************
+ * Copyright (c) 2009, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+

+ 64 - 0
source/src/ports/socket_timer.h

@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2009, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#ifndef SRC_PORTS_SOCKET_TIMER_H_
+#define SRC_PORTS_SOCKET_TIMER_H_
+
+#include "typedefs.h"
+
+/** @brief Data structure to store last usage times for sockets
+ *
+ */
+typedef struct socket_timer {
+  int socket;       /**< key */
+  MilliSeconds last_update;       /**< time stop of last update */
+} SocketTimer;
+
+void SocketTimerSetSocket(SocketTimer *const socket_timer, const int socket) {
+  socket_timer->socket = socket;
+}
+
+void SocketTimerSetLastUpdate(SocketTimer *const socket_timer,
+                              const MilliSeconds actual_time) {
+  if(NULL != socket_timer) {
+    socket_timer->last_update = actual_time;
+  }
+}
+
+MilliSeconds GetSocketTimerLastUpdate(SocketTimer *const socket_timer) {
+  return socket_timer->last_update;
+}
+
+void DeleteSocketTimer(SocketTimer *const socket_timer) {
+  socket_timer->socket = kEipInvalidSocket;
+  socket_timer->last_update = 0;
+}
+
+void SocketTimerArrayInitialize(SocketTimer *const array_of_socket_timers,
+                                const size_t array_length) {
+  for( size_t i = 0; i < array_length; ++i ) {
+    DeleteSocketTimer(&array_of_socket_timers[i]);
+  }
+}
+
+SocketTimer *GetSocketTimer(SocketTimer *const array_of_socket_timers,
+                            const size_t array_length,
+                            const int socket) {
+  for( size_t i = 0; i < array_length; ++i ) {
+    if(socket == array_of_socket_timers[i].socket) {
+      return &array_of_socket_timers[i];
+    }
+  }
+  return NULL;
+}
+
+SocketTimer *GetEmptySocketTimer(SocketTimer *const array_of_socket_timers,
+                                 const size_t array_length) {
+  return GetSocketTimer(array_of_socket_timers, array_length,
+                        kEipInvalidSocket);
+}
+
+#endif /* SRC_PORTS_SOCKET_TIMER_H_ */

+ 8 - 7
source/src/trace.h

@@ -31,9 +31,10 @@
 #ifndef OPENER_TRACE_LEVEL
 #ifdef WIN32
 #pragma message( \
-    "OPENER_TRACE_LEVEL was not defined setting it to OPENER_TRACE_LEVEL_ERROR")
+  "OPENER_TRACE_LEVEL was not defined setting it to OPENER_TRACE_LEVEL_ERROR")
 #else
-#warning OPENER_TRACE_LEVEL was not defined setting it to OPENER_TRACE_LEVEL_ERROR
+#warning \
+  OPENER_TRACE_LEVEL was not defined setting it to OPENER_TRACE_LEVEL_ERROR
 #endif
 
 #define OPENER_TRACE_LEVEL OPENER_TRACE_LEVEL_ERROR
@@ -48,7 +49,7 @@
  */
 #define OPENER_TRACE_ERR(...)                                                  \
   do {                                                                         \
-    if (OPENER_TRACE_LEVEL_ERROR & OPENER_TRACE_LEVEL) LOG_TRACE(__VA_ARGS__); \
+    if (OPENER_TRACE_LEVEL_ERROR & OPENER_TRACE_LEVEL) {LOG_TRACE(__VA_ARGS__);} \
   } while (0)
 
 /** @def OPENER_TRACE_WARN(...) Trace warning messages.
@@ -57,8 +58,8 @@
  */
 #define OPENER_TRACE_WARN(...)                           \
   do {                                                   \
-    if (OPENER_TRACE_LEVEL_WARNING & OPENER_TRACE_LEVEL) \
-      LOG_TRACE(__VA_ARGS__);                            \
+    if (OPENER_TRACE_LEVEL_WARNING & OPENER_TRACE_LEVEL) { \
+      LOG_TRACE(__VA_ARGS__);}                            \
   } while (0)
 
 /** @def OPENER_TRACE_STATE(...) Trace state messages.
@@ -67,7 +68,7 @@
  */
 #define OPENER_TRACE_STATE(...)                                                \
   do {                                                                         \
-    if (OPENER_TRACE_LEVEL_STATE & OPENER_TRACE_LEVEL) LOG_TRACE(__VA_ARGS__); \
+    if (OPENER_TRACE_LEVEL_STATE & OPENER_TRACE_LEVEL) {LOG_TRACE(__VA_ARGS__);} \
   } while (0)
 
 /** @def OPENER_TRACE_INFO(...) Trace information messages.
@@ -76,7 +77,7 @@
  */
 #define OPENER_TRACE_INFO(...)                                                \
   do {                                                                        \
-    if (OPENER_TRACE_LEVEL_INFO & OPENER_TRACE_LEVEL) LOG_TRACE(__VA_ARGS__); \
+    if (OPENER_TRACE_LEVEL_INFO & OPENER_TRACE_LEVEL) {LOG_TRACE(__VA_ARGS__);} \
   } while (0)
 
 #else

+ 3 - 1
source/tests/CMakeLists.txt

@@ -14,8 +14,9 @@ add_test_includes()
 #configure_file( CTestCustom.cmake ${PROJECT_BINARY_DIR}/CTestCustom.cmake )
 
 add_subdirectory( cip )
-add_subdirectory( utils )
+add_subdirectory( ports )
 add_subdirectory( enet_encap )
+add_subdirectory( utils )
 add_executable( OpENer_Tests OpENerTests.cpp )
 
 find_library ( CPPUTEST_LIBRARY CppUTest ${CPPUTEST_HOME}/cpputest_build/lib )
@@ -25,6 +26,7 @@ target_link_libraries( OpENer_Tests gcov ${CPPUTEST_LIBRARY} ${CPPUTESTEXT_LIBRA
 target_link_libraries( OpENer_Tests UtilsTest Utils ) 
 target_link_libraries( OpENer_Tests EthernetEncapsulationTest ENET_ENCAP )
 target_link_libraries( OpENer_Tests CipTest CIP )
+target_link_libraries( OpENer_Tests PortsTest PLATFORM_GENERIC )
 
 ########################################
 # Adds test to CTest environment       #

+ 1 - 2
source/tests/OpENerTests.cpp

@@ -1,7 +1,6 @@
 #include "OpENerTests.h"
 
-int main(int argc, char** argv)
-{
+int main(int argc, char **argv) {
   /* These checks are here to make sure assertions outside test runs don't crash */
   CHECK(true);
   LONGS_EQUAL(1, 1);

+ 1 - 0
source/tests/OpENerTests.h

@@ -5,3 +5,4 @@ IMPORT_TEST_GROUP(XorShiftRandom);
 IMPORT_TEST_GROUP(EndianConversion);
 IMPORT_TEST_GROUP(CipEpath);
 IMPORT_TEST_GROUP(CipElectronicKey);
+IMPORT_TEST_GROUP(SocketTimer);

+ 8 - 1
source/tests/cip/CMakeLists.txt

@@ -1,6 +1,13 @@
-
+#######################################
+# Add common includes                 #
+#######################################
 opener_common_includes()
 
+#######################################
+# Add platform-specific includes      #
+#######################################
+opener_platform_support("INCLUDES")
+
 set( CipTestSrc cipepathtest.cpp cipelectronickeytest.cpp )
 
 include_directories( ${SRC_DIR}/cip )

+ 8 - 1
source/tests/enet_encap/CMakeLists.txt

@@ -1,6 +1,13 @@
-
+#######################################
+# Add common includes                 #
+#######################################
 opener_common_includes()
 
+#######################################
+# Add platform-specific includes      #
+#######################################
+opener_platform_support("INCLUDES")
+
 set( EthernetEncapsulationTestSrc endianconvtest.cpp )
 
 include_directories( ${SRC_DIR}/enet_encap )

+ 8 - 0
source/tests/ports/CMakeLists.txt

@@ -0,0 +1,8 @@
+
+opener_common_includes()
+
+set( PortsTestSrc socket_timer_tests.cpp )
+
+include_directories( ${SRC_DIR}/ports )
+
+add_library( PortsTest ${PortsTestSrc} )

+ 30 - 0
source/tests/ports/socket_timer_tests.cpp

@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2016, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+#include <CppUTest/TestHarness.h>
+#include <stdint.h>
+#include <string.h>
+
+extern "C" {
+
+#include "socket_timer.h"
+
+}
+
+TEST_GROUP(SocketTimer) {
+
+};
+
+TEST(SocketTimer, GetAvailableEmptySocketTimer) {
+  SocketTimer timers[10];
+  SocketTimerArrayInitialize(timers, 10);
+  POINTERS_EQUAL( &timers[0], GetEmptySocketTimer(timers, 10) );
+}
+
+TEST(SocketTimer, NoEmptySocketTimerAvailable) {
+  SocketTimer timers[10];
+  POINTERS_EQUAL( NULL, GetEmptySocketTimer(timers, 10) );
+}