- added code to deserialize an BER encoded MMS data element into a MmsValue instance

pull/6/head
Michael Zillgith 9 years ago
parent 24e1c902e4
commit 3eca0d62c5

@ -280,7 +280,7 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe
while (element != NULL) { while (element != NULL) {
MmsValue* dataSetEntry = (MmsValue*) element->data; MmsValue* dataSetEntry = (MmsValue*) element->data;
dataSetSize += mmsServer_encodeAccessResult(dataSetEntry, NULL, 0, false); dataSetSize += MmsValue_encodeMmsData(dataSetEntry, NULL, 0, false);
element = LinkedList_getNext(element); element = LinkedList_getNext(element);
} }
@ -344,7 +344,7 @@ createGoosePayload(GoosePublisher self, LinkedList dataSetValues, uint8_t* buffe
while (element != NULL) { while (element != NULL) {
MmsValue* dataSetEntry = (MmsValue*) element->data; MmsValue* dataSetEntry = (MmsValue*) element->data;
bufPos = mmsServer_encodeAccessResult(dataSetEntry, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(dataSetEntry, buffer, bufPos, true);
element = LinkedList_getNext(element); element = LinkedList_getNext(element);
} }

@ -304,7 +304,7 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
break; break;
default: default:
if (DEBUG_GOOSE_SUBSCRIBER) if (DEBUG_GOOSE_SUBSCRIBER)
printf("GOOSE_SUBSCRIBER: found unkown tag %02x\n", tag); printf("GOOSE_SUBSCRIBER: found unknown tag %02x\n", tag);
goto exit_with_error; goto exit_with_error;
} }

@ -950,6 +950,21 @@ MmsValue_getTypeString(MmsValue* self);
char* char*
MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize); MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize);
/**
* \brief create a new MmsValue instance from a BER encoded MMS Data element (deserialize)
*
*/
MmsValue*
MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength);
/**
* \brief Serialize the MmsValue instance as BER encoded MMS Data element
*
* \param self the MmsValue instance
*/
int
MmsValue_encodeMmsData(MmsValue* self, uint8_t* buffer, int bufPos, bool encode);
/**@}*/ /**@}*/
/**@}*/ /**@}*/

@ -26,7 +26,4 @@
#include "mms_value.h" #include "mms_value.h"
int
mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode);
#endif /* MMS_ACCESS_RESULT_H_ */ #endif /* MMS_ACCESS_RESULT_H_ */

@ -1,7 +1,7 @@
/* /*
* mms_access_result.c * mms_access_result.c
* *
* Copyright 2013 Michael Zillgith * Copyright 2013, 2016 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -41,7 +41,7 @@ encodeArrayAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encod
for (i = 0; i < arraySize; i++) { for (i = 0; i < arraySize; i++) {
MmsValue* element = MmsValue_getElement(value, i); MmsValue* element = MmsValue_getElement(value, i);
elementsSize += mmsServer_encodeAccessResult(element, NULL, 0, false); elementsSize += MmsValue_encodeMmsData(element, NULL, 0, false);
} }
if (encode) { if (encode) {
@ -51,7 +51,7 @@ encodeArrayAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encod
for (i = 0; i < arraySize; i++) { for (i = 0; i < arraySize; i++) {
MmsValue* element = MmsValue_getElement(value, i); MmsValue* element = MmsValue_getElement(value, i);
bufPos = mmsServer_encodeAccessResult(element, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(element, buffer, bufPos, true);
} }
size = bufPos; size = bufPos;
@ -75,14 +75,14 @@ encodeStructuredAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
MmsValue** components = value->value.structure.components; MmsValue** components = value->value.structure.components;
for (i = 0; i < componentCount; i++) for (i = 0; i < componentCount; i++)
componentsSize += mmsServer_encodeAccessResult(components[i], NULL, 0, false); componentsSize += MmsValue_encodeMmsData(components[i], NULL, 0, false);
if (encode) { if (encode) {
buffer[bufPos++] = 0xa2; /* tag for structure */ buffer[bufPos++] = 0xa2; /* tag for structure */
bufPos = BerEncoder_encodeLength(componentsSize, buffer, bufPos); bufPos = BerEncoder_encodeLength(componentsSize, buffer, bufPos);
for (i = 0; i < componentCount; i++) for (i = 0; i < componentCount; i++)
bufPos = mmsServer_encodeAccessResult(components[i], buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(components[i], buffer, bufPos, true);
size = bufPos; size = bufPos;
} }
@ -92,102 +92,297 @@ encodeStructuredAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
return size; return size;
} }
static int
getNumberOfElements(uint8_t* buffer, int bufPos, int elementLength)
{
int elementIndex = 0;
int elementEndBufPos = bufPos + elementLength;
while (bufPos < elementEndBufPos) {
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, elementEndBufPos);
if (bufPos + elementLength > elementEndBufPos) {
goto exit_with_error;
}
switch (tag) {
case 0x80: /* reserved for access result */
break;
case 0xa1: /* array */
break;
case 0xa2: /* structure */
break;
case 0x83: /* boolean */
break;
case 0x84: /* BIT STRING */
break;
case 0x85: /* integer */
break;
case 0x86: /* unsigned integer */
break;
case 0x87: /* Float */
break;
case 0x89: /* octet string */
break;
case 0x8a: /* visible string */
break;
case 0x8c: /* binary time */
break;
case 0x91: /* Utctime */
break;
default:
goto exit_with_error;
}
bufPos += elementLength;
elementIndex++;
}
return elementIndex;
exit_with_error:
return -1;
}
static MmsValue*
decodeData(uint8_t* buffer, int bufPos, int bufferLength)
{
int dataEndBufPos = bufPos + bufferLength;
uint8_t tag = buffer[bufPos++];
int dataLength;
bufPos = BerDecoder_decodeLength(buffer, &dataLength, bufPos, dataEndBufPos);
if (bufPos + dataLength > dataEndBufPos)
goto exit_with_error;
MmsValue* value = NULL;
switch (tag) {
case 0xa1: /* MMS_ARRAY */
case 0xa2: /* MMS_STRUCTURE */
{
int elementCount = getNumberOfElements(buffer, bufPos, dataLength);
if (tag == 0xa1)
value = MmsValue_createEmptyArray(elementCount);
else
value = MmsValue_createEmptyStructure(elementCount);
int i;
for (i = 0; i < elementCount; i++) {
int elementLength;
int newBufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos + 1, dataEndBufPos);
if (newBufPos == -1)
goto exit_with_error;
MmsValue* elementValue = decodeData(buffer, bufPos, dataLength);
if (elementValue == NULL)
goto exit_with_error;
MmsValue_setElement(value, i, elementValue);
bufPos = newBufPos + elementLength;
}
if (value == NULL)
goto exit_with_error;
}
break;
case 0x83: /* MMS_BOOLEAN */
value = MmsValue_newBoolean(BerDecoder_decodeBoolean(buffer, bufPos));
break;
case 0x84: /* MMS_BIT_STRING */
{
int padding = buffer[bufPos];
int bitStringLength = (8 * (dataLength - 1)) - padding;
value = MmsValue_newBitString(bitStringLength);
memcpy(value->value.bitString.buf, buffer + bufPos + 1, dataLength - 1);
}
break;
case 0x85: /* MMS_INTEGER */
value = MmsValue_newInteger(dataLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, dataLength);
value->value.integer->size = dataLength;
break;
case 0x86: /* MMS_UNSIGNED */
value = MmsValue_newUnsigned(dataLength * 8);
memcpy(value->value.integer->octets, buffer + bufPos, dataLength);
value->value.integer->size = dataLength;
break;
case 0x87: /* MMS_FLOAT */
if (dataLength == 9)
value = MmsValue_newDouble(BerDecoder_decodeDouble(buffer, bufPos));
else if (dataLength == 5)
value = MmsValue_newFloat(BerDecoder_decodeFloat(buffer, bufPos));
break;
case 0x89: /* MMS_OCTET_STRING */
value = MmsValue_newOctetString(dataLength, dataLength);
memcpy(value->value.octetString.buf, buffer + bufPos, dataLength);
break;
case 0x8a: /* MMS_VISIBLE_STRING */
value = MmsValue_newVisibleStringFromByteArray(buffer + bufPos, dataLength);
break;
case 0x8c: /* MMS_BINARY_TIME */
if (dataLength == 4)
value = MmsValue_newBinaryTime(true);
else if (dataLength == 6)
value = MmsValue_newBinaryTime(false);
if ((dataLength == 4) || (dataLength == 6))
memcpy(value->value.binaryTime.buf, buffer + bufPos, dataLength);
break;
case 0x91: /* MMS_UTC_TIME */
if (dataLength == 8) {
value = MmsValue_newUtcTime(0);
MmsValue_setUtcTimeByBuffer(value, buffer + bufPos);
}
else
goto exit_with_error;
break;
default: /* unknown tag -> decoding error */
goto exit_with_error;
}
return value;
exit_with_error:
if (value != NULL)
MmsValue_delete(value);
return NULL;
}
MmsValue*
MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength)
{
return decodeData(buffer, bufPos, bufferLength);
}
int int
mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool encode) MmsValue_encodeMmsData(MmsValue* self, uint8_t* buffer, int bufPos, bool encode)
{ {
int size; int size;
switch (value->type) { switch (self->type) {
case MMS_BOOLEAN: case MMS_BOOLEAN:
if (encode) if (encode)
bufPos = BerEncoder_encodeBoolean(0x83, value->value.boolean, buffer, bufPos); bufPos = BerEncoder_encodeBoolean(0x83, self->value.boolean, buffer, bufPos);
else else
size = 3; size = 3;
break; break;
case MMS_STRUCTURE: case MMS_STRUCTURE:
if (encode) if (encode)
bufPos = encodeStructuredAccessResult(value, buffer, bufPos, true); bufPos = encodeStructuredAccessResult(self, buffer, bufPos, true);
else else
size = encodeStructuredAccessResult(value, buffer, bufPos, false); size = encodeStructuredAccessResult(self, buffer, bufPos, false);
break; break;
case MMS_ARRAY: case MMS_ARRAY:
if (encode) if (encode)
bufPos = encodeArrayAccessResult(value, buffer, bufPos, true); bufPos = encodeArrayAccessResult(self, buffer, bufPos, true);
else else
size = encodeArrayAccessResult(value, buffer, bufPos, false); size = encodeArrayAccessResult(self, buffer, bufPos, false);
break; break;
case MMS_DATA_ACCESS_ERROR: case MMS_DATA_ACCESS_ERROR:
if (encode) { if (encode) {
int length = BerEncoder_UInt32determineEncodedSize((uint32_t) value->value.dataAccessError); int length = BerEncoder_UInt32determineEncodedSize((uint32_t) self->value.dataAccessError);
bufPos = BerEncoder_encodeTL(0x80, length, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x80, length, buffer, bufPos);
bufPos = BerEncoder_encodeUInt32((uint32_t) value->value.dataAccessError, buffer, bufPos); bufPos = BerEncoder_encodeUInt32((uint32_t) self->value.dataAccessError, buffer, bufPos);
} }
else else
size = 2 + BerEncoder_UInt32determineEncodedSize((uint32_t) value->value.dataAccessError); size = 2 + BerEncoder_UInt32determineEncodedSize((uint32_t) self->value.dataAccessError);
break; break;
case MMS_VISIBLE_STRING: case MMS_VISIBLE_STRING:
if (encode) if (encode)
bufPos = BerEncoder_encodeStringWithTag(0x8a, value->value.visibleString.buf, buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x8a, self->value.visibleString.buf, buffer, bufPos);
else else
size = BerEncoder_determineEncodedStringSize(value->value.visibleString.buf); size = BerEncoder_determineEncodedStringSize(self->value.visibleString.buf);
break; break;
case MMS_UNSIGNED: case MMS_UNSIGNED:
if (encode) if (encode)
bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x86, value->value.integer, buffer, bufPos); bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x86, self->value.integer, buffer, bufPos);
else else
size = 2 + value->value.integer->size; size = 2 + self->value.integer->size;
break; break;
case MMS_INTEGER: case MMS_INTEGER:
if (encode) if (encode)
bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x85, value->value.integer, buffer, bufPos); bufPos = BerEncoder_encodeAsn1PrimitiveValue(0x85, self->value.integer, buffer, bufPos);
else else
size = 2 + value->value.integer->size; size = 2 + self->value.integer->size;
break; break;
case MMS_UTC_TIME: case MMS_UTC_TIME:
if (encode) if (encode)
bufPos = BerEncoder_encodeOctetString(0x91, value->value.utcTime, 8, buffer, bufPos); bufPos = BerEncoder_encodeOctetString(0x91, self->value.utcTime, 8, buffer, bufPos);
else else
size = 10; size = 10;
break; break;
case MMS_BIT_STRING: case MMS_BIT_STRING:
if (encode) if (encode)
bufPos = BerEncoder_encodeBitString(0x84, value->value.bitString.size, bufPos = BerEncoder_encodeBitString(0x84, self->value.bitString.size,
value->value.bitString.buf, buffer, bufPos); self->value.bitString.buf, buffer, bufPos);
else else
size = BerEncoder_determineEncodedBitStringSize(value->value.bitString.size); size = BerEncoder_determineEncodedBitStringSize(self->value.bitString.size);
break; break;
case MMS_BINARY_TIME: case MMS_BINARY_TIME:
if (encode) if (encode)
bufPos = BerEncoder_encodeOctetString(0x8c, value->value.binaryTime.buf, bufPos = BerEncoder_encodeOctetString(0x8c, self->value.binaryTime.buf,
value->value.binaryTime.size, buffer, bufPos); self->value.binaryTime.size, buffer, bufPos);
else else
size = 2 + value->value.binaryTime.size; size = 2 + self->value.binaryTime.size;
break; break;
case MMS_OCTET_STRING: case MMS_OCTET_STRING:
if (encode) if (encode)
bufPos = BerEncoder_encodeOctetString(0x89, value->value.octetString.buf, bufPos = BerEncoder_encodeOctetString(0x89, self->value.octetString.buf,
value->value.octetString.size, buffer, bufPos); self->value.octetString.size, buffer, bufPos);
else else
size = 1 + BerEncoder_determineLengthSize(value->value.octetString.size) size = 1 + BerEncoder_determineLengthSize(self->value.octetString.size)
+ value->value.octetString.size; + self->value.octetString.size;
break; break;
case MMS_FLOAT: case MMS_FLOAT:
{ {
int floatSize = (value->value.floatingPoint.formatWidth / 8) + 1; int floatSize = (self->value.floatingPoint.formatWidth / 8) + 1;
if (encode) { if (encode) {
bufPos = BerEncoder_encodeTL(0x87, floatSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x87, floatSize, buffer, bufPos);
bufPos = BerEncoder_encodeFloat(value->value.floatingPoint.buf, bufPos = BerEncoder_encodeFloat(self->value.floatingPoint.buf,
value->value.floatingPoint.formatWidth, self->value.floatingPoint.formatWidth,
value->value.floatingPoint.exponentWidth, self->value.floatingPoint.exponentWidth,
buffer, bufPos); buffer, bufPos);
} }
else else
@ -196,9 +391,9 @@ mmsServer_encodeAccessResult(MmsValue* value, uint8_t* buffer, int bufPos, bool
break; break;
case MMS_STRING: case MMS_STRING:
if (encode) if (encode)
bufPos = BerEncoder_encodeStringWithTag(0x90, value->value.visibleString.buf, buffer, bufPos); bufPos = BerEncoder_encodeStringWithTag(0x90, self->value.visibleString.buf, buffer, bufPos);
else else
size = BerEncoder_determineEncodedStringSize(value->value.visibleString.buf); size = BerEncoder_determineEncodedStringSize(self->value.visibleString.buf);
break; break;
default: default:
if (DEBUG_MMS_SERVER) if (DEBUG_MMS_SERVER)

@ -38,7 +38,7 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
uint32_t sequenceSize = 1 + BerEncoder_determineLengthSize(varSpecSize) + varSpecSize; uint32_t sequenceSize = 1 + BerEncoder_determineLengthSize(varSpecSize) + varSpecSize;
uint32_t listOfVariableSize = 1 + BerEncoder_determineLengthSize(sequenceSize) + sequenceSize; uint32_t listOfVariableSize = 1 + BerEncoder_determineLengthSize(sequenceSize) + sequenceSize;
uint32_t accessResultSize = mmsServer_encodeAccessResult(value, NULL, 0, false); uint32_t accessResultSize = MmsValue_encodeMmsData(value, NULL, 0, false);
uint32_t listOfAccessResultSize = 1 + BerEncoder_determineLengthSize(accessResultSize) + accessResultSize; uint32_t listOfAccessResultSize = 1 + BerEncoder_determineLengthSize(accessResultSize) + accessResultSize;
@ -77,7 +77,7 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
/* encode access result (variable value) */ /* encode access result (variable value) */
bufPos = BerEncoder_encodeTL(0xa0, accessResultSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0xa0, accessResultSize, buffer, bufPos);
bufPos = mmsServer_encodeAccessResult(value, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(value, buffer, bufPos, true);
reportBuffer->size = bufPos; reportBuffer->size = bufPos;
@ -128,7 +128,7 @@ MmsServerConnection_sendInformationReportListOfVariables(
while (valueElement != NULL) { while (valueElement != NULL) {
MmsValue* value = (MmsValue*) valueElement->data; MmsValue* value = (MmsValue*) valueElement->data;
accessResultSize += mmsServer_encodeAccessResult(value, NULL, 0, false); accessResultSize += MmsValue_encodeMmsData(value, NULL, 0, false);
valueElement = LinkedList_getNext(valueElement); valueElement = LinkedList_getNext(valueElement);
} }
@ -204,7 +204,7 @@ MmsServerConnection_sendInformationReportListOfVariables(
while (valueElement != NULL) { while (valueElement != NULL) {
MmsValue* value = (MmsValue*) valueElement->data; MmsValue* value = (MmsValue*) valueElement->data;
bufPos = mmsServer_encodeAccessResult(value, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(value, buffer, bufPos, true);
valueElement = LinkedList_getNext(valueElement); valueElement = LinkedList_getNext(valueElement);
} }
@ -241,7 +241,7 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
MmsValue* data = (MmsValue*) value->data; MmsValue* data = (MmsValue*) value->data;
accessResultSize += mmsServer_encodeAccessResult(data, NULL, 0, false); accessResultSize += MmsValue_encodeMmsData(data, NULL, 0, false);
value = LinkedList_getNext(value); value = LinkedList_getNext(value);
} }
@ -286,7 +286,7 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
MmsValue* data = (MmsValue*) value->data; MmsValue* data = (MmsValue*) value->data;
bufPos = mmsServer_encodeAccessResult(data, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(data, buffer, bufPos, true);
value = LinkedList_getNext(value); value = LinkedList_getNext(value);
} }

@ -406,7 +406,7 @@ encodeReadResponse(MmsServerConnection connection,
MmsValue* data = (MmsValue*) value->data; MmsValue* data = (MmsValue*) value->data;
accessResultSize += mmsServer_encodeAccessResult(data, NULL, 0, false); accessResultSize += MmsValue_encodeMmsData(data, NULL, 0, false);
value = LinkedList_getNext(value); value = LinkedList_getNext(value);
} }
@ -467,7 +467,7 @@ encodeReadResponse(MmsServerConnection connection,
for (i = 0; i < variableCount; i++) { for (i = 0; i < variableCount; i++) {
MmsValue* data = (MmsValue*) value->data; MmsValue* data = (MmsValue*) value->data;
bufPos = mmsServer_encodeAccessResult(data, buffer, bufPos, true); bufPos = MmsValue_encodeMmsData(data, buffer, bufPos, true);
value = LinkedList_getNext(value); value = LinkedList_getNext(value);
} }

Loading…
Cancel
Save