ソースを参照

make typedescription branch work

Julius Pfrommer 10 年 前
コミット
b985935593

+ 61 - 85
CMakeLists.txt

@@ -14,35 +14,6 @@ if (NOT CMAKE_BUILD_TYPE)
     set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build." FORCE)
 endif()
 
-# main sources of libopen62541
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
-file(GLOB_RECURSE exported_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
-file(GLOB_RECURSE headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
-file(GLOB generated_headers "${PROJECT_BINARY_DIR}/src_generated/*.h")
-set(lib_sources 
-                src/ua_types.c
-                src/ua_types_encoding_binary.c
-                ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
-                ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
-                src/ua_securechannel.c
-                src/ua_session.c
-                # src/server/ua_server.c
-				# src/server/ua_server_addressspace.c
-				# src/server/ua_server_binary.c
-                # src/server/ua_server_worker.c
-                src/server/ua_securechannel_manager.c
-                src/server/ua_session_manager.c
-                # src/server/ua_services_attribute.c
-                # src/server/ua_services_session.c
-                # src/server/ua_services_discovery.c
-                # src/server/ua_services_securechannel.c
-                # src/server/ua_services_nodemanagement.c
-                # src/server/ua_services_view.c
-				${exported_headers}
-				${generated_headers}
-                ${headers})
-
 # compiler flags
 if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
 add_definitions(-std=c99 -pipe -Wall -Wextra -Werror -Wformat
@@ -61,8 +32,44 @@ add_definitions(-std=c99 -pipe -Wall -Wextra -Werror -Wformat
 	endif()
 endif()
 
-# build settings
-set(generate_src_options) # the options for the tools that generate code from xml-schema definitions
+# main sources of libopen62541
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
+include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
+file(GLOB_RECURSE exported_headers "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h")
+file(GLOB generated_headers "${PROJECT_BINARY_DIR}/src_generated/*.h")
+set(lib_sources src/ua_types.c
+                src/ua_types_encoding_binary.c
+                ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
+                ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
+                ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
+                src/ua_securechannel.c
+                src/ua_session.c
+                src/server/ua_server.c
+				src/server/ua_server_addressspace.c
+				src/server/ua_server_binary.c
+				src/server/ua_nodes.c
+                src/server/ua_server_worker.c
+                src/server/ua_securechannel_manager.c
+                src/server/ua_session_manager.c
+                src/server/ua_services_discovery.c
+                src/server/ua_services_securechannel.c
+                src/server/ua_services_session.c
+                src/server/ua_services_attribute.c
+                src/server/ua_services_nodemanagement.c
+                src/server/ua_services_view.c
+				${exported_headers}
+				${generated_headers} )
+
+## multithreading
+option(MULTITHREADING "Enable multithreading" OFF)
+if(MULTITHREADING)
+    set(UA_MULTITHREADING ON)
+    find_package(Threads REQUIRED)
+    list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
+else()
+    list(APPEND lib_sources src/server/ua_nodestore.c)
+endif()
+
 
 ## set debug flag
 if(CMAKE_BUILD_TYPE MATCHES Debug)
@@ -102,42 +109,6 @@ if(ENABLE_SELFSIGNED)
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/certs/localhost.cnf)
 endif()
 
-# ### xml
-# option(ENABLE_XML_ENCODING "Enable XML-encoding of the UA types" OFF)
-# if(ENABLE_XML_ENCODING)
-#     MATH(EXPR UA_ENCODING_AMOUNT "${UA_ENCODING_AMOUNT}+1")
-#     find_package(EXPAT REQUIRED)
-#     if(EXPAT_FOUND)
-#         include_directories(${EXPAT_INCLUDE_DIRS})
-#     else(EXPAT_FOUND)
-#         message(FATAL_ERROR "Expat library not found.")
-#     endif(EXPAT_FOUND)
-# 	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/ongoing")
-#     list(APPEND lib_sources src/ongoing/ua_types_encoding_xml.c
-#                             src/ongoing/ua_namespace_xml.c
-#                             src/ongoing/ua_xml.c)
-#     list(APPEND generate_src_options "--with-xml")
-# endif()
-
-# ### json
-# option(ENABLE_JSON_ENCODING "Enable JSON-encoding of the UA types" OFF)
-# if(ENABLE_JSON_ENCODING)
-#     MATH(EXPR UA_ENCODING_AMOUNT "${UA_ENCODING_AMOUNT}+1")
-# 	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/ongoing")
-#     list(APPEND lib_sources src/ongoing/ua_types_encoding_json.c)
-#     list(APPEND generate_src_options "--with-json")
-# endif(ENABLE_JSON_ENCODING)
-
-## multithreading
-# option(MULTITHREADING "Enable multithreading" OFF)
-# if(MULTITHREADING)
-#     set(UA_MULTITHREADING ON)
-#     find_package(Threads REQUIRED)
-#     list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
-# else()
-#     list(APPEND lib_sources src/server/ua_nodestore.c)
-# endif()
-
 add_library(open62541-objects OBJECT ${lib_sources}) # static version that exports all symbols
 add_library(open62541 SHARED $<TARGET_OBJECTS:open62541-objects>)
 target_compile_definitions(open62541-objects PUBLIC UA_DYNAMIC_LINKING)
@@ -187,7 +158,12 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_gener
                    PRE_BUILD
                    COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --ns0-types-xml ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd 1 ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
-                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd
+                           ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd)
+
+add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
+                   PRE_BUILD
+                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_nodeids.py ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids
+                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_nodeids.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
 
 # build example client
@@ -204,23 +180,23 @@ if(CLIENT)
 endif()
 
 # build example server
-# option(EXAMPLESERVER "Build a test server" OFF)
-# if(EXAMPLESERVER)
-# set(server_sources examples/opcuaServer.c
-#                    examples/networklayer_tcp.c
-#                    examples/logger_stdout.c)
-# if(EXTENSION_UDP)
-# 	list(APPEND server_sources examples/networklayer_udp.c)
-# endif()
-# add_executable(exampleServer ${server_sources} ${exported_headers} ${generated_headers})
-# target_link_libraries(exampleServer open62541)
-# if(WIN32)
-#     target_link_libraries(exampleServer ws2_32)
-# endif(WIN32)
-# if(MULTITHREADING)
-#     target_link_libraries(exampleServer urcu-cds urcu urcu-common pthread)
-# endif()
-# endif()
+option(EXAMPLESERVER "Build a test server" OFF)
+if(EXAMPLESERVER)
+set(server_sources examples/opcuaServer.c
+                   examples/networklayer_tcp.c
+                   examples/logger_stdout.c)
+if(EXTENSION_UDP)
+	list(APPEND server_sources examples/networklayer_udp.c)
+endif()
+add_executable(exampleServer ${server_sources} ${exported_headers} ${generated_headers})
+target_link_libraries(exampleServer open62541)
+if(WIN32)
+    target_link_libraries(exampleServer ws2_32)
+endif(WIN32)
+if(MULTITHREADING)
+    target_link_libraries(exampleServer urcu-cds urcu urcu-common pthread)
+endif()
+endif()
 
 # build unit tests
 option(ENABLE_UNIT_TESTS "Run unit tests after building" OFF)

+ 9 - 9
examples/opcuaServer.c

@@ -2,6 +2,8 @@
  * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  */
+#include <time.h>
+#include "ua_types.h"
 
 #include <stdio.h>
 #include <stdlib.h> 
@@ -10,7 +12,6 @@
 
 // provided by the open62541 lib
 #include "ua_server.h"
-#include "ua_namespace_0.h"
 
 // provided by the user, implementations available in the /examples folder
 #include "logger_stdout.h"
@@ -20,6 +21,7 @@
 #endif
 
 #include "ua_types.h"
+#include "ua_nodeids.h"
 
 UA_Boolean running = 1;
 
@@ -60,7 +62,6 @@ static void testCallback(UA_Server *server, void *data) {
 
 int main(int argc, char** argv) {
 	signal(SIGINT, stopHandler); /* catches ctrl-c */
-    printf("--- %lu\n", sizeof(UA_DataType));
 
 	UA_Server *server = UA_Server_new();
     UA_Server_setServerCertificate(server, loadCertificate());
@@ -70,7 +71,6 @@ int main(int argc, char** argv) {
     UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
 #endif
 
-
     UA_WorkItem work = {.type = UA_WORKITEMTYPE_METHODCALL, .work.methodCall = {.method = testCallback, .data = UA_NULL} };
     UA_Server_addRepeatedWorkItem(server, &work, 20000000, UA_NULL); // call every 2 sec
 
@@ -78,11 +78,11 @@ int main(int argc, char** argv) {
     UA_Int32 *myInteger = UA_Int32_new();
     *myInteger = 42;
     UA_QualifiedName myIntegerName;
-    UA_QUALIFIEDNAME_STATIC(myIntegerName, "the answer");
+    UA_QUALIFIEDNAME_ASSIGN(myIntegerName, "the answer");
     UA_Server_addScalarVariableNode(server, &myIntegerName,
-                                    myInteger, &UA_TYPES[UA_INT32],
-                                    &UA_EXPANDEDNODEIDS[UA_OBJECTSFOLDER],
-                                    &UA_NODEIDS[UA_ORGANIZES]);
+                                    myInteger, UA_NODEID_STATIC(UA_TYPES_IDS[UA_TYPES_INT32],0),
+                                    &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_OBJECTSFOLDER,0),
+                                    &UA_NODEID_STATIC(UA_NS0ID_ORGANIZES,0));
     
 #ifdef BENCHMARK
     UA_UInt32 nodeCount = 500;
@@ -102,8 +102,8 @@ int main(int argc, char** argv) {
         tmpNode->value.storageType = UA_VARIANT_DATA_NODELETE;
         tmpNode->value.storage.data.arrayLength = 1;
         UA_Server_addNode(server, (const UA_Node**)&tmpNode,
-                          &UA_EXPANDEDNODEIDS[UA_OBJECTSFOLDER],
-                          &UA_NODEIDS[UA_HASCOMPONENT]);
+                          &UA_EXPANDEDNODEID_STATIC(UA_OBJECTSFOLDER,0),
+                          &UA_NODEID_STATIC(UA_HASCOMPONENT,0));
     }
 #endif
 

+ 0 - 1
include/ua_client.h

@@ -2,7 +2,6 @@
 #include "ua_types.h"
 #include "ua_connection.h"
 #include "ua_transport_generated.h"
-#include "ua_namespace_0.h"
 
 /**
  * The client networklayer can handle only a single connection. The networklayer

+ 10 - 20
include/ua_server.h

@@ -24,7 +24,7 @@ extern "C" {
 #include "ua_util.h"
 #include "ua_types_generated.h"
 #include "ua_connection.h"
-#include "ua_nodes.h"
+    //#include "ua_nodes.h"
 #include "ua_log.h"
 
 /**
@@ -56,28 +56,18 @@ void UA_EXPORT UA_Server_delete(UA_Server *server);
  */
 UA_StatusCode UA_EXPORT UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_Boolean *running);
 
-/**
- * Add a node to the server's address space
- *
- * If adding the node succeeds, the pointer to the node is set to null. If the
- * original nodeid is null (ns=0,i=0), a unique new nodeid is created for the
- * node and returned in the AddNodesResult struct. */
-UA_AddNodesResult UA_EXPORT UA_Server_addNode(UA_Server *server, const UA_Node **node,
-                                              const UA_ExpandedNodeId *parentNodeId,
-                                              const UA_NodeId *referenceTypeId);
-
 /** Add a reference to the server's address space */
 UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item);
 
-/* /\** */
-/*  * Add a scalar variable (node) to the server's address space */
-/*  * */
-/*  * The value must lie on the heap and must not be reused after adding it, as it */
-/*  * becomes attached to the lifecycle of the VariableNode. *\/ */
-/* void UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName, */
-/*                                                void *value, const UA_TypeVTable *vt, */
-/*                                                const UA_ExpandedNodeId *parentNodeId, */
-/*                                                const UA_NodeId *referenceTypeId ); */
+/**
+ * Add a scalar variable (node) to the server's address space
+ *
+ * The value must lie on the heap and must not be reused after adding it, as it
+ * becomes attached to the lifecycle of the VariableNode. */
+UA_StatusCode UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName,
+                                                        void *value, const UA_NodeId typeId,
+                                                        const UA_ExpandedNodeId *parentNodeId,
+                                                        const UA_NodeId *referenceTypeId );
 
 /** Work that is run in the main loop (singlethreaded) or dispatched to a worker
     thread. */

+ 11 - 0
include/ua_types.h

@@ -371,13 +371,24 @@ UA_Boolean UA_EXPORT UA_NodeId_isNull(const UA_NodeId *p);
     VARIABLE.namespaceIndex = NAMESPACE;                      \
     VARIABLE.identifierType = UA_NODEIDTYPE_NUMERIC;          \
     VARIABLE.identifier.numeric = NUMERICID; } while(0);
+#define UA_NODEID_STATIC(NUMERICID, NAMESPACE)                          \
+    (UA_NodeId){.namespaceIndex = NAMESPACE, .identifierType = UA_NODEIDTYPE_NUMERIC, \
+            .identifier.numeric = NUMERICID}
 
 /* ExpandedNodeId */
 UA_Boolean UA_EXPORT UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p);
+#define UA_EXPANDEDNODEID_STATIC(NUMERICID, NAMESPACE)                  \
+    (UA_ExpandedNodeId){.nodeId = {.namespaceIndex = NAMESPACE, .identifierType = UA_NODEIDTYPE_NUMERIC, \
+                                   .identifier.numeric = NUMERICID},    \
+            .serverIndex = 0, .namespaceUri = {.length = -1, .data = UA_NULL} }
 
 /* QualifiedName */
 UA_StatusCode UA_EXPORT UA_QualifiedName_copycstring(char const *src, UA_QualifiedName *dst);
 void UA_EXPORT UA_QualifiedName_printf(char const *label, const UA_QualifiedName *qn);
+#define UA_QUALIFIEDNAME_ASSIGN(VARIABLE, STRING) do {          \
+        VARIABLE.namespaceIndex = 0;                            \
+        UA_STRING_ASSIGN(VARIABLE.name, STRING); } while(0)
+    
 
 /* LocalizedText */
 UA_StatusCode UA_EXPORT UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);

+ 329 - 0
src/server/ua_nodes.c

@@ -0,0 +1,329 @@
+#include "ua_nodes.h"
+#include "ua_util.h"
+
+/* UA_Node */
+static void UA_Node_init(UA_Node *p) {
+	UA_NodeId_init(&p->nodeId);
+	UA_NodeClass_init(&p->nodeClass);
+	UA_QualifiedName_init(&p->browseName);
+	UA_LocalizedText_init(&p->displayName);
+	UA_LocalizedText_init(&p->description);
+	UA_UInt32_init(&p->writeMask);
+	UA_UInt32_init(&p->userWriteMask);
+	p->referencesSize = -1;
+	p->references = UA_NULL;
+}
+
+static void UA_Node_deleteMembers(UA_Node *p) {
+	UA_NodeId_deleteMembers(&p->nodeId);
+	UA_QualifiedName_deleteMembers(&p->browseName);
+	UA_LocalizedText_deleteMembers(&p->displayName);
+	UA_LocalizedText_deleteMembers(&p->description);
+	UA_Array_delete((void*)p->references, p->referencesSize, &UA_TYPES[UA_TYPES_REFERENCENODE]);
+}
+
+static UA_StatusCode UA_Node_copy(const UA_Node *src, UA_Node *dst) {
+	UA_StatusCode retval = UA_STATUSCODE_GOOD;
+	UA_Node_init(dst);
+	retval |= UA_NodeId_copy(&src->nodeId, &dst->nodeId);
+	dst->nodeClass = src->nodeClass;
+	retval |= UA_QualifiedName_copy(&src->browseName, &dst->browseName);
+	retval |= UA_LocalizedText_copy(&src->displayName, &dst->displayName);
+	retval |= UA_LocalizedText_copy(&src->description, &dst->description);
+	dst->writeMask = src->writeMask;
+	dst->userWriteMask = src->userWriteMask;
+	dst->referencesSize = src->referencesSize;
+	retval |= UA_Array_copy(src->references, src->referencesSize, (void**)&dst->references,
+                            &UA_TYPES[UA_TYPES_REFERENCENODE]);
+	if(retval)
+    	UA_Node_deleteMembers(dst);
+	return retval;
+}
+
+/* UA_ObjectNode */
+void UA_ObjectNode_init(UA_ObjectNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->eventNotifier = 0;
+}
+
+UA_ObjectNode * UA_ObjectNode_new(void) {
+    UA_ObjectNode *p = (UA_ObjectNode*)UA_malloc(sizeof(UA_ObjectNode));
+    if(p)
+        UA_ObjectNode_init(p);
+    return p;
+}
+
+void UA_ObjectNode_deleteMembers(UA_ObjectNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+}
+
+void UA_ObjectNode_delete(UA_ObjectNode *p) {
+    UA_ObjectNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
+    dst->eventNotifier = src->eventNotifier;
+	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+}
+
+/* UA_ObjectTypeNode */
+void UA_ObjectTypeNode_init(UA_ObjectTypeNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->isAbstract = UA_FALSE;
+}
+
+UA_ObjectTypeNode * UA_ObjectTypeNode_new(void) {
+    UA_ObjectTypeNode *p = (UA_ObjectTypeNode*)UA_malloc(sizeof(UA_ObjectTypeNode));
+    if(p)
+        UA_ObjectTypeNode_init(p);
+    return p;
+}
+
+void UA_ObjectTypeNode_deleteMembers(UA_ObjectTypeNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+}
+
+void UA_ObjectTypeNode_delete(UA_ObjectTypeNode *p) {
+    UA_ObjectTypeNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
+    dst->isAbstract = src->isAbstract;
+	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+}
+
+/* UA_VariableNode */
+void UA_VariableNode_init(UA_VariableNode *p) {
+	UA_Node_init((UA_Node*)p);
+    UA_Variant_init(&p->value);
+    UA_NodeId_init(&p->dataType);
+    p->valueRank = 0;
+    p->arrayDimensionsSize = -1;
+    p->arrayDimensions = UA_NULL;
+    p->accessLevel = 0;
+    p->userAccessLevel = 0;
+    p->minimumSamplingInterval = 0.0;
+    p->historizing = UA_FALSE;
+}
+
+UA_VariableNode * UA_VariableNode_new(void) {
+    UA_VariableNode *p = (UA_VariableNode*)UA_malloc(sizeof(UA_VariableNode));
+    if(p)
+        UA_VariableNode_init(p);
+    return p;
+}
+
+void UA_VariableNode_deleteMembers(UA_VariableNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+    UA_Variant_deleteMembers(&p->value);
+    UA_Array_delete(&p->arrayDimensions, p->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+    p->arrayDimensionsSize = -1;
+}
+
+void UA_VariableNode_delete(UA_VariableNode *p) {
+    UA_VariableNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
+    UA_VariableNode_init(dst);
+	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+    if(retval)
+        return retval;
+    retval = UA_Variant_copy(&src->value, &dst->value);
+    retval |= UA_NodeId_copy(&src->dataType, &dst->dataType);
+    if(retval) {
+        UA_VariableNode_deleteMembers(dst);
+        return retval;
+    }
+    retval = UA_Array_copy(src->arrayDimensions, src->arrayDimensionsSize, (void**)&dst->arrayDimensions,
+                           &UA_TYPES[UA_TYPES_UINT32]);
+    if(retval) {
+        UA_VariableNode_deleteMembers(dst);
+        return retval;
+    }
+    dst->arrayDimensionsSize = src->arrayDimensionsSize;
+    dst->accessLevel = src->accessLevel;
+    dst->userAccessLevel = src->accessLevel;
+    dst->minimumSamplingInterval = src->minimumSamplingInterval;
+    dst->historizing = src->historizing;
+    return UA_STATUSCODE_GOOD;
+}
+
+/* UA_VariableTypeNode */
+void UA_VariableTypeNode_init(UA_VariableTypeNode *p) {
+	UA_Node_init((UA_Node*)p);
+    UA_Variant_init(&p->value);
+    UA_NodeId_init(&p->dataType);
+    p->valueRank = 0;
+    p->arrayDimensionsSize = -1;
+    p->arrayDimensions = UA_NULL;
+    p->isAbstract = UA_FALSE;
+}
+
+UA_VariableTypeNode * UA_VariableTypeNode_new(void) {
+    UA_VariableTypeNode *p = (UA_VariableTypeNode*)UA_malloc(sizeof(UA_VariableTypeNode));
+    if(p)
+        UA_VariableTypeNode_init(p);
+    return p;
+}
+
+void UA_VariableTypeNode_deleteMembers(UA_VariableTypeNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+    UA_Variant_deleteMembers(&p->value);
+    UA_Array_delete(&p->arrayDimensions, p->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+    p->arrayDimensionsSize = -1;
+}
+
+void UA_VariableTypeNode_delete(UA_VariableTypeNode *p) {
+    UA_VariableTypeNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_VariableTypeNode_copy(const UA_VariableTypeNode *src, UA_VariableTypeNode *dst) {
+    UA_VariableTypeNode_init(dst);
+	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+    if(retval)
+        return retval;
+    retval = UA_Variant_copy(&src->value, &dst->value);
+    retval |= UA_NodeId_copy(&src->dataType, &dst->dataType);
+    if(retval) {
+        UA_VariableTypeNode_deleteMembers(dst);
+        return retval;
+    }
+    retval = UA_Array_copy(src->arrayDimensions, src->arrayDimensionsSize, (void**)&dst->arrayDimensions,
+                           &UA_TYPES[UA_TYPES_UINT32]);
+    if(retval) {
+        UA_VariableTypeNode_deleteMembers(dst);
+        return retval;
+    }
+    dst->arrayDimensionsSize = src->arrayDimensionsSize;
+    dst->isAbstract = src->isAbstract;
+    return UA_STATUSCODE_GOOD;
+}
+
+/* UA_ReferenceTypeNode */
+void UA_ReferenceTypeNode_init(UA_ReferenceTypeNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->isAbstract = UA_FALSE;
+    p->symmetric = UA_FALSE;
+    UA_LocalizedText_init(&p->inverseName);
+}
+
+UA_ReferenceTypeNode * UA_ReferenceTypeNode_new(void) {
+    UA_ReferenceTypeNode *p = (UA_ReferenceTypeNode*)UA_malloc(sizeof(UA_ReferenceTypeNode));
+    if(p)
+        UA_ReferenceTypeNode_init(p);
+    return p;
+}
+
+void UA_ReferenceTypeNode_deleteMembers(UA_ReferenceTypeNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+    UA_LocalizedText_deleteMembers(&p->inverseName);
+}
+
+void UA_ReferenceTypeNode_delete(UA_ReferenceTypeNode *p) {
+    UA_ReferenceTypeNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src, UA_ReferenceTypeNode *dst) {
+	UA_StatusCode retval = UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+    if(retval)
+        return retval;
+    retval = UA_LocalizedText_copy(&src->inverseName, &dst->inverseName);
+    if(retval) {
+        UA_ReferenceTypeNode_deleteMembers(dst);
+        return retval;
+    }
+    dst->isAbstract = src->isAbstract;
+    dst->symmetric = src->symmetric;
+    return UA_STATUSCODE_GOOD;
+}
+
+/* UA_MethodNode */
+void UA_MethodNode_init(UA_MethodNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->executable = UA_FALSE;
+    p->userExecutable = UA_FALSE;
+}
+
+UA_MethodNode * UA_MethodNode_new(void) {
+    UA_MethodNode *p = (UA_MethodNode*)UA_malloc(sizeof(UA_MethodNode));
+    if(p)
+        UA_MethodNode_init(p);
+    return p;
+}
+
+void UA_MethodNode_deleteMembers(UA_MethodNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+}
+
+void UA_MethodNode_delete(UA_MethodNode *p) {
+    UA_MethodNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
+    dst->executable = src->executable;
+    dst->userExecutable = src->userExecutable;
+	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+}
+
+/* UA_ViewNode */
+void UA_ViewNode_init(UA_ViewNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->containsNoLoops = UA_FALSE;
+    p->eventNotifier = 0;
+}
+
+UA_ViewNode * UA_ViewNode_new(void) {
+    UA_ViewNode *p = UA_malloc(sizeof(UA_ViewNode));
+    if(p)
+        UA_ViewNode_init(p);
+    return p;
+}
+
+void UA_ViewNode_deleteMembers(UA_ViewNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+}
+
+void UA_ViewNode_delete(UA_ViewNode *p) {
+    UA_ViewNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
+    dst->containsNoLoops = src->containsNoLoops;
+    dst->eventNotifier = src->eventNotifier;
+	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+}
+
+/* UA_DataTypeNode */
+void UA_DataTypeNode_init(UA_DataTypeNode *p) {
+	UA_Node_init((UA_Node*)p);
+    p->isAbstract = UA_FALSE;
+}
+
+UA_DataTypeNode * UA_DataTypeNode_new(void) {
+    UA_DataTypeNode *p = UA_malloc(sizeof(UA_DataTypeNode));
+    if(p)
+        UA_DataTypeNode_init(p);
+    return p;
+}
+
+void UA_DataTypeNode_deleteMembers(UA_DataTypeNode *p) {
+    UA_Node_deleteMembers((UA_Node*)p);
+}
+
+void UA_DataTypeNode_delete(UA_DataTypeNode *p) {
+    UA_DataTypeNode_deleteMembers(p);
+    UA_free(p);
+}
+
+UA_StatusCode UA_DataTypeNode_copy(const UA_DataTypeNode *src, UA_DataTypeNode *dst) {
+    dst->isAbstract = src->isAbstract;
+	return UA_Node_copy((const UA_Node*)src, (UA_Node*)dst);
+}

+ 9 - 0
include/ua_nodes.h

@@ -2,6 +2,7 @@
 #define UA_NODES_H_
 
 #include "ua_types_generated.h"
+#include "ua_types_encoding_binary.h"
 
 #define UA_STANDARD_NODEMEMBERS                 \
     UA_NodeId nodeId;                           \
@@ -22,11 +23,13 @@ typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Byte eventNotifier;
 } UA_ObjectNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_ObjectNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Boolean isAbstract;
 } UA_ObjectTypeNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_ObjectTypeNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
@@ -40,6 +43,7 @@ typedef struct {
     UA_Double minimumSamplingInterval;
     UA_Boolean historizing;
 } UA_VariableNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_VariableNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
@@ -50,6 +54,7 @@ typedef struct {
     UA_UInt32 *arrayDimensions;
     UA_Boolean isAbstract;
 } UA_VariableTypeNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_VariableTypeNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
@@ -57,22 +62,26 @@ typedef struct {
     UA_Boolean symmetric;
     UA_LocalizedText inverseName;
 } UA_ReferenceTypeNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_ReferenceTypeNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Boolean executable;
     UA_Boolean userExecutable;
 } UA_MethodNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_MethodNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Boolean containsNoLoops;
     UA_Byte eventNotifier;
 } UA_ViewNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_ViewNode)
 
 typedef struct {
     UA_STANDARD_NODEMEMBERS
     UA_Boolean isAbstract;
 } UA_DataTypeNode;
+UA_TYPE_HANDLING_FUNCTIONS(UA_DataTypeNode)
 
 #endif /* UA_NODES_H_ */

+ 119 - 89
src/server/ua_server.c

@@ -1,14 +1,15 @@
 #ifdef UA_MULTITHREADING
 #define _LGPL_SOURCE
 #include <urcu.h>
-//#include <urcu-call-rcu.h>
 #endif
 
+#include "ua_types.h"
 #include "ua_server_internal.h"
 #include "ua_securechannel_manager.h"
 #include "ua_session_manager.h"
 #include "ua_util.h"
 #include "ua_services.h"
+#include "ua_nodeids.h"
 
 /**********************/
 /* Namespace Handling */
@@ -60,7 +61,8 @@ void UA_Server_delete(UA_Server *server) {
     UA_SessionManager_deleteMembers(&server->sessionManager);
     UA_NodeStore_delete(server->nodestore);
     UA_ByteString_deleteMembers(&server->serverCertificate);
-    UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize, &UA_TYPES[UA_ENDPOINTDESCRIPTION]);
+    UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize,
+                    &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
     UA_free(server);
 #ifdef UA_MULTITHREADING
     rcu_barrier(); // wait for all scheduled call_rcu work to complete
@@ -156,7 +158,7 @@ UA_Server * UA_Server_new(void) {
     /* bootstrap by manually inserting "references" and "hassubtype" */
     UA_ReferenceTypeNode *references = UA_ReferenceTypeNode_new();
     COPYNAMES(references, "References");
-    references->nodeId     = UA_NODEIDS[UA_REFERENCES];
+    references->nodeId.identifier.numeric = UA_NS0ID_REFERENCES;
     references->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     references->isAbstract = UA_TRUE;
     references->symmetric  = UA_TRUE;
@@ -166,7 +168,7 @@ UA_Server * UA_Server_new(void) {
     UA_ReferenceTypeNode *hassubtype = UA_ReferenceTypeNode_new();
     COPYNAMES(hassubtype, "HasSubtype");
     UA_LocalizedText_copycstring("SubtypeOf", &hassubtype->inverseName);
-    hassubtype->nodeId     = UA_NODEIDS[UA_HASSUBTYPE];
+    hassubtype->nodeId.identifier.numeric = UA_NS0ID_HASSUBTYPE;
     hassubtype->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hassubtype->isAbstract = UA_FALSE;
     hassubtype->symmetric  = UA_FALSE;
@@ -175,297 +177,322 @@ UA_Server * UA_Server_new(void) {
     /* continue adding reference types with normal "addnode" */
     UA_ReferenceTypeNode *hierarchicalreferences = UA_ReferenceTypeNode_new();
     COPYNAMES(hierarchicalreferences, "Hierarchicalreferences");
-    hierarchicalreferences->nodeId     = UA_NODEIDS[UA_HIERARCHICALREFERENCES];
+    hierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_HIERARCHICALREFERENCES;
     hierarchicalreferences->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hierarchicalreferences->isAbstract = UA_TRUE;
     hierarchicalreferences->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node**)&hierarchicalreferences,
-                      &UA_EXPANDEDNODEIDS[UA_REFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_REFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *nonhierarchicalreferences = UA_ReferenceTypeNode_new();
     COPYNAMES(nonhierarchicalreferences, "NonHierarchicalReferences");
-    nonhierarchicalreferences->nodeId     = UA_NODEIDS[UA_NONHIERARCHICALREFERENCES];
+    nonhierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES;
     nonhierarchicalreferences->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     nonhierarchicalreferences->isAbstract = UA_TRUE;
     nonhierarchicalreferences->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&nonhierarchicalreferences,
-                      &UA_EXPANDEDNODEIDS[UA_REFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_REFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *haschild = UA_ReferenceTypeNode_new();
     COPYNAMES(haschild, "HasChild");
-    haschild->nodeId     = UA_NODEIDS[UA_HASCHILD];
+    haschild->nodeId.identifier.numeric = UA_NS0ID_HASCHILD;
     haschild->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     haschild->isAbstract = UA_TRUE;
     haschild->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&haschild,
-                      &UA_EXPANDEDNODEIDS[UA_HIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new();
     COPYNAMES(organizes, "Organizes");
     UA_LocalizedText_copycstring("OrganizedBy", &organizes->inverseName);
-    organizes->nodeId     = UA_NODEIDS[UA_ORGANIZES];
+    organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
     organizes->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     organizes->isAbstract = UA_FALSE;
     organizes->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&organizes,
-                      &UA_EXPANDEDNODEIDS[UA_HIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *haseventsource = UA_ReferenceTypeNode_new();
     COPYNAMES(haseventsource, "HasEventSource");
     UA_LocalizedText_copycstring("EventSourceOf", &haseventsource->inverseName);
-    haseventsource->nodeId     = UA_NODEIDS[UA_HASEVENTSOURCE];
+    haseventsource->nodeId.identifier.numeric = UA_NS0ID_HASEVENTSOURCE;
     haseventsource->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     haseventsource->isAbstract = UA_FALSE;
     haseventsource->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&haseventsource,
-                      &UA_EXPANDEDNODEIDS[UA_HIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasmodellingrule = UA_ReferenceTypeNode_new();
     COPYNAMES(hasmodellingrule, "HasModellingRule");
     UA_LocalizedText_copycstring("ModellingRuleOf", &hasmodellingrule->inverseName);
-    hasmodellingrule->nodeId     = UA_NODEIDS[UA_HASMODELLINGRULE];
+    hasmodellingrule->nodeId.identifier.numeric = UA_NS0ID_HASMODELLINGRULE;
     hasmodellingrule->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasmodellingrule->isAbstract = UA_FALSE;
     hasmodellingrule->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasmodellingrule,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasencoding = UA_ReferenceTypeNode_new();
     COPYNAMES(hasencoding, "HasEncoding");
     UA_LocalizedText_copycstring("EncodingOf", &hasencoding->inverseName);
-    hasencoding->nodeId     = UA_NODEIDS[UA_HASENCODING];
+    hasencoding->nodeId.identifier.numeric = UA_NS0ID_HASENCODING;
     hasencoding->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasencoding->isAbstract = UA_FALSE;
     hasencoding->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasencoding,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasdescription = UA_ReferenceTypeNode_new();
     COPYNAMES(hasdescription, "HasDescription");
     UA_LocalizedText_copycstring("DescriptionOf", &hasdescription->inverseName);
-    hasdescription->nodeId     = UA_NODEIDS[UA_HASDESCRIPTION];
+    hasdescription->nodeId.identifier.numeric = UA_NS0ID_HASDESCRIPTION;
     hasdescription->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasdescription->isAbstract = UA_FALSE;
     hasdescription->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasdescription,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hastypedefinition = UA_ReferenceTypeNode_new();
     COPYNAMES(hastypedefinition, "HasTypeDefinition");
     UA_LocalizedText_copycstring("TypeDefinitionOf", &hastypedefinition->inverseName);
-    hastypedefinition->nodeId     = UA_NODEIDS[UA_HASTYPEDEFINITION];
+    hastypedefinition->nodeId.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION;
     hastypedefinition->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hastypedefinition->isAbstract = UA_FALSE;
     hastypedefinition->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hastypedefinition,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *generatesevent = UA_ReferenceTypeNode_new();
     COPYNAMES(generatesevent, "GeneratesEvent");
     UA_LocalizedText_copycstring("GeneratedBy", &generatesevent->inverseName);
-    generatesevent->nodeId     = UA_NODEIDS[UA_GENERATESEVENT];
+    generatesevent->nodeId.identifier.numeric = UA_NS0ID_GENERATESEVENT;
     generatesevent->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     generatesevent->isAbstract = UA_FALSE;
     generatesevent->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&generatesevent,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *aggregates = UA_ReferenceTypeNode_new();
     COPYNAMES(aggregates, "Aggregates");
     // Todo: Is there an inverse name?
-    aggregates->nodeId     = UA_NODEIDS[UA_AGGREGATES];
+    aggregates->nodeId.identifier.numeric = UA_NS0ID_AGGREGATES;
     aggregates->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     aggregates->isAbstract = UA_TRUE;
     aggregates->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&aggregates,
-                      &UA_EXPANDEDNODEIDS[UA_HASCHILD], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HASCHILD,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     // complete bootstrap of hassubtype
-    ADDREFERENCE(UA_NODEIDS[UA_HASCHILD], UA_NODEIDS[UA_HASSUBTYPE],
-                 UA_EXPANDEDNODEIDS[UA_HASSUBTYPE]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_HASCHILD,0), UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasproperty = UA_ReferenceTypeNode_new();
     COPYNAMES(hasproperty, "HasProperty");
     UA_LocalizedText_copycstring("PropertyOf", &hasproperty->inverseName);
-    hasproperty->nodeId     = UA_NODEIDS[UA_HASPROPERTY];
+    hasproperty->nodeId.identifier.numeric = UA_NS0ID_HASPROPERTY;
     hasproperty->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasproperty->isAbstract = UA_FALSE;
     hasproperty->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasproperty,
-                      &UA_EXPANDEDNODEIDS[UA_AGGREGATES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_AGGREGATES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hascomponent = UA_ReferenceTypeNode_new();
     COPYNAMES(hascomponent, "HasComponent");
     UA_LocalizedText_copycstring("ComponentOf", &hascomponent->inverseName);
-    hascomponent->nodeId     = UA_NODEIDS[UA_HASCOMPONENT];
+    hascomponent->nodeId.identifier.numeric = UA_NS0ID_HASCOMPONENT;
     hascomponent->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hascomponent->isAbstract = UA_FALSE;
     hascomponent->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hascomponent,
-                      &UA_EXPANDEDNODEIDS[UA_AGGREGATES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_AGGREGATES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasnotifier = UA_ReferenceTypeNode_new();
     COPYNAMES(hasnotifier, "HasNotifier");
     UA_LocalizedText_copycstring("NotifierOf", &hasnotifier->inverseName);
-    hasnotifier->nodeId     = UA_NODEIDS[UA_HASNOTIFIER];
+    hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
     hasnotifier->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasnotifier->isAbstract = UA_FALSE;
     hasnotifier->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasnotifier,
-                      &UA_EXPANDEDNODEIDS[UA_HASEVENTSOURCE], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HASEVENTSOURCE,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasorderedcomponent = UA_ReferenceTypeNode_new();
     COPYNAMES(hasorderedcomponent, "HasOrderedComponent");
     UA_LocalizedText_copycstring("OrderedComponentOf", &hasorderedcomponent->inverseName);
-    hasorderedcomponent->nodeId     = UA_NODEIDS[UA_HASORDEREDCOMPONENT];
+    hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
     hasorderedcomponent->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasorderedcomponent->isAbstract = UA_FALSE;
     hasorderedcomponent->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasorderedcomponent,
-                      &UA_EXPANDEDNODEIDS[UA_HASCOMPONENT], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_HASCOMPONENT,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hasmodelparent = UA_ReferenceTypeNode_new();
     COPYNAMES(hasmodelparent, "HasModelParent");
     UA_LocalizedText_copycstring("ModelParentOf", &hasmodelparent->inverseName);
-    hasmodelparent->nodeId     = UA_NODEIDS[UA_HASMODELPARENT];
+    hasmodelparent->nodeId.identifier.numeric = UA_NS0ID_HASMODELPARENT;
     hasmodelparent->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hasmodelparent->isAbstract = UA_FALSE;
     hasmodelparent->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hasmodelparent,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *fromstate = UA_ReferenceTypeNode_new();
     COPYNAMES(fromstate, "FromState");
     UA_LocalizedText_copycstring("ToTransition", &fromstate->inverseName);
-    fromstate->nodeId     = UA_NODEIDS[UA_FROMSTATE];
+    fromstate->nodeId.identifier.numeric = UA_NS0ID_FROMSTATE;
     fromstate->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     fromstate->isAbstract = UA_FALSE;
     fromstate->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&fromstate,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *tostate = UA_ReferenceTypeNode_new();
     COPYNAMES(tostate, "ToState");
     UA_LocalizedText_copycstring("FromTransition", &tostate->inverseName);
-    tostate->nodeId     = UA_NODEIDS[UA_TOSTATE];
+    tostate->nodeId.identifier.numeric = UA_NS0ID_TOSTATE;
     tostate->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     tostate->isAbstract = UA_FALSE;
     tostate->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&tostate,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hascause = UA_ReferenceTypeNode_new();
     COPYNAMES(hascause, "HasCause");
     UA_LocalizedText_copycstring("MayBeCausedBy", &hascause->inverseName);
-    hascause->nodeId     = UA_NODEIDS[UA_HASCAUSE];
+    hascause->nodeId.identifier.numeric = UA_NS0ID_HASCAUSE;
     hascause->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hascause->isAbstract = UA_FALSE;
     hascause->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hascause,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
-
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
+    
     UA_ReferenceTypeNode *haseffect = UA_ReferenceTypeNode_new();
     COPYNAMES(haseffect, "HasEffect");
     UA_LocalizedText_copycstring("MayBeEffectedBy", &haseffect->inverseName);
-    haseffect->nodeId     = UA_NODEIDS[UA_HASEFFECT];
+    haseffect->nodeId.identifier.numeric = UA_NS0ID_HASEFFECT;
     haseffect->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     haseffect->isAbstract = UA_FALSE;
     haseffect->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&haseffect,
-                      &UA_EXPANDEDNODEIDS[UA_NONHIERARCHICALREFERENCES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_NONHIERARCHICALREFERENCES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     UA_ReferenceTypeNode *hashistoricalconfiguration = UA_ReferenceTypeNode_new();
     COPYNAMES(hashistoricalconfiguration, "HasHistoricalConfiguration");
     UA_LocalizedText_copycstring("HistoricalConfigurationOf", &hashistoricalconfiguration->inverseName);
-    hashistoricalconfiguration->nodeId     = UA_NODEIDS[UA_HASHISTORICALCONFIGURATION];
+    hashistoricalconfiguration->nodeId.identifier.numeric = UA_NS0ID_HASHISTORICALCONFIGURATION;
     hashistoricalconfiguration->nodeClass  = UA_NODECLASS_REFERENCETYPE;
     hashistoricalconfiguration->isAbstract = UA_FALSE;
     hashistoricalconfiguration->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&hashistoricalconfiguration,
-                      &UA_EXPANDEDNODEIDS[UA_AGGREGATES], &UA_NODEIDS[UA_HASSUBTYPE]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_AGGREGATES,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASSUBTYPE,0));
 
     /***********/
     /* Objects */
     /***********/
     
     UA_ObjectNode *folderType = UA_ObjectNode_new();
-    folderType->nodeId    = UA_NODEIDS[UA_FOLDERTYPE];
+    folderType->nodeId.identifier.numeric = UA_NS0ID_FOLDERTYPE;
     folderType->nodeClass = UA_NODECLASS_OBJECTTYPE;
     COPYNAMES(folderType, "FolderType");
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&folderType, UA_FALSE);
 
     UA_ObjectNode *root = UA_ObjectNode_new();
     COPYNAMES(root, "Root");
-    root->nodeId    = UA_NODEIDS[UA_ROOTFOLDER];
+    root->nodeId.identifier.numeric = UA_NS0ID_ROOTFOLDER;
     root->nodeClass = UA_NODECLASS_OBJECT;
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&root, UA_FALSE);
-    ADDREFERENCE(UA_NODEIDS[UA_ROOTFOLDER], UA_NODEIDS[UA_HASTYPEDEFINITION],
-                 UA_EXPANDEDNODEIDS[UA_FOLDERTYPE]);
-    ADDREFERENCE(UA_NODEIDS[UA_ROOTFOLDER], UA_NODEIDS[UA_ORGANIZES],
-                 UA_EXPANDEDNODEIDS[UA_OBJECTSFOLDER]);
-    ADDREFERENCE(UA_NODEIDS[UA_ROOTFOLDER], UA_NODEIDS[UA_ORGANIZES],
-                 UA_EXPANDEDNODEIDS[UA_TYPESFOLDER]);
-    ADDREFERENCE(UA_NODEIDS[UA_ROOTFOLDER], UA_NODEIDS[UA_ORGANIZES],
-                 UA_EXPANDEDNODEIDS[UA_VIEWSFOLDER]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_ROOTFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_HASTYPEDEFINITION,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_FOLDERTYPE,0));
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_ROOTFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_ORGANIZES,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_OBJECTSFOLDER,0));
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_ROOTFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_ORGANIZES,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_TYPESFOLDER,0));
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_ROOTFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_ORGANIZES,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_VIEWSFOLDER,0));
 
     UA_ObjectNode *objects = UA_ObjectNode_new();
     COPYNAMES(objects, "Objects");
-    objects->nodeId    = UA_NODEIDS[UA_OBJECTSFOLDER];
+    objects->nodeId.identifier.numeric = UA_NS0ID_OBJECTSFOLDER;
     objects->nodeClass = UA_NODECLASS_OBJECT;
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&objects, UA_FALSE);
-    ADDREFERENCE(UA_NODEIDS[UA_OBJECTSFOLDER], UA_NODEIDS[UA_HASTYPEDEFINITION],
-                 UA_EXPANDEDNODEIDS[UA_FOLDERTYPE]);
-    ADDREFERENCE(UA_NODEIDS[UA_OBJECTSFOLDER], UA_NODEIDS[UA_ORGANIZES], UA_EXPANDEDNODEIDS[UA_SERVER]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_OBJECTSFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_HASTYPEDEFINITION,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_FOLDERTYPE,0));
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_OBJECTSFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_ORGANIZES,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_SERVER,0));
 
     UA_ObjectNode *types = UA_ObjectNode_new();
     COPYNAMES(types, "Types");
-    types->nodeId    = UA_NODEIDS[UA_TYPESFOLDER];
+    types->nodeId.identifier.numeric = UA_NS0ID_TYPESFOLDER;
     types->nodeClass = UA_NODECLASS_OBJECT;
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&types, UA_FALSE);
-    ADDREFERENCE(UA_NODEIDS[UA_TYPESFOLDER], UA_NODEIDS[UA_HASTYPEDEFINITION],
-                 UA_EXPANDEDNODEIDS[UA_FOLDERTYPE]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_TYPESFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_HASTYPEDEFINITION,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_FOLDERTYPE,0));
 
     UA_ObjectNode *views = UA_ObjectNode_new();
     COPYNAMES(views, "Views");
-    views->nodeId    = UA_NODEIDS[UA_VIEWSFOLDER];
+    views->nodeId.identifier.numeric = UA_NS0ID_VIEWSFOLDER;
     views->nodeClass = UA_NODECLASS_OBJECT;
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&views, UA_FALSE);
-    ADDREFERENCE(UA_NODEIDS[UA_VIEWSFOLDER], UA_NODEIDS[UA_HASTYPEDEFINITION],
-                 UA_EXPANDEDNODEIDS[UA_FOLDERTYPE]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_VIEWSFOLDER,0), UA_NODEID_STATIC(UA_NS0ID_HASTYPEDEFINITION,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_FOLDERTYPE,0));
 
     UA_ObjectNode *servernode = UA_ObjectNode_new();
     COPYNAMES(servernode, "Server");
-    servernode->nodeId    = UA_NODEIDS[UA_SERVER];
+    servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
     servernode->nodeClass = UA_NODECLASS_OBJECT;
     UA_NodeStore_insert(server->nodestore, (const UA_Node**)&servernode, UA_FALSE);
-    ADDREFERENCE(UA_NODEIDS[UA_SERVER], UA_NODEIDS[UA_HASCOMPONENT],
-                 UA_EXPANDEDNODEIDS[UA_SERVER_SERVERCAPABILITIES]);
-    ADDREFERENCE(UA_NODEIDS[UA_SERVER], UA_NODEIDS[UA_HASPROPERTY], UA_EXPANDEDNODEIDS[UA_SERVER_SERVERARRAY]);
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_SERVER,0), UA_NODEID_STATIC(UA_NS0ID_HASCOMPONENT,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_SERVER_SERVERCAPABILITIES,0));
+    ADDREFERENCE(UA_NODEID_STATIC(UA_NS0ID_SERVER,0), UA_NODEID_STATIC(UA_NS0ID_HASPROPERTY,0),
+                 UA_EXPANDEDNODEID_STATIC(UA_NS0ID_SERVER_SERVERARRAY,0));
 
     UA_VariableNode *namespaceArray = UA_VariableNode_new();
     COPYNAMES(namespaceArray, "NamespaceArray");
-    namespaceArray->nodeId    = UA_NODEIDS[UA_SERVER_NAMESPACEARRAY];
+    namespaceArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_NAMESPACEARRAY;
     namespaceArray->nodeClass = UA_NODECLASS_VARIABLE;
-    UA_Array_new(&namespaceArray->value.storage.data.dataPtr, 2, &UA_TYPES[UA_STRING]);
-    namespaceArray->value.vt = &UA_TYPES[UA_STRING];
+    UA_Array_new(&namespaceArray->value.storage.data.dataPtr, 2, &UA_TYPES[UA_TYPES_STRING]);
     namespaceArray->value.storage.data.arrayLength = 2;
+    namespaceArray->value.type = &UA_TYPES[UA_TYPES_STRING];
+    namespaceArray->value.typeId.identifier.numeric = UA_TYPES_IDS[UA_TYPES_STRING];
     // Fixme: Insert the external namespaces
     UA_String_copycstring("http://opcfoundation.org/UA/",
                           &((UA_String *)(namespaceArray->value.storage.data.dataPtr))[0]);
     UA_String_copycstring("urn:myServer:myApplication",
                           &((UA_String *)(namespaceArray->value.storage.data.dataPtr))[1]);
-    UA_UInt32 *dimensions = UA_malloc(sizeof(UA_UInt32));
-    if(dimensions) {
-        *dimensions = 2;
-        namespaceArray->arrayDimensions = dimensions;
-        namespaceArray->arrayDimensionsSize = 1;
-    }
-    namespaceArray->dataType = UA_NODEIDS[UA_STRING];
+    /* UA_UInt32 *dimensions = UA_malloc(sizeof(UA_UInt32)); */
+    /* if(dimensions) { */
+    /*     *dimensions = 2; */
+    /*     namespaceArray->arrayDimensions = dimensions; */
+    /*     namespaceArray->arrayDimensionsSize = 1; */
+    /* } */
+    namespaceArray->dataType.identifier.numeric = UA_TYPES_IDS[UA_TYPES_STRING];
     namespaceArray->valueRank = 1;
     namespaceArray->minimumSamplingInterval = 1.0;
     namespaceArray->historizing = UA_FALSE;
     UA_Server_addNode(server, (const UA_Node **)&namespaceArray,
-                      &UA_EXPANDEDNODEIDS[UA_SERVER], &UA_NODEIDS[UA_HASCOMPONENT]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_SERVER,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASCOMPONENT,0));
 
     UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
     status->startTime   = UA_DateTime_now();
@@ -481,22 +508,25 @@ UA_Server * UA_Server_new(void) {
     UA_LocalizedText_copycstring("because", &status->shutdownReason);
     UA_VariableNode *serverstatus = UA_VariableNode_new();
     COPYNAMES(serverstatus, "ServerStatus");
-    serverstatus->nodeId    = UA_NODEIDS[UA_SERVER_SERVERSTATUS];
+    serverstatus->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERSTATUS;
     serverstatus->nodeClass = UA_NODECLASS_VARIABLE;
-    serverstatus->value.vt = &UA_TYPES[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
+    serverstatus->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
+    serverstatus->value.typeId.identifier.numeric = UA_TYPES_IDS[UA_TYPES_SERVERSTATUSDATATYPE];
     serverstatus->value.storage.data.arrayLength = 1;
     serverstatus->value.storage.data.dataPtr = status;
     UA_Server_addNode(server, (const UA_Node **)&serverstatus,
-                      &UA_EXPANDEDNODEIDS[UA_SERVER], &UA_NODEIDS[UA_HASPROPERTY]);
+                      &UA_EXPANDEDNODEID_STATIC(UA_NS0ID_SERVER,0),
+                      &UA_NODEID_STATIC(UA_NS0ID_HASPROPERTY,0));
 
     // todo: make this variable point to a member of the serverstatus
     UA_VariableNode *state = UA_VariableNode_new();
     UA_ServerState *stateEnum = UA_ServerState_new();
     *stateEnum = UA_SERVERSTATE_RUNNING;
     COPYNAMES(state, "State");
-    state->nodeId    = UA_NODEIDS[UA_SERVER_SERVERSTATUS_STATE];
+    state->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERSTATUS_STATE;
     state->nodeClass = UA_NODECLASS_VARIABLE;
-    state->value.vt = &UA_TYPES[UA_SERVERSTATE];
+    state->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
+    state->value.typeId.identifier.numeric = UA_TYPES_IDS[UA_TYPES_SERVERSTATE];
     state->value.storage.data.arrayLength = 1;
     state->value.storage.data.dataPtr = stateEnum; // points into the other object.
     state->value.storageType = UA_VARIANT_DATA;

+ 95 - 36
src/server/ua_server_addressspace.c

@@ -1,45 +1,60 @@
 #include "ua_server.h"
 #include "ua_server_internal.h"
-#include "ua_namespace_0.h"
 
-static const UA_TypeVTable * UA_Node_getTypeVT(const UA_Node *node) {
-    switch(node->nodeClass) {
-    case UA_NODECLASS_OBJECT:
-        return &UA_TYPES[UA_OBJECTNODE];
-    case UA_NODECLASS_VARIABLE:
-        return &UA_TYPES[UA_VARIABLENODE];
-    case UA_NODECLASS_METHOD:
-        return &UA_TYPES[UA_METHODNODE];
-    case UA_NODECLASS_OBJECTTYPE:
-        return &UA_TYPES[UA_OBJECTTYPENODE];
-    case UA_NODECLASS_VARIABLETYPE:
-        return &UA_TYPES[UA_VARIABLETYPENODE];
-    case UA_NODECLASS_REFERENCETYPE:
-        return &UA_TYPES[UA_REFERENCETYPENODE];
-    case UA_NODECLASS_DATATYPE:
-        return &UA_TYPES[UA_DATATYPENODE];
-    case UA_NODECLASS_VIEW:
-        return &UA_TYPES[UA_VIEWNODE];
-    default: break;
-    }
+/* static const UA_TypeVTable * UA_Node_getTypeVT(const UA_Node *node) { */
+/*     switch(node->nodeClass) { */
+/*     case UA_NODECLASS_OBJECT: */
+/*         return &UA_TYPES[UA_OBJECTNODE]; */
+/*     case UA_NODECLASS_VARIABLE: */
+/*         return &UA_TYPES[UA_VARIABLENODE]; */
+/*     case UA_NODECLASS_METHOD: */
+/*         return &UA_TYPES[UA_METHODNODE]; */
+/*     case UA_NODECLASS_OBJECTTYPE: */
+/*         return &UA_TYPES[UA_OBJECTTYPENODE]; */
+/*     case UA_NODECLASS_VARIABLETYPE: */
+/*         return &UA_TYPES[UA_VARIABLETYPENODE]; */
+/*     case UA_NODECLASS_REFERENCETYPE: */
+/*         return &UA_TYPES[UA_REFERENCETYPENODE]; */
+/*     case UA_NODECLASS_DATATYPE: */
+/*         return &UA_TYPES[UA_DATATYPENODE]; */
+/*     case UA_NODECLASS_VIEW: */
+/*         return &UA_TYPES[UA_VIEWNODE]; */
+/*     default: break; */
+/*     } */
 
-    return &UA_TYPES[UA_INVALIDTYPE];
-}
+/*     return &UA_TYPES[UA_INVALIDTYPE]; */
+/* } */
 
-void UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName, void *value,
-                                     const UA_TypeVTable *vt, const UA_ExpandedNodeId *parentNodeId,
-                                     const UA_NodeId *referenceTypeId) {
+UA_StatusCode UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName,
+                                              void *value, const UA_NodeId typeId,
+                                              const UA_ExpandedNodeId *parentNodeId,
+                                              const UA_NodeId *referenceTypeId ) {
+    if(typeId.namespaceIndex != 0)
+        return UA_STATUSCODE_BADINTERNALERROR;
     UA_VariableNode *tmpNode = UA_VariableNode_new();
     UA_QualifiedName_copy(browseName, &tmpNode->browseName);
     UA_String_copy(&browseName->name, &tmpNode->displayName.text);
     /* UA_LocalizedText_copycstring("integer value", &tmpNode->description); */
     tmpNode->nodeClass = UA_NODECLASS_VARIABLE;
     tmpNode->valueRank = -1;
-    tmpNode->value.vt = vt;
+    UA_NodeId_copy(&typeId, &tmpNode->dataType);
+    UA_NodeId_copy(&typeId, &tmpNode->value.typeId);
     tmpNode->value.storage.data.dataPtr = value;
     tmpNode->value.storageType = UA_VARIANT_DATA;
     tmpNode->value.storage.data.arrayLength = 1;
-    UA_Server_addNode(server, (const UA_Node**)&tmpNode, parentNodeId, referenceTypeId);
+    size_t i;
+    for(i = 0;i<UA_TYPES_COUNT;i++) {
+        if(UA_TYPES_IDS[i] == typeId.identifier.numeric)
+            break;
+    }
+    if(i >= UA_TYPES_COUNT) {
+        UA_VariableNode_delete(tmpNode);
+        return UA_STATUSCODE_BADINTERNALERROR;
+    }
+    tmpNode->value.type = &UA_TYPES[i];
+    UA_Server_addNodeWithSession(server, &adminSession, (const UA_Node**)&tmpNode,
+                                 parentNodeId, referenceTypeId);
+    return UA_STATUSCODE_GOOD;
 }
 
 /* Adds a one-way reference to the local nodestore */
@@ -51,9 +66,52 @@ static UA_StatusCode addOneWayReferenceWithSession(UA_Server *server, UA_Session
     if(!node)
         return UA_STATUSCODE_BADINTERNALERROR;
 
-    const UA_TypeVTable *nodeVT = UA_Node_getTypeVT(node);
-    UA_Node *newNode = nodeVT->new();
-    nodeVT->copy(node, newNode);
+    UA_Node *newNode = UA_NULL;
+    void (*deleteNode)(UA_Node*) = UA_NULL;
+    switch(node->nodeClass) {
+    case UA_NODECLASS_OBJECT:
+        newNode = (UA_Node*)UA_ObjectNode_new();
+        UA_ObjectNode_copy((const UA_ObjectNode*)node, (UA_ObjectNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_ObjectNode_delete;
+        break;
+    case UA_NODECLASS_VARIABLE:
+        newNode = (UA_Node*)UA_VariableNode_new();
+        UA_VariableNode_copy((const UA_VariableNode*)node, (UA_VariableNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_VariableNode_delete;
+        break;
+    case UA_NODECLASS_METHOD:
+        newNode = (UA_Node*)UA_MethodNode_new();
+        UA_MethodNode_copy((const UA_MethodNode*)node, (UA_MethodNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_MethodNode_delete;
+        break;
+    case UA_NODECLASS_OBJECTTYPE:
+        newNode = (UA_Node*)UA_ObjectTypeNode_new();
+        UA_ObjectTypeNode_copy((const UA_ObjectTypeNode*)node, (UA_ObjectTypeNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_ObjectTypeNode_delete;
+        break;
+    case UA_NODECLASS_VARIABLETYPE:
+        newNode = (UA_Node*)UA_VariableTypeNode_new();
+        UA_VariableTypeNode_copy((const UA_VariableTypeNode*)node, (UA_VariableTypeNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_VariableTypeNode_delete;
+        break;
+    case UA_NODECLASS_REFERENCETYPE:
+        newNode = (UA_Node*)UA_ReferenceTypeNode_new();
+        UA_ReferenceTypeNode_copy((const UA_ReferenceTypeNode*)node, (UA_ReferenceTypeNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_ReferenceTypeNode_delete;
+        break;
+    case UA_NODECLASS_DATATYPE:
+        newNode = (UA_Node*)UA_DataTypeNode_new();
+        UA_DataTypeNode_copy((const UA_DataTypeNode*)node, (UA_DataTypeNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_DataTypeNode_delete;
+        break;
+    case UA_NODECLASS_VIEW:
+        newNode = (UA_Node*)UA_ViewNode_new();
+        UA_ViewNode_copy((const UA_ViewNode*)node, (UA_ViewNode*)newNode);
+        deleteNode = (void (*)(UA_Node*))UA_ViewNode_delete;
+        break;
+    default:
+        UA_assert(UA_FALSE);
+    }
 
     UA_Int32 count = node->referencesSize;
     if(count < 0)
@@ -61,7 +119,7 @@ static UA_StatusCode addOneWayReferenceWithSession(UA_Server *server, UA_Session
     UA_ReferenceNode *old_refs = newNode->references;
     UA_ReferenceNode *new_refs = UA_malloc(sizeof(UA_ReferenceNode)*(count+1));
     if(!new_refs) {
-        nodeVT->delete(newNode);
+        deleteNode(newNode);
         UA_NodeStore_release(node);
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
@@ -73,10 +131,10 @@ static UA_StatusCode addOneWayReferenceWithSession(UA_Server *server, UA_Session
     new_refs[count].isInverse = !item->isForward;
     retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[count].targetId);
     if(retval != UA_STATUSCODE_GOOD) {
-        UA_Array_delete(new_refs, ++count, &UA_TYPES[UA_REFERENCENODE]);
+        UA_Array_delete(new_refs, ++count, &UA_TYPES[UA_TYPES_REFERENCENODE]);
         newNode->references = UA_NULL;
         newNode->referencesSize = 0;
-        nodeVT->delete(newNode);
+        deleteNode(newNode);
         UA_NodeStore_release(node);
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
@@ -92,7 +150,7 @@ static UA_StatusCode addOneWayReferenceWithSession(UA_Server *server, UA_Session
     
     // error presumably because the node was replaced and an old version was updated
     // just try again
-    nodeVT->delete(newNode);
+    deleteNode(newNode);
     return addOneWayReferenceWithSession(server, session, item);
 }
 
@@ -144,7 +202,8 @@ UA_AddNodesResult UA_Server_addNode(UA_Server *server, const UA_Node **node,
 }
 
 UA_AddNodesResult UA_Server_addNodeWithSession(UA_Server *server, UA_Session *session, const UA_Node **node,
-                                               const UA_ExpandedNodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
+                                               const UA_ExpandedNodeId *parentNodeId,
+                                               const UA_NodeId *referenceTypeId) {
     UA_AddNodesResult result;
     UA_AddNodesResult_init(&result);
 

+ 42 - 38
src/server/ua_server_binary.c

@@ -1,11 +1,14 @@
 #include <stdio.h>
 
 #include "ua_server_internal.h"
+#include "ua_types_encoding_binary.h"
+#include "ua_transport_generated.h"
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 #include "ua_securechannel_manager.h"
 #include "ua_session_manager.h"
 #include "ua_util.h"
+#include "ua_nodeids.h"
 
 /** Max size of messages that are allocated on the stack */
 #define MAX_STACK_MESSAGE 65536
@@ -41,8 +44,7 @@ static void processHEL(UA_Connection *connection, const UA_ByteString *msg, UA_U
     ackMessage.maxChunkCount     = connection->localConf.maxChunkCount;
 
     UA_TcpMessageHeader ackHeader;
-    ackHeader.messageType = UA_MESSAGETYPE_ACK;
-    ackHeader.isFinal     = 'F';
+    ackHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_ACKF;
     ackHeader.messageSize = UA_TcpAcknowledgeMessage_calcSizeBinary(&ackMessage) +
                             UA_TcpMessageHeader_calcSizeBinary(&ackHeader);
 
@@ -90,12 +92,12 @@ static void processOPN(UA_Connection *connection, UA_Server *server, const UA_By
 
     /* Response */
     UA_SecureConversationMessageHeader respHeader;
-    respHeader.messageHeader.messageType = UA_MESSAGETYPE_OPN;
-    respHeader.messageHeader.isFinal     = 'F';
+    respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
     respHeader.messageHeader.messageSize = 0;
     respHeader.secureChannelId = p.securityToken.channelId;
 
-    UA_NodeId responseType = UA_NODEIDS[UA_OPENSECURECHANNELRESPONSE];
+    UA_NodeId responseType;
+    UA_NODEID_ASSIGN(responseType, UA_NS0ID_OPENSECURECHANNELRESPONSE, 0);
     responseType.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
 
     respHeader.messageHeader.messageSize =
@@ -128,12 +130,6 @@ static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r
     r->timestamp       = UA_DateTime_now();
 }
 
-#define CHECK_PROCESS(CODE, CLEANUP)         \
-    do { if(CODE != UA_STATUSCODE_GOOD) {    \
-            CLEANUP;                         \
-            return;                          \
-        } } while(0)
-
 // if the message is small enough, we allocate it on the stack and save a malloc
 #define ALLOC_MESSAGE(MESSAGE, SIZE) do {                               \
         UA_UInt32 messageSize = SIZE;                                   \
@@ -148,7 +144,8 @@ static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r
 #define INVOKE_SERVICE(TYPE) do {                                       \
         UA_##TYPE##Request p;                                           \
         UA_##TYPE##Response r;                                          \
-        CHECK_PROCESS(UA_##TYPE##Request_decodeBinary(msg, pos, &p),;); \
+        if(UA_##TYPE##Request_decodeBinary(msg, pos, &p))               \
+            return;                                                     \
         UA_##TYPE##Response_init(&r);                                   \
         init_response_header(&p.requestHeader, &r.responseHeader);      \
         Service_##TYPE(server, clientSession, &p, &r);                  \
@@ -181,7 +178,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     UA_UInt32 tokenId;
     UA_UInt32_decodeBinary(msg, pos, &tokenId);
     UA_SequenceHeader sequenceHeader;
-    CHECK_PROCESS(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader),; );
+    if(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader))
+        return;
 
     clientChannel->sequenceNumber = sequenceHeader.sequenceNumber;
     clientChannel->requestId = sequenceHeader.requestId;
@@ -191,7 +189,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
 
     // 3) Read the nodeid of the request
     UA_NodeId requestType;
-    CHECK_PROCESS(UA_NodeId_decodeBinary(msg, pos, &requestType),; );
+    if(UA_NodeId_decodeBinary(msg, pos, &requestType))
+        return;
     if(requestType.identifierType != UA_NODEIDTYPE_NUMERIC) {
         // if the nodeidtype is numeric, we do not have to free anything
         UA_NodeId_deleteMembers(&requestType);
@@ -228,7 +227,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     				requestType.namespaceIndex, requestType.identifier.numeric);
     		UA_RequestHeader  p;
     		UA_ResponseHeader r;
-    		CHECK_PROCESS(UA_RequestHeader_decodeBinary(msg, pos, &p),; );
+    		if(UA_RequestHeader_decodeBinary(msg, pos, &p))
+                return;
     		UA_ResponseHeader_init(&r);
     		init_response_header(&p, &r);
     		r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
@@ -236,7 +236,7 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		UA_ResponseHeader_encodeBinary(&r, message, &sendOffset);
     		UA_RequestHeader_deleteMembers(&p);
     		UA_ResponseHeader_deleteMembers(&r);
-    		responseType = UA_NODEIDS[UA_RESPONSEHEADER].identifier.numeric + UA_ENCODINGOFFSET_BINARY; }
+    		responseType = UA_NS0ID_RESPONSEHEADER + UA_ENCODINGOFFSET_BINARY; }
             break;
     	}
     } else {
@@ -244,10 +244,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     	//non-stateless service calls
     	//subtract UA_ENCODINGOFFSET_BINARY for binary encoding
     	switch(requestType.identifier.numeric - UA_ENCODINGOFFSET_BINARY) {
-    	case UA_GETENDPOINTSREQUEST_NS0: {
+    	case UA_NS0ID_GETENDPOINTSREQUEST: {
     		UA_GetEndpointsRequest  p;
     		UA_GetEndpointsResponse r;
-    		CHECK_PROCESS(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p),; );
+    		if(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p))
+                return;
     		UA_GetEndpointsResponse_init(&r);
     		init_response_header(&p.requestHeader, &r.responseHeader);
     		Service_GetEndpoints(server, &p, &r);
@@ -259,10 +260,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		break;
     	}
 
-    	case UA_CREATESESSIONREQUEST_NS0: {
+    	case UA_NS0ID_CREATESESSIONREQUEST: {
     		UA_CreateSessionRequest  p;
     		UA_CreateSessionResponse r;
-    		CHECK_PROCESS(UA_CreateSessionRequest_decodeBinary(msg, pos, &p),; );
+            if(UA_CreateSessionRequest_decodeBinary(msg, pos, &p))
+                return;
     		UA_CreateSessionResponse_init(&r);
     		init_response_header(&p.requestHeader, &r.responseHeader);
     		Service_CreateSession(server, clientChannel,  &p, &r);
@@ -274,10 +276,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		break;
     	}
 
-    	case UA_ACTIVATESESSIONREQUEST_NS0: {
+    	case UA_NS0ID_ACTIVATESESSIONREQUEST: {
     		UA_ActivateSessionRequest  p;
     		UA_ActivateSessionResponse r;
-    		CHECK_PROCESS(UA_ActivateSessionRequest_decodeBinary(msg, pos, &p),; );
+    		if(UA_ActivateSessionRequest_decodeBinary(msg, pos, &p))
+                return;
     		UA_ActivateSessionResponse_init(&r);
     		init_response_header(&p.requestHeader, &r.responseHeader);
     		Service_ActivateSession(server, clientChannel,  &p, &r);
@@ -289,10 +292,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		break;
     	}
 
-    	case UA_CLOSESESSIONREQUEST_NS0: {
+    	case UA_NS0ID_CLOSESESSIONREQUEST: {
     		UA_CloseSessionRequest  p;
     		UA_CloseSessionResponse r;
-    		CHECK_PROCESS(UA_CloseSessionRequest_decodeBinary(msg, pos, &p),; );
+    		if(UA_CloseSessionRequest_decodeBinary(msg, pos, &p))
+                return;
     		UA_CloseSessionResponse_init(&r);
     		init_response_header(&p.requestHeader, &r.responseHeader);
     		Service_CloseSession(server, &p, &r);
@@ -304,23 +308,23 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		break;
     	}
 
-    	case UA_READREQUEST_NS0:
+    	case UA_NS0ID_READREQUEST:
     		INVOKE_SERVICE(Read);
     		break;
 
-    	case UA_WRITEREQUEST_NS0:
+    	case UA_NS0ID_WRITEREQUEST:
     		INVOKE_SERVICE(Write);
     		break;
 
-    	case UA_BROWSEREQUEST_NS0:
+    	case UA_NS0ID_BROWSEREQUEST:
     		INVOKE_SERVICE(Browse);
     		break;
 
-    	case UA_ADDREFERENCESREQUEST_NS0:
+    	case UA_NS0ID_ADDREFERENCESREQUEST:
     		INVOKE_SERVICE(AddReferences);
     		break;
 
-    	case UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0:
+    	case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST:
     		INVOKE_SERVICE(TranslateBrowsePathsToNodeIds);
     		break;
 
@@ -329,7 +333,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     				requestType.namespaceIndex, requestType.identifier.numeric);
     		UA_RequestHeader  p;
     		UA_ResponseHeader r;
-    		CHECK_PROCESS(UA_RequestHeader_decodeBinary(msg, pos, &p),; );
+    		if(UA_RequestHeader_decodeBinary(msg, pos, &p))
+                return;
     		UA_ResponseHeader_init(&r);
     		init_response_header(&p, &r);
     		r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
@@ -337,7 +342,7 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     		UA_ResponseHeader_encodeBinary(&r, message, &sendOffset);
     		UA_RequestHeader_deleteMembers(&p);
     		UA_ResponseHeader_deleteMembers(&r);
-    		responseType = UA_NODEIDS[UA_RESPONSEHEADER].identifier.numeric + UA_ENCODINGOFFSET_BINARY;
+    		responseType = UA_NS0ID_RESPONSEHEADER + UA_ENCODINGOFFSET_BINARY;
     	}
     	break;
     	}
@@ -347,8 +352,7 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
 
     // 5) Build the header
     UA_SecureConversationMessageHeader respHeader;
-    respHeader.messageHeader.messageType = UA_MESSAGETYPE_MSG;
-    respHeader.messageHeader.isFinal     = 'F';
+    respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
     respHeader.messageHeader.messageSize = 0;
     respHeader.secureChannelId = clientChannel->securityToken.channelId;
 
@@ -411,16 +415,16 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
         }
 
         UA_UInt32 targetpos = pos - 8 + tcpMessageHeader.messageSize;
-        switch(tcpMessageHeader.messageType) {
-        case UA_MESSAGETYPE_HEL:
+        switch(tcpMessageHeader.messageTypeAndFinal & 0xffffff) {
+        case UA_MESSAGETYPEANDFINAL_HELF & 0xffffff:
             processHEL(connection, msg, &pos);
             break;
 
-        case UA_MESSAGETYPE_OPN:
+        case UA_MESSAGETYPEANDFINAL_OPNF & 0xffffff:
             processOPN(connection, server, msg, &pos);
             break;
 
-        case UA_MESSAGETYPE_MSG:
+        case UA_MESSAGETYPEANDFINAL_MSGF & 0xffffff:
 #ifndef EXTENSION_STATELESS
             if(connection->state == UA_CONNECTION_ESTABLISHED && connection->channel != UA_NULL)
                 processMSG(connection, server, msg, &pos);
@@ -431,7 +435,7 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
 #endif
             break;
 
-        case UA_MESSAGETYPE_CLO:
+        case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff:
             processCLO(connection, server, msg, &pos);
             connection->close(connection);
             return;

+ 3 - 0
src/server/ua_server_internal.h

@@ -67,6 +67,9 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
 UA_AddNodesResult UA_Server_addNodeWithSession(UA_Server *server, UA_Session *session, const UA_Node **node,
                                                const UA_ExpandedNodeId *parentNodeId, const UA_NodeId *referenceTypeId);
 
+UA_AddNodesResult UA_Server_addNode(UA_Server *server, const UA_Node **node,
+                                    const UA_ExpandedNodeId *parentNodeId, const UA_NodeId *referenceTypeId);
+
 UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item);
 
 void UA_Server_deleteTimedWork(UA_Server *server);

+ 71 - 71
src/server/ua_services_attribute.c

@@ -3,13 +3,12 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 #include "ua_nodestore.h"
-#include "ua_namespace_0.h"
 #include "ua_util.h"
 
 #define CHECK_NODECLASS(CLASS)                                  \
     if(!(node->nodeClass & (CLASS))) {                          \
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE; \
-        v->status       = UA_STATUSCODE_BADNOTREADABLE;         \
+        v->hasStatus = UA_TRUE;                                 \
+        v->status = UA_STATUSCODE_BADNOTREADABLE;               \
         break;                                                  \
     }
 
@@ -17,8 +16,8 @@
 static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue *v) {
     UA_Node const *node = UA_NodeStore_get(server->nodestore, &(id->nodeId));
     if(!node) {
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-        v->status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
+        v->hasStatus = UA_TRUE;
+        v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
         return;
     }
 
@@ -26,157 +25,157 @@ static void readValue(UA_Server *server, const UA_ReadValueId *id, UA_DataValue
 
     switch(id->attributeId) {
     case UA_ATTRIBUTEID_NODEID:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_NODEID], &node->nodeId);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->nodeId, UA_TYPES_NODEID);
         break;
 
     case UA_ATTRIBUTEID_NODECLASS:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_INT32], &node->nodeClass);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->nodeClass, UA_TYPES_INT32);
         break;
 
     case UA_ATTRIBUTEID_BROWSENAME:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_QUALIFIEDNAME], &node->browseName);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->browseName, UA_TYPES_QUALIFIEDNAME);
         break;
 
     case UA_ATTRIBUTEID_DISPLAYNAME:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_LOCALIZEDTEXT], &node->displayName);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->displayName, UA_TYPES_LOCALIZEDTEXT);
         break;
 
     case UA_ATTRIBUTEID_DESCRIPTION:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_LOCALIZEDTEXT], &node->description);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->description, UA_TYPES_LOCALIZEDTEXT);
         break;
 
     case UA_ATTRIBUTEID_WRITEMASK:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_UINT32], &node->writeMask);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->writeMask, UA_TYPES_UINT32);
         break;
 
     case UA_ATTRIBUTEID_USERWRITEMASK:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_UINT32], &node->userWriteMask);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &node->userWriteMask,
+                                          UA_TYPES_UINT32);
         break;
 
     case UA_ATTRIBUTEID_ISABSTRACT:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE | UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE |
                         UA_NODECLASS_DATATYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_ReferenceTypeNode *)node)->isAbstract);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->isAbstract,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     case UA_ATTRIBUTEID_SYMMETRIC:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_ReferenceTypeNode *)node)->symmetric);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->symmetric,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     case UA_ATTRIBUTEID_INVERSENAME:
         CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_LOCALIZEDTEXT],
-                                          &((const UA_ReferenceTypeNode *)node)->inverseName);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_ReferenceTypeNode *)node)->inverseName,
+                                          UA_TYPES_LOCALIZEDTEXT);
         break;
 
     case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
         CHECK_NODECLASS(UA_NODECLASS_VIEW);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_ViewNode *)node)->containsNoLoops);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_ViewNode *)node)->containsNoLoops,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     case UA_ATTRIBUTEID_EVENTNOTIFIER:
         CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BYTE],
-                                          &((const UA_ViewNode *)node)->eventNotifier);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_ViewNode *)node)->eventNotifier,
+                                          UA_TYPES_BYTE);
         break;
 
     case UA_ATTRIBUTEID_VALUE:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        v->hasVariant = UA_TRUE;
         retval |= UA_Variant_copy(&((const UA_VariableNode *)node)->value, &v->value); // todo: zero-copy
         break;
 
     case UA_ATTRIBUTEID_DATATYPE:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_NODEID],
-                                          &((const UA_VariableTypeNode *)node)->dataType);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableTypeNode *)node)->dataType,
+                                          UA_TYPES_NODEID);
         break;
 
     case UA_ATTRIBUTEID_VALUERANK:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_INT32],
-                                          &((const UA_VariableTypeNode *)node)->valueRank);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableTypeNode *)node)->valueRank,
+                                          UA_TYPES_INT32);
         break;
 
     case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        UA_Variant_copySetArray(&v->value, &UA_TYPES[UA_UINT32],
-                                ((const UA_VariableTypeNode *)node)->arrayDimensionsSize,
-                                &((const UA_VariableTypeNode *)node)->arrayDimensions);
+        v->hasVariant = UA_TRUE;
+        UA_Variant_copySetArray(&v->value, &((const UA_VariableTypeNode *)node)->arrayDimensions,
+                                ((const UA_VariableTypeNode *)node)->arrayDimensionsSize, UA_TYPES_UINT32);
         break;
 
     case UA_ATTRIBUTEID_ACCESSLEVEL:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BYTE],
-                                          &((const UA_VariableNode *)node)->accessLevel);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableNode *)node)->accessLevel,
+                                          UA_TYPES_BYTE);
         break;
 
     case UA_ATTRIBUTEID_USERACCESSLEVEL:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BYTE],
-                                          &((const UA_VariableNode *)node)->userAccessLevel);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableNode *)node)->userAccessLevel,
+                                          UA_TYPES_BYTE);
         break;
 
     case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_DOUBLE],
-                                          &((const UA_VariableNode *)node)->minimumSamplingInterval);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableNode *)node)->minimumSamplingInterval,
+                                          UA_TYPES_DOUBLE);
         break;
 
     case UA_ATTRIBUTEID_HISTORIZING:
         CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_VariableNode *)node)->historizing);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_VariableNode *)node)->historizing,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     case UA_ATTRIBUTEID_EXECUTABLE:
         CHECK_NODECLASS(UA_NODECLASS_METHOD);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_MethodNode *)node)->executable);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_MethodNode *)node)->executable,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     case UA_ATTRIBUTEID_USEREXECUTABLE:
         CHECK_NODECLASS(UA_NODECLASS_METHOD);
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-        retval |= UA_Variant_copySetValue(&v->value, &UA_TYPES[UA_BOOLEAN],
-                                          &((const UA_MethodNode *)node)->userExecutable);
+        v->hasVariant = UA_TRUE;
+        retval |= UA_Variant_copySetValue(&v->value, &((const UA_MethodNode *)node)->userExecutable,
+                                          UA_TYPES_BOOLEAN);
         break;
 
     default:
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-        v->status       = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+        v->hasStatus = UA_TRUE;
+        v->status = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
         break;
     }
 
     UA_NodeStore_release(node);
 
     if(retval != UA_STATUSCODE_GOOD) {
-        v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-        v->status       = UA_STATUSCODE_BADNOTREADABLE;
+        v->hasStatus = UA_TRUE;
+        v->status = UA_STATUSCODE_BADNOTREADABLE;
     }
 }
 
@@ -188,7 +187,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
     }
 
     UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToReadSize,
-                                        &UA_TYPES[UA_DATAVALUE]);
+                                        &UA_TYPES[UA_TYPES_DATAVALUE]);
     if(retval != UA_STATUSCODE_GOOD) {
         response->responseHeader.serviceResult = retval;
         return;
@@ -227,7 +226,7 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 		UA_ExtensionObject additionalHeader;
 		UA_ExtensionObject_init(&additionalHeader);
 		additionalHeader.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
-		additionalHeader.typeId = UA_NODEIDS[UA_VARIANT];
+		additionalHeader.typeId.identifier.numeric = UA_TYPES_IDS[UA_TYPES_VARIANT];
 
 		UA_Variant variant;
 		UA_Variant_init(&variant);
@@ -377,7 +376,7 @@ static UA_StatusCode writeValue(UA_Server *server, UA_WriteValue *aWriteValue) {
                 break;
             }
 
-            if(aWriteValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT)
+            if(aWriteValue->value.hasVariant)
                 retval |= UA_Variant_copy(&aWriteValue->value.value, &((UA_VariableNode *)newNode)->value); // todo: zero-copy
             break;
 
@@ -488,7 +487,8 @@ void Service_Write(UA_Server *server, UA_Session *session,
                    const UA_WriteRequest *request, UA_WriteResponse *response) {
     UA_assert(server != UA_NULL && session != UA_NULL && request != UA_NULL && response != UA_NULL);
 
-    UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToWriteSize, &UA_TYPES[UA_STATUSCODE]);
+    UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToWriteSize,
+                                        &UA_TYPES[UA_TYPES_STATUSCODE]);
     if(retval) {
         response->responseHeader.serviceResult = retval;
         return;

+ 0 - 1
src/server/ua_services_discovery.c

@@ -1,6 +1,5 @@
 #include "ua_server_internal.h"
 #include "ua_services.h"
-#include "ua_namespace_0.h"
 #include "ua_util.h"
 
 void Service_GetEndpoints(UA_Server                    *server,

+ 30 - 26
src/server/ua_services_nodemanagement.c

@@ -1,6 +1,5 @@
 #include "ua_server_internal.h"
 #include "ua_services.h"
-#include "ua_namespace_0.h"
 #include "ua_statuscodes.h"
 #include "ua_nodestore.h"
 #include "ua_session.h"
@@ -21,10 +20,9 @@
         vnode->userWriteMask = attr.userWriteMask;                      \
     } while(0)
 
-static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node **new_node,
-                                       const UA_TypeVTable **vt) {
+static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     if(attributes->typeId.identifier.numeric !=
-       UA_NODEIDS[UA_VARIABLEATTRIBUTES].identifier.numeric + UA_ENCODINGOFFSET_BINARY)
+       UA_TYPES_IDS[UA_TYPES_VARIABLEATTRIBUTES] + UA_ENCODINGOFFSET_BINARY)
         return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
 
     UA_VariableAttributes attr;
@@ -78,14 +76,12 @@ static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node *
     UA_VariableAttributes_deleteMembers(&attr);
 
     *new_node = (UA_Node*)vnode;
-    *vt = &UA_TYPES[UA_VARIABLENODE];
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes,
-                                     UA_Node **new_node, const UA_TypeVTable **vt) {
+static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     if(attributes->typeId.identifier.numeric !=
-       UA_NODEIDS[UA_OBJECTATTRIBUTES].identifier.numeric + UA_ENCODINGOFFSET_BINARY)  // VariableAttributes_Encoding_DefaultBinary
+       UA_TYPES_IDS[UA_TYPES_OBJECTATTRIBUTES] + UA_ENCODINGOFFSET_BINARY)  // VariableAttributes_Encoding_DefaultBinary
         return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
     UA_ObjectAttributes attr;
     UA_UInt32 pos = 0;
@@ -104,12 +100,10 @@ static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes,
         vnode->eventNotifier = attr.eventNotifier;
     UA_ObjectAttributes_deleteMembers(&attr);
     *new_node = (UA_Node*) vnode;
-    *vt = &UA_TYPES[UA_OBJECTNODE];
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode parseReferenceTypeNode(UA_ExtensionObject *attributes,
-                                            UA_Node **new_node, const UA_TypeVTable **vt) {
+static UA_StatusCode parseReferenceTypeNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     UA_ReferenceTypeAttributes attr;
     UA_UInt32 pos = 0;
     // todo return more informative error codes from decodeBinary
@@ -136,12 +130,10 @@ static UA_StatusCode parseReferenceTypeNode(UA_ExtensionObject *attributes,
     }
     UA_ReferenceTypeAttributes_deleteMembers(&attr);
     *new_node = (UA_Node*) vnode;
-    *vt = &UA_TYPES[UA_REFERENCETYPENODE];
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode parseObjectTypeNode(UA_ExtensionObject *attributes,
-                                         UA_Node **new_node, const UA_TypeVTable **vt) {
+static UA_StatusCode parseObjectTypeNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     UA_ObjectTypeAttributes attr;
     UA_UInt32 pos = 0;
     // todo return more informative error codes from decodeBinary
@@ -160,12 +152,10 @@ static UA_StatusCode parseObjectTypeNode(UA_ExtensionObject *attributes,
     }
     UA_ObjectTypeAttributes_deleteMembers(&attr);
     *new_node = (UA_Node*) vnode;
-    *vt = &UA_TYPES[UA_OBJECTTYPENODE];
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode parseViewNode(UA_ExtensionObject *attributes, UA_Node **new_node,
-                                   const UA_TypeVTable **vt) {
+static UA_StatusCode parseViewNode(UA_ExtensionObject *attributes, UA_Node **new_node) {
     UA_ViewAttributes attr;
     UA_UInt32 pos = 0;
     // todo return more informative error codes from decodeBinary
@@ -184,7 +174,6 @@ static UA_StatusCode parseViewNode(UA_ExtensionObject *attributes, UA_Node **new
         vnode->eventNotifier = attr.eventNotifier;
     UA_ViewAttributes_deleteMembers(&attr);
     *new_node = (UA_Node*) vnode;
-    *vt = &UA_TYPES[UA_VIEWNODE];
     return UA_STATUSCODE_GOOD;
 }
 
@@ -198,20 +187,19 @@ static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_Add
 
     // parse the node
     UA_Node *node = UA_NULL;
-    const UA_TypeVTable *nodeVT = UA_NULL;
 
     switch (item->nodeClass) {
     case UA_NODECLASS_OBJECT:
-        result->statusCode = parseObjectNode(&item->nodeAttributes, &node, &nodeVT);
+        result->statusCode = parseObjectNode(&item->nodeAttributes, &node);
         break;
     case UA_NODECLASS_OBJECTTYPE:
-        result->statusCode = parseObjectTypeNode(&item->nodeAttributes, &node, &nodeVT);
+        result->statusCode = parseObjectTypeNode(&item->nodeAttributes, &node);
         break;
     case UA_NODECLASS_REFERENCETYPE:
-        result->statusCode = parseReferenceTypeNode(&item->nodeAttributes, &node, &nodeVT);
+        result->statusCode = parseReferenceTypeNode(&item->nodeAttributes, &node);
         break;
     case UA_NODECLASS_VARIABLE:
-        result->statusCode = parseVariableNode(&item->nodeAttributes, &node, &nodeVT);
+        result->statusCode = parseVariableNode(&item->nodeAttributes, &node);
         break;
     default:
         result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
@@ -224,8 +212,24 @@ static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_Add
     const UA_Node *constNode = node; // compilers complain if we cast directly
     *result = UA_Server_addNodeWithSession(server, session, &constNode, &item->parentNodeId,
                                            &item->referenceTypeId);
-    if(result->statusCode != UA_STATUSCODE_GOOD)
-        nodeVT->delete(node);
+    if(result->statusCode != UA_STATUSCODE_GOOD) {
+        switch (node->nodeClass) {
+        case UA_NODECLASS_OBJECT:
+            UA_ObjectNode_delete((UA_ObjectNode*)node);
+            break;
+        case UA_NODECLASS_OBJECTTYPE:
+            UA_ObjectTypeNode_delete((UA_ObjectTypeNode*)node);
+            break;
+        case UA_NODECLASS_REFERENCETYPE:
+            UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode*)node);
+            break;
+        case UA_NODECLASS_VARIABLE:
+            UA_VariableNode_delete((UA_VariableNode*)node);
+            break;
+        default:
+            UA_assert(UA_FALSE);
+        }
+    }
 }
 
 void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
@@ -236,7 +240,7 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
     }
 
     UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToAddSize,
-                                        &UA_TYPES[UA_ADDNODESRESULT]);
+                                        &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
     if(retval) {
         response->responseHeader.serviceResult = retval;
         return;

+ 8 - 7
src/server/ua_services_view.c

@@ -2,7 +2,6 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 #include "ua_nodestore.h"
-#include "ua_namespace_0.h"
 #include "ua_util.h"
 
 /* Releases the current node, even if it was supplied as an argument. */
@@ -133,7 +132,7 @@ static UA_StatusCode findRelevantReferenceTypes(UA_NodeStore *ns, const UA_NodeI
     } while(++currentIndex <= currentLastIndex && retval == UA_STATUSCODE_GOOD);
 
     if(retval)
-        UA_Array_delete(typeArray, currentLastIndex, &UA_TYPES[UA_NODEID]);
+        UA_Array_delete(typeArray, currentLastIndex, &UA_TYPES[UA_TYPES_NODEID]);
     else {
         *referenceTypes = typeArray;
         *referenceTypesSize = currentLastIndex + 1;
@@ -168,7 +167,7 @@ static void getBrowseResult(UA_NodeStore *ns, const UA_BrowseDescription *browse
     if(!parentNode) {
         browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
         if(!returnAll)
-            UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesSize, &UA_TYPES[UA_NODEID]);
+            UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesSize, &UA_TYPES[UA_TYPES_NODEID]);
         return;
     }
 
@@ -203,7 +202,8 @@ static void getBrowseResult(UA_NodeStore *ns, const UA_BrowseDescription *browse
             if(fillReferenceDescription(ns, currentNode, &parentNode->references[i],
                                         browseDescription->resultMask,
                                         &browseResult->references[currentRefs]) != UA_STATUSCODE_GOOD) {
-                UA_Array_delete(browseResult->references, currentRefs, &UA_TYPES[UA_REFERENCEDESCRIPTION]);
+                UA_Array_delete(browseResult->references, currentRefs,
+                                &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
                 currentRefs = 0;
                 browseResult->references = UA_NULL;
                 browseResult->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
@@ -221,7 +221,7 @@ static void getBrowseResult(UA_NodeStore *ns, const UA_BrowseDescription *browse
 
     UA_NodeStore_release(parentNode);
     if(!returnAll)
-        UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesSize, &UA_TYPES[UA_NODEID]);
+        UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesSize, &UA_TYPES[UA_TYPES_NODEID]);
 }
 
 void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseRequest *request,
@@ -232,7 +232,7 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
     }
 
     UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToBrowseSize,
-                                        &UA_TYPES[UA_BROWSERESULT]);
+                                        &UA_TYPES[UA_TYPES_BROWSERESULT]);
     if(retval) {
         response->responseHeader.serviceResult = retval;
         return;
@@ -279,7 +279,8 @@ void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *sessio
         return;
     }
 
-    UA_StatusCode retval = UA_Array_new((void**)&response->results, request->browsePathsSize, &UA_TYPES[UA_BROWSEPATHRESULT]);
+    UA_StatusCode retval = UA_Array_new((void**)&response->results, request->browsePathsSize,
+                                        &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
     if(retval) {
         response->responseHeader.serviceResult = retval;
         return;

+ 5 - 0
src/ua_securechannel.c

@@ -6,6 +6,11 @@
 #include <urcu/uatomic.h>
 #endif
 
+// max message size is 64k
+const UA_ConnectionConfig UA_ConnectionConfig_standard =
+    {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize  = 65536,
+     .maxMessageSize = 65536, .maxChunkCount   = 1};
+
 void UA_SecureChannel_init(UA_SecureChannel *channel) {
     UA_MessageSecurityMode_init(&channel->securityMode);
     UA_ChannelSecurityToken_init(&channel->securityToken);

+ 10 - 10
src/ua_types_encoding_binary.c

@@ -650,9 +650,6 @@ UA_StatusCode UA_ExtensionObject_decodeBinary(UA_ByteString const *src, UA_UInt3
         break;
 
     case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING:
-    	//retval |= UA_TYPES[UA_ns0ToVTableIndex(&dst->typeId)].encodings[UA_ENCODING_BINARY].decode(src, offset, &dst->body);
-    	//break;
-
     case UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML:
         retval |= UA_ByteString_decodeBinary(src, offset, &dst->body);
         break;
@@ -1172,9 +1169,10 @@ UA_StatusCode UA_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, void
 
         if(member->isArray) {
             ptr += (member->padding >> 3);
-            UA_Int32 noElements = *((UA_Int32*)ptr);
+            UA_Int32 *noElements = (UA_Int32*)ptr;
+            UA_Int32_decodeBinary(src, offset, noElements);
             ptr += sizeof(UA_Int32) + (member->padding & 0x07);
-            retval = UA_Array_decodeBinary(src, offset, noElements, (void**)ptr, memberType);
+            retval = UA_Array_decodeBinary(src, offset, *noElements, (void**)ptr, memberType);
             ptr += sizeof(void*);
             continue;
         }
@@ -1260,7 +1258,7 @@ UA_StatusCode UA_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, void
 
 UA_UInt32 UA_Array_calcSizeBinary(const void *p, UA_Int32 noElements, const UA_DataType *dataType) {
     if(noElements <= 0)
-        return 0;
+        return 4;
     UA_UInt32 size = 4; // the array size encoding
     if(dataType->fixedSize) {
         size += noElements * UA_calcSizeBinary(p, dataType);
@@ -1276,10 +1274,11 @@ UA_UInt32 UA_Array_calcSizeBinary(const void *p, UA_Int32 noElements, const UA_D
 
 UA_StatusCode UA_Array_encodeBinary(const void *src, UA_Int32 noElements, const UA_DataType *dataType,
                                     UA_ByteString *dst, UA_UInt32 *offset) {
-    if(noElements <= 0)
-        return 0;
-    const UA_Byte *ptr = (const UA_Byte*)src;
+    if(noElements <= -1)
+        noElements = -1;
+    UA_Int32_encodeBinary(&noElements, dst, offset);
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    const UA_Byte *ptr = (const UA_Byte*)src;
     for(int i=0;i<noElements && retval == UA_STATUSCODE_GOOD;i++) {
         retval = UA_encodeBinary(ptr, dataType, dst, offset);
         ptr += dataType->memSize;
@@ -1297,7 +1296,8 @@ UA_StatusCode UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset,
     if(dataType->memSize * noElements < 0 || dataType->memSize * noElements > MAX_ARRAY_SIZE )
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
-    if(*offset + (dataType->memSize * noElements) > (UA_UInt32)src->length)
+    // filter out arrays that can obviously not be parsed
+    if(*offset + ((dataType->memSize * noElements)/8) > (UA_UInt32)src->length)
         return UA_STATUSCODE_BADDECODINGERROR;
 
     *dst = UA_malloc(dataType->memSize * noElements);

+ 7 - 8
tools/generate_datatypes.py

@@ -40,7 +40,6 @@ class TypeDescription(object):
         self.namespaceid = namespaceid
 
 def parseTypeDescriptions(filename, namespaceid):
-    print(filename)
     definitions = {}
     f = open(filename[0])
     input_str = f.read()
@@ -118,14 +117,14 @@ class EnumerationType(object):
             ".namespaceZero = UA_TRUE, .padding = 0, .isArray = UA_FALSE }}, .typeIndex = %s }" % (outname.upper() + "_" + self.name[3:].upper())
 
     def functions_c(self, typeTableName):
-        return '''#define %s_new (UA_Int32*)UA_Int32_new
+        return '''#define %s_new (%s*)UA_Int32_new
 #define %s_init(p) UA_Int32_init((UA_Int32*)p)
 #define %s_delete(p) UA_Int32_delete((UA_Int32*)p)
 #define %s_deleteMembers(p) UA_Int32_deleteMembers((UA_Int32*)p)
-#define %s_copy(src, dst) UA_Int32_copy((UA_Int32*)src, (UA_Int32*)dst)
+#define %s_copy(src, dst) UA_Int32_copy((const UA_Int32*)src, (UA_Int32*)dst)
 #define %s_calcSizeBinary(p) UA_Int32_calcSizeBinary((UA_Int32*)p)
 #define %s_encodeBinary(src, dst, offset) UA_Int32_encodeBinary((UA_Int32*)src, dst, offset)
-#define %s_decodeBinary(src, offset, dst) UA_Int32_decodeBinary(src, offset, (UA_Int32*)dst)''' % tuple(itertools.repeat(self.name, 8))
+#define %s_decodeBinary(src, offset, dst) UA_Int32_decodeBinary(src, offset, (UA_Int32*)dst)''' % tuple(itertools.repeat(self.name, 9))
 
 class OpaqueType(object):
     def __init__(self, name, description = ""):
@@ -241,7 +240,7 @@ class StructType(object):
         return layout + "}}"
 
     def functions_c(self, typeTableName):
-        return '''#define %s_new UA_new(%s)
+        return '''#define %s_new() UA_new(%s)
 #define %s_init(p) UA_init(p, %s)
 #define %s_delete(p) UA_delete(p, %s)
 #define %s_deleteMembers(p) UA_deleteMembers(p, %s)
@@ -417,8 +416,8 @@ extern "C" {
 */
 ''')
 printh("#define " + outname.upper() + "_COUNT %s\n" % (str(len(types))))
-printh("extern const UA_DataType *" + outname.upper() + ";\n")
-printh("extern const UA_UInt32 *" + outname.upper() + "_IDS;\n")
+printh("extern UA_EXPORT const UA_DataType *" + outname.upper() + ";\n")
+printh("extern UA_EXPORT const UA_UInt32 *" + outname.upper() + "_IDS;\n")
 
 i = 0
 for t in types.itervalues():
@@ -463,4 +462,4 @@ if args.typedescriptions:
     printc("};")
 
 fh.close()
-fc.close()
+fc.close()

+ 62 - 0
tools/generate_nodeids.py

@@ -0,0 +1,62 @@
+from __future__ import print_function
+import inspect
+import sys
+import platform
+import getpass
+import time
+import re
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument('nodeids', help='path/to/NodeIds.csv')
+parser.add_argument('outfile', help='outfile w/o extension')
+args = parser.parse_args()
+
+def useNodeId(row):
+    if row[0] == "":
+        return False
+    if "Test" in row[0]:
+        return False
+    if row[0].startswith("OpcUa_"):
+        return False
+    if row[0].startswith("SessionsDiagnosticsSummaryType_"):
+        return False
+    if "Type_" in row[0]:
+        return False
+    if "_Encoding_Default" in row[0]:
+        return False
+    return True
+
+f = open(args.nodeids)
+input_str = f.read() + "\nHasModelParent,50,ReferenceType"
+f.close()
+input_str = input_str.replace('\r','')
+rows = map(lambda x:tuple(x.split(',')), input_str.split('\n'))
+for index, row in enumerate(rows):
+    if row[0] == "BaseDataType":
+    	rows[index]= ("Variant", row[1], row[2])
+    elif row[0] == "Structure":
+    	rows[index] = ("ExtensionObject", row[1], row[2])
+
+fh = open(args.outfile + ".h",'w')
+def printh(string):
+    print(string, end='\n', file=fh)
+
+printh('''/**********************************************************
+ * '''+args.outfile+'''.hgen -- do not modify
+ **********************************************************
+ * Generated from '''+args.nodeids+''' with script '''+sys.argv[0]+'''
+ * on host '''+platform.uname()[1]+''' by user '''+getpass.getuser()+''' at '''+
+       time.strftime("%Y-%m-%d %I:%M:%S")+'''
+ **********************************************************/\n 
+#ifndef ''' + args.outfile.upper().split("/")[-1] + '''_H_
+#define ''' + args.outfile.upper().split("/")[-1] + '''_H_
+''')
+
+for row in rows:
+    if useNodeId(row):
+        printh("#define UA_NS0ID_%s %s // %s" % (row[0].upper(), row[1], row[2]))
+
+printh('\n#endif /* ' + args.outfile.upper().split("/")[-1] + '_H_ */')
+
+fh.close()

+ 10 - 2
tools/schema/Custom.Opc.Ua.Transport.bsd

@@ -11,10 +11,18 @@
 
 <!-- Transport types begin  -->
 
+  <opc:EnumeratedType Name="MessageTypeAndFinal" LengthInBits="32">
+    <opc:Documentation>Message Type and whether the message contains the final chunk</opc:Documentation>
+    <opc:EnumeratedValue Name="ACKF" Value="1179337537" />
+    <opc:EnumeratedValue Name="CLOF" Value="1179601987" />
+    <opc:EnumeratedValue Name="HELF" Value="1179403592" />
+    <opc:EnumeratedValue Name="MSGF" Value="1179079501" />
+    <opc:EnumeratedValue Name="OPNF" Value="1179537487" />
+  </opc:EnumeratedType>
+
    <opc:StructuredType Name="TcpMessageHeader">
     <opc:Documentation>TCP Header</opc:Documentation>
-    <opc:Field Name="MessageType" TypeName="opc:UInt32" /> <!-- The MessageType type is custom and implemented by hand -->
-    <opc:Field Name="IsFinal" TypeName="opc:Byte" />
+    <opc:Field Name="MessageTypeAndFinal" TypeName="opc:UInt32" />
     <opc:Field Name="MessageSize" TypeName="opc:UInt32" />
   </opc:StructuredType>