MmsValueIndication MmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value) { MmsValueIndication indication; if (self->writeHandler != NULL) { indication = self->writeHandler(self->writeHandlerParameter, domain, itemId, value); } else { //TODO if value in cache write to cache //else access denied MmsValue* cachedValue; cachedValue = MmsServer_getValueFromCache(self, domain, itemId); if (cachedValue != NULL) { MmsValue_update(cachedValue, value); indication = MMS_VALUE_OK; } else indication = MMS_VALUE_ACCESS_DENIED; } return indication; }
MmsDataAccessError mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value, MmsServerConnection* connection) { MmsDataAccessError indication; if (self->writeHandler != NULL) { indication = self->writeHandler(self->writeHandlerParameter, domain, itemId, value, connection); } else { MmsValue* cachedValue; if (domain == NULL) domain = (MmsDomain*) self->device; cachedValue = MmsServer_getValueFromCache(self, domain, itemId); if (cachedValue != NULL) { MmsValue_update(cachedValue, value); indication = DATA_ACCESS_ERROR_SUCCESS; } else indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; } return indication; }
static void updateDataSetsWithCachedValues(IedServer self) { DataSet* dataSet = self->model->dataSets; while (dataSet != NULL) { DataSetEntry* dataSetEntry = dataSet->fcdas; while (dataSetEntry != NULL) { MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, dataSetEntry->logicalDeviceName); MmsValue* value = MmsServer_getValueFromCache(self->mmsServer, domain, dataSetEntry->variableName); if (value == NULL) { if (DEBUG_IED_SERVER) { printf("LD: %s dataset: %s : error cannot get value from cache for %s -> %s!\n", dataSet->logicalDeviceName, dataSet->name, dataSetEntry->logicalDeviceName, dataSetEntry->variableName); } } else dataSetEntry->value = value; dataSetEntry = dataSetEntry->sibling; } dataSet = dataSet->sibling; } }
static void initialize(ControlObject* self) { if (emptyString == NULL) emptyString = MmsValue_newVisibleString(NULL); if (!(self->initialized)) { char* ctlModelName = createString(4, self->lnName, "$CF$", self->name, "$ctlModel"); MmsValue* ctlModel = MmsServer_getValueFromCache(self->mmsServer, self->mmsDomain, ctlModelName); free(ctlModelName); if (ctlModel != NULL) { uint32_t ctlModelVal = MmsValue_toInt32(ctlModel); self->ctlModel = ctlModelVal; if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */ char* sboTimeoutName = createString(4, self->lnName, "$CF$", self->name, "$sboTimeout"); char* controlObjectReference = createString(6, self->mmsDomain->domainName, "/", self->lnName, "$", self->name, "$SBO"); self->sbo = MmsValue_newVisibleString(controlObjectReference); MmsValue* sboTimeout = MmsServer_getValueFromCache(self->mmsServer, self->mmsDomain, sboTimeoutName); free(controlObjectReference); free(sboTimeoutName); if (sboTimeout != NULL) { uint32_t sboTimeoutVal = MmsValue_toInt32(sboTimeout); self->selectTimeout = sboTimeoutVal; } } else { self->sbo = emptyString; } } self->initialized = true; } }
MmsValue* MmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId) { MmsValue* value = NULL; value = MmsServer_getValueFromCache(self, domain, itemId); if (value == NULL) if (self->readHandler != NULL) value = self->readHandler(self->readHandlerParameter, domain, itemId); return value; }
MmsValue* IedServer_getFunctionalConstrainedData(IedServer self, DataObject* dataObject, FunctionalConstraint fc) { char buffer[128]; /* buffer for variable name string */ char* currentStart = buffer + 127; currentStart[0] = 0; int nameLen; while (dataObject->modelType == DataObjectModelType) { nameLen = strlen(dataObject->name); currentStart -= nameLen; memcpy(currentStart, dataObject->name, nameLen); currentStart--; *currentStart = '$'; if (dataObject->parent->modelType == DataObjectModelType) dataObject = (DataObject*) dataObject->parent; else break; } char* fcString = FunctionalConstraint_toString(fc); currentStart--; *currentStart = fcString[1]; currentStart--; *currentStart = fcString[0]; currentStart--; *currentStart = '$'; LogicalNode* ln = (LogicalNode*) dataObject->parent; nameLen = strlen(ln->name); currentStart -= nameLen; memcpy(currentStart, ln->name, nameLen); LogicalDevice* ld = (LogicalDevice*) ln->parent; MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, ld->name); MmsValue* value = MmsServer_getValueFromCache(self->mmsServer, domain, currentStart); return value; }
static void installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribute, char* objectReference, int position) { sprintf(objectReference + position, ".%s", dataAttribute->name); char mmsVariableName[65]; /* maximum size is 64 according to 61850-8-1 */ MmsValue* value = dataAttribute->mmsValue; MmsMapping_createMmsVariableNameFromObjectReference(objectReference, dataAttribute->fc, mmsVariableName); char domainName[65]; MmsMapping_getMmsDomainFromObjectReference(objectReference, domainName); MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, domainName); if (domain == NULL) { if (DEBUG_IED_SERVER) printf("Error domain (%s) not found!\n", domainName); return; } MmsValue* cacheValue = MmsServer_getValueFromCache(self->mmsServer, domain, mmsVariableName); dataAttribute->mmsValue = cacheValue; if (value != NULL) { MmsValue_update(cacheValue, value); MmsValue_delete(value); } int childPosition = strlen(objectReference); DataAttribute* subDataAttribute = (DataAttribute*) dataAttribute->firstChild; while (subDataAttribute != NULL) { installDefaultValuesForDataAttribute(self, subDataAttribute, objectReference, childPosition); subDataAttribute = (DataAttribute*) subDataAttribute->sibling; } }
/********************************************************************************************** * mmsServer_handleWriteRequest * возвращает MmsServiceError *********************************************************************************************/ int mmsServer_handleWriteRequest( MmsServerConnection* connection, WriteRequest_t* writeRequest, int invokeId, ByteBuffer* response) { ListOfVariableSeq_t* varSpec; Identifier_t domainId; char* domainIdStr; MmsDevice* device; MmsDomain* domain; Identifier_t nameId; char* nameIdStr; MmsTypeSpecification* variable; AlternateAccess_t* alternateAccess; Data_t* dataElement; MmsValue* value; MmsValueIndication valueIndication; if (writeRequest->variableAccessSpecification.choice.listOfVariable.list.count != 1) return -1; varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); device = MmsServer_getDevice(connection->server); domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); return 0; } nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) goto return_access_denied; if (writeRequest->listOfData.list.count != 1) goto return_access_denied; alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) goto return_access_denied; if (!mmsServer_isIndexAccess(alternateAccess)) goto return_access_denied; } dataElement = writeRequest->listOfData.list.array[0]; value = mmsMsg_parseDataElement(dataElement); if (value == NULL) goto return_access_denied; if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); int index; MmsValue* elementValue; if (cachedArray == NULL) { MmsValue_delete(value); goto return_access_denied; } index = mmsServer_getLowIndex(alternateAccess); elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { MmsValue_delete(value); goto return_access_denied; } if (MmsValue_update(elementValue, value) == false) { MmsValue_delete(value); goto return_access_denied; } } MmsServer_lockModel(connection->server); valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); MmsServer_unlockModel(connection->server); createMmsWriteResponse(connection, invokeId, response, valueIndication); MmsValue_delete(value); free(nameIdStr); return 0; return_access_denied: createMmsWriteResponse(connection, invokeId, response, MMS_VALUE_ACCESS_DENIED); free(nameIdStr); return 0; }
void mmsServer_handleWriteRequest( MmsServerConnection* connection, uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeId, ByteBuffer* response) { WriteRequest_t* writeRequest = 0; MmsPdu_t* mmsPdu = 0; asn_dec_rval_t rval; /* Decoder return value */ rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, CONFIG_MMS_MAXIMUM_PDU_SIZE); if (rval.code != RC_OK) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } writeRequest = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.write); int numberOfWriteItems = writeRequest->variableAccessSpecification.choice.listOfVariable.list.count; if (numberOfWriteItems < 1) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } if (numberOfWriteItems > CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_OTHER, response); return; } if (writeRequest->listOfData.list.count != numberOfWriteItems) { mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response); return; } MmsDataAccessError accessResults[CONFIG_MMS_WRITE_SERVICE_MAX_NUMBER_OF_WRITE_ITEMS * sizeof(MmsDataAccessError)]; bool sendResponse = true; int i; for (i = 0; i < numberOfWriteItems; i++) { ListOfVariableSeq_t* varSpec = writeRequest->variableAccessSpecification.choice.listOfVariable.list.array[i]; if (varSpec->variableSpecification.present != VariableSpecification_PR_name) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } if (varSpec->variableSpecification.choice.name.present != ObjectName_PR_domainspecific) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } Identifier_t domainId = varSpec->variableSpecification.choice.name.choice.domainspecific.domainId; char* domainIdStr = createStringFromBuffer(domainId.buf, domainId.size); MmsDevice* device = MmsServer_getDevice(connection->server); MmsDomain* domain = MmsDevice_getDomain(device, domainIdStr); free(domainIdStr); if (domain == NULL) { accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } Identifier_t nameId = varSpec->variableSpecification.choice.name.choice.domainspecific.itemId; char* nameIdStr = createStringFromBuffer(nameId.buf, nameId.size); MmsVariableSpecification* variable = MmsDomain_getNamedVariable(domain, nameIdStr); if (variable == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT; continue; } AlternateAccess_t* alternateAccess = varSpec->alternateAccess; if (alternateAccess != NULL) { if (variable->type != MMS_ARRAY) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (!mmsServer_isIndexAccess(alternateAccess)) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ACCESS_UNSUPPORTED; continue; } } Data_t* dataElement = writeRequest->listOfData.list.array[i]; MmsValue* value = mmsMsg_parseDataElement(dataElement); if (value == NULL) { free(nameIdStr); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (alternateAccess != NULL) { MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr); if (cachedArray == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } int index = mmsServer_getLowIndex(alternateAccess); MmsValue* elementValue = MmsValue_getElement(cachedArray, index); if (elementValue == NULL) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; continue; } if (MmsValue_update(elementValue, value) == false) { free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT; continue; } free(nameIdStr); MmsValue_delete(value); accessResults[i] = DATA_ACCESS_ERROR_SUCCESS; continue; } MmsDataAccessError valueIndication = mmsServer_setValue(connection->server, domain, nameIdStr, value, connection); if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE) sendResponse = false; accessResults[i] = valueIndication; MmsValue_delete(value); free(nameIdStr); } if (sendResponse) { mmsServer_createMmsWriteResponse(connection, invokeId, response, numberOfWriteItems, accessResults); } asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); }
static void initialize(ControlObject* self) { if (!(self->initialized)) { MmsServer mmsServer = IedServer_getMmsServer(self->iedServer); self->emptyString = MmsValue_newVisibleString(NULL); char* ctlModelName = createString(4, self->lnName, "$CF$", self->name, "$ctlModel"); if (DEBUG_IED_SERVER) printf("initialize control for %s\n", ctlModelName); MmsValue* ctlModel = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, ctlModelName); if (ctlModel == NULL) { if (DEBUG_IED_SERVER) printf("No control model found for variable %s\n", ctlModelName); } GLOBAL_FREEMEM(ctlModelName); char* sboClassName = createString(4, self->lnName, "$CF$", self->name, "$sboClass"); self->sboClass = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, sboClassName); GLOBAL_FREEMEM(sboClassName); self->ctlObjectName = (char*) GLOBAL_MALLOC(130); StringUtils_createStringInBuffer(self->ctlObjectName, 5, MmsDomain_getName(self->mmsDomain), "/", self->lnName, "$CO$", self->name); self->error = MmsValue_newIntegerFromInt32(0); self->addCause = MmsValue_newIntegerFromInt32(0); if (ctlModel != NULL) { uint32_t ctlModelVal = MmsValue_toInt32(ctlModel); self->ctlModel = ctlModelVal; if (DEBUG_IED_SERVER) printf(" ctlModel: %i\n", ctlModelVal); if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */ char* sboTimeoutName = createString(4, self->lnName, "$CF$", self->name, "$sboTimeout"); char* controlObjectReference = createString(6, self->mmsDomain->domainName, "/", self->lnName, "$", self->name, "$SBO"); self->sbo = MmsValue_newVisibleString(controlObjectReference); self->sboTimeout = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, sboTimeoutName); updateSboTimeoutValue(self); setState(self, STATE_UNSELECTED); if (DEBUG_IED_SERVER) printf("timeout for %s is %i\n", sboTimeoutName, self->selectTimeout); GLOBAL_FREEMEM(controlObjectReference); GLOBAL_FREEMEM(sboTimeoutName); } else { self->sbo = MmsValue_newVisibleString(NULL); setState(self, STATE_READY); } } self->initialized = true; } }