Browse Source

fix last CTT issues for AddNodes

Julius Pfrommer 8 years ago
parent
commit
7a39748e4d
2 changed files with 52 additions and 18 deletions
  1. 21 15
      src/server/ua_server.c
  2. 31 3
      src/server/ua_services_nodemanagement.c

+ 21 - 15
src/server/ua_server.c

@@ -433,18 +433,10 @@ createVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
     return variabletype;
 }
 
-static void
-addVariableTypeNode_organized(UA_Server *server, char* name, UA_UInt32 variabletypeid,
-                              UA_UInt32 parent, UA_Boolean abstract) {
-    UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
-    addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdOrganizes);
-}
-
 static void
 addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32 variabletypeid,
                             UA_UInt32 parent, UA_Boolean abstract) {
-    UA_VariableTypeNode *variabletype =
-        createVariableTypeNode(server, name, variabletypeid, parent, abstract);
+    UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
     addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdHasSubType);
 }
 
@@ -703,7 +695,8 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
     hasnotifier->isAbstract = false;
     hasnotifier->symmetric  = false;
-    addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE), nodeIdHasSubType);
+    addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE),
+                    nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasorderedcomponent = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
@@ -711,7 +704,8 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
     hasorderedcomponent->isAbstract = false;
     hasorderedcomponent->symmetric  = false;
-    addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), nodeIdHasSubType);
+    addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                    nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasmodelparent = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)hasmodelparent, "HasModelParent");
@@ -744,7 +738,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hascause->isAbstract = false;
     hascause->symmetric  = false;
     addNodeInternal(server, (UA_Node*)hascause, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
-    
+
     UA_ReferenceTypeNode *haseffect = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)haseffect, "HasEffect");
     haseffect->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeEffectedBy");
@@ -823,7 +817,6 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     /* Link in the bootstrapped baseobjecttype */
     addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdOrganizes,
                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), true);
-
     addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
     addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
                       UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
@@ -877,13 +870,26 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     addDataTypeNode(server, "Enumeration", UA_NS0ID_ENUMERATION, UA_NS0ID_BASEDATATYPE);
         addDataTypeNode(server, "ServerState", UA_NS0ID_SERVERSTATE, UA_NS0ID_ENUMERATION);
 
+    /******************/
+    /* Variable Types */
+    /******************/
+
     UA_ObjectNode *variabletypes = UA_NodeStore_newObjectNode();
     copyNames((UA_Node*)variabletypes, "VariableTypes");
     variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
     addNodeInternalWithType(server, (UA_Node*)variabletypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
                             nodeIdOrganizes, nodeIdFolderType);
-    addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE,
-                                  UA_NS0ID_VARIABLETYPESFOLDER, true);
+
+    /* Bootstrap the BaseVariableType */
+    UA_VariableTypeNode *basevariabletype = UA_NodeStore_newVariableTypeNode();
+    copyNames((UA_Node*)basevariabletype, "BaseVariableType");
+    basevariabletype->nodeId.identifier.numeric = UA_NS0ID_BASEVARIABLETYPE;
+    UA_RCU_LOCK();
+    UA_NodeStore_insert(server->nodestore, (UA_Node*)basevariabletype);
+    UA_RCU_UNLOCK();
+    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER), nodeIdOrganizes,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE), true);
+
     addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
                                 UA_NS0ID_BASEVARIABLETYPE, false);
     addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE,

+ 31 - 3
src/server/ua_services_nodemanagement.c

@@ -148,6 +148,32 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         return;
     }
 
+    /* Test if the reference to the parent is valid */
+    const UA_NodeId nodeIdHasSubtype = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
+    switch(node->nodeClass) {
+    case UA_NODECLASS_OBJECTTYPE:
+    case UA_NODECLASS_VARIABLETYPE:
+    case UA_NODECLASS_REFERENCETYPE:
+        /* DataTypeNodes have no subtype relations */
+        /* -- CTT throw errors with this check as they test all combinations of node and reference type -- */
+        /* if(!UA_NodeId_equal(referenceTypeId, &nodeIdHasSubtype)) { */
+        /*     UA_LOG_DEBUG_SESSION(server->config.logger, session, */
+        /*                          "AddNodes: Trying to add a type node without a hassubtype relation"); */
+        /*     result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED; */
+        /*     UA_NodeStore_deleteNode(node); */
+        /*     return; */
+        /* } */
+        break;
+    default:
+        if(UA_NodeId_equal(referenceTypeId, &nodeIdHasSubtype)) {
+            UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                 "AddNodes: Trying to add a non-type node with a hassubtype relation");
+            result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
+            UA_NodeStore_deleteNode(node);
+            return;
+        }
+    }
+
     const UA_ReferenceTypeNode *referenceType =
         (const UA_ReferenceTypeNode *)UA_NodeStore_get(server->nodestore, referenceTypeId);
     if(!referenceType) {
@@ -207,7 +233,7 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
-                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The object if not derived from BaseObjectType");
+                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The object is not derived from BaseObjectType");
                 goto remove_node;
             }
         }
@@ -229,7 +255,7 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
-                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The variable if not derived from BaseVariableType");
+                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The variable is not derived from BaseVariableType");
                 goto remove_node;
             }
         }
@@ -652,7 +678,9 @@ void Service_AddNodes_single(UA_Server *server, UA_Session *session, const UA_Ad
         node = variableNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_OBJECTTYPE:
-        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]) {
+        /* The structures of UA_ObjectTypeAttributes and UA_ObjectType are identical. CTT uses this. */
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES] &&
+           item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]) {
             result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
             return;
         }