Browse Source

Fixes ListIdentity response

Signed-off-by: Martin Melik Merkumians <melik-merkumians@acin.tuwien.ac.at>
Martin Melik Merkumians 7 năm trước cách đây
mục cha
commit
72d0b5147f

+ 1 - 0
source/CMakeLists.txt

@@ -65,6 +65,7 @@ if( OpENer_TESTS )
   enable_language( CXX )
   set( CPPUTEST_HOME "" CACHE PATH "Path to CppUTest directory" )
   INCLUDE( ${OpENer_BUILDSUPPORT_DIR}/OpENer_Tests.cmake )
+  add_test_includes()
   add_subdirectory( tests )
 endif( OpENer_TESTS )
 

+ 2 - 2
source/buildsupport/OpENer_Tests.cmake

@@ -2,7 +2,7 @@
 # Adds test includes                  #
 #######################################
 macro( add_test_includes )
-  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -include ${CPPUTEST_HOME}/include/CppUTest/MemoryLeakDetectorNewMacros.h" )
-  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -include ${CPPUTEST_HOME}/include/CppUTest/MemoryLeakDetectorMallocMacros.h" )
+  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage -include ${CPPUTEST_HOME}/include/CppUTest/MemoryLeakDetectorNewMacros.h" )
+  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage -include ${CPPUTEST_HOME}/include/CppUTest/MemoryLeakDetectorMallocMacros.h" )
   include_directories( ${CPPUTEST_HOME}/include )
 endmacro( add_test_includes )

+ 43 - 24
source/src/enet_encap/encap.c

@@ -130,10 +130,6 @@ EipStatus HandleReceivedInvalidCommand(
 
 int GetFreeSessionIndex(void);
 
-EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer,
-                                      int receive_buffer_length,
-                                      EncapsulationData *const encapsulation_data);
-
 SessionStatus CheckRegisteredSessions(
   const EncapsulationData *const receive_data);
 
@@ -142,10 +138,6 @@ int EncapsulateData(const EncapsulationData *const send_data);
 void DetermineDelayTime(const EipByte *const buffer_start,
                         DelayedEncapsulationMessage *const delayed_message_buffer);
 
-void EncapsulateListIdentityResponseMessage(
-  const EncapsulationData *const receive_data,
-  ENIPMessage *const outgoing_message);
-
 /*   @brief Initializes session list and interface information. */
 void EncapsulationInit(void) {
 
@@ -334,11 +326,11 @@ int HandleReceivedExplictUdpData(const int socket,
 
       if (kEipStatusOk < status) {
         /* if status is greater than 0 data has to be sent */
-        status = EncapsulateData(&encapsulation_data);
+        //status = EncapsulateData(&encapsulation_data);
       }
     }
   }
-  return status;
+  return outgoing_message->used_message_length;
 }
 
 /* Probably not needed with new approach */
@@ -439,7 +431,6 @@ void HandleReceivedListIdentityCommandTcp(
   EncapsulateListIdentityResponseMessage(receive_data, outgoing_message);
 }
 
-//TODO: Check and update this - Issue 141
 void HandleReceivedListIdentityCommandUdp(const int socket,
                                           const struct sockaddr_in *const from_address,
                                           const EncapsulationData *const receive_data,
@@ -475,21 +466,46 @@ void EncapsulateListIdentityResponseMessage(
   const EncapsulationData *const receive_data,
   ENIPMessage *const outgoing_message) {
 
-  const CipUint kEncapsulationCommandListIdentity = 0x63;
+
+  const CipUint kEncapsulationCommandListIdentityCommandSpecificLength =
+    sizeof(CipUint) + sizeof(CipInt) + sizeof(CipUint) + sizeof(CipUdint) +
+    8 *
+    sizeof(CipUsint) + sizeof(CipUint) + sizeof(CipUint) + sizeof(CipUint) + 2 *
+    sizeof(CipUsint) + sizeof(CipWord) + sizeof(CipUdint) +
+    sizeof(
+      CipUsint) + product_name_.length + sizeof(CipUsint);
+  const CipUint kEncapsulationCommandListIdentityLength =
+    kEncapsulationCommandListIdentityCommandSpecificLength + sizeof(CipUint) +
+    sizeof(CipUint)
+    + sizeof(CipUint);               /* Last element is item count */
+
+  GenerateEncapsulationHeader(receive_data,
+                              kEncapsulationCommandListIdentityLength,
+                              0,   /* Session handle will be ignored by receiver */
+                              kEncapsulationProtocolSuccess,
+                              outgoing_message);
 
   outgoing_message->used_message_length += AddIntToMessage(1,
                                                            &outgoing_message->current_message_position); /* Item count: one item */
+
+  /* Item ID*/
+  const CipUint kItemIDCipIdentity = 0x0C;
   outgoing_message->used_message_length += AddIntToMessage(
-    kEncapsulationCommandListIdentity,
+    kItemIDCipIdentity,
     &outgoing_message->current_message_position);
 
+
   EipByte *id_length_buffer = outgoing_message->current_message_position;
-  outgoing_message->used_message_length += MoveMessageNOctets(2,
-                                                              (const CipOctet **) (
-                                                                &
-                                                                outgoing_message
-                                                                ->
-                                                                current_message_position) ); /*at this place the real length will be inserted below*/
+//  outgoing_message->used_message_length += MoveMessageNOctets(2,
+//                                                              (const CipOctet **) (
+//                                                                &
+//                                                                outgoing_message
+//                                                                ->
+//                                                                current_message_position) ); /*at this place the real length will be inserted below*/
+
+  outgoing_message->used_message_length += AddIntToMessage(
+    kEncapsulationCommandListIdentityCommandSpecificLength,
+    &outgoing_message->current_message_position);
 
   outgoing_message->used_message_length += AddIntToMessage(
     kSupportedProtocolVersion,
@@ -499,9 +515,10 @@ void EncapsulateListIdentityResponseMessage(
     htons(kOpenerEthernetPort), interface_configuration_.ip_address,
     &outgoing_message->current_message_position);
 
+  /** Array of USINT - length 8 shall be set to zero */
   memset(outgoing_message->current_message_position, 0, 8);
-  MoveMessageNOctets(8,
-                     (const CipOctet **) &outgoing_message->current_message_position);
+  outgoing_message->used_message_length += MoveMessageNOctets(8,
+                                                              (const CipOctet **) &outgoing_message->current_message_position);
 
   outgoing_message->used_message_length += AddIntToMessage(vendor_id_,
                                                            &outgoing_message->current_message_position);
@@ -520,16 +537,18 @@ void EncapsulateListIdentityResponseMessage(
   *outgoing_message->current_message_position++ =
     (unsigned char) product_name_.length;
   outgoing_message->used_message_length++;
+
   memcpy(outgoing_message->current_message_position, product_name_.string,
          product_name_.length);
   outgoing_message->current_message_position += product_name_.length;
   outgoing_message->used_message_length += product_name_.length;
+
   *outgoing_message->current_message_position++ = 0xFF;
   outgoing_message->used_message_length++;
 
-  outgoing_message->used_message_length += AddIntToMessage(
-    outgoing_message->current_message_position - id_length_buffer - 2,
-    &id_length_buffer);                     /* the -2 is for not counting the length field*/
+//  outgoing_message->used_message_length += AddIntToMessage(
+//    outgoing_message->current_message_position - id_length_buffer - 2,
+//    &id_length_buffer);                     /* the -2 is for not counting the length field*/
 }
 
 void DetermineDelayTime(const EipByte *const buffer_start,

+ 10 - 0
source/src/enet_encap/encap.h

@@ -93,4 +93,14 @@ void CloseEncapsulationSessionBySockAddr(
 
 void CloseClass3ConnectionBasedOnSession(size_t encapsulation_session_handle);
 
+/* No reason to use this functions outside the encapsulation layer, they are here for testing */
+typedef struct enip_message ENIPMessage;
+void EncapsulateListIdentityResponseMessage(
+  const EncapsulationData *const receive_data,
+  ENIPMessage *const outgoing_message);
+
+EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer,
+                                      int receive_buffer_length,
+                                      EncapsulationData *const encapsulation_data);
+
 #endif /* OPENER_ENCAP_H_ */

+ 1 - 1
source/src/utils/enipmessage.h

@@ -8,7 +8,7 @@
 
 #include "opener_user_conf.h"
 
-typedef struct {
+typedef struct enip_message {
   CipOctet message_buffer[PC_OPENER_ETHERNET_BUFFER_SIZE];
   CipOctet *current_message_position;
   size_t used_message_length;

+ 3 - 1
source/tests/CMakeLists.txt

@@ -7,6 +7,7 @@
 #######################################
 add_test_includes()
 
+opener_common_includes()
 
 ###################################################
 # Copy custom test output file to binary location #
@@ -17,12 +18,13 @@ add_subdirectory( cip )
 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 )
 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 rt )
 
 target_link_libraries( OpENer_Tests gcov ${CPPUTEST_LIBRARY} ${CPPUTESTEXT_LIBRARY} )
 target_link_libraries( OpENer_Tests UtilsTest Utils ) 

+ 6 - 0
source/tests/OpENerTests.cpp

@@ -1,10 +1,16 @@
 #include "OpENerTests.h"
 
+extern "C" {
+#include "endianconv.h"
+}
+
 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);
 
+  DetermineEndianess();
+
   return CommandLineTestRunner::RunAllTests(argc, argv);
 }

+ 1 - 0
source/tests/OpENerTests.h

@@ -9,3 +9,4 @@ IMPORT_TEST_GROUP(CipConnectionManager);
 IMPORT_TEST_GROUP(CipConnectionObject);
 IMPORT_TEST_GROUP(SocketTimer);
 IMPORT_TEST_GROUP(DoublyLinkedList);
+IMPORT_TEST_GROUP(EncapsulationProtocol);

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

@@ -8,7 +8,7 @@ opener_common_includes()
 #######################################
 opener_platform_support("INCLUDES")
 
-set( EthernetEncapsulationTestSrc endianconvtest.cpp )
+set( EthernetEncapsulationTestSrc endianconvtest.cpp encaptest.cpp)
 
 include_directories( ${SRC_DIR}/enet_encap )
 

+ 48 - 0
source/tests/enet_encap/encaptest.cpp

@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2018, Rockwell Automation, Inc.
+ * All rights reserved.
+ *
+ ******************************************************************************/
+
+
+#include <CppUTest/TestHarness.h>
+#include <stdint.h>
+#include <string.h>
+
+extern "C" {
+
+#include "encap.h"
+
+#include "ciptypes.h"
+#include "enipmessage.h"
+
+}
+
+TEST_GROUP(EncapsulationProtocol) {
+
+};
+
+TEST(EncapsulationProtocol, AnswerListIdentityRequest) {
+
+  CipOctet incoming_message[] =
+    "\x63\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd7\xdd\x00\x00" \
+    "\x00\x00\x00\x00\x00\x00\x00\x00";
+
+  CipOctet expected_outgoing_message[] =
+    "\x63\x00\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd7\xdd\x00\x00" \
+    "\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x0c\x00\x2b\x00\x01\x00" \
+    "\x00\x02\xaf\x12\xc0\xa8\x38\x65\x00\x00\x00\x00\x00\x00\x00\x00" \
+    "\x01\x00\x0c\x00\xe9\xfd\x02\x01\x00\x00\x15\xcd\x5b\x07\x09\x4f" \
+    "\x70\x45\x4e\x65\x72\x20\x50\x43\xff";
+
+  EncapsulationData receive_data;
+  ENIPMessage outgoing_message;
+  InitializeENIPMessage(&outgoing_message);
+
+  CreateEncapsulationStructure(incoming_message,
+                               sizeof(incoming_message),
+                               &receive_data);
+
+  EncapsulateListIdentityResponseMessage(&receive_data, &outgoing_message);
+
+}