11 #include "opener_user_conf.h"
40 static const int g_kNumberOfConnectableObjects = 2 +
69 struct sockaddr *originator_address,
70 const int encapsulation_session);
76 struct sockaddr *originator_address,
77 const int encapsulation_session);
83 struct sockaddr *originator_address,
84 const int encapsulation_session);
156 unsigned int padded_logical_path = *(*logical_path_segment)++;
158 if ( (padded_logical_path & 3) == 0 ) {
159 padded_logical_path = *(*logical_path_segment)++;
160 }
else if ( (padded_logical_path & 3) == 1 ) {
161 (*logical_path_segment)++;
162 padded_logical_path = *(*logical_path_segment)++;
163 padded_logical_path |= *(*logical_path_segment)++ << 8;
167 return padded_logical_path;
178 static CipUint connection_id = 18;
188 (
void *) &class->revision,
202 (
void *) &class->highest_attribute_number,
211 g_kCipConnectionManagerClassCode,
219 "connection manager",
222 if (connection_manager == NULL) {
226 "GetAttributeSingle");
233 "GetConnectionOwner");
246 struct sockaddr_in *from_address
265 if (connection_object == NULL) {
271 == from_address->sin_addr.s_addr) {
295 "Connected Message Data Received with wrong address information\n");
333 message_router_response,
359 message_router_response,
384 message_router_response,
411 g_dummy_connection_object) )
414 &g_dummy_connection_object,
415 message_router_response,
421 message_router_request,
425 message_router_response, temp,
433 if (NULL != connection_management_entry) {
435 &g_dummy_connection_object, &connection_status);
446 message_router_response, temp,
452 message_router_response,
464 handle_forward_open_request_functions[2][2] =
496 struct sockaddr *originator_address,
497 const int encapsulation_session
501 bool is_null_request =
false;
502 bool is_matching_request =
false;
506 &g_dummy_connection_object);
508 encapsulation_session;
521 &g_dummy_connection_object, message_router_response,
528 &g_dummy_connection_object, message_router_response,
536 is_null_request =
true;
539 is_null_request =
false;
546 is_matching_request =
true;
550 is_matching_request =
false;
554 handle_forward_open_request_functions[is_null_request][is_matching_request];
556 return choosen_function(&g_dummy_connection_object, instance,
557 message_router_request, message_router_response);
564 struct sockaddr *originator_address,
565 const int encapsulation_session) {
577 message_router_request->
data += 2;
580 &message_router_request->
data);
582 &message_router_request->
data);
584 &message_router_request->
data);
590 while (NULL != node) {
598 == connection_serial_number)
601 == originator_serial_number) ) {
604 if ( ( (
struct sockaddr_in *) originator_address )->sin_addr.s_addr
621 "Connection not found! Requested connection triad: %u, %u, %u\n",
622 connection_serial_number,
623 originator_vendor_id,
624 originator_serial_number);
628 originator_vendor_id,
629 originator_serial_number,
630 message_router_request,
631 message_router_response,
640 struct sockaddr *originator_address,
641 const int encapsulation_session) {
644 (void) message_router_request;
645 (void) message_router_response;
658 while (NULL != node) {
683 && (kEipInvalidSocket
684 != connection_object->
socket[
690 connection_object) ) {
692 if (elapsed_time <= connection_object->production_inhibit_timer) {
707 "sending of UDP data in manage Connection failed\n");
714 connection_object) ) {
750 cip_common_packet_format_data->
item_count = 2;
765 cip_common_packet_format_data->
item_count = 3;
767 cip_common_packet_format_data->
item_count = 4;
780 switch (general_status) {
788 switch (extended_status) {
796 correct_originator_to_target_size;
807 correct_target_to_originator_size;
884 common_data_packet_format_data->
item_count = 2;
895 | message_router_request->
service);
903 *message = *message_router_request->
data;
923 while(NULL != iterator) {
928 return iterator->
data;
930 iterator = iterator->
next;
939 while(NULL != iterator) {
945 output_assembly_id ==
947 return iterator->
data;
949 iterator = iterator->
next;
959 while(NULL != iterator) {
963 return iterator->
data;
966 iterator = iterator->
next;
981 if (4 != key_format) {
1010 if (
false == compatiblity_mode) {
1055 const EipUint8 *message = message_router_request->
data;
1057 size_t remaining_path = connection_path_size;
1069 *extended_error = 0;
1076 *extended_error = 0;
1081 if (remaining_path > 0) {
1091 if (remaining_path < 5) {
1092 *extended_error = 0;
1104 remaining_path -= 5;
1106 "key: ven ID %d, dev type %d, prod code %d, major %d, minor %d\n",
1110 electronic_key.key_data),
1112 electronic_key.key_data),
1114 electronic_key.key_data),
1116 electronic_key.key_data) );
1137 connection_object) ) {
1143 == network_segment_subtype) {
1147 remaining_path -= 1;
1157 class = GetCipClass(class_id);
1158 if (NULL ==
class) {
1162 if (class_id >= 0xC8) {
1180 remaining_path -= 1;
1197 remaining_path -= (instance_id > 0xFF) ? 2 : 1;
1204 connection_object) )
1207 if (remaining_path > 0) {
1209 "Too much data in connection path for class 3 connection\n");
1216 if ( (class_id != kCipMessageRouterClassCode)
1217 || (1 != instance_id) ) {
1225 .instance_id = instance_id,
1226 .attribute_id_or_connection_point = 0
1232 memcpy(&(connection_object->
produced_path), &connection_epath,
1239 .instance_id = instance_id,
1240 .attribute_id_or_connection_point = 0
1256 size_t number_of_encoded_paths = 0;
1259 originator_to_target_connection_type) {
1261 target_to_originator_connection_type) {
1262 number_of_encoded_paths = 0;
1266 number_of_encoded_paths = 1;
1271 target_to_originator_connection_type) {
1273 number_of_encoded_paths = 1;
1279 number_of_encoded_paths = 2;
1283 for (
size_t i = 0; i < number_of_encoded_paths; i++)
1293 .instance_id = attribute_id,
1294 .attribute_id_or_connection_point = 0
1296 memcpy(paths_to_encode[i], &connection_epath,
1299 "connection point %" PRIu32
"\n",
1310 remaining_path -= (attribute_id > 0xFF) ? 2 : 1;
1321 while (remaining_path > 0) {
1324 switch (segment_type) {
1328 switch (data_segment_type) {
1350 connection_object) ) {
1354 remaining_path -= 2;
1356 *extended_error = connection_path_size - remaining_path;
1369 "No data segment identifier found for the configuration data\n");
1370 *extended_error = connection_path_size - remaining_path;
1381 message_router_request->
data = message;
1415 iterator = iterator->
next) {
1416 if(iterator->data == connection_object) {
1429 while (NULL != node) {
1431 CipDword consumed_connection_point =
1433 if (instance_number == consumed_connection_point &&
1435 is_connected =
true;
1440 return is_connected;
1450 for (
size_t i = 0; i < g_kNumberOfConnectableObjects; ++i) {
1451 if ( (0 == g_connection_management_list[i].class_id)
1452 || (class_id == g_connection_management_list[i].class_id) ) {
1453 g_connection_management_list[i].
class_id = class_id;
1455 open_connection_function;
1469 for (
size_t i = 0; i < g_kNumberOfConnectableObjects; ++i) {
1470 if (class_id == g_connection_management_list[i].class_id) {
1471 connection_management_entry = &(g_connection_management_list[i]);
1475 return connection_management_entry;
1479 unsigned int output_assembly,
1480 unsigned int input_assembly
1485 while (NULL != node) {
1488 && (input_assembly ==
1493 connection_object) ) {
1497 production_inhibit_time;
1511 bool non_timed_out_connection_found =
false;
1512 while(NULL != search_node) {
1515 && connection_object != search_connection
1518 non_timed_out_connection_found =
true;
1521 search_node = search_node->
next;
1523 if(
false == non_timed_out_connection_found) {
1524 CloseSessions(connection_object);
1529 memset( g_connection_management_list, 0,
1530 g_kNumberOfConnectableObjects *
EipStatus EstablishClass3Connection(CipConnectionObject *RESTRICT const connection_object, EipUint16 *const extended_error)
Check if Class3 connection is available and if yes setup all data.
ConnectionObjectTransportClassTriggerDirection ConnectionObjectGetTransportClassTriggerDirection(const CipConnectionObject *const connection_object)
EipStatus CheckElectronicKeyData(EipUint8 key_format, void *key_data, EipUint16 *extended_status)
Compare the electronic key received with a forward open request with the device's data...
ConnectionManagementHandling g_connection_management_list[2+OPENER_CIP_NUM_APPLICATION_SPECIFIC_CONNECTABLE_OBJECTS]
void InsertAttribute(CipInstance *const instance, const EipUint16 attribute_number, const EipUint8 cip_type, void *const data, const EipByte cip_flags)
Insert an attribute in an instance of a CIP class.
ConnectionObjectConnectionType
EipStatus ConnectionManagerInit(EipUint16 unique_connection_id)
Initialize the data of the connection manager object.
EipStatus EstablishIoConnection(CipConnectionObject *RESTRICT const connection_object, EipUint16 *const extended_error)
Establishes a new IO Type 1 Connection.
size_t associated_encapsulation_session
void DoublyLinkedListInsertAtHead(DoublyLinkedList *const list, void *data)
EipStatus CreateCommonPacketFormatStructure(const EipUint8 *data, size_t data_length, CipCommonPacketFormatData *common_packet_format_data)
Creates Common Packet Format structure out of data.
bool ConnectionObjectIsTypeIOConnection(const CipConnectionObject *const connection_object)
Tracing infrastructure for OpENer.
void ElectronicKeyFormat4Delete(ElectronicKeyFormat4 **electronic_key)
Destructor for the electroic key format 4 class.
EipUint16 additional_status[MAX_SIZE_OF_ADD_STATUS]
EipUint8 * g_config_data_buffer
network_segment_subtype
All types of network segment types for the use in all code.
ConnectionReceiveDataFunction connection_receive_data_function
EipStatus AssembleForwardCloseResponse(EipUint16 connection_serial_number, EipUint16 originatior_vendor_id, EipUint32 originator_serial_number, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, EipUint16 extended_error_code)
EipStatus HandleNonNullNonMatchingForwardOpenRequest(CipConnectionObject *connection_object, CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response)
Handles a Non Null Non Matching Forward Open Request.
DoublyLinkedList connection_list
CipConnectionObject * CheckForExistingConnection(const CipConnectionObject *const connection_object)
check if the data given in the connection object match with an already established connection ...
DoublyLinkedListNode * first
ConnectionManagerExtendedStatusCode
Connection Manager Error codes.
CIP Message Router Request.
CipConnectionObject * GetConnectedOutputAssembly(const EipUint32 output_assembly_id)
CipUint ConnectionObjectGetExpectedPacketRate(const CipConnectionObject *const connection_object)
void ConnectionObjectResetProductionInhibitTimer(CipConnectionObject *const connection_object)
Class is a subclass of Instance.
void InitializeConnectionManager(CipClass *class)
#define OPENER_ASSERT(assertion)
OpenConnectionFunction open_connection_function
CipUint ElectronicKeyFormat4GetDeviceType(const ElectronicKeyFormat4 *const electronic_key)
Gets the device type from a format 4 electronic key.
EipStatus(* OpenConnectionFunction)(CipConnectionObject *RESTRICT const connection_object, EipUint16 *const extended_error_code)
Function prototype for handling the opening of connections.
CipConnectionObject g_dummy_connection_object
CipByte ElectronicKeyFormat4GetMajorRevision(const ElectronicKeyFormat4 *const electronic_key)
Gets the major revision from an format 4 electronic key.
CipUdint ConnectionObjectGetCipConsumedConnectionID(const CipConnectionObject *const connection_object)
ConnectionObjectConnectionType ConnectionObjectGetTToOConnectionType(const CipConnectionObject *const connection_object)
EipUint32 GetDintFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT32 from *buffer and converts little endian to host.
void RemoveFromActiveConnections(CipConnectionObject *const connection_object)
Removes connection from the list of active connections.
void ConnectionObjectSetProductionInhibitTime(CipConnectionObject *const connection_object, const CipUint production_inhibit_time)
CipCommonPacketFormatData g_common_packet_format_data_item
Data storage for the any CPF data Currently we are single threaded and need only one CPF at the time...
void ConnectionObjectResetInactivityWatchdogTimerValue(CipConnectionObject *const connection_object)
EipStatus AddConnectableObject(const EipUint32 class_id, OpenConnectionFunction open_connection_function)
register open functions for an specific object.
Responsible for Endianess conversion.
#define OPENER_TRACE_ERR(...)
void DoublyLinkedListRemoveNode(DoublyLinkedList *const list, DoublyLinkedListNode **pointer_to_node_pointer)
EipUint8 GetSintFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT8 from *buffer and converts little endian to host.
enum data_segment_subtype DataSegmentSubtype
Data segment sub types.
void ConnectionObjectResetLastPackageInactivityTimerValue(CipConnectionObject *const connection_object)
void ManageEncapsulationMessages(const MilliSeconds elapsed_time)
Handle delayed encapsulation message responses.
Public interface of the QoS Object.
CipOctet * consumed_connection_path
ConnectionCloseFunction connection_close_function
void ConnectionObjectInitializeEmpty(CipConnectionObject *const connection_object)
DataSegmentSubtype GetPathDataSegmentSubtype(const unsigned char *const cip_path)
Gets the Data Segment subtype of a Data Segment EPath message.
CipClass * CreateCipClass(const EipUint32 class_id, const int number_of_class_attributes, const EipUint32 highest_class_attribute_number, const int number_of_class_services, const int number_of_instance_attributes, const EipUint32 highest_instance_attribute_number, const int number_of_instance_services, const int number_of_instances, char *name, const EipUint16 revision, void(*InitializeCipClass)(CipClass *))
CipUdint t_to_o_requested_packet_interval
CipUint ElectronicKeyFormat4GetVendorId(const ElectronicKeyFormat4 *const electronic_key)
Gets the vendor ID form the electronic key.
LogicalSegmentSpecialTypeLogicalFormat GetPathLogicalSegmentSpecialTypeLogicalType(const unsigned char *const cip_path)
Gets the Special Type Logical Type of a Logical Segment EPath message.
DoublyLinkedListNode * next
ElectronicKeySegmentFormat GetPathLogicalSegmentElectronicKeyFormat(const unsigned char *const cip_path)
Gets the Electronic Key format of a Logical Segment Special Type EPath message.
int AddIntToMessage(const EipUint16 data, EipUint8 **const buffer)
converts UINT16 data from host to little endian an writes it to buffer.
unsigned int GetPaddedLogicalPath(const EipUint8 **logical_path_segment)
gets the padded logical path TODO: enhance documentation
void AddNullAddressItem(CipCommonPacketFormatData *common_data_packet_format_data)
Adds a Null Address Item to the common data packet format data.
EipStatus
EIP stack status enum.
bool ConnectionObjectEqualOriginator(const CipConnectionObject *const object1, const CipConnectionObject *const object2)
void InsertService(const CipClass *const class, const EipUint8 service_number, const CipServiceFunction service_function, char *const service_name)
Insert a service in an instance of a CIP object.
enum network_segment_subtype NetworkSegmentSubtype
All types of network segment types for the use in all code.
CipInstance class_instance
void HandleApplication(void)
Allow the device specific application to perform its execution.
EipStatus GetAttributeAll(CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Generic implementation of the GetAttributeAll CIP service.
CipInstance * consuming_instance
int AddDintToMessage(const EipUint32 data, EipUint8 **const buffer)
Converts UINT32 data from host to little endian and writes it to buffer.
enum segment_type SegmentType
Segment type Enum.
ConnectionObjectConnectionType ConnectionObjectGetOToTConnectionType(const CipConnectionObject *const connection_object)
EipStatus ManageConnections(MilliSeconds elapsed_time)
Check if any of the connection timers (TransmissionTrigger or WatchdogTimeout) have timed out...
void ConnectionObjectInitializeFromMessage(const CipOctet **message, CipConnectionObject *const connection_object)
#define OPENER_TRACE_INFO(...)
CipUint connection_serial_number
void CloseUdpSocket(int socket_handle)
EipStatus TriggerConnections(unsigned int output_assembly, unsigned int input_assembly)
Trigger the production of an application triggered connection.
CipConnectionPathEpath produced_path
CipUdint originator_serial_number
EipStatus ForwardClose(CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
NetworkSegmentSubtype GetPathNetworkSegmentSubtype(const unsigned char *const cip_path)
Return the Network Segment subtype.
EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance, CipMessageRouterRequest *const message_router_request, CipMessageRouterResponse *const message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Generic implementation of the GetAttributeSingle CIP service.
EipStatus ForwardOpen(CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Check if resources for new connection available, generate ForwardOpen Reply message.
void CloseConnection(CipConnectionObject *RESTRICT connection_object)
Close the given connection.
CipInstance * GetCipInstance(const CipClass *RESTRICT const cip_class, EipUint32 instance_number)
Get a pointer to an instance.
EipUint32 sequence_number
CipUdint cip_consumed_connection_id
ConnectionObjectState ConnectionObjectGetState(const CipConnectionObject *const connection_object)
CipConnectionPathEpath configuration_path
LogicalSegmentLogicalType GetPathLogicalSegmentLogicalType(const unsigned char *const cip_path)
Gets the Logical Type of an EPath Logical Segment message.
EipStatus HandleNonNullMatchingForwardOpenRequest(CipConnectionObject *connection_object, CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response)
Handles a Non Null Matching Forward Open Request.
CipUdint o_to_t_requested_packet_interval
EipStatus AssembleForwardOpenResponse(CipConnectionObject *connection_object, CipMessageRouterResponse *message_router_response, EipUint8 general_status, EipUint16 extended_status)
Assembles the Forward Open Response.
uint8_t EipByte
EIP Data type definitions.
ConnectionTimeoutFunction connection_timeout_function
CipElectronicKey electronic_key
uint64_t transmission_trigger_timer
#define OPENER_TRACE_WARN(...)
void InitializeClass3ConnectionData(void)
Initializes the explicit connections mechanism.
unsigned int g_config_data_length
bool ElectronicKeyFormat4GetMajorRevisionCompatibility(const ElectronicKeyFormat4 *const electronic_key)
Gets the Compatibility flag from the format 4 electronic key.
This file contains the public interface of the encapsulation layer.
CipUint originator_vendor_id
EipStatus HandleNullNonMatchingForwardOpenRequest(CipConnectionObject *connection_object, CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response)
Handles a Null Non Matching Forward Open Request.
unsigned long MilliSeconds
void(* CloseSessionFunction)(const CipConnectionObject *const connection_object)
CipConnectionObject * GetConnectedObject(const EipUint32 connection_id)
Get a connected object dependent on requested ConnectionID.
CipConnectionPathEpath consumed_path
CipUdint cip_produced_connection_id
CipUint consumed_connection_path_length
EipStatus(* HandleForwardOpenRequestFunction)(CipConnectionObject *connection_object, CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response)
Function prototype for all Forward Open handle functions.
EipUint8 ParseConnectionPath(CipConnectionObject *connection_object, CipMessageRouterRequest *message_router_request, EipUint16 *extended_error)
Parse the connection path of a forward open request.
uint64_t production_inhibit_timer
EipUint32 eip_level_sequence_count_consuming
const CipDword CipEpathGetLogicalValue(const EipUint8 **message)
ElectronicKeyFormat4 * ElectronicKeyFormat4New()
Constructor for the electroic key format 4 class.
CipUint GetConnectionId(void)
Generate a new connection Id utilizing the Incarnation Id as described in the EIP specs...
EipUint32 connection_identifier
EipUint16 highest_attribute_number
EipStatus HandleReceivedConnectedData(const EipUint8 *const data, int data_length, struct sockaddr_in *from_address)
Notify the connection manager that data for a connection has been received.
EipUint16 GetIntFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT16 from *buffer and converts little endian to host.
EipStatus HandleNullMatchingForwardOpenRequest(CipConnectionObject *connection_object, CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response)
Handles a Null Matching Forward Open request.
Struct storing the CIP revision.
void GetElectronicKeyFormat4FromMessage(const CipOctet **const message, ElectronicKeyFormat4 *key)
Gets the data for an Electronic Key of format 4 from the EPath message.
ConnectionSendDataFunction connection_send_data_function
CIP Message Router Response.
ConnectionObjectTransportClassTriggerProductionTrigger ConnectionObjectGetTransportClassTriggerProductionTrigger(const CipConnectionObject *const connection_object)
void ConnectionObjectSetState(CipConnectionObject *const connection_object, const ConnectionObjectState state)
struct cip_class * cip_class
CipUint ConnectionObjectGetRequestedPacketInterval(const CipConnectionObject *const connection_object)
segment_type
Segment type Enum.
CipUint production_inhibit_time
EipUint32 g_incarnation_id
Holds the connection ID's "incarnation ID" in the upper 16 bits.
CipUint ElectronicKeyFormat4GetProductCode(const ElectronicKeyFormat4 *const electronic_key)
Gets the product code from an format 4 electronic key.
CipUsint ElectronicKeyFormat4GetMinorRevision(const ElectronicKeyFormat4 *const electronic_key)
Gets the minor revision from an format 4 electronic key.
ConnectionObjectInstanceType ConnectionObjectGetInstanceType(const CipConnectionObject *const connection_object)
EipBool8 IsConnectedOutputAssembly(const EipUint32 instance_number)
struct sockaddr_in originator_address
void InitializeIoConnectionData(void)
EipInt16 request_path_size
ConnectionManagementHandling * GetConnectionManagementEntry(const EipUint32 class_id)
uint64_t inactivity_watchdog_timer
SegmentType GetPathSegmentType(const CipOctet *const cip_path)
Gets the basic segment type of a CIP EPath.
const size_t g_kForwardOpenHeaderLength
EipStatus GetConnectionOwner(CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
uint64_t last_package_watchdog_timer
void CheckForTimedOutConnectionsAndCloseTCPConnections(const CipConnectionObject *const connection_object, CloseSessionFunction CloseSessions)
void AddNewActiveConnection(const CipConnectionObject *const connection_object)
Insert the given connection object to the list of currently active and managed connections.
#define OPENER_CIP_NUM_APPLICATION_SPECIFIC_CONNECTABLE_OBJECTS
Identity configuration of the device.
CipUsint size_of_additional_status
ConnectionObjectTransportClassTriggerTransportClass ConnectionObjectGetTransportClassTriggerTransportClass(const CipConnectionObject *const connection_object)
bool EqualConnectionTriad(const CipConnectionObject *const object1, const CipConnectionObject *const object2)
void InitializeConnectionManagerData(void)