From d574cac1f6cfa7447c61d44a7eaeaeb8417c2d5d Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 18 Jul 2025 13:49:19 +0100 Subject: [PATCH] - added first version of ClientConnection_abort function (LIB61850-488) --- src/iec61850/inc/iec61850_server.h | 12 +++ src/mms/inc/mms_server.h | 5 +- src/mms/inc_private/iso_server.h | 6 +- src/mms/inc_private/mms_server_connection.h | 3 + src/mms/iso_mms/server/mms_server.c | 23 ++++++ .../iso_mms/server/mms_server_connection.c | 6 ++ src/mms/iso_server/iso_server.c | 77 ++++++++++++++----- 7 files changed, 111 insertions(+), 21 deletions(-) diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 63fe2268..f1dee00d 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -825,6 +825,18 @@ ClientConnection_getLocalAddress(ClientConnection self); LIB61850_API void* ClientConnection_getSecurityToken(ClientConnection self); +/** + * \brief Abort/Close the client connection + * + * \note After calling this function the ClientConnection instance can no longer be used. + * + * \param self the ClientConnection instance + * + * \return true, when the client connection has been closed, false otherwise + */ +LIB61850_API bool +ClientConnection_abort(ClientConnection self); + /** * \brief User provided callback function that is invoked whenever a new client connects or an existing connection is closed * or detected as lost. diff --git a/src/mms/inc/mms_server.h b/src/mms/inc/mms_server.h index 15248789..220b86f3 100644 --- a/src/mms/inc/mms_server.h +++ b/src/mms/inc/mms_server.h @@ -411,7 +411,10 @@ LIB61850_INTERNAL void* MmsServerConnection_getSecurityToken(MmsServerConnection self); LIB61850_INTERNAL void -MmsServer_ignoreClientRequests(MmsServer self, bool enable);; +MmsServer_ignoreClientRequests(MmsServer self, bool enable); + +LIB61850_INTERNAL bool +MmsServer_abortConnection(MmsServer self, MmsServerConnection con); /**@}*/ diff --git a/src/mms/inc_private/iso_server.h b/src/mms/inc_private/iso_server.h index 8ce80bdc..29811215 100644 --- a/src/mms/inc_private/iso_server.h +++ b/src/mms/inc_private/iso_server.h @@ -157,7 +157,11 @@ LIB61850_INTERNAL void IsoServer_stopListeningThreadless(IsoServer self); LIB61850_INTERNAL void -IsoServer_closeConnection(IsoServer self, IsoConnection isoConnection); +IsoServer_closeConnectionIndication(IsoServer self, IsoConnection isoConnection); + +/* Used by MmsServer instance to actively close a connection */ +LIB61850_INTERNAL bool +IsoServer_closeConnection(IsoServer self, IsoConnection con); LIB61850_INTERNAL void IsoServer_destroy(IsoServer self); diff --git a/src/mms/inc_private/mms_server_connection.h b/src/mms/inc_private/mms_server_connection.h index bb35fa9e..54459e0e 100644 --- a/src/mms/inc_private/mms_server_connection.h +++ b/src/mms/inc_private/mms_server_connection.h @@ -112,6 +112,9 @@ MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self); LIB61850_INTERNAL const char* MmsServerConnection_getFilesystemBasepath(MmsServerConnection self); +LIB61850_INTERNAL MmsServer +MmsServerConnection_getServer(MmsServerConnection self); + #ifdef __cplusplus } #endif diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index 1e860f3a..823e8542 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -926,3 +926,26 @@ MmsServer_ignoreClientRequests(MmsServer self, bool enable) { self->blockRequests = enable; } + +bool +MmsServer_abortConnection(MmsServer self, MmsServerConnection con) +{ + if (self->isoServerList) + { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) + { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + if (IsoServer_closeConnection(isoServer, con->isoConnection)) + { + return true; + } + + elem = LinkedList_getNext(elem); + } + } + + return false; +} diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c index d01ce40a..d8c1b657 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -925,3 +925,9 @@ MmsServerConnection_getFilesystemBasepath(MmsServerConnection self) return CONFIG_VIRTUAL_FILESTORE_BASEPATH; #endif } + +MmsServer +MmsServerConnection_getServer(MmsServerConnection self) +{ + return self->server; +} diff --git a/src/mms/iso_server/iso_server.c b/src/mms/iso_server/iso_server.c index a2daa6ad..137fc996 100644 --- a/src/mms/iso_server/iso_server.c +++ b/src/mms/iso_server/iso_server.c @@ -177,24 +177,31 @@ addClientConnection(IsoServer self, IsoConnection connection) } -static void +static bool removeClientConnection(IsoServer self, IsoConnection connection) { + bool removed = false; + #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) - LinkedList_remove(self->openClientConnections, connection); + removed = LinkedList_remove(self->openClientConnections, connection); #if (CONFIG_MMS_SINGLE_THREADED == 1) - IsoConnection_removeFromHandleSet(connection, self->handleset); + if (removed) + { + IsoConnection_removeFromHandleSet(connection, self->handleset); + } #endif - #else int i; - for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) { - if (self->openClientConnections[i] == connection) { + for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) + { + if (self->openClientConnections[i] == connection) + { + removed = true; #if (CONFIG_MMS_SINGLE_THREADED == 1) IsoConnection_removeFromHandleSet(connection, self->handleset); @@ -208,6 +215,8 @@ removeClientConnection(IsoServer self, IsoConnection connection) } } #endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */ + + return removed; } static void @@ -221,12 +230,14 @@ removeTerminatedConnections(IsoServer self, bool isSingleThread) LinkedList openConnection = LinkedList_getNext(self->openClientConnections); - while (openConnection) { + while (openConnection) + { IsoConnection isoConnection = (IsoConnection) openConnection->data; - if (isSingleThread) { - if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_STOPPED) { - + if (isSingleThread) + { + if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_STOPPED) + { self->connectionHandler(ISO_CONNECTION_CLOSED, self->connectionHandlerParameter, isoConnection); @@ -234,7 +245,8 @@ removeTerminatedConnections(IsoServer self, bool isSingleThread) } } - if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_TERMINATED) { + if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_TERMINATED) + { removeClientConnection(self, isoConnection); IsoConnection_destroy(isoConnection); openConnection = LinkedList_getNext(self->openClientConnections); @@ -246,14 +258,16 @@ removeTerminatedConnections(IsoServer self, bool isSingleThread) #else int i; - for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) { - if (self->openClientConnections[i] != NULL) { - + for (i = 0; i < CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; i++) + { + if (self->openClientConnections[i] != NULL) + { IsoConnection isoConnection = self->openClientConnections[i]; - if (isSingleThread) { - if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_STOPPED) { - + if (isSingleThread) + { + if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_STOPPED) + { self->connectionHandler(ISO_CONNECTION_CLOSED, self->connectionHandlerParameter, isoConnection); @@ -263,7 +277,8 @@ removeTerminatedConnections(IsoServer self, bool isSingleThread) } } - if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_TERMINATED) { + if (IsoConnection_getState(isoConnection) == ISO_CON_STATE_TERMINATED) + { removeClientConnection(self, isoConnection); IsoConnection_destroy(isoConnection); } @@ -271,10 +286,34 @@ removeTerminatedConnections(IsoServer self, bool isSingleThread) } #endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */ +#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) + unlockClientConnections(self); +#endif +} + +bool +IsoServer_closeConnection(IsoServer self, IsoConnection con) +{ + bool closed = false; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) + lockClientConnections(self); +#endif + + /* check if the connection is handled by this IsoServer instance */ + if (removeClientConnection(self, con)) + { + closed = true; + printf("ISO_SERVER (%p): Connection (%p) removed\n", self, con); + IsoConnection_close(con); + IsoConnection_destroy(con); + } + #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) unlockClientConnections(self); #endif + return closed; } static void @@ -800,7 +839,7 @@ IsoServer_stopListening(IsoServer self) #endif void -IsoServer_closeConnection(IsoServer self, IsoConnection isoConnection) +IsoServer_closeConnectionIndication(IsoServer self, IsoConnection isoConnection) { if (getState(self) != ISO_SVR_STATE_IDLE) { self->connectionHandler(ISO_CONNECTION_CLOSED, self->connectionHandlerParameter,