Skip to content

Commit

Permalink
feat(server): Return filter results if EventFilter validation fails
Browse files Browse the repository at this point in the history
  • Loading branch information
jpfr committed Sep 21, 2023
1 parent 64b79a6 commit ebed817
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 21 deletions.
73 changes: 52 additions & 21 deletions src/server/ua_services_monitoreditem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions tests/server/check_subscription_event_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit ebed817

Please sign in to comment.