Procházet zdrojové kódy

compatibleDataType: compatibility checks for data types of "nodes against nodes" are different from those of "values/variants against nodes"

Thomas Bender před 7 roky
rodič
revize
e2b71e8475

+ 1 - 1
src/server/ua_server_internal.h

@@ -276,7 +276,7 @@ compatibleValueRankArrayDimensions(UA_Int32 valueRank, size_t arrayDimensionsSiz
 
 UA_Boolean
 compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
-                   const UA_NodeId *constraintDataType);
+                   const UA_NodeId *constraintDataType, UA_Boolean isValue);
 
 UA_Boolean
 compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank);

+ 21 - 14
src/server/ua_services_attribute.c

@@ -536,7 +536,7 @@ static const UA_NodeId enumNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ENUMERA
 
 UA_Boolean
 compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
-                   const UA_NodeId *constraintDataType) {
+                   const UA_NodeId *constraintDataType, UA_Boolean isValue) {
     /* Do not allow empty datatypes */
     if(UA_NodeId_isNull(dataType))
        return false;
@@ -545,6 +545,10 @@ compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
     if(UA_NodeId_isNull(constraintDataType))
         return true;
 
+    /* Same datatypes */
+    if (UA_NodeId_equal(dataType, constraintDataType))
+        return true;
+
     /* Variant allows any subtype */
     if(UA_NodeId_equal(constraintDataType, &UA_TYPES[UA_TYPES_VARIANT].typeId))
         return true;
@@ -553,22 +557,25 @@ compatibleDataType(UA_Server *server, const UA_NodeId *dataType,
     if(isNodeInTree(&server->config.nodestore, dataType, constraintDataType, &subtypeId, 1))
         return true;
 
-    /* If value is a built-in type: The target data type may be a sub type of
-     * the built-in type. (e.g. UtcTime is sub-type of DateTime and has a
-     * DateTime value). A type is builtin if its NodeId is in Namespace 0 and
-     * has a numeric identifier <= 25 (DiagnosticInfo) */
-    if(dataType->namespaceIndex == 0 &&
-       dataType->identifierType == UA_NODEIDTYPE_NUMERIC &&
-       dataType->identifier.numeric <= 25 &&
-       isNodeInTree(&server->config.nodestore, constraintDataType,
-                    dataType, &subtypeId, 1))
-        return true;
-
     /* Enum allows Int32 (only) */
     if(UA_NodeId_equal(dataType, &UA_TYPES[UA_TYPES_INT32].typeId) &&
        isNodeInTree(&server->config.nodestore, constraintDataType, &enumNodeId, &subtypeId, 1))
         return true;
 
+    /* More checks for the data type of real values (variants) */
+    if(isValue) {
+        /* If value is a built-in type: The target data type may be a sub type of
+         * the built-in type. (e.g. UtcTime is sub-type of DateTime and has a
+         * DateTime value). A type is builtin if its NodeId is in Namespace 0 and
+         * has a numeric identifier <= 25 (DiagnosticInfo) */
+        if(dataType->namespaceIndex == 0 &&
+           dataType->identifierType == UA_NODEIDTYPE_NUMERIC &&
+           dataType->identifier.numeric <= 25 &&
+           isNodeInTree(&server->config.nodestore, constraintDataType,
+                        dataType, &subtypeId, 1))
+            return true;
+    }
+
     return false;
 }
 
@@ -696,7 +703,7 @@ compatibleValue(UA_Server *server, const UA_NodeId *targetDataTypeId,
 
     /* Has the value a subtype of the required type? BaseDataType (Variant) can
      * be anything... */
-    if(!compatibleDataType(server, &value->type->typeId, targetDataTypeId))
+    if(!compatibleDataType(server, &value->type->typeId, targetDataTypeId, true))
         return false;
 
     /* Array dimensions are checked later when writing the range */
@@ -872,7 +879,7 @@ writeDataTypeAttribute(UA_Server *server, UA_Session *session,
         return UA_STATUSCODE_BADINTERNALERROR;
 
     /* Does the new type match the constraints of the variabletype? */
-    if(!compatibleDataType(server, dataType, &type->dataType))
+    if(!compatibleDataType(server, dataType, &type->dataType, false))
         return UA_STATUSCODE_BADTYPEMISMATCH;
 
     /* Check if the current value would match the new type */

+ 1 - 1
src/server/ua_services_nodemanagement.c

@@ -156,7 +156,7 @@ typeCheckVariableNode(UA_Server *server, UA_Session *session,
         return retval;
 
     /* Check the datatype against the vt */
-    if(!compatibleDataType(server, &node->dataType, &vt->dataType))
+    if(!compatibleDataType(server, &node->dataType, &vt->dataType, false))
         return UA_STATUSCODE_BADTYPEMISMATCH;
 
     /* Get the array dimensions */