- 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 * socket_hal.h
* *
* Copyright 2013-2018 Michael Zillgith * Copyright 2013-2020 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -87,7 +87,7 @@ PAL_API void
Handleset_reset(HandleSet self); 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 self the HandleSet instance
* \param sock the socket to add * \param sock the socket to add
@ -95,6 +95,12 @@ Handleset_reset(HandleSet self);
PAL_API void PAL_API void
Handleset_addSocket(HandleSet self, const Socket sock); 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 * \brief wait for a socket to become ready
* *

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

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

@ -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 int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs) Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{ {

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

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

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

Loading…
Cancel
Save