Просмотр исходного кода

implemented detection of duplicated references (UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED)

Thomas Bender лет назад: 7
Родитель
Сommit
577f6d5cf3
2 измененных файлов с 30 добавлено и 7 удалено
  1. 15 5
      src/server/ua_nodes.c
  2. 15 2
      src/server/ua_services_nodemanagement.c

+ 15 - 5
src/server/ua_nodes.c

@@ -527,13 +527,23 @@ addReferenceKind(UA_Node *node, const UA_AddReferencesItem *item) {
 
 UA_StatusCode
 UA_Node_addReference(UA_Node *node, const UA_AddReferencesItem *item) {
+    UA_NodeReferenceKind *existingRefs = NULL;
     for(size_t i = 0; i < node->referencesSize; ++i) {
         UA_NodeReferenceKind *refs = &node->references[i];
-        if(refs->isInverse == item->isForward)
-            continue;
-        if(!UA_NodeId_equal(&refs->referenceTypeId, &item->referenceTypeId))
-            continue;
-        return addReferenceTarget(refs, &item->targetNodeId);
+        if(refs->isInverse != item->isForward
+                && UA_NodeId_equal(&refs->referenceTypeId, &item->referenceTypeId)) {
+            existingRefs = refs;
+            break;
+        }
+    }
+    if(existingRefs != NULL) {
+        for(size_t i = 0; i < existingRefs->targetIdsSize; i++) {
+            if(UA_ExpandedNodeId_equal(&existingRefs->targetIds[i],
+                                       &item->targetNodeId)) {
+                return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
+            }
+        }
+        return addReferenceTarget(existingRefs, &item->targetNodeId);
     }
     return addReferenceKind(node, item);
 }

+ 15 - 2
src/server/ua_services_nodemanagement.c

@@ -1258,7 +1258,11 @@ Operation_addReference(UA_Server *server, UA_Session *session, void *context,
     /* Add the first direction */
     *retval = UA_Server_editNode(server, session, &item->sourceNodeId,
                                  (UA_EditNodeCallback)addOneWayReference, item);
-    if(*retval != UA_STATUSCODE_GOOD)
+    UA_Boolean firstExisted = UA_FALSE;
+    if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+        *retval = UA_STATUSCODE_GOOD;
+        firstExisted = UA_TRUE;
+    } else if(*retval != UA_STATUSCODE_GOOD)
         return;
 
     /* Add the second direction */
@@ -1273,7 +1277,11 @@ Operation_addReference(UA_Server *server, UA_Session *session, void *context,
                                  (UA_EditNodeCallback)addOneWayReference, &secondItem);
 
     /* remove reference if the second direction failed */
-    if(*retval != UA_STATUSCODE_GOOD) {
+    UA_Boolean secondExisted = UA_FALSE;
+    if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
+        *retval = UA_STATUSCODE_GOOD;
+        secondExisted = UA_TRUE;
+    } else if(*retval != UA_STATUSCODE_GOOD && !firstExisted) {
         UA_DeleteReferencesItem deleteItem;
         deleteItem.sourceNodeId = item->sourceNodeId;
         deleteItem.referenceTypeId = item->referenceTypeId;
@@ -1284,6 +1292,11 @@ Operation_addReference(UA_Server *server, UA_Session *session, void *context,
         UA_Server_editNode(server, session, &item->sourceNodeId,
                            (UA_EditNodeCallback)deleteOneWayReference, &deleteItem);
     }
+
+    /* Calculate common duplicate reference not allowed result and set bad result
+     * if BOTH directions already existed */
+    if(firstExisted && secondExisted)
+        *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
 }
 
 void Service_AddReferences(UA_Server *server, UA_Session *session,