From dc4fbd76adbd63ce153f8fd490f6adcfda9cf4a2 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Mon, 23 Jul 2018 20:56:28 +0200 Subject: [PATCH] - unification of HAL with lib60870 --- src/hal/inc/hal_socket.h | 50 +++++++++++++++++++++++---- src/hal/inc/hal_thread.h | 4 +++ src/hal/inc/hal_time.h | 7 +++- src/hal/socket/bsd/socket_bsd.c | 48 ++++++++++++++++++++++++-- src/hal/socket/linux/socket_linux.c | 52 ++++++++++++++++++++++++++--- src/hal/socket/win32/socket_win32.c | 48 ++++++++++++++++++++++++++ 6 files changed, 194 insertions(+), 15 deletions(-) diff --git a/src/hal/inc/hal_socket.h b/src/hal/inc/hal_socket.h index 3fddd3f2..41ec55de 100644 --- a/src/hal/inc/hal_socket.h +++ b/src/hal/inc/hal_socket.h @@ -1,7 +1,7 @@ /* * socket_hal.h * - * Copyright 2013, 2014 Michael Zillgith + * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. * @@ -27,11 +27,21 @@ #include #include +/** + * \file hal_socket.h + * \brief Abstraction layer TCP/IP sockets + * Has to be implemented for CS 104 TCP/IP. + */ + #ifdef __cplusplus extern "C" { #endif -/*! \addtogroup hal Platform (Hardware/OS) abstraction layer +/*! \defgroup hal Platform (Hardware/OS) abstraction layer + * + * Platform abstraction layer. These functions have to be implemented when the library is + * to be ported to new platforms. It might not be required to implement all interfaces + * depending on the required library features. * * @{ */ @@ -40,7 +50,7 @@ extern "C" { * @defgroup HAL_SOCKET Interface to the TCP/IP stack (abstract socket layer) * * Thread and Socket abstraction layer. This functions have to be implemented to - * port libIEC61850 to a new hardware/OS platform. + * port lib60870 to a new hardware/OS platform when TCP/IP is required. * * @{ */ @@ -63,7 +73,13 @@ HandleSet Handleset_new(void); /** - * \brief add a socket to an existing handle set + * \brief Reset the handle set for reuse + */ +void +Handleset_reset(HandleSet self); + +/** + * \brief add a soecket to an existing handle set * * \param self the HandleSet instance * \param sock the socket to add @@ -75,7 +91,10 @@ Handleset_addSocket(HandleSet self, const Socket sock); * \brief wait for a socket to become ready * * This function is corresponding to the BSD socket select function. - * The function will return after \p timeoutMs ms if no data is pending. + * It returns the number of sockets on which data is pending or 0 if no data is pending + * on any of the monitored connections. The function will return after "timeout" ms if no + * data is pending. + * The function shall return -1 if a socket error occures. * * \param self the HandleSet instance * \param timeout in milliseconds (ms) @@ -188,7 +207,7 @@ Socket_setConnectTimeout(Socket self, uint32_t timeoutInMs); * \param address the IP address or hostname as C string * \param port the TCP port of the application to connect to * - * \return a new client socket instance. + * \return true if the connection was established successfully, false otherwise */ bool Socket_connect(Socket self, const char* address, int port); @@ -229,7 +248,7 @@ Socket_write(Socket self, uint8_t* buf, int size); * * The peer address has to be returned as * - * Implementation of this function is MANDATORY + * Implementation of this function is MANDATORY (libiec61850) * * \param self the client, connection or server socket instance * @@ -238,6 +257,23 @@ Socket_write(Socket self, uint8_t* buf, int size); char* Socket_getPeerAddress(Socket self); +/** + * \brief Get the address of the peer application (IP address and port number) + * + * The peer address has to be returned as + * + * Implementation of this function is MANDATORY (lib60870) + * + * \param self the client, connection or server socket instance + * \param peerAddressString a string to store the peer address (the string should have space + * for at least 60 characters) + * + * \return the IP address and port number as strings separated by the ':' character. If the + * address is an IPv6 address the IP part is encapsulated in square brackets. + */ +char* +Socket_getPeerAddressStatic(Socket self, char* peerAddressString); + /** * \brief destroy a socket (close the socket if a connection is established) * diff --git a/src/hal/inc/hal_thread.h b/src/hal/inc/hal_thread.h index 7d719f95..7dbb390a 100644 --- a/src/hal/inc/hal_thread.h +++ b/src/hal/inc/hal_thread.h @@ -32,6 +32,10 @@ extern "C" { #endif +/** + * \file hal_thread.h + * \brief Abstraction layer for threading and synchronization + */ /*! \addtogroup hal * diff --git a/src/hal/inc/hal_time.h b/src/hal/inc/hal_time.h index 50fcf505..12164901 100644 --- a/src/hal/inc/hal_time.h +++ b/src/hal/inc/hal_time.h @@ -28,6 +28,10 @@ extern "C" { #endif +/** + * \file hal_time.h + * \brief Abstraction layer for system time access + */ /*! \addtogroup hal * @@ -48,7 +52,8 @@ extern "C" { * * \return the system time with millisecond resolution. */ -uint64_t Hal_getTimeInMs(void); +uint64_t +Hal_getTimeInMs(void); /*! @} */ diff --git a/src/hal/socket/bsd/socket_bsd.c b/src/hal/socket/bsd/socket_bsd.c index 800ee426..6207c71a 100644 --- a/src/hal/socket/bsd/socket_bsd.c +++ b/src/hal/socket/bsd/socket_bsd.c @@ -70,6 +70,14 @@ Handleset_new(void) return result; } +void +Handleset_reset(HandleSet self) +{ + FD_ZERO(&self->handles); + self->maxHandle = -1; +} + + void Handleset_addSocket(HandleSet self, const Socket sock) { @@ -105,6 +113,7 @@ Handleset_destroy(HandleSet self) GLOBAL_FREEMEM(self); } +#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1) static void activateKeepAlive(int sd) { @@ -127,6 +136,7 @@ activateKeepAlive(int sd) #endif /* SO_KEEPALIVE */ } +#endif /* (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1) */ static bool prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr) @@ -348,11 +358,45 @@ Socket_getPeerAddress(Socket self) return clientConnection; } +char* +Socket_getPeerAddressStatic(Socket self, char* peerAddressString) +{ + struct sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); + + char addrString[INET6_ADDRSTRLEN + 7]; + int port; + + bool isIPv6; + + if (addr.ss_family == AF_INET) { + struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr; + port = ntohs(ipv4Addr->sin_port); + inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN); + isIPv6 = false; + } + else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr; + port = ntohs(ipv6Addr->sin6_port); + inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN); + isIPv6 = true; + } + else + return NULL ; + + if (isIPv6) + sprintf(peerAddressString, "[%s]:%i", addrString, port); + else + sprintf(peerAddressString, "%s:%i", addrString, port); + + return peerAddressString; +} + int Socket_read(Socket self, uint8_t* buf, int size) { - assert(self != NULL); - if (self->fd == -1) return -1; diff --git a/src/hal/socket/linux/socket_linux.c b/src/hal/socket/linux/socket_linux.c index cbf6c25d..e1761d47 100644 --- a/src/hal/socket/linux/socket_linux.c +++ b/src/hal/socket/linux/socket_linux.c @@ -24,6 +24,7 @@ #include "hal_socket.h" #include #include +#include #include #include #include @@ -70,6 +71,13 @@ Handleset_new(void) return result; } +void +Handleset_reset(HandleSet self) +{ + FD_ZERO(&self->handles); + self->maxHandle = -1; +} + void Handleset_addSocket(HandleSet self, const Socket sock) { @@ -197,7 +205,7 @@ TcpServerSocket_create(const char* address, int port) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optionReuseAddr, sizeof(int)); if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) { - serverSocket = GLOBAL_MALLOC(sizeof(struct sServerSocket)); + serverSocket = (ServerSocket) GLOBAL_MALLOC(sizeof(struct sServerSocket)); serverSocket->fd = fd; serverSocket->backLog = 0; @@ -281,7 +289,7 @@ ServerSocket_destroy(ServerSocket self) Socket TcpSocket_create() { - Socket self = GLOBAL_MALLOC(sizeof(struct sSocket)); + Socket self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket)); self->fd = -1; self->connectTimeout = 5000; @@ -374,7 +382,7 @@ Socket_getPeerAddress(Socket self) else return NULL ; - char* clientConnection = GLOBAL_MALLOC(strlen(addrString) + 9); + char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9); if (isIPv6) @@ -385,11 +393,45 @@ Socket_getPeerAddress(Socket self) return clientConnection; } +char* +Socket_getPeerAddressStatic(Socket self, char* peerAddressString) +{ + struct sockaddr_storage addr; + socklen_t addrLen = sizeof(addr); + + getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); + + char addrString[INET6_ADDRSTRLEN + 7]; + int port; + + bool isIPv6; + + if (addr.ss_family == AF_INET) { + struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr; + port = ntohs(ipv4Addr->sin_port); + inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN); + isIPv6 = false; + } + else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr; + port = ntohs(ipv6Addr->sin6_port); + inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN); + isIPv6 = true; + } + else + return NULL ; + + if (isIPv6) + sprintf(peerAddressString, "[%s]:%i", addrString, port); + else + sprintf(peerAddressString, "%s:%i", addrString, port); + + return peerAddressString; +} + int Socket_read(Socket self, uint8_t* buf, int size) { - assert(self != NULL); - if (self->fd == -1) return -1; diff --git a/src/hal/socket/win32/socket_win32.c b/src/hal/socket/win32/socket_win32.c index 777d17c8..b699816e 100644 --- a/src/hal/socket/win32/socket_win32.c +++ b/src/hal/socket/win32/socket_win32.c @@ -70,6 +70,13 @@ Handleset_new(void) return result; } +void +Handleset_reset(HandleSet self) +{ + FD_ZERO(&self->handles); + self->maxHandle = INVALID_SOCKET; +} + void Handleset_addSocket(HandleSet self, const Socket sock) { @@ -396,6 +403,47 @@ Socket_getPeerAddress(Socket self) return clientConnection; } +char* +Socket_getPeerAddressStatic(Socket self, char* peerAddressString) +{ + struct sockaddr_storage addr; + int addrLen = sizeof(addr); + + getpeername(self->fd, (struct sockaddr*) &addr, &addrLen); + + char addrString[INET6_ADDRSTRLEN + 7]; + int addrStringLen = INET6_ADDRSTRLEN + 7; + int port; + + bool isIPv6; + + if (addr.ss_family == AF_INET) { + struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr; + port = ntohs(ipv4Addr->sin_port); + ipv4Addr->sin_port = 0; + WSAAddressToString((LPSOCKADDR) ipv4Addr, sizeof(struct sockaddr_storage), NULL, + (LPSTR) addrString, (LPDWORD) & addrStringLen); + isIPv6 = false; + } + else if (addr.ss_family == AF_INET6) { + struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr; + port = ntohs(ipv6Addr->sin6_port); + ipv6Addr->sin6_port = 0; + WSAAddressToString((LPSOCKADDR) ipv6Addr, sizeof(struct sockaddr_storage), NULL, + (LPSTR) addrString, (LPDWORD) & addrStringLen); + isIPv6 = true; + } + else + return NULL; + + if (isIPv6) + sprintf(peerAddressString, "[%s]:%i", addrString, port); + else + sprintf(peerAddressString, "%s:%i", addrString, port); + + return peerAddressString; +} + int Socket_read(Socket self, uint8_t* buf, int size) {