瀏覽代碼

Merge pull request #372 from micsat/CommonServices

Common services
Martin Melik-Merkumians 3 年之前
父節點
當前提交
607a771bbf
共有 4 個文件被更改,包括 248 次插入45 次删除
  1. 57 38
      source/src/cip/cipcommon.c
  2. 180 5
      source/src/cip/cipstringi.c
  3. 6 0
      source/src/cip/cipstringi.h
  4. 5 2
      source/src/cip/ciptypes.h

+ 57 - 38
source/src/cip/cipcommon.c

@@ -162,15 +162,34 @@ CipInstance *AddCipInstances(CipClass *RESTRICT const cip_class,
                     number_of_instances,
                     cip_class->class_name);
 
-  next_instance = &cip_class->instances; /* get address of pointer to head of chain */
-  while(*next_instance) /* as long as what pp points to is not zero */
-  {
-    next_instance = &(*next_instance)->next; /* follow the chain until pp points to pointer that contains a zero */
-    instance_number++; /* keep track of what the first new instance number will be */
-  }
-
   /* Allocate and initialize all needed instances one by one. */
   for(new_instances = 0; new_instances < number_of_instances; new_instances++) {
+
+    /* Find next free instance number */
+    CipBool found_free_number = false;
+
+    while (!found_free_number) {
+      next_instance = &cip_class->instances;           /* set pointer to head of existing instances chain */
+
+      found_free_number = true; /* anticipate instance_number is not in use*/
+
+      /* loop through existing instances */
+      while (*next_instance)           /* as long as what next_instance points to is not zero */
+      {
+        /* check if instance number in use */
+        if(instance_number == (*next_instance)->instance_number) {
+          found_free_number = false;  /* instance number exists already */
+          break;
+        }
+        next_instance = &(*next_instance)->next;                /* get next instance in instances chain*/
+      }
+
+      if(!found_free_number) {
+        instance_number++;                         /* try next instance_number and loop again through existing instances */
+      }
+
+    }
+
     CipInstance *current_instance =
       (CipInstance *) CipCalloc(1, sizeof(CipInstance) );
     OPENER_ASSERT(NULL != current_instance); /* fail if run out of memory */
@@ -1290,13 +1309,14 @@ int DecodePaddedEPath(CipEpath *epath,
 }
 
 EipStatus CipCreateService(CipInstance *RESTRICT const instance,
-                             CipMessageRouterRequest *const message_router_request,
-                             CipMessageRouterResponse *const message_router_response,
-                             const struct sockaddr *originator_address,
-                             const int encapsulation_session) {
+                           CipMessageRouterRequest *const message_router_request,
+                           CipMessageRouterResponse *const message_router_response,
+                           const struct sockaddr *originator_address,
+                           const int encapsulation_session) {
 
   InitializeENIPMessage(&message_router_response->message);
-  message_router_response->reply_service = (0x80 | message_router_request->service);
+  message_router_response->reply_service =
+    (0x80 | message_router_request->service);
   message_router_response->general_status = kCipErrorSuccess;
   message_router_response->size_of_additional_status = 0;
 
@@ -1306,7 +1326,9 @@ EipStatus CipCreateService(CipInstance *RESTRICT const instance,
 
   /* Call the PreCreateCallback if the class provides one. */
   if( NULL != class->PreCreateCallback) {
-    internal_state = class->PreCreateCallback(instance, message_router_request, message_router_response);
+    internal_state = class->PreCreateCallback(instance,
+                                              message_router_request,
+                                              message_router_response);
   }
 
   if (kEipStatusOk == internal_state) {
@@ -1315,23 +1337,27 @@ EipStatus CipCreateService(CipInstance *RESTRICT const instance,
 
     /* Call the PostCreateCallback if the class provides one. */
     if (NULL != class->PostCreateCallback) {
-      class->PostCreateCallback(new_instance, message_router_request, message_router_response);
+      class->PostCreateCallback(new_instance,
+                                message_router_request,
+                                message_router_response);
     }
-    OPENER_TRACE_INFO("Instance number %d created\n", new_instance->instance_number);
+    OPENER_TRACE_INFO("Instance number %d created\n",
+                      new_instance->instance_number);
   }
   return kEipStatusOkSend;
 }
 
 EipStatus CipDeleteService(CipInstance *RESTRICT const instance,
-                 CipMessageRouterRequest *const message_router_request,
-                 CipMessageRouterResponse *const message_router_response,
-                 const struct sockaddr *originator_address,
-                 const int encapsulation_session) {
+                           CipMessageRouterRequest *const message_router_request,
+                           CipMessageRouterResponse *const message_router_response,
+                           const struct sockaddr *originator_address,
+                           const int encapsulation_session) {
 
   message_router_response->general_status = kCipErrorInstanceNotDeletable;
   message_router_response->size_of_additional_status = 0;
   InitializeENIPMessage(&message_router_response->message);
-  message_router_response->reply_service = (0x80 | message_router_request->service);
+  message_router_response->reply_service =
+    (0x80 | message_router_request->service);
 
   EipStatus internal_state = kEipStatusOk;
 
@@ -1362,14 +1388,6 @@ EipStatus CipDeleteService(CipInstance *RESTRICT const instance,
         instances = instances->next;
       }
     }
-    // free all allocated attributes of instance
-    CipAttributeStruct *attribute =
-        instance->attributes; /* init pointer to array of attributes*/
-    for (EipUint16 i = 0; i < instance->cip_class->number_of_attributes; i++) {
-      CipFree(attribute->data);
-      ++attribute;
-    }
-    CipFree(instance->attributes);
 
     /* Call the PostDeleteCallback if the class provides one. */
     if (NULL != class->PostDeleteCallback) {
@@ -1377,8 +1395,6 @@ EipStatus CipDeleteService(CipInstance *RESTRICT const instance,
                                 message_router_response);
     }
 
-    OPENER_TRACE_INFO("Instance number %d deleted\n",
-                      instance->instance_number);
     CipFree(instance);  // delete instance
 
     class->number_of_instances--; /* update the total number of instances
@@ -1386,11 +1402,14 @@ EipStatus CipDeleteService(CipInstance *RESTRICT const instance,
 
     // update largest instance number (class Attribute 2)
     instances = class->instances;
-    while (NULL !=
-           instances->next) {  // get last element - should be largest number
+    EipUint16 max_instance = 0;
+    while (NULL != instances->next) {
+      if(instances->instance_number > max_instance) {
+        max_instance = instances->instance_number;
+      }
       instances = instances->next;
     }
-    class->max_instance = instances->instance_number;
+    class->max_instance = max_instance;
 
     message_router_response->general_status = kCipErrorSuccess;
   }
@@ -1398,15 +1417,15 @@ EipStatus CipDeleteService(CipInstance *RESTRICT const instance,
 }
 
 EipStatus CipResetService(CipInstance *RESTRICT const instance,
-                CipMessageRouterRequest *const message_router_request,
-                CipMessageRouterResponse *const message_router_response,
-                const struct sockaddr *originator_address,
-                const int encapsulation_session) {
+                          CipMessageRouterRequest *const message_router_request,
+                          CipMessageRouterResponse *const message_router_response,
+                          const struct sockaddr *originator_address,
+                          const int encapsulation_session) {
   message_router_response->general_status = kCipErrorSuccess;
   message_router_response->size_of_additional_status = 0;
   InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service =
-      (0x80 | message_router_request->service);
+    (0x80 | message_router_request->service);
 
   EipStatus internal_state = kEipStatusOk;
 

+ 180 - 5
source/src/cip/cipstringi.c

@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2021, Rockwell Automation, Inc.
+ * Copyright (c) 2022, Rockwell Automation, Inc.
  * All rights reserved.
  *
  ******************************************************************************/
@@ -11,6 +11,7 @@
 #include "opener_api.h"
 #include "cipstring.h"
 #include "trace.h"
+#include "endianconv.h"
 
 void CipStringIDelete(CipStringI *const string) {
   for(size_t i = 0; i < string->number_of_strings; ++i) {
@@ -21,19 +22,19 @@ void CipStringIDelete(CipStringI *const string) {
     switch(string->array_of_string_i_structs[i].char_string_struct) {
       case kCipShortString:
         ClearCipShortString(
-           (CipShortString *) &string->array_of_string_i_structs[i].string );
+          (CipShortString *) &string->array_of_string_i_structs[i].string );
         break;
       case kCipString:
         ClearCipString(
-           (CipString *) &string->array_of_string_i_structs[i].string );
+          (CipString *) &string->array_of_string_i_structs[i].string );
         break;
       case kCipString2:
         ClearCipString2(
-           (CipString2 *) &string->array_of_string_i_structs[i].string );
+          (CipString2 *) &string->array_of_string_i_structs[i].string );
         break;
       case kCipStringN:
         ClearCipStringN(
-           (CipStringN *) &string->array_of_string_i_structs[i].string );
+          (CipStringN *) &string->array_of_string_i_structs[i].string );
         break;
       default:
         OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
@@ -154,3 +155,177 @@ void CipStringICopy(CipStringI *const to,
     CipStringIDeepCopyInternalString(toStruct, fromStruct);
   }
 }
+
+void CipStringIDecodeFromMessage(CipStringI *data_to,
+                                 CipMessageRouterRequest *const message_router_request)
+{
+
+  CipStringI *target_stringI = data_to;
+
+  target_stringI->number_of_strings = GetUsintFromMessage(
+    &message_router_request->data);
+
+  target_stringI->array_of_string_i_structs = CipCalloc(
+    target_stringI->number_of_strings, sizeof(CipStringIStruct) );
+
+  for (size_t i = 0; i < target_stringI->number_of_strings; ++i) {
+
+    target_stringI->array_of_string_i_structs[i].language_char_1 =
+      GetUsintFromMessage(&message_router_request->data);
+    target_stringI->array_of_string_i_structs[i].language_char_2 =
+      GetUsintFromMessage(&message_router_request->data);
+    target_stringI->array_of_string_i_structs[i].language_char_3 =
+      GetUsintFromMessage(&message_router_request->data);
+    target_stringI->array_of_string_i_structs[i].char_string_struct =
+      GetUsintFromMessage(&message_router_request->data);
+    target_stringI->array_of_string_i_structs[i].character_set =
+      GetUintFromMessage(&message_router_request->data);
+
+    switch (target_stringI->array_of_string_i_structs[i].char_string_struct) {
+      case kCipShortString: {
+        target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
+                                                                        sizeof(
+                                                                          CipShortString) );
+        CipShortString *short_string =
+          (CipShortString *) (target_stringI->array_of_string_i_structs[i].
+                              string);
+        CipUsint length = GetUsintFromMessage(
+          &message_router_request->data);
+        SetCipShortStringByData(short_string, length,
+                                message_router_request->data);
+        message_router_request->data += length;
+
+      }
+      break;
+      case kCipString: {
+        target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
+                                                                        sizeof(
+                                                                          CipString) );
+        CipString *const string =
+          (CipString *const ) target_stringI->array_of_string_i_structs[i].
+          string;
+        CipUint length = GetUintFromMessage(&message_router_request->data);
+        SetCipStringByData(string, length, message_router_request->data);
+        message_router_request->data += length;
+      }
+      break;
+      case kCipString2: {
+        target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
+                                                                        sizeof(
+                                                                          CipString2) );
+        CipString2 *const string =
+          (CipString2 *const ) target_stringI->array_of_string_i_structs[i].
+          string;
+        CipUint length = GetUintFromMessage(&message_router_request->data);
+        SetCipString2ByData(string, length, message_router_request->data);
+        message_router_request->data += length * 2 * sizeof(CipOctet);
+      }
+      break;
+      case kCipStringN: {
+        CipUint size = GetUintFromMessage(&message_router_request->data);
+        CipUint length = GetUintFromMessage(&message_router_request->data);
+
+        target_stringI->array_of_string_i_structs[i].string = CipCalloc(1,
+                                                                        sizeof(
+                                                                          CipStringN) );
+        CipStringN *const string =
+          (CipStringN *const ) target_stringI->array_of_string_i_structs[i].
+          string;
+        SetCipStringNByData(string, length, size,
+                            message_router_request->data);
+        message_router_request->data += length * size;
+      }
+      break;
+      default:
+        OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
+    }
+  }       //end for
+}
+
+bool CipStringICompare(const CipStringI *const stringI_1,
+                       const CipStringI *const stringI_2) {
+
+  /*loop through struct 1 strings*/
+  for (size_t i = 0; i < stringI_1->number_of_strings; ++i) {
+    // String 1
+    void *string_1 = stringI_1->array_of_string_i_structs[i].string;
+    void *string_1_data = NULL;
+    CipUint len_1 = 0; //size of string-struct in bytes
+
+    switch (stringI_1->array_of_string_i_structs[i].char_string_struct) {
+      case kCipShortString: {
+        len_1 = ((CipShortString *)string_1)->length;
+        string_1_data = ((CipShortString *)string_1)->string;
+      }
+      break;
+      case kCipString: {
+        len_1 = ((CipString *)string_1)->length;
+        string_1_data = ((CipString *)string_1)->string;
+      }
+
+      break;
+      case kCipString2: {
+        len_1 = ((CipString2 *)string_1)->length * 2;
+        string_1_data = ((CipString2 *)string_1)->string;
+      }
+      break;
+      case kCipStringN: {
+        CipUint length = ((CipStringN *)string_1)->length;
+        CipUint size = ((CipStringN *)string_1)->size; //bytes per symbol
+        len_1 = length * size;
+        string_1_data = ((CipStringN *)string_1)->string;
+
+      }
+      break;
+      default:
+        OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
+    }
+
+    /*loop through struct 2 strings*/
+    for (size_t j = 0; j < stringI_2->number_of_strings; ++j) {
+      // String 2
+      void *string_2 = stringI_2->array_of_string_i_structs[j].string;
+      void *string_2_data = NULL;
+      CipUint len_2 = 0; //size of string-struct in bytes
+
+      switch (stringI_2->array_of_string_i_structs[j].char_string_struct) {
+        case kCipShortString: {
+          len_2 = ((CipShortString *)string_2)->length;
+          string_2_data = ((CipShortString *)string_2)->string;
+        }
+        break;
+        case kCipString: {
+          len_2 = ((CipString *)string_2)->length;
+          string_2_data = ((CipString *)string_2)->string;
+        }
+
+        break;
+        case kCipString2: {
+          len_2 = ((CipString2 *)string_2)->length * 2;
+          string_2_data = ((CipString2 *)string_2)->string;
+        }
+        break;
+        case kCipStringN: {
+          CipUint length = ((CipStringN *)string_2)->length;
+          CipUint size = ((CipStringN *)string_2)->size; //bytes per symbol
+          len_2 = length * size;
+          string_2_data = ((CipStringN *)string_2)->string;
+
+        }
+        break;
+        default:
+          OPENER_TRACE_ERR("CIP File: No valid String type received!\n");
+      }
+
+      /*compare strings*/ //TODO: compare works only for same data types
+      if (len_1 == len_2) {
+        if (0 == memcmp(string_1_data, string_2_data, len_1) ) {
+          return true;
+        }
+      }
+    }             //end for 1
+  }       //end for 2
+
+  return false;
+}
+

+ 6 - 0
source/src/cip/cipstringi.h

@@ -12,3 +12,9 @@ bool CipStringIsAnyStringEmpty(const CipStringI *const string);
 
 void CipStringICopy(CipStringI *const to,
                     const CipStringI *const from);
+
+void CipStringIDecodeFromMessage(CipStringI *data_to,
+                                 CipMessageRouterRequest *const message_router_request);
+
+bool CipStringICompare(const CipStringI *const stringI_1,
+                       const CipStringI *const stringI_2);

+ 5 - 2
source/src/cip/ciptypes.h

@@ -314,6 +314,7 @@ typedef struct cip_instance {
   struct cip_class *cip_class;   /**< class the instance belongs to */
   struct cip_instance *next;   /**< next instance, all instances of a class live
                                   in a linked list */
+  void *data; /**< pointer to instance data struct */
 } CipInstance;
 
 /** @ingroup CIP_API
@@ -347,8 +348,10 @@ typedef EipStatus (*CipGetSetCallback)(CipInstance *const instance,
  *  @return           status of kEipStatusOk or kEipStatusError on failure
  */
 typedef EipStatus (*CipCallback)(CipInstance *const instance,
-                const CipMessageRouterRequest *const message_router_request,
-		CipMessageRouterResponse *const message_router_response);
+                                 const CipMessageRouterRequest *const
+                                 message_router_request,
+                                 CipMessageRouterResponse *const
+                                 message_router_response);
 
 /** @brief Type definition of CipClass that is a subclass of CipInstance */
 typedef struct cip_class {