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