From d55afdfb92ac915bff0382acc76dcc9a7e9b6626 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Thu, 7 May 2020 12:28:21 +0200 Subject: [PATCH] - IEC 61850 server: added support to listen on multiple IP addresses and ports (new function IedServer_addAccessPoint) --- src/common/linked_list.c | 20 +- src/common/map.c | 24 +- src/iec61850/inc/iec61850_server.h | 13 + src/iec61850/server/impl/ied_server.c | 11 + src/mms/inc_private/mms_server_internal.h | 7 +- src/mms/inc_private/mms_server_libinternal.h | 6 + src/mms/iso_mms/server/mms_server.c | 329 ++++++++++++++++--- src/mms/iso_server/iso_server.c | 65 ++-- 8 files changed, 373 insertions(+), 102 deletions(-) diff --git a/src/common/linked_list.c b/src/common/linked_list.c index 8bcd3ee4..693d5890 100644 --- a/src/common/linked_list.c +++ b/src/common/linked_list.c @@ -51,19 +51,21 @@ LinkedList_create() void LinkedList_destroyDeep(LinkedList list, LinkedListValueDeleteFunction valueDeleteFunction) { - LinkedList nextElement = list; - LinkedList currentElement; + if (list) { + LinkedList nextElement = list; + LinkedList currentElement; - do { - currentElement = nextElement; - nextElement = currentElement->next; + do { + currentElement = nextElement; + nextElement = currentElement->next; - if (currentElement->data != NULL) - valueDeleteFunction(currentElement->data); + if (currentElement->data != NULL) + valueDeleteFunction(currentElement->data); - GLOBAL_FREEMEM(currentElement); + GLOBAL_FREEMEM(currentElement); + } + while (nextElement != NULL); } - while (nextElement != NULL); } void diff --git a/src/common/map.c b/src/common/map.c index d0ab9e33..3b210c67 100644 --- a/src/common/map.c +++ b/src/common/map.c @@ -142,18 +142,20 @@ Map_deleteStatic(Map map, bool deleteKey) } void -Map_deleteDeep(Map map, bool deleteKey, void -(*valueDeleteFunction)(void*)) +Map_deleteDeep(Map map, bool deleteKey, void (*valueDeleteFunction)(void*)) { - LinkedList element = map->entries; + if (map) { + LinkedList element = map->entries; - while ((element = LinkedList_getNext(element)) != NULL) { - MapEntry* entry = (MapEntry*) element->data; - if (deleteKey == true) - GLOBAL_FREEMEM(entry->key); - valueDeleteFunction(entry->value); - } + while ((element = LinkedList_getNext(element)) != NULL) { + MapEntry* entry = (MapEntry*) element->data; + if (deleteKey == true) + GLOBAL_FREEMEM(entry->key); + valueDeleteFunction(entry->value); + } - LinkedList_destroy(map->entries); - GLOBAL_FREEMEM(map); + LinkedList_destroy(map->entries); + + GLOBAL_FREEMEM(map); + } } diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index d6e2cd27..00935096 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -338,6 +338,19 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio LIB61850_API void IedServer_destroy(IedServer self); +/** + * \brief Add a new local access point (server will listen to provided IP/port combination) + * + * \param self the instance of IedServer to operate on. + * \param ipAddr the local IP address to listen on + * \param tcpPort the local TCP port to listen on or -1 to use the standard TCP port + * \oaram tlsConfiguration the TLS configuration or NULL when TLS is not used for this access point + * + * \return true in case of success, false otherwise + */ +LIB61850_API bool +IedServer_addAccessPoint(IedServer self, const char* ipAddr, int tcpPort, TLSConfiguration tlsConfiguration); + /** * \brief Set the local IP address to listen on * diff --git a/src/iec61850/server/impl/ied_server.c b/src/iec61850/server/impl/ied_server.c index f31bdf9f..086011be 100644 --- a/src/iec61850/server/impl/ied_server.c +++ b/src/iec61850/server/impl/ied_server.c @@ -696,6 +696,17 @@ IedServer_processIncomingData(IedServer self) MmsServer_handleIncomingMessages(self->mmsServer); } +bool +IedServer_addAccessPoint(IedServer self, const char* ipAddr, int tcpPort, TLSConfiguration tlsConfiguration) +{ + if (self->mmsServer) { + return MmsServer_addAP(self->mmsServer, ipAddr, tcpPort, tlsConfiguration); + } + else { + return false; + } +} + void IedServer_stopThreadless(IedServer self) { diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index dfc0dbd7..1628487f 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -103,7 +103,9 @@ struct sMmsObtainFileTask { #endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */ struct sMmsServer { - IsoServer isoServer; + + LinkedList /**/ isoServerList; + MmsDevice* device; MmsReadVariableHandler readHandler; @@ -121,6 +123,9 @@ struct sMmsServer { MmsNamedVariableListChangedHandler variableListChangedHandler; /* TODO this is only required if dynamic data sets are supported! */ void* variableListChangedHandlerParameter; + AcseAuthenticator authenticator; + void* authenticatorParameter; + #if (CONFIG_MMS_THREADLESS_STACK != 1) Semaphore openConnectionsLock; #endif diff --git a/src/mms/inc_private/mms_server_libinternal.h b/src/mms/inc_private/mms_server_libinternal.h index b516a2d7..c18a7ac3 100644 --- a/src/mms/inc_private/mms_server_libinternal.h +++ b/src/mms/inc_private/mms_server_libinternal.h @@ -46,6 +46,12 @@ MmsServer_create(MmsDevice* device, TLSConfiguration tlsConfiguration); LIB61850_INTERNAL void MmsServer_destroy(MmsServer self); +/** + * \brief Add a new passive access point to the server + */ +LIB61850_INTERNAL bool +MmsServer_addAP(MmsServer self, const char* ipAddr, int tcpPort, TLSConfiguration tlsConfiguration); + LIB61850_INTERNAL void MmsServer_installReadHandler(MmsServer self, MmsReadVariableHandler, void* parameter); diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index 16df4506..2803e82c 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -1,7 +1,7 @@ /* * mms_server.c * - * Copyright 2013 - 2016 Michael Zillgith + * Copyright 2013-2020 Michael Zillgith * * This file is part of libIEC61850. * @@ -52,48 +52,133 @@ MmsServer_create(MmsDevice* device, TLSConfiguration tlsConfiguration) { MmsServer self = (MmsServer) GLOBAL_CALLOC(1, sizeof(struct sMmsServer)); - self->isoServer = IsoServer_create(tlsConfiguration); - self->device = device; - self->openConnections = Map_create(); - self->valueCaches = createValueCaches(device); - self->isLocked = false; + if (self) { +#if (CONFIG_MMS_THREADLESS_STACK != 1) + self->openConnectionsLock = Semaphore_create(1); - self->transmitBuffer = ByteBuffer_create(NULL, CONFIG_MMS_MAXIMUM_PDU_SIZE); + if (self->openConnectionsLock == NULL) + goto exit_error; -#if (CONFIG_MMS_THREADLESS_STACK != 1) - self->openConnectionsLock = Semaphore_create(1); + self->modelMutex = Semaphore_create(1); - self->modelMutex = Semaphore_create(1); - self->transmitBufferMutex = Semaphore_create(1); + if (self->modelMutex == NULL) + goto exit_error; - IsoServer_setUserLock(self->isoServer, self->modelMutex); + self->transmitBufferMutex = Semaphore_create(1); + + if (self->transmitBufferMutex == NULL) + goto exit_error; #endif + self->isoServerList = LinkedList_create(); + + if (self->isoServerList == NULL) + goto exit_error; + + if (tlsConfiguration) { + IsoServer isoServer = IsoServer_create(tlsConfiguration); + + if (isoServer == NULL) + goto exit_error; + + #if (CONFIG_MMS_THREADLESS_STACK != 1) + IsoServer_setUserLock(isoServer, self->modelMutex); + #endif + + LinkedList_add(self->isoServerList, isoServer); + } + + self->device = device; + self->openConnections = Map_create(); + + if (self->openConnections == NULL) + goto exit_error; + + self->valueCaches = createValueCaches(device); + + if (self->valueCaches == NULL) + goto exit_error; + + self->isLocked = false; + + self->transmitBuffer = ByteBuffer_create(NULL, CONFIG_MMS_MAXIMUM_PDU_SIZE); + + if (self->transmitBuffer == NULL) + goto exit_error; + #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) - self->fileServiceEnabled = true; - self->dynamicVariableListServiceEnabled = true; - self->journalServiceEnabled = true; - self->maxDataSetEntries = CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS; - self->maxAssociationSpecificDataSets = CONFIG_MMS_MAX_NUMBER_OF_ASSOCIATION_SPECIFIC_DATA_SETS; - self->maxDomainSpecificDataSets = CONFIG_MMS_MAX_NUMBER_OF_DOMAIN_SPECIFIC_DATA_SETS; + self->fileServiceEnabled = true; + self->dynamicVariableListServiceEnabled = true; + self->journalServiceEnabled = true; + self->maxDataSetEntries = CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS; + self->maxAssociationSpecificDataSets = CONFIG_MMS_MAX_NUMBER_OF_ASSOCIATION_SPECIFIC_DATA_SETS; + self->maxDomainSpecificDataSets = CONFIG_MMS_MAX_NUMBER_OF_DOMAIN_SPECIFIC_DATA_SETS; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ + } return self; + +exit_error: + + MmsServer_destroy(self); + + return NULL; +} + +bool +MmsServer_addAP(MmsServer self, const char* ipAddr, int tcpPort, TLSConfiguration tlsConfiguration) +{ + IsoServer isoServer = IsoServer_create(tlsConfiguration); + + if (isoServer) { + + IsoServer_setUserLock(isoServer, self->modelMutex); + + IsoServer_setLocalIpAddress(isoServer, ipAddr); + + if (tcpPort != -1) + IsoServer_setTcpPort(isoServer, tcpPort); + + if (self->authenticator) + IsoServer_setAuthenticator(isoServer, self->authenticator, self->authenticatorParameter); + + LinkedList_add(self->isoServerList, isoServer); + + return true; + } + + return false; } void MmsServer_setLocalIpAddress(MmsServer self, const char* localIpAddress) { - IsoServer_setLocalIpAddress(self->isoServer, localIpAddress); + if (LinkedList_size(self->isoServerList) == 0) { + MmsServer_addAP(self, NULL, -1, NULL); + } + + LinkedList elem = LinkedList_get(self->isoServerList, 0); + + if (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_setLocalIpAddress(isoServer, localIpAddress); + } } bool MmsServer_isRunning(MmsServer self) { - if (IsoServer_getState(self->isoServer) == ISO_SVR_STATE_RUNNING) - return true; - else - return false; + LinkedList elem = LinkedList_get(self->isoServerList, 0); + + if (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + if (IsoServer_getState(isoServer) == ISO_SVR_STATE_RUNNING) + return true; + } + + return false; } void @@ -115,7 +200,22 @@ MmsServer_setFilestoreBasepath(MmsServer self, const char* basepath) void MmsServer_setMaxConnections(MmsServer self, int maxConnections) { - IsoServer_setMaxConnections(self->isoServer, maxConnections); + if (self->isoServerList) { + + if (LinkedList_size(self->isoServerList) == 0) { + MmsServer_addAP(self, NULL, -1, NULL); + } + + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_setMaxConnections(isoServer, maxConnections); + + elem = LinkedList_getNext(elem); + } + } } void @@ -250,7 +350,21 @@ MmsServer_installVariableListChangedHandler(MmsServer self, MmsNamedVariableList void MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator, void* authenticatorParameter) { - IsoServer_setAuthenticator(self->isoServer, authenticator, authenticatorParameter); + self->authenticator = authenticator; + self->authenticatorParameter = authenticatorParameter; + + if (self->isoServerList) { + + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_setAuthenticator(isoServer, authenticator, authenticatorParameter); + + elem = LinkedList_getNext(elem); + } + } } #if (MMS_FILE_SERVICE == 1) @@ -295,26 +409,33 @@ deleteSingleCache(MmsValueCache cache) void MmsServer_destroy(MmsServer self) { - IsoServer_destroy(self->isoServer); + if (self) { + LinkedList_destroyDeep(self->isoServerList, (LinkedListValueDeleteFunction) IsoServer_destroy); - Map_deleteDeep(self->openConnections, false, closeConnection); - Map_deleteDeep(self->valueCaches, false, (void (*) (void*)) deleteSingleCache); + Map_deleteDeep(self->openConnections, false, closeConnection); + Map_deleteDeep(self->valueCaches, false, (void (*) (void*)) deleteSingleCache); -#if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_destroy(self->openConnectionsLock); + #if (CONFIG_MMS_THREADLESS_STACK != 1) + if (self->openConnectionsLock) + Semaphore_destroy(self->openConnectionsLock); - Semaphore_destroy(self->modelMutex); - Semaphore_destroy(self->transmitBufferMutex); -#endif + if (self->modelMutex) + Semaphore_destroy(self->modelMutex); - ByteBuffer_destroy(self->transmitBuffer); + if (self->transmitBufferMutex) + Semaphore_destroy(self->transmitBufferMutex); + #endif -#if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) - if (self->filestoreBasepath != NULL) - GLOBAL_FREEMEM(self->filestoreBasepath); -#endif + if (self->transmitBuffer) + ByteBuffer_destroy(self->transmitBuffer); - GLOBAL_FREEMEM(self); + #if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) + if (self->filestoreBasepath != NULL) + GLOBAL_FREEMEM(self->filestoreBasepath); + #endif + + GLOBAL_FREEMEM(self); + } } MmsValue* @@ -448,44 +569,120 @@ isoConnectionIndicationHandler(IsoConnectionIndication indication, #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED != 1) void -MmsServer_startListening(MmsServer server, int tcpPort) +MmsServer_startListening(MmsServer self, int tcpPort) { - IsoServer_setConnectionHandler(server->isoServer, isoConnectionIndicationHandler, (void*) server); + if (self->isoServerList) { + + if (LinkedList_size(self->isoServerList) == 0) { + MmsServer_addAP(self, NULL, -1, NULL); + } + + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_setConnectionHandler(isoServer, isoConnectionIndicationHandler, (void*) self); - if (tcpPort != -1) - IsoServer_setTcpPort(server->isoServer, tcpPort); + if (tcpPort != -1) + IsoServer_setTcpPort(isoServer, tcpPort); - IsoServer_startListening(server->isoServer); + IsoServer_startListening(isoServer); + + elem = LinkedList_getNext(elem); + } + } } void -MmsServer_stopListening(MmsServer server) +MmsServer_stopListening(MmsServer self) { - IsoServer_stopListening(server->isoServer); + if (self->isoServerList) { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_stopListening(isoServer); + + elem = LinkedList_getNext(elem); + } + } } #endif /* (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED != 1)*/ void MmsServer_startListeningThreadless(MmsServer self, int tcpPort) { - IsoServer_setConnectionHandler(self->isoServer, isoConnectionIndicationHandler, (void*) self); + if (self->isoServerList) { + + if (LinkedList_size(self->isoServerList) == 0) { + MmsServer_addAP(self, NULL, -1, NULL); + } + + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_setConnectionHandler(isoServer, isoConnectionIndicationHandler, (void*) self); + + if (tcpPort != -1) + IsoServer_setTcpPort(isoServer, tcpPort); - if (tcpPort != -1) - IsoServer_setTcpPort(self->isoServer, tcpPort); + IsoServer_startListeningThreadless(isoServer); - IsoServer_startListeningThreadless(self->isoServer); + elem = LinkedList_getNext(elem); + } + } } int MmsServer_waitReady(MmsServer self, unsigned int timeoutMs) { - return IsoServer_waitReady(self->isoServer, timeoutMs); + bool isFirst = true; + int result = 0; + + if (self->isoServerList) { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + int serverResult; + + if (isFirst) { + serverResult = IsoServer_waitReady(isoServer, timeoutMs); + isFirst = false; + } + else { + serverResult = IsoServer_waitReady(isoServer, 0); + } + + if (serverResult > 0) + result += serverResult; + + elem = LinkedList_getNext(elem); + } + } + + return result; } void MmsServer_handleIncomingMessages(MmsServer self) { - IsoServer_processIncomingMessages(self->isoServer); + if (self->isoServerList) { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_processIncomingMessages(isoServer); + + elem = LinkedList_getNext(elem); + } + } } void @@ -507,7 +704,21 @@ MmsServer_handleBackgroundTasks(MmsServer self) int MmsServer_getConnectionCounter(MmsServer self) { - return IsoServer_getConnectionCounter(self->isoServer); + int count = 0; + + if (self->isoServerList) { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + count += IsoServer_getConnectionCounter(isoServer); + + elem = LinkedList_getNext(elem); + } + } + + return count; } void @@ -521,6 +732,16 @@ MmsServer_callConnectionHandler(MmsServer self, MmsServerConnection connection) void MmsServer_stopListeningThreadless(MmsServer self) { - IsoServer_stopListeningThreadless(self->isoServer); + if (self->isoServerList) { + LinkedList elem = LinkedList_getNext(self->isoServerList); + + while (elem) { + IsoServer isoServer = (IsoServer) LinkedList_getData(elem); + + IsoServer_stopListeningThreadless(isoServer); + + elem = LinkedList_getNext(elem); + } + } } diff --git a/src/mms/iso_server/iso_server.c b/src/mms/iso_server/iso_server.c index 19615eee..40c263ab 100644 --- a/src/mms/iso_server/iso_server.c +++ b/src/mms/iso_server/iso_server.c @@ -70,7 +70,7 @@ struct sIsoServer { Socket serverSocket; int tcpPort; - const char* localIpAddress; + char* localIpAddress; TLSConfiguration tlsConfiguration; @@ -565,33 +565,35 @@ IsoServer_create(TLSConfiguration tlsConfiguration) { IsoServer self = (IsoServer) GLOBAL_CALLOC(1, sizeof(struct sIsoServer)); - self->state = ISO_SVR_STATE_IDLE; + if (self) { + self->state = ISO_SVR_STATE_IDLE; - if (tlsConfiguration == NULL) - self->tcpPort = TCP_PORT; - else - self->tcpPort = SECURE_TCP_PORT; + if (tlsConfiguration == NULL) + self->tcpPort = TCP_PORT; + else + self->tcpPort = SECURE_TCP_PORT; - self->tlsConfiguration = tlsConfiguration; + self->tlsConfiguration = tlsConfiguration; #if (CONFIG_MMS_THREADLESS_STACK != 1) - self->stateLock = Semaphore_create(1); + self->stateLock = Semaphore_create(1); #endif #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) - self->openClientConnections = LinkedList_create(); + self->openClientConnections = LinkedList_create(); #endif #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) - self->maxConnections = CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; + self->maxConnections = CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS; #endif #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) - self->connectionCounterMutex = Semaphore_create(1); - self->openClientConnectionsMutex = Semaphore_create(1); + self->connectionCounterMutex = Semaphore_create(1); + self->openClientConnectionsMutex = Semaphore_create(1); #endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */ - self->connectionCounter = 0; + self->connectionCounter = 0; + } return self; } @@ -613,7 +615,12 @@ IsoServer_setTcpPort(IsoServer self, int port) void IsoServer_setLocalIpAddress(IsoServer self, const char* ipAddress) { - self->localIpAddress = ipAddress; + GLOBAL_FREEMEM(self->localIpAddress); + + if (ipAddress) + self->localIpAddress = StringUtils_copyString(ipAddress); + else + self->localIpAddress = NULL; } IsoServerState @@ -795,41 +802,45 @@ IsoServer_setConnectionHandler(IsoServer self, ConnectionIndicationHandler handl void IsoServer_destroy(IsoServer self) { + if (self) { #if (CONFIG_MMS_THREADLESS_STACK != 1) - if (self->state == ISO_SVR_STATE_RUNNING) - IsoServer_stopListening(self); + if (self->state == ISO_SVR_STATE_RUNNING) + IsoServer_stopListening(self); #endif #if (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) #if (CONFIG_MMS_SINGLE_THREADED == 1) - if (self->openClientConnections != NULL) - LinkedList_destroy(self->openClientConnections); + if (self->openClientConnections != NULL) + LinkedList_destroy(self->openClientConnections); #else - if (self->openClientConnections != NULL) - LinkedList_destroyStatic(self->openClientConnections); + if (self->openClientConnections != NULL) + LinkedList_destroyStatic(self->openClientConnections); #endif /* (CONFIG_MMS_SINGLE_THREADED == 1) */ #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) - lockClientConnections(self); + lockClientConnections(self); #endif #endif /* (CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS == -1) */ #if (CONFIG_MMS_THREADLESS_STACK != 1) && (CONFIG_MMS_SINGLE_THREADED == 0) - Semaphore_destroy(self->connectionCounterMutex); - Semaphore_destroy(self->openClientConnectionsMutex); + Semaphore_destroy(self->connectionCounterMutex); + Semaphore_destroy(self->openClientConnectionsMutex); #endif - if (self->handleset) - Handleset_destroy(self->handleset); + if (self->handleset) + Handleset_destroy(self->handleset); #if (CONFIG_MMS_THREADLESS_STACK != 1) - Semaphore_destroy(self->stateLock); + Semaphore_destroy(self->stateLock); #endif - GLOBAL_FREEMEM(self); + GLOBAL_FREEMEM(self->localIpAddress); + + GLOBAL_FREEMEM(self); + } } void