From 9896742d120fdf644e9160d123917746eacbcee7 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Wed, 28 Oct 2015 14:18:05 +0100 Subject: [PATCH] - added support for sorted getNameList reponse (can be switched off by setting CONFIG_MMS_SORT_NAME_LIST to 0) --- config/stack_config.h | 4 + src/common/string_utilities.c | 81 +++---- .../iso_mms/server/mms_get_namelist_service.c | 220 ++---------------- 3 files changed, 60 insertions(+), 245 deletions(-) diff --git a/config/stack_config.h b/config/stack_config.h index da4c5adc..53c649fc 100644 --- a/config/stack_config.h +++ b/config/stack_config.h @@ -188,6 +188,10 @@ /* VMD scope named variables are not used by IEC 61850 (one application is ICCP) */ #define CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES 0 +/* Sort getNameList response according to the MMS specified collation order - this is required by the standard + * Set to 0 only for performance reasons and when no certification is required! */ +#define CONFIG_MMS_SORT_NAME_LIST 1 + #define CONFIG_INCLUDE_PLATFORM_SPECIFIC_HEADERS 0 /* use short FC defines as in old API */ diff --git a/src/common/string_utilities.c b/src/common/string_utilities.c index 0004dec3..b33a3f71 100644 --- a/src/common/string_utilities.c +++ b/src/common/string_utilities.c @@ -300,69 +300,64 @@ StringUtils_compareStrings(const char* a, const char* b) void StringUtils_sortList(LinkedList list) { - LinkedList firstElement = list->next; - LinkedList prevElement = NULL; + LinkedList selectedElement = list->next; - while (true) { + if (selectedElement == NULL) /* list is empty */ + return; - /* Check for end of list */ - if (firstElement->next) { + list->next = selectedElement->next; + selectedElement->next = NULL; - char* str1 = (char*) LinkedList_getData(firstElement); - char* str2 = (char*) LinkedList_getData(firstElement->next); + struct sLinkedList sortedListData; - /* Compare first element with next element */ - if (StringUtils_compareStrings(str1, str2) > 0) { - LinkedList removedElement = firstElement; + LinkedList sortedList = &sortedListData; - if (firstElement == list->next) - list->next = firstElement->next; - else - prevElement->next = firstElement->next; + sortedList->next = selectedElement; - firstElement = firstElement->next; + selectedElement = list->next; - /* search for place to insert */ - LinkedList compareElement = removedElement->next->next; - LinkedList prevCompareElement = removedElement->next; + while (selectedElement != NULL) { - while (true) { - str2 = (char*) LinkedList_getData(compareElement); + list->next = selectedElement->next; + selectedElement->next = NULL; - if (StringUtils_compareStrings(str1, str2) < 0) { - /* insert element before */ - prevCompareElement->next = removedElement; - removedElement->next = compareElement; + char* str1 = (char*) LinkedList_getData(selectedElement); - break; - } + LinkedList prevElement = sortedList; - prevCompareElement = compareElement; - compareElement = compareElement->next; + while (true) { - /* Are we at the end of the list? */ - if (compareElement == NULL) { - /* Insert removed element at end of list */ - prevCompareElement->next = removedElement; - removedElement->next = NULL; - break; - } + if (prevElement->next == NULL) { + prevElement->next = selectedElement; + break; + } + + char* str2 = (char*) LinkedList_getData(prevElement->next); + + if (StringUtils_compareStrings(str1, str2) < 0) { + /* insert "nextElement" before */ + if (sortedList == prevElement) { + selectedElement->next = sortedList->next; + sortedList->next = selectedElement; + } + else { + selectedElement->next = prevElement->next; + prevElement->next = selectedElement; } + break; } - else { - prevElement = firstElement; - firstElement = firstElement->next; - } + prevElement = prevElement->next; + } + selectedElement = list->next; - } - else + if (selectedElement == NULL) break; - } -} + list->next = sortedList->next; +} diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c index 4bc40481..ef8116b2 100644 --- a/src/mms/iso_mms/server/mms_get_namelist_service.c +++ b/src/mms/iso_mms/server/mms_get_namelist_service.c @@ -32,6 +32,10 @@ * MMS GetNameList Service *********************************************************************************************/ +#ifndef CONFIG_MMS_SORT_NAME_LIST +#define CONFIG_MMS_SORT_NAME_LIST 1 +#endif + #define OBJECT_CLASS_NAMED_VARIABLE 0 #define OBJECT_CLASS_NAMED_VARIABLE_LIST 2 #define OBJECT_CLASS_JOURNAL 8 @@ -160,84 +164,6 @@ getNameListDomainSpecific(MmsServerConnection connection, char* domainName) } - -#if 0 -typedef struct sGetNextListElementDomainSpecificState { - const char* continueAfter; - MmsVariableSpecification** variables; - int variablesCount; -} GetNextListElementDomainSpecificState; - - -static bool -getNextListElement_DomainSpecific_init(MmsServerConnection connection, char* domainName, - GetNextListElementDomainSpecificState* state, const char* continueAfter) -{ - MmsDevice* device = MmsServer_getDevice(connection->server); - MmsDomain* domain = MmsDevice_getDomain(device, domainName); - - state->continueAfter = continueAfter; - - if (domain != NULL) { - state->variables = domain->namedVariables; - state->variablesCount = domain->namedVariablesCount; - } -} - - -static LinkedList -TEMP_addSubNamedVaribleNamesToList(LinkedList nameList, char* prefix, MmsVariableSpecification* variable) -{ - LinkedList listElement = nameList; - - if (variable->type == MMS_STRUCTURE) { - - int i; - - MmsVariableSpecification** variables = variable->typeSpec.structure.elements; - - for (i = 0; i < variable->typeSpec.structure.elementCount; i++) { - char* variableName = appendMmsSubVariable(prefix, variables[i]->name); - - listElement = LinkedList_insertAfter(listElement, variableName); - - listElement = addSubNamedVaribleNamesToList(listElement, variableName, variables[i]); - } - } - - return listElement; -} - - -// return NULL if no more elements are left -static char* -getNextListElement_DomainSpecific(void* stateParameter) -{ - GetNextListElementDomainSpecificState* state = (GetNextListElementDomainSpecificState*) stateParameter; - - = NULL; - - int i; - - LinkedList element = nameList; - - for (i = 0; i < state->variablesCount; i++) { - element = LinkedList_insertAfter(element, copyString(state->variables[i]->name)); - -#if (CONFIG_MMS_SUPPORT_FLATTED_NAME_SPACE == 1) - char* prefix = state->variables[i]->name; - element = TEMP_addSubNamedVaribleNamesToList(element, prefix, state->variables[i]); -#endif - - } - - - return nameList; -} -#endif - - - #if (MMS_DATA_SET_SERVICE == 1) static LinkedList @@ -409,122 +335,6 @@ createNameListResponse( printf("MMS_SERVER: getNameList: encoded %i bytes\n", response->size); } -#if 0 -static void -NEW_createNameListResponse( - MmsServerConnection connection, - int invokeId, - LinkedList nameList, - ByteBuffer* response, - char* continueAfter) -{ - - -#if 0 - - //TODO move continueAfter handling in variable name generation code! - LinkedList startElement = NULL; - - - if (continueAfter != NULL) { - LinkedList element = nameList; - - while ((element = LinkedList_getNext(element)) != NULL) { - if (strcmp((char*) (element->data), continueAfter) == 0) { - startElement = element; - break; - } - } - - if (startElement == NULL) { - mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED); - return; - } - } - - /* determine number of identifiers to include in response */ - if (startElement == NULL) - startElement = nameList; -#endif - - - - int nameCount = 0; - int estimatedMmsPduLength = 27; /* estimated overhead size of PDU encoding */ - int maxPduSize = connection->maxPduSize; - - bool moreFollows = false; - - LinkedList element = startElement; - - uint32_t identifierListSize = 0; - - while ((element = LinkedList_getNext(element)) != NULL) { - int elementLength; - - elementLength = BerEncoder_determineEncodedStringSize((char*) element->data); - - if ((estimatedMmsPduLength + elementLength) > maxPduSize) { - moreFollows = true; - break; - } - else { - estimatedMmsPduLength += elementLength; - identifierListSize += elementLength; - nameCount++; - } - - } - - uint32_t listOfIdentifierSize = 1 + BerEncoder_determineLengthSize(identifierListSize) + identifierListSize; - - uint32_t getNameListSize = listOfIdentifierSize; - - if (moreFollows == false) - getNameListSize += 3; - - uint32_t confirmedServiceResponseSize = 1 + BerEncoder_determineLengthSize(getNameListSize) + getNameListSize; - - uint32_t invokeIdSize = BerEncoder_UInt32determineEncodedSize((uint32_t) invokeId) + 2; - - uint32_t confirmedResponsePDUSize = confirmedServiceResponseSize + invokeIdSize; - - /* encode response */ - element = startElement; - - uint8_t* buffer = response->buffer; - int bufPos = 0; - - 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(0xa1, getNameListSize, buffer, bufPos); - bufPos = BerEncoder_encodeTL(0xa0, identifierListSize, buffer, bufPos); - - int i = 0; - - while ((element = LinkedList_getNext(element)) != NULL) { - bufPos = BerEncoder_encodeStringWithTag(0x1a, (char*) element->data, buffer, bufPos); - - i++; - - if (i == nameCount) - break; - } - - if (moreFollows == false) - bufPos = BerEncoder_encodeBoolean(0x81, moreFollows, buffer, bufPos); - - response->size = bufPos; - - if (DEBUG_MMS_SERVER) - printf("MMS_SERVER: getNameList: encoded %i bytes\n", response->size); -} -#endif - - void mmsServer_handleGetNameListRequest( MmsServerConnection connection, @@ -626,14 +436,9 @@ mmsServer_handleGetNameListRequest( mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { - printf("\n-------------\n"); - LinkedList_printStringList(nameList); - +#if (CONFIG_MMS_SORT_NAME_LIST == 1) StringUtils_sortList(nameList); - - printf("\n-------------\n"); - LinkedList_printStringList(nameList); - printf("\n-------------\n"); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfterId); LinkedList_destroy(nameList); @@ -646,7 +451,10 @@ mmsServer_handleGetNameListRequest( if (nameList == NULL) mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT); else { + +#if (CONFIG_MMS_SORT_NAME_LIST == 1) StringUtils_sortList(nameList); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfter); LinkedList_destroy(nameList); @@ -667,7 +475,9 @@ mmsServer_handleGetNameListRequest( LinkedList nameList = getDomainNames(connection); +#if (CONFIG_MMS_SORT_NAME_LIST == 1) StringUtils_sortList(nameList); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfter); @@ -688,7 +498,9 @@ mmsServer_handleGetNameListRequest( else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) { LinkedList nameList = getnamedVariableListsVMDSpecific(connection); +#if (CONFIG_MMS_SORT_NAME_LIST == 1) StringUtils_sortList(nameList); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfter); @@ -699,7 +511,9 @@ mmsServer_handleGetNameListRequest( else if (objectClass == OBJECT_CLASS_JOURNAL) { LinkedList nameList = LinkedList_create(); - // StringUtils_sortList(nameList); +#if (CONFIG_MMS_SORT_NAME_LIST == 1) + StringUtils_sortList(nameList); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfter); @@ -720,7 +534,9 @@ mmsServer_handleGetNameListRequest( if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) { LinkedList nameList = getNamedVariableListAssociationSpecific(connection); +#if (CONFIG_MMS_SORT_NAME_LIST == 1) StringUtils_sortList(nameList); +#endif createNameListResponse(connection, invokeId, nameList, response, continueAfter);