static int
createVariableAccessAttributesResponse(
		MmsServerConnection* connection,
		char* domainId,
		char* nameId,
		int invokeId,
		ByteBuffer* response)
{
	MmsDevice* device = MmsServer_getDevice(connection->server);

	MmsDomain* domain = MmsDevice_getDomain(device, domainId);

	if (domain == NULL) {
		if (DEBUG) printf("mms_server: domain %s not known\n", domainId);
		return -1;
	}

	MmsTypeSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameId);

	if (namedVariable == NULL) {
		if (DEBUG) printf("mms_server: named variable %s not known\n", nameId);
		return -1;
	}

	MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);

	mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
			ConfirmedServiceResponse_PR_getVariableAccessAttributes;

	GetVariableAccessAttributesResponse_t* getVarAccessAttr;

	getVarAccessAttr = &(mmsPdu->choice.confirmedResponsePdu.
			confirmedServiceResponse.choice.getVariableAccessAttributes);

	getVarAccessAttr->mmsDeletable = 0;

	createTypeSpecification(namedVariable, &getVarAccessAttr->typeSpecification);

	asn_enc_rval_t rval;

	rval = der_encode(&asn_DEF_MmsPdu, mmsPdu,
			mmsServer_write_out, (void*) response);

	if (DEBUG) xer_fprint(stdout, &asn_DEF_MmsPdu, mmsPdu);

	deleteVariableAccessAttributesResponse(getVarAccessAttr);

	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

	return 0;
}
void
mmsServer_handleGetNamedVariableListAttributesRequest(
    MmsServerConnection* connection,
    GetNamedVariableListAttributesRequest_t* request,
    int invokeId,
    ByteBuffer* response)
{
    if (request->present == ObjectName_PR_domainspecific) {

        char* domainName = createStringFromBuffer(
                               request->choice.domainspecific.domainId.buf,
                               request->choice.domainspecific.domainId.size);

        char* itemName = createStringFromBuffer(
                             request->choice.domainspecific.itemId.buf,
                             request->choice.domainspecific.itemId.size);

        MmsDevice* mmsDevice = MmsServer_getDevice(connection->server);

        MmsDomain* domain = MmsDevice_getDomain(mmsDevice, domainName);

        if (domain != NULL) {
            MmsNamedVariableList variableList =
                MmsDomain_getNamedVariableList(domain, itemName);

            if (variableList != NULL)
                createGetNamedVariableListAttributesResponse(invokeId, response, variableList, domainName);
            else
                mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);
        }
        else
            mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);


        free(domainName);
        free(itemName);
    }
    else {
        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);
    }
}
static void
handleReadNamedVariableListRequest(
		MmsServerConnection* connection,
		ReadRequest_t* read,
		int invokeId,
		ByteBuffer* response)
{
	if (read->variableAccessSpecification.choice.variableListName.present ==
			ObjectName_PR_domainspecific)
	{
		char* domainId = mmsMsg_createStringFromAsnIdentifier(
				read->variableAccessSpecification.choice.variableListName.choice.domainspecific.domainId);

		char* listName = mmsMsg_createStringFromAsnIdentifier(
				read->variableAccessSpecification.choice.variableListName.choice.domainspecific.itemId);

		VarAccessSpec accessSpec;

		accessSpec.isNamedVariableList = true;
		accessSpec.specific = 1;
		accessSpec.domainId = domainId;
		accessSpec.itemId = listName;

		MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainId);

		if (domain == NULL) {
			if (DEBUG) printf("MMS read: domain %s not found!\n", domainId);
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);
		}
		else {
			MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, listName);

			if (namedList != NULL) {
				createNamedVariableListResponse(connection, namedList, invokeId, response, read,
						&accessSpec);
			}
			else {
				if (DEBUG) printf("MMS read: named variable list %s not found!\n", listName);
				mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);
			}
		}

		free(domainId);
		free(listName);
	}
	else if (read->variableAccessSpecification.choice.variableListName.present ==
				ObjectName_PR_aaspecific)
	{
		char* listName = mmsMsg_createStringFromAsnIdentifier(read->variableAccessSpecification.
				choice.variableListName.choice.aaspecific);

		MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName);

		VarAccessSpec accessSpec;

		accessSpec.isNamedVariableList = true;
		accessSpec.specific = 2;
		accessSpec.domainId = NULL;
		accessSpec.itemId = listName;

		if (namedList == NULL)
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);
		else {
			createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec);
		}

		free(listName);
	}
	else
		mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);
}
static void
handleReadListOfVariablesRequest(
		MmsServerConnection* connection,
		ReadRequest_t* read,
		uint32_t invokeId,
		ByteBuffer* response)
{
	int variableCount = read->variableAccessSpecification.choice.listOfVariable.list.count;

	LinkedList /*<MmsValue>*/ values = LinkedList_create();

	if (isSpecWithResult(read)) { /* add specification to result */
		//TODO add va spec to result
	}

	MmsServer_lockModel(connection->server);

	int i;

	for (i = 0; i < variableCount; i++) {
		VariableSpecification_t varSpec =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->variableSpecification;

		AlternateAccess_t* alternateAccess =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->alternateAccess;

		if (varSpec.present == VariableSpecification_PR_name) {

			if (varSpec.choice.name.present == ObjectName_PR_domainspecific) {
				char* domainIdStr = mmsMsg_createStringFromAsnIdentifier(
						varSpec.choice.name.choice.domainspecific.domainId);


				char* nameIdStr = mmsMsg_createStringFromAsnIdentifier(
						varSpec.choice.name.choice.domainspecific.itemId);

				MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);

				if (domain == NULL) {
					if (DEBUG) printf("MMS read: domain %s not found!\n", domainIdStr);

					appendErrorToResultList(values, 10 /* object-non-existant*/);
					break;
				}

				MmsTypeSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameIdStr);

				addNamedVariableToResultList(namedVariable, domain, nameIdStr,
						values, connection, alternateAccess);

				free(domainIdStr);
				free(nameIdStr);
			}
			else {
                appendErrorToResultList(values, 10 /* object-non-existant*/);

				if (DEBUG) printf("MMS read: object name type not supported!\n");
			}
		}
		else {
			//TODO should we send a ConfirmedErrorPdu here?
			if (DEBUG) printf("MMS read: varspec type not supported!\n");
		}
	}

	encodeReadResponse(connection, invokeId, response, values, NULL);

	MmsServer_unlockModel(connection->server);

exit:
    deleteValueList(values);
}
/**********************************************************************************************
 * 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_handleDeleteNamedVariableListRequest(MmsServerConnection* connection,
        DeleteNamedVariableListRequest_t* request,
        int invokeId,
        ByteBuffer* response)
{
    //TODO implement for association specific named variable lists

    MmsDevice* device;
    long scopeOfDelete;
    request->scopeOfDelete;

    asn_INTEGER2long(request->scopeOfDelete, &scopeOfDelete);

    device = MmsServer_getDevice(connection->server);

    if (scopeOfDelete == DeleteNamedVariableListRequest__scopeOfDelete_specific) {
        int numberMatched = 0;
        int numberDeleted = 0;

        int numberItems = request->listOfVariableListName->list.count;

        int i;

        for (i = 0; i < numberItems; i++) {
            if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_domainspecific) {
                char* domainId = mmsMsg_createStringFromAsnIdentifier(
                                     request->listOfVariableListName->list.array[i]->choice.domainspecific.domainId);

                MmsDomain* domain = MmsDevice_getDomain(device, domainId);

                char* itemId = mmsMsg_createStringFromAsnIdentifier(
                                   request->listOfVariableListName->list.array[i]->choice.domainspecific.itemId);

                MmsNamedVariableList variableList = MmsDomain_getNamedVariableList(domain, itemId);

                if (variableList != NULL) {
                    numberMatched++;

                    if (MmsNamedVariableList_isDeletable(variableList)) {
                        MmsDomain_deleteNamedVariableList(domain, itemId);
                        numberDeleted++;
                    }
                }

                free(domainId);
                free(itemId);
            }
            else if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_aaspecific) {
                char* itemId = mmsMsg_createStringFromAsnIdentifier(
                                   request->listOfVariableListName->list.array[i]->choice.aaspecific);

                MmsNamedVariableList variableList = MmsServerConnection_getNamedVariableList(connection, itemId);

                if (variableList != NULL) {
                    numberMatched++;
                    numberDeleted++;

                    MmsServerConnection_deleteNamedVariableList(connection, itemId);
                }

                free(itemId);
            }
            //TODO else send error???
        }

        createDeleteNamedVariableListResponse(invokeId, response, numberMatched, numberDeleted);
    }
    else {
        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);
    }
}
void
mmsServer_handleDefineNamedVariableListRequest(
    MmsServerConnection* connection,
    DefineNamedVariableListRequest_t* request,
    int invokeId,
    ByteBuffer* response)
{
    MmsDevice* device = MmsServer_getDevice(connection->server);

    if (request->variableListName.present == ObjectName_PR_domainspecific) {

        MmsNamedVariableList namedVariableList;
        char* variableListName;
        char* domainName = createStringFromBuffer(
                               request->variableListName.choice.domainspecific.domainId.buf,
                               request->variableListName.choice.domainspecific.domainId.size);

        MmsDomain* domain = MmsDevice_getDomain(device, domainName);

        free(domainName);

        if (domain == NULL) {
            mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_NON_EXISTENT);
            return;
        }

        variableListName = createStringFromBuffer(
                               request->variableListName.choice.domainspecific.itemId.buf,
                               request->variableListName.choice.domainspecific.itemId.size);

        namedVariableList = createNamedVariableList(device,
                            request, variableListName);

        free(variableListName);

        if (namedVariableList != NULL) {
            MmsDomain_addNamedVariableList(domain, namedVariableList);
            createDefineNamedVariableListResponse(invokeId, response);
        }
        else
            mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);

    }
    else if (request->variableListName.present == ObjectName_PR_aaspecific) {

        char* variableListName = createStringFromBuffer(
                                     request->variableListName.choice.aaspecific.buf,
                                     request->variableListName.choice.aaspecific.size);

        MmsNamedVariableList namedVariableList = createNamedVariableList(device,
                request, variableListName);

        if (namedVariableList != NULL) {
            MmsServerConnection_addNamedVariableList(connection, namedVariableList);
            createDefineNamedVariableListResponse(invokeId, response);
        }
        else
            mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);

        free(variableListName);
    }
    else
        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_OBJECT_ACCESS_UNSUPPORTED);
}
void
mmsServer_handleDefineNamedVariableListRequest(
		MmsServerConnection connection,
		uint8_t* buffer, int bufPos, int maxBufPos,
		uint32_t invokeId,
		ByteBuffer* response)
{
	DefineNamedVariableListRequest_t* request = 0;

	MmsPdu_t* mmsPdu = 0;

	asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, maxBufPos);

	if (rval.code != RC_OK) {
	    mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
	    goto exit_function;
	}

	request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.defineNamedVariableList);

	MmsDevice* device = MmsServer_getDevice(connection->server);

	if (request->variableListName.present == ObjectName_PR_domainspecific) {

	    char domainName[65];

	    if (request->variableListName.choice.domainspecific.domainId.size > 64) {
	        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
	        goto exit_free_struct;
	    }

	    StringUtils_createStringFromBufferInBuffer(domainName,
	            request->variableListName.choice.domainspecific.domainId.buf,
	            request->variableListName.choice.domainspecific.domainId.size);

		MmsDomain* domain = MmsDevice_getDomain(device, domainName);

		if (domain == NULL) {
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
			goto exit_free_struct;
		}

		if (LinkedList_size(domain->namedVariableLists) < CONFIG_MMS_MAX_NUMBER_OF_DOMAIN_SPECIFIC_DATA_SETS) {
		    char variableListName[65];

		    if (request->variableListName.choice.domainspecific.itemId.size > 64) {
		        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
                goto exit_free_struct;
		    }

		    StringUtils_createStringFromBufferInBuffer(variableListName,
		            request->variableListName.choice.domainspecific.itemId.buf,
                    request->variableListName.choice.domainspecific.itemId.size);

            if (MmsDomain_getNamedVariableList(domain, variableListName) != NULL) {
                mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS);
            }
            else {
                MmsError mmsError;

                MmsNamedVariableList namedVariableList = createNamedVariableList(domain, device,
                                request, variableListName, &mmsError);

                if (namedVariableList != NULL) {

                    mmsError = mmsServer_callVariableListChangedHandler(true, MMS_DOMAIN_SPECIFIC, domain, variableListName, connection);

                    if (mmsError == MMS_ERROR_NONE) {
                        MmsDomain_addNamedVariableList(domain, namedVariableList);
                        createDefineNamedVariableListResponse(invokeId, response);
                    }
                    else {
                        MmsNamedVariableList_destroy(namedVariableList);
                        mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError);
                    }
                }
                else
                    mmsServer_createConfirmedErrorPdu(invokeId, response, mmsError);
            }
		}
		else
		    mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE);


	}
	else if (request->variableListName.present == ObjectName_PR_aaspecific) {

	    if (LinkedList_size(connection->namedVariableLists) < CONFIG_MMS_MAX_NUMBER_OF_ASSOCIATION_SPECIFIC_DATA_SETS) {

	        char variableListName[65];

	        if (request->variableListName.choice.aaspecific.size > 64) {
                mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
                goto exit_free_struct;
            }

	        StringUtils_createStringFromBufferInBuffer(variableListName,
	                request->variableListName.choice.aaspecific.buf,
	                request->variableListName.choice.aaspecific.size);

            if (MmsServerConnection_getNamedVariableList(connection, variableListName) != NULL) {
                mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS);
            }
            else {
                MmsError mmsError;

                MmsNamedVariableList namedVariableList = createNamedVariableList(NULL, device,
                        request, variableListName, &mmsError);

                if (namedVariableList != NULL) {

                    if (mmsServer_callVariableListChangedHandler(true, MMS_ASSOCIATION_SPECIFIC, NULL, variableListName, connection) == MMS_ERROR_NONE) {
                        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);
            }
	    }
	    else
	        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE);
	}
	else
		mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED);

exit_free_struct:
	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

exit_function:
    return;
}
void
mmsServer_handleGetNamedVariableListAttributesRequest(
		MmsServerConnection connection,
		uint8_t* buffer, int bufPos, int maxBufPos,
		uint32_t invokeId,
		ByteBuffer* response)
{
	GetNamedVariableListAttributesRequest_t* request = 0;

	asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_GetNamedVariableListAttributesRequest,
				(void**) &request, buffer + bufPos, maxBufPos - bufPos);

	if (rval.code != RC_OK) {
	    mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
	    return;
	}

	if (request->present == ObjectName_PR_domainspecific) {

	    char domainName[65];
	    char itemName[65];

	    if ((request->choice.domainspecific.domainId.size > 64) ||
	        (request->choice.domainspecific.itemId.size > 64)) {
	        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER);
	        goto exit_function;
	    }

	    StringUtils_createStringFromBufferInBuffer(domainName, request->choice.domainspecific.domainId.buf,
	            request->choice.domainspecific.domainId.size);

	    StringUtils_createStringFromBufferInBuffer(itemName, request->choice.domainspecific.itemId.buf,
                request->choice.domainspecific.itemId.size);

		MmsDevice* mmsDevice = MmsServer_getDevice(connection->server);

		MmsDomain* domain = MmsDevice_getDomain(mmsDevice, domainName);

		if (domain != NULL) {
			MmsNamedVariableList variableList =
					MmsDomain_getNamedVariableList(domain, itemName);

			if (variableList != NULL)
				createGetNamedVariableListAttributesResponse(invokeId, response, variableList);
			else
				mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
		}
		else
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);

	}
#if (MMS_DYNAMIC_DATA_SETS == 1)
	else if (request->present == ObjectName_PR_aaspecific) {

	    char listName[65];

        if (request->choice.aaspecific.size > 64) {
            mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER);
            goto exit_function;
        }

	    StringUtils_createStringFromBufferInBuffer(listName, request->choice.aaspecific.buf,
	            request->choice.aaspecific.size);

	    MmsNamedVariableList varList = MmsServerConnection_getNamedVariableList(connection, listName);

	    if (varList != NULL)
	        createGetNamedVariableListAttributesResponse(invokeId, response, varList);
	    else
	        mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
	}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
	else {
		mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
	}

exit_function:

	asn_DEF_GetVariableAccessAttributesRequest.free_struct(&asn_DEF_GetNamedVariableListAttributesRequest,
			request, 0);
}
void
mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
		uint8_t* buffer, int bufPos, int maxBufPos,
		uint32_t invokeId,
		ByteBuffer* response)
{
	DeleteNamedVariableListRequest_t* request = 0;

    MmsPdu_t* mmsPdu = 0;

    asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu, (void**) &mmsPdu, buffer, maxBufPos);

    if (rval.code != RC_OK) {
        mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
        goto exit_function;
    }

    request = &(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.deleteNamedVariableList);

	long scopeOfDelete;

	asn_INTEGER2long(request->scopeOfDelete, &scopeOfDelete);

	MmsDevice* device = MmsServer_getDevice(connection->server);

	if (scopeOfDelete == DeleteNamedVariableListRequest__scopeOfDelete_specific) {
		int numberMatched = 0;
		int numberDeleted = 0;

		int numberItems = request->listOfVariableListName->list.count;

		int i;

		for (i = 0; i < numberItems; i++) {
			if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_domainspecific) {
		        char domainName[65];
		        char listName[65];

		        mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.domainspecific.domainId,
		                domainName, 65);

		        mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.domainspecific.itemId,
		                listName, 65);

		        MmsDomain* domain = MmsDevice_getDomain(device, domainName);

		        if (domain != NULL) {

                    MmsNamedVariableList variableList = MmsDomain_getNamedVariableList(domain, listName);

                    if (variableList != NULL) {
                        numberMatched++;

                        if (MmsNamedVariableList_isDeletable(variableList)) {

                            if (mmsServer_callVariableListChangedHandler(false, MMS_DOMAIN_SPECIFIC, domain, listName, connection) == MMS_ERROR_NONE) {
                                MmsDomain_deleteNamedVariableList(domain, listName);
                                numberDeleted++;
                            }
                        }
                    }
		        }
			}
			else if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_aaspecific) {
			    char listName[65];

			    mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.aaspecific,
			            listName, 65);

				MmsNamedVariableList variableList = MmsServerConnection_getNamedVariableList(connection, listName);

				if (variableList != NULL) {
					numberMatched++;

					if (mmsServer_callVariableListChangedHandler(false, MMS_ASSOCIATION_SPECIFIC, NULL, listName, connection) == MMS_ERROR_NONE) {
					    numberDeleted++;
					    MmsServerConnection_deleteNamedVariableList(connection, listName);
					}
				}
			}
		}

		createDeleteNamedVariableListResponse(invokeId, response, numberMatched, numberDeleted);
	}
	else {
		mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
	}

    asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

exit_function:
    return;
}
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
createVariableAccessAttributesResponse(
		MmsServerConnection connection,
		char* domainId,
		char* nameId,
		int invokeId,
		ByteBuffer* response)
{
	MmsDevice* device = MmsServer_getDevice(connection->server);

	MmsVariableSpecification* namedVariable = NULL;

	if (domainId != NULL) {
	    MmsDomain* domain = MmsDevice_getDomain(device, domainId);

	    if (domain == NULL) {
	        if (DEBUG_MMS_SERVER) printf("MMS_SERVER: domain %s not known\n", domainId);

	        mmsServer_createConfirmedErrorPdu(invokeId, response,
	                              MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
	        goto exit_function;
	    }

	    namedVariable = MmsDomain_getNamedVariable(domain, nameId);
	}
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)
	else
	    namedVariable = MmsDevice_getNamedVariable(device, nameId);
#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */


	if (namedVariable == NULL) {
		if (DEBUG_MMS_SERVER) printf("MMS_SERVER: named variable %s not known\n", nameId);

		mmsServer_createConfirmedErrorPdu(invokeId, response,
		                          MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);

		goto exit_function;
	}

	MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);

	mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
			ConfirmedServiceResponse_PR_getVariableAccessAttributes;

	GetVariableAccessAttributesResponse_t* getVarAccessAttr;

	getVarAccessAttr = &(mmsPdu->choice.confirmedResponsePdu.
			confirmedServiceResponse.choice.getVariableAccessAttributes);

	getVarAccessAttr->mmsDeletable = 0;

	createTypeSpecification(namedVariable, &getVarAccessAttr->typeSpecification);

	asn_enc_rval_t rval =
	        der_encode(&asn_DEF_MmsPdu, mmsPdu, mmsServer_write_out, (void*) response);

	if (rval.encoded == -1) {
	    response->size = 0;

        if (DEBUG_MMS_SERVER)
            printf("MMS getVariableAccessAttributes: message to large! send error PDU!\n");

        mmsServer_createConfirmedErrorPdu(invokeId, response,
                      MMS_ERROR_SERVICE_OTHER);

        goto exit_function;
	}

	deleteVariableAccessAttributesResponse(getVarAccessAttr);

	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);

exit_function:
	return;
}
Beispiel #13
0
static void
handleReadNamedVariableListRequest(
		MmsServerConnection connection,
		ReadRequest_t* read,
		int invokeId,
		ByteBuffer* response)
{
	if (read->variableAccessSpecification.choice.variableListName.present ==
			ObjectName_PR_domainspecific)
	{
        char domainIdStr[65];
        char nameIdStr[65];

        mmsMsg_copyAsn1IdentifierToStringBuffer(read->variableAccessSpecification.choice.variableListName.choice.domainspecific.domainId,
                domainIdStr, 65);

        mmsMsg_copyAsn1IdentifierToStringBuffer(read->variableAccessSpecification.choice.variableListName.choice.domainspecific.itemId,
                nameIdStr, 65);

		VarAccessSpec accessSpec;

		accessSpec.isNamedVariableList = true;
		accessSpec.specific = 1;
		accessSpec.domainId = domainIdStr;
		accessSpec.itemId = nameIdStr;

		MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);

		if (domain == NULL) {
			if (DEBUG_MMS_SERVER) printf("MMS read: domain %s not found!\n", domainIdStr);
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
		}
		else {
			MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, nameIdStr);

			if (namedList != NULL) {
				createNamedVariableListResponse(connection, namedList, invokeId, response, read,
						&accessSpec);
			}
			else {
				if (DEBUG_MMS_SERVER) printf("MMS read: named variable list %s not found!\n", nameIdStr);
				mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
			}
		}
	}
#if (MMS_DYNAMIC_DATA_SETS == 1)
	else if (read->variableAccessSpecification.choice.variableListName.present ==
				ObjectName_PR_aaspecific)
	{
        char listName[65];

        mmsMsg_copyAsn1IdentifierToStringBuffer(read->variableAccessSpecification.choice.variableListName.choice.aaspecific,
                listName, 65);

		MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName);

		VarAccessSpec accessSpec;

		accessSpec.isNamedVariableList = true;
		accessSpec.specific = 2;
		accessSpec.domainId = NULL;
		accessSpec.itemId = listName;

		if (namedList == NULL)
			mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
		else
			createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec);
	}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
	else
		mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}
Beispiel #14
0
static void
handleReadListOfVariablesRequest(
		MmsServerConnection connection,
		ReadRequest_t* read,
		uint32_t invokeId,
		ByteBuffer* response)
{
	int variableCount = read->variableAccessSpecification.choice.listOfVariable.list.count;

	LinkedList /*<MmsValue>*/ values = LinkedList_create();

	if (isSpecWithResult(read)) { /* add specification to result */
		// ignore - not required for IEC 61850
	}

	int i;

	for (i = 0; i < variableCount; i++) {
		VariableSpecification_t varSpec =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->variableSpecification;

		AlternateAccess_t* alternateAccess =
			read->variableAccessSpecification.choice.listOfVariable.list.array[i]->alternateAccess;

		if (varSpec.present == VariableSpecification_PR_name) {

			if (varSpec.choice.name.present == ObjectName_PR_domainspecific) {
				char domainIdStr[65];
				char nameIdStr[65];

				mmsMsg_copyAsn1IdentifierToStringBuffer(varSpec.choice.name.choice.domainspecific.domainId,
				        domainIdStr, 65);

				mmsMsg_copyAsn1IdentifierToStringBuffer(varSpec.choice.name.choice.domainspecific.itemId,
				        nameIdStr, 65);

				MmsDomain* domain = MmsDevice_getDomain(MmsServer_getDevice(connection->server), domainIdStr);

				if (DEBUG_MMS_SERVER)
				    printf("MMS_SERVER: READ domainId: (%s) nameId: (%s)\n", domainIdStr, nameIdStr);

				if (domain == NULL) {
					if (DEBUG_MMS_SERVER)
					    printf("MMS_SERVER: READ domain %s not found!\n", domainIdStr);

					appendErrorToResultList(values, 10 /* object-non-existent*/);
				}
				else {
                    MmsVariableSpecification* namedVariable = MmsDomain_getNamedVariable(domain, nameIdStr);

                    if (namedVariable == NULL)
                        appendErrorToResultList(values, 10 /* object-non-existent*/);
                    else
                        addNamedVariableToResultList(namedVariable, domain, nameIdStr,
                            values, connection, alternateAccess);
				}
			}
#if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1)

			else if (varSpec.choice.name.present == ObjectName_PR_vmdspecific) {
			    char nameIdStr[65];

			    mmsMsg_copyAsn1IdentifierToStringBuffer(varSpec.choice.name.choice.vmdspecific, nameIdStr, 65);

			    if (DEBUG_MMS_SERVER)
			        printf("MMS_SERVER: READ vmd-specific nameId:%s\n", nameIdStr);

			    MmsVariableSpecification* namedVariable = MmsDevice_getNamedVariable(MmsServer_getDevice(connection->server), nameIdStr);

                if (namedVariable == NULL)
                    appendErrorToResultList(values, 10 /* object-non-existent*/);
                else
                    addNamedVariableToResultList(namedVariable, (MmsDomain*) MmsServer_getDevice(connection->server), nameIdStr,
                            values, connection, alternateAccess);

			}
#endif /* (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) */

			else {
                appendErrorToResultList(values, 10 /* object-non-existent*/);

				if (DEBUG_MMS_SERVER) printf("MMS_SERVER: READ object name type not supported!\n");
			}
		}
		else {
			if (DEBUG_MMS_SERVER) printf("MMS_SERVER: READ varspec type not supported!\n");
			mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
			goto exit;
		}
	}

	encodeReadResponse(connection, invokeId, response, values, NULL);

exit:

    deleteValueList(values);
}