Browse Source

search upwards in the tree with multiple reference types

Julius Pfrommer 8 years ago
parent
commit
d20f97c3b0

+ 2 - 1
src/server/ua_server_internal.h

@@ -92,6 +92,7 @@ UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range);
 
 UA_StatusCode
 isNodeInTree(UA_NodeStore *ns, const UA_NodeId *rootNode, const UA_NodeId *nodeToFind,
-             const UA_NodeId *referenceTypeId, size_t maxDepth, UA_Boolean *found);
+             const UA_NodeId *referenceTypeIds, size_t referenceTypeIdsSize,
+             size_t maxDepth, UA_Boolean *found);
 
 #endif /* UA_SERVER_INTERNAL_H_ */

+ 4 - 4
src/server/ua_services_call.c

@@ -30,11 +30,11 @@ satisfySignature(UA_Server *server, const UA_Variant *var, const UA_Argument *ar
         if(!UA_NodeId_equal(&var->type->typeId, &UA_TYPES[UA_TYPES_INT32].typeId))
             return UA_STATUSCODE_BADINVALIDARGUMENT;
 
-        //enumerations are encoded as int32 -> if provided var is integer, check if arg is an enumeration type
-        UA_NodeId ENUMERATION_NODEID_NS0 = UA_NODEID_NUMERIC(0,29);
+        /* enumerations are encoded as int32 -> if provided var is integer, check if arg is an enumeration type */
+        UA_NodeId enumerationNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ENUMERATION);
         UA_NodeId hasSubTypeNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_HASSUBTYPE);
         UA_Boolean found = false;
-        UA_StatusCode retval = isNodeInTree(server->nodestore, &arg->dataType, &ENUMERATION_NODEID_NS0, &hasSubTypeNodeId, 1, &found);
+        UA_StatusCode retval = isNodeInTree(server->nodestore, &arg->dataType, &enumerationNodeId, &hasSubTypeNodeId, 1, 1, &found);
         if(retval != UA_STATUSCODE_GOOD)
             return UA_STATUSCODE_BADINTERNALERROR;
         if(!found)
@@ -122,7 +122,7 @@ Service_Call_single(UA_Server *server, UA_Session *session, const UA_CallMethodR
     UA_Boolean found = false;
     UA_NodeId hasComponentNodeId = UA_NODEID_NUMERIC(0,UA_NS0ID_HASCOMPONENT);
     result->statusCode = isNodeInTree(server->nodestore, &request->methodId, &request->objectId,
-                                      &hasComponentNodeId, 1, &found);
+                                      &hasComponentNodeId, 1, 1, &found);
     if(!found)
         result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
     if(result->statusCode != UA_STATUSCODE_GOOD)

+ 38 - 12
src/server/ua_services_nodemanagement.c

@@ -5,33 +5,49 @@
 /* Helper Functions */
 /********************/
 
-/* Recursively searches "upwards" in the tree following a specific reference type */
+/* Recursively searches "upwards" in the tree following specific reference types */
 UA_StatusCode
 isNodeInTree(UA_NodeStore *ns, const UA_NodeId *rootNode, const UA_NodeId *nodeToFind,
-             const UA_NodeId *referenceTypeId, size_t maxDepth, UA_Boolean *found) {
+             const UA_NodeId *referenceTypeIds, size_t referenceTypeIdsSize,
+             size_t maxDepth, UA_Boolean *found) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     if(UA_NodeId_equal(rootNode, nodeToFind)) {
         *found = true;
         return UA_STATUSCODE_GOOD;
     }
+
+    *found = false;
     const UA_Node *node = UA_NodeStore_get(ns,rootNode);
     if(!node)
         return UA_STATUSCODE_BADINTERNALERROR;
 
-    *found = false;
     maxDepth = maxDepth - 1;
     for(size_t i = 0; i < node->referencesSize; i++) {
-        if(!UA_NodeId_equal(&node->references[i].referenceTypeId, referenceTypeId))
-            continue; /* not the reference type we are looking for */
+        /* Search only upwards */
         if(!node->references[i].isInverse)
-            continue; /* search only upwards */
+            continue;
+
+        /* Go up only for some reference types */
+        UA_Boolean reftype_found = false;
+        for(size_t j = 0; j < referenceTypeIdsSize; j++) {
+            if(UA_NodeId_equal(&node->references[i].referenceTypeId, &referenceTypeIds[j])) {
+                reftype_found = true;
+                break;
+            }
+        }
+        if(!reftype_found)
+            continue;
+
+        /* Is the it node we seek? */
         if(UA_NodeId_equal(&node->references[i].targetId.nodeId, nodeToFind)) {
             *found = true;
             return UA_STATUSCODE_GOOD;
         }
-        if(maxDepth > 0) { /* recurse */
+
+        /* Recurse */
+        if(maxDepth > 0) {
             retval = isNodeInTree(ns, &node->references[i].targetId.nodeId, nodeToFind,
-                                  referenceTypeId, maxDepth, found);
+                                  referenceTypeIds, referenceTypeIdsSize, maxDepth, found);
             if(*found || retval != UA_STATUSCODE_GOOD)
                 break;
         }
@@ -125,7 +141,7 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         } else {
             /* Check if the supplied type is a subtype of BaseObjectType */
             UA_Boolean found = false;
-            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &baseobjtype, &hassubtype, 10, &found);
+            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &baseobjtype, &hassubtype, 1, 10, &found);
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
@@ -147,7 +163,7 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         } else {
             /* Check if the supplied type is a subtype of BaseVariableType */
             UA_Boolean found = false;
-            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &basevartype, &hassubtype, 10, &found);
+            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &basevartype, &hassubtype, 1, 10, &found);
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
@@ -227,7 +243,12 @@ copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *va
         const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
         if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
             continue;
-        instantiateVariableNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        UA_StatusCode retval = instantiateVariableNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        if(retval != UA_STATUSCODE_GOOD) {
+            Service_DeleteNodes_single(server, &adminSession, &res.addedNodeId, true);
+            UA_AddNodesResult_deleteMembers(&res);
+            return retval;
+        }
     }
 
     if(instantiationCallback)
@@ -284,7 +305,12 @@ copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *vari
         const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
         if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
             continue;
-        instantiateObjectNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        UA_StatusCode retval = instantiateObjectNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        if(retval != UA_STATUSCODE_GOOD) {
+            Service_DeleteNodes_single(server, &adminSession, &res.addedNodeId, true);
+            UA_AddNodesResult_deleteMembers(&res);
+            return retval;
+        }
     }
 
     if(instantiationCallback)