static void createDeleteNamedVariableListResponse(uint32_t invokeId, ByteBuffer* response, uint32_t numberMatched, uint32_t numberDeleted) { uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId) + 2; uint32_t numberMatchedSize = 2 + BerEncoder_UInt32determineEncodedSize(numberMatched); uint32_t numberDeletedSize = 2 + BerEncoder_UInt32determineEncodedSize(numberDeleted); uint32_t deleteNVLSize = 2 + numberMatchedSize + numberDeletedSize; uint32_t confirmedResponsePDUSize = invokeIdSize + deleteNVLSize; int bufPos = 0; uint8_t* buffer = response->buffer; bufPos = BerEncoder_encodeTL(0xa1, confirmedResponsePDUSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); bufPos = BerEncoder_encodeTL(0xad, numberMatchedSize + numberDeletedSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x80, numberMatchedSize - 2, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(numberMatched, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x81, numberDeletedSize - 2, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(numberDeleted, buffer, bufPos); response->size = bufPos; }
static int encodeVariableAccessSpecification(VarAccessSpec* accessSpec, uint8_t* buffer, int bufPos, bool encode) { /* determine size */ int varAccessSpecSize = 0; int itemIdLen = strlen(accessSpec->itemId); varAccessSpecSize += itemIdLen + BerEncoder_determineLengthSize(itemIdLen) + 1; if (accessSpec->domainId != NULL) { int domainIdLen = strlen(accessSpec->domainId); varAccessSpecSize += domainIdLen + BerEncoder_determineLengthSize(domainIdLen) + 1; } int specificityLength = varAccessSpecSize; varAccessSpecSize += 1 + BerEncoder_determineLengthSize(specificityLength); int variableListNameLength = varAccessSpecSize; varAccessSpecSize += 1 + BerEncoder_determineLengthSize(variableListNameLength); int varAccessSpecLength = varAccessSpecSize; varAccessSpecSize += 1 + BerEncoder_determineLengthSize(varAccessSpecLength); if (encode == false) return varAccessSpecSize; /* encode to buffer */ bufPos = BerEncoder_encodeTL(0xa0, varAccessSpecLength, buffer, bufPos); if (accessSpec->isNamedVariableList == true) { bufPos = BerEncoder_encodeTL(0xa1, variableListNameLength, buffer, bufPos); if (accessSpec->specific == 0) { /* vmd-specific */ bufPos = BerEncoder_encodeTL(0xa0, specificityLength, buffer, bufPos); } else if (accessSpec->specific == 1) { /* domain-specific */ bufPos = BerEncoder_encodeTL(0xa1, specificityLength, buffer, bufPos); } else { /* association-specific */ bufPos = BerEncoder_encodeTL(0xa2, specificityLength, buffer, bufPos); } if (accessSpec->domainId != NULL) bufPos = BerEncoder_encodeStringWithTag(0x1a, accessSpec->domainId, buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x1a, accessSpec->itemId, buffer, bufPos); } return bufPos; }
static int createInitiateResponse(MmsServerConnection* self, ByteBuffer* writeBuffer) { uint8_t* buffer = writeBuffer->buffer; int bufPos = 0; int initiateResponseLength = 0; initiateResponseLength += 2 + BerEncoder_UInt32determineEncodedSize(self->maxPduSize); initiateResponseLength += 2 + BerEncoder_UInt32determineEncodedSize(self->maxServOutstandingCalling); initiateResponseLength += 2 + BerEncoder_UInt32determineEncodedSize(self->maxServOutstandingCalled); initiateResponseLength += 2 + BerEncoder_UInt32determineEncodedSize(self->dataStructureNestingLevel); initiateResponseLength += encodeInitResponseDetail(parameterCBB, servicesSupported, NULL, 0, false); /* Initiate response pdu */ bufPos = BerEncoder_encodeTL(0xa9, initiateResponseLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32WithTL(0x80, self->maxPduSize, buffer, bufPos); bufPos = BerEncoder_encodeUInt32WithTL(0x81, self->maxServOutstandingCalling, buffer, bufPos); bufPos = BerEncoder_encodeUInt32WithTL(0x82, self->maxServOutstandingCalled, buffer, bufPos); bufPos = BerEncoder_encodeUInt32WithTL(0x83, self->dataStructureNestingLevel, buffer, bufPos); bufPos = encodeInitResponseDetail(parameterCBB, servicesSupported, buffer, bufPos, true); writeBuffer->size = bufPos; return bufPos; }
void mmsServer_handleStatusRequest( MmsServerConnection connection, uint8_t* requestBuffer, int bufPos, int invokeId, ByteBuffer* response) { /* check for extended derivation */ bool extendedDerivation = BerDecoder_decodeBoolean(requestBuffer, bufPos); if (DEBUG_MMS_SERVER) printf("mms_status_service.c: statusRequest (extendedDerivation: %i)\n", extendedDerivation); bufPos = 0; uint8_t* buffer = response->buffer; uint32_t invokeIdLength = BerEncoder_UInt32determineEncodedSize(invokeId); MmsServer mmsServer = connection->server; /* Invoke user provided callback */ if (mmsServer->statusRequestListener != NULL) mmsServer->statusRequestListener(mmsServer->statusRequestListenerParameter, mmsServer, connection, extendedDerivation); uint32_t vmdPhysicalStatusLength = BerEncoder_UInt32determineEncodedSize((uint32_t) mmsServer->vmdPhysicalStatus); uint32_t vmdLogicalStatusLength = BerEncoder_UInt32determineEncodedSize((uint32_t) mmsServer->vmdLogicalStatus); uint32_t statusLength = 2 + vmdPhysicalStatusLength + 2 + vmdLogicalStatusLength; uint32_t statusResponseLength = invokeIdLength + 2 + 1 + BerEncoder_determineLengthSize(statusLength) + statusLength; /* Status response pdu */ bufPos = BerEncoder_encodeTL(0xa1, statusResponseLength, buffer, bufPos); /* invokeId */ bufPos = BerEncoder_encodeTL(0x02, invokeIdLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); bufPos = BerEncoder_encodeTL(0xa0, statusLength, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x80, vmdLogicalStatusLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32((uint32_t) mmsServer->vmdLogicalStatus, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x81, vmdPhysicalStatusLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32((uint32_t) mmsServer->vmdPhysicalStatus, buffer, bufPos); response->size = bufPos; }
void mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request) { uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId); uint32_t confirmedRequestPduSize = 2 + 2 + invokeIdSize; int bufPos = 0; uint8_t* buffer = request->buffer; bufPos = BerEncoder_encodeTL(0xa0, confirmedRequestPduSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x02, invokeIdSize, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x82, 0, buffer, bufPos); request->size = bufPos; }
static void createDefineNamedVariableListResponse(uint32_t invokeId, ByteBuffer* response) { uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize((uint32_t) invokeId) + 2; uint32_t confirmedResponsePDUSize = 2 + invokeIdSize; int bufPos = 0; uint8_t* buffer = response->buffer; bufPos = BerEncoder_encodeTL(0xa1, confirmedResponsePDUSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos); bufPos = BerEncoder_encodeUInt32((uint32_t) invokeId, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x8b, 0, buffer, bufPos); response->size = bufPos; }
static void handleIdentifyRequest( MmsServerConnection* connection, int invokeId, ByteBuffer* response) { int bufPos = 0; uint8_t* buffer = response->buffer; uint32_t invokeIdLength = BerEncoder_UInt32determineEncodedSize(invokeId); MmsServer mmsServer = connection->server; uint32_t vendorNameLength = strlen(MmsServer_getVendorName(mmsServer)); uint32_t modelNameLength = strlen(MmsServer_getModelName(mmsServer)); uint32_t revisionLength = strlen(MmsServer_getRevision(mmsServer)); uint32_t identityLength = 3 + BerEncoder_determineLengthSize(vendorNameLength) + BerEncoder_determineLengthSize(modelNameLength) + BerEncoder_determineLengthSize(revisionLength) + vendorNameLength + modelNameLength + revisionLength; uint32_t identifyResponseLength = invokeIdLength + 2 + 1 + BerEncoder_determineLengthSize(identityLength) + identityLength; /* Identify response pdu */ bufPos = BerEncoder_encodeTL(0xa1, identifyResponseLength, buffer, bufPos); /* invokeId */ bufPos = BerEncoder_encodeTL(0x02, invokeIdLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); bufPos = BerEncoder_encodeTL(0xa2, identityLength, buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x80, MmsServer_getVendorName(mmsServer), buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x81, MmsServer_getModelName(mmsServer), buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x82, MmsServer_getRevision(mmsServer), buffer, bufPos); response->size = bufPos; }
static int encodeInitResponseDetail(uint8_t parameterCBB[], uint8_t servicesSupported[], uint8_t* buffer, int bufPos, bool encode) { int initResponseDetailSize = 14 + 5 + 3; if (encode == false) return initResponseDetailSize + 2; bufPos = BerEncoder_encodeTL(0xa4, initResponseDetailSize, buffer, bufPos); bufPos = BerEncoder_encodeUInt32WithTL(0x80, 1, buffer, bufPos); /* negotiated protocol version */ bufPos = BerEncoder_encodeBitString(0x81, 11, parameterCBB, buffer, bufPos); bufPos = BerEncoder_encodeBitString(0x82, 85, servicesSupported, buffer, bufPos); return bufPos; }
static void encodeReadResponse(MmsServerConnection* connection, uint32_t invokeId, ByteBuffer* response, LinkedList values, VarAccessSpec* accessSpec) { int i; int variableCount = LinkedList_size(values); int varAccessSpecSize = 0; if (accessSpec != NULL) { varAccessSpecSize = encodeVariableAccessSpecification(accessSpec, NULL, 0, false); } /* determine BER encoded message sizes */ int accessResultSize = 0; /* iterate values list to determine encoded size */ LinkedList value = LinkedList_getNext(values); for (i = 0; i < variableCount; i++) { MmsValue* data = (MmsValue*) value->data; accessResultSize += mmsServer_encodeAccessResult(data, NULL, 0, false); value = LinkedList_getNext(value); } int listOfAccessResultsLength = 1 + BerEncoder_determineLengthSize(accessResultSize) + accessResultSize; int confirmedServiceResponseContentLength = listOfAccessResultsLength + varAccessSpecSize; int confirmedServiceResponseLength = 1 + BerEncoder_determineLengthSize(confirmedServiceResponseContentLength) + confirmedServiceResponseContentLength; int invokeIdSize = BerEncoder_UInt32determineEncodedSize(invokeId) + 2; int confirmedResponseContentSize = confirmedServiceResponseLength + invokeIdSize; int mmsPduSize = 1 + BerEncoder_determineLengthSize(confirmedResponseContentSize) + confirmedResponseContentSize; /* Check if message would fit in the MMS PDU */ if (mmsPduSize > connection->maxPduSize) { if (DEBUG) printf("MMS read: message to large! send error PDU!\n"); mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_TYPE_RESPONSE_EXCEEDS_MAX_PDU_SIZE); return; } /* encode message */ uint8_t* buffer = response->buffer; int bufPos = 0; /* confirmed response PDU */ bufPos = BerEncoder_encodeTL(0xa1, confirmedResponseContentSize, buffer, bufPos); /* invoke id */ bufPos = BerEncoder_encodeTL(0x02, invokeIdSize - 2, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(invokeId, buffer, bufPos); /* confirmed-service-response read */ bufPos = BerEncoder_encodeTL(0xa4, confirmedServiceResponseContentLength, buffer, bufPos); /* encode variable access specification */ if (accessSpec != NULL) bufPos = encodeVariableAccessSpecification(accessSpec, buffer, bufPos, true); /* encode list of access results */ bufPos = BerEncoder_encodeTL(0xa1, accessResultSize, buffer, bufPos); /* encode access results */ value = LinkedList_getNext(values); for (i = 0; i < variableCount; i++) { MmsValue* data = (MmsValue*) value->data; bufPos = mmsServer_encodeAccessResult(data, buffer, bufPos, true); value = LinkedList_getNext(value); } response->size = bufPos; if (DEBUG) printf("MMS read: sent message for request with id %u (size = %i)\n", invokeId, bufPos); }
int mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode) { int size; switch (value->type) { case MMS_STRUCTURE: if (encode) bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true); else size = encodeStructuredAccessResult(value, buffer, bufPos, false); break; case MMS_ARRAY: if (encode) bufPos = encodeArrayAccessResult(value, buffer, bufPos, true); else size = encodeArrayAccessResult(value, buffer, bufPos, false); break; case MMS_DATA_ACCESS_ERROR: if (encode) { int length = BerEncoder_UInt32determineEncodedSize(value->value.dataAccessError.code); bufPos = BerEncoder_encodeTL(0x80, length, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(value->value.dataAccessError.code, buffer, bufPos); } else size = 2 + BerEncoder_UInt32determineEncodedSize(value->value.dataAccessError.code); break; case MMS_VISIBLE_STRING: if (encode) bufPos = BerEncoder_encodeStringWithTag(0x8a, value->value.visibleString, buffer, bufPos); else size = BerEncoder_determineEncodedStringSize(value->value.visibleString); break; case MMS_UNSIGNED: if (encode) bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x86, value->value.unsignedInteger, buffer, bufPos); else size = 2 + value->value.unsignedInteger->size; break; case MMS_INTEGER: if (encode) bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x85, value->value.integer, buffer, bufPos); else size = 2 + value->value.integer->size; break; case MMS_UTC_TIME: if (encode) bufPos = BerEncoder_encodeOctetString(0x91, value->value.utcTime, 8, buffer, bufPos); else size = 10; break; case MMS_BIT_STRING: if (encode) bufPos = BerEncoder_encodeBitString(0x84, value->value.bitString.size, value->value.bitString.buf, buffer, bufPos); else size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size); break; case MMS_BOOLEAN: if (encode) bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos); else size = 3; break; case MMS_BINARY_TIME: if (encode) bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf, value->value.binaryTime.size, buffer, bufPos); else size = 2 + value->value.binaryTime.size; break; case MMS_OCTET_STRING: if (encode) bufPos = BerEncoder_encodeOctetString(0x89, value->value.octetString.buf, value->value.octetString.size, buffer, bufPos); else size = 1 + BerEncoder_determineLengthSize(value->value.octetString.size) + value->value.octetString.size; break; case MMS_FLOAT: { int floatSize = (value->value.floatingPoint.formatWidth / 8) + 1; if (encode) { bufPos = BerEncoder_encodeTL(0x87, floatSize, buffer, bufPos); bufPos = BerEncoder_encodeFloat(value->value.floatingPoint.buf, value->value.floatingPoint.formatWidth, value->value.floatingPoint.exponentWidth, buffer, bufPos); } else size = floatSize + 2; /* 2 for tag and length */ } break; case MMS_STRING: if (encode) bufPos = BerEncoder_encodeStringWithTag(0x90, value->value.mmsString, buffer, bufPos); else size = BerEncoder_determineEncodedStringSize(value->value.mmsString); break; default: printf("encodeAccessResult: error unsupported type!\n"); break; } if (encode) return bufPos; else return size; }