- fixed bug in reporting when write to RptEna=false when RptEna already is false

- allow client to set data set in RCB to empty string
- data set deletion will be denied if data set is referenced in a RCB
pull/6/head
Michael Zillgith 11 years ago
parent e461a0fb46
commit 1a95580f94

@ -1048,7 +1048,7 @@ createDataSets(MmsDevice* mmsDevice, IedModel* iedModel)
MmsDomain* dataSetDomain = MmsDevice_getDomain(mmsDevice, domainName); MmsDomain* dataSetDomain = MmsDevice_getDomain(mmsDevice, domainName);
MmsNamedVariableList varList = MmsNamedVariableList_create(dataset->name, false); MmsNamedVariableList varList = MmsNamedVariableList_create(dataSetDomain, dataset->name, false);
DataSetEntry* dataSetEntry = dataset->fcdas; DataSetEntry* dataSetEntry = dataset->fcdas;
@ -2052,6 +2052,73 @@ mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsS
return DATA_ACCESS_ERROR_SUCCESS; return DATA_ACCESS_ERROR_SUCCESS;
} }
static bool
variableListChangedHandler (void* parameter, bool create, MmsVariableListType listType, MmsDomain* domain,
char* listName, MmsServerConnection* connection)
{
bool allow = true;
#if (DEBUG_IED_SERVER == 1)
if (create)
printf("create data set ");
else
printf("delete data set ");
switch (listType) {
case MMS_VMD_SPECIFIC:
printf("VMD ");
break;
case MMS_ASSOCIATION_SPECIFIC:
printf("association ");
break;
case MMS_DOMAIN_SPECIFIC:
printf("domain ");
break;
}
printf("specific (name=%s)\n", listName);
#endif /* (DEBUG_IED_SERVER == 1) */
MmsMapping* self = (MmsMapping*) parameter;
if (create == false) {
/* Check if data set is referenced in a report */
LinkedList element = self->reportControls;
while ((element = LinkedList_getNext(element)) != NULL) {
ReportControl* rc = (ReportControl*) element->data;
if (rc->isDynamicDataSet) {
if (rc->dataSet != NULL) {
if (listType == MMS_DOMAIN_SPECIFIC) {
if (rc->dataSet->logicalDeviceName != NULL) {
if (strcmp(rc->dataSet->name, listName) == 0) {
if (strcmp(rc->dataSet->logicalDeviceName, MmsDomain_getName(domain)) == 0) {
allow = false;
break;
}
}
}
}
else if (listType == MMS_ASSOCIATION_SPECIFIC) {
if (rc->dataSet->logicalDeviceName == NULL) {
if (strcmp(rc->dataSet->name, listName) == 0) {
allow = false;
break;
}
}
}
}
}
}
}
return allow;
}
void void
MmsMapping_installHandlers(MmsMapping* self) MmsMapping_installHandlers(MmsMapping* self)
{ {
@ -2059,6 +2126,7 @@ MmsMapping_installHandlers(MmsMapping* self)
MmsServer_installWriteHandler(self->mmsServer, mmsWriteHandler, (void*) self); MmsServer_installWriteHandler(self->mmsServer, mmsWriteHandler, (void*) self);
MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self); MmsServer_installReadAccessHandler(self->mmsServer, mmsReadAccessHandler, (void*) self);
MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self); MmsServer_installConnectionHandler(self->mmsServer, mmsConnectionHandler, (void*) self);
MmsServer_installVariableListChangedHandler(self->mmsServer, variableListChangedHandler, (void*) self);
} }
void void
@ -2446,7 +2514,10 @@ MmsMapping_createDataSetByNamedVariableList(MmsMapping* self, MmsNamedVariableLi
{ {
DataSet* dataSet = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet)); DataSet* dataSet = (DataSet*) GLOBAL_MALLOC(sizeof(DataSet));
dataSet->logicalDeviceName = NULL; /* name is not relevant for dynamically created data set */ if (variableList->domain != NULL)
dataSet->logicalDeviceName = MmsDomain_getName(variableList->domain);
else
dataSet->logicalDeviceName = NULL; /* name is not relevant for association specific data sets */
dataSet->name = variableList->name; dataSet->name = variableList->name;
dataSet->elementCount = LinkedList_size(variableList->listOfVariables); dataSet->elementCount = LinkedList_size(variableList->listOfVariables);

@ -468,13 +468,17 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
MmsValue* dataSetValue; MmsValue* dataSetValue;
if (newDatSet != NULL) if (newDatSet != NULL) {
if (strcmp(MmsValue_toString(newDatSet), "") == 0) {
success = true;
dataSetValue = NULL;
}
else
dataSetValue = newDatSet; dataSetValue = newDatSet;
}
else else
dataSetValue = ReportControl_getRCBValue(rc, "DatSet"); dataSetValue = ReportControl_getRCBValue(rc, "DatSet");
char* dataSetName = MmsValue_toString(dataSetValue);
if (rc->isDynamicDataSet) { if (rc->isDynamicDataSet) {
if (rc->dataSet != NULL) { if (rc->dataSet != NULL) {
deleteDataSetValuesShadowBuffer(rc); deleteDataSetValuesShadowBuffer(rc);
@ -485,6 +489,8 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
} }
if (dataSetValue != NULL) { if (dataSetValue != NULL) {
char* dataSetName = MmsValue_toString(dataSetValue);
DataSet* dataSet = IedModel_lookupDataSet(mapping->model, dataSetName); DataSet* dataSet = IedModel_lookupDataSet(mapping->model, dataSetName);
if (dataSet == NULL) { if (dataSet == NULL) {
@ -1084,10 +1090,10 @@ updateOwner(ReportControl* rc, MmsServerConnection* connection)
if (connection != NULL) { if (connection != NULL) {
char* clientAddressString = MmsServerConnection_getClientAddress(connection); char* clientAddressString = MmsServerConnection_getClientAddress(connection);
if (DEBUG_IED_SERVER) printf("reporting.c: set owner to %s\n", clientAddressString); if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: set owner to %s\n", clientAddressString);
if (strchr(clientAddressString, '.') != NULL) { if (strchr(clientAddressString, '.') != NULL) {
if (DEBUG_IED_SERVER) printf("reporting.c: client address is IPv4 address\n"); if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: client address is IPv4 address\n");
{ {
uint8_t ipV4Addr[4]; uint8_t ipV4Addr[4];
@ -1114,7 +1120,7 @@ updateOwner(ReportControl* rc, MmsServerConnection* connection)
else { else {
uint8_t ipV6Addr[16]; uint8_t ipV6Addr[16];
MmsValue_setOctetString(owner, ipV6Addr, 0); MmsValue_setOctetString(owner, ipV6Addr, 0);
if (DEBUG_IED_SERVER) printf("reporting.c: client address is IPv6 address or unknown\n"); if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: client address is IPv6 address or unknown\n");
} }
} }
else { else {
@ -1219,6 +1225,9 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
} }
} }
else { else {
if (rc->enabled == false)
goto exit_function;
if (((rc->enabled) || (rc->reserved)) && (rc->clientConnection != connection)) { if (((rc->enabled) || (rc->reserved)) && (rc->clientConnection != connection)) {
retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; retVal = DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
goto exit_function; goto exit_function;
@ -1247,7 +1256,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (strcmp(elementName, "GI") == 0) { if (strcmp(elementName, "GI") == 0) {
if ((rc->enabled) && (rc->clientConnection == connection)) { if ((rc->enabled) && (rc->clientConnection == connection)) {
if (MmsValue_getBoolean(value))
rc->gi = true; rc->gi = true;
retVal = DATA_ACCESS_ERROR_SUCCESS; retVal = DATA_ACCESS_ERROR_SUCCESS;
goto exit_function; goto exit_function;
} }
@ -1299,7 +1311,6 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function; goto exit_function;
} }
} }
retVal = DATA_ACCESS_ERROR_SUCCESS; retVal = DATA_ACCESS_ERROR_SUCCESS;
@ -1381,6 +1392,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
goto exit_function; goto exit_function;
} }
else if (strcmp(elementName, "SqNum") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "Owner") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
MmsValue* rcbValue = ReportControl_getRCBValue(rc, elementName); MmsValue* rcbValue = ReportControl_getRCBValue(rc, elementName);

@ -38,6 +38,7 @@ extern "C" {
struct sMmsNamedVariableList { struct sMmsNamedVariableList {
bool deletable; bool deletable;
MmsDomain* domain;
char* name; char* name;
LinkedList listOfVariables; LinkedList listOfVariables;
}; };
@ -55,11 +56,14 @@ char*
MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self); MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self);
MmsNamedVariableList MmsNamedVariableList
MmsNamedVariableList_create(char* name, bool deletable); MmsNamedVariableList_create(MmsDomain* domain, char* name, bool deletable);
char* char*
MmsNamedVariableList_getName(MmsNamedVariableList self); MmsNamedVariableList_getName(MmsNamedVariableList self);
MmsDomain*
MmsNamedVariableList_getDomain(MmsNamedVariableList self);
bool bool
MmsNamedVariableList_isDeletable(MmsNamedVariableList self); MmsNamedVariableList_isDeletable(MmsNamedVariableList self);

@ -62,17 +62,24 @@ MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self) {
} }
MmsNamedVariableList MmsNamedVariableList
MmsNamedVariableList_create(char* name, bool deletable) MmsNamedVariableList_create(MmsDomain* domain, char* name, bool deletable)
{ {
MmsNamedVariableList self = (MmsNamedVariableList) GLOBAL_MALLOC(sizeof(struct sMmsNamedVariableList)); MmsNamedVariableList self = (MmsNamedVariableList) GLOBAL_MALLOC(sizeof(struct sMmsNamedVariableList));
self->deletable = deletable; self->deletable = deletable;
self->name = copyString(name); self->name = copyString(name);
self->listOfVariables = LinkedList_create(); self->listOfVariables = LinkedList_create();
self->domain = domain;
return self; return self;
} }
MmsDomain*
MmsNamedVariableList_getDomain(MmsNamedVariableList self)
{
return self->domain;
}
char* char*
MmsNamedVariableList_getName(MmsNamedVariableList self) MmsNamedVariableList_getName(MmsNamedVariableList self)
{ {

@ -236,7 +236,7 @@ checkIfVariableExists(MmsDevice* device, MmsAccessSpecifier* accessSpecifier)
static MmsNamedVariableList static MmsNamedVariableList
createNamedVariableList(MmsDevice* device, createNamedVariableList(MmsDomain* domain, MmsDevice* device,
DefineNamedVariableListRequest_t* request, DefineNamedVariableListRequest_t* request,
char* variableListName, MmsError* mmsError) char* variableListName, MmsError* mmsError)
{ {
@ -249,7 +249,7 @@ createNamedVariableList(MmsDevice* device,
goto exit_function; goto exit_function;
} }
namedVariableList = MmsNamedVariableList_create(variableListName, true); namedVariableList = MmsNamedVariableList_create(domain, variableListName, true);
int i; int i;
for (i = 0; i < variableCount; i++) { for (i = 0; i < variableCount; i++) {
@ -315,11 +315,11 @@ createNamedVariableList(MmsDevice* device,
varSpec->choice.name.choice.domainspecific.domainId.buf, varSpec->choice.name.choice.domainspecific.domainId.buf,
varSpec->choice.name.choice.domainspecific.domainId.size); varSpec->choice.name.choice.domainspecific.domainId.size);
MmsDomain* domain = MmsDevice_getDomain(device, domainId); MmsDomain* elementDomain = MmsDevice_getDomain(device, domainId);
MmsAccessSpecifier accessSpecifier; MmsAccessSpecifier accessSpecifier;
accessSpecifier.domain = domain; accessSpecifier.domain = elementDomain;
accessSpecifier.variableName = variableName; accessSpecifier.variableName = variableName;
accessSpecifier.arrayIndex = arrayIndex; accessSpecifier.arrayIndex = arrayIndex;
accessSpecifier.componentName = componentName; accessSpecifier.componentName = componentName;
@ -412,7 +412,7 @@ mmsServer_handleDefineNamedVariableListRequest(
else { else {
MmsError mmsError; MmsError mmsError;
MmsNamedVariableList namedVariableList = createNamedVariableList(device, MmsNamedVariableList namedVariableList = createNamedVariableList(domain, device,
request, variableListName, &mmsError); request, variableListName, &mmsError);
if (namedVariableList != NULL) { if (namedVariableList != NULL) {
@ -456,7 +456,7 @@ mmsServer_handleDefineNamedVariableListRequest(
else { else {
MmsError mmsError; MmsError mmsError;
MmsNamedVariableList namedVariableList = createNamedVariableList(device, MmsNamedVariableList namedVariableList = createNamedVariableList(NULL, device,
request, variableListName, &mmsError); request, variableListName, &mmsError);
if (namedVariableList != NULL) { if (namedVariableList != NULL) {

Loading…
Cancel
Save