|
|
|
@ -1,7 +1,7 @@
|
|
|
|
|
/*
|
|
|
|
|
* mms_client_read.c
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2013-2018 Michael Zillgith
|
|
|
|
|
* Copyright 2013-2019 Michael Zillgith
|
|
|
|
|
*
|
|
|
|
|
* This file is part of libIEC61850.
|
|
|
|
|
*
|
|
|
|
@ -46,11 +46,14 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < elementCount; i++) {
|
|
|
|
|
|
|
|
|
|
value = NULL;
|
|
|
|
|
|
|
|
|
|
AccessResult_PR presentType = accessResultList[i]->present;
|
|
|
|
|
|
|
|
|
|
if (presentType == AccessResult_PR_failure) {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("access error!\n");
|
|
|
|
|
printf("MMS CLIENT: received access error!\n");
|
|
|
|
|
|
|
|
|
|
if (accessResultList[i]->choice.failure.size > 0) {
|
|
|
|
|
int errorCode = (int) accessResultList[i]->choice.failure.buf[0];
|
|
|
|
@ -66,12 +69,13 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_UNKNOWN);
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_array) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_ARRAY;
|
|
|
|
|
|
|
|
|
|
int arrayElementCount =
|
|
|
|
|
accessResultList[i]->choice.array.list.count;
|
|
|
|
|
|
|
|
|
|
if (arrayElementCount > 0) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_ARRAY;
|
|
|
|
|
value->value.structure.size = arrayElementCount;
|
|
|
|
|
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(arrayElementCount, sizeof(MmsValue*));
|
|
|
|
|
|
|
|
|
@ -80,15 +84,28 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
for (j = 0; j < arrayElementCount; j++) {
|
|
|
|
|
value->value.structure.components[j] = mmsMsg_parseDataElement(
|
|
|
|
|
accessResultList[i]->choice.array.list.array[j]);
|
|
|
|
|
|
|
|
|
|
if (value->value.structure.components[j] == NULL) {
|
|
|
|
|
MmsValue_delete(value);
|
|
|
|
|
value = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid array size)!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_structure) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_STRUCTURE;
|
|
|
|
|
|
|
|
|
|
int componentCount =
|
|
|
|
|
accessResultList[i]->choice.structure.list.count;
|
|
|
|
|
|
|
|
|
|
if (componentCount > 0) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_STRUCTURE;
|
|
|
|
|
value->value.structure.size = componentCount;
|
|
|
|
|
value->value.structure.components = (MmsValue**) GLOBAL_CALLOC(componentCount, sizeof(MmsValue*));
|
|
|
|
|
|
|
|
|
@ -96,12 +113,34 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
for (j = 0; j < componentCount; j++) {
|
|
|
|
|
value->value.structure.components[j] = mmsMsg_parseDataElement(
|
|
|
|
|
accessResultList[i]->choice.structure.list.array[j]);
|
|
|
|
|
|
|
|
|
|
if (value->value.structure.components[j] == NULL) {
|
|
|
|
|
MmsValue_delete(value);
|
|
|
|
|
value = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid structure size)!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_bitstring) {
|
|
|
|
|
|
|
|
|
|
int size = accessResultList[i]->choice.bitstring.size;
|
|
|
|
|
|
|
|
|
|
if (size > 0) {
|
|
|
|
|
|
|
|
|
|
int maxSize = (size * 8);
|
|
|
|
|
int bitSize = maxSize - accessResultList[i]->choice.bitstring.bits_unused;
|
|
|
|
|
|
|
|
|
|
if ((bitSize > 0) && (maxSize >= bitSize)) {
|
|
|
|
|
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_BIT_STRING;
|
|
|
|
|
int size = accessResultList[i]->choice.bitstring.size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value->value.bitString.size = (size * 8)
|
|
|
|
|
- accessResultList[i]->choice.bitstring.bits_unused;
|
|
|
|
@ -109,29 +148,59 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
value->value.bitString.buf = (uint8_t*) GLOBAL_MALLOC(size);
|
|
|
|
|
memcpy(value->value.bitString.buf,
|
|
|
|
|
accessResultList[i]->choice.bitstring.buf, size);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (bit string padding problem)!\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (bit string size 0 or negative)!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_integer) {
|
|
|
|
|
|
|
|
|
|
int size = accessResultList[i]->choice.integer.size;
|
|
|
|
|
|
|
|
|
|
if (size > 0) {
|
|
|
|
|
Asn1PrimitiveValue* berInteger =
|
|
|
|
|
BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf,
|
|
|
|
|
accessResultList[i]->choice.integer.size);
|
|
|
|
|
BerInteger_createFromBuffer(accessResultList[i]->choice.integer.buf, size);
|
|
|
|
|
|
|
|
|
|
value = MmsValue_newIntegerFromBerInteger(berInteger);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid integer size)!\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_unsigned) {
|
|
|
|
|
|
|
|
|
|
int size = accessResultList[i]->choice.Unsigned.size;
|
|
|
|
|
|
|
|
|
|
if (size > 0) {
|
|
|
|
|
Asn1PrimitiveValue* berInteger =
|
|
|
|
|
BerInteger_createFromBuffer(accessResultList[i]->choice.Unsigned.buf,
|
|
|
|
|
accessResultList[i]->choice.Unsigned.size);
|
|
|
|
|
|
|
|
|
|
value = MmsValue_newUnsignedFromBerInteger(berInteger);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid unsigned size)!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_floatingpoint) {
|
|
|
|
|
|
|
|
|
|
int size = accessResultList[i]->choice.floatingpoint.size;
|
|
|
|
|
|
|
|
|
|
if (size == 5) { /* FLOAT32 */
|
|
|
|
|
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_FLOAT;
|
|
|
|
|
|
|
|
|
|
if (size == 5) { /* FLOAT32 */
|
|
|
|
|
value->value.floatingPoint.formatWidth = 32;
|
|
|
|
|
value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];
|
|
|
|
|
|
|
|
|
@ -146,8 +215,11 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (size == 9) { /* FLOAT64 */
|
|
|
|
|
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_FLOAT;
|
|
|
|
|
|
|
|
|
|
if (size == 9) { /* FLOAT64 */
|
|
|
|
|
value->value.floatingPoint.formatWidth = 64;
|
|
|
|
|
value->value.floatingPoint.exponentWidth = accessResultList[i]->choice.floatingpoint.buf[0];
|
|
|
|
|
|
|
|
|
@ -161,15 +233,20 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
memcpy(value->value.floatingPoint.buf, floatBuf, 8);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing float (size must be 5 or 9, is %i)\n", size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_visiblestring) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
|
|
|
|
|
value->type = MMS_VISIBLE_STRING;
|
|
|
|
|
|
|
|
|
|
int strSize = accessResultList[i]->choice.visiblestring.size;
|
|
|
|
|
|
|
|
|
|
if (strSize >= 0) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
|
|
|
|
|
value->type = MMS_VISIBLE_STRING;
|
|
|
|
|
value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
|
|
|
|
|
value->value.visibleString.size = strSize;
|
|
|
|
|
|
|
|
|
@ -179,13 +256,20 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
|
|
|
|
|
value->value.visibleString.buf[strSize] = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_mMSString) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid visible-string size)\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value->type = MMS_STRING;
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_mMSString) {
|
|
|
|
|
|
|
|
|
|
int strSize = accessResultList[i]->choice.mMSString.size;
|
|
|
|
|
|
|
|
|
|
if (strSize >= 0) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
|
|
|
|
|
value->type = MMS_STRING;
|
|
|
|
|
value->value.visibleString.buf = (char*) GLOBAL_MALLOC(strSize + 1);
|
|
|
|
|
value->value.visibleString.size = strSize;
|
|
|
|
|
|
|
|
|
@ -193,14 +277,26 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
accessResultList[i]->choice.mMSString.buf, strSize);
|
|
|
|
|
|
|
|
|
|
value->value.visibleString.buf[strSize] = 0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid mms-string size)\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_utctime) {
|
|
|
|
|
|
|
|
|
|
int size = accessResultList[i]->choice.utctime.size;
|
|
|
|
|
|
|
|
|
|
if (size == 8) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
|
|
|
|
|
value->type = MMS_UTC_TIME;
|
|
|
|
|
memcpy(value->value.utcTime,
|
|
|
|
|
accessResultList[i]->choice.utctime.buf, 8);
|
|
|
|
|
memcpy(value->value.utcTime, accessResultList[i]->choice.utctime.buf, 8);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing UTC time (size is %i instead of 8\n", size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_boolean) {
|
|
|
|
|
value = MmsValue_newBoolean(accessResultList[i]->choice.boolean);
|
|
|
|
@ -208,16 +304,21 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
else if (presentType == AccessResult_PR_binarytime) {
|
|
|
|
|
int size = accessResultList[i]->choice.binarytime.size;
|
|
|
|
|
|
|
|
|
|
if (size <= 6) {
|
|
|
|
|
if ((size == 4) || (size == 6)) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_BINARY_TIME;
|
|
|
|
|
value->value.binaryTime.size = size;
|
|
|
|
|
memcpy(value->value.binaryTime.buf, accessResultList[i]->choice.binarytime.buf, size);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing binary time (size must be 4 or 6, is %i\n", size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (presentType == AccessResult_PR_octetstring) {
|
|
|
|
|
int size = accessResultList[i]->choice.octetstring.size;
|
|
|
|
|
|
|
|
|
|
if (size >= 0) {
|
|
|
|
|
value = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
|
|
|
|
|
value->type = MMS_OCTET_STRING;
|
|
|
|
|
value->value.octetString.maxSize = size;
|
|
|
|
@ -226,7 +327,13 @@ mmsClient_parseListOfAccessResults(AccessResult_t** accessResultList, int listSi
|
|
|
|
|
memcpy(value->value.octetString.buf, accessResultList[i]->choice.octetstring.buf, size);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
printf("unknown type %i\n", presentType);
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: error parsing access result (invalid octet-string size)\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (DEBUG_MMS_CLIENT)
|
|
|
|
|
printf("MMS CLIENT: unknown type %i in access result\n", presentType);
|
|
|
|
|
value = MmsValue_newDataAccessError(DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -254,9 +361,7 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create
|
|
|
|
|
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 (rval.code == RC_OK) {
|
|
|
|
|
if (mmsPdu->present == MmsPdu_PR_confirmedResponsePdu) {
|
|
|
|
|
|
|
|
|
|
if (invokeId != NULL)
|
|
|
|
@ -271,6 +376,7 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create
|
|
|
|
|
elementCount, createArray);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0);
|
|
|
|
|
|
|
|
|
|