Browse Source

NodeManagement: Allow AddNodes with an undecoded ExtensionObject value

Fix for #2918.
Julius Pfrommer 4 years ago
parent
commit
0a2e0aede1
2 changed files with 29 additions and 19 deletions
  1. 2 19
      src/server/ua_nodes.c
  2. 27 0
      tests/server/check_services_nodemanagement.c

+ 2 - 19
src/server/ua_nodes.c

@@ -318,26 +318,9 @@ copyCommonVariableAttributes(UA_VariableNode *node,
     node->valueRank = attr->valueRank;
 
     /* Copy the value */
-    node->valueSource = UA_VALUESOURCE_DATA;
-    UA_NodeId extensionObject = UA_NODEID_NUMERIC(0, UA_NS0ID_STRUCTURE);
-    /* If we have an extension object which is still encoded (e.g. from the
-     * nodeset compiler) return an error.
-     * This was used in the old version of the nodeset compiler and is not
-     * needed anymore. */
-    if(attr->value.type != NULL && UA_NodeId_equal(&attr->value.type->typeId, &extensionObject)) {
-        /* Do nothing since we got an empty array of extension objects */
-        if(attr->value.data == UA_EMPTY_ARRAY_SENTINEL)
-            return UA_STATUSCODE_GOOD;
-
-        const UA_ExtensionObject *obj = (const UA_ExtensionObject *)attr->value.data;
-        if(obj && obj->encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) {
-            return UA_STATUSCODE_BADNOTSUPPORTED;
-        }
-    }
-
     retval = UA_Variant_copy(&attr->value, &node->value.data.value.value);
-
-    node->value.data.value.hasValue = node->value.data.value.value.type != NULL;
+    node->valueSource = UA_VALUESOURCE_DATA;
+    node->value.data.value.hasValue = (node->value.data.value.value.type != NULL);
 
     return retval;
 }

+ 27 - 0
tests/server/check_services_nodemanagement.c

@@ -57,6 +57,32 @@ START_TEST(AddVariableNode) {
     ck_assert_int_eq(UA_STATUSCODE_GOOD, res);
 } END_TEST
 
+START_TEST(AddVariableNode_ExtensionObject) {
+    /* Add a variable node to the address space */
+    UA_VariableAttributes attr = UA_VariableAttributes_default;
+    attr.displayName = UA_LOCALIZEDTEXT("en-US","the extensionobject");
+
+    /* Set an ExtensionObject with an unknown binary encoding */
+    UA_ExtensionObject myExtensionObject;
+    UA_ExtensionObject_init(&myExtensionObject);
+    myExtensionObject.encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
+    myExtensionObject.content.encoded.typeId = UA_NODEID_NUMERIC(5, 1234);
+    UA_ByteString byteString = UA_BYTESTRING("String Payload as a ByteString extension");
+    myExtensionObject.content.encoded.body = byteString;
+    UA_Variant_setScalar(&attr.value, &myExtensionObject, &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
+
+    UA_NodeId myEONodeId = UA_NODEID_STRING(1, "the.extensionobject");
+    UA_QualifiedName myEOName = UA_QUALIFIEDNAME(1, "the extensionobject");
+    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
+    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
+    UA_StatusCode res =
+        UA_Server_addVariableNode(server, myEONodeId, parentNodeId,
+                                  parentReferenceNodeId, myEOName,
+                                  UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                                  attr, NULL, NULL);
+    ck_assert_int_eq(UA_STATUSCODE_GOOD, res);
+} END_TEST
+
 static UA_NodeId pointTypeId;
 
 static void
@@ -565,6 +591,7 @@ int main(void) {
     TCase *tc_addnodes = tcase_create("addnodes");
     tcase_add_checked_fixture(tc_addnodes, setup, teardown);
     tcase_add_test(tc_addnodes, AddVariableNode);
+    tcase_add_test(tc_addnodes, AddVariableNode_ExtensionObject);
     tcase_add_test(tc_addnodes, InstantiateVariableTypeNode);
     tcase_add_test(tc_addnodes, InstantiateVariableTypeNodeWrongDims);
     tcase_add_test(tc_addnodes, InstantiateVariableTypeNodeLessDims);