68 #define ENCAP_NUMBER_OF_SUPPORTED_DELAYED_ENCAP_MESSAGES 2
70 #define ENCAP_MAX_DELAYED_ENCAP_MESSAGE_SIZE ( ENCAPSULATION_HEADER_LENGTH + \
71 39 + sizeof(OPENER_DEVICE_NAME) )
79 struct sockaddr_in receiver;
97 const struct sockaddr_in *
const from_address,
107 const struct sockaddr *
const originator_address,
138 g_delayed_encapsulation_messages[i].
socket = kEipInvalidSocket;
156 int *remaining_bytes,
157 struct sockaddr *originator_address,
166 &encapsulation_data);
170 if (*remaining_bytes >= 0)
211 &encapsulation_data, outgoing_message);
217 &encapsulation_data, originator_address, outgoing_message);
223 &encapsulation_data, originator_address, outgoing_message);
238 const struct sockaddr_in *from_address,
240 const size_t buffer_length,
241 int *number_of_remaining_bytes,
251 &encapsulation_data);
255 if (*number_of_remaining_bytes >= 0)
270 if (unicast ==
true) {
297 encapsulation_data.
status =
318 const size_t command_specific_data_length,
319 const size_t session_handle,
326 command_specific_data_length,
331 encapsulation_protocol_status,
350 const size_t kListServicesCommandSpecificDataLength =
sizeof(
CipUint)
352 g_interface_information);
354 kListServicesCommandSpecificDataLength,
386 const size_t kListInterfacesCommandSpecificDataLength =
sizeof(
CipUint)
388 g_interface_information);
390 kListInterfacesCommandSpecificDataLength,
406 const struct sockaddr_in *
const from_address,
413 if (kEipInvalidSocket == g_delayed_encapsulation_messages[i].socket) {
414 delayed_message_buffer = &(g_delayed_encapsulation_messages[i]);
419 if (NULL != delayed_message_buffer) {
420 delayed_message_buffer->
socket = socket;
421 memcpy( (&delayed_message_buffer->
receiver), from_address,
422 sizeof(
struct sockaddr_in) );
425 delayed_message_buffer);
427 memcpy(&(delayed_message_buffer->
message[0]),
432 receive_data, outgoing_message);
441 const CipUint kEncapsulationCommandListIdentityCommandSpecificLength =
448 const CipUint kEncapsulationCommandListIdentityLength =
449 kEncapsulationCommandListIdentityCommandSpecificLength +
sizeof(
CipUint) +
454 kEncapsulationCommandListIdentityLength,
463 const CipUint kItemIDCipIdentity = 0x0C;
469 kEncapsulationCommandListIdentityCommandSpecificLength,
477 htons(kOpenerEthernetPort), interface_configuration_.
ip_address,
500 (
unsigned char) product_name_.
length;
519 (
const EipUint8 **
const ) &buffer_start);
521 if (0 == maximum_delay_time) {
526 delayed_message_buffer->
time_out = (maximum_delay_time * rand() ) / RAND_MAX;
531 const size_t session_handle,
536 const size_t kListInterfacesCommandSpecificDataLength =
sizeof(
CipUint)
538 assert(kListInterfacesCommandSpecificDataLength == 4);
540 kListInterfacesCommandSpecificDataLength,
542 encapsulation_protocol_status,
559 int session_index = 0;
560 size_t session_handle = 0;
572 if ( (0 < protocol_version)
574 && (0 == option_flag) ) {
580 "Error: A session is already registered at socket %d\n",
582 session_handle = i + 1;
593 encapsulation_protocol_status =
598 OPENER_NUMBER_OF_SUPPORTED_SESSIONS);
602 session_handle = session_index + 1;
612 encapsulation_protocol_status,
654 const struct sockaddr *
const originator_address,
674 return_value = send_size;
700 const struct sockaddr *
const originator_address,
719 return_value = send_size;
755 for (
size_t session_index = 0;
759 return session_index;
775 int receive_buffer_length,
805 if (kEipInvalidSocket
860 if (kEipInvalidSocket != g_delayed_encapsulation_messages[i].socket) {
861 g_delayed_encapsulation_messages[i].
time_out -= elapsed_time;
862 if (0 >= g_delayed_encapsulation_messages[i].time_out) {
864 SendUdpData(&(g_delayed_encapsulation_messages[i].receiver),
865 g_delayed_encapsulation_messages[i].socket,
866 &(g_delayed_encapsulation_messages[i].message[0]),
867 g_delayed_encapsulation_messages[i].message_size);
868 g_delayed_encapsulation_messages[i].
socket = kEipInvalidSocket;
878 struct sockaddr_in encapsulation_session_addr = { 0 };
879 socklen_t addrlength =
sizeof(encapsulation_session_addr);
881 &encapsulation_session_addr, &addrlength) < 0) {
885 "encap.c: error on getting peer name on closing session: %d - %s\n",
886 error_code, error_message);
889 if (encapsulation_session_addr.sin_addr.s_addr
908 while (NULL != node) {
914 == encapsulation_session_handle) {
size_t associated_encapsulation_session
#define OPENER_NUMBER_OF_SUPPORTED_SESSIONS
Number of sessions that can be handled at the same time.
Tracing infrastructure for OpENer.
MilliSeconds g_actual_time
void CloseSession(int socket)
Inform the encapsulation layer that the remote host has closed the connection.
EipStatus SendUdpData(struct sockaddr_in *socket_data, int socket_handle, EipUint8 *data, EipUint16 data_length)
Create a producing or consuming UDP socket.
Data structure to store last usage times for sockets.
char * GetErrorMessage(int error_number)
Returns a human readable message for the given error number.
void EncapsulateListIdentityResponseMessage(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
Delayed Encapsulation Message structure.
DoublyLinkedListNode * first
This file includes the prototypes for error resolution functions like strerror_r or WSAGetLastError...
void CloseEncapsulationSessionBySockAddr(const CipConnectionObject *const connection_object)
const EipUint8 * current_communication_buffer_position
int HandleReceivedExplictUdpData(const int socket, const struct sockaddr_in *from_address, const EipUint8 *buffer, const size_t buffer_length, int *number_of_remaining_bytes, bool unicast, ENIPMessage *const outgoing_message)
Notify the encapsulation layer that an explicit message has been received via UDP.
void HandleReceivedListServicesCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
generate reply with "Communications Services" + compatibility Flags.
const int kSenderContextSize
const int kListIdentityDefaultDelayTime
void HandleReceivedListInterfacesCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
EipStatus HandleReceivedUnregisterSessionCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
EipUint32 GetDintFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT32 from *buffer and converts little endian to host.
CipOctet * current_message_position
Responsible for Endianess conversion.
#define OPENER_TRACE_ERR(...)
EipByte message[ENCAP_MAX_DELAYED_ENCAP_MESSAGE_SIZE]
SocketTimer g_timestamps[OPENER_NUMBER_OF_SUPPORTED_SESSIONS]
void InitializeENIPMessage(ENIPMessage *const message)
void GenerateEncapsulationHeader(const EncapsulationData *const receive_data, const size_t command_specific_data_length, const size_t session_handle, const EncapsulationProtocolErrorCode encapsulation_protocol_status, ENIPMessage *const outgoing_message)
void ManageEncapsulationMessages(const MilliSeconds elapsed_time)
Handle delayed encapsulation message responses.
const int kListIdentityMinimumDelayTime
CipShortString product_name_
void EncapsulateRegisterSessionCommandResponseMessage(const EncapsulationData *const receive_data, const size_t session_handle, const EncapsulationProtocolErrorCode encapsulation_protocol_status, ENIPMessage *const outgoing_message)
EncapsulationCommand
definition of known encapsulation commands
EipStatus HandleReceivedSendUnitDataCommand(const EncapsulationData *const receive_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
Call Connection Manager.
EncapsulationProtocolErrorCode
definition of status codes in encapsulation protocol All other codes are either legacy codes...
DelayedEncapsulationMessage g_delayed_encapsulation_messages[ENCAP_NUMBER_OF_SUPPORTED_DELAYED_ENCAP_MESSAGES]
ConnectionCloseFunction connection_close_function
void DetermineDelayTime(const EipByte *const buffer_start, DelayedEncapsulationMessage *const delayed_message_buffer)
void HandleReceivedListIdentityCommandTcp(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
uint8_t CipOctet
Data types as defined in the CIP Specification Vol 1 Appendix C.
DoublyLinkedListNode * next
int AddIntToMessage(const EipUint16 data, EipUint8 **const buffer)
converts UINT16 data from host to little endian an writes it to buffer.
void CloseClass3ConnectionBasedOnSession(size_t encapsulation_session_handle)
EipStatus
EIP stack status enum.
void CloseSessionBySessionHandle(const CipConnectionObject *const connection_object)
EipStatus HandleReceivedInvalidCommand(const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
int AddDintToMessage(const EipUint32 data, EipUint8 **const buffer)
Converts UINT32 data from host to little endian and writes it to buffer.
void HandleReceivedListIdentityCommandUdp(const int socket, const struct sockaddr_in *const from_address, const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
#define OPENER_TRACE_INFO(...)
void SkipEncapsulationHeader(ENIPMessage *const outgoing_message)
int MoveMessageNOctets(const int amount_of_bytes_moved, const CipOctet **message_runner)
void EncapsulationShutDown(void)
Shutdown the encapsulation layer.
int NotifyConnectedCommonPacketFormat(const EncapsulationData *const received_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
CipOctet sender_context[8]
const int kEncapsulationHeaderSessionHandlePosition
#define ENCAPSULATION_HEADER_LENGTH
SocketTimer * SocketTimerArrayGetEmptySocketTimer(SocketTimer *const array_of_socket_timers, const size_t array_length)
Get an empty Socket Timer entry.
SessionStatus CheckRegisteredSessions(const EncapsulationData *const receive_data)
Check if received package belongs to registered session.
void RemoveSession(const int socket)
#define ENCAP_MAX_DELAYED_ENCAP_MESSAGE_SIZE
const int kSupportedProtocolVersion
Struct for saving TCP/IP interface information.
EncapsulationInterfaceInformation g_interface_information
DoublyLinkedList connection_list
uint8_t EipByte
EIP Data type definitions.
EipStatus HandleReceivedSendRequestResponseDataCommand(const EncapsulationData *const receive_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
Call UCMM or Message Router if UCMM not implemented.
int g_registered_sessions[OPENER_NUMBER_OF_SUPPORTED_SESSIONS]
void EncapsulationInit(void)
Initialize the encapsulation layer.
struct sockaddr_in receiver
This file contains the public interface of the encapsulation layer.
unsigned long MilliSeconds
CapabilityFlags
definition of capability flags
EipInt16 CreateEncapsulationStructure(const EipUint8 *receive_buffer, int receive_buffer_length, EncapsulationData *const encapsulation_data)
copy data from pa_buf in little endian to host in structure.
void HandleReceivedRegisterSessionCommand(int socket, const EncapsulationData *const receive_data, ENIPMessage *const outgoing_message)
#define ENCAP_NUMBER_OF_SUPPORTED_DELAYED_ENCAP_MESSAGES
size_t GetSessionFromSocket(const int socket_handle)
const EipUint8 * communication_buffer_start
EipUint16 GetIntFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT16 from *buffer and converts little endian to host.
Struct storing the CIP revision.
void FreeErrorMessage(char *error_message)
Frees the space of the error message generated by GetErrorMessage(int)
size_t used_message_length
const int kEncapsulationHeaderOptionsFlag
int EncapsulateIpAddress(EipUint16 port, EipUint32 address, EipByte **communication_buffer)
Encapsulate the sockaddr information as necessary for the Common Packet Format data items...
void DetermineEndianess()
Detects Endianess of the platform and sets global g_nOpENerPlatformEndianess variable accordingly...
void SocketTimerSetSocket(SocketTimer *const socket_timer, const int socket)
Sets socket of a Socket Timer.
CipTcpIpNetworkInterfaceConfiguration interface_configuration_
struct sockaddr_in originator_address
int GetSocketErrorNumber()
Gets the error number or equivalent.
void SocketTimerSetLastUpdate(SocketTimer *const socket_timer, const MilliSeconds actual_time)
Sets time stamp entry of the Socket Timer.
int HandleReceivedExplictTcpData(int socket, EipUint8 *buffer, size_t length, int *remaining_bytes, struct sockaddr *originator_address, ENIPMessage *const outgoing_message)
Notify the encapsulation layer that an explicit message has been received via TCP.
int GetFreeSessionIndex(void)
search for available sessions an return index.
int NotifyCommonPacketFormat(EncapsulationData *const received_data, const struct sockaddr *const originator_address, ENIPMessage *const outgoing_message)
void CloseTcpSocket(int socket_handle)
ConnectionObjectTransportClassTriggerTransportClass ConnectionObjectGetTransportClassTriggerTransportClass(const CipConnectionObject *const connection_object)