Forráskód Böngészése

cosmetic improvements

Julius Pfrommer 10 éve
szülő
commit
8ac02604c5
1 módosított fájl, 204 hozzáadás és 216 törlés
  1. 204 216
      src/server/ua_services_view.c

+ 204 - 216
src/server/ua_services_view.c

@@ -4,223 +4,203 @@
 #include "ua_nodestore.h"
 #include "ua_util.h"
 
-static UA_StatusCode fillReferenceDescription(UA_NodeStore *ns, const UA_Node *currentNode, UA_ReferenceNode *reference,
-                                              UA_UInt32 resultMask, UA_ReferenceDescription *referenceDescription) {
+static UA_StatusCode fillrefdescr(UA_NodeStore *ns, const UA_Node *curr, UA_ReferenceNode *ref,
+                                  UA_UInt32 mask, UA_ReferenceDescription *descr)
+{
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_ReferenceDescription_init(referenceDescription);
-    retval |= UA_NodeId_copy(&currentNode->nodeId, &referenceDescription->nodeId.nodeId);
+    UA_ReferenceDescription_init(descr);
+    retval |= UA_NodeId_copy(&curr->nodeId, &descr->nodeId.nodeId);
     //TODO: ExpandedNodeId is mocked up
-    referenceDescription->nodeId.serverIndex = 0;
-    referenceDescription->nodeId.namespaceUri.length = -1;
-
-    if(resultMask & UA_BROWSERESULTMASK_REFERENCETYPEID)
-        retval |= UA_NodeId_copy(&reference->referenceTypeId, &referenceDescription->referenceTypeId);
-    if(resultMask & UA_BROWSERESULTMASK_ISFORWARD)
-        referenceDescription->isForward = !reference->isInverse;
-    if(resultMask & UA_BROWSERESULTMASK_NODECLASS)
-        retval |= UA_NodeClass_copy(&currentNode->nodeClass, &referenceDescription->nodeClass);
-    if(resultMask & UA_BROWSERESULTMASK_BROWSENAME)
-        retval |= UA_QualifiedName_copy(&currentNode->browseName, &referenceDescription->browseName);
-    if(resultMask & UA_BROWSERESULTMASK_DISPLAYNAME)
-        retval |= UA_LocalizedText_copy(&currentNode->displayName, &referenceDescription->displayName);
-    if(resultMask & UA_BROWSERESULTMASK_TYPEDEFINITION ) {
-        for(UA_Int32 i = 0;i < currentNode->referencesSize;i++) {
-            UA_ReferenceNode *ref = &currentNode->references[i];
-            if(ref->referenceTypeId.identifier.numeric == UA_NS0ID_HASTYPEDEFINITION) {
-                retval |= UA_ExpandedNodeId_copy(&ref->targetId, &referenceDescription->typeDefinition);
+    descr->nodeId.serverIndex = 0;
+    descr->nodeId.namespaceUri.length = -1;
+
+    if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID)
+        retval |= UA_NodeId_copy(&ref->referenceTypeId, &descr->referenceTypeId);
+    if(mask & UA_BROWSERESULTMASK_ISFORWARD)
+        descr->isForward = !ref->isInverse;
+    if(mask & UA_BROWSERESULTMASK_NODECLASS)
+        retval |= UA_NodeClass_copy(&curr->nodeClass, &descr->nodeClass);
+    if(mask & UA_BROWSERESULTMASK_BROWSENAME)
+        retval |= UA_QualifiedName_copy(&curr->browseName, &descr->browseName);
+    if(mask & UA_BROWSERESULTMASK_DISPLAYNAME)
+        retval |= UA_LocalizedText_copy(&curr->displayName, &descr->displayName);
+    if(mask & UA_BROWSERESULTMASK_TYPEDEFINITION ) {
+        for(UA_Int32 i = 0;i < curr->referencesSize;i++) {
+            UA_ReferenceNode *refnode = &curr->references[i];
+            if(refnode->referenceTypeId.identifier.numeric == UA_NS0ID_HASTYPEDEFINITION) {
+                retval |= UA_ExpandedNodeId_copy(&refnode->targetId, &descr->typeDefinition);
                 break;
             }
         }
     }
 
     if(retval)
-        UA_ReferenceDescription_deleteMembers(referenceDescription);
+        UA_ReferenceDescription_deleteMembers(descr);
     return retval;
 }
 
 /* Tests if the node is relevant to the browse request and shall be returned. If
    so, it is retrieved from the Nodestore. If not, null is returned. */
-static const UA_Node * getRelevantTargetNode(UA_NodeStore *ns, const UA_BrowseDescription *browseDescription,
-                                             UA_Boolean returnAll, UA_ReferenceNode *reference,
-                                             UA_NodeId *relevantRefTypes, size_t relevantRefTypesCount) {
-    if(reference->isInverse == UA_TRUE &&
-       browseDescription->browseDirection == UA_BROWSEDIRECTION_FORWARD)
+static const UA_Node
+*relevant_node(UA_NodeStore *ns, const UA_BrowseDescription *descr, UA_Boolean return_all,
+               UA_ReferenceNode *reference, UA_NodeId *relevant, size_t relevant_count)
+{
+    if(reference->isInverse == UA_TRUE && descr->browseDirection == UA_BROWSEDIRECTION_FORWARD)
         return UA_NULL;
-    else if(reference->isInverse == UA_FALSE &&
-            browseDescription->browseDirection == UA_BROWSEDIRECTION_INVERSE)
+    else if(reference->isInverse == UA_FALSE && descr->browseDirection == UA_BROWSEDIRECTION_INVERSE)
         return UA_NULL;
 
-    UA_Boolean isRelevant = returnAll;
-    if(!isRelevant) {
-        for(size_t i = 0;i < relevantRefTypesCount;i++) {
-            if(UA_NodeId_equal(&reference->referenceTypeId, &relevantRefTypes[i]))
-                isRelevant = UA_TRUE;
+    if(!return_all) {
+        for(size_t i = 0; i < relevant_count; i++) {
+            if(UA_NodeId_equal(&reference->referenceTypeId, &relevant[i]))
+                goto is_relevant;
         }
-        if(!isRelevant)
-            return UA_NULL;
+        return UA_NULL;
     }
-
+is_relevant: ;
     const UA_Node *node = UA_NodeStore_get(ns, &reference->targetId.nodeId);
-    if(node && browseDescription->nodeClassMask != 0 && (node->nodeClass & browseDescription->nodeClassMask) == 0) {
+    if(node && descr->nodeClassMask != 0 && (node->nodeClass & descr->nodeClassMask) == 0) {
         UA_NodeStore_release(node);
-        node = UA_NULL;
+        return UA_NULL;
     }
     return node;
 }
 
-/* Find all referencetypes that are subtypes (of subtypes) of the given root referencetype */
-static UA_StatusCode findReferenceTypeSubTypes(UA_NodeStore *ns, const UA_NodeId *rootReferenceType,
-                                               UA_NodeId **referenceTypes, size_t *referenceTypesSize) {
-    /* The references form a tree. We walk the tree by adding new nodes to the end of the array. */
-    size_t index = 0;
-    size_t lastIndex = 0;
-    size_t arraySize = 20; // should be more than enough. if not, increase the array size.
-    UA_NodeId *typeArray = UA_malloc(sizeof(UA_NodeId) * arraySize);
-    if(!typeArray)
+/**
+ * We find all subtypes by a single iteration over the array. We start with an array with a single
+ * root nodeid at the beginning. When we find relevant references, we add the nodeids to the back of
+ * the array and increase the size. Since the hierarchy is not cyclic, we can safely progress in the
+ * array to process the newly found referencetype nodeids (emulated recursion).
+ */
+static UA_StatusCode
+findsubtypes(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size_t *reftypes_count)
+{
+    size_t results_size = 20; // probably too big, but saves mallocs
+    UA_NodeId *results = UA_malloc(sizeof(UA_NodeId) * results_size);
+    if(!results)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    retval |= UA_NodeId_copy(rootReferenceType, &typeArray[0]);
-    if(retval) {
-        UA_free(typeArray);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
+    UA_StatusCode retval = UA_NodeId_copy(root, &results[0]);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_free(results);
+        return retval;
     }
         
-    /**
-     * We find all subtypes by a single iteration over the array. We start with an array with a
-     * single root nodeid at the beginning. When we find relevant references, we add the nodeids to
-     * the back of the array and increase the size. Since the hierarchy is not cyclic, we can safely
-     * progress in the array to process the newly found referencetype nodeids (emulated recursion).
-     */
+    size_t index = 0; // where are we currently in the array?
+    size_t last = 0; // where is the last element in the array?
     do {
-        // 1) Get the node
-        const UA_ReferenceTypeNode *node =
-            (const UA_ReferenceTypeNode *)UA_NodeStore_get(ns, &typeArray[index]);
+        const UA_Node *node = UA_NodeStore_get(ns, &results[index]);
         if(!node)
             break;
-
-        // 2) Check that we have the right type of node
-        if(node->nodeClass != UA_NODECLASS_REFERENCETYPE) 
-            continue;
-
-        // 3) Find references to subtypes
-        for(UA_Int32 i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
-            // Is this a subtype reference?
-            if(node->references[i].referenceTypeId.identifier.numeric != 45 /* HasSubtype */ ||
+        for(UA_Int32 i = 0; i < node->referencesSize; i++) {
+            if(node->references[i].referenceTypeId.identifier.numeric != UA_NS0ID_HASSUBTYPE ||
                node->references[i].isInverse == UA_TRUE)
                 continue;
 
-            // Do we have enough space in the array?
-            if(lastIndex + 1 >= arraySize) {
-                UA_NodeId *newArray = UA_malloc(sizeof(UA_NodeId) * arraySize * 2);
-                if(!newArray) {
+            if(++last >= results_size) { // is the array big enough?
+                UA_NodeId *new_results = UA_malloc(sizeof(UA_NodeId) * results_size * 2);
+                if(!new_results) {
                     retval = UA_STATUSCODE_BADOUTOFMEMORY;
                     break;
                 }
-                UA_memcpy(newArray, typeArray, sizeof(UA_NodeId) * arraySize);
-                arraySize *= 2;
-                UA_free(typeArray);
-                typeArray = newArray;
+                UA_memcpy(new_results, results, sizeof(UA_NodeId) * results_size);
+                results_size *= 2;
+                UA_free(results);
+                results = new_results;
             }
 
-            // Copy the node
-            retval |= UA_NodeId_copy(&node->references[i].targetId.nodeId, &typeArray[++lastIndex]);
-            if(retval)
-                lastIndex--; // undo if we need to delete the typeArray
+            retval = UA_NodeId_copy(&node->references[i].targetId.nodeId, &results[last]);
+            if(retval != UA_STATUSCODE_GOOD) {
+                last--;
+                break;
+            }
         }
-        UA_NodeStore_release((const UA_Node*)node);
-    } while(++index <= lastIndex && retval == UA_STATUSCODE_GOOD);
+        UA_NodeStore_release(node);
+        index++;
+    } while(index <= last && retval == UA_STATUSCODE_GOOD);
 
     if(retval) {
-        UA_Array_delete(typeArray, &UA_TYPES[UA_TYPES_NODEID], lastIndex);
+        UA_Array_delete(results, &UA_TYPES[UA_TYPES_NODEID], last);
         return retval;
     }
 
-    *referenceTypes = typeArray;
-    *referenceTypesSize = lastIndex + 1;
+    *reftypes = results;
+    *reftypes_count = last + 1;
     return UA_STATUSCODE_GOOD;
 }
 
 /* Results for a single browsedescription. */
-static void getBrowseResult(UA_NodeStore *ns, const UA_BrowseDescription *browseDescription,
-                            UA_UInt32 maxReferences, UA_BrowseResult *browseResult) {
-    size_t relevantReferenceTypesSize = 0;
-    UA_NodeId *relevantReferenceTypes = UA_NULL;
-
-    // if the referencetype is null, all referencetypes are returned
-    UA_Boolean returnAll = UA_NodeId_isNull(&browseDescription->referenceTypeId);
-    if(!returnAll) {
-        if(browseDescription->includeSubtypes) {
-            browseResult->statusCode =
-                findReferenceTypeSubTypes(ns, &browseDescription->referenceTypeId, &relevantReferenceTypes,
-                                          &relevantReferenceTypesSize);
-            if(browseResult->statusCode != UA_STATUSCODE_GOOD)
+static void
+browse(UA_NodeStore *ns, const UA_BrowseDescription *descr, UA_UInt32 maxrefs, UA_BrowseResult *result)
+{
+    size_t relevant_refs_size = 0;
+    UA_NodeId *relevant_refs = UA_NULL;
+
+    // what are the relevant references?
+    UA_Boolean all_refs = UA_NodeId_isNull(&descr->referenceTypeId);
+    if(!all_refs) {
+        if(descr->includeSubtypes) {
+            result->statusCode = findsubtypes(ns, &descr->referenceTypeId, &relevant_refs, &relevant_refs_size);
+            if(result->statusCode != UA_STATUSCODE_GOOD)
                 return;
         } else {
-            relevantReferenceTypes = UA_NodeId_new();
-            UA_NodeId_copy(&browseDescription->referenceTypeId, relevantReferenceTypes);
-            relevantReferenceTypesSize = 1;
+            relevant_refs = (UA_NodeId*)(uintptr_t)&descr->referenceTypeId;
+            relevant_refs_size = 1;
         }
     }
 
-    const UA_Node *parentNode = UA_NodeStore_get(ns, &browseDescription->nodeId);
-    if(!parentNode) {
-        browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-        if(!returnAll)
-            UA_Array_delete(relevantReferenceTypes, &UA_TYPES[UA_TYPES_NODEID], relevantReferenceTypesSize);
+    // get the node
+    const UA_Node *node = UA_NodeStore_get(ns, &descr->nodeId);
+    if(!node) {
+        result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
+        if(!all_refs && descr->includeSubtypes)
+            UA_Array_delete(relevant_refs, &UA_TYPES[UA_TYPES_NODEID], relevant_refs_size);
         return;
     }
 
-    if(parentNode->referencesSize <= 0) {
-        UA_NodeStore_release(parentNode);
-        browseResult->referencesSize = 0;
-        if(!returnAll)
-            UA_Array_delete(relevantReferenceTypes, &UA_TYPES[UA_TYPES_NODEID], relevantReferenceTypesSize);
-        return;
+    if(node->referencesSize <= 0) {
+        result->referencesSize = 0;
+        goto cleanup;
     }
-    maxReferences = parentNode->referencesSize; // 0 => unlimited references
-
-    /* We allocate an array that is probably too big. But since most systems
-       have more than enough memory, this has zero impact on speed and
-       performance. Call Array_delete with the actual content size! */
-    browseResult->references = UA_malloc(sizeof(UA_ReferenceDescription) * maxReferences);
-    if(!browseResult->references) {
-        browseResult->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
-    } else {
-        size_t currentRefs = 0;
-        for(UA_Int32 i = 0;i < parentNode->referencesSize && currentRefs < maxReferences;i++) {
-            // 1) Is the node relevant? If yes, the node is retrieved from the nodestore.
-            const UA_Node *currentNode =
-                getRelevantTargetNode(ns, browseDescription, returnAll, &parentNode->references[i],
-                                      relevantReferenceTypes, relevantReferenceTypesSize);
-            if(!currentNode)
-                continue;
 
-            // 2) Fill the reference description. This also releases the current node.
-            UA_StatusCode retval = fillReferenceDescription(ns, currentNode, &parentNode->references[i],
-                                                            browseDescription->resultMask,
-                                                            &browseResult->references[currentRefs]);
-            UA_NodeStore_release(currentNode);
-            if(retval) {
-                UA_Array_delete(browseResult->references, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], currentRefs);
-                currentRefs = 0;
-                browseResult->references = UA_NULL;
-                browseResult->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
-                break;
-            }
-            currentRefs++;
-        }
-        if(currentRefs != 0)
-            browseResult->referencesSize = currentRefs;
-        else {
-            UA_free(browseResult->references);
-            browseResult->references = UA_NULL;
+    // allocate memory for the results
+    maxrefs = node->referencesSize; // allocate enough space for all of them
+    result->references = UA_malloc(sizeof(UA_ReferenceDescription) * maxrefs);
+    if(!result->references) {
+        result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+        goto cleanup;
+    }
+
+    size_t count = 0;
+    for(UA_Int32 i = 0; i < node->referencesSize && count < maxrefs; i++) {
+        const UA_Node *current;
+        current = relevant_node(ns, descr, all_refs, &node->references[i], relevant_refs, relevant_refs_size);
+        if(!current)
+            continue;
+
+        UA_StatusCode retval = fillrefdescr(ns, current, &node->references[i], descr->resultMask, &result->references[count]);
+        UA_NodeStore_release(current);
+
+        if(retval) {
+            UA_Array_delete(result->references, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], count);
+            count = 0;
+            result->references = UA_NULL;
+            result->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
+            break;
         }
+        count++;
+    }
+    if(count != 0)
+        result->referencesSize = count;
+    else {
+        UA_free(result->references);
+        result->references = UA_NULL;
     }
 
-    UA_NodeStore_release(parentNode);
-    if(!returnAll)
-        UA_Array_delete(relevantReferenceTypes, &UA_TYPES[UA_TYPES_NODEID], relevantReferenceTypesSize);
+cleanup:
+    UA_NodeStore_release(node);
+    if(!all_refs && descr->includeSubtypes)
+        UA_Array_delete(relevant_refs, &UA_TYPES[UA_TYPES_NODEID], relevant_refs_size);
 }
 
 void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseRequest *request,
@@ -262,86 +242,94 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
     response->resultsSize = size;
     for(size_t i = 0;i < size;i++){
         if(!isExternal[i])
-            getBrowseResult(server->nodestore, &request->nodesToBrowse[i],
-                        request->requestedMaxReferencesPerNode, &response->results[i]);
+            browse(server->nodestore, &request->nodesToBrowse[i],
+                   request->requestedMaxReferencesPerNode, &response->results[i]);
     }
 }
 
-static UA_StatusCode walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *current,
-                                    const UA_RelativePath *path, size_t pathindex,
-                                    UA_BrowsePathTarget *targets, size_t *targetsSize,
-                                    UA_Int32 *currentTargets) {
+/***********************/
+/* TranslateBrowsePath */
+/***********************/
 
+static UA_StatusCode
+walkBrowsePath(UA_Server *server, UA_Session *session, const UA_Node *node, const UA_RelativePath *path, UA_Int32 pathindex,
+               UA_BrowsePathTarget **targets, UA_Int32 *targets_size, UA_Int32 *target_count)
+{
     const UA_RelativePathElement *elem = &path->elements[pathindex];
     if(elem->targetName.name.length == -1)
         return UA_STATUSCODE_BADBROWSENAMEINVALID;
+
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    UA_NodeId *referenceTypes;
-    size_t referenceTypesSize;
-    UA_Boolean allReferences = UA_FALSE;
-    if(UA_NodeId_isNull(&elem->referenceTypeId)) {
-        allReferences = UA_TRUE;
-        referenceTypesSize = 1; // so we enter the inner loop once
-    } else if(elem->includeSubtypes) {
-        retval = findReferenceTypeSubTypes(server->nodestore, &elem->referenceTypeId, &referenceTypes,
-                                           &referenceTypesSize);
-        if(retval != UA_STATUSCODE_GOOD)
-            return UA_STATUSCODE_BADNOMATCH;
-    } else {
-        uintptr_t ptr = (uintptr_t)&elem->referenceTypeId; // ptr magic due to const cast
-        referenceTypes = (UA_NodeId*)ptr;
-        referenceTypesSize = 1;
-    }
+    UA_NodeId *reftypes;
+    size_t reftypes_count = 1; // all_refs or no subtypes => 1
+    UA_Boolean all_refs = UA_FALSE;
+    if(UA_NodeId_isNull(&elem->referenceTypeId))
+        all_refs = UA_TRUE;
+    else if(!elem->includeSubtypes)
+        reftypes = (UA_NodeId*)(uintptr_t)&elem->referenceTypeId; // ptr magic due to const cast
+    else
+        retval = findsubtypes(server->nodestore, &elem->referenceTypeId, &reftypes, &reftypes_count);
+
+    for(UA_Int32 i = 0; i < node->referencesSize && retval == UA_STATUSCODE_GOOD; i++) {
+        UA_Boolean match = all_refs;
+        for(size_t j = 0; j < reftypes_count && !match; j++) {
+            if(node->references[i].isInverse == elem->isInverse &&
+               UA_NodeId_equal(&node->references[i].referenceTypeId, &reftypes[j]))
+                match = UA_TRUE;
+        }
+        if(!match)
+            continue;
 
-    for(UA_Int32 i=0;i<current->referencesSize && retval == UA_STATUSCODE_GOOD;i++) {
-        for(size_t j=0;j<referenceTypesSize && retval == UA_STATUSCODE_GOOD;j++) {
-            if(!allReferences && (!UA_NodeId_equal(&current->references[i].referenceTypeId, &referenceTypes[j])
-                                   || current->references[i].isInverse != elem->isInverse))
-                continue;
-            // todo: expandednodeid
-            const UA_Node *next = UA_NodeStore_get(server->nodestore, &current->references[i].targetId.nodeId);
-            if(!next)
-                continue;
-            if(elem->targetName.namespaceIndex == next->browseName.namespaceIndex &&
-               UA_String_equal(&elem->targetName.name, &next->browseName.name)) {
-                if((UA_Int32)pathindex + 1 >= path->elementsSize) {
-                    // at the end of the path.. add the node
-                    if(*currentTargets >= (UA_Int32)*targetsSize) {
-                        UA_BrowsePathTarget *newtargets = UA_realloc(targets, sizeof(UA_BrowsePathTarget) *
-                                                                     (*targetsSize) * 2);
-                        if(!newtargets) {
-                            retval = UA_STATUSCODE_BADOUTOFMEMORY;
-                        } else {
-                            targets = newtargets;
-                            *targetsSize *= 2;
-                        }
-                    }
-                    if(retval == UA_STATUSCODE_GOOD) {
-                        UA_ExpandedNodeId_init(&targets[*currentTargets].targetId);
-                        UA_NodeId_copy(&next->nodeId, &targets[*currentTargets].targetId.nodeId);
-                        targets[*currentTargets].remainingPathIndex = UA_UINT32_MAX;
-                        *currentTargets += 1;
-                        UA_NodeStore_release(next);
-                        break; // go to the next node
-                    }
-                } else {
-                    // recurse deeper into the path
-                    retval = walkBrowsePath(server, session, next, path, pathindex + 1,
-                                            targets, targetsSize, currentTargets);
+        // get the node, todo: expandednodeid
+        const UA_Node *next = UA_NodeStore_get(server->nodestore, &node->references[i].targetId.nodeId);
+        if(!next)
+            continue;
+
+        // test the browsename
+        if(elem->targetName.namespaceIndex != next->browseName.namespaceIndex ||
+           !UA_String_equal(&elem->targetName.name, &next->browseName.name)) {
+            UA_NodeStore_release(next);
+            continue;
+        }
+
+        if(pathindex + 1 < path->elementsSize) {
+            // recursion if the path is longer
+            retval = walkBrowsePath(server, session, next, path, pathindex + 1,
+                                    targets, targets_size, target_count);
+            UA_NodeStore_release(next);
+        } else {
+            // add the browsetarget
+            if(*target_count >= *targets_size) {
+                UA_BrowsePathTarget *newtargets;
+                newtargets = UA_realloc(targets, sizeof(UA_BrowsePathTarget) * (*targets_size) * 2);
+                if(!newtargets) {
+                    retval = UA_STATUSCODE_BADOUTOFMEMORY;
+                    UA_NodeStore_release(next);
+                    break;
                 }
+                *targets = newtargets;
+                *targets_size *= 2;
             }
+
+            UA_BrowsePathTarget *res = *targets;
+            UA_ExpandedNodeId_init(&res[*target_count].targetId);
+            retval = UA_NodeId_copy(&next->nodeId, &res[*target_count].targetId.nodeId);
             UA_NodeStore_release(next);
+            if(retval != UA_STATUSCODE_GOOD)
+                break;
+            res[*target_count].remainingPathIndex = UA_UINT32_MAX;
+            *target_count += 1;
         }
     }
 
-    if(!allReferences && elem->includeSubtypes)
-        UA_Array_delete(referenceTypes, &UA_TYPES[UA_TYPES_NODEID], (UA_Int32)referenceTypesSize);
+    if(!all_refs && elem->includeSubtypes)
+        UA_Array_delete(reftypes, &UA_TYPES[UA_TYPES_NODEID], (UA_Int32)reftypes_count);
     return retval;
 }
 
 static void translateBrowsePath(UA_Server *server, UA_Session *session, const UA_BrowsePath *path,
                                 UA_BrowsePathResult *result) {
-    size_t arraySize = 10;
+    UA_Int32 arraySize = 10;
     result->targets = UA_malloc(sizeof(UA_BrowsePathTarget) * arraySize);
     if(!result->targets) {
         result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
@@ -356,7 +344,7 @@ static void translateBrowsePath(UA_Server *server, UA_Session *session, const UA
     }
     if(path->relativePath.elementsSize > 0)
         result->statusCode = walkBrowsePath(server, session, firstNode, &path->relativePath, 0,
-                                            result->targets, &arraySize, &result->targetsSize);
+                                            &result->targets, &arraySize, &result->targetsSize);
     else
         result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
     UA_NodeStore_release(firstNode);