diff --git a/CHANGELOG b/CHANGELOG index ecd71382..eaaa9046 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +Changes to version 1.5.0 +------------------------ +- IEC 61850 server: control models - allow delaying select response with check handler (new handler return value CONTROL_WAITING_FOR_SELECT) + Changes to version 1.4.1 ------------------------ - MMS server: refactored connection handling; more efficient use of HandleSet diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index f34e67ea..f1d653c2 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -1146,6 +1146,7 @@ IedServer_setEditSettingGroupConfirmationHandler(IedServer self, SettingGroupCon */ typedef enum { CONTROL_ACCEPTED = -1, /** check passed */ + CONTROL_WAITING_FOR_SELECT = 0, /** select operation in progress - handler will be called again later */ CONTROL_HARDWARE_FAULT = 1, /** check failed due to hardware fault */ CONTROL_TEMPORARILY_UNAVAILABLE = 2, /** control is already selected or operated */ CONTROL_OBJECT_ACCESS_DENIED = 3, /** check failed due to access control reason - access denied for this client or state */ diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c index cca6d5f3..e78a1894 100644 --- a/src/iec61850/server/mms_mapping/control.c +++ b/src/iec61850/server/mms_mapping/control.c @@ -1,7 +1,7 @@ /* * control.c * - * Copyright 2013-2019 Michael Zillgith + * Copyright 2013-2020 Michael Zillgith * * This file is part of libIEC61850. * @@ -45,6 +45,7 @@ #define STATE_PERFORM_TEST 3 #define STATE_WAIT_FOR_EXECUTION 4 #define STATE_OPERATE 5 +#define STATE_WAIT_FOR_SELECT 6 #define PENDING_EVENT_SELECTED 1 #define PENDING_EVENT_UNSELECTED 2 @@ -55,6 +56,8 @@ static MmsValue emptyString = {MMS_STRUCTURE}; +static MmsValue delayedResponse = {MMS_DATA_ACCESS_ERROR, 0, {DATA_ACCESS_ERROR_NO_RESPONSE}}; + void ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connection, char* ctlVariable, int error, ControlAddCause addCause, MmsValue* ctlNum, MmsValue* origin, bool handlerMode); @@ -65,10 +68,6 @@ ControlObject_sendCommandTerminationPositive(ControlObject* self); void ControlObject_sendCommandTerminationNegative(ControlObject* self); -MmsValue* -Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, - MmsServerConnection connection); - static void unselectObject(ControlObject* self); @@ -123,6 +122,65 @@ setStSeld(ControlObject* self, bool value) } } +static void +updateSboTimeoutValue(ControlObject* self) +{ + if (self->sboTimeout != NULL) { + uint32_t sboTimeoutVal = MmsValue_toInt32(self->sboTimeout); + + if (DEBUG_IED_SERVER) + printf("IED_SERVER: set timeout for %s/%s.%s to %u\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name, sboTimeoutVal); + + self->selectTimeout = sboTimeoutVal; + } + else + self->selectTimeout = CONFIG_CONTROL_DEFAULT_SBO_TIMEOUT; +} + +static void +selectObject(ControlObject* self, uint64_t selectTime, MmsServerConnection connection) +{ + if (DEBUG_IED_SERVER) + printf("IED_SERVER: control %s/%s.%s selected\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name); + + updateSboTimeoutValue(self); + + self->selectTime = selectTime; + self->mmsConnection = connection; + setStSeld(self, true); + setState(self, STATE_READY); +} + +static void +unselectObject(ControlObject* self) +{ + setState(self, STATE_UNSELECTED); + + setStSeld(self, false); + + if (DEBUG_IED_SERVER) + printf("IED_SERVER: control %s/%s.%s unselected\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name); +} + +static void +checkSelectTimeout(ControlObject* self, uint64_t currentTime) +{ + if ((self->ctlModel == 2) || (self->ctlModel == 4)) { + + if (getState(self) == STATE_READY) { + if (self->selectTimeout > 0) { + if (currentTime > (self->selectTime + self->selectTimeout)) { + if (DEBUG_IED_SERVER) + printf("IED_SERVER: select-timeout (timeout-val = %i) for control %s/%s.%s\n", + self->selectTimeout, MmsDomain_getName(self->mmsDomain), self->lnName, self->name); + + unselectObject(self); + } + } + } + } +} + static void setOpRcvd(ControlObject* self, bool value) { @@ -159,7 +217,6 @@ setOpOk(ControlObject* self, bool value, uint64_t currentTimeInMs) /* TODO update time quality */ } - self->pendingEvents |= PENDING_EVENT_OP_OK_TRUE; } else @@ -171,21 +228,6 @@ setOpOk(ControlObject* self, bool value, uint64_t currentTimeInMs) } } -static void -updateSboTimeoutValue(ControlObject* self) -{ - if (self->sboTimeout != NULL) { - uint32_t sboTimeoutVal = MmsValue_toInt32(self->sboTimeout); - - if (DEBUG_IED_SERVER) - printf("IED_SERVER: set timeout for %s/%s.%s to %u\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name, sboTimeoutVal); - - self->selectTimeout = sboTimeoutVal; - } - else - self->selectTimeout = CONFIG_CONTROL_DEFAULT_SBO_TIMEOUT; -} - static bool isSboClassOperateOnce(ControlObject* self) { @@ -280,6 +322,74 @@ executeStateMachine: switch (state) { + case STATE_WAIT_FOR_SELECT: + { + self->isSelect = 1; + + CheckHandlerResult checkHandlerResult = self->checkHandler((ControlAction) self, self->checkHandlerParameter, NULL, false, false); + + self->isSelect = 0; + + if (checkHandlerResult != CONTROL_WAITING_FOR_SELECT) { + + if (self->ctlModel == 2) { + LinkedList values = LinkedList_create(); + + if (checkHandlerResult == CONTROL_ACCEPTED) { + LinkedList_add(values, self->sbo); + + selectObject(self, Hal_getTimeInMs(), self->mmsConnection); + } + else { + LinkedList_add(values, &emptyString); + + setState(self, STATE_UNSELECTED); + } + + MmsServerConnection_sendReadResponse(self->mmsConnection, self->operateInvokeId, values, false); + + LinkedList_destroyStatic(values); + } + else if (self->ctlModel == 4) { + if (checkHandlerResult == CONTROL_ACCEPTED) { + + selectObject(self, Hal_getTimeInMs(), self->mmsConnection); + + if (self->ctlNumSt) + MmsValue_update(self->ctlNumSt, self->ctlNum); + + if (self->originSt) + MmsValue_update(self->originSt, self->origin); + + MmsServerConnection_sendWriteResponse(self->mmsConnection, self->operateInvokeId, DATA_ACCESS_ERROR_SUCCESS, false); + + if (DEBUG_IED_SERVER) + printf("IED_SERVER: SBOw - selected successful\n"); + } + else { + + setState(self, STATE_UNSELECTED); + + ControlObject_sendLastApplError(self, self->mmsConnection, "SBOw", 0, + ADD_CAUSE_SELECT_FAILED, self->ctlNum, self->origin, false); + + MmsServerConnection_sendWriteResponse(self->mmsConnection, self->operateInvokeId, (MmsDataAccessError) checkHandlerResult, false); + + if (DEBUG_IED_SERVER) + printf("IED_SERVER: SBOw - select rejected by application!\n"); + } + } + else { + /* ERROR: invalid internal state! */ + setState(self, STATE_WAIT_FOR_SELECT); + } + + } + + } + break; + + case STATE_WAIT_FOR_ACTIVATION_TIME: case STATE_WAIT_FOR_EXECUTION: { @@ -681,50 +791,6 @@ ControlObject_getMmsValue(ControlObject* self) return self->mmsValue; } -static void -selectObject(ControlObject* self, uint64_t selectTime, MmsServerConnection connection) -{ - if (DEBUG_IED_SERVER) - printf("IED_SERVER: control %s/%s.%s selected\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name); - - updateSboTimeoutValue(self); - - self->selectTime = selectTime; - self->mmsConnection = connection; - setStSeld(self, true); - setState(self, STATE_READY); -} - -static void -unselectObject(ControlObject* self) -{ - setState(self, STATE_UNSELECTED); - - setStSeld(self, false); - - if (DEBUG_IED_SERVER) - printf("IED_SERVER: control %s/%s.%s unselected\n", MmsDomain_getName(self->mmsDomain), self->lnName, self->name); -} - -static void -checkSelectTimeout(ControlObject* self, uint64_t currentTime) -{ - if ((self->ctlModel == 2) || (self->ctlModel == 4)) { - - if (getState(self) == STATE_READY) { - if (self->selectTimeout > 0) { - if (currentTime > (self->selectTime + self->selectTimeout)) { - if (DEBUG_IED_SERVER) - printf("IED_SERVER: select-timeout (timeout-val = %i) for control %s/%s.%s\n", - self->selectTimeout, MmsDomain_getName(self->mmsDomain), self->lnName, self->name); - - unselectObject(self); - } - } - } - } -} - bool ControlObject_unselect(ControlObject* self, MmsServerConnection connection) { @@ -1181,7 +1247,7 @@ doesElementEquals(char* element, char* name) MmsValue* Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, - MmsServerConnection connection) + MmsServerConnection connection, bool isDirectAccess) { MmsValue* value = NULL; @@ -1259,28 +1325,36 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia value = &emptyString; - checkSelectTimeout(controlObject, currentTime); + if (isDirectAccess == true) { + checkSelectTimeout(controlObject, currentTime); - if (getState(controlObject) == STATE_UNSELECTED) { - CheckHandlerResult checkResult = CONTROL_ACCEPTED; + if (getState(controlObject) == STATE_UNSELECTED) { + CheckHandlerResult checkResult = CONTROL_ACCEPTED; - /* opRcvd must not be set here! */ + /* opRcvd must not be set here! */ - controlObject->addCauseValue = ADD_CAUSE_UNKNOWN; + controlObject->addCauseValue = ADD_CAUSE_UNKNOWN; - if (controlObject->checkHandler != NULL) { /* perform operative tests */ + if (controlObject->checkHandler != NULL) { /* perform operative tests */ - controlObject->isSelect = 1; + controlObject->isSelect = 1; - checkResult = controlObject->checkHandler((ControlAction) controlObject, - controlObject->checkHandlerParameter, NULL, false, false); + checkResult = controlObject->checkHandler((ControlAction) controlObject, + controlObject->checkHandlerParameter, NULL, false, false); - controlObject->isSelect = 0; - } + controlObject->isSelect = 0; + } - if (checkResult == CONTROL_ACCEPTED) { - selectObject(controlObject, currentTime, connection); - value = controlObject->sbo; + if (checkResult == CONTROL_ACCEPTED) { + selectObject(controlObject, currentTime, connection); + value = controlObject->sbo; + } + else if (checkResult == CONTROL_WAITING_FOR_SELECT) { + controlObject->mmsConnection = connection; + controlObject->operateInvokeId = MmsServerConnection_getLastInvokeId(connection); + setState(controlObject, STATE_WAIT_FOR_SELECT); + value = &delayedResponse; + } } } @@ -1398,11 +1472,9 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari varName = NULL; } - if (DEBUG_IED_SERVER) printf("IED_SERVER: write access control: objectName: (%s) varName: (%s)\n", objectName, varName); - if (varName == NULL) { indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; goto free_and_return; @@ -1489,6 +1561,18 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari if (DEBUG_IED_SERVER) printf("IED_SERVER: SBOw - selected successful\n"); } + else if (checkResult == CONTROL_WAITING_FOR_SELECT) { + controlObject->mmsConnection = connection; + controlObject->operateInvokeId = MmsServerConnection_getLastInvokeId(connection); + + MmsValue_update(controlObject->ctlVal, ctlVal); + MmsValue_update(controlObject->ctlNum, ctlNum); + MmsValue_update(controlObject->origin, origin); + + setState(controlObject, STATE_WAIT_FOR_SELECT); + + indication = DATA_ACCESS_ERROR_NO_RESPONSE; + } else { indication = (MmsDataAccessError) checkResult; diff --git a/src/iec61850/server/mms_mapping/mms_mapping.c b/src/iec61850/server/mms_mapping/mms_mapping.c index a9f75615..5a097453 100644 --- a/src/iec61850/server/mms_mapping/mms_mapping.c +++ b/src/iec61850/server/mms_mapping/mms_mapping.c @@ -71,7 +71,7 @@ typedef struct #if (CONFIG_IEC61850_CONTROL_SERVICE == 1) MmsValue* Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* variableIdOrig, - MmsServerConnection connection); + MmsServerConnection connection, bool isDirectAccess); #endif void /* Create PHYCOMADDR ACSI type instance */ @@ -2248,7 +2248,7 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI static MmsValue* -mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection) +mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection, bool isDirectAccess) { MmsMapping* self = (MmsMapping*) parameter; @@ -2267,7 +2267,7 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo #if (CONFIG_IEC61850_CONTROL_SERVICE == 1) /* Controllable objects - CO */ if (isControllable(separator)) { - retValue = Control_readAccessControlObject(self, domain, variableId, connection); + retValue = Control_readAccessControlObject(self, domain, variableId, connection, isDirectAccess); goto exit_function; } #endif @@ -2362,7 +2362,6 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo /* handle read access to other objects */ - exit_function: return retValue; } @@ -2436,7 +2435,7 @@ mmsConnectionHandler(void* parameter, MmsServerConnection connection, MmsServerE } static MmsDataAccessError -mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection) +mmsReadAccessHandler (void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection, bool isDirectAccess) { MmsMapping* self = (MmsMapping*) parameter; diff --git a/src/mms/inc_private/mms_server_connection.h b/src/mms/inc_private/mms_server_connection.h index 15d4c1a9..cb4e8fb8 100644 --- a/src/mms/inc_private/mms_server_connection.h +++ b/src/mms/inc_private/mms_server_connection.h @@ -99,6 +99,9 @@ LIB61850_INTERNAL void MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeId, MmsDataAccessError indication, bool handlerMode); +LIB61850_INTERNAL void +MmsServerConnection_sendReadResponse(MmsServerConnection self, uint32_t invokeId, LinkedList values, + bool handlerMode); LIB61850_INTERNAL uint32_t MmsServerConnection_getLastInvokeId(MmsServerConnection self); diff --git a/src/mms/inc_private/mms_server_internal.h b/src/mms/inc_private/mms_server_internal.h index 23430d4d..dfc0dbd7 100644 --- a/src/mms/inc_private/mms_server_internal.h +++ b/src/mms/inc_private/mms_server_internal.h @@ -391,8 +391,13 @@ LIB61850_INTERNAL MmsDataAccessError mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value, MmsServerConnection connection); +/** + * \brief Get the current value of a variable in the server data model + * + * \param isDirectAccess the access is result of a direct single read access to the variable and no part of broader read request + */ LIB61850_INTERNAL MmsValue* -mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection); +mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess); LIB61850_INTERNAL void mmsServer_createMmsWriteResponse(MmsServerConnection connection, diff --git a/src/mms/inc_private/mms_server_libinternal.h b/src/mms/inc_private/mms_server_libinternal.h index b516513a..b516a2d7 100644 --- a/src/mms/inc_private/mms_server_libinternal.h +++ b/src/mms/inc_private/mms_server_libinternal.h @@ -28,10 +28,10 @@ #include "mms_device_model.h" typedef MmsValue* (*MmsReadVariableHandler)(void* parameter, MmsDomain* domain, - char* variableId, MmsServerConnection connection); + char* variableId, MmsServerConnection connection, bool isDirectAccess); typedef MmsDataAccessError (*MmsReadAccessHandler) (void* parameter, MmsDomain* domain, - char* variableId, MmsServerConnection connection); + char* variableId, MmsServerConnection connection, bool isDirectAccess); typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter, MmsDomain* domain, char* variableId, MmsValue* value, diff --git a/src/mms/iso_mms/server/mms_read_service.c b/src/mms/iso_mms/server/mms_read_service.c index dba52d1b..2f38a854 100644 --- a/src/mms/iso_mms/server/mms_read_service.c +++ b/src/mms/iso_mms/server/mms_read_service.c @@ -51,7 +51,7 @@ addNamedVariableValue(MmsVariableSpecification* namedVariable, MmsServerConnecti if (namedVariable->type == MMS_STRUCTURE) { - value = mmsServer_getValue(connection->server, domain, itemId, connection); + value = mmsServer_getValue(connection->server, domain, itemId, connection, false); if (value != NULL) goto exit_function; @@ -86,7 +86,7 @@ addNamedVariableValue(MmsVariableSpecification* namedVariable, MmsServerConnecti } } else { - value = mmsServer_getValue(connection->server, domain, itemId, connection); + value = mmsServer_getValue(connection->server, domain, itemId, connection, false); } exit_function: @@ -183,7 +183,6 @@ getComponent(MmsServerConnection connection, MmsDomain* domain, AlternateAccess_ strcat(variableName, "$"); strncat(variableName, (const char*) component.buf, component.size); - if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess != NULL) { retValue = @@ -193,7 +192,7 @@ getComponent(MmsServerConnection connection, MmsDomain* domain, AlternateAccess_ variableName); } else { - retValue = mmsServer_getValue(connection->server, domain, variableName, connection); + retValue = mmsServer_getValue(connection->server, domain, variableName, connection, false); } } } @@ -275,7 +274,7 @@ alternateArrayAccess(MmsServerConnection connection, int index = lowIndex; - MmsValue* arrayValue = mmsServer_getValue(connection->server, domain, itemId, connection); + MmsValue* arrayValue = mmsServer_getValue(connection->server, domain, itemId, connection, false); if (arrayValue != NULL) { @@ -335,7 +334,7 @@ alternateArrayAccess(MmsServerConnection connection, static void addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain* domain, char* nameIdStr, - LinkedList /**/ values, MmsServerConnection connection, AlternateAccess_t* alternateAccess) + LinkedList /**/ values, MmsServerConnection connection, AlternateAccess_t* alternateAccess, bool isAccessToSingleVariable) { if (namedVariable != NULL) { @@ -345,7 +344,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain* if (namedVariable->type == MMS_STRUCTURE) { - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection, isAccessToSingleVariable); if (alternateAccess != NULL) { @@ -379,7 +378,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain* nameIdStr, values, namedVariable); } else { /* return complete array */ - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection, isAccessToSingleVariable); appendValueToResultList(value, values); } } @@ -389,7 +388,7 @@ addNamedVariableToResultList(MmsVariableSpecification* namedVariable, MmsDomain* appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); } else { - MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection); + MmsValue* value = mmsServer_getValue(connection->server, domain, nameIdStr, connection, isAccessToSingleVariable); if (value == NULL) { if (DEBUG_MMS_SERVER) @@ -641,7 +640,7 @@ handleReadListOfVariablesRequest( appendErrorToResultList(values, DATA_ACCESS_ERROR_OBJECT_NONE_EXISTENT); else addNamedVariableToResultList(namedVariable, domain, nameIdStr, - values, connection, alternateAccess); + values, connection, alternateAccess, variableCount == 1); } } #if (CONFIG_MMS_SUPPORT_VMD_SCOPE_NAMED_VARIABLES == 1) @@ -678,7 +677,28 @@ handleReadListOfVariablesRequest( } } - encodeReadResponse(connection, invokeId, response, values, NULL); + bool sendResponse = true; + + LinkedList valueElement = LinkedList_getNext(values); + + while (valueElement) { + + MmsValue* value = (MmsValue*) LinkedList_getData(valueElement); + + if (value) { + if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) { + if (MmsValue_getDataAccessError(value) == DATA_ACCESS_ERROR_NO_RESPONSE) { + sendResponse = false; + break; + } + } + } + + valueElement = LinkedList_getNext(valueElement); + } + + if (sendResponse) + encodeReadResponse(connection, invokeId, response, values, NULL); exit: @@ -689,7 +709,7 @@ exit: static void createNamedVariableListResponse(MmsServerConnection connection, MmsNamedVariableList namedList, - int invokeId, ByteBuffer* response, ReadRequest_t* read, VarAccessSpec* accessSpec) + int invokeId, ByteBuffer* response, bool isSpecWithResult, VarAccessSpec* accessSpec) { LinkedList /**/ values = LinkedList_create(); @@ -712,12 +732,12 @@ createNamedVariableListResponse(MmsServerConnection connection, MmsNamedVariable variableName); addNamedVariableToResultList(namedVariable, variableDomain, variableName, - values, connection, NULL); + values, connection, NULL, false); variable = LinkedList_getNext(variable); } - if (isSpecWithResult(read)) /* add specification to result */ + if (isSpecWithResult) /* add specification to result */ encodeReadResponse(connection, invokeId, response, values, accessSpec); else encodeReadResponse(connection, invokeId, response, values, NULL); @@ -769,7 +789,7 @@ handleReadNamedVariableListRequest( MmsNamedVariableList namedList = MmsDomain_getNamedVariableList(domain, nameIdStr); if (namedList != NULL) { - createNamedVariableListResponse(connection, namedList, invokeId, response, read, + createNamedVariableListResponse(connection, namedList, invokeId, response, isSpecWithResult(read), &accessSpec); } else { @@ -798,7 +818,7 @@ handleReadNamedVariableListRequest( accessSpec.domainId = NULL; accessSpec.itemId = listName; - createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec); + createNamedVariableListResponse(connection, namedList, invokeId, response, isSpecWithResult(read), &accessSpec); } } #if (MMS_DYNAMIC_DATA_SETS == 1) @@ -822,7 +842,7 @@ handleReadNamedVariableListRequest( accessSpec.domainId = NULL; accessSpec.itemId = listName; - createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec); + createNamedVariableListResponse(connection, namedList, invokeId, response, isSpecWithResult(read), &accessSpec); } } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ @@ -868,3 +888,23 @@ exit_function: asn_DEF_MmsPdu.free_struct(&asn_DEF_MmsPdu, mmsPdu, 0); } +void +MmsServerConnection_sendReadResponse(MmsServerConnection self, uint32_t invokeId, LinkedList values, bool handlerMode) +{ + if (handlerMode == false) + IsoConnection_lock(self->isoConnection); + + ByteBuffer* response = MmsServer_reserveTransmitBuffer(self->server); + + ByteBuffer_setSize(response, 0); + + encodeReadResponse(self, invokeId, response, values, NULL); + + IsoConnection_sendMessage(self->isoConnection, response); + + MmsServer_releaseTransmitBuffer(self->server); + + if (handlerMode == false) + IsoConnection_unlock(self->isoConnection); +} + diff --git a/src/mms/iso_mms/server/mms_server.c b/src/mms/iso_mms/server/mms_server.c index b5af1737..16df4506 100644 --- a/src/mms/iso_mms/server/mms_server.c +++ b/src/mms/iso_mms/server/mms_server.c @@ -367,14 +367,14 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va MmsValue* -mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection) +mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess) { MmsValue* value = NULL; if (self->readAccessHandler != NULL) { MmsDataAccessError accessError = self->readAccessHandler(self->readAccessHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain, - itemId, connection); + itemId, connection, isDirectAccess); if (accessError != DATA_ACCESS_ERROR_SUCCESS) { value = MmsValue_newDataAccessError(accessError); @@ -388,7 +388,7 @@ mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerCon if (value == NULL) if (self->readHandler != NULL) value = self->readHandler(self->readHandlerParameter, (domain == (MmsDomain*) self->device) ? NULL : domain, - itemId, connection); + itemId, connection, isDirectAccess); exit_function: return value; diff --git a/src/mms/iso_mms/server/mms_write_service.c b/src/mms/iso_mms/server/mms_write_service.c index 08afbc1c..dd8a7cd3 100644 --- a/src/mms/iso_mms/server/mms_write_service.c +++ b/src/mms/iso_mms/server/mms_write_service.c @@ -359,7 +359,7 @@ createWriteNamedVariableListResponse( MmsDomain* variableDomain = MmsNamedVariableListEntry_getDomain(variableListEntry); char* variableName = MmsNamedVariableListEntry_getVariableName(variableListEntry); - MmsValue* oldValue = mmsServer_getValue(connection->server, variableDomain, variableName, connection); + MmsValue* oldValue = mmsServer_getValue(connection->server, variableDomain, variableName, connection, false); Data_t* dataElement = writeRequest->listOfData.list.array[i];