Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
    }
}
Example #4
0
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;
    }
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #9
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);
}
Example #10
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;
    }
}