From 452abd7dbf74b85cbf874e5fc0752b0e005fb883 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 1 Feb 2019 18:16:43 +0100 Subject: [PATCH] - MMS client/server: added support for component alternate access for generic variable read requests --- examples/CMakeLists.txt | 1 + examples/mms_utility/mms_utility.c | 22 ++- src/iec61850/inc/iec61850_common.h | 2 +- src/mms/inc/mms_client_connection.h | 35 ++++ src/mms/inc_private/mms_client_internal.h | 3 + src/mms/inc_private/mms_server_internal.h | 5 +- .../iso_mms/client/mms_client_connection.c | 61 ++++++ src/mms/iso_mms/client/mms_client_read.c | 126 +++++++++++++ src/mms/iso_mms/server/mms_read_service.c | 177 +++++++++++++----- src/mms/iso_mms/server/mms_server_common.c | 40 ++-- 10 files changed, 404 insertions(+), 68 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7ab6ae5c..9483830d 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -24,6 +24,7 @@ add_subdirectory(iec61850_client_example_array) add_subdirectory(iec61850_client_example_files) add_subdirectory(iec61850_client_example_async) add_subdirectory(iec61850_client_file_async) +add_subdirectory(mms_utility) if(WIN32) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/wpcap.lib") diff --git a/examples/mms_utility/mms_utility.c b/examples/mms_utility/mms_utility.c index e2a48669..8eec1c92 100644 --- a/examples/mms_utility/mms_utility.c +++ b/examples/mms_utility/mms_utility.c @@ -3,14 +3,14 @@ #include #include #include "string_utilities.h" +#include "iec61850_common.h" #include "mms_client_connection.h" #include "conversions.h" static void print_help() { - - printf("MMS utility (libiec61850 " LIBIEC61850_VERSION ") options:\n"); + printf("MMS utility (libiec61850 %s) options:\n", LibIEC61850_getVersionString()); printf("-h specify hostname\n"); printf("-p specify port\n"); printf("-l specify maximum PDU size\n"); @@ -18,6 +18,7 @@ print_help() printf("-i show server identity\n"); printf("-t show domain directory\n"); printf("-r read domain variable\n"); + printf("-c specify component name for variable read\n"); printf("-a specify domain for read or write command\n"); printf("-f show file list\n"); printf("-g get file attributes\n"); @@ -105,6 +106,7 @@ int main(int argc, char** argv) { char* domainName = NULL; char* variableName = NULL; + char* componentName = NULL; char* filename = NULL; char* journalName = NULL; @@ -122,7 +124,7 @@ int main(int argc, char** argv) { int c; - while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:")) != -1) + while ((c = getopt(argc, argv, "mifdh:p:l:t:a:r:g:j:x:v:c:")) != -1) switch (c) { case 'm': printRawMmsMessages = 1; @@ -155,6 +157,9 @@ int main(int argc, char** argv) { readVariable = 1; variableName = StringUtils_copyString(optarg); break; + case 'c': + componentName = StringUtils_copyString(optarg); + break; case 'v': readVariableList = 1; variableName = StringUtils_copyString(optarg); @@ -332,7 +337,13 @@ int main(int argc, char** argv) { if (readVariable) { if (readWriteHasDomain) { - MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName); + + MmsValue* result; + + if (componentName == NULL) + result = MmsConnection_readVariable(con, &error, domainName, variableName); + else + result = MmsConnection_readVariableComponent(con, &error, domainName, variableName, componentName); if (error != MMS_ERROR_NONE) { printf("Reading variable failed: (ERROR %i)\n", error); @@ -347,6 +358,8 @@ int main(int argc, char** argv) { MmsValue_printToBuffer(result, outbuf, 1024); printf("%s\n", outbuf); + + MmsValue_delete(result); } else printf("result: NULL\n"); @@ -403,6 +416,7 @@ exit: free(domainName); free(variableName); free(journalName); + free(componentName); MmsConnection_destroy(con); } diff --git a/src/iec61850/inc/iec61850_common.h b/src/iec61850/inc/iec61850_common.h index 075a8d91..3017e68e 100644 --- a/src/iec61850/inc/iec61850_common.h +++ b/src/iec61850/inc/iec61850_common.h @@ -1,7 +1,7 @@ /* * iec61850_common.h * - * Copyright 2013 Michael Zillgith + * Copyright 2013-2019 Michael Zillgith * * This file is part of libIEC61850. * diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h index 80e15f04..3cd9feb6 100644 --- a/src/mms/inc/mms_client_connection.h +++ b/src/mms/inc/mms_client_connection.h @@ -496,6 +496,41 @@ LIB61850_API uint32_t MmsConnection_readVariableAsync(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId, MmsConnection_ReadVariableHandler handler, void* parameter); +/** + * \brief Read a component of a single variable from the server. + * + * \param self MmsConnection instance to operate on + * \param mmsError user provided variable to store error code + * \param domainId the domain name of the variable to be read or NULL to read a VMD specific named variable + * \param itemId name of the variable to be read + * \param componentId the component name + * + * \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can + * either be a simple value or a complex value or array. It is also possible that the return value is NULL + * even if mmsError = MMS_ERROR_NON. This is the case when the servers returns an empty result list. + */ +LIB61850_API MmsValue* +MmsConnection_readVariableComponent(MmsConnection self, MmsError* mmsError, + const char* domainId, const char* itemId, const char* componentId); + +/** + * \brief Read a component of a single variable from the server (asynchronous version) + * + * \param self MmsConnection instance to operate on + * \param mmsError user provided variable to store error code + * \param domainId the domain name of the variable to be read or NULL to read a VMD specific named variable + * \param itemId name of the variable to be read + * \param componentId the component name + * \param handler + * \param parameter + * + * \return invoke ID of the request when the request was sent successfully + */ +LIB61850_API uint32_t +MmsConnection_readVariableComponentAsync(MmsConnection self, MmsError* mmsError, + const char* domainId, const char* itemId, const char* componentId, + MmsConnection_ReadVariableHandler handler, void* parameter); + /** * \brief Read one or more elements of a single array variable from the server. * diff --git a/src/mms/inc_private/mms_client_internal.h b/src/mms/inc_private/mms_client_internal.h index 077b4e63..bab9bb7d 100644 --- a/src/mms/inc_private/mms_client_internal.h +++ b/src/mms/inc_private/mms_client_internal.h @@ -194,6 +194,9 @@ mmsClient_parseReadResponse(ByteBuffer* message, uint32_t* invokeId, bool create LIB61850_INTERNAL int mmsClient_createReadRequest(uint32_t invokeId, const char* domainId, const char* itemId, ByteBuffer* writeBuffer); +LIB61850_INTERNAL int +mmsClient_createReadRequestComponent(uint32_t invokeId, const char* domainId, const char* itemId, const char* component, ByteBuffer* writeBuffer); + LIB61850_INTERNAL int mmsClient_createReadRequestAlternateAccessIndex(uint32_t invokeId, const char* domainId, const char* itemId, uint32_t index, uint32_t elementCount, ByteBuffer* writeBuffer); diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index 0cab6c2a..fbfa4f55 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -357,9 +357,12 @@ mmsServer_handleObtainFileRequest( uint32_t invokeId, ByteBuffer* response); -LIB61850_INTERNAL int +LIB61850_INTERNAL bool mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess); +LIB61850_INTERNAL bool +mmsServer_isComponentAccess(AlternateAccess_t* alternateAccess); + LIB61850_INTERNAL int mmsServer_getLowIndex(AlternateAccess_t* alternateAccess); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 7f4bac36..7da2ee0b 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -2115,6 +2115,67 @@ MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, return value; } +uint32_t +MmsConnection_readVariableComponentAsync(MmsConnection self, MmsError* mmsError, + const char* domainId, const char* itemId, const char* componentId, + MmsConnection_ReadVariableHandler handler, void* parameter) +{ + uint32_t invokeId = 0; + + if (getConnectionState(self) != MMS_CONNECTION_STATE_CONNECTED) { + if (mmsError) + *mmsError = MMS_ERROR_CONNECTION_LOST; + + goto exit_function; + } + + ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient); + + invokeId = getNextInvokeId(self); + + mmsClient_createReadRequestComponent(invokeId, domainId, itemId, componentId, payload); + + MmsError err = sendAsyncRequest(self, invokeId, payload, MMS_CALL_TYPE_READ_VARIABLE, handler, parameter, NULL); + + if (mmsError) + *mmsError = err; + +exit_function: + return invokeId; +} + +MmsValue* +MmsConnection_readVariableComponent(MmsConnection self, MmsError* mmsError, + const char* domainId, const char* itemId, const char* componentId) +{ + MmsValue* value = NULL; + MmsError err = MMS_ERROR_NONE; + + struct readNVParameters parameter; + + parameter.sem = Semaphore_create(1);; + parameter.value = NULL; + parameter.err = MMS_ERROR_NONE; + + Semaphore_wait(parameter.sem); + + MmsConnection_readVariableComponentAsync(self, &err, domainId, itemId, componentId, readVariableHandler, ¶meter); + + if (err == MMS_ERROR_NONE) { + Semaphore_wait(parameter.sem); + + value = parameter.value; + err = parameter.err; + } + + Semaphore_destroy(parameter.sem); + + if (mmsError) + *mmsError = err; + + return value; +} + MmsValue* MmsConnection_readArrayElements(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId, diff --git a/src/mms/iso_mms/client/mms_client_read.c b/src/mms/iso_mms/client/mms_client_read.c index ceef5885..795cff9c 100644 --- a/src/mms/iso_mms/client/mms_client_read.c +++ b/src/mms/iso_mms/client/mms_client_read.c @@ -527,6 +527,132 @@ mmsClient_createReadRequest(uint32_t invokeId, const char* domainId, const char* return rval.encoded; } +static AlternateAccess_t* +createAlternateAccessComponent(const char* componentName) +{ + AlternateAccess_t* alternateAccess = (AlternateAccess_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccess_t)); + alternateAccess->list.count = 1; + alternateAccess->list.array = (struct AlternateAccess__Member**) GLOBAL_CALLOC(1, sizeof(struct AlternateAccess__Member*)); + alternateAccess->list.array[0] = (struct AlternateAccess__Member*) GLOBAL_CALLOC(1, sizeof(struct AlternateAccess__Member)); + alternateAccess->list.array[0]->present = AlternateAccess__Member_PR_unnamed; + + alternateAccess->list.array[0]->choice.unnamed = (AlternateAccessSelection_t*) GLOBAL_CALLOC(1, sizeof(AlternateAccessSelection_t)); + + const char* separator = strchr(componentName, '$'); + + if (separator) { + int size = separator - componentName; + + alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAlternateAccess; + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present = + AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component; + + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.buf = + (uint8_t*) StringUtils_copySubString((char*) componentName, (char*) separator); + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.size = size; + + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess = createAlternateAccessComponent(separator + 1); + } + else { + int size = strlen(componentName); + + alternateAccess->list.array[0]->choice.unnamed->present = AlternateAccessSelection_PR_selectAccess; + + alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present = + AlternateAccessSelection__selectAccess_PR_component; + + alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.buf = + (uint8_t*) StringUtils_copyString(componentName); + alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.size = size; + } + + return alternateAccess; +} + +static void +deleteAlternateAccessComponent(AlternateAccess_t* alternateAccess) +{ + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess) + deleteAlternateAccessComponent(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess); + + if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAlternateAccess) + GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.choice.component.buf); + else if (alternateAccess->list.array[0]->choice.unnamed->present == AlternateAccessSelection_PR_selectAccess) + GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component.buf); + + GLOBAL_FREEMEM(alternateAccess->list.array[0]->choice.unnamed); + GLOBAL_FREEMEM(alternateAccess->list.array[0]); + GLOBAL_FREEMEM(alternateAccess->list.array); + GLOBAL_FREEMEM(alternateAccess); +} + +static ListOfVariableSeq_t* +createNewVariableSpecification(const char* domainId, const char* itemId, const char* componentName, bool associationSpecific) +{ + ListOfVariableSeq_t* varSpec = (ListOfVariableSeq_t*) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t)); + + varSpec->variableSpecification.present = VariableSpecification_PR_name; + + if (domainId) { + varSpec->variableSpecification.choice.name.present = ObjectName_PR_domainspecific; + varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.buf = (uint8_t*) domainId; + varSpec->variableSpecification.choice.name.choice.domainspecific.domainId.size = strlen(domainId); + varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.buf = (uint8_t*) itemId; + varSpec->variableSpecification.choice.name.choice.domainspecific.itemId.size = strlen(itemId); + } + else if (associationSpecific) { + varSpec->variableSpecification.choice.name.present = ObjectName_PR_aaspecific; + varSpec->variableSpecification.choice.name.choice.aaspecific.buf = (uint8_t*) itemId; + varSpec->variableSpecification.choice.name.choice.aaspecific.size = strlen(itemId); + } + else { + varSpec->variableSpecification.choice.name.present = ObjectName_PR_vmdspecific; + varSpec->variableSpecification.choice.name.choice.vmdspecific.buf = (uint8_t*) itemId; + varSpec->variableSpecification.choice.name.choice.vmdspecific.size = strlen(itemId); + } + + if (componentName) + varSpec->alternateAccess = createAlternateAccessComponent(componentName); + + return varSpec; +} + +/** + * Request a single value with optional component + */ +int +mmsClient_createReadRequestComponent(uint32_t invokeId, const char* domainId, const char* itemId, const char* component, ByteBuffer* writeBuffer) +{ + MmsPdu_t* mmsPdu = mmsClient_createConfirmedRequestPdu(invokeId); + + ReadRequest_t* readRequest = createReadRequest(mmsPdu); + + readRequest->specificationWithResult = NULL; + + readRequest->variableAccessSpecification.present = VariableAccessSpecification_PR_listOfVariable; + readRequest->variableAccessSpecification.choice.listOfVariable.list.count = 1; + readRequest->variableAccessSpecification.choice.listOfVariable.list.size = 1; + readRequest->variableAccessSpecification.choice.listOfVariable.list.array = + (ListOfVariableSeq_t**) GLOBAL_CALLOC(1, sizeof(ListOfVariableSeq_t*)); + readRequest->variableAccessSpecification.choice.listOfVariable.list.array[0] = createNewVariableSpecification(domainId, itemId, component, false); + + asn_enc_rval_t rval; + + rval = der_encode(&asn_DEF_MmsPdu, mmsPdu, + (asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer); + + /* clean up data structures */ + deleteAlternateAccessComponent(readRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]->alternateAccess); + + GLOBAL_FREEMEM(readRequest->variableAccessSpecification.choice.listOfVariable.list.array[0]); + GLOBAL_FREEMEM(readRequest->variableAccessSpecification.choice.listOfVariable.list.array); + readRequest->variableAccessSpecification.choice.listOfVariable.list.array = NULL; + readRequest->variableAccessSpecification.choice.listOfVariable.list.count = 0; + asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); + + return rval.encoded; +} + static ListOfVariableSeq_t* createVariableIdentifier(const char* domainId, const char* itemId) { diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c index 727f5ed6..dba52d1b 100644 --- a/src/mms/iso_mms/server/mms_read_service.c +++ b/src/mms/iso_mms/server/mms_read_service.c @@ -155,6 +155,57 @@ isAccessToArrayComponent(AlternateAccess_t* alternateAccess) return false; } +static MmsValue* +getComponent(MmsServerConnection connection, MmsDomain* domain, AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable, char* variableName) +{ + MmsValue* retValue = NULL; + + if (mmsServer_isComponentAccess(alternateAccess)) { + Identifier_t component = + alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.choice.component; + + if (component.size > 129) + goto exit_function; + + if (namedVariable->type == MMS_STRUCTURE) { + + int i; + + for (i = 0; i < namedVariable->typeSpec.structure.elementCount; i++) { + + if ((int) strlen(namedVariable->typeSpec.structure.elements[i]->name) + == component.size) { + if (!strncmp(namedVariable->typeSpec.structure.elements[i]->name, + (char*) component.buf, component.size)) + { + if (strlen(variableName) + component.size < 199) { + + strcat(variableName, "$"); + strncat(variableName, (const char*) component.buf, component.size); + + + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess + != NULL) { + retValue = + getComponent(connection, domain, + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess, + namedVariable->typeSpec.structure.elements[i], + variableName); + } + else { + retValue = mmsServer_getValue(connection->server, domain, variableName, connection); + } + } + } + } + } + } + } + +exit_function: + return retValue; +} + static MmsValue* getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable, MmsValue* structuredValue) @@ -180,19 +231,26 @@ getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecif int i; for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++) { - if (strncmp (structSpec->typeSpec.structure.elements[i]->name, (char*) component.buf, - component.size) == 0) - { - MmsValue* value = MmsValue_getElement(structuredValue, i); - - if (isAccessToArrayComponent(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) { - retValue = getComponentOfArrayElement(alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess, - structSpec->typeSpec.structure.elements[i], value); - } - else - retValue = value; - goto exit_function; + if ((int) strlen(structSpec->typeSpec.structure.elements[i]->name) + == component.size) { + if (strncmp(structSpec->typeSpec.structure.elements[i]->name, + (char*) component.buf, component.size) == 0) { + MmsValue* value = MmsValue_getElement(structuredValue, i); + + if (isAccessToArrayComponent( + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) { + retValue = + getComponentOfArrayElement( + alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess, + structSpec->typeSpec.structure.elements[i], + value); + } + else + retValue = value; + + goto exit_function; + } } } } @@ -279,50 +337,73 @@ static void addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain* domain, char* nameIdStr, LinkedList /**/ values, MmsServerConnection connection, AlternateAccess_t* alternateAccess) { - if (namedVariable != NULL) { + if (namedVariable != NULL) { - if (DEBUG_MMS_SERVER) printf("MMS read: found named variable %s with search string %s\n", - namedVariable->name, nameIdStr); + if (DEBUG_MMS_SERVER) + printf("MMS read: found named variable %s with search string %s\n", + namedVariable->name, nameIdStr); - if (namedVariable->type == MMS_STRUCTURE) { + if (namedVariable->type == MMS_STRUCTURE) { - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); - if (value != NULL) { - appendValueToResultList(value, values); - } - else { - addComplexValueToResultList(namedVariable, - values, connection, domain, nameIdStr); - } - } - else if (namedVariable->type == MMS_ARRAY) { + if (alternateAccess != NULL) { - if (alternateAccess != NULL) { - alternateArrayAccess(connection, alternateAccess, domain, - nameIdStr, values, namedVariable); - } - else { /* return complete array */ - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); - appendValueToResultList(value, values); - } - } - else { - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + char variableName[200]; + variableName[0] = 0; + strcat(variableName, nameIdStr); - if (value == NULL) { - if (DEBUG_MMS_SERVER) - printf("MMS read: value of known variable is not found. Maybe illegal access to array element!\n"); + value = getComponent(connection, domain, alternateAccess, namedVariable, variableName); - appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); - } - else - appendValueToResultList(value, values); - } + if (value != NULL) { + appendValueToResultList(value, values); + } + else { + appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); + } + } + else { + if (value != NULL) { + appendValueToResultList(value, values); + } + else { + addComplexValueToResultList(namedVariable, + values, connection, domain, nameIdStr); + } + } + } + else if (namedVariable->type == MMS_ARRAY) { - } - else - appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); + if (alternateAccess != NULL) { + alternateArrayAccess(connection, alternateAccess, domain, + nameIdStr, values, namedVariable); + } + else { /* return complete array */ + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + appendValueToResultList(value, values); + } + } + else { + + if (alternateAccess != NULL) { + appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); + } + else { + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + + if (value == NULL) { + if (DEBUG_MMS_SERVER) + printf("MMS read: value of known variable is not found. Maybe illegal access to array element!\n"); + + appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); + } + else + appendValueToResultList(value, values); + } + } + } + else + appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); } diff --git a/src/mms/iso_mms/server/mms_server_common.c b/src/mms/iso_mms/server/mms_server_common.c index e6522bf4..96709b6c 100644 --- a/src/mms/iso_mms/server/mms_server_common.c +++ b/src/mms/iso_mms/server/mms_server_common.c @@ -208,22 +208,34 @@ mmsMsg_createServiceErrorPdu(uint32_t invokeId, ByteBuffer* response, MmsError e mmsServer_createServiceErrorPduWithServiceSpecificInfo(invokeId, response, errorType, NULL, 0); } -int +bool mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess) { - if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) { - if ((alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present - == AlternateAccessSelection__selectAccess_PR_index) || - (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present - == AlternateAccessSelection__selectAccess_PR_indexRange)) - { - return 1; - } - else - return 0; - } - else - return 0; + if (alternateAccess->list.array[0]->present == AlternateAccess__Member_PR_unnamed) { + if ((alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present + == AlternateAccessSelection__selectAccess_PR_index) || + (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present + == AlternateAccessSelection__selectAccess_PR_indexRange)) + { + return true; + } + } + + return false; +} + +bool +mmsServer_isComponentAccess(AlternateAccess_t* alternateAccess) +{ + if (alternateAccess->list.array[0]->present + == AlternateAccess__Member_PR_unnamed) { + if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAccess.present + == AlternateAccessSelection__selectAccess_PR_component) { + return true; + } + } + + return false; } int