|
|
@@ -14,6 +14,7 @@
|
|
|
#include "ciperror.h"
|
|
|
#include "cipconnectionmanager.h"
|
|
|
#include "trace.h"
|
|
|
+#include "encap.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 */
|
|
|
@@ -22,15 +23,16 @@ const size_t sequenced_address_item_length = 8;
|
|
|
|
|
|
CipCommonPacketFormatData g_common_packet_format_data_item; /**< CPF global data items */
|
|
|
|
|
|
-int NotifyCommonPacketFormat(EncapsulationData *const receive_data,
|
|
|
- EipUint8 *reply_buffer,
|
|
|
- struct sockaddr *originator_address) {
|
|
|
+int NotifyCommonPacketFormat(EncapsulationData *const received_data,
|
|
|
+ const struct sockaddr *const originator_address,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
int return_value = kEipStatusError;
|
|
|
|
|
|
- if ( ( return_value = CreateCommonPacketFormatStructure(
|
|
|
- receive_data->current_communication_buffer_position,
|
|
|
- receive_data->data_length, &g_common_packet_format_data_item) )
|
|
|
- == kEipStatusError ) {
|
|
|
+ if (kEipStatusError == ( return_value = CreateCommonPacketFormatStructure(
|
|
|
+ received_data->
|
|
|
+ current_communication_buffer_position,
|
|
|
+ received_data->data_length,
|
|
|
+ &g_common_packet_format_data_item) ) ) {
|
|
|
OPENER_TRACE_ERR("notifyCPF: error from createCPFstructure\n");
|
|
|
} else {
|
|
|
return_value = kEipStatusOk; /* In cases of errors we normally need to send an error response */
|
|
|
@@ -43,30 +45,53 @@ int NotifyCommonPacketFormat(EncapsulationData *const receive_data,
|
|
|
g_common_packet_format_data_item.data_item.data,
|
|
|
g_common_packet_format_data_item.data_item.length,
|
|
|
originator_address,
|
|
|
- receive_data->session_handle);
|
|
|
+ received_data->session_handle);
|
|
|
if (return_value != kEipStatusError) {
|
|
|
+ SkipEncapsulationHeader(outgoing_message);
|
|
|
return_value = AssembleLinearMessage(
|
|
|
&g_message_router_response, &g_common_packet_format_data_item,
|
|
|
- reply_buffer);
|
|
|
+ outgoing_message);
|
|
|
+
|
|
|
+ CipOctet *buffer = outgoing_message->current_message_position;
|
|
|
+ outgoing_message->current_message_position =
|
|
|
+ outgoing_message->message_buffer;
|
|
|
+ GenerateEncapsulationHeader(received_data,
|
|
|
+ return_value,
|
|
|
+ received_data->session_handle,
|
|
|
+ kEncapsulationProtocolSuccess,
|
|
|
+ outgoing_message);
|
|
|
+ outgoing_message->current_message_position = buffer;
|
|
|
+ return_value = outgoing_message->used_message_length;
|
|
|
}
|
|
|
} else {
|
|
|
/* wrong data item detected*/
|
|
|
OPENER_TRACE_ERR(
|
|
|
"notifyCPF: got something besides the expected CIP_ITEM_ID_UNCONNECTEDMESSAGE\n");
|
|
|
- receive_data->status = kEncapsulationProtocolIncorrectData;
|
|
|
+ GenerateEncapsulationHeader(received_data,
|
|
|
+ return_value,
|
|
|
+ received_data->session_handle,
|
|
|
+ kEncapsulationProtocolIncorrectData,
|
|
|
+ outgoing_message);
|
|
|
+ return_value = outgoing_message->used_message_length;
|
|
|
}
|
|
|
} else {
|
|
|
OPENER_TRACE_ERR(
|
|
|
"notifyCPF: got something besides the expected CIP_ITEM_ID_NULL\n");
|
|
|
- receive_data->status = kEncapsulationProtocolIncorrectData;
|
|
|
+ GenerateEncapsulationHeader(received_data,
|
|
|
+ return_value,
|
|
|
+ received_data->session_handle,
|
|
|
+ kEncapsulationProtocolIncorrectData,
|
|
|
+ outgoing_message);
|
|
|
+ return_value = outgoing_message->used_message_length;
|
|
|
}
|
|
|
}
|
|
|
return return_value;
|
|
|
}
|
|
|
|
|
|
-int NotifyConnectedCommonPacketFormat(EncapsulationData *received_data,
|
|
|
- EipUint8 *reply_buffer,
|
|
|
- struct sockaddr *originator_address) {
|
|
|
+int NotifyConnectedCommonPacketFormat(
|
|
|
+ const EncapsulationData *const received_data,
|
|
|
+ const struct sockaddr *const originator_address,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
int return_value = CreateCommonPacketFormatStructure(
|
|
|
received_data->current_communication_buffer_position,
|
|
|
@@ -86,12 +111,41 @@ int NotifyConnectedCommonPacketFormat(EncapsulationData *received_data,
|
|
|
/* reset the watchdog timer */
|
|
|
ConnectionObjectResetInactivityWatchdogTimerValue(connection_object);
|
|
|
|
|
|
- /*TODO check connection id and sequence count */
|
|
|
+ /*TODO check connection id and sequence count */
|
|
|
if (g_common_packet_format_data_item.data_item.type_id
|
|
|
== kCipItemIdConnectedDataItem) { /* connected data item received*/
|
|
|
EipUint8 *buffer = g_common_packet_format_data_item.data_item.data;
|
|
|
g_common_packet_format_data_item.address_item.data.sequence_number =
|
|
|
(EipUint32) GetIntFromMessage( (const EipUint8 **const)&buffer );
|
|
|
+ OPENER_TRACE_INFO(
|
|
|
+ "Class 3 sequence number: %d, last sequence number: %d\n",
|
|
|
+ g_common_packet_format_data_item.address_item.data.sequence_number,
|
|
|
+ connection_object->sequence_count_consuming);
|
|
|
+ if(connection_object->sequence_count_consuming ==
|
|
|
+ g_common_packet_format_data_item.address_item.data.sequence_number)
|
|
|
+ {
|
|
|
+ memcpy(outgoing_message,
|
|
|
+ &(connection_object->last_reply_sent),
|
|
|
+ sizeof(ENIPMessage) );
|
|
|
+ outgoing_message->current_message_position =
|
|
|
+ outgoing_message->message_buffer;
|
|
|
+ /* Regenerate encapsulation header for new message */
|
|
|
+ outgoing_message->used_message_length -=
|
|
|
+ ENCAPSULATION_HEADER_LENGTH;
|
|
|
+ GenerateEncapsulationHeader(received_data,
|
|
|
+ outgoing_message->used_message_length,
|
|
|
+ received_data->session_handle,
|
|
|
+ kEncapsulationProtocolSuccess,
|
|
|
+ outgoing_message);
|
|
|
+ outgoing_message->current_message_position = buffer;
|
|
|
+ /* End regenerate encapsulation header for new message */
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
+ }
|
|
|
+ connection_object->sequence_count_consuming =
|
|
|
+ g_common_packet_format_data_item.address_item.data.sequence_number;
|
|
|
+
|
|
|
+ ConnectionObjectResetInactivityWatchdogTimerValue(connection_object);
|
|
|
+
|
|
|
return_value = NotifyMessageRouter(
|
|
|
buffer,
|
|
|
g_common_packet_format_data_item.data_item.length - 2,
|
|
|
@@ -102,9 +156,24 @@ int NotifyConnectedCommonPacketFormat(EncapsulationData *received_data,
|
|
|
g_common_packet_format_data_item.address_item.data
|
|
|
.connection_identifier = connection_object
|
|
|
->cip_produced_connection_id;
|
|
|
+ SkipEncapsulationHeader(outgoing_message);
|
|
|
return_value = AssembleLinearMessage(
|
|
|
&g_message_router_response, &g_common_packet_format_data_item,
|
|
|
- reply_buffer);
|
|
|
+ outgoing_message);
|
|
|
+
|
|
|
+ CipOctet *buffer = outgoing_message->current_message_position;
|
|
|
+ outgoing_message->current_message_position =
|
|
|
+ outgoing_message->message_buffer;
|
|
|
+ GenerateEncapsulationHeader(received_data,
|
|
|
+ return_value,
|
|
|
+ received_data->session_handle,
|
|
|
+ kEncapsulationProtocolSuccess,
|
|
|
+ outgoing_message);
|
|
|
+ outgoing_message->current_message_position = buffer;
|
|
|
+ memcpy(&connection_object->last_reply_sent,
|
|
|
+ outgoing_message,
|
|
|
+ sizeof(ENIPMessage) );
|
|
|
+ return_value = outgoing_message->used_message_length;
|
|
|
}
|
|
|
} else {
|
|
|
/* wrong data item detected*/
|
|
|
@@ -120,7 +189,7 @@ int NotifyConnectedCommonPacketFormat(EncapsulationData *received_data,
|
|
|
"notifyConnectedCPF: got something besides the expected CIP_ITEM_ID_NULL\n");
|
|
|
}
|
|
|
}
|
|
|
- return return_value;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -142,7 +211,7 @@ EipStatus CreateCommonPacketFormatStructure(
|
|
|
|
|
|
int length_count = 0;
|
|
|
CipUint item_count = GetIntFromMessage(&data);
|
|
|
- OPENER_ASSERT(4U >= item_count); /* Sanitizing data - probably needs to be changed for productive code */
|
|
|
+ OPENER_ASSERT(4U >= item_count) /* Sanitizing data - probably needs to be changed for productive code */
|
|
|
common_packet_format_data->item_count = item_count;
|
|
|
length_count += 2;
|
|
|
if (common_packet_format_data->item_count >= 1U) {
|
|
|
@@ -221,267 +290,266 @@ EipStatus CreateCommonPacketFormatStructure(
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes a Null Address Item into the message frame
|
|
|
- * @param message The message frame
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
-int EncodeNullAddressItem(EipUint8 **message,
|
|
|
- int size) {
|
|
|
- size += AddIntToMessage(kCipItemIdNullAddress, message);
|
|
|
+int EncodeNullAddressItem(ENIPMessage *const outgoing_message) {
|
|
|
+ outgoing_message->used_message_length += AddIntToMessage(
|
|
|
+ kCipItemIdNullAddress,
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
/* null address item -> address length set to 0 */
|
|
|
- size += AddIntToMessage(0, message);
|
|
|
- return size;
|
|
|
+ outgoing_message->used_message_length += AddIntToMessage(0,
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Encodes a Connected Address Item into the message frame
|
|
|
- * @param message The message frame
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
int EncodeConnectedAddressItem(
|
|
|
- EipUint8 **message,
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- int size) {
|
|
|
+ const CipCommonPacketFormatData *const common_packet_format_data_item,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
/* connected data item -> address length set to 4 and copy ConnectionIdentifier */
|
|
|
- size += AddIntToMessage(kCipItemIdConnectionAddress, message);
|
|
|
- size += AddIntToMessage(4, message);
|
|
|
- size += AddDintToMessage(
|
|
|
+ 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,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes a sequenced address item into the message
|
|
|
*
|
|
|
- * @param message Pointer to the message memory start
|
|
|
* @param common_packet_format_data_item Common Packet Format item which is used in the encoding
|
|
|
- * @param size Size of the message at the start of the function
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return New message size after encoding
|
|
|
*/
|
|
|
int EncodeSequencedAddressItem(
|
|
|
- EipUint8 **message,
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- int size) {
|
|
|
+ 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 */
|
|
|
- size += AddIntToMessage(kCipItemIdSequencedAddressItem, message);
|
|
|
- size += AddIntToMessage(sequenced_address_item_length, message);
|
|
|
- size += AddDintToMessage(
|
|
|
+ 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,
|
|
|
- message);
|
|
|
- size += AddDintToMessage(
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ outgoing_message->used_message_length += AddDintToMessage(
|
|
|
common_packet_format_data_item->address_item.data.sequence_number,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Adds the item count to the message frame
|
|
|
*
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message The message frame
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
-int EncodeItemCount(CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message,
|
|
|
- int size) {
|
|
|
- size += AddIntToMessage(common_packet_format_data_item->item_count, message); /* item count */
|
|
|
- return size;
|
|
|
+int 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Adds the data item type to the message frame
|
|
|
*
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message The message frame
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
int EncodeDataItemType(
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message,
|
|
|
- int size) {
|
|
|
- size += AddIntToMessage(common_packet_format_data_item->data_item.type_id,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Adds the data item section length to the message frame
|
|
|
*
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message The message frame
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
int EncodeDataItemLength(
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message,
|
|
|
- int size) {
|
|
|
- size += AddIntToMessage(common_packet_format_data_item->data_item.length,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Adds the data items to the message frame
|
|
|
*
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message Message frame to which the data is added
|
|
|
- * @param size The actual size of the message frame
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message frame after encoding
|
|
|
*/
|
|
|
int EncodeDataItemData(
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message,
|
|
|
- int size) {
|
|
|
- for (int i = 0; i < common_packet_format_data_item->data_item.length; i++) {
|
|
|
- size += AddSintToMessage(
|
|
|
- *(common_packet_format_data_item->data_item.data + i), message);
|
|
|
+ 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);
|
|
|
}
|
|
|
- return size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the Connected Data item length
|
|
|
*
|
|
|
* @param message_router_response The Router Response message which shall be answered
|
|
|
- * @param message Message frame to which the data is added
|
|
|
- * @param size Current size of the message buffer
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message buffer
|
|
|
*/
|
|
|
|
|
|
int EncodeConnectedDataItemLength(
|
|
|
- CipMessageRouterResponse *message_router_response,
|
|
|
- EipUint8 **message,
|
|
|
- int size) {
|
|
|
- size += AddIntToMessage(
|
|
|
+ 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) ),
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes a sequence number into the message
|
|
|
*
|
|
|
- * @param size The current size of the message buffer
|
|
|
* @param common_packet_format_data_item
|
|
|
- * @param message Message frame to which the data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return The new size of the message buffer
|
|
|
*
|
|
|
*/
|
|
|
int EncodeSequenceNumber(
|
|
|
- int size,
|
|
|
- const CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message) {
|
|
|
- size += AddIntToMessage(
|
|
|
+ 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,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the reply service code for the requested service
|
|
|
*
|
|
|
- * @param size The current size of the message buffer
|
|
|
- * @param message Message frame to which the data is added
|
|
|
- * @param message_rounter_response The router response message data structure to be processed
|
|
|
+ * @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(int size,
|
|
|
- EipUint8 **message,
|
|
|
- CipMessageRouterResponse *message_router_response) {
|
|
|
- size += AddSintToMessage(message_router_response->reply_service, message);
|
|
|
- return size;
|
|
|
+int 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the reserved byte in the message router response
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
- * @param message Message frame to which the data is added
|
|
|
* @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(
|
|
|
- int size,
|
|
|
- EipUint8 **message,
|
|
|
- CipMessageRouterResponse *message_router_response) {
|
|
|
- size += AddSintToMessage(message_router_response->reserved, message);
|
|
|
- return size;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the general status of a Router Response
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
- * @param message Message frame to which the data is added
|
|
|
* @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(int size,
|
|
|
- EipUint8 **message,
|
|
|
- CipMessageRouterResponse *message_router_response) {
|
|
|
- size += AddSintToMessage(message_router_response->general_status, message);
|
|
|
- return size;
|
|
|
+int 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the length of the extended status data part
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
- * @param message Message frame to which the data is added
|
|
|
* @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(
|
|
|
- int size,
|
|
|
- EipUint8 **message,
|
|
|
- CipMessageRouterResponse *message_router_response) {
|
|
|
- size += AddSintToMessage(message_router_response->size_of_additional_status,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the extended status data items
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
* @param message_router_response Router Response message to be processed
|
|
|
- * @param message Message frame to which the data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return New size of the message buffer
|
|
|
*/
|
|
|
-int EncodeExtendedStatusDataItems(
|
|
|
- int size,
|
|
|
- CipMessageRouterResponse *message_router_response,
|
|
|
- EipUint8 **message) {
|
|
|
- for (int i = 0; i < message_router_response->size_of_additional_status;
|
|
|
- i++) {
|
|
|
- size += AddIntToMessage(message_router_response->additional_status[i],
|
|
|
- message);
|
|
|
+size_t 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);
|
|
|
}
|
|
|
-
|
|
|
- return size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -490,147 +558,130 @@ int EncodeExtendedStatusDataItems(
|
|
|
* This function uses EncodeExtendedStatusLength and EncodeExtendedStatusDataItems
|
|
|
* to encode the complete extended status information into the message
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
- * @param message Message frame to which the data is added
|
|
|
* @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(int size,
|
|
|
- EipUint8 **message,
|
|
|
- CipMessageRouterResponse *message_router_response) {
|
|
|
- size = EncodeExtendedStatusLength(size, message, message_router_response);
|
|
|
- size = EncodeExtendedStatusDataItems(size, message_router_response, message);
|
|
|
+int EncodeExtendedStatus(
|
|
|
+ const CipMessageRouterResponse *const message_router_response,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
+ EncodeExtendedStatusLength(message_router_response, outgoing_message);
|
|
|
+ EncodeExtendedStatusDataItems(message_router_response, outgoing_message);
|
|
|
|
|
|
- return size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encode the data item length of the unconnected data segment
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
* @param message_router_response Router Response message to be processed
|
|
|
- * @param message Message frame to which the data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return New size of the message buffer
|
|
|
*/
|
|
|
int EncodeUnconnectedDataItemLength(
|
|
|
- int size,
|
|
|
- CipMessageRouterResponse *message_router_response,
|
|
|
- EipUint8 **message) {
|
|
|
- size += AddIntToMessage(
|
|
|
+ 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) ),
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the Message Router Response data
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
* @param message_router_response Router Response message to be processed
|
|
|
- * @param message Message frame to which the data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*/
|
|
|
int EncodeMessageRouterResponseData(
|
|
|
- int size,
|
|
|
- CipMessageRouterResponse *message_router_response,
|
|
|
- EipUint8 **message) {
|
|
|
- for (int i = 0; i < message_router_response->data_length; i++) {
|
|
|
- size += AddSintToMessage( (message_router_response->data)[i], &*message );
|
|
|
+ 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 size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the sockaddr info type id into the message
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
* @param item_type
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message Message frame to which the encoded data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return New size of the message buffer
|
|
|
*/
|
|
|
int EncodeSockaddrInfoItemTypeId(
|
|
|
- int size,
|
|
|
int item_type,
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message) {
|
|
|
- OPENER_ASSERT(item_type == 0 || item_type == 1);
|
|
|
- size += AddIntToMessage(
|
|
|
+ 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,
|
|
|
- message);
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
|
|
|
- return size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* @brief Encodes the sockaddr info length into the message
|
|
|
*
|
|
|
- * @param size Current size of the message buffer
|
|
|
* @param item_type
|
|
|
* @param common_packet_format_data_item The Common Packet Format data structure from which the message is constructed
|
|
|
- * @param message Message frame to which the encoded data is added
|
|
|
+ * @param outgoing_message The outgoing message object
|
|
|
*
|
|
|
* @return New size of the message buffer
|
|
|
*/
|
|
|
int EncodeSockaddrInfoLength(
|
|
|
- int size,
|
|
|
int item_type,
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 **message) {
|
|
|
- size += AddIntToMessage(
|
|
|
+ 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,
|
|
|
- message);
|
|
|
- return size;
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
-/** @brief Copy data from message_router_response struct and common_packet_format_data_item into linear memory in
|
|
|
- * pa_msg for transmission over in encapsulation.
|
|
|
- *
|
|
|
- * @param message_router_response pointer to message router response which has to be aligned into linear memory.
|
|
|
- * @param common_packet_format_data_item pointer to CPF structure which has to be aligned into linear memory.
|
|
|
- * @param message pointer to linear memory.
|
|
|
- * @return length of reply in message in bytes
|
|
|
- * -1 .. error
|
|
|
- */
|
|
|
int AssembleLinearMessage(
|
|
|
- CipMessageRouterResponse *message_router_response,
|
|
|
- CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 *message) {
|
|
|
-
|
|
|
- size_t message_size = 0;
|
|
|
+ const CipMessageRouterResponse *const message_router_response,
|
|
|
+ const CipCommonPacketFormatData *const common_packet_format_data_item,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
|
|
|
if (message_router_response) {
|
|
|
/* add Interface Handle and Timeout = 0 -> only for SendRRData and SendUnitData necessary */
|
|
|
- AddDintToMessage(0, &message);
|
|
|
- AddIntToMessage(0, &message);
|
|
|
- message_size += 6;
|
|
|
+ outgoing_message->used_message_length += AddDintToMessage(0,
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
+ outgoing_message->used_message_length += AddIntToMessage(0,
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
}
|
|
|
|
|
|
- message_size = EncodeItemCount(common_packet_format_data_item, &message,
|
|
|
- message_size);
|
|
|
+ EncodeItemCount(common_packet_format_data_item, outgoing_message);
|
|
|
|
|
|
/* process Address Item */
|
|
|
switch (common_packet_format_data_item->address_item.type_id) {
|
|
|
case kCipItemIdNullAddress: {
|
|
|
- message_size = EncodeNullAddressItem(&message, message_size);
|
|
|
+ EncodeNullAddressItem(outgoing_message);
|
|
|
break;
|
|
|
}
|
|
|
case kCipItemIdConnectionAddress: {
|
|
|
- message_size = EncodeConnectedAddressItem(&message,
|
|
|
- common_packet_format_data_item,
|
|
|
- message_size);
|
|
|
+ EncodeConnectedAddressItem(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
break;
|
|
|
}
|
|
|
case kCipItemIdSequencedAddressItem: {
|
|
|
- message_size = EncodeSequencedAddressItem(&message,
|
|
|
- common_packet_format_data_item,
|
|
|
- message_size);
|
|
|
+ EncodeSequencedAddressItem(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
break;
|
|
|
}
|
|
|
+ default:
|
|
|
+ OPENER_TRACE_INFO("Unknown CIP Item in AssembleLinearMessage");
|
|
|
+ return kEipStatusError;
|
|
|
}
|
|
|
|
|
|
/* process Data Item */
|
|
|
@@ -640,44 +691,38 @@ int AssembleLinearMessage(
|
|
|
== kCipItemIdConnectedDataItem) ) {
|
|
|
|
|
|
if (message_router_response) {
|
|
|
- message_size = EncodeDataItemType(common_packet_format_data_item,
|
|
|
- &message, message_size);
|
|
|
+ EncodeDataItemType(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
|
|
|
if (common_packet_format_data_item->data_item.type_id
|
|
|
== kCipItemIdConnectedDataItem) { /* Connected Item */
|
|
|
- message_size = EncodeConnectedDataItemLength(message_router_response,
|
|
|
- &message, message_size);
|
|
|
- message_size = EncodeSequenceNumber(message_size,
|
|
|
- &g_common_packet_format_data_item,
|
|
|
- &message);
|
|
|
+ EncodeConnectedDataItemLength(message_router_response,
|
|
|
+ outgoing_message);
|
|
|
+ EncodeSequenceNumber(&g_common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
|
|
|
} else { /* Unconnected Item */
|
|
|
- message_size = EncodeUnconnectedDataItemLength(message_size,
|
|
|
- message_router_response,
|
|
|
- &message);
|
|
|
+ EncodeUnconnectedDataItemLength(message_router_response,
|
|
|
+ outgoing_message);
|
|
|
}
|
|
|
|
|
|
/* write message router response into linear memory */
|
|
|
- message_size = EncodeReplyService(message_size, &message,
|
|
|
- message_router_response);
|
|
|
- message_size = EncodeReservedFieldOfLengthByte(message_size, &message,
|
|
|
- message_router_response);
|
|
|
- message_size = EncodeGeneralStatus(message_size, &message,
|
|
|
- message_router_response);
|
|
|
- message_size = EncodeExtendedStatus(message_size, &message,
|
|
|
- message_router_response);
|
|
|
- message_size = EncodeMessageRouterResponseData(message_size,
|
|
|
- message_router_response,
|
|
|
- &message);
|
|
|
+ EncodeReplyService(message_router_response, outgoing_message);
|
|
|
+ EncodeReservedFieldOfLengthByte(message_router_response,
|
|
|
+ outgoing_message);
|
|
|
+ EncodeGeneralStatus(message_router_response, outgoing_message);
|
|
|
+ EncodeExtendedStatus(message_router_response, outgoing_message);
|
|
|
+ EncodeMessageRouterResponseData(message_router_response,
|
|
|
+ outgoing_message);
|
|
|
} else { /* connected IO Message to send */
|
|
|
- message_size = EncodeDataItemType(common_packet_format_data_item,
|
|
|
- &message, message_size);
|
|
|
+ EncodeDataItemType(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
|
|
|
- message_size = EncodeDataItemLength(common_packet_format_data_item,
|
|
|
- &message, message_size);
|
|
|
+ EncodeDataItemLength(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
|
|
|
- message_size = EncodeDataItemData(common_packet_format_data_item,
|
|
|
- &message, message_size);
|
|
|
+ EncodeDataItemData(common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -691,30 +736,30 @@ int AssembleLinearMessage(
|
|
|
for (int j = 0; j < 2; j++) {
|
|
|
if (common_packet_format_data_item->address_info_item[j].type_id
|
|
|
== type) {
|
|
|
- message_size = EncodeSockaddrInfoItemTypeId(
|
|
|
- message_size, j, common_packet_format_data_item, &message);
|
|
|
+ EncodeSockaddrInfoItemTypeId(
|
|
|
+ j, common_packet_format_data_item, outgoing_message);
|
|
|
|
|
|
- message_size = EncodeSockaddrInfoLength(message_size, j,
|
|
|
- common_packet_format_data_item,
|
|
|
- &message);
|
|
|
+ EncodeSockaddrInfoLength(j,common_packet_format_data_item,
|
|
|
+ outgoing_message);
|
|
|
|
|
|
- message_size += EncapsulateIpAddress(
|
|
|
+ outgoing_message->used_message_length += EncapsulateIpAddress(
|
|
|
common_packet_format_data_item->address_info_item[j].sin_port,
|
|
|
common_packet_format_data_item->address_info_item[j].sin_addr,
|
|
|
- &message);
|
|
|
+ &outgoing_message->current_message_position);
|
|
|
|
|
|
- message_size += FillNextNMessageOctetsWithValueAndMoveToNextPosition(
|
|
|
- 0, 8, &message);
|
|
|
+ outgoing_message->used_message_length +=
|
|
|
+ FillNextNMessageOctetsWithValueAndMoveToNextPosition(
|
|
|
+ 0, 8, &outgoing_message->current_message_position);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return message_size;
|
|
|
+ return outgoing_message->used_message_length;
|
|
|
}
|
|
|
|
|
|
-int AssembleIOMessage(CipCommonPacketFormatData *common_packet_format_data_item,
|
|
|
- EipUint8 *message) {
|
|
|
+int AssembleIOMessage(
|
|
|
+ const CipCommonPacketFormatData *const common_packet_format_data_item,
|
|
|
+ ENIPMessage *const outgoing_message) {
|
|
|
return AssembleLinearMessage(0, common_packet_format_data_item,
|
|
|
- &g_message_data_reply_buffer[0]);
|
|
|
+ outgoing_message);
|
|
|
}
|
|
|
-
|