From ebed8170d5cee5aa07ffb44dfa1aac34576bee88 Mon Sep 17 00:00:00 2001 From: Julius Pfrommer Date: Thu, 21 Sep 2023 08:06:49 +0200 Subject: [PATCH] feat(server): Return filter results if EventFilter validation fails --- src/server/ua_services_monitoreditem.c | 73 +++++++++++++------ .../server/check_subscription_event_filter.c | 3 + 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/src/server/ua_services_monitoreditem.c b/src/server/ua_services_monitoreditem.c index eadfc8841f9..0ff0ef9cb54 100644 --- a/src/server/ua_services_monitoreditem.c +++ b/src/server/ua_services_monitoreditem.c @@ -282,7 +282,8 @@ checkAdjustMonitoredItemParams(UA_Server *server, UA_Session *session, static UA_StatusCode checkEventFilterParam(UA_Server *server, UA_Session *session, const UA_MonitoredItem *mon, - UA_MonitoringParameters *params){ + UA_MonitoringParameters *params, + UA_MonitoredItemCreateResult *result) { if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER) return UA_STATUSCODE_GOOD; @@ -296,36 +297,66 @@ checkEventFilterParam(UA_Server *server, UA_Session *session, if(eventFilter->selectClausesSize > 128) return UA_STATUSCODE_BADCONFIGURATIONERROR; + UA_ContentFilterResult contentFilterResult; + UA_Event_staticWhereClauseValidation(server, &eventFilter->whereClause, + &contentFilterResult); + + UA_StatusCode selectClauseValidationResult[128]; + UA_Event_staticSelectClauseValidation(server,eventFilter, + selectClauseValidationResult); + //check the where clause for logical consistency - if(eventFilter->whereClause.elementsSize != 0) { - UA_ContentFilterResult contentFilterResult; - UA_Event_staticWhereClauseValidation(server, &eventFilter->whereClause, - &contentFilterResult); - for(size_t i = 0; i < contentFilterResult.elementResultsSize; ++i) { - if(contentFilterResult.elementResults[i].statusCode != UA_STATUSCODE_GOOD){ - //ToDo currently we return the first non good status code, check if - //we can use the detailed contentFilterResult later - UA_StatusCode whereResult = - contentFilterResult.elementResults[i].statusCode; - UA_ContentFilterResult_clear(&contentFilterResult); - return whereResult; - } + UA_StatusCode res = UA_STATUSCODE_GOOD; + for(size_t i = 0; i < contentFilterResult.elementResultsSize; ++i) { + if(contentFilterResult.elementResults[i].statusCode != UA_STATUSCODE_GOOD){ + //ToDo currently we return the first non good status code, check if + //we can use the detailed contentFilterResult later + res = contentFilterResult.elementResults[i].statusCode; + break; } - UA_ContentFilterResult_clear(&contentFilterResult); } + //check the select clause for logical consistency - UA_StatusCode selectClauseValidationResult[128]; - UA_Event_staticSelectClauseValidation(server,eventFilter, - selectClauseValidationResult); for(size_t i = 0; i < eventFilter->selectClausesSize; ++i){ //ToDo currently we return the first non good status code, check if //we can use the detailed status code list later if(selectClauseValidationResult[i] != UA_STATUSCODE_GOOD){ - return selectClauseValidationResult[i]; + res = selectClauseValidationResult[i]; + break; } } - return UA_STATUSCODE_GOOD; + if(res == UA_STATUSCODE_GOOD) { + UA_ContentFilterResult_clear(&contentFilterResult); + return res; + } + + /* Create the EventFilterResult output */ + UA_EventFilterResult *efr = UA_EventFilterResult_new(); + if(!efr) { + UA_ContentFilterResult_clear(&contentFilterResult); + return UA_STATUSCODE_BADOUTOFMEMORY; + } + + efr->whereClauseResult = contentFilterResult; + /* UA_ContentFilterResult_init(&contentFilterResult); */ + + efr->selectClauseResults = (UA_StatusCode*) + UA_Array_new(eventFilter->selectClausesSize, + &UA_TYPES[UA_TYPES_STATUSCODE]); + if(!efr->selectClauseResults) { + UA_EventFilterResult_delete(efr); + return UA_STATUSCODE_BADOUTOFMEMORY; + } + + efr->selectClauseResultsSize = eventFilter->selectClausesSize; + memcpy(efr->selectClauseResults, selectClauseValidationResult, + sizeof(UA_StatusCode) * efr->selectClauseResultsSize); + + UA_ExtensionObject_setValue(&result->filterResult, efr, + &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]); + + return res; } #endif @@ -471,7 +502,7 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, valueType, &newMon->parameters); #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS result->statusCode |= checkEventFilterParam(server, session, newMon, - &newMon->parameters); + &newMon->parameters, result); #endif if(result->statusCode != UA_STATUSCODE_GOOD) { UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub, diff --git a/tests/server/check_subscription_event_filter.c b/tests/server/check_subscription_event_filter.c index b391a617d0b..8744708bcee 100644 --- a/tests/server/check_subscription_event_filter.c +++ b/tests/server/check_subscription_event_filter.c @@ -480,16 +480,19 @@ START_TEST(selectFilterValidation) { createResult = addMonitoredItem(handler_events_simple, &filter, true); ck_assert_uint_eq(createResult.statusCode, UA_STATUSCODE_BADNODEIDUNKNOWN); UA_QualifiedName_clear(&filter.selectClauses->browsePath[0]); + UA_MonitoredItemCreateResult_clear(&createResult); filter.selectClauses->browsePath[0] = UA_QUALIFIEDNAME_ALLOC(0, ""); createResult = addMonitoredItem(handler_events_simple, &filter, true); ck_assert_uint_eq(createResult.statusCode, UA_STATUSCODE_BADNODEIDUNKNOWN); + UA_MonitoredItemCreateResult_clear(&createResult); UA_QualifiedName_delete(&filter.selectClauses->browsePath[0]); filter.selectClauses->browsePath = NULL; filter.selectClauses->browsePathSize = 0; createResult = addMonitoredItem(handler_events_simple, &filter, true); ck_assert_uint_eq(createResult.statusCode, UA_STATUSCODE_BADBROWSENAMEINVALID); + UA_MonitoredItemCreateResult_clear(&createResult); UA_EventFilter_clear(&filter); } END_TEST