diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index f092170f..2ee9443e 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -1756,7 +1756,7 @@ namespace IEC61850 } } - public class ClientConnection + public class ClientConnection : IDisposable { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientConnection_getPeerAddress(IntPtr self); @@ -1764,31 +1764,90 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientConnection_getLocalAddress(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientConnection_abort(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr ClientConnection_claimOwnership(IntPtr self); + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern void ClientConnection_release(IntPtr self); + internal IntPtr self; - internal ClientConnection (IntPtr self) { - this.self = self; + internal ClientConnection(IntPtr self) + { + this.self = ClientConnection_claimOwnership(self); } public string GetPeerAddress() { - IntPtr peerAddrPtr = ClientConnection_getPeerAddress (self); + lock (this) + { + if (self != IntPtr.Zero) + { + IntPtr peerAddrPtr = ClientConnection_getPeerAddress(self); - if (peerAddrPtr != IntPtr.Zero) - return Marshal.PtrToStringAnsi (peerAddrPtr); - else - return null; + if (peerAddrPtr != IntPtr.Zero) + return Marshal.PtrToStringAnsi(peerAddrPtr); + } + } + + return null; } public string GetLocalAddress() { - IntPtr localAddrPtr = ClientConnection_getLocalAddress(self); + lock (this) + { + if (self != IntPtr.Zero) + { + IntPtr localAddrPtr = ClientConnection_getLocalAddress(self); - if (localAddrPtr != IntPtr.Zero) - return Marshal.PtrToStringAnsi(localAddrPtr); - else - return null; + if (localAddrPtr != IntPtr.Zero) + return Marshal.PtrToStringAnsi(localAddrPtr); + } + } + + return null; } + + /// + /// Abort/Close the client connection + /// + /// true, when connection has been closed, false when connection was already close + public bool Abort() + { + lock (this) + { + if (self != IntPtr.Zero) + { + return ClientConnection_abort(self); + } + } + + return false; + } + + public void Dispose() + { + lock (this) + { + if (self != IntPtr.Zero) + { + ClientConnection_release(self); + + self = IntPtr.Zero; + } + } + } + + ~ClientConnection () + { + Dispose(); + } + } public class MmsGooseControlBlock diff --git a/dotnet/server1/Program.cs b/dotnet/server1/Program.cs index d41cff1c..5ba70359 100644 --- a/dotnet/server1/Program.cs +++ b/dotnet/server1/Program.cs @@ -101,22 +101,16 @@ namespace server1 void ConnectionCallBack(IedServer server, ClientConnection clientConnection, bool connected, object parameter) { string allowedIp = parameter as string; - string ipAddress = clientConnection.GetPeerAddress(); - if (allowedIp == ipAddress) + string ipAddress = clientConnection.GetLocalAddress(); + if (allowedIp != ipAddress) { - + clientConnection.Abort(); } - else - { - - } - - } var connectionCallBack = new ConnectionIndicationHandler(ConnectionCallBack); - iedServer.SetConnectionIndicationHandler(connectionCallBack, "127.0.0.2"); + iedServer.SetConnectionIndicationHandler(connectionCallBack, "127.0.0.1:103"); iedServer.Start(102); diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 63fe2268..cacbc524 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -825,6 +825,44 @@ 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 Claim ownership of the ClientConnection instance to store and use it outside of a callback + * + * \note The application has to call \ref ClientConnection_release when the instance is no longer used + * order to avoid memory leaks + * + * \param self the ClientConnection instance + * + * \return the connection instance when ownership is granted + */ +LIB61850_API ClientConnection +ClientConnection_claimOwnership(ClientConnection self); + +/** + * \brief Release the ownership of the ClientConnection instance. + * + * This function will also destroy the ClientConnection instance when no other owners exist. + * + * \note The application should only call this function once for each call for \ref ClientConnection_claimOwnership + * for a specific ClientConnection instance. The reference must not be used after calling this function! + * + * \param self the ClientConnection instance + */ +LIB61850_API void +ClientConnection_release(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/iec61850/inc_private/ied_server_private.h b/src/iec61850/inc_private/ied_server_private.h index 8dc5fede..e51a48ed 100644 --- a/src/iec61850/inc_private/ied_server_private.h +++ b/src/iec61850/inc_private/ied_server_private.h @@ -96,7 +96,7 @@ LIB61850_INTERNAL ClientConnection private_ClientConnection_create(void* serverConnectionHandle); LIB61850_INTERNAL void -private_ClientConnection_destroy(ClientConnection self); +private_ClientConnection_invalidate(ClientConnection self); LIB61850_INTERNAL int private_ClientConnection_getTasksCount(ClientConnection self); diff --git a/src/iec61850/server/impl/client_connection.c b/src/iec61850/server/impl/client_connection.c index 6eac160d..e8a6e2de 100644 --- a/src/iec61850/server/impl/client_connection.c +++ b/src/iec61850/server/impl/client_connection.c @@ -1,7 +1,7 @@ /* * client_connection.c * - * Copyright 2013-2024 Michael Zillgith + * Copyright 2013-2025 Michael Zillgith * * This file is part of libIEC61850. * @@ -32,16 +32,45 @@ #include "libiec61850_platform_includes.h" +#if __STDC_VERSION__ >= 201112L +#include +#else +#define _TLS_OWN_CNT_SEM 1 +#endif + struct sClientConnection { #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore tasksCountMutex; + Semaphore accessMutex; #endif - int tasksCount; - void* serverConnectionHandle; + int tasksCount; /* protected by accessMutex */ + void* serverConnectionHandle; /* protected by accessMutex */ + +#ifdef _TLS_OWN_CNT_SEM + #if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore ownerCountMutex; + #endif /*#if (CONFIG_MMS_THREADLESS_STACK != 1) */ + int ownerCount; +#else + _Atomic(int) ownerCount; +#endif /* _TLS_OWN_CNT_SEM */ }; +void +private_ClientConnection_invalidate(ClientConnection self) +{ +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + + self->serverConnectionHandle = NULL; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif +} + ClientConnection private_ClientConnection_create(void* serverConnectionHandle) { @@ -50,9 +79,14 @@ private_ClientConnection_create(void* serverConnectionHandle) if (self) { #if (CONFIG_MMS_THREADLESS_STACK != 1) - self->tasksCountMutex = Semaphore_create(1); + self->accessMutex = Semaphore_create(1); + + #ifdef _TLS_OWN_CNT_SEM + self->ownerCount = Semaphore_create(1); + #endif #endif + self->ownerCount = 1; self->tasksCount = 0; self->serverConnectionHandle = serverConnectionHandle; } @@ -60,13 +94,17 @@ private_ClientConnection_create(void* serverConnectionHandle) return self; } -void +static void private_ClientConnection_destroy(ClientConnection self) { if (self) { #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_destroy(self->tasksCountMutex); + Semaphore_destroy(self->accessMutex); + + #ifdef _TLS_OWN_CNT_SEM + Semaphore_destroy(self->ownerCountMutex); + #endif #endif GLOBAL_FREEMEM(self); @@ -79,13 +117,13 @@ private_ClientConnection_getTasksCount(ClientConnection self) int tasksCount; #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_wait(self->tasksCountMutex); + Semaphore_wait(self->accessMutex); #endif tasksCount = self->tasksCount; #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_post(self->tasksCountMutex); + Semaphore_post(self->accessMutex); #endif return tasksCount; @@ -95,13 +133,13 @@ void private_ClientConnection_increaseTasksCount(ClientConnection self) { #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_wait(self->tasksCountMutex); + Semaphore_wait(self->accessMutex); #endif self->tasksCount++; #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_post(self->tasksCountMutex); + Semaphore_post(self->accessMutex); #endif } @@ -109,43 +147,183 @@ void private_ClientConnection_decreaseTasksCount(ClientConnection self) { #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_wait(self->tasksCountMutex); + Semaphore_wait(self->accessMutex); #endif self->tasksCount--; #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_post(self->tasksCountMutex); + Semaphore_post(self->accessMutex); #endif } void* private_ClientConnection_getServerConnectionHandle(ClientConnection self) { - return self->serverConnectionHandle; + void* handle = NULL; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + + handle = self->serverConnectionHandle; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif + + return handle; } const char* ClientConnection_getPeerAddress(ClientConnection self) { - MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + char* peerAddress = NULL; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + + if (self->serverConnectionHandle) + { + MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + + peerAddress = MmsServerConnection_getClientAddress(mmsConnection); + } + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif - return MmsServerConnection_getClientAddress(mmsConnection); + return peerAddress; } const char* ClientConnection_getLocalAddress(ClientConnection self) { - MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + char* localAddress = NULL; - return MmsServerConnection_getLocalAddress(mmsConnection); -} +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + if (self->serverConnectionHandle) + { + MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + + localAddress = MmsServerConnection_getLocalAddress(mmsConnection); + } + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif + + return localAddress; +} void* ClientConnection_getSecurityToken(ClientConnection self) { - MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + void* secToken = NULL; - return MmsServerConnection_getSecurityToken(mmsConnection); +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + + if (self->serverConnectionHandle) + { + MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + + secToken = MmsServerConnection_getSecurityToken(mmsConnection); + } + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif + + return secToken; +} + +bool +ClientConnection_abort(ClientConnection self) +{ + bool aborted = false; + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->accessMutex); +#endif + + if (self->serverConnectionHandle) + { + MmsServerConnection mmsConnection = (MmsServerConnection) self->serverConnectionHandle; + + if (mmsConnection) + { + MmsServer mmsServer = MmsServerConnection_getServer(mmsConnection); + + aborted = MmsServer_abortConnection(mmsServer, mmsConnection); + + if (aborted) + { + /* remove reference to underlying connection. Instance cannot be used any longer */ + self->serverConnectionHandle = NULL; + } + } + } + +#if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->accessMutex); +#endif + + return aborted; +} + +ClientConnection +ClientConnection_claimOwnership(ClientConnection self) +{ +#ifdef _TLS_OWN_CNT_SEM + #if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->ownerCountMutex); + #endif + self->ownerCount++; + #if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->ownerCountMutex); + #endif +#else + atomic_fetch_add(&(self->ownerCount), 1); +#endif + + return self; +} + +void +ClientConnection_release(ClientConnection self) +{ + if (self) + { +#ifdef _TLS_OWN_CNT_SEM + + int cnt; + + #if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_wait(self->ownerCountMutex); + #endif + + cnt = self->ownerCount; + self->ownerCount--; + + #if (CONFIG_MMS_THREADLESS_STACK != 1) + Semaphore_post(self->ownerCountMutex); + #endif + + if (cnt == 1) { + private_ClientConnection_destroy(self); + } +#else + if (atomic_fetch_sub(&(self->ownerCount), 1) == 1) + { + private_ClientConnection_destroy(self); + } +#endif /* #ifdef _TLS_OWN_CNT_SEM */ + } } diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index b2b29e57..0a61d7bb 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -808,7 +808,7 @@ IedServer_destroy(IedServer self) if (self->mmsMapping) MmsMapping_destroy(self->mmsMapping); - LinkedList_destroyDeep(self->clientConnections, (LinkedListValueDeleteFunction) private_ClientConnection_destroy); + LinkedList_destroyDeep(self->clientConnections, (LinkedListValueDeleteFunction) ClientConnection_release); #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore_destroy(self->dataModelLock); diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index a184ffe5..e5e6b034 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -3354,7 +3354,9 @@ mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerE unselectAllSettingGroups(self, connection); #endif - private_ClientConnection_destroy(clientConnection); + private_ClientConnection_invalidate(clientConnection); + + ClientConnection_release(clientConnection); } else if (event == MMS_SERVER_NEW_CONNECTION) { /* call user provided handler function */ 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..644fcdb1 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -818,7 +818,6 @@ MmsServerConnection_init(MmsServerConnection connection, MmsServer server, IsoCo void MmsServerConnection_destroy(MmsServerConnection self) { - #if (MMS_FILE_SERVICE == 1) int frsmIndex = 0; @@ -925,3 +924,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_connection.c b/src/mms/iso_server/iso_connection.c index bca4fafd..5395b1e2 100644 --- a/src/mms/iso_server/iso_connection.c +++ b/src/mms/iso_server/iso_connection.c @@ -479,7 +479,7 @@ handleTcpConnection(void* parameter) while(self->state == ISO_CON_STATE_RUNNING) IsoConnection_handleTcpConnection(self, false); - IsoServer_closeConnection(self->isoServer, self); + IsoServer_closeConnectionIndication(self->isoServer, self); finalizeIsoConnection(self); 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,