Browse Source

Merge branch '0.2'

Julius Pfrommer 7 years ago
parent
commit
a1d4b29d9e
50 changed files with 3227 additions and 1712 deletions
  1. 1 0
      .travis.yml
  2. 14 3
      CMakeLists.txt
  3. 2 0
      doc/CMakeLists.txt
  4. 4 3
      doc/building.rst
  5. 5 4
      doc/conf.py
  6. 0 2
      doc/index.rst
  7. 1 1
      doc/internal.rst
  8. 193 108
      doc/tutorial_noderelations.rst
  9. 53 50
      examples/server_method.c
  10. 10 5
      examples/server_variable.c
  11. 119 70
      include/ua_client.h
  12. 374 167
      include/ua_client_highlevel.h
  13. 13 28
      include/ua_config.h.in
  14. 2 1
      include/ua_connection.h
  15. 8 7
      include/ua_log.h
  16. 263 138
      include/ua_server.h
  17. 105 71
      include/ua_types.h
  18. 16 0
      plugins/ua_config_standard.c
  19. 1 0
      plugins/ua_config_standard.h
  20. 6 5
      plugins/ua_log_stdout.c
  21. 14 9
      src/client/ua_client.c
  22. 0 9
      src/client/ua_client_highlevel_subscriptions.c
  23. 16 8
      src/server/ua_nodestore.h
  24. 37 284
      src/server/ua_server.c
  25. 1 0
      src/server/ua_server_binary.c
  26. 18 20
      src/server/ua_services.h
  27. 153 42
      src/server/ua_services_attribute.c
  28. 281 83
      src/server/ua_services_nodemanagement.c
  29. 32 6
      src/server/ua_services_view.c
  30. 2 1
      src/server/ua_subscription.c
  31. 1 0
      src/ua_connection.c
  32. 3 1
      src/ua_securechannel.c
  33. 1 0
      src/ua_session.c
  34. 100 84
      src/ua_types.c
  35. 28 17
      src/ua_types_encoding_binary.c
  36. 1 0
      tests/CMakeLists.txt
  37. 1 0
      tests/check_builtin.c
  38. 1 0
      tests/check_chunking.c
  39. 149 152
      tests/check_memory.c
  40. 2 2
      tools/amalgamate.py
  41. 106 63
      tools/generate_datatypes.py
  42. 1 0
      tools/pyUANamespace/generate_open62541CCode.py
  43. 4 0
      tools/pyUANamespace/open62541_MacroHelper.py
  44. 9 1
      tools/pyUANamespace/open62541_XMLPreprocessor.py
  45. 7 1
      tools/pyUANamespace/ua_builtin_types.py
  46. 931 64
      tools/schema/NodeIds.csv
  47. 135 138
      tools/schema/Opc.Ua.Types.bsd
  48. 1 63
      tools/schema/namespace0/Opc.Ua.NodeSet2.Minimal.xml
  49. 1 1
      tools/travis/travis_linux_script.sh
  50. 1 0
      tools/travis/travis_osx_before_install.sh

+ 1 - 0
.travis.yml

@@ -53,6 +53,7 @@ addons:
       - wget
       - xutils-dev
       - zip
+      - graphviz
     # - libsubunit-dev #for check_0.10.0
   coverity_scan:
     project:

+ 14 - 3
CMakeLists.txt

@@ -10,16 +10,21 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/tools/cmake")
 find_package(PythonInterp REQUIRED)
 find_package(Git)
 if(GIT_FOUND)
-  execute_process(COMMAND ${GIT_EXECUTABLE} describe --abbrev=7 --dirty --always --tags
+  execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
                   RESULT_VARIABLE res_var OUTPUT_VARIABLE GIT_COM_ID WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
+  execute_process(COMMAND ${GIT_EXECUTABLE} describe --abbrev=0 --always --tags
+                  RESULT_VARIABLE res_var OUTPUT_VARIABLE GIT_REL_ID WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
     if(NOT ${res_var} EQUAL 0)
-        set(GIT_COMMIT_ID "unknown--git-commit-id-unknown")
+        set(GIT_COMMIT_ID "commit id unknown")
+        set(GIT_RELEASE_ID "release unknown")
         message(STATUS "Git failed (not a repo, or no tags). Build will not contain git revision info." )
     else()
         string(REPLACE "\n" "" GIT_COMMIT_ID ${GIT_COM_ID} )
+        string(REPLACE "\n" "" GIT_RELEASE_ID ${GIT_REL_ID} )
     endif()
 else()
-    set(GIT_COMMIT_ID "unknown--no-git-found")
+    set(GIT_COMMIT_ID "commit id unknown")
+    set(GIT_RELEASE_ID "release unknown")
     message(STATUS "Git not found. Build will not contain git revision info." )
 endif()
 message(STATUS "Git version: "  ${GIT_COMMIT_ID})
@@ -43,6 +48,8 @@ option(UA_ENABLE_MULTITHREADING "Enable multithreading" OFF)
 option(UA_ENABLE_DISCOVERY "Enable Discovery Service (LDS)" ON)
 option(UA_ENABLE_AMALGAMATION "Concatenate the library to a single file open62541.h/.c" OFF)
 option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
+option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
+
 if(UA_ENABLE_COVERAGE)
   set(CMAKE_BUILD_TYPE DEBUG)
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
@@ -158,6 +165,7 @@ set(exported_headers ${PROJECT_BINARY_DIR}/src_generated/ua_config.h
                      ${PROJECT_SOURCE_DIR}/include/ua_types.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
+                     ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_handling.h
                      ${PROJECT_SOURCE_DIR}/include/ua_connection.h
                      ${PROJECT_SOURCE_DIR}/include/ua_job.h
                      ${PROJECT_SOURCE_DIR}/include/ua_log.h
@@ -175,6 +183,7 @@ set(internal_headers ${PROJECT_SOURCE_DIR}/deps/queue.h
                      ${PROJECT_SOURCE_DIR}/src/ua_types_encoding_binary.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_encoding_binary.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
+                     ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_handling.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_encoding_binary.h
                      ${PROJECT_SOURCE_DIR}/src/ua_connection_internal.h
                      ${PROJECT_SOURCE_DIR}/src/ua_securechannel.h
@@ -244,6 +253,7 @@ endif()
 # standard data types
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
+                          ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_handling.h
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_encoding_binary.h
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
@@ -258,6 +268,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated
 # transport data types
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
+                          ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_handling.h
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_encoding_binary.h
                    PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py

+ 2 - 0
doc/CMakeLists.txt

@@ -7,6 +7,8 @@ set(DOC_SRC_DIR   ${PROJECT_BINARY_DIR}/doc_src)
 
 make_directory(${DOC_SRC_DIR})
 file(GLOB DOC_SRC "${PROJECT_SOURCE_DIR}/doc/*")
+list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/conf.py")
+configure_file("${PROJECT_SOURCE_DIR}/doc/conf.py" "${DOC_SRC_DIR}/conf.py")
 file(COPY ${DOC_SRC} DESTINATION ${DOC_SRC_DIR})
 
 function(generate_rst in out)

+ 4 - 3
doc/building.rst

@@ -11,7 +11,7 @@ Using the GCC compiler, the following calls build the examples on Linux.
 .. code-block:: bash
 
    cp /path-to/open62541.* . # copy single-file distribution to the local directory
-   cp /path-to/examples/server_variable.c . # copy the example server to the local directory
+   cp /path-to/examples/server_variable.c . # copy the example server
    gcc -std=c99 open62541.c server_variable.c -o server
 
 Building the Library
@@ -27,7 +27,7 @@ Building with CMake on Ubuntu or Debian
    # enable additional features
    sudo apt-get install liburcu-dev # for multithreading
    sudo apt-get install check # for unit tests
-   sudo apt-get install sphinx # for documentation generation
+   sudo apt-get install sphinx graphviz # for documentation generation
    sudo apt-get install python-sphinx-rtd-theme # documentation style
 
    cd open62541
@@ -61,7 +61,7 @@ with MinGW, just replace the compiler selection in the call to CMake.
    mkdir build
    cd build
    <path-to>\cmake.exe .. -G "Visual Studio 14 2015"
-   :: You can use use cmake-gui for a graphical user-interface to select single features
+   :: You can use use cmake-gui for a graphical user-interface to select features
 
 - Then open :file:`build\open62541.sln` in Visual Studio 2015 and build as usual
 
@@ -81,6 +81,7 @@ Building on OS X
    brew install cmake
    pip install sphinx # for documentation generation
    pip install sphinx_rtd_theme # documentation style
+   brew install graphviz # for graphics in the documentation
    brew install check # for unit tests
    brew install userspace-rcu # for multi-threading support
 

+ 5 - 4
doc/conf.py

@@ -29,7 +29,7 @@ import shlex
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = []
+extensions = ['sphinx.ext.graphviz']
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['_templates']
@@ -55,16 +55,17 @@ author = u'The open62541 authors'
 # built documents.
 #
 # The short X.Y version.
-version = '0.2'
+version = "${GIT_RELEASE_ID}"
+# The full version, including alpha/beta/rc tags.
+release = "${GIT_COMMIT_ID}"
 # The full version, including alpha/beta/rc tags.
-release = '1'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = "en"
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:

+ 0 - 2
doc/index.rst

@@ -27,6 +27,4 @@ standard.
    constants
    server
    client
-   client_highlevel
    internal
-

+ 1 - 1
doc/internal.rst

@@ -5,6 +5,6 @@ Internals
 
    services
    nodestore
-   types_generated
    connection
    log
+   types_generated

File diff suppressed because it is too large
+ 193 - 108
doc/tutorial_noderelations.rst


+ 53 - 50
examples/server_method.c

@@ -18,27 +18,29 @@ UA_Boolean running = true;
 UA_Logger logger = UA_Log_Stdout;
 
 
-// EXAMPLE 1 method
+/* Example 1 */
 static UA_StatusCode
-helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
+helloWorldMethod(void *handle, const UA_NodeId objectId,
+                 size_t inputSize, const UA_Variant *input,
                  size_t outputSize, UA_Variant *output) {
-        UA_String *inputStr = (UA_String*)input->data;
-        UA_String tmp = UA_STRING_ALLOC("Hello ");
-        if(inputStr->length > 0) {
-            tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
-            memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
-            tmp.length += inputStr->length;
-        }
-        UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
-        UA_String_deleteMembers(&tmp);
-        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called");
-        return UA_STATUSCODE_GOOD;
+    UA_String *inputStr = (UA_String*)input->data;
+    UA_String tmp = UA_STRING_ALLOC("Hello ");
+    if(inputStr->length > 0) {
+        tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
+        memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
+        tmp.length += inputStr->length;
+    }
+    UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
+    UA_String_deleteMembers(&tmp);
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called");
+    return UA_STATUSCODE_GOOD;
 }
 
-// EXAMPLE 2 method
+/* Example 2 */
 static UA_StatusCode
-IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId, size_t inputSize,
-                          const UA_Variant *input, size_t outputSize, UA_Variant *output) {
+IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId,
+                          size_t inputSize, const UA_Variant *input,
+                          size_t outputSize, UA_Variant *output) {
     UA_Variant_setArrayCopy(output, input->data, 5, &UA_TYPES[UA_TYPES_INT32]);
     for(size_t i = 0; i< input->arrayLength; i++)
         ((UA_Int32*)output->data)[i] = ((UA_Int32*)input->data)[i] + 1;
@@ -46,22 +48,23 @@ IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId, size_t inputSi
 }
 
 
-// EXAMPLE 3 method
+/* Example 3 */
 static UA_StatusCode
-fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
-                 size_t outputSize, UA_Variant *output) {
-    // Exactly the same as helloWorld, but returns foobar
-        UA_String *inputStr = (UA_String*)input->data;
-        UA_String tmp = UA_STRING_ALLOC("FooBar! ");
-        if(inputStr->length > 0) {
-            tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
-            memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
-            tmp.length += inputStr->length;
-        }
-        UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
-        UA_String_deleteMembers(&tmp);
-        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "FooBar was called");
-        return UA_STATUSCODE_GOOD;
+fooBarMethod(void *handle, const UA_NodeId objectId,
+             size_t inputSize, const UA_Variant *input,
+             size_t outputSize, UA_Variant *output) {
+    /* the same as helloWorld, but returns foobar */
+    UA_String *inputStr = (UA_String*)input->data;
+    UA_String tmp = UA_STRING_ALLOC("FooBar! ");
+    if(inputStr->length > 0) {
+        tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
+        memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
+        tmp.length += inputStr->length;
+    }
+    UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
+    UA_String_deleteMembers(&tmp);
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "FooBar was called");
+    return UA_STATUSCODE_GOOD;
 }
 
 static void stopHandler(int sign) {
@@ -74,12 +77,13 @@ int main(int argc, char** argv) {
 
     /* initialize the server */
     UA_ServerConfig config = UA_ServerConfig_standard;
-    UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
+    UA_ServerNetworkLayer nl;
+    nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
     config.networkLayers = &nl;
     config.networkLayersSize = 1;
     UA_Server *server = UA_Server_new(config);
 
-    //EXAMPLE 1
+    /* Example 1 */
     /* add the method node with the callback */
     UA_Argument inputArguments1;
     UA_Argument_init(&inputArguments1);
@@ -111,11 +115,9 @@ int main(int argc, char** argv) {
                             UA_QUALIFIEDNAME(1, "hello world"),
                             helloAttr, &helloWorldMethod, NULL,
                             1, &inputArguments1, 1, &outputArguments1, NULL);
-    //END OF EXAMPLE 1
 
-    //EXAMPLE 2
+    /* Example 2 */
     /* add another method node: output argument as 1d Int32 array*/
-    // define input arguments
     UA_Argument inputArguments2;
     UA_Argument_init(&inputArguments2);
     inputArguments2.arrayDimensionsSize = 1;
@@ -128,7 +130,6 @@ int main(int argc, char** argv) {
     inputArguments2.name = UA_STRING("int32 value");
     inputArguments2.valueRank = 1;
 
-    // define output arguments
     UA_Argument outputArguments2;
     UA_Argument_init(&outputArguments2);
     outputArguments2.arrayDimensionsSize = 1;
@@ -136,14 +137,16 @@ int main(int argc, char** argv) {
     pOutputDimensions[0] = 5;
     outputArguments2.arrayDimensions = pOutputDimensions;
     outputArguments2.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
-    outputArguments2.description = UA_LOCALIZEDTEXT("en_US", "increment each array index");
-    outputArguments2.name = UA_STRING("output is the array, each index is incremented by one");
+    outputArguments2.description = UA_LOCALIZEDTEXT("en_US",
+                                                    "increment each array index");
+    outputArguments2.name = UA_STRING("output is the array, "
+                                      "each index is incremented by one");
     outputArguments2.valueRank = 1;
 
     UA_MethodAttributes incAttr;
     UA_MethodAttributes_init(&incAttr);
-    incAttr.description = UA_LOCALIZEDTEXT("en_US","1dArrayExample");
-    incAttr.displayName = UA_LOCALIZEDTEXT("en_US","1dArrayExample");
+    incAttr.description = UA_LOCALIZEDTEXT("en_US", "1dArrayExample");
+    incAttr.displayName = UA_LOCALIZEDTEXT("en_US", "1dArrayExample");
     incAttr.executable = true;
     incAttr.userExecutable = true;
     UA_Server_addMethodNode(server, UA_NODEID_STRING(1, "IncInt32ArrayValues"),
@@ -152,25 +155,25 @@ int main(int argc, char** argv) {
                             UA_QUALIFIEDNAME(1, "IncInt32ArrayValues"),
                             incAttr, &IncInt32ArrayValuesMethod, NULL,
                             1, &inputArguments2, 1, &outputArguments2, NULL);
-    //END OF EXAMPLE 2
 
-    //EXAMPLE 3
+    /* Example 3 */
     UA_MethodAttributes method3Attr;
     UA_MethodAttributes_init(&method3Attr);
-    method3Attr.description = UA_LOCALIZEDTEXT("en_US","FooBar");
-    method3Attr.displayName = UA_LOCALIZEDTEXT("en_US","FooBar");
+    method3Attr.description = UA_LOCALIZEDTEXT("en_US", "FooBar");
+    method3Attr.displayName = UA_LOCALIZEDTEXT("en_US", "FooBar");
     method3Attr.executable = true;
     method3Attr.userExecutable = true;
-    UA_Server_addMethodNode(server, UA_NODEID_STRING(1,"FooBar"),
+    UA_Server_addMethodNode(server, UA_NODEID_STRING(1, "FooBar"),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                             UA_QUALIFIEDNAME(1, "FooBar"),
                             method3Attr, NULL, NULL,
                             1, &inputArguments1, 1, &outputArguments1, NULL);
-    /*  If the method node has no callback (because it was instantiated without one) or
-        if we just want to change it, this can be done with UA_Server_setMethodNode_callback() */
-    UA_Server_setMethodNode_callback(server,  UA_NODEID_NUMERIC(1,62542), &fooBarMethod, NULL);
-    //END OF EXAMPLE 3
+    /* If the method node has no callback (because it was instantiated without
+     * one) or if we just want to change it, this can be done
+     * UA_Server_setMethodNode_callback() */
+    UA_Server_setMethodNode_callback(server,  UA_NODEID_NUMERIC(1,62542),
+                                     &fooBarMethod, NULL);
 
     /* start server */
     UA_StatusCode retval = UA_Server_run(server, &running);

+ 10 - 5
examples/server_variable.c

@@ -21,19 +21,24 @@ static void stopHandler(int sign) {
     running = false;
 }
 
-static void onRead(void *handle, const UA_NodeId nodeid, const UA_Variant *data, const UA_NumericRange *range) {
-    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "onRead; handle is: %i", (uintptr_t)handle);
+static void onRead(void *handle, const UA_NodeId nodeid, const UA_Variant *data,
+                   const UA_NumericRange *range) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "onRead; handle is: %i",
+                (uintptr_t)handle);
 }
 
-static void onWrite(void *h, const UA_NodeId nodeid, const UA_Variant *data, const UA_NumericRange *range) {
-    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "onWrite; handle: %i", (uintptr_t)h);
+static void onWrite(void *h, const UA_NodeId nodeid, const UA_Variant *data,
+                    const UA_NumericRange *range) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "onWrite; handle: %i",
+                (uintptr_t)h);
 }
 
 int main(int argc, char** argv) {
     signal(SIGINT, stopHandler); /* catches ctrl-c */
 
     UA_ServerConfig config = UA_ServerConfig_standard;
-    UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
+    UA_ServerNetworkLayer nl;
+    nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
     config.networkLayers = &nl;
     config.networkLayersSize = 1;
     UA_Server *server = UA_Server_new(config);

+ 119 - 70
include/ua_client.h

@@ -23,6 +23,7 @@ extern "C" {
 #include "ua_connection.h"
 #include "ua_log.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 
 /**
  * .. _client:
@@ -43,13 +44,14 @@ extern "C" {
  *
  * Client Configuration
  * -------------------- */
-typedef UA_Connection (*UA_ConnectClientConnection)(UA_ConnectionConfig localConf,
-                                                    const char *endpointUrl,
-                                                    UA_Logger logger);
+typedef UA_Connection
+(*UA_ConnectClientConnection)(UA_ConnectionConfig localConf,
+                              const char *endpointUrl, UA_Logger logger);
 
 typedef struct UA_ClientConfig {
-    UA_UInt32 timeout; //sync response timeout
-    UA_UInt32 secureChannelLifeTime; // lifetime in ms (then the channel needs to be renewed)
+    UA_UInt32 timeout;               /* Sync response timeout */
+    UA_UInt32 secureChannelLifeTime; /* Lifetime in ms (then the channel needs
+                                        to be renewed) */
     UA_Logger logger;
     UA_ConnectionConfig localConnectionConfig;
     UA_ConnectClientConnection connectionFunc;
@@ -59,17 +61,17 @@ typedef struct UA_ClientConfig {
  * Client Lifecycle
  * ---------------- */
 typedef enum {
-     UA_CLIENTSTATE_READY,     /* The client is not connected but initialized and ready to
-                                  use. */
+     UA_CLIENTSTATE_READY,     /* The client is not connected but initialized
+                                  and ready to use. */
      UA_CLIENTSTATE_CONNECTED, /* The client is connected to a server. */
-     UA_CLIENTSTATE_FAULTED,   /* An error has occured that might have influenced the
-                                  connection state. A successfull service call or renewal
-                                  of the secure channel will reset the state to
-                                  CONNECTED. */
-     UA_CLIENTSTATE_ERRORED    /* A non-recoverable error has occured and the connection
-                                  is no longer reliable. The client needs to be
-                                  disconnected and reinitialized to recover into a
-                                  CONNECTED state. */
+     UA_CLIENTSTATE_FAULTED,   /* An error has occured that might have
+                                  influenced the connection state. A successfull
+                                  service call or renewal of the secure channel
+                                  will reset the state to CONNECTED. */
+     UA_CLIENTSTATE_ERRORED    /* A non-recoverable error has occured and the
+                                  connection is no longer reliable. The client
+                                  needs to be disconnected and reinitialized to
+                                  recover into a CONNECTED state. */
 } UA_ClientState;
 
 struct UA_Client;
@@ -77,9 +79,10 @@ typedef struct UA_Client UA_Client;
 
 /* Create a new client
  *
- * @param config for the new client. You can use UA_ClientConfig_standard which has sane defaults
- * @param logger function pointer to a logger function. See examples/logger_stdout.c for a simple
- *               implementation
+ * @param config for the new client. You can use UA_ClientConfig_standard
+ *        which has sane defaults
+ * @param logger function pointer to a logger function. See
+ *        examples/logger_stdout.c for a simple implementation
  * @return return the new Client object */
 UA_Client UA_EXPORT * UA_Client_new(UA_ClientConfig config);
 
@@ -100,7 +103,8 @@ void UA_EXPORT UA_Client_delete(UA_Client *client);
  * @param client to use
  * @param server url to connect (for example "opc.tcp://localhost:16664")
  * @param endpointDescriptionsSize size of the array of endpoint descriptions
- * @param endpointDescriptions array of endpoint descriptions that is allocated by the function (you need to free manually)
+ * @param endpointDescriptions array of endpoint descriptions that is allocated
+ *        by the function (you need to free manually)
  * @return Indicates whether the operation succeeded or returns an error code */
 UA_StatusCode UA_EXPORT
 UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
@@ -137,12 +141,14 @@ UA_StatusCode UA_EXPORT UA_Client_manuallyRenewSecureChannel(UA_Client *client);
  *
  * Raw Services
  * ------------
- * The raw OPC UA services are exposed to the client. But most of them time, it is better to use the
- * convenience functions from ``ua_client_highlevel.h`` that wrap the raw services. */
+ * The raw OPC UA services are exposed to the client. But most of them time, it
+ * is better to use the convenience functions from ``ua_client_highlevel.h``
+ * that wrap the raw services. */
 /* Don't use this function. Use the type versions below instead. */
 void UA_EXPORT
-__UA_Client_Service(UA_Client *client, const void *request, const UA_DataType *requestType,
-                    void *response, const UA_DataType *responseType);
+__UA_Client_Service(UA_Client *client, const void *request,
+                    const UA_DataType *requestType, void *response,
+                    const UA_DataType *responseType);
 
 /**
  * Attribute Service Set
@@ -152,14 +158,16 @@ UA_Client_Service_read(UA_Client *client, const UA_ReadRequest request) {
     UA_ReadResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
                         &response, &UA_TYPES[UA_TYPES_READRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_WriteResponse
 UA_Client_Service_write(UA_Client *client, const UA_WriteRequest request) {
     UA_WriteResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_WRITEREQUEST],
                         &response, &UA_TYPES[UA_TYPES_WRITERESPONSE]);
-    return response; }
+    return response;
+}
 
 /**
  * Method Service Set
@@ -169,7 +177,8 @@ UA_Client_Service_call(UA_Client *client, const UA_CallRequest request) {
     UA_CallResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CALLREQUEST],
                         &response, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
-    return response; }
+    return response;
+}
 
 /**
  * NodeManagement Service Set
@@ -179,28 +188,35 @@ UA_Client_Service_addNodes(UA_Client *client, const UA_AddNodesRequest request)
     UA_AddNodesResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ADDNODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_AddReferencesResponse
-UA_Client_Service_addReferences(UA_Client *client, const UA_AddReferencesRequest request) {
+UA_Client_Service_addReferences(UA_Client *client,
+                                const UA_AddReferencesRequest request) {
     UA_AddReferencesResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ADDNODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_DeleteNodesResponse
-UA_Client_Service_deleteNodes(UA_Client *client, const UA_DeleteNodesRequest request) {
+UA_Client_Service_deleteNodes(UA_Client *client,
+                              const UA_DeleteNodesRequest request) {
     UA_DeleteNodesResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETENODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_DeleteReferencesResponse
-UA_Client_Service_deleteReferences(UA_Client *client, const UA_DeleteReferencesRequest request) {
+UA_Client_Service_deleteReferences(UA_Client *client,
+                                   const UA_DeleteReferencesRequest request) {
     UA_DeleteReferencesResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETENODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 /**
  * View Service Set
@@ -210,53 +226,68 @@ UA_Client_Service_browse(UA_Client *client, const UA_BrowseRequest request) {
     UA_BrowseResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_BROWSEREQUEST],
                         &response, &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_BrowseNextResponse
-UA_Client_Service_browseNext(UA_Client *client, const UA_BrowseNextRequest request) {
+UA_Client_Service_browseNext(UA_Client *client,
+                             const UA_BrowseNextRequest request) {
     UA_BrowseNextResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST],
                         &response, &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_TranslateBrowsePathsToNodeIdsResponse
 UA_Client_Service_translateBrowsePathsToNodeIds(UA_Client *client,
-                                                const UA_TranslateBrowsePathsToNodeIdsRequest request) {
+                        const UA_TranslateBrowsePathsToNodeIdsRequest request) {
     UA_TranslateBrowsePathsToNodeIdsResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST],
+                        &response,
+                        &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
+    return response;
+}
 
 static UA_INLINE UA_RegisterNodesResponse
-UA_Client_Service_registerNodes(UA_Client *client, const UA_RegisterNodesRequest request) {
+UA_Client_Service_registerNodes(UA_Client *client,
+                                const UA_RegisterNodesRequest request) {
     UA_RegisterNodesResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_UnregisterNodesResponse
-UA_Client_Service_unregisterNodes(UA_Client *client, const UA_UnregisterNodesRequest request) {
+UA_Client_Service_unregisterNodes(UA_Client *client,
+                                  const UA_UnregisterNodesRequest request) {
     UA_UnregisterNodesResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST],
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST],
                         &response, &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]);
-    return response; }
+    return response;
+}
 
 /**
  * Query Service Set
  * ^^^^^^^^^^^^^^^^^ */
 static UA_INLINE UA_QueryFirstResponse
-UA_Client_Service_queryFirst(UA_Client *client, const UA_QueryFirstRequest request) {
+UA_Client_Service_queryFirst(UA_Client *client,
+                             const UA_QueryFirstRequest request) {
     UA_QueryFirstResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_QUERYFIRSTREQUEST],
                         &response, &UA_TYPES[UA_TYPES_QUERYFIRSTRESPONSE]);
-    return response; }
+    return response;
+}
 
 static UA_INLINE UA_QueryNextResponse
-UA_Client_Service_queryNext(UA_Client *client, const UA_QueryNextRequest request) {
+UA_Client_Service_queryNext(UA_Client *client,
+                            const UA_QueryNextRequest request) {
     UA_QueryNextResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_QUERYFIRSTREQUEST],
                         &response, &UA_TYPES[UA_TYPES_QUERYFIRSTRESPONSE]);
-    return response; }
+    return response;
+}
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 
@@ -264,52 +295,70 @@ UA_Client_Service_queryNext(UA_Client *client, const UA_QueryNextRequest request
  * MonitoredItem Service Set
  * ^^^^^^^^^^^^^^^^^^^^^^^^^ */
 static UA_INLINE UA_CreateMonitoredItemsResponse
-UA_Client_Service_createMonitoredItems(UA_Client *client, const UA_CreateMonitoredItemsRequest request) {
+UA_Client_Service_createMonitoredItems(UA_Client *client,
+                                 const UA_CreateMonitoredItemsRequest request) {
     UA_CreateMonitoredItemsResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], &response,
+                        &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
+    return response;
+}
 
 static UA_INLINE UA_DeleteMonitoredItemsResponse
-UA_Client_Service_deleteMonitoredItems(UA_Client *client, const UA_DeleteMonitoredItemsRequest request) {
+UA_Client_Service_deleteMonitoredItems(UA_Client *client,
+                                 const UA_DeleteMonitoredItemsRequest request) {
     UA_DeleteMonitoredItemsResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], &response,
+                        &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
+    return response;
+}
 
 /**
  * Subscription Service Set
  * ^^^^^^^^^^^^^^^^^^^^^^^^ */
 static UA_INLINE UA_CreateSubscriptionResponse
-UA_Client_Service_createSubscription(UA_Client *client, const UA_CreateSubscriptionRequest request) {
+UA_Client_Service_createSubscription(UA_Client *client,
+                                   const UA_CreateSubscriptionRequest request) {
     UA_CreateSubscriptionResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], &response,
+                        &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
+    return response;
+}
 
 static UA_INLINE UA_ModifySubscriptionResponse
-UA_Client_Service_modifySubscription(UA_Client *client, const UA_ModifySubscriptionRequest request) {
+UA_Client_Service_modifySubscription(UA_Client *client,
+                                   const UA_ModifySubscriptionRequest request) {
     UA_ModifySubscriptionResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], &response,
+                        &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
+    return response;
+}
 
 static UA_INLINE UA_DeleteSubscriptionsResponse
-UA_Client_Service_deleteSubscriptions(UA_Client *client, const UA_DeleteSubscriptionsRequest request) {
+UA_Client_Service_deleteSubscriptions(UA_Client *client,
+                                  const UA_DeleteSubscriptionsRequest request) {
     UA_DeleteSubscriptionsResponse response;
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
-    return response; }
+    __UA_Client_Service(client, &request,
+                        &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], &response,
+                        &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
+    return response;
+}
 
 static UA_INLINE UA_PublishResponse
 UA_Client_Service_publish(UA_Client *client, const UA_PublishRequest request) {
     UA_PublishResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
                         &response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
-    return response; }
+    return response;
+}
 
 #endif
 
+/** .. include:: client_highlevel.rst */
+
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 374 - 167
include/ua_client_highlevel.h

@@ -42,105 +42,185 @@ extern "C" {
  * using the raw :ref:`OPC UA services <client-services>`.
  *
  * Read Attributes
- * ===============
+ * ^^^^^^^^^^^^^^^
  * The following functions can be used to retrieve a single node attribute. Use
  * the regular service to read several attributes at once. */
 /* Don't call this function, use the typed versions */
 UA_StatusCode UA_EXPORT
-__UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId, UA_AttributeId attributeId,
-                          void *out, const UA_DataType *outDataType);
+__UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
+                          UA_AttributeId attributeId, void *out,
+                          const UA_DataType *outDataType);
 
 static UA_INLINE UA_StatusCode
-UA_Client_readNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId, UA_NodeId *outNodeId) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID, outNodeId, &UA_TYPES[UA_TYPES_NODEID]); }
+UA_Client_readNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId,
+                              UA_NodeId *outNodeId) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID,
+                                     outNodeId, &UA_TYPES[UA_TYPES_NODEID]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId, UA_NodeClass *outNodeClass) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS, outNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]); }
+UA_Client_readNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                 UA_NodeClass *outNodeClass) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
+                                     outNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId, UA_QualifiedName *outBrowseName) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME, outBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+UA_Client_readBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  UA_QualifiedName *outBrowseName) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+                                     outBrowseName,
+                                     &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId, UA_LocalizedText *outDisplayName) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME, outDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_readDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   UA_LocalizedText *outDisplayName) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+                                     outDisplayName,
+                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId, UA_LocalizedText *outDescription) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION, outDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_readDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   UA_LocalizedText *outDescription) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+                                     outDescription,
+                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId, UA_UInt32 *outWriteMask) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK, outWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_readWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                 UA_UInt32 *outWriteMask) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+                                     outWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId, UA_UInt32 *outUserWriteMask) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK, outUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_readUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                     UA_UInt32 *outUserWriteMask) {
+    return __UA_Client_readAttribute(client, &nodeId,
+                                     UA_ATTRIBUTEID_USERWRITEMASK,
+                                     outUserWriteMask,
+                                     &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outIsAbstract) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT, outIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  UA_Boolean *outIsAbstract) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+                                     outIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outSymmetric) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC, outSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                 UA_Boolean *outSymmetric) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
+                                     outSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId, UA_LocalizedText *outInverseName) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME, outInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_readInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   UA_LocalizedText *outInverseName) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+                                     outInverseName,
+                                     &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outContainsNoLoops) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS, outContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                       UA_Boolean *outContainsNoLoops) {
+    return __UA_Client_readAttribute(client, &nodeId,
+                                     UA_ATTRIBUTEID_CONTAINSNOLOOPS,
+                                     outContainsNoLoops,
+                                     &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Byte *outEventNotifier) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, outEventNotifier, &UA_TYPES[UA_TYPES_BYTE]); }
+UA_Client_readEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                     UA_Byte *outEventNotifier) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
+                                     outEventNotifier, &UA_TYPES[UA_TYPES_BYTE]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readValueAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Variant *outValue) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE, outValue, &UA_TYPES[UA_TYPES_VARIANT]); }
+UA_Client_readValueAttribute(UA_Client *client, const UA_NodeId nodeId,
+                             UA_Variant *outValue) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
+                                     outValue, &UA_TYPES[UA_TYPES_VARIANT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId, UA_NodeId *outDataType) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE, outDataType, &UA_TYPES[UA_TYPES_NODEID]); }
+UA_Client_readDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                UA_NodeId *outDataType) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+                                     outDataType, &UA_TYPES[UA_TYPES_NODEID]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readValueRankAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Int32 *outValueRank) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK, outValueRank, &UA_TYPES[UA_TYPES_INT32]); }
+UA_Client_readValueRankAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                 UA_Int32 *outValueRank) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+                                     outValueRank, &UA_TYPES[UA_TYPES_INT32]);
+}
 
 UA_StatusCode UA_EXPORT
 UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
-                                       UA_Int32 **outArrayDimensions, size_t *outArrayDimensionsSize);
+                                       UA_Int32 **outArrayDimensions,
+                                       size_t *outArrayDimensionsSize);
 
 static UA_INLINE UA_StatusCode
-UA_Client_readAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId, UA_UInt32 *outAccessLevel) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, outAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_readAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   UA_UInt32 *outAccessLevel) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+                                     outAccessLevel, &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId, UA_UInt32 *outUserAccessLevel) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL, outUserAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_readUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                       UA_UInt32 *outUserAccessLevel) {
+    return __UA_Client_readAttribute(client, &nodeId,
+                                     UA_ATTRIBUTEID_USERACCESSLEVEL,
+                                     outUserAccessLevel,
+                                     &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readMinimumSamplingIntervalAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Double *outMinimumSamplingInterval) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, outMinimumSamplingInterval, &UA_TYPES[UA_TYPES_DOUBLE]); }
+UA_Client_readMinimumSamplingIntervalAttribute(UA_Client *client,
+                                               const UA_NodeId nodeId,
+                                               UA_Double *outMinSamplingInterval) {
+    return __UA_Client_readAttribute(client, &nodeId,
+                                     UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+                                     outMinSamplingInterval,
+                                     &UA_TYPES[UA_TYPES_DOUBLE]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outHistorizing) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING, outHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   UA_Boolean *outHistorizing) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
+                                     outHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readExecutableAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outExecutable) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE, outExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  UA_Boolean *outExecutable) {
+    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+                                     outExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_readUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId, UA_Boolean *outUserExecutable) {
-    return __UA_Client_readAttribute(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE, outUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_readUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                      UA_Boolean *outUserExecutable) {
+    return __UA_Client_readAttribute(client, &nodeId,
+                                     UA_ATTRIBUTEID_USEREXECUTABLE,
+                                     outUserExecutable,
+                                     &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 /**
  * Write Attributes
- * ================
+ * ^^^^^^^^^^^^^^^^
  * The following functions can be use to write a single node attribute at a
  * time. Use the regular write service to write several attributes at once. */
 /* Don't call this function, use the typed versions */
@@ -150,213 +230,331 @@ __UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId,
                            const UA_DataType *inDataType);
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_NodeId *newNodeId) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID, newNodeId, &UA_TYPES[UA_TYPES_NODEID]); }
+UA_Client_writeNodeIdAttribute(UA_Client *client, const UA_NodeId nodeId,
+                               const UA_NodeId *newNodeId) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODEID,
+                                      newNodeId, &UA_TYPES[UA_TYPES_NODEID]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_NodeClass *newNodeClass) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS, newNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]); }
+UA_Client_writeNodeClassAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  const UA_NodeClass *newNodeClass) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_NODECLASS,
+                                      newNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_QualifiedName *newBrowseName) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME, newBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+UA_Client_writeBrowseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   const UA_QualifiedName *newBrowseName) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+                                      newBrowseName,
+                                      &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_LocalizedText *newDisplayName) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME, newDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_writeDisplayNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                    const UA_LocalizedText *newDisplayName) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+                                      newDisplayName,
+                                      &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_LocalizedText *newDescription) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION, newDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_writeDescriptionAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                    const UA_LocalizedText *newDescription) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+                                      newDescription,
+                                      &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_UInt32 *newWriteMask) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK, newWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_writeWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  const UA_UInt32 *newWriteMask) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+                                      newWriteMask, &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_UInt32 *newUserWriteMask) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USERWRITEMASK, newUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_writeUserWriteMaskAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                      const UA_UInt32 *newUserWriteMask) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_USERWRITEMASK,
+                                      newUserWriteMask,
+                                      &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newIsAbstract) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT, newIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeIsAbstractAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   const UA_Boolean *newIsAbstract) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+                                      newIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newSymmetric) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC, newSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeSymmetricAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  const UA_Boolean *newSymmetric) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
+                                      newSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_LocalizedText *newInverseName) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME, newInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+UA_Client_writeInverseNameAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                    const UA_LocalizedText *newInverseName) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+                                      newInverseName,
+                                      &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newContainsNoLoops) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS, newContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeContainsNoLoopsAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                        const UA_Boolean *newContainsNoLoops) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_CONTAINSNOLOOPS,
+                                      newContainsNoLoops,
+                                      &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Byte *newEventNotifier) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, newEventNotifier, &UA_TYPES[UA_TYPES_BYTE]); }
+UA_Client_writeEventNotifierAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                      const UA_Byte *newEventNotifier) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_EVENTNOTIFIER,
+                                      newEventNotifier,
+                                      &UA_TYPES[UA_TYPES_BYTE]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeValueAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Variant *newValue) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE, newValue, &UA_TYPES[UA_TYPES_VARIANT]); }
+UA_Client_writeValueAttribute(UA_Client *client, const UA_NodeId nodeId,
+                              const UA_Variant *newValue) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUE,
+                                      newValue, &UA_TYPES[UA_TYPES_VARIANT]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_NodeId *newDataType) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE, newDataType, &UA_TYPES[UA_TYPES_NODEID]); }
+UA_Client_writeDataTypeAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                 const UA_NodeId *newDataType) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+                                      newDataType, &UA_TYPES[UA_TYPES_NODEID]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeValueRankAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Int32 *newValueRank) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK, newValueRank, &UA_TYPES[UA_TYPES_INT32]); }
+UA_Client_writeValueRankAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                  const UA_Int32 *newValueRank) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+                                      newValueRank, &UA_TYPES[UA_TYPES_INT32]);
+}
 
 UA_StatusCode UA_EXPORT
 UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
-                                        const UA_Int32 *newArrayDimensions, size_t newArrayDimensionsSize);
+                                        const UA_Int32 *newArrayDimensions,
+                                        size_t newArrayDimensionsSize);
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_UInt32 *newAccessLevel) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, newAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_writeAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                    const UA_UInt32 *newAccessLevel) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+                                      newAccessLevel, &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_UInt32 *newUserAccessLevel) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL, newUserAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+UA_Client_writeUserAccessLevelAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                        const UA_UInt32 *newUserAccessLevel) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_USERACCESSLEVEL,
+                                      newUserAccessLevel,
+                                      &UA_TYPES[UA_TYPES_UINT32]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeMinimumSamplingIntervalAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Double *newMinimumSamplingInterval) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, newMinimumSamplingInterval, &UA_TYPES[UA_TYPES_DOUBLE]); }
+UA_Client_writeMinimumSamplingIntervalAttribute(UA_Client *client,
+                                                const UA_NodeId nodeId,
+                                                const UA_Double *newMinInterval) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+                                      newMinInterval, &UA_TYPES[UA_TYPES_DOUBLE]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newHistorizing) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING, newHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeHistorizingAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                    const UA_Boolean *newHistorizing) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
+                                      newHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeExecutableAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newExecutable) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE, newExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                   const UA_Boolean *newExecutable) {
+    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+                                      newExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Client_writeUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId, const UA_Boolean *newUserExecutable) {
-    return __UA_Client_writeAttribute(client, &nodeId, UA_ATTRIBUTEID_USEREXECUTABLE, newUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+UA_Client_writeUserExecutableAttribute(UA_Client *client, const UA_NodeId nodeId,
+                                       const UA_Boolean *newUserExecutable) {
+    return __UA_Client_writeAttribute(client, &nodeId,
+                                      UA_ATTRIBUTEID_USEREXECUTABLE,
+                                      newUserExecutable,
+                                      &UA_TYPES[UA_TYPES_BOOLEAN]);
+}
 
 /**
  * Method Calling
- * ============== */
+ * ^^^^^^^^^^^^^^ */
 UA_StatusCode UA_EXPORT
-UA_Client_call(UA_Client *client, const UA_NodeId objectId, const UA_NodeId methodId,
-               size_t inputSize, const UA_Variant *input, size_t *outputSize, UA_Variant **output);
+UA_Client_call(UA_Client *client, const UA_NodeId objectId,
+               const UA_NodeId methodId, size_t inputSize, const UA_Variant *input,
+               size_t *outputSize, UA_Variant **output);
 
 /**
  * Node Management
- * ===============
- *
- * See the section on :ref:`server-side node management <addnodes>`.
- */
+ * ^^^^^^^^^^^^^^^
+ * See the section on :ref:`server-side node management <addnodes>`. */
 UA_StatusCode UA_EXPORT
-UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
-                       UA_Boolean isForward, const UA_String targetServerUri,
-                       const UA_ExpandedNodeId targetNodeId, UA_NodeClass targetNodeClass);
+UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId,
+                       const UA_NodeId referenceTypeId, UA_Boolean isForward,
+                       const UA_String targetServerUri,
+                       const UA_ExpandedNodeId targetNodeId,
+                       UA_NodeClass targetNodeClass);
 
 UA_StatusCode UA_EXPORT
-UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
-                          UA_Boolean isForward, const UA_ExpandedNodeId targetNodeId,
+UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId,
+                          const UA_NodeId referenceTypeId, UA_Boolean isForward,
+                          const UA_ExpandedNodeId targetNodeId,
                           UA_Boolean deleteBidirectional);
 
 UA_StatusCode UA_EXPORT
-UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId, UA_Boolean deleteTargetReferences);
+UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId,
+                     UA_Boolean deleteTargetReferences);
 
 /* Don't call this function, use the typed versions */
 UA_StatusCode UA_EXPORT
 __UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClass,
-                    const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
-                    const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
+                    const UA_NodeId requestedNewNodeId,
+                    const UA_NodeId parentNodeId,
+                    const UA_NodeId referenceTypeId,
+                    const UA_QualifiedName browseName,
                     const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
                     const UA_DataType *attributeType, UA_NodeId *outNewNodeId);
 
 static UA_INLINE UA_StatusCode
 UA_Client_addVariableNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                          const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                          const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
-                          const UA_VariableAttributes attr, UA_NodeId *outNewNodeId) {
+                          const UA_NodeId parentNodeId,
+                          const UA_NodeId referenceTypeId,
+                          const UA_QualifiedName browseName,
+                          const UA_NodeId typeDefinition,
+                          const UA_VariableAttributes attr,
+                          UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_VARIABLE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, typeDefinition,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
-                               outNewNodeId); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_addVariableTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                              const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                              const UA_QualifiedName browseName, const UA_VariableTypeAttributes attr,
+                               parentNodeId, referenceTypeId, browseName,
+                               typeDefinition, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
+                               outNewNodeId);
+}
+
+static UA_INLINE UA_StatusCode
+UA_Client_addVariableTypeNode(UA_Client *client,
+                              const UA_NodeId requestedNewNodeId,
+                              const UA_NodeId parentNodeId,
+                              const UA_NodeId referenceTypeId,
+                              const UA_QualifiedName browseName,
+                              const UA_VariableTypeAttributes attr,
                               UA_NodeId *outNewNodeId) {
-    return __UA_Client_addNode(client, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
-                               outNewNodeId); }
+    return __UA_Client_addNode(client, UA_NODECLASS_VARIABLETYPE,
+                               requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
+                               outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Client_addObjectNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                        const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                        const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
+                        const UA_NodeId parentNodeId,
+                        const UA_NodeId referenceTypeId,
+                        const UA_QualifiedName browseName,
+                        const UA_NodeId typeDefinition,
                         const UA_ObjectAttributes attr, UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_OBJECT, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, typeDefinition,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
-                               outNewNodeId); }
+                               parentNodeId, referenceTypeId, browseName,
+                               typeDefinition, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Client_addObjectTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                            const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                            const UA_QualifiedName browseName, const UA_ObjectTypeAttributes attr,
+                            const UA_NodeId parentNodeId,
+                            const UA_NodeId referenceTypeId,
+                            const UA_QualifiedName browseName,
+                            const UA_ObjectTypeAttributes attr,
                             UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],
-                               outNewNodeId); }
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],
+                               outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Client_addViewNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                      const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                      const UA_QualifiedName browseName, const UA_ViewAttributes attr,
+                      const UA_NodeId parentNodeId,
+                      const UA_NodeId referenceTypeId,
+                      const UA_QualifiedName browseName,
+                      const UA_ViewAttributes attr,
                       UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_VIEW, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_VIEWATTRIBUTES],
-                               outNewNodeId); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_addReferenceTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                               const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                               const UA_QualifiedName browseName, const UA_ReferenceTypeAttributes attr,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_VIEWATTRIBUTES], outNewNodeId);
+}
+
+static UA_INLINE UA_StatusCode
+UA_Client_addReferenceTypeNode(UA_Client *client,
+                               const UA_NodeId requestedNewNodeId,
+                               const UA_NodeId parentNodeId,
+                               const UA_NodeId referenceTypeId,
+                               const UA_QualifiedName browseName,
+                               const UA_ReferenceTypeAttributes attr,
                                UA_NodeId *outNewNodeId) {
-    return __UA_Client_addNode(client, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],
-                               outNewNodeId); }
+    return __UA_Client_addNode(client, UA_NODECLASS_REFERENCETYPE,
+                               requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],
+                               outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Client_addDataTypeNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                          const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                          const UA_QualifiedName browseName, const UA_DataTypeAttributes attr,
+                          const UA_NodeId parentNodeId,
+                          const UA_NodeId referenceTypeId,
+                          const UA_QualifiedName browseName,
+                          const UA_DataTypeAttributes attr,
                           UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_DATATYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],
-                               outNewNodeId); }
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],
+                               outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Client_addMethodNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
-                          const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                          const UA_QualifiedName browseName, const UA_MethodAttributes attr,
-                          UA_NodeId *outNewNodeId) {
+                        const UA_NodeId parentNodeId,
+                        const UA_NodeId referenceTypeId,
+                        const UA_QualifiedName browseName,
+                        const UA_MethodAttributes attr,
+                        UA_NodeId *outNewNodeId) {
     return __UA_Client_addNode(client, UA_NODECLASS_METHOD, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_METHODATTRIBUTES],
-                               outNewNodeId); }
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
+                               &UA_TYPES[UA_TYPES_METHODATTRIBUTES], outNewNodeId);
+}
 
 /**
  * .. _client-subscriptions:
  *
  * Subscriptions Handling
- * ======================
- *
+ * ^^^^^^^^^^^^^^^^^^^^^^
  * At this point, the client does not yet contain its own thread or event-driven
  * main-loop. So the client will not perform any actions automatically in the
  * background. This is especially relevant for subscriptions. The user will have
@@ -382,25 +580,31 @@ UA_Client_Subscriptions_new(UA_Client *client, UA_SubscriptionSettings settings,
 UA_StatusCode UA_EXPORT
 UA_Client_Subscriptions_remove(UA_Client *client, UA_UInt32 subscriptionId);
 
-UA_StatusCode UA_EXPORT UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client);
+UA_StatusCode UA_EXPORT
+UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client);
 
-typedef void (*UA_MonitoredItemHandlingFunction) (UA_UInt32 monId, UA_DataValue *value, void *context);
+typedef void (*UA_MonitoredItemHandlingFunction)(UA_UInt32 monId,
+                                                 UA_DataValue *value,
+                                                 void *context);
 
 UA_StatusCode UA_EXPORT
-UA_Client_Subscriptions_addMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
+UA_Client_Subscriptions_addMonitoredItem(UA_Client *client,
+                                         UA_UInt32 subscriptionId,
                                          UA_NodeId nodeId, UA_UInt32 attributeID,
-                                         UA_MonitoredItemHandlingFunction handlingFunction,
-                                         void *handlingContext, UA_UInt32 *newMonitoredItemId);
+                                         UA_MonitoredItemHandlingFunction hFunc,
+                                         void *handlingContext,
+                                         UA_UInt32 *newMonitoredItemId);
 
 UA_StatusCode UA_EXPORT
-UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
+UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client,
+                                            UA_UInt32 subscriptionId,
                                             UA_UInt32 monitoredItemId);
 
 #endif
 
 /**
  * Misc Highlevel Functionality
- * ============================ */
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
 /* Get the namespace-index of a namespace-URI
  *
  * @param client The UA_Client struct for this connection
@@ -409,14 +613,17 @@ UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client, UA_UInt32 subscri
  *        in case of an error
  * @return Indicates whether the operation succeeded or returns an error code */
 UA_StatusCode UA_EXPORT
-UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex);
+UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
+                            UA_UInt16 *namespaceIndex);
 
 #ifndef HAVE_NODEITER_CALLBACK
 #define HAVE_NODEITER_CALLBACK
 /* Iterate over all nodes referenced by parentNodeId by calling the callback
    function for each child node */
-typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
-                                                  UA_NodeId referenceTypeId, void *handle);
+typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId,
+                                                 UA_Boolean isInverse,
+                                                 UA_NodeId referenceTypeId,
+                                                 void *handle);
 #endif
 
 UA_StatusCode UA_EXPORT

+ 13 - 28
include/ua_config.h.in

@@ -109,8 +109,15 @@ extern "C" {
 #endif
 
 /**
+ * Binary Encoding Overlays
+ * ------------------------
+ * Integers and floating point numbers are transmitted in little-endian (IEE 754
+ * for floating point) encoding. If the target architecture uses the same
+ * format, numeral datatypes can be memcpy'd (overlayed) on the binary stream.
+ * This speeds up encoding.
+ *
  * Integer Endianness
- * ------------------ */
+ * ^^^^^^^^^^^^^^^^^^ */
 #if defined(_WIN32) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
                         (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) /* little endian detected */
 # define UA_BINARY_OVERLAYABLE_INTEGER true
@@ -149,9 +156,13 @@ extern "C" {
 # endif
 #endif
 
+#ifndef UA_BINARY_OVERLAYABLE_INTEGER
+# define UA_BINARY_OVERLAYABLE_INTEGER false
+#endif
+
 /**
  * Float Endianness
- * ---------------- */
+ * ^^^^^^^^^^^^^^^^ */
 #if defined(_WIN32)
 # define UA_BINARY_OVERLAYABLE_FLOAT true
 #elif defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
@@ -162,34 +173,8 @@ extern "C" {
 # define UA_BINARY_OVERLAYABLE_FLOAT true
 #endif
 
-/**
- * Binary Encoding Overlays
- * ------------------------
- * Some data types have the same layout in memory as on the binary data stream.
- * This can be used to speed up the decoding. If we could not detect
- * little-endianness of integers and floats, this is not possible for types that
- * contain integers or floats respectively. See the definition of the
- * overlayable flag defined in `UA_DataType`. */
-
-/* Demote error to a warning on clang. There is no robust way to detect float
- * endianness here. On x86/x86-64, floats are always in the right IEEE 754
- * format. So floats are overlayable is the architecture is little-endian. */
-#if defined(__clang__)
-# pragma GCC diagnostic push
-# pragma GCC diagnostic warning "-W#warnings"
-#endif
-
-#ifndef UA_BINARY_OVERLAYABLE_INTEGER
-# define UA_BINARY_OVERLAYABLE_INTEGER false
-# warning Slow Integer Encoding. This warning can be removed safely. It is only an indicator that integer endianness could not be detected.
-#endif
 #ifndef UA_BINARY_OVERLAYABLE_FLOAT
 # define UA_BINARY_OVERLAYABLE_FLOAT false
-# warning Slow Float Encoding. This warning can be removed safely. It is only an indicator that the float encoding could not be detected.
-#endif
-
-#if defined(__clang__)
-# pragma GCC diagnostic pop
 #endif
 
 /**

+ 2 - 1
include/ua_connection.h

@@ -104,7 +104,8 @@ struct UA_Connection {
      *         can be repeated, UA_STATUSCODE_GOOD if it succeeded and
      *         UA_STATUSCODE_BADCONNECTIONCLOSED if the connection was
      *         closed. */
-    UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout);
+    UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response,
+                          UA_UInt32 timeout);
 
     /* Release the buffer of a received message */
     void (*releaseRecvBuffer)(UA_Connection *connection, UA_ByteString *buf);

+ 8 - 7
include/ua_log.h

@@ -58,7 +58,8 @@ typedef enum {
  *
  * Do not use the logger directly but make use of the following macros that take
  * the minimum log-level defined in ua_config.h into account. */
-typedef void (*UA_Logger)(UA_LogLevel level, UA_LogCategory category, const char *msg, ...);
+typedef void (*UA_Logger)(UA_LogLevel level, UA_LogCategory category,
+                          const char *msg, ...);
 
 #if UA_LOGLEVEL <= 100
 #define UA_LOG_TRACE(LOGGER, CATEGORY, ...) do { \
@@ -106,12 +107,12 @@ typedef void (*UA_Logger)(UA_LogLevel level, UA_LogCategory category, const char
  * Convenience macros for complex types
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 #define UA_PRINTF_GUID_FORMAT "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"
-#define UA_PRINTF_GUID_DATA(GUID) (GUID).identifier.guid.data1, (GUID).identifier.guid.data2, \
-        (GUID).identifier.guid.data3, (GUID).identifier.guid.data4[0],  \
-        (GUID).identifier.guid.data4[1], (GUID).identifier.guid.data4[2], \
-        (GUID).identifier.guid.data4[3], (GUID).identifier.guid.data4[4], \
-        (GUID).identifier.guid.data4[5], (GUID).identifier.guid.data4[6], \
-        (GUID).identifier.guid.data4[7]
+#define UA_PRINTF_GUID_DATA(GUID) (GUID).identifier.guid.data1,     \
+        (GUID).identifier.guid.data2, (GUID).identifier.guid.data3, \
+        (GUID).identifier.guid.data4[0], (GUID).identifier.guid.data4[1], \
+        (GUID).identifier.guid.data4[2], (GUID).identifier.guid.data4[3], \
+        (GUID).identifier.guid.data4[4], (GUID).identifier.guid.data4[5], \
+        (GUID).identifier.guid.data4[6], (GUID).identifier.guid.data4[7]
 
 #define UA_PRINTF_STRING_FORMAT "\"%.*s\""
 #define UA_PRINTF_STRING_DATA(STRING) (STRING).length, (STRING).data

+ 263 - 138
include/ua_server.h

@@ -1,4 +1,4 @@
- /*
+/*
  * Copyright (C) 2014 the contributors as stated in the AUTHORS file
  *
  * This file is part of open62541. open62541 is free software: you can
@@ -23,6 +23,7 @@ extern "C" {
 #include "ua_config.h"
 #include "ua_types.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 #include "ua_nodeids.h"
 #include "ua_log.h"
 #include "ua_job.h"
@@ -50,24 +51,27 @@ struct UA_ServerNetworkLayer {
      * @param logger The logger
      * @return Returns UA_STATUSCODE_GOOD or an error code. */
     UA_StatusCode (*start)(UA_ServerNetworkLayer *nl, UA_Logger logger);
-    
+
     /* Gets called from the main server loop and returns the jobs (accumulated
      * messages and close events) for dispatch.
      *
      * @param nl The network layer
-     * @param jobs When the returned integer is >0, *jobs points to an array of UA_Job of the
-     *             returned size.
-     * @param timeout The timeout during which an event must arrive in microseconds
-     * @return The size of the jobs array. If the result is negative, an error has occurred. */
+     * @param jobs When the returned integer is >0, *jobs points to an array of
+     *        UA_Job of the returned size.
+     * @param timeout The timeout during which an event must arrive in
+     *        microseconds
+     * @return The size of the jobs array. If the result is negative,
+     *         an error has occurred. */
     size_t (*getJobs)(UA_ServerNetworkLayer *nl, UA_Job **jobs, UA_UInt16 timeout);
 
     /* Closes the network connection and returns all the jobs that need to be
      * finished before the network layer can be safely deleted.
      *
      * @param nl The network layer
-     * @param jobs When the returned integer is >0, jobs points to an array of UA_Job of the
-     *             returned size.
-     * @return The size of the jobs array. If the result is negative, an error has occurred. */
+     * @param jobs When the returned integer is >0, jobs points to an array of
+     *        UA_Job of the returned size.
+     * @return The size of the jobs array. If the result is negative,
+     *         an error has occurred. */
     size_t (*stop)(UA_ServerNetworkLayer *nl, UA_Job **jobs);
 
     /** Deletes the network content. Call only after stopping. */
@@ -142,6 +146,9 @@ typedef struct {
 
 } UA_ServerConfig;
 
+/* Add a new namespace to the server. Returns the index of the new namespace */
+UA_UInt16 UA_EXPORT UA_Server_addNamespace(UA_Server *server, const char* name);
+
 /**
  * Server Lifecycle
  * ---------------- */
@@ -153,11 +160,14 @@ void UA_EXPORT UA_Server_delete(UA_Server *server);
  * be triggered.
  *
  * @param server The server object.
- * @param running The loop is run as long as *running is true. Otherwise, the server shuts down.
+ * @param running The loop is run as long as *running is true.
+ *        Otherwise, the server shuts down.
  * @return Returns the statuscode of the UA_Server_run_shutdown method */
-UA_StatusCode UA_EXPORT UA_Server_run(UA_Server *server, volatile UA_Boolean *running);
+UA_StatusCode UA_EXPORT
+UA_Server_run(UA_Server *server, volatile UA_Boolean *running);
 
-/* The prologue part of UA_Server_run (no need to use if you call UA_Server_run) */
+/* The prologue part of UA_Server_run (no need to use if you call
+ * UA_Server_run) */
 UA_StatusCode UA_EXPORT UA_Server_run_startup(UA_Server *server);
 
 /* Executes a single iteration of the server's main loop.
@@ -166,15 +176,18 @@ UA_StatusCode UA_EXPORT UA_Server_run_startup(UA_Server *server);
  * @param waitInternal Should we wait for messages in the networklayer?
  *        Otherwise, the timouts for the networklayers are set to zero.
  *        The default max wait time is 50millisec.
- * @return Returns how long we can wait until the next scheduled job (in millisec) */
-UA_UInt16 UA_EXPORT UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal);
+ * @return Returns how long we can wait until the next scheduled
+ *         job (in millisec) */
+UA_UInt16 UA_EXPORT
+UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal);
 
-/* The epilogue part of UA_Server_run (no need to use if you call UA_Server_run) */
+/* The epilogue part of UA_Server_run (no need to use if you call
+ * UA_Server_run) */
 UA_StatusCode UA_EXPORT UA_Server_run_shutdown(UA_Server *server);
 
 /**
- * Modify a running server
- * ----------------------- */
+ * Repeated jobs
+ * ------------- */
 /* Add a job for cyclic repetition to the server.
  *
  * @param server The server object.
@@ -184,39 +197,51 @@ UA_StatusCode UA_EXPORT UA_Server_run_shutdown(UA_Server *server);
  *        occurs at now() + interval at the latest.
  * @param jobId Set to the guid of the repeated job. This can be used to cancel
  *        the job later on. If the pointer is null, the guid is not set.
- * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code otherwise. */
-UA_StatusCode UA_EXPORT UA_Server_addRepeatedJob(UA_Server *server, UA_Job job,
-                                                 UA_UInt32 interval, UA_Guid *jobId);
+ * @return Upon success, UA_STATUSCODE_GOOD is returned.
+ *         An error code otherwise. */
+UA_StatusCode UA_EXPORT
+UA_Server_addRepeatedJob(UA_Server *server, UA_Job job,
+                         UA_UInt32 interval, UA_Guid *jobId);
 
 /* Remove repeated job. The entry will be removed asynchronously during the next
  * iteration of the server main loop.
  *
  * @param server The server object.
  * @param jobId The id of the job that shall be removed.
- * @return Upon sucess, UA_STATUSCODE_GOOD is returned. An error code otherwise. */
-UA_StatusCode UA_EXPORT UA_Server_removeRepeatedJob(UA_Server *server, UA_Guid jobId);
-
-/* Add a new namespace to the server. Returns the index of the new namespace */
-UA_UInt16 UA_EXPORT UA_Server_addNamespace(UA_Server *server, const char* name);
+ * @return Upon sucess, UA_STATUSCODE_GOOD is returned.
+ *         An error code otherwise. */
+UA_StatusCode UA_EXPORT
+UA_Server_removeRepeatedJob(UA_Server *server, UA_Guid jobId);
 
 /**
- * Reading / Writing Node Attributes
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ * Reading and Writing Node Attributes
+ * -----------------------------------
+ * The functions for reading and writing node attributes call the regular read
+ * and write service in the background that are also used over the network.
  *
- * The node attributes are read/written separately. The read/write functions do
- * not require the construction of variants used in the service definition. This
- * is handled internally.
- *
- * Reading Node Attributes
- * ~~~~~~~~~~~~~~~~~~~~~~~
- *
- * The following attributes cannot be read, since the local "admin" user always has
- * full rights.
+ * The following attributes cannot be read, since the local "admin" user always
+ * has full rights.
  *
  * - UserWriteMask
  * - UserAccessLevel
  * - UserExecutable */
-/* Don't use this function. There are typed versions for every supported attribute. */
+/* Read an attribute of a node. The specialized functions below provide a more
+ * concise syntax.
+ *
+ * @param server The server object.
+ * @param item ReadValueIds contain the NodeId of the target node, the id of the
+ *             attribute to read and (optionally) an index range to read parts
+ *             of an array only. See the section on NumericRange for the format
+ *             used for array ranges.
+ * @param timestamps Which timestamps to return for the attribute.
+ * @return Returns a DataValue that contains either an error code, or a variant
+ *         with the attribute value and the timestamps. */
+UA_DataValue UA_EXPORT
+UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
+               UA_TimestampsToReturn timestamps);
+    
+/* Don't use this function. There are typed versions for every supported
+ * attribute. */
 UA_StatusCode UA_EXPORT
 __UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
                  UA_AttributeId attributeId, void *v);
@@ -224,106 +249,137 @@ __UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
 static UA_INLINE UA_StatusCode
 UA_Server_readNodeId(UA_Server *server, const UA_NodeId nodeId,
                      UA_NodeId *outNodeId) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODEID, outNodeId); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODEID, outNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readNodeClass(UA_Server *server, const UA_NodeId nodeId,
                         UA_NodeClass *outNodeClass) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODECLASS, outNodeClass); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_NODECLASS,
+                            outNodeClass);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readBrowseName(UA_Server *server, const UA_NodeId nodeId,
                          UA_QualifiedName *outBrowseName) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME, outBrowseName); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
+                            outBrowseName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readDisplayName(UA_Server *server, const UA_NodeId nodeId,
                           UA_LocalizedText *outDisplayName) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME, outDisplayName); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
+                            outDisplayName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readDescription(UA_Server *server, const UA_NodeId nodeId,
                           UA_LocalizedText *outDescription) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION, outDescription); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
+                            outDescription);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readWriteMask(UA_Server *server, const UA_NodeId nodeId,
                         UA_UInt32 *outWriteMask) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK, outWriteMask); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
+                            outWriteMask);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readIsAbstract(UA_Server *server, const UA_NodeId nodeId,
                          UA_Boolean *outIsAbstract) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT, outIsAbstract); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
+                            outIsAbstract);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readSymmetric(UA_Server *server, const UA_NodeId nodeId,
                         UA_Boolean *outSymmetric) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_SYMMETRIC, outSymmetric); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_SYMMETRIC,
+                            outSymmetric);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readInverseName(UA_Server *server, const UA_NodeId nodeId,
                           UA_LocalizedText *outInverseName) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME, outInverseName); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
+                            outInverseName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readContainsNoLoop(UA_Server *server, const UA_NodeId nodeId,
                              UA_Boolean *outContainsNoLoops) {
     return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
-                            outContainsNoLoops); }
+                            outContainsNoLoops);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readEventNotifier(UA_Server *server, const UA_NodeId nodeId,
                             UA_Byte *outEventNotifier) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, outEventNotifier); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
+                            outEventNotifier);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readValue(UA_Server *server, const UA_NodeId nodeId,
                     UA_Variant *outValue) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUE, outValue); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUE, outValue);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readDataType(UA_Server *server, const UA_NodeId nodeId,
                        UA_NodeId *outDataType) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DATATYPE, outDataType); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
+                            outDataType);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readValueRank(UA_Server *server, const UA_NodeId nodeId,
                         UA_Int32 *outValueRank) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUERANK, outValueRank); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
+                            outValueRank);
+}
 
 /* Returns a variant with an int32 array */
 static UA_INLINE UA_StatusCode
 UA_Server_readArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
                               UA_Variant *outArrayDimensions) {
     return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
-                            outArrayDimensions); }
+                            outArrayDimensions);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readAccessLevel(UA_Server *server, const UA_NodeId nodeId,
                           UA_UInt32 *outAccessLevel) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, outAccessLevel); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
+                            outAccessLevel);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
                                       UA_Double *outMinimumSamplingInterval) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
-                            outMinimumSamplingInterval); }
+    return __UA_Server_read(server, &nodeId,
+                            UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+                            outMinimumSamplingInterval);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readHistorizing(UA_Server *server, const UA_NodeId nodeId,
                           UA_Boolean *outHistorizing) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_HISTORIZING, outHistorizing); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_HISTORIZING,
+                            outHistorizing);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_readExecutable(UA_Server *server, const UA_NodeId nodeId,
                          UA_Boolean *outExecutable) {
-    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE, outExecutable); }
+    return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
+                            outExecutable);
+}
 
 /**
- * Writing Node Attributes
- * ~~~~~~~~~~~~~~~~~~~~~~~
- *
  * The following node attributes cannot be changed once a node has been created:
  *
  * - NodeClass
@@ -346,7 +402,21 @@ UA_Server_readExecutable(UA_Server *server, const UA_NodeId nodeId,
  * - ArrayDimensions
  *
  * Historizing is currently unsupported */
-/* Don't use this function. There are typed versions with no additional overhead. */
+/* Overwrite an attribute of a node. The specialized functions below provide a
+ * more concise syntax.
+ *
+ * @param server The server object.
+ * @param value WriteValues contain the NodeId of the target node, the id of the
+ *              attribute to overwritten, the actual value and (optionally) an
+ *              index range to replace parts of an array only. of an array only.
+ *              See the section on NumericRange for the format used for array
+ *              ranges.
+ * @return Returns a status code. */
+UA_StatusCode UA_EXPORT
+UA_Server_write(UA_Server *server, const UA_WriteValue *value);
+
+/* Don't use this function. There are typed versions with no additional
+ * overhead. */
 UA_StatusCode UA_EXPORT
 __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
                   const UA_AttributeId attributeId,
@@ -356,61 +426,73 @@ static UA_INLINE UA_StatusCode
 UA_Server_writeBrowseName(UA_Server *server, const UA_NodeId nodeId,
                           const UA_QualifiedName browseName) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_BROWSENAME,
-                             &UA_TYPES[UA_TYPES_QUALIFIEDNAME], &browseName); }
+                             &UA_TYPES[UA_TYPES_QUALIFIEDNAME], &browseName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeDisplayName(UA_Server *server, const UA_NodeId nodeId,
                            const UA_LocalizedText displayName) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
-                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &displayName); }
+                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &displayName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeDescription(UA_Server *server, const UA_NodeId nodeId,
                            const UA_LocalizedText description) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DESCRIPTION,
-                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &description); }
+                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &description);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeWriteMask(UA_Server *server, const UA_NodeId nodeId,
                          const UA_UInt32 writeMask) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_WRITEMASK,
-                             &UA_TYPES[UA_TYPES_UINT32], &writeMask); }
+                             &UA_TYPES[UA_TYPES_UINT32], &writeMask);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeIsAbstract(UA_Server *server, const UA_NodeId nodeId,
                           const UA_Boolean isAbstract) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ISABSTRACT,
-                             &UA_TYPES[UA_TYPES_BOOLEAN], &isAbstract); }
+                             &UA_TYPES[UA_TYPES_BOOLEAN], &isAbstract);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeInverseName(UA_Server *server, const UA_NodeId nodeId,
                            const UA_LocalizedText inverseName) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_INVERSENAME,
-                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &inverseName); }
+                             &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], &inverseName);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeEventNotifier(UA_Server *server, const UA_NodeId nodeId,
                              const UA_Byte eventNotifier) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
-                             &UA_TYPES[UA_TYPES_BYTE], &eventNotifier); }
+                             &UA_TYPES[UA_TYPES_BYTE], &eventNotifier);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeValue(UA_Server *server, const UA_NodeId nodeId,
                      const UA_Variant value) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUE,
-                             &UA_TYPES[UA_TYPES_VARIANT], &value); }
+                             &UA_TYPES[UA_TYPES_VARIANT], &value);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeAccessLevel(UA_Server *server, const UA_NodeId nodeId,
                            const UA_UInt32 accessLevel) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
-                             &UA_TYPES[UA_TYPES_UINT32], &accessLevel); }
+                             &UA_TYPES[UA_TYPES_UINT32], &accessLevel);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
                                        const UA_Double miniumSamplingInterval) {
-    return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
-                             &UA_TYPES[UA_TYPES_DOUBLE], &miniumSamplingInterval); }
+    return __UA_Server_write(server, &nodeId,
+                             UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
+                             &UA_TYPES[UA_TYPES_DOUBLE],
+                             &miniumSamplingInterval);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
@@ -422,7 +504,8 @@ UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
  * Browsing
  * -------- */
 UA_BrowseResult UA_EXPORT
-UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr);
+UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs,
+                 const UA_BrowseDescription *descr);
 
 UA_BrowseResult UA_EXPORT
 UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
@@ -433,8 +516,9 @@ UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
 /* Iterate over all nodes referenced by parentNodeId by calling the callback
  * function for each child node (in ifdef because GCC/CLANG handle include order
  * differently) */
-typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
-                                                 UA_NodeId referenceTypeId, void *handle);
+typedef UA_StatusCode
+(*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
+						   UA_NodeId referenceTypeId, void *handle);
 #endif
 
 UA_StatusCode UA_EXPORT
@@ -508,10 +592,11 @@ typedef struct {
                      multiple sources */
     /* Copies the data from the source into the provided value.
      *
-     * @param handle An optional pointer to user-defined data for the specific data source
+     * @param handle An optional pointer to user-defined data for the
+     *        specific data source
      * @param nodeid Id of the read node
-     * @param includeSourceTimeStamp If true, then the datasource is expected to set the source
-     *        timestamp in the returned value
+     * @param includeSourceTimeStamp If true, then the datasource is expected to
+     *        set the source timestamp in the returned value
      * @param range If not null, then the datasource shall return only a
      *        selection of the (nonscalar) data. Set
      *        UA_STATUSCODE_BADINDEXRANGEINVALID in the value if this does not
@@ -523,13 +608,14 @@ typedef struct {
      *         original caller are set in the value. If an error is returned,
      *         then no releasing of the value is done. */
     UA_StatusCode (*read)(void *handle, const UA_NodeId nodeid,
-                          UA_Boolean includeSourceTimeStamp, const UA_NumericRange *range,
-                          UA_DataValue *value);
+                          UA_Boolean includeSourceTimeStamp,
+                          const UA_NumericRange *range, UA_DataValue *value);
 
     /* Write into a data source. The write member of UA_DataSource can be empty
      * if the operation is unsupported.
      *
-     * @param handle An optional pointer to user-defined data for the specific data source
+     * @param handle An optional pointer to user-defined data for the
+     *        specific data source
      * @param nodeid Id of the node being written to
      * @param data The data to be written into the data source
      * @param range An optional data range. If the data source is scalar or does
@@ -573,15 +659,17 @@ typedef struct {
 } UA_ObjectLifecycleManagement;
 
 UA_StatusCode UA_EXPORT
-UA_Server_setObjectTypeNode_lifecycleManagement(UA_Server *server, UA_NodeId nodeId,
+UA_Server_setObjectTypeNode_lifecycleManagement(UA_Server *server,
+                                                UA_NodeId nodeId,
                                                 UA_ObjectLifecycleManagement olm);
 
 /**
  * Method Callbacks
  * ~~~~~~~~~~~~~~~~ */
-typedef UA_StatusCode (*UA_MethodCallback)(void *methodHandle, const UA_NodeId objectId,
-                                           size_t inputSize, const UA_Variant *input,
-                                           size_t outputSize, UA_Variant *output);
+typedef UA_StatusCode
+(*UA_MethodCallback)(void *methodHandle, const UA_NodeId objectId,
+                     size_t inputSize, const UA_Variant *input,
+                     size_t outputSize, UA_Variant *output);
 
 #ifdef UA_ENABLE_METHODCALLS
 UA_StatusCode UA_EXPORT
@@ -609,142 +697,179 @@ UA_Server_setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId
  * also called for all sub-nodes contained in an object or variable type node
  * that is instantiated. */
 typedef struct {
-  UA_StatusCode (*method)(const UA_NodeId objectId, const UA_NodeId typeDefinitionId, void *handle);
+  UA_StatusCode (*method)(const UA_NodeId objectId,
+                          const UA_NodeId typeDefinitionId, void *handle);
   void *handle;
 } UA_InstantiationCallback;
 
 /* Don't use this function. There are typed versions as inline functions. */
 UA_StatusCode UA_EXPORT
 __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
-                    const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
-                    const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
-                    const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
+                    const UA_NodeId requestedNewNodeId,
+                    const UA_NodeId parentNodeId,
+                    const UA_NodeId referenceTypeId,
+                    const UA_QualifiedName browseName,
+                    const UA_NodeId typeDefinition,
+                    const UA_NodeAttributes *attr,
                     const UA_DataType *attributeType,
-                    UA_InstantiationCallback *instantiationCallback, UA_NodeId *outNewNodeId);
+                    UA_InstantiationCallback *instantiationCallback,
+                    UA_NodeId *outNewNodeId);
 
 static UA_INLINE UA_StatusCode
 UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                          const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                          const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
+                          const UA_NodeId parentNodeId,
+                          const UA_NodeId referenceTypeId,
+                          const UA_QualifiedName browseName,
+                          const UA_NodeId typeDefinition,
                           const UA_VariableAttributes attr,
                           UA_InstantiationCallback *instantiationCallback,
                           UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_VARIABLE, requestedNewNodeId, parentNodeId,
-                               referenceTypeId, browseName, typeDefinition,
-                               (const UA_NodeAttributes*)&attr,
+    return __UA_Server_addNode(server, UA_NODECLASS_VARIABLE, requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               typeDefinition, (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Server_addVariableTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                              const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+UA_Server_addVariableTypeNode(UA_Server *server,
+                              const UA_NodeId requestedNewNodeId,
+                              const UA_NodeId parentNodeId,
+                              const UA_NodeId referenceTypeId,
                               const UA_QualifiedName browseName,
                               const UA_VariableTypeAttributes attr,
                               UA_InstantiationCallback *instantiationCallback,
                               UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
+    return __UA_Server_addNode(server, UA_NODECLASS_VARIABLETYPE,
+                               requestedNewNodeId, parentNodeId, referenceTypeId,
+                               browseName, UA_NODEID_NULL,
                                (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                        const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                        const UA_QualifiedName browseName, const UA_NodeId typeDefinition,
+                        const UA_NodeId parentNodeId,
+                        const UA_NodeId referenceTypeId,
+                        const UA_QualifiedName browseName,
+                        const UA_NodeId typeDefinition,
                         const UA_ObjectAttributes attr,
                         UA_InstantiationCallback *instantiationCallback,
                         UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_OBJECT, requestedNewNodeId, parentNodeId,
-                               referenceTypeId, browseName, typeDefinition,
-                               (const UA_NodeAttributes*)&attr,
+    return __UA_Server_addNode(server, UA_NODECLASS_OBJECT, requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               typeDefinition, (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                            const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+                            const UA_NodeId parentNodeId,
+                            const UA_NodeId referenceTypeId,
                             const UA_QualifiedName browseName,
                             const UA_ObjectTypeAttributes attr,
                             UA_InstantiationCallback *instantiationCallback,
                             UA_NodeId *outNewNodeId) {
     return __UA_Server_addNode(server, UA_NODECLASS_OBJECTTYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
 UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                      const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                      const UA_QualifiedName browseName, const UA_ViewAttributes attr,
+                      const UA_NodeId parentNodeId,
+                      const UA_NodeId referenceTypeId,
+                      const UA_QualifiedName browseName,
+                      const UA_ViewAttributes attr,
                       UA_InstantiationCallback *instantiationCallback,
                       UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_VIEW, requestedNewNodeId, parentNodeId,
-                               referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr,
+    return __UA_Server_addNode(server, UA_NODECLASS_VIEW, requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_VIEWATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Server_addReferenceTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                               const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
+UA_Server_addReferenceTypeNode(UA_Server *server,
+                               const UA_NodeId requestedNewNodeId,
+                               const UA_NodeId parentNodeId,
+                               const UA_NodeId referenceTypeId,
                                const UA_QualifiedName browseName,
                                const UA_ReferenceTypeAttributes attr,
                                UA_InstantiationCallback *instantiationCallback,
                                UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_REFERENCETYPE, requestedNewNodeId,
-                               parentNodeId, referenceTypeId, browseName, UA_NODEID_NULL,
+    return __UA_Server_addNode(server, UA_NODECLASS_REFERENCETYPE,
+                               requestedNewNodeId, parentNodeId, referenceTypeId,
+                               browseName, UA_NODEID_NULL,
                                (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 static UA_INLINE UA_StatusCode
-UA_Server_addDataTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                          const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                          const UA_QualifiedName browseName, const UA_DataTypeAttributes attr,
+UA_Server_addDataTypeNode(UA_Server *server,
+                          const UA_NodeId requestedNewNodeId,
+                          const UA_NodeId parentNodeId,
+                          const UA_NodeId referenceTypeId,
+                          const UA_QualifiedName browseName,
+                          const UA_DataTypeAttributes attr,
                           UA_InstantiationCallback *instantiationCallback,
                           UA_NodeId *outNewNodeId) {
-    return __UA_Server_addNode(server, UA_NODECLASS_DATATYPE, requestedNewNodeId, parentNodeId,
-                               referenceTypeId, browseName, UA_NODEID_NULL,
-                               (const UA_NodeAttributes*)&attr,
+    return __UA_Server_addNode(server, UA_NODECLASS_DATATYPE, requestedNewNodeId,
+                               parentNodeId, referenceTypeId, browseName,
+                               UA_NODEID_NULL, (const UA_NodeAttributes*)&attr,
                                &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],
-                               instantiationCallback, outNewNodeId); }
+                               instantiationCallback, outNewNodeId);
+}
 
 UA_StatusCode UA_EXPORT
-UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
+UA_Server_addDataSourceVariableNode(UA_Server *server,
+                                    const UA_NodeId requestedNewNodeId,
                                     const UA_NodeId parentNodeId,
                                     const UA_NodeId referenceTypeId,
                                     const UA_QualifiedName browseName,
                                     const UA_NodeId typeDefinition,
                                     const UA_VariableAttributes attr,
-                                    const UA_DataSource dataSource, UA_NodeId *outNewNodeId);
+                                    const UA_DataSource dataSource,
+                                    UA_NodeId *outNewNodeId);
 
 #ifdef UA_ENABLE_METHODCALLS
 UA_StatusCode UA_EXPORT
 UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
-                        const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId,
-                        const UA_QualifiedName browseName, const UA_MethodAttributes attr,
+                        const UA_NodeId parentNodeId,
+                        const UA_NodeId referenceTypeId,
+                        const UA_QualifiedName browseName,
+                        const UA_MethodAttributes attr,
                         UA_MethodCallback method, void *handle,
-                        size_t inputArgumentsSize, const UA_Argument* inputArguments, 
-                        size_t outputArgumentsSize, const UA_Argument* outputArguments,
+                        size_t inputArgumentsSize,
+                        const UA_Argument* inputArguments, 
+                        size_t outputArgumentsSize,
+                        const UA_Argument* outputArguments,
                         UA_NodeId *outNewNodeId);
 #endif
 
 UA_StatusCode UA_EXPORT
-UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId, UA_Boolean deleteReferences);
+UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
+                     UA_Boolean deleteReferences);
 
 /**
  * Reference Management
  * -------------------- */
 UA_StatusCode UA_EXPORT
-UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId,
+UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
+                       const UA_NodeId refTypeId,
                        const UA_ExpandedNodeId targetId, UA_Boolean isForward);
 
 UA_StatusCode UA_EXPORT
 UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
                           const UA_NodeId referenceTypeId, UA_Boolean isForward,
-                          const UA_ExpandedNodeId targetNodeId, UA_Boolean deleteBidirectional);
+                          const UA_ExpandedNodeId targetNodeId,
+                          UA_Boolean deleteBidirectional);
 
 #ifdef __cplusplus
 }

+ 105 - 71
include/ua_types.h

@@ -39,12 +39,14 @@ extern "C" {
  *   Initialize the data type. This is synonymous with zeroing out the memory,
  *   i.e. ``memset(dataptr, 0, sizeof(T))``.
  * ``T* T_new()``
- *   Allocate and return the memory for the data type. The memory is already initialized.
+ *   Allocate and return the memory for the data type. The memory is already
+ *   initialized.
  * ``UA_StatusCode T_copy(const T *src, T *dst)``
  *   Copy the content of the data type. Returns ``UA_STATUSCODE_GOOD`` or
  *   ``UA_STATUSCODE_BADOUTOFMEMORY``.
  * ``void T_deleteMembers(T *ptr)``
- *   Delete the dynamically allocated content of the data type, but not the data type itself.
+ *   Delete the dynamically allocated content of the data type and perform a
+ *   ``T_init`` to reset the type.
  * ``void T_delete(T *ptr)``
  *   Delete the content of the data type and the memory for the data type itself.
  *
@@ -115,7 +117,8 @@ typedef uint32_t UA_UInt32;
 /**
  * Int64
  * ^^^^^
- * An integer value between -10 223 372 036 854 775 808 and 9 223 372 036 854 775 807. */
+ * An integer value between -10 223 372 036 854 775 808 and
+ * 9 223 372 036 854 775 807. */
 typedef int64_t UA_Int64;
 #define UA_INT64_MAX (int64_t)9223372036854775807
 #define UA_INT64_MIN ((int64_t)-9223372036854775808)
@@ -145,8 +148,9 @@ typedef double UA_Double;
  *
  * StatusCode
  * ^^^^^^^^^^
- * A numeric identifier for a error or condition that is associated with a value or an
- * operation. See the section :ref:`statuscodes` for the meaning of a specific code. */
+ * A numeric identifier for a error or condition that is associated with a value
+ * or an operation. See the section :ref:`statuscodes` for the meaning of a
+ * specific code. */
 typedef uint32_t UA_StatusCode;
 
 /**
@@ -183,7 +187,9 @@ void UA_EXPORT * UA_Array_new(size_t size, const UA_DataType *type) UA_FUNC_ATTR
  * @param dst The location of the pointer to the new array
  * @param type The datatype of the array members
  * @return Returns UA_STATUSCODE_GOOD or UA_STATUSCODE_BADOUTOFMEMORY */
-UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, size_t size, void **dst, const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
+UA_StatusCode UA_EXPORT
+UA_Array_copy(const void *src, size_t size, void **dst,
+              const UA_DataType *type) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
 
 /* Deletes an array.
  *
@@ -192,6 +198,25 @@ UA_StatusCode UA_EXPORT UA_Array_copy(const void *src, size_t size, void **dst,
  * @param type The datatype of the array members */
 void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
 
+/**
+ * .. _numericrange:
+ *
+ * NumericRange
+ * ^^^^^^^^^^^^
+ *
+ * NumericRanges are used to indicate subsets of a (multidimensional) variant
+ * array. NumericRange has no official type structure in the standard. On the
+ * wire, it only exists as an encoded string, such as "1:2,0:3,5". The colon
+ * separates min/max index and the comma separates dimensions. A single value
+ * indicates a range with a single element (min==max). */
+typedef struct {
+    size_t dimensionsSize;
+    struct UA_NumericRangeDimension {
+        UA_UInt32 min;
+        UA_UInt32 max;
+    } *dimensions;
+} UA_NumericRange;
+
 /**
  * Builtin Types, Part 2
  * ---------------------
@@ -242,7 +267,8 @@ typedef int64_t UA_DateTime;
 /* The current time */
 UA_DateTime UA_EXPORT UA_DateTime_now(void);
 
-/* CPU clock invariant to system time changes. Use only for time diffs, not current time */
+/* CPU clock invariant to system time changes. Use only for time diffs, not
+ * current time */
 UA_DateTime UA_EXPORT UA_DateTime_nowMonotonic(void);
 
 typedef struct UA_DateTimeStruct {
@@ -284,10 +310,13 @@ typedef UA_String UA_ByteString;
 
 static UA_INLINE UA_Boolean
 UA_ByteString_equal(const UA_ByteString *string1, const UA_ByteString *string2) {
-    return UA_String_equal((const UA_String*)string1, (const UA_String*)string2); }
+    return UA_String_equal((const UA_String*)string1, (const UA_String*)string2);
+}
 
-/* Allocates memory of size length for the bytestring. The content is not set to zero. */
-UA_StatusCode UA_EXPORT UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length);
+/* Allocates memory of size length for the bytestring.
+ * The content is not set to zero. */
+UA_StatusCode UA_EXPORT
+UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length);
 
 UA_EXPORT extern const UA_ByteString UA_BYTESTRING_NULL;
 
@@ -314,8 +343,9 @@ typedef UA_String UA_XmlElement;
  * ^^^^^^
  * An identifier for a node in the address space of an OPC UA Server. */
 enum UA_NodeIdType {
-    UA_NODEIDTYPE_NUMERIC    = 0, /* In the binary encoding, this can also become 1 or 2
-                                     (2byte and 4byte encoding of small numeric nodeids) */
+    UA_NODEIDTYPE_NUMERIC    = 0, /* In the binary encoding, this can also
+                                     become 1 or 2 (2byte and 4byte encoding of
+                                     small numeric nodeids) */
     UA_NODEIDTYPE_STRING     = 3,
     UA_NODEIDTYPE_GUID       = 4,
     UA_NODEIDTYPE_BYTESTRING = 5
@@ -489,8 +519,9 @@ typedef struct {
         UA_EXTENSIONOBJECT_ENCODED_BYTESTRING = 1,
         UA_EXTENSIONOBJECT_ENCODED_XML        = 2,
         UA_EXTENSIONOBJECT_DECODED            = 3,
-        UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4 /* Don't delete the decoded content
-                                                     at the lifecycle end */
+        UA_EXTENSIONOBJECT_DECODED_NODELETE   = 4 /* Don't delete the content
+                                                     together with the
+                                                     ExtensionObject */
     } encoding;
     union {
         struct {
@@ -532,18 +563,20 @@ typedef struct {
 typedef struct {
     const UA_DataType *type; /* The data type description */
     enum {
-        UA_VARIANT_DATA,          /* The data has the same lifecycle as the variant */
-        UA_VARIANT_DATA_NODELETE, /* The data is "borrowed" by the variant and shall not be
-                                     deleted at the end of the variant's lifecycle. */
+        UA_VARIANT_DATA,          /* The data has the same lifecycle as the
+                                     variant */
+        UA_VARIANT_DATA_NODELETE, /* The data is "borrowed" by the variant and
+                                     shall not be deleted at the end of the
+                                     variant's lifecycle. */
     } storageType;
-    size_t arrayLength;  // The number of elements in the data array
-    void *data; // Points to the scalar or array data
-    size_t arrayDimensionsSize; // The number of dimensions the data-array has
-    UA_Int32 *arrayDimensions; // The length of each dimension of the data-array
+    size_t arrayLength;         /* The number of elements in the data array */
+    void *data;                 /* Points to the scalar or array data */
+    size_t arrayDimensionsSize; /* The number of dimensions the data-array has */
+    UA_Int32 *arrayDimensions;  /* The length of each dimension */
 } UA_Variant;
 
-/* Returns true if the variant contains a scalar value. Note that empty variants contain
- * an array of length -1 (undefined).
+/* Returns true if the variant contains a scalar value. Note that empty variants
+ * contain an array of length -1 (undefined).
  *
  * @param v The variant
  * @return Does the variant contain a scalar value. */
@@ -552,23 +585,27 @@ UA_Variant_isScalar(const UA_Variant *v) {
     return (v->arrayLength == 0 && v->data > UA_EMPTY_ARRAY_SENTINEL);
 }
 
-/* Set the variant to a scalar value that already resides in memory. The value takes on
- * the lifecycle of the variant and is deleted with it.
+/* Set the variant to a scalar value that already resides in memory. The value
+ * takes on the lifecycle of the variant and is deleted with it.
  *
  * @param v The variant
  * @param p A pointer to the value data
  * @param type The datatype of the value in question */
-void UA_EXPORT UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p, const UA_DataType *type);
+void UA_EXPORT
+UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
+                     const UA_DataType *type);
 
 /* Set the variant to a scalar value that is copied from an existing variable.
  * @param v The variant
  * @param p A pointer to the value data
  * @param type The datatype of the value
  * @return Indicates whether the operation succeeded or returns an error code */
-UA_StatusCode UA_EXPORT UA_Variant_setScalarCopy(UA_Variant *v, const void *p, const UA_DataType *type);
+UA_StatusCode UA_EXPORT
+UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
+                         const UA_DataType *type);
 
-/* Set the variant to an array that already resides in memory. The array takes on the
- * lifecycle of the variant and is deleted with it.
+/* Set the variant to an array that already resides in memory. The array takes
+ * on the lifecycle of the variant and is deleted with it.
  *
  * @param v The variant
  * @param array A pointer to the array data
@@ -589,30 +626,17 @@ UA_StatusCode UA_EXPORT
 UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
                         size_t arraySize, const UA_DataType *type);
 
-/**
- * NumericRanges are used to indicate subsets of a (multidimensional) variant
- * array. NumericRange has no official type structure in the standard. On the
- * wire, it only exists as an encoded string, such as "1:2,0:3,5". The colon
- * separates min/max index and the comma separates dimensions. A single value
- * indicates a range with a single element (min==max). */
-typedef struct {
-    size_t dimensionsSize;
-    struct UA_NumericRangeDimension {
-        UA_UInt32 min;
-        UA_UInt32 max;
-    } *dimensions;
-} UA_NumericRange;
-
-/* Copy the variant, but use only a subset of the (multidimensional) array into a variant.
- * Returns an error code if the variant is not an array or if the indicated range does not
- * fit.
+/* Copy the variant, but use only a subset of the (multidimensional) array into
+ * a variant. Returns an error code if the variant is not an array or if the
+ * indicated range does not fit.
  *
  * @param src The source variant
  * @param dst The target variant
  * @param range The range of the copied data
  * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
-UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRange range);
+UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
+                     const UA_NumericRange range);
 
 /* Insert a range of data into an existing variant. The data array can't be
  * reused afterwards if it contains types without a fixed size (e.g. strings)
@@ -620,7 +644,8 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRan
  *
  * @param v The variant
  * @param dataArray The data array. The type must match the variant
- * @param dataArraySize The length of the data array. This is checked to match the range size.
+ * @param dataArraySize The length of the data array. This is checked to match
+ *        the range size.
  * @param range The range of where the new data is inserted
  * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
@@ -631,7 +656,8 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
  *
  * @param v The variant
  * @param dataArray The data array. The type must match the variant
- * @param dataArraySize The length of the data array. This is checked to match the range size.
+ * @param dataArraySize The length of the data array. This is checked to match
+ *        the range size.
  * @param range The range of where the new data is inserted
  * @return Returns UA_STATUSCODE_GOOD or an error code */
 UA_StatusCode UA_EXPORT
@@ -690,14 +716,17 @@ typedef struct {
 #ifdef UA_ENABLE_TYPENAMES
     const char *memberName;
 #endif
-    UA_UInt16 memberTypeIndex;    /* Index of the member in the array of data types */
-    UA_Byte   padding;            /* How much padding is there before this member element?
-                                     For arrays this is the padding before the size_t
-                                     lenght member. (No padding between size_t and the
+    UA_UInt16 memberTypeIndex;    /* Index of the member in the array of data
+                                     types */
+    UA_Byte   padding;            /* How much padding is there before this
+                                     member element? For arrays this is the
+                                     padding before the size_t lenght member.
+                                     (No padding between size_t and the
                                      following ptr.) */
-    UA_Boolean namespaceZero : 1; /* The type of the member is defined in namespace zero.
-                                     In this implementation, types from custom namespace
-                                     may contain members from the same namespace or ns0
+    UA_Boolean namespaceZero : 1; /* The type of the member is defined in
+                                     namespace zero. In this implementation,
+                                     types from custom namespace may contain
+                                     members from the same namespace or ns0
                                      only.*/
     UA_Boolean isArray       : 1; /* The member is an array */
 } UA_DataTypeMember;
@@ -710,9 +739,10 @@ struct UA_DataType {
     UA_UInt16  memSize;          /* Size of the struct in memory */
     UA_UInt16  typeIndex;        /* Index of the type in the datatypetable */
     UA_Byte    membersSize;      /* How many members does the type have? */
-    UA_Boolean builtin      : 1; /* The type is "builtin" and has dedicated de- and
-                                    encoding functions */
-    UA_Boolean fixedSize    : 1; /* The type (and its members) contains no pointers */
+    UA_Boolean builtin      : 1; /* The type is "builtin" and has dedicated de-
+                                    and encoding functions */
+    UA_Boolean fixedSize    : 1; /* The type (and its members) contains no
+                                    pointers */
     UA_Boolean overlayable  : 1; /* The type has the identical memory layout in
                                     memory and on the binary stream. */
     UA_DataTypeMember *members;
@@ -723,7 +753,8 @@ struct UA_DataType {
 /* Allocates and initializes a variable of type dataType
  *
  * @param type The datatype description
- * @return Returns the memory location of the variable or (void*)0 if no memory is available */
+ * @return Returns the memory location of the variable or (void*)0 if no
+ *         memory is available */
 void UA_EXPORT * UA_new(const UA_DataType *type) UA_FUNC_ATTR_MALLOC;
 
 /* Initializes a variable to default values
@@ -735,19 +766,21 @@ UA_init(void *p, const UA_DataType *type) {
     memset(p, 0, type->memSize);
 }
 
-/* Copies the content of two variables. If copying fails (e.g. because no memory was
- * available for an array), then dst is emptied and initialized to prevent memory leaks.
+/* Copies the content of two variables. If copying fails (e.g. because no memory
+ * was available for an array), then dst is emptied and initialized to prevent
+ * memory leaks.
  *
  * @param src The memory location of the source variable
  * @param dst The memory location of the destination variable
  * @param type The datatype description
  * @return Indicates whether the operation succeeded or returns an error code */
-UA_StatusCode UA_EXPORT UA_copy(const void *src, void *dst, const UA_DataType *type);
+UA_StatusCode UA_EXPORT
+UA_copy(const void *src, void *dst, const UA_DataType *type);
 
-/* Deletes the dynamically allocated content of a variable (e.g. resets all arrays to
- * undefined arrays). Afterwards, the variable can be safely deleted without causing
- * memory leaks. But the variable is not initialized and may contain old data that is not
- * memory-relevant.
+/* Deletes the dynamically allocated content of a variable (e.g. resets all
+ * arrays to undefined arrays). Afterwards, the variable can be safely deleted
+ * without causing memory leaks. But the variable is not initialized and may
+ * contain old data that is not memory-relevant.
  *
  * @param p The memory location of the variable
  * @param type The datatype description of the variable */
@@ -762,11 +795,12 @@ void UA_EXPORT UA_delete(void *p, const UA_DataType *type);
 /**
  * Random Number Generator
  * -----------------------
- * If UA_ENABLE_MULTITHREADING is defined, then the seed is stored in thread local
- * storage. The seed is initialized for every thread in the server/client. */
+ * If UA_ENABLE_MULTITHREADING is defined, then the seed is stored in thread
+ * local storage. The seed is initialized for every thread in the
+ * server/client. */
 void UA_EXPORT UA_random_seed(UA_UInt64 seed);
-UA_UInt32 UA_EXPORT UA_UInt32_random(void); /* do not use for cryptographic entropy */
-UA_Guid UA_EXPORT UA_Guid_random(void); /* do not use for cryptographic entropy */
+UA_UInt32 UA_EXPORT UA_UInt32_random(void); /* no cryptographic entropy */
+UA_Guid UA_EXPORT UA_Guid_random(void);     /* no cryptographic entropy */
 
 #ifdef __cplusplus
 } // extern "C"

+ 16 - 0
plugins/ua_config_standard.c

@@ -108,3 +108,19 @@ const UA_EXPORT UA_ClientConfig UA_ClientConfig_standard = {
     },
     .connectionFunc = UA_ClientConnectionTCP
 };
+/****************************************/
+/* Default Client Subscription Settings */
+/****************************************/
+
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+
+const UA_SubscriptionSettings UA_SubscriptionSettings_standard = {
+    .requestedPublishingInterval = 500.0,
+    .requestedLifetimeCount = 10000,
+    .requestedMaxKeepAliveCount = 1,
+    .maxNotificationsPerPublish = 10,
+    .publishingEnabled = true,
+    .priority = 0
+};
+
+#endif

+ 1 - 0
plugins/ua_config_standard.h

@@ -6,6 +6,7 @@
 
 #include "ua_server.h"
 #include "ua_client.h"
+#include "ua_client_highlevel.h"
 
 #ifdef __cplusplus
 extern "C" {

+ 6 - 5
plugins/ua_log_stdout.c

@@ -5,13 +5,14 @@
 #include <stdarg.h>
 #include "ua_log_stdout.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 
 const char *LogLevelNames[6] = {"trace", "debug", "info", "warning", "error", "fatal"};
 const char *LogCategoryNames[6] = {"network", "channel", "session", "server", "client", "userland"};
 
-#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#if (defined(__GNUC__) && defined(__GNUC_MINOR__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-nonliteral"
 #endif
 
 void UA_Log_Stdout(UA_LogLevel level, UA_LogCategory category, const char *msg, ...) {
@@ -25,6 +26,6 @@ void UA_Log_Stdout(UA_LogLevel level, UA_LogCategory category, const char *msg,
     printf("\n");
 }
 
-#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
-#pragma GCC diagnostic pop
+#if (defined(__GNUC__) && defined(__GNUC_MINOR__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+# pragma GCC diagnostic pop
 #endif

+ 14 - 9
src/client/ua_client.c

@@ -4,10 +4,11 @@
 #include "ua_client_internal.h"
 #include "ua_connection_internal.h"
 #include "ua_types_generated.h"
-#include "ua_nodeids.h"
 #include "ua_types_encoding_binary.h"
-#include "ua_transport_generated.h"
 #include "ua_types_generated_encoding_binary.h"
+#include "ua_nodeids.h"
+#include "ua_transport_generated.h"
+#include "ua_transport_generated_handling.h"
 #include "ua_transport_generated_encoding_binary.h"
 
 /*********************/
@@ -59,6 +60,7 @@ static void UA_Client_deleteMembers(UA_Client* client) {
     if(client->endpointUrl.data)
         UA_String_deleteMembers(&client->endpointUrl);
     UA_UserTokenPolicy_deleteMembers(&client->token);
+    UA_NodeId_deleteMembers(&client->authenticationToken);
     if(client->username.data)
         UA_String_deleteMembers(&client->username);
     if(client->password.data)
@@ -339,7 +341,6 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
     UA_ActivateSessionRequest_init(&request);
 
     request.requestHeader.requestHandle = ++client->requestHandle;
-    request.requestHeader.authenticationToken = client->authenticationToken;
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 600000;
 
@@ -384,7 +385,6 @@ static UA_StatusCode
 GetEndpoints(UA_Client *client, size_t* endpointDescriptionsSize, UA_EndpointDescription** endpointDescriptions) {
     UA_GetEndpointsRequest request;
     UA_GetEndpointsRequest_init(&request);
-    request.requestHeader.authenticationToken = client->authenticationToken;
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
     request.endpointUrl = client->endpointUrl; // assume the endpointurl outlives the service call
@@ -468,8 +468,6 @@ static UA_StatusCode SessionHandshake(UA_Client *client) {
     UA_CreateSessionRequest request;
     UA_CreateSessionRequest_init(&request);
 
-    // todo: is this needed for all requests?
-    UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
     UA_ByteString_copy(&client->channel->clientNonce, &request.clientNonce);
@@ -495,7 +493,6 @@ static UA_StatusCode CloseSession(UA_Client *client) {
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
     request.deleteSubscriptions = true;
-    UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
     UA_CloseSessionResponse response;
     __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
                         &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
@@ -512,7 +509,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
     request.requestHeader.requestHandle = ++client->requestHandle;
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
-    request.requestHeader.authenticationToken = client->authenticationToken;
+    UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
 
     UA_SecureConversationMessageHeader msgHeader;
     msgHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_CLO + UA_CHUNKTYPE_FINAL;
@@ -530,8 +527,10 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
     UA_ByteString message;
     UA_Connection *c = client->connection;
     UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
-    if(retval != UA_STATUSCODE_GOOD)
+    if(retval != UA_STATUSCODE_GOOD){
+        UA_CloseSecureChannelRequest_deleteMembers(&request);
         return retval;
+    }
 
     size_t offset = 12;
     retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
@@ -551,6 +550,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
         client->connection->releaseSendBuffer(client->connection, &message);
     }
     client->connection->close(client->connection);
+    UA_CloseSecureChannelRequest_deleteMembers(&request);
     return retval;
 }
 
@@ -688,6 +688,7 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
     }
 
     /* handling request parameters */
+    //here const *r is 'violated'
     UA_NodeId_copy(&client->authenticationToken, &request->authenticationToken);
     request->timestamp = UA_DateTime_now();
     request->requestHandle = ++client->requestHandle;
@@ -717,6 +718,8 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
         if(retval != UA_STATUSCODE_GOOD) {
             respHeader->serviceResult = retval;
             client->state = UA_CLIENTSTATE_ERRORED;
+            //free token
+            UA_NodeId_deleteMembers(&request->authenticationToken);
             return;
         }
     } while(!reply.data);
@@ -776,6 +779,8 @@ void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *re
     } else {
       client->state = UA_CLIENTSTATE_CONNECTED;
     }
+    //free token
+    UA_NodeId_deleteMembers(&request->authenticationToken);
     UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_CLIENT,
                  "Received a response of type %i", responseId.identifier.numeric);
 }

+ 0 - 9
src/client/ua_client_highlevel_subscriptions.c

@@ -5,15 +5,6 @@
 
 #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
 
-const UA_SubscriptionSettings UA_SubscriptionSettings_standard = {
-    .requestedPublishingInterval = 500.0,
-    .requestedLifetimeCount = 10000,
-    .requestedMaxKeepAliveCount = 1,
-    .maxNotificationsPerPublish = 10,
-    .publishingEnabled = true,
-    .priority = 0
-};
-
 UA_StatusCode UA_Client_Subscriptions_new(UA_Client *client, UA_SubscriptionSettings settings,
                                           UA_UInt32 *newSubscriptionId) {
     UA_CreateSubscriptionRequest request;

+ 16 - 8
src/server/ua_nodestore.h

@@ -36,14 +36,22 @@ void UA_NodeStore_delete(UA_NodeStore *ns);
  * added to the nodestore.) */
 /* Create an editable node of the given NodeClass. */
 UA_Node * UA_NodeStore_newNode(UA_NodeClass nodeClass);
-#define UA_NodeStore_newObjectNode() (UA_ObjectNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECT)
-#define UA_NodeStore_newVariableNode() (UA_VariableNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLE)
-#define UA_NodeStore_newMethodNode() (UA_MethodNode*)UA_NodeStore_newNode(UA_NODECLASS_METHOD)
-#define UA_NodeStore_newObjectTypeNode() (UA_ObjectTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECTTYPE)
-#define UA_NodeStore_newVariableTypeNode() (UA_VariableTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLETYPE)
-#define UA_NodeStore_newReferenceTypeNode() (UA_ReferenceTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_REFERENCETYPE)
-#define UA_NodeStore_newDataTypeNode() (UA_DataTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_DATATYPE)
-#define UA_NodeStore_newViewNode() (UA_ViewNode*)UA_NodeStore_newNode(UA_NODECLASS_VIEW)
+#define UA_NodeStore_newObjectNode() \
+	(UA_ObjectNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECT)
+#define UA_NodeStore_newVariableNode() \
+	(UA_VariableNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLE)
+#define UA_NodeStore_newMethodNode() \
+	(UA_MethodNode*)UA_NodeStore_newNode(UA_NODECLASS_METHOD)
+#define UA_NodeStore_newObjectTypeNode() \
+	(UA_ObjectTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECTTYPE)
+#define UA_NodeStore_newVariableTypeNode() \
+	(UA_VariableTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLETYPE)
+#define UA_NodeStore_newReferenceTypeNode() \
+	(UA_ReferenceTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_REFERENCETYPE)
+#define UA_NodeStore_newDataTypeNode() \
+	(UA_DataTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_DATATYPE)
+#define UA_NodeStore_newViewNode() \
+	(UA_ViewNode*)UA_NodeStore_newNode(UA_NODECLASS_VIEW)
 
 /* Delete an editable node. */
 void UA_NodeStore_deleteNode(UA_Node *node);

+ 37 - 284
src/server/ua_server.c

@@ -61,27 +61,25 @@ static const UA_NodeId nodeIdNonHierarchicalReferences = {
 /* Namespace Handling */
 /**********************/
 
-static UA_UInt16 addNamespaceInternal(UA_Server *server, const UA_String *name) {
-    //check if the namespace already exists in the server's namespace array
+UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
+    /* Override const attribute to get string (dirty hack) */
+    const UA_String nameString = (UA_String){.length = strlen(name),
+                                             .data = (UA_Byte*)(uintptr_t)name};
+
+    /* Check if the namespace already exists in the server's namespace array */
     for(UA_UInt16 i=0;i<server->namespacesSize;i++) {
-        if(UA_String_equal(name, &server->namespaces[i]))
+        if(UA_String_equal(&nameString, &server->namespaces[i]))
             return i;
     }
-    //the namespace URI did not match - add a new namespace to the namsepace array
+
+    /* Add a new namespace to the namsepace array */
     server->namespaces = UA_realloc(server->namespaces,
-        sizeof(UA_String) * (server->namespacesSize + 1));
-    UA_String_copy(name, &(server->namespaces[server->namespacesSize]));
+                                    sizeof(UA_String) * (server->namespacesSize + 1));
+    UA_String_copy(&nameString, &server->namespaces[server->namespacesSize]);
     server->namespacesSize++;
     return (UA_UInt16)(server->namespacesSize - 1);
 }
 
-UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
-    UA_String nameString = UA_STRING_ALLOC(name);
-    UA_UInt16 retVal = addNamespaceInternal(server, &nameString);
-    UA_String_deleteMembers(&nameString);
-    return retVal;
-}
-
 #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
 static void UA_ExternalNamespace_init(UA_ExternalNamespace *ens) {
     ens->index = 0;
@@ -105,9 +103,17 @@ static void UA_Server_deleteExternalNamespaces(UA_Server *server) {
 
 UA_StatusCode UA_EXPORT
 UA_Server_addExternalNamespace(UA_Server *server, const UA_String *url,
-                               UA_ExternalNodeStore *nodeStore, UA_UInt16 *assignedNamespaceIndex) {
+                               UA_ExternalNodeStore *nodeStore,
+                               UA_UInt16 *assignedNamespaceIndex) {
     if(!nodeStore)
         return UA_STATUSCODE_BADARGUMENTSMISSING;
+
+    char urlString[256];
+    if(url.length >= 256)
+        return UA_STATUSCODE_BADINTERNALERROR;
+    memcpy(urlString, url.data, url.length);
+    urlString[url.length] = 0;
+
     size_t size = server->externalNamespacesSize;
     server->externalNamespaces =
         UA_realloc(server->externalNamespaces, sizeof(UA_ExternalNamespace) * (size + 1));
@@ -116,35 +122,12 @@ UA_Server_addExternalNamespace(UA_Server *server, const UA_String *url,
     *assignedNamespaceIndex = (UA_UInt16)server->namespacesSize;
     UA_String_copy(url, &server->externalNamespaces[size].url);
     server->externalNamespacesSize++;
-    addNamespaceInternal(server, url);
+    addNamespaceInternal(server, urlString);
+
     return UA_STATUSCODE_GOOD;
 }
 #endif /* UA_ENABLE_EXTERNAL_NAMESPACES*/
 
-UA_StatusCode
-UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId, UA_Boolean deleteReferences) {
-    UA_RCU_LOCK();
-    UA_StatusCode retval = Service_DeleteNodes_single(server, &adminSession, &nodeId, deleteReferences);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-UA_StatusCode
-UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
-                          UA_Boolean isForward, const UA_ExpandedNodeId targetNodeId,
-                          UA_Boolean deleteBidirectional) {
-    UA_DeleteReferencesItem item;
-    item.sourceNodeId = sourceNodeId;
-    item.referenceTypeId = referenceTypeId;
-    item.isForward = isForward;
-    item.targetNodeId = targetNodeId;
-    item.deleteBidirectional = deleteBidirectional;
-    UA_RCU_LOCK();
-    UA_StatusCode retval = Service_DeleteReferences_single(server, &adminSession, &item);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
 UA_StatusCode
 UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
                                UA_NodeIteratorCallback callback, void *handle) {
@@ -164,22 +147,6 @@ UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
     return retval;
 }
 
-UA_StatusCode
-UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
-                       const UA_NodeId refTypeId, const UA_ExpandedNodeId targetId,
-                       UA_Boolean isForward) {
-    UA_AddReferencesItem item;
-    UA_AddReferencesItem_init(&item);
-    item.sourceNodeId = sourceId;
-    item.referenceTypeId = refTypeId;
-    item.isForward = isForward;
-    item.targetNodeId = targetId;
-    UA_RCU_LOCK();
-    UA_StatusCode retval = Service_AddReferences_single(server, &adminSession, &item);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
 static UA_StatusCode
 addReferenceInternal(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId,
                      const UA_ExpandedNodeId targetId, UA_Boolean isForward) {
@@ -219,36 +186,6 @@ addNodeInternalWithType(UA_Server *server, UA_Node *node, const UA_NodeId parent
     return res;
 }
 
-UA_StatusCode
-__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
-                    const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
-                    const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
-                    const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
-                    const UA_DataType *attributeType,
-                    UA_InstantiationCallback *instantiationCallback, UA_NodeId *outNewNodeId) {
-    UA_AddNodesItem item;
-    UA_AddNodesItem_init(&item);
-    item.parentNodeId.nodeId = parentNodeId;
-    item.referenceTypeId = referenceTypeId;
-    item.requestedNewNodeId.nodeId = requestedNewNodeId;
-    item.browseName = browseName;
-    item.nodeClass = nodeClass;
-    item.typeDefinition.nodeId = typeDefinition;
-    item.nodeAttributes = (UA_ExtensionObject){.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE,
-                                               .content.decoded = {attributeType, (void*)(uintptr_t)attr}};
-    UA_AddNodesResult result;
-    UA_AddNodesResult_init(&result);
-    UA_RCU_LOCK();
-    Service_AddNodes_single(server, &adminSession, &item, &result, instantiationCallback);
-    UA_RCU_UNLOCK();
-
-    if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
-        *outNewNodeId = result.addedNodeId;
-    else
-        UA_AddNodesResult_deleteMembers(&result);
-    return result.statusCode;
-}
-
 /**********/
 /* Server */
 /**********/
@@ -452,10 +389,18 @@ createVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
     return variabletype;
 }
 
+static void
+addVariableTypeNode_organized(UA_Server *server, char* name, UA_UInt32 variabletypeid,
+                              UA_UInt32 parent, UA_Boolean abstract) {
+    UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
+    addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdOrganizes);
+}
+
 static void
 addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32 variabletypeid,
                             UA_UInt32 parent, UA_Boolean abstract) {
-    UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
+    UA_VariableTypeNode *variabletype =
+        createVariableTypeNode(server, name, variabletypeid, parent, abstract);
     addNodeInternal(server, (UA_Node*)variabletype, UA_NODEID_NUMERIC(0, parent), nodeIdHasSubType);
 }
 
@@ -720,8 +665,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
     hasnotifier->isAbstract = false;
     hasnotifier->symmetric  = false;
-    addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE),
-                    nodeIdHasSubType);
+    addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasorderedcomponent = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
@@ -729,8 +673,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
     hasorderedcomponent->isAbstract = false;
     hasorderedcomponent->symmetric  = false;
-    addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-                    nodeIdHasSubType);
+    addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasmodelparent = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)hasmodelparent, "HasModelParent");
@@ -763,7 +706,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     hascause->isAbstract = false;
     hascause->symmetric  = false;
     addNodeInternal(server, (UA_Node*)hascause, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
-
+    
     UA_ReferenceTypeNode *haseffect = UA_NodeStore_newReferenceTypeNode();
     copyNames((UA_Node*)haseffect, "HasEffect");
     haseffect->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeEffectedBy");
@@ -842,6 +785,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     /* Link in the bootstrapped baseobjecttype */
     addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdOrganizes,
                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), true);
+
     addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
     addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
                       UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
@@ -895,26 +839,13 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     addDataTypeNode(server, "Enumeration", UA_NS0ID_ENUMERATION, UA_NS0ID_BASEDATATYPE);
         addDataTypeNode(server, "ServerState", UA_NS0ID_SERVERSTATE, UA_NS0ID_ENUMERATION);
 
-    /******************/
-    /* Variable Types */
-    /******************/
-
     UA_ObjectNode *variabletypes = UA_NodeStore_newObjectNode();
     copyNames((UA_Node*)variabletypes, "VariableTypes");
     variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
     addNodeInternalWithType(server, (UA_Node*)variabletypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
                             nodeIdOrganizes, nodeIdFolderType);
-
-    /* Bootstrap the BaseVariableType */
-    UA_VariableTypeNode *basevariabletype = UA_NodeStore_newVariableTypeNode();
-    copyNames((UA_Node*)basevariabletype, "BaseVariableType");
-    basevariabletype->nodeId.identifier.numeric = UA_NS0ID_BASEVARIABLETYPE;
-    UA_RCU_LOCK();
-    UA_NodeStore_insert(server->nodestore, (UA_Node*)basevariabletype);
-    UA_RCU_UNLOCK();
-    addReferenceInternal(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER), nodeIdOrganizes,
-                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE), true);
-
+    addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE,
+                                  UA_NS0ID_VARIABLETYPESFOLDER, true);
     addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
                                 UA_NS0ID_BASEVARIABLETYPE, false);
     addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE,
@@ -1344,184 +1275,6 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     return server;
 }
 
-UA_StatusCode
-__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
-                  const UA_AttributeId attributeId, const UA_DataType *attr_type,
-                  const void *value) {
-    UA_WriteValue wvalue;
-    UA_WriteValue_init(&wvalue);
-    wvalue.nodeId = *nodeId;
-    wvalue.attributeId = attributeId;
-    if(attributeId != UA_ATTRIBUTEID_VALUE)
-        /* hacked cast. the target WriteValue is used as const anyway */
-        UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)value, attr_type);
-    else {
-        if(attr_type != &UA_TYPES[UA_TYPES_VARIANT])
-            return UA_STATUSCODE_BADTYPEMISMATCH;
-        wvalue.value.value = *(const UA_Variant*)value;
-    }
-    wvalue.value.hasValue = true;
-    UA_RCU_LOCK();
-    UA_StatusCode retval = Service_Write_single(server, &adminSession, &wvalue);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-static UA_StatusCode
-setValueCallback(UA_Server *server, UA_Session *session, UA_VariableNode *node, UA_ValueCallback *callback) {
-    if(node->nodeClass != UA_NODECLASS_VARIABLE)
-        return UA_STATUSCODE_BADNODECLASSINVALID;
-    node->value.variant.callback = *callback;
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_EXPORT
-UA_Server_setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId,
-                                        const UA_ValueCallback callback) {
-    UA_RCU_LOCK();
-    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
-                                              (UA_EditNodeCallback)setValueCallback, &callback);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-static UA_StatusCode
-setDataSource(UA_Server *server, UA_Session *session,
-              UA_VariableNode* node, UA_DataSource *dataSource) {
-    if(node->nodeClass != UA_NODECLASS_VARIABLE)
-        return UA_STATUSCODE_BADNODECLASSINVALID;
-    if(node->valueSource == UA_VALUESOURCE_VARIANT)
-        UA_Variant_deleteMembers(&node->value.variant.value);
-    node->value.dataSource = *dataSource;
-    node->valueSource = UA_VALUESOURCE_DATASOURCE;
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
-                                     const UA_DataSource dataSource) {
-    UA_RCU_LOCK();
-    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
-                                              (UA_EditNodeCallback)setDataSource, &dataSource);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-static UA_StatusCode
-setObjectTypeLifecycleManagement(UA_Server *server, UA_Session *session, UA_ObjectTypeNode* node,
-                                 UA_ObjectLifecycleManagement *olm) {
-    if(node->nodeClass != UA_NODECLASS_OBJECTTYPE)
-        return UA_STATUSCODE_BADNODECLASSINVALID;
-    node->lifecycleManagement = *olm;
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_EXPORT
-UA_Server_setObjectTypeNode_lifecycleManagement(UA_Server *server, UA_NodeId nodeId,
-                                                UA_ObjectLifecycleManagement olm) {
-    UA_RCU_LOCK();
-    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
-                                              (UA_EditNodeCallback)setObjectTypeLifecycleManagement, &olm);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-#ifdef UA_ENABLE_METHODCALLS
-
-struct addMethodCallback {
-    UA_MethodCallback callback;
-    void *handle;
-};
-
-static UA_StatusCode
-editMethodCallback(UA_Server *server, UA_Session* session, UA_Node* node, const void* handle) {
-    if(node->nodeClass != UA_NODECLASS_METHOD)
-        return UA_STATUSCODE_BADNODECLASSINVALID;
-    const struct addMethodCallback *newCallback = handle;
-    UA_MethodNode *mnode = (UA_MethodNode*) node;
-    mnode->attachedMethod = newCallback->callback;
-    mnode->methodHandle   = newCallback->handle;
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_EXPORT
-UA_Server_setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId,
-                                 UA_MethodCallback method, void *handle) {
-    struct addMethodCallback cb = { method, handle };
-    UA_RCU_LOCK();
-    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &methodNodeId, editMethodCallback, &cb);
-    UA_RCU_UNLOCK();
-    return retval;
-}
-
-#endif
-
-UA_StatusCode
-__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId, const UA_AttributeId attributeId, void *v) {
-    UA_ReadValueId item;
-    UA_ReadValueId_init(&item);
-    item.nodeId = *nodeId;
-    item.attributeId = attributeId;
-    UA_DataValue dv;
-    UA_DataValue_init(&dv);
-    UA_RCU_LOCK();
-    Service_Read_single(server, &adminSession, UA_TIMESTAMPSTORETURN_NEITHER,
-                        &item, &dv);
-    UA_RCU_UNLOCK();
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    if(dv.hasStatus)
-        retval = dv.hasStatus;
-    else if(!dv.hasValue)
-        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
-    if(retval != UA_STATUSCODE_GOOD) {
-        UA_DataValue_deleteMembers(&dv);
-        return retval;
-    }
-    if(attributeId == UA_ATTRIBUTEID_VALUE ||
-       attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS)
-        memcpy(v, &dv.value, sizeof(UA_Variant));
-    else {
-        memcpy(v, dv.value.data, dv.value.type->memSize);
-        dv.value.data = NULL;
-        dv.value.arrayLength = 0;
-        UA_Variant_deleteMembers(&dv.value);
-    }
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_BrowseResult
-UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr) {
-    UA_BrowseResult result;
-    UA_BrowseResult_init(&result);
-    UA_RCU_LOCK();
-    Service_Browse_single(server, &adminSession, NULL, descr, maxrefs, &result);
-    UA_RCU_UNLOCK();
-    return result;
-}
-
-UA_BrowseResult
-UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
-                     const UA_ByteString *continuationPoint) {
-    UA_BrowseResult result;
-    UA_BrowseResult_init(&result);
-    UA_RCU_LOCK();
-    UA_Server_browseNext_single(server, &adminSession, releaseContinuationPoint,
-                                continuationPoint, &result);
-    UA_RCU_UNLOCK();
-    return result;
-}
-
-#ifdef UA_ENABLE_METHODCALLS
-UA_CallMethodResult UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
-    UA_CallMethodResult result;
-    UA_CallMethodResult_init(&result);
-    UA_RCU_LOCK();
-    Service_Call_single(server, &adminSession, request, &result);
-    UA_RCU_UNLOCK();
-    return result;
-}
-#endif
-
 #ifdef UA_ENABLE_DISCOVERY
 static UA_StatusCode register_server_with_discovery_server(UA_Server *server, const char* discoveryServerUrl, const UA_Boolean isUnregister, const char* semaphoreFilePath) {
     UA_Client *client = UA_Client_new(UA_ClientConfig_standard);

+ 1 - 0
src/server/ua_server_binary.c

@@ -5,6 +5,7 @@
 #include "ua_session_manager.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_transport_generated.h"
+#include "ua_transport_generated_handling.h"
 #include "ua_transport_generated_encoding_binary.h"
 
 /********************/

+ 18 - 20
src/server/ua_services.h

@@ -79,7 +79,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
  * any other Service request after CreateSession. Failure to do so shall cause
  * the Server to close the Session. */
 void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
-                             UA_Session *session, const UA_ActivateSessionRequest *request,
+                             UA_Session *session,
+                             const UA_ActivateSessionRequest *request,
                              UA_ActivateSessionResponse *response);
 
 /* Used to terminate a Session. */
@@ -102,16 +103,14 @@ void Service_AddNodes(UA_Server *server, UA_Session *session,
                       const UA_AddNodesRequest *request,
                       UA_AddNodesResponse *response);
 
-void Service_AddNodes_single(UA_Server *server, UA_Session *session,
-                             const UA_AddNodesItem *item, UA_AddNodesResult *result,
-                             UA_InstantiationCallback *instantiationCallback);
-
 /* Add an existing node. The node is assumed to be "finished", i.e. no
  * instantiation from inheritance is necessary */
 void
 Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
-                          const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
-                          const UA_NodeId *typeDefinition, UA_InstantiationCallback *instantiationCallback,
+                          const UA_NodeId *parentNodeId,
+                          const UA_NodeId *referenceTypeId,
+                          const UA_NodeId *typeDefinition,
+                          UA_InstantiationCallback *instantiationCallback,
                           UA_AddNodesResult *result);
 
 /* Used to add one or more References to one or more Nodes. */
@@ -119,7 +118,8 @@ void Service_AddReferences(UA_Server *server, UA_Session *session,
                            const UA_AddReferencesRequest *request,
                            UA_AddReferencesResponse *response);
 
-UA_StatusCode Service_AddReferences_single(UA_Server *server, UA_Session *session,
+UA_StatusCode Service_AddReferences_single(UA_Server *server,
+                                           UA_Session *session,
                                            const UA_AddReferencesItem *item);
 
 /* Used to delete one or more Nodes from the AddressSpace. */
@@ -136,8 +136,8 @@ void Service_DeleteReferences(UA_Server *server, UA_Session *session,
                               const UA_DeleteReferencesRequest *request,
                               UA_DeleteReferencesResponse *response);
 
-UA_StatusCode Service_DeleteReferences_single(UA_Server *server, UA_Session *session,
-                                              const UA_DeleteReferencesItem *item);
+UA_StatusCode Service_DeleteReferences_single(UA_Server *server,
+                      UA_Session *session, const UA_DeleteReferencesItem *item);
 
 /**
  * View Service Set
@@ -153,7 +153,8 @@ void Service_Browse(UA_Server *server, UA_Session *session,
                     UA_BrowseResponse *response);
 
 void Service_Browse_single(UA_Server *server, UA_Session *session,
-                           struct ContinuationPointEntry *cp, const UA_BrowseDescription *descr,
+                           struct ContinuationPointEntry *cp,
+                           const UA_BrowseDescription *descr,
                            UA_UInt32 maxrefs, UA_BrowseResult *result);
 
 /* Used to request the next set of Browse or BrowseNext response information
@@ -165,17 +166,13 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session,
                         const UA_BrowseNextRequest *request,
                         UA_BrowseNextResponse *response);
 
-void UA_Server_browseNext_single(UA_Server *server, UA_Session *session,
-                                 UA_Boolean releaseContinuationPoint,
-                                 const UA_ByteString *continuationPoint,
-                                 UA_BrowseResult *result);
-
 /* Used to translate textual node paths to their respective ids. */
 void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
-                                           const UA_TranslateBrowsePathsToNodeIdsRequest *request,
-                                           UA_TranslateBrowsePathsToNodeIdsResponse *response);
+             const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+             UA_TranslateBrowsePathsToNodeIdsResponse *response);
 
-void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session *session,
+void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server,
+                                                  UA_Session *session,
                                                   const UA_BrowsePath *path,
                                                   UA_BrowsePathResult *result);
 
@@ -283,7 +280,8 @@ void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
                                   const UA_ModifyMonitoredItemsRequest *request,
                                   UA_ModifyMonitoredItemsResponse *response);
 
-/* Used to set the monitoring mode for one or more MonitoredItems of a Subscription. */
+/* Used to set the monitoring mode for one or more MonitoredItems of a
+   Subscription. */
 void Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
                                const UA_SetMonitoringModeRequest *request,
                                UA_SetMonitoringModeResponse *response);

+ 153 - 42
src/server/ua_services_attribute.c

@@ -56,7 +56,8 @@ UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range) {
         /* alloc dimensions */
         if(idx >= dimensionsMax) {
             struct UA_NumericRangeDimension *newds;
-            newds = UA_realloc(dimensions, sizeof(struct UA_NumericRangeDimension) * (dimensionsMax + 2));
+            size_t newdssize = sizeof(struct UA_NumericRangeDimension) * (dimensionsMax + 2);
+            newds = UA_realloc(dimensions, newdssize);
             if(!newds) {
                 retval = UA_STATUSCODE_BADOUTOFMEMORY;
                 break;
@@ -66,7 +67,8 @@ UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range) {
         }
 
         /* read the dimension */
-        size_t progress = readDimension(&str->data[offset], str->length - offset, &dimensions[idx]);
+        size_t progress = readDimension(&str->data[offset], str->length - offset,
+                                        &dimensions[idx]);
         if(progress == 0) {
             retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
             break;
@@ -100,15 +102,19 @@ UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range) {
         break;                                                  \
     }
 
-static void handleServerTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
-    if(v && (timestamps == UA_TIMESTAMPSTORETURN_SERVER || timestamps == UA_TIMESTAMPSTORETURN_BOTH)) {
+static void
+handleServerTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
+    if(v && (timestamps == UA_TIMESTAMPSTORETURN_SERVER ||
+             timestamps == UA_TIMESTAMPSTORETURN_BOTH)) {
         v->hasServerTimestamp = true;
         v->serverTimestamp = UA_DateTime_now();
     }
 }
 
-static void handleSourceTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
-    if(timestamps == UA_TIMESTAMPSTORETURN_SOURCE || timestamps == UA_TIMESTAMPSTORETURN_BOTH) {
+static void
+handleSourceTimestamps(UA_TimestampsToReturn timestamps, UA_DataValue* v) {
+    if(timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
+       timestamps == UA_TIMESTAMPSTORETURN_BOTH) {
         v->hasSourceTimestamp = true;
         v->sourceTimestamp = UA_DateTime_now();
     }
@@ -123,8 +129,10 @@ static void forceVariantSetScalar(UA_Variant *v, const void *p, const UA_DataTyp
 }
 
 static UA_StatusCode
-getVariableNodeValue(UA_Server *server, UA_Session *session, const UA_VariableNode *vn,
-                     const UA_TimestampsToReturn timestamps, const UA_ReadValueId *id, UA_DataValue *v) {
+getVariableNodeValue(UA_Server *server, UA_Session *session,
+                     const UA_VariableNode *vn,
+                     const UA_TimestampsToReturn timestamps,
+                     const UA_ReadValueId *id, UA_DataValue *v) {
     UA_NumericRange range;
     UA_NumericRange *rangeptr = NULL;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
@@ -148,7 +156,8 @@ getVariableNodeValue(UA_Server *server, UA_Session *session, const UA_VariableNo
             handleSourceTimestamps(timestamps, v);
     } else {
         if(!vn->value.dataSource.read) {
-            UA_LOG_DEBUG_SESSION(server->config.logger, session, "DataSource cannot be read in ReadRequest");
+            UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                 "DataSource cannot be read in ReadRequest");
             retval = UA_STATUSCODE_BADINTERNALERROR;
         } else {
             UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
@@ -169,7 +178,8 @@ getVariableNodeDataType(UA_Server *server, UA_Session *session,
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     if(vn->valueSource == UA_VALUESOURCE_VARIANT) {
         if(vn->value.variant.value.type) {
-            forceVariantSetScalar(&v->value, &vn->value.variant.value.type->typeId, &UA_TYPES[UA_TYPES_NODEID]);
+            forceVariantSetScalar(&v->value, &vn->value.variant.value.type->typeId,
+                                  &UA_TYPES[UA_TYPES_NODEID]);
         } else {
             UA_NodeId nullid;
             UA_NodeId_init(&nullid);
@@ -178,17 +188,20 @@ getVariableNodeDataType(UA_Server *server, UA_Session *session,
     } else {
         /* Read from the datasource to see the data type */
         if(!vn->value.dataSource.read) {
-            UA_LOG_DEBUG_SESSION(server->config.logger, session, "DataSource cannot be read in ReadRequest");
+            UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                 "DataSource cannot be read in ReadRequest");
             return UA_STATUSCODE_BADINTERNALERROR;
         }
         UA_DataValue val;
         UA_DataValue_init(&val);
         val.hasValue = false; // always assume we are not given a value by userspace
-        retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId, false, NULL, &val);
+        retval = vn->value.dataSource.read(vn->value.dataSource.handle,
+                                           vn->nodeId, false, NULL, &val);
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
         if(val.hasValue && val.value.type)
-          retval = UA_Variant_setScalarCopy(&v->value, &val.value.type->typeId, &UA_TYPES[UA_TYPES_NODEID]);
+          retval = UA_Variant_setScalarCopy(&v->value, &val.value.type->typeId,
+                                            &UA_TYPES[UA_TYPES_NODEID]);
         UA_DataValue_deleteMembers(&val);
     }
     return retval;
@@ -200,21 +213,25 @@ getVariableNodeArrayDimensions(UA_Server *server, UA_Session *session,
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     if(vn->valueSource == UA_VALUESOURCE_VARIANT) {
         UA_Variant_setArray(&v->value, vn->value.variant.value.arrayDimensions,
-                            vn->value.variant.value.arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
+                            vn->value.variant.value.arrayDimensionsSize,
+                            &UA_TYPES[UA_TYPES_INT32]);
         v->value.storageType = UA_VARIANT_DATA_NODELETE;
     } else {
         if(!vn->value.dataSource.read) {
-            UA_LOG_DEBUG_SESSION(server->config.logger, session, "DataSource cannot be read in ReadRequest");
+            UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                 "DataSource cannot be read in ReadRequest");
             return UA_STATUSCODE_BADINTERNALERROR;
         }
         /* Read the datasource to see the array dimensions */
         UA_DataValue val;
         UA_DataValue_init(&val);
-        retval = vn->value.dataSource.read(vn->value.dataSource.handle, vn->nodeId, false, NULL, &val);
+        retval = vn->value.dataSource.read(vn->value.dataSource.handle,
+                                           vn->nodeId, false, NULL, &val);
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
         retval = UA_Variant_setArrayCopy(&v->value, val.value.arrayDimensions,
-                                         val.value.arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
+                                         val.value.arrayDimensionsSize,
+                                         &UA_TYPES[UA_TYPES_INT32]);
         UA_DataValue_deleteMembers(&val);
     }
     return retval;
@@ -228,7 +245,8 @@ static const UA_String binEncoding = {sizeof("DefaultBinary")-1, (UA_Byte*)"Defa
 void Service_Read_single(UA_Server *server, UA_Session *session,
                          const UA_TimestampsToReturn timestamps,
                          const UA_ReadValueId *id, UA_DataValue *v) {
-    UA_LOG_DEBUG_SESSION(server->config.logger, session, "Read the attribute %i", id->attributeId);
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Read the attribute %i", id->attributeId);
     if(id->dataEncoding.name.length > 0 &&
        !UA_String_equal(&binEncoding, &id->dataEncoding.name)) {
            v->hasStatus = true;
@@ -250,7 +268,8 @@ void Service_Read_single(UA_Server *server, UA_Session *session,
         return;
     }
 
-    /* When setting the value fails in the switch, we get an error code and set hasValue to false */
+    /* When setting the value fails in the switch, we get an error code and set
+       hasValue to false */
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     v->hasValue = true;
     switch(id->attributeId) {
@@ -407,7 +426,8 @@ void Service_Read(UA_Server *server, UA_Session *session,
             continue;
         UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
         ens->readNodes(ens->ensHandle, &request->requestHeader, request->nodesToRead,
-                       indices, (UA_UInt32)indexSize, response->results, false, response->diagnosticInfos);
+                       indices, (UA_UInt32)indexSize, response->results, false,
+                       response->diagnosticInfos);
     }
 #endif
 
@@ -433,20 +453,24 @@ void Service_Read(UA_Server *server, UA_Session *session,
         UA_Variant_init(&variant);
 
         UA_DateTime* expireArray = NULL;
-        expireArray = UA_Array_new(request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
+        expireArray = UA_Array_new(request->nodesToReadSize,
+                                   &UA_TYPES[UA_TYPES_DATETIME]);
         variant.data = expireArray;
 
         /* expires in 20 seconds */
         for(UA_UInt32 i = 0;i < response->resultsSize;i++) {
             expireArray[i] = UA_DateTime_now() + 20 * 100 * 1000 * 1000;
         }
-        UA_Variant_setArray(&variant, expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
+        UA_Variant_setArray(&variant, expireArray, request->nodesToReadSize,
+                            &UA_TYPES[UA_TYPES_DATETIME]);
 
         size_t offset = 0;
         UA_ByteString str;
-        UA_ByteString_allocBuffer(&str, UA_calcSizeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT]));
+        size_t strlength = UA_calcSizeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT]);
+        UA_ByteString_allocBuffer(&str, strlength);
         /* No chunking callback for the encoding */
-        UA_StatusCode retval = UA_encodeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT], NULL, NULL, &str, &offset);
+        UA_StatusCode retval = UA_encodeBinary(&variant, &UA_TYPES[UA_TYPES_VARIANT],
+                                               NULL, NULL, &str, &offset);
         UA_Array_delete(expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
         if(retval == UA_STATUSCODE_GOOD){
             additionalHeader.content.encoded.body.data = str.data;
@@ -457,12 +481,68 @@ void Service_Read(UA_Server *server, UA_Session *session,
 #endif
 }
 
+UA_DataValue
+UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
+               UA_TimestampsToReturn timestamps) {
+    UA_DataValue dv;
+    UA_DataValue_init(&dv);
+    UA_RCU_LOCK();
+    Service_Read_single(server, &adminSession, timestamps, item, &dv);
+    UA_RCU_UNLOCK();
+    return dv;
+}
+
+UA_StatusCode
+__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
+                 const UA_AttributeId attributeId, void *v) {
+    /* Call the read service */
+    UA_ReadValueId item;
+    UA_ReadValueId_init(&item);
+    item.nodeId = *nodeId;
+    item.attributeId = attributeId;
+    UA_DataValue dv = UA_Server_read(server, &item, UA_TIMESTAMPSTORETURN_NEITHER);
+
+    /* Check the return value */
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    if(dv.hasStatus)
+        retval = dv.hasStatus;
+    else if(!dv.hasValue)
+        retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_DataValue_deleteMembers(&dv);
+        return retval;
+    }
+
+    /* Prepare the result */
+     if(attributeId == UA_ATTRIBUTEID_VALUE ||
+        attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS) {
+         /* Return the entire variant */
+         if(dv.value.storageType == UA_VARIANT_DATA_NODELETE) {
+             retval = UA_Variant_copy(dv.value.data, v);
+         } else { /* storageType is UA_VARIANT_DATA */
+             memcpy(v, &dv.value, sizeof(UA_Variant));
+         }
+     }  else {
+         /* Return the variant content only */
+         if(dv.value.storageType == UA_VARIANT_DATA_NODELETE) {
+             retval = UA_copy(dv.value.data, v, dv.value.type);
+         } else { /* storageType is UA_VARIANT_DATA */
+             /* Copy the content of the type (including pointers and all)*/
+             memcpy(v, dv.value.data, dv.value.type->memSize);
+             /* Delete the "carrier" in the variant */
+             UA_free(dv.value.data);
+         }
+    }
+    return retval;
+}
+
 /*******************/
 /* Write Attribute */
 /*******************/
 
-UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                                 UA_EditNodeCallback callback, const void *data) {
+UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session,
+                                 const UA_NodeId *nodeId, UA_EditNodeCallback callback,
+                                 const void *data) {
     UA_StatusCode retval;
     do {
 #ifndef UA_ENABLE_MULTITHREADING
@@ -502,10 +582,12 @@ UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const U
     }
 
 static UA_StatusCode
-Service_Write_single_ValueDataSource(UA_Server *server, UA_Session *session, const UA_VariableNode *node,
-                                     const UA_WriteValue *wvalue) {
+Service_Write_single_ValueDataSource(UA_Server *server, UA_Session *session,
+                                     const UA_VariableNode *node, const UA_WriteValue *wvalue)
+{
     UA_assert(wvalue->attributeId == UA_ATTRIBUTEID_VALUE);
-    UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_VARIABLETYPE);
+    UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE ||
+              node->nodeClass == UA_NODECLASS_VARIABLETYPE);
     UA_assert(node->valueSource == UA_VALUESOURCE_DATASOURCE);
 
     if(node->value.dataSource.write == NULL)
@@ -546,15 +628,10 @@ static enum type_equivalence typeEquivalence(const UA_DataType *t) {
 static UA_StatusCode
 CopyValueIntoNode(UA_VariableNode *node, const UA_WriteValue *wvalue) {
     UA_assert(wvalue->attributeId == UA_ATTRIBUTEID_VALUE);
-    UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE || node->nodeClass == UA_NODECLASS_VARIABLETYPE);
+    UA_assert(node->nodeClass == UA_NODECLASS_VARIABLE ||
+              node->nodeClass == UA_NODECLASS_VARIABLETYPE);
     UA_assert(node->valueSource == UA_VALUESOURCE_VARIANT);
 
-    UA_Variant *oldV = &node->value.variant.value;
-    /* Don't run NodeId_equal on a NULL pointer (happens if the variable never
-       held a variant) */
-    if(!oldV->type)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
     /* Parse the range */
     UA_NumericRange range;
     UA_NumericRange *rangeptr = NULL;
@@ -568,9 +645,10 @@ CopyValueIntoNode(UA_VariableNode *node, const UA_WriteValue *wvalue) {
 
     /* The nodeid on the wire may be != the nodeid in the node: opaque types,
        enums and bytestrings. nodeV contains the correct type definition. */
+    UA_Variant *oldV = &node->value.variant.value;
     const UA_Variant *newV = &wvalue->value.value;
     UA_Variant cast_v;
-    if(!UA_NodeId_equal(&oldV->type->typeId, &newV->type->typeId)) {
+    if(oldV->type && !UA_NodeId_equal(&oldV->type->typeId, &newV->type->typeId)) {
         cast_v = wvalue->value.value;
         newV = &cast_v;
         enum type_equivalence te1 = typeEquivalence(oldV->type);
@@ -597,7 +675,8 @@ CopyValueIntoNode(UA_VariableNode *node, const UA_WriteValue *wvalue) {
         UA_Variant_deleteMembers(&node->value.variant.value);
         UA_Variant_copy(newV, &node->value.variant.value);
     } else
-        retval = UA_Variant_setRangeCopy(&node->value.variant.value, newV->data, newV->arrayLength, range);
+        retval = UA_Variant_setRangeCopy(&node->value.variant.value, newV->data,
+                                         newV->arrayLength, range);
     if(node->value.variant.callback.onWrite)
         node->value.variant.callback.onWrite(node->value.variant.callback.handle, node->nodeId,
                                              &node->value.variant.value, rangeptr);
@@ -678,7 +757,9 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
         if(((const UA_VariableNode*)node)->valueSource == UA_VALUESOURCE_VARIANT)
             retval = CopyValueIntoNode((UA_VariableNode*)node, wvalue);
         else
-            retval = Service_Write_single_ValueDataSource(server, session, (const UA_VariableNode*)node, wvalue);
+            retval = Service_Write_single_ValueDataSource(server, session,
+                                                          (const UA_VariableNode*)node,
+                                                          wvalue);
         break;
     case UA_ATTRIBUTEID_ACCESSLEVEL:
         CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
@@ -721,8 +802,10 @@ CopyAttributeIntoNode(UA_Server *server, UA_Session *session,
     return retval;
 }
 
-UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session, const UA_WriteValue *wvalue) {
-    return UA_Server_editNode(server, session, &wvalue->nodeId, (UA_EditNodeCallback)CopyAttributeIntoNode, wvalue);
+UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
+                                   const UA_WriteValue *wvalue) {
+    return UA_Server_editNode(server, session, &wvalue->nodeId,
+                              (UA_EditNodeCallback)CopyAttributeIntoNode, wvalue);
 }
 
 void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest *request,
@@ -733,7 +816,8 @@ void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest
         return;
     }
 
-    response->results = UA_Array_new(request->nodesToWriteSize, &UA_TYPES[UA_TYPES_STATUSCODE]);
+    response->results = UA_Array_new(request->nodesToWriteSize,
+                                     &UA_TYPES[UA_TYPES_STATUSCODE]);
     if(!response->results) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
@@ -769,3 +853,30 @@ void Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest
             response->results[i] = Service_Write_single(server, session, &request->nodesToWrite[i]);
     }
 }
+
+UA_StatusCode UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
+    UA_RCU_LOCK();
+    return Service_Write_single(server, &adminSession, value);
+    UA_RCU_UNLOCK();
+}
+
+UA_StatusCode
+__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
+                  const UA_AttributeId attributeId, const UA_DataType *attr_type,
+                  const void *value) {
+    UA_WriteValue wvalue;
+    UA_WriteValue_init(&wvalue);
+    wvalue.nodeId = *nodeId;
+    wvalue.attributeId = attributeId;
+    if(attributeId != UA_ATTRIBUTEID_VALUE)
+        /* hacked cast. the target WriteValue is used as const anyway */
+        UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)value, attr_type);
+    else {
+        if(attr_type != &UA_TYPES[UA_TYPES_VARIANT])
+            return UA_STATUSCODE_BADTYPEMISMATCH;
+        wvalue.value.value = *(const UA_Variant*)value;
+    }
+    wvalue.value.hasValue = true;
+    UA_StatusCode retval = UA_Server_write(server, &wvalue);
+    return retval;
+}

+ 281 - 83
src/server/ua_services_nodemanagement.c

@@ -5,11 +5,14 @@
 /* Helper Functions */
 /********************/
 
-/* Returns the type and all subtypes. We start with an array with a single root nodeid. When a relevant
- * reference is found, we add the nodeids to the back of the array and increase the size. Since the hierarchy
- * is not cyclic, we can safely progress in the array to process the newly found referencetype nodeids. */
+/* Returns the type and all subtypes. We start with an array with a single root
+ * nodeid. When a relevant reference is found, we add the nodeids to the back of
+ * the array and increase the size. Since the hierarchy is not cyclic, we can
+ * safely progress in the array to process the newly found referencetype
+ * nodeids. */
 UA_StatusCode
-getTypeHierarchy(UA_NodeStore *ns, const UA_NodeId *root, UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
+getTypeHierarchy(UA_NodeStore *ns, const UA_NodeId *root,
+                 UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
     const UA_Node *node = UA_NodeStore_get(ns, root);
     if(!node)
         return UA_STATUSCODE_BADNOMATCH;
@@ -121,6 +124,11 @@ isNodeInTree(UA_NodeStore *ns, const UA_NodeId *rootNode, const UA_NodeId *nodeT
 /* Add Node */
 /************/
 
+static void
+Service_AddNodes_single(UA_Server *server, UA_Session *session,
+                        const UA_AddNodesItem *item, UA_AddNodesResult *result,
+                        UA_InstantiationCallback *instantiationCallback);
+
 static UA_StatusCode
 instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
                         const UA_NodeId *typeId, UA_InstantiationCallback *instantiationCallback);
@@ -131,7 +139,8 @@ instantiateObjectNode(UA_Server *server, UA_Session *session, const UA_NodeId *n
 void
 Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
                           const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
-                          const UA_NodeId *typeDefinition, UA_InstantiationCallback *instantiationCallback,
+                          const UA_NodeId *typeDefinition,
+                          UA_InstantiationCallback *instantiationCallback,
                           UA_AddNodesResult *result) {
     if(node->nodeId.namespaceIndex >= server->namespacesSize) {
         UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Namespace invalid");
@@ -148,32 +157,6 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         return;
     }
 
-    /* Test if the reference to the parent is valid */
-    const UA_NodeId nodeIdHasSubtype = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE);
-    switch(node->nodeClass) {
-    case UA_NODECLASS_OBJECTTYPE:
-    case UA_NODECLASS_VARIABLETYPE:
-    case UA_NODECLASS_REFERENCETYPE:
-        /* DataTypeNodes have no subtype relations */
-        /* -- CTT throw errors with this check as they test all combinations of node and reference type -- */
-        /* if(!UA_NodeId_equal(referenceTypeId, &nodeIdHasSubtype)) { */
-        /*     UA_LOG_DEBUG_SESSION(server->config.logger, session, */
-        /*                          "AddNodes: Trying to add a type node without a hassubtype relation"); */
-        /*     result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED; */
-        /*     UA_NodeStore_deleteNode(node); */
-        /*     return; */
-        /* } */
-        break;
-    default:
-        if(UA_NodeId_equal(referenceTypeId, &nodeIdHasSubtype)) {
-            UA_LOG_DEBUG_SESSION(server->config.logger, session,
-                                 "AddNodes: Trying to add a non-type node with a hassubtype relation");
-            result->statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
-            UA_NodeStore_deleteNode(node);
-            return;
-        }
-    }
-
     const UA_ReferenceTypeNode *referenceType =
         (const UA_ReferenceTypeNode *)UA_NodeStore_get(server->nodestore, referenceTypeId);
     if(!referenceType) {
@@ -199,7 +182,8 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
     // todo: namespace index is assumed to be valid
     result->statusCode = UA_NodeStore_insert(server->nodestore, node);
     if(result->statusCode != UA_STATUSCODE_GOOD) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Node could not be added to the nodestore with error code 0x%08x",
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Node could not be added to the nodestore with error code 0x%08x",
                              result->statusCode);
         return;
     }
@@ -214,7 +198,8 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
     item.targetNodeId.nodeId = *parentNodeId;
     result->statusCode = Service_AddReferences_single(server, session, &item);
     if(result->statusCode != UA_STATUSCODE_GOOD) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Could not add the reference to the parent");
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Could not add the reference to the parent");
         goto remove_node;
     }
 
@@ -229,11 +214,13 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         } else {
             /* Check if the supplied type is a subtype of BaseObjectType */
             UA_Boolean found = false;
-            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &baseobjtype, &hassubtype, 1, 10, &found);
+            result->statusCode = isNodeInTree(server->nodestore, typeDefinition,
+                                              &baseobjtype, &hassubtype, 1, 10, &found);
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
-                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The object is not derived from BaseObjectType");
+                UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                     "AddNodes: The object if not derived from BaseObjectType");
                 goto remove_node;
             }
         }
@@ -251,11 +238,13 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
         } else {
             /* Check if the supplied type is a subtype of BaseVariableType */
             UA_Boolean found = false;
-            result->statusCode = isNodeInTree(server->nodestore, typeDefinition, &basevartype, &hassubtype, 1, 10, &found);
+            result->statusCode = isNodeInTree(server->nodestore, typeDefinition,
+                                              &basevartype, &hassubtype, 1, 10, &found);
             if(!found)
                 result->statusCode = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
             if(result->statusCode != UA_STATUSCODE_GOOD) {
-                UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: The variable is not derived from BaseVariableType");
+                UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                                     "AddNodes: The variable if not derived from BaseVariableType");
                 goto remove_node;
             }
         }
@@ -267,7 +256,8 @@ Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
 
     /* Custom callback */
     if(instantiationCallback)
-        instantiationCallback->method(result->addedNodeId, *typeDefinition, instantiationCallback->handle);
+        instantiationCallback->method(result->addedNodeId, *typeDefinition,
+                                      instantiationCallback->handle);
 
     return;
 
@@ -282,7 +272,8 @@ static UA_StatusCode
 copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *variable,
                      const UA_NodeId *referenceType, const UA_NodeId *parent,
                      UA_InstantiationCallback *instantiationCallback) {
-    const UA_VariableNode *node = (const UA_VariableNode*)UA_NodeStore_get(server->nodestore, variable);
+    const UA_VariableNode *node =
+        (const UA_VariableNode*)UA_NodeStore_get(server->nodestore, variable);
     if(!node)
         return UA_STATUSCODE_BADNODEIDINVALID;
     if(node->nodeClass != UA_NODECLASS_VARIABLE)
@@ -331,7 +322,8 @@ copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *va
         const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
         if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
             continue;
-        UA_StatusCode retval = instantiateVariableNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        UA_StatusCode retval = instantiateVariableNode(server, session, &res.addedNodeId,
+                                                       &rn->targetId.nodeId, instantiationCallback);
         if(retval != UA_STATUSCODE_GOOD) {
             Service_DeleteNodes_single(server, &adminSession, &res.addedNodeId, true);
             UA_AddNodesResult_deleteMembers(&res);
@@ -340,7 +332,8 @@ copyExistingVariable(UA_Server *server, UA_Session *session, const UA_NodeId *va
     }
 
     if(instantiationCallback)
-        instantiationCallback->method(res.addedNodeId, node->nodeId, instantiationCallback->handle);
+        instantiationCallback->method(res.addedNodeId, node->nodeId,
+                                      instantiationCallback->handle);
 
     UA_AddNodesResult_deleteMembers(&res);
     return UA_STATUSCODE_GOOD;
@@ -393,7 +386,8 @@ copyExistingObject(UA_Server *server, UA_Session *session, const UA_NodeId *vari
         const UA_NodeId hasTypeDef = UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION);
         if(!UA_NodeId_equal(&rn->referenceTypeId, &hasTypeDef))
             continue;
-        UA_StatusCode retval = instantiateObjectNode(server, session, &res.addedNodeId, &rn->targetId.nodeId, instantiationCallback);
+        UA_StatusCode retval = instantiateObjectNode(server, session, &res.addedNodeId,
+                                                     &rn->targetId.nodeId, instantiationCallback);
         if(retval != UA_STATUSCODE_GOOD) {
             Service_DeleteNodes_single(server, &adminSession, &res.addedNodeId, true);
             UA_AddNodesResult_deleteMembers(&res);
@@ -417,15 +411,18 @@ setObjectInstanceHandle(UA_Server *server, UA_Session *session, UA_ObjectNode* n
 }
 
 static UA_StatusCode
-instantiateObjectNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                      const UA_NodeId *typeId, UA_InstantiationCallback *instantiationCallback) {
+instantiateObjectNode(UA_Server *server, UA_Session *session,
+                      const UA_NodeId *nodeId, const UA_NodeId *typeId,
+                      UA_InstantiationCallback *instantiationCallback) {
     const UA_ObjectTypeNode *typenode = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId);
     if(!typenode) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Could not instantiate an object from an unknown nodeid");
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Could not instantiate an object from an unknown nodeid");
         return UA_STATUSCODE_BADNODEIDINVALID;
     }
     if(typenode->nodeClass != UA_NODECLASS_OBJECTTYPE) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Could not instantiate an object from a non-objecttype node");
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Could not instantiate an object from a non-objecttype node");
         return UA_STATUSCODE_BADNODECLASSINVALID;
     }
 
@@ -478,20 +475,24 @@ instantiateObjectNode(UA_Server *server, UA_Session *session, const UA_NodeId *n
     const UA_ObjectLifecycleManagement *olm = &typenode->lifecycleManagement;
     if(olm->constructor)
         UA_Server_editNode(server, session, nodeId,
-                           (UA_EditNodeCallback)setObjectInstanceHandle, olm->constructor(*nodeId));
+                           (UA_EditNodeCallback)setObjectInstanceHandle,
+                           olm->constructor(*nodeId));
     return UA_STATUSCODE_GOOD;
 }
 
 static UA_StatusCode
-instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                        const UA_NodeId *typeId, UA_InstantiationCallback *instantiationCallback) {
+instantiateVariableNode(UA_Server *server, UA_Session *session,
+                        const UA_NodeId *nodeId, const UA_NodeId *typeId,
+                        UA_InstantiationCallback *instantiationCallback) {
     const UA_ObjectTypeNode *typenode = (const UA_ObjectTypeNode*)UA_NodeStore_get(server->nodestore, typeId);
     if(!typenode) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Could not instantiate a variable from an unknown nodeid");
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Could not instantiate a variable from an unknown nodeid");
         return UA_STATUSCODE_BADNODEIDINVALID;
     }
     if(typenode->nodeClass != UA_NODECLASS_VARIABLETYPE) {
-        UA_LOG_DEBUG_SESSION(server->config.logger, session, "AddNodes: Could not instantiate a variable from a non-variabletype node");
+        UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                             "AddNodes: Could not instantiate a variable from a non-variabletype node");
         return UA_STATUSCODE_BADNODECLASSINVALID;
     }
 
@@ -530,7 +531,8 @@ instantiateVariableNode(UA_Server *server, UA_Session *session, const UA_NodeId
 }
 
 static UA_StatusCode
-copyStandardAttributes(UA_Node *node, const UA_AddNodesItem *item, const UA_NodeAttributes *attr) {
+copyStandardAttributes(UA_Node *node, const UA_AddNodesItem *item,
+                       const UA_NodeAttributes *attr) {
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     retval |= UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId);
     retval |= UA_QualifiedName_copy(&item->browseName, &node->browseName);
@@ -542,11 +544,13 @@ copyStandardAttributes(UA_Node *node, const UA_AddNodesItem *item, const UA_Node
 }
 
 static UA_Node *
-variableNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableAttributes *attr) {
+variableNodeFromAttributes(const UA_AddNodesItem *item,
+                           const UA_VariableAttributes *attr) {
     UA_VariableNode *vnode = UA_NodeStore_newVariableNode();
     if(!vnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     // todo: test if the type / valueRank / value attributes are consistent
     vnode->accessLevel = attr->accessLevel;
     vnode->userAccessLevel = attr->userAccessLevel;
@@ -562,11 +566,13 @@ variableNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableAttribu
 }
 
 static UA_Node *
-objectNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectAttributes *attr) {
+objectNodeFromAttributes(const UA_AddNodesItem *item,
+                         const UA_ObjectAttributes *attr) {
     UA_ObjectNode *onode = UA_NodeStore_newObjectNode();
     if(!onode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)onode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)onode, item,
+                                                  (const UA_NodeAttributes*)attr);
     onode->eventNotifier = attr->eventNotifier;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_NodeStore_deleteNode((UA_Node*)onode);
@@ -576,11 +582,13 @@ objectNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectAttributes
 }
 
 static UA_Node *
-referenceTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ReferenceTypeAttributes *attr) {
+referenceTypeNodeFromAttributes(const UA_AddNodesItem *item,
+                                const UA_ReferenceTypeAttributes *attr) {
     UA_ReferenceTypeNode *rtnode = UA_NodeStore_newReferenceTypeNode();
     if(!rtnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)rtnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)rtnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     rtnode->isAbstract = attr->isAbstract;
     rtnode->symmetric = attr->symmetric;
     retval |= UA_LocalizedText_copy(&attr->inverseName, &rtnode->inverseName);
@@ -592,11 +600,13 @@ referenceTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ReferenceT
 }
 
 static UA_Node *
-objectTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectTypeAttributes *attr) {
+objectTypeNodeFromAttributes(const UA_AddNodesItem *item,
+                             const UA_ObjectTypeAttributes *attr) {
     UA_ObjectTypeNode *otnode = UA_NodeStore_newObjectTypeNode();
     if(!otnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)otnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)otnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     otnode->isAbstract = attr->isAbstract;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_NodeStore_deleteNode((UA_Node*)otnode);
@@ -606,11 +616,13 @@ objectTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_ObjectTypeAtt
 }
 
 static UA_Node *
-variableTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableTypeAttributes *attr) {
+variableTypeNodeFromAttributes(const UA_AddNodesItem *item,
+                               const UA_VariableTypeAttributes *attr) {
     UA_VariableTypeNode *vtnode = UA_NodeStore_newVariableTypeNode();
     if(!vtnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vtnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vtnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     UA_Variant_copy(&attr->value, &vtnode->value.variant.value);
     // datatype is taken from the value
     vtnode->valueRank = attr->valueRank;
@@ -624,11 +636,13 @@ variableTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_VariableTyp
 }
 
 static UA_Node *
-viewNodeFromAttributes(const UA_AddNodesItem *item, const UA_ViewAttributes *attr) {
+viewNodeFromAttributes(const UA_AddNodesItem *item,
+                       const UA_ViewAttributes *attr) {
     UA_ViewNode *vnode = UA_NodeStore_newViewNode();
     if(!vnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)vnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     vnode->containsNoLoops = attr->containsNoLoops;
     vnode->eventNotifier = attr->eventNotifier;
     if(retval != UA_STATUSCODE_GOOD) {
@@ -639,11 +653,13 @@ viewNodeFromAttributes(const UA_AddNodesItem *item, const UA_ViewAttributes *att
 }
 
 static UA_Node *
-dataTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_DataTypeAttributes *attr) {
+dataTypeNodeFromAttributes(const UA_AddNodesItem *item,
+                           const UA_DataTypeAttributes *attr) {
     UA_DataTypeNode *dtnode = UA_NodeStore_newDataTypeNode();
     if(!dtnode)
         return NULL;
-    UA_StatusCode retval = copyStandardAttributes((UA_Node*)dtnode, item, (const UA_NodeAttributes*)attr);
+    UA_StatusCode retval = copyStandardAttributes((UA_Node*)dtnode, item,
+                                                  (const UA_NodeAttributes*)attr);
     dtnode->isAbstract = attr->isAbstract;
     if(retval != UA_STATUSCODE_GOOD) {
         UA_NodeStore_deleteNode((UA_Node*)dtnode);
@@ -652,8 +668,10 @@ dataTypeNodeFromAttributes(const UA_AddNodesItem *item, const UA_DataTypeAttribu
     return (UA_Node*)dtnode;
 }
 
-void Service_AddNodes_single(UA_Server *server, UA_Session *session, const UA_AddNodesItem *item,
-                             UA_AddNodesResult *result, UA_InstantiationCallback *instantiationCallback) {
+static void
+Service_AddNodes_single(UA_Server *server, UA_Session *session,
+                        const UA_AddNodesItem *item, UA_AddNodesResult *result,
+                        UA_InstantiationCallback *instantiationCallback) {
     if(item->nodeAttributes.encoding < UA_EXTENSIONOBJECT_DECODED ||
        !item->nodeAttributes.content.decoded.type) {
         result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
@@ -678,9 +696,7 @@ void Service_AddNodes_single(UA_Server *server, UA_Session *session, const UA_Ad
         node = variableNodeFromAttributes(item, item->nodeAttributes.content.decoded.data);
         break;
     case UA_NODECLASS_OBJECTTYPE:
-        /* The structures of UA_ObjectTypeAttributes and UA_ObjectType are identical. CTT uses this. */
-        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES] &&
-           item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES]) {
+        if(item->nodeAttributes.content.decoded.type != &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]) {
             result->statusCode = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
             return;
         }
@@ -734,7 +750,8 @@ void Service_AddNodes_single(UA_Server *server, UA_Session *session, const UA_Ad
         Service_DeleteNodes_single(server, session, &result->addedNodeId, true);
 }
 
-void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
+void Service_AddNodes(UA_Server *server, UA_Session *session,
+                      const UA_AddNodesRequest *request,
                       UA_AddNodesResponse *response) {
     UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing AddNodesRequest");
     if(request->nodesToAddSize <= 0) {
@@ -771,8 +788,9 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
         if(indexSize == 0)
             continue;
         UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
-        ens->addNodes(ens->ensHandle, &request->requestHeader, request->nodesToAdd,
-                      indices, (UA_UInt32)indexSize, response->results, response->diagnosticInfos);
+        ens->addNodes(ens->ensHandle, &request->requestHeader,
+                      request->nodesToAdd, indices, (UA_UInt32)indexSize,
+                      response->results, response->diagnosticInfos);
     }
 #endif
 
@@ -781,10 +799,46 @@ void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesR
 #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
         if(!isExternal[i])
 #endif
-            Service_AddNodes_single(server, session, &request->nodesToAdd[i], &response->results[i], NULL);
+            Service_AddNodes_single(server, session, &request->nodesToAdd[i],
+                                    &response->results[i], NULL);
     }
 }
 
+UA_StatusCode
+__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
+                    const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
+                    const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
+                    const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
+                    const UA_DataType *attributeType,
+                    UA_InstantiationCallback *instantiationCallback, UA_NodeId *outNewNodeId) {
+    /* prepare the item */
+    UA_AddNodesItem item;
+    UA_AddNodesItem_init(&item);
+    item.parentNodeId.nodeId = parentNodeId;
+    item.referenceTypeId = referenceTypeId;
+    item.requestedNewNodeId.nodeId = requestedNewNodeId;
+    item.browseName = browseName;
+    item.nodeClass = nodeClass;
+    item.typeDefinition.nodeId = typeDefinition;
+    item.nodeAttributes = (UA_ExtensionObject){
+        .encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE,
+        .content.decoded = {attributeType, (void*)(uintptr_t)attr}};
+
+    /* run the service */
+    UA_AddNodesResult result;
+    UA_AddNodesResult_init(&result);
+    UA_RCU_LOCK();
+    Service_AddNodes_single(server, &adminSession, &item, &result, instantiationCallback);
+    UA_RCU_UNLOCK();
+
+    /* prepare the output */
+    if(outNewNodeId && result.statusCode == UA_STATUSCODE_GOOD)
+        *outNewNodeId = result.addedNodeId;
+    else
+        UA_NodeId_deleteMembers(&result.addedNodeId);
+    return result.statusCode;
+}
+
 /**************************************************/
 /* Add Special Nodes (not possible over the wire) */
 /**************************************************/
@@ -968,7 +1022,8 @@ UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
 
 /* Adds a one-way reference to the local nodestore */
 static UA_StatusCode
-addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, const UA_AddReferencesItem *item) {
+addOneWayReference(UA_Server *server, UA_Session *session,
+                   UA_Node *node, const UA_AddReferencesItem *item) {
     size_t i = node->referencesSize;
     size_t refssize = (i+1) | 3; // so the realloc is not necessary every time
     UA_ReferenceNode *new_refs = UA_realloc(node->references, sizeof(UA_ReferenceNode) * refssize);
@@ -987,7 +1042,8 @@ addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, const
 }
 
 UA_StatusCode
-Service_AddReferences_single(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item) {
+Service_AddReferences_single(UA_Server *server, UA_Session *session,
+                             const UA_AddReferencesItem *item) {
 UA_StatusCode retval = UA_STATUSCODE_GOOD;
 #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
     UA_Boolean handledExternally = UA_FALSE;
@@ -1011,7 +1067,7 @@ UA_StatusCode retval = UA_STATUSCODE_GOOD;
     /* cast away the const to loop the call through UA_Server_editNode beware
         the "if" above for external nodestores */
     retval = UA_Server_editNode(server, session, &item->sourceNodeId,
-                                              (UA_EditNodeCallback)addOneWayReference, item);
+                                (UA_EditNodeCallback)addOneWayReference, item);
 #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
     }
 #endif
@@ -1049,9 +1105,11 @@ UA_StatusCode retval = UA_STATUSCODE_GOOD;
     return retval;
 }
 
-void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddReferencesRequest *request,
+void Service_AddReferences(UA_Server *server, UA_Session *session,
+                           const UA_AddReferencesRequest *request,
                            UA_AddReferencesResponse *response) {
-    UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing AddReferencesRequest");
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Processing AddReferencesRequest");
     if(request->referencesToAddSize <= 0) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
         return;
@@ -1099,6 +1157,22 @@ void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddR
     }
 }
 
+UA_StatusCode
+UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
+                       const UA_NodeId refTypeId, const UA_ExpandedNodeId targetId,
+                       UA_Boolean isForward) {
+    UA_AddReferencesItem item;
+    UA_AddReferencesItem_init(&item);
+    item.sourceNodeId = sourceId;
+    item.referenceTypeId = refTypeId;
+    item.isForward = isForward;
+    item.targetNodeId = targetId;
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_AddReferences_single(server, &adminSession, &item);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
 /****************/
 /* Delete Nodes */
 /****************/
@@ -1106,8 +1180,8 @@ void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddR
 // TODO: Check consistency constraints, remove the references.
 
 UA_StatusCode
-Service_DeleteNodes_single(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
-                           UA_Boolean deleteReferences) {
+Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
+                           const UA_NodeId *nodeId, UA_Boolean deleteReferences) {
     const UA_Node *node = UA_NodeStore_get(server->nodestore, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDINVALID;
@@ -1157,7 +1231,8 @@ Service_DeleteNodes_single(UA_Server *server, UA_Session *session, const UA_Node
     return UA_NodeStore_remove(server->nodestore, nodeId);
 }
 
-void Service_DeleteNodes(UA_Server *server, UA_Session *session, const UA_DeleteNodesRequest *request,
+void Service_DeleteNodes(UA_Server *server, UA_Session *session,
+                         const UA_DeleteNodesRequest *request,
                          UA_DeleteNodesResponse *response) {
     UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing DeleteNodesRequest");
     if(request->nodesToDeleteSize <= 0) {
@@ -1177,6 +1252,16 @@ void Service_DeleteNodes(UA_Server *server, UA_Session *session, const UA_Delete
     }
 }
 
+UA_StatusCode
+UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
+                     UA_Boolean deleteReferences) {
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_DeleteNodes_single(server, &adminSession,
+                                                      &nodeId, deleteReferences);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
 /*********************/
 /* Delete References */
 /*********************/
@@ -1244,3 +1329,116 @@ Service_DeleteReferences(UA_Server *server, UA_Session *session,
         response->results[i] =
             Service_DeleteReferences_single(server, session, &request->referencesToDelete[i]);
 }
+
+UA_StatusCode
+UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
+                          const UA_NodeId referenceTypeId,
+                          UA_Boolean isForward, const UA_ExpandedNodeId targetNodeId,
+                          UA_Boolean deleteBidirectional) {
+    UA_DeleteReferencesItem item;
+    item.sourceNodeId = sourceNodeId;
+    item.referenceTypeId = referenceTypeId;
+    item.isForward = isForward;
+    item.targetNodeId = targetNodeId;
+    item.deleteBidirectional = deleteBidirectional;
+    UA_RCU_LOCK();
+    UA_StatusCode retval = Service_DeleteReferences_single(server, &adminSession, &item);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+/***********************/
+/* Edit Node Callbacks */
+/***********************/
+
+static UA_StatusCode
+setValueCallback(UA_Server *server, UA_Session *session,
+                 UA_VariableNode *node, UA_ValueCallback *callback) {
+    if(node->nodeClass != UA_NODECLASS_VARIABLE)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    node->value.variant.callback = *callback;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Server_setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId,
+                                        const UA_ValueCallback callback) {
+    UA_RCU_LOCK();
+    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
+                                              (UA_EditNodeCallback)setValueCallback, &callback);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+static UA_StatusCode
+setDataSource(UA_Server *server, UA_Session *session,
+              UA_VariableNode* node, UA_DataSource *dataSource) {
+    if(node->nodeClass != UA_NODECLASS_VARIABLE)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    if(node->valueSource == UA_VALUESOURCE_VARIANT)
+        UA_Variant_deleteMembers(&node->value.variant.value);
+    node->value.dataSource = *dataSource;
+    node->valueSource = UA_VALUESOURCE_DATASOURCE;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
+                                     const UA_DataSource dataSource) {
+    UA_RCU_LOCK();
+    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
+                                              (UA_EditNodeCallback)setDataSource, &dataSource);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+static UA_StatusCode
+setObjectTypeLifecycleManagement(UA_Server *server, UA_Session *session,
+                                 UA_ObjectTypeNode* node,
+                                 UA_ObjectLifecycleManagement *olm) {
+    if(node->nodeClass != UA_NODECLASS_OBJECTTYPE)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    node->lifecycleManagement = *olm;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Server_setObjectTypeNode_lifecycleManagement(UA_Server *server, UA_NodeId nodeId,
+                                                UA_ObjectLifecycleManagement olm) {
+    UA_RCU_LOCK();
+    UA_StatusCode retval = UA_Server_editNode(server, &adminSession, &nodeId,
+                                              (UA_EditNodeCallback)setObjectTypeLifecycleManagement, &olm);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+#ifdef UA_ENABLE_METHODCALLS
+
+struct addMethodCallback {
+    UA_MethodCallback callback;
+    void *handle;
+};
+
+static UA_StatusCode
+editMethodCallback(UA_Server *server, UA_Session* session, UA_Node* node, const void* handle) {
+    if(node->nodeClass != UA_NODECLASS_METHOD)
+        return UA_STATUSCODE_BADNODECLASSINVALID;
+    const struct addMethodCallback *newCallback = handle;
+    UA_MethodNode *mnode = (UA_MethodNode*) node;
+    mnode->attachedMethod = newCallback->callback;
+    mnode->methodHandle   = newCallback->handle;
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_EXPORT
+UA_Server_setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId,
+                                 UA_MethodCallback method, void *handle) {
+    struct addMethodCallback cb = { method, handle };
+    UA_RCU_LOCK();
+    UA_StatusCode retval = UA_Server_editNode(server, &adminSession,
+                                              &methodNodeId, editMethodCallback, &cb);
+    UA_RCU_UNLOCK();
+    return retval;
+}
+
+#endif

+ 32 - 6
src/server/ua_services_view.c

@@ -208,8 +208,9 @@ static void removeCp(struct ContinuationPointEntry *cp, UA_Session* session) {
  * @param result The entry in the request
  */
 void
-Service_Browse_single(UA_Server *server, UA_Session *session, struct ContinuationPointEntry *cp,
-                      const UA_BrowseDescription *descr, UA_UInt32 maxrefs, UA_BrowseResult *result) { 
+Service_Browse_single(UA_Server *server, UA_Session *session,
+                      struct ContinuationPointEntry *cp, const UA_BrowseDescription *descr,
+                      UA_UInt32 maxrefs, UA_BrowseResult *result) { 
     size_t referencesCount = 0;
     size_t referencesIndex = 0;
     /* set the browsedescription if a cp is given */
@@ -295,8 +296,10 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
         if(skipped < continuationIndex) {
             skipped++;
         } else {
-            retval |= fillReferenceDescription(server->nodestore, current, &node->references[referencesIndex],
-                                               descr->resultMask, &result->references[referencesCount]);
+            retval |= fillReferenceDescription(server->nodestore, current,
+                                               &node->references[referencesIndex],
+                                               descr->resultMask,
+                                               &result->references[referencesCount]);
             referencesCount++;
         }
     }
@@ -308,7 +311,8 @@ Service_Browse_single(UA_Server *server, UA_Session *session, struct Continuatio
     }
 
     if(retval != UA_STATUSCODE_GOOD) {
-        UA_Array_delete(result->references, result->referencesSize, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
+        UA_Array_delete(result->references, result->referencesSize,
+                        &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
         result->references = NULL;
         result->referencesSize = 0;
         result->statusCode = retval;
@@ -409,7 +413,17 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
     }
 }
 
-void
+UA_BrowseResult
+UA_Server_browse(UA_Server *server, UA_UInt32 maxrefs, const UA_BrowseDescription *descr) {
+    UA_BrowseResult result;
+    UA_BrowseResult_init(&result);
+    UA_RCU_LOCK();
+    Service_Browse_single(server, &adminSession, NULL, descr, maxrefs, &result);
+    UA_RCU_UNLOCK();
+    return result;
+}
+
+static void
 UA_Server_browseNext_single(UA_Server *server, UA_Session *session, UA_Boolean releaseContinuationPoint,
                             const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
     result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
@@ -446,6 +460,18 @@ void Service_BrowseNext(UA_Server *server, UA_Session *session, const UA_BrowseN
                                     &request->continuationPoints[i], &response->results[i]);
 }
 
+UA_BrowseResult
+UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
+                     const UA_ByteString *continuationPoint) {
+    UA_BrowseResult result;
+    UA_BrowseResult_init(&result);
+    UA_RCU_LOCK();
+    UA_Server_browseNext_single(server, &adminSession, releaseContinuationPoint,
+                                continuationPoint, &result);
+    UA_RCU_UNLOCK();
+    return result;
+}
+
 /***********************/
 /* TranslateBrowsePath */
 /***********************/

+ 2 - 1
src/server/ua_subscription.c

@@ -67,7 +67,8 @@ void UA_MoniteredItem_SampleCallback(UA_Server *server, UA_MonitoredItem *monito
     rvid.nodeId = monitoredItem->monitoredNodeId;
     rvid.attributeId = monitoredItem->attributeID;
     rvid.indexRange = monitoredItem->indexRange;
-    Service_Read_single(server, sub->session, monitoredItem->timestampsToReturn, &rvid, &newvalue->value);
+    Service_Read_single(server, sub->session, monitoredItem->timestampsToReturn,
+                        &rvid, &newvalue->value);
 
     /* encode to see if the data has changed */
     size_t binsize = UA_calcSizeBinary(&newvalue->value.value, &UA_TYPES[UA_TYPES_VARIANT]);

+ 1 - 0
src/ua_connection.c

@@ -2,6 +2,7 @@
 #include "ua_connection_internal.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated_encoding_binary.h"
+#include "ua_types_generated_handling.h"
 #include "ua_securechannel.h"
 
 void UA_Connection_init(UA_Connection *connection) {

+ 3 - 1
src/ua_securechannel.c

@@ -4,6 +4,8 @@
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_transport_generated_encoding_binary.h"
+#include "ua_types_generated_handling.h"
+#include "ua_transport_generated_handling.h"
 
 #define UA_SECURE_MESSAGE_HEADER_LENGTH 24
 
@@ -139,7 +141,7 @@ UA_SecureChannel_sendChunk(UA_ChunkInfo *ci, UA_ByteString *dst, size_t offset)
     dst->length += UA_SECURE_MESSAGE_HEADER_LENGTH;
     offset += UA_SECURE_MESSAGE_HEADER_LENGTH;
 
-    if(ci->messageSizeSoFar + offset > connection->remoteConf.maxMessageSize && connection->remoteConf.maxChunkCount > 0)
+    if(ci->messageSizeSoFar + offset > connection->remoteConf.maxMessageSize && connection->remoteConf.maxMessageSize > 0)
         ci->errorCode = UA_STATUSCODE_BADRESPONSETOOLARGE;
     if(++ci->chunksSoFar > connection->remoteConf.maxChunkCount && connection->remoteConf.maxChunkCount > 0)
         ci->errorCode = UA_STATUSCODE_BADRESPONSETOOLARGE;

+ 1 - 0
src/ua_session.c

@@ -1,4 +1,5 @@
 #include "ua_session.h"
+#include "ua_types_generated_handling.h"
 #include "ua_util.h"
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 #include "server/ua_subscription.h"

+ 100 - 84
src/ua_types.c

@@ -1,6 +1,7 @@
 #include "ua_util.h"
 #include "ua_types.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 
 #include "pcg_basic.h"
 #include "libc_time.h"
@@ -14,6 +15,8 @@ UA_EXPORT const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {
     .nodeId = { .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = 0 },
     .namespaceUri = {.length = 0, .data = NULL}, .serverIndex = 0 };
 
+static void UA_deleteMembers_noInit(void *p, const UA_DataType *type);
+
 /***************************/
 /* Random Number Generator */
 /***************************/
@@ -51,6 +54,10 @@ UA_Boolean UA_String_equal(const UA_String *string1, const UA_String *string2) {
     return (is == 0) ? true : false;
 }
 
+static void String_deleteMembers(UA_String *s, const UA_DataType *_) {
+    UA_free((void*)((uintptr_t)s->data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
+}
+
 /* DateTime */
 UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime t) {
     /* Calculating the the milli-, micro- and nanoseconds */
@@ -150,8 +157,7 @@ static void NodeId_deleteMembers(UA_NodeId *p, const UA_DataType *_) {
     switch(p->identifierType) {
     case UA_NODEIDTYPE_STRING:
     case UA_NODEIDTYPE_BYTESTRING:
-        UA_free((void*)((uintptr_t)p->identifier.byteString.data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
-        p->identifier.byteString = UA_BYTESTRING_NULL;
+        String_deleteMembers(&p->identifier.string, NULL);
         break;
     default: break;
     }
@@ -177,8 +183,6 @@ static UA_StatusCode NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_
     }
     dst->namespaceIndex = src->namespaceIndex;
     dst->identifierType = src->identifierType;
-    if(retval != UA_STATUSCODE_GOOD)
-        NodeId_deleteMembers(dst, NULL);
     return retval;
 }
 
@@ -228,7 +232,7 @@ UA_Boolean UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2) {
 /* ExpandedNodeId */
 static void ExpandedNodeId_deleteMembers(UA_ExpandedNodeId *p, const UA_DataType *_) {
     NodeId_deleteMembers(&p->nodeId, _);
-    UA_String_deleteMembers(&p->namespaceUri);
+    String_deleteMembers(&p->namespaceUri, NULL);
 }
 
 static UA_StatusCode
@@ -236,8 +240,6 @@ ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst, const
     UA_StatusCode retval = NodeId_copy(&src->nodeId, &dst->nodeId, NULL);
     retval |= UA_String_copy(&src->namespaceUri, &dst->namespaceUri);
     dst->serverIndex = src->serverIndex;
-    if(retval != UA_STATUSCODE_GOOD)
-        ExpandedNodeId_deleteMembers(dst, NULL);
     return retval;
 }
 
@@ -248,18 +250,12 @@ static void ExtensionObject_deleteMembers(UA_ExtensionObject *p, const UA_DataTy
     case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
     case UA_EXTENSIONOBJECT_ENCODED_XML:
         NodeId_deleteMembers(&p->content.encoded.typeId, NULL);
-        UA_free((void*)((uintptr_t)p->content.encoded.body.data & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
-        p->content.encoded.body = UA_BYTESTRING_NULL;
+        String_deleteMembers(&p->content.encoded.body, NULL);
         break;
     case UA_EXTENSIONOBJECT_DECODED:
-        if(!p->content.decoded.data)
-            break;
-        UA_delete(p->content.decoded.data, p->content.decoded.type);
-        p->content.decoded.data = NULL;
-        p->content.decoded.type = NULL;
+        if(p->content.decoded.data)
+            UA_delete(p->content.decoded.data, p->content.decoded.type);
         break;
-    case UA_EXTENSIONOBJECT_DECODED_NODELETE:
-        p->content.decoded.type = NULL;
     default:
         break;
     }
@@ -299,14 +295,9 @@ static void Variant_deletemembers(UA_Variant *p, const UA_DataType *_) {
         if(p->arrayLength == 0)
             p->arrayLength = 1;
         UA_Array_delete(p->data, p->arrayLength, p->type);
-        p->data = NULL;
-        p->arrayLength = 0;
-    }
-    if(p->arrayDimensions) {
-        UA_Array_delete(p->arrayDimensions, p->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
-        p->arrayDimensions = NULL;
-        p->arrayDimensionsSize = 0;
     }
+    if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
+        UA_free(p->arrayDimensions);
 }
 
 static UA_StatusCode
@@ -322,12 +313,11 @@ Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) {
     if(src->arrayDimensions) {
         retval = UA_Array_copy(src->arrayDimensions, src->arrayDimensionsSize,
             (void**)&dst->arrayDimensions, &UA_TYPES[UA_TYPES_INT32]);
-        if(retval == UA_STATUSCODE_GOOD)
-            dst->arrayDimensionsSize = src->arrayDimensionsSize;
-        else
-            Variant_deletemembers(dst, NULL);
+        if(retval != UA_STATUSCODE_GOOD)
+            return retval;
+        dst->arrayDimensionsSize = src->arrayDimensionsSize;
     }
-    return retval;
+    return UA_STATUSCODE_GOOD;
 }
 
 /**
@@ -397,9 +387,11 @@ processRangeDefinition(const UA_Variant *v, const UA_NumericRange range, size_t
 }
 
 UA_StatusCode
-UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRange range) {
+UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst,
+                     const UA_NumericRange range) {
     size_t count, block, stride, first;
-    UA_StatusCode retval = processRangeDefinition(src, range, &count, &block, &stride, &first);
+    UA_StatusCode retval = processRangeDefinition(src, range, &count, &block,
+                                                  &stride, &first);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     UA_Variant_init(dst);
@@ -439,22 +431,27 @@ UA_Variant_copyRange(const UA_Variant *src, UA_Variant *dst, const UA_NumericRan
 
     /* Copy the range dimensions */
     if(src->arrayDimensionsSize > 0) {
-        dst->arrayDimensions = UA_Array_new(src->arrayDimensionsSize, &UA_TYPES[UA_TYPES_UINT32]);
+        dst->arrayDimensions = UA_Array_new(src->arrayDimensionsSize,
+                                            &UA_TYPES[UA_TYPES_UINT32]);
         if(!dst->arrayDimensions) {
             Variant_deletemembers(dst, NULL);
+            memset(dst, 0, sizeof(UA_Variant)); /* init */
             return UA_STATUSCODE_BADOUTOFMEMORY;
         }
         dst->arrayDimensionsSize = src->arrayDimensionsSize;
         for(size_t k = 0; k < src->arrayDimensionsSize; k++)
-            dst->arrayDimensions[k] = (UA_Int32)(range.dimensions[k].max - range.dimensions[k].min + 1);
+            dst->arrayDimensions[k] =
+                (UA_Int32)(range.dimensions[k].max - range.dimensions[k].min + 1);
     }
     return UA_STATUSCODE_GOOD;
 }
 
 UA_StatusCode
-UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, const UA_NumericRange range) {
+UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize,
+                    const UA_NumericRange range) {
     size_t count, block, stride, first;
-    UA_StatusCode retval = processRangeDefinition(v, range, &count, &block, &stride, &first);
+    UA_StatusCode retval = processRangeDefinition(v, range, &count, &block,
+                                                  &stride, &first);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     if(count != arraySize)
@@ -467,7 +464,7 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, c
     for(size_t i = 0; i < block_count; i++) {
         if(!v->type->fixedSize) {
             for(size_t j = 0; j < block; j++) {
-                UA_deleteMembers((void*)nextdst, v->type);
+                UA_deleteMembers_noInit((void*)nextdst, v->type);
                 nextdst += elem_size;
             }
             nextdst -= block * elem_size;
@@ -480,9 +477,11 @@ UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, size_t arraySize, c
 }
 
 UA_StatusCode
-UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize, const UA_NumericRange range) {
+UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize,
+                        const UA_NumericRange range) {
     size_t count, block, stride, first;
-    UA_StatusCode retval = processRangeDefinition(v, range, &count, &block, &stride, &first);
+    UA_StatusCode retval = processRangeDefinition(v, range, &count, &block,
+                                                  &stride, &first);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     if(count != arraySize)
@@ -501,7 +500,7 @@ UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize, cons
     } else {
         for(size_t i = 0; i < block_count; i++) {
             for(size_t j = 0; j < block; j++) {
-                UA_deleteMembers((void*)nextdst, v->type);
+                UA_deleteMembers_noInit((void*)nextdst, v->type);
                 retval |= UA_copy((void*)nextsrc, (void*)nextdst, v->type);
                 nextdst += elem_size;
                 nextsrc += elem_size;
@@ -512,14 +511,16 @@ UA_Variant_setRangeCopy(UA_Variant *v, const void *array, size_t arraySize, cons
     return retval;
 }
 
-void UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p, const UA_DataType *type) {
+void UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
+                          const UA_DataType *type) {
     UA_Variant_init(v);
     v->type = type;
     v->arrayLength = 0;
     v->data = p;
 }
 
-UA_StatusCode UA_Variant_setScalarCopy(UA_Variant *v, const void *p, const UA_DataType *type) {
+UA_StatusCode UA_Variant_setScalarCopy(UA_Variant *v, const void *p,
+                                       const UA_DataType *type) {
     void *new = UA_malloc(type->memSize);
     if(!new)
         return UA_STATUSCODE_BADOUTOFMEMORY;
@@ -534,9 +535,8 @@ UA_StatusCode UA_Variant_setScalarCopy(UA_Variant *v, const void *p, const UA_Da
     return UA_STATUSCODE_GOOD;
 }
 
-void
-UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
-                    size_t arraySize, const UA_DataType *type) {
+void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
+                         size_t arraySize, const UA_DataType *type) {
     UA_Variant_init(v);
     v->data = array;
     v->arrayLength = arraySize;
@@ -556,13 +556,15 @@ UA_Variant_setArrayCopy(UA_Variant *v, const void *array,
 }
 
 /* LocalizedText */
-static void LocalizedText_deleteMembers(UA_LocalizedText *p, const UA_DataType *_) {
-    UA_String_deleteMembers(&p->locale);
-    UA_String_deleteMembers(&p->text);
+static void
+LocalizedText_deleteMembers(UA_LocalizedText *p, const UA_DataType *_) {
+    String_deleteMembers(&p->locale, NULL);
+    String_deleteMembers(&p->text, NULL);
 }
 
 static UA_StatusCode
-LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst, const UA_DataType *_) {
+LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst,
+                   const UA_DataType *_) {
     UA_StatusCode retval = UA_String_copy(&src->locale, &dst->locale);
     retval |= UA_String_copy(&src->text, &dst->text);
     return retval;
@@ -574,7 +576,8 @@ static void DataValue_deleteMembers(UA_DataValue *p, const UA_DataType *_) {
 }
 
 static UA_StatusCode
-DataValue_copy(UA_DataValue const *src, UA_DataValue *dst, const UA_DataType *_) {
+DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
+               const UA_DataType *_) {
     memcpy(dst, src, sizeof(UA_DataValue));
     UA_Variant_init(&dst->value);
     UA_StatusCode retval = Variant_copy(&src->value, &dst->value, NULL);
@@ -584,8 +587,9 @@ DataValue_copy(UA_DataValue const *src, UA_DataValue *dst, const UA_DataType *_)
 }
 
 /* DiagnosticInfo */
-static void DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p, const UA_DataType *_) {
-    UA_String_deleteMembers(&p->additionalInfo);
+static void
+DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p, const UA_DataType *_) {
+    String_deleteMembers(&p->additionalInfo, NULL);
     if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
         DiagnosticInfo_deleteMembers(p->innerDiagnosticInfo, NULL);
         UA_free(p->innerDiagnosticInfo);
@@ -595,7 +599,8 @@ static void DiagnosticInfo_deleteMembers(UA_DiagnosticInfo *p, const UA_DataType
 }
 
 static UA_StatusCode
-DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst, const UA_DataType *_) {
+DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
+                    const UA_DataType *_) {
     memcpy(dst, src, sizeof(UA_DiagnosticInfo));
     UA_String_init(&dst->additionalInfo);
     dst->innerDiagnosticInfo = NULL;
@@ -604,55 +609,61 @@ DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst, const
        retval = UA_String_copy(&src->additionalInfo, &dst->additionalInfo);
     if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
         if((dst->innerDiagnosticInfo = UA_malloc(sizeof(UA_DiagnosticInfo)))) {
-            retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo, NULL);
+            retval |= DiagnosticInfo_copy(src->innerDiagnosticInfo,
+                                          dst->innerDiagnosticInfo, NULL);
             dst->hasInnerDiagnosticInfo = true;
         } else {
             dst->hasInnerDiagnosticInfo = false;
             retval |= UA_STATUSCODE_BADOUTOFMEMORY;
         }
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        DiagnosticInfo_deleteMembers(dst, NULL);
     return retval;
 }
 
-/*******************/
-/* Structure Types */
-/*******************/
+/********************/
+/* Structured Types */
+/********************/
 
 void * UA_new(const UA_DataType *type) {
     void *p = UA_calloc(1, type->memSize);
     return p;
 }
 
-static UA_StatusCode copyByte(const void *src, void *dst, const UA_DataType *_) {
-    memcpy(dst, src, sizeof(UA_Byte));
+static UA_StatusCode
+copyByte(const UA_Byte *src, UA_Byte *dst, const UA_DataType *_) {
+    *dst = *src;
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode copy2Byte(const void *src, void *dst, const UA_DataType *_) {
-    memcpy(dst, src, sizeof(UA_UInt16));
+static UA_StatusCode
+copy2Byte(const UA_UInt16 *src, UA_UInt16 *dst, const UA_DataType *_) {
+    *dst = *src;
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode copy4Byte(const void *src, void *dst, const UA_DataType *_) {
-    memcpy(dst, src, sizeof(UA_UInt32));
+static UA_StatusCode
+copy4Byte(const UA_UInt32 *src, UA_UInt32 *dst, const UA_DataType *_) {
+    *dst = *src;
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode copy8Byte(const void *src, void *dst, const UA_DataType *_) {
-    memcpy(dst, src, sizeof(UA_UInt64));
+static UA_StatusCode
+copy8Byte(const UA_UInt64 *src, UA_UInt64 *dst, const UA_DataType *_) {
+    *dst = *src;
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode copyFixedSize(const void *src, void *dst, const UA_DataType *type) {
-    memcpy(dst, src, type->memSize);
+static UA_StatusCode
+copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
+    *dst = *src;
     return UA_STATUSCODE_GOOD;
 }
 
 static UA_StatusCode copyNoInit(const void *src, void *dst, const UA_DataType *type);
 
-typedef UA_StatusCode (*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
+typedef UA_StatusCode
+(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
+
 static const UA_copySignature copyJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
     (UA_copySignature)copyByte, // Boolean
     (UA_copySignature)copyByte, // SByte
@@ -667,7 +678,7 @@ static const UA_copySignature copyJumpTable[UA_BUILTIN_TYPES_COUNT + 1] = {
     (UA_copySignature)copy8Byte, // Double
     (UA_copySignature)copyNoInit, // String
     (UA_copySignature)copy8Byte, // DateTime
-    (UA_copySignature)copyFixedSize, // Guid
+    (UA_copySignature)copyGuid, // Guid
     (UA_copySignature)copyNoInit, // ByteString
     (UA_copySignature)copyNoInit, // XmlElement
     (UA_copySignature)NodeId_copy,
@@ -706,21 +717,23 @@ static UA_StatusCode copyNoInit(const void *src, void *dst, const UA_DataType *t
             ptrs += sizeof(size_t);
             ptrd += sizeof(size_t);
             retval |= UA_Array_copy(*(void* const*)ptrs, size, (void**)ptrd, memberType);
-            *dst_size = size;
-            if(retval != UA_STATUSCODE_GOOD)
+            if(retval == UA_STATUSCODE_GOOD)
+                *dst_size = size;
+            else
                 *dst_size = 0;
             ptrs += sizeof(void*);
             ptrd += sizeof(void*);
         }
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_deleteMembers(dst, type);
     return retval;
 }
 
 UA_StatusCode UA_copy(const void *src, void *dst, const UA_DataType *type) {
-    memset(dst, 0, type->memSize);
-    return copyNoInit(src, dst, type);
+    memset(dst, 0, type->memSize); /* init */
+    UA_StatusCode retval = copyNoInit(src, dst, type);
+    if(retval != UA_STATUSCODE_GOOD)
+        UA_deleteMembers(dst, type);
+    return retval;
 }
 
 typedef void (*UA_deleteMembersSignature)(void *p, const UA_DataType *type);
@@ -738,24 +751,24 @@ static const UA_deleteMembersSignature deleteMembersJumpTable[UA_BUILTIN_TYPES_C
     (UA_deleteMembersSignature)nopDeleteMembers, // UInt64
     (UA_deleteMembersSignature)nopDeleteMembers, // Float
     (UA_deleteMembersSignature)nopDeleteMembers, // Double
-    (UA_deleteMembersSignature)UA_deleteMembers, // String
+    (UA_deleteMembersSignature)String_deleteMembers, // String
     (UA_deleteMembersSignature)nopDeleteMembers, // DateTime
     (UA_deleteMembersSignature)nopDeleteMembers, // Guid
-    (UA_deleteMembersSignature)UA_deleteMembers, // ByteString
-    (UA_deleteMembersSignature)UA_deleteMembers, // XmlElement
+    (UA_deleteMembersSignature)String_deleteMembers, // ByteString
+    (UA_deleteMembersSignature)String_deleteMembers, // XmlElement
     (UA_deleteMembersSignature)NodeId_deleteMembers,
     (UA_deleteMembersSignature)ExpandedNodeId_deleteMembers, // ExpandedNodeId
     (UA_deleteMembersSignature)nopDeleteMembers, // StatusCode
-    (UA_deleteMembersSignature)UA_deleteMembers, // QualifiedName
+    (UA_deleteMembersSignature)UA_deleteMembers_noInit, // QualifiedName
     (UA_deleteMembersSignature)LocalizedText_deleteMembers, // LocalizedText
     (UA_deleteMembersSignature)ExtensionObject_deleteMembers,
     (UA_deleteMembersSignature)DataValue_deleteMembers,
     (UA_deleteMembersSignature)Variant_deletemembers,
     (UA_deleteMembersSignature)DiagnosticInfo_deleteMembers,
-    (UA_deleteMembersSignature)UA_deleteMembers,
+    (UA_deleteMembersSignature)UA_deleteMembers_noInit,
 };
 
-void UA_deleteMembers(void *p, const UA_DataType *type) {
+static void UA_deleteMembers_noInit(void *p, const UA_DataType *type) {
     uintptr_t ptr = (uintptr_t)p;
     UA_Byte membersSize = type->membersSize;
     for(size_t i = 0; i < membersSize; i++) {
@@ -770,17 +783,20 @@ void UA_deleteMembers(void *p, const UA_DataType *type) {
         } else {
             ptr += member->padding;
             size_t length = *(size_t*)ptr;
-            *(size_t*)ptr = 0;
             ptr += sizeof(size_t);
             UA_Array_delete(*(void**)ptr, length, memberType);
-            *(void**)ptr = NULL;
             ptr += sizeof(void*);
         }
     }
 }
 
+void UA_deleteMembers(void *p, const UA_DataType *type) {
+    UA_deleteMembers_noInit(p, type);
+    memset(p, 0, type->memSize); /* init */
+}
+
 void UA_delete(void *p, const UA_DataType *type) {
-    UA_deleteMembers(p, type);
+    UA_deleteMembers_noInit(p, type);
     UA_free(p);
 }
 

+ 28 - 17
src/ua_types_encoding_binary.c

@@ -1,6 +1,26 @@
 #include "ua_util.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
+
+/* There is no robust way to detect float endianness in clang. This warning can
+ * be removed if the target is known to be little endian with floats in the IEEE
+ * 754 format. */
+#if defined(__clang__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic warning "-W#warnings"
+#endif
+
+#ifndef UA_BINARY_OVERLAYABLE_INTEGER
+# warning Integer endianness could not be detected to be little endian. Use slow generic encoding.
+#endif
+#ifndef UA_BINARY_OVERLAYABLE_FLOAT
+# warning Float endianness could not be detected to be little endian in the IEEE 754 format. Use slow generic encoding.
+#endif
+
+#if defined(__clang__)
+# pragma GCC diagnostic pop
+#endif
 
 /* Jumptables for de-/encoding and computing the buffer length */
 typedef UA_StatusCode (*UA_encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type);
@@ -601,8 +621,6 @@ NodeId_decodeBinary(UA_NodeId *dst, const UA_DataType *_) {
         retval |= UA_STATUSCODE_BADINTERNALERROR; // the client sends an encodingByte we do not recognize
         break;
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_NodeId_deleteMembers(dst);
     return retval;
 }
 
@@ -640,8 +658,6 @@ ExpandedNodeId_decodeBinary(UA_ExpandedNodeId *dst, const UA_DataType *_) {
     }
     if(encodingByte & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
         retval |= UInt32_decodeBinary(&dst->serverIndex, NULL);
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_ExpandedNodeId_deleteMembers(dst);
     return retval;
 }
 
@@ -672,8 +688,6 @@ LocalizedText_decodeBinary(UA_LocalizedText *dst, const UA_DataType *_) {
         retval |= String_decodeBinary(&dst->locale, NULL);
     if(encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
         retval |= String_decodeBinary(&dst->text, NULL);
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_LocalizedText_deleteMembers(dst);
     return retval;
 }
 
@@ -776,8 +790,6 @@ ExtensionObject_decodeBinary(UA_ExtensionObject *dst, const UA_DataType *_) {
             dst->content.encoded.typeId = typeId;
         }
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_ExtensionObject_deleteMembers(dst);
     return retval;
 }
 
@@ -938,8 +950,6 @@ Variant_decodeBinary(UA_Variant *dst, const UA_DataType *_) {
                                         &dst->arrayDimensionsSize, &UA_TYPES[UA_TYPES_INT32]);
     }
 
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_Variant_deleteMembers(dst);
     return retval;
 }
 
@@ -1001,8 +1011,6 @@ DataValue_decodeBinary(UA_DataValue *dst, const UA_DataType *_) {
         if(dst->serverPicoseconds > MAX_PICO_SECONDS)
             dst->serverPicoseconds = MAX_PICO_SECONDS;
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_DataValue_deleteMembers(dst);
     return retval;
 }
 
@@ -1071,8 +1079,6 @@ DiagnosticInfo_decodeBinary(UA_DiagnosticInfo *dst, const UA_DataType *_) {
             retval |= UA_STATUSCODE_BADOUTOFMEMORY;
         }
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_DiagnosticInfo_deleteMembers(dst);
     return retval;
 }
 
@@ -1182,8 +1188,10 @@ UA_decodeBinaryInternal(void *dst, const UA_DataType *type) {
             ptr += sizeof(void*);
         }
     }
-    if(retval != UA_STATUSCODE_GOOD)
-        UA_deleteMembers(dst, type);
+    /* deleteMembers is executed only at the highest level in UA_decodeBinary to
+       avoid duplicate work */
+    /* if(retval != UA_STATUSCODE_GOOD) */
+    /*     UA_deleteMembers(dst, type); */
     return retval;
 }
 
@@ -1222,7 +1230,10 @@ UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst, const UA_Da
     pos = &src->data[*offset];
     end = &src->data[src->length];
     UA_StatusCode retval = UA_decodeBinaryInternal(dst, type);
-    *offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
+    if(retval == UA_STATUSCODE_GOOD)
+        *offset = (size_t)(pos - src->data) / sizeof(UA_Byte);
+    else
+        UA_deleteMembers(dst, type);
     return retval;
 }
 

+ 1 - 0
tests/CMakeLists.txt

@@ -3,6 +3,7 @@ include_directories(${PROJECT_SOURCE_DIR}/deps)
 include_directories(${PROJECT_SOURCE_DIR}/src)
 include_directories(${PROJECT_SOURCE_DIR}/plugins)
 include_directories(${PROJECT_BINARY_DIR}/src_generated)
+include_directories(${CHECK_INCLUDE_DIRS})
 
 find_package(Check REQUIRED)
 find_package(Threads REQUIRED)

+ 1 - 0
tests/check_builtin.c

@@ -5,6 +5,7 @@
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_util.h"
 #include "check.h"

+ 1 - 0
tests/check_chunking.c

@@ -1,6 +1,7 @@
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_securechannel.h"
 #include "ua_util.h"

+ 149 - 152
tests/check_memory.c

@@ -4,45 +4,46 @@
 
 #include "ua_types.h"
 #include "ua_types_generated.h"
+#include "ua_types_generated_handling.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_util.h"
 #include "check.h"
 
 START_TEST(newAndEmptyObjectShallBeDeleted) {
-	// given
-	void *obj = UA_new(&UA_TYPES[_i]);
-	// then
-	ck_assert_ptr_ne(obj, NULL);
+    // given
+    void *obj = UA_new(&UA_TYPES[_i]);
+    // then
+    ck_assert_ptr_ne(obj, NULL);
     // finally
-	UA_delete(obj, &UA_TYPES[_i]);
+    UA_delete(obj, &UA_TYPES[_i]);
 }
 END_TEST
 
 START_TEST(arrayCopyShallMakeADeepCopy) {
-	// given
-	UA_String a1[3];
-	a1[0] = (UA_String){1, (UA_Byte*)"a"};
-	a1[1] = (UA_String){2, (UA_Byte*)"bb"};
-	a1[2] = (UA_String){3, (UA_Byte*)"ccc"};
-	// when
-	UA_String *a2;
-	UA_Int32 retval = UA_Array_copy((const void *)a1, 3, (void **)&a2, &UA_TYPES[UA_TYPES_STRING]);
-	// then
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
-	ck_assert_int_eq(a1[0].length, 1);
-	ck_assert_int_eq(a1[1].length, 2);
-	ck_assert_int_eq(a1[2].length, 3);
-	ck_assert_int_eq(a1[0].length, a2[0].length);
-	ck_assert_int_eq(a1[1].length, a2[1].length);
-	ck_assert_int_eq(a1[2].length, a2[2].length);
-	ck_assert_ptr_ne(a1[0].data, a2[0].data);
-	ck_assert_ptr_ne(a1[1].data, a2[1].data);
-	ck_assert_ptr_ne(a1[2].data, a2[2].data);
-	ck_assert_int_eq(a1[0].data[0], a2[0].data[0]);
-	ck_assert_int_eq(a1[1].data[0], a2[1].data[0]);
-	ck_assert_int_eq(a1[2].data[0], a2[2].data[0]);
-	// finally
-	UA_Array_delete((void *)a2, 3, &UA_TYPES[UA_TYPES_STRING]);
+    // given
+    UA_String a1[3];
+    a1[0] = (UA_String){1, (UA_Byte*)"a"};
+    a1[1] = (UA_String){2, (UA_Byte*)"bb"};
+    a1[2] = (UA_String){3, (UA_Byte*)"ccc"};
+    // when
+    UA_String *a2;
+    UA_Int32 retval = UA_Array_copy((const void *)a1, 3, (void **)&a2, &UA_TYPES[UA_TYPES_STRING]);
+    // then
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    ck_assert_int_eq(a1[0].length, 1);
+    ck_assert_int_eq(a1[1].length, 2);
+    ck_assert_int_eq(a1[2].length, 3);
+    ck_assert_int_eq(a1[0].length, a2[0].length);
+    ck_assert_int_eq(a1[1].length, a2[1].length);
+    ck_assert_int_eq(a1[2].length, a2[2].length);
+    ck_assert_ptr_ne(a1[0].data, a2[0].data);
+    ck_assert_ptr_ne(a1[1].data, a2[1].data);
+    ck_assert_ptr_ne(a1[2].data, a2[2].data);
+    ck_assert_int_eq(a1[0].data[0], a2[0].data[0]);
+    ck_assert_int_eq(a1[1].data[0], a2[1].data[0]);
+    ck_assert_int_eq(a1[2].data[0], a2[2].data[0]);
+    // finally
+    UA_Array_delete((void *)a2, 3, &UA_TYPES[UA_TYPES_STRING]);
 }
 END_TEST
 
@@ -55,137 +56,133 @@ START_TEST(encodeShallYieldDecode) {
        _i != UA_TYPES_CREATESUBSCRIPTIONREQUEST || _i != UA_TYPES_CREATESUBSCRIPTIONRESPONSE)
         return;
 
-	// given
-	UA_ByteString msg1, msg2;
-	size_t pos = 0;
-	void *obj1 = UA_new(&UA_TYPES[_i]);
+    // given
+    UA_ByteString msg1, msg2;
+    size_t pos = 0;
+    void *obj1 = UA_new(&UA_TYPES[_i]);
     UA_StatusCode retval = UA_ByteString_allocBuffer(&msg1, 65000); // fixed buf size
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
     retval = UA_encodeBinary(obj1, &UA_TYPES[_i], NULL, NULL, &msg1, &pos);
     msg1.length = pos;
-	if(retval != UA_STATUSCODE_GOOD) {
-		UA_delete(obj1, &UA_TYPES[_i]);
-		UA_ByteString_deleteMembers(&msg1);
-		return;	
-	}
-
-	// when
-	void *obj2 = UA_new(&UA_TYPES[_i]);
-	pos = 0; retval = UA_decodeBinary(&msg1, &pos, obj2, &UA_TYPES[_i]);
+    if(retval != UA_STATUSCODE_GOOD) {
+        UA_delete(obj1, &UA_TYPES[_i]);
+        UA_ByteString_deleteMembers(&msg1);
+        return;
+    }
+
+    // when
+    void *obj2 = UA_new(&UA_TYPES[_i]);
+    pos = 0; retval = UA_decodeBinary(&msg1, &pos, obj2, &UA_TYPES[_i]);
     ck_assert_msg(retval == UA_STATUSCODE_GOOD, "could not decode idx=%d,nodeid=%i",
                   _i, UA_TYPES[_i].typeId.identifier.numeric);
     ck_assert(!memcmp(obj1, obj2, UA_TYPES[_i].memSize)); // bit identical decoding
-	retval = UA_ByteString_allocBuffer(&msg2, 65000);
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
-	pos = 0; retval = UA_encodeBinary(obj2, &UA_TYPES[_i], NULL, NULL, &msg2, &pos);
+    retval = UA_ByteString_allocBuffer(&msg2, 65000);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    pos = 0; retval = UA_encodeBinary(obj2, &UA_TYPES[_i], NULL, NULL, &msg2, &pos);
     msg2.length = pos;
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
 
-	// then
+    // then
     ck_assert_msg(UA_ByteString_equal(&msg1, &msg2) == true, "messages differ idx=%d,nodeid=%i", _i,
                   UA_TYPES[_i].typeId.identifier.numeric);
 
-	// finally
-	UA_delete(obj1, &UA_TYPES[_i]);
-	UA_delete(obj2, &UA_TYPES[_i]);
-	UA_ByteString_deleteMembers(&msg1);
-	UA_ByteString_deleteMembers(&msg2);
+    // finally
+    UA_delete(obj1, &UA_TYPES[_i]);
+    UA_delete(obj2, &UA_TYPES[_i]);
+    UA_ByteString_deleteMembers(&msg1);
+    UA_ByteString_deleteMembers(&msg2);
 }
 END_TEST
 
 START_TEST(decodeShallFailWithTruncatedBufferButSurvive) {
-	// given
-	UA_ByteString msg1;
-	void *obj1 = UA_new(&UA_TYPES[_i]);
-	size_t pos = 0;
+    // given
+    UA_ByteString msg1;
+    void *obj1 = UA_new(&UA_TYPES[_i]);
+    size_t pos = 0;
     UA_StatusCode retval = UA_ByteString_allocBuffer(&msg1, 65000); // fixed buf size
     retval |= UA_encodeBinary(obj1, &UA_TYPES[_i], NULL, NULL, &msg1, &pos);
-	UA_delete(obj1, &UA_TYPES[_i]);
+    UA_delete(obj1, &UA_TYPES[_i]);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ByteString_deleteMembers(&msg1);
         return; // e.g. variants cannot be encoded after an init without failing (no datatype set)
     }
-	// when
-	void *obj2 = UA_new(&UA_TYPES[_i]);
-	msg1.length = pos / 2;
-	pos = 0;
-	//fprintf(stderr,"testing %s with half buffer\n",UA_TYPES[_i].name);
-	retval = UA_decodeBinary(&msg1, &pos, obj2, &UA_TYPES[_i]);
-	ck_assert_int_ne(retval, UA_STATUSCODE_GOOD);
-	//then
-	// finally
-	//fprintf(stderr,"delete %s with half buffer\n",UA_TYPES[_i].name);
-	UA_delete(obj2, &UA_TYPES[_i]);
-	UA_ByteString_deleteMembers(&msg1);
+    // when
+    void *obj2 = UA_new(&UA_TYPES[_i]);
+    msg1.length = pos / 2;
+    pos = 0;
+    retval = UA_decodeBinary(&msg1, &pos, obj2, &UA_TYPES[_i]);
+    ck_assert_int_ne(retval, UA_STATUSCODE_GOOD);
+    UA_delete(obj2, &UA_TYPES[_i]);
+    UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST
 
 #define RANDOM_TESTS 1000
 
 START_TEST(decodeScalarBasicTypeFromRandomBufferShallSucceed) {
-	// given
-	void *obj1 = NULL;
-	UA_ByteString msg1;
-	UA_Int32 retval = UA_STATUSCODE_GOOD;
-	UA_Int32 buflen = 256;
-	retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
+    // given
+    void *obj1 = NULL;
+    UA_ByteString msg1;
+    UA_Int32 retval = UA_STATUSCODE_GOOD;
+    UA_Int32 buflen = 256;
+    retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
 #ifdef _WIN32
-	srand(42);
+    srand(42);
 #else
-	srandom(42);
+    srandom(42);
 #endif
-	for(int n = 0;n < RANDOM_TESTS;n++) {
-		for(UA_Int32 i = 0;i < buflen;i++) {
+    for(int n = 0;n < RANDOM_TESTS;n++) {
+        for(UA_Int32 i = 0;i < buflen;i++) {
 #ifdef _WIN32
-			UA_UInt32 rnd;
-			rnd = rand();
-			msg1.data[i] = rnd;
+            UA_UInt32 rnd;
+            rnd = rand();
+            msg1.data[i] = rnd;
 #else
-			msg1.data[i] = (UA_Byte)random();  // when
+            msg1.data[i] = (UA_Byte)random();  // when
 #endif
-		}
-		size_t pos = 0;
-		obj1 = UA_new(&UA_TYPES[_i]);
-		retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i]);
-		//then
-		ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Decoding %d from random buffer", UA_TYPES[_i].typeId.identifier.numeric);
-		// finally
-		UA_delete(obj1, &UA_TYPES[_i]);
-	}
-	UA_ByteString_deleteMembers(&msg1);
+        }
+        size_t pos = 0;
+        obj1 = UA_new(&UA_TYPES[_i]);
+        retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i]);
+        //then
+        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Decoding %d from random buffer", UA_TYPES[_i].typeId.identifier.numeric);
+        // finally
+        UA_delete(obj1, &UA_TYPES[_i]);
+    }
+    UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST
 
 START_TEST(decodeComplexTypeFromRandomBufferShallSurvive) {
-	// given
-	UA_ByteString msg1;
-	UA_Int32 retval = UA_STATUSCODE_GOOD;
-	UA_Int32 buflen = 256;
-	retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
+    // given
+    UA_ByteString msg1;
+    UA_Int32 retval = UA_STATUSCODE_GOOD;
+    UA_Int32 buflen = 256;
+    retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
 #ifdef _WIN32
-	srand(42);
+    srand(42);
 #else
-	srandom(42);
+    srandom(42);
 #endif
-	// when
-	for(int n = 0;n < RANDOM_TESTS;n++) {
-		for(UA_Int32 i = 0;i < buflen;i++) {
+    // when
+    for(int n = 0;n < RANDOM_TESTS;n++) {
+        for(UA_Int32 i = 0;i < buflen;i++) {
 #ifdef _WIN32
-			UA_UInt32 rnd;
-			rnd = rand();
-			msg1.data[i] = rnd;
+            UA_UInt32 rnd;
+            rnd = rand();
+            msg1.data[i] = rnd;
 #else
-			msg1.data[i] = (UA_Byte)random();  // when
+            msg1.data[i] = (UA_Byte)random();  // when
 #endif
-		}
-		size_t pos = 0;
-		void *obj1 = UA_new(&UA_TYPES[_i]);
-		retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i]);
-		UA_delete(obj1, &UA_TYPES[_i]);
-	}
-
-	// finally
-	UA_ByteString_deleteMembers(&msg1);
+        }
+        size_t pos = 0;
+        void *obj1 = UA_new(&UA_TYPES[_i]);
+        retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i]);
+        UA_delete(obj1, &UA_TYPES[_i]);
+    }
+
+    // finally
+    UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST
 
@@ -195,51 +192,51 @@ START_TEST(calcSizeBinaryShallBeCorrect) {
        _i == UA_TYPES_VARIABLEATTRIBUTES ||
        _i == UA_TYPES_VARIABLETYPEATTRIBUTES)
         return;
-	void *obj = UA_new(&UA_TYPES[_i]);
+    void *obj = UA_new(&UA_TYPES[_i]);
     size_t predicted_size = UA_calcSizeBinary(obj, &UA_TYPES[_i]);
-	ck_assert_int_ne(predicted_size, 0);
+    ck_assert_int_ne(predicted_size, 0);
     UA_ByteString msg;
     UA_StatusCode retval = UA_ByteString_allocBuffer(&msg, predicted_size);
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
     size_t offset = 0;
-retval = UA_encodeBinary(obj, &UA_TYPES[_i], NULL, NULL, &msg, &offset);
+    retval = UA_encodeBinary(obj, &UA_TYPES[_i], NULL, NULL, &msg, &offset);
     if(retval)
         printf("%i\n",_i);
-	ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
-	ck_assert_int_eq(offset, predicted_size);
+    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
+    ck_assert_int_eq(offset, predicted_size);
     UA_delete(obj, &UA_TYPES[_i]);
     UA_ByteString_deleteMembers(&msg);
 }
 END_TEST
 
 int main(void) {
-	int number_failed = 0;
-	SRunner *sr;
-
-	Suite *s  = suite_create("testMemoryHandling");
-	TCase *tc = tcase_create("Empty Objects");
-	tcase_add_loop_test(tc, newAndEmptyObjectShallBeDeleted, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
-	tcase_add_test(tc, arrayCopyShallMakeADeepCopy);
-	tcase_add_loop_test(tc, encodeShallYieldDecode, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
-	suite_add_tcase(s, tc);
-	tc = tcase_create("Truncated Buffers");
-	tcase_add_loop_test(tc, decodeShallFailWithTruncatedBufferButSurvive, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
-	suite_add_tcase(s, tc);
-
-	tc = tcase_create("Fuzzing with Random Buffers");
-	tcase_add_loop_test(tc, decodeScalarBasicTypeFromRandomBufferShallSucceed, UA_TYPES_BOOLEAN, UA_TYPES_DOUBLE);
-	tcase_add_loop_test(tc, decodeComplexTypeFromRandomBufferShallSurvive, UA_TYPES_NODEID, UA_TYPES_COUNT - 1);
-	suite_add_tcase(s, tc);
-
-	tc = tcase_create("Test calcSizeBinary");
-	tcase_add_loop_test(tc, calcSizeBinaryShallBeCorrect, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
-	suite_add_tcase(s, tc);
-
-	sr = srunner_create(s);
-	srunner_set_fork_status(sr, CK_NOFORK);
-	srunner_run_all (sr, CK_NORMAL);
-	number_failed += srunner_ntests_failed(sr);
-	srunner_free(sr);
-
-	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+    int number_failed = 0;
+    SRunner *sr;
+
+    Suite *s  = suite_create("testMemoryHandling");
+    TCase *tc = tcase_create("Empty Objects");
+    tcase_add_loop_test(tc, newAndEmptyObjectShallBeDeleted, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
+    tcase_add_test(tc, arrayCopyShallMakeADeepCopy);
+    tcase_add_loop_test(tc, encodeShallYieldDecode, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
+    suite_add_tcase(s, tc);
+    tc = tcase_create("Truncated Buffers");
+    tcase_add_loop_test(tc, decodeShallFailWithTruncatedBufferButSurvive, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
+    suite_add_tcase(s, tc);
+
+    tc = tcase_create("Fuzzing with Random Buffers");
+    tcase_add_loop_test(tc, decodeScalarBasicTypeFromRandomBufferShallSucceed, UA_TYPES_BOOLEAN, UA_TYPES_DOUBLE);
+    tcase_add_loop_test(tc, decodeComplexTypeFromRandomBufferShallSurvive, UA_TYPES_NODEID, UA_TYPES_COUNT - 1);
+    suite_add_tcase(s, tc);
+
+    tc = tcase_create("Test calcSizeBinary");
+    tcase_add_loop_test(tc, calcSizeBinaryShallBeCorrect, UA_TYPES_BOOLEAN, UA_TYPES_COUNT - 1);
+    suite_add_tcase(s, tc);
+
+    sr = srunner_create(s);
+    srunner_set_fork_status(sr, CK_NOFORK);
+    srunner_run_all (sr, CK_NORMAL);
+    number_failed += srunner_ntests_failed(sr);
+    srunner_free(sr);
+
+    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }

+ 2 - 2
tools/amalgamate.py

@@ -44,8 +44,8 @@ file.write(u"""/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN6
  */\n\n""" % args.version)
 
 if is_c:
-    file.write(u'''#ifndef UA_DYNAMIC_LINKING
-# define UA_DYNAMIC_LINKING
+    file.write(u'''#ifndef UA_DYNAMIC_LINKING_EXPORT
+# define UA_DYNAMIC_LINKING_EXPORT
 #endif
 
 #include "%s.h"

+ 106 - 63
tools/generate_datatypes.py

@@ -117,22 +117,22 @@ class Type(object):
 
     def datatype_ptr(self):
         return "&" + self.outname.upper() + "[" + self.outname.upper() + "_" + self.name.upper() + "]"
-        
+
     def functions_c(self):
-        funcs = "static UA_INLINE void UA_%s_init(UA_%s *p) { memset(p, 0, sizeof(UA_%s)); }\n" % (self.name, self.name, self.name)
-        funcs += "static UA_INLINE UA_%s * UA_%s_new(void) { return (UA_%s*) UA_new(%s); }\n" % (self.name, self.name, self.name, self.datatype_ptr())
+        funcs = "static UA_INLINE void\nUA_%s_init(UA_%s *p) {\n    memset(p, 0, sizeof(UA_%s));\n}\n\n" % (self.name, self.name, self.name)
+        funcs += "static UA_INLINE UA_%s *\nUA_%s_new(void) {\n    return (UA_%s*)UA_new(%s);\n}\n\n" % (self.name, self.name, self.name, self.datatype_ptr())
         if self.fixed_size == "true":
-            funcs += "static UA_INLINE UA_StatusCode UA_%s_copy(const UA_%s *src, UA_%s *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }\n" % (self.name, self.name, self.name)
-            funcs += "static UA_INLINE void UA_%s_deleteMembers(UA_%s *p) { }\n" % (self.name, self.name)
+            funcs += "static UA_INLINE UA_StatusCode\nUA_%s_copy(const UA_%s *src, UA_%s *dst) {\n    *dst = *src;\n    return UA_STATUSCODE_GOOD;\n}\n\n" % (self.name, self.name, self.name)
+            funcs += "static UA_INLINE void\nUA_%s_deleteMembers(UA_%s *p) { }\n\n" % (self.name, self.name)
         else:
-            funcs += "static UA_INLINE UA_StatusCode UA_%s_copy(const UA_%s *src, UA_%s *dst) { return UA_copy(src, dst, %s); }\n" % (self.name, self.name, self.name, self.datatype_ptr())
-            funcs += "static UA_INLINE void UA_%s_deleteMembers(UA_%s *p) { UA_deleteMembers(p, %s); }\n" % (self.name, self.name, self.datatype_ptr())
-        funcs += "static UA_INLINE void UA_%s_delete(UA_%s *p) { UA_delete(p, %s); }" % (self.name, self.name, self.datatype_ptr())
+            funcs += "static UA_INLINE UA_StatusCode\nUA_%s_copy(const UA_%s *src, UA_%s *dst) {\n    return UA_copy(src, dst, %s);\n}\n\n" % (self.name, self.name, self.name, self.datatype_ptr())
+            funcs += "static UA_INLINE void\nUA_%s_deleteMembers(UA_%s *p) {\n    UA_deleteMembers(p, %s);\n}\n\n" % (self.name, self.name, self.datatype_ptr())
+        funcs += "static UA_INLINE void\nUA_%s_delete(UA_%s *p) {\n    UA_delete(p, %s);\n}" % (self.name, self.name, self.datatype_ptr())
         return funcs
 
     def encoding_h(self):
-        enc = "static UA_INLINE UA_StatusCode UA_%s_encodeBinary(const UA_%s *src, UA_ByteString *dst, size_t *offset) { return UA_encodeBinary(src, %s, NULL, NULL, dst, offset); }\n"
-        enc += "static UA_INLINE UA_StatusCode UA_%s_decodeBinary(const UA_ByteString *src, size_t *offset, UA_%s *dst) { return UA_decodeBinary(src, offset, dst, %s); }"
+        enc = "static UA_INLINE UA_StatusCode\nUA_%s_encodeBinary(const UA_%s *src, UA_ByteString *dst, size_t *offset) {\n    return UA_encodeBinary(src, %s, NULL, NULL, dst, offset);\n}\n"
+        enc += "static UA_INLINE UA_StatusCode\nUA_%s_decodeBinary(const UA_ByteString *src, size_t *offset, UA_%s *dst) {\n    return UA_decodeBinary(src, offset, dst, %s);\n}"
         return enc % tuple(list(itertools.chain(*itertools.repeat([self.name, self.name, self.datatype_ptr()], 2))))
 
 class BuiltinType(Type):
@@ -168,13 +168,13 @@ class EnumerationType(Type):
         for child in xml:
             if child.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedValue":
                 self.elements[child.get("Name")] = child.get("Value")
-    
+
     def typedef_h(self):
         if sys.version_info[0] < 3:
             values = self.elements.iteritems()
         else:
             values = self.elements.items()
-        return "typedef enum { \n    " + ",\n    ".join(map(lambda kv : "UA_" + self.name.upper() + "_" + kv[0].upper() + \
+        return "typedef enum {\n    " + ",\n    ".join(map(lambda kv : "UA_" + self.name.upper() + "_" + kv[0].upper() + \
                                                             " = " + kv[1], values)) + "\n} UA_%s;" % self.name
 
 class OpaqueType(Type):
@@ -328,7 +328,7 @@ parser.add_argument('typexml_additional', nargs='*', help='path/to/Opc.Ua.Types.
 parser.add_argument('outfile', help='output file w/o extension')
 args = parser.parse_args()
 
-outname = args.outfile.split("/")[-1] 
+outname = args.outfile.split("/")[-1]
 inname = ', '.join([args.typexml_ns0.split("/")[-1]] + list(map(lambda x:x.split("/")[-1], args.typexml_additional)))
 
 ################
@@ -358,15 +358,30 @@ if args.selected_types:
 #############################
 
 fh = open(args.outfile + "_generated.h",'w')
+ff = open(args.outfile + "_generated_handling.h",'w')
 fe = open(args.outfile + "_generated_encoding_binary.h",'w')
 fc = open(args.outfile + "_generated.c",'w')
 def printh(string):
     print(string, end='\n', file=fh)
+def printf(string):
+    print(string, end='\n', file=ff)
 def printe(string):
     print(string, end='\n', file=fe)
 def printc(string):
     print(string, end='\n', file=fc)
 
+def iter_types(v):
+    l = None
+    if sys.version_info[0] < 3:
+        l = list(v.itervalues())
+    else:
+        l = list(v.values())
+    return filter(lambda t: t.name in selected_types, l)
+
+################
+# Print Header #
+################
+
 printh('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
  * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
        ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
@@ -379,9 +394,7 @@ extern "C" {
 #endif
 
 #include "ua_types.h"
-#ifdef UA_INTERNAL
-#include "ua_types_encoding_binary.h"
-#endif''' + ('\n#include "ua_types_generated.h"\n' if outname != "ua_types" else '') + '''
+''' + ('\n#include "ua_types_generated.h"\n' if outname != "ua_types" else '') + '''
 
 /**
  * Additional Data Type Definitions
@@ -392,45 +405,8 @@ extern "C" {
 printh("#define " + outname.upper() + "_COUNT %s" % (str(len(selected_types))))
 printh("extern UA_EXPORT const UA_DataType " + outname.upper() + "[" + outname.upper() + "_COUNT];")
 
-printc('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
- * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
-       ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
- 
-#include "stddef.h"
-#include "ua_types.h"
-#include "''' + outname + '''_generated.h"''')
-
-printe('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
- * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
-       ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
- 
-#include "ua_types_encoding_binary.h"
-#include "''' + outname + '''_generated.h"''')
-
-if sys.version_info[0] < 3:
-    values = types.itervalues()
-else:
-    values = types.values()
-
-# Datatype members
-for t in values:
-    if not t.name in selected_types:
-        continue
-    printc("")
-    printc("/* " + t.name + " */")
-    printc(t.members_c())
-printc("const UA_DataType %s[%s_COUNT] = {" % (outname.upper(), outname.upper()))
-
-if sys.version_info[0] < 3:
-    values = types.itervalues()
-else:
-    values = types.values()
-
 i = 0
-for t in values:
-    if not t.name in selected_types:
-        continue
-    # Header
+for t in iter_types(types):
     printh("\n/**\n * " +  t.name)
     printh(" * " + "-" * len(t.name))
     if t.description == "":
@@ -440,16 +416,7 @@ for t in values:
     if type(t) != BuiltinType:
         printh(t.typedef_h() + "\n")
     printh("#define " + outname.upper() + "_" + t.name.upper() + " " + str(i))
-    printh(t.functions_c())
     i += 1
-    # Datatype
-    printc("")
-    printc("/* " + t.name + " */")
-    printc(t.datatype_c() + ",")
-    # Encoding
-    printe("")
-    printe("/* " + t.name + " */")
-    printe(t.encoding_h())
 
 printh('''
 #ifdef __cplusplus
@@ -457,8 +424,84 @@ printh('''
 #endif\n
 #endif /* %s_GENERATED_H_ */''' % outname.upper())
 
+##################
+# Print Handling #
+##################
+
+printf('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
+ * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
+       ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
+
+#ifndef ''' + outname.upper() + '''_GENERATED_HANDLING_H_
+#define ''' + outname.upper() + '''_GENERATED_HANDLING_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "''' + outname + '''_generated.h"
+
+#if defined(__GNUC__) && __GNUC__ <= 4
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+# pragma GCC diagnostic ignored "-Wmissing-braces"
+#endif
+''')
+
+for t in iter_types(types):
+    printf("\n/* " + t.name + " */")
+    printf(t.functions_c())
+
+printf('''
+#if defined(__GNUC__) && __GNUC__ <= 4
+# pragma GCC diagnostic pop
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif\n
+#endif /* %s_GENERATED_HANDLING_H_ */''' % outname.upper())
+
+###########################
+# Print Description Array #
+###########################
+
+printc('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
+ * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
+       ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
+
+#include "stddef.h"
+#include "ua_types.h"
+#include "''' + outname + '''_generated.h"''')
+
+for t in iter_types(types):
+    printc("")
+    printc("/* " + t.name + " */")
+    printc(t.members_c())
+
+printc("const UA_DataType %s[%s_COUNT] = {" % (outname.upper(), outname.upper()))
+for t in iter_types(types):
+    printc("")
+    printc("/* " + t.name + " */")
+    printc(t.datatype_c() + ",")
 printc("};\n")
 
+##################
+# Print Encoding #
+##################
+
+printe('''/* Generated from ''' + inname + ''' with script ''' + sys.argv[0] + '''
+ * on host ''' + platform.uname()[1] + ''' by user ''' + getpass.getuser() + \
+       ''' at ''' + time.strftime("%Y-%m-%d %I:%M:%S") + ''' */
+
+#include "ua_types_encoding_binary.h"
+#include "''' + outname + '''_generated.h"''')
+
+for t in iter_types(types):
+    printe("\n/* " + t.name + " */")
+    printe(t.encoding_h())
+
 fh.close()
+ff.close()
 fc.close()
 fe.close()

+ 1 - 0
tools/pyUANamespace/generate_open62541CCode.py

@@ -76,6 +76,7 @@ elif (verbosity==3):
   level = logging.INFO
 elif (verbosity>=4):
   level = logging.DEBUG
+
 logging.basicConfig(level=level)
 logger.setLevel(logging.INFO)
 

+ 4 - 0
tools/pyUANamespace/open62541_MacroHelper.py

@@ -200,6 +200,10 @@ class open62541_MacroHelper():
     code.append("attr.displayName = UA_LOCALIZEDTEXT(\"\", \"" + str(node.displayName()) + "\");")
     code.append("attr.description = UA_LOCALIZEDTEXT(\"\", \"" + str(node.description()) + "\");")
 
+    if nodetype == "Variable":
+      code.append("attr.accessLevel = %s;"     % str(node.accessLevel()))
+      code.append("attr.userAccessLevel = %s;" % str(node.userAccessLevel()))
+
     if nodetype in ["Variable", "VariableType"]:
       code = code + node.printOpen62541CCode_SubtypeEarly(bootstrapping = False)
     elif nodetype == "Method":

+ 9 - 1
tools/pyUANamespace/open62541_XMLPreprocessor.py

@@ -155,7 +155,7 @@ class preProcessDocument:
       if idDict[entry] > max:
         max = idDict[entry]
         namespaceIdGuessed = entry
-    logger.debug("XML Contents are propably in namespace " + str(entry) + " (used by " + str(idDict[entry]) + " Nodes)")
+    #logger.debug("XML Contents are propably in namespace " + str(entry) + " (used by " + str(idDict[entry]) + " Nodes)")
     return namespaceIdGuessed
 
   def getReferencedNamespaceUri(self, nsId):
@@ -216,6 +216,14 @@ class preProcessDocument:
 
         returns: nothing
     """
+
+    #change ids in aliases
+    ns = self.nodeset.getElementsByTagName("Alias")
+    for al in ns:
+      if al.nodeType == al.ELEMENT_NODE:
+        if al.hasAttribute("Alias"):
+          al.firstChild.data = al.firstChild.data.replace("ns=" + str(currentNsId), "ns=" + str(newNsId))
+
     logger.debug("Migrating nodes /w ns index " + str(currentNsId) + " to " + str(newNsId))
     for nd in self.containedNodes:
       if nd[0].ns == currentNsId:

+ 7 - 1
tools/pyUANamespace/ua_builtin_types.py

@@ -396,12 +396,18 @@ class opcua_value_t():
         if self.value[0].__binTypeId__ == BUILTINTYPE_TYPEID_EXTENSIONOBJECT:
           code.append("UA_" + self.value[0].stringRepresentation + " *" + valueName + " = " + self.value[0].printOpen62541CCode_SubType() + ";")
           code.append("UA_Variant_setScalar( &attr.value, " + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
+
           #FIXME: There is no membership definition for extensionObjects generated in this function.
           #code.append("UA_" + self.value[0].stringRepresentation + "_deleteMembers(" + valueName + ");")
         else:
+          if bootstrapping == True:
+              code.append("UA_Variant* " + self.parent.getCodePrintableID() + "_variant = UA_Variant_new();" )
           code.append("UA_" + self.value[0].stringRepresentation + " *" + valueName + " =  UA_" + self.value[0].stringRepresentation + "_new();")
           code.append("*" + valueName + " = " + self.value[0].printOpen62541CCode_SubType() + ";")
-          code.append("UA_Variant_setScalar( &attr.value, " + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
+          if bootstrapping == False:
+            code.append("UA_Variant_setScalar( &attr.value, " + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
+          else:
+            code.append("UA_Variant_setScalar( "+self.parent.getCodePrintableID()+"_variant, " + valueName + ", &UA_TYPES[UA_TYPES_" + self.value[0].stringRepresentation.upper() + "]);")
           #code.append("UA_" + self.value[0].stringRepresentation + "_deleteMembers(" + valueName + ");")
     return code
 

File diff suppressed because it is too large
+ 931 - 64
tools/schema/NodeIds.csv


+ 135 - 138
tools/schema/Opc.Ua.Types.bsd

@@ -6,12 +6,9 @@
   DefaultByteOrder="LittleEndian"
   TargetNamespace="http://opcfoundation.org/UA/"
 >
-  <!-- This File was generated on 2013-03-06 and supports the specifications supported by version 1.1.334.4 of the OPC UA deliverables. -->
+  <!-- This File was generated on 2015-08-18 and supports the specifications supported by version 1.1.335.1 of the OPC UA deliverables. -->
 
   <opc:Import Namespace="http://opcfoundation.org/BinarySchema/" />
- 
- 
- 
 
   <opc:StructuredType Name="XmlElement">
     <opc:Documentation>An XML element encoded as a UTF-8 string.</opc:Documentation>
@@ -93,14 +90,15 @@
     <opc:Documentation>A recursive structure containing diagnostic information associated with a status code.</opc:Documentation>
     <opc:Field Name="SymbolicIdSpecified" TypeName="opc:Bit" />
     <opc:Field Name="NamespaceURISpecified" TypeName="opc:Bit" />
-    <opc:Field Name="LocalizedTextSpecified" TypeName="opc:Bit" />
     <opc:Field Name="LocaleSpecified" TypeName="opc:Bit" />
+    <opc:Field Name="LocalizedTextSpecified" TypeName="opc:Bit" />
     <opc:Field Name="AdditionalInfoSpecified" TypeName="opc:Bit" />
     <opc:Field Name="InnerStatusCodeSpecified" TypeName="opc:Bit" />
     <opc:Field Name="InnerDiagnosticInfoSpecified" TypeName="opc:Bit" />
-    <opc:Field Name="Reserved1" TypeName="opc:Bit" Length="1" />
+    <opc:Field Name="Reserved1" TypeName="opc:Bit" Length="2" />
     <opc:Field Name="SymbolicId" TypeName="opc:Int32" SwitchField="SymbolicIdSpecified" />
     <opc:Field Name="NamespaceURI" TypeName="opc:Int32" SwitchField="NamespaceURISpecified" />
+    <opc:Field Name="Locale" TypeName="opc:Int32" SwitchField="LocaleSpecified" />
     <opc:Field Name="LocalizedText" TypeName="opc:Int32" SwitchField="LocalizedTextSpecified" />
     <opc:Field Name="AdditionalInfo" TypeName="opc:CharArray" SwitchField="AdditionalInfoSpecified" />
     <opc:Field Name="InnerStatusCode" TypeName="ua:StatusCode" SwitchField="InnerStatusCodeSpecified" />
@@ -152,7 +150,8 @@
 
   <opc:StructuredType Name="Variant">
     <opc:Documentation>A union of several types.</opc:Documentation>
-    <opc:Field Name="VariantType" TypeName="opc:Bit" Length="7" />
+    <opc:Field Name="VariantType" TypeName="opc:Bit" Length="6" />
+    <opc:Field Name="ArrayDimensionsSpecified" TypeName="opc:Bit" Length="1"/>
     <opc:Field Name="ArrayLengthSpecified" TypeName="opc:Bit" Length="1"/>
     <opc:Field Name="ArrayLength" TypeName="opc:Int32" SwitchField="ArrayLengthSpecified" />
     <opc:Field Name="Boolean" TypeName="opc:Boolean" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="1" />
@@ -166,7 +165,7 @@
     <opc:Field Name="UInt64" TypeName="opc:UInt64" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="9" />
     <opc:Field Name="Float" TypeName="opc:Float" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="10" />
     <opc:Field Name="Double" TypeName="opc:Double" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="11" />
-    <opc:Field Name="String" TypeName="opc:String" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="12" />
+    <opc:Field Name="String" TypeName="opc:CharArray" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="12" />
     <opc:Field Name="DateTime" TypeName="opc:DateTime" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="13" />
     <opc:Field Name="Guid" TypeName="opc:Guid" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="14" />
     <opc:Field Name="ByteString" TypeName="opc:ByteString" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="15" />
@@ -174,13 +173,22 @@
     <opc:Field Name="NodeId" TypeName="ua:NodeId" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="17" />
     <opc:Field Name="ExpandedNodeId" TypeName="ua:ExpandedNodeId" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="18" />
     <opc:Field Name="StatusCode" TypeName="ua:StatusCode" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="19" />
-    <opc:Field Name="DiagnosticInfo" TypeName="ua:DiagnosticInfo" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="20" />
-    <opc:Field Name="QualifiedName" TypeName="ua:QualifiedName" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="21" />
-    <opc:Field Name="LocalizedText" TypeName="ua:LocalizedText" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="22" />
-    <opc:Field Name="ExtensionObject" TypeName="ua:ExtensionObject" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="23" />
-    <opc:Field Name="DataValue" TypeName="ua:DataValue" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="24" />
-    <opc:Field Name="Variant" TypeName="ua:Variant" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="25" />
-  </opc:StructuredType>
+    <opc:Field Name="QualifiedName" TypeName="ua:QualifiedName" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="20" />
+    <opc:Field Name="LocalizedText" TypeName="ua:LocalizedText" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="21" />
+    <opc:Field Name="ExtensionObject" TypeName="ua:ExtensionObject" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="22" />
+    <opc:Field Name="DataValue" TypeName="ua:DataValue" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="23" />
+    <opc:Field Name="Variant" TypeName="ua:Variant" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="24" />
+    <opc:Field Name="DiagnosticInfo" TypeName="ua:DiagnosticInfo" LengthField="ArrayLength" SwitchField="VariantType" SwitchValue="25" />
+    <opc:Field Name="NoOfArrayDimensions" TypeName="opc:Int32" SwitchField="ArrayDimensionsSpecified" />
+    <opc:Field Name="ArrayDimensions" TypeName="opc:Int32" LengthField="NoOfArrayDimensions" SwitchField="ArrayDimensionsSpecified" />
+  </opc:StructuredType>
+
+  <opc:EnumeratedType Name="NamingRuleType" LengthInBits="32">
+    <opc:EnumeratedValue Name="Mandatory" Value="1" />
+    <opc:EnumeratedValue Name="Optional" Value="2" />
+    <opc:EnumeratedValue Name="Constraint" Value="3" />
+  </opc:EnumeratedType>
+    
 
   <opc:OpaqueType Name="ImageBMP">
     <opc:Documentation>An image encoded in BMP format.</opc:Documentation>
@@ -205,10 +213,31 @@
   <opc:EnumeratedType Name="OpenFileMode" LengthInBits="32">
     <opc:EnumeratedValue Name="Read" Value="1" />
     <opc:EnumeratedValue Name="Write" Value="2" />
-    <opc:EnumeratedValue Name="EraseExisiting" Value="4" />
+    <opc:EnumeratedValue Name="EraseExisting" Value="4" />
     <opc:EnumeratedValue Name="Append" Value="8" />
   </opc:EnumeratedType>
 
+  <opc:EnumeratedType Name="TrustListMasks" LengthInBits="32">
+    <opc:EnumeratedValue Name="None" Value="0" />
+    <opc:EnumeratedValue Name="TrustedCertificates" Value="1" />
+    <opc:EnumeratedValue Name="TrustedCrls" Value="2" />
+    <opc:EnumeratedValue Name="IssuerCertificates" Value="4" />
+    <opc:EnumeratedValue Name="IssuerCrls" Value="8" />
+    <opc:EnumeratedValue Name="All" Value="15" />
+  </opc:EnumeratedType>
+
+  <opc:StructuredType Name="TrustListDataType" BaseType="ua:ExtensionObject">
+    <opc:Field Name="SpecifiedLists" TypeName="opc:UInt32" />
+    <opc:Field Name="NoOfTrustedCertificates" TypeName="opc:Int32" />
+    <opc:Field Name="TrustedCertificates" TypeName="opc:ByteString" LengthField="NoOfTrustedCertificates" />
+    <opc:Field Name="NoOfTrustedCrls" TypeName="opc:Int32" />
+    <opc:Field Name="TrustedCrls" TypeName="opc:ByteString" LengthField="NoOfTrustedCrls" />
+    <opc:Field Name="NoOfIssuerCertificates" TypeName="opc:Int32" />
+    <opc:Field Name="IssuerCertificates" TypeName="opc:ByteString" LengthField="NoOfIssuerCertificates" />
+    <opc:Field Name="NoOfIssuerCrls" TypeName="opc:Int32" />
+    <opc:Field Name="IssuerCrls" TypeName="opc:ByteString" LengthField="NoOfIssuerCrls" />
+  </opc:StructuredType>
+
   <opc:EnumeratedType Name="IdType" LengthInBits="32">
     <opc:Documentation>The type of identifier used in a node id.</opc:Documentation>
     <opc:EnumeratedValue Name="Numeric" Value="0" />
@@ -418,8 +447,38 @@
     <opc:Field Name="Description" TypeName="ua:LocalizedText" />
   </opc:StructuredType>
 
+  <opc:StructuredType Name="OptionSet" BaseType="ua:ExtensionObject">
+    <opc:Documentation>This abstract Structured DataType is the base DataType for all DataTypes representing a bit mask.</opc:Documentation>
+    <opc:Field Name="Value" TypeName="opc:ByteString" />
+    <opc:Field Name="ValidBits" TypeName="opc:ByteString" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="Union" BaseType="ua:ExtensionObject">
+    <opc:Documentation>This abstract DataType is the base DataType for all union DataTypes.</opc:Documentation>
+  </opc:StructuredType>
+
+  <opc:OpaqueType Name="NormalizedString">
+    <opc:Documentation>A string normalized based on the rules in the unicode specification.</opc:Documentation>
+  </opc:OpaqueType>
+
+  <opc:OpaqueType Name="DecimalString">
+    <opc:Documentation>An arbitraty numeric value.</opc:Documentation>
+  </opc:OpaqueType>
+
+  <opc:OpaqueType Name="DurationString">
+    <opc:Documentation>A period of time formatted as defined in ISO 8601-2000.</opc:Documentation>
+  </opc:OpaqueType>
+
+  <opc:OpaqueType Name="TimeString">
+    <opc:Documentation>A time formatted as defined in ISO 8601-2000.</opc:Documentation>
+  </opc:OpaqueType>
+
+  <opc:OpaqueType Name="DateString">
+    <opc:Documentation>A date formatted as defined in ISO 8601-2000.</opc:Documentation>
+  </opc:OpaqueType>
+
   <opc:OpaqueType Name="Duration">
-    <opc:Documentation>A period of time measured in seconds.</opc:Documentation>
+    <opc:Documentation>A period of time measured in milliseconds.</opc:Documentation>
   </opc:OpaqueType>
 
   <opc:OpaqueType Name="UtcTime">
@@ -503,6 +562,29 @@
     <opc:Field Name="Servers" TypeName="tns:ApplicationDescription" LengthField="NoOfServers" />
   </opc:StructuredType>
 
+  <opc:StructuredType Name="ServerOnNetwork" BaseType="ua:ExtensionObject">
+    <opc:Field Name="RecordId" TypeName="opc:UInt32" />
+    <opc:Field Name="ServerName" TypeName="opc:String" />
+    <opc:Field Name="DiscoveryUrl" TypeName="opc:String" />
+    <opc:Field Name="NoOfServerCapabilities" TypeName="opc:Int32" />
+    <opc:Field Name="ServerCapabilities" TypeName="opc:String" LengthField="NoOfServerCapabilities" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="FindServersOnNetworkRequest" BaseType="ua:ExtensionObject">
+    <opc:Field Name="RequestHeader" TypeName="tns:RequestHeader" />
+    <opc:Field Name="StartingRecordId" TypeName="opc:UInt32" />
+    <opc:Field Name="MaxRecordsToReturn" TypeName="opc:UInt32" />
+    <opc:Field Name="NoOfServerCapabilityFilter" TypeName="opc:Int32" />
+    <opc:Field Name="ServerCapabilityFilter" TypeName="opc:String" LengthField="NoOfServerCapabilityFilter" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="FindServersOnNetworkResponse" BaseType="ua:ExtensionObject">
+    <opc:Field Name="ResponseHeader" TypeName="tns:ResponseHeader" />
+    <opc:Field Name="LastCounterResetTime" TypeName="opc:DateTime" />
+    <opc:Field Name="NoOfServers" TypeName="opc:Int32" />
+    <opc:Field Name="Servers" TypeName="tns:ServerOnNetwork" LengthField="NoOfServers" />
+  </opc:StructuredType>
+
   <opc:OpaqueType Name="ApplicationInstanceCertificate">
     <opc:Documentation>A certificate for an instance of an application.</opc:Documentation>
   </opc:OpaqueType>
@@ -521,6 +603,7 @@
     <opc:EnumeratedValue Name="UserName" Value="1" />
     <opc:EnumeratedValue Name="Certificate" Value="2" />
     <opc:EnumeratedValue Name="IssuedToken" Value="3" />
+    <opc:EnumeratedValue Name="Kerberos" Value="4" />
   </opc:EnumeratedType>
 
   <opc:StructuredType Name="UserTokenPolicy" BaseType="ua:ExtensionObject">
@@ -587,6 +670,32 @@
     <opc:Field Name="ResponseHeader" TypeName="tns:ResponseHeader" />
   </opc:StructuredType>
 
+  <opc:StructuredType Name="DiscoveryConfiguration" BaseType="ua:ExtensionObject">
+    <opc:Documentation>A base type for discovery configuration information.</opc:Documentation>
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="MdnsDiscoveryConfiguration" BaseType="tns:DiscoveryConfiguration">
+    <opc:Documentation>The discovery information needed for mDNS registration.</opc:Documentation>
+    <opc:Field Name="MdnsServerName" TypeName="opc:String" />
+    <opc:Field Name="NoOfServerCapabilities" TypeName="opc:Int32" />
+    <opc:Field Name="ServerCapabilities" TypeName="opc:String" LengthField="NoOfServerCapabilities" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="RegisterServer2Request" BaseType="ua:ExtensionObject">
+    <opc:Field Name="RequestHeader" TypeName="tns:RequestHeader" />
+    <opc:Field Name="Server" TypeName="tns:RegisteredServer" />
+    <opc:Field Name="NoOfDiscoveryConfiguration" TypeName="opc:Int32" />
+    <opc:Field Name="DiscoveryConfiguration" TypeName="ua:ExtensionObject" LengthField="NoOfDiscoveryConfiguration" />
+  </opc:StructuredType>
+
+  <opc:StructuredType Name="RegisterServer2Response" BaseType="ua:ExtensionObject">
+    <opc:Field Name="ResponseHeader" TypeName="tns:ResponseHeader" />
+    <opc:Field Name="NoOfConfigurationResults" TypeName="opc:Int32" />
+    <opc:Field Name="ConfigurationResults" TypeName="ua:StatusCode" LengthField="NoOfConfigurationResults" />
+    <opc:Field Name="NoOfDiagnosticInfos" TypeName="opc:Int32" />
+    <opc:Field Name="DiagnosticInfos" TypeName="ua:DiagnosticInfo" LengthField="NoOfDiagnosticInfos" />
+  </opc:StructuredType>
+
   <opc:EnumeratedType Name="SecurityTokenRequestType" LengthInBits="32">
     <opc:Documentation>Indicates whether a token if being created or renewed.</opc:Documentation>
     <opc:EnumeratedValue Name="Issue" Value="0" />
@@ -698,6 +807,11 @@
     <opc:Field Name="CertificateData" TypeName="opc:ByteString" />
   </opc:StructuredType>
 
+  <opc:StructuredType Name="KerberosIdentityToken" BaseType="tns:UserIdentityToken">
+    <opc:Field Name="PolicyId" TypeName="opc:String" SourceType="tns:UserIdentityToken" />
+    <opc:Field Name="TicketData" TypeName="opc:ByteString" />
+  </opc:StructuredType>
+
   <opc:StructuredType Name="IssuedIdentityToken" BaseType="tns:UserIdentityToken">
     <opc:Documentation>A token representing a user identified by a WS-Security XML token.</opc:Documentation>
     <opc:Field Name="PolicyId" TypeName="opc:String" SourceType="tns:UserIdentityToken" />
@@ -999,7 +1113,7 @@
   </opc:StructuredType>
 
   <opc:EnumeratedType Name="AttributeWriteMask" LengthInBits="32">
-    <opc:Documentation>Define bits used to indicate which attributes are writeable.</opc:Documentation>
+    <opc:Documentation>Define bits used to indicate which attributes are writable.</opc:Documentation>
     <opc:EnumeratedValue Name="None" Value="0" />
     <opc:EnumeratedValue Name="AccessLevel" Value="1" />
     <opc:EnumeratedValue Name="ArrayDimensions" Value="2" />
@@ -1604,11 +1718,6 @@
     <opc:Field Name="DiagnosticInfos" TypeName="ua:DiagnosticInfo" LengthField="NoOfDiagnosticInfos" />
   </opc:StructuredType>
 
-  <opc:StructuredType Name="HistoryUpdateEventResult" BaseType="ua:ExtensionObject">
-    <opc:Field Name="StatusCode" TypeName="ua:StatusCode" />
-    <opc:Field Name="EventFilterResult" TypeName="tns:EventFilterResult" />
-  </opc:StructuredType>
-
   <opc:StructuredType Name="HistoryUpdateRequest" BaseType="ua:ExtensionObject">
     <opc:Field Name="RequestHeader" TypeName="tns:RequestHeader" />
     <opc:Field Name="NoOfHistoryUpdateDetails" TypeName="opc:Int32" />
@@ -2008,118 +2117,6 @@
     <opc:EnumeratedValue Name="Green" Value="5" />
   </opc:EnumeratedType>
 
-  <opc:StructuredType Name="ScalarTestType" BaseType="ua:ExtensionObject">
-    <opc:Documentation>A complex type containing all possible scalar types used for testing.</opc:Documentation>
-    <opc:Field Name="Boolean" TypeName="opc:Boolean" />
-    <opc:Field Name="SByte" TypeName="opc:SByte" />
-    <opc:Field Name="Byte" TypeName="opc:Byte" />
-    <opc:Field Name="Int16" TypeName="opc:Int16" />
-    <opc:Field Name="UInt16" TypeName="opc:UInt16" />
-    <opc:Field Name="Int32" TypeName="opc:Int32" />
-    <opc:Field Name="UInt32" TypeName="opc:UInt32" />
-    <opc:Field Name="Int64" TypeName="opc:Int64" />
-    <opc:Field Name="UInt64" TypeName="opc:UInt64" />
-    <opc:Field Name="Float" TypeName="opc:Float" />
-    <opc:Field Name="Double" TypeName="opc:Double" />
-    <opc:Field Name="String" TypeName="opc:String" />
-    <opc:Field Name="DateTime" TypeName="opc:DateTime" />
-    <opc:Field Name="Guid" TypeName="opc:Guid" />
-    <opc:Field Name="ByteString" TypeName="opc:ByteString" />
-    <opc:Field Name="XmlElement" TypeName="ua:XmlElement" />
-    <opc:Field Name="NodeId" TypeName="ua:NodeId" />
-    <opc:Field Name="ExpandedNodeId" TypeName="ua:ExpandedNodeId" />
-    <opc:Field Name="StatusCode" TypeName="ua:StatusCode" />
-    <opc:Field Name="DiagnosticInfo" TypeName="ua:DiagnosticInfo" />
-    <opc:Field Name="QualifiedName" TypeName="ua:QualifiedName" />
-    <opc:Field Name="LocalizedText" TypeName="ua:LocalizedText" />
-    <opc:Field Name="ExtensionObject" TypeName="ua:ExtensionObject" />
-    <opc:Field Name="DataValue" TypeName="ua:DataValue" />
-    <opc:Field Name="EnumeratedValue" TypeName="tns:EnumeratedTestType" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="ArrayTestType" BaseType="ua:ExtensionObject">
-    <opc:Documentation>A complex type containing all possible array types used for testing.</opc:Documentation>
-    <opc:Field Name="NoOfBooleans" TypeName="opc:Int32" />
-    <opc:Field Name="Booleans" TypeName="opc:Boolean" LengthField="NoOfBooleans" />
-    <opc:Field Name="NoOfSBytes" TypeName="opc:Int32" />
-    <opc:Field Name="SBytes" TypeName="opc:SByte" LengthField="NoOfSBytes" />
-    <opc:Field Name="NoOfInt16s" TypeName="opc:Int32" />
-    <opc:Field Name="Int16s" TypeName="opc:Int16" LengthField="NoOfInt16s" />
-    <opc:Field Name="NoOfUInt16s" TypeName="opc:Int32" />
-    <opc:Field Name="UInt16s" TypeName="opc:UInt16" LengthField="NoOfUInt16s" />
-    <opc:Field Name="NoOfInt32s" TypeName="opc:Int32" />
-    <opc:Field Name="Int32s" TypeName="opc:Int32" LengthField="NoOfInt32s" />
-    <opc:Field Name="NoOfUInt32s" TypeName="opc:Int32" />
-    <opc:Field Name="UInt32s" TypeName="opc:UInt32" LengthField="NoOfUInt32s" />
-    <opc:Field Name="NoOfInt64s" TypeName="opc:Int32" />
-    <opc:Field Name="Int64s" TypeName="opc:Int64" LengthField="NoOfInt64s" />
-    <opc:Field Name="NoOfUInt64s" TypeName="opc:Int32" />
-    <opc:Field Name="UInt64s" TypeName="opc:UInt64" LengthField="NoOfUInt64s" />
-    <opc:Field Name="NoOfFloats" TypeName="opc:Int32" />
-    <opc:Field Name="Floats" TypeName="opc:Float" LengthField="NoOfFloats" />
-    <opc:Field Name="NoOfDoubles" TypeName="opc:Int32" />
-    <opc:Field Name="Doubles" TypeName="opc:Double" LengthField="NoOfDoubles" />
-    <opc:Field Name="NoOfStrings" TypeName="opc:Int32" />
-    <opc:Field Name="Strings" TypeName="opc:String" LengthField="NoOfStrings" />
-    <opc:Field Name="NoOfDateTimes" TypeName="opc:Int32" />
-    <opc:Field Name="DateTimes" TypeName="opc:DateTime" LengthField="NoOfDateTimes" />
-    <opc:Field Name="NoOfGuids" TypeName="opc:Int32" />
-    <opc:Field Name="Guids" TypeName="opc:Guid" LengthField="NoOfGuids" />
-    <opc:Field Name="NoOfByteStrings" TypeName="opc:Int32" />
-    <opc:Field Name="ByteStrings" TypeName="opc:ByteString" LengthField="NoOfByteStrings" />
-    <opc:Field Name="NoOfXmlElements" TypeName="opc:Int32" />
-    <opc:Field Name="XmlElements" TypeName="ua:XmlElement" LengthField="NoOfXmlElements" />
-    <opc:Field Name="NoOfNodeIds" TypeName="opc:Int32" />
-    <opc:Field Name="NodeIds" TypeName="ua:NodeId" LengthField="NoOfNodeIds" />
-    <opc:Field Name="NoOfExpandedNodeIds" TypeName="opc:Int32" />
-    <opc:Field Name="ExpandedNodeIds" TypeName="ua:ExpandedNodeId" LengthField="NoOfExpandedNodeIds" />
-    <opc:Field Name="NoOfStatusCodes" TypeName="opc:Int32" />
-    <opc:Field Name="StatusCodes" TypeName="ua:StatusCode" LengthField="NoOfStatusCodes" />
-    <opc:Field Name="NoOfDiagnosticInfos" TypeName="opc:Int32" />
-    <opc:Field Name="DiagnosticInfos" TypeName="ua:DiagnosticInfo" LengthField="NoOfDiagnosticInfos" />
-    <opc:Field Name="NoOfQualifiedNames" TypeName="opc:Int32" />
-    <opc:Field Name="QualifiedNames" TypeName="ua:QualifiedName" LengthField="NoOfQualifiedNames" />
-    <opc:Field Name="NoOfLocalizedTexts" TypeName="opc:Int32" />
-    <opc:Field Name="LocalizedTexts" TypeName="ua:LocalizedText" LengthField="NoOfLocalizedTexts" />
-    <opc:Field Name="NoOfExtensionObjects" TypeName="opc:Int32" />
-    <opc:Field Name="ExtensionObjects" TypeName="ua:ExtensionObject" LengthField="NoOfExtensionObjects" />
-    <opc:Field Name="NoOfDataValues" TypeName="opc:Int32" />
-    <opc:Field Name="DataValues" TypeName="ua:DataValue" LengthField="NoOfDataValues" />
-    <opc:Field Name="NoOfVariants" TypeName="opc:Int32" />
-    <opc:Field Name="Variants" TypeName="ua:Variant" LengthField="NoOfVariants" />
-    <opc:Field Name="NoOfEnumeratedValues" TypeName="opc:Int32" />
-    <opc:Field Name="EnumeratedValues" TypeName="tns:EnumeratedTestType" LengthField="NoOfEnumeratedValues" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="CompositeTestType" BaseType="ua:ExtensionObject">
-    <opc:Field Name="Field1" TypeName="tns:ScalarTestType" />
-    <opc:Field Name="Field2" TypeName="tns:ArrayTestType" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="TestStackRequest" BaseType="ua:ExtensionObject">
-    <opc:Field Name="RequestHeader" TypeName="tns:RequestHeader" />
-    <opc:Field Name="TestId" TypeName="opc:UInt32" />
-    <opc:Field Name="Iteration" TypeName="opc:Int32" />
-    <opc:Field Name="Input" TypeName="ua:Variant" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="TestStackResponse" BaseType="ua:ExtensionObject">
-    <opc:Field Name="ResponseHeader" TypeName="tns:ResponseHeader" />
-    <opc:Field Name="Output" TypeName="ua:Variant" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="TestStackExRequest" BaseType="ua:ExtensionObject">
-    <opc:Field Name="RequestHeader" TypeName="tns:RequestHeader" />
-    <opc:Field Name="TestId" TypeName="opc:UInt32" />
-    <opc:Field Name="Iteration" TypeName="opc:Int32" />
-    <opc:Field Name="Input" TypeName="tns:CompositeTestType" />
-  </opc:StructuredType>
-
-  <opc:StructuredType Name="TestStackExResponse" BaseType="ua:ExtensionObject">
-    <opc:Field Name="ResponseHeader" TypeName="tns:ResponseHeader" />
-    <opc:Field Name="Output" TypeName="tns:CompositeTestType" />
-  </opc:StructuredType>
-
   <opc:StructuredType Name="BuildInfo" BaseType="ua:ExtensionObject">
     <opc:Field Name="ProductUri" TypeName="opc:String" />
     <opc:Field Name="ManufacturerName" TypeName="opc:String" />
@@ -2385,10 +2382,10 @@
 
   <opc:EnumeratedType Name="ExceptionDeviationFormat" LengthInBits="32">
     <opc:EnumeratedValue Name="AbsoluteValue" Value="0" />
-    <opc:EnumeratedValue Name="PercentOfRange" Value="1" />
-    <opc:EnumeratedValue Name="PercentOfValue" Value="2" />
+    <opc:EnumeratedValue Name="PercentOfValue" Value="1" />
+    <opc:EnumeratedValue Name="PercentOfRange" Value="2" />
     <opc:EnumeratedValue Name="PercentOfEURange" Value="3" />
     <opc:EnumeratedValue Name="Unknown" Value="4" />
   </opc:EnumeratedType>
 
-</opc:TypeDictionary>
+</opc:TypeDictionary>

+ 1 - 63
tools/schema/namespace0/Opc.Ua.NodeSet2.Minimal.xml

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <UANodeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.02" LastModified="2013-03-06T05:36:44.0862658Z" xmlns="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">
   <Aliases>
     <Alias Alias="Boolean">i=1</Alias>
@@ -268,17 +268,6 @@
     <DisplayName>ServerType</DisplayName>
     <Description>Specifies the current status and capabilities of the server.</Description>
     <References>
-      <Reference ReferenceType="HasProperty">i=2005</Reference>
-      <Reference ReferenceType="HasProperty">i=2006</Reference>
-      <Reference ReferenceType="HasComponent">i=2007</Reference>
-      <Reference ReferenceType="HasProperty">i=2008</Reference>
-      <Reference ReferenceType="HasProperty">i=2742</Reference>
-      <Reference ReferenceType="HasComponent">i=2009</Reference>
-      <Reference ReferenceType="HasComponent">i=2010</Reference>
-      <Reference ReferenceType="HasComponent">i=2011</Reference>
-      <Reference ReferenceType="HasComponent">i=2012</Reference>
-      <Reference ReferenceType="HasComponent">i=11527</Reference>
-      <Reference ReferenceType="HasComponent">i=11489</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
     </References>
   </UAObjectType>
@@ -286,11 +275,6 @@
     <DisplayName>ServerDiagnosticsType</DisplayName>
     <Description>The diagnostics information for a server.</Description>
     <References>
-      <Reference ReferenceType="HasComponent">i=2021</Reference>
-      <Reference ReferenceType="HasComponent">i=2022</Reference>
-      <Reference ReferenceType="HasComponent">i=2023</Reference>
-      <Reference ReferenceType="HasComponent">i=2744</Reference>
-      <Reference ReferenceType="HasProperty">i=2025</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
     </References>
   </UAObjectType>
@@ -298,43 +282,18 @@
     <DisplayName>ServerCapabilitiesType</DisplayName>
     <Description>Describes the capabilities supported by the server.</Description>
     <References>
-      <Reference ReferenceType="HasProperty">i=2014</Reference>
-      <Reference ReferenceType="HasProperty">i=2016</Reference>
-      <Reference ReferenceType="HasProperty">i=2017</Reference>
-      <Reference ReferenceType="HasProperty">i=2732</Reference>
-      <Reference ReferenceType="HasProperty">i=2733</Reference>
-      <Reference ReferenceType="HasProperty">i=2734</Reference>
-      <Reference ReferenceType="HasProperty">i=3049</Reference>
-      <Reference ReferenceType="HasProperty">i=11549</Reference>
-      <Reference ReferenceType="HasProperty">i=11550</Reference>
-      <Reference ReferenceType="HasComponent">i=11551</Reference>
-      <Reference ReferenceType="HasComponent">i=2019</Reference>
-      <Reference ReferenceType="HasComponent">i=2754</Reference>
-      <Reference ReferenceType="HasComponent">i=11562</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
     </References>
   </UAObjectType>
   <UAVariableType NodeId="i=2138" BrowseName="ServerStatusType" DataType="i=862">
     <DisplayName>ServerStatusType</DisplayName>
     <References>
-      <Reference ReferenceType="HasComponent">i=2139</Reference>
-      <Reference ReferenceType="HasComponent">i=2140</Reference>
-      <Reference ReferenceType="HasComponent">i=2141</Reference>
-      <Reference ReferenceType="HasComponent">i=2142</Reference>
-      <Reference ReferenceType="HasComponent">i=2752</Reference>
-      <Reference ReferenceType="HasComponent">i=2753</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=63</Reference>
     </References>
   </UAVariableType>
   <UAVariableType NodeId="i=3051" BrowseName="BuildInfoType" DataType="i=338">
     <DisplayName>BuildInfoType</DisplayName>
     <References>
-      <Reference ReferenceType="HasComponent">i=3052</Reference>
-      <Reference ReferenceType="HasComponent">i=3053</Reference>
-      <Reference ReferenceType="HasComponent">i=3054</Reference>
-      <Reference ReferenceType="HasComponent">i=3055</Reference>
-      <Reference ReferenceType="HasComponent">i=3056</Reference>
-      <Reference ReferenceType="HasComponent">i=3057</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=63</Reference>
     </References>
   </UAVariableType>
@@ -581,7 +540,6 @@
   <UADataType NodeId="i=852" BrowseName="ServerState">
     <DisplayName>ServerState</DisplayName>
     <References>
-      <Reference ReferenceType="HasProperty">i=7612</Reference>
       <Reference ReferenceType="HasSubtype" IsForward="false">i=29</Reference>
     </References>
     <Definition Name="ServerState">
@@ -631,14 +589,8 @@
       <Reference ReferenceType="HasProperty">i=2254</Reference>
       <Reference ReferenceType="HasProperty">i=2255</Reference>
       <Reference ReferenceType="HasComponent">i=2256</Reference>
-      <Reference ReferenceType="HasProperty">i=2267</Reference>
-      <Reference ReferenceType="HasProperty">i=2994</Reference>
       <Reference ReferenceType="HasComponent">i=2268</Reference>
       <Reference ReferenceType="HasComponent">i=2274</Reference>
-      <Reference ReferenceType="HasComponent">i=2295</Reference>
-      <Reference ReferenceType="HasComponent">i=2296</Reference>
-      <Reference ReferenceType="HasComponent">i=11715</Reference>
-      <Reference ReferenceType="HasComponent">i=11492</Reference>
       <Reference ReferenceType="Organizes" IsForward="false">i=85</Reference>
       <Reference ReferenceType="HasTypeDefinition">i=2004</Reference>
     </References>
@@ -663,18 +615,8 @@
     <DisplayName>ServerCapabilities</DisplayName>
     <Description>Describes capabilities supported by the server.</Description>
     <References>
-      <Reference ReferenceType="HasProperty">i=2269</Reference>
       <Reference ReferenceType="HasProperty">i=2271</Reference>
-      <Reference ReferenceType="HasProperty">i=2272</Reference>
       <Reference ReferenceType="HasProperty">i=2735</Reference>
-      <Reference ReferenceType="HasProperty">i=2736</Reference>
-      <Reference ReferenceType="HasProperty">i=2737</Reference>
-      <Reference ReferenceType="HasProperty">i=3704</Reference>
-      <Reference ReferenceType="HasProperty">i=11702</Reference>
-      <Reference ReferenceType="HasProperty">i=11703</Reference>
-      <Reference ReferenceType="HasComponent">i=11704</Reference>
-      <Reference ReferenceType="HasComponent">i=2996</Reference>
-      <Reference ReferenceType="HasComponent">i=2997</Reference>
       <Reference ReferenceType="HasTypeDefinition">i=2013</Reference>
       <Reference ReferenceType="HasComponent" IsForward="false">i=2253</Reference>
     </References>
@@ -699,10 +641,6 @@
     <DisplayName>ServerDiagnostics</DisplayName>
     <Description>Reports diagnostics about the server.</Description>
     <References>
-      <Reference ReferenceType="HasComponent">i=2275</Reference>
-      <Reference ReferenceType="HasComponent">i=2289</Reference>
-      <Reference ReferenceType="HasComponent">i=2290</Reference>
-      <Reference ReferenceType="HasComponent">i=3706</Reference>
       <Reference ReferenceType="HasProperty">i=2294</Reference>
       <Reference ReferenceType="HasTypeDefinition">i=2020</Reference>
       <Reference ReferenceType="HasComponent" IsForward="false">i=2253</Reference>

+ 1 - 1
tools/travis/travis_linux_script.sh

@@ -118,7 +118,7 @@ else
     echo "-> Current repo: ${TRAVIS_REPO_SLUG}"
     if ([ "$CC" = "gcc-4.8" ] || [ "$CC" = "gcc" ]) && ([ "${TRAVIS_REPO_SLUG}" = "open62541/open62541" ] || [ "${TRAVIS_REPO_SLUG}" = "Pro/open62541" ]); then
         echo "  Building coveralls for ${TRAVIS_REPO_SLUG}"
-        coveralls --gcov /usr/bin/gcov-4.8 -E '.*\.h' -E '.*CMakeCXXCompilerId\.cpp' -E '.*CMakeCCompilerId\.c' -r ../
+        coveralls --gcov /usr/bin/gcov-4.8 -E '.*\.h' -E '.*CMakeCXXCompilerId\.cpp' -E '.*CMakeCCompilerId\.c' -r ../ || true # ignore result
     else
         echo "  Skipping coveralls since not gcc and/or ${TRAVIS_REPO_SLUG} is not the main repo"
     fi

+ 1 - 0
tools/travis/travis_osx_before_install.sh

@@ -8,6 +8,7 @@ else
     brew install check
     brew install userspace-rcu
     brew install valgrind
+    brew install graphviz
 
     pip install --user sphinx
     pip install --user breathe