static int
handleConfirmedRequestPdu(
		MmsServerConnection* self,
		ConfirmedRequestPdu_t* request,
		ByteBuffer* response)
{
	long invokeIdLong;
	int32_t invokeId;

	asn_INTEGER2long((INTEGER_t*) &(request->invokeID), &invokeIdLong);

	invokeId = (int32_t) invokeIdLong;

	if (DEBUG) printf("invokeId: %i\n", invokeId);

	switch(request->confirmedServiceRequest.present) {
	case ConfirmedServiceRequest_PR_getNameList:
		mmsServer_handleGetNameListRequest(self, &(request->confirmedServiceRequest.choice.getNameList),
				invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_read:
		mmsServer_handleReadRequest(self, &(request->confirmedServiceRequest.choice.read),
				invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_write:
		mmsServer_handleWriteRequest(self, &(request->confirmedServiceRequest.choice.write),
						invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_getVariableAccessAttributes:
		mmsServer_handleGetVariableAccessAttributesRequest(self,
				&(request->confirmedServiceRequest.choice.getVariableAccessAttributes),
				invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_defineNamedVariableList:
		mmsServer_handleDefineNamedVariableListRequest(self,
				&(request->confirmedServiceRequest.choice.defineNamedVariableList),
				invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_getNamedVariableListAttributes:
		mmsServer_handleGetNamedVariableListAttributesRequest(self,
				&(request->confirmedServiceRequest.choice.getNamedVariableListAttributes),
				invokeId, response);
		break;
	case ConfirmedServiceRequest_PR_deleteNamedVariableList:
		mmsServer_handleDeleteNamedVariableListRequest(self,
				&(request->confirmedServiceRequest.choice.deleteNamedVariableList),
				invokeId, response);
		break;
	default:
		writeMmsRejectPdu(&invokeId, REJECT_UNRECOGNIZED_SERVICE, response);
		break;
	}
}
static inline MmsIndication
parseMmsPdu(MmsServerConnection* self, ByteBuffer* message, ByteBuffer* response)
{
	MmsIndication retVal;

	uint8_t* buffer = message->buffer;

	if (message->size < 2)
		return MMS_ERROR;

	int bufPos = 0;

	uint8_t pduType = buffer[bufPos++];
	uint32_t pduLength;

	bufPos = BerDecoder_decodeLength(buffer, (int*) &pduLength, bufPos, message->size);

	if (bufPos < 0)
		return MMS_ERROR;

	if (DEBUG) printf("mms_server: recvd MMS-PDU type: %02x size: %u\n", pduType, pduLength);

	switch (pduType) {
	case 0xa8: /* Initiate request PDU */
		handleInitiateRequestPdu(self, buffer, bufPos, bufPos + pduLength, response);
		retVal = MMS_INITIATE;
		break;
	case 0xa0: /* Confirmed request PDU */
		handleConfirmedRequestPdu(self, buffer, bufPos, bufPos + pduLength, response);
		retVal = MMS_CONFIRMED_REQUEST;
		break;
	case 0x8b: /* Conclude request PDU */
		mmsServer_writeConcludeResponsePdu(response);
		IsoConnection_close(self->isoConnection);
		retVal = MMS_CONCLUDE;
		break;
	case 0xa4: /* Reject PDU */
		//TODO evaluate reject PDU
		/* silently ignore */
		retVal = MMS_OK;
		break;
	default:
		writeMmsRejectPdu(NULL, REJECT_UNKNOWN_PDU_TYPE, response);
		retVal = MMS_ERROR;
		break;
	}

parseMmsPdu_exit:
	return retVal;
}
static inline MmsIndication
parseMmsPdu(MmsServerConnection* self, ByteBuffer* message, ByteBuffer* response)
{
	MmsPdu_t* mmsPdu = 0; /* allow asn1c to allocate structure */
	MmsIndication retVal;

	asn_dec_rval_t rval; /* Decoder return value  */

	rval = ber_decode(NULL, &asn_DEF_MmsPdu,
			(void**) &mmsPdu, (void*) message->buffer, message->size);

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

	if (rval.code != RC_OK) {
		retVal = MMS_ERROR;
		goto parseMmsPdu_exit;
	}

	switch (mmsPdu->present) {
	case MmsPdu_PR_initiateRequestPdu:
		handleInitiateRequestPdu(self, &(mmsPdu->choice.initiateRequestPdu), response);
		retVal = MMS_INITIATE;
		break;
	case MmsPdu_PR_confirmedRequestPdu:
		handleConfirmedRequestPdu(self, &(mmsPdu->choice.confirmedRequestPdu), response);
		retVal = MMS_CONFIRMED_REQUEST;
		break;
	case MmsPdu_PR_concludeRequestPDU:
		mmsServer_writeConcludeResponsePdu(response);
		IsoConnection_close(self->isoConnection);
		retVal = MMS_CONCLUDE;
		break;
	default:
		writeMmsRejectPdu(NULL, REJECT_UNKNOWN_PDU_TYPE, response);
		retVal = MMS_ERROR;
		break;
	}

parseMmsPdu_exit:
	asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
	return retVal;
}
static void
handleConfirmedRequestPdu(
		MmsServerConnection* self,
		uint8_t* buffer, int bufPos, int maxBufPos,
		ByteBuffer* response)
{
	uint32_t invokeId = 0;

	if (DEBUG) printf("invokeId: %i\n", invokeId);

	while (bufPos < maxBufPos) {
		uint8_t tag = buffer[bufPos++];
		uint32_t length;

		bufPos = BerDecoder_decodeLength(buffer, (int*) &length, bufPos, maxBufPos);

		if (bufPos < 0)  {
			writeMmsRejectPdu((int*) &invokeId, REJECT_UNRECOGNIZED_SERVICE, response);
			return;
		}

		if (DEBUG) printf("tag %02x size: %i\n", tag, length);

		switch(tag) {
		case 0x02: /* invoke Id */
			invokeId = BerDecoder_decodeUint32(buffer, length, bufPos);
			break;
		case 0xa1: /* get-name-list-request */
			mmsServer_handleGetNameListRequest(self, buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		case 0xa4: /* read-request */
			mmsServer_handleReadRequest(self, buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		case 0xa5: /* write-request */
			mmsServer_handleWriteRequest(self, buffer, bufPos, bufPos + length,
							invokeId, response);
			break;
		case 0xa6: /* get-variable-access-attributes-request */
			mmsServer_handleGetVariableAccessAttributesRequest(self,
					buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		case 0xab: /* define-named-variable-list */
			mmsServer_handleDefineNamedVariableListRequest(self,
					buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		case 0xac: /* get-named-variable-list-attributes-request */
			mmsServer_handleGetNamedVariableListAttributesRequest(self,
					buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		case 0xad: /* delete-named-variable-list-request */
			mmsServer_handleDeleteNamedVariableListRequest(self,
					buffer, bufPos, bufPos + length,
					invokeId, response);
			break;
		default:
			writeMmsRejectPdu((int*) &invokeId, REJECT_UNRECOGNIZED_SERVICE, response);
			return;
			break;
		}

		bufPos += length;
	}
}