- Socket layer: Added function HandleSet_removeSocket

- Socket layer (Linux/BSD): replaced select by poll
pull/211/head
Michael Zillgith 6 years ago
parent df0e7c08df
commit f788256247

@ -1,7 +1,7 @@
/*
* socket_hal.h
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2020 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -87,7 +87,7 @@ PAL_API void
Handleset_reset(HandleSet self);
/**
* \brief add a soecket to an existing handle set
* \brief add a socket to an existing handle set
*
* \param self the HandleSet instance
* \param sock the socket to add
@ -95,6 +95,12 @@ Handleset_reset(HandleSet self);
PAL_API void
Handleset_addSocket(HandleSet self, const Socket sock);
/**
* \brief remove a socket from an existing handle set
*/
void
Handleset_removeSocket(HandleSet self, const Socket sock);
/**
* \brief wait for a socket to become ready
*

@ -1,7 +1,7 @@
/*
* socket_bsd.c
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2020 Michael Zillgith
* contributions by Michael Clausen (School of engineering Valais).
*
* This file is part of libIEC61850.
@ -36,6 +36,10 @@
#include <netinet/tcp.h> // required for TCP keepalive
#include <signal.h>
#include <poll.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
@ -54,63 +58,117 @@ struct sServerSocket {
};
struct sHandleSet {
fd_set handles;
int maxHandle;
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
int nfds;
};
HandleSet
Handleset_new(void)
{
HandleSet result = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
HandleSet self = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (result != NULL) {
FD_ZERO(&result->handles);
result->maxHandle = -1;
if (self) {
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
self->nfds = 0;
}
return result;
return self;
}
void
Handleset_reset(HandleSet self)
{
FD_ZERO(&self->handles);
self->maxHandle = -1;
if (self) {
if (self->sockets) {
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
}
}
}
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
FD_SET(sock->fd, &self->handles);
if (sock->fd > self->maxHandle) {
self->maxHandle = sock->fd;
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
}
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
}
int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
int result;
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
if (self != NULL && self->maxHandle >= 0) {
struct timeval timeout;
self->nfds = LinkedList_size(self->sockets);
self->fds = GLOBAL_CALLOC(self->nfds, sizeof(struct pollfd));
int i;
for (i = 0; i < self->nfds; i++) {
LinkedList sockElem = LinkedList_get(self->sockets, i);
timeout.tv_sec = timeoutMs / 1000;
timeout.tv_usec = (timeoutMs % 1000) * 1000;
result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout);
} else {
result = -1;
if (sockElem) {
Socket sock = (Socket) LinkedList_getData(sockElem);
if (sock) {
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
}
}
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1) {
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
/* there is no socket to wait for */
return 0;
}
}
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
if (self->fds)
GLOBAL_FREEMEM(self->fds);
GLOBAL_FREEMEM(self);
}
}
void

@ -1,7 +1,7 @@
/*
* socket_linux.c
*
* Copyright 2013-2018 Michael Zillgith
* Copyright 2013-2020 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -35,6 +35,12 @@
#include <netinet/tcp.h> /* required for TCP keepalive */
#include <linux/version.h>
#define _GNU_SOURCE
#include <signal.h>
#include <poll.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
@ -53,62 +59,118 @@ struct sServerSocket {
};
struct sHandleSet {
fd_set handles;
int maxHandle;
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
int nfds;
};
HandleSet
Handleset_new(void)
{
HandleSet result = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
HandleSet self = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (result != NULL) {
FD_ZERO(&result->handles);
result->maxHandle = -1;
if (self) {
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
self->nfds = 0;
}
return result;
return self;
}
void
Handleset_reset(HandleSet self)
{
FD_ZERO(&self->handles);
self->maxHandle = -1;
if (self) {
if (self->sockets) {
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
}
}
}
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
FD_SET(sock->fd, &self->handles);
if (sock->fd > self->maxHandle) {
self->maxHandle = sock->fd;
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
}
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
}
int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
int result;
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
if ((self != NULL) && (self->maxHandle >= 0)) {
struct timeval timeout;
self->nfds = LinkedList_size(self->sockets);
self->fds = GLOBAL_CALLOC(self->nfds, sizeof(struct pollfd));
int i;
for (i = 0; i < self->nfds; i++) {
LinkedList sockElem = LinkedList_get(self->sockets, i);
if (sockElem) {
Socket sock = (Socket) LinkedList_getData(sockElem);
if (sock) {
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
}
}
timeout.tv_sec = timeoutMs / 1000;
timeout.tv_usec = (timeoutMs % 1000) * 1000;
result = select(self->maxHandle + 1, &self->handles, NULL, NULL, &timeout);
} else {
result = -1;
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1) {
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
/* there is no socket to wait for */
return 0;
}
}
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
if (self->fds)
GLOBAL_FREEMEM(self->fds);
GLOBAL_FREEMEM(self);
}
}
void
@ -557,10 +619,12 @@ Socket_read(Socket self, uint8_t* buf, int size)
case EAGAIN:
return 0;
case EBADF:
return -1;
default:
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: recv returned error (errno=%i)\n", error);
return -1;
}
}
@ -577,9 +641,16 @@ Socket_write(Socket self, uint8_t* buf, int size)
/* MSG_NOSIGNAL - prevent send to signal SIGPIPE when peer unexpectedly closed the socket */
int retVal = send(self->fd, buf, size, MSG_NOSIGNAL);
if ((retVal == -1) && (errno == EAGAIN))
if (retVal == -1) {
if (errno == EAGAIN) {
return 0;
else
}
else {
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: send returned error (errno=%i)\n", errno);
}
}
return retVal;
}

@ -89,6 +89,14 @@ Handleset_addSocket(HandleSet self, const Socket sock)
}
}
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
FD_CLR(sock->fd, &self->handles);
}
}
int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{

@ -39,8 +39,11 @@ IsoConnection_destroy(IsoConnection self);
LIB61850_INTERNAL void
IsoConnection_handleTcpConnection(IsoConnection self);
/**
* \brief Add the connection socket to the given HandleSet instance
*/
LIB61850_INTERNAL void
IsoConnection_addHandleSet(const IsoConnection self, HandleSet handles);
IsoConnection_addToHandleSet(const IsoConnection self, HandleSet handles);
LIB61850_INTERNAL void
private_IsoServer_increaseConnectionCounter(IsoServer self);

@ -134,7 +134,7 @@ finalizeIsoConnection(IsoConnection self)
}
void
IsoConnection_addHandleSet(const IsoConnection self, HandleSet handles)
IsoConnection_addToHandleSet(const IsoConnection self, HandleSet handles)
{
Handleset_addSocket(handles, self->socket);
}

@ -645,10 +645,9 @@ IsoServer_waitReady(IsoServer self, unsigned int timeoutMs)
int result;
if (getState(self) == ISO_SVR_STATE_RUNNING) {
HandleSet handles;
HandleSet handles = Handleset_new();
handles = Handleset_new();
if (handles != NULL) {
if (handles) {
#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0)
lockClientConnections(self);
@ -663,7 +662,7 @@ IsoServer_waitReady(IsoServer self, unsigned int timeoutMs)
IsoConnection isoConnection = (IsoConnection) openConnection->data;
if (IsoConnection_isRunning(isoConnection)) {
IsoConnection_addHandleSet(isoConnection, handles);
IsoConnection_addToHandleSet(isoConnection, handles);
openConnection = LinkedList_getNext(openConnection);
} else {
#if ((CONFIG_MMS_SINGLE_THREADED == 1) || (CONFIG_MMS_THREADLESS_STACK == 1))
@ -683,7 +682,7 @@ IsoServer_waitReady(IsoServer self, unsigned int timeoutMs)
for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) {
if (self->openClientConnections[i] != NULL) {
if (IsoConnection_isRunning(self->openClientConnections[i])) {
IsoConnection_addHandleSet(self->openClientConnections[i], handles);
IsoConnection_addToHandleSet(self->openClientConnections[i], handles);
}
else {
#if ((CONFIG_MMS_SINGLE_THREADED == 1) || (CONFIG_MMS_THREADLESS_STACK == 1))

Loading…
Cancel
Save