diff --git a/src/mms/inc/mms_server.h b/src/mms/inc/mms_server.h index 1a91a35..1b42f5a 100644 --- a/src/mms/inc/mms_server.h +++ b/src/mms/inc/mms_server.h @@ -32,9 +32,10 @@ extern "C" { #endif +#include "stack_config.h" + #include "mms_device_model.h" #include "mms_value.h" - #include "iso_server.h" typedef enum { @@ -67,9 +68,11 @@ typedef struct sMmsServerConnection { int maxPduSize; /* local detail */ IsoConnection isoConnection; MmsServer server; - LinkedList /**/namedVariableLists; /* aa-specific named variable lists */ - uint32_t lastInvokeId; + uint32_t lastInvokeId; +#if (MMS_DYNAMIC_DATA_SETS == 1) + LinkedList /**/namedVariableLists; /* aa-specific named variable lists */ +#endif #if (MMS_FILE_SERVICE == 1) int32_t nextFrsmId; @@ -78,6 +81,12 @@ typedef struct sMmsServerConnection { } MmsServerConnection; +typedef enum { + MMS_DOMAIN_SPECIFIC, + MMS_ASSOCIATION_SPECIFIC, + MMS_VMD_SPECIFIC +} MmsVariableListType; + typedef MmsValue* (*MmsReadVariableHandler)(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection* connection); @@ -127,6 +136,32 @@ MmsServer_getValueFromCache(MmsServer self, MmsDomain* domain, char* itemId); bool MmsServer_isLocked(MmsServer self); +/** + * \brief callback handler that is called whenever a named variable list changes + * + * \param parameter a user provided parameter + * \param create if true the the request if a request to create a new variable list, false is a delete request + * \param listType the type (scope) of the named variable list (either domain, association or VMD specific) + * \param domain the MMS domain the list is belonging to (is NULL for association or VMD specific lists!) + * \param listName the name + * \param connection client connection that requests the creation of deletion of the variable list + * + * \return true if operation has to be accepted, false if operation has to be rejected. In case of false an error message + * is returned to the client. + */ +typedef bool (*MmsNamedVariableListChangedHandler)(void* parameter, bool create, MmsVariableListType listType, MmsDomain* domain, + char* listName, MmsServerConnection* connection); + +/** + * \brief Install callback handler that is called when a named variable list changes (is created or deleted) + * + * \param self the MmsServer instance to operate on + * \param handler the callback handler function + * \param parameter user provided parameter that is passed to the callback handler + */ +void +MmsServer_installVariableListChangedHandler(MmsServer self, MmsNamedVariableListChangedHandler handler, void* parameter); + /** * \brief lock the cached server data model * diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index 69a9cef..b6ebb4f 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -74,6 +74,9 @@ struct sMmsServer { MmsConnectionHandler connectionHandler; void* connectionHandlerParameter; + MmsNamedVariableListChangedHandler variableListChangedHandler; + void* variableListChangedHandlerParameter; + Map openConnections; Map valueCaches; bool isLocked; @@ -82,14 +85,14 @@ struct sMmsServer { Semaphore modelMutex; #endif -#if MMS_STATUS_SERVICE == 1 +#if (MMS_STATUS_SERVICE == 1) int vmdLogicalStatus; int vmdPhysicalStatus; MmsStatusRequestListener statusRequestListener; void* statusRequestListenerParameter; #endif /* MMS_STATUS_SERVICE == 1 */ -#if MMS_IDENTIFY_SERVICE == 1 +#if (MMS_IDENTIFY_SERVICE == 1) char* vendorName; char* modelName; char* revision; @@ -245,4 +248,8 @@ mmsServer_createMmsWriteResponse(MmsServerConnection* connection, void mmsServer_writeMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response); +bool +mmsServer_callVariableListChangedHandler(bool create, MmsVariableListType listType, MmsDomain* domain, + char* listName, MmsServerConnection* connection); + #endif /* MMS_SERVER_INTERNAL_H_ */ diff --git a/src/mms/iso_mms/server/mms_named_variable_list_service.c b/src/mms/iso_mms/server/mms_named_variable_list_service.c index b9a801b..9714d89 100644 --- a/src/mms/iso_mms/server/mms_named_variable_list_service.c +++ b/src/mms/iso_mms/server/mms_named_variable_list_service.c @@ -1,24 +1,24 @@ /* * mms_named_variable_list_service.c * - * Copyright 2013, 2014 Michael Zillgith + * Copyright 2013-2015 Michael Zillgith * * This file is part of libIEC61850. * - * libIEC61850 is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * libIEC61850 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * libIEC61850 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * libIEC61850 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with libIEC61850. If not, see . + * You should have received a copy of the GNU General Public License + * along with libIEC61850. If not, see . * - * See COPYING file for the complete license text. + * See COPYING file for the complete license text. */ #include "mms_server_internal.h" @@ -47,6 +47,19 @@ #define CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS 50 #endif +bool +mmsServer_callVariableListChangedHandler(bool create, MmsVariableListType listType, MmsDomain* domain, + char* listName, MmsServerConnection* connection) +{ + MmsServer self = connection->server; + + if (self->variableListChangedHandler != NULL) + return self->variableListChangedHandler(self->variableListChangedHandlerParameter, + create, listType, domain, listName, connection); + else + return true; +} + static void createDeleteNamedVariableListResponse(uint32_t invokeId, ByteBuffer* response, uint32_t numberMatched, uint32_t numberDeleted) @@ -117,41 +130,46 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection* connection, for (i = 0; i < numberItems; i++) { if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_domainspecific) { - char domainIdStr[65]; - char nameIdStr[65]; + char domainName[65]; + char listName[65]; mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.domainspecific.domainId, - domainIdStr, 65); + domainName, 65); mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.domainspecific.itemId, - nameIdStr, 65); + listName, 65); - MmsDomain* domain = MmsDevice_getDomain(device, domainIdStr); + MmsDomain* domain = MmsDevice_getDomain(device, domainName); - MmsNamedVariableList variableList = MmsDomain_getNamedVariableList(domain, nameIdStr); + MmsNamedVariableList variableList = MmsDomain_getNamedVariableList(domain, listName); if (variableList != NULL) { numberMatched++; if (MmsNamedVariableList_isDeletable(variableList)) { - MmsDomain_deleteNamedVariableList(domain, nameIdStr); - numberDeleted++; + + if (mmsServer_callVariableListChangedHandler(false, MMS_DOMAIN_SPECIFIC, domain, listName, connection) == true) { + MmsDomain_deleteNamedVariableList(domain, listName); + numberDeleted++; + } } } } else if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_aaspecific) { - char itemId[65]; + char listName[65]; mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.aaspecific, - itemId, 65); + listName, 65); - MmsNamedVariableList variableList = MmsServerConnection_getNamedVariableList(connection, itemId); + MmsNamedVariableList variableList = MmsServerConnection_getNamedVariableList(connection, listName); if (variableList != NULL) { numberMatched++; - numberDeleted++; - MmsServerConnection_deleteNamedVariableList(connection, itemId); + if (mmsServer_callVariableListChangedHandler(false, MMS_ASSOCIATION_SPECIFIC, NULL, listName, connection) == true) { + numberDeleted++; + MmsServerConnection_deleteNamedVariableList(connection, listName); + } } } } @@ -398,8 +416,15 @@ mmsServer_handleDefineNamedVariableListRequest( request, variableListName, &mmsError); if (namedVariableList != NULL) { - MmsDomain_addNamedVariableList(domain, namedVariableList); - createDefineNamedVariableListResponse(invokeId, response); + + if (mmsServer_callVariableListChangedHandler(true, MMS_DOMAIN_SPECIFIC, domain, variableListName, connection) == true) { + MmsDomain_addNamedVariableList(domain, namedVariableList); + createDefineNamedVariableListResponse(invokeId, response); + } + else { + MmsNamedVariableList_destroy(namedVariableList); + mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); + } } else mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError); @@ -435,8 +460,16 @@ mmsServer_handleDefineNamedVariableListRequest( request, variableListName, &mmsError); if (namedVariableList != NULL) { - MmsServerConnection_addNamedVariableList(connection, namedVariableList); - createDefineNamedVariableListResponse(invokeId, response); + + if (mmsServer_callVariableListChangedHandler(true, MMS_ASSOCIATION_SPECIFIC, NULL, variableListName, connection) == true) { + MmsServerConnection_addNamedVariableList(connection, namedVariableList); + createDefineNamedVariableListResponse(invokeId, response); + } + else { + MmsNamedVariableList_destroy(namedVariableList); + mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED); + } + } else mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError); diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index 6f4f07a..76ab58f 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -112,6 +112,13 @@ MmsServer_installConnectionHandler(MmsServer self, MmsConnectionHandler connecti self->connectionHandlerParameter = parameter; } +void +MmsServer_installVariableListChangedHandler(MmsServer self, MmsNamedVariableListChangedHandler handler, void* parameter) +{ + self->variableListChangedHandler = handler; + self->variableListChangedHandlerParameter = parameter; +} + void MmsServer_setClientAuthenticator(MmsServer self, AcseAuthenticator authenticator, void* authenticatorParameter) {