- added Socket_activateTcpKeepAlive function

pull/72/head
Michael Zillgith 7 years ago
parent 02cda48128
commit 0b51d6841a

@ -126,15 +126,8 @@ set(WITH_MBEDTLS 1)
endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0) endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0)
if(WITH_MBEDTLS) if(WITH_MBEDTLS)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/tls/mbedtls
${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0/include
)
file(GLOB tls_SRCS ${CMAKE_CURRENT_LIST_DIR}/third_party/mbedtls/mbedtls-2.6.0/library/*.c)
add_definitions(-DCONFIG_MMS_SUPPORT_TLS=1) add_definitions(-DCONFIG_MMS_SUPPORT_TLS=1)
add_definitions(-DMBEDTLS_CONFIG_FILE="mbedtls_config.h")
endif(WITH_MBEDTLS) endif(WITH_MBEDTLS)

@ -13,6 +13,14 @@ set(LIBHAL_VERSION_MAJOR "2")
set(LIBHAL_VERSION_MINOR "0") set(LIBHAL_VERSION_MINOR "0")
set(LIBHAL_VERSION_PATCH "0") set(LIBHAL_VERSION_PATCH "0")
# feature checks
include(CheckLibraryExists)
check_library_exists(rt clock_gettime "time.h" CONFIG_SYSTEM_HAS_CLOCK_GETTIME)
# check if we are on a little or a big endian
include (TestBigEndian)
test_big_endian(PLATFORM_IS_BIGENDIAN)
if(WIN32) if(WIN32)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib")

@ -31,7 +31,6 @@
#include <unistd.h> #include <unistd.h>
#include "hal_filesystem.h" #include "hal_filesystem.h"
#include "stack_config.h"
#include "lib_memory.h" #include "lib_memory.h"
struct sDirectoryHandle { struct sDirectoryHandle {

@ -32,7 +32,6 @@
#include "hal_filesystem.h" #include "hal_filesystem.h"
#include "platform_endian.h" #include "platform_endian.h"
#include "stack_config.h"
#include "lib_memory.h" #include "lib_memory.h"
#include <malloc.h> #include <malloc.h>

@ -147,9 +147,21 @@ ServerSocket_listen(ServerSocket self);
Socket Socket
ServerSocket_accept(ServerSocket self); ServerSocket_accept(ServerSocket self);
/**
* \brief active TCP keep alive for socket and set keep alive parameters
*
* NOTE: implementation is mandatory for IEC 61850 MMS
*
* \param self server socket instance
* \param idleTime time (in s) between last received message and first keep alive message
* \param interval time (in s) between subsequent keep alive messages if no ACK received
* \param count number of not missing keep alive ACKs until socket is considered dead
*/
void
Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count);
/** /**
* \brief set the maximum number of pending connection in the queue * \brief set the maximum number of pending connections in the queue
* *
* Implementation of this function is OPTIONAL. * Implementation of this function is OPTIONAL.
* *

@ -28,6 +28,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdint.h>
/** /**
* \file hal_time.h * \file hal_time.h
* \brief Abstraction layer for system time access * \brief Abstraction layer for system time access

@ -1,7 +1,7 @@
/* /*
* endian.h * platform_endian.h
* *
* Copyright 2013 Michael Zillgith * Copyright 2013-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -24,8 +24,6 @@
#ifndef ENDIAN_H_ #ifndef ENDIAN_H_
#define ENDIAN_H_ #define ENDIAN_H_
#include "stack_config.h"
#ifndef PLATFORM_IS_BIGENDIAN #ifndef PLATFORM_IS_BIGENDIAN
#ifdef __GNUC__ #ifdef __GNUC__
#ifdef __BYTE_ORDER__ #ifdef __BYTE_ORDER__

@ -1,7 +1,8 @@
/* /*
* socket_bsd.c * socket_bsd.c
* *
* Copyright 2013, 2014 Michael Zillgith, contributions by Michael Clausen (School of engineering Valais). * Copyright 2013-2018 Michael Zillgith
* contributions by Michael Clausen (School of engineering Valais).
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -36,8 +37,7 @@
#include <netinet/tcp.h> // required for TCP keepalive #include <netinet/tcp.h> // required for TCP keepalive
#include "hal_thread.h" #include "hal_thread.h"
#include "lib_memory.h"
#include "libiec61850_platform_includes.h"
#ifndef DEBUG_SOCKET #ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0 #define DEBUG_SOCKET 0
@ -113,30 +113,28 @@ Handleset_destroy(HandleSet self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1) void
static void Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
activateKeepAlive(int sd)
{ {
#if defined SO_KEEPALIVE #if defined SO_KEEPALIVE
int optval; int optval;
socklen_t optlen = sizeof(optval); socklen_t optlen = sizeof(optval);
optval = CONFIG_TCP_KEEPALIVE_IDLE; optval = idleTime;
setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
optval = 1; optval = 1;
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &optval, optlen); setsockopt(self->fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, optlen);
#if defined TCP_KEEPCNT #if defined TCP_KEEPCNT
optval = CONFIG_TCP_KEEPALIVE_INTERVAL; optval = interval;
setsockopt(sd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);
optval = CONFIG_TCP_KEEPALIVE_CNT; optval = count;
setsockopt(sd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen); setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);
#endif /* TCP_KEEPCNT */ #endif /* TCP_KEEPCNT */
#endif /* SO_KEEPALIVE */ #endif /* SO_KEEPALIVE */
} }
#endif /* (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1) */
static bool static bool
prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr) prepareServerAddress(const char* address, int port, struct sockaddr_in* sockaddr)
@ -196,10 +194,6 @@ TcpServerSocket_create(const char* address, int port)
return NULL ; return NULL ;
} }
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(fd);
#endif
setSocketNonBlocking((Socket) serverSocket); setSocketNonBlocking((Socket) serverSocket);
} }
@ -294,10 +288,6 @@ Socket_connect(Socket self, const char* address, int port)
self->fd = socket(AF_INET, SOCK_STREAM, 0); self->fd = socket(AF_INET, SOCK_STREAM, 0);
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(self->fd);
#endif
fd_set fdSet; fd_set fdSet;
FD_ZERO(&fdSet); FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet); FD_SET(self->fd, &fdSet);

@ -32,14 +32,10 @@
#include <netdb.h> #include <netdb.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <netinet/tcp.h> // required for TCP keepalive #include <netinet/tcp.h> // required for TCP keepalive
#include "hal_thread.h" #include "hal_thread.h"
#include "stack_config.h"
#include "lib_memory.h" #include "lib_memory.h"
#ifndef DEBUG_SOCKET #ifndef DEBUG_SOCKET
@ -115,25 +111,25 @@ Handleset_destroy(HandleSet self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
static void void
activateKeepAlive(int sd) Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
{ {
#if defined SO_KEEPALIVE #if defined SO_KEEPALIVE
int optval; int optval;
socklen_t optlen = sizeof(optval); socklen_t optlen = sizeof(optval);
optval = 1; optval = 1;
setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
#if defined TCP_KEEPCNT #if defined TCP_KEEPCNT
optval = CONFIG_TCP_KEEPALIVE_IDLE; optval = idleTime;
setsockopt(sd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen); setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);
optval = CONFIG_TCP_KEEPALIVE_INTERVAL; optval = interval;
setsockopt(sd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);
optval = CONFIG_TCP_KEEPALIVE_CNT; optval = count;
setsockopt(sd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen); setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);
#endif /* TCP_KEEPCNT */ #endif /* TCP_KEEPCNT */
#endif /* SO_KEEPALIVE */ #endif /* SO_KEEPALIVE */
@ -217,10 +213,6 @@ TcpServerSocket_create(const char* address, int port)
close(fd); close(fd);
return NULL ; return NULL ;
} }
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(fd);
#endif
} }
return serverSocket; return serverSocket;
@ -326,10 +318,6 @@ Socket_connect(Socket self, const char* address, int port)
activateTcpNoDelay(self); activateTcpNoDelay(self);
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
activateKeepAlive(self->fd);
#endif
fcntl(self->fd, F_SETFL, O_NONBLOCK); fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) { if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {

@ -1,7 +1,7 @@
/* /*
* socket_win32.c * socket_win32.c
* *
* Copyright 2013, 2014 Michael Zillgith * Copyright 2013-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -116,25 +116,26 @@ Handleset_destroy(HandleSet self)
static bool wsaStartupCalled = false; static bool wsaStartupCalled = false;
static int socketCount = 0; static int socketCount = 0;
static void void
activateKeepAlive(SOCKET s) Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
{ {
struct tcp_keepalive keepalive; struct tcp_keepalive keepalive;
DWORD retVal=0; DWORD retVal=0;
keepalive.onoff = 1; keepalive.onoff = 1;
keepalive.keepalivetime = CONFIG_TCP_KEEPALIVE_IDLE * 1000; keepalive.keepalivetime = CONFIG_TCP_KEEPALIVE_IDLE * 1000;
keepalive.keepaliveinterval = CONFIG_TCP_KEEPALIVE_INTERVAL * 1000; keepalive.keepaliveinterval = CONFIG_TCP_KEEPALIVE_INTERVAL * 1000;
if (WSAIoctl(s, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), if (WSAIoctl(self->fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive),
NULL, 0, &retVal, NULL, NULL) == SOCKET_ERROR) NULL, 0, &retVal, NULL, NULL) == SOCKET_ERROR)
{ {
if (DEBUG_SOCKET) if (DEBUG_SOCKET)
printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n", printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n",
WSAGetLastError()); WSAGetLastError());
} }
} }
static void static void
setSocketNonBlocking(Socket self) setSocketNonBlocking(Socket self)
{ {
@ -223,10 +224,6 @@ TcpServerSocket_create(const char* address, int port)
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(listen_socket);
#endif
if (listen_socket == INVALID_SOCKET) { if (listen_socket == INVALID_SOCKET) {
if (DEBUG_SOCKET) if (DEBUG_SOCKET)
printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError()); printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError());
@ -335,10 +332,6 @@ Socket_connect(Socket self, const char* address, int port)
self->fd = socket(AF_INET, SOCK_STREAM, 0); self->fd = socket(AF_INET, SOCK_STREAM, 0);
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
activateKeepAlive(self->fd);
#endif
setSocketNonBlocking(self); setSocketNonBlocking(self);
fd_set fdSet; fd_set fdSet;

@ -21,10 +21,7 @@
* See COPYING file for the complete license text. * See COPYING file for the complete license text.
*/ */
#include "hal_time.h"
#include "libiec61850_platform_includes.h"
#include "stack_config.h"
#include <time.h> #include <time.h>

@ -21,10 +21,7 @@
* See COPYING file for the complete license text. * See COPYING file for the complete license text.
*/ */
#include "hal_time.h"
#include "libiec61850_platform_includes.h"
#include "stack_config.h"
#include <time.h> #include <time.h>

@ -5,6 +5,8 @@
#ifndef LIBIEC61850_PLATFORM_INCLUDES_H_ #ifndef LIBIEC61850_PLATFORM_INCLUDES_H_
#define LIBIEC61850_PLATFORM_INCLUDES_H_ #define LIBIEC61850_PLATFORM_INCLUDES_H_
#include "stack_config.h"
#include "libiec61850_common_api.h" #include "libiec61850_common_api.h"
#include "string_utilities.h" #include "string_utilities.h"

@ -21,12 +21,11 @@
* See COPYING file for the complete license text. * See COPYING file for the complete license text.
*/ */
#include "stack_config.h"
#include "libiec61850_platform_includes.h" #include "libiec61850_platform_includes.h"
#include "iec61850_client.h" #include "iec61850_client.h"
#include "stack_config.h"
#include "mms_client_connection.h" #include "mms_client_connection.h"
#include "ied_connection_private.h" #include "ied_connection_private.h"

@ -23,6 +23,7 @@
#include "iec61850_model.h" #include "iec61850_model.h"
#include "stack_config.h"
#include "libiec61850_platform_includes.h" #include "libiec61850_platform_includes.h"
static void static void

@ -289,6 +289,13 @@ IsoClientConnection_associate(IsoClientConnection self, IsoConnectionParameters
Socket_setConnectTimeout(self->socket, connectTimeoutInMs); Socket_setConnectTimeout(self->socket, connectTimeoutInMs);
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
Socket_activateTcpKeepAlive(self->socket,
CONFIG_TCP_KEEPALIVE_IDLE,
CONFIG_TCP_KEEPALIVE_INTERVAL,
CONFIG_TCP_KEEPALIVE_CNT);
#endif
if (!Socket_connect(self->socket, params->hostname, params->tcpPort)) if (!Socket_connect(self->socket, params->hostname, params->tcpPort))
goto returnError; goto returnError;

@ -342,6 +342,13 @@ setupIsoServer(IsoServer self)
goto exit_function; goto exit_function;
} }
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
Socket_activateTcpKeepAlive(self->serverSocket,
CONFIG_TCP_KEEPALIVE_IDLE,
CONFIG_TCP_KEEPALIVE_INTERVAL,
CONFIG_TCP_KEEPALIVE_CNT);
#endif
ServerSocket_setBacklog((ServerSocket) self->serverSocket, BACKLOG); ServerSocket_setBacklog((ServerSocket) self->serverSocket, BACKLOG);
ServerSocket_listen((ServerSocket) self->serverSocket); ServerSocket_listen((ServerSocket) self->serverSocket);

Loading…
Cancel
Save