Browse Source

Merge branch 'master' of github.com:acplt/open62541 into 0.2

Conflicts:
	src/server/ua_services_view.c
	src/ua_types_encoding_binary.c
Stasik0 8 years ago
parent
commit
38d4e7fbad

+ 13 - 7
include/ua_types.h

@@ -21,6 +21,9 @@ extern "C" {
 #endif
 
 #include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
 #include <stdbool.h>
 #include "ua_config.h"
 #include "ua_constants.h"
@@ -216,9 +219,11 @@ UA_EXPORT extern const UA_String UA_STRING_NULL;
  * ``UA_STRING_ALLOC`` is shorthand for ``UA_String_fromChars`` and makes a copy
  * of the char-array. */
 static UA_INLINE UA_String
-UA_STRING(char *chars) {
+UA_STRING(const char *chars) {
     UA_String str; str.length = strlen(chars);
-    str.data = (UA_Byte*)chars; return str;
+    str.length = strlen(chars);
+    str.data = (UA_Byte *) malloc(str.length ); memcpy(str.data, chars, str.length ); 
+    return str;
 }
 
 #define UA_STRING_ALLOC(CHARS) UA_String_fromChars(CHARS)
@@ -290,7 +295,7 @@ UA_StatusCode UA_EXPORT UA_ByteString_allocBuffer(UA_ByteString *bs, size_t leng
 UA_EXPORT extern const UA_ByteString UA_BYTESTRING_NULL;
 
 static UA_INLINE UA_ByteString
-UA_BYTESTRING(char *chars) {
+UA_BYTESTRING( char *chars) {
     UA_ByteString str; str.length = strlen(chars);
     str.data = (UA_Byte*)chars; return str;
 }
@@ -415,7 +420,7 @@ UA_EXPANDEDNODEID_STRING_GUID(UA_UInt16 nsIndex, UA_Guid guid) {
 }
 
 static UA_INLINE UA_ExpandedNodeId
-UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex, char *chars) {
+UA_EXPANDEDNODEID_BYTESTRING(UA_UInt16 nsIndex,  char *chars) {
     UA_ExpandedNodeId id; id.nodeId = UA_NODEID_BYTESTRING(nsIndex, chars);
     id.serverIndex = 0; id.namespaceUri = UA_STRING_NULL; return id;
 }
@@ -442,9 +447,10 @@ UA_QualifiedName_isNull(const UA_QualifiedName *q) {
 }
 
 static UA_INLINE UA_QualifiedName
-UA_QUALIFIEDNAME(UA_UInt16 nsIndex, char *chars) {
+UA_QUALIFIEDNAME(UA_UInt16 nsIndex, const char *chars) {
     UA_QualifiedName qn; qn.namespaceIndex = nsIndex;
-    qn.name = UA_STRING(chars); return qn;
+    qn.name.length = strlen(chars);
+    qn.name.data = (UA_Byte *) malloc(qn.name.length ); memcpy(qn.name.data, chars, qn.name.length ); return qn;
 }
 
 static UA_INLINE UA_QualifiedName
@@ -463,7 +469,7 @@ typedef struct {
 } UA_LocalizedText;
 
 static UA_INLINE UA_LocalizedText
-UA_LOCALIZEDTEXT(char *locale, char *text) {
+UA_LOCALIZEDTEXT( const char *locale,  const char *text) {
     UA_LocalizedText lt; lt.locale = UA_STRING(locale);
     lt.text = UA_STRING(text); return lt;
 }

+ 5 - 1
src/server/ua_server_internal.h

@@ -90,8 +90,12 @@ void UA_Server_deleteAllRepeatedJobs(UA_Server *server);
 UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range);
 #endif
 
+UA_StatusCode
+getTypeHierarchy(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **reftypes, size_t *reftypes_count);
+
 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_ */

+ 8 - 5
src/server/ua_services_call.c

@@ -26,15 +26,18 @@ getArgumentsVariableNode(UA_Server *server, const UA_MethodNode *ofMethod,
 
 static UA_StatusCode
 satisfySignature(UA_Server *server, const UA_Variant *var, const UA_Argument *arg) {
-    if(!UA_NodeId_equal(&var->type->typeId, &arg->dataType)){
+  if(var == NULL || var->type == NULL) 
+    return UA_STATUSCODE_BADINVALIDARGUMENT;
+  
+  if(!UA_NodeId_equal(&var->type->typeId, &arg->dataType)){
         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 +125,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)

+ 100 - 12
src/server/ua_services_nodemanagement.c

@@ -5,33 +5,111 @@
 /* Helper Functions */
 /********************/
 
-/* Recursively searches "upwards" in the tree following a specific reference type */
+/* Returns the type and all subtypes. We start with an array with a single root nodeid. When a relevant
+ * reference is found, 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. */
+UA_StatusCode
+getTypeHierarchy(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
+    const UA_Node *node = UA_NodeStore_get(ns, root);
+    if(!node)
+        return UA_STATUSCODE_BADNOMATCH;
+    if(node->nodeClass != UA_NODECLASS_REFERENCETYPE)
+        return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+
+    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_NodeId_copy(root, &results[0]);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_free(results);
+        return retval;
+    }
+
+    size_t idx = 0; // where are we currently in the array?
+    size_t last = 0; // where is the last element in the array?
+    const UA_NodeId hasSubtypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
+    do {
+        node = UA_NodeStore_get(ns, &results[idx]);
+        if(!node || node->nodeClass != UA_NODECLASS_REFERENCETYPE)
+            continue;
+        for(size_t i = 0; i < node->referencesSize; i++) {
+            if(node->references[i].isInverse == true ||
+               !UA_NodeId_equal(&hasSubtypeNodeId, &node->references[i].referenceTypeId))
+                continue;
+
+            if(++last >= results_size) { // is the array big enough?
+                UA_NodeId *new_results = UA_realloc(results, sizeof(UA_NodeId) * results_size * 2);
+                if(!new_results) {
+                    retval = UA_STATUSCODE_BADOUTOFMEMORY;
+                    break;
+                }
+                results = new_results;
+                results_size *= 2;
+            }
+
+            retval = UA_NodeId_copy(&node->references[i].targetId.nodeId, &results[last]);
+            if(retval != UA_STATUSCODE_GOOD) {
+                last--; // for array_delete
+                break;
+            }
+        }
+    } while(++idx <= last && retval == UA_STATUSCODE_GOOD);
+
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_Array_delete(results, last, &UA_TYPES[UA_TYPES_NODEID]);
+        return retval;
+    }
+
+    *typeHierarchy = results;
+    *typeHierarchySize = last + 1;
+    return UA_STATUSCODE_GOOD;
+}
+
+/* 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 +203,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 +225,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 +305,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 +367,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)

+ 6 - 4
src/server/ua_subscription.c

@@ -108,10 +108,12 @@ static void SampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
             return;
         }
         MonitoredItem_queuedValue *queueItem = TAILQ_LAST(&monitoredItem->queue, QueueOfQueueDataValues);
-        TAILQ_REMOVE(&monitoredItem->queue, queueItem, listEntry);
-        UA_DataValue_deleteMembers(&queueItem->value);
-        UA_free(queueItem);
-        monitoredItem->currentQueueSize--;
+        if (queueItem != NULL) {
+          TAILQ_REMOVE(&monitoredItem->queue, queueItem, listEntry);
+          UA_DataValue_deleteMembers(&queueItem->value);
+          UA_free(queueItem);
+          monitoredItem->currentQueueSize--;
+        }
     }
 
     /* add the sample */