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

Changes how encoding is handled

In this first commit there are radical changes to the messaging, attribute,
and encoding infrastructure to enable easier extension of new types and
detangling od AttributeAll and AttributeSingle

Signed-off-by: Martin Melik Merkumians <melik-merkumians@acin.tuwien.ac.at>
Martin Melik Merkumians 5 лет назад
Родитель
Сommit
1de1c50f7d

+ 5 - 3
source/src/cip/cipassembly.c

@@ -117,15 +117,17 @@ CipInstance *CreateAssemblyObject(const EipUint32 instance_id,
 
   assembly_byte_array->length = data_length;
   assembly_byte_array->data = data;
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   3,
                   kCipByteArray,
+				  EncodeCipByteArray,
                   assembly_byte_array,
                   kSetAndGetAble | kPreGetFunc | kPostSetFunc);
   /* Attribute 4 Number of bytes in Attribute 3 */
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   4,
                   kCipUint,
+				  EncodeCipUint,
                   &(assembly_byte_array->length),
                   kGetableSingle);
 
@@ -161,7 +163,7 @@ EipStatus SetAssemblyAttributeSingle(CipInstance *const instance,
 
   const EipUint8 *const router_request_data = message_router_request->data;
 
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service =
     (0x80 | message_router_request->service);
   message_router_response->general_status = kCipErrorAttributeNotSupported;

+ 228 - 117
source/src/cip/cipcommon.c

@@ -22,6 +22,9 @@
 #if defined(OPENER_IS_DLR_DEVICE) && 0 != OPENER_IS_DLR_DEVICE
   #include "cipdlr.h"
 #endif
+
+//#include "../cip_objects/CIPFileObject/cipfile.h"
+
 #include "cipqos.h"
 #include "cpf.h"
 #include "trace.h"
@@ -30,11 +33,11 @@
 #include "stdlib.h"
 
 /* global public variables */
-EipUint8 g_message_data_reply_buffer[OPENER_MESSAGE_DATA_REPLY_BUFFER]; /**< Reply buffer */
-
+//EipUint8 g_message_data_reply_buffer[OPENER_MESSAGE_DATA_REPLY_BUFFER]; /**< Reply buffer */
+//TODO: Delete
 /* private functions*/
-int EncodeEPath(CipEpath *epath,
-                EipUint8 **message);
+void EncodeEPath(CipEpath *epath,
+                ENIPMessage *message);
 
 void CipStackInit(const EipUint16 unique_connection_id) {
   /* The message router is the first CIP object be initialized!!! */
@@ -56,6 +59,8 @@ void CipStackInit(const EipUint16 unique_connection_id) {
 #endif
   eip_status = CipQoSInit();
   OPENER_ASSERT(kEipStatusOk == eip_status)
+//  eip_status = CipFileInit();
+//  OPENER_ASSERT(kEipStatusOk == eip_status)
   /* the application has to be initialized at last */
   eip_status = ApplicationInitialization();
   OPENER_ASSERT(kEipStatusOk == eip_status)
@@ -128,7 +133,7 @@ EipStatus NotifyClass(const CipClass *RESTRICT const cip_class,
 
   /* handle error replies*/
   message_router_response->size_of_additional_status = 0;       /* fill in the rest of the reply with not much of anything*/
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service = (0x80
                                             | message_router_request->service); /* except the reply code is an echo of the command + the reply flag */
 
@@ -286,27 +291,27 @@ CipClass *CreateCipClass(const CipUdint class_code,
   AllocateAttributeMasks(cip_class);  /* Allocation of bitmasks for Instance Attributes */
 
   if (NULL == initializer) {
-    InsertAttribute( (CipInstance *) cip_class, 1, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 1, kCipUint, EncodeCipUint,
                      (void *) &cip_class->revision, kGetableSingleAndAll ); /* revision */
-    InsertAttribute( (CipInstance *) cip_class, 2, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 2, kCipUint, EncodeCipUint,
                      (void *) &cip_class->number_of_instances,
                      kGetableSingleAndAll );                        /*  largest instance number */
-    InsertAttribute( (CipInstance *) cip_class, 3, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 3, kCipUint, EncodeCipUint,
                      (void *) &cip_class->number_of_instances,
                      kGetableSingleAndAll );                        /* number of instances currently existing*/
-    InsertAttribute( (CipInstance *) cip_class, 4, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 4, kCipUint, EncodeCipUint,
                      (void *) &kCipUintZero, kGetableAll );         /* optional attribute list - default = 0 */
-    InsertAttribute( (CipInstance *) cip_class, 5, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 5, kCipUint, EncodeCipUint,
                      (void *) &kCipUintZero, kNotSetOrGetable );    /* optional service list - default = 0 */
-    InsertAttribute( (CipInstance *) cip_class, 6, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 6, kCipUint, EncodeCipUint,
                      (void *) &meta_class->highest_attribute_number,
                      kGetableSingle );                              /* max class attribute number*/
-    InsertAttribute( (CipInstance *) cip_class, 7, kCipUint,
+    InsertAttribute2( (CipInstance *) cip_class, 7, kCipUint, EncodeCipUint,
                      (void *) &cip_class->highest_attribute_number,
                      kGetableSingle );                              /* max instance attribute number*/
 	  if (number_of_class_services > 0) {
 		if (number_of_class_services > 1) {             /*only if the mask has values add the get_attribute_all service */
-		  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll,
+		  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll2,
 						"GetAttributeAll");                     /* bind instance services to the metaclass*/
 		}
 		InsertService(meta_class, kGetAttributeSingle, &GetAttributeSingle,
@@ -335,6 +340,50 @@ void InsertAttribute(CipInstance *const instance,
     if (attribute->data == NULL) {             /* found non set attribute */
       attribute->attribute_number = attribute_number;
       attribute->type = cip_type;
+      attribute->encode = NULL;
+      attribute->attribute_flags = cip_flags;
+      attribute->data = data;
+
+      OPENER_ASSERT(attribute_number <= cip_class->highest_attribute_number)
+
+      size_t index = CalculateIndex(attribute_number);
+
+      cip_class->get_single_bit_mask[index] |=
+        (cip_flags & kGetableSingle) ?
+        1 << (attribute_number) % 8 : 0;
+      cip_class->get_all_bit_mask[index] |=
+        (cip_flags & kGetableAll) ? 1 << (attribute_number) % 8 : 0;
+      cip_class->set_bit_mask[index] |=
+        ( (cip_flags & kSetable) ? 1 : 0 ) << ( (attribute_number) % 8 );
+
+      return;
+    }
+    attribute++;
+  }
+  OPENER_TRACE_ERR(
+    "Tried to insert too many attributes into class: %" PRIu32 " '%s', instance %" PRIu32 "\n",
+    cip_class->class_code, cip_class->class_name, instance->instance_number);
+  OPENER_ASSERT(0)
+  /* trying to insert too many attributes*/
+}
+
+void InsertAttribute2(CipInstance *const instance,
+                     const EipUint16 attribute_number,
+                     const EipUint8 cip_type,
+					 CipAttributeEncodeInMessage encode_function,
+                     void *const data,
+                     const EipByte cip_flags) {
+
+  CipAttributeStruct *attribute = instance->attributes;
+  CipClass *cip_class = instance->cip_class;
+
+  OPENER_ASSERT(NULL != attribute)
+  /* adding a attribute to a class that was not declared to have any attributes is not allowed */
+  for (int i = 0; i < instance->cip_class->number_of_attributes; i++) {
+    if (attribute->data == NULL) {             /* found non set attribute */
+      attribute->attribute_number = attribute_number;
+      attribute->type = cip_type;
+      attribute->encode = encode_function;
       attribute->attribute_flags = cip_flags;
       attribute->data = data;
 
@@ -428,11 +477,10 @@ CipAttributeStruct *GetCipAttribute(const CipInstance *const instance,
 }
 
 void GenerateGetAttributeSingleHeader(const CipMessageRouterRequest *const message_router_request, CipMessageRouterResponse *const message_router_response) {
-	  message_router_response->data_length = 0;
-	  message_router_response->reply_service = (0x80
-	                                            | message_router_request->service);
-	  message_router_response->general_status = kCipErrorAttributeNotSupported;
-	  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->general_status = kCipErrorAttributeNotSupported;
+  message_router_response->size_of_additional_status = 0;
 }
 
 /* TODO this needs to check for buffer overflow*/
@@ -445,7 +493,6 @@ EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance,
 
   CipAttributeStruct *attribute = GetCipAttribute(instance,
                                                   message_router_request->request_path.attribute_number);
-  EipByte *message = message_router_response->data;
 
   GenerateGetAttributeSingleHeader(message_router_request, message_router_response);
 
@@ -474,9 +521,11 @@ EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance,
       }
 
       OPENER_ASSERT(NULL != attribute)
-      message_router_response->data_length = EncodeData(attribute->type,
-                                                        attribute->data,
-                                                        &message);
+      if(NULL == attribute->encode) {
+    	  EncodeData(attribute->type, attribute->data, message_router_response);
+      } else {
+    	  attribute->encode(attribute->data, &message_router_response->message);
+      }
       message_router_response->general_status = kCipErrorSuccess;
 
       /* Call the PostGetCallback if enabled for this attribute and the class provides one. */
@@ -489,10 +538,70 @@ EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance,
   return kEipStatusOkSend;
 }
 
-int EncodeData(const EipUint8 cip_type,
+void EncodeCipBool(const void *const data, ENIPMessage *const outgoing_message) {
+  AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
+}
+
+void EncodeCipUsint(const void *const data, ENIPMessage *const outgoing_message) {
+  AddSintToMessage(*(EipUint8 *) (data), outgoing_message);
+}
+
+void EncodeCipUint(const void *const data, ENIPMessage *const outgoing_message) {
+  AddIntToMessage(*(EipUint16 *) (data), outgoing_message);
+}
+
+void EncodeCipUdint(const void *const data, ENIPMessage *const outgoing_message) {
+  AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
+}
+
+void EncodeCipWord(const void *const data, ENIPMessage *const outgoing_message) {
+  AddIntToMessage(*(EipUint16 *) (data), outgoing_message);
+}
+
+void EncodeCipDword(const void *const data, ENIPMessage *const outgoing_message) {
+  AddDintToMessage(*(EipUint32 *) (data), outgoing_message);
+}
+
+void EncodeCipShortString(const void *const data, ENIPMessage *const outgoing_message) {
+  CipShortString *const short_string = (CipShortString *) data;
+
+  AddSintToMessage(short_string->length, outgoing_message);
+
+  memcpy(outgoing_message->current_message_position, short_string->string, short_string->length);
+  outgoing_message->current_message_position += short_string->length;
+  outgoing_message->used_message_length += short_string->length;
+}
+
+void EncodeCipString(const void *const data, ENIPMessage *const outgoing_message) {
+    CipString *const string = (CipString *) data;
+
+    AddIntToMessage(*(EipUint16 *) &(string->length), outgoing_message);
+    memcpy(outgoing_message->current_message_position, string->string, string->length);
+    outgoing_message->current_message_position += string->length;
+    outgoing_message->used_message_length += string->length;
+
+    if (outgoing_message->used_message_length & 0x01) {
+      /* we have an odd byte count */
+  	  AddSintToMessage(0, outgoing_message);
+    }
+}
+
+
+void EncodeCipByteArray(const void *const data, ENIPMessage *const outgoing_message) {
+    OPENER_TRACE_INFO(" -> get attribute byte array\r\n");
+    CipByteArray *cip_byte_array = (CipByteArray *) data;
+    memcpy(&outgoing_message->current_message_position, cip_byte_array->data, cip_byte_array->length);
+    outgoing_message->current_message_position += cip_byte_array->length;
+    outgoing_message->used_message_length += cip_byte_array->length;
+}
+
+void EncodeCipEPath(const void *const data, ENIPMessage *const outgoing_message) {
+	EncodeEPath( (CipEpath *) data, outgoing_message );
+}
+
+void EncodeData(const EipUint8 cip_type,
                const void *const cip_data,
-               EipUint8 **cip_message) {
-  int counter = 0;
+			   CipMessageRouterResponse *const message_router_response) {
 
   switch (cip_type)
   /* check the data type of attribute */
@@ -501,20 +610,20 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipSint):
     case (kCipUsint):
     case (kCipByte):
-      counter = AddSintToMessage(*(EipUint8 *) (cip_data), cip_message);
+	  AddSintToMessage(*(EipUint8 *) (cip_data), &message_router_response->message);
       break;
 
     case (kCipInt):
     case (kCipUint):
     case (kCipWord):
-      counter = AddIntToMessage(*(EipUint16 *) (cip_data), cip_message);
+      AddIntToMessage(*(EipUint16 *) (cip_data), &message_router_response->message);
       break;
 
     case (kCipDint):
     case (kCipUdint):
     case (kCipDword):
     case (kCipReal):
-      counter = AddDintToMessage(*(EipUint32 *) (cip_data), cip_message);
+      AddDintToMessage(*(EipUint32 *) (cip_data), &message_router_response->message);
       break;
 
 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
@@ -522,7 +631,7 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipUlint):
     case (kCipLword):
     case (kCipLreal):
-      counter = AddLintToMessage(*(EipUint64 *) (cip_data), cip_message);
+      AddLintToMessage(*(EipUint64 *) (cip_data), &message_router_response->message);
       break;
 #endif
 
@@ -534,16 +643,14 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipString): {
       CipString *const string = (CipString *) cip_data;
 
-      AddIntToMessage(*(EipUint16 *) &(string->length), cip_message);
-      memcpy(*cip_message, string->string, string->length);
-      *cip_message += string->length;
+      AddIntToMessage(*(EipUint16 *) &(string->length), &message_router_response->message);
+      memcpy(message_router_response->message.current_message_position, string->string, string->length);
+      message_router_response->message.current_message_position += string->length;
+      message_router_response->message.used_message_length += string->length;
 
-      counter = string->length + 2;           /* we have a two byte length field */
-      if (counter & 0x01) {
+      if (message_router_response->message.used_message_length & 0x01) {
         /* we have an odd byte count */
-        **cip_message = 0;
-        ++(*cip_message);
-        counter++;
+    	  AddSintToMessage(0, &message_router_response->message);
       }
       break;
     }
@@ -557,13 +664,11 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipShortString): {
       CipShortString *const short_string = (CipShortString *) cip_data;
 
-      **cip_message = short_string->length;
-      ++(*cip_message);
-
-      memcpy(*cip_message, short_string->string, short_string->length);
-      *cip_message += short_string->length;
+      AddSintToMessage(short_string->length, &message_router_response->message);
 
-      counter = short_string->length + 1;
+      memcpy(message_router_response->message.current_message_position, short_string->string, short_string->length);
+      message_router_response->message.current_message_position += short_string->length;
+      message_router_response->message.used_message_length += short_string->length;
       break;
     }
 
@@ -571,7 +676,7 @@ int EncodeData(const EipUint8 cip_type,
       break;
 
     case (kCipEpath):
-      counter = EncodeEPath( (CipEpath *) cip_data, cip_message );
+      EncodeEPath( (CipEpath *) cip_data, &message_router_response->message );
       break;
 
     case (kCipEngUnit):
@@ -580,11 +685,9 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipUsintUsint): {
       CipRevision *revision = (CipRevision *) cip_data;
 
-      **cip_message = revision->major_revision;
-      ++(*cip_message);
-      **cip_message = revision->minor_revision;
-      ++(*cip_message);
-      counter = 2;
+      AddSintToMessage(revision->major_revision, &message_router_response->message);
+      AddSintToMessage(revision->minor_revision, &message_router_response->message);
+
       break;
     }
 
@@ -593,32 +696,20 @@ int EncodeData(const EipUint8 cip_type,
       CipTcpIpInterfaceConfiguration *
         tcp_ip_network_interface_configuration =
         (CipTcpIpInterfaceConfiguration *) cip_data;
-      counter += AddDintToMessage(
-        ntohl(tcp_ip_network_interface_configuration->ip_address),
-        cip_message);
-      counter += AddDintToMessage(
-        ntohl(tcp_ip_network_interface_configuration->network_mask),
-        cip_message);
-      counter += AddDintToMessage(
-        ntohl(tcp_ip_network_interface_configuration->gateway),
-        cip_message);
-      counter += AddDintToMessage(
-        ntohl(tcp_ip_network_interface_configuration->name_server),
-        cip_message);
-      counter += AddDintToMessage(
-        ntohl(tcp_ip_network_interface_configuration->name_server_2),
-        cip_message);
-      counter += EncodeData(kCipString,
-                            &(tcp_ip_network_interface_configuration->
-                              domain_name),
-                            cip_message);
+      AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->ip_address), &message_router_response->message);
+      AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->network_mask), &message_router_response->message);
+      AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->gateway), &message_router_response->message);
+      AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->name_server), &message_router_response->message);
+      AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->name_server_2),&message_router_response->message);
+      EncodeData(kCipString, &(tcp_ip_network_interface_configuration->domain_name), message_router_response);
       break;
     }
 
     case (kCip6Usint): {
       EipUint8 *p = (EipUint8 *) cip_data;
-      memcpy(*cip_message, p, 6);
-      counter = 6;
+      memcpy(&message_router_response->message.current_message_position, p, 6);
+      message_router_response->message.current_message_position += 6;
+      message_router_response->message.used_message_length += 6;
       break;
     }
 
@@ -628,9 +719,9 @@ int EncodeData(const EipUint8 cip_type,
     case (kCipByteArray): {
       OPENER_TRACE_INFO(" -> get attribute byte array\r\n");
       CipByteArray *cip_byte_array = (CipByteArray *) cip_data;
-      memcpy(*cip_message, cip_byte_array->data, cip_byte_array->length);
-      *cip_message += cip_byte_array->length;
-      counter = cip_byte_array->length;
+      memcpy(&message_router_response->message.current_message_position, cip_byte_array->data, cip_byte_array->length);
+      message_router_response->message.current_message_position += cip_byte_array->length;
+      message_router_response->message.used_message_length += cip_byte_array->length;
     }
     break;
 
@@ -638,21 +729,18 @@ int EncodeData(const EipUint8 cip_type,
     {
       EipUint16 *internal_unit16_6 = (EipUint16 *) cip_data;
 
-      AddIntToMessage(internal_unit16_6[0], cip_message);
-      AddIntToMessage(internal_unit16_6[1], cip_message);
-      AddIntToMessage(internal_unit16_6[2], cip_message);
-      AddIntToMessage(internal_unit16_6[3], cip_message);
-      AddIntToMessage(internal_unit16_6[4], cip_message);
-      AddIntToMessage(internal_unit16_6[5], cip_message);
-      counter = 12;
+      AddIntToMessage(internal_unit16_6[0], &message_router_response->message);
+      AddIntToMessage(internal_unit16_6[1], &message_router_response->message);
+      AddIntToMessage(internal_unit16_6[2], &message_router_response->message);
+      AddIntToMessage(internal_unit16_6[3], &message_router_response->message);
+      AddIntToMessage(internal_unit16_6[4], &message_router_response->message);
+      AddIntToMessage(internal_unit16_6[5], &message_router_response->message);
       break;
     }
     default:
       break;
 
   }
-
-  return counter;
 }
 
 int DecodeData(const EipUint8 cip_data_type,
@@ -744,13 +832,51 @@ CipServiceStruct *GetCipService(const CipInstance *const instance,
   return NULL; /* didn't find the service */
 }
 
+EipStatus GetAttributeAll2(CipInstance *instance,
+                          CipMessageRouterRequest *message_router_request,
+                          CipMessageRouterResponse *message_router_response,
+                          const struct sockaddr *originator_address,
+                          const int encapsulation_session) {
+
+  InitializeENIPMessage(&message_router_response->message);
+  CipAttributeStruct *attribute = instance->attributes;       /* pointer to list of attributes*/
+
+  //Missing header
+
+  if (0 == instance->cip_class->number_of_attributes) {
+    /*there are no attributes to be sent back*/
+    message_router_response->reply_service =
+      (0x80 | message_router_request->service);
+    message_router_response->general_status = kCipErrorServiceNotSupported;
+    message_router_response->size_of_additional_status = 0;
+  } else {
+	  GenerateGetAttributeSingleHeader(message_router_request, message_router_response);
+	  message_router_response->general_status = kCipErrorSuccess;
+    for (size_t j = 0; j < instance->cip_class->number_of_attributes; j++) {
+      /* for each instance attribute of this class */
+      EipUint16 attribute_number = attribute->attribute_number;
+      if ( (instance->cip_class->get_all_bit_mask[CalculateIndex(
+                                                    attribute_number)]) &
+           (1 << (attribute_number % 8) ) ) {
+        /* only return attributes that are flagged as being part of GetAttributeALl */
+        message_router_request->request_path.attribute_number =
+          attribute_number;
+
+        attribute->encode(attribute->data, &message_router_response->message);
+      }
+      attribute++;
+    }
+  }
+  return kEipStatusOkSend;
+}
+
 EipStatus GetAttributeAll(CipInstance *instance,
                           CipMessageRouterRequest *message_router_request,
                           CipMessageRouterResponse *message_router_response,
                           const struct sockaddr *originator_address,
                           const int encapsulation_session) {
 
-  EipUint8 *reply = message_router_response->data;       /* pointer into the reply */
+  InitializeENIPMessage(&message_router_response->message);
   CipAttributeStruct *attribute = instance->attributes;       /* pointer to list of attributes*/
   CipServiceStruct *service = GetCipService(instance, kGetAttributeSingle);       /* pointer to list of services*/
 
@@ -761,7 +887,7 @@ EipStatus GetAttributeAll(CipInstance *instance,
   }
 
   if (0 == instance->cip_class->number_of_attributes) {
-    message_router_response->data_length = 0;                         /*there are no attributes to be sent back*/
+    /*there are no attributes to be sent back*/
     message_router_response->reply_service =
       (0x80 | message_router_request->service);
     message_router_response->general_status = kCipErrorServiceNotSupported;
@@ -777,79 +903,64 @@ EipStatus GetAttributeAll(CipInstance *instance,
         message_router_request->request_path.attribute_number =
           attribute_number;
         if (kEipStatusOkSend !=
-            service->service_function(instance, message_router_request,
+            service->service_function(instance,
+            		                  message_router_request,
                                       message_router_response,
                                       originator_address,
                                       encapsulation_session) ) {
-          message_router_response->data = reply;
           return kEipStatusError;
         }
-        message_router_response->data += message_router_response->data_length;
       }
       attribute++;
     }
-    message_router_response->data_length = message_router_response->data -
-                                           reply;
-    message_router_response->data = reply;
   }
   return kEipStatusOkSend;
 }
 
-int EncodeEPath(CipEpath *epath,
-                EipUint8 **message) {
+void EncodeEPath(CipEpath *epath,
+                ENIPMessage *message) {
   unsigned int length = epath->path_size;
+  size_t start_length = message->used_message_length;
   AddIntToMessage(epath->path_size, message);
 
   if (epath->class_id < 256) {
-    **message = 0x20;             /*8Bit Class Id */
-    ++(*message);
-    **message = (EipUint8) epath->class_id;
-    ++(*message);
+	AddSintToMessage(0x20, message); /* 8 Bit Class Id */
+	AddSintToMessage((EipUint8) epath->class_id, message);
     length -= 1;
   } else {
-    **message = 0x21;             /*16Bit Class Id */
-    ++(*message);
-    **message = 0;             /*pad byte */
-    ++(*message);
+	AddSintToMessage(0x21, message); /*16Bit Class Id */
+	AddSintToMessage(0, message); /*pad byte */
     AddIntToMessage(epath->class_id, message);
     length -= 2;
   }
 
   if (0 < length) {
     if (epath->instance_number < 256) {
-      **message = 0x24;                   /*8Bit Instance Id */
-      ++(*message);
-      **message = (EipUint8) epath->instance_number;
-      ++(*message);
+      AddSintToMessage(0x24, message); /*8Bit Instance Id */
+      AddSintToMessage(epath->instance_number, message);
       length -= 1;
     } else {
-      **message = 0x25;                   /*16Bit Instance Id */
-      ++(*message);
-      **message = 0;                   /*padd byte */
-      ++(*message);
+      AddSintToMessage(0x25, message); /*16Bit Instance Id */
+      AddSintToMessage(0, message); /*pad byte */
       AddIntToMessage(epath->instance_number, message);
       length -= 2;
     }
 
     if (0 < length) {
       if (epath->attribute_number < 256) {
-        **message = 0x30;                         /*8Bit Attribute Id */
-        ++(*message);
-        **message = (EipUint8) epath->attribute_number;
-        ++(*message);
+    	AddSintToMessage(0x30, message); /*8Bit Attribute Id */
+    	AddSintToMessage(epath->attribute_number, message);
         length -= 1;
       } else {
-        **message = 0x31;                         /*16Bit Attribute Id */
-        ++(*message);
-        **message = 0;                         /*pad byte */
-        ++(*message);
+    	AddSintToMessage(0x31, message); /*16Bit Attribute Id */
+        AddSintToMessage(0, message); /*pad byte */
         AddIntToMessage(epath->attribute_number, message);
         length -= 2;
       }
     }
   }
 
-  return 2 + epath->path_size * 2;       /* path size is in 16 bit chunks according to the specification */
+  OPENER_ASSERT(2 + epath->path_size * 2 == message->used_message_length - start_length);  /* path size is in 16 bit chunks according to the specification */
 }
 
 int DecodePaddedEPath(CipEpath *epath,

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

@@ -81,6 +81,12 @@ EipStatus GetAttributeAll(CipInstance *instance,
                           const struct sockaddr *originator_address,
                           const int encapsulation_session);
 
+EipStatus GetAttributeAll2(CipInstance *instance,
+                          CipMessageRouterRequest *message_router_request,
+                          CipMessageRouterResponse *message_router_response,
+                          const struct sockaddr *originator_address,
+                          const int encapsulation_session);
+
 /** @brief Decodes padded EPath
  *  @param epath EPath object to the receiving element
  *  @param message pointer to the message to decode

+ 27 - 32
source/src/cip/cipconnectionmanager.c

@@ -176,25 +176,25 @@ void InitializeConnectionManager(CipClass *class) {
 
   CipClass *meta_class = class->class_instance.cip_class;
 
-  InsertAttribute( (CipInstance *) class, 1, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 1, kCipUint, EncodeCipUint,
                    (void *) &class->revision,
                    kGetableSingleAndAll ); /* revision */
-  InsertAttribute( (CipInstance *) class, 2, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 2, kCipUint, EncodeCipUint,
                    (void *) &class->number_of_instances, kGetableSingleAndAll ); /*  largest instance number */
-  InsertAttribute( (CipInstance *) class, 3, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 3, kCipUint, EncodeCipUint,
                    (void *) &class->number_of_instances, kGetableSingle ); /* number of instances currently existing*/
-  InsertAttribute( (CipInstance *) class, 4, kCipUint, (void *) &kCipUintZero,
+  InsertAttribute2( (CipInstance *) class, 4, kCipUint, EncodeCipUint, (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional attribute list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 5, kCipUint, (void *) &kCipUintZero,
+  InsertAttribute2( (CipInstance *) class, 5, kCipUint, EncodeCipUint, (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional service list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 6, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 6, kCipUint, EncodeCipUint,
                    (void *) &meta_class->highest_attribute_number,
                    kGetableSingleAndAll ); /* max class attribute number*/
-  InsertAttribute( (CipInstance *) class, 7, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 7, kCipUint, EncodeCipUint,
                    (void *) &class->highest_attribute_number,
                    kGetableSingleAndAll ); /* max instance attribute number*/
 
-  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll,	"GetAttributeAll"); /* bind instance services to the metaclass*/
+  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll2,	"GetAttributeAll"); /* bind instance services to the metaclass*/
   InsertService(meta_class, kGetAttributeSingle, &GetAttributeSingle, "GetAttributeSingle");
 
 }
@@ -741,7 +741,6 @@ EipStatus AssembleForwardOpenResponse(
   /* write reply information in CPF struct dependent of pa_status */
   CipCommonPacketFormatData *cip_common_packet_format_data =
     &g_common_packet_format_data_item;
-  EipByte *message = message_router_response->data;
   cip_common_packet_format_data->item_count = 2;
   cip_common_packet_format_data->data_item.type_id =
     kCipItemIdUnconnectedDataItem;
@@ -753,7 +752,7 @@ EipStatus AssembleForwardOpenResponse(
 
   if (kCipErrorSuccess == general_status) {
     OPENER_TRACE_INFO("assembleFWDOpenResponse: sending success response\n");
-    message_router_response->data_length = 26; /* if there is no application specific data */
+    /* if there is no application specific data, total length should be 26 */
     message_router_response->size_of_additional_status = 0;
 
     if (cip_common_packet_format_data->address_info_item[0].type_id != 0) {
@@ -763,14 +762,14 @@ EipStatus AssembleForwardOpenResponse(
       }
     }
 
-    AddDintToMessage(connection_object->cip_consumed_connection_id, &message);
-    AddDintToMessage(connection_object->cip_produced_connection_id, &message);
+    AddDintToMessage(connection_object->cip_consumed_connection_id, &message_router_response->message);
+    AddDintToMessage(connection_object->cip_produced_connection_id, &message_router_response->message);
   } else {
     /* we have an connection creation error */
     OPENER_TRACE_INFO("AssembleForwardOpenResponse: sending error response\n");
     ConnectionObjectSetState(connection_object,
                              kConnectionObjectStateNonExistent);
-    message_router_response->data_length = 10;
+    /* Expected data length is 10 octets */
 
     switch (general_status) {
       case kCipErrorNotEnoughData:
@@ -814,22 +813,20 @@ EipStatus AssembleForwardOpenResponse(
     }
   }
 
-  AddIntToMessage(connection_object->connection_serial_number, &message);
-  AddIntToMessage(connection_object->originator_vendor_id, &message);
-  AddDintToMessage(connection_object->originator_serial_number, &message);
+  AddIntToMessage(connection_object->connection_serial_number, &message_router_response->message);
+  AddIntToMessage(connection_object->originator_vendor_id, &message_router_response->message);
+  AddDintToMessage(connection_object->originator_serial_number, &message_router_response->message);
 
   if (kCipErrorSuccess == general_status) {
     /* set the actual packet rate to requested packet rate */
     AddDintToMessage(connection_object->o_to_t_requested_packet_interval,
-                     &message);
+                     &message_router_response->message);
     AddDintToMessage(connection_object->t_to_o_requested_packet_interval,
-                     &message);
+                     &message_router_response->message);
   }
 
-  *message = 0; /* remaining path size - for routing devices relevant */
-  message++;
-  *message = 0; /* reserved */
-  message++;
+  AddSintToMessage(0, &message_router_response->message); /* remaining path size - for routing devices relevant */
+  AddSintToMessage(0, &message_router_response->message); /* reserved */
 
   return kEipStatusOkSend; /* send reply */
 }
@@ -875,27 +872,26 @@ EipStatus AssembleForwardCloseResponse(
   /* write reply information in CPF struct dependent of pa_status */
   CipCommonPacketFormatData *common_data_packet_format_data =
     &g_common_packet_format_data_item;
-  EipByte *message = message_router_response->data;
   common_data_packet_format_data->item_count = 2;
   common_data_packet_format_data->data_item.type_id =
     kCipItemIdUnconnectedDataItem;
 
   AddNullAddressItem(common_data_packet_format_data);
 
-  AddIntToMessage(connection_serial_number, &message);
-  AddIntToMessage(originatior_vendor_id, &message);
-  AddDintToMessage(originator_serial_number, &message);
+  AddIntToMessage(connection_serial_number, &message_router_response->message);
+  AddIntToMessage(originatior_vendor_id, &message_router_response->message);
+  AddDintToMessage(originator_serial_number, &message_router_response->message);
 
   message_router_response->reply_service = (0x80
                                             | message_router_request->service);
-  message_router_response->data_length = 10; /* if there is no application specific data */
+  /* excepcted length is 10 if there is no application specific data */
 
   if (kConnectionManagerExtendedStatusCodeSuccess == extended_error_code) {
-    *message = 0; /* no application data */
+    AddSintToMessage(0, &message_router_response->message); /* no application data */
     message_router_response->general_status = kCipErrorSuccess;
     message_router_response->size_of_additional_status = 0;
   } else {
-    *message = *message_router_request->data; /* remaining path size */
+    AddSintToMessage(*message_router_request->data, &message_router_response->message); /* remaining path size */
     if (kConnectionManagerExtendedStatusWrongCloser == extended_error_code) {
       message_router_response->general_status = kCipErrorPrivilegeViolation;
     } else {
@@ -905,9 +901,8 @@ EipStatus AssembleForwardCloseResponse(
     }
   }
 
-  message++;
-  *message = 0; /* reserved */
-  message++;
+  // TODO: check if needed message++; seem superfluous with the new AddSint command above
+  AddSintToMessage(0, &message_router_response->message); /* reserved */
 
   return kEipStatusOkSend;
 }

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

@@ -144,7 +144,7 @@ void ConnectionObjectInitializeFromMessage(
                                                  GetSintFromMessage(
                                                    message) );
 
-  MoveMessageNOctets(3, message); /* 3 bytes reserved */
+  (*message) += 3; /* 3 bytes reserved */
 
   /* the requested packet interval parameter needs to be a multiple of TIMERTICK from the header file */
   OPENER_TRACE_INFO(

+ 10 - 17
source/src/cip/cipdlr.c

@@ -49,6 +49,7 @@
 #include "cipcommon.h"
 #include "opener_api.h"
 #include "trace.h"
+#include "endianconv.h"
 
 /* ********************************************************************
  * defines
@@ -89,14 +90,9 @@ CipDlrObject g_dlr;  /**< definition of DLR object instance 1 data */
 /* ********************************************************************
  * local functions
  */
-static int EncodeNodeAddress(CipNodeAddress *node_address, CipOctet **message) {
-  int encoded_len = 0;
-  encoded_len += EncodeData(kCipUdint, &node_address->device_ip,
-                            message);
-  encoded_len += EncodeData(kCip6Usint,
-                            &node_address->device_mac,
-                            message);
-  return encoded_len;
+static void EncodeNodeAddress(CipNodeAddress *node_address, CipMessageRouterResponse *const message_router_response) {
+  EncodeData(kCipUdint, &node_address->device_ip, message_router_response);
+  EncodeData(kCip6Usint, &node_address->device_mac, message_router_response);
 }
 
 static EipStatus GetAttributeSingleDlr(
@@ -108,9 +104,7 @@ static EipStatus GetAttributeSingleDlr(
 
   CipAttributeStruct *attribute = GetCipAttribute(
     instance, message_router_request->request_path.attribute_number);
-  EipByte *message = message_router_response->data;
-
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service = (0x80
                                             | message_router_request->service);
   message_router_response->general_status = kCipErrorAttributeNotSupported;
@@ -149,7 +143,7 @@ static EipStatus GetAttributeSingleDlr(
 
       /* Call the PreGetCallback if enabled for this attribute and the common handler is not used. */
       if (!use_common_handler) {
-        if (attribute->attribute_flags & kPreGetFunc && NULL != instance->cip_class->PreGetCallback) {
+        if ((attribute->attribute_flags & kPreGetFunc) && NULL != instance->cip_class->PreGetCallback) {
           instance->cip_class->PreGetCallback(instance, attribute, message_router_request->service);
         }
       }
@@ -158,17 +152,16 @@ static EipStatus GetAttributeSingleDlr(
         case 4: {
           /* This attribute is not implemented and only reached by GetAttributesAll. */
           const size_t kRingSupStructSize = 12u;
-          memset(message_router_response->data, 0, kRingSupStructSize);
-          message_router_response->data += kRingSupStructSize;
+          FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, kRingSupStructSize, &message_router_response->message);
           message_router_response->general_status = kCipErrorSuccess;
           break;
         }
         case 6: /* fall through */
         case 7: /* fall through */
         case 10:
-          message_router_response->data_length = EncodeNodeAddress(
+          EncodeNodeAddress(
             (CipNodeAddress *)attribute->data,
-            &message);
+            message_router_response);
           message_router_response->general_status = kCipErrorSuccess;
           break;
 
@@ -181,7 +174,7 @@ static EipStatus GetAttributeSingleDlr(
 
       /* Call the PostGetCallback if enabled for this attribute and the common handler is not used. */
       if (!use_common_handler) {
-        if (attribute->attribute_flags & kPostGetFunc && NULL != instance->cip_class->PostGetCallback) {
+        if ((attribute->attribute_flags & kPostGetFunc) && NULL != instance->cip_class->PostGetCallback) {
           instance->cip_class->PostGetCallback(instance, attribute, message_router_request->service);
         }
       }

+ 18 - 18
source/src/cip/cipepath.c

@@ -333,17 +333,17 @@ CipDword CipEpathGetLogicalValue(const EipUint8 **message) {
   LogicalSegmentLogicalFormat logical_format =
     GetPathLogicalSegmentLogicalFormat(*message);
   CipDword data = 0;
-  MoveMessageNOctets(1, message); /* Move to logical value */
+  (*message) += 1; /* Move to logical value */
   switch (logical_format) {
     case kLogicalSegmentLogicalFormatEightBit:
       data = GetSintFromMessage(message);
       break;
     case kLogicalSegmentLogicalFormatSixteenBit:
-      MoveMessageNOctets(1, message); /* Pad byte needs to be skipped */
+      (*message) += 1; /* Pad byte needs to be skipped */
       data = GetIntFromMessage(message);
       break;
     case kLogicalSegmentLogicalFormatThirtyTwoBit:
-      MoveMessageNOctets(1, message); /* Pad byte needs to be skipped */
+      (*message) += 1; /* Pad byte needs to be skipped */
       data = GetDintFromMessage(message);
       break;
     default:
@@ -353,27 +353,25 @@ CipDword CipEpathGetLogicalValue(const EipUint8 **message) {
   return data;
 }
 
-size_t CipEpathSetLogicalValue(const CipDword logical_value,
+void CipEpathSetLogicalValue(const CipDword logical_value,
                                const LogicalSegmentLogicalFormat logical_format,
-                               CipOctet **message) {
-  size_t written_bytes = 0;
+                               CipMessageRouterResponse *const message) {
   switch(logical_value) {
     case kLogicalSegmentLogicalFormatEightBit:
-      written_bytes = AddSintToMessage(logical_value, message);
+      AddSintToMessage(logical_value, &message->message);
       break;
     case kLogicalSegmentLogicalFormatSixteenBit:
-      written_bytes = MoveMessageNOctets(1, (const CipOctet **)message); /* Needed for padding */
-      written_bytes += AddIntToMessage(logical_value, message);
+      MoveMessageNOctets(1, &message->message); /* Needed for padding */
+      AddIntToMessage(logical_value, message);
       break;
     case kLogicalSegmentLogicalFormatThirtyTwoBit:
-      written_bytes = MoveMessageNOctets(1,(const CipOctet **)message); /* Needed for padding */
-      written_bytes += AddDintToMessage(logical_value, message);
+      MoveMessageNOctets(1, &message->message); /* Needed for padding */
+      AddDintToMessage(logical_value, message);
       break;
     default:
-      OPENER_ASSERT(false) /* This should never happen! */
-      written_bytes = 0;
+      OPENER_ASSERT(false); /* This should never happen! */
+	  break;
   }
-  return written_bytes;
 }
 
 LogicalSegmentExtendedLogicalType GetPathLogicalSegmentExtendedLogicalType(
@@ -444,7 +442,7 @@ void GetElectronicKeyFormat4FromMessage(
   OPENER_ASSERT( kElectronicKeySegmentFormatKeyFormat4 ==
                  GetPathLogicalSegmentElectronicKeyFormat(*message) )
 
-  MoveMessageNOctets(2, message);
+  (*message) += 2;
   ElectronicKeyFormat4SetVendorId(key, GetIntFromMessage(message) );
   ElectronicKeyFormat4SetDeviceType(key, GetIntFromMessage(message) );
   ElectronicKeyFormat4SetProductCode(key, GetIntFromMessage(message) );
@@ -642,6 +640,8 @@ LogicalSegmentLogicalFormat CipEpathGetNeededLogicalFormatForValue(
   return logical_format;
 }
 
+
+//TODO: Does not match the actual interface anymore, check how to fix
 size_t CipEpathEncodeConnectionEpath(
   const CipConnectionPathEpath *const connection_epath,
   CipOctet **encoded_path) {
@@ -656,7 +656,7 @@ size_t CipEpathEncodeConnectionEpath(
     SetPathLogicalSegmentLogicalFormat(logical_value, *encoded_path);
     encoded_path_length += 1;
     MoveMessageNOctets(1, (const CipOctet **)encoded_path);
-    encoded_path_length += CipEpathSetLogicalValue(connection_epath->class_id,
+    CipEpathSetLogicalValue(connection_epath->class_id,
                                                    logical_value,
                                                    encoded_path);
   }
@@ -670,7 +670,7 @@ size_t CipEpathEncodeConnectionEpath(
     SetPathLogicalSegmentLogicalFormat(logical_value, *encoded_path);
     encoded_path_length += 1;
     MoveMessageNOctets(1, (const CipOctet **)encoded_path);
-    encoded_path_length += CipEpathSetLogicalValue(
+    CipEpathSetLogicalValue(
       connection_epath->instance_id,
       logical_value,
       encoded_path);
@@ -686,7 +686,7 @@ size_t CipEpathEncodeConnectionEpath(
     SetPathLogicalSegmentLogicalFormat(logical_value, *encoded_path);
     encoded_path_length += 1;
     MoveMessageNOctets(1, (const CipOctet **)encoded_path);
-    encoded_path_length += CipEpathSetLogicalValue(
+    CipEpathSetLogicalValue(
       connection_epath->attribute_id_or_connection_point,
       logical_value,
       encoded_path);

+ 2 - 2
source/src/cip/cipepath.h

@@ -259,9 +259,9 @@ void SetPathLogicalSegmentLogicalFormat(LogicalSegmentLogicalFormat format,
 
 CipDword CipEpathGetLogicalValue(const EipUint8 **message);
 
-size_t CipEpathSetLogicalValue(const CipDword logical_value,
+void CipEpathSetLogicalValue(const CipDword logical_value,
                                const LogicalSegmentLogicalFormat logical_format,
-                               CipOctet **message);
+							   CipMessageRouterResponse *const message);
 
 /** @brief  Gets the Extended Logical Type of a Logical Segment EPath message
  *

+ 139 - 171
source/src/cip/cipethernetlink.c

@@ -84,13 +84,20 @@ typedef struct speed_duplex_array_entry {
 
 
 /* forward declaration of functions to encode certain attribute objects */
-static int EncodeInterfaceCounters(CipUdint instance_id, CipOctet **message);
+static void EncodeInterfaceCounters(CipUdint instance_id, CipMessageRouterResponse *const message_router_response);
 
-static int EncodeMediaCounters(CipUdint instance_id, CipOctet **message);
+static void EncodeMediaCounters(CipUdint instance_id, CipMessageRouterResponse *const message_router_response);
 
-static int EncodeInterfaceControl(CipUdint instance_id, CipOctet **message);
+static void EncodeCipEthernetLinkInterfaceControl(const void *const data, ENIPMessage *const outgoing_message);
 
-static int EncodeInterfaceCapability(CipUdint instance_id, CipOctet **message);
+static void EncodeCipEthernetLinkInterfaceCaps(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipEthernetLinkPhyisicalAddress(const void *const data, ENIPMessage *const outgoing_message) {
+    EipUint8 *p = (EipUint8 *) data;
+    memcpy(outgoing_message->current_message_position, p, 6);
+    outgoing_message->current_message_position += 6;
+    outgoing_message->used_message_length += 6;
+}
 
 
 /* forward declaration for the GetAttributeSingle service handler function */
@@ -240,9 +247,9 @@ EipStatus CipEthernetLinkInit(void) {
   if (ethernet_link_class != NULL) {
     /* add services to the class */
     InsertService(ethernet_link_class, kGetAttributeSingle,
-                  &GetAttributeSingleEthernetLink,
+                  &GetAttributeSingle,
                   "GetAttributeSingleEthernetLink");
-    InsertService(ethernet_link_class, kGetAttributeAll, &GetAttributeAll,
+    InsertService(ethernet_link_class, kGetAttributeAll, &GetAttributeAll2,
                   "GetAttributeAll");
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
     InsertService(ethernet_link_class, kEthLinkGetAndClear,
@@ -259,48 +266,48 @@ EipStatus CipEthernetLinkInit(void) {
       CipInstance *ethernet_link_instance =
         GetCipInstance(ethernet_link_class, idx+1);
 
-      InsertAttribute(ethernet_link_instance, 1, kCipUdint,
+      InsertAttribute2(ethernet_link_instance, 1, kCipUdint, EncodeCipUdint,
                       &g_ethernet_link[idx].interface_speed, kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 2, kCipDword,
+      InsertAttribute2(ethernet_link_instance, 2, kCipDword, EncodeCipDword,
                       &g_ethernet_link[idx].interface_flags, kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 3, kCip6Usint,
+      InsertAttribute2(ethernet_link_instance, 3, kCip6Usint, EncodeCipEthernetLinkPhyisicalAddress,
                       &g_ethernet_link[idx].physical_address, kGetableSingleAndAll);
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
-      InsertAttribute(ethernet_link_instance, 4, kCipUsint,
+      InsertAttribute(ethernet_link_instance, 4, kCipUsint, EncodeCipUsint,
                       &g_ethernet_link[idx].interface_cntrs, kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 5, kCipUsint,
+      InsertAttribute(ethernet_link_instance, 5, kCipUsint, EncodeCipUsint,
                       &g_ethernet_link[idx].media_cntrs, kGetableSingleAndAll);
 #else
-      InsertAttribute(ethernet_link_instance, 4, kCipUsint,
+      InsertAttribute2(ethernet_link_instance, 4, kCipUsint, EncodeCipUsint,
                       &dummy_attribute_udint, kGetableAll);
-      InsertAttribute(ethernet_link_instance, 5, kCipUsint,
+      InsertAttribute2(ethernet_link_instance, 5, kCipUsint, EncodeCipUsint,
                       &dummy_attribute_udint, kGetableAll);
 #endif  /* ... && 0 != OPENER_ETHLINK_CNTRS_ENABLE */
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && 0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
       if (2 == idx) {
         /* Interface control of internal switch port is never settable. */
-        InsertAttribute(ethernet_link_instance, 6, kCipAny,
+        InsertAttribute2(ethernet_link_instance, 6, kCipAny, EncodeCipEthernetLinkInterfaceControl,
                         &g_ethernet_link[idx].interface_control,
                         IFACE_CTRL_ACCESS_MODE & ~kSetable);
       } else {
-        InsertAttribute(ethernet_link_instance, 6, kCipAny,
+        InsertAttribute2(ethernet_link_instance, 6, kCipAny, EncodeCipEthernetLinkInterfaceControl,
                         &g_ethernet_link[idx].interface_control,
                         IFACE_CTRL_ACCESS_MODE);
       }
 #else
-      InsertAttribute(ethernet_link_instance, 6, kCipAny, &s_interface_control,
+      InsertAttribute2(ethernet_link_instance, 6, kCipAny, EncodeCipEthernetLinkInterfaceControl, &s_interface_control,
                       kGetableAll);
 #endif
-      InsertAttribute(ethernet_link_instance, 7, kCipUsint,
+      InsertAttribute2(ethernet_link_instance, 7, kCipUsint, EncodeCipUsint,
                       &g_ethernet_link[idx].interface_type, kGetableSingleAndAll);
-      InsertAttribute(ethernet_link_instance, 8, kCipUsint,
+      InsertAttribute2(ethernet_link_instance, 8, kCipUsint, EncodeCipUsint,
                       &dummy_attribute_usint, kGetableAll);
-      InsertAttribute(ethernet_link_instance, 9, kCipUsint,
+      InsertAttribute2(ethernet_link_instance, 9, kCipUsint, EncodeCipUsint,
                       &dummy_attribute_usint, kGetableAll);
-      InsertAttribute(ethernet_link_instance, 10, kCipShortString,
+      InsertAttribute2(ethernet_link_instance, 10, kCipShortString, EncodeCipShortString,
                       &g_ethernet_link[idx].interface_label,
                       IFACE_LABEL_ACCESS_MODE);
-      InsertAttribute(ethernet_link_instance, 11, kCipAny,
+      InsertAttribute2(ethernet_link_instance, 11, kCipAny,  EncodeCipEthernetLinkInterfaceCaps,
                       &g_ethernet_link[idx].interface_caps, kGetableSingleAndAll);
     }
   } else {
@@ -320,190 +327,155 @@ void CipEthernetLinkSetMac(EipUint8 *p_physical_address) {
   return;
 }
 
-static int EncodeInterfaceCounters(CipUdint instance_id, CipOctet **message) {
-  int encoded_len = 0;
+static void EncodeInterfaceCounters(CipUdint instance_id, CipMessageRouterResponse *const message_router_response) {
   for (size_t i = 0; i < 11; i++) {
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
     /* Encode real values using the access through the array of the
      *  interface_cntrs union. */
-    encoded_len += EncodeData(
-                    kCipUdint,
-                    g_ethernet_link[instance_id-1].interface_cntrs.cntr32 +i,
-                    message);
+    EncodeData(kCipUdint, g_ethernet_link[instance_id-1].interface_cntrs.cntr32 + i, message_router_response);
 #else
     /* Encode the default counter value of 0 */
-    encoded_len += EncodeData(kCipUdint, &dummy_attribute_udint, message);
+    EncodeData(kCipUdint, &dummy_attribute_udint, message_router_response);
 #endif
   }
-  return encoded_len;
 }
 
-static int EncodeMediaCounters(CipUdint instance_id, CipOctet **message) {
-  int encoded_len = 0;
+static void EncodeMediaCounters(CipUdint instance_id, CipMessageRouterResponse *const message_router_response) {
   for (size_t i = 0; i < 12; i++) {
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
     /* Encode real values using the access through the array of the
      *  media_cntrs union. */
-    encoded_len += EncodeData(
-                    kCipUdint,
-                    g_ethernet_link[instance_id-1].media_cntrs.cntr32 +i,
-                    message);
+    EncodeData(kCipUdint, g_ethernet_link[instance_id-1].media_cntrs.cntr32 + i, message_router_response);
 #else
     /* Encode the default counter value of 0 */
-    encoded_len += EncodeData(kCipUdint, &dummy_attribute_udint, message);
+    EncodeData(kCipUdint, &dummy_attribute_udint, message_router_response);
 #endif
   }
-  return encoded_len;
 }
 
-static int EncodeInterfaceControl(CipUdint instance_id, CipOctet **message) {
+static void EncodeCipEthernetLinkInterfaceControl(const void *const data, ENIPMessage *const outgoing_message) {
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && 0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
-  CipEthernetLinkInterfaceControl *interface_control =
-  	&g_ethernet_link[instance_id-1].interface_control;
+  const CipEthernetLinkInterfaceControl *const interface_control =
+  	data;
 #else
   CipEthernetLinkInterfaceControl *interface_control = &s_interface_control;
 #endif
-  int encoded_len = 0;
-  encoded_len += EncodeData(kCipWord, &interface_control->control_bits,
-                            message);
-  encoded_len += EncodeData(kCipUint,
-                            &interface_control->forced_interface_speed,
-                            message);
-  return encoded_len;
+  EncodeCipWord(&interface_control->control_bits, outgoing_message);
+  EncodeCipUint(&interface_control->forced_interface_speed, outgoing_message);
 }
 
 #define NELEMENTS(x)  ((sizeof(x)/sizeof(x[0])))
-static int EncodeInterfaceCapability(CipUdint instance_id, CipOctet **message)
+static void EncodeCipEthernetLinkInterfaceCaps(const void *const data, ENIPMessage *const outgoing_message)
 {
-  int encoded_len = 0;
-  encoded_len += EncodeData(
-                    kCipDword,
-                    &g_ethernet_link[instance_id - 1].interface_caps.capability_bits,
-                    message);
-  uint16_t selected = g_ethernet_link[instance_id - 1].interface_caps.speed_duplex_selector;
+  const CipEthernetLinkMetaInterfaceCapability *const interface_caps = data;
+  EncodeCipDword(&interface_caps->capability_bits, outgoing_message);
+  uint16_t selected = interface_caps->speed_duplex_selector;
   CipUsint count;
   for (count = 0; selected; count++) { /* count # of bits set */
 	  selected &= selected - 1U;  /* clear the least significant bit set */
   }
-  encoded_len += EncodeData(kCipUsint, &count, message);
+  EncodeCipUsint(&count, outgoing_message);
 
   for (size_t i = 0; i < NELEMENTS(speed_duplex_table); i++) {
-    if (g_ethernet_link[instance_id - 1].interface_caps.speed_duplex_selector &
+    if (interface_caps->speed_duplex_selector &
         (1U << i)) {
-      encoded_len += EncodeData(
-                        kCipUint,
-                        &speed_duplex_table[i].interface_speed,
-                        message);
-      encoded_len += EncodeData(
-                        kCipUsint,
-                        &speed_duplex_table[i].interface_duplex_mode,
-                        message);
+      EncodeCipUint(&speed_duplex_table[i].interface_speed, outgoing_message);
+      EncodeCipUsint(&speed_duplex_table[i].interface_duplex_mode, outgoing_message);
     }
   }
-  return encoded_len;
 }
 
-EipStatus GetAttributeSingleEthernetLink(
-  CipInstance *RESTRICT const instance,
-  CipMessageRouterRequest *const message_router_request,
-  CipMessageRouterResponse *const message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session) {
-
-  CipAttributeStruct *attribute = GetCipAttribute(
-    instance, message_router_request->request_path.attribute_number);
-  EipByte *message = message_router_response->data;
-
-  message_router_response->data_length = 0;
-  message_router_response->reply_service = (0x80
-                                            | message_router_request->service);
-  message_router_response->general_status = kCipErrorAttributeNotSupported;
-  message_router_response->size_of_additional_status = 0;
-
-  EipUint16 attribute_number = message_router_request->request_path
-                               .attribute_number;
-
-  if ( (NULL != attribute) && (NULL != attribute->data) ) {
-    /* Mask for filtering get-ability */
-    uint8_t get_bit_mask = 0;
-    if (kGetAttributeAll == message_router_request->service) {
-      get_bit_mask = (instance->cip_class->get_all_bit_mask[CalculateIndex(
-                                                              attribute_number)]);
-      message_router_response->general_status = kCipErrorSuccess;
-    } else {
-      get_bit_mask = (instance->cip_class->get_single_bit_mask[CalculateIndex(
-                                                                 attribute_number)
-                      ]);
-    }
-    if ( 0 != ( get_bit_mask & ( 1 << (attribute_number % 8) ) ) ) {
-
-      /* create a reply message containing the data*/
-      bool use_common_handler;
-      switch (attribute_number) {
-      case 4: /* fall through */
-      case 5: /* fall through */
-      case 6: /* fall through */
-      case 11:
-        use_common_handler = false;
-        OPENER_TRACE_INFO("getAttribute %d\n", attribute_number);
-        break;
-      default:
-        use_common_handler = true;
-        break;
-      }
-
-      /* Call the PreGetCallback if enabled for this attribute and the common handler is not used. */
-      if (!use_common_handler) {
-        if (attribute->attribute_flags & kPreGetFunc && NULL != instance->cip_class->PreGetCallback) {
-          instance->cip_class->PreGetCallback(instance, attribute, message_router_request->service);
-        }
-      }
-
-      switch (attribute_number) {
-        case 4:
-          message_router_response->data_length = EncodeInterfaceCounters(
-            instance->instance_number,
-            &message);
-          message_router_response->general_status = kCipErrorSuccess;
-          break;
-        case 5:
-          message_router_response->data_length = EncodeMediaCounters(
-            instance->instance_number,
-            &message);
-          message_router_response->general_status = kCipErrorSuccess;
-          break;
-        case 6:
-          message_router_response->data_length = EncodeInterfaceControl(
-            instance->instance_number,
-            &message);
-          message_router_response->general_status = kCipErrorSuccess;
-          break;
-        case 11:
-          message_router_response->data_length = EncodeInterfaceCapability(
-            instance->instance_number,
-            &message);
-          message_router_response->general_status = kCipErrorSuccess;
-          break;
-
-        default:
-          GetAttributeSingle(instance, message_router_request,
-                             message_router_response,
-                             originator_address,
-                             encapsulation_session);
-      }
-
-      /* Call the PostGetCallback if enabled for this attribute and the common handler is not used. */
-      if (!use_common_handler) {
-        if (attribute->attribute_flags & kPostGetFunc && NULL != instance->cip_class->PostGetCallback) {
-          instance->cip_class->PostGetCallback(instance, attribute, message_router_request->service);
-        }
-      }
-
-    }
-  }
-
-  return kEipStatusOkSend;
-}
+//EipStatus GetAttributeSingleEthernetLink(
+//  CipInstance *RESTRICT const instance,
+//  CipMessageRouterRequest *const message_router_request,
+//  CipMessageRouterResponse *const message_router_response,
+//  const struct sockaddr *originator_address,
+//  const int encapsulation_session) {
+//
+//  CipAttributeStruct *attribute = GetCipAttribute(
+//    instance, message_router_request->request_path.attribute_number);
+//  InitializeENIPMessage(&message_router_response->message);
+//  message_router_response->reply_service = (0x80
+//                                            | message_router_request->service);
+//  message_router_response->general_status = kCipErrorAttributeNotSupported;
+//  message_router_response->size_of_additional_status = 0;
+//
+//  EipUint16 attribute_number = message_router_request->request_path
+//                               .attribute_number;
+//
+//  if ( (NULL != attribute) && (NULL != attribute->data) ) {
+//    /* Mask for filtering get-ability */
+//    uint8_t get_bit_mask = 0;
+//    if (kGetAttributeAll == message_router_request->service) {
+//      get_bit_mask = (instance->cip_class->get_all_bit_mask[CalculateIndex(
+//                                                              attribute_number)]);
+//      message_router_response->general_status = kCipErrorSuccess;
+//    } else {
+//      get_bit_mask = (instance->cip_class->get_single_bit_mask[CalculateIndex(
+//                                                                 attribute_number)
+//                      ]);
+//    }
+//    if ( 0 != ( get_bit_mask & ( 1 << (attribute_number % 8) ) ) ) {
+//
+//      /* create a reply message containing the data*/
+//      bool use_common_handler;
+//      switch (attribute_number) {
+//      case 4: /* fall through */
+//      case 5: /* fall through */
+//      case 6: /* fall through */
+//      case 11:
+//        use_common_handler = false;
+//        OPENER_TRACE_INFO("getAttribute %d\n", attribute_number);
+//        break;
+//      default:
+//        use_common_handler = true;
+//        break;
+//      }
+//
+//      /* Call the PreGetCallback if enabled for this attribute and the common handler is not used. */
+//      if (!use_common_handler) {
+//        if ((attribute->attribute_flags & kPreGetFunc) && NULL != instance->cip_class->PreGetCallback) {
+//          instance->cip_class->PreGetCallback(instance, attribute, message_router_request->service);
+//        }
+//      }
+//
+//      switch (attribute_number) {
+//        case 4:
+//          EncodeInterfaceCounters(instance->instance_number, message_router_response);
+//          message_router_response->general_status = kCipErrorSuccess;
+//          break;
+//        case 5:
+//          EncodeMediaCounters(instance->instance_number, message_router_response);
+//          message_router_response->general_status = kCipErrorSuccess;
+//          break;
+//        case 6:
+//          EncodeInterfaceControl(instance->instance_number, message_router_response);
+//          message_router_response->general_status = kCipErrorSuccess;
+//          break;
+//        case 11:
+//          EncodeInterfaceCapability(instance->instance_number, message_router_response);
+//          message_router_response->general_status = kCipErrorSuccess;
+//          break;
+//
+//        default:
+//          GetAttributeSingle(instance, message_router_request,
+//                             message_router_response,
+//                             originator_address,
+//                             encapsulation_session);
+//      }
+//
+//      /* Call the PostGetCallback if enabled for this attribute and the common handler is not used. */
+//      if (!use_common_handler) {
+//        if ((attribute->attribute_flags & kPostGetFunc) && NULL != instance->cip_class->PostGetCallback) {
+//          instance->cip_class->PostGetCallback(instance, attribute, message_router_request->service);
+//        }
+//      }
+//
+//    }
+//  }
+//
+//  return kEipStatusOkSend;
+//}
 
 #if defined(OPENER_ETHLINK_CNTRS_ENABLE) && 0 != OPENER_ETHLINK_CNTRS_ENABLE
 EipStatus GetAndClearEthernetLink(
@@ -558,11 +530,7 @@ EipStatus GetAndClearEthernetLink(
 #endif  /* ... && 0 != OPENER_ETHLINK_CNTRS_ENABLE */
 
 #if defined(OPENER_ETHLINK_IFACE_CTRL_ENABLE) && 0 != OPENER_ETHLINK_IFACE_CTRL_ENABLE
-static bool IsIfaceControlAllowed
-(
-  CipUdint instance_id,
-  CipEthernetLinkInterfaceControl const *iface_cntrl)
-{
+static bool IsIfaceControlAllowed(CipUdint instance_id, CipEthernetLinkInterfaceControl const *iface_cntrl) {
   const CipUsint duplex_mode =
        (iface_cntrl->control_bits & kEthLinkIfCntrlForcedDuplex) ? 1 : 0;
   for (size_t i = 0; i < NELEMENTS(speed_duplex_table); i++) {

+ 30 - 17
source/src/cip/cipidentity.c

@@ -179,7 +179,7 @@ static EipStatus Reset(CipInstance *instance,
     }
   }
 
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   return eip_status;
 }
 
@@ -188,31 +188,40 @@ void InitializeCipIdentity(CipClass *class) {
 
   CipClass *meta_class = class->class_instance.cip_class;
 
-  InsertAttribute( (CipInstance *) class, 1, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 1, kCipUint,
+		           EncodeCipUint,
                    (void *) &class->revision,
                    kGetableSingleAndAll );                 /* revision */
-  InsertAttribute( (CipInstance *) class, 2, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 2, kCipUint,
+		           EncodeCipUint,
                    (void *) &class->number_of_instances, kGetableSingleAndAll ); /*  largest instance number */
-  InsertAttribute( (CipInstance *) class, 3, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 3, kCipUint,
+		           EncodeCipUint,
                    (void *) &class->number_of_instances, kGetAttributeSingle ); /* number of instances currently existing*/
-  InsertAttribute( (CipInstance *) class, 4, kCipUint, (void *) &kCipUintZero,
+  InsertAttribute2( (CipInstance *) class, 4, kCipUint, EncodeCipUint, (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional attribute list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 5, kCipUint, (void *) &kCipUintZero,
+  InsertAttribute2( (CipInstance *) class, 5, kCipUint, EncodeCipUint, (void *) &kCipUintZero,
                    kNotSetOrGetable ); /* optional service list - default = 0 */
-  InsertAttribute( (CipInstance *) class, 6, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 6, kCipUint, EncodeCipUint,
                    (void *) &meta_class->highest_attribute_number,
                    kGetableSingleAndAll );                 /* max class attribute number*/
-  InsertAttribute( (CipInstance *) class, 7, kCipUint,
+  InsertAttribute2( (CipInstance *) class, 7, kCipUint, EncodeCipUint,
                    (void *) &class->highest_attribute_number,
                    kGetableSingleAndAll );                 /* max instance attribute number*/
 
-  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll,
+  InsertService(meta_class, kGetAttributeAll, &GetAttributeAll2,
                     "GetAttributeAll");                     /* bind instance services to the metaclass*/
   InsertService(meta_class, kGetAttributeSingle, &GetAttributeSingle,
                   "GetAttributeSingle");
 
 }
 
+void EncodeRevision(const void *const data, ENIPMessage *const outgoing_message) {
+  CipRevision *revision = (CipRevision *) data;
+  AddSintToMessage(revision->major_revision, outgoing_message);
+  AddSintToMessage(revision->minor_revision, outgoing_message);
+}
+
 EipStatus CipIdentityInit() {
 
   CipClass *class = CreateCipClass(kCipIdentityClassCode,
@@ -232,35 +241,39 @@ EipStatus CipIdentityInit() {
   }
 
   CipInstance *instance = GetCipInstance(class, 1);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   1,
                   kCipUint,
+				  EncodeCipUint,
                   &g_identity.vendor_id,
                   kGetableSingleAndAll);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   2,
                   kCipUint,
+				  EncodeCipUint,
                   &g_identity.device_type,
                   kGetableSingleAndAll);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   3,
                   kCipUint,
+				  EncodeCipUint,
                   &g_identity.product_code,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 4, kCipUsintUsint, &g_identity.revision,
+  InsertAttribute2(instance,4, kCipUsintUsint, EncodeRevision, &g_identity.revision,
                   kGetableSingleAndAll);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   5,
                   kCipWord,
+				  EncodeCipWord,
                   &g_identity.status,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 6, kCipUdint, &g_identity.serial_number,
+  InsertAttribute2(instance, 6, kCipUdint, EncodeCipUdint, &g_identity.serial_number,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 7, kCipShortString, &g_identity.product_name,
+  InsertAttribute2(instance, 7, kCipShortString, EncodeCipShortString, &g_identity.product_name,
                   kGetableSingleAndAll);
   InsertService(class, kGetAttributeSingle, &GetAttributeSingle,
                 "GetAttributeSingle");
-  InsertService(class, kGetAttributeAll, &GetAttributeAll, "GetAttributeAll");
+  InsertService(class, kGetAttributeAll, &GetAttributeAll2, "GetAttributeAll");
   InsertService(class, kReset, &Reset, "Reset");
 
   return kEipStatusOk;

+ 8 - 5
source/src/cip/cipmessagerouter.c

@@ -5,14 +5,17 @@
  ******************************************************************************/
 #include "opener_api.h"
 #include "cipcommon.h"
-#include "cipmessagerouter.h"
 #include "endianconv.h"
 #include "ciperror.h"
 #include "trace.h"
+#include "enipmessage.h"
+
+#include "cipmessagerouter.h"
 
 CipMessageRouterRequest g_message_router_request;
 CipMessageRouterResponse g_message_router_response;
 
+
 /** @brief A class registry list node
  *
  * A linked list of this  object is the registry of classes known to the message router
@@ -101,7 +104,7 @@ EipStatus CipMessageRouterInit() {
 
   /* reserved for future use -> set to zero */
   g_message_router_response.reserved = 0;
-  g_message_router_response.data = g_message_data_reply_buffer; /* set reply buffer, using a fixed buffer (OPENER_MESSAGE_DATA_REPLY_BUFFER bytes) */
+  InitializeENIPMessage(&g_message_router_response.message);
 
   return kEipStatusOk;
 }
@@ -183,7 +186,7 @@ EipStatus NotifyMessageRouter(EipUint8 *data,
   EipStatus eip_status = kEipStatusOkSend;
   CipError status = kCipErrorSuccess;
 
-  g_message_router_response.data = g_message_data_reply_buffer; /* set reply buffer, using a fixed buffer (OPENER_MESSAGE_DATA_REPLY_BUFFER bytes) */
+  InitializeENIPMessage(&g_message_router_response.message); /* Initialize reply buffer */
 
   OPENER_TRACE_INFO("NotifyMessageRouter: routing unconnected message\n");
   if ( kCipErrorSuccess
@@ -194,7 +197,7 @@ EipStatus NotifyMessageRouter(EipUint8 *data,
     g_message_router_response.general_status = status;
     g_message_router_response.size_of_additional_status = 0;
     g_message_router_response.reserved = 0;
-    g_message_router_response.data_length = 0;
+    InitializeENIPMessage(&g_message_router_response.message);
     g_message_router_response.reply_service = (0x80
                                                | g_message_router_request.
                                                service);
@@ -210,7 +213,7 @@ EipStatus NotifyMessageRouter(EipUint8 *data,
         kCipErrorPathDestinationUnknown;   /*according to the test tool this should be the correct error flag instead of CIP_ERROR_OBJECT_DOES_NOT_EXIST;*/
       g_message_router_response.size_of_additional_status = 0;
       g_message_router_response.reserved = 0;
-      g_message_router_response.data_length = 0;
+      InitializeENIPMessage(&g_message_router_response.message);
       g_message_router_response.reply_service = (0x80
                                                  | g_message_router_request.
                                                  service);

+ 22 - 39
source/src/cip/cipqos.c

@@ -55,18 +55,6 @@ static CipQosDscpValues s_active_dscp = {
 };
 
 /************** Functions ****************************************/
-EipStatus GetAttributeSingleQoS(
-  CipInstance *const RESTRICT instance,
-  CipMessageRouterRequest *RESTRICT const message_router_request,
-  CipMessageRouterResponse *RESTRICT const message_router_response,
-  const struct sockaddr *originator_address,
-  const int encapsulation_session) {
-
-  return GetAttributeSingle(instance, message_router_request,
-                            message_router_response, originator_address,
-                            encapsulation_session);
-}
-
 EipStatus SetAttributeSingleQoS(
   CipInstance *instance,
   CipMessageRouterRequest *message_router_request,
@@ -123,7 +111,7 @@ EipStatus SetAttributeSingleQoS(
   }
 
   message_router_response->size_of_additional_status = 0;
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service = (0x80
                                             | message_router_request->service);
 
@@ -154,34 +142,21 @@ CipUsint CipQosGetDscpPriority(ConnectionObjectPriority priority) {
   return priority_value;
 }
 
-/** @brief Class level attribute initializer for QoS class
- *
- * This function is provided as class level attribute initializer to
- *  @ref CreateCipClass. It replaces the default initialization of
- *  @ref CreateCipClass.
- * Because we do NOT initialize anything here all the class attributes
- *  which are optional for the QoS class are NOT created!
- *  This is intended.
- */
-void InitializeCipQos(CipClass *cip_class) {
-  /* Function is empty by intend. */
-}
-
 EipStatus CipQoSInit() {
 
   CipClass *qos_class = NULL;
 
   if( ( qos_class = CreateCipClass(kCipQoSClassCode,
-                                   0, /* # class attributes */
+                                   7, /* # class attributes */
                                    7, /* # highest class attribute number */
-                                   0, /* # class services */
+                                   2, /* # class services */
                                    8, /* # instance attributes */
                                    8, /* # highest instance attribute number */
                                    2, /* # instance services */
                                    1, /* # instances */
                                    "Quality of Service",
                                    1, /* # class revision */
-                                   &InitializeCipQos /* # function pointer for initialization */
+                                   NULL /* # function pointer for initialization */
                                    ) ) == 0 ) {
 
     return kEipStatusError;
@@ -189,49 +164,57 @@ EipStatus CipQoSInit() {
 
   CipInstance *instance = GetCipInstance(qos_class, 1); /* bind attributes to the instance #1 that was created above */
 
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   1,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.q_frames_enable,
                   kNotSetOrGetable);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   2,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.event,
                   kNotSetOrGetable);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   3,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.general,
                   kNotSetOrGetable);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   4,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.urgent,
                   kGetableSingle | kSetable | kNvDataFunc);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   5,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.scheduled,
                   kGetableSingle | kSetable | kNvDataFunc);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   6,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.high,
                   kGetableSingle | kSetable | kNvDataFunc);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   7,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.low,
                   kGetableSingle | kSetable | kNvDataFunc);
-  InsertAttribute(instance,
+  InsertAttribute2(instance,
                   8,
                   kCipUsint,
+				  EncodeCipUsint,
                   (void *) &g_qos.dscp.explicit,
                   kGetableSingle | kSetable | kNvDataFunc);
 
-  InsertService(qos_class, kGetAttributeSingle, &GetAttributeSingleQoS,
-                "GetAttributeSingleQoS");
+  InsertService(qos_class, kGetAttributeSingle, &GetAttributeSingle,
+                "GetAttributeSingle");
   InsertService(qos_class, kSetAttributeSingle, &SetAttributeSingleQoS,
                 "SetAttributeSingleQoS");
 

+ 69 - 45
source/src/cip/ciptcpipinterface.c

@@ -83,6 +83,7 @@ CipTcpIpObject g_tcpip =
     1,  /* we currently use only one multicast address */
     0   /* the multicast address will be allocated on IP address configuration */
   },
+  .select_acd = false,
   .encapsulation_inactivity_timeout = 120 /* attribute #13 encapsulation_inactivity_timeout, use a default value of 120 */
 };
 
@@ -308,6 +309,40 @@ static bool IsIOConnectionActive(void)
 
 
 /************** Functions ****************************************/
+
+void EncoodeCipTcpIpInterfaceConfiguration(const void *const data, ENIPMessage *const outgoing_message) {
+    CipTcpIpInterfaceConfiguration *
+      tcp_ip_network_interface_configuration =
+      (CipTcpIpInterfaceConfiguration *) data;
+    AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->ip_address), outgoing_message);
+    AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->network_mask), outgoing_message);
+    AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->gateway), outgoing_message);
+    AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->name_server), outgoing_message);
+    AddDintToMessage(ntohl(tcp_ip_network_interface_configuration->name_server_2),outgoing_message);
+    EncodeCipString(&(tcp_ip_network_interface_configuration->domain_name), outgoing_message);
+}
+
+void EncodeCipTcpIpMulticastConfiguration(const void *const data, ENIPMessage *const outgoing_message) {
+  EncodeCipUsint(&(g_tcpip.mcast_config.alloc_control), outgoing_message);
+  EncodeCipUsint(&(g_tcpip.mcast_config.reserved_shall_be_zero), outgoing_message);
+  EncodeCipUint(&(g_tcpip.mcast_config.number_of_allocated_multicast_addresses), outgoing_message);
+
+  CipUdint multicast_address = ntohl(
+    g_tcpip.mcast_config.starting_multicast_address);
+
+  EncodeCipUdint(&multicast_address, outgoing_message);
+}
+
+void EncodeSafetyNetworkNumber(const void *const data, ENIPMessage *const outgoing_message) {
+	FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, 6, outgoing_message);
+}
+
+void EncodeCipLastConflictDetected(const void *const data, ENIPMessage *const outgoing_message) {
+  const size_t kAttribute11Size = sizeof(CipUsint) + 6 * sizeof(CipUsint) + 28 * sizeof(CipUsint);
+  OPENER_ASSERT(kAttribute11Size == 35);
+  FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, kAttribute11Size, outgoing_message);
+}
+
 EipStatus GetAttributeSingleTcpIpInterface(
   CipInstance *const RESTRICT instance,
   CipMessageRouterRequest *const RESTRICT message_router_request,
@@ -500,7 +535,7 @@ EipStatus SetAttributeSingleTcpIpInterface(
   }
 
   message_router_response->size_of_additional_status = 0;
-  message_router_response->data_length = 0;
+  InitializeENIPMessage(&message_router_response->message);
   message_router_response->reply_service = (0x80
                                             | message_router_request->service);
   return kEipStatusOkSend;
@@ -513,7 +548,7 @@ EipStatus CipTcpIpInterfaceInit() {
                                        0, /* # class attributes */
                                        7, /* # highest class attribute number */
                                        2, /* # class services */
-                                       9, /* # instance attributes */
+                                       13, /* # instance attributes */
                                        13, /* # highest instance attribute number */
                                        3, /* # instance services */
                                        1, /* # instances */
@@ -525,35 +560,42 @@ EipStatus CipTcpIpInterfaceInit() {
 
   CipInstance *instance = GetCipInstance(tcp_ip_class, 1); /* bind attributes to the instance #1 that was created above */
 
-  InsertAttribute(instance, 1, kCipDword, &g_tcpip.status,
+  InsertAttribute2(instance, 1, kCipDword, EncodeCipDword, &g_tcpip.status,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 2, kCipDword, &g_tcpip.config_capability,
+  InsertAttribute2(instance, 2, kCipDword, EncodeCipDword, &g_tcpip.config_capability,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 3, kCipDword, &g_tcpip.config_control,
+  InsertAttribute2(instance, 3, kCipDword, EncodeCipDword, &g_tcpip.config_control,
                   kSetAndGetAble | kNvDataFunc | IFACE_CFG_SET_MODE );
-  InsertAttribute(instance, 4, kCipEpath, &g_tcpip.physical_link_object,
+  InsertAttribute2(instance, 4, kCipEpath, EncodeCipEPath, &g_tcpip.physical_link_object,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 5, kCipUdintUdintUdintUdintUdintString,
+  InsertAttribute2(instance, 5, kCipUdintUdintUdintUdintUdintString, EncoodeCipTcpIpInterfaceConfiguration,
                   &g_tcpip.interface_configuration,
                   kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
-  InsertAttribute(instance, 6, kCipString, &g_tcpip.hostname,
+  InsertAttribute2(instance, 6, kCipString, EncodeCipString, &g_tcpip.hostname,
                   kGetableSingleAndAll | kNvDataFunc | IFACE_CFG_SET_MODE);
+  InsertAttribute2(instance, 7, kCipAny, EncodeSafetyNetworkNumber, NULL,
+                    kGetableAll);
 
-  InsertAttribute(instance, 8, kCipUsint, &g_tcpip.mcast_ttl_value,
+  InsertAttribute2(instance, 8, kCipUsint, EncodeCipUsint, &g_tcpip.mcast_ttl_value,
                   kGetableSingleAndAll);
-  InsertAttribute(instance, 9, kCipAny, &g_tcpip.mcast_config,
+  InsertAttribute2(instance, 9, kCipAny, EncodeCipTcpIpMulticastConfiguration, &g_tcpip.mcast_config,
                   kGetableSingleAndAll);
-  InsertAttribute(instance,
+  InsertAttribute2(instance, 10, kCipBool, EncodeCipBool, &g_tcpip.select_acd,
+                    kGetableSingleAndAll);
+  InsertAttribute2(instance, 11, kCipBool, EncodeCipLastConflictDetected, NULL,
+                      kGetableSingleAndAll);
+  InsertAttribute2(instance,
                   13,
                   kCipUint,
+				  EncodeCipUint,
                   &g_tcpip.encapsulation_inactivity_timeout,
                   kSetAndGetAble | kNvDataFunc);
 
   InsertService(tcp_ip_class, kGetAttributeSingle,
-                &GetAttributeSingleTcpIpInterface,
+                &GetAttributeSingle,
                 "GetAttributeSingleTCPIPInterface");
 
-  InsertService(tcp_ip_class, kGetAttributeAll, &GetAttributeAllTcpIpInterface,
+  InsertService(tcp_ip_class, kGetAttributeAll, &GetAttributeAll2,
                 "GetAttributeAllTCPIPInterface");
 
   InsertService(tcp_ip_class, kSetAttributeSingle,
@@ -596,9 +638,7 @@ EipStatus GetAttributeSingleTcpIpInterface(
   }
 
   { /* attribute 9 can not be easily handled with the default mechanism therefore we will do it by hand */
-    EipByte *message = message_router_response->data;
-
-    message_router_response->data_length = 0;
+    InitializeENIPMessage(&message_router_response->message);
     message_router_response->reply_service = (0x80
                                               | message_router_request->service);
     message_router_response->size_of_additional_status = 0;
@@ -620,22 +660,14 @@ EipStatus GetAttributeSingleTcpIpInterface(
                         message_router_request->request_path.attribute_number);
 
       /* create a reply message containing the data*/
-      message_router_response->data_length += EncodeData(
-        kCipUsint, &(g_tcpip.mcast_config.alloc_control), &message);
-      message_router_response->data_length += EncodeData(
-        kCipUsint, &(g_tcpip.mcast_config.reserved_shall_be_zero),
-        &message);
-      message_router_response->data_length += EncodeData(
-        kCipUint,
-        &(g_tcpip.mcast_config.number_of_allocated_multicast_addresses),
-        &message);
+      EncodeData(kCipUsint, &(g_tcpip.mcast_config.alloc_control), message_router_response);
+      EncodeData(kCipUsint, &(g_tcpip.mcast_config.reserved_shall_be_zero), message_router_response);
+      EncodeData(kCipUint, &(g_tcpip.mcast_config.number_of_allocated_multicast_addresses), message_router_response);
 
       CipUdint multicast_address = ntohl(
         g_tcpip.mcast_config.starting_multicast_address);
 
-      message_router_response->data_length += EncodeData(kCipUdint,
-                                                         &multicast_address,
-                                                         &message);
+      EncodeData(kCipUdint, &multicast_address, message_router_response);
       message_router_response->general_status = kCipErrorSuccess;
     }
   }
@@ -650,10 +682,9 @@ EipStatus GetAttributeAllTcpIpInterface(
   const struct sockaddr *originator_address,
   const int encapsulation_session) {
 
-  EipUint8 *response = message_router_response->data; /* pointer into the reply */
   CipAttributeStruct *attribute = instance->attributes;
 
-  for (int j = 0; j < instance->cip_class->number_of_attributes; j++) /* for each instance attribute of this class */
+  for (size_t j = 0; j < instance->cip_class->number_of_attributes; j++) /* for each instance attribute of this class */
   {
     int attribute_number = attribute->attribute_number;
     if (attribute_number < 32) /* only return attributes that are flagged as being part of GetAttributeALl */
@@ -661,8 +692,7 @@ EipStatus GetAttributeAllTcpIpInterface(
       message_router_request->request_path.attribute_number = attribute_number;
 
       if (8 == attribute_number) { /* insert 6 zeros for the required empty safety network number according to Table 5-3.10 */
-        memset(message_router_response->data, 0, 6);
-        message_router_response->data += 6;
+    	FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, 6, &message_router_response->message);
       }
 
       if ( kEipStatusOkSend
@@ -670,35 +700,29 @@ EipStatus GetAttributeAllTcpIpInterface(
                                                message_router_response,
                                                originator_address,
                                                encapsulation_session) ) {
-        message_router_response->data = response;
         return kEipStatusError;
       }
-      message_router_response->data += message_router_response->data_length;
 
       if (9 == attribute_number) {
         /* returning default value for unimplemented attributes 10,11 and 12 */
 
         /* attribute 10, type: BOOL, default value: 0 */
-        message_router_response->data += 6;
-        *(message_router_response->data) = 0;
-        message_router_response->data += 1;
+        //message_router_response->data += 6;
+    	AddSintToMessage(0, &message_router_response->message);
+
 
         /* attribute 11, type: STRUCT OF USINT, ARRAY of 6 USINTs, ARRAY of 28 USINTs default value: 0 */
-        memset(message_router_response->data, 0, 29);
-        message_router_response->data += 29;
+    	const size_t kAttribute11Size = sizeof(CipUsint) + 6 * sizeof(CipUsint) + 28 * sizeof(CipUsint);
+    	OPENER_ASSERT(kAttribute11Size == 35);
+    	FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, kAttribute11Size, &message_router_response->message);
 
         /* attribute 12, type: BOOL default value: 0 */
-        *(message_router_response->data) = 0;
-        message_router_response->data += 1;
+    	AddSintToMessage(0, &message_router_response->message);
       }
 
     }
     attribute++;
   }
-  message_router_response->data_length = message_router_response->data
-                                         - response;
-  message_router_response->data = response;
-
   return kEipStatusOkSend;
 }
 

+ 1 - 0
source/src/cip/ciptcpipinterface.h

@@ -56,6 +56,7 @@ typedef struct {
 
   /** #9 The multicast configuration for this device */
   MulticastAddressConfiguration mcast_config;
+  CipBool select_acd;
 
   /** #13 Number of seconds of inactivity before TCP connection is closed */
   CipUint encapsulation_inactivity_timeout;

+ 7 - 3
source/src/cip/ciptypes.h

@@ -243,6 +243,8 @@ typedef struct {
 
 #define MAX_SIZE_OF_ADD_STATUS 2 /* for now we support extended status codes up to 2 16bit values there is mostly only one 16bit value used */
 
+typedef struct enip_message ENIPMessage;
+
 /** @brief CIP Message Router Response
  *
  */
@@ -257,16 +259,18 @@ typedef struct {
   EipUint16 additional_status[MAX_SIZE_OF_ADD_STATUS]; /**< Array of 16 bit words; Additional status;
                                                           If SizeOfAdditionalStatus is 0. there is no
                                                           Additional Status */
-  EipInt16 data_length; /**< Supportative non-CIP variable, gives length of data segment */
-  CipOctet *data; /**< Array of octet; Response data per object definition from
-                     request */
+  ENIPMessage message; /* The construct message */
 } CipMessageRouterResponse;
 
+/** @brief self-describing data encoding for CIP types */
+typedef void (*CipAttributeEncodeInMessage)(const void *const data, ENIPMessage *const outgoing_message);
+
 /** @brief Structure to describe a single CIP attribute of an object
 */
 typedef struct {
   EipUint16 attribute_number; /**< The attribute number of this attribute. */
   EipUint8 type;  /**< The @ref CipDataType of this attribute. */
+  CipAttributeEncodeInMessage encode; /**< Self-describing its data encoding */
   CIPAttributeFlag attribute_flags; /**< See @ref CIPAttributeFlag declaration for valid values. */
   void *data;
 } CipAttributeStruct;

+ 57 - 160
source/src/enet_encap/cpf.c

@@ -15,6 +15,7 @@
 #include "cipconnectionmanager.h"
 #include "trace.h"
 #include "encap.h"
+#include "enipmessage.h"
 
 const size_t item_count_field_size = 2; /**< The size of the item count field in the message */
 const size_t item_data_type_id_field_length = 2; /**< The size of the item count field in the message */
@@ -299,39 +300,25 @@ EipStatus CreateCommonPacketFormatStructure(
 /**
  * @brief Encodes a Null Address Item into the message frame
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeNullAddressItem(ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    kCipItemIdNullAddress,
-    &outgoing_message->current_message_position);
+void EncodeNullAddressItem(ENIPMessage *const outgoing_message) {
+  AddIntToMessage(kCipItemIdNullAddress, outgoing_message);
   /* null address item -> address length set to 0 */
-  outgoing_message->used_message_length += AddIntToMessage(0,
-                                                           &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(0, outgoing_message);
 }
 
 /**
  * Encodes a Connected Address Item into the message frame
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeConnectedAddressItem(
+void EncodeConnectedAddressItem(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
   /* connected data item -> address length set to 4 and copy ConnectionIdentifier */
-  outgoing_message->used_message_length += AddIntToMessage(
-    kCipItemIdConnectionAddress,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(4,
-                                                           &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddDintToMessage(
-    common_packet_format_data_item->address_item.data.connection_identifier,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(kCipItemIdConnectionAddress, outgoing_message);
+  AddIntToMessage(4, outgoing_message);
+  AddDintToMessage(common_packet_format_data_item->address_item.data.connection_identifier, outgoing_message);
 }
 
 /**
@@ -339,26 +326,15 @@ int EncodeConnectedAddressItem(
  *
  * @param common_packet_format_data_item Common Packet Format item which is used in the encoding
  * @param outgoing_message The outgoing message object
- *
- * @return New message size after encoding
  */
-int EncodeSequencedAddressItem(
+void EncodeSequencedAddressItem(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
   /* sequenced address item -> address length set to 8 and copy ConnectionIdentifier and SequenceNumber */
-  outgoing_message->used_message_length += AddIntToMessage(
-    kCipItemIdSequencedAddressItem,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    sequenced_address_item_length,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddDintToMessage(
-    common_packet_format_data_item->address_item.data.connection_identifier,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddDintToMessage(
-    common_packet_format_data_item->address_item.data.sequence_number,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(kCipItemIdSequencedAddressItem, outgoing_message);
+  AddIntToMessage(sequenced_address_item_length, outgoing_message);
+  AddDintToMessage(common_packet_format_data_item->address_item.data.connection_identifier, outgoing_message);
+  AddDintToMessage(common_packet_format_data_item->address_item.data.sequence_number, outgoing_message);
 }
 
 /**
@@ -366,16 +342,11 @@ int EncodeSequencedAddressItem(
  *
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeItemCount(
+void EncodeItemCount(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    common_packet_format_data_item->item_count,
-    &outgoing_message->current_message_position);                                                                                                    /* item count */
-  return outgoing_message->used_message_length;
+  AddIntToMessage(common_packet_format_data_item->item_count, outgoing_message); /* item count */
 }
 
 /**
@@ -383,16 +354,11 @@ int EncodeItemCount(
  *
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeDataItemType(
+void EncodeDataItemType(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    common_packet_format_data_item->data_item.type_id,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(common_packet_format_data_item->data_item.type_id, outgoing_message);
 }
 
 /**
@@ -400,16 +366,11 @@ int EncodeDataItemType(
  *
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeDataItemLength(
+void EncodeDataItemLength(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    common_packet_format_data_item->data_item.length,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(common_packet_format_data_item->data_item.length, outgoing_message);
 }
 
 /**
@@ -417,19 +378,15 @@ int EncodeDataItemLength(
  *
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message frame after encoding
  */
-int EncodeDataItemData(
+void EncodeDataItemData(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
   for (size_t i = 0; i < common_packet_format_data_item->data_item.length;
        i++) {
-    outgoing_message->used_message_length += AddSintToMessage(
-      *(common_packet_format_data_item->data_item.data + i),
-      &outgoing_message->current_message_position);
+    AddSintToMessage(*(common_packet_format_data_item->data_item.data + i),
+      outgoing_message);
   }
-  return outgoing_message->used_message_length;
 }
 
 /**
@@ -437,18 +394,14 @@ int EncodeDataItemData(
  *
  * @param message_router_response The Router Response message which shall be answered
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message buffer
  */
 
-int EncodeConnectedDataItemLength(
+void EncodeConnectedDataItemLength(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    (EipUint16) ( message_router_response->data_length + 4 + 2  /* TODO: Magic numbers */
-                  + (2 * message_router_response->size_of_additional_status) ),
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+
+  AddIntToMessage((EipUint16) ( message_router_response->message.used_message_length + 4 + 2  /* TODO: Magic numbers */
+                  + (2 * message_router_response->size_of_additional_status) ), outgoing_message);
 }
 
 /**
@@ -456,18 +409,11 @@ int EncodeConnectedDataItemLength(
  *
  * @param common_packet_format_data_item
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message buffer
- *
  */
-int EncodeSequenceNumber(
+void EncodeSequenceNumber(
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    (EipUint16) common_packet_format_data_item->address_item.data
-    .sequence_number,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage((EipUint16) common_packet_format_data_item->address_item.data.sequence_number, outgoing_message);
 }
 
 /**
@@ -475,16 +421,11 @@ int EncodeSequenceNumber(
  *
  * @param message_router_response The router response message data structure to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return The new size of the message buffer
  */
-int EncodeReplyService(
+void EncodeReplyService(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddSintToMessage(
-    message_router_response->reply_service,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddSintToMessage(message_router_response->reply_service, outgoing_message);
 }
 
 /**
@@ -492,16 +433,11 @@ int EncodeReplyService(
  *
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
-int EncodeReservedFieldOfLengthByte(
+void EncodeReservedFieldOfLengthByte(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddSintToMessage(
-    message_router_response->reserved,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddSintToMessage(message_router_response->reserved, outgoing_message);
 }
 
 /**
@@ -509,16 +445,11 @@ int EncodeReservedFieldOfLengthByte(
  *
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
-int EncodeGeneralStatus(
+void EncodeGeneralStatus(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddSintToMessage(
-    message_router_response->general_status,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddSintToMessage(message_router_response->general_status, outgoing_message);
 }
 
 /**
@@ -526,17 +457,12 @@ int EncodeGeneralStatus(
  *
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
 
-int EncodeExtendedStatusLength(
+void EncodeExtendedStatusLength(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddSintToMessage(
-    message_router_response->size_of_additional_status,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddSintToMessage(message_router_response->size_of_additional_status, outgoing_message);
 }
 
 /**
@@ -544,20 +470,15 @@ int EncodeExtendedStatusLength(
  *
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
-size_t EncodeExtendedStatusDataItems(
+void EncodeExtendedStatusDataItems(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
   for (size_t i = 0;
        i < message_router_response->size_of_additional_status &&
        i < MAX_SIZE_OF_ADD_STATUS; i++) {
-    outgoing_message->used_message_length += AddIntToMessage(
-      message_router_response->additional_status[i],
-      &outgoing_message->current_message_position);
+    AddIntToMessage(message_router_response->additional_status[i], outgoing_message);
   }
-  return outgoing_message->used_message_length;
 }
 
 /**
@@ -568,17 +489,13 @@ size_t EncodeExtendedStatusDataItems(
  *
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
 
-int EncodeExtendedStatus(
+void EncodeExtendedStatus(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
   EncodeExtendedStatusLength(message_router_response, outgoing_message);
   EncodeExtendedStatusDataItems(message_router_response, outgoing_message);
-
-  return outgoing_message->used_message_length;
 }
 
 /**
@@ -587,16 +504,12 @@ int EncodeExtendedStatus(
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
  *
- * @return New size of the message buffer
  */
-int EncodeUnconnectedDataItemLength(
+void EncodeUnconnectedDataItemLength(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    (EipUint16) ( message_router_response->data_length + 4  /* TODO: Magic number */
-                  + (2 * message_router_response->size_of_additional_status) ),
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage((EipUint16) ( message_router_response->message.used_message_length + 4  /* TODO: Magic number */
+                  + (2 * message_router_response->size_of_additional_status) ), outgoing_message);
 }
 
 /**
@@ -605,15 +518,13 @@ int EncodeUnconnectedDataItemLength(
  * @param message_router_response Router Response message to be processed
  * @param outgoing_message The outgoing message object
  */
-int EncodeMessageRouterResponseData(
+void EncodeMessageRouterResponseData(
   const CipMessageRouterResponse *const message_router_response,
   ENIPMessage *const outgoing_message) {
-  for (size_t i = 0; i < message_router_response->data_length; i++) {
-    outgoing_message->used_message_length +=
-      AddSintToMessage( (message_router_response->data)[i],
-                        &outgoing_message->current_message_position );
-  }
-  return outgoing_message->used_message_length;
+//  for (size_t i = 0; i < message_router_response->message.used_message_length; i++) {
+//    AddSintToMessage( (message_router_response->message.message_buffer)[i], outgoing_message);
+//  }
+  memcpy(outgoing_message->current_message_position, message_router_response->message.message_buffer, message_router_response->message.used_message_length);
 }
 
 /**
@@ -622,19 +533,13 @@ int EncodeMessageRouterResponseData(
  * @param item_type
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
-int EncodeSockaddrInfoItemTypeId(
+void EncodeSockaddrInfoItemTypeId(
   int item_type,
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
   OPENER_ASSERT(item_type == 0 || item_type == 1)
-  outgoing_message->used_message_length += AddIntToMessage(
-    common_packet_format_data_item->address_info_item[item_type].type_id,
-    &outgoing_message->current_message_position);
-
-  return outgoing_message->used_message_length;
+  AddIntToMessage(common_packet_format_data_item->address_info_item[item_type].type_id, outgoing_message);
 }
 
 /**
@@ -643,17 +548,12 @@ int EncodeSockaddrInfoItemTypeId(
  * @param item_type
  * @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
  * @param outgoing_message The outgoing message object
- *
- * @return New size of the message buffer
  */
-int EncodeSockaddrInfoLength(
+void EncodeSockaddrInfoLength(
   int item_type,
   const CipCommonPacketFormatData *const common_packet_format_data_item,
   ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    common_packet_format_data_item->address_info_item[item_type].length,
-    &outgoing_message->current_message_position);
-  return outgoing_message->used_message_length;
+  AddIntToMessage(common_packet_format_data_item->address_info_item[item_type].length, outgoing_message);
 }
 
 int AssembleLinearMessage(
@@ -663,10 +563,8 @@ int AssembleLinearMessage(
 
   if (message_router_response) {
     /* add Interface Handle and Timeout = 0 -> only for SendRRData and SendUnitData necessary */
-    outgoing_message->used_message_length += AddDintToMessage(0,
-                                                              &outgoing_message->current_message_position);
-    outgoing_message->used_message_length += AddIntToMessage(0,
-                                                             &outgoing_message->current_message_position);
+    AddDintToMessage(0, outgoing_message);
+    AddIntToMessage(0, outgoing_message);
   }
 
   EncodeItemCount(common_packet_format_data_item, outgoing_message);
@@ -750,14 +648,13 @@ int AssembleLinearMessage(
         EncodeSockaddrInfoLength(j,common_packet_format_data_item,
                                  outgoing_message);
 
-        outgoing_message->used_message_length += EncapsulateIpAddress(
+        EncapsulateIpAddress(
           common_packet_format_data_item->address_info_item[j].sin_port,
           common_packet_format_data_item->address_info_item[j].sin_addr,
-          &outgoing_message->current_message_position);
+          outgoing_message);
 
-        outgoing_message->used_message_length +=
-          FillNextNMessageOctetsWithValueAndMoveToNextPosition(
-            0, 8, &outgoing_message->current_message_position);
+        FillNextNMessageOctetsWithValueAndMoveToNextPosition(
+            0, 8, outgoing_message);
         break;
       }
     }

+ 30 - 80
source/src/enet_encap/encap.c

@@ -300,8 +300,7 @@ EipStatus HandleReceivedExplictUdpData
 }
 
 void SkipEncapsulationHeader(ENIPMessage *const outgoing_message) {
-  MoveMessageNOctets(ENCAPSULATION_HEADER_LENGTH,
-                     (const CipOctet **)&outgoing_message->current_message_position);
+  MoveMessageNOctets(ENCAPSULATION_HEADER_LENGTH, outgoing_message);
 }
 
 void GenerateEncapsulationHeader(const EncapsulationData *const receive_data,
@@ -309,23 +308,15 @@ void GenerateEncapsulationHeader(const EncapsulationData *const receive_data,
                                  const size_t session_handle,
                                  const EncapsulationProtocolErrorCode encapsulation_protocol_status,
                                  ENIPMessage *const outgoing_message) {
-  outgoing_message->used_message_length += AddIntToMessage(
-    receive_data->command_code,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    command_specific_data_length,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddDintToMessage(session_handle,
-                                                            &outgoing_message->current_message_position); //Session handle
-  outgoing_message->used_message_length += AddDintToMessage(
-    encapsulation_protocol_status,
-    &outgoing_message->current_message_position);                                                         //Status
+  AddIntToMessage(receive_data->command_code, outgoing_message);
+  AddIntToMessage(command_specific_data_length, outgoing_message);
+  AddDintToMessage(session_handle, outgoing_message); //Session handle
+  AddDintToMessage(encapsulation_protocol_status, outgoing_message); //Status
   memcpy(outgoing_message->current_message_position,
          receive_data->sender_context, kSenderContextSize);                // sender context
   outgoing_message->current_message_position += kSenderContextSize;
   outgoing_message->used_message_length += kSenderContextSize;
-  outgoing_message->used_message_length += AddDintToMessage(0,
-                                                            &outgoing_message->current_message_position); // options
+  AddDintToMessage(0, outgoing_message); // options
 }
 
 /** @brief generate reply with "Communications Services" + compatibility Flags.
@@ -347,20 +338,11 @@ void HandleReceivedListServicesCommand(
                               outgoing_message);
 
   /* Command specific data copy Interface data to msg for sending */
-  outgoing_message->used_message_length += AddIntToMessage(1,
-                                                           &outgoing_message->current_message_position); // Item count
-  outgoing_message->used_message_length += AddIntToMessage(
-    g_service_information.type_code,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    (EipUint16) (g_service_information.length - 4),
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    g_service_information.encapsulation_protocol_version,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    g_service_information.capability_flags,
-    &outgoing_message->current_message_position);
+  AddIntToMessage(1, outgoing_message); // Item count
+  AddIntToMessage(g_service_information.type_code, outgoing_message);
+  AddIntToMessage((EipUint16) (g_service_information.length - 4), outgoing_message);
+  AddIntToMessage(g_service_information.encapsulation_protocol_version, outgoing_message);
+  AddIntToMessage(g_service_information.capability_flags, outgoing_message);
   memcpy(outgoing_message->current_message_position,
          g_service_information.name_of_service,
          sizeof(g_service_information.name_of_service) );
@@ -381,8 +363,7 @@ void HandleReceivedListInterfacesCommand(
                               kEncapsulationProtocolSuccess,
                               outgoing_message);
   /* Command specific data */
-  outgoing_message->used_message_length += AddIntToMessage(0x0000,
-                                                           &outgoing_message->current_message_position); /* Set Item Count to 0: no Target Items follow. */
+  AddIntToMessage(0x0000, outgoing_message); /* Set Item Count to 0: no Target Items follow. */
 }
 
 void HandleReceivedListIdentityCommandTcp(
@@ -432,59 +413,32 @@ CipUint ListIdentityGetCipIdentityItemLength() {
 void EncodeListIdentityCipIdentityItem(ENIPMessage *const outgoing_message) {
   /* Item ID*/
   const CipUint kItemIDCipIdentity = 0x0C;
-  outgoing_message->used_message_length += AddIntToMessage(
-    kItemIDCipIdentity,
-    &outgoing_message->current_message_position);
+  AddIntToMessage(kItemIDCipIdentity, outgoing_message);
 
-  outgoing_message->used_message_length += AddIntToMessage(
-    ListIdentityGetCipIdentityItemLength(),
-    &outgoing_message->current_message_position);
+  AddIntToMessage(ListIdentityGetCipIdentityItemLength(), outgoing_message);
 
-  outgoing_message->used_message_length += AddIntToMessage(
-    kSupportedProtocolVersion,
-    &outgoing_message->current_message_position);
+  AddIntToMessage(kSupportedProtocolVersion, outgoing_message);
 
-  outgoing_message->used_message_length += EncapsulateIpAddress(
-    htons(kOpenerEthernetPort), g_tcpip.interface_configuration.ip_address,
-    &outgoing_message->current_message_position);
+  EncapsulateIpAddress(htons(kOpenerEthernetPort), g_tcpip.interface_configuration.ip_address, outgoing_message);
 
   /** Array of USINT - length 8 shall be set to zero */
-  memset(outgoing_message->current_message_position, 0, 8);
-  outgoing_message->used_message_length += MoveMessageNOctets(8,
-                                                              (const CipOctet **) &outgoing_message->current_message_position);
-
-  outgoing_message->used_message_length += AddIntToMessage(g_identity.vendor_id,
-                                                           &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    g_identity.device_type,
-    &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddIntToMessage(
-    g_identity.product_code,
-    &outgoing_message->current_message_position);
-  *(outgoing_message->current_message_position)++ =
-    g_identity.revision.major_revision;
-  outgoing_message->used_message_length++;
-  *(outgoing_message->current_message_position)++ =
-    g_identity.revision.minor_revision;
-  outgoing_message->used_message_length++;
-  outgoing_message->used_message_length += AddIntToMessage(g_identity.status,
-                                                           &outgoing_message->current_message_position);
-  outgoing_message->used_message_length += AddDintToMessage(
-    g_identity.serial_number,
-    &outgoing_message->current_message_position);
-  *outgoing_message->current_message_position++ =
-    (unsigned char) g_identity.product_name.length;
-  outgoing_message->used_message_length++;
-
+  FillNextNMessageOctetsWithValueAndMoveToNextPosition(0, 8, outgoing_message);
+
+  AddIntToMessage(g_identity.vendor_id, outgoing_message);
+  AddIntToMessage(g_identity.device_type, outgoing_message);
+  AddIntToMessage(g_identity.product_code, outgoing_message);
+  AddSintToMessage(g_identity.revision.major_revision, outgoing_message);
+  AddSintToMessage(g_identity.revision.minor_revision, outgoing_message);
+  AddIntToMessage(g_identity.status, outgoing_message);
+  AddDintToMessage(g_identity.serial_number, outgoing_message);
+  AddSintToMessage((unsigned char) g_identity.product_name.length, outgoing_message);
   memcpy(outgoing_message->current_message_position,
          g_identity.product_name.string,
          g_identity.product_name.length);
   outgoing_message->current_message_position += g_identity.product_name.length;
   outgoing_message->used_message_length += g_identity.product_name.length;
 
-  *outgoing_message->current_message_position++ = g_identity.state;
-  outgoing_message->used_message_length++;
-
+  AddSintToMessage(g_identity.state, outgoing_message);
 }
 
 void EncapsulateListIdentityResponseMessage(
@@ -502,8 +456,7 @@ void EncapsulateListIdentityResponseMessage(
                               kEncapsulationProtocolSuccess,
                               outgoing_message);
 
-  outgoing_message->used_message_length += AddIntToMessage(1,
-                                                           &outgoing_message->current_message_position); /* Item count: one item */
+  AddIntToMessage(1, outgoing_message); /* Item count: one item */
   EncodeListIdentityCipIdentityItem(outgoing_message);
 
 }
@@ -541,11 +494,8 @@ void EncapsulateRegisterSessionCommandResponseMessage(
                               encapsulation_protocol_status,
                               outgoing_message);
 
-  outgoing_message->used_message_length += AddIntToMessage(1,
-                                                           &outgoing_message->current_message_position); /* protocol version*/
-  outgoing_message->used_message_length += AddIntToMessage(
-    0,
-    &outgoing_message->current_message_position);                     /* Options flag, shall be set to zero */
+  AddIntToMessage(1, outgoing_message); /* protocol version*/
+  AddIntToMessage(0, outgoing_message); /* Options flag, shall be set to zero */
 }
 
 /* @brief Check supported protocol, generate session handle, send replay back to originator.

+ 60 - 74
source/src/enet_encap/endianconv.c

@@ -100,13 +100,12 @@ CipUdint GetUdintFromMessage(const CipOctet **const buffer_address) {
  * @param data value to be written
  * @param buffer pointer where data should be written.
  */
-int AddSintToMessage(const EipUint8 data,
-                     EipUint8 **const buffer) {
-  unsigned char *p = (unsigned char *) *buffer;
+void AddSintToMessage(const EipUint8 data,
+		ENIPMessage *const outgoing_message) {
 
-  p[0] = (unsigned char) data;
-  *buffer += 1;
-  return 1;
+	outgoing_message->current_message_position[0] = (unsigned char) data;
+	outgoing_message->current_message_position += 1;
+	outgoing_message->used_message_length += 1;
 }
 
 /**
@@ -114,14 +113,13 @@ int AddSintToMessage(const EipUint8 data,
  * @param data value to be written
  * @param buffer pointer where data should be written.
  */
-int AddIntToMessage(const EipUint16 data,
-                    EipUint8 **const buffer) {
-  unsigned char *p = (unsigned char *) *buffer;
+void AddIntToMessage(const EipUint16 data,
+		ENIPMessage *const outgoing_message) {
 
-  p[0] = (unsigned char) data;
-  p[1] = (unsigned char) (data >> 8);
-  *buffer += 2;
-  return 2;
+  outgoing_message->current_message_position[0] = (unsigned char) data;
+  outgoing_message->current_message_position[1] = (unsigned char) (data >> 8);
+  outgoing_message->current_message_position += 2;
+  outgoing_message->used_message_length += 2;
 }
 
 /**
@@ -129,17 +127,15 @@ int AddIntToMessage(const EipUint16 data,
  * @param data value to be written
  * @param buffer pointer where data should be written.
  */
-int AddDintToMessage(const EipUint32 data,
-                     EipUint8 **const buffer) {
-  unsigned char *p = (unsigned char *) *buffer;
-
-  p[0] = (unsigned char) data;
-  p[1] = (unsigned char) (data >> 8);
-  p[2] = (unsigned char) (data >> 16);
-  p[3] = (unsigned char) (data >> 24);
-  *buffer += 4;
-
-  return 4;
+void AddDintToMessage(const EipUint32 data,
+		ENIPMessage *const outgoing_message) {
+  outgoing_message->current_message_position[0] = (unsigned char) data;
+  outgoing_message->current_message_position[1] = (unsigned char) (data >> 8);
+  outgoing_message->current_message_position[2] = (unsigned char) (data >> 16);
+  outgoing_message->current_message_position[3] = (unsigned char) (data >> 24);
+
+  outgoing_message->current_message_position += 4;
+  outgoing_message->used_message_length += 4;
 }
 
 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
@@ -175,59 +171,51 @@ EipUint64 GetLintFromMessage(const EipUint8 **const buffer) {
  * @param data value to be written
  * @param buffer pointer where data should be written.
  */
-int AddLintToMessage(const EipUint64 data,
-                     EipUint8 **const buffer) {
-  EipUint8 *buffer_address = *buffer;
-  buffer_address[0] = (EipUint8) (data >> 56) & 0xFF;
-  buffer_address[1] = (EipUint8) (data >> 48) & 0xFF;
-  buffer_address[2] = (EipUint8) (data >> 40) & 0xFF;
-  buffer_address[3] = (EipUint8) (data >> 32) & 0xFF;
-  buffer_address[4] = (EipUint8) (data >> 24) & 0xFF;
-  buffer_address[5] = (EipUint8) (data >> 16) & 0xFF;
-  buffer_address[6] = (EipUint8) (data >> 8) & 0xFF;
-  buffer_address[7] = (EipUint8) (data) & 0xFF;
-  (*buffer) += 8;
-
-  return 8;
+void AddLintToMessage(const EipUint64 data,
+		ENIPMessage *const outgoing_message) {
+
+  outgoing_message->current_message_position[0] = (EipUint8) (data >> 56) & 0xFF;
+  outgoing_message->current_message_position[1] = (EipUint8) (data >> 48) & 0xFF;
+  outgoing_message->current_message_position[2] = (EipUint8) (data >> 40) & 0xFF;
+  outgoing_message->current_message_position[3] = (EipUint8) (data >> 32) & 0xFF;
+  outgoing_message->current_message_position[4] = (EipUint8) (data >> 24) & 0xFF;
+  outgoing_message->current_message_position[5] = (EipUint8) (data >> 16) & 0xFF;
+  outgoing_message->current_message_position[6] = (EipUint8) (data >> 8) & 0xFF;
+  outgoing_message->current_message_position[7] = (EipUint8) (data) & 0xFF;
+  outgoing_message->current_message_position += 8;
+  outgoing_message->used_message_length += 8;
 }
 
 #endif
 
 
-int EncapsulateIpAddress(EipUint16 port,
+void EncapsulateIpAddress(EipUint16 port,
                          EipUint32 address,
-                         EipByte **communication_buffer) {
-  int size = 0;
+						 ENIPMessage *const outgoing_message) {
   if (kOpENerEndianessLittle == g_opener_platform_endianess) {
-    size += AddIntToMessage(htons(AF_INET), communication_buffer);
-    size += AddIntToMessage(port, communication_buffer);
-    size += AddDintToMessage(address, communication_buffer);
+    AddIntToMessage(htons(AF_INET), outgoing_message);
+    AddIntToMessage(port, outgoing_message);
+    AddDintToMessage(address, outgoing_message);
 
   } else {
     if (kOpENerEndianessBig == g_opener_platform_endianess) {
-      (*communication_buffer)[0] = (unsigned char) (AF_INET >> 8);
-      (*communication_buffer)[1] = (unsigned char) AF_INET;
-      *communication_buffer += 2;
-      size += 2;
-
-      (*communication_buffer)[0] = (unsigned char) (port >> 8);
-      (*communication_buffer)[1] = (unsigned char) port;
-      *communication_buffer += 2;
-      size += 2;
-
-      (*communication_buffer)[3] = (unsigned char) address;
-      (*communication_buffer)[2] = (unsigned char) (address >> 8);
-      (*communication_buffer)[1] = (unsigned char) (address >> 16);
-      (*communication_buffer)[0] = (unsigned char) (address >> 24);
-      *communication_buffer += 4;
-      size += 4;
+
+      AddIntToMessage(htons(AF_INET), outgoing_message);
+
+      AddSintToMessage((unsigned char) (port >> 8), outgoing_message);
+      AddSintToMessage((unsigned char) port, outgoing_message);
+
+      AddSintToMessage((unsigned char) address, outgoing_message);
+      AddSintToMessage((unsigned char) (address >> 8), outgoing_message);
+      AddSintToMessage((unsigned char) (address >> 16), outgoing_message);
+      AddSintToMessage((unsigned char) (address >> 24), outgoing_message);
+
     } else {
       fprintf(stderr,
               "No endianess detected! Probably the DetermineEndianess function was not executed!");
       exit (EXIT_FAILURE);
     }
   }
-  return size;
 }
 
 /**
@@ -255,24 +243,22 @@ int GetEndianess() {
   return g_opener_platform_endianess;
 }
 
-int MoveMessageNOctets(const int amount_of_bytes_moved,
-                       const CipOctet **message_runner) {
-  (*message_runner) += amount_of_bytes_moved;
-  return amount_of_bytes_moved;
+void MoveMessageNOctets(const int amount_of_bytes_moved,
+		ENIPMessage *const outgoing_message) {
+  outgoing_message->current_message_position += amount_of_bytes_moved;
+  outgoing_message->used_message_length += amount_of_bytes_moved;
 }
 
-int FillNextNMessageOctetsWith(CipOctet value,
+void FillNextNMessageOctetsWith(CipOctet value,
                                unsigned int amount_of_bytes_written,
-                               CipOctet **message) {
-  memset(*message, value, amount_of_bytes_written);
-  return amount_of_bytes_written;
+							   ENIPMessage *const outgoing_message) {
+  memset(outgoing_message->current_message_position, value, amount_of_bytes_written);
 }
 
-int FillNextNMessageOctetsWithValueAndMoveToNextPosition(CipOctet value,
+void FillNextNMessageOctetsWithValueAndMoveToNextPosition(CipOctet value,
                                                          unsigned int amount_of_filled_bytes,
-                                                         CipOctet **message) {
-  FillNextNMessageOctetsWith(value, amount_of_filled_bytes, message);
-  MoveMessageNOctets(amount_of_filled_bytes, (const CipOctet **)message);
-  return amount_of_filled_bytes;
+														 ENIPMessage *const outgoing_message) {
+  FillNextNMessageOctetsWith(value, amount_of_filled_bytes, outgoing_message);
+  MoveMessageNOctets(amount_of_filled_bytes, outgoing_message);
 }
 

+ 18 - 19
source/src/enet_encap/endianconv.h

@@ -7,6 +7,7 @@
 #define OPENER_ENDIANCONV_H_
 
 #include "typedefs.h"
+#include "ciptypes.h"
 
 /** @file endianconv.h
  * @brief Responsible for Endianess conversion
@@ -57,8 +58,8 @@ CipUdint GetUdintFromMessage(const CipOctet **const buffer_address);
  * @param data value to be written
  * @param buffer pointer where data should be written.
  */
-int AddSintToMessage(const EipUint8 data,
-                     EipUint8 **const buffer);
+void AddSintToMessage(const EipUint8 data,
+		ENIPMessage *const outgoing_message);
 
 /** @ingroup ENCAP
  *
@@ -68,8 +69,8 @@ int AddSintToMessage(const EipUint8 data,
  *
  * @return Length in bytes of the encoded message
  */
-int AddIntToMessage(const EipUint16 data,
-                    EipUint8 **const buffer);
+void AddIntToMessage(const EipUint16 data,
+		ENIPMessage *const outgoing_message);
 
 /** @ingroup ENCAP
  *
@@ -79,8 +80,8 @@ int AddIntToMessage(const EipUint16 data,
  *
  * @return Length in bytes of the encoded message
  */
-int AddDintToMessage(const EipUint32 data,
-                     EipUint8 **const buffer);
+void AddDintToMessage(const EipUint32 data,
+		ENIPMessage *const outgoing_message);
 
 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
 
@@ -92,10 +93,9 @@ EipUint64 GetLintFromMessage(const EipUint8 **const buffer);
  * @param data value to write
  * @param buffer pointer to the network buffer array. This pointer will be incremented by 8!
  *
- * @return Length in bytes of the encoded message
  */
-int AddLintToMessage(const EipUint64 pa_unData,
-                     EipUint8 **const buffer);
+void AddLintToMessage(const EipUint64 pa_unData,
+		ENIPMessage *const outgoing_message);
 
 #endif
 
@@ -107,9 +107,9 @@ int AddLintToMessage(const EipUint64 pa_unData,
  * @param address IP address of the socket, has to be provided in big-endian
  * @param communication_buffer The message buffer for sending the message
  */
-int EncapsulateIpAddress(EipUint16 port,
+void EncapsulateIpAddress(EipUint16 port,
                          EipUint32 address,
-                         EipByte **communication_buffer);
+						 ENIPMessage *const outgoing_message);
 
 /** Identify if we are running on a big or little endian system and set
  * variable.
@@ -124,14 +124,13 @@ void DetermineEndianess(void);
  */
 int GetEndianess(void);
 
-int MoveMessageNOctets(const int n,
-                       const CipOctet **message_runner);
+void MoveMessageNOctets(const int amount_of_bytes_moved,
+		ENIPMessage *const outgoing_message);
+
+void FillNextNMessageOctetsWith(CipOctet value,
+                               unsigned int amount_of_bytes_written,
+							   ENIPMessage *const outgoing_message);
 
-int FillNextNMessageOctetsWith(CipOctet value,
-                               unsigned int n,
-                               CipOctet **message);
+void FillNextNMessageOctetsWithValueAndMoveToNextPosition(CipOctet value, unsigned int amount_of_filled_bytes, ENIPMessage *const outgoing_message);
 
-int FillNextNMessageOctetsWithValueAndMoveToNextPosition(CipOctet value,
-                                                         unsigned int n,
-                                                         CipOctet **message);
 #endif /* OPENER_ENDIANCONV_H_ */

+ 30 - 5
source/src/opener_api.h

@@ -238,6 +238,13 @@ void InsertAttribute(CipInstance *const cip_instance,
                      void *const cip_data,
                      const EipByte cip_flags);
 
+void InsertAttribute2(CipInstance *const instance,
+                     const EipUint16 attribute_number,
+                     const EipUint8 cip_type,
+					 CipAttributeEncodeInMessage encode_function,
+                     void *const data,
+                     const EipByte cip_flags);
+
 
 /** @ingroup CIP_API
  * @brief Allocates Attribute bitmasks
@@ -302,13 +309,31 @@ void InsertGetSetCallback
  * requester (e.g., getAttributeSingle for special structs).
  *  @param cip_data_type the cip type to encode
  *  @param cip_data pointer to data value.
- *  @param cip_message pointer to memory where response should be written
- *  @return length of attribute in bytes
- *          -1 .. error
+ *  @param message_router_response The message router response construct
  */
-int EncodeData(const EipUint8 cip_data_type,
+void EncodeData(const EipUint8 cip_data_type,
                const void *const cip_data,
-               EipUint8 **cip_message);
+			   CipMessageRouterResponse *const message_router_response);
+
+void EncodeCipBool(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipUsint(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipUint(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipUdint(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipWord(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipDword(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipShortString(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipString(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipByteArray(const void *const data, ENIPMessage *const outgoing_message);
+
+void EncodeCipEPath(const void *const data, ENIPMessage *const outgoing_message);
 
 /** @ingroup CIP_API
  * @brief Retrieve the given data according to CIP encoding from the message