diff --git a/include/open62541/server.h b/include/open62541/server.h index 54f981164f8..340ddeb240e 100644 --- a/include/open62541/server.h +++ b/include/open62541/server.h @@ -910,7 +910,7 @@ typedef void (*UA_Server_EventNotificationCallback) * @return Returns a description of the created MonitoredItem. The structure * also contains a StatusCode (in case of an error) and the identifier of the * new MonitoredItem. */ -UA_MonitoredItemCreateResult UA_EXPORT +UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE UA_Server_createDataChangeMonitoredItem(UA_Server *server, UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item, @@ -923,7 +923,7 @@ UA_Server_createDataChangeMonitoredItem(UA_Server *server, /* const UA_MonitoredItemCreateRequest item, void *context, */ /* UA_Server_EventNotificationCallback callback); */ -UA_StatusCode UA_EXPORT +UA_StatusCode UA_EXPORT UA_THREADSAFE UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId); #endif @@ -1315,7 +1315,7 @@ UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, * @param eventType The type of the event for which a node should be created * @param outNodeId The NodeId of the newly created node for the event * @return The StatusCode of the UA_Server_createEvent method */ -UA_StatusCode UA_EXPORT +UA_StatusCode UA_EXPORT UA_THREADSAFE UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, UA_NodeId *outNodeId); @@ -1326,7 +1326,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, * @param outEvent the EventId of the new event * @param deleteEventNode Specifies whether the node representation of the event should be deleted * @return The StatusCode of the UA_Server_triggerEvent method */ -UA_StatusCode UA_EXPORT +UA_StatusCode UA_EXPORT UA_THREADSAFE UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_NodeId originId, UA_ByteString *outEventId, const UA_Boolean deleteEventNode); diff --git a/src/server/ua_server_internal.h b/src/server/ua_server_internal.h index 7cbf40c9592..d0d8711395d 100644 --- a/src/server/ua_server_internal.h +++ b/src/server/ua_server_internal.h @@ -247,6 +247,13 @@ readWithReadValue(UA_Server *server, const UA_NodeId *nodeId, UA_BrowsePathResult translateBrowsePathToNodeIds(UA_Server *server, const UA_BrowsePath *browsePath); +void +monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem); + +UA_BrowsePathResult +browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, + size_t browsePathSize, const UA_QualifiedName *browsePath); + /***************************************/ /* Check Information Model Consistency */ /***************************************/ diff --git a/src/server/ua_services_attribute.c b/src/server/ua_services_attribute.c index 70d2f08effd..314a6bfc16f 100644 --- a/src/server/ua_services_attribute.c +++ b/src/server/ua_services_attribute.c @@ -613,7 +613,7 @@ UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId, bp.relativePath.elements = &rpe; UA_StatusCode retval; - UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); + UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_BrowsePathResult_deleteMembers(&bpr); @@ -1669,7 +1669,7 @@ UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId, bp.relativePath.elements = &rpe; UA_StatusCode retval; - UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp); + UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_BrowsePathResult_deleteMembers(&bpr); diff --git a/src/server/ua_services_monitoreditem.c b/src/server/ua_services_monitoreditem.c index 091f187209e..05286f96de5 100644 --- a/src/server/ua_services_monitoreditem.c +++ b/src/server/ua_services_monitoreditem.c @@ -247,10 +247,12 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre if(server->config.monitoredItemRegisterCallback) { void *targetContext = NULL; UA_Server_getNodeContext(server, request->itemToMonitor.nodeId, &targetContext); + UA_UNLOCK(server->serviceMutex); server->config.monitoredItemRegisterCallback(server, &session->sessionId, session->sessionHandle, &request->itemToMonitor.nodeId, targetContext, newMon->attributeId, false); + UA_LOCK(server->serviceMutex); newMon->registered = true; } @@ -263,7 +265,7 @@ Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, struct cre /* Create the first sample */ if(request->monitoringMode == UA_MONITORINGMODE_REPORTING && newMon->attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER) - UA_MonitoredItem_sampleCallback(server, newMon); + monitoredItem_sampleCallback(server, newMon); /* Prepare the response */ result->revisedSamplingInterval = newMon->samplingInterval; @@ -321,7 +323,9 @@ UA_Server_createDataChangeMonitoredItem(UA_Server *server, UA_MonitoredItemCreateResult result; UA_MonitoredItemCreateResult_init(&result); + UA_LOCK(server->serviceMutex); Operation_CreateMonitoredItem(server, &server->adminSession, &cmc, &item, &result); + UA_UNLOCK(server->serviceMutex); return result; } @@ -544,14 +548,17 @@ Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session, UA_StatusCode UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId) { + UA_LOCK(server->serviceMutex); UA_MonitoredItem *mon; LIST_FOREACH(mon, &server->localMonitoredItems, listEntry) { if(mon->monitoredItemId != monitoredItemId) continue; LIST_REMOVE(mon, listEntry); UA_MonitoredItem_delete(server, mon); + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_GOOD; } + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; } diff --git a/src/server/ua_services_view.c b/src/server/ua_services_view.c index 6006c800aa1..c7190c2102e 100644 --- a/src/server/ua_services_view.c +++ b/src/server/ua_services_view.c @@ -289,6 +289,7 @@ UA_StatusCode UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd, size_t *resultsSize, UA_ExpandedNodeId **results) { /* Set the list of relevant reference types */ + UA_LOCK(server->serviceMutex); UA_NodeId *refTypes = NULL; size_t refTypesSize = 0; UA_StatusCode retval = UA_STATUSCODE_GOOD; @@ -299,8 +300,10 @@ UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd, } else { retval = referenceSubtypes(server, &bd->referenceTypeId, &refTypesSize, &refTypes); - if(retval != UA_STATUSCODE_GOOD) + if(retval != UA_STATUSCODE_GOOD) { + UA_UNLOCK(server->serviceMutex); return retval; + } } } @@ -311,6 +314,8 @@ UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd, /* Clean up */ if(refTypes && bd->includeSubtypes) UA_Array_delete(refTypes, refTypesSize, &UA_TYPES[UA_TYPES_NODEID]); + + UA_UNLOCK(server->serviceMutex); return retval; } @@ -724,7 +729,9 @@ UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences, const UA_BrowseDescription *bd) { UA_BrowseResult result; UA_BrowseResult_init(&result); + UA_LOCK(server->serviceMutex); Operation_Browse(server, &server->adminSession, &maxReferences, bd, &result); + UA_UNLOCK(server->serviceMutex); return result; } @@ -789,8 +796,10 @@ UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint, const UA_ByteString *continuationPoint) { UA_BrowseResult result; UA_BrowseResult_init(&result); + UA_LOCK(server->serviceMutex); Operation_BrowseNext(server, &server->adminSession, &releaseContinuationPoint, continuationPoint, &result); + UA_UNLOCK(server->serviceMutex); return result; } @@ -1143,8 +1152,8 @@ Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session, } UA_BrowsePathResult -UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, - size_t browsePathSize, const UA_QualifiedName *browsePath) { +browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, + size_t browsePathSize, const UA_QualifiedName *browsePath) { /* Construct the BrowsePath */ UA_BrowsePath bp; UA_BrowsePath_init(&bp); @@ -1167,6 +1176,15 @@ UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, return bpr; } +UA_BrowsePathResult +UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, + size_t browsePathSize, const UA_QualifiedName *browsePath) { + UA_LOCK(server->serviceMutex); + UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin, browsePathSize, browsePath);; + UA_UNLOCK(server->serviceMutex); + return bpr; +} + /************/ /* Register */ /************/ diff --git a/src/server/ua_subscription_datachange.c b/src/server/ua_subscription_datachange.c index 7398878f002..c025272eafb 100644 --- a/src/server/ua_subscription_datachange.c +++ b/src/server/ua_subscription_datachange.c @@ -112,7 +112,7 @@ detectValueChangeWithFilter(UA_Server *server, UA_Session *session, UA_Monitored else if(mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_PERCENT) { /* Browse for the percent range */ UA_QualifiedName qn = UA_QUALIFIEDNAME(0, "EURange"); - UA_BrowsePathResult bpr = UA_Server_browseSimplifiedBrowsePath(server, mon->monitoredNodeId, 1, &qn); + UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, mon->monitoredNodeId, 1, &qn); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { UA_BrowsePathResult_deleteMembers(&bpr); return UA_STATUSCODE_GOOD; @@ -306,18 +306,28 @@ sampleCallbackWithValue(UA_Server *server, UA_Session *session, UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) mon; void *nodeContext = NULL; UA_Server_getNodeContext(server, mon->monitoredNodeId, &nodeContext); + UA_UNLOCK(server->serviceMutex); localMon->callback.dataChangeCallback(server, mon->monitoredItemId, localMon->context, &mon->monitoredNodeId, nodeContext, mon->attributeId, value); + UA_LOCK(server->serviceMutex); } return UA_STATUSCODE_GOOD; } void -UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) { +UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) +{ + UA_LOCK(server->serviceMutex); + monitoredItem_sampleCallback(server, monitoredItem); + UA_UNLOCK(server->serviceMutex) +} + +void +monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) { UA_Subscription *sub = monitoredItem->subscription; UA_Session *session = &server->adminSession; if(sub) diff --git a/src/server/ua_subscription_events.c b/src/server/ua_subscription_events.c index 584818537d0..24911ebd3e4 100644 --- a/src/server/ua_subscription_events.c +++ b/src/server/ua_subscription_events.c @@ -57,10 +57,12 @@ generateEventId(UA_ByteString *generatedId) { UA_StatusCode UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, UA_NodeId *outNodeId) { + UA_LOCK(server->serviceMutex); if(!outNodeId) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND, "outNodeId must not be NULL. The event's NodeId must be returned " "so it can be triggered."); + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_BADINVALIDARGUMENT; } @@ -70,6 +72,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, if(!isNodeInTree(server->nsCtx, &eventType, &baseEventTypeId, &hasSubtypeId, 1)) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Event type must be a subtype of BaseEventType!"); + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_BADINVALIDARGUMENT; } @@ -79,17 +82,16 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, name = UA_QUALIFIEDNAME(0,"E"); UA_NodeId newNodeId = UA_NODEID_NULL; UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; - UA_StatusCode retval = - UA_Server_addObjectNode(server, - UA_NODEID_NULL, /* Set a random unused NodeId */ - UA_NODEID_NULL, /* No parent */ - UA_NODEID_NULL, /* No parent reference */ - name, /* an event does not have a name */ - eventType, /* the type of the event */ - oAttr, /* default attributes are fine */ - NULL, /* no node context */ - &newNodeId); - + UA_StatusCode retval = addNode(server, UA_NODECLASS_OBJECT, + &UA_NODEID_NULL, /* Set a random unused NodeId */ + &UA_NODEID_NULL, /* No parent */ + &UA_NODEID_NULL, /* No parent reference */ + name, /* an event does not have a name */ + &eventType, /* the type of the event */ + (const UA_NodeAttributes*)&oAttr, /* default attributes are fine */ + &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], + NULL, /* no node context */ + &newNodeId); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Adding event failed. StatusCode %s", UA_StatusCode_name(retval)); @@ -98,12 +100,13 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, /* Find the eventType variable */ name = UA_QUALIFIEDNAME(0, "EventType"); - UA_BrowsePathResult bpr = UA_Server_browseSimplifiedBrowsePath(server, newNodeId, 1, &name); + UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, newNodeId, 1, &name); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_BrowsePathResult_deleteMembers(&bpr); - UA_Server_deleteNode(server, newNodeId, true); + deleteNode(server, newNodeId, true); UA_NodeId_deleteMembers(&newNodeId); + UA_UNLOCK(server->serviceMutex); return retval; } @@ -111,15 +114,17 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, UA_Variant value; UA_Variant_init(&value); UA_Variant_setScalar(&value, (void*)(uintptr_t)&eventType, &UA_TYPES[UA_TYPES_NODEID]); - retval = UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); + retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value); UA_BrowsePathResult_deleteMembers(&bpr); if(retval != UA_STATUSCODE_GOOD) { - UA_Server_deleteNode(server, newNodeId, true); + deleteNode(server, newNodeId, true); UA_NodeId_deleteMembers(&newNodeId); + UA_UNLOCK(server->serviceMutex); return retval; } *outNodeId = newNodeId; + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_GOOD; } @@ -128,8 +133,7 @@ isValidEvent(UA_Server *server, const UA_NodeId *validEventParent, const UA_NodeId *eventId) { /* find the eventType variableNode */ UA_QualifiedName findName = UA_QUALIFIEDNAME(0, "EventType"); - UA_BrowsePathResult bpr = - UA_Server_browseSimplifiedBrowsePath(server, *eventId, 1, &findName); + UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, *eventId, 1, &findName); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { UA_BrowsePathResult_deleteMembers(&bpr); return false; @@ -141,7 +145,7 @@ isValidEvent(UA_Server *server, const UA_NodeId *validEventParent, /* Read the Value of EventType Property Node (the Value should be a NodeId) */ UA_StatusCode retval = - UA_Server_readValue(server, bpr.targets[0].targetId.nodeId, &tOutVariant); + readWithReadValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &tOutVariant); if(retval != UA_STATUSCODE_GOOD || !UA_Variant_hasScalarType(&tOutVariant, &UA_TYPES[UA_TYPES_NODEID])) { UA_BrowsePathResult_deleteMembers(&bpr); @@ -200,7 +204,7 @@ resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session, const UA_N /* Resolve the browse path */ UA_BrowsePathResult bpr = - UA_Server_browseSimplifiedBrowsePath(server, *origin, sao->browsePathSize, + browseSimplifiedBrowsePath(server, *origin, sao->browsePathSize, sao->browsePath); if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD) bpr.statusCode = UA_STATUSCODE_BADNOTFOUND; @@ -283,7 +287,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, /* Set the SourceNode */ UA_StatusCode retval; UA_QualifiedName name = UA_QUALIFIEDNAME(0, "SourceNode"); - UA_BrowsePathResult bpr = UA_Server_browseSimplifiedBrowsePath(server, *event, 1, &name); + UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, *event, 1, &name); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_BrowsePathResult_deleteMembers(&bpr); @@ -292,7 +296,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, UA_Variant value; UA_Variant_init(&value); UA_Variant_setScalarCopy(&value, origin, &UA_TYPES[UA_TYPES_NODEID]); - retval = UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); + retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value); UA_Variant_deleteMembers(&value); UA_BrowsePathResult_deleteMembers(&bpr); if(retval != UA_STATUSCODE_GOOD) @@ -300,7 +304,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, /* Set the ReceiveTime */ name = UA_QUALIFIEDNAME(0, "ReceiveTime"); - bpr = UA_Server_browseSimplifiedBrowsePath(server, *event, 1, &name); + bpr = browseSimplifiedBrowsePath(server, *event, 1, &name); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_BrowsePathResult_deleteMembers(&bpr); @@ -308,7 +312,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, } UA_DateTime rcvTime = UA_DateTime_now(); UA_Variant_setScalar(&value, &rcvTime, &UA_TYPES[UA_TYPES_DATETIME]); - retval = UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); + retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value); UA_BrowsePathResult_deleteMembers(&bpr); if(retval != UA_STATUSCODE_GOOD) return retval; @@ -319,7 +323,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, if(retval != UA_STATUSCODE_GOOD) return retval; name = UA_QUALIFIEDNAME(0, "EventId"); - bpr = UA_Server_browseSimplifiedBrowsePath(server, *event, 1, &name); + bpr = browseSimplifiedBrowsePath(server, *event, 1, &name); if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { retval = bpr.statusCode; UA_ByteString_deleteMembers(&eventId); @@ -328,7 +332,7 @@ eventSetStandardFields(UA_Server *server, const UA_NodeId *event, } UA_Variant_init(&value); UA_Variant_setScalar(&value, &eventId, &UA_TYPES[UA_TYPES_BYTESTRING]); - retval = UA_Server_writeValue(server, bpr.targets[0].targetId.nodeId, value); + retval = writeWithWriteValue(server, &bpr.targets[0].targetId.nodeId, UA_ATTRIBUTEID_VALUE, &UA_TYPES[UA_TYPES_VARIANT], &value); UA_BrowsePathResult_deleteMembers(&bpr); if(retval != UA_STATUSCODE_GOOD) { UA_ByteString_deleteMembers(&eventId); @@ -380,11 +384,13 @@ static const UA_NodeId parentReferences_events[2] = UA_StatusCode UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_NodeId origin, UA_ByteString *outEventId, const UA_Boolean deleteEventNode) { + UA_LOCK(server->serviceMutex); /* Check that the origin node exists */ const UA_Node *originNode = UA_Nodestore_getNode(server->nsCtx, &origin); if(!originNode) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Origin node for event does not exist."); + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_BADNOTFOUND; } UA_Nodestore_releaseNode(server->nsCtx, originNode); @@ -394,6 +400,7 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_ parentReferences_events, 2)) { UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND, "Node for event must be in ObjectsFolder!"); + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_BADINVALIDARGUMENT; } @@ -402,6 +409,7 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Events: Could not set the standard event fields with StatusCode %s", UA_StatusCode_name(retval)); + UA_UNLOCK(server->serviceMutex); return retval; } @@ -414,6 +422,7 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_ UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Events: Could not create the list of nodes listening on the " "event with StatusCode %s", UA_StatusCode_name(retval)); + UA_UNLOCK(server->serviceMutex); return retval; } @@ -441,14 +450,16 @@ UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_ /* Delete the node representation of the event */ if(deleteEventNode) { - retval = UA_Server_deleteNode(server, eventNodeId, true); + retval = deleteNode(server, eventNodeId, true); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Attempt to remove event using deleteNode failed. StatusCode %s", UA_StatusCode_name(retval)); + UA_UNLOCK(server->serviceMutex); return retval; } } + UA_UNLOCK(server->serviceMutex); return UA_STATUSCODE_GOOD; } diff --git a/tests/server/check_server_readspeed.c b/tests/server/check_server_readspeed.c index e2fa45454e5..7585ad0f439 100644 --- a/tests/server/check_server_readspeed.c +++ b/tests/server/check_server_readspeed.c @@ -94,7 +94,9 @@ START_TEST(readSpeed) { size_t offset = 0; retval |= UA_decodeBinary(&request_msg, &offset, &req, &UA_TYPES[UA_TYPES_READREQUEST], NULL); + UA_LOCK(server->serviceMutex); Service_Read(server, &server->adminSession, &req, &res); + UA_UNLOCK(server->serviceMutex); UA_Byte *rpos = response_msg.data; const UA_Byte *rend = &response_msg.data[response_msg.length]; diff --git a/tests/server/check_services_subscriptions.c b/tests/server/check_services_subscriptions.c index dc74ff8afae..1d3290fca41 100644 --- a/tests/server/check_services_subscriptions.c +++ b/tests/server/check_services_subscriptions.c @@ -67,7 +67,9 @@ createSubscription(void) { UA_CreateSubscriptionResponse response; UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); subscriptionId = response.subscriptionId; @@ -98,7 +100,9 @@ createMonitoredItem(void) { UA_CreateMonitoredItemsResponse response; UA_CreateMonitoredItemsResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateMonitoredItems(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -118,8 +122,9 @@ START_TEST(Server_createSubscription) { UA_CreateSubscriptionResponse response; UA_CreateSubscriptionResponse_init(&response); - + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); subscriptionId = response.subscriptionId; @@ -145,7 +150,9 @@ START_TEST(Server_modifySubscription) { UA_ModifySubscriptionResponse response; UA_ModifySubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_ModifySubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); UA_ModifySubscriptionResponse_deleteMembers(&response); @@ -164,7 +171,10 @@ START_TEST(Server_setPublishingMode) { UA_SetPublishingModeResponse response; UA_SetPublishingModeResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_SetPublishingMode(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); + ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0], UA_STATUSCODE_GOOD); @@ -184,7 +194,9 @@ START_TEST(Server_republish) { UA_RepublishResponse response; UA_RepublishResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_Republish(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_BADMESSAGENOTAVAILABLE); UA_RepublishResponse_deleteMembers(&response); @@ -201,7 +213,9 @@ START_TEST(Server_republish_invalid) { UA_RepublishResponse response; UA_RepublishResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_Republish(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID); UA_RepublishResponse_deleteMembers(&response); @@ -220,7 +234,9 @@ START_TEST(Server_deleteSubscription) { UA_DeleteSubscriptionsResponse del_response; UA_DeleteSubscriptionsResponse_init(&del_response); + UA_LOCK(server->serviceMutex); Service_DeleteSubscriptions(server, session, &del_request, &del_response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(del_response.resultsSize, 1); ck_assert_uint_eq(del_response.results[0], UA_STATUSCODE_GOOD); @@ -236,7 +252,9 @@ START_TEST(Server_publishCallback) { UA_CreateSubscriptionRequest_init(&request); request.publishingEnabled = true; UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); UA_UInt32 subscriptionId1 = response.subscriptionId; UA_CreateSubscriptionResponse_deleteMembers(&response); @@ -245,7 +263,9 @@ START_TEST(Server_publishCallback) { UA_CreateSubscriptionRequest_init(&request); request.publishingEnabled = true; UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); UA_UInt32 subscriptionId2 = response.subscriptionId; UA_Double publishingInterval = response.revisedPublishingInterval; @@ -277,7 +297,9 @@ START_TEST(Server_publishCallback) { UA_DeleteSubscriptionsResponse del_response; UA_DeleteSubscriptionsResponse_init(&del_response); + UA_LOCK(server->serviceMutex); Service_DeleteSubscriptions(server, session, &del_request, &del_response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(del_response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(del_response.resultsSize, 2); ck_assert_uint_eq(del_response.results[0], UA_STATUSCODE_GOOD); @@ -318,7 +340,9 @@ START_TEST(Server_modifyMonitoredItems) { UA_ModifyMonitoredItemsResponse response; UA_ModifyMonitoredItemsResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_ModifyMonitoredItems(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -336,7 +360,9 @@ START_TEST(Server_overflow) { UA_CreateSubscriptionRequest_init(&createSubscriptionRequest); createSubscriptionRequest.publishingEnabled = true; UA_CreateSubscriptionResponse_init(&createSubscriptionResponse); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &createSubscriptionRequest, &createSubscriptionResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(createSubscriptionResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); UA_UInt32 localSubscriptionId = createSubscriptionResponse.subscriptionId; UA_Double publishingInterval = createSubscriptionResponse.revisedPublishingInterval; @@ -368,7 +394,9 @@ START_TEST(Server_overflow) { UA_CreateMonitoredItemsResponse createMonitoredItemsResponse; UA_CreateMonitoredItemsResponse_init(&createMonitoredItemsResponse); + UA_LOCK(server->serviceMutex); Service_CreateMonitoredItems(server, session, &createMonitoredItemsRequest, &createMonitoredItemsResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(createMonitoredItemsResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(createMonitoredItemsResponse.resultsSize, 1); ck_assert_uint_eq(createMonitoredItemsResponse.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -438,8 +466,10 @@ START_TEST(Server_overflow) { UA_ModifyMonitoredItemsResponse modifyMonitoredItemsResponse; UA_ModifyMonitoredItemsResponse_init(&modifyMonitoredItemsResponse); + UA_LOCK(server->serviceMutex); Service_ModifyMonitoredItems(server, session, &modifyMonitoredItemsRequest, &modifyMonitoredItemsResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(modifyMonitoredItemsResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(modifyMonitoredItemsResponse.resultsSize, 1); ck_assert_uint_eq(modifyMonitoredItemsResponse.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -468,8 +498,10 @@ START_TEST(Server_overflow) { UA_ModifyMonitoredItemsResponse_init(&modifyMonitoredItemsResponse); + UA_LOCK(server->serviceMutex); Service_ModifyMonitoredItems(server, session, &modifyMonitoredItemsRequest, &modifyMonitoredItemsResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(modifyMonitoredItemsResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(modifyMonitoredItemsResponse.resultsSize, 1); ck_assert_uint_eq(modifyMonitoredItemsResponse.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -497,8 +529,10 @@ START_TEST(Server_overflow) { UA_ModifyMonitoredItemsResponse_init(&modifyMonitoredItemsResponse); + UA_LOCK(server->serviceMutex); Service_ModifyMonitoredItems(server, session, &modifyMonitoredItemsRequest, &modifyMonitoredItemsResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(modifyMonitoredItemsResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(modifyMonitoredItemsResponse.resultsSize, 1); ck_assert_uint_eq(modifyMonitoredItemsResponse.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -522,8 +556,10 @@ START_TEST(Server_overflow) { UA_DeleteSubscriptionsResponse deleteSubscriptionsResponse; UA_DeleteSubscriptionsResponse_init(&deleteSubscriptionsResponse); + UA_LOCK(server->serviceMutex); Service_DeleteSubscriptions(server, session, &deleteSubscriptionsRequest, &deleteSubscriptionsResponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(deleteSubscriptionsResponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(deleteSubscriptionsResponse.resultsSize, 1); ck_assert_uint_eq(deleteSubscriptionsResponse.results[0], UA_STATUSCODE_GOOD); @@ -547,7 +583,9 @@ START_TEST(Server_setMonitoringMode) { UA_SetMonitoringModeResponse response; UA_SetMonitoringModeResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_SetMonitoringMode(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0], UA_STATUSCODE_GOOD); @@ -569,7 +607,9 @@ START_TEST(Server_deleteMonitoredItems) { UA_DeleteMonitoredItemsResponse response; UA_DeleteMonitoredItemsResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_DeleteMonitoredItems(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0], UA_STATUSCODE_GOOD); @@ -588,7 +628,9 @@ START_TEST(Server_lifeTimeCount) { request.requestedLifetimeCount = 3; request.requestedMaxKeepAliveCount = 1; UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.revisedMaxKeepAliveCount, 1); ck_assert_uint_eq(response.revisedLifetimeCount, 3); @@ -600,7 +642,9 @@ START_TEST(Server_lifeTimeCount) { request.requestedLifetimeCount = 4; request.requestedMaxKeepAliveCount = 2; UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.revisedMaxKeepAliveCount, 2); /* revisedLifetimeCount is revised to 3*MaxKeepAliveCount == 3 */ @@ -633,7 +677,9 @@ START_TEST(Server_lifeTimeCount) { UA_CreateMonitoredItemsResponse mresponse; UA_CreateMonitoredItemsResponse_init(&mresponse); + UA_LOCK(server->serviceMutex); Service_CreateMonitoredItems(server, session, &mrequest, &mresponse); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(mresponse.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(mresponse.resultsSize, 1); ck_assert_uint_eq(mresponse.results[0].statusCode, UA_STATUSCODE_GOOD); @@ -740,7 +786,9 @@ START_TEST(Server_invalidPublishingInterval) { request.publishingEnabled = true; request.requestedPublishingInterval = -5.0; // Must be positive UA_CreateSubscriptionResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateSubscription(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert(response.revisedPublishingInterval == server->config.publishingIntervalLimits.min); @@ -778,7 +826,9 @@ START_TEST(Server_invalidSamplingInterval) { UA_CreateMonitoredItemsResponse response; UA_CreateMonitoredItemsResponse_init(&response); + UA_LOCK(server->serviceMutex); Service_CreateMonitoredItems(server, session, &request, &response); + UA_UNLOCK(server->serviceMutex); ck_assert_uint_eq(response.responseHeader.serviceResult, UA_STATUSCODE_GOOD); ck_assert_uint_eq(response.resultsSize, 1); ck_assert_uint_eq(response.results[0].statusCode, UA_STATUSCODE_GOOD); diff --git a/tests/server/check_subscription_events.c b/tests/server/check_subscription_events.c index dec0c1e552c..74f8bfe2254 100644 --- a/tests/server/check_subscription_events.c +++ b/tests/server/check_subscription_events.c @@ -144,9 +144,10 @@ removeSubscription(void) { UA_DeleteSubscriptionsResponse deleteSubscriptionsResponse; UA_DeleteSubscriptionsResponse_init(&deleteSubscriptionsResponse); - + UA_LOCK(server->serviceMutex); Service_DeleteSubscriptions(server, &server->adminSession, &deleteSubscriptionsRequest, &deleteSubscriptionsResponse); + UA_UNLOCK(server->serviceMutex); UA_DeleteSubscriptionsResponse_deleteMembers(&deleteSubscriptionsResponse); }