Переглянути джерело

Issue102 103 fix (#105)

* Fixes #102, fixes #103 
adds test, fixes test setup for tests including connectionmanager, updates travis.yml and several CMakeLists to make TravisCI build work

Signed-off-by: CapXilinx <melik-merkumians@acin.tuwien.ac.at>
Martin Melik-Merkumians 8 роки тому
батько
коміт
bad465626f

+ 19 - 0
.travis.yml

@@ -28,6 +28,25 @@ addons:
       - doxygen-gui
       - graphviz
 
+install:
+  ############################################################################
+  # All the dependencies are installed in ${TRAVIS_BUILD_DIR}/deps/
+  ############################################################################
+  - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
+  - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
+  ############################################################################
+  # Install a recent CMake (unless already installed on OS X)
+  ############################################################################
+  - |
+    if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
+      CMAKE_URL="https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz"
+      mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
+      export PATH=${DEPS_DIR}/cmake/bin:${PATH}
+    else
+      brew upgrade cmake || brew install cmake
+    fi
+    cmake --version
+
 #Prepare CppUTest from source, as package is not available
 before_script:
   - cd $TRAVIS_BUILD_DIR/source

+ 1 - 1
source/CMakeLists.txt

@@ -1,7 +1,7 @@
 #######################################
 # Required CMake version              #
 #######################################
-cmake_minimum_required( VERSION 2.8.7 )
+cmake_minimum_required( VERSION 3.7.2 )
 
 #######################################
 # Project name                        #

+ 8 - 3
source/buildsupport/POSIX/OpENer_PLATFORM_INCLUDES.cmake

@@ -1,6 +1,11 @@
 macro(opener_platform_spec)
   include_directories(${PORTS_SRC_DIR}/${OpENer_PLATFORM} ${PORTS_SRC_DIR}/${OpENer_PLATFORM}/sample_application)
   set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Werror=implicit-function-declaration" )
-  add_definitions( -D_POSIX_C_SOURCE=200112L -D__USE_GNU -D__USE_XOPEN2K -DRESTRICT=restrict)
-endmacro(opener_platform_spec)
-
+  add_definitions( -D_POSIX_C_SOURCE=200112L -D__USE_GNU -D__USE_XOPEN2K)
+  get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES)
+  if ("CXX" IN_LIST languages)
+  	add_definitions(-DRESTRICT=)
+  elseif()
+  	add_definitions(-DRESTRICT=restrict)
+  endif()
+endmacro(opener_platform_spec)

+ 19 - 4
source/src/cip/cipconnectionmanager.c

@@ -98,10 +98,22 @@ void SetProductionInhibitTime(const EipUint16 production_inhibit_time,
 }
 
 CipUdint GetTargetToOriginatorRequestedPackedInterval(
-  const ConnectionObject *const connection_object) {
+  const ConnectionObject *const RESTRICT connection_object) {
   return connection_object->t_to_o_requested_packet_interval;
 }
 
+ConnectionObjectFixedVariable
+GetConnectionObjectTargetToOriginatorFixedOrVariableConnectionSize(
+  const ConnectionObject *const RESTRICT connection_object) {
+  const EipUint16 kFixedOrVariableMask = 1 << 9;
+  if ( ( (connection_object->t_to_o_network_connection_parameter) &
+         kFixedOrVariableMask ) == kFixedOrVariableMask ) {
+    return kConnectionObjectVariableConnectionSize;
+  } else {
+    return kConnectionObjectFixedConnectionSize;
+  }
+}
+
 /* Connection Object functions end */
 
 /* global variables private */
@@ -112,7 +124,10 @@ ConnectionManagementHandling g_connection_management_list[2 +
                                                           OPENER_CIP_NUM_APPLICATION_SPECIFIC_CONNECTABLE_OBJECTS
 ];
 
-/** List holding all currently active connections*/
+/** @brief List holding all currently active connections
+ *
+ * An implicit list structure inside the ConnectionObject, so the g_active_connection_list holds the first element of the list
+ * */
 /*@null@*/ ConnectionObject *g_active_connection_list = NULL;
 
 /** buffer connection object needed for forward open */
@@ -729,7 +744,7 @@ void GeneralConnectionConfiguration(ConnectionObject *connection_object) {
   connection_object->production_inhibit_timer = connection_object
                                                 ->production_inhibit_time = 0;
 
-  /*setup the preconsuption timer: max(ConnectionTimeoutMultiplier * ExpectedPacketRate, 10s) */
+  /*setup the preconsumption timer: max(ConnectionTimeoutMultiplier * ExpectedPacketRate, 10s) */
   connection_object->inactivity_watchdog_timer =
     ( ( ( (connection_object->o_to_t_requested_packet_interval) / 1000 )
         << (2 + connection_object->connection_timeout_multiplier) ) > 10000 ) ?
@@ -965,7 +980,7 @@ EipStatus AssembleForwardOpenResponse(
           }
 
           case
-            kConnectionManagerExtendedStatusCodeErrorInvalidTToOConnectionSize:
+            kConnectionManagerExtendedStatusCodeErrorInvalidToOConnectionSize:
           {
             message_router_response->size_of_additional_status = 2;
             message_router_response->additional_status[0] = extended_status;

+ 27 - 16
source/src/cip/cipconnectionmanager.h

@@ -74,7 +74,7 @@ typedef enum {
     = 0x0125,                                                                              /**< Shall be returned as the result of specifying an O->T Redundant Owner flag that is not supported. */
   kConnectionManagerExtendedStatusCodeInvalidConfigurationSize = 0x0126, /**< The data segment provided in the Connection_Path parameter did not contain an acceptable number of 16-bit words for the the configuration application path requested. Two additional status words shall follow, the error code plus the max size in words */
   kConnectionManagerExtendedStatusCodeErrorInvalidOToTConnectionSize = 0x0127, /**< The size of the consuming object declared in the Forward_Open request and available on the target does not match the size declared in the O->T Network Connection Parameter. Two additional status words shall follow, the error code plus the max size in words */
-  kConnectionManagerExtendedStatusCodeErrorInvalidTToOConnectionSize = 0x0128, /**< The size of the consuming object declared in the Forward_Open request and available on the target does not match the size declared in the T->O Network Connection Parameter. Two additional status words shall follow, the error code plus the max size in words  */
+  kConnectionManagerExtendedStatusCodeErrorInvalidToOConnectionSize = 0x0128, /**< The size of the consuming object declared in the Forward_Open request and available on the target does not match the size declared in the T->O Network Connection Parameter. Two additional status words shall follow, the error code plus the max size in words  */
   kConnectionManagerExtendedStatusCodeInvalidConfigurationApplicationPath =
     0x0129,                                                                         /**< Configuration application path specified does not correspond to a valid configuration application path within the target application. This error could also be returned if a configuration application path was required, but not provided by a connection request. */
   kConnectionManagerExtendedStatusCodeInvalidConsumingApplicationPath = 0x012A, /**< Consumed application path specified does not correspond to a valid consumed application path within the target application. This error could also be returned if a consumed application path was required, but not provided by a connection request. */
@@ -89,6 +89,8 @@ typedef enum {
   kConnectionManagerExtendedStatusCodeConnectionTimeoutMultiplierNotAcceptable
     =
       0x0133,
+  kConnectionManagerExtendedStatusCodeMismatchedTToONetworkConnectionFixVar =
+    0x135,
   kConnectionManagerExtendedStatusCodeConnectionTimedOut = 0x0203,
   kConnectionManagerExtendedStatusCodeUnconnectedRequestTimedOut = 0x0204,
   kConnectionManagerExtendedStatusCodeErrorParameterErrorInUnconnectedSendService
@@ -151,21 +153,6 @@ typedef enum ProductionTrigger {
   kProductionTriggerApplicationObjectTriggered = 2
 } ProductionTrigger;
 
-ProductionTrigger GetProductionTrigger(
-  const ConnectionObject *const connection_object);
-
-void SetProductionTrigger(const ProductionTrigger production_trigger,
-                          ConnectionObject *connection_object);
-
-CipUint GetProductionInhibitTime(
-  const ConnectionObject *const connection_object);
-
-void SetProductionInhibitTime(const EipUint16 production_inhibit_time,
-                              ConnectionObject *const connection_object);
-
-CipUdint GetTargetToOriginatorRequestedPackedInterval(
-  const ConnectionObject *const connection_object);
-
 /** @brief macros for comparing sequence numbers according to CIP spec vol
  * 2 3-4.2 for int type variables
  * @define SEQ_LEQ32(a, b) Checks if sequence number a is less or equal than b
@@ -204,6 +191,11 @@ typedef enum {
   kConnectionTypeIoListenOnly = 0x21
 } ConnectionType;
 
+typedef enum {
+  kConnectionObjectFixedConnectionSize,
+  kConnectionObjectVariableConnectionSize
+} ConnectionObjectFixedVariable;
+
 /** @brief Possible values for the watch dog time out action of a connection */
 typedef enum {
   kWatchdogTimeoutActionTransitionToTimedOut = 0, /**< , invalid for explicit message connections */
@@ -417,4 +409,23 @@ void RemoveFromActiveConnections(ConnectionObject *connection_object);
 ForwardOpenConnectionType GetConnectionType(
   EipUint16 network_connection_parameter);
 
+ProductionTrigger GetProductionTrigger(
+  const ConnectionObject *const connection_object);
+
+void SetProductionTrigger(const ProductionTrigger production_trigger,
+                          ConnectionObject *connection_object);
+
+CipUint GetProductionInhibitTime(
+  const ConnectionObject *const connection_object);
+
+void SetProductionInhibitTime(const EipUint16 production_inhibit_time,
+                              ConnectionObject *const connection_object);
+
+CipUdint GetTargetToOriginatorRequestedPackedInterval(
+  const ConnectionObject *const RESTRICT connection_object);
+
+ConnectionObjectFixedVariable
+GetConnectionObjectTargetToOriginatorFixedOrVariableConnectionSize(
+  const ConnectionObject *const RESTRICT connection_object);
+
 #endif /* OPENER_CIPCONNECTIONMANAGER_H_ */

+ 30 - 5
source/src/cip/cipioconnection.c

@@ -5,6 +5,7 @@
  ******************************************************************************/
 
 #include <string.h>
+#include <stdbool.h>
 
 #include "cipioconnection.h"
 
@@ -169,7 +170,7 @@ EipUint16 SetupIoConnectionOriginatorToTargetConnectionPoint(
     /* an assembly object should always have an attribute 3 */
     CipAttributeStruct *attribute = GetCipAttribute(instance, 3);
     OPENER_ASSERT(attribute != NULL);
-    int is_heartbeat = ( ( (CipByteArray *) attribute->data )->length == 0 );
+    bool is_heartbeat = ( ( (CipByteArray *) attribute->data )->length == 0 );
     if ( kCipConnectionObjectTransportClassTriggerClass1
          == GetConnectionTransportClass(io_connection_object) ) {
       //if ((io_connection_object->transport_type_class_trigger & 0x0F) == 1) {
@@ -199,10 +200,33 @@ EipUint16 SetupIoConnectionTargetToOriginatorConnectionPoint(
   ConnectionObject *const io_connection_object,
   ConnectionObject *const RESTRICT connection_object)
 {
+  ConnectionObject *iterator = g_active_connection_list;
+  while (NULL != iterator) {
+    if(io_connection_object->connection_path.connection_point[
+         kConnectionPointProducer] ==
+       iterator->connection_path.connection_point[kConnectionPointProducer]) {
+      //Check parameters
+      if( GetTargetToOriginatorRequestedPackedInterval(io_connection_object) !=
+          GetTargetToOriginatorRequestedPackedInterval(iterator) ) {
+        return kConnectionManagerExtendedStatusCodeErrorRpiValuesNotAcceptable;
+      }
+      if( GetConnectionObjectTargetToOriginatorFixedOrVariableConnectionSize(
+            io_connection_object) !=
+          GetConnectionObjectTargetToOriginatorFixedOrVariableConnectionSize(
+            iterator) ) {
+        return
+          kConnectionManagerExtendedStatusCodeMismatchedTToONetworkConnectionFixVar;
+      }
+
+    }
+
+    iterator = iterator->next_connection_object;
+  }
+
   /*setup producer side*/
   CipClass *const assembly_class = GetCipClass(kCipAssemblyClassCode);
   CipInstance *instance = NULL;
-  if ( 0
+  if ( NULL
        != ( instance =
               GetCipInstance(
                 assembly_class,
@@ -222,7 +246,7 @@ EipUint16 SetupIoConnectionTargetToOriginatorConnectionPoint(
     /* an assembly object should always have an attribute 3 */
     CipAttributeStruct *attribute = GetCipAttribute(instance, 3);
     OPENER_ASSERT(attribute != NULL);
-    int is_heartbeat = ( ( (CipByteArray *) attribute->data )->length == 0 );
+    bool is_heartbeat = ( ( (CipByteArray *) attribute->data )->length == 0 );
     if ( kCipConnectionObjectTransportClassTriggerClass1 ==
          GetConnectionTransportClass(io_connection_object) ) {
       /* class 1 connection */
@@ -239,7 +263,7 @@ EipUint16 SetupIoConnectionTargetToOriginatorConnectionPoint(
       /*wrong connection size*/
       connection_object->correct_target_to_originator_size =
         ( (CipByteArray *) attribute->data )->length + diff_size;
-      return kConnectionManagerExtendedStatusCodeErrorInvalidTToOConnectionSize;
+      return kConnectionManagerExtendedStatusCodeErrorInvalidToOConnectionSize;
     }
   } else {
     return kConnectionManagerExtendedStatusCodeInvalidProducingApplicationPath;
@@ -272,6 +296,7 @@ EipStatus EstablishIoConnection(
   }
 
   *extended_error = ProcessProductionInhibitTime(io_connection_object);
+
   if(0 != *extended_error) {
     return kCipErrorConnectionFailure;
   }
@@ -330,7 +355,7 @@ EipStatus EstablishIoConnection(
     }
   }
 
-  eip_status = OpenCommunicationChannels(io_connection_object);  // Only use T->O Sockaddr Info Item in Forward_Open Request not working
+  eip_status = OpenCommunicationChannels(io_connection_object);
   if (kEipStatusOk != eip_status) {
     *extended_error = 0; /*TODO find out the correct extended error code*/
     return eip_status;

+ 2 - 4
source/src/ports/POSIX/CMakeLists.txt

@@ -12,10 +12,8 @@ opener_common_includes()
 #######################################
 opener_platform_support("INCLUDES")
 
-set (PLATFORMLIBNAME ${OpENer_PLATFORM}PLATFORM)
-
-add_library( ${PLATFORMLIBNAME} ${PLATFORM_SPEC_SRC})
+add_library( ${OpENer_PLATFORM}PLATFORM ${PLATFORM_SPEC_SRC})
 
 add_executable(OpENer main.c)
 
-target_link_libraries( OpENer CIP SAMPLE_APP ENET_ENCAP PLATFORM_GENERIC ${PLATFORMLIBNAME} ${PLATFORM_SPEC_LIBS} ${OpENer_ADD_CIP_OBJECTS} rt)
+target_link_libraries( OpENer CIP SAMPLE_APP ENET_ENCAP PLATFORM_GENERIC ${OpENer_PLATFORM}PLATFORM ${PLATFORM_SPEC_LIBS} ${OpENer_ADD_CIP_OBJECTS} rt)

+ 5 - 5
source/src/ports/generic_networkhandler.c

@@ -300,7 +300,7 @@ void CheckAndHandleTcpListenerSocket(void) {
     FD_SET(new_socket, &master_socket);
     /* add newfd to master set */
     if (new_socket > highest_socket_handle) {
-      OPENER_TRACE_INFO("New highest socket: %d", new_socket);
+      OPENER_TRACE_INFO("New highest socket: %d\n", new_socket);
       highest_socket_handle = new_socket;
     }
 
@@ -799,7 +799,7 @@ int CreateUdpSocket(UdpCommuncationDirection communication_direction,
   /* add new socket to the master list                                             */
   FD_SET(new_socket, &master_socket);
   if (new_socket > highest_socket_handle) {
-    OPENER_TRACE_INFO("New highest socket: %d", new_socket);
+    OPENER_TRACE_INFO("New highest socket: %d\n", new_socket);
     highest_socket_handle = new_socket;
   }
   return new_socket;
@@ -894,9 +894,9 @@ void CheckEncapsulationInactivity(int socket_handle) {
       OPENER_NUMBER_OF_SUPPORTED_SESSIONS,
       socket_handle);
 
-    OPENER_TRACE_INFO("Check socket %d - socket timer: %p\n",
-                      socket_handle,
-                      socket_timer);
+//    OPENER_TRACE_INFO("Check socket %d - socket timer: %p\n",
+//                      socket_handle,
+//                      socket_timer);
     if(NULL != socket_timer) {
       MilliSeconds diffms = g_actual_time - SocketTimerGetLastUpdate(
         socket_timer);

+ 2 - 0
source/tests/CMakeLists.txt

@@ -22,6 +22,8 @@ add_executable( OpENer_Tests OpENerTests.cpp )
 find_library ( CPPUTEST_LIBRARY CppUTest ${CPPUTEST_HOME}/cpputest_build/lib )
 find_library ( CPPUTESTEXT_LIBRARY CppUTestExt ${CPPUTEST_HOME}/cpputest_build/lib )
 
+target_link_libraries( OpENer_Tests CIP ENET_ENCAP PLATFORM_GENERIC SAMPLE_APP ${OpENer_PLATFORM}PLATFORM rt )
+
 target_link_libraries( OpENer_Tests gcov ${CPPUTEST_LIBRARY} ${CPPUTESTEXT_LIBRARY} )
 target_link_libraries( OpENer_Tests UtilsTest Utils ) 
 target_link_libraries( OpENer_Tests EthernetEncapsulationTest ENET_ENCAP )

+ 1 - 0
source/tests/OpENerTests.h

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

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

@@ -8,10 +8,12 @@ opener_common_includes()
 #######################################
 opener_platform_support("INCLUDES")
 
-set( CipTestSrc cipepathtest.cpp cipelectronickeytest.cpp )
+set( CipTestSrc cipepathtest.cpp cipelectronickeytest.cpp cipconnectionmanagertest.cpp )
 
 include_directories( ${SRC_DIR}/cip )
 
 add_library( CipTest ${CipTestSrc} )
 
+target_link_libraries( CipTest CIP ENET_ENCAP PLATFORM_GENERIC SAMPLE_APP ${OpENer_PLATFORM}PLATFORM ${PLATFORM_SPEC_LIBS} rt)
+
 target_link_libraries( CipTest gcov ${CPPUTEST_LIBRARY} ${CPPUTESTEXT_LIBRARY} )

+ 9 - 0
source/tests/cip/connectionmanagertest.cpp → source/tests/cip/cipconnectionmanagertest.cpp

@@ -17,3 +17,12 @@ extern "C" {
 TEST_GROUP(CipConnectionManager) {
 
 };
+
+TEST(CipConnectionManager, GetForwardOpenFixedVarFlag) {
+  ConnectionObject connection_object;
+  connection_object.t_to_o_network_connection_parameter = 0x2222;
+  ConnectionObjectFixedVariable fixed_variable =
+    GetConnectionObjectTargetToOriginatorFixedOrVariableConnectionSize(
+      &connection_object);
+  CHECK_EQUAL(kConnectionObjectVariableConnectionSize, fixed_variable);
+}