- IED server: added new function IedServer_handleWriteAccessForComplexAttribute. Changed WriteAccessHandler behavior when ACCESS_POLICY_ALLOW.

pull/331/head
Michael Zillgith 5 years ago
parent cc905b5013
commit 842bc271cd

@ -1615,6 +1615,10 @@ typedef MmsDataAccessError
* or denied. If a WriteAccessHandler is set for a specific data attribute - the
* default write access policy will not be performed for that data attribute.
*
* NOTE: If the data attribute has sub data attributes, the WriteAccessHandler is not
* set for the sub data attributes and will not be called when the sub data attribute is
* written directly!
*
* \param self the instance of IedServer to operate on.
* \param dataAttribute the data attribute to monitor
* \param handler the callback function that is invoked if a client tries to write to
@ -1625,6 +1629,29 @@ LIB61850_API void
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute,
WriteAccessHandler handler, void* parameter);
/**
* \brief Install a WriteAccessHandler for a data attribute and for all sub data attributes
*
* This instructs the server to monitor write attempts by MMS clients to specific
* data attributes. If a client tries to write to the monitored data attribute the
* handler is invoked. The handler can decide if the write access will be allowed
* or denied. If a WriteAccessHandler is set for a specific data attribute - the
* default write access policy will not be performed for that data attribute.
*
* When the data attribute is a complex attribute then the handler will also be installed
* for all sub data attributes. When the data attribute is a basic data attribute then
* this function behaves like \ref IedServer_handleWriteAccess.
*
* \param self the instance of IedServer to operate on.
* \param dataAttribute the data attribute to monitor
* \param handler the callback function that is invoked if a client tries to write to
* the monitored data attribute.
* \param parameter a user provided parameter that is passed to the WriteAccessHandler when called.
*/
LIB61850_API void
IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* dataAttribute,
WriteAccessHandler handler, void* parameter);
typedef enum {
ACCESS_POLICY_ALLOW,
ACCESS_POLICY_DENY

@ -1512,6 +1512,26 @@ IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteA
}
}
void
IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
{
if (dataAttribute == NULL) {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: IedServer_handleWriteAccessForComplexAttribute - dataAttribute == NULL!\n");
}
else {
MmsMapping_installWriteAccessHandler(self->mmsMapping, dataAttribute, handler, parameter);
DataAttribute* subDa = (DataAttribute*) dataAttribute->firstChild;
while (subDa) {
IedServer_handleWriteAccessForComplexAttribute(self, subDa, handler, parameter);
subDa = (DataAttribute*) subDa->sibling;
}
}
}
void
IedServer_setReadAccessHandler(IedServer self, ReadAccessHandler handler, void* parameter)
{

@ -1,7 +1,7 @@
/*
* mms_mapping.c
*
* Copyright 2013-2019 Michael Zillgith
* Copyright 2013-2021 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -2374,6 +2374,7 @@ writeAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variable
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if 0
static MmsValue*
checkIfValueBelongsToModelNode(DataAttribute* dataAttribute, MmsValue* value, MmsValue* newValue)
{
@ -2408,6 +2409,7 @@ checkIfValueBelongsToModelNode(DataAttribute* dataAttribute, MmsValue* value, Mm
return NULL;
}
#endif
static FunctionalConstraint
getFunctionalConstraintForWritableNode(char* separator)
@ -2813,51 +2815,25 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
AttributeAccessHandler* accessHandler = (AttributeAccessHandler*) writeHandlerListElement->data;
DataAttribute* dataAttribute = accessHandler->attribute;
if (nodeAccessPolicy == ACCESS_POLICY_ALLOW) {
MmsValue* matchingValue = checkIfValueBelongsToModelNode(dataAttribute, cachedValue, value);
if (dataAttribute->mmsValue == cachedValue) {
if (matchingValue != NULL) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, value, clientConnection,
accessHandler->parameter);
MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, matchingValue, clientConnection,
accessHandler->parameter);
if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) {
handlerFound = true;
if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) {
handlerFound = true;
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)
updateValue = false;
}
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)
updateValue = false;
else
return handlerResult;
}
}
else { /* if ACCESS_POLICY_DENY only allow direct access to handled data attribute */
if (dataAttribute->mmsValue == cachedValue) {
ClientConnection clientConnection = private_IedServer_getClientConnectionByHandle(self->iedServer,
connection);
MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, value, clientConnection,
accessHandler->parameter);
if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) {
handlerFound = true;
if (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)
updateValue = false;
break;
}
else
return handlerResult;
break;
}
else
return handlerResult;
}
writeHandlerListElement = LinkedList_getNext(writeHandlerListElement);

Loading…
Cancel
Save