24 #include "opener_user_conf.h"
28 #define MAX_NO_OF_TCP_SOCKETS 10
81 socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) )
92 int set_socket_option_value = 1;
95 (
char *) &set_socket_option_value,
96 sizeof(set_socket_option_value) ) == -1) {
98 "error setting socket option SO_REUSEADDR on tcp_listener\n");
104 "error setting socket to non-blocking on new socket\n");
112 == kEipInvalidSocket ) {
116 "error allocating UDP global broadcast listener socket, %d - %s\n",
126 kEipInvalidSocket ) {
130 error_code, error_message);
137 SO_REUSEADDR, (
char *) &set_socket_option_value,
138 sizeof(set_socket_option_value) ) == -1) {
140 "error setting socket option SO_REUSEADDR on udp_broadcast_listener\n");
147 "error setting socket to non-blocking on new socket\n");
153 SO_REUSEADDR, (
char *) &set_socket_option_value,
154 sizeof(set_socket_option_value) ) == -1) {
156 "error setting socket option SO_REUSEADDR on udp_unicast_listener\n");
162 "error setting socket to non-blocking on udp_unicast_listener\n");
166 struct sockaddr_in my_address = { .sin_family = AF_INET, .sin_port = htons(
167 kOpenerEthernetPort),
168 .sin_addr.s_addr = interface_configuration_
174 sizeof(
struct sockaddr) ) ) == -1 ) {
184 (
struct sockaddr *) &my_address,
185 sizeof(
struct sockaddr) ) ) == -1 ) {
195 struct sockaddr_in global_broadcast_address = { .sin_family = {AF_INET},
197 kOpenerEthernetPort),
198 .sin_addr.s_addr = htonl(
205 (
char *) &set_socket_option_value,
sizeof(
int) ) ) {
209 "error with setting broadcast receive for UDP socket: %d - %s\n",
210 error_code, error_message);
216 (
struct sockaddr *) &global_broadcast_address,
217 sizeof(
struct sockaddr) ) ) == -1 ) {
293 int new_socket = kEipInvalidSocket;
299 if (new_socket == kEipInvalidSocket) {
303 error_code, error_message);
312 "networkhandler: error on set QoS on on new socket %d: %d - %s\n",
360 if (ready_socket == kEipInvalidSocket) {
375 if (ready_socket > 0) {
431 struct sockaddr_in from_address = {0};
432 socklen_t from_address_length =
sizeof(from_address);
435 "networkhandler: unsolicited UDP message on EIP global broadcast socket\n");
441 sizeof(incoming_message),
442 0, (
struct sockaddr *) &from_address,
443 &from_address_length);
445 if (received_size <= 0) {
449 "networkhandler: error on recvfrom UDP global broadcast port: %d - %s\n",
458 const EipUint8 *receive_buffer = &incoming_message[0];
459 int remaining_bytes = 0;
472 receive_buffer += received_size - remaining_bytes;
473 received_size = remaining_bytes;
475 if (reply_length > 0) {
482 (
struct sockaddr *) &from_address,
sizeof(from_address) )
485 "networkhandler: UDP response was not fully sent\n");
488 }
while (remaining_bytes > 0);
496 struct sockaddr_in from_address = {0};
497 socklen_t from_address_length =
sizeof(from_address);
500 "networkhandler: unsolicited UDP message on EIP unicast socket\n");
506 sizeof(incoming_message),
507 0, (
struct sockaddr *) &from_address,
508 &from_address_length);
510 if (received_size <= 0) {
514 "networkhandler: error on recvfrom UDP unicast port: %d - %s\n",
523 EipUint8 *receive_buffer = &incoming_message[0];
524 int remaining_bytes = 0;
530 received_size, &remaining_bytes,
true, &outgoing_message);
532 receive_buffer += received_size - remaining_bytes;
533 received_size = remaining_bytes;
535 if (reply_length > 0) {
542 (
struct sockaddr *) &from_address,
sizeof(from_address) )
545 "networkhandler: UDP unicast response was not fully sent\n");
548 }
while (remaining_bytes > 0);
562 .destination_port = ntohs(address->sin_port),
563 .packet_length = kUpdHeaderLength + data_length,
568 memcpy(complete_message + kUpdHeaderLength, data, data_length);
573 interface_configuration_
575 address->sin_addr.s_addr) ) );
578 int sent_length = sendto( socket_handle,
579 (
char *) complete_message,
580 data_length + kUpdHeaderLength,
582 (
struct sockaddr *) address,
585 if (sent_length < 0) {
589 "networkhandler: error with sendto in sendUDPData: %d - %s\n",
596 if (sent_length != data_length + kUpdHeaderLength) {
598 "data length sent_length mismatch; probably not all data was sent in SendUdpData, sent %d of %d\n",
609 int remaining_bytes = 0;
621 long number_of_read_bytes = recv(socket, incoming_message, 4,
628 if (number_of_read_bytes == 0) {
632 "networkhandler: socket: %d - connection closed by client: %d - %s\n",
641 if (number_of_read_bytes < 0) {
654 const EipUint8 *read_buffer = &incoming_message[2];
660 "too large packet received will be ignored, will drop the data\n");
665 "Entering consumption loop, remaining data to receive: %zu\n",
667 number_of_read_bytes = recv(socket, &incoming_message[0],
670 if (number_of_read_bytes == 0)
675 "networkhandler: socket: %d - connection closed by client: %d - %s\n",
683 if (number_of_read_bytes < 0) {
695 data_size -= number_of_read_bytes;
697 data_sent = data_size;
699 }
while (0 < data_size);
704 number_of_read_bytes = recv(socket, &incoming_message[4],
707 if (0 == number_of_read_bytes)
712 "networkhandler: socket: %d - connection closed by client: %d - %s\n",
721 if (number_of_read_bytes < 0) {
734 if ( (
unsigned) number_of_read_bytes == data_size ) {
742 struct sockaddr sender_address;
743 memset( &sender_address, 0,
sizeof(sender_address) );
744 socklen_t fromlen =
sizeof(sender_address);
745 if (getpeername(socket, (
struct sockaddr *)&sender_address, &fromlen) < 0) {
757 socket, incoming_message, data_size, &remaining_bytes,
758 &sender_address, &outgoing_message);
763 if(NULL != socket_timer) {
769 if (remaining_bytes != 0) {
771 "Warning: received packet was to long: %d Bytes left!\n",
775 if (number_of_bytes_to_send > 0) {
778 data_sent = send(socket, (
char *) outgoing_message.
message_buffer,
785 if (data_sent != number_of_bytes_to_send) {
809 struct sockaddr_in *socket_data,
811 struct sockaddr_in peer_address;
812 int new_socket = kEipInvalidSocket;
814 socklen_t peer_address_length =
sizeof(
struct sockaddr_in);
817 new_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
821 new_socket = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
824 if (new_socket == kEipInvalidSocket) {
836 "error setting socket to non-blocking on new socket\n");
846 "networkhandler: error on set QoS on socket on new socket: %d - %s\n",
856 int option_value = 1;
857 if (setsockopt( new_socket, SOL_SOCKET, SO_REUSEADDR,
858 (
char *) &option_value,
859 sizeof(option_value) ) == -1) {
861 "error setting socket option SO_REUSEADDR on consuming udp socket\n");
867 if ( ( bind( new_socket, (
struct sockaddr *) socket_data,
868 sizeof(
struct sockaddr) ) ) == -1 ) {
881 int option_value = 1;
882 setsockopt( new_socket, SOL_SOCKET, SO_REUSEADDR,
883 (
char *) &option_value,
884 sizeof(option_value) );
886 if (socket_data->sin_addr.s_addr
889 if ( setsockopt(new_socket, IPPROTO_IP, IP_MULTICAST_TTL,
895 "networkhandler: could not set the TTL to: %d, error: %d - %s\n",
905 || (0 == socket_data->sin_addr.s_addr) ) {
908 (
struct sockaddr *) &peer_address, &peer_address_length)
919 socket_data->sin_addr.s_addr = peer_address.sin_addr.s_addr;
940 while (NULL != iterator) {
942 iterator = iterator->
next;
944 if ( (kEipInvalidSocket
945 != current_connection_object->
socket[
949 current_connection_object->
socket[
952 struct sockaddr_in from_address = {0};
953 socklen_t from_address_length =
sizeof(from_address);
956 int received_size = recvfrom(
958 incoming_message,
sizeof(incoming_message), 0,
959 (
struct sockaddr *) &from_address, &from_address_length);
960 if (0 == received_size) {
964 "networkhandler: socket: %d - connection closed by client: %d - %s\n",
965 current_connection_object->
socket[
971 current_connection_object);
975 if (0 > received_size) {
986 current_connection_object);
991 received_size, &from_address);
1001 if (kEipInvalidSocket != socket_handle) {
1012 if ( (socket1 > socket2) && (socket1 > socket3) && (socket1 > socket4) ) {
1016 if ( (socket2 > socket1) && (socket2 > socket3) && (socket2 > socket4) ) {
1020 if ( (socket3 > socket1) && (socket3 > socket2) && (socket3 > socket4) ) {
1037 if(NULL != socket_timer) {
1041 if ( diff_milliseconds >=
1044 size_t encapsulation_session_handle =
MilliSeconds GetMilliSeconds(void)
This function shall return the current time in milliseconds relative to epoch, and shall be implement...
void CloseSocketPlatform(int socket_handle)
Platform dependent code to close a socket.
#define OPENER_NUMBER_OF_SUPPORTED_SESSIONS
Number of sessions that can be handled at the same time.
void SocketTimerArrayInitialize(SocketTimer *const array_of_socket_timers, const size_t array_length)
Initializes an array of Socket Timer entries.
EipStatus NetworkHandlerProcessOnce(void)
Tracing infrastructure for OpENer.
MilliSeconds g_actual_time
MilliSeconds SocketTimerGetLastUpdate(SocketTimer *const socket_timer)
Gets time stamp of the last update.
uint16_t UDPHeaderCalculateChecksum(const void *udp_packet, const size_t udp_packet_length, const in_addr_t source_addr, const in_addr_t destination_addr)
Calculates the checksum based on the set UDP packet data and pseudo IP header.
EipStatus SendUdpData(struct sockaddr_in *address, 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.
EipStatus NetworkHandlerFinish(void)
void UDPHeaderSetChecksum(UDPHeader *const header, const uint16_t checksum)
Sets checksum field.
DoublyLinkedListNode * first
This file includes the prototypes for error resolution functions like strerror_r or WSAGetLastError...
void SocketTimerClear(SocketTimer *const socket_timer)
Clears a Socket Timer entry.
CipOctet message_buffer[PC_OPENER_ETHERNET_BUFFER_SIZE]
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 UDPHeaderGenerate(const UDPHeader *header, char *message)
Generate the UDP header in the message according to the header.
void CheckAndHandleConsumingUdpSockets(void)
check if on one of the UDP consuming sockets data has been received and if yes handle it correctly ...
#define OPENER_ASSERT(assertion)
#define PC_OPENER_ETHERNET_BUFFER_SIZE
The number of bytes used for the Ethernet message buffer on the pc port. For different platforms it m...
UdpCommuncationDirection
Communication direction of an UDP socket; consuming is receiver, producing is sender.
int udp_global_broadcast_listener
#define OPENER_TRACE_ERR(...)
SocketTimer g_timestamps[OPENER_NUMBER_OF_SUPPORTED_SESSIONS]
void InitializeENIPMessage(ENIPMessage *const message)
MulticastAddressConfiguration g_multicast_configuration
#9 The multicast configuration for this device
Public interface of the QoS Object.
EipStatus HandleDataOnTcpSocket(int socket)
Handles data on an established TCP connection, processed connection is given by socket.
struct timeval g_time_value
ConnectionCloseFunction connection_close_function
void CheckAndHandleUdpUnicastSocket(void)
Checks and processes request received via the UDP unicast socket, currently the implementation is por...
void CheckEncapsulationInactivity(int socket_handle)
int SetSocketToNonBlocking(int socket_handle)
uint8_t CipOctet
Data types as defined in the CIP Specification Vol 1 Appendix C.
DoublyLinkedListNode * next
void CloseClass3ConnectionBasedOnSession(size_t encapsulation_session_handle)
EipStatus
EIP stack status enum.
EipStatus ManageConnections(MilliSeconds elapsed_time)
Check if any of the connection timers (TransmissionTrigger or WatchdogTimeout) have timed out...
#define OPENER_TRACE_INFO(...)
void CloseUdpSocket(int socket_handle)
#define MAX_NO_OF_TCP_SOCKETS
CipUint g_encapsulation_inactivity_timeout
#13 Number of seconds of inactivity before TCP connection is closed
SocketTimer * SocketTimerArrayGetSocketTimer(SocketTimer *const array_of_socket_timers, const size_t array_length, const int socket)
Get the Socket Timer entry with the spezified socket value.
int highest_socket_handle
#define ENCAPSULATION_HEADER_LENGTH
SocketTimer * SocketTimerArrayGetEmptySocketTimer(SocketTimer *const array_of_socket_timers, const size_t array_length)
Get an empty Socket Timer entry.
void CheckAndHandleTcpListenerSocket(void)
handle any connection request coming in the TCP server socket.
int SetQosOnSocket(int socket, CipUsint qos_value)
EipStatus NetworkHandlerInitializePlatform(void)
Executes platform dependent network handler initialization code.
#define OPENER_TRACE_STATE(...)
void RemoveSocketTimerFromList(const int socket_handle)
void RemoveSession(const int socket)
NetworkStatus g_network_status
Includes a basic set of operations for UDP header creation and checksum calculation.
CipUsint GetPriorityForSocket(ConnectionObjectPriority priority)
Initializing the data structures of the TCP/IP interface object.
void CheckAndHandleUdpGlobalBroadcastSocket(void)
Checks and handles incoming messages via UDP broadcast.
Public interface of the TCP/IP Interface Object.
Struct for saving TCP/IP interface information.
DoublyLinkedList connection_list
int g_current_active_tcp_socket
This variable holds the TCP socket the received to last explicit message. It is needed for opening po...
#define OPENER_TRACE_WARN(...)
This file contains the public interface of the encapsulation layer.
MilliSeconds elapsed_time
unsigned long MilliSeconds
int CreateUdpSocket(UdpCommuncationDirection communication_direction, struct sockaddr_in *socket_data, CipUsint qos_for_socket)
create a new UDP socket for the connection manager
size_t GetSessionFromSocket(const int socket_handle)
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.
void FreeErrorMessage(char *error_message)
Frees the space of the error message generated by GetErrorMessage(int)
size_t used_message_length
EipStatus NetworkHandlerInitialize(void)
Initializes the network handler, shall be implemented by a port-specific networkhandler.
void CloseSocket(const int socket_handle)
Close the given socket and clean up the stack.
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.
CipTcpIpNetworkInterfaceConfiguration interface_configuration_
void CloseTcpSocket(int socket_handle)
EipUint8 g_time_to_live_value
#8 the time to live value to be used for multi-cast connections
#define OPENER_SOCKET_WOULD_BLOCK
int GetMaxSocket(int socket1, int socket2, int socket3, int socket4)
Returns the socket with the highest id.
CipUdint starting_multicast_address
EipBool8 CheckSocketSet(int socket)
check if the given socket is set in the read set