MmsVariableSpecification*
mmsClient_parseGetVariableAccessAttributesResponse(ByteBuffer* message, uint32_t* invokeId)
{
	MmsPdu_t* mmsPdu = 0; /* allow asn1c to allocate structure */
	MmsVariableSpecification* typeSpec = NULL;

	asn_dec_rval_t rval = ber_decode(NULL, &asn_DEF_MmsPdu,
			(void**) &mmsPdu, ByteBuffer_getBuffer(message), ByteBuffer_getSize(message));

	if (rval.code != RC_OK)
	    return NULL;

	if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {

	    if (invokeId != NULL)
	        *invokeId = mmsClient_getInvokeId(&mmsPdu->choice.confirmedResponsePdu);

		if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
				ConfirmedServiceResponse_PR_getVariableAccessAttributes)
		{
			GetVariableAccessAttributesResponse_t* response;

			response = &(mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.choice.getVariableAccessAttributes);
			TypeSpecification_t* asnTypeSpec = &response->typeSpecification;

			typeSpec = createTypeSpecification(asnTypeSpec);
		}
	}

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

	return typeSpec;
}
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;
}
static int
createTypeSpecification (
		MmsTypeSpecification* namedVariable,
		TypeSpecification_t* typeSpec)
{

	if (namedVariable->type == MMS_ARRAY) {
		typeSpec->present = TypeSpecification_PR_array;
		typeSpec->choice.array.numberOfElements;

		asn_long2INTEGER(&(typeSpec->choice.array.numberOfElements),
				(long) namedVariable->typeSpec.array.elementCount);

		typeSpec->choice.array.packed = NULL;
		typeSpec->choice.array.elementType = (TypeSpecification *) calloc(1, sizeof(TypeSpecification_t));

		createTypeSpecification(namedVariable->typeSpec.array.elementTypeSpec,
				typeSpec->choice.array.elementType);
	}
	else if (namedVariable->type == MMS_STRUCTURE) {

		typeSpec->present = TypeSpecification_PR_structure;

		int componentCount = namedVariable->typeSpec.structure.elementCount;

		typeSpec->choice.structure.components.list.count = componentCount;
		typeSpec->choice.structure.components.list.size = componentCount;

		typeSpec->choice.structure.components.list.array
			= (StructComponent **) calloc(componentCount, sizeof(StructComponent_t*));

		int i;

		for (i = 0; i < componentCount; i++) {

			typeSpec->choice.structure.components.list.array[i] =
					(StructComponent *) calloc(1, sizeof(StructComponent_t));

			typeSpec->choice.structure.components.list.array[i]->componentName =
					(Identifier_t *) calloc(1, sizeof(Identifier_t));

			typeSpec->choice.structure.components.list.array[i]->componentName->buf =
			        (uint8_t*) copyString(namedVariable->typeSpec.structure.elements[i]->name);

			typeSpec->choice.structure.components.list.array[i]->componentName->size =
					strlen(namedVariable->typeSpec.structure.elements[i]->name);

			typeSpec->choice.structure.components.list.array[i]->componentType =
					(TypeSpecification *) calloc(1, sizeof(TypeSpecification_t));

			createTypeSpecification(namedVariable->typeSpec.structure.elements[i],
					typeSpec->choice.structure.components.list.array[i]->componentType);
		}
	}
	else {

		switch (namedVariable->type) {
		case MMS_BOOLEAN:
			typeSpec->present = TypeSpecification_PR_boolean;
			break;
		case MMS_BIT_STRING:
			typeSpec->present = TypeSpecification_PR_bitstring;
			typeSpec->choice.bitstring = namedVariable->typeSpec.bitString;
			break;
		case MMS_INTEGER:
			typeSpec->present = TypeSpecification_PR_integer;
			typeSpec->choice.integer = namedVariable->typeSpec.integer;
			break;
		case MMS_UNSIGNED:
			typeSpec->present = TypeSpecification_PR_unsigned;
			typeSpec->choice.Unsigned = namedVariable->typeSpec.unsignedInteger;
			break;
		case MMS_FLOAT:
			typeSpec->present = TypeSpecification_PR_floatingpoint;
			typeSpec->choice.floatingpoint.exponentwidth =
					namedVariable->typeSpec.floatingpoint.exponentWidth;
			typeSpec->choice.floatingpoint.formatwidth =
					namedVariable->typeSpec.floatingpoint.formatWidth;
			break;
		case MMS_OCTET_STRING:
			typeSpec->present = TypeSpecification_PR_octetstring;
			typeSpec->choice.octetstring = namedVariable->typeSpec.octetString;
			break;
		case MMS_VISIBLE_STRING:
			typeSpec->present = TypeSpecification_PR_visiblestring;
			typeSpec->choice.visiblestring = namedVariable->typeSpec.visibleString;
			break;
		case MMS_STRING:
			typeSpec->present = TypeSpecification_PR_mMSString;
			typeSpec->choice.mMSString = namedVariable->typeSpec.mmsString;
			break;
		case MMS_UTC_TIME:
			typeSpec->present = TypeSpecification_PR_utctime;
			break;
		case MMS_BINARY_TIME:
			typeSpec->present = TypeSpecification_PR_binarytime;
			break;
		default:
			if (DEBUG) printf("MMS-SERVER: Unsupported type %i!\n", namedVariable->type);
			return -1;
			break;
		}
	}

	return 1;
}
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;
}
static MmsVariableSpecification*
createTypeSpecification(TypeSpecification_t* asnTypeSpec) {
	MmsVariableSpecification* typeSpec = (MmsVariableSpecification*) 
        GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));

	switch (asnTypeSpec->present) {
	case TypeSpecification_PR_structure:
		{
			typeSpec->type = MMS_STRUCTURE;

			int elementCount = asnTypeSpec->choice.structure.components.list.count;
			typeSpec->typeSpec.structure.elementCount = elementCount;

			typeSpec->typeSpec.structure.elements = (MmsVariableSpecification**)
                GLOBAL_CALLOC(elementCount, sizeof(MmsVariableSpecification*));

			int i;

			for (i = 0; i < elementCount; i++) {

				char* name = createStringFromBuffer(
						asnTypeSpec->choice.structure.components.list.array[i]->componentName->buf,
						asnTypeSpec->choice.structure.components.list.array[i]->componentName->size);

				typeSpec->typeSpec.structure.elements[i] =
						createTypeSpecification(asnTypeSpec->choice.structure.components.
								list.array[i]->componentType);

				typeSpec->typeSpec.structure.elements[i]->name = name;
			}
		}
		break;
	case TypeSpecification_PR_array:
		{
			typeSpec->type = MMS_ARRAY;

			long elementCount;
			asn_INTEGER2long(&asnTypeSpec->choice.array.numberOfElements, &elementCount);

			typeSpec->typeSpec.array.elementCount = elementCount;

			typeSpec->typeSpec.array.elementTypeSpec =
					createTypeSpecification(asnTypeSpec->choice.array.elementType);
		}
		break;
	case TypeSpecification_PR_boolean:
		typeSpec->type = MMS_BOOLEAN;
		break;
	case TypeSpecification_PR_bitstring:
		typeSpec->type = MMS_BIT_STRING;
		typeSpec->typeSpec.bitString = asnTypeSpec->choice.bitstring;
		break;
	case TypeSpecification_PR_integer:
		typeSpec->type = MMS_INTEGER;
		typeSpec->typeSpec.integer = asnTypeSpec->choice.integer;
		break;
	case TypeSpecification_PR_unsigned:
		typeSpec->type = MMS_UNSIGNED;
		typeSpec->typeSpec.unsignedInteger = asnTypeSpec->choice.Unsigned;
		break;
	case TypeSpecification_PR_floatingpoint:
		typeSpec->type = MMS_FLOAT;
		typeSpec->typeSpec.floatingpoint.exponentWidth =
				asnTypeSpec->choice.floatingpoint.exponentwidth;
		typeSpec->typeSpec.floatingpoint.formatWidth =
						asnTypeSpec->choice.floatingpoint.formatwidth;
		break;
	case TypeSpecification_PR_octetstring:
		typeSpec->type = MMS_OCTET_STRING;
		typeSpec->typeSpec.octetString = asnTypeSpec->choice.octetstring;
		break;
	case TypeSpecification_PR_visiblestring:
		typeSpec->type = MMS_VISIBLE_STRING;
		typeSpec->typeSpec.visibleString = asnTypeSpec->choice.visiblestring;
		break;
	case TypeSpecification_PR_mMSString:
		typeSpec->type = MMS_STRING;
		typeSpec->typeSpec.mmsString = asnTypeSpec->choice.mMSString;
		break;
	case TypeSpecification_PR_utctime:
		typeSpec->type = MMS_UTC_TIME;
		break;
	case TypeSpecification_PR_binarytime:
	    typeSpec->type = MMS_BINARY_TIME;
	    if (asnTypeSpec->choice.binarytime == 0)
	        typeSpec->typeSpec.binaryTime = 4;
	    else
	        typeSpec->typeSpec.binaryTime = 6;
	    break;
	default:
		printf("ERROR: unknown type in type specification\n");
		break;
	}

	return typeSpec;
}