15 次代碼提交 2165b9966c ... 2cc948e837

作者 SHA1 備註 提交日期
  thomas 2cc948e837 Merge branch 'master' into v1.0-cdpdev 5 年之前
  Stefan Profanter 95b3deb6a1 fix(core): Avoid buffer overflow in base64 decoding (length check) 5 年之前
  Stefan Profanter 17776739a3 fix(core): Avoid buffer overflow in base64 decoding 5 年之前
  jrcoding 53793d9e79 feat(doc): example debian packaging inside docker container 5 年之前
  Stefan Profanter ffb0afb041 fix(ci): Pin msys2 to specific version otherwise install fails. 5 年之前
  jrcoding b6baa5906e fix(debian):use texlive-plain-generic since debian/bullseye or ubuntu/eoan 5 年之前
  Joachim Rahn d05677afae build(core): Add static library to dev package 5 年之前
  Stefan Profanter 8bcea80e8b ci(debian): Split debian build into separate build and move to azure pipeline 5 年之前
  Stefan Profanter 760ce81453 ci: Better structure azure pipelines into multiple files 5 年之前
  jrcoding fecf931135 remove only leftovers dh_sphinxdoc ignores 5 年之前
  jrcoding 39be483320 feat(debian): add PDF and HTML docs including examples 5 年之前
  jrcoding 68599ac1b7 include needed .csv files of ua-nodeset 5 年之前
  jrcoding e4ad13d060 include only needed subset of ua_nodeset 5 年之前
  jrcoding cd8eafdfa0 remove git from build-depends 5 年之前
  jrcoding 077118e6ff separate tools from dev, bump standards to current version and extend description 5 年之前
共有 100 個文件被更改,包括 2150 次插入10306 次删除
  1. 61 0
      .azure-pipelines/azure-pipelines-dist.yml
  2. 0 28
      .azure-pipelines/azure-pipelines-linux.yml
  3. 4 5
      .github/lock.yml
  4. 0 18
      .github/semantic.yml
  5. 1 8
      .travis.yml
  6. 90 169
      CMakeLists.txt
  7. 3 92
      CONTRIBUTING.md
  8. 1 4
      docker/Dockerfile
  9. 0 7
      README.md
  10. 0 12
      arch/eCos/ua_architecture.h
  11. 0 15
      arch/freertosLWIP/ua_architecture.h
  12. 2 3
      arch/network_tcp.c
  13. 0 309
      arch/network_ws.c
  14. 1 1
      arch/posix/CMakeLists.txt
  15. 0 28
      arch/posix/ua_architecture.h
  16. 0 12
      arch/vxworks/ua_architecture.h
  17. 0 11
      arch/wec7/ua_architecture.h
  18. 0 21
      arch/win32/ua_architecture.h
  19. 10 1
      azure-pipelines.yml
  20. 58 8
      debian/control-template
  21. 1 1
      debian/libopen62541-dev.install-template
  22. 9 0
      debian/libopen62541-tools.install-template
  23. 16 0
      debian/open62541-doc.doc-base-template
  24. 2 0
      debian/open62541-doc.install-template
  25. 5 0
      debian/rules-template
  26. 1 1
      deps/mdnsd
  27. 0 1701
      deps/mqtt-c/mqtt.c
  28. 0 1542
      deps/mqtt-c/mqtt.h
  29. 0 112
      deps/mqtt-c/mqtt_pal.h
  30. 19 0
      doc/CMakeLists.txt
  31. 86 19
      doc/building.rst
  32. 0 19
      docker/README.md
  33. 0 17
      examples/CMakeLists.txt
  34. 1 1
      examples/access_control/server_access_control.c
  35. 2 2
      examples/client_connect.c
  36. 0 270
      examples/client_method_async.c
  37. 2 2
      examples/nodeset/CMakeLists.txt
  38. 0 4
      examples/pubsub/pubsub_subscribe_standalone.c
  39. 0 851
      examples/pubsub/server_pubsub_publisher_iop.c
  40. 0 205
      examples/pubsub/server_pubsub_publisher_rt_level.c
  41. 2 2
      examples/pubsub/tutorial_pubsub_connection.c
  42. 0 372
      examples/pubsub/tutorial_pubsub_mqtt_publish.c
  43. 1 16
      examples/pubsub/tutorial_pubsub_publish.c
  44. 23 60
      examples/pubsub/tutorial_pubsub_subscribe.c
  45. 14 53
      examples/pubsub_realtime/pubsub_interrupt_publish.c
  46. 57 92
      examples/server_ctt.c
  47. 0 7
      examples/tutorial_client_events.c
  48. 0 232
      examples/tutorial_server_method_async.c
  49. 0 35
      examples/tutorial_server_variable.c
  50. 49 53
      include/open62541/architecture_definitions.h
  51. 2 10
      include/open62541/client.h
  52. 0 4
      include/open62541/client_config.h
  53. 1 72
      include/open62541/client_subscriptions.h
  54. 4 8
      include/open62541/config.h.in
  55. 1 2
      include/open62541/constants.h
  56. 0 22
      include/open62541/network_ws.h
  57. 1 1
      include/open62541/plugin/accesscontrol.h
  58. 3 50
      include/open62541/plugin/historydatabase.h
  59. 0 24
      include/open62541/plugin/log.h
  60. 2 2
      include/open62541/plugin/network.h
  61. 62 52
      include/open62541/plugin/nodestore.h
  62. 3 2
      include/open62541/plugin/pki.h
  63. 1 1
      include/open62541/plugin/securitypolicy.h
  64. 90 178
      include/open62541/server.h
  65. 1 27
      include/open62541/server_config.h
  66. 9 80
      include/open62541/server_pubsub.h
  67. 5 6
      include/open62541/types.h
  68. 2 3
      plugins/historydata/ua_history_database_default.c
  69. 0 3
      plugins/include/open62541/client_config_default.h
  70. 0 32
      plugins/include/open62541/plugin/nodestore_default.h
  71. 0 7
      plugins/include/open62541/plugin/securitypolicy_mbedtls_common.h
  72. 0 20
      plugins/include/open62541/server_config_default.h
  73. 0 322
      plugins/mqtt/ua_mqtt_adapter.c
  74. 0 39
      plugins/mqtt/ua_mqtt_adapter.h
  75. 0 43
      plugins/mqtt/ua_mqtt_pal.c
  76. 8 12
      plugins/securityPolicies/ua_securitypolicy_basic128rsa15.c
  77. 9 12
      plugins/securityPolicies/ua_securitypolicy_basic256.c
  78. 8 12
      plugins/securityPolicies/ua_securitypolicy_basic256sha256.c
  79. 6 6
      plugins/securityPolicies/ua_securitypolicy_none.c
  80. 2 3
      plugins/ua_accesscontrol_default.c
  81. 67 139
      plugins/ua_config_default.c
  82. 3 3
      plugins/ua_log_stdout.c
  83. 0 304
      plugins/ua_network_pubsub_mqtt.c
  84. 0 47
      plugins/ua_network_pubsub_mqtt.h
  85. 98 65
      plugins/ua_nodestore_ziptree.c
  86. 0 455
      plugins/ua_nodestore_hashmap.c
  87. 11 15
      plugins/ua_pki_default.c
  88. 10 19
      src/client/ua_client.c
  89. 16 27
      src/client/ua_client_highlevel.c
  90. 3 14
      src/client/ua_client_internal.h
  91. 119 575
      src/client/ua_client_subscriptions.c
  92. 1 1
      src/client/ua_client_worker.c
  93. 911 809
      src/pubsub/ua_pubsub_writer.c
  94. 8 24
      src/pubsub/ua_pubsub.h
  95. 117 114
      src/pubsub/ua_pubsub_manager.c
  96. 3 3
      src/pubsub/ua_pubsub_manager.h
  97. 33 166
      src/pubsub/ua_pubsub_networkmessage.c
  98. 2 42
      src/pubsub/ua_pubsub_networkmessage.h
  99. 7 8
      src/pubsub/ua_pubsub_ns0.c
  100. 0 0
      src/pubsub/ua_pubsub_reader.c

+ 61 - 0
.azure-pipelines/azure-pipelines-dist.yml

@@ -0,0 +1,61 @@
+# Docs see here:
+# https://aka.ms/yaml
+
+jobs:
+- job: 'dist_debian'
+  displayName: 'Dist (debian)'
+  pool:
+    vmImage: 'ubuntu-18.04'
+  steps:
+  - checkout: self
+    submodules: recursive
+
+  - task: Bash@3
+    inputs:
+      targetType: FilePath
+      filePath: ./tools/azure-devops/debian/install.sh
+      failOnStderr: false
+    displayName: Installing required packages
+
+  - task: Bash@3
+    inputs:
+      targetType: FilePath
+      filePath: ./tools/azure-devops/debian/build.sh
+      failOnStderr: false
+    displayName: Building & Testing
+
+  - task: PublishBuildArtifacts@1
+    inputs:
+      PathtoPublish: '$(Build.ArtifactStagingDirectory)'
+      ArtifactName: libopen62541-debian
+      # publishing artifacts from PRs from a fork is currently blocked
+    condition: succeeded()
+    displayName: "Publish Artifact: open62541 Debian Packages"
+
+  # See https://github.com/microsoft/azure-pipelines-tasks/issues/11260#issuecomment-527343172
+  - bash: echo "##vso[task.setvariable variable=TAG]${BUILD_SOURCEBRANCH##refs/tags/}"
+    displayName: Set TAG variable for $(Build.SourceBranch)
+    condition: startswith(variables['Build.SourceBranch'], 'refs/tags/')
+  - task: GitHubRelease@0
+    # Only execute this task if a tags build
+    condition: startswith(variables['Build.SourceBranch'], 'refs/tags/')
+    inputs:
+      gitHubConnection: 'open62541-azure-bot'
+      repositoryName: '$(Build.Repository.Name)'
+      action: 'edit' # Options: create, edit, delete
+      target: '$(Build.SourceVersion)' # Required when action == Create || Action == Edit
+      tagSource: 'Git tag'
+      #tagPattern: # Optional
+      tag: $(TAG) # Required when action == Edit || Action == Delete || TagSource == Manual
+      #title: # Optional
+      #releaseNotesSource: 'file' # Optional. Options: file, input
+      #releaseNotesFile: # Optional
+      #releaseNotes: # Optional
+      assets: '$(Build.ArtifactStagingDirectory)/*' # Optional
+      assetUploadMode: 'replace' # Optional. Options: delete, replace
+      #isDraft: false # Optional
+      #isPreRelease: false # Optional
+      addChangeLog: false # Optional
+      #compareWith: 'lastFullRelease' # Required when addChangeLog == True. Options: lastFullRelease, lastRelease, lastReleaseByTag
+      #releaseTag: # Required when compareWith == LastReleaseByTag
+

+ 0 - 28
.azure-pipelines/azure-pipelines-linux.yml

@@ -1,28 +0,0 @@
-# Docs see here:
-# https://aka.ms/yaml
-
-jobs:
-- job: 'cross_freeRTOS'
-  displayName: 'Arch (freeRTOS)'
-  pool:
-    vmImage: 'ubuntu-18.04'
-  variables:
-    IDF_PATH: $(Build.BinariesDirectory)/esp-idf
-  steps:
-  - checkout: self
-    submodules: recursive
-
-  - task: Bash@3
-    inputs:
-      targetType: FilePath
-      filePath: ./tools/azure-devops/freeRTOS/install.sh
-      failOnStderr: false
-    displayName: Installing required packages
-
-  - task: Bash@3
-    inputs:
-      targetType: FilePath
-      filePath: ./tools/azure-devops/freeRTOS/build.sh
-      failOnStderr: false
-    displayName: Building & Testing
-

+ 4 - 5
.github/lock.yml

@@ -14,11 +14,10 @@ exemptLabels: []
 lockLabel: false
 
 # Comment to post before locking. Set to `false` to disable
-lockComment: false
-#lockComment: >
-#  This thread has been automatically locked since there has not been
-#  any recent activity after it was closed. Please open a new issue for
-#  related bugs.
+lockComment: >
+  This thread has been automatically locked since there has not been
+  any recent activity after it was closed. Please open a new issue for
+  related bugs.
 
 # Assign `resolved` as the reason for locking. Set to `false` to disable
 setLockReason: true

+ 0 - 18
.github/semantic.yml

@@ -1,18 +0,0 @@
-# Valid scopes for commit messages. 
-scopes:
-  - appveyor
-  - arch
-  - client
-  - core
-  - encrypt
-  - example
-  - fuzz
-  - multithread
-# Nodeset Compiler
-  - nc
-  - plugin
-  - pack
-  - pubsub
-  - server
-  - travis
-

+ 1 - 8
.travis.yml

@@ -22,7 +22,7 @@ matrix:
 #
 # gcc-4.8 (trusty) full host and cross build with tests:
 # doc, cert, cross-mingw32, cross-mingw64, cross-linux32, cross-raspi, linux64,
-# amalgamated, shared, multithread, encryption, discovery, json, test-ns0-full, test-ns0-minimal, debian-package
+# amalgamated, shared, multithread, encryption, discovery, json, test-ns0-full, test-ns0-minimal
     - os: linux
       compiler: gcc-4.8
       addons:
@@ -36,10 +36,7 @@ matrix:
             - gcc-mingw-w64-x86-64
             - binutils-mingw-w64-i686
             - g++-multilib
-            # debian packaging
             - cmake
-            - debhelper
-            - fakeroot
             # doc
             - python-sphinx
             - graphviz
@@ -53,7 +50,6 @@ matrix:
             - valgrind
       env:
         - MINGW=true
-        - DEBIAN=true
 #
 # gcc-8 full host build with tests:
 # doc, cert, linux64,
@@ -262,8 +258,6 @@ matrix:
     # clang-format code analysis
     - env:
         - CLANG_FORMAT=true
-    - env:
-        - SONAR=true
 
 cache:
   pip: true
@@ -378,7 +372,6 @@ deploy:
     - open62541-raspberrypi.tar.gz
     - open62541.c
     - open62541.h
-    - open62541*.deb
   file_glob: true
   skip_cleanup: true
   on:

+ 90 - 169
CMakeLists.txt

@@ -103,13 +103,7 @@ set(ua_architecture_headers ${ua_architecture_headers}
     ${PROJECT_SOURCE_DIR}/include/open62541/architecture_functions.h
 )
 
-if(UA_ENABLE_WEBSOCKET_SERVER)
-    set(ua_architecture_sources ${ua_architecture_sources}
-                                ${PROJECT_SOURCE_DIR}/arch/network_ws.c)
 
-    set(ua_architecture_headers ${ua_architecture_headers}
-                                ${PROJECT_SOURCE_DIR}/include/open62541/network_ws.h)
-endif()
 
 if(${UA_ARCHITECTURE} STREQUAL "None")
   message(FATAL_ERROR "No architecture was selected. Please select the architecture of your target platform")
@@ -125,20 +119,20 @@ foreach(arch_ ${architectures})
 endforeach(arch_ ${architectures})
 
 # Options
-option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
 set(UA_LOGLEVEL 300 CACHE STRING "Level at which logs shall be reported")
-set(UA_MULTITHREADING 0 CACHE STRING "Level of multithreading (0-99: No Multithreading, 100-199: Thread-Safe API, >=200: Internal Threads")
 option(UA_ENABLE_HISTORIZING "Enable server and client to provide historical access." OFF)
+option(UA_ENABLE_EXPERIMENTAL_HISTORIZING "Enable client experimental historical access features." OFF)
 option(UA_ENABLE_METHODCALLS "Enable the Method service set" ON)
 option(UA_ENABLE_NODEMANAGEMENT "Enable dynamic addition and removal of nodes at runtime" ON)
 option(UA_ENABLE_SUBSCRIPTIONS "Enable subscriptions support." ON)
 option(UA_ENABLE_SUBSCRIPTIONS_EVENTS "Enable the use of event subscriptions" OFF)
 option(UA_ENABLE_DISCOVERY "Enable Discovery Service (LDS)" ON)
 option(UA_ENABLE_DISCOVERY_MULTICAST "Enable Discovery Service with multicast support (LDS-ME)" OFF)
+option(UA_ENABLE_QUERY "Enable query support." OFF)
+option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
 option(UA_ENABLE_ENCRYPTION "Enable encryption support (uses mbedTLS)" OFF)
-option(UA_ENABLE_DA "Enable OPC UA DataAccess (Part 8) definitions" ON)
 option(UA_ENABLE_MICRO_EMB_DEV_PROFILE "Builds CTT Compliant Micro Embedded Device Server Profile" OFF)
-option(UA_ENABLE_WEBSOCKET_SERVER "Enable websocket support (uses libwebsockets)" OFF)
+option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
 
 # Namespace Zero
 set(UA_NAMESPACE_ZERO "REDUCED" CACHE STRING "Completeness of the generated namespace zero (minimal/reduced/full)")
@@ -172,6 +166,7 @@ if(UA_BUILD_FUZZING OR UA_BUILD_OSS_FUZZ OR UA_BUILD_FUZZING_CORPUS)
     set(UA_ENABLE_SUBSCRIPTIONS_EVENTS ON CACHE STRING "" FORCE)
 endif()
 
+
 # It should not be possible to enable events without enabling subscriptions and full ns0
 #if((UA_ENABLE_SUBSCRIPTIONS_EVENTS) AND (NOT (UA_ENABLE_SUBSCRIPTIONS AND UA_NAMESPACE_ZERO STREQUAL "FULL")))
 #    message(FATAL_ERROR "Unable to enable events without UA_ENABLE_SUBSCRIPTIONS and full namespace 0")
@@ -190,24 +185,24 @@ if(UA_ENABLE_DISCOVERY_MULTICAST AND NOT UA_ENABLE_DISCOVERY)
 endif()
 
 # Advanced options
-option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
-mark_as_advanced(UA_ENABLE_COVERAGE)
-
-option(UA_ENABLE_QUERY "Enable query support in the client (most servers don't support it)" OFF)
-mark_as_advanced(UA_ENABLE_QUERY)
+option(UA_ENABLE_MULTITHREADING "Enable multithreading (EXPERIMENTAL)" OFF)
+mark_as_advanced(UA_ENABLE_MULTITHREADING)
 
 option(UA_ENABLE_IMMUTABLE_NODES "Nodes in the information model are not edited but copied and replaced" OFF)
 mark_as_advanced(UA_ENABLE_IMMUTABLE_NODES)
-if(UA_MULTITHREADING GREATER 100)
+if(UA_ENABLE_MULTITHREADING)
     set(UA_ENABLE_IMMUTABLE_NODES ON)
 endif()
 
-option(UA_ENABLE_EXPERIMENTAL_HISTORIZING "Enable client experimental historical access features" OFF)
-mark_as_advanced(UA_ENABLE_EXPERIMENTAL_HISTORIZING)
+option(UA_ENABLE_CUSTOM_NODESTORE "Do not compile the default Nodestore implementation into the library" OFF)
+mark_as_advanced(UA_ENABLE_CUSTOM_NODESTORE)
 
 option(UA_ENABLE_PUBSUB "Enable publish/subscribe" OFF)
 mark_as_advanced(UA_ENABLE_PUBSUB)
 
+option(UA_ENABLE_DA "Enable data access" ON)
+mark_as_advanced(UA_ENABLE_DA)
+
 option(UA_ENABLE_PUBSUB_ETH_UADP "Enable publish/subscribe UADP over Ethernet" OFF)
 mark_as_advanced(UA_ENABLE_PUBSUB_ETH_UADP)
 if(UA_ENABLE_PUBSUB_ETH_UADP)
@@ -249,23 +244,11 @@ endif()
 option(UA_ENABLE_JSON_ENCODING "Enable Json encoding (EXPERIMENTAL)" OFF)
 mark_as_advanced(UA_ENABLE_JSON_ENCODING)
 
-option(UA_ENABLE_PUBSUB_MQTT "Enable publish/subscribe with mqtt (experimental)" OFF)
-mark_as_advanced(UA_ENABLE_PUBSUB_MQTT)
-if(UA_ENABLE_PUBSUB_MQTT)
-    # Warn if run in Windows
-    if(WIN32)
-        MESSAGE(WARNING "Multithreading is enabled in MQTT plugin. This feature is under development and marked as EXPERIMENTAL")
-    endif()
-    if(NOT UA_ENABLE_PUBSUB)
-    message(FATAL_ERROR "Mqtt cannot be used with disabled PubSub function.")
-    endif()
-endif()
-
 option(UA_ENABLE_STATUSCODE_DESCRIPTIONS "Enable conversion of StatusCode to human-readable error message" ON)
 mark_as_advanced(UA_ENABLE_STATUSCODE_DESCRIPTIONS)
 
-option(UA_ENABLE_TYPEDESCRIPTION "Add the type and member names to the UA_DataType structure" ON)
-mark_as_advanced(UA_ENABLE_TYPEDESCRIPTION)
+option(UA_ENABLE_TYPENAMES "Add the type and member names to the UA_DataType structure" ON)
+mark_as_advanced(UA_ENABLE_TYPENAMES)
 
 option(UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS "Set node description attribute for nodeset compiler generated nodes" ON)
 mark_as_advanced(UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS)
@@ -291,13 +274,6 @@ mark_as_advanced(UA_MSVC_FORCE_STATIC_CRT)
 option(UA_FILE_NS0 "Override the NodeSet xml file used to generate namespace zero")
 mark_as_advanced(UA_FILE_NS0)
 
-# Blacklist file passed as --blacklist to the nodeset compiler. All the given nodes will be removed from the generated
-# nodeset, including all the references to and from that node. The format is a node id per line.
-# Supported formats: "i=123" (for NS0), "ns=2;s=asdf" (matches NS2 in that specific file), or recommended
-# "ns=http://opcfoundation.org/UA/DI/;i=123" namespace index independent node id
-option(UA_FILE_NS0_BLACKLIST "File containing blacklisted nodes which should not be included in the generated nodeset code.")
-mark_as_advanced(UA_FILE_NS0_BLACKLIST)
-
 # Semaphores/file system may not be available on embedded devices. It can be
 # disabled with the following option
 option(UA_ENABLE_DISCOVERY_SEMAPHORE "Enable Discovery Semaphore support" ON)
@@ -328,7 +304,6 @@ mark_as_advanced(UA_ENABLE_HARDENING)
 
 if(CMAKE_VERSION VERSION_GREATER 3.6)
     set(UA_ENABLE_STATIC_ANALYZER "OFF" CACHE STRING "Enable installed static analyzer during build process (off/minimal/reduced/full)")
-    mark_as_advanced(UA_ENABLE_STATIC_ANALYZER)
     SET_PROPERTY(CACHE UA_ENABLE_STATIC_ANALYZER PROPERTY STRINGS "OFF" "MINIMAL" "REDUCED" "FULL")
 endif()
 
@@ -353,7 +328,7 @@ option(UA_BUILD_FUZZING_CORPUS "Build the fuzzing corpus" OFF)
 mark_as_advanced(UA_BUILD_FUZZING_CORPUS)
 if(UA_BUILD_FUZZING_CORPUS)
     add_definitions(-DUA_DEBUG_DUMP_PKGS_FILE)
-    set(UA_ENABLE_TYPEDESCRIPTION ON CACHE STRING "" FORCE)
+    set(UA_ENABLE_TYPENAMES ON CACHE STRING "" FORCE)
     #set(UA_DEBUG_DUMP_PKGS ON CACHE STRING "" FORCE)
 endif()
 
@@ -374,8 +349,8 @@ if(BUILD_SHARED_LIBS)
 endif()
 
 # Warn if experimental features are enabled
-if(UA_MULTITHREADING GREATER 199)
-    MESSAGE(WARNING "UA_MULTITHREADING >= 200. Internal threads of the server are an EXPERIMENTAL feature. Expect bugs")
+if(UA_ENABLE_MULTITHREADING)
+    MESSAGE(WARNING "UA_ENABLE_MULTITHREADING is enabled. The feature is under development and marked as EXPERIMENTAL")
 endif()
 
 ########################
@@ -406,75 +381,37 @@ if(UA_ENABLE_ENCRYPTION)
     list(APPEND open62541_LIBRARIES ${MBEDTLS_LIBRARIES})
 endif()
 
-if(UA_ENABLE_WEBSOCKET_SERVER)
-    # The recommended way is to install libwebsockets via the OS package manager. If
-    # that is not possible, manually compile libwebsockets and set the cmake variables
-    # defined in /tools/cmake/Findlibwebsockets.cmake
-    find_package(libwebsockets REQUIRED)
-    list(APPEND open62541_LIBRARIES ${LIBWEBSOCKETS_LIBRARIES})
-endif()
-
 #####################
 # Compiler Settings #
 #####################
 
-# Check if a C compiler flag is supported and add it (if supported)
-# Taken from https://stackoverflow.com/a/33266748
-include(CheckCCompilerFlag)
-function(check_add_cc_flag CC_FLAG)
-    string(FIND "${CMAKE_C_FLAGS}" "${CC_FLAG}" flag_already_set)
-    if(flag_already_set EQUAL -1)
-        message(STATUS "Test CC flag ${CC_FLAG}")
-        check_c_compiler_flag("${CC_FLAG}" flag_supported)
-        if(flag_supported)
-            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CC_FLAG}" PARENT_SCOPE)
-        endif()
-        unset(flag_supported CACHE)
-    endif()
-endfunction()
-
+include(CompilerFlags)
 if(NOT UA_COMPILE_AS_CXX AND (CMAKE_COMPILER_IS_GNUCC OR "x${CMAKE_C_COMPILER_ID}" STREQUAL "xClang"))
-    check_add_cc_flag("-std=c99")   # C99 mode
-    check_add_cc_flag("-pipe")      # Avoid writing temporary files (for compiler speed)
-    check_add_cc_flag("-Wall")      # Warnings
-    check_add_cc_flag("-Wextra")    # More warnings
-    check_add_cc_flag("-Wpedantic") # Standard compliance
-    check_add_cc_flag("-Werror")    # All warnings are errors
-
-    check_add_cc_flag("-Wno-static-in-inline") # Clang doesn't like the use of static inline methods inside static inline methods
-    check_add_cc_flag("-Wno-overlength-strings") # May happen in the nodeset compiler when complex values are directly encoded
-    check_add_cc_flag("-Wno-unused-parameter") # some methods may require unused arguments to cast to a method pointer
-
-    # Use a strict subset of the C and C++ languages
-    check_add_cc_flag("-Wc++-compat")
-
-    # Check that format strings (printf/scanf) are sane
-    check_add_cc_flag("-Wformat")
-    check_add_cc_flag("-Wformat-security")
-    check_add_cc_flag("-Wformat-nonliteral")
-
-    # Check prototype definitions
-    check_add_cc_flag("-Wmissing-prototypes")
-    check_add_cc_flag("-Wstrict-prototypes")
-    check_add_cc_flag("-Wredundant-decls")
-
-    check_add_cc_flag("-Wuninitialized")
-    check_add_cc_flag("-Winit-self")
-    check_add_cc_flag("-Wcast-qual")
-    check_add_cc_flag("-Wstrict-overflow")
-    check_add_cc_flag("-Wnested-externs")
-    check_add_cc_flag("-Wmultichar")
-    check_add_cc_flag("-Wundef")
-    check_add_cc_flag("-fno-strict-aliasing") # fewer compiler assumptions about pointer types
-    check_add_cc_flag("-fexceptions") # recommended for multi-threaded C code, also in combination with C++ code
+    # Compiler
+    add_definitions(-std=c99 -pipe
+                    -Wall -Wextra -Wpedantic
+                    -Wno-static-in-inline # clang doesn't like the use of static inline methods inside static inline methods
+                    -Wno-overlength-strings # may happen in the nodeset compiler when complex values are directly encoded
+                    -Wno-unused-parameter # some methods may require unused arguments to cast to a method pointer
+                    -Wmissing-prototypes -Wstrict-prototypes -Wredundant-decls
+                    -Wformat -Wformat-security -Wformat-nonliteral
+                    -Wuninitialized -Winit-self
+                    -Wcast-qual
+                    -Wstrict-overflow
+                    -Wnested-externs
+                    -Wmultichar
+                    -Wundef
+                    -Wc++-compat
+                    -fno-strict-aliasing # fewer compiler assumptions about pointer types
+                    -fexceptions # recommended for multi-threaded C code, also in combination with C++ code
+                    )
+    set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Werror")
 
     if (NOT MINGW)
         if(UA_ENABLE_HARDENING)
-            check_add_cc_flag("-fstack-protector-strong") # more performant stack protector, available since gcc 4.9
-            check_add_cc_flag("-fstack-clash-protection") # increased reliability of stack overflow detection, available since gcc 8
-            # future use (control flow integrity protection)
-            check_add_cc_flag("-mcet")
-            check_add_cc_flag("-fcf-protection")
+            check_cc_flag("-fstack-protector-strong") # more performant stack protector, available since gcc 4.9
+            check_cc_flag("-fstack-clash-protection") # increased reliability of stack overflow detection, available since gcc 8
+            check_cc_flag_untested("-mcet -fcf-protection") # future use (control flow integrity protection)
         endif()
 
         # IPO requires too much memory for unit tests
@@ -516,21 +453,16 @@ if(NOT UA_COMPILE_AS_CXX AND (CMAKE_COMPILER_IS_GNUCC OR "x${CMAKE_C_COMPILER_ID
     endif()
 
     if(UA_ENABLE_HARDENING AND ((CMAKE_BUILD_TYPE STREQUAL "Release") OR (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")))
-        check_add_cc_flag("-D_FORTIFY_SOURCE=2") # run-time buffer overflow detection (needs at least -O1)
+        check_cc_flag("-D_FORTIFY_SOURCE=2") # run-time buffer overflow detection (needs at least -O1)
     endif()
 
     # Strip release builds
     if(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" OR CMAKE_BUILD_TYPE STREQUAL "Release")
-        check_add_cc_flag("-ffunction-sections")
-        check_add_cc_flag("-fdata-sections")
-        check_add_cc_flag("-fno-unwind-tables")
-        check_add_cc_flag("-fno-asynchronous-unwind-tables")
-        check_add_cc_flag("-fno-math-errno")
-        check_add_cc_flag("-fno-ident")
-
+        add_definitions(-ffunction-sections -fdata-sections -fno-unwind-tables
+                        -fno-asynchronous-unwind-tables -fno-math-errno -fno-ident)
         # remove stack-protector with MinSizeRel
         if(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
-            check_add_cc_flag("-fno-stack-protector")
+            add_definitions(-fno-stack-protector)
         endif()
         if(NOT OS9)
             set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -s")
@@ -550,6 +482,8 @@ if(NOT UA_COMPILE_AS_CXX AND (CMAKE_COMPILER_IS_GNUCC OR "x${CMAKE_C_COMPILER_ID
     endif()
 endif()
 
+
+
 if(APPLE)
     set(CMAKE_MACOSX_RPATH 1)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_DARWIN_C_SOURCE=1")
@@ -660,8 +594,7 @@ set(internal_headers ${PROJECT_SOURCE_DIR}/deps/open62541_queue.h
                      ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_ns0.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_server_internal.h
                      ${PROJECT_SOURCE_DIR}/src/server/ua_services.h
-                     ${PROJECT_SOURCE_DIR}/src/client/ua_client_internal.h
-					 ${PROJECT_SOURCE_DIR}/src/server/ua_server_async.h)
+                     ${PROJECT_SOURCE_DIR}/src/client/ua_client_internal.h)
 
 # TODO: make client optional
 set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
@@ -682,12 +615,10 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server_binary.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server_utils.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server_discovery.c
-				${PROJECT_SOURCE_DIR}/src/server/ua_server_async.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_securechannel_manager.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_session_manager.c
                 ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_networkmessage.c
-                ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_writer.c
-                ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_reader.c
+                ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub.c
                 ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_manager.c
                 ${PROJECT_SOURCE_DIR}/src/pubsub/ua_pubsub_ns0.c
                 # services
@@ -718,7 +649,6 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
 set(default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/accesscontrol_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/pki_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/log_stdout.h
-                           ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/nodestore_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/server_config_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/client_config_default.h
                            ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/securitypolicy_default.h
@@ -727,8 +657,7 @@ set(default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugi
 set(default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_log_stdout.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_accesscontrol_default.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_pki_default.c
-                           ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_ziptree.c
-                           ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_hashmap.c
+                           ${PROJECT_SOURCE_DIR}/plugins/ua_nodestore_default.c
                            ${PROJECT_SOURCE_DIR}/plugins/ua_config_default.c
                            ${PROJECT_SOURCE_DIR}/plugins/securityPolicies/ua_securitypolicy_none.c
 )
@@ -774,20 +703,6 @@ if(UA_ENABLE_PUBSUB)
         list(APPEND default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/include/open62541/plugin/pubsub_ethernet.h)
         list(APPEND default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_pubsub_ethernet.c)
     endif()
-    if(UA_ENABLE_PUBSUB_MQTT)
-        if(WIN32)
-            MESSAGE(WARNING "Multithreading is enabled in MQTT plugin. This feature is under development and marked as EXPERIMENTAL")
-        else()
-            list(APPEND default_plugin_headers ${PROJECT_SOURCE_DIR}/deps/mqtt-c/mqtt_pal.h)
-            list(APPEND default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/mqtt/ua_mqtt_pal.c)
-            list(APPEND default_plugin_headers ${PROJECT_SOURCE_DIR}/deps/mqtt-c/mqtt.h)
-            list(APPEND default_plugin_sources ${PROJECT_SOURCE_DIR}/deps/mqtt-c/mqtt.c)
-            list(APPEND default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/ua_network_pubsub_mqtt.h)
-            list(APPEND default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/ua_network_pubsub_mqtt.c)
-            list(APPEND default_plugin_headers ${PROJECT_SOURCE_DIR}/plugins/mqtt/ua_mqtt_adapter.h)
-            list(APPEND default_plugin_sources ${PROJECT_SOURCE_DIR}/plugins/mqtt/ua_mqtt_adapter.c)
-        endif()
-    endif()
 endif()
 
 if(UA_ENABLE_JSON_ENCODING)
@@ -869,7 +784,7 @@ if(UA_NAMESPACE_ZERO STREQUAL "FULL")
     set(UA_FILE_TYPES_BSD ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.Types.bsd)
 else()
     if(NOT UA_FILE_NS0)
-        set(UA_FILE_NS0 ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Reduced.xml)
+        set(UA_FILE_NS0 ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Minimal.xml)
     endif()
     set(UA_FILE_NODESETS "${UA_FILE_NS0}")
 
@@ -912,10 +827,6 @@ else()
     endif()
 	if(UA_ENABLE_DA)
 		list(APPEND UA_FILE_DATATYPES ${PROJECT_SOURCE_DIR}/tools/schema/datatypes_dataaccess.txt)
-        set(UA_NODESET_FILE_DA ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Part8_Subset.xml)
-    endif()
-    if(UA_ENABLE_TYPEDESCRIPTION)
-        list(APPEND UA_FILE_DATATYPES ${PROJECT_SOURCE_DIR}/tools/schema/datatypes_typedescription.txt)
     endif()
 endif()
 
@@ -993,9 +904,8 @@ endif()
 
 ua_generate_nodeset(
     NAME "ns0"
-    FILE ${UA_FILE_NODESETS} ${UA_NODESET_FILE_DA}
+    FILE ${UA_FILE_NODESETS}
     INTERNAL
-    BLACKLIST ${UA_FILE_NS0_BLACKLIST}
     IGNORE "${PROJECT_SOURCE_DIR}/tools/nodeset_compiler/NodeID_NS0_Base.txt"
     DEPENDS_TARGET "open62541-generator-types"
 )
@@ -1032,13 +942,12 @@ if(UA_ENABLE_AMALGAMATION)
     # make sure the open62541_amalgamation target builds before so that amalgamation is finished and it is not executed again for open62541-object
     # and thus may overwrite the amalgamation result during multiprocessor compilation
     # the header is already a dependency of open62541 target itself
-    add_custom_target(open62541-code-generation DEPENDS
-                      open62541-amalgamation-header
-                      open62541-generator-types
-                      open62541-generator-transport
-                      open62541-generator-statuscode
-                      open62541-amalgamation-source
-    )
+    add_dependencies(open62541-object
+                     open62541-amalgamation-header
+                     open62541-generator-types
+                     open62541-generator-transport
+                     open62541-generator-statuscode
+                     open62541-amalgamation-source)
 
     add_library(open62541 $<TARGET_OBJECTS:open62541-object>)
     # the only directory that needs to be included if open62541 (amalgameted) target from
@@ -1053,14 +962,12 @@ if(UA_ENABLE_AMALGAMATION)
     add_dependencies(open62541-amalgamation-header open62541-generator-namespace)
 else()
     add_library(open62541-object OBJECT ${lib_sources} ${internal_headers} ${exported_headers})
-
-    add_custom_target(open62541-code-generation DEPENDS
-                      open62541-generator-types
-                      open62541-generator-transport
-                      open62541-generator-statuscode
-                      open62541-generator-namespace
-                      )
-
+    add_dependencies(open62541-object
+                     open62541-generator-types
+                     open62541-generator-transport
+                     open62541-generator-statuscode
+                     open62541-generator-namespace
+                     )
     target_include_directories(open62541-object PRIVATE ${PROJECT_SOURCE_DIR}/src)
 
     add_library(open62541-plugins OBJECT ${default_plugin_sources} ${ua_architecture_sources} ${exported_headers})
@@ -1070,6 +977,10 @@ else()
     target_compile_definitions(open62541-plugins PRIVATE -DUA_DYNAMIC_LINKING_EXPORT)
     set_target_properties(open62541-plugins PROPERTIES FOLDER "open62541/lib")
 
+    if(UA_PACK_DEBIAN)
+        add_library(open62541-static STATIC $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-plugins>)
+        set_target_properties(open62541-static PROPERTIES OUTPUT_NAME open62541)
+    endif()
     add_library(open62541 $<TARGET_OBJECTS:open62541-object> $<TARGET_OBJECTS:open62541-plugins>)
 
     if(UA_COMPILE_AS_CXX)
@@ -1114,8 +1025,6 @@ else()
 
 endif()
 
-add_dependencies(open62541-object open62541-code-generation)
-
 # Ensure that the open62541::open62541 alias can be used inside open62541's build
 add_library(open62541::open62541 ALIAS open62541)
 
@@ -1140,9 +1049,6 @@ GET_PROPERTY(ua_architecture_remove_definitions GLOBAL PROPERTY UA_ARCHITECTURE_
 if (NOT "${ua_architecture_remove_definitions}" STREQUAL "")
   string(REPLACE " " ";" ua_architecture_remove_definitions_list ${ua_architecture_remove_definitions})
   remove_definitions(${ua_architecture_remove_definitions_list})
-  foreach ( flag ${ua_architecture_remove_definitions} )
-      string(REPLACE "${flag}" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
-  endforeach()
 endif(NOT "${ua_architecture_remove_definitions}" STREQUAL "")
 
 GET_PROPERTY(ua_architecture_append_to_library GLOBAL PROPERTY UA_ARCHITECTURE_APPEND_TO_LIBRARY)
@@ -1234,7 +1140,7 @@ endif()
 if(UA_ENABLE_SUBSCRIPTIONS_EVENTS)
     list(APPEND open62541_enabled_components "Events")
 endif()
-if(UA_MULTITHREADING)
+if(UA_ENABLE_MULTITHREADING)
     list(APPEND open62541_enabled_components "Multithreading")
 endif()
 if(UA_ENABLE_DISCOVERY)
@@ -1245,7 +1151,12 @@ if(UA_ENABLE_DISCOVERY_MULTICAST)
 endif()
 
 # export library (either static or shared depending on BUILD_SHARED_LIBS)
-install(TARGETS open62541
+if(UA_PACK_DEBIAN)
+    set(EXTRATARGETS "open62541-static")
+else()
+    set(EXTRATARGETS "")
+endif()
+install(TARGETS open62541 ${EXTRATARGETS}
         EXPORT open62541Targets
         LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
         ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -1316,6 +1227,19 @@ install(DIRECTORY ${UA_install_tools_dirs}
 
 install(FILES ${UA_install_tools_files} DESTINATION ${open62541_install_tools_dir})
 
+if (UA_PACK_DEBIAN)    
+    set(UA_install_examples_dirs "examples/"
+        "examples/access_control"
+        "examples/custom_datatype"
+        "examples/discovery"
+        "examples/encryption"
+        "examples/nodeset"
+        "examples/pubsub")
+
+    set(open62541_install_examples_dir share/open62541/examples)
+    install(DIRECTORY ${UA_install_examples_dirs} COMPONENT examples DESTINATION ${open62541_install_examples_dir} USE_SOURCE_PERMISSIONS)
+endif()
+
 if(NOT UA_ENABLE_AMALGAMATION)
     # Recreate the include folder structure from the source also in /usr/lib/include/open62541
 
@@ -1340,11 +1264,7 @@ if(NOT UA_ENABLE_AMALGAMATION)
         string(REPLACE ${BASE_PATH_DEPS} "" file ${file})
 
         get_filename_component( dir ${file} DIRECTORY )
-        if(${full_path} MATCHES "deps")
-            install( FILES ${full_path} DESTINATION include${dir} )
-        else()
-            install( FILES ${full_path} DESTINATION include/open62541${dir} )
-        endif()
+        install( FILES ${full_path} DESTINATION include/open62541${dir} )
     endforeach()
 
 else()
@@ -1373,3 +1293,4 @@ set_target_properties(open62541-generator-namespace PROPERTIES FOLDER "open62541
 set_target_properties(open62541-generator-statuscode PROPERTIES FOLDER "open62541/generators")
 set_target_properties(open62541-generator-transport PROPERTIES FOLDER "open62541/generators")
 set_target_properties(open62541-generator-types PROPERTIES FOLDER "open62541/generators")
+

+ 3 - 92
CONTRIBUTING.md

@@ -43,97 +43,7 @@ The following are the minimal requirements that every PR needs to meet.
   link automatically appears on the page of the first PR. In addition, the CLA
   text can be accessed [here](https://cla-assistant.io/open62541/open62541).
 
-## Commit and PR Hygiene
-
-We have very precise rules over how our git commit messages can be formatted.  This leads to **more
-readable messages** that are easy to follow when looking through the **project history**.  But also,
-we use the git commit messages to **generate the change log**.
-
-This convention is identical to the [Conventional Commits](https://www.conventionalcommits.org) specification or the one used by Angular.
-
-### Commit Message Format
-Each commit message consists of a **header**, a **body** and a **footer**.  The header has a special
-format that includes a **type**, a **scope** and a **subject**:
-
-```text
-<type>(<scope>): <subject>
-<BLANK LINE>
-<body>
-<BLANK LINE>
-<footer>
-```
-
-The **header** is mandatory and the **scope** of the header is optional.
-
-Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
-to read on GitHub as well as in various git tools.
-
-The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
-
-Samples: (even more [samples](https://github.com/angular/angular/commits/master))
-
-```text
-docs(server): add function documentation
-```
-```text
-fix(core): fix parsing of endpoint url
-
-Parsing of endpoint urls now also supports https
-```
-
-### Revert
-If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
-
-### Type
-Must be one of the following:
-
-- **build**: Changes that affect the build system or external dependencies
-- **ci**: Changes to our CI configuration files and scripts (example scopes: travis, appveyor, fuzz)
-- **docs**: Documentation only changes
-- **feat**: A new feature
-- **fix**: A bug fix
-- **perf**: A code change that improves performance
-- **refactor**: A code change that neither fixes a bug nor adds a feature
-- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
-- **test**: Adding missing tests or correcting existing tests
-
-### Scope
-The scope is optional, but recommended to be used. It should be the name of the component which is affected (as perceived by the person reading the changelog generated from commit messages).
-
-The following is the list of supported scopes:
-
-- **arch**: Changes to specific architecture code in `root/arch`
-- **client**: Changes only affecting client code
-- **core**: Core functionality used by the client and server
-- **ex**: Example code changes
-- **mt**: Changes specifically for multithreading
-- **nc**: Nodeset compiler
-- **pack**: Packaging setting changes
-- **plugin**: Change to any (optional) plugin
-- **pubsub**: Changes to the pubsub code
-- **sec**: Changes to security, encryption, etc.
-- **server**: Changes only affecting server code
-
-### Subject
-The subject contains a succinct description of the change:
-
-- use the imperative, present tense: "change" not "changed" nor "changes"
-- don't capitalize the first letter
-- no dot (.) at the end
-
-### Body
-Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
-The body should include the motivation for the change and contrast this with previous behavior.
-
-### Footer
-The footer should contain any information about **Breaking Changes** and is also the place to
-reference GitHub issues that this commit **Closes**.
-
-**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
-
-## General commit hygiene
-
-We are using the [Conventional Commits](https://www.conventionalcommits.org) specification (see previous section).
+### Commit and PR Hygiene
 
 These sites explain a core set of good practice rules for preparing a PR:
 
@@ -154,7 +64,8 @@ The following points will be especially looked at during the review.
   commit changes that belong together.
 
 - **Commit Messages**: Good commit messages help in understanding changes.
-  See previous section.
+  Consider the following article with best practices for commit messages:
+  https://chris.beams.io/posts/git-commit
 
 - **Linear Commit History**: Our goal is to maintain a linear commit history
   where possible. Use the `git rebase` functionality before pushing a PR. Use

+ 1 - 4
docker/Dockerfile

@@ -5,10 +5,7 @@ ADD . /opt/open62541
 # Get all the git tags to make sure we detect the correct version with git describe
 WORKDIR /opt/open62541
 RUN git remote add github-upstream https://github.com/open62541/open62541.git
-RUN git fetch -f --tags github-upstream
-# Ignore error here. This always fails on Docker Cloud. It's fine there because the submodule is alread initialized. See also:
-# https://stackoverflow.com/questions/58690455/how-to-correctly-initialize-git-submodules-in-dockerfile-for-docker-cloud
-RUN git submodule update --init --recursive || true
+RUN git fetch --tags github-upstream
 
 WORKDIR /opt/open62541/build
 RUN cmake -DBUILD_SHARED_LIBS=ON \

+ 0 - 7
README.md

@@ -122,12 +122,6 @@ Jointly with the overall open62541 community, the core maintainers steer the lon
 - Julius Pfrommer (Fraunhofer IOSB, Karlsruhe)
 - Stefan Profanter (fortiss, Munich)
 
-### Docker container
-
-Official docker container builds are available on [Docker Cloud](https://cloud.docker.com/u/open62541/repository/registry-1.docker.io/open62541/open62541)
-
-More information can be found in the [Docker README](docker/README.md)
-
 ## Support & Development
 
 ### Commercial Support
@@ -236,7 +230,6 @@ int main(int argc, char** argv)
 #include <stdio.h>
 #include <open62541/client.h>
 #include <open62541/client_config_default.h>
-#include <open62541/client_highlevel.h>
 
 int main(int argc, char *argv[])
 {

+ 0 - 12
arch/eCos/ua_architecture.h

@@ -83,18 +83,6 @@ int gethostname_ecos(char* name, size_t len);
     LOG; \
 }
 
-#if UA_MULTITHREADING >= 100
-#error Multithreading unsupported
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
 #include <open62541/architecture_functions.h>
 
 #endif /* PLUGINS_ARCH_ECOS_UA_ARCHITECTURE_H_ */

+ 0 - 15
arch/freertosLWIP/ua_architecture.h

@@ -14,21 +14,6 @@
 #include "ua_lwip.h"
 #include "ua_freeRTOS.h"
 
-#if UA_MULTITHREADING >= 100
-#error Multithreading unsupported
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
-// freeRTOS does not have getifaddr
-#undef UA_HAS_GETIFADDR
-
 #include <open62541/architecture_functions.h>
 
 #endif /* PLUGINS_ARCH_FREERTOSLWIP_UA_ARCHITECTURE_H_ */

+ 2 - 3
arch/network_tcp.c

@@ -185,7 +185,7 @@ typedef struct {
 
 static void
 ServerNetworkLayerTCP_freeConnection(UA_Connection *connection) {
-    UA_Connection_clear(connection);
+    UA_Connection_deleteMembers(connection);
     UA_free(connection);
 }
 
@@ -546,7 +546,7 @@ UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
                          UA_Logger *logger) {
     UA_ServerNetworkLayer nl;
     memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
-    nl.clear = ServerNetworkLayerTCP_deleteMembers;
+    nl.deleteMembers = ServerNetworkLayerTCP_deleteMembers;
     nl.localConnectionConfig = config;
     nl.start = ServerNetworkLayerTCP_start;
     nl.listen = ServerNetworkLayerTCP_listen;
@@ -775,7 +775,6 @@ UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpoint
 
     TCPClientConnection *tcpClientConnection = (TCPClientConnection*) UA_malloc(
                     sizeof(TCPClientConnection));
-    memset(tcpClientConnection, 0, sizeof(TCPClientConnection));
     connection.handle = (void*) tcpClientConnection;
     tcpClientConnection->timeout = timeout;
     UA_String hostnameString = UA_STRING_NULL;

+ 0 - 309
arch/network_ws.c

@@ -1,309 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- *    relies heavily on concepts from libwebsockets minimal examples
- *    Copyright 2019 (c) Matthias Konnerth
- *    Copyright 2019 (c) Michael Derfler
- */
-
-#define UA_INTERNAL
-
-#include <open62541/network_ws.h>
-#include <open62541/plugin/log_stdout.h>
-#include <open62541/util.h>
-#include "open62541_queue.h"
-#include <libwebsockets.h>
-#include <string.h>
-
-struct BufferEntry {
-    UA_ByteString msg;
-    SIMPLEQ_ENTRY(BufferEntry) next;
-};
-
-typedef struct BufferEntry BufferEntry;
-
-struct ConnectionUserData {
-    struct lws *wsi;
-    SIMPLEQ_HEAD(, BufferEntry) messages;
-};
-
-typedef struct ConnectionUserData ConnectionUserData;
-
-//one of these is created for each client connecting to us
-struct SessionData {
-    UA_Connection *connection;
-};
-
-// one of these is created for each vhost our protocol is used with
-struct VHostData {
-    struct lws_context *context;
-};
-
-typedef struct {
-    const UA_Logger *logger;
-    UA_UInt16 port;
-    struct lws_context *context;
-    UA_Server *server;
-    UA_ConnectionConfig config;
-} ServerNetworkLayerWS;
-
-static UA_StatusCode
-connection_getsendbuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
-    if(length > connection->config.sendBufferSize)
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    return UA_ByteString_allocBuffer(buf, length);
-}
-
-static void
-connection_releasesendbuffer(UA_Connection *connection, UA_ByteString *buf) {
-    UA_ByteString_deleteMembers(buf);
-}
-
-static void
-connection_releaserecvbuffer(UA_Connection *connection, UA_ByteString *buf) {
-    UA_ByteString_deleteMembers(buf);
-}
-
-static UA_StatusCode
-connection_send(UA_Connection *connection, UA_ByteString *buf) {
-    ConnectionUserData *buffer = (ConnectionUserData *)connection->handle;
-    if(connection->state == UA_CONNECTION_CLOSED) {
-        UA_ByteString_deleteMembers(buf);
-        return UA_STATUSCODE_BADCONNECTIONCLOSED;
-    }
-
-    BufferEntry *entry = (BufferEntry *)malloc(sizeof(BufferEntry));
-    entry->msg.length = buf->length;
-    entry->msg.data = (UA_Byte *)malloc(LWS_PRE + buf->length);
-    memcpy(entry->msg.data + LWS_PRE, buf->data, buf->length);
-    UA_ByteString_deleteMembers(buf);
-    SIMPLEQ_INSERT_TAIL(&buffer->messages, entry, next);
-    lws_callback_on_writable(buffer->wsi);
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-ServerNetworkLayerWS_close(UA_Connection *connection) {
-    if(connection->state == UA_CONNECTION_CLOSED)
-        return;
-    connection->state = UA_CONNECTION_CLOSED;
-}
-
-static void
-freeConnection(UA_Connection *connection) {
-    if(connection->handle) {
-        UA_free(connection->handle);
-    }
-    UA_Connection_clear(connection);
-    UA_free(connection);
-}
-
-static int
-callback_opcua(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in,
-               size_t len) {
-    struct SessionData *pss = (struct SessionData *)user;
-    struct VHostData *vhd =
-        (struct VHostData *)lws_protocol_vh_priv_get(lws_get_vhost(wsi),
-                                                                   lws_get_protocol(wsi));
-
-    switch(reason) {
-        case LWS_CALLBACK_PROTOCOL_INIT:
-            vhd = (struct VHostData *)lws_protocol_vh_priv_zalloc(
-                lws_get_vhost(wsi), lws_get_protocol(wsi),
-                sizeof(struct VHostData));
-            vhd->context = lws_get_context(wsi);
-            break;
-
-        case LWS_CALLBACK_ESTABLISHED:
-            if(!wsi)
-                break;
-            ServerNetworkLayerWS *layer = (ServerNetworkLayerWS*)lws_context_user(vhd->context);
-            UA_Connection *c = (UA_Connection *)malloc(sizeof(UA_Connection));
-            ConnectionUserData *buffer =
-                (ConnectionUserData *)malloc(sizeof(ConnectionUserData));
-            SIMPLEQ_INIT(&buffer->messages);
-            buffer->wsi = wsi;
-            memset(c, 0, sizeof(UA_Connection));
-            c->sockfd = 0;
-            c->handle = buffer;
-            c->config = layer->config;
-            c->send = connection_send;
-            c->close = ServerNetworkLayerWS_close;
-            c->free = freeConnection;
-            c->getSendBuffer = connection_getsendbuffer;
-            c->releaseSendBuffer = connection_releasesendbuffer;
-            c->releaseRecvBuffer = connection_releaserecvbuffer;
-            // stack sets the connection to established
-            c->state = UA_CONNECTION_OPENING;
-            c->openingDate = UA_DateTime_nowMonotonic();
-            pss->connection = c;
-            break;
-
-        case LWS_CALLBACK_CLOSED:
-            // notify server
-            if(!pss->connection->state != UA_CONNECTION_CLOSED) {
-                pss->connection->state = UA_CONNECTION_CLOSED;
-            }
-
-            layer = (ServerNetworkLayerWS*)lws_context_user(vhd->context);
-            if(layer && layer->server)
-            {
-                UA_Server_removeConnection(layer->server, pss->connection);
-            }
-            
-            break;
-
-        case LWS_CALLBACK_SERVER_WRITEABLE:
-            if(!pss->connection)
-                break;
-
-            ConnectionUserData *b = (ConnectionUserData *)pss->connection->handle;
-            do {
-
-                BufferEntry *entry = SIMPLEQ_FIRST(&b->messages);
-                if(!entry)
-                    break;
-
-                int m = lws_write(wsi, entry->msg.data + LWS_PRE, entry->msg.length,
-                                  LWS_WRITE_BINARY);
-                if(m < (int)entry->msg.length) {
-                    lwsl_err("ERROR %d writing to ws\n", m);
-                    return -1;
-                }
-                UA_ByteString_deleteMembers(&entry->msg);
-                UA_free(entry);
-                SIMPLEQ_REMOVE_HEAD(&b->messages, next);
-            } while(!lws_send_pipe_choked(wsi));
-
-            // process remaining messages
-            if(SIMPLEQ_FIRST(&b->messages)) {
-                lws_callback_on_writable(wsi);
-            }
-            break;
-
-        case LWS_CALLBACK_RECEIVE:
-            if(!vhd->context)
-                break;
-            layer =
-                (ServerNetworkLayerWS *)lws_context_user(vhd->context);
-            if(!layer->server)
-                break;
-
-            UA_ByteString message = {len, (UA_Byte *)in};
-            UA_Server_processBinaryMessage(layer->server, pss->connection, &message);
-            break;
-
-        default:
-            break;
-    }
-
-    return 0;
-}
-
-static struct lws_protocols protocols[] = {
-    {"http", lws_callback_http_dummy, 0, 0, 0, NULL, 0},
-    {"opcua", callback_opcua, sizeof(struct SessionData), 0, 0, NULL, 0},
-    {NULL, NULL, 0, 0, 0, NULL, 0}
-};
-
-// make the opcua protocol callback the default one
-const struct lws_protocol_vhost_options pvo_opt = {NULL, NULL, "default", "1"};
-const struct lws_protocol_vhost_options pvo = {NULL, &pvo_opt, "opcua", ""};
-
-static UA_StatusCode
-ServerNetworkLayerWS_start(UA_ServerNetworkLayer *nl, const UA_String *customHostname) {
-    UA_initialize_architecture_network();
-
-    ServerNetworkLayerWS *layer = (ServerNetworkLayerWS *)nl->handle;
-
-    /* Get the discovery url from the hostname */
-    UA_String du = UA_STRING_NULL;
-    char discoveryUrlBuffer[256];
-    char hostnameBuffer[256];
-    if(customHostname->length) {
-        du.length = (size_t)UA_snprintf(discoveryUrlBuffer, 255, "ws://%.*s:%d/",
-                                        (int)customHostname->length, customHostname->data,
-                                        layer->port);
-        du.data = (UA_Byte *)discoveryUrlBuffer;
-    } else {
-        if(UA_gethostname(hostnameBuffer, 255) == 0) {
-            du.length = (size_t)UA_snprintf(discoveryUrlBuffer, 255, "ws://%s:%d/",
-                                            hostnameBuffer, layer->port);
-            du.data = (UA_Byte *)discoveryUrlBuffer;
-        } else {
-            UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK,
-                         "Could not get the hostname");
-        }
-    }
-    UA_String_copy(&du, &nl->discoveryUrl);
-
-    UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
-                "Websocket network layer listening on %.*s", (int)nl->discoveryUrl.length,
-                nl->discoveryUrl.data);
-
-    struct lws_context_creation_info info;
-    int logLevel = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
-    lws_set_log_level(logLevel, NULL);
-    memset(&info, 0, sizeof info);
-    info.port = layer->port;
-    info.protocols = protocols;
-    info.vhost_name = (char *)du.data;
-    info.ws_ping_pong_interval = 10;
-    info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE;
-    info.pvo = &pvo;
-    info.user = layer;
-
-    struct lws_context *context = lws_create_context(&info);
-    if(!context) {
-        UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK, "lws init failed");
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-    layer->context = context;
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_StatusCode
-ServerNetworkLayerWS_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
-                            UA_UInt16 timeout) {
-    ServerNetworkLayerWS *layer = (ServerNetworkLayerWS *)nl->handle;
-    layer->server = server;
-    // set timeout to zero to return immediately if nothing to do
-    lws_service(layer->context, 0);
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-ServerNetworkLayerWS_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
-    ServerNetworkLayerWS *layer = (ServerNetworkLayerWS *)nl->handle;
-    UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
-                "Shutting down the WS network layer");
-    lws_context_destroy(layer->context);
-    UA_deinitialize_architecture_network();
-}
-
-static void
-ServerNetworkLayerWS_clear(UA_ServerNetworkLayer *nl) {
-    UA_free(nl->handle);
-    UA_String_deleteMembers(&nl->discoveryUrl);
-}
-
-UA_ServerNetworkLayer
-UA_ServerNetworkLayerWS(UA_ConnectionConfig config, UA_UInt16 port, UA_Logger *logger) {
-    UA_ServerNetworkLayer nl;
-    memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
-    nl.clear = ServerNetworkLayerWS_clear;
-    nl.localConnectionConfig = config;
-    nl.start = ServerNetworkLayerWS_start;
-    nl.listen = ServerNetworkLayerWS_listen;
-    nl.stop = ServerNetworkLayerWS_stop;
-
-    ServerNetworkLayerWS *layer =
-        (ServerNetworkLayerWS *)UA_calloc(1, sizeof(ServerNetworkLayerWS));
-    if(!layer)
-        return nl;
-    nl.handle = layer;
-    layer->logger = logger;
-    layer->port = port;
-    layer->config = config;
-    return nl;
-}

+ 1 - 1
arch/posix/CMakeLists.txt

@@ -22,7 +22,7 @@ if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "posix")
           ua_architecture_append_to_library(m)
           #TODO - Error on first make run if pthread is included conditional?
           ua_architecture_append_to_library(pthread)
-          if(UA_MULTITHREADING OR UA_BUILD_UNIT_TESTS)
+          if(UA_ENABLE_MULTITHREADING OR UA_BUILD_UNIT_TESTS)
             ua_architecture_append_to_library(pthread)
           endif()
           if(NOT APPLE AND (NOT ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD"))

+ 0 - 28
arch/posix/ua_architecture.h

@@ -147,34 +147,6 @@ extern void * (*UA_globalRealloc)(void *ptr, size_t size);
     LOG; \
 }
 
-#if UA_MULTITHREADING >= 100
-#include <pthread.h>
-#define Sleep(x) sleep(x / 1000)
-#define UA_LOCK_TYPE(mutexName) pthread_mutex_t mutexName; \
-                                        pthread_mutexattr_t mutexName##_attr; \
-                                        int mutexName##Counter;
-#define UA_LOCK_INIT(mutexName) pthread_mutexattr_init(&mutexName##_attr); \
-                                        pthread_mutexattr_settype(&mutexName##_attr, PTHREAD_MUTEX_RECURSIVE); \
-                                        pthread_mutex_init(&mutexName, &mutexName##_attr); \
-                                        mutexName##Counter = 0;
-#define UA_LOCK_DESTROY(mutexName) pthread_mutex_destroy(&mutexName); \
-                                   pthread_mutexattr_destroy(&mutexName##_attr);
-
-#define UA_LOCK(mutexName) pthread_mutex_lock(&mutexName); \
-                           UA_assert(++(mutexName##Counter) == 1); \
-
-#define UA_UNLOCK(mutexName) UA_assert(--(mutexName##Counter) == 0); \
-                             pthread_mutex_unlock(&mutexName);
-#define UA_LOCK_ASSERT(mutexName, num) UA_assert(mutexName##Counter == num);
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
 #include <open62541/architecture_functions.h>
 
 #if defined(__APPLE__)  && defined(_SYS_QUEUE_H_)

+ 0 - 12
arch/vxworks/ua_architecture.h

@@ -109,18 +109,6 @@
     LOG; \
 }
 
-#if UA_MULTITHREADING >= 100
-#error Multithreading unsupported
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
 #include <open62541/architecture_functions.h>
 
 #endif /* PLUGINS_ARCH_VXWORKS_UA_ARCHITECTURE_H_ */

+ 0 - 11
arch/wec7/ua_architecture.h

@@ -137,17 +137,6 @@ char *strerror(int errnum);
 }
 #define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP
 
-#if UA_MULTITHREADING >= 100
-#error Multithreading unsupported
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#endif
-
 #include <open62541/architecture_functions.h>
 
 /* Fix redefinition of SLIST_ENTRY on mingw winnt.h */

+ 0 - 21
arch/win32/ua_architecture.h

@@ -143,27 +143,6 @@
 }
 #define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP
 
-#if UA_MULTITHREADING >= 100
-#define UA_LOCK_TYPE(mutexName) CRITICAL_SECTION mutexName; \
-                                int mutexName##Counter;
-#define UA_LOCK_INIT(mutexName) InitializeCriticalSection(&mutexName); \
-                                mutexName##Counter = 0;;
-#define UA_LOCK_DESTROY(mutexName) DeleteCriticalSection(&mutexName);
-#define UA_LOCK(mutexName) EnterCriticalSection(&mutexName); \
-                           UA_assert(++(mutexName##Counter) == 1);
-#define UA_UNLOCK(mutexName) UA_assert(--(mutexName##Counter) == 0); \
-                             LeaveCriticalSection(&mutexName);
-#define UA_LOCK_ASSERT(mutexName, num) UA_assert(mutexName##Counter == num);
-#else
-#define UA_LOCK_TYPE(mutexName)
-#define UA_LOCK_TYPE_POINTER(mutexName)
-#define UA_LOCK_INIT(mutexName)
-#define UA_LOCK_DESTROY(mutexName)
-#define UA_LOCK(mutexName)
-#define UA_UNLOCK(mutexName)
-#define UA_LOCK_ASSERT(mutexName, num)
-#endif
-
 #include <open62541/architecture_functions.h>
 
 /* Fix redefinition of SLIST_ENTRY on mingw winnt.h */

+ 10 - 1
azure-pipelines.yml

@@ -1,3 +1,12 @@
+
+trigger:
+ tags:
+   include:
+     - '*'
+ branches:
+   include:
+     - '*'
+
 jobs:
-    - template: ./.azure-pipelines/azure-pipelines-linux.yml
     - template: ./.azure-pipelines/azure-pipelines-win.yml
+    - template: ./.azure-pipelines/azure-pipelines-dist.yml

+ 58 - 8
debian/control-template

@@ -3,10 +3,15 @@ Priority: optional
 Maintainer: open62541 Team <open62541-core@googlegroups.com>
 Build-Depends: debhelper (>= 9),
  cmake (>= 2.8),
- git,
- graphviz,
  python (>= 2.7),
-Standards-Version: 4.1.2
+ python-sphinx,
+ python-sphinx-rtd-theme | base-files (<= 7.2ubuntu5.6~),
+ graphviz,
+ texlive-fonts-recommended,
+ texlive-latex-extra,
+ texlive-plain-generic | texlive-generic-extra,
+ latexmk
+Standards-Version: 4.4.1
 Section: libs
 Homepage: https://open62541.org/
 Vcs-Git: https://github.com/open62541/open62541.git
@@ -16,13 +21,58 @@ Package: libopen62541-<soname>-dev
 Section: libdevel
 Architecture: any
 Multi-Arch: same
-Depends: libopen62541-<soname> (= ${binary:Version}), ${misc:Depends}, python
-Description: Development header files for open62541
- open62541 is an open source C (C99) implementation of the OPC UA standard
+Depends: libopen62541-<soname> (= ${binary:Version}), ${misc:Depends}
+Description: Open source implementation of OPC UA - development files
+ open62541 (http://open62541.org) is an open source and free implementation
+ of OPC UA (OPC Unified Architecture) written in the common subset of the
+ C99 and C++98 languages.
+ The library is usable with all major compilers and provides the necessary
+ tools to implement dedicated OPC UA clients and servers, or to integrate
+ OPC UA-based communication into existing applications.
+ .
+ This package provides the open62541 header and development files
+
+Package: libopen62541-<soname>-tools
+Section: libdevel
+Architecture: all
+Depends: ${misc:Depends}, python
+Recommends: libopen62541-<soname>-dev
+Description: Open source implementation of OPC UA - tools
+ open62541 (http://open62541.org) is an open source and free implementation
+ of OPC UA (OPC Unified Architecture) written in the common subset of the
+ C99 and C++98 languages.
+ The library is usable with all major compilers and provides the necessary
+ tools to implement dedicated OPC UA clients and servers, or to integrate
+ OPC UA-based communication into existing applications.
+ .
+ This package provides some open62541 tools, e.g. the nodeset compiler
 
 Package: libopen62541-<soname>
 Architecture: any
 Multi-Arch: same
 Depends: ${shlibs:Depends}, ${misc:Depends}
-Description: Open source implementation of OPC UA (OPC Unified Architecture) aka IEC 62541
- open62541 is an open source C (C99) implementation of the OPC UA standard
+Description: Open source implementation of OPC UA - shared library
+ open62541 (http://open62541.org) is an open source and free implementation
+ of OPC UA (OPC Unified Architecture) written in the common subset of the
+ C99 and C++98 languages.
+ The library is usable with all major compilers and provides the necessary
+ tools to implement dedicated OPC UA clients and servers, or to integrate
+ OPC UA-based communication into existing applications.
+ .
+ This package provides the open62541 shared library
+
+Package: open62541-doc
+Section: doc
+Architecture: all
+Multi-Arch: foreign
+Depends: ${misc:Depends}, ${sphinxdoc:Depends}
+Description: Open source implementation of OPC UA - documentation
+ open62541 (http://open62541.org) is an open source and free implementation
+ of OPC UA (OPC Unified Architecture) written in the common subset of the
+ C99 and C++98 languages.
+ The library is usable with all major compilers and provides the necessary
+ tools to implement dedicated OPC UA clients and servers, or to integrate
+ OPC UA-based communication into existing applications.
+ .
+ This package provides the open62541 documentation as PDF and HTML
+ and example applications

+ 1 - 1
debian/libopen62541-dev.install-template

@@ -1,5 +1,5 @@
 usr/include
 usr/lib/*/*.so
+usr/lib/*/*.a
 usr/lib/*/cmake/open62541/*
 usr/lib/*/pkgconfig/open62541.pc
-usr/share/open62541/*

+ 9 - 0
debian/libopen62541-tools.install-template

@@ -0,0 +1,9 @@
+usr/share/open62541/tools/*.py
+usr/share/open62541/tools/certs
+usr/share/open62541/tools/nodeset_compiler
+usr/share/open62541/tools/schema
+usr/share/open62541/tools/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml
+usr/share/open62541/tools/ua-nodeset/Schema/Opc.Ua.Types.bsd
+usr/share/open62541/tools/ua-nodeset/Schema/AttributeIds.csv
+usr/share/open62541/tools/ua-nodeset/Schema/NodeIds.csv
+usr/share/open62541/tools/ua-nodeset/Schema/StatusCode.csv

+ 16 - 0
debian/open62541-doc.doc-base-template

@@ -0,0 +1,16 @@
+Document: open62541
+Title: open62541 Manual
+Author: The open62541 Team <open62541-core@googlegroups.com>
+Abstract: open62541 (http://open62541.org) is an open source 
+ and free implementation of OPC UA (OPC Unified Architecture) 
+ written in the common subset of the C99 and C++98 languages.   
+ This manual contains an introduction to the open62541 library 
+ and describes how to use it for server and client applications. 
+Section: Network/Communication
+
+Format: HTML
+Index: /usr/share/doc/open62541/open62541.html/index.html
+Files: /usr/share/doc/open62541/open62541.html/*
+
+Format: PDF
+Files: /usr/share/doc/open62541/open62541.pdf.gz

+ 2 - 0
debian/open62541-doc.install-template

@@ -0,0 +1,2 @@
+usr/share/doc/open62541
+usr/share/open62541/examples

+ 5 - 0
debian/rules-template

@@ -12,6 +12,11 @@ override_dh_auto_test:
 
 override_dh_auto_build:
 	dh_auto_build -- -j`nproc --ignore=2`
+	make -C obj-${DEB_HOST_GNU_TYPE} doc doc_pdf
+
+override_dh_install:
+	dh_install
+	dh_sphinxdoc -X_sources
 
 %:
 	dh $@ --buildsystem=cmake --parallel

+ 1 - 1
deps/mdnsd

@@ -1 +1 @@
-Subproject commit 5af316c4b79460c0c1b6c2a674a37e28a85441a3
+Subproject commit f7f0dd543f12fa7bbf2b667cceb287b9c8184b7d

File diff suppressed because it is too large
+ 0 - 1701
deps/mqtt-c/mqtt.c


File diff suppressed because it is too large
+ 0 - 1542
deps/mqtt-c/mqtt.h


+ 0 - 112
deps/mqtt-c/mqtt_pal.h

@@ -1,112 +0,0 @@
-#ifndef __MQTT_PAL_H__
-#define __MQTT_PAL_H__
-
-/**
- * Copyright (c) 2019 Kalycito Infotech Private Limited
- * @file
- * @brief Includes/supports the types/calls required by the MQTT-C client.
- * 
- * @note This is the \em only file included in mqtt.h, and mqtt.c. It is therefore 
- *       responsible for including/supporting all the required types and calls. 
- * 
- * @defgroup pal Platform abstraction layer
- * @brief Documentation of the types and calls required to port MQTT-C to a new platform.
- * 
- * mqtt_pal.h is the \em only header file included in mqtt.c. Therefore, to port MQTT-C to a 
- * new platform the following types, functions, constants, and macros must be defined in 
- * mqtt_pal.h:
- *  - Types:
- *      - \c size_t, \c ssize_t
- *      - \c uint8_t, \c uint16_t, \c uint32_t
- *      - \c va_list
- *      - \c mqtt_pal_time_t : return type of \c MQTT_PAL_TIME() 
- *      - \c mqtt_pal_mutex_t : type of the argument that is passed to \c MQTT_PAL_MUTEX_LOCK and 
- *        \c MQTT_PAL_MUTEX_RELEASE
- *  - Functions:
- *      - \c memcpy, \c strlen
- *      - \c va_start, \c va_arg, \c va_end
- *  - Constants:
- *      - \c INT_MIN
- * 
- * Additionally, three macro's are required:
- *  - \c MQTT_PAL_HTONS(s) : host-to-network endian conversion for uint16_t.
- *  - \c MQTT_PAL_NTOHS(s) : network-to-host endian conversion for uint16_t.
- *  - \c MQTT_PAL_TIME()   : returns [type: \c mqtt_pal_time_t] current time in seconds. 
- *  - \c MQTT_PAL_MUTEX_LOCK(mtx_pointer) : macro that locks the mutex pointed to by \c mtx_pointer.
- *  - \c MQTT_PAL_MUTEX_RELEASE(mtx_pointer) : macro that unlocks the mutex pointed to by 
- *    \c mtx_pointer.
- * 
- * Lastly, \ref mqtt_pal_sendall and \ref mqtt_pal_recvall, must be implemented in mqtt_pal.c 
- * for sending and receiving data using the platforms socket calls.
- */
-
-#include <open62541/types.h>
-
-/* UNIX-like platform support */
-#ifdef __unix__
-    #include <limits.h>
-    #include <string.h>
-    #include <stdarg.h>
-    #include <time.h>
-    #include <arpa/inet.h>
-    #include <pthread.h>
-
-    /*#ifdef MQTT_USE_BIO
-        #include <openssl/bio.h>
-        typedef BIO* mqtt_pal_socket_handle;
-    #else
-        typedef int mqtt_pal_socket_handle;
-    #endif*/
-#endif
-
-#ifdef __MINGW32__
-    #include <pthread.h>
-#endif
-
-
-    #define MQTT_PAL_HTONS(s) htons(s)
-    #define MQTT_PAL_NTOHS(s) ntohs(s)
-
-    #define MQTT_PAL_TIME() time(NULL)
-
-    typedef time_t mqtt_pal_time_t;
-    typedef pthread_mutex_t mqtt_pal_mutex_t;
-
-    #define MQTT_PAL_MUTEX_INIT(mtx_ptr) pthread_mutex_init(mtx_ptr, NULL)
-    #define MQTT_PAL_MUTEX_LOCK(mtx_ptr) pthread_mutex_lock(mtx_ptr)
-    #define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) pthread_mutex_unlock(mtx_ptr)
-
-    struct my_custom_socket_handle {
-        void* client;
-        void* connection;
-        uint16_t timeout;
-    };
-    
-    typedef struct my_custom_socket_handle* mqtt_pal_socket_handle;
-/**
- * @brief Sends all the bytes in a buffer.
- * @ingroup pal
- * 
- * @param[in] fd The file-descriptor (or handle) of the socket.
- * @param[in] buf A pointer to the first byte in the buffer to send.
- * @param[in] len The number of bytes to send (starting at \p buf).
- * @param[in] flags Flags which are passed to the underlying socket.
- * 
- * @returns The number of bytes sent if successful, an \ref MQTTErrors otherwise.
- */
-ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void* buf, size_t len, int flags);
-
-/**
- * @brief Non-blocking receive all the byte available.
- * @ingroup pal
- * 
- * @param[in] fd The file-descriptor (or handle) of the socket.
- * @param[in] buf A pointer to the receive buffer.
- * @param[in] bufsz The max number of bytes that can be put into \p buf.
- * @param[in] flags Flags which are passed to the underlying socket.
- * 
- * @returns The number of bytes received if successful, an \ref MQTTErrors otherwise.
- */
-ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void* buf, size_t bufsz, int flags);
-
-#endif /* __MQTT_PAL_H__ */

+ 19 - 0
doc/CMakeLists.txt

@@ -86,3 +86,22 @@ add_dependencies(doc open62541)
 
 set_target_properties(doc doc_latex doc_pdf PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE)
 set_target_properties(doc doc_latex doc_pdf PROPERTIES FOLDER "open62541/doc")
+
+if (UA_PACK_DEBIAN)
+    set(open62541_install_debdoc_html_dir share/doc/open62541/open62541.html)
+    set(open62541_install_debdoc_dir share/doc/open62541)
+
+    set(open62541_debdoc_pdf_files "${DOC_LATEX_DIR}/open62541.pdf")
+
+    install(DIRECTORY ${DOC_HTML_DIR}/
+        COMPONENT htmldoc 
+        DESTINATION ${open62541_install_debdoc_dir}/open62541.html 
+        USE_SOURCE_PERMISSIONS
+        FILES_MATCHING 
+        PATTERN "*.*"
+        PATTERN "_sources" EXCLUDE
+        PATTERN "CMakeFiles" EXCLUDE
+        PATTERN "cmake_install.cmake" EXCLUDE
+        )
+    install(FILES ${open62541_debdoc_pdf_files} COMPONENT pdfdoc DESTINATION ${open62541_install_debdoc_dir})
+endif()

+ 86 - 19
doc/building.rst

@@ -111,6 +111,79 @@ The procedure below works on OpenBSD 5.8 with gcc version 4.8.4, cmake version 3
    cmake ..
    make
 
+Building Debian Packages inside Docker Container with CMake on Ubuntu or Debian
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Here is an example howto build the library as Debian package inside a Docker container
+
+- Download and install
+
+  - Docker Engine: https://docs.docker.com/install/linux/docker-ce/debian/
+  - docker-deb-builder: https://github.com/tsaarni/docker-deb-builder.git
+  - open62541: https://github.com/open62541/open62541.git
+
+Install Docker as described at https://docs.docker.com/install/linux/docker-ce/debian/ .
+
+Get the docker-deb-builder utility from github and make Docker images for the needed
+Debian and/or Ubuntu relases
+
+.. code-block:: bash
+
+   # make and goto local development path (e.g. ~/development)
+   mkdir ~/development
+   cd ~/development
+
+   # clone docker-deb-builder utility from github and change into builder directory
+   git clone https://github.com/tsaarni/docker-deb-builder.git
+   cd docker-deb-builder
+
+   # make Docker builder images (e.g. Ubuntu 18.04 and 17.04)
+   docker build -t docker-deb-builder:18.04 -f Dockerfile-ubuntu-18.04 .
+   docker build -t docker-deb-builder:17.04 -f Dockerfile-ubuntu-17.04 .
+
+Make a local copy of the open62541 git repo and checkout a pack branch
+
+.. code-block:: bash
+
+   # make a local copy of the open62541 git repo (e.g. in the home directory) 
+   # and checkout a pack branch (e.g. pack/1.0)
+   cd ~
+   git clone https://github.com/open62541/open62541.git
+   cd ~/open62541
+   git checkout pack/1.0
+
+Now it's all set to build Debian/Ubuntu open62541 packages
+
+.. code-block:: bash
+
+   # goto local developmet path
+   cd ~/development
+   
+   # make a local output directory for the builder where the packages can be placed after build
+   mkdir output
+   
+   # build Debian/Ubuntu packages inside Docker container (e.g. Ubuntu-18.04)
+   ./build -i docker-deb-builder:18.04 -o output ~/open62541
+
+After a successfull build the Debian/Ubuntu packages can be found at :file:`~/development/docker-deb-builder/output`
+
+CMake Build Options and Debian Packaging
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If the open62541 library will be build as a Debian package using a pack branch (e.g. pack/master or pack/1.0)
+then altering or adding CMake build options should be done inside the :file:`debian/rules` file respectively in
+the :file:`debian/rules-template` file if working with a development branch (e.g. master or 1.0).
+
+The section in :file:`debian/rules` where the CMake build options are defined is 
+
+.. code-block:: bash
+
+   ...
+   override_dh_auto_configure:
+       dh_auto_configure -- -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUA_NAMESPACE_ZERO=FULL -DUA_ENABLE_AMALGAMATION=OFF -DUA_PACK_DEBIAN=ON
+   ...
+
+This CMake build options will be passed as command line variables to CMake during Debian packaging.
 
 .. _build_options:
 
@@ -139,22 +212,12 @@ Main Build Options
    The SDK logs events of the level defined in ``UA_LOGLEVEL`` and above only.
    The logging event levels are as follows:
 
-   - 600: Fatal
-   - 500: Error
-   - 400: Warning
-   - 300: Info
-   - 200: Debug
-   - 100: Trace
-
-**UA_MULTITHREADING**
-   Level of multi-threading support. The supported levels are currently as follows:
-
-  - 0-199: Multithreading support disabled.
-  - 100-199: API functions marked with the UA_THREADSAFE-macro are protected internally with mutexes.
-    Multiple threads are allowed to call these functions of the SDK at the same time without causing race conditions.
-    Furthermore, this level support the handling of asynchronous method calls from external worker threads.
-  - >=200: Work is distributed to a number of internal worker threads. Those worker threads are created within the SDK.
-    (EXPERIMENTAL FEATURE! Expect bugs.)
+     - 600: Fatal
+     - 500: Error
+     - 400: Warning
+     - 300: Info
+     - 200: Debug
+     - 100: Trace
 
 Select build artefacts
 ^^^^^^^^^^^^^^^^^^^^^^
@@ -190,12 +253,16 @@ Detailed SDK Features
 **UA_ENABLE_AMALGAMATION**
    Compile a single-file release into the files :file:`open62541.c` and :file:`open62541.h`. Not recommended for installation.
 
+**UA_ENABLE_MULTITHREADING (EXPERIMENTAL)**
+   Enable multi-threading support. Work is distributed to a number of worker threads.
+   This is a new feature and currently marked as EXPERIMENTAL.
+
 **UA_ENABLE_IMMUTABLE_NODES**
    Nodes in the information model are not edited but copied and replaced. The
    replacement is done with atomic operations so that the information model is
    always consistent and can be accessed from an interrupt or parallel thread
    (depends on the node storage plugin implementation). This feature is a
-   prerequisite for ``UA_MULTITHREADING``.
+   prerequisite for ``UA_ENABLE_MULTITHREADING``.
 
 **UA_ENABLE_COVERAGE**
    Measure the coverage of unit tests
@@ -223,7 +290,7 @@ Detailed SDK Features
 Some options are marked as advanced. The advanced options need to be toggled to
 be visible in the cmake GUIs.
 
-**UA_ENABLE_TYPEDESCRIPTION**
+**UA_ENABLE_TYPENAMES**
    Add the type and member names to the UA_DataType structure. Enabled by default.
 
 **UA_ENABLE_STATUSCODE_DESCRIPTIONS**
@@ -278,7 +345,7 @@ communication.
 Last, logging messages take up a lot of space in the binary and might not be
 needed in embedded scenarios. Setting ``UA_LOGLEVEL`` to a value above 600
 (``FATAL``) disables all logging. In addition, the feature-flags
-``UA_ENABLE_TYPEDESCRIPTION`` and ``UA_ENABLE_STATUSCODE_DESCRIPTIONS`` add static
+``UA_ENABLE_TYPENAMES`` and ``UA_ENABLE_STATUSCODE_DESCRIPTIONS`` add static
 information to the binary that is only used for human-readable logging and
 debugging.
 

+ 0 - 19
docker/README.md

@@ -1,19 +0,0 @@
-# open62541 Docker Build
-
-Official docker container builds are available on [Docker Cloud](https://cloud.docker.com/u/open62541/repository/registry-1.docker.io/open62541/open62541)
-
-The container includes the source code itself under `/opt/open62541` and prebuilt examples in `/opt/open62541/build/bin/examples/`.
-
-You can use this container as a basis for your own application. 
-
-Just starting the docker container will start the `server_ctt` example.
-
-## Build locally
-
-To build the container locally use:
-
-```bash
-git clone https://github.com/open62541/open62541
-cd open62541
-docker build -f docker/Dockerfile .
-```

+ 0 - 17
examples/CMakeLists.txt

@@ -87,9 +87,6 @@ add_example(tutorial_server_object tutorial_server_object.c)
 
 if(UA_ENABLE_METHODCALLS)
     add_example(tutorial_server_method tutorial_server_method.c)
-    if (UA_MULTITHREADING EQUAL 100)
-        add_example(tutorial_server_method_async tutorial_server_method_async.c)
-    endif()
 endif()
 
 add_example(tutorial_client_firststeps tutorial_client_firststeps.c)
@@ -128,12 +125,6 @@ install(PROGRAMS $<TARGET_FILE:client>
 
 add_example(client_async client_async.c)
 
-if(UA_ENABLE_METHODCALLS)
-    if (UA_MULTITHREADING EQUAL 100)
-        add_example(client_method_async client_method_async.c)
-    endif()
-endif()
-
 add_example(client_connect_loop client_connect_loop.c)
 
 add_example(client_connectivitycheck_loop client_connectivitycheck_loop.c)
@@ -192,18 +183,10 @@ add_subdirectory(nodeset)
 if(UA_ENABLE_PUBSUB)
     add_example(tutorial_pubsub_connection pubsub/tutorial_pubsub_connection.c)
     add_example(tutorial_pubsub_publish pubsub/tutorial_pubsub_publish.c)
-	add_example(server_pubsub_publisher_iop pubsub/server_pubsub_publisher_iop.c)
-	add_example(server_pubsub_publish_rt_level pubsub/server_pubsub_publisher_rt_level.c)
     if(UA_ENABLE_AMALGAMATION)
         message(WARNING "PubSub subscriber tutorial (preview) can not be used with AMALGAMATION. Skipping tutorial_pubsub_subscribe.")
     else(NOT UA_ENABLE_AMALGAMATION)
         add_example(tutorial_pubsub_subscribe pubsub/tutorial_pubsub_subscribe.c)
         add_example(pubsub_subscribe_standalone pubsub/pubsub_subscribe_standalone.c)
     endif()
-    if(UA_ENABLE_PUBSUB_MQTT)
-        if(NOT WIN32)
-            include_directories(${PROJECT_SOURCE_DIR}/../plugins)
-            add_example(tutorial_pubsub_mqtt_publish pubsub/tutorial_pubsub_mqtt_publish.c)
-        endif()
-    endif()
 endif()

+ 1 - 1
examples/access_control/server_access_control.c

@@ -61,7 +61,7 @@ int main(void) {
     UA_ServerConfig_setDefault(config);
 
     /* Disable anonymous logins, enable two user/password logins */
-    config->accessControl.clear(&config->accessControl);
+    config->accessControl.deleteMembers(&config->accessControl);
     UA_StatusCode retval = UA_AccessControl_default(config, false,
              &config->securityPolicies[config->securityPoliciesSize-1].policyUri, 2, logins);
     if(retval != UA_STATUSCODE_GOOD)

+ 2 - 2
examples/client_connect.c

@@ -102,8 +102,8 @@ int main(int argc, char *argv[]) {
         UA_ByteString privateKey  = loadFile(keyfile);
         UA_ClientConfig_setDefaultEncryption(cc, certificate, privateKey,
                                              NULL, 0, NULL, 0);
-        UA_ByteString_clear(&certificate);
-        UA_ByteString_clear(&privateKey);
+        UA_ByteString_deleteMembers(&certificate);
+        UA_ByteString_deleteMembers(&privateKey);
     } else {
         UA_ClientConfig_setDefault(cc);
     }

+ 0 - 270
examples/client_method_async.c

@@ -1,270 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
-
-#include <open62541/client_config_default.h>
-#include <open62541/client_highlevel_async.h>
-#include <open62541/client_subscriptions.h>
-#include <open62541/plugin/log_stdout.h>
-#include <open62541/server_config_default.h>
-#include <open62541/client_subscriptions.h>
-
-#include <stdlib.h>
-#include <signal.h>
-
-UA_Boolean running = true;
-static void InitCallMulti(UA_Client* client);
-
-#ifdef UA_ENABLE_METHODCALLS
-
-static void
-methodCalled(UA_Client *client, void *userdata, UA_UInt32 requestId,
-    UA_CallResponse *response) {
-    UA_UInt32 i;
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** CallRequest Response - Req:%u with %u results",
-        requestId, (UA_UInt32)response->resultsSize);
-    UA_StatusCode retval = response->responseHeader.serviceResult;
-    if (retval == UA_STATUSCODE_GOOD) {
-        for (i = 0; i < response->resultsSize; i++) {
-            if (response->resultsSize >= i)
-                retval = response->results[i].statusCode;
-            else
-                retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
-            if (retval != UA_STATUSCODE_GOOD) {
-                UA_CallResponse_clear(response);
-                UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** CallRequest Response - Req: %u (%u) failed", requestId,i);
-                if (i == response->resultsSize)
-                    return;
-                else
-                    continue;
-            }
-
-            /* Move the output arguments */
-            UA_Variant *output = response->results[i].outputArguments;
-            size_t outputSize = response->results[i].outputArgumentsSize;
-            response->results[i].outputArguments = NULL;
-            response->results[i].outputArgumentsSize = 0;
-
-            if (retval == UA_STATUSCODE_GOOD) {
-                printf("---Method call was successful, returned %lu values.\n",
-                    (unsigned long)outputSize);
-                UA_Array_delete(output, outputSize, &UA_TYPES[UA_TYPES_VARIANT]);
-            }
-            else {
-                printf("---Method call was unsuccessful, returned %x values.\n",
-                    retval);
-            }
-        }
-    }
-    else
-    {
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** CallRequest Response - Req:%u FAILED", requestId);
-    }
-    UA_CallResponse_clear(response);
-    
-    /* We initiate the MultiCall (2 methods within one CallRequest) */
-    InitCallMulti(client);
-}
-
-#ifdef UA_ENABLE_METHODCALLS
-/* Workaround because we do not have an API for that yet */
-
-static UA_StatusCode
-UA_Client_call_asyncMulti(UA_Client *client,
-    const UA_NodeId objectId1, const UA_NodeId methodId1, size_t inputSize1, const UA_Variant *input1,
-    const UA_NodeId objectId2, const UA_NodeId methodId2, size_t inputSize2, const UA_Variant *input2,
-    UA_ClientAsyncServiceCallback callback, void *userdata, UA_UInt32 *reqId) {
-    UA_CallRequest request;
-    UA_CallRequest_init(&request);
-    UA_CallMethodRequest item[2];
-    UA_CallMethodRequest_init(&item[0]);
-    item[0].methodId = methodId1;
-    item[0].objectId = objectId1;
-    item[0].inputArguments = (UA_Variant *)(void*)(uintptr_t)input1; // cast const...
-    item[0].inputArgumentsSize = inputSize1;
-
-    UA_CallMethodRequest_init(&item[1]);
-    item[1].methodId = methodId2;
-    item[1].objectId = objectId2;
-    item[1].inputArguments = (UA_Variant *)(void*)(uintptr_t)input2; // cast const...
-    item[1].inputArgumentsSize = inputSize2;
-
-    request.methodsToCall = &item[0];
-    request.methodsToCallSize = 2;
-
-    return __UA_Client_AsyncService(client, &request,
-        &UA_TYPES[UA_TYPES_CALLREQUEST], callback,
-        &UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, reqId);
-}
-/* End Workaround */
-
-static void InitCallMulti(UA_Client* client) {
-    UA_UInt32 reqId = 0;
-    UA_Variant input;
-    UA_Variant_init(&input);
-    UA_String stringValue = UA_String_fromChars("World 3 (multi)");
-    UA_Variant_setScalar(&input, &stringValue, &UA_TYPES[UA_TYPES_STRING]);
-
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** Initiating CallRequest 3");
-    UA_Client_call_asyncMulti(client,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-        UA_NODEID_NUMERIC(1, 62542), 1, &input,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-        UA_NODEID_NUMERIC(1, 62541), 1, &input,
-        (UA_ClientAsyncServiceCallback)methodCalled, NULL, &reqId);
-    UA_String_clear(&stringValue);
-}
-#endif
-#endif /* UA_ENABLE_METHODCALLS */
-
-static void stopHandler(int sign) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Received Ctrl-C");
-    running = 0;
-}
-
-static void
-handler_currentTimeChanged(UA_Client *client, UA_UInt32 subId, void *subContext,
-    UA_UInt32 monId, void *monContext, UA_DataValue *value) {
-    //UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "currentTime has changed!");
-    if (UA_Variant_hasScalarType(&value->value, &UA_TYPES[UA_TYPES_DATETIME])) {
-        UA_DateTime raw_date = *(UA_DateTime *)value->value.data;
-        UA_DateTimeStruct dts = UA_DateTime_toStruct(raw_date);
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-            "date is: %02u-%02u-%04u %02u:%02u:%02u.%03u",
-            dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec);
-    }
-}
-
-static void
-deleteSubscriptionCallback(UA_Client *client, UA_UInt32 subscriptionId, void *subscriptionContext) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-        "Subscription Id %u was deleted", subscriptionId);
-}
-
-static void
-subscriptionInactivityCallback(UA_Client *client, UA_UInt32 subId, void *subContext) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Inactivity for subscription %u", subId);
-}
-
-static void
-stateCallback(UA_Client *client, UA_ClientState clientState) {
-    switch (clientState) {
-    case UA_CLIENTSTATE_DISCONNECTED:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "The client is disconnected");
-        break;
-    case UA_CLIENTSTATE_WAITING_FOR_ACK:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Waiting for ack");
-        break;
-    case UA_CLIENTSTATE_CONNECTED:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-            "A TCP connection to the server is open");
-        break;
-    case UA_CLIENTSTATE_SECURECHANNEL:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-            "A SecureChannel to the server is open");
-        break;
-    case UA_CLIENTSTATE_SESSION: {
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "A session with the server is open");
-        /* A new session was created. We need to create the subscription. */
-        /* Create a subscription */
-        UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
-        UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
-            NULL, NULL, deleteSubscriptionCallback);
-
-        if (response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                "Create subscription succeeded, id %u", response.subscriptionId);
-        else
-            return;
-
-        /* Add a MonitoredItem */
-        UA_MonitoredItemCreateRequest monRequest =
-            UA_MonitoredItemCreateRequest_default(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME));
-
-        UA_MonitoredItemCreateResult monResponse =
-            UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId,
-                UA_TIMESTAMPSTORETURN_BOTH,
-                monRequest, NULL, handler_currentTimeChanged, NULL);
-        if (monResponse.statusCode == UA_STATUSCODE_GOOD)
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                "Monitoring UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME', id %u",
-                monResponse.monitoredItemId);
-
-        //TODO: check the existance of the nodes inside these functions (otherwise seg faults)
-#ifdef UA_ENABLE_METHODCALLS		
-        UA_UInt32 reqId = 0;
-        UA_Variant input;
-        UA_Variant_init(&input);
-        UA_String stringValue = UA_String_fromChars("World 1");
-        UA_Variant_setScalar(&input, &stringValue, &UA_TYPES[UA_TYPES_STRING]);
-
-        /* Initiate Call 1 */
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** Initiating CallRequest 1");
-        UA_Client_call_async(client,
-            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-            UA_NODEID_NUMERIC(1, 62541), 1, &input,
-            methodCalled, NULL, &reqId);
-        UA_String_clear(&stringValue);
-
-        /* Initiate Call 2 */
-        UA_Variant_init(&input);
-        stringValue = UA_String_fromChars("World 2");
-        UA_Variant_setScalar(&input, &stringValue, &UA_TYPES[UA_TYPES_STRING]);
-
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "**** Initiating CallRequest 2");
-        UA_Client_call_async(client,
-            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-            UA_NODEID_NUMERIC(1, 62542), 1, &input,
-            methodCalled, NULL, &reqId);
-        UA_String_clear(&stringValue);
-
-#endif /* UA_ENABLE_METHODCALLS */
-    }
-    break;
-    case UA_CLIENTSTATE_SESSION_RENEWED:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-            "A session with the server is open (renewed)");
-        /* The session was renewed. We don't need to recreate the subscription. */
-        break;
-    case UA_CLIENTSTATE_SESSION_DISCONNECTED:
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Session disconnected");
-        break;
-    }
-    return;
-}
-
-int
-main(int argc, char *argv[]) {
-    signal(SIGINT, stopHandler); /* catches ctrl-c */
-
-    UA_Client *client = UA_Client_new();
-    UA_ClientConfig *cc = UA_Client_getConfig(client);
-    UA_ClientConfig_setDefault(cc);
-    /* we use a high timeout because there may be other client and
-    * processing may take long if many method calls are waiting */
-    cc->timeout = 60000;
-
-    /* Set stateCallback */
-    cc->stateCallback = stateCallback;
-    cc->subscriptionInactivityCallback = subscriptionInactivityCallback;
-
-    UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
-    if(retval != UA_STATUSCODE_GOOD) {
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                     "Not connected. Retrying to connect in 1 second");
-        UA_Client_delete(client);
-        return EXIT_SUCCESS;
-    }
-
-    /* Endless loop runAsync */
-    while (running) {
-        UA_Client_run_iterate(client, 100);
-    }
-
-    /* Clean up */
-    /* Async disconnect kills unprocessed requests */
-    // UA_Client_disconnect_async (client, &reqId); //can only be used when connected = true
-    // UA_Client_run_iterate (client, &timedOut);
-    UA_Client_disconnect(client);
-    UA_Client_delete(client);
-    return EXIT_SUCCESS;
-}

+ 2 - 2
examples/nodeset/CMakeLists.txt

@@ -20,10 +20,10 @@ if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
     ua_generate_nodeset_and_datatypes(
         NAME "example"
         FILE_NS "${FILE_NS_DIRPREFIX}/server_nodeset.xml"
-        DEPENDS "${CMAKE_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Reduced.xml"
+        DEPENDS "${CMAKE_SOURCE_DIR}/tools/schema/Opc.Ua.NodeSet2.Minimal.xml"
     )
 else()
-    # standalone examples build expects already installed Opc.Ua.NodeSet2.Reduced.xml
+    # standalone examples build expects already installed Opc.Ua.NodeSet2.Minimal.xml
     ua_generate_nodeset_and_datatypes(
         NAME "example"
         FILE_NS "${FILE_NS_DIRPREFIX}/server_nodeset.xml"

+ 0 - 4
examples/pubsub/pubsub_subscribe_standalone.c

@@ -85,10 +85,6 @@ subscriberListen(UA_PubSubChannel *psc) {
                 UA_Byte value = *(UA_Byte *)dsm->data.keyFrameData.dataSetFields[i].value.data;
                 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                             "Message content: [Byte] \tReceived data: %i", value);
-            } else if (currentType == &UA_TYPES[UA_TYPES_UINT32]) {
-                UA_UInt32 value = *(UA_UInt32 *)dsm->data.keyFrameData.dataSetFields[i].value.data;
-                UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                            "Message content: [UInt32] \tReceived data: %u", value);
             } else if (currentType == &UA_TYPES[UA_TYPES_DATETIME]) {
                 UA_DateTime value = *(UA_DateTime *)dsm->data.keyFrameData.dataSetFields[i].value.data;
                 UA_DateTimeStruct receivedTime = UA_DateTime_toStruct(value);

+ 0 - 851
examples/pubsub/server_pubsub_publisher_iop.c

@@ -1,851 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
-
-#include <open62541/plugin/log_stdout.h>
-#include <open62541/plugin/pubsub_udp.h>
-#ifdef UA_ENABLE_PUBSUB_ETH_UADP
-#include <open62541/plugin/pubsub_ethernet.h>
-#endif
-#include <open62541/server.h>
-#include <open62541/server_config_default.h>
-
-#include <signal.h>
-#include <stdlib.h>
-
-#define Publisher_ID 60
-
-static void addPublisher1(UA_Server *server, UA_NodeId publishedDataSetId);
-static void addPublisher2(UA_Server *server, UA_NodeId publishedDataSetId);
-
-static UA_NodeId ds1BoolToggleId;
-static int ds1BoolToggleCount = 0;
-static UA_Boolean ds1BoolToggleVal = false;
-static UA_NodeId ds1Int32Id;
-static UA_Int32 ds1Int32Val = 0;
-static UA_NodeId ds1Int32FastId;
-static UA_Int32 ds1Int32FastVal = 0;
-static UA_NodeId ds1DateTimeId;
-
-static UA_NodeId ds2BoolToggleId;
-static UA_Boolean ds2BoolToggleVal = false;
-static UA_NodeId ds2ByteId;
-static UA_Byte ds2ByteVal = 0;
-static UA_NodeId ds2Int16Id;
-static UA_Int16 ds2Int16Val = 0;
-static UA_NodeId ds2Int32Id;
-static UA_Int32 ds2Int32Val = 0;
-static UA_NodeId ds2Int64Id;
-static UA_Int64 ds2Int64Val = 0;
-static UA_NodeId ds2SByteId;
-static UA_SByte ds2SByteVal = 0;
-static UA_NodeId ds2UInt16Id;
-static UA_UInt16 ds2UInt16Val = 0;
-static UA_NodeId ds2UInt32Id;
-static UA_UInt32 ds2UInt32Val = 0;
-static UA_NodeId ds2UInt64Id;
-static UA_UInt64 ds2UInt64Val = 0;
-static UA_NodeId ds2FloatId;
-static UA_Float ds2FloatVal = 0;
-static UA_NodeId ds2DoubleId;
-static UA_Double ds2DoubleVal = 0;
-static UA_String *ds2StringArray = NULL;
-static size_t ds2StringArrayLen = 0;
-static size_t ds2StringIndex = 0;
-static UA_NodeId ds2StringId;
-static UA_NodeId ds2ByteStringId;
-static UA_NodeId ds2GuidId;
-static UA_NodeId ds2DateTimeId;
-static UA_NodeId ds2UInt32ArrId;
-static UA_UInt32 ds2UInt32ArrValue[10] = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
-
-UA_NodeId connectionIdent;
-
-void
-timerCallback(UA_Server *server, void *data);
-
-static void
-addPubSubConnection(UA_Server *server, UA_String *transportProfile,
-    UA_NetworkAddressUrlDataType *networkAddressUrl) {
-    /* Details about the connection configuration and handling are located
-    * in the pubsub connection tutorial */
-    UA_PubSubConnectionConfig connectionConfig;
-    memset(&connectionConfig, 0, sizeof(connectionConfig));
-    connectionConfig.name = UA_STRING("UADP Connection 1");
-    connectionConfig.transportProfileUri = *transportProfile;
-    connectionConfig.enabled = UA_TRUE;
-    UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
-        &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
-    connectionConfig.publisherId.numeric = Publisher_ID;
-    UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
-}
-
-static void addPublisher1(UA_Server *server, UA_NodeId publishedDataSetId) {
-    UA_NodeId folderId;
-    UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
-    oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Publisher 1");
-    UA_Server_addObjectNode(server, UA_NODEID_NULL,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-        UA_QUALIFIEDNAME(1, "Publisher 1"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
-        oAttr, NULL, &folderId);
-
-    UA_NodeId_init(&ds1BoolToggleId);
-    UA_VariableAttributes boolToggleAttr = UA_VariableAttributes_default;
-    boolToggleAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_BOOLEAN].typeId, &boolToggleAttr.dataType);
-    UA_Variant_setScalar(&boolToggleAttr.value, &ds1BoolToggleVal, &UA_TYPES[UA_TYPES_BOOLEAN]);
-    boolToggleAttr.displayName = UA_LOCALIZEDTEXT("en-US", "BoolToggle");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher1.BoolToggle"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "BoolToggle"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), boolToggleAttr, NULL, &ds1BoolToggleId);
-
-    UA_NodeId_init(&ds1Int32Id);
-    UA_VariableAttributes int32Attr = UA_VariableAttributes_default;
-    int32Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT32].typeId, &int32Attr.dataType);
-    int32Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&int32Attr.value, &ds1Int32Val, &UA_TYPES[UA_TYPES_INT32]);
-    int32Attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int32");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher1.Int32"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Int32"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), int32Attr, NULL, &ds1Int32Id);
-
-    UA_NodeId_init(&ds1Int32FastId);
-    UA_VariableAttributes int32FastAttr = UA_VariableAttributes_default;
-    int32FastAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT32].typeId, &int32FastAttr.dataType);
-    int32FastAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&int32FastAttr.value, &ds1Int32FastVal, &UA_TYPES[UA_TYPES_INT32]);
-    int32FastAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Int32Fast");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher1.Int32Fast"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Int32Fast"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), int32FastAttr, NULL, &ds1Int32FastId);
-
-    UA_NodeId_init(&ds1DateTimeId);
-    UA_VariableAttributes dateTimeAttr = UA_VariableAttributes_default;
-    dateTimeAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_DATETIME].typeId, &dateTimeAttr.dataType);
-    dateTimeAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_DateTime dateTimeVal = UA_DateTime_now();
-    UA_Variant_setScalar(&dateTimeAttr.value, &dateTimeVal, &UA_TYPES[UA_TYPES_DATETIME]);
-    dateTimeAttr.displayName = UA_LOCALIZEDTEXT("en-US", "DateTime");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher1.DateTime"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "DateTime"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), dateTimeAttr, NULL, &ds1DateTimeId);
-
-    if (!UA_NodeId_equal(&publishedDataSetId, &UA_NODEID_NULL))
-    {
-        // Create and add fields to the PublishedDataSet
-        UA_DataSetFieldConfig boolToggleConfig;
-        memset(&boolToggleConfig, 0, sizeof(UA_DataSetFieldConfig));
-        boolToggleConfig.field.variable.fieldNameAlias = UA_STRING("BoolToggle");
-        boolToggleConfig.field.variable.promotedField = false;
-        boolToggleConfig.field.variable.publishParameters.publishedVariable = ds1BoolToggleId;
-        boolToggleConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig int32Config;
-        memset(&int32Config, 0, sizeof(UA_DataSetFieldConfig));
-        int32Config.field.variable.fieldNameAlias = UA_STRING("Int32");
-        int32Config.field.variable.promotedField = false;
-        int32Config.field.variable.publishParameters.publishedVariable = ds1Int32Id;
-        int32Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig int32FastConfig;
-        memset(&int32FastConfig, 0, sizeof(UA_DataSetFieldConfig));
-        int32FastConfig.field.variable.fieldNameAlias = UA_STRING("Int32Fast");
-        int32FastConfig.field.variable.promotedField = false;
-        int32FastConfig.field.variable.publishParameters.publishedVariable = ds1Int32FastId;
-        int32FastConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig dateTimeConfig;
-        memset(&dateTimeConfig, 0, sizeof(UA_DataSetFieldConfig));
-        dateTimeConfig.field.variable.fieldNameAlias = UA_STRING("DateTime");
-        dateTimeConfig.field.variable.promotedField = false;
-        dateTimeConfig.field.variable.publishParameters.publishedVariable = ds1DateTimeId;
-        dateTimeConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_NodeId f1, f2, f3, f4;
-        // add fields in reverse order, because all fields are added to the beginning of the list
-        UA_Server_addDataSetField(server, publishedDataSetId, &dateTimeConfig, &f4);
-        UA_Server_addDataSetField(server, publishedDataSetId, &int32FastConfig, &f3);
-        UA_Server_addDataSetField(server, publishedDataSetId, &int32Config, &f2);
-        UA_Server_addDataSetField(server, publishedDataSetId, &boolToggleConfig, &f1);
-    }
-}
-
-static void addPublisher2(UA_Server *server, UA_NodeId publishedDataSetId) {
-    UA_NodeId folderId;
-    UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
-    oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Publisher 2");
-    UA_Server_addObjectNode(server, UA_NODEID_NULL,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-        UA_QUALIFIEDNAME(1, "Publisher 2"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
-        oAttr, NULL, &folderId);
-
-    UA_NodeId_init(&ds2BoolToggleId);
-    UA_VariableAttributes boolToggleAttr = UA_VariableAttributes_default;
-    boolToggleAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_BOOLEAN].typeId, &boolToggleAttr.dataType);
-    UA_Variant_setScalar(&boolToggleAttr.value, &ds2BoolToggleVal, &UA_TYPES[UA_TYPES_BOOLEAN]);
-    boolToggleAttr.displayName = UA_LOCALIZEDTEXT("en-US", "BoolToggle");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.BoolToggle"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "BoolToggle"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), boolToggleAttr, NULL, &ds2BoolToggleId);
-
-    UA_NodeId_init(&ds2ByteId);
-    UA_VariableAttributes byteAttr = UA_VariableAttributes_default;
-    byteAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_BYTE].typeId, &byteAttr.dataType);
-    byteAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&byteAttr.value, &ds2ByteVal, &UA_TYPES[UA_TYPES_BYTE]);
-    byteAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Byte");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Byte"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Byte"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), byteAttr, NULL, &ds2ByteId);
-
-    UA_NodeId_init(&ds2Int16Id);
-    UA_VariableAttributes int16Attr = UA_VariableAttributes_default;
-    int16Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT16].typeId, &int16Attr.dataType);
-    int16Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&int16Attr.value, &ds2Int16Val, &UA_TYPES[UA_TYPES_INT16]);
-    int16Attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int16");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Int16"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Int16"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), int16Attr, NULL, &ds2Int16Id);
-
-    UA_NodeId_init(&ds2Int32Id);
-    UA_VariableAttributes int32Attr = UA_VariableAttributes_default;
-    int32Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT32].typeId, &int32Attr.dataType);
-    int32Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&int32Attr.value, &ds2Int32Val, &UA_TYPES[UA_TYPES_INT32]);
-    int32Attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int32");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Int32"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Int32"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), int32Attr, NULL, &ds2Int32Id);
-
-    UA_NodeId_init(&ds2Int64Id);
-    UA_VariableAttributes int64Attr = UA_VariableAttributes_default;
-    int64Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT64].typeId, &int64Attr.dataType);
-    int64Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&int64Attr.value, &ds2Int64Val, &UA_TYPES[UA_TYPES_INT64]);
-    int64Attr.displayName = UA_LOCALIZEDTEXT("en-US", "Int64");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Int64"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Int64"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), int64Attr, NULL, &ds2Int64Id);
-
-    UA_NodeId_init(&ds2SByteId);
-    UA_VariableAttributes sbyteAttr = UA_VariableAttributes_default;
-    sbyteAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_SBYTE].typeId, &sbyteAttr.dataType);
-    sbyteAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&sbyteAttr.value, &ds2SByteVal, &UA_TYPES[UA_TYPES_SBYTE]);
-    sbyteAttr.displayName = UA_LOCALIZEDTEXT("en-US", "SByte");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.SByte"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "SByte"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), sbyteAttr, NULL, &ds2SByteId);
-
-    UA_NodeId_init(&ds2UInt16Id);
-    UA_VariableAttributes uint16Attr = UA_VariableAttributes_default;
-    uint16Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_UINT16].typeId, &uint16Attr.dataType);
-    uint16Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&uint16Attr.value, &ds2UInt16Val, &UA_TYPES[UA_TYPES_UINT16]);
-    uint16Attr.displayName = UA_LOCALIZEDTEXT("en-US", "UInt16");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.UInt16"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "UInt16"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), uint16Attr, NULL, &ds2UInt16Id);
-
-    UA_NodeId_init(&ds2UInt32Id);
-    UA_VariableAttributes uint32Attr = UA_VariableAttributes_default;
-    uint32Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_UINT32].typeId, &uint32Attr.dataType);
-    uint32Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&uint32Attr.value, &ds2UInt32Val, &UA_TYPES[UA_TYPES_UINT32]);
-    uint32Attr.displayName = UA_LOCALIZEDTEXT("en-US", "UInt32");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.UInt32"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "UInt32"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), uint32Attr, NULL, &ds2UInt32Id);
-
-    UA_NodeId_init(&ds2UInt64Id);
-    UA_VariableAttributes uint64Attr = UA_VariableAttributes_default;
-    uint64Attr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_UINT64].typeId, &uint64Attr.dataType);
-    uint64Attr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&uint64Attr.value, &ds2UInt64Val, &UA_TYPES[UA_TYPES_UINT64]);
-    uint64Attr.displayName = UA_LOCALIZEDTEXT("en-US", "UInt64");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.UInt64"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "UInt64"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), uint64Attr, NULL, &ds2UInt64Id);
-
-    UA_NodeId_init(&ds2FloatId);
-    UA_VariableAttributes floatAttr = UA_VariableAttributes_default;
-    floatAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_FLOAT].typeId, &floatAttr.dataType);
-    floatAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&floatAttr.value, &ds2FloatVal, &UA_TYPES[UA_TYPES_FLOAT]);
-    floatAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Float");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Float"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Float"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), floatAttr, NULL, &ds2FloatId);
-
-    UA_NodeId_init(&ds2DoubleId);
-    UA_VariableAttributes doubleAttr = UA_VariableAttributes_default;
-    doubleAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_DOUBLE].typeId, &doubleAttr.dataType);
-    doubleAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&doubleAttr.value, &ds2DoubleVal, &UA_TYPES[UA_TYPES_DOUBLE]);
-    doubleAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Double");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Double"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Double"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), doubleAttr, NULL, &ds2DoubleId);
-
-    ds2StringArrayLen = 26;
-    ds2StringArray = (UA_String*)UA_Array_new(ds2StringArrayLen, &UA_TYPES[UA_TYPES_STRING]);
-    ds2StringArray[0] = UA_STRING_ALLOC("Alpha");
-    ds2StringArray[1] = UA_STRING_ALLOC("Bravo");
-    ds2StringArray[2] = UA_STRING_ALLOC("Charlie");
-    ds2StringArray[3] = UA_STRING_ALLOC("Delta");
-    ds2StringArray[4] = UA_STRING_ALLOC("Echo");
-    ds2StringArray[5] = UA_STRING_ALLOC("Foxtrot");
-    ds2StringArray[6] = UA_STRING_ALLOC("Golf");
-    ds2StringArray[7] = UA_STRING_ALLOC("Hotel");
-    ds2StringArray[8] = UA_STRING_ALLOC("India");
-    ds2StringArray[9] = UA_STRING_ALLOC("Juliet");
-    ds2StringArray[10] = UA_STRING_ALLOC("Kilo");
-    ds2StringArray[11] = UA_STRING_ALLOC("Lima");
-    ds2StringArray[12] = UA_STRING_ALLOC("Mike");
-    ds2StringArray[13] = UA_STRING_ALLOC("November");
-    ds2StringArray[14] = UA_STRING_ALLOC("Oscar");
-    ds2StringArray[15] = UA_STRING_ALLOC("Papa");
-    ds2StringArray[16] = UA_STRING_ALLOC("Quebec");
-    ds2StringArray[17] = UA_STRING_ALLOC("Romeo");
-    ds2StringArray[18] = UA_STRING_ALLOC("Sierra");
-    ds2StringArray[19] = UA_STRING_ALLOC("Tango");
-    ds2StringArray[20] = UA_STRING_ALLOC("Uniform");
-    ds2StringArray[21] = UA_STRING_ALLOC("Victor");
-    ds2StringArray[22] = UA_STRING_ALLOC("Whiskey");
-    ds2StringArray[23] = UA_STRING_ALLOC("X-ray");
-    ds2StringArray[24] = UA_STRING_ALLOC("Yankee");
-    ds2StringArray[25] = UA_STRING_ALLOC("Zulu");
-
-    UA_String stringVal;
-    UA_String_init(&stringVal);
-
-    UA_NodeId_init(&ds2StringId);
-    UA_VariableAttributes stringAttr = UA_VariableAttributes_default;
-    stringAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_STRING].typeId, &stringAttr.dataType);
-    stringAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&stringAttr.value, &stringVal, &UA_TYPES[UA_TYPES_STRING]);
-    stringAttr.displayName = UA_LOCALIZEDTEXT("en-US", "String");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.String"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "String"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), stringAttr, NULL, &ds2StringId);
-
-    UA_Byte data[] = { 0x00 };
-    UA_ByteString byteStringVal = { 1, data };
-
-    UA_NodeId_init(&ds2ByteStringId);
-    UA_VariableAttributes byteStringAttr = UA_VariableAttributes_default;
-    byteStringAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_BYTESTRING].typeId, &byteStringAttr.dataType);
-    byteStringAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&byteStringAttr.value, &byteStringVal, &UA_TYPES[UA_TYPES_BYTESTRING]);
-    byteStringAttr.displayName = UA_LOCALIZEDTEXT("en-US", "ByteString");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.ByteString"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "ByteString"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), byteStringAttr, NULL, &ds2ByteStringId);
-
-    UA_Guid guidVal = UA_Guid_random();
-    UA_NodeId_init(&ds2GuidId);
-    UA_VariableAttributes guidAttr = UA_VariableAttributes_default;
-    guidAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_GUID].typeId, &guidAttr.dataType);
-    guidAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_Variant_setScalar(&guidAttr.value, &guidVal, &UA_TYPES[UA_TYPES_GUID]);
-    guidAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Guid");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.Guid"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "Guid"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), guidAttr, NULL, &ds2GuidId);
-
-    UA_NodeId_init(&ds2DateTimeId);
-    UA_VariableAttributes dateTimeAttr = UA_VariableAttributes_default;
-    dateTimeAttr.valueRank = -1;
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_DATETIME].typeId, &dateTimeAttr.dataType);
-    dateTimeAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-    UA_DateTime dateTimeVal = UA_DateTime_now();
-    UA_Variant_setScalar(&dateTimeAttr.value, &dateTimeVal, &UA_TYPES[UA_TYPES_DATETIME]);
-    dateTimeAttr.displayName = UA_LOCALIZEDTEXT("en-US", "DateTime");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.DateTime"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "DateTime"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), dateTimeAttr, NULL, &ds2DateTimeId);
-
-    // UInt32Array
-    UA_NodeId_init(&ds2UInt32ArrId);
-    UA_VariableAttributes uint32ArrAttr = UA_VariableAttributes_default;
-    uint32ArrAttr.valueRank = 1;    // 1-dimensional array
-    uint32ArrAttr.arrayDimensionsSize = 1;
-    UA_UInt32 arrayDims[1] = { 10 };
-    uint32ArrAttr.arrayDimensions = arrayDims;
-
-    UA_NodeId_copy(&UA_TYPES[UA_TYPES_UINT32].typeId, &uint32ArrAttr.dataType);
-    uint32ArrAttr.accessLevel = UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE;
-
-    UA_Variant_setArray(&uint32ArrAttr.value, ds2UInt32ArrValue, 10, &UA_TYPES[UA_TYPES_UINT32]);
-    uint32ArrAttr.displayName = UA_LOCALIZEDTEXT("en-US", "UInt32Array");
-    UA_Server_addVariableNode(server, UA_NODEID_STRING(1, "Publisher2.UInt32Array"), folderId,
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-        UA_QUALIFIEDNAME(1, "UInt32Array"),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), uint32ArrAttr, NULL, &ds2UInt32ArrId);
-
-    if (!UA_NodeId_equal(&publishedDataSetId, &UA_NODEID_NULL))
-    {
-        // Create and add fields to the PublishedDataSet
-        UA_DataSetFieldConfig boolToggleConfig;
-        memset(&boolToggleConfig, 0, sizeof(UA_DataSetFieldConfig));
-        boolToggleConfig.field.variable.fieldNameAlias = UA_STRING("BoolToggle");
-        boolToggleConfig.field.variable.promotedField = false;
-        boolToggleConfig.field.variable.publishParameters.publishedVariable = ds2BoolToggleId;
-        boolToggleConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig byteConfig;
-        memset(&byteConfig, 0, sizeof(UA_DataSetFieldConfig));
-        byteConfig.field.variable.fieldNameAlias = UA_STRING("Byte");
-        byteConfig.field.variable.promotedField = false;
-        byteConfig.field.variable.publishParameters.publishedVariable = ds2ByteId;
-        byteConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig int16Config;
-        memset(&int16Config, 0, sizeof(UA_DataSetFieldConfig));
-        int16Config.field.variable.fieldNameAlias = UA_STRING("Int16");
-        int16Config.field.variable.promotedField = false;
-        int16Config.field.variable.publishParameters.publishedVariable = ds2Int16Id;
-        int16Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig int32Config;
-        memset(&int32Config, 0, sizeof(UA_DataSetFieldConfig));
-        int32Config.field.variable.fieldNameAlias = UA_STRING("Int32");
-        int32Config.field.variable.promotedField = false;
-        int32Config.field.variable.publishParameters.publishedVariable = ds2Int32Id;
-        int32Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig int64Config;
-        memset(&int64Config, 0, sizeof(UA_DataSetFieldConfig));
-        int64Config.field.variable.fieldNameAlias = UA_STRING("Int64");
-        int64Config.field.variable.promotedField = false;
-        int64Config.field.variable.publishParameters.publishedVariable = ds2Int64Id;
-        int64Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig sbyteConfig;
-        memset(&sbyteConfig, 0, sizeof(UA_DataSetFieldConfig));
-        sbyteConfig.field.variable.fieldNameAlias = UA_STRING("SByte");
-        sbyteConfig.field.variable.promotedField = false;
-        sbyteConfig.field.variable.publishParameters.publishedVariable = ds2SByteId;
-        sbyteConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig uint16Config;
-        memset(&uint16Config, 0, sizeof(UA_DataSetFieldConfig));
-        uint16Config.field.variable.fieldNameAlias = UA_STRING("UInt16");
-        uint16Config.field.variable.promotedField = false;
-        uint16Config.field.variable.publishParameters.publishedVariable = ds2UInt16Id;
-        uint16Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig uint32Config;
-        memset(&uint32Config, 0, sizeof(UA_DataSetFieldConfig));
-        uint32Config.field.variable.fieldNameAlias = UA_STRING("UInt32");
-        uint32Config.field.variable.promotedField = false;
-        uint32Config.field.variable.publishParameters.publishedVariable = ds2UInt32Id;
-        uint32Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig uint64Config;
-        memset(&uint64Config, 0, sizeof(UA_DataSetFieldConfig));
-        uint64Config.field.variable.fieldNameAlias = UA_STRING("UInt64");
-        uint64Config.field.variable.promotedField = false;
-        uint64Config.field.variable.publishParameters.publishedVariable = ds2UInt64Id;
-        uint64Config.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig floatConfig;
-        memset(&floatConfig, 0, sizeof(UA_DataSetFieldConfig));
-        floatConfig.field.variable.fieldNameAlias = UA_STRING("Float");
-        floatConfig.field.variable.promotedField = false;
-        floatConfig.field.variable.publishParameters.publishedVariable = ds2FloatId;
-        floatConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig doubleConfig;
-        memset(&doubleConfig, 0, sizeof(UA_DataSetFieldConfig));
-        doubleConfig.field.variable.fieldNameAlias = UA_STRING("Double");
-        doubleConfig.field.variable.promotedField = false;
-        doubleConfig.field.variable.publishParameters.publishedVariable = ds2DoubleId;
-        doubleConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig stringConfig;
-        memset(&stringConfig, 0, sizeof(UA_DataSetFieldConfig));
-        stringConfig.field.variable.fieldNameAlias = UA_STRING("String");
-        stringConfig.field.variable.promotedField = false;
-        stringConfig.field.variable.publishParameters.publishedVariable = ds2StringId;
-        stringConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig byteStringConfig;
-        memset(&byteStringConfig, 0, sizeof(UA_DataSetFieldConfig));
-        byteStringConfig.field.variable.fieldNameAlias = UA_STRING("ByteString");
-        byteStringConfig.field.variable.promotedField = false;
-        byteStringConfig.field.variable.publishParameters.publishedVariable = ds2ByteStringId;
-        byteStringConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig guidConfig;
-        memset(&guidConfig, 0, sizeof(UA_DataSetFieldConfig));
-        guidConfig.field.variable.fieldNameAlias = UA_STRING("Guid");
-        guidConfig.field.variable.promotedField = false;
-        guidConfig.field.variable.publishParameters.publishedVariable = ds2GuidId;
-        guidConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig dateTimeConfig;
-        memset(&dateTimeConfig, 0, sizeof(UA_DataSetFieldConfig));
-        dateTimeConfig.field.variable.fieldNameAlias = UA_STRING("DateTime");
-        dateTimeConfig.field.variable.promotedField = false;
-        dateTimeConfig.field.variable.publishParameters.publishedVariable = ds2DateTimeId;
-        dateTimeConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_DataSetFieldConfig uint32ArrConfig;
-        memset(&uint32ArrConfig, 0, sizeof(UA_DataSetFieldConfig));
-        uint32ArrConfig.field.variable.fieldNameAlias = UA_STRING("UInt32Array");
-        uint32ArrConfig.field.variable.promotedField = false;
-        uint32ArrConfig.field.variable.publishParameters.publishedVariable = ds2UInt32ArrId;
-        uint32ArrConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-        UA_NodeId f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16;
-        // add fields in reverse order, because all fields are added to the beginning of the list
-        UA_Server_addDataSetField(server, publishedDataSetId, &uint32ArrConfig, &f16);
-        UA_Server_addDataSetField(server, publishedDataSetId, &dateTimeConfig, &f15);
-        UA_Server_addDataSetField(server, publishedDataSetId, &guidConfig, &f14);
-        UA_Server_addDataSetField(server, publishedDataSetId, &byteStringConfig, &f13);
-        UA_Server_addDataSetField(server, publishedDataSetId, &stringConfig, &f12);
-        UA_Server_addDataSetField(server, publishedDataSetId, &doubleConfig, &f11);
-        UA_Server_addDataSetField(server, publishedDataSetId, &floatConfig, &f10);
-        UA_Server_addDataSetField(server, publishedDataSetId, &uint64Config, &f9);
-        UA_Server_addDataSetField(server, publishedDataSetId, &uint32Config, &f8);
-        UA_Server_addDataSetField(server, publishedDataSetId, &uint16Config, &f7);
-        UA_Server_addDataSetField(server, publishedDataSetId, &sbyteConfig, &f6);
-        UA_Server_addDataSetField(server, publishedDataSetId, &int64Config, &f5);
-        UA_Server_addDataSetField(server, publishedDataSetId, &int32Config, &f4);
-        UA_Server_addDataSetField(server, publishedDataSetId, &int16Config, &f3);
-        UA_Server_addDataSetField(server, publishedDataSetId, &byteConfig, &f2);
-        UA_Server_addDataSetField(server, publishedDataSetId, &boolToggleConfig, &f1);
-    }
-}
-
-void
-timerCallback(UA_Server *server, void *data) {
-    // DataSet 1
-    // BoolToggle
-    ds1BoolToggleCount++;
-    UA_Variant tmpVari;
-    if (ds1BoolToggleCount >= 3) {
-        if (ds1BoolToggleVal) {
-            ds1BoolToggleVal = false;
-        } else {
-            ds1BoolToggleVal = true;
-        }
-
-        UA_Variant_init(&tmpVari);
-        UA_Variant_setScalar(&tmpVari, &ds1BoolToggleVal, &UA_TYPES[UA_TYPES_BOOLEAN]);
-        UA_Server_writeValue(server, ds1BoolToggleId, tmpVari);
-        ds1BoolToggleCount = 0;
-    }
-
-    // Int32
-    UA_Variant_init(&tmpVari);
-    ds1Int32Val++;
-    if(ds1Int32Val > 10000)
-        ds1Int32Val = 0;
-    UA_Variant_setScalar(&tmpVari, &ds1Int32Val, &UA_TYPES[UA_TYPES_INT32]);
-    UA_Server_writeValue(server, ds1Int32Id, tmpVari);
-
-    // Int32Fast
-    UA_Variant_init(&tmpVari);
-    ds1Int32FastVal += 100;
-    if(ds1Int32FastVal > 10000)
-        ds1Int32FastVal = 0;
-    UA_Variant_setScalar(&tmpVari, &ds1Int32FastVal, &UA_TYPES[UA_TYPES_INT32]);
-    UA_Server_writeValue(server, ds1Int32FastId, tmpVari);
-
-    // DateTime
-    UA_Variant_init(&tmpVari);
-    UA_DateTime tmpTime = UA_DateTime_now();
-    UA_Variant_setScalar(&tmpVari, &tmpTime, &UA_TYPES[UA_TYPES_DATETIME]);
-    UA_Server_writeValue(server, ds1DateTimeId, tmpVari);
-
-    // DataSet 2
-    UA_Server_writeValue(server, ds2DateTimeId, tmpVari);
-
-    // BoolToggle
-    if (ds2BoolToggleVal)
-        ds2BoolToggleVal = false;
-    else
-        ds2BoolToggleVal = true;
-
-    // Write new value
-    UA_Variant_init(&tmpVari);
-    UA_Variant_setScalar(&tmpVari, &ds2BoolToggleVal, &UA_TYPES[UA_TYPES_BOOLEAN]);
-    UA_Server_writeValue(server, ds2BoolToggleId, tmpVari);
-
-    // Byte
-    UA_Variant_init(&tmpVari);
-    ds2ByteVal++;
-    UA_Variant_setScalar(&tmpVari, &ds2ByteVal, &UA_TYPES[UA_TYPES_BYTE]);
-    UA_Server_writeValue(server, ds2ByteId, tmpVari);
-
-    // Int16
-    UA_Variant_init(&tmpVari);
-    ds2Int16Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2Int16Val, &UA_TYPES[UA_TYPES_INT16]);
-    UA_Server_writeValue(server, ds2Int16Id, tmpVari);
-
-    // Int32
-    UA_Variant_init(&tmpVari);
-    ds2Int32Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2Int32Val, &UA_TYPES[UA_TYPES_INT32]);
-    UA_Server_writeValue(server, ds2Int32Id, tmpVari);
-
-    // Int64
-    UA_Variant_init(&tmpVari);
-    ds2Int64Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2Int64Val, &UA_TYPES[UA_TYPES_INT64]);
-    UA_Server_writeValue(server, ds2Int64Id, tmpVari);
-
-    // SByte
-    UA_Variant_init(&tmpVari);
-    ds2SByteVal++;
-    UA_Variant_setScalar(&tmpVari, &ds2SByteVal, &UA_TYPES[UA_TYPES_SBYTE]);
-    UA_Server_writeValue(server, ds2SByteId, tmpVari);
-
-    // UInt16
-    UA_Variant_init(&tmpVari);
-    ds2UInt16Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2UInt16Val, &UA_TYPES[UA_TYPES_UINT16]);
-    UA_Server_writeValue(server, ds2UInt16Id, tmpVari);
-
-    // UInt32
-    UA_Variant_init(&tmpVari);
-    ds2UInt32Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2UInt32Val, &UA_TYPES[UA_TYPES_UINT32]);
-    UA_Server_writeValue(server, ds2UInt32Id, tmpVari);
-
-    // UInt64
-    UA_Variant_init(&tmpVari);
-    ds2UInt64Val++;
-    UA_Variant_setScalar(&tmpVari, &ds2UInt64Val, &UA_TYPES[UA_TYPES_UINT64]);
-    UA_Server_writeValue(server, ds2UInt64Id, tmpVari);
-
-    // Float
-    UA_Variant_init(&tmpVari);
-    ds2FloatVal++;
-    UA_Variant_setScalar(&tmpVari, &ds2FloatVal, &UA_TYPES[UA_TYPES_FLOAT]);
-    UA_Server_writeValue(server, ds2FloatId, tmpVari);
-
-    // Double
-    UA_Variant_init(&tmpVari);
-    ds2DoubleVal++;
-    UA_Variant_setScalar(&tmpVari, &ds2DoubleVal, &UA_TYPES[UA_TYPES_DOUBLE]);
-    UA_Server_writeValue(server, ds2DoubleId, tmpVari);
-
-    // String 
-    UA_Variant_init(&tmpVari);
-    ds2StringIndex++;
-    if(ds2StringIndex >= ds2StringArrayLen)
-        ds2StringIndex = 0;
-
-    UA_Variant_setScalar(&tmpVari, &ds2StringArray[ds2StringIndex], &UA_TYPES[UA_TYPES_STRING]);
-    UA_Server_writeValue(server, ds2StringId, tmpVari);
-
-    // ByteString 
-    UA_Variant_init(&tmpVari);
-    UA_ByteString bs;
-    UA_ByteString_init(&bs);
-    UA_ByteString_allocBuffer(&bs, 4);
-    UA_UInt32 ui2 = UA_UInt32_random();
-    memcpy(bs.data, &ui2, 4);
-
-    UA_Variant_setScalar(&tmpVari, &bs, &UA_TYPES[UA_TYPES_BYTESTRING]);
-    UA_Server_writeValue(server, ds2ByteStringId, tmpVari);
-    UA_ByteString_clear(&bs);
-
-    // Guid 
-    UA_Variant_init(&tmpVari);
-    UA_Guid g = UA_Guid_random();
-    UA_Variant_setScalar(&tmpVari, &g, &UA_TYPES[UA_TYPES_GUID]);
-    UA_Server_writeValue(server, ds2GuidId, tmpVari);
-
-    // UInt32Array
-    for(size_t i = 0; i < 10; i++)
-        ds2UInt32ArrValue[i]++;
-
-    UA_Variant_init(&tmpVari);
-    UA_Variant_setArray(&tmpVari, ds2UInt32ArrValue, 10, &UA_TYPES[UA_TYPES_UINT32]);
-    UA_Server_writeValue(server, ds2UInt32ArrId, tmpVari);
-}
-
-UA_Boolean running = true;
-static void stopHandler(int sig) {
-    running = false;
-}
-
-static int run(UA_String *transportProfile,
-    UA_NetworkAddressUrlDataType *networkAddressUrl) {
-    signal(SIGINT, stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    UA_Server *server = UA_Server_new();
-    UA_ServerConfig *config = UA_Server_getConfig(server);
-    UA_ServerConfig_setMinimal(config, 4802, NULL);
-
-    /* Details about the connection configuration and handling are located in
-    * the pubsub connection tutorial */
-    config->pubsubTransportLayers =
-        (UA_PubSubTransportLayer *)UA_calloc(2, sizeof(UA_PubSubTransportLayer));
-    if (!config->pubsubTransportLayers) {
-        UA_Server_delete(server);
-        return EXIT_FAILURE;
-    }
-    config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP();
-    config->pubsubTransportLayersSize++;
-#ifdef UA_ENABLE_PUBSUB_ETH_UADP
-    config->pubsubTransportLayers[1] = UA_PubSubTransportLayerEthernet();
-    config->pubsubTransportLayersSize++;
-#endif
-
-    addPubSubConnection(server, transportProfile, networkAddressUrl);
-    
-    /* Create a PublishedDataSet based on a PublishedDataSetConfig. */
-    UA_PublishedDataSetConfig publishedDataSetConfig;
-    publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
-    publishedDataSetConfig.name = UA_STRING("DataSet 1 (Simple)");
-
-    UA_NodeId publishedDataSetIdent;
-    UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent);
-
-    addPublisher1(server, publishedDataSetIdent);
-
-    /* Create a new WriterGroup and configure parameters like the publish interval. */
-    UA_WriterGroupConfig writerGroupConfig;
-    memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
-    writerGroupConfig.name = UA_STRING("DataSet WriterGroup");
-    writerGroupConfig.publishingInterval = 500;
-    writerGroupConfig.enabled = UA_FALSE;
-    writerGroupConfig.writerGroupId = 100;
-    writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
-    writerGroupConfig.maxEncapsulatedDataSetMessageCount = 3;
-
-    /* Add the new WriterGroup to an existing Connection. */
-    UA_NodeId writerGroupIdent;
-    UA_Server_addWriterGroup(server, connectionIdent, &writerGroupConfig, &writerGroupIdent);
-    UA_Server_setWriterGroupOperational(server, writerGroupIdent);
-
-    /* Create a new Writer and connect it with an existing PublishedDataSet */
-    // DataSetWriter ID 1 with Variant Encoding 
-    UA_DataSetWriterConfig dataSetWriterConfig;
-    memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
-    dataSetWriterConfig.name = UA_STRING("DataSet 1 DataSetWriter");
-    dataSetWriterConfig.dataSetWriterId = 1;
-    //The creation of delta messages is configured in the following line. Value
-    // 0 -> no delta messages are created. 
-    dataSetWriterConfig.keyFrameCount = 10;
-
-    UA_NodeId writerIdentifier;
-    UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
-        &dataSetWriterConfig, &writerIdentifier);
-
-    // Published DataSet 2
-    UA_PublishedDataSetConfig publishedDataSetConfig2;
-    publishedDataSetConfig2.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
-    publishedDataSetConfig2.name = UA_STRING("DataSet 2 (AllTypes)");
-
-    UA_NodeId publishedDataSetIdent2;
-    UA_Server_addPublishedDataSet(server, &publishedDataSetConfig2, &publishedDataSetIdent2);
-
-    addPublisher2(server, publishedDataSetIdent2);
-
-    // DataSet Writer 2
-    // Create a new Writer and connect it with an existing PublishedDataSet
-    UA_DataSetWriterConfig dataSetWriterConfig2;
-
-    memset(&dataSetWriterConfig2, 0, sizeof(UA_DataSetWriterConfig));
-    dataSetWriterConfig2.name = UA_STRING("DataSet 2 DataSetWriter");
-    dataSetWriterConfig2.dataSetWriterId = 2;
-    //The creation of delta messages is configured in the following line. Value
-    // 0 -> no delta messages are created. 
-    dataSetWriterConfig2.keyFrameCount = 10;
-
-    UA_NodeId writerIdentifier2;
-    UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent2,
-        &dataSetWriterConfig2, &writerIdentifier2);
-
-    UA_UInt64 timerCallbackId = 0;
-    UA_Server_addRepeatedCallback(server, (UA_ServerCallback)timerCallback, NULL, 1000, &timerCallbackId);
-
-    UA_StatusCode retval = UA_Server_run(server, &running);
-
-    UA_Server_delete(server);
-    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
-}
-
-static void
-usage(char *progname) {
-    printf("usage: %s <uri> [device]\n", progname);
-}
-
-int main(int argc, char **argv) {
-    UA_String transportProfile =
-        UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
-    UA_NetworkAddressUrlDataType networkAddressUrl =
-    { UA_STRING_NULL, UA_STRING("opc.udp://239.0.0.1:4840/") };
-
-    if (argc > 1) {
-        if (strcmp(argv[1], "-h") == 0) {
-            usage(argv[0]);
-            return EXIT_SUCCESS;
-        }
-        else if (strncmp(argv[1], "opc.udp://", 10) == 0) {
-            networkAddressUrl.url = UA_STRING(argv[1]);
-        }
-        else if (strncmp(argv[1], "opc.eth://", 10) == 0) {
-            transportProfile =
-                UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp");
-            if (argc < 3) {
-                printf("Error: UADP/ETH needs an interface name\n");
-                return EXIT_FAILURE;
-            }
-            networkAddressUrl.networkInterface = UA_STRING(argv[2]);
-            networkAddressUrl.url = UA_STRING(argv[1]);
-        }
-        else {
-            printf("Error: unknown URI\n");
-            return EXIT_FAILURE;
-        }
-    }
-
-    return run(&transportProfile, &networkAddressUrl);
-}

+ 0 - 205
examples/pubsub/server_pubsub_publisher_rt_level.c

@@ -1,205 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
-
-#include <open62541/plugin/log_stdout.h>
-#include <open62541/plugin/pubsub_udp.h>
-#include <open62541/server.h>
-#include <open62541/server_config_default.h>
-
-#include <signal.h>
-#include <stdlib.h>
-#include <open62541/server_pubsub.h>
-
-/* possible options: PUBSUB_CONFIG_FASTPATH_NONE, PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS, PUBSUB_CONFIG_FASTPATH_STATIC_VALUES */
-#define PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS
-#define PUBSUB_CONFIG_PUBLISH_CYCLE_MS 100
-#define PUBSUB_CONFIG_PUBLISH_CYCLES 100
-#define PUBSUB_CONFIG_FIELD_COUNT 10
-
-/**
- * The PubSub RT level example points out the configuration of different PubSub RT-levels. These levels will be
- * used together with an RT capable OS for deterministic message generation. The main target is to reduce the time
- * spread and effort during the publish cycle. Most of the RT levels are based on pre-generated and buffered
- * DataSetMesseges and NetworkMessages. Since changes in the PubSub-configuration will invalidate the buffered
- * frames, the PubSub configuration must be frozen after the configuration phase.
- *
- * This example can be configured to compare and measure the different PubSub options by the following define options:
- * PUBSUB_CONFIG_FASTPATH_NONE -> The published fields are added to the information model and published in the default non-RT mode
- * PUBSUB_CONFIG_FASTPATH_STATIC_VALUES -> The published fields are not visible in the information model. The publish cycle is improved
- * by prevent the value lookup within the information model.
- * PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS -> The published fields are not visible in the information model. After the PubSub-configuration
- * freeze, the NetworkMessages and DataSetMessages will be calculated and buffered. During the publish cycle these buffers will only be updated.
- */
-
-UA_NodeId publishedDataSetIdent, dataSetFieldIdent, writerGroupIdent, connectionIdentifier;
-UA_UInt32 *valueStore[PUBSUB_CONFIG_FIELD_COUNT];
-
-UA_Boolean running = true;
-static void stopHandler(int sign) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
-    running = false;
-}
-
-/* The following PubSub configuration does not differ from the 'normal' configuration */
-static void
-addMinimalPubSubConfiguration(UA_Server * server){
-    /* Add one PubSubConnection */
-    UA_PubSubConnectionConfig connectionConfig;
-    memset(&connectionConfig, 0, sizeof(connectionConfig));
-    connectionConfig.name = UA_STRING("UDP-UADP Connection 1");
-    connectionConfig.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
-    connectionConfig.enabled = UA_TRUE;
-    UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL , UA_STRING("opc.udp://224.0.0.22:4840/")};
-    UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
-    connectionConfig.publisherId.numeric = UA_UInt32_random();
-    UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdentifier);
-    /* Add one PublishedDataSet */
-    UA_PublishedDataSetConfig publishedDataSetConfig;
-    memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
-    publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
-    publishedDataSetConfig.name = UA_STRING("Demo PDS");
-    /* Add one DataSetField to the PDS */
-    UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent);
-}
-
-static void
-valueUpdateCallback(UA_Server *server, void *data) {
-#if defined PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS || defined PUBSUB_CONFIG_FASTPATH_STATIC_VALUES
-    for (int i = 0; i < PUBSUB_CONFIG_FIELD_COUNT; ++i)
-        *valueStore[i] = *valueStore[i] + 1;
-    if(*valueStore[0] > PUBSUB_CONFIG_PUBLISH_CYCLES)
-        running = false;
-#endif
-#if defined PUBSUB_CONFIG_FASTPATH_NONE
-    for(size_t i = 0; i < PUBSUB_CONFIG_FIELD_COUNT; i++){
-        UA_Variant value;
-        UA_Variant_init(&value);
-        if(UA_Server_readValue(server, UA_NODEID_NUMERIC(1, 1000 + (UA_UInt32) i), &value) != UA_STATUSCODE_GOOD) {
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Failed to read publish value. Node number: %zu", i);
-            continue;
-        }
-        UA_UInt32 *intValue = (UA_UInt32 *) value.data;
-        *intValue = *intValue + 1;
-        if(UA_Server_writeValue(server, UA_NODEID_NUMERIC(1, 1000 + (UA_UInt32) i), value) != UA_STATUSCODE_GOOD){
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Failed to update publish value. Node number: %zu", i);
-            continue;
-        }
-        if(i == 0 && *intValue  > PUBSUB_CONFIG_PUBLISH_CYCLES)
-            running = false;
-        UA_Variant_deleteMembers(&value);
-    }
-#endif
-}
-
-int main(void) {
-    signal(SIGINT, stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    UA_Server *server = UA_Server_new();
-    UA_ServerConfig *config = UA_Server_getConfig(server);
-    UA_ServerConfig_setDefault(config);
-
-    config->pubsubTransportLayers = (UA_PubSubTransportLayer *) UA_malloc(sizeof(UA_PubSubTransportLayer));
-    if(!config->pubsubTransportLayers) {
-        UA_Server_delete(server);
-        return -1;
-    }
-    config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP();
-    config->pubsubTransportLayersSize++;
-
-    /*Add standard PubSub configuration (no difference to the std. configuration)*/
-    addMinimalPubSubConfiguration(server);
-
-    UA_WriterGroupConfig writerGroupConfig;
-    memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
-    writerGroupConfig.name = UA_STRING("Demo WriterGroup");
-    writerGroupConfig.publishingInterval = PUBSUB_CONFIG_PUBLISH_CYCLE_MS;
-    writerGroupConfig.enabled = UA_FALSE;
-    writerGroupConfig.writerGroupId = 100;
-    writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
-    writerGroupConfig.messageSettings.encoding             = UA_EXTENSIONOBJECT_DECODED;
-    writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
-    UA_UadpWriterGroupMessageDataType writerGroupMessage;
-    UA_UadpWriterGroupMessageDataType_init(&writerGroupMessage);
-    /* Change message settings of writerGroup to send PublisherId,
-     * WriterGroupId in GroupHeader and DataSetWriterId in PayloadHeader
-     * of NetworkMessage */
-    writerGroupMessage.networkMessageContentMask = (UA_UadpNetworkMessageContentMask) ((UA_UadpNetworkMessageContentMask) UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID |
-                                                    (UA_UadpNetworkMessageContentMask) UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER |
-                                                    (UA_UadpNetworkMessageContentMask) UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID |
-                                                    (UA_UadpNetworkMessageContentMask) UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER);
-    writerGroupConfig.messageSettings.content.decoded.data = &writerGroupMessage;
-#ifdef PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS
-    writerGroupConfig.rtLevel = UA_PUBSUB_RT_FIXED_SIZE;
-#elif defined PUBSUB_CONFIG_FASTPATH_STATIC_VALUES
-    writerGroupConfig.rtLevel = UA_PUBSUB_RT_DIRECT_VALUE_ACCESS;
-#endif
-    UA_Server_addWriterGroup(server, connectionIdentifier, &writerGroupConfig, &writerGroupIdent);
-    /* Add one DataSetWriter */
-    UA_NodeId dataSetWriterIdent;
-    UA_DataSetWriterConfig dataSetWriterConfig;
-    memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
-    dataSetWriterConfig.name = UA_STRING("Demo DataSetWriter");
-    dataSetWriterConfig.dataSetWriterId = 62541;
-    dataSetWriterConfig.keyFrameCount = 10;
-    UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent, &dataSetWriterConfig, &dataSetWriterIdent);
-
-#if defined PUBSUB_CONFIG_FASTPATH_FIXED_OFFSETS || defined PUBSUB_CONFIG_FASTPATH_STATIC_VALUES
-    /* Add one DataSetField with static value source to PDS */
-    UA_DataSetFieldConfig dsfConfig;
-    for(size_t i = 0; i < PUBSUB_CONFIG_FIELD_COUNT; i++){
-        memset(&dsfConfig, 0, sizeof(UA_DataSetFieldConfig));
-        /* Create Variant and configure as DataSetField source */
-        UA_UInt32 *intValue = UA_UInt32_new();
-        *intValue = (UA_UInt32) i * 1000;
-        valueStore[i] = intValue;
-        UA_Variant variant;
-        memset(&variant, 0, sizeof(UA_Variant));
-        UA_Variant_setScalar(&variant, intValue, &UA_TYPES[UA_TYPES_UINT32]);
-        UA_DataValue staticValueSource;
-        memset(&staticValueSource, 0, sizeof(staticValueSource));
-        staticValueSource.value = variant;
-        dsfConfig.field.variable.staticValueSourceEnabled = UA_TRUE;
-        dsfConfig.field.variable.staticValueSource.value = variant;
-        UA_Server_addDataSetField(server, publishedDataSetIdent, &dsfConfig, &dataSetFieldIdent);
-    }
-#endif
-#if defined PUBSUB_CONFIG_FASTPATH_NONE
-    UA_DataSetFieldConfig dsfConfig;
-    memset(&dsfConfig, 0, sizeof(UA_DataSetFieldConfig));
-    for(size_t i = 0; i < PUBSUB_CONFIG_FIELD_COUNT; i++){
-        UA_VariableAttributes attributes = UA_VariableAttributes_default;
-        UA_Variant value;
-        UA_Variant_init(&value);
-        UA_UInt32 intValue = (UA_UInt32) i * 1000;
-        UA_Variant_setScalar(&value, &intValue, &UA_TYPES[UA_TYPES_UINT32]);
-        attributes.value = value;
-        if(UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1,  1000 + (UA_UInt32) i),
-                UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-                UA_QUALIFIEDNAME(1, "variable"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
-                 attributes, NULL, NULL) != UA_STATUSCODE_GOOD){
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Failed to add Publish-Node to the server. Node number: %zu", i);
-            continue;
-        }
-        dsfConfig.field.variable.publishParameters.publishedVariable = UA_NODEID_NUMERIC(1, 1000 + (UA_UInt32) i);
-        dsfConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-        UA_Server_addDataSetField(server, publishedDataSetIdent, &dsfConfig, &dataSetFieldIdent);
-    }
-#endif
-    /* The PubSub configuration is currently editable and the publish callback is not running */
-    writerGroupConfig.publishingInterval = PUBSUB_CONFIG_PUBLISH_CYCLE_MS;
-    UA_Server_updateWriterGroupConfig(server, writerGroupIdent, &writerGroupConfig);
-
-    /* Freeze the PubSub configuration (and start implicitly the publish callback) */
-    UA_Server_freezeWriterGroupConfiguration(server, writerGroupIdent);
-    UA_Server_setWriterGroupOperational(server, writerGroupIdent);
-
-    UA_UInt64 callbackId;
-    UA_Server_addRepeatedCallback(server, valueUpdateCallback, NULL, PUBSUB_CONFIG_PUBLISH_CYCLE_MS, &callbackId);
-
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    retval |= UA_Server_run(server, &running);
-
-    UA_Server_delete(server);
-    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
-}

+ 2 - 2
examples/pubsub/tutorial_pubsub_connection.c

@@ -64,10 +64,10 @@ int main(void) {
     UA_Variant_setScalar(&connectionOptions[0].value, &ttl, &UA_TYPES[UA_TYPES_UINT32]);
     connectionOptions[1].key = UA_QUALIFIEDNAME(0, "loopback");
     UA_Boolean loopback = UA_FALSE;
-    UA_Variant_setScalar(&connectionOptions[1].value, &loopback, &UA_TYPES[UA_TYPES_BOOLEAN]);
+    UA_Variant_setScalar(&connectionOptions[1].value, &loopback, &UA_TYPES[UA_TYPES_UINT32]);
     connectionOptions[2].key = UA_QUALIFIEDNAME(0, "reuse");
     UA_Boolean reuse = UA_TRUE;
-    UA_Variant_setScalar(&connectionOptions[2].value, &reuse, &UA_TYPES[UA_TYPES_BOOLEAN]);
+    UA_Variant_setScalar(&connectionOptions[2].value, &reuse, &UA_TYPES[UA_TYPES_UINT32]);
     connectionConfig.connectionProperties = connectionOptions;
     connectionConfig.connectionPropertiesSize = 3;
     /* Create a new concrete connection and add the connection

+ 0 - 372
examples/pubsub/tutorial_pubsub_mqtt_publish.c

@@ -1,372 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
-
-/**
- * .. _pubsub-tutorial:
- *
- * Working with Publish/Subscribe
- * ------------------------------
- *
- * Work in progress: This Tutorial will be continuously extended during the next
- * PubSub batches. More details about the PubSub extension and corresponding
- * open62541 API are located here: :ref:`pubsub`.
- *
- * Publishing Fields
- * ^^^^^^^^^^^^^^^^^
- * The PubSub MQTT publish example demonstrate the simplest way to publish
- * informations from the information model over MQTT using the UADP (or later
- * JSON) encoding. To receive information the subscribe functionality of mqtt is
- * used. A periodical call to yield is necessary to update the mqtt stack.
- *
- * **Connection handling**
- * PubSubConnections can be created and deleted on runtime. More details about
- * the system preconfiguration and connection can be found in
- * ``tutorial_pubsub_connection.c``.
- */
-
-#include "open62541/server.h"
-#include "open62541/server_config_default.h"
-#include "ua_pubsub.h"
-#include "ua_network_pubsub_mqtt.h"
-#include "open62541/plugin/log_stdout.h"
-#include <signal.h>
-
-#define CONNECTION_NAME              "MQTT Publisher Connection"
-#define TRANSPORT_PROFILE_URI        "http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt"
-#define MQTT_CLIENT_ID               "TESTCLIENTPUBSUBMQTT"
-#define CONNECTIONOPTION_NAME        "mqttClientId"
-#define PUBLISHER_TOPIC              "customTopic"
-#define PUBLISHER_METADATAQUEUENAME  "MetaDataTopic"
-#define PUBLISHER_METADATAUPDATETIME 0
-#define BROKER_ADDRESS_URL           "opc.mqtt://127.0.0.1:1883"
-#define PUBLISH_INTERVAL             500
-
-static UA_Boolean useJson = false;
-static UA_NodeId connectionIdent;
-static UA_NodeId publishedDataSetIdent;
-static UA_NodeId writerGroupIdent;
-
-static void
-addPubSubConnection(UA_Server *server, char *addressUrl) {
-    /* Details about the connection configuration and handling are located
-     * in the pubsub connection tutorial */
-    UA_PubSubConnectionConfig connectionConfig;
-    memset(&connectionConfig, 0, sizeof(connectionConfig));
-    connectionConfig.name = UA_STRING(CONNECTION_NAME);
-    connectionConfig.transportProfileUri = UA_STRING(TRANSPORT_PROFILE_URI);
-    connectionConfig.enabled = UA_TRUE;
-
-    /* configure address of the mqtt broker (local on default port) */
-    UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL , UA_STRING(addressUrl)};
-    UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrl,
-                         &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
-    /* Changed to static publisherId from random generation to identify
-     * the publisher on Subscriber side */
-    connectionConfig.publisherId.numeric = 2234;
-
-    /* configure options, set mqtt client id */
-    UA_KeyValuePair connectionOptions[1];
-    connectionOptions[0].key = UA_QUALIFIEDNAME(0, CONNECTIONOPTION_NAME);
-    UA_String mqttClientId = UA_STRING(MQTT_CLIENT_ID);
-    UA_Variant_setScalar(&connectionOptions[0].value, &mqttClientId, &UA_TYPES[UA_TYPES_STRING]);
-    connectionConfig.connectionProperties = connectionOptions;
-    connectionConfig.connectionPropertiesSize = 1;
-    UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
-}
-
-/**
- * **PublishedDataSet handling**
- * The PublishedDataSet (PDS) and PubSubConnection are the toplevel entities and
- * can exist alone. The PDS contains the collection of the published fields. All
- * other PubSub elements are directly or indirectly linked with the PDS or
- * connection.
- */
-static void
-addPublishedDataSet(UA_Server *server) {
-    /* The PublishedDataSetConfig contains all necessary public
-    * informations for the creation of a new PublishedDataSet */
-    UA_PublishedDataSetConfig publishedDataSetConfig;
-    memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
-    publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
-    publishedDataSetConfig.name = UA_STRING("Demo PDS");
-    /* Create new PublishedDataSet based on the PublishedDataSetConfig. */
-    UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent);
-}
-
-/**
- * **DataSetField handling**
- * The DataSetField (DSF) is part of the PDS and describes exactly one published field.
- */
-static void
-addDataSetField(UA_Server *server) {
-    /* Add a field to the previous created PublishedDataSet */
-    UA_DataSetFieldConfig dataSetFieldConfig;
-    memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
-    dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
-
-    dataSetFieldConfig.field.variable.fieldNameAlias = UA_STRING("Server localtime");
-    dataSetFieldConfig.field.variable.promotedField = UA_FALSE;
-    dataSetFieldConfig.field.variable.publishParameters.publishedVariable =
-    UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
-    dataSetFieldConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-    UA_Server_addDataSetField(server, publishedDataSetIdent, &dataSetFieldConfig, NULL);
-
-}
-
-/**
- * **WriterGroup handling**
- * The WriterGroup (WG) is part of the connection and contains the primary configuration
- * parameters for the message creation.
- */
-static void
-addWriterGroup(UA_Server *server, char *topic, int interval) {
-    /* Now we create a new WriterGroupConfig and add the group to the existing PubSubConnection. */
-    UA_WriterGroupConfig writerGroupConfig;
-    memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
-    writerGroupConfig.name = UA_STRING("Demo WriterGroup");
-    writerGroupConfig.publishingInterval = interval;
-    writerGroupConfig.enabled = UA_FALSE;
-    writerGroupConfig.writerGroupId = 100;
-
-    /* decide whether to use JSON or UADP encoding*/
-#ifdef UA_ENABLE_JSON_ENCODING
-    if(useJson)
-        writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_JSON;
-    else
-#endif
-        writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
-    writerGroupConfig.messageSettings.encoding             = UA_EXTENSIONOBJECT_DECODED;
-    writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
-    /* The configuration flags for the messages are encapsulated inside the
-     * message- and transport settings extension objects. These extension
-     * objects are defined by the standard. e.g.
-     * UadpWriterGroupMessageDataType */
-    UA_UadpWriterGroupMessageDataType *writerGroupMessage  = UA_UadpWriterGroupMessageDataType_new();
-    /* Change message settings of writerGroup to send PublisherId,
-     * WriterGroupId in GroupHeader and DataSetWriterId in PayloadHeader
-     * of NetworkMessage */
-    writerGroupMessage->networkMessageContentMask =
-        (UA_UadpNetworkMessageContentMask)(UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID |
-        (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER |
-        (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID |
-        (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER);
-    writerGroupConfig.messageSettings.content.decoded.data = writerGroupMessage;
-
-    /* configure the mqtt publish topic */
-    UA_BrokerWriterGroupTransportDataType brokerTransportSettings;
-    memset(&brokerTransportSettings, 0, sizeof(UA_BrokerWriterGroupTransportDataType));
-    /* Assign the Topic at which MQTT publish should happen */
-    /*ToDo: Pass the topic as argument from the writer group */
-    brokerTransportSettings.queueName = UA_STRING(topic);
-    brokerTransportSettings.resourceUri = UA_STRING_NULL;
-    brokerTransportSettings.authenticationProfileUri = UA_STRING_NULL;
-
-    /* Choose the QOS Level for MQTT */
-    brokerTransportSettings.requestedDeliveryGuarantee = UA_BROKERTRANSPORTQUALITYOFSERVICE_BESTEFFORT;
-
-    /* Encapsulate config in transportSettings */
-    UA_ExtensionObject transportSettings;
-    memset(&transportSettings, 0, sizeof(UA_ExtensionObject));
-    transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
-    transportSettings.content.decoded.type = &UA_TYPES[UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE];
-    transportSettings.content.decoded.data = &brokerTransportSettings;
-
-    writerGroupConfig.transportSettings = transportSettings;
-    UA_Server_addWriterGroup(server, connectionIdent, &writerGroupConfig, &writerGroupIdent);
-    UA_Server_setWriterGroupOperational(server, writerGroupIdent);
-    UA_UadpWriterGroupMessageDataType_delete(writerGroupMessage);
-}
-
-/**
- * **DataSetWriter handling**
- * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is
- * linked to exactly one PDS and contains additional informations for the
- * message generation.
- */
-static void
-addDataSetWriter(UA_Server *server, char *topic) {
-    /* We need now a DataSetWriter within the WriterGroup. This means we must
-     * create a new DataSetWriterConfig and add call the addWriterGroup function. */
-    UA_NodeId dataSetWriterIdent;
-    UA_DataSetWriterConfig dataSetWriterConfig;
-    memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
-    dataSetWriterConfig.name = UA_STRING("Demo DataSetWriter");
-    dataSetWriterConfig.dataSetWriterId = 62541;
-    dataSetWriterConfig.keyFrameCount = 10;
-
-#ifdef UA_ENABLE_JSON_ENCODING
-    UA_JsonDataSetWriterMessageDataType jsonDswMd;
-    UA_ExtensionObject messageSettings;
-    if(useJson) {
-        /* JSON config for the dataSetWriter */
-        jsonDswMd.dataSetMessageContentMask = (UA_JsonDataSetMessageContentMask)
-            (UA_JSONDATASETMESSAGECONTENTMASK_DATASETWRITERID |
-             UA_JSONDATASETMESSAGECONTENTMASK_SEQUENCENUMBER |
-             UA_JSONDATASETMESSAGECONTENTMASK_STATUS |
-             UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION |
-             UA_JSONDATASETMESSAGECONTENTMASK_TIMESTAMP);
-
-        messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
-        messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE];
-        messageSettings.content.decoded.data = &jsonDswMd;
-
-        dataSetWriterConfig.messageSettings = messageSettings;
-    }
-#endif
-    /*TODO: Modify MQTT send to add DataSetWriters broker transport settings */
-    /*TODO: Pass the topic as argument from the writer group */
-    /*TODO: Publish Metadata to metaDataQueueName */
-    /* configure the mqtt publish topic */
-    UA_BrokerDataSetWriterTransportDataType brokerTransportSettings;
-    memset(&brokerTransportSettings, 0, sizeof(UA_BrokerDataSetWriterTransportDataType));
-
-    /* Assign the Topic at which MQTT publish should happen */
-    brokerTransportSettings.queueName = UA_STRING(topic);
-    brokerTransportSettings.resourceUri = UA_STRING_NULL;
-    brokerTransportSettings.authenticationProfileUri = UA_STRING_NULL;
-    brokerTransportSettings.metaDataQueueName = UA_STRING(PUBLISHER_METADATAQUEUENAME);
-    brokerTransportSettings.metaDataUpdateTime = PUBLISHER_METADATAUPDATETIME;
-
-    /* Choose the QOS Level for MQTT */
-    brokerTransportSettings.requestedDeliveryGuarantee = UA_BROKERTRANSPORTQUALITYOFSERVICE_BESTEFFORT;
-
-    /* Encapsulate config in transportSettings */
-    UA_ExtensionObject transportSettings;
-    memset(&transportSettings, 0, sizeof(UA_ExtensionObject));
-    transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
-    transportSettings.content.decoded.type = &UA_TYPES[UA_TYPES_BROKERDATASETWRITERTRANSPORTDATATYPE];
-    transportSettings.content.decoded.data = &brokerTransportSettings;
-
-    dataSetWriterConfig.transportSettings = transportSettings;
-    UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
-                               &dataSetWriterConfig, &dataSetWriterIdent);
-}
-
-/**
- * That's it! You're now publishing the selected fields. Open a packet
- * inspection tool of trust e.g. wireshark and take a look on the outgoing
- * packages. The following graphic figures out the packages created by this
- * tutorial.
- *
- * .. figure:: ua-wireshark-pubsub.png
- *     :figwidth: 100 %
- *     :alt: OPC UA PubSub communication in wireshark
- *
- * The open62541 subscriber API will be released later. If you want to process
- * the the datagrams, take a look on the ua_network_pubsub_networkmessage.c
- * which already contains the decoding code for UADP messages.
- *
- * It follows the main server code, making use of the above definitions. */
-UA_Boolean running = true;
-static void stopHandler(int sign) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
-    running = false;
-}
-
-static void usage(void) {
-    printf("Usage: tutorial_pubsub_mqtt [--url <opc.mqtt://hostname:port>] "
-           "[--topic <mqttTopic>] "
-           "[--freq <frequency in ms> "
-           "[--json]\n"
-           "  Defaults are:\n"
-           "  - Url: opc.mqtt://127.0.0.1:1883\n"
-           "  - Topic: customTopic\n"
-           "  - Frequency: 500\n"
-           "  - JSON: Off\n");
-}
-
-int main(int argc, char **argv) {
-    signal(SIGINT, stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    /* TODO: Change to secure mqtt port:8883 */
-    char *addressUrl = BROKER_ADDRESS_URL;
-    char *topic = PUBLISHER_TOPIC;
-    int interval = PUBLISH_INTERVAL;
-
-    /* Parse arguments */
-    for(int argpos = 1; argpos < argc; argpos++) {
-        if(strcmp(argv[argpos], "--help") == 0) {
-            usage();
-            return 0;
-        }
-
-        if(strcmp(argv[argpos], "--json") == 0) {
-            useJson = true;
-            continue;
-        }
-
-        if(strcmp(argv[argpos], "--url") == 0) {
-            if(argpos + 1 == argc) {
-                usage();
-                return -1;
-            }
-            argpos++;
-            addressUrl = argv[argpos];
-            continue;
-        }
-
-        if(strcmp(argv[argpos], "--topic") == 0) {
-            if(argpos + 1 == argc) {
-                usage();
-                return -1;
-            }
-            argpos++;
-            topic = argv[argpos];
-            continue;
-        }
-
-        if(strcmp(argv[argpos], "--freq") == 0) {
-            if(argpos + 1 == argc) {
-                usage();
-                return -1;
-            }
-            if(sscanf(argv[argpos], "%d", &interval) != 1) {
-                usage();
-                return -1;
-            }
-            if(interval <= 10) {
-                UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                               "Publication interval too small");
-                return -1;
-            }
-            continue;
-        }
-
-        usage();
-        return -1;
-    }
-
-    /* Set up the server config */
-    UA_Server *server = UA_Server_new();
-    UA_ServerConfig *config = UA_Server_getConfig(server);
-    /* Details about the connection configuration and handling are located in
-     * the pubsub connection tutorial */
-    UA_ServerConfig_setDefault(config);
-     config->pubsubTransportLayers = (UA_PubSubTransportLayer *)
-         UA_malloc(1 * sizeof(UA_PubSubTransportLayer));
-    if(!config->pubsubTransportLayers) {
-        return -1;
-    }
-    config->pubsubTransportLayers[0] = UA_PubSubTransportLayerMQTT();
-    config->pubsubTransportLayersSize++;
-
-    addPubSubConnection(server, addressUrl);
-    addPublishedDataSet(server);
-    addDataSetField(server);
-    addWriterGroup(server, topic, interval);
-    addDataSetWriter(server, topic);
-    UA_PubSubConnection *connection = UA_PubSubConnection_findConnectionbyId(server, connectionIdent);
-
-    if(!connection) {
-        UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                       "Could not create a PubSubConnection");
-        UA_Server_delete(server);
-        return -1;
-    }
-
-    UA_Server_run(server, &running);
-    UA_Server_delete(server);
-    return 0;
-}
-

+ 1 - 16
examples/pubsub/tutorial_pubsub_publish.c

@@ -46,9 +46,7 @@ addPubSubConnection(UA_Server *server, UA_String *transportProfile,
     connectionConfig.enabled = UA_TRUE;
     UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
                          &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
-    /* Changed to static publisherId from random generation to identify
-     * the publisher on Subscriber side */
-    connectionConfig.publisherId.numeric = 2234;
+    connectionConfig.publisherId.numeric = UA_UInt32_random();
     UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
 }
 
@@ -108,24 +106,11 @@ addWriterGroup(UA_Server *server) {
     writerGroupConfig.enabled = UA_FALSE;
     writerGroupConfig.writerGroupId = 100;
     writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
-    writerGroupConfig.messageSettings.encoding             = UA_EXTENSIONOBJECT_DECODED;
-    writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
     /* The configuration flags for the messages are encapsulated inside the
      * message- and transport settings extension objects. These extension
      * objects are defined by the standard. e.g.
      * UadpWriterGroupMessageDataType */
-    UA_UadpWriterGroupMessageDataType *writerGroupMessage  = UA_UadpWriterGroupMessageDataType_new();
-    /* Change message settings of writerGroup to send PublisherId,
-     * WriterGroupId in GroupHeader and DataSetWriterId in PayloadHeader
-     * of NetworkMessage */
-    writerGroupMessage->networkMessageContentMask          = (UA_UadpNetworkMessageContentMask)(UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID |
-                                                              (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER |
-                                                              (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID |
-                                                              (UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER);
-    writerGroupConfig.messageSettings.content.decoded.data = writerGroupMessage;
     UA_Server_addWriterGroup(server, connectionIdent, &writerGroupConfig, &writerGroupIdent);
-    UA_Server_setWriterGroupOperational(server, writerGroupIdent);
-    UA_UadpWriterGroupMessageDataType_delete(writerGroupMessage);
 }
 
 /**

+ 23 - 60
examples/pubsub/tutorial_pubsub_subscribe.c

@@ -35,15 +35,14 @@ UA_DataSetReaderConfig readerConfig;
 static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData);
 
 /* Add new connection to the server */
-static UA_StatusCode
+static void
 addPubSubConnection(UA_Server *server, UA_String *transportProfile,
                     UA_NetworkAddressUrlDataType *networkAddressUrl) {
     if((server == NULL) || (transportProfile == NULL) ||
         (networkAddressUrl == NULL)) {
-        return UA_STATUSCODE_BADINTERNALERROR;
+        return;
     }
 
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
     /* Configuration creation for the connection */
     UA_PubSubConnectionConfig connectionConfig;
     memset (&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
@@ -51,69 +50,49 @@ addPubSubConnection(UA_Server *server, UA_String *transportProfile,
     connectionConfig.transportProfileUri = *transportProfile;
     connectionConfig.enabled = UA_TRUE;
     UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
-                         &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
+                          &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
     connectionConfig.publisherId.numeric = UA_UInt32_random ();
-    retval |= UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier);
-    if (retval != UA_STATUSCODE_GOOD) {
-        return retval;
-    }
-    retval |= UA_PubSubConnection_regist(server, &connectionIdentifier);
-    return retval;
+    UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier);
 }
 
 /* Add ReaderGroup to the created connection */
-static UA_StatusCode
+static void
 addReaderGroup(UA_Server *server) {
     if(server == NULL) {
-        return UA_STATUSCODE_BADINTERNALERROR;
+        return;
     }
 
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_ReaderGroupConfig readerGroupConfig;
     memset (&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig));
     readerGroupConfig.name = UA_STRING("ReaderGroup1");
-    retval |= UA_Server_addReaderGroup(server, connectionIdentifier, &readerGroupConfig,
-                                       &readerGroupIdentifier);
-    return retval;
+    UA_Server_addReaderGroup(server, connectionIdentifier, &readerGroupConfig,
+                                        &readerGroupIdentifier);
 }
 
 /* Add DataSetReader to the ReaderGroup */
-static UA_StatusCode
+static void
 addDataSetReader(UA_Server *server) {
     if(server == NULL) {
-        return UA_STATUSCODE_BADINTERNALERROR;
+        return;
     }
 
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
     memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
     readerConfig.name = UA_STRING("DataSet Reader 1");
-    /* Parameters to filter which DataSetMessage has to be processed
-     * by the DataSetReader */
-    /* The following parameters are used to show that the data published by
-     * tutorial_pubsub_publish.c is being subscribed and is being updated in
-     * the information model */
-    UA_UInt16 publisherIdentifier = 2234;
-    readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
-    readerConfig.publisherId.data = &publisherIdentifier;
-    readerConfig.writerGroupId    = 100;
-    readerConfig.dataSetWriterId  = 62541;
+    readerConfig.dataSetWriterId = 1;
 
     /* Setting up Meta data configuration in DataSetReader */
     fillTestDataSetMetaData(&readerConfig.dataSetMetaData);
-    retval |= UA_Server_addDataSetReader(server, readerGroupIdentifier, &readerConfig,
-                                         &readerIdentifier);
-    return retval;
+    UA_Server_addDataSetReader(server, readerGroupIdentifier, &readerConfig,
+                                          &readerIdentifier);
 }
 
 /* Set SubscribedDataSet type to TargetVariables data type
  * Add subscribedvariables to the DataSetReader */
-static UA_StatusCode
-addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
+static void addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
     if(server == NULL) {
-        return UA_STATUSCODE_BADINTERNALERROR;
+        return;
     }
 
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
     UA_NodeId folderId;
     UA_String folderName = readerConfig.dataSetMetaData.name;
     UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
@@ -135,11 +114,10 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
                              folderBrowseName, UA_NODEID_NUMERIC (0,
                              UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
 
-    retval |= UA_Server_DataSetReader_addTargetVariables (server, &folderId,
-                                                          dataSetReaderId,
-                                                          UA_PUBSUB_SDS_TARGET);
+    UA_Server_DataSetReader_addTargetVariables (server, &folderId,
+                                               dataSetReaderId,
+                                               UA_PUBSUB_SDS_TARGET);
     UA_free(readerConfig.dataSetMetaData.fields);
-    return retval;
 }
 
 /* Define MetaData for TargetVariables */
@@ -202,7 +180,7 @@ run(UA_String *transportProfile, UA_NetworkAddressUrlDataType *networkAddressUrl
     signal(SIGINT, stopHandler);
     signal(SIGTERM, stopHandler);
     /* Return value initialized to Status Good */
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    UA_StatusCode retval;
     UA_Server *server = UA_Server_new();
     UA_ServerConfig *config = UA_Server_getConfig(server);
     UA_ServerConfig_setMinimal(config, 4801, NULL);
@@ -226,25 +204,10 @@ run(UA_String *transportProfile, UA_NetworkAddressUrlDataType *networkAddressUrl
 #endif
 
     /* API calls */
-    /* Add PubSubConnection */
-    retval |= addPubSubConnection(server, transportProfile, networkAddressUrl);
-    if (retval != UA_STATUSCODE_GOOD)
-        return EXIT_FAILURE;
-
-    /* Add ReaderGroup to the created PubSubConnection */
-    retval |= addReaderGroup(server);
-    if (retval != UA_STATUSCODE_GOOD)
-        return EXIT_FAILURE;
-
-    /* Add DataSetReader to the created ReaderGroup */
-    retval |= addDataSetReader(server);
-    if (retval != UA_STATUSCODE_GOOD)
-        return EXIT_FAILURE;
-
-    /* Add SubscribedVariables to the created DataSetReader */
-    retval |= addSubscribedVariables(server, readerIdentifier);
-    if (retval != UA_STATUSCODE_GOOD)
-        return EXIT_FAILURE;
+    addPubSubConnection(server, transportProfile, networkAddressUrl);
+    addReaderGroup(server);
+    addDataSetReader(server);
+    addSubscribedVariables(server, readerIdentifier);
 
     retval = UA_Server_run(server, &running);
     UA_Server_delete(server);

+ 14 - 53
examples/pubsub_realtime/pubsub_interrupt_publish.c

@@ -28,7 +28,7 @@
 
 UA_NodeId counterNodePublisher = {1, UA_NODEIDTYPE_NUMERIC, {1234}};
 UA_Int64 pubIntervalNs;
-UA_ServerCallback pubCallback = NULL; /* Sentinel if a timer is active */
+UA_ServerCallback pubCallback = NULL;
 UA_Server *pubServer;
 UA_Boolean running = true;
 void *pubData;
@@ -43,26 +43,6 @@ struct timespec cycleStartDelay[MAX_MEASUREMENTS+1];
 struct timespec cycleDuration[MAX_MEASUREMENTS+1];
 size_t publisherMeasurementsCounter  = 0;
 
-/* The RT level of the publisher */
-//#define PUBSUB_RT_LEVEL UA_PUBSUB_RT_NONE
-//#define PUBSUB_RT_LEVEL UA_PUBSUB_RT_DIRECT_VALUE_ACCESS
-#define PUBSUB_RT_LEVEL UA_PUBSUB_RT_FIXED_SIZE
-
-/* The value to published */
-static UA_UInt64 publishValue = 62541;
-
-static UA_StatusCode
-readPublishValue(UA_Server *server,
-                const UA_NodeId *sessionId, void *sessionContext,
-                const UA_NodeId *nodeId, void *nodeContext,
-                UA_Boolean sourceTimeStamp, const UA_NumericRange *range,
-                UA_DataValue *dataValue) {
-    UA_Variant_setScalarCopy(&dataValue->value, &publishValue,
-                             &UA_TYPES[UA_TYPES_UINT64]);
-    dataValue->hasValue = true;
-    return UA_STATUSCODE_GOOD;
-}
-
 static void
 timespec_diff(struct timespec *start, struct timespec *stop,
               struct timespec *result) {
@@ -164,6 +144,9 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
 
     /* Set global values for the publish callback */
     int resultTimerCreate = 0;
+    pubServer = server;
+    pubCallback = callback;
+    pubData = data;
     pubIntervalNs = (UA_Int64) (interval_ms * MILLI_AS_NANO_SECONDS);
 
     /* Handle the signal */
@@ -181,8 +164,7 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
     resultTimerCreate = timer_create(CLOCKID, &pubEvent, &pubEventTimer);
     if(resultTimerCreate != 0) {
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                       "Failed to create a system event with code %s",
-                       strerror(errno));
+                       "Failed to create a system event");
         return UA_STATUSCODE_BADINTERNALERROR;
     }
 
@@ -195,7 +177,7 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
     resultTimerCreate = timer_settime(pubEventTimer, 0, &timerspec, NULL);
     if(resultTimerCreate != 0) {
         UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                       "Failed to arm the system timer with code %i", resultTimerCreate);
+                       "Failed to arm the system timer");
         timer_delete(pubEventTimer);
         return UA_STATUSCODE_BADINTERNALERROR;
     }
@@ -206,11 +188,6 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
     calculatedCycleStartTime[0].tv_nsec += pubIntervalNs;
     nanoSecondFieldConversion(&calculatedCycleStartTime[0]);
 
-    /* Set the callback -- used as a sentinel to detect an operational publisher */
-    pubServer = server;
-    pubCallback = callback;
-    pubData = data;
-
     return UA_STATUSCODE_GOOD;
 }
 
@@ -224,7 +201,7 @@ UA_PubSubManager_changeRepeatedCallbackInterval(UA_Server *server,
     struct itimerspec timerspec;
     int resultTimerCreate = 0;
     pubIntervalNs = (UA_Int64) (interval_ms * MILLI_AS_NANO_SECONDS);
-    timerspec.it_interval.tv_sec = (long int) (pubIntervalNs / SECONDS_AS_NANO_SECONDS);
+    timerspec.it_interval.tv_sec = (long int) (pubIntervalNs % SECONDS_AS_NANO_SECONDS);
     timerspec.it_interval.tv_nsec = (long int) (pubIntervalNs % SECONDS_AS_NANO_SECONDS);
     timerspec.it_value.tv_sec = (long int) (pubIntervalNs / (SECONDS_AS_NANO_SECONDS));
     timerspec.it_value.tv_nsec = (long int) (pubIntervalNs % SECONDS_AS_NANO_SECONDS);
@@ -245,8 +222,6 @@ UA_PubSubManager_changeRepeatedCallbackInterval(UA_Server *server,
 
 void
 UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId) {
-    if(!pubCallback)
-        return;
     timer_delete(pubEventTimer);
     pubCallback = NULL; /* So that a new callback can be registered */
 }
@@ -285,14 +260,6 @@ addPubSubConfiguration(UA_Server* server) {
     counterValue.field.variable.promotedField = UA_FALSE;
     counterValue.field.variable.publishParameters.publishedVariable = counterNodePublisher;
     counterValue.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
-
-#if (PUBSUB_RT_LEVEL == UA_PUBSUB_RT_FIXED_SIZE) || (PUBSUB_RT_LEVEL == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS)
-    counterValue.field.variable.staticValueSourceEnabled = true;
-    UA_DataValue_init(&counterValue.field.variable.staticValueSource);
-    UA_Variant_setScalar(&counterValue.field.variable.staticValueSource.value,
-                         &publishValue, &UA_TYPES[UA_TYPES_UINT64]);
-    counterValue.field.variable.staticValueSource.value.storageType = UA_VARIANT_DATA_NODELETE;
-#endif
     UA_Server_addDataSetField(server, publishedDataSetIdent, &counterValue,
                               &dataSetFieldIdentCounter);
 
@@ -302,7 +269,6 @@ addPubSubConfiguration(UA_Server* server) {
     writerGroupConfig.publishingInterval = PUB_INTERVAL;
     writerGroupConfig.enabled = UA_FALSE;
     writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
-    writerGroupConfig.rtLevel = PUBSUB_RT_LEVEL;
     UA_Server_addWriterGroup(server, connectionIdent,
                              &writerGroupConfig, &writerGroupIdent);
 
@@ -314,9 +280,6 @@ addPubSubConfiguration(UA_Server* server) {
     dataSetWriterConfig.keyFrameCount = 10;
     UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
                                &dataSetWriterConfig, &dataSetWriterIdent);
-
-    UA_Server_freezeWriterGroupConfiguration(server, writerGroupIdent);
-    UA_Server_setWriterGroupOperational(server, writerGroupIdent);
 }
 
 static void
@@ -326,15 +289,12 @@ addServerNodes(UA_Server* server) {
     UA_Variant_setScalar(&publisherAttr.value, &publishValue, &UA_TYPES[UA_TYPES_UINT64]);
     publisherAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Publisher Counter");
     publisherAttr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
-    UA_DataSource dataSource;
-    dataSource.read = readPublishValue;
-    dataSource.write = NULL;
-    UA_Server_addDataSourceVariableNode(server, counterNodePublisher,
-                                        UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-                                        UA_QUALIFIEDNAME(1, "Publisher Counter"),
-                                        UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
-                                        publisherAttr, dataSource, NULL, NULL);
+    UA_Server_addVariableNode(server, counterNodePublisher,
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
+                              UA_QUALIFIEDNAME(1, "Publisher Counter"),
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                              publisherAttr, NULL, NULL);
 }
 
 /* Stop signal */
@@ -362,6 +322,7 @@ int main(void) {
     /* Run the server */
     UA_StatusCode retval = UA_Server_run(server, &running);
     UA_Server_delete(server);
+    UA_ServerConfig_delete(config);
 
     return (int)retval;
 }

+ 57 - 92
examples/server_ctt.c

@@ -122,7 +122,7 @@ readRandomInt32Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-
+    
 static UA_StatusCode
 readRandomInt64Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -143,7 +143,7 @@ readRandomInt64Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-
+    
 static UA_StatusCode
 readRandomUInt16Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -185,7 +185,7 @@ readRandomUInt32Data(UA_Server *server,
     }
     return UA_STATUSCODE_GOOD;
 }
-
+    
 static UA_StatusCode
 readRandomUInt64Data(UA_Server *server,
              const UA_NodeId *sessionId, void *sessionContext,
@@ -293,7 +293,7 @@ readByteString (UA_Server *server,
     }
    return UA_STATUSCODE_GOOD;
 }
-
+    
 /* Method Node Example */
 #ifdef UA_ENABLE_METHODCALLS
 
@@ -498,7 +498,7 @@ setInformationModel(UA_Server *server) {
 
         UA_VariableAttributes attr = UA_VariableAttributes_default;
         attr.dataType = UA_TYPES[type].typeId;
-#ifndef UA_ENABLE_TYPEDESCRIPTION
+#ifndef UA_ENABLE_TYPENAMES
         char name[15];
         UA_snprintf(name, 15, "%02d", type);
         attr.displayName = UA_LOCALIZEDTEXT("en-US", name);
@@ -547,7 +547,7 @@ setInformationModel(UA_Server *server) {
                                   UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), qualifiedName,
                                   baseDataVariableType, attr, NULL, NULL);
         UA_Variant_clear(&attr.value);
-#ifdef UA_ENABLE_TYPEDESCRIPTION
+#ifdef UA_ENABLE_TYPENAMES
         UA_LocalizedText_clear(&attr.displayName);
         UA_QualifiedName_clear(&qualifiedName);
 #endif
@@ -676,7 +676,7 @@ setInformationModel(UA_Server *server) {
 
         for(size_t j = 0; j < 100; j++) {
             char name[32];
-#ifndef UA_ENABLE_TYPEDESCRIPTION
+#ifndef UA_ENABLE_TYPENAMES
             UA_snprintf(name, 20, "%02d - %i", type, scale_i);
 #else
             UA_snprintf(name, 20, "%s - %i", UA_TYPES[type].typeName, scale_i);
@@ -948,11 +948,11 @@ usage(void) {
 #endif
                    "\t[--enableUnencrypted]\n"
                    "\t[--enableOutdatedSecurityPolicy]\n"
+                   "\t[--enableTimestampCheck]\n"
                    "\t[--disableBasic128]\n"
                    "\t[--disableBasic256]\n"
                    "\t[--disableBasic256Sha256]\n"
 #endif
-                   "\t[--enableTimestampCheck]\n"
                    "\t[--enableAnonymous]\n");
 }
 
@@ -1000,6 +1000,7 @@ int main(int argc, char **argv) {
     char filetype = ' '; /* t==trustlist, l == issuerList, r==revocationlist */
     UA_Boolean enableUnencr = false;
     UA_Boolean enableSec = false;
+    UA_Boolean enableTime = false;
     UA_Boolean disableBasic128 = false;
     UA_Boolean disableBasic256 = false;
     UA_Boolean disableBasic256Sha256 = false;
@@ -1015,12 +1016,11 @@ int main(int argc, char **argv) {
     const char *trustlistFolder = NULL;
     const char *issuerlistFolder = NULL;
     const char *revocationlistFolder = NULL;
-#endif /* __linux__ */
+#endif
 
-#endif /* UA_ENABLE_ENCRYPTION */
+#endif
 
     UA_Boolean enableAnon = false;
-    UA_Boolean enableTime = false;
 
     /* Loop over the remaining arguments */
     for(; pos < (size_t)argc; pos++) {
@@ -1030,11 +1030,6 @@ int main(int argc, char **argv) {
             continue;
         }
 
-        if(strcmp(argv[pos], "--enableTimestampCheck") == 0) {
-            enableTime = true;
-            continue;
-        }
-
 #ifdef UA_ENABLE_ENCRYPTION
         if(strcmp(argv[pos], "--enableUnencrypted") == 0) {
             enableUnencr = true;
@@ -1046,18 +1041,8 @@ int main(int argc, char **argv) {
             continue;
         }
 
-        if(strcmp(argv[pos], "--disableBasic128") == 0) {
-            disableBasic128 = true;
-            continue;
-        }
-
-        if(strcmp(argv[pos], "--disableBasic256") == 0) {
-            disableBasic256 = true;
-            continue;
-        }
-
-        if(strcmp(argv[pos], "--disableBasic256Sha256") == 0) {
-            disableBasic256Sha256 = true;
+        if(strcmp(argv[pos], "--enableTimestampCheck") == 0) {
+            enableTime = true;
             continue;
         }
 
@@ -1074,7 +1059,7 @@ int main(int argc, char **argv) {
         if(strcmp(argv[pos], "--disableBasic256Sha256") == 0) {
             disableBasic256Sha256 = true;
             continue;
-        }
+        }        
 
 #ifndef __linux__
         if(strcmp(argv[pos], "--trustlist") == 0) {
@@ -1139,7 +1124,7 @@ int main(int argc, char **argv) {
             revocationListSize++;
             continue;
         }
-#else /* __linux__ */
+#else
         if(strcmp(argv[pos], "--trustlistFolder") == 0) {
             filetype = 't';
             continue;
@@ -1169,40 +1154,30 @@ int main(int argc, char **argv) {
             revocationlistFolder = argv[pos];
             continue;
         }
-#endif /* __linux__ */
+#endif
 
-#endif /* UA_ENABLE_ENCRYPTION */
+#endif
 
         usage();
         return EXIT_FAILURE;
     }
 
-    UA_Server *server = NULL;
-
 #ifdef UA_ENABLE_ENCRYPTION
 #ifndef __linux__
-    UA_StatusCode res =
-        UA_ServerConfig_setDefaultWithSecurityPolicies(&config, 4840,
-                                                       &certificate, &privateKey,
-                                                       trustList, trustListSize,
-                                                       issuerList, issuerListSize,
-                                                       revocationList, revocationListSize);
-    if(res != UA_STATUSCODE_GOOD)
-        goto cleanup;
-#else /* On Linux we can monitor the certs folder and reload when changes are made */
-    UA_StatusCode res =
-        UA_ServerConfig_setDefaultWithSecurityPolicies(&config, 4840,
-                                                       &certificate, &privateKey,
-                                                       NULL, 0, NULL, 0, NULL, 0);
-    if(res != UA_STATUSCODE_GOOD)
-        goto cleanup;
-    config.certificateVerification.clear(&config.certificateVerification);
-    res = UA_CertificateVerification_CertFolders(&config.certificateVerification,
-                                                 trustlistFolder, issuerlistFolder,
-                                                 revocationlistFolder);
-    if(res != UA_STATUSCODE_GOOD)
-        goto cleanup;
-#endif /* __linux__ */
+    UA_ServerConfig_setDefaultWithSecurityPolicies(&config, 4840,
+                                                   &certificate, &privateKey,
+                                                   trustList, trustListSize,
+                                                   issuerList, issuerListSize,
+                                                   revocationList, revocationListSize);
+#else
+    UA_ServerConfig_setDefaultWithSecurityPolicies(&config, 4840,
+                                                   &certificate, &privateKey,
+                                                   NULL, 0, NULL, 0, NULL, 0);
+    config.certificateVerification.deleteMembers(&config.certificateVerification);
+    UA_CertificateVerification_CertFolders(&config.certificateVerification,
+                                           trustlistFolder, issuerlistFolder,
+                                           revocationlistFolder);
+#endif
 
     if(!enableUnencr)
         disableUnencrypted(&config);
@@ -1216,16 +1191,6 @@ int main(int argc, char **argv) {
     if(disableBasic256Sha256)
         disableBasic256Sha256SecurityPolicy(&config);
 
-#else /* UA_ENABLE_ENCRYPTION */
-    UA_StatusCode res =
-        UA_ServerConfig_setMinimal(&config, 4840, &certificate);
-    if(res != UA_STATUSCODE_GOOD)
-        goto cleanup;
-#endif /* UA_ENABLE_ENCRYPTION */
-
-    if(!enableAnon)
-        disableAnonymous(&config);
-
     /* Set operation limits */
     config.maxNodesPerRead = MAX_OPERATION_LIMIT;
     config.maxNodesPerWrite = MAX_OPERATION_LIMIT;
@@ -1238,9 +1203,29 @@ int main(int argc, char **argv) {
 
     /* If RequestTimestamp is '0', log the warning and proceed */
     config.verifyRequestTimestamp = UA_RULEHANDLING_WARN;
+
     if(enableTime)
         config.verifyRequestTimestamp = UA_RULEHANDLING_DEFAULT;
 
+#else
+    UA_ServerConfig_setMinimal(&config, 4840, &certificate);
+#endif
+
+    if(!enableAnon)
+        disableAnonymous(&config);
+
+    /* Clean up temp values */
+    UA_ByteString_clear(&certificate);
+#if defined(UA_ENABLE_ENCRYPTION) && !defined(__linux__)
+    UA_ByteString_clear(&privateKey);
+    for(size_t i = 0; i < trustListSize; i++)
+        UA_ByteString_clear(&trustList[i]);
+    for(size_t i = 0; i < issuerListSize; i++)
+        UA_ByteString_clear(&issuerList[i]);
+    for(size_t i = 0; i < revocationListSize; i++)
+        UA_ByteString_clear(&revocationList[i]);
+#endif
+
     /* Override with a custom access control policy */
     config.accessControl.getUserAccessLevel = getUserAccessLevel_disallowSpecific;
     UA_String_clear(&config.applicationDescription.applicationUri);
@@ -1249,35 +1234,15 @@ int main(int argc, char **argv) {
 
     config.shutdownDelay = 5000.0; /* 5s */
 
-    server = UA_Server_newWithConfig(&config);
-    if(!server) {
-        res = UA_STATUSCODE_BADINTERNALERROR;
-        goto cleanup;
-    }
+    UA_Server *server = UA_Server_newWithConfig(&config);
+    if(server == NULL)
+        return EXIT_FAILURE;
 
     setInformationModel(server);
 
     /* run server */
-    res = UA_Server_run(server, &running);
-
- cleanup:
-    if(server)
-        UA_Server_delete(server);
-    else
-        UA_ServerConfig_clean(&config);
-
-    UA_ByteString_clear(&certificate);
-#if defined(UA_ENABLE_ENCRYPTION)
-    UA_ByteString_clear(&privateKey);
-#ifndef __linux__
-    for(size_t i = 0; i < trustListSize; i++)
-        UA_ByteString_clear(&trustList[i]);
-    for(size_t i = 0; i < issuerListSize; i++)
-        UA_ByteString_clear(&issuerList[i]);
-    for(size_t i = 0; i < revocationListSize; i++)
-        UA_ByteString_clear(&revocationList[i]);
-#endif
-#endif
+    UA_StatusCode retval = UA_Server_run(server, &running);
 
-    return res == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
+    UA_Server_delete(server);
+    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
 }

+ 0 - 7
examples/tutorial_client_events.c

@@ -8,7 +8,6 @@
 #include <open62541/plugin/log_stdout.h>
 #include <open62541/server.h>
 #include <open62541/server_config_default.h>
-#include <open62541/util.h>
 
 #include <signal.h>
 
@@ -51,14 +50,8 @@ handler_events(UA_Client *client, UA_UInt32 subId, void *subContext,
                         "Message: '%.*s'", (int)lt->text.length, lt->text.data);
         }
         else {
-#ifdef UA_ENABLE_TYPEDESCRIPTION
             UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                         "Don't know how to handle type: '%s'", eventFields[i].type->typeName);
-#else
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
-                        "Don't know how to handle type, enable UA_ENABLE_TYPEDESCRIPTION "
-                        "for typename");
-#endif
         }
     }
 }

+ 0 - 232
examples/tutorial_server_method_async.c

@@ -1,232 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
-
-/**
- * Adding Async Methods to Objects
- * -------------------------
- *
- * An object in an OPC UA information model may contain methods similar to
- * objects in a programming language. Methods are represented by a MethodNode.
- * Note that several objects may reference the same MethodNode. When an object
- * type is instantiated, a reference to the method is added instead of copying
- * the MethodNode. Therefore, the identifier of the context object is always
- * explicitly stated when a method is called.
- *
- * The method callback takes as input a custom data pointer attached to the
- * method node, the identifier of the object from which the method is called,
- * and two arrays for the input and output arguments. The input and output
- * arguments are all of type :ref:`variant`. Each variant may in turn contain a
- * (multi-dimensional) array or scalar of any data type.
- *
- * Constraints for the method arguments are defined in terms of data type, value
- * rank and array dimension (similar to variable definitions). The argument
- * definitions are stored in child VariableNodes of the MethodNode with the
- * respective BrowseNames ``(0, "InputArguments")`` and ``(0,
- * "OutputArguments")``.
- *
- * Example: Hello World Method
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- * The method takes a string scalar and returns a string scalar with "Hello "
- * prepended. The type and length of the input arguments is checked internally
- * by the SDK, so that we don't have to verify the arguments in the callback. */
-
-#include <open62541/client_config_default.h>
-#include <open62541/plugin/log_stdout.h>
-#include <open62541/server.h>
-#include <open62541/server_config_default.h>
-
-#include <signal.h>
-#include <stdlib.h>
-
-#ifndef WIN32
-#include <pthread.h>
-#define THREAD_HANDLE pthread_t
-#define THREAD_CREATE(handle, callback) pthread_create(&handle, NULL, callback, NULL)
-#define THREAD_JOIN(handle) pthread_join(handle, NULL)
-#define THREAD_CALLBACK(name) static void * name(void *_)
-#else
-#include <windows.h>
-#define THREAD_HANDLE HANDLE
-#define THREAD_CREATE(handle, callback) { handle = CreateThread( NULL, 0, callback, NULL, 0, NULL); }
-#define THREAD_JOIN(handle) WaitForSingleObject(handle, INFINITE)
-#define THREAD_CALLBACK(name) static DWORD WINAPI name( LPVOID lpParam )
-#endif
-
-static UA_Server* globalServer;
-static volatile UA_Boolean running = true;
-
-static void stopHandler(int sign) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
-    running = false;
-}
-
-static UA_StatusCode
-helloWorldMethodCallback1(UA_Server *server,
-                         const UA_NodeId *sessionId, void *sessionHandle,
-                         const UA_NodeId *methodId, void *methodContext,
-                         const UA_NodeId *objectId, void *objectContext,
-                         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 = (UA_Byte *)UA_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]);   
-    char* test = (char*)calloc(1,tmp.length+1);
-    memcpy(test, tmp.data, tmp.length);    
-    UA_String_clear(&tmp);
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "'Hello World 1 (async)' was called and will take 3 seconds");
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "    Data 1: %s", test);
-    free(test);
-	UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "'Hello World 1 (async)' has ended");
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-addHellWorldMethod1(UA_Server *server) {
-    UA_Argument inputArgument;
-    UA_Argument_init(&inputArgument);
-    inputArgument.description = UA_LOCALIZEDTEXT("en-US", "A String");
-    inputArgument.name = UA_STRING("MyInput");
-    inputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-    inputArgument.valueRank = UA_VALUERANK_SCALAR;
-
-    UA_Argument outputArgument;
-    UA_Argument_init(&outputArgument);
-    outputArgument.description = UA_LOCALIZEDTEXT("en-US", "A String");
-    outputArgument.name = UA_STRING("MyOutput");
-    outputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-    outputArgument.valueRank = UA_VALUERANK_SCALAR;
-
-    UA_MethodAttributes helloAttr = UA_MethodAttributes_default;
-    helloAttr.description = UA_LOCALIZEDTEXT("en-US","Say `Hello World` async");
-    helloAttr.displayName = UA_LOCALIZEDTEXT("en-US","Hello World async");
-    helloAttr.executable = true;
-    helloAttr.userExecutable = true;
-    UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1,62541),
-                            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
-                            UA_QUALIFIEDNAME(1, "hello world"),
-                            helloAttr, &helloWorldMethodCallback1,
-                            1, &inputArgument, 1, &outputArgument, NULL, NULL);	
-	/* Get the method node */
-	UA_NodeId id = UA_NODEID_NUMERIC(1, 62541);
-	UA_Server_setMethodNodeAsync(server, id, UA_TRUE);	
-}
-
-static UA_StatusCode
-helloWorldMethodCallback2(UA_Server *server,
-	const UA_NodeId *sessionId, void *sessionHandle,
-	const UA_NodeId *methodId, void *methodContext,
-	const UA_NodeId *objectId, void *objectContext,
-	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 = (UA_Byte *)UA_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]);
-    char* test = (char*)calloc(1, tmp.length + 1);
-    memcpy(test, tmp.data, tmp.length);
-	UA_String_clear(&tmp);
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "'Hello World 2 (async)' was called and will take 1 seconds");
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "    Data 2: %s", test);
-    free(test);
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "'Hello World 2 (async)' has ended");
-	return UA_STATUSCODE_GOOD;
-}
-
-static void
-addHellWorldMethod2(UA_Server *server) {
-	UA_Argument inputArgument;
-	UA_Argument_init(&inputArgument);
-	inputArgument.description = UA_LOCALIZEDTEXT("en-US", "A String");
-	inputArgument.name = UA_STRING("MyInput");
-	inputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-	inputArgument.valueRank = UA_VALUERANK_SCALAR;
-
-	UA_Argument outputArgument;
-	UA_Argument_init(&outputArgument);
-	outputArgument.description = UA_LOCALIZEDTEXT("en-US", "A String");
-	outputArgument.name = UA_STRING("MyOutput");
-	outputArgument.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-	outputArgument.valueRank = UA_VALUERANK_SCALAR;
-
-	UA_MethodAttributes helloAttr = UA_MethodAttributes_default;
-	helloAttr.description = UA_LOCALIZEDTEXT("en-US", "Say `Hello World` sync");
-	helloAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Hello World sync");
-	helloAttr.executable = true;
-	helloAttr.userExecutable = true;
-	UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1, 62542),
-		UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-		UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
-		UA_QUALIFIEDNAME(1, "hello world 2"),
-		helloAttr, &helloWorldMethodCallback2,
-		1, &inputArgument, 1, &outputArgument, NULL, NULL);
-	/* Get the method node */
-	UA_NodeId id = UA_NODEID_NUMERIC(1, 62542);
-	UA_Server_setMethodNodeAsync(server, id, UA_TRUE);
-}
-
-THREAD_CALLBACK(ThreadWorker) {
-    while(running) {
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
-                    "Try to dequeue an async operation");
-        const UA_AsyncOperationRequest* request = NULL;
-        void *context = NULL;
-        UA_AsyncOperationType type;
-        if(UA_Server_getAsyncOperationNonBlocking(globalServer, &type, &request, &context, NULL) == true) {
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AsyncMethod_Testing: Got entry: OKAY");
-            UA_CallMethodResult response = UA_Server_call(globalServer, &request->callMethodRequest);
-            UA_Server_setAsyncOperationResult(globalServer, (UA_AsyncOperationResponse*)&response,
-                                              context);
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "AsyncMethod_Testing: Call done: OKAY");
-            UA_CallMethodResult_clear(&response);
-        } else {
-            /* not a good style, but done for simplicity :-) */
-            Sleep(5000);
-        }
-    }
-    return 0;
-}
-
-/* This callback will be called when a new entry is added to the Callrequest queue */
-static void
-TestCallback(UA_Server *server) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
-                "Dispatched an async method");
-}
-
-int main(void) {
-    signal(SIGINT, stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    globalServer = UA_Server_new();
-    UA_ServerConfig *config = UA_Server_getConfig(globalServer);
-    UA_ServerConfig_setDefault(config);
-
-    /* Set the NotifyCallback */
-    config->asyncOperationNotifyCallback = TestCallback;
-
-    /* Start the Worker-Thread */
-    THREAD_HANDLE hThread;
-    THREAD_CREATE(hThread, ThreadWorker);
-    
-    /* Add methods */
-    addHellWorldMethod1(globalServer);
-	addHellWorldMethod2(globalServer);
-
-    UA_StatusCode retval = UA_Server_run(globalServer, &running);
-
-    /* Shutdown the thread */
-    THREAD_JOIN(hThread);
-
-    UA_Server_delete(globalServer);
-    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
-}

+ 0 - 35
examples/tutorial_server_variable.c

@@ -42,35 +42,6 @@ addVariable(UA_Server *server) {
                               UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL);
 }
 
-static void
-addMatrixVariable(UA_Server *server) {
-    UA_VariableAttributes attr = UA_VariableAttributes_default;
-    attr.displayName = UA_LOCALIZEDTEXT("en-US", "Double Matrix");
-    attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
-
-    /* Set the variable value constraints */
-    attr.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId;
-    attr.valueRank = UA_VALUERANK_TWO_DIMENSIONS;
-    UA_UInt32 arrayDims[2] = {2,2};
-    attr.arrayDimensions = arrayDims;
-    attr.arrayDimensionsSize = 2;
-
-    /* Set the value. The array dimensions need to be the same for the value. */
-    UA_Double zero[4] = {0.0, 0.0, 0.0, 0.0};
-    UA_Variant_setArray(&attr.value, zero, 4, &UA_TYPES[UA_TYPES_DOUBLE]);
-    attr.value.arrayDimensions = arrayDims;
-    attr.value.arrayDimensionsSize = 2;
-
-    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "double.matrix");
-    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "double matrix");
-    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
-    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-    UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
-                              parentReferenceNodeId, myIntegerName,
-                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
-                              attr, NULL, NULL);
-}
-
 /**
  * Now we change the value with the write service. This uses the same service
  * implementation that can also be reached over the network by an OPC UA client.
@@ -140,14 +111,8 @@ int main(void) {
 
     UA_Server *server = UA_Server_new();
     UA_ServerConfig_setDefault(UA_Server_getConfig(server));
-    UA_ServerConfig* config = UA_Server_getConfig(server);
-    config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-    UA_ServerConfig_addNetworkLayerWS(UA_Server_getConfig(server), 7681, 0, 0);
-#endif
 
     addVariable(server);
-    addMatrixVariable(server);
     writeVariable(server);
     writeWrongVariable(server);
 

+ 49 - 53
include/open62541/architecture_definitions.h

@@ -10,8 +10,6 @@
 #ifndef ARCH_UA_ARCHITECTURE_DEFINITIONS_H_
 #define ARCH_UA_ARCHITECTURE_DEFINITIONS_H_
 
-#include <open62541/config.h>
-
 /**
  * C99 Definitions
  * --------------- */
@@ -93,8 +91,6 @@
 # define UA_EXPORT /* fallback to default */
 #endif
 
-#define UA_THREADSAFE
-
 /**
  * Inline Functions
  * ---------------- */
@@ -277,101 +273,101 @@ UA_STATIC_ASSERT(sizeof(bool) == 1, cannot_overlay_integers_with_large_bool);
  * Atomic operations that synchronize across processor cores (for
  * multithreading). Only the inline-functions defined next are used. Replace
  * with architecture-specific operations if necessary. */
-#if UA_MULTITHREADING >= 200
-    #ifdef _MSC_VER /* Visual Studio */
-    #define UA_atomic_sync() _ReadWriteBarrier()
-    #else /* GCC/Clang */
-    #define UA_atomic_sync() __sync_synchronize()
-    #endif
+#ifndef UA_ENABLE_MULTITHREADING
+# define UA_atomic_sync()
 #else
-    #define UA_atomic_sync()
+# ifdef _MSC_VER /* Visual Studio */
+#  define UA_atomic_sync() _ReadWriteBarrier()
+# else /* GCC/Clang */
+#  define UA_atomic_sync() __sync_synchronize()
+# endif
 #endif
 
 static UA_INLINE void *
 UA_atomic_xchg(void * volatile * addr, void *newptr) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedExchangePointer(addr, newptr);
-#else /* GCC/Clang */
-    return __sync_lock_test_and_set(addr, newptr);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     void *old = *addr;
     *addr = newptr;
     return old;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedExchangePointer(addr, newptr);
+# else /* GCC/Clang */
+    return __sync_lock_test_and_set(addr, newptr);
+# endif
 #endif
 }
 
 static UA_INLINE void *
 UA_atomic_cmpxchg(void * volatile * addr, void *expected, void *newptr) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedCompareExchangePointer(addr, expected, newptr);
-#else /* GCC/Clang */
-    return __sync_val_compare_and_swap(addr, expected, newptr);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     void *old = *addr;
     if(old == expected) {
         *addr = newptr;
     }
     return old;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedCompareExchangePointer(addr, expected, newptr);
+# else /* GCC/Clang */
+    return __sync_val_compare_and_swap(addr, expected, newptr);
+# endif
 #endif
 }
 
 static UA_INLINE uint32_t
 UA_atomic_addUInt32(volatile uint32_t *addr, uint32_t increase) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedExchangeAdd(addr, increase) + increase;
-#else /* GCC/Clang */
-    return __sync_add_and_fetch(addr, increase);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     *addr += increase;
     return *addr;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedExchangeAdd(addr, increase) + increase;
+# else /* GCC/Clang */
+    return __sync_add_and_fetch(addr, increase);
+# endif
 #endif
 }
 
 static UA_INLINE size_t
 UA_atomic_addSize(volatile size_t *addr, size_t increase) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedExchangeAdd(addr, increase) + increase;
-#else /* GCC/Clang */
-    return __sync_add_and_fetch(addr, increase);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     *addr += increase;
     return *addr;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedExchangeAdd(addr, increase) + increase;
+# else /* GCC/Clang */
+    return __sync_add_and_fetch(addr, increase);
+# endif
 #endif
 }
 
 static UA_INLINE uint32_t
 UA_atomic_subUInt32(volatile uint32_t *addr, uint32_t decrease) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedExchangeSub(addr, decrease) - decrease;
-#else /* GCC/Clang */
-    return __sync_sub_and_fetch(addr, decrease);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     *addr -= decrease;
     return *addr;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedExchangeSub(addr, decrease) - decrease;
+# else /* GCC/Clang */
+    return __sync_sub_and_fetch(addr, decrease);
+# endif
 #endif
 }
 
 static UA_INLINE size_t
 UA_atomic_subSize(volatile size_t *addr, size_t decrease) {
-#if UA_MULTITHREADING >= 200
-#ifdef _MSC_VER /* Visual Studio */
-    return _InterlockedExchangeSub(addr, decrease) - decrease;
-#else /* GCC/Clang */
-    return __sync_sub_and_fetch(addr, decrease);
-#endif
-#else
+#ifndef UA_ENABLE_MULTITHREADING
     *addr -= decrease;
     return *addr;
+#else
+    # ifdef _MSC_VER /* Visual Studio */
+    return _InterlockedExchangeSub(addr, decrease) - decrease;
+# else /* GCC/Clang */
+    return __sync_sub_and_fetch(addr, decrease);
+# endif
 #endif
 }
 

+ 2 - 10
include/open62541/client.h

@@ -48,17 +48,9 @@ _UA_BEGIN_DECLS
  * Client Lifecycle
  * ---------------- */
 
-/* The method UA_Client_new is defined in client_config_default.h. So default
- * plugins outside of the core library (for logging, etc) are already available
- * during the initialization.
- *
- * UA_Client UA_EXPORT * UA_Client_new(void);
- */
-
-/* Creates a new client. Moves the config into the client with a shallow copy.
- * The config content is cleared together with the client. */
+/* Create a new client */
 UA_Client UA_EXPORT *
-UA_Client_newWithConfig(const UA_ClientConfig *config);
+UA_Client_new(void);
 
 /* Get the client connection status */
 UA_ClientState UA_EXPORT

+ 0 - 4
include/open62541/client_config.h

@@ -55,10 +55,6 @@ typedef struct {
     void *clientContext; /* User-defined data attached to the client */
     UA_Logger logger;   /* Logger used by the client */
     UA_UInt32 timeout;  /* Response timeout in ms */
-
-    /* The description must be internally consistent.
-     * - The ApplicationUri set in the ApplicationDescription must match the
-     *   URI set in the server certificate */
     UA_ApplicationDescription clientDescription;
 
     /* Basic connection configuration */

+ 1 - 72
include/open62541/client_subscriptions.h

@@ -69,33 +69,13 @@ UA_Client_Subscriptions_create(UA_Client *client,
                                UA_Client_StatusChangeNotificationCallback statusChangeCallback,
                                UA_Client_DeleteSubscriptionCallback deleteCallback);
 
-UA_StatusCode UA_EXPORT
-UA_Client_Subscriptions_create_async(
-    UA_Client *client, const UA_CreateSubscriptionRequest request,
-    void *subscriptionContext,
-    UA_Client_StatusChangeNotificationCallback statusChangeCallback,
-    UA_Client_DeleteSubscriptionCallback deleteCallback,
-    UA_ClientAsyncServiceCallback callback, void *userdata, UA_UInt32 *requestId);
-
 UA_ModifySubscriptionResponse UA_EXPORT
 UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionRequest request);
 
-UA_StatusCode UA_EXPORT
-UA_Client_Subscriptions_modify_async(UA_Client *client,
-                                     const UA_ModifySubscriptionRequest request,
-                                     UA_ClientAsyncServiceCallback callback,
-                                     void *userdata, UA_UInt32 *requestId);
-
 UA_DeleteSubscriptionsResponse UA_EXPORT
 UA_Client_Subscriptions_delete(UA_Client *client,
                                const UA_DeleteSubscriptionsRequest request);
 
-UA_StatusCode UA_EXPORT
-UA_Client_Subscriptions_delete_async(UA_Client *client,
-                                     const UA_DeleteSubscriptionsRequest request,
-                                     UA_ClientAsyncServiceCallback callback,
-                                     void *userdata, UA_UInt32 *requestId);
-
 /* Delete a single subscription */
 UA_StatusCode UA_EXPORT
 UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId);
@@ -164,13 +144,6 @@ UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
             UA_Client_DataChangeNotificationCallback *callbacks,
             UA_Client_DeleteMonitoredItemCallback *deleteCallbacks);
 
-UA_StatusCode UA_EXPORT
-UA_Client_MonitoredItems_createDataChanges_async(
-    UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
-    UA_Client_DataChangeNotificationCallback *callbacks,
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId);
-
 UA_MonitoredItemCreateResult UA_EXPORT
 UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
           UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
@@ -184,14 +157,6 @@ UA_Client_MonitoredItems_createEvents(UA_Client *client,
             UA_Client_EventNotificationCallback *callback,
             UA_Client_DeleteMonitoredItemCallback *deleteCallback);
 
-/* Monitor the EventNotifier attribute only */
-UA_StatusCode UA_EXPORT
-UA_Client_MonitoredItems_createEvents_async(
-    UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
-    UA_Client_EventNotificationCallback *callbacks,
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId);
-
 UA_MonitoredItemCreateResult UA_EXPORT
 UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId,
           UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
@@ -202,14 +167,7 @@ UA_DeleteMonitoredItemsResponse UA_EXPORT
 UA_Client_MonitoredItems_delete(UA_Client *client, const UA_DeleteMonitoredItemsRequest);
 
 UA_StatusCode UA_EXPORT
-UA_Client_MonitoredItems_delete_async(UA_Client *client,
-                                      const UA_DeleteMonitoredItemsRequest request,
-                                      UA_ClientAsyncServiceCallback callback,
-                                      void *userdata, UA_UInt32 *requestId);
-
-UA_StatusCode UA_EXPORT
-UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId,
-                                      UA_UInt32 monitoredItemId);
+UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId, UA_UInt32 monitoredItemId);
 
 /* The clientHandle parameter will be filled automatically */
 UA_ModifyMonitoredItemsResponse UA_EXPORT
@@ -240,35 +198,6 @@ UA_Client_MonitoredItems_setTriggering(UA_Client *client,
     return response;
 }
 
-static UA_INLINE UA_StatusCode
-UA_Client_MonitoredItems_modify_async(UA_Client *client,
-                                      const UA_ModifyMonitoredItemsRequest request,
-                                      UA_ClientAsyncServiceCallback callback,
-                                      void *userdata, UA_UInt32 *requestId) {
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], callback,
-        &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], userdata, requestId);
-}
-
-static UA_INLINE UA_StatusCode
-UA_Client_MonitoredItems_setMonitoringMode_async(
-    UA_Client *client, const UA_SetMonitoringModeRequest request,
-    UA_ClientAsyncServiceCallback callback, void *userdata, UA_UInt32 *requestId) {
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST], callback,
-        &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE], userdata, requestId);
-}
-
-static UA_INLINE UA_StatusCode
-UA_Client_MonitoredItems_setTriggering_async(UA_Client *client,
-                                             const UA_SetTriggeringRequest request,
-                                             UA_ClientAsyncServiceCallback callback,
-                                             void *userdata, UA_UInt32 *requestId) {
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST], callback,
-        &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE], userdata, requestId);
-}
-
 #endif
 
 _UA_END_DECLS

+ 4 - 8
include/open62541/config.h.in

@@ -38,23 +38,22 @@
 #cmakedefine UA_ENABLE_EXPERIMENTAL_HISTORIZING
 #cmakedefine UA_ENABLE_SUBSCRIPTIONS_EVENTS
 #cmakedefine UA_ENABLE_JSON_ENCODING
-#cmakedefine UA_ENABLE_PUBSUB_MQTT
 
 /* Multithreading */
+#cmakedefine UA_ENABLE_MULTITHREADING
 #cmakedefine UA_ENABLE_IMMUTABLE_NODES
-#define UA_MULTITHREADING ${UA_MULTITHREADING}
-#if UA_MULTITHREADING >= 200 && !defined(UA_ENABLE_IMMUTABLE_NODES)
+#if defined(UA_ENABLE_MULTITHREADING) && !defined(UA_ENABLE_IMMUTABLE_NODES)
 #error "The multithreading feature requires nodes to be immutable"
 #endif
 
 /* Advanced Options */
+#cmakedefine UA_ENABLE_CUSTOM_NODESTORE
 #cmakedefine UA_ENABLE_STATUSCODE_DESCRIPTIONS
-#cmakedefine UA_ENABLE_TYPEDESCRIPTION
+#cmakedefine UA_ENABLE_TYPENAMES
 #cmakedefine UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
 #cmakedefine UA_ENABLE_DETERMINISTIC_RNG
 #cmakedefine UA_ENABLE_DISCOVERY
 #cmakedefine UA_ENABLE_DISCOVERY_MULTICAST
-#cmakedefine UA_ENABLE_WEBSOCKET_SERVER
 #cmakedefine UA_ENABLE_QUERY
 #cmakedefine UA_ENABLE_MALLOC_SINGLETON
 #cmakedefine UA_ENABLE_DISCOVERY_SEMAPHORE
@@ -103,9 +102,6 @@
 # endif
 #endif
 
-// specific architectures can undef this
-#define UA_HAS_GETIFADDR
-
 #include "${UA_ARCHITECTURE}/ua_architecture.h"
 
 #endif /* UA_CONFIG_H_ */

+ 1 - 2
include/open62541/constants.h

@@ -50,8 +50,7 @@ typedef enum {
     UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL = 19,
     UA_ATTRIBUTEID_HISTORIZING             = 20,
     UA_ATTRIBUTEID_EXECUTABLE              = 21,
-    UA_ATTRIBUTEID_USEREXECUTABLE          = 22,
-    UA_ATTRIBUTEID_DATATYPEDEFINITION      = 23
+    UA_ATTRIBUTEID_USEREXECUTABLE          = 22
 } UA_AttributeId;
 
 /**

+ 0 - 22
include/open62541/network_ws.h

@@ -1,22 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. 
- *
- *    Copyright 2016 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- */
-
-#ifndef UA_NETWORK_WS_H_
-#define UA_NETWORK_WS_H_
-
-#include <open62541/client.h>
-#include <open62541/plugin/log.h>
-#include <open62541/server.h>
-
-_UA_BEGIN_DECLS
-
-UA_ServerNetworkLayer UA_EXPORT
-UA_ServerNetworkLayerWS(UA_ConnectionConfig config, UA_UInt16 port, UA_Logger *logger);
-
-
-_UA_END_DECLS
-
-#endif /* UA_NETWORK_WS_H_ */

+ 1 - 1
include/open62541/plugin/accesscontrol.h

@@ -26,7 +26,7 @@ typedef struct UA_AccessControl UA_AccessControl;
 
 struct UA_AccessControl {
     void *context;
-    void (*clear)(UA_AccessControl *ac);
+    void (*deleteMembers)(UA_AccessControl *ac);
 
     /* Supported login mechanisms. The server endpoints are created from here. */
     size_t userTokenPoliciesSize;

+ 3 - 50
include/open62541/plugin/historydatabase.h

@@ -17,7 +17,8 @@ typedef struct UA_HistoryDatabase UA_HistoryDatabase;
 struct UA_HistoryDatabase {
     void *context;
 
-    void (*clear)(UA_HistoryDatabase *hdb);
+    void
+    (*deleteMembers)(UA_HistoryDatabase *hdb);
 
     /* This function will be called when a nodes value is set.
      * Use this to insert data into your database(s) if polling is not suitable
@@ -75,54 +76,6 @@ struct UA_HistoryDatabase {
                UA_HistoryReadResponse *response,
                UA_HistoryData * const * const historyData);
 
-    /* No default implementation is provided by UA_HistoryDatabase_default
-     * for the following function */
-    void
-    (*readModified)(UA_Server *server,
-               void *hdbContext,
-               const UA_NodeId *sessionId,
-               void *sessionContext,
-               const UA_RequestHeader *requestHeader,
-               const UA_ReadRawModifiedDetails *historyReadDetails,
-               UA_TimestampsToReturn timestampsToReturn,
-               UA_Boolean releaseContinuationPoints,
-               size_t nodesToReadSize,
-               const UA_HistoryReadValueId *nodesToRead,
-               UA_HistoryReadResponse *response,
-               UA_HistoryModifiedData * const * const historyData);
-
-    /* No default implementation is provided by UA_HistoryDatabase_default
-     * for the following function */
-    void
-    (*readProcessed)(UA_Server *server,
-               void *hdbContext,
-               const UA_NodeId *sessionId,
-               void *sessionContext,
-               const UA_RequestHeader *requestHeader,
-               const UA_ReadProcessedDetails *historyReadDetails,
-               UA_TimestampsToReturn timestampsToReturn,
-               UA_Boolean releaseContinuationPoints,
-               size_t nodesToReadSize,
-               const UA_HistoryReadValueId *nodesToRead,
-               UA_HistoryReadResponse *response,
-               UA_HistoryData * const * const historyData);
-
-    /* No default implementation is provided by UA_HistoryDatabase_default
-     * for the following function */
-    void
-    (*readAtTime)(UA_Server *server,
-               void *hdbContext,
-               const UA_NodeId *sessionId,
-               void *sessionContext,
-               const UA_RequestHeader *requestHeader,
-               const UA_ReadAtTimeDetails *historyReadDetails,
-               UA_TimestampsToReturn timestampsToReturn,
-               UA_Boolean releaseContinuationPoints,
-               size_t nodesToReadSize,
-               const UA_HistoryReadValueId *nodesToRead,
-               UA_HistoryReadResponse *response,
-               UA_HistoryData * const * const historyData);
-
     void
     (*updateData)(UA_Server *server,
                   void *hdbContext,
@@ -142,7 +95,7 @@ struct UA_HistoryDatabase {
                          UA_HistoryUpdateResult *result);
 
     /* Add more function pointer here.
-     * For example for read_event, read_annotation, update_details */
+     * For example for read_event, read_modified, read_processed, read_at_time */
 };
 
 _UA_END_DECLS

+ 0 - 24
include/open62541/plugin/log.h

@@ -68,10 +68,6 @@ UA_LOG_TRACE(const UA_Logger *logger, UA_LogCategory category, const char *msg,
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_TRACE, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 
@@ -83,10 +79,6 @@ UA_LOG_DEBUG(const UA_Logger *logger, UA_LogCategory category, const char *msg,
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_DEBUG, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 
@@ -98,10 +90,6 @@ UA_LOG_INFO(const UA_Logger *logger, UA_LogCategory category, const char *msg, .
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_INFO, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 
@@ -113,10 +101,6 @@ UA_LOG_WARNING(const UA_Logger *logger, UA_LogCategory category, const char *msg
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_WARNING, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 
@@ -128,10 +112,6 @@ UA_LOG_ERROR(const UA_Logger *logger, UA_LogCategory category, const char *msg,
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_ERROR, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 
@@ -143,10 +123,6 @@ UA_LOG_FATAL(const UA_Logger *logger, UA_LogCategory category, const char *msg,
     va_list args; va_start(args, msg);
     logger->log(logger->context, UA_LOGLEVEL_FATAL, category, msg, args);
     va_end(args);
-#else
-    (void) logger;
-    (void) category;
-    (void) msg;
 #endif
 }
 

+ 2 - 2
include/open62541/plugin/network.h

@@ -114,7 +114,7 @@ struct UA_Connection {
 
 /* Cleans up half-received messages, and so on. Called from connection->free. */
 void UA_EXPORT
-UA_Connection_clear(UA_Connection *connection);
+UA_Connection_deleteMembers(UA_Connection *connection);
 
 /**
  * Server Network Layer
@@ -184,7 +184,7 @@ struct UA_ServerNetworkLayer {
     void (*stop)(UA_ServerNetworkLayer *nl, UA_Server *server);
 
     /* Deletes the network layer context. Call only after stopping. */
-    void (*clear)(UA_ServerNetworkLayer *nl);
+    void (*deleteMembers)(UA_ServerNetworkLayer *nl);
 };
 
 /**

+ 62 - 52
include/open62541/plugin/nodestore.h

@@ -248,9 +248,6 @@ typedef struct {
 
     /* Members specific to open62541 */
     UA_MethodCallback method;
-#if UA_MULTITHREADING >= 100
-    UA_Boolean async; /* Indicates an async method call */
-#endif
 } UA_MethodNode;
 
 /**
@@ -446,52 +443,65 @@ typedef struct {
  * nodes. Please use the OPC UA services for that. Otherwise, all consistency
  * checks are omitted. This can crash the application eventually. */
 
-typedef void (*UA_NodestoreVisitor)(void *visitorCtx, const UA_Node *node);
+/* For non-multithreaded access, some nodestores allow that nodes are edited
+ * without a copy/replace. This is not possible when the node is only an
+ * intermediate representation and stored e.g. in a database backend. */
+extern const UA_Boolean inPlaceEditAllowed;
 
-typedef struct {
-    /* Nodestore context and lifecycle */
-    void *context;
-    void (*clear)(void *nsCtx);
-
-    /* The following definitions are used to create empty nodes of the different
-     * node types. The memory is managed by the nodestore. Therefore, the node
-     * has to be removed via a special deleteNode function. (If the new node is
-     * not added to the nodestore.) */
-    UA_Node * (*newNode)(void *nsCtx, UA_NodeClass nodeClass);
-
-    void (*deleteNode)(void *nsCtx, UA_Node *node);
-
-    /* ``Get`` returns a pointer to an immutable node. ``Release`` indicates
-     * that the pointer is no longer accessed afterwards. */
-    const UA_Node * (*getNode)(void *nsCtx, const UA_NodeId *nodeId);
-
-    void (*releaseNode)(void *nsCtx, const UA_Node *node);
-
-    /* Returns an editable copy of a node (needs to be deleted with the
-     * deleteNode function or inserted / replaced into the nodestore). */
-    UA_StatusCode (*getNodeCopy)(void *nsCtx, const UA_NodeId *nodeId,
-                                 UA_Node **outNode);
-
-    /* Inserts a new node into the nodestore. If the NodeId is zero, then a
-     * fresh numeric NodeId is assigned. If insertion fails, the node is
-     * deleted. */
-    UA_StatusCode (*insertNode)(void *nsCtx, UA_Node *node,
-                                UA_NodeId *addedNodeId);
-
-    /* To replace a node, get an editable copy of the node, edit and replace
-     * with this function. If the node was already replaced since the copy was
-     * made, UA_STATUSCODE_BADINTERNALERROR is returned. If the NodeId is not
-     * found, UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases,
-     * the editable node is deleted. */
-    UA_StatusCode (*replaceNode)(void *nsCtx, UA_Node *node);
-
-    /* Removes a node from the nodestore. */
-    UA_StatusCode (*removeNode)(void *nsCtx, const UA_NodeId *nodeId);
-
-    /* Execute a callback for every node in the nodestore. */
-    void (*iterate)(void *nsCtx, UA_NodestoreVisitor visitor,
-                    void *visitorCtx);
-} UA_Nodestore;
+/* Nodestore context and lifecycle */
+UA_StatusCode UA_Nodestore_new(void **nsCtx);
+void UA_Nodestore_delete(void *nsCtx);
+
+/**
+ * The following definitions are used to create empty nodes of the different
+ * node types. The memory is managed by the nodestore. Therefore, the node has
+ * to be removed via a special deleteNode function. (If the new node is not
+ * added to the nodestore.) */
+
+UA_Node *
+UA_Nodestore_newNode(void *nsCtx, UA_NodeClass nodeClass);
+
+void
+UA_Nodestore_deleteNode(void *nsCtx, UA_Node *node);
+
+/**
+ *``Get`` returns a pointer to an immutable node. ``Release`` indicates that the
+ * pointer is no longer accessed afterwards. */
+
+const UA_Node *
+UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId);
+
+void
+UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node);
+
+/* Returns an editable copy of a node (needs to be deleted with the
+ * deleteNode function or inserted / replaced into the nodestore). */
+UA_StatusCode
+UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
+                         UA_Node **outNode);
+
+/* Inserts a new node into the nodestore. If the NodeId is zero, then a fresh
+ * numeric NodeId is assigned. If insertion fails, the node is deleted. */
+UA_StatusCode
+UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId);
+
+/* To replace a node, get an editable copy of the node, edit and replace with
+ * this function. If the node was already replaced since the copy was made,
+ * UA_STATUSCODE_BADINTERNALERROR is returned. If the NodeId is not found,
+ * UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases, the editable
+ * node is deleted. */
+UA_StatusCode
+UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node);
+
+/* Removes a node from the nodestore. */
+UA_StatusCode
+UA_Nodestore_removeNode(void *nsCtx, const UA_NodeId *nodeId);
+
+/* Execute a callback for every node in the nodestore. */
+typedef void (*UA_NodestoreVisitor)(void *visitorCtx, const UA_Node *node);
+void
+UA_Nodestore_iterate(void *nsCtx, UA_NodestoreVisitor visitor,
+                     void *visitorCtx);
 
 /**
  * Node Handling
@@ -504,8 +514,8 @@ typedef struct {
 /* Attributes must be of a matching type (VariableAttributes, ObjectAttributes,
  * and so on). The attributes are copied. Note that the attributes structs do
  * not contain NodeId, NodeClass and BrowseName. The NodeClass of the node needs
- * to be correctly set before calling this method. UA_Node_clear is called on
- * the node when an error occurs internally. */
+ * to be correctly set before calling this method. UA_Node_deleteMembers is
+ * called on the node when an error occurs internally. */
 UA_StatusCode UA_EXPORT
 UA_Node_setAttributes(UA_Node *node, const void *attributes,
                       const UA_DataType *attributeType);
@@ -530,9 +540,9 @@ UA_Node_deleteReference(UA_Node *node, const UA_DeleteReferencesItem *item);
 void UA_EXPORT
 UA_Node_deleteReferences(UA_Node *node);
 
-/* Remove all malloc'ed members of the node and reset */
+/* Remove all malloc'ed members of the node */
 void UA_EXPORT
-UA_Node_clear(UA_Node *node);
+UA_Node_deleteMembers(UA_Node *node);
 
 _UA_END_DECLS
 

+ 3 - 2
include/open62541/plugin/pki.h

@@ -27,7 +27,8 @@ _UA_BEGIN_DECLS
  * Usually, implementations of the certificate verification plugin provide an
  * initialization method that takes a trust-list and a revocation-list as input.
  * The lifecycle of the plugin is attached to a server or client config. The
- * ``clear`` method is called automatically when the config is destroyed. */
+ * ``deleteMembers`` method is called automatically when the config is
+ * destroyed. */
 
 struct UA_CertificateVerification;
 typedef struct UA_CertificateVerification UA_CertificateVerification;
@@ -45,7 +46,7 @@ struct UA_CertificateVerification {
                                           const UA_String *applicationURI);
 
     /* Delete the certificate verification context */
-    void (*clear)(UA_CertificateVerification *cv);
+    void (*deleteMembers)(UA_CertificateVerification *cv);
 };
 
 _UA_END_DECLS

+ 1 - 1
include/open62541/plugin/securitypolicy.h

@@ -358,7 +358,7 @@ struct UA_SecurityPolicy {
                                                     const UA_ByteString newPrivateKey);
 
     /* Deletes the dynamic content of the policy */
-    void (*clear)(UA_SecurityPolicy *policy);
+    void (*deleteMembers)(UA_SecurityPolicy *policy);
 };
 
 /* Gets the number of bytes that are needed by the encryption function in

+ 90 - 178
include/open62541/server.h

@@ -42,14 +42,9 @@ struct UA_Client;
  * Server Lifecycle
  * ---------------- */
 
-/* The method UA_Server_new is defined in server_config_default.h. So default
- * plugins outside of the core library (for logging, etc) are already available
- * during the initialization.
- *
- * UA_Server UA_EXPORT * UA_Server_new(void);
- */
+UA_Server UA_EXPORT * UA_Server_new(void);
 
-/* Creates a new server. Moves the config into the server with a shallow copy.
+/* Makes a (shallow) copy of the config into the server object.
  * The config content is cleared together with the server. */
 UA_Server UA_EXPORT *
 UA_Server_newWithConfig(const UA_ServerConfig *config);
@@ -108,7 +103,7 @@ typedef void (*UA_ServerCallback)(UA_Server *server, void *data);
  *        identifier is not set.
  * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code
  *         otherwise. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
                            void *data, UA_DateTime date, UA_UInt64 *callbackId);
 
@@ -125,11 +120,11 @@ UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
  *        identifier is not set.
  * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code
  *         otherwise. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
                               void *data, UA_Double interval_ms, UA_UInt64 *callbackId);
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
                                          UA_Double interval_ms);
 
@@ -137,7 +132,7 @@ UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId
  *
  * @param server The server object.
  * @param callbackId The id of the callback */
-void UA_EXPORT UA_THREADSAFE
+void UA_EXPORT
 UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId);
 
 #define UA_Server_removeRepeatedCallback(server, callbackId) \
@@ -166,106 +161,106 @@ UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId);
  * @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_THREADSAFE
+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_THREADSAFE
+UA_StatusCode UA_EXPORT
 __UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
                  UA_AttributeId attributeId, void *v);
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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,
@@ -273,21 +268,21 @@ UA_Server_readValueRank(UA_Server *server, const UA_NodeId nodeId,
 }
 
 /* Returns a variant with an int32 array */
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_readAccessLevel(UA_Server *server, const UA_NodeId nodeId,
                           UA_Byte *outAccessLevel) {
     return __UA_Server_read(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
                             outAccessLevel);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_readMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
                                       UA_Double *outMinimumSamplingInterval) {
     return __UA_Server_read(server, &nodeId,
@@ -295,14 +290,14 @@ UA_Server_readMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId,
                             outMinimumSamplingInterval);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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,
@@ -335,101 +330,101 @@ UA_Server_readExecutable(UA_Server *server, const UA_NodeId nodeId,
  *              See the section on NumericRange for the format used for array
  *              ranges.
  * @return Returns a status code. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+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_THREADSAFE
+UA_StatusCode UA_EXPORT
 __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
                   const UA_AttributeId attributeId,
                   const UA_DataType *attr_type, const void *attr);
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeDataType(UA_Server *server, const UA_NodeId nodeId,
                         const UA_NodeId dataType) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_DATATYPE,
                              &UA_TYPES[UA_TYPES_NODEID], &dataType);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeValueRank(UA_Server *server, const UA_NodeId nodeId,
                          const UA_Int32 valueRank) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_VALUERANK,
                              &UA_TYPES[UA_TYPES_INT32], &valueRank);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeArrayDimensions(UA_Server *server, const UA_NodeId nodeId,
                                const UA_Variant arrayDimensions) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
                              &UA_TYPES[UA_TYPES_VARIANT], &arrayDimensions);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeAccessLevel(UA_Server *server, const UA_NodeId nodeId,
                            const UA_Byte accessLevel) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
                              &UA_TYPES[UA_TYPES_BYTE], &accessLevel);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+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,
@@ -438,7 +433,7 @@ UA_Server_writeMinimumSamplingInterval(UA_Server *server, const UA_NodeId nodeId
                              &miniumSamplingInterval);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeHistorizing(UA_Server *server, const UA_NodeId nodeId,
                           const UA_Boolean historizing) {
     return __UA_Server_write(server, &nodeId,
@@ -447,7 +442,7 @@ UA_Server_writeHistorizing(UA_Server *server, const UA_NodeId nodeId,
                              &historizing);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
                           const UA_Boolean executable) {
     return __UA_Server_write(server, &nodeId, UA_ATTRIBUTEID_EXECUTABLE,
@@ -459,22 +454,22 @@ UA_Server_writeExecutable(UA_Server *server, const UA_NodeId nodeId,
 
 /* Browse the references of a particular node. See the definition of
  * BrowseDescription structure for details. */
-UA_BrowseResult UA_EXPORT UA_THREADSAFE
+UA_BrowseResult UA_EXPORT
 UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
                  const UA_BrowseDescription *bd);
 
-UA_BrowseResult UA_EXPORT UA_THREADSAFE
+UA_BrowseResult UA_EXPORT
 UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
                      const UA_ByteString *continuationPoint);
 
 /* Nonstandard version of the browse service that recurses into child nodes.
  * Possible loops (that can occur for non-hierarchical references) are handled
  * by adding every target node at most once to the results array. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
                           size_t *resultsSize, UA_ExpandedNodeId **results);
 
-UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
+UA_BrowsePathResult UA_EXPORT
 UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
                                        const UA_BrowsePath *browsePath);
 
@@ -486,7 +481,7 @@ UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
  * RelativePath that specifies forward references which are subtypes of the
  * HierarchicalReferences ReferenceType. All Nodes followed by the browsePath
  * shall be of the NodeClass Object or Variable. */
-UA_BrowsePathResult UA_EXPORT UA_THREADSAFE
+UA_BrowsePathResult UA_EXPORT
 UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
                                      size_t browsePathSize,
                                      const UA_QualifiedName *browsePath);
@@ -501,7 +496,7 @@ typedef UA_StatusCode
                            UA_NodeId referenceTypeId, void *handle);
 #endif
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
                                UA_NodeIteratorCallback callback, void *handle);
 
@@ -522,7 +517,7 @@ UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
  * @param client the client which is used to call the RegisterServer. It must
  *        already be connected to the correct endpoint
  * @param semaphoreFilePath optional parameter pointing to semaphore file. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_register_discovery(UA_Server *server, struct UA_Client *client,
                              const char* semaphoreFilePath);
 
@@ -531,7 +526,7 @@ UA_Server_register_discovery(UA_Server *server, struct UA_Client *client,
  * @param server
  * @param client the client which is used to call the RegisterServer. It must
  *        already be connected to the correct endpoint */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_unregister_discovery(UA_Server *server, struct UA_Client *client);
 
  /* Adds a periodic callback to register the server with the LDS (local discovery server)
@@ -557,7 +552,7 @@ UA_Server_unregister_discovery(UA_Server *server, struct UA_Client *client);
   * @param intervalMs
   * @param delayFirstRegisterMs
   * @param periodicCallbackId */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addPeriodicServerRegisterCallback(UA_Server *server, struct UA_Client *client,
                                             const char* discoveryServerUrl,
                                             UA_Double intervalMs,
@@ -577,7 +572,7 @@ typedef void (*UA_Server_registerServerCallback)(const UA_RegisteredServer *regi
  * @param cb the callback
  * @param data data passed to the callback
  * @return UA_STATUSCODE_SUCCESS on success */
-void UA_EXPORT UA_THREADSAFE
+void UA_EXPORT
 UA_Server_setRegisterServerCallback(UA_Server *server, UA_Server_registerServerCallback cb,
                                     void* data);
 
@@ -605,7 +600,7 @@ typedef void (*UA_Server_serverOnNetworkCallback)(const UA_ServerOnNetwork *serv
  * @param cb the callback
  * @param data data passed to the callback
  * @return UA_STATUSCODE_SUCCESS on success */
-void UA_EXPORT UA_THREADSAFE
+void UA_EXPORT
 UA_Server_setServerOnNetworkCallback(UA_Server *server,
                                      UA_Server_serverOnNetworkCallback cb,
                                      void* data);
@@ -734,16 +729,16 @@ typedef struct {
                        const UA_NodeId *nodeId, void **nodeContext);
 } UA_NodeTypeLifecycle;
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
                                UA_NodeTypeLifecycle lifecycle);
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
                          void **nodeContext);
 
 /* Careful! The user has to ensure that the destructor callbacks still work. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
                          void *nodeContext);
 
@@ -826,7 +821,7 @@ typedef struct {
                            const UA_DataValue *value);
 } UA_DataSource;
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
                                      const UA_DataSource dataSource);
 
@@ -873,7 +868,7 @@ typedef struct {
                     const UA_DataValue *data);
 } UA_ValueCallback;
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_setVariableNode_valueCallback(UA_Server *server,
                                         const UA_NodeId nodeId,
                                         const UA_ValueCallback callback);
@@ -915,7 +910,7 @@ typedef void (*UA_Server_EventNotificationCallback)
  * @return Returns a description of the created MonitoredItem. The structure
  * also contains a StatusCode (in case of an error) and the identifier of the
  * new MonitoredItem. */
-UA_MonitoredItemCreateResult UA_EXPORT UA_THREADSAFE
+UA_MonitoredItemCreateResult UA_EXPORT
 UA_Server_createDataChangeMonitoredItem(UA_Server *server,
           UA_TimestampsToReturn timestampsToReturn,
           const UA_MonitoredItemCreateRequest item,
@@ -928,7 +923,7 @@ UA_Server_createDataChangeMonitoredItem(UA_Server *server,
 /*           const UA_MonitoredItemCreateRequest item, void *context, */
 /*           UA_Server_EventNotificationCallback callback); */
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId);
 
 #endif
@@ -951,7 +946,7 @@ typedef UA_StatusCode
                      UA_Variant *output);
 
 #ifdef UA_ENABLE_METHODCALLS
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_setMethodNode_callback(UA_Server *server,
                                  const UA_NodeId methodNodeId,
                                  UA_MethodCallback methodCallback);
@@ -976,13 +971,13 @@ UA_Server_setMethodNode_callback(UA_Server *server,
  * @param propertyName The name of the property
  * @param value The value to be set for the event attribute
  * @return The StatusCode for setting the event attribute */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
                               const UA_QualifiedName propertyName,
                               const UA_Variant value);
 
 /* Directly point to the scalar value instead of a variant */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId,
                                      const UA_QualifiedName propertyName,
                                      const void *value, const UA_DataType *type);
@@ -994,13 +989,13 @@ UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId
  * @param propertyName The name of the property
  * @param value Contains the property value after reading. Must not be NULL.
  * @return The StatusCode for setting the event attribute */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
                              const UA_QualifiedName propertyName,
                              UA_Variant *value);
 
 #ifdef UA_ENABLE_METHODCALLS
-UA_CallMethodResult UA_EXPORT UA_THREADSAFE
+UA_CallMethodResult UA_EXPORT
 UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request);
 #endif
 
@@ -1047,7 +1042,7 @@ UA_EXPORT extern const UA_ViewAttributes UA_ViewAttributes_default;
 #endif
 
 /* Don't use this function. There are typed versions as inline functions. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
                     const UA_NodeId *requestedNewNodeId,
                     const UA_NodeId *parentNodeId,
@@ -1058,7 +1053,7 @@ __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
                     const UA_DataType *attributeType,
                     void *nodeContext, UA_NodeId *outNewNodeId);
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                           const UA_NodeId parentNodeId,
                           const UA_NodeId referenceTypeId,
@@ -1073,7 +1068,7 @@ UA_Server_addVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addVariableTypeNode(UA_Server *server,
                               const UA_NodeId requestedNewNodeId,
                               const UA_NodeId parentNodeId,
@@ -1090,7 +1085,7 @@ UA_Server_addVariableTypeNode(UA_Server *server,
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                         const UA_NodeId parentNodeId,
                         const UA_NodeId referenceTypeId,
@@ -1105,7 +1100,7 @@ UA_Server_addObjectNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                             const UA_NodeId parentNodeId,
                             const UA_NodeId referenceTypeId,
@@ -1119,7 +1114,7 @@ UA_Server_addObjectTypeNode(UA_Server *server, const UA_NodeId requestedNewNodeI
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                       const UA_NodeId parentNodeId,
                       const UA_NodeId referenceTypeId,
@@ -1133,7 +1128,7 @@ UA_Server_addViewNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addReferenceTypeNode(UA_Server *server,
                                const UA_NodeId requestedNewNodeId,
                                const UA_NodeId parentNodeId,
@@ -1149,7 +1144,7 @@ UA_Server_addReferenceTypeNode(UA_Server *server,
                                nodeContext, outNewNodeId);
 }
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 UA_Server_addDataTypeNode(UA_Server *server,
                           const UA_NodeId requestedNewNodeId,
                           const UA_NodeId parentNodeId,
@@ -1164,7 +1159,7 @@ UA_Server_addDataTypeNode(UA_Server *server,
                                nodeContext, outNewNodeId);
 }
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addDataSourceVariableNode(UA_Server *server,
                                     const UA_NodeId requestedNewNodeId,
                                     const UA_NodeId parentNodeId,
@@ -1177,7 +1172,7 @@ UA_Server_addDataSourceVariableNode(UA_Server *server,
 
 #ifdef UA_ENABLE_METHODCALLS
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
                           const UA_NodeId parentNodeId,
                           const UA_NodeId referenceTypeId,
@@ -1191,7 +1186,7 @@ UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
                           UA_NodeId *outputArgumentsOutNewNodeId,
                           void *nodeContext, UA_NodeId *outNewNodeId);
 
-static UA_INLINE UA_THREADSAFE UA_StatusCode
+static UA_INLINE UA_StatusCode
 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,
@@ -1242,7 +1237,7 @@ UA_Server_addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
  * ``VariableAttributes`` for variables, ``ObjectAttributes`` for objects, and
  * so on. Missing attributes are taken from the TypeDefinition node if
  * applicable. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
                         const UA_NodeId requestedNewNodeId,
                         const UA_NodeId parentNodeId,
@@ -1252,12 +1247,12 @@ UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
                         const void *attr, const UA_DataType *attributeType,
                         void *nodeContext, UA_NodeId *outNewNodeId);
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId);
 
 #ifdef UA_ENABLE_METHODCALLS
 
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
                          UA_MethodCallback method,
                          size_t inputArgumentsSize, const UA_Argument* inputArguments,
@@ -1266,19 +1261,19 @@ UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
 #endif
 
 /* Deletes a node and optionally all references leading to the node. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
                      UA_Boolean deleteReferences);
 
 /**
  * Reference Management
  * -------------------- */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 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_THREADSAFE
+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,
@@ -1320,7 +1315,7 @@ UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
  * @param eventType The type of the event for which a node should be created
  * @param outNodeId The NodeId of the newly created node for the event
  * @return The StatusCode of the UA_Server_createEvent method */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
                       UA_NodeId *outNodeId);
 
@@ -1331,7 +1326,7 @@ UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
  * @param outEvent the EventId of the new event
  * @param deleteEventNode Specifies whether the node representation of the event should be deleted
  * @return The StatusCode of the UA_Server_triggerEvent method */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, const UA_NodeId originId,
                        UA_ByteString *outEventId, const UA_Boolean deleteEventNode);
 
@@ -1349,22 +1344,22 @@ UA_Server_updateCertificate(UA_Server *server,
  * Utility Functions
  * ----------------- */
 /* Add a new namespace to the server. Returns the index of the new namespace */
-UA_UInt16 UA_EXPORT UA_THREADSAFE UA_Server_addNamespace(UA_Server *server, const char* name);
+UA_UInt16 UA_EXPORT UA_Server_addNamespace(UA_Server *server, const char* name);
 
 /* Get namespace by name from the server. */
-UA_StatusCode UA_EXPORT UA_THREADSAFE
+UA_StatusCode UA_EXPORT
 UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
                              size_t* foundIndex);
 
 #ifdef UA_ENABLE_HISTORIZING
-UA_Boolean UA_EXPORT UA_THREADSAFE
+UA_Boolean UA_EXPORT
 UA_Server_AccessControl_allowHistoryUpdateUpdateData(UA_Server *server,
                                                      const UA_NodeId *sessionId, void *sessionContext,
                                                      const UA_NodeId *nodeId,
                                                      UA_PerformUpdateType performInsertReplace,
                                                      const UA_DataValue *value);
 
-UA_Boolean UA_EXPORT UA_THREADSAFE
+UA_Boolean UA_EXPORT
 UA_Server_AccessControl_allowHistoryUpdateDeleteRawModified(UA_Server *server,
                                                             const UA_NodeId *sessionId, void *sessionContext,
                                                             const UA_NodeId *nodeId,
@@ -1373,89 +1368,6 @@ UA_Server_AccessControl_allowHistoryUpdateDeleteRawModified(UA_Server *server,
                                                             bool isDeleteModified);
 #endif // UA_ENABLE_HISTORIZING
 
-/**
-* .. _async_operations:
-*
-* Async Operations
-* ----------------
-* Some operations (such as reading out a sensor that needs to warm up) can take
-* quite some time. In order not to block the server during such an operation, it
-* can be "outsourced" to a worker thread.
-*
-* Take the example of a CallRequest. It is split into the individual method call
-* operations. If the method is marked as async, then the operation is put into a
-* queue where it is be retrieved by a worker. The worker returns the result when
-* ready. See the examples in ``/examples/tutorial_server_method_async.c`` for
-* the usage.
-*
-* Note that the operation can time out (see the asyncOperationTimeout setting in
-* the server config) also when it has been retrieved by the worker. */
-
-#if UA_MULTITHREADING >= 100
-
-/* Set the async flag in a method node */
-UA_StatusCode UA_EXPORT
-UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id,
-                             UA_Boolean isAsync);
-
-typedef enum {
-    UA_ASYNCOPERATIONTYPE_INVALID, /* 0, the default */
-    UA_ASYNCOPERATIONTYPE_CALL
-    /* UA_ASYNCOPERATIONTYPE_READ, */
-    /* UA_ASYNCOPERATIONTYPE_WRITE, */
-} UA_AsyncOperationType;
-
-typedef union {
-    UA_CallMethodRequest callMethodRequest;
-    /* UA_ReadValueId readValueId; */
-    /* UA_WriteValue writeValue; */
-} UA_AsyncOperationRequest;
-
-typedef union {
-    UA_CallMethodResult callMethodResult;
-    /* UA_DataValue readResult; */
-    /* UA_StatusCode writeResult; */
-} UA_AsyncOperationResponse;
-
-/* Get the next async operation without blocking
- *
- * @param server The server object
- * @param type The type of the async operation
- * @param request Receives pointer to the operation
- * @param context Receives the pointer to the operation context
- * @param timeout The timestamp when the operation times out and can
- *        no longer be returned to the client. The response has to
- *        be set in UA_Server_setAsyncOperationResult in any case.
- * @return false if queue is empty, true else */
-UA_Boolean UA_EXPORT
-UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type,
-                                       const UA_AsyncOperationRequest **request,
-                                       void **context, UA_DateTime *timeout);
-
-/* UA_Boolean UA_EXPORT */
-/* UA_Server_getAsyncOperationBlocking(UA_Server *server, UA_AsyncOperationType *type, */
-/*                                     const UA_AsyncOperationRequest **request, */
-/*                                     void **context, UA_DateTime *timeout); */
-
-/* Submit an async operation result
- *
- * @param server The server object
- * @param response Pointer to the operation result
- * @param context Pointer to the operation context */
-void UA_EXPORT
-UA_Server_setAsyncOperationResult(UA_Server *server,
-                                  const UA_AsyncOperationResponse *response,
-                                  void *context);
-
-/* Get the next async operation. Attention! This method is deprecated and has
- * been replaced by UA_Server_getAsyncOperationNonBlocking! */
-UA_DEPRECATED UA_Boolean UA_EXPORT
-UA_Server_getAsyncOperation(UA_Server *server, UA_AsyncOperationType *type,
-                            const UA_AsyncOperationRequest **request,
-                            void **context);
-
-#endif /* !UA_MULTITHREADING >= 100 */
-
 _UA_END_DECLS
 
 #endif /* UA_SERVER_H_ */

+ 1 - 27
include/open62541/server_config.h

@@ -12,7 +12,6 @@
 #define UA_SERVER_CONFIG_H_
 
 #include <open62541/plugin/accesscontrol.h>
-#include <open62541/plugin/nodestore.h>
 #include <open62541/plugin/log.h>
 #include <open62541/plugin/network.h>
 #include <open62541/plugin/pki.h>
@@ -78,27 +77,17 @@ typedef struct {
 #ifdef UA_ENABLE_DISCOVERY_MULTICAST
     UA_MdnsDiscoveryConfiguration mdns;
     UA_String mdnsInterfaceIP;
-# if !defined(UA_HAS_GETIFADDR)
-    uint32_t *ipAddressList;
-    size_t ipAddressListSize;
-# endif
 #endif
 
 } UA_ServerConfig_Discovery;
 
 #endif
 
-typedef void
-(*UA_Server_AsyncOperationNotifyCallback)(UA_Server *server);
-
 struct UA_ServerConfig {
     UA_UInt16 nThreads; /* only if multithreading is enabled */
     UA_Logger logger;
 
-    /* Server Description:
-     * The description must be internally consistent.
-     * - The ApplicationUri set in the ApplicationDescription must match the
-     *   URI set in the server certificate */
+    /* Server Description */
     UA_BuildInfo buildInfo;
     UA_ApplicationDescription applicationDescription;
     UA_ByteString serverCertificate;
@@ -151,21 +140,6 @@ struct UA_ServerConfig {
      * .. note:: See the section for :ref:`access-control
      *    handling<access-control>`. */
 
-    /* Async Operations */
-#if UA_MULTITHREADING >= 100
-    UA_Double asyncOperationTimeout; /* in ms, 0 => unlimited */
-    size_t maxAsyncOperationQueueSize; /* 0 => unlimited */
-    UA_Double asyncCallRequestTimeout UA_DEPRECATED; /* in ms, 0 => unlimited */
-    /* Notify workers when an async operation was enqueued */
-    UA_Server_AsyncOperationNotifyCallback asyncOperationNotifyCallback;
-#endif
-    /**
-     * .. note:: See the section for :ref:`async
-     * operations<async-operations>`. */
-
-    /* Nodestore */
-    UA_Nodestore nodestore;
-
     /* Certificate Verification */
     UA_CertificateVerification certificateVerification;
 

+ 9 - 80
include/open62541/server_pubsub.h

@@ -120,9 +120,6 @@ typedef struct {
     size_t connectionPropertiesSize;
     UA_KeyValuePair *connectionProperties;
     UA_Variant connectionTransportSettings;
-
-    /* This flag is 'read only' and is set internally based on the PubSub state. */
-    UA_Boolean configurationFrozen;
 } UA_PubSubConnectionConfig;
 
 UA_StatusCode UA_EXPORT
@@ -191,12 +188,10 @@ typedef struct {
         UA_PublishedEventConfig event;
         UA_PublishedEventTemplateConfig eventTemplate;
     } config;
-    /* This flag is 'read only' and is set internally based on the PubSub state. */
-    UA_Boolean configurationFrozen;
 } UA_PublishedDataSetConfig;
 
 void UA_EXPORT
-UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig);
+UA_PublishedDataSetConfig_deleteMembers(UA_PublishedDataSetConfig *pdsConfig);
 
 typedef struct {
     UA_StatusCode addResult;
@@ -215,11 +210,6 @@ UA_StatusCode UA_EXPORT
 UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
                                     UA_PublishedDataSetConfig *config);
 
-/* Returns a deep copy of the DataSetMetaData for an specific PDS */
-UA_StatusCode UA_EXPORT
-UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
-                                      UA_DataSetMetaDataType *metaData);
-
 /* Remove PublishedDataSet, identified by the NodeId. Deletion of PDS removes
  * all contained and linked PDS Fields. Connected WriterGroups will be also
  * removed. */
@@ -239,9 +229,6 @@ typedef struct{
     UA_String fieldNameAlias;
     UA_Boolean promotedField;
     UA_PublishedVariableDataType publishParameters;
-    /* non std. field */
-    UA_Boolean staticValueSourceEnabled;
-    UA_DataValue staticValueSource;
 } UA_DataSetVariableConfig;
 
 typedef enum {
@@ -255,12 +242,10 @@ typedef struct {
         /* events need other config later */
         UA_DataSetVariableConfig variable;
     } field;
-    /* This flag is 'read only' and is set internally based on the PubSub state. */
-    UA_Boolean configurationFrozen;
 } UA_DataSetFieldConfig;
 
 void UA_EXPORT
-UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig);
+UA_DataSetFieldConfig_deleteMembers(UA_DataSetFieldConfig *dataSetFieldConfig);
 
 typedef struct {
     UA_StatusCode result;
@@ -297,41 +282,6 @@ typedef enum {
     UA_PUBSUB_ENCODING_UADP
 } UA_PubSubEncodingType;
 
-/**
- * WriterGroup
- * -----------
- * The message publishing can be configured for realtime requirements. The RT-levels
- * go along with different requirements. The below listed levels can be configured:
- *
- * UA_PUBSUB_RT_NONE -
- * ---> Description: Default "none-RT" Mode
- * ---> Requirements: -
- * ---> Restrictions: -
- * UA_PUBSUB_RT_DIRECT_VALUE_ACCESS (Preview - not implemented)
- * ---> Description: Normally, the latest value for each DataSetField is read out of the information model. Within this RT-mode, the
- * value source of each field configured as static pointer to an DataValue. The publish cycle won't use call the server read function.
- * ---> Requirements: All fields must be configured with a 'staticValueSource'.
- * ---> Restrictions: -
- * UA_PUBSUB_RT_FIXED_LENGTH (Preview - not implemented)
- * ---> Description: All DataSetFields have a known, non-changing length. The server will pre-generate some
- * buffers and use only memcopy operations to generate requested PubSub packages.
- * ---> Requirements: DataSetFields with variable size can't be used within this mode.
- * ---> Restrictions: The configuration must be frozen and changes are not allowed while the WriterGroup is 'Operational'.
- * UA_PUBSUB_RT_DETERMINISTIC (Preview - not implemented)
- * ---> Description: -
- * ---> Requirements: -
- * ---> Restrictions: -
- *
- * WARNING! For hard real time requirements the underlying system must be rt-capable.
- *
- */
-typedef enum {
-    UA_PUBSUB_RT_NONE = 0,
-    UA_PUBSUB_RT_DIRECT_VALUE_ACCESS = 1,
-    UA_PUBSUB_RT_FIXED_SIZE = 2,
-    UA_PUBSUB_RT_DETERMINISTIC = 4,
-} UA_PubSubRTLevel;
-
 typedef struct {
     UA_String name;
     UA_Boolean enabled;
@@ -349,14 +299,10 @@ typedef struct {
     /* non std. config parameter. maximum count of embedded DataSetMessage in
      * one NetworkMessage */
     UA_UInt16 maxEncapsulatedDataSetMessageCount;
-    /* This flag is 'read only' and is set internally based on the PubSub state. */
-    UA_Boolean configurationFrozen;
-    /* non std. field */
-    UA_PubSubRTLevel rtLevel;
 } UA_WriterGroupConfig;
 
 void UA_EXPORT
-UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig);
+UA_WriterGroupConfig_deleteMembers(UA_WriterGroupConfig *writerGroupConfig);
 
 /* Add a new WriterGroup to an existing Connection */
 UA_StatusCode UA_EXPORT
@@ -376,21 +322,8 @@ UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdenti
 UA_StatusCode UA_EXPORT
 UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup);
 
-UA_StatusCode UA_EXPORT
-UA_Server_freezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupOperational(UA_Server *server, const UA_NodeId writerGroup);
-
-UA_StatusCode UA_EXPORT
-UA_Server_setWriterGroupDisabled(UA_Server *server, const UA_NodeId writerGroup);
-
 /**
- * .. _dsw:    UA_Boolean configurationFrozen;
-
+ * .. _dsw:
  *
  * DataSetWriter
  * -------------
@@ -406,16 +339,13 @@ typedef struct {
     UA_DataSetFieldContentMask dataSetFieldContentMask;
     UA_UInt32 keyFrameCount;
     UA_ExtensionObject messageSettings;
-    UA_ExtensionObject transportSettings;
     UA_String dataSetName;
     size_t dataSetWriterPropertiesSize;
     UA_KeyValuePair *dataSetWriterProperties;
-    /* This flag is 'read only' and is set internally based on the PubSub state. */
-    UA_Boolean configurationFrozen;
 } UA_DataSetWriterConfig;
 
 void UA_EXPORT
-UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig);
+UA_DataSetWriterConfig_deleteMembers(UA_DataSetWriterConfig *pdsConfig);
 
 /* Add a new DataSetWriter to a existing WriterGroup. The DataSetWriter must be
  * coupled with a PublishedDataSet on creation.
@@ -511,11 +441,10 @@ UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
 UA_StatusCode
 UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier);
 
-/* To Do: Update Configuration of ReaderGroup
- * UA_StatusCode
- * UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
- *                                    const UA_ReaderGroupConfig *config);
- */
+/* To Do: Update Configuration of ReaderGroup */
+UA_StatusCode
+UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
+                                  const UA_ReaderGroupConfig *config);
 
 /* Get configuraiton of ReaderGroup */
 UA_StatusCode

+ 5 - 6
include/open62541/types.h

@@ -225,7 +225,6 @@ typedef struct UA_DateTimeStruct {
 } UA_DateTimeStruct;
 
 UA_DateTimeStruct UA_EXPORT UA_DateTime_toStruct(UA_DateTime t);
-UA_DateTime UA_EXPORT UA_DateTime_fromStruct(UA_DateTimeStruct ts);
 
 /* The C99 standard (7.23.1) says: "The range and precision of times
  * representable in clock_t and time_t are implementation-defined." On most
@@ -801,7 +800,7 @@ typedef struct UA_DiagnosticInfo {
  * type operations as static inline functions. */
 
 typedef struct {
-#ifdef UA_ENABLE_TYPEDESCRIPTION
+#ifdef UA_ENABLE_TYPENAMES
     const char *memberName;
 #endif
     UA_UInt16 memberTypeIndex;    /* Index of the member in the array of data
@@ -857,7 +856,7 @@ typedef enum {
 } UA_DataTypeKind;
 
 struct UA_DataType {
-#ifdef UA_ENABLE_TYPEDESCRIPTION
+#ifdef UA_ENABLE_TYPENAMES
     const char *typeName;
 #endif
     UA_NodeId typeId;                /* The nodeid of the type */
@@ -869,7 +868,7 @@ struct UA_DataType {
     UA_UInt32 overlayable      : 1;  /* The type has the identical memory layout
                                       * in memory and on the binary stream. */
     UA_UInt32 membersSize      : 8;  /* How many members does the type have? */
-    UA_UInt32 binaryEncodingId;      /* NodeId of datatype when encoded as binary */
+    UA_UInt32 binaryEncodingId : 16; /* NodeId of datatype when encoded as binary */
     //UA_UInt16  xmlEncodingId;      /* NodeId of datatype when encoded as XML */
     UA_DataTypeMember *members;
 };
@@ -979,7 +978,7 @@ void UA_EXPORT UA_Array_delete(void *p, size_t size, const UA_DataType *type);
 /**
  * Random Number Generator
  * -----------------------
- * If UA_MULTITHREADING is defined, then the seed is stored in thread
+ * 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);
@@ -997,7 +996,7 @@ UA_Guid UA_EXPORT UA_Guid_random(void);     /* no cryptographic entropy */
 
 /* The following is used to exclude type names in the definition of UA_DataType
  * structures if the feature is disabled. */
-#ifdef UA_ENABLE_TYPEDESCRIPTION
+#ifdef UA_ENABLE_TYPENAMES
 # define UA_TYPENAME(name) name,
 #else
 # define UA_TYPENAME(name)

+ 2 - 3
plugins/historydata/ua_history_database_default.c

@@ -602,7 +602,7 @@ setValue_service_default(UA_Server *server,
 }
 
 static void
-clear_service_default(UA_HistoryDatabase *hdb)
+deleteMembers_service_default(UA_HistoryDatabase *hdb)
 {
     if (hdb == NULL || hdb->context == NULL)
         return;
@@ -615,7 +615,6 @@ UA_HistoryDatabase
 UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
 {
     UA_HistoryDatabase hdb;
-    memset(&hdb, 0, sizeof(UA_HistoryDatabase));
     UA_HistoryDatabaseContext_default *context =
             (UA_HistoryDatabaseContext_default*)
             UA_calloc(1, sizeof(UA_HistoryDatabaseContext_default));
@@ -625,6 +624,6 @@ UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
     hdb.setValue = &setValue_service_default;
     hdb.updateData = &updateData_service_default;
     hdb.deleteRawModified = &deleteRawModified_service_default;
-    hdb.clear = clear_service_default;
+    hdb.deleteMembers = &deleteMembers_service_default;
     return hdb;
 }

+ 0 - 3
plugins/include/open62541/client_config_default.h

@@ -10,12 +10,9 @@
 #define UA_CLIENT_CONFIG_DEFAULT_H_
 
 #include <open62541/client_config.h>
-#include <open62541/client.h>
 
 _UA_BEGIN_DECLS
 
-UA_Client UA_EXPORT * UA_Client_new(void);
-
 UA_StatusCode UA_EXPORT
 UA_ClientConfig_setDefault(UA_ClientConfig *config);
 

+ 0 - 32
plugins/include/open62541/plugin/nodestore_default.h

@@ -1,32 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- *    Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
- */
-
-#ifndef UA_NODESTORE_DEFAULT_H_
-#define UA_NODESTORE_DEFAULT_H_
-
-#include <open62541/plugin/nodestore.h>
-
-_UA_BEGIN_DECLS
-
-/* The HashMap Nodestore holds all nodes in RAM in single hash-map. Lookip is
- * done based on hashing/comparison of the NodeId with close to O(1) lookup
- * time. However, sometimes the underlying array has to be resized when nodes
- * are added/removed. This can take O(n) time. */
-UA_EXPORT UA_StatusCode
-UA_Nodestore_HashMap(UA_Nodestore *ns);
-
-/* The ZipTree Nodestore holds all nodes in RAM in a tree structure. The lookup
- * time is about O(log n). Adding/removing nodes does not require resizing of
- * the underlying array with the linear overhead.
- *
- *  For most usage scenarios the hash-map Nodestore will be faster.
- */
-UA_EXPORT UA_StatusCode
-UA_Nodestore_ZipTree(UA_Nodestore *ns);
-
-_UA_END_DECLS
-
-#endif /* UA_NODESTORE_DEFAULT_H_ */

+ 0 - 7
plugins/include/open62541/plugin/securitypolicy_mbedtls_common.h

@@ -15,13 +15,6 @@
 #include <mbedtls/x509_crt.h>
 #include <mbedtls/ctr_drbg.h>
 
-#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
-#define MBEDTLS_ENTROPY_POLL_METHOD mbedtls_platform_entropy_poll
-#else
-// MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy
-#define MBEDTLS_ENTROPY_POLL_METHOD mbedtls_hardware_poll
-#endif
-
 #define UA_SHA1_LENGTH 20
 
 _UA_BEGIN_DECLS

+ 0 - 20
plugins/include/open62541/server_config_default.h

@@ -14,10 +14,6 @@
 
 _UA_BEGIN_DECLS
 
-/* Create a new server with default plugins for logging etc. used during
- * initialization. No network layer and SecurityPolicies are set so far. */
-UA_Server UA_EXPORT * UA_Server_new(void);
-
 /**********************/
 /* Default Connection */
 /**********************/
@@ -109,22 +105,6 @@ UA_EXPORT UA_StatusCode
 UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
                                    UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize);
 
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-/* Adds a Websocket network layer with custom buffer sizes
- *
- * @param conf The configuration to manipulate
- * @param portNumber The port number for the tcp network layer
- * @param sendBufferSize The size in bytes for the network send buffer. Pass 0
- *        to use defaults.
- * @param recvBufferSize The size in bytes for the network receive buffer.
- *        Pass 0 to use defaults.
- */
-
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
-                                  UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize);
-#endif
-
 /* Adds the security policy ``SecurityPolicy#None`` to the server. A
  * server certificate may be supplied but is optional.
  *

+ 0 - 322
plugins/mqtt/ua_mqtt_adapter.c

@@ -1,322 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright (c) 2018 Fraunhofer IOSB (Author: Lukas Meling)
- */
-
-#include "ua_mqtt_adapter.h"
-#include "../../deps/mqtt-c/mqtt.h"
-#include "open62541/plugin/log_stdout.h"
-#include "open62541/util.h"
-
-/* forward decl for callback */
-void
-publish_callback(void**, struct mqtt_response_publish*);
-
-UA_StatusCode
-connectMqtt(UA_PubSubChannelDataMQTT* channelData){
-    if(channelData == NULL){
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-
-    /* Get address and replace mqtt with tcp
-     * because we use a tcp UA_ClientConnectionTCP for mqtt */
-    UA_NetworkAddressUrlDataType address = channelData->address;
-
-    UA_String hostname, path;
-    UA_UInt16 networkPort;
-    if(UA_parseEndpointUrl(&address.url, &hostname, &networkPort, &path) != UA_STATUSCODE_GOOD){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
-                     "MQTT PubSub Connection creation failed. Invalid URL.");
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-
-    /* Build the url, replace mqtt with tcp */
-    UA_STACKARRAY(UA_Byte, addressAsChar, 10 + (sizeof(char) * path.length));
-    memcpy((char*)addressAsChar, "opc.tcp://", 10);
-    memcpy((char*)&addressAsChar[10],(char*)path.data, path.length);
-    address.url.data = addressAsChar;
-    address.url.length = 10 + (sizeof(char) * path.length);
-
-    /* check if buffers are correct */
-    if(!(channelData->mqttRecvBufferSize > 0 && channelData->mqttRecvBuffer != NULL
-            && channelData->mqttSendBufferSize > 0 && channelData->mqttSendBuffer != NULL)){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "MQTT PubSub Connection creation failed. No Mqtt buffer allocated.");
-        return UA_STATUSCODE_BADARGUMENTSMISSING;
-    }
-
-    /* Config with default parameters */
-    UA_ConnectionConfig conf;
-    memset(&conf, 0, sizeof(UA_ConnectionConfig));
-    conf.protocolVersion = 0;
-    conf.sendBufferSize = 1000;
-    conf.recvBufferSize = 2000;
-    conf.maxMessageSize = 1000;
-    conf.maxChunkCount = 1;
-
-    /* Create TCP connection: open the blocking TCP socket (connecting to the broker) */
-    UA_Connection connection = UA_ClientConnectionTCP( conf, address.url, 1000, NULL);
-    if(connection.state != UA_CONNECTION_ESTABLISHED && connection.state != UA_CONNECTION_OPENING){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK, "PubSub MQTT: Connection creation failed. Tcp connection failed!");
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-
-    /* Set socket to nonblocking!*/
-    UA_socket_set_nonblocking(connection.sockfd);
-
-    /* save connection */
-    channelData->connection = (UA_Connection*)UA_calloc(1, sizeof(UA_Connection));
-    if(!channelData->connection){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Connection creation failed. Out of memory.");
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    memcpy(channelData->connection, &connection, sizeof(UA_Connection));
-
-    /* calloc mqtt_client */
-    struct mqtt_client* client = (struct mqtt_client*)UA_calloc(1, sizeof(struct mqtt_client));
-    if(!client){
-        UA_free(channelData->connection);
-
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Connection creation failed. Out of memory.");
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    /* save reference */
-    channelData->mqttClient = client;
-
-    /* create custom sockethandle */
-    struct my_custom_socket_handle* handle =
-        (struct my_custom_socket_handle*)UA_calloc(1, sizeof(struct my_custom_socket_handle));
-    if(!handle){
-        UA_free(channelData->connection);
-        UA_free(client);
-
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Connection creation failed. Out of memory.");
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-    handle->client = client;
-    handle->connection = channelData->connection;
-
-    /* init mqtt client struct with buffers and callback */
-    enum MQTTErrors mqttErr = mqtt_init(client, handle, channelData->mqttSendBuffer, channelData->mqttSendBufferSize,
-                channelData->mqttRecvBuffer, channelData->mqttRecvBufferSize, publish_callback);
-    if(mqttErr != MQTT_OK){
-        UA_free(channelData->connection);
-        UA_free(client);
-
-        const char* errorStr = mqtt_error_str(mqttErr);
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Connection creation failed. MQTT error: %s", errorStr);
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-
-    /* Init custom data for subscribe callback function:
-     * A reference to the channeldata will be available in the callback.
-     * This is used to call the user callback channelData.callback */
-    client->publish_response_callback_state = channelData;
-
-    /* Convert clientId UA_String to char* null terminated */
-    char* clientId = (char*)calloc(1,channelData->mqttClientId->length + 1);
-    if(!clientId){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Connection creation failed. Out of memory.");
-        UA_free(channelData->connection);
-        UA_free(client);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-    memcpy(clientId, channelData->mqttClientId->data, channelData->mqttClientId->length);
-
-    /* Connect mqtt with socket fd of networktcp  */
-    mqttErr = mqtt_connect(client, clientId, NULL, NULL, 0, NULL, NULL, 0, 400);
-    UA_free(clientId);
-    if(mqttErr != MQTT_OK){
-        UA_free(channelData->connection);
-        UA_free(client);
-
-        const char* errorStr = mqtt_error_str(mqttErr);
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s", errorStr);
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-
-    /* sync the first mqtt packets in the buffer to send connection request.
-       After that yield must be called frequently to exchange mqtt messages. */
-    UA_StatusCode ret = yieldMqtt(channelData, 100);
-    if(ret != UA_STATUSCODE_GOOD){
-        UA_free(channelData->connection);
-        UA_free(client);
-        return ret;
-    }
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-disconnectMqtt(UA_PubSubChannelDataMQTT* channelData){
-    if(channelData == NULL){
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-    channelData->callback = NULL;
-    struct mqtt_client* client = (struct mqtt_client*)channelData->mqttClient;
-    if(client){
-        mqtt_disconnect(client);
-        yieldMqtt(channelData, 10);
-        UA_free(client->socketfd);
-    }
-    if(channelData->connection != NULL){
-        channelData->connection->close(channelData->connection);
-        channelData->connection->free(channelData->connection);
-        UA_free(channelData->connection);
-        channelData->connection = NULL;
-    }
-    UA_free(channelData->mqttRecvBuffer);
-    channelData->mqttRecvBuffer = NULL;
-    UA_free(channelData->mqttSendBuffer);
-    channelData->mqttSendBuffer = NULL;
-    UA_free(channelData->mqttClient);
-    channelData->mqttClient = NULL;
-    return UA_STATUSCODE_GOOD;
-}
-
-void
-publish_callback(void** channelDataPtr, struct mqtt_response_publish *published)
-{
-    if(channelDataPtr != NULL){
-        UA_PubSubChannelDataMQTT *channelData = (UA_PubSubChannelDataMQTT*)*channelDataPtr;
-        if(channelData != NULL){
-            if(channelData->callback != NULL){
-                //Setup topic
-                UA_ByteString *topic = UA_ByteString_new();
-                if(!topic) return;
-                UA_ByteString *msg = UA_ByteString_new();  
-                if(!msg) return;
-                
-                /* memory for topic */
-                UA_StatusCode ret = UA_ByteString_allocBuffer(topic, published->topic_name_size);
-                if(ret){
-                    UA_free(topic);
-                    UA_free(msg);
-                    return;
-                }
-                /* memory for message */
-                ret = UA_ByteString_allocBuffer(msg, published->application_message_size);
-                if(ret){
-                    UA_ByteString_delete(topic);
-                    UA_free(msg);
-                    return;
-                }
-                /* copy topic and msg, call the cb */
-                memcpy(topic->data, published->topic_name, published->topic_name_size);
-                memcpy(msg->data, published->application_message, published->application_message_size);
-                channelData->callback(msg, topic);
-            }
-        }
-    }  
-}
-
-UA_StatusCode
-subscribeMqtt(UA_PubSubChannelDataMQTT* channelData, UA_String topic, UA_Byte qos){
-    if(channelData == NULL || topic.length == 0){
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-    struct mqtt_client* client = (struct mqtt_client*)channelData->mqttClient;
-    
-    UA_STACKARRAY(char, topicStr, sizeof(char) * topic.length +1);
-    memcpy(topicStr, topic.data, topic.length);
-    topicStr[topic.length] = '\0';
-
-    enum MQTTErrors mqttErr = mqtt_subscribe(client, topicStr, (UA_Byte) qos);
-    if(mqttErr != MQTT_OK){
-        const char* errorStr = mqtt_error_str(mqttErr);
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: subscribe: %s", errorStr);
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode
-unSubscribeMqtt(UA_PubSubChannelDataMQTT* channelData, UA_String topic){
-    return UA_STATUSCODE_BADNOTIMPLEMENTED;
-}
-
-UA_StatusCode
-yieldMqtt(UA_PubSubChannelDataMQTT* channelData, UA_UInt16 timeout){
-    if(channelData == NULL || timeout == 0){
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-
-    UA_Connection *connection = channelData->connection;
-    if(connection == NULL){
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-    
-    if(connection->state != UA_CONNECTION_ESTABLISHED && connection->state != UA_CONNECTION_OPENING){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK, "PubSub MQTT: yield: Tcp Connection not established!");
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-    
-    struct mqtt_client* client = (struct mqtt_client*)channelData->mqttClient;
-    client->socketfd->timeout = timeout;
-
-    enum MQTTErrors error = mqtt_sync(client);
-    if(error == MQTT_OK){
-        return UA_STATUSCODE_GOOD;
-    }else if(error == -1){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK, "PubSub MQTT: yield: Communication Error.");
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-    
-    /* map mqtt errors to ua errors */
-    const char* errorStr = mqtt_error_str(error);
-    UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: yield: error: %s", errorStr);
-    
-    switch(error){
-        case MQTT_ERROR_CONNECTION_CLOSED:
-            return UA_STATUSCODE_BADNOTCONNECTED;
-        case MQTT_ERROR_SOCKET_ERROR:
-            return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-        case MQTT_ERROR_CONNECTION_REFUSED:
-            return UA_STATUSCODE_BADCONNECTIONREJECTED;
-            
-        default:
-            return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    }
-}
-
-UA_StatusCode
-publishMqtt(UA_PubSubChannelDataMQTT* channelData, UA_String topic, const UA_ByteString *buf, UA_Byte qos){
-    if(channelData == NULL || buf == NULL ){
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-
-    UA_STACKARRAY(char, topicChar, sizeof(char) * topic.length +1);
-    memcpy(topicChar, topic.data, topic.length);
-    topicChar[topic.length] = '\0';
-    
-    struct mqtt_client* client = (struct mqtt_client*)channelData->mqttClient;
-    if(client == NULL)
-        return UA_STATUSCODE_BADNOTCONNECTED;
-
-    /* publish */
-    enum MQTTPublishFlags flags;
-    if(qos == 0){
-        flags = MQTT_PUBLISH_QOS_0;
-    }else if( qos == 1){
-        flags = MQTT_PUBLISH_QOS_1;
-    }else if( qos == 2){
-        flags = MQTT_PUBLISH_QOS_2;
-    }else{
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK, "PubSub MQTT: publish: Bad Qos Level.");
-        return UA_STATUSCODE_BADINVALIDARGUMENT;
-    }
-    mqtt_publish(client, topicChar, buf->data, buf->length, (uint8_t)flags);
-    if (client->error != MQTT_OK) {
-        if(client->error == MQTT_ERROR_SEND_BUFFER_IS_FULL){
-            UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: publish: Send buffer is full. "
-                                                               "Possible reasons: send buffer is to small, "
-                                                               "sending to fast, broker not responding.");
-        }else{
-            UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: publish: %s", mqtt_error_str(client->error));
-        }
-        return UA_STATUSCODE_BADCONNECTIONREJECTED;
-    }
-    return UA_STATUSCODE_GOOD;
-}

+ 0 - 39
plugins/mqtt/ua_mqtt_adapter.h

@@ -1,39 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright (c) 2018 Fraunhofer IOSB (Author: Lukas Meling)
- */
-
-#ifndef UA_PLUGIN_MQTT_H_
-#define UA_PLUGIN_MQTT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ua_network_pubsub_mqtt.h"
-
-UA_StatusCode
-connectMqtt(UA_PubSubChannelDataMQTT*);
-
-UA_StatusCode
-disconnectMqtt(UA_PubSubChannelDataMQTT*);
-
-UA_StatusCode
-unSubscribeMqtt(UA_PubSubChannelDataMQTT*, UA_String topic);
-
-UA_StatusCode
-publishMqtt(UA_PubSubChannelDataMQTT*, UA_String topic, const UA_ByteString *buf, UA_Byte qos);
-
-UA_StatusCode
-subscribeMqtt(UA_PubSubChannelDataMQTT*, UA_String topic, UA_Byte qos);
-
-UA_StatusCode
-yieldMqtt(UA_PubSubChannelDataMQTT*, UA_UInt16 timeout);
-    
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* UA_PLUGIN_MQTT_H_ */

+ 0 - 43
plugins/mqtt/ua_mqtt_pal.c

@@ -1,43 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright (c) 2018 Fraunhofer IOSB (Author: Lukas Meling)
- * Copyright (c) 2019 Kalycito Infotech Private Limited
- */
-
-#include "../../deps/mqtt-c/mqtt.h"
-#include <open62541/network_tcp.h>
-
-ssize_t
-mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void* buf, size_t len, int flags) {
-    UA_Connection *connection = (UA_Connection*) fd->connection;
-    UA_ByteString sendBuffer;
-    sendBuffer.data = (UA_Byte*)UA_malloc(len);
-    sendBuffer.length = len;
-    memcpy(sendBuffer.data, buf, len);
-    UA_StatusCode ret = connection->send(connection, &sendBuffer);
-    if(ret != UA_STATUSCODE_GOOD)
-        return -1;
-    return (ssize_t)len;
-}
-
-ssize_t
-mqtt_pal_recvall(mqtt_pal_socket_handle fd, void* buf, size_t bufsz, int flags) {
-    UA_Connection *connection = (UA_Connection*) fd->connection;
-    connection->config.recvBufferSize = (UA_UInt32) bufsz;
-    UA_ByteString inBuffer;
-    UA_StatusCode ret = connection->recv(connection, &inBuffer, fd->timeout);
-    if(ret == UA_STATUSCODE_GOOD ){
-        // Buffer received, copy to recv buffer
-        memcpy(buf, inBuffer.data, inBuffer.length);
-        ssize_t bytesReceived = (ssize_t)inBuffer.length;
-        /* free recv buffer */
-        connection->releaseRecvBuffer(connection, &inBuffer);
-        return bytesReceived;
-    }else if(ret == UA_STATUSCODE_GOODNONCRITICALTIMEOUT){
-        return 0;
-    }else{
-        return -1; //error case, no free necessary
-    }
-}

+ 8 - 12
plugins/securityPolicies/ua_securitypolicy_basic128rsa15.c

@@ -578,15 +578,15 @@ channelContext_compareCertificate_sp_basic128rsa15(const Basic128Rsa15_ChannelCo
 }
 
 static void
-clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
+deleteMembers_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
     if(securityPolicy == NULL)
         return;
 
-    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
-
     if(securityPolicy->policyContext == NULL)
         return;
 
+    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+
     /* delete all allocated members in the context */
     Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
         securityPolicy->policyContext;
@@ -648,7 +648,7 @@ updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolic
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not update certificate and private key");
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic128rsa15(securityPolicy);
+        deleteMembers_sp_basic128rsa15(securityPolicy);
     return retval;
 }
 
@@ -691,7 +691,7 @@ policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
 
     /* Add the system entropy source */
     mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
-                                         MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
+                                         mbedtls_platform_entropy_poll, NULL, 0,
                                          MBEDTLS_ENTROPY_SOURCE_STRONG);
     if(mbedErr) {
         retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -733,7 +733,7 @@ error:
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not create securityContext: %s", UA_StatusCode_name(retval));
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic128rsa15(securityPolicy);
+        deleteMembers_sp_basic128rsa15(securityPolicy);
     return retval;
 }
 
@@ -869,13 +869,9 @@ UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy,
         channelContext_compareCertificate_sp_basic128rsa15;
 
     policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic128rsa15;
-    policy->clear = clear_sp_basic128rsa15;
-
-    UA_StatusCode res = policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey);
-    if(res != UA_STATUSCODE_GOOD)
-        clear_sp_basic128rsa15(policy);
+    policy->deleteMembers = deleteMembers_sp_basic128rsa15;
 
-    return res;
+    return policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey);
 }
 
 #endif

+ 9 - 12
plugins/securityPolicies/ua_securitypolicy_basic256.c

@@ -18,6 +18,7 @@
 #include <open62541/types.h>
 #include <open62541/util.h>
 
+
 #include <mbedtls/aes.h>
 #include <mbedtls/entropy.h>
 #include <mbedtls/entropy_poll.h>
@@ -526,15 +527,15 @@ channelContext_compareCertificate_sp_basic256(const Basic256_ChannelContext *cc,
 }
 
 static void
-clear_sp_basic256(UA_SecurityPolicy *securityPolicy) {
+deleteMembers_sp_basic256(UA_SecurityPolicy *securityPolicy) {
     if(securityPolicy == NULL)
         return;
 
-    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
-
     if(securityPolicy->policyContext == NULL)
         return;
 
+    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+
     /* delete all allocated members in the context */
     Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
         securityPolicy->policyContext;
@@ -598,7 +599,7 @@ updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy,
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not update certificate and private key");
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic256(securityPolicy);
+        deleteMembers_sp_basic256(securityPolicy);
     return retval;
 }
 
@@ -641,7 +642,7 @@ policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy,
 
     /* Add the system entropy source */
     mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
-                                         MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
+                                         mbedtls_platform_entropy_poll, NULL, 0,
                                          MBEDTLS_ENTROPY_SOURCE_STRONG);
     if(mbedErr) {
         retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -682,7 +683,7 @@ error:
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not create securityContext: %s", UA_StatusCode_name(retval));
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic256(securityPolicy);
+        deleteMembers_sp_basic256(securityPolicy);
     return retval;
 }
 
@@ -818,13 +819,9 @@ UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy,
         channelContext_compareCertificate_sp_basic256;
 
     policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256;
-    policy->clear = clear_sp_basic256;
-
-    UA_StatusCode res = policyContext_newContext_sp_basic256(policy, localPrivateKey);
-    if(res != UA_STATUSCODE_GOOD)
-        clear_sp_basic256(policy);
+    policy->deleteMembers = deleteMembers_sp_basic256;
 
-    return res;
+    return policyContext_newContext_sp_basic256(policy, localPrivateKey);
 }
 
 #endif

+ 8 - 12
plugins/securityPolicies/ua_securitypolicy_basic256sha256.c

@@ -568,15 +568,15 @@ channelContext_compareCertificate_sp_basic256sha256(const Basic256Sha256_Channel
 }
 
 static void
-clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
+deleteMembers_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
     if(securityPolicy == NULL)
         return;
 
-    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
-
     if(securityPolicy->policyContext == NULL)
         return;
 
+    UA_ByteString_deleteMembers(&securityPolicy->localCertificate);
+
     /* delete all allocated members in the context */
     Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
         securityPolicy->policyContext;
@@ -639,7 +639,7 @@ updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPoli
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not update certificate and private key");
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic256sha256(securityPolicy);
+        deleteMembers_sp_basic256sha256(securityPolicy);
     return retval;
 }
 
@@ -682,7 +682,7 @@ policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
 
     /* Add the system entropy source */
     mbedErr = mbedtls_entropy_add_source(&pc->entropyContext,
-                                         MBEDTLS_ENTROPY_POLL_METHOD, NULL, 0,
+                                         mbedtls_platform_entropy_poll, NULL, 0,
                                          MBEDTLS_ENTROPY_SOURCE_STRONG);
     if(mbedErr) {
         retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
@@ -723,7 +723,7 @@ error:
     UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
                  "Could not create securityContext: %s", UA_StatusCode_name(retval));
     if(securityPolicy->policyContext != NULL)
-        clear_sp_basic256sha256(securityPolicy);
+        deleteMembers_sp_basic256sha256(securityPolicy);
     return retval;
 }
 
@@ -859,13 +859,9 @@ UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy,
         channelContext_compareCertificate_sp_basic256sha256;
 
     policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256sha256;
-    policy->clear = clear_sp_basic256sha256;
-
-    UA_StatusCode res = policyContext_newContext_sp_basic256sha256(policy, localPrivateKey);
-    if(res != UA_STATUSCODE_GOOD)
-        clear_sp_basic256sha256(policy);
+    policy->deleteMembers = deleteMembers_sp_basic256sha256;
 
-    return res;
+    return policyContext_newContext_sp_basic256sha256(policy, localPrivateKey);
 }
 
 #endif

+ 6 - 6
plugins/securityPolicies/ua_securitypolicy_none.c

@@ -76,14 +76,14 @@ generateNonce_none(const UA_SecurityPolicy *securityPolicy, UA_ByteString *out)
     /* Fill blocks of four byte */
     size_t i = 0;
     while(i + 3 < out->length) {
-        UA_UInt32 randNumber = UA_UInt32_random();
-        memcpy(&out->data[i], &randNumber, 4);
+        UA_UInt32 rand = UA_UInt32_random();
+        memcpy(&out->data[i], &rand, 4);
         i = i+4;
     }
 
     /* Fill the remaining byte */
-    UA_UInt32 randNumber = UA_UInt32_random();
-    memcpy(&out->data[i], &randNumber, out->length % 4);
+    UA_UInt32 rand = UA_UInt32_random();
+    memcpy(&out->data[i], &rand, out->length % 4);
 
     return UA_STATUSCODE_GOOD;
 }
@@ -122,7 +122,7 @@ updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy,
 
 
 static void
-policy_clear_none(UA_SecurityPolicy *policy) {
+policy_deletemembers_none(UA_SecurityPolicy *policy) {
     UA_ByteString_deleteMembers(&policy->localCertificate);
 }
 
@@ -181,7 +181,7 @@ UA_SecurityPolicy_None(UA_SecurityPolicy *policy,
     policy->channelModule.setRemoteSymIv = setContextValue_none;
     policy->channelModule.compareCertificate = compareCertificate_none;
     policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none;
-    policy->clear = policy_clear_none;
+    policy->deleteMembers = policy_deletemembers_none;
 
     return UA_STATUSCODE_GOOD;
 }

+ 2 - 3
plugins/ua_accesscontrol_default.c

@@ -193,7 +193,7 @@ allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl
 /* Create Delete Access Control Plugin */
 /***************************************/
 
-static void clear_default(UA_AccessControl *ac) {
+static void deleteMembers_default(UA_AccessControl *ac) {
     UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
                     ac->userTokenPoliciesSize,
                     &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
@@ -210,7 +210,6 @@ static void clear_default(UA_AccessControl *ac) {
         if(context->usernamePasswordLoginSize > 0)
             UA_free(context->usernamePasswordLogin);
         UA_free(ac->context);
-        ac->context = NULL;
     }
 }
 
@@ -220,7 +219,7 @@ UA_AccessControl_default(UA_ServerConfig *config, UA_Boolean allowAnonymous,
                          size_t usernamePasswordLoginSize,
                          const UA_UsernamePasswordLogin *usernamePasswordLogin) {
     UA_AccessControl *ac = &config->accessControl;
-    ac->clear = clear_default;
+    ac->deleteMembers = deleteMembers_default;
     ac->activateSession = activateSession_default;
     ac->closeSession = closeSession_default;
     ac->getUserRightsMask = getUserRightsMask_default;

+ 67 - 139
plugins/ua_config_default.c

@@ -13,11 +13,7 @@
 
 #include <open62541/client_config_default.h>
 #include <open62541/network_tcp.h>
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-#include <open62541/network_ws.h>
-#endif
 #include <open62541/plugin/accesscontrol_default.h>
-#include <open62541/plugin/nodestore_default.h>
 #include <open62541/plugin/log_stdout.h>
 #include <open62541/plugin/pki_default.h>
 #include <open62541/plugin/securitypolicy_default.h>
@@ -38,16 +34,6 @@ UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
     return range;
 }
 
-UA_Server *
-UA_Server_new() {
-    UA_ServerConfig config;
-    memset(&config, 0, sizeof(UA_ServerConfig));
-    /* Set a default logger and NodeStore for the initialization */
-    config.logger = UA_Log_Stdout_;
-    UA_Nodestore_HashMap(&config.nodestore);
-    return UA_Server_newWithConfig(&config);
-}
-
 /*******************************/
 /* Default Connection Settings */
 /*******************************/
@@ -114,8 +100,9 @@ setDefaultConfig(UA_ServerConfig *conf) {
     if (!conf)
         return UA_STATUSCODE_BADINVALIDARGUMENT;
 
-    if(conf->nodestore.context == NULL)
-        UA_Nodestore_HashMap(&conf->nodestore);
+    /* Zero out.. All members have a valid initial value */
+    UA_ServerConfig_clean(conf);
+    memset(conf, 0, sizeof(UA_ServerConfig));
 
     /* --> Start setting the default static config <-- */
     conf->nThreads = 1;
@@ -124,7 +111,6 @@ setDefaultConfig(UA_ServerConfig *conf) {
     conf->shutdownDelay = 0.0;
 
     /* Server Description */
-    UA_BuildInfo_clear(&conf->buildInfo);
     conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI);
     conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME);
     conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME);
@@ -138,7 +124,6 @@ setDefaultConfig(UA_ServerConfig *conf) {
     #endif
     conf->buildInfo.buildDate = UA_DateTime_now();
 
-    UA_ApplicationDescription_clear(&conf->applicationDescription);
     conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER);
     conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI);
     conf->applicationDescription.applicationName =
@@ -150,12 +135,8 @@ setDefaultConfig(UA_ServerConfig *conf) {
     /* conf->applicationDescription.discoveryUrls = NULL; */
 
 #ifdef UA_ENABLE_DISCOVERY_MULTICAST
-    UA_MdnsDiscoveryConfiguration_clear(&conf->discovery.mdns);
+    UA_MdnsDiscoveryConfiguration_init(&conf->discovery.mdns);
     conf->discovery.mdnsInterfaceIP = UA_STRING_NULL;
-# if !defined(UA_HAS_GETIFADDR)
-    conf->discovery.ipAddressList = NULL;
-    conf->discovery.ipAddressListSize = 0;
-# endif
 #endif
 
     /* Custom DataTypes */
@@ -174,11 +155,11 @@ setDefaultConfig(UA_ServerConfig *conf) {
      * overwritten when the policy is specialized. */
     UA_CertificateVerification_AcceptAll(&conf->certificateVerification);
 
-    /* * Global Node Lifecycle * */
-    /* conf->nodeLifecycle.constructor = NULL; */
-    /* conf->nodeLifecycle.destructor = NULL; */
-    /* conf->nodeLifecycle.createOptionalChild = NULL; */
-    /* conf->nodeLifecycle.generateChildNodeId = NULL; */
+    /* Global Node Lifecycle */
+    conf->nodeLifecycle.constructor = NULL;
+    conf->nodeLifecycle.destructor = NULL;
+    conf->nodeLifecycle.createOptionalChild = NULL;
+    conf->nodeLifecycle.generateChildNodeId = NULL;
 
     /* Relax constraints for the InformationModel */
     conf->relaxEmptyValueConstraint = true; /* Allow empty values */
@@ -232,11 +213,6 @@ setDefaultConfig(UA_ServerConfig *conf) {
     /* conf->deleteAtTimeDataCapability = UA_FALSE; */
 #endif
 
-#if UA_MULTITHREADING >= 100
-    conf->maxAsyncOperationQueueSize = 0;
-    conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */
-#endif
-
     /* --> Finish setting the default static config <-- */
 
     return UA_STATUSCODE_GOOD;
@@ -244,11 +220,7 @@ setDefaultConfig(UA_ServerConfig *conf) {
 
 UA_EXPORT UA_StatusCode
 UA_ServerConfig_setBasics(UA_ServerConfig* conf) {
-    UA_StatusCode res = setDefaultConfig(conf);
-    UA_LOG_WARNING(&conf->logger, UA_LOGCATEGORY_USERLAND,
-                   "AcceptAll Certificate Verification. "
-                   "Any remote certificate will be accepted.");
-    return res;
+    return setDefaultConfig(conf);
 }
 
 static UA_StatusCode
@@ -257,41 +229,13 @@ addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber,
     return UA_ServerConfig_addNetworkLayerTCP(conf, portNumber, sendBufferSize, recvBufferSize);
 }
 
-#ifdef UA_ENABLE_WEBSOCKET_SERVER
-UA_EXPORT UA_StatusCode
-UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
-                                   UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
-    /* Add a network layer */
-    UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
-        UA_realloc(conf->networkLayers,
-                   sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
-    if(!tmp)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    conf->networkLayers = tmp;
-
-    UA_ConnectionConfig config = UA_ConnectionConfig_default;
-    if (sendBufferSize > 0)
-        config.sendBufferSize = sendBufferSize;
-    if (recvBufferSize > 0)
-        config.recvBufferSize = recvBufferSize;
-
-    conf->networkLayers[conf->networkLayersSize] =
-        UA_ServerNetworkLayerWS(config, portNumber, &conf->logger);
-    if (!conf->networkLayers[conf->networkLayersSize].handle)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    conf->networkLayersSize++;
-
-    return UA_STATUSCODE_GOOD;
-}
-#endif
 
 UA_EXPORT UA_StatusCode
 UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
                                    UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
     /* Add a network layer */
     UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
-        UA_realloc(conf->networkLayers,
-                   sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
+        UA_realloc(conf->networkLayers, sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     conf->networkLayers = tmp;
@@ -314,10 +258,11 @@ UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
 UA_EXPORT UA_StatusCode
 UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config, 
                                       const UA_ByteString *certificate) {
+    UA_StatusCode retval;
+
     /* Allocate the SecurityPolicies */
     UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
-        UA_realloc(config->securityPolicies,
-                   sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+        UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     config->securityPolicies = tmp;
@@ -326,9 +271,8 @@ UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
     UA_ByteString localCertificate = UA_BYTESTRING_NULL;
     if(certificate)
         localCertificate = *certificate;
-    UA_StatusCode retval =
-        UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize],
-                               NULL, localCertificate, &config->logger);
+    retval = UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize], NULL,
+                                    localCertificate, &config->logger);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->securityPoliciesSize++;
@@ -338,11 +282,13 @@ UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
 
 UA_EXPORT UA_StatusCode
 UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri, 
-                            UA_MessageSecurityMode securityMode) {
+                            UA_MessageSecurityMode securityMode)
+{
+    UA_StatusCode retval;
+
     /* Allocate the endpoint */
-    UA_EndpointDescription *tmp = (UA_EndpointDescription *)
-        UA_realloc(config->endpoints,
-                   sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
+    UA_EndpointDescription * tmp = (UA_EndpointDescription *)
+        UA_realloc(config->endpoints, sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
     if(!tmp) {
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
@@ -360,9 +306,8 @@ UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPol
         return UA_STATUSCODE_BADINVALIDARGUMENT;
 
     /* Populate the endpoint */
-    UA_StatusCode retval =
-        createEndpoint(config, &config->endpoints[config->endpointsSize],
-                       policy, securityMode);
+    retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
+                            policy, securityMode);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->endpointsSize++;
@@ -372,36 +317,33 @@ UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPol
 
 UA_EXPORT UA_StatusCode
 UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) {
+    UA_StatusCode retval;
+
     /* Allocate the endpoints */
     UA_EndpointDescription * tmp = (UA_EndpointDescription *)
-        UA_realloc(config->endpoints,
-                   sizeof(UA_EndpointDescription) *
-                   (2 * config->securityPoliciesSize + config->endpointsSize));
+        UA_realloc(config->endpoints, sizeof(UA_EndpointDescription) * (2 * config->securityPoliciesSize + config->endpointsSize));
     if(!tmp) {
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
     config->endpoints = tmp;
 
     /* Populate the endpoints */
-    for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
-        if(UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &config->securityPolicies[i].policyUri)) {
-            UA_StatusCode retval =
-                createEndpoint(config, &config->endpoints[config->endpointsSize],
-                               &config->securityPolicies[i], UA_MESSAGESECURITYMODE_NONE);
+    for (size_t i = 0; i < config->securityPoliciesSize; ++i) {
+        if (UA_String_equal(&UA_SECURITY_POLICY_NONE_URI, &config->securityPolicies[i].policyUri)) {
+            retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
+                                    &config->securityPolicies[i], UA_MESSAGESECURITYMODE_NONE);
             if(retval != UA_STATUSCODE_GOOD)
                 return retval;
             config->endpointsSize++;
         } else {
-            UA_StatusCode retval =
-                createEndpoint(config, &config->endpoints[config->endpointsSize],
-                               &config->securityPolicies[i], UA_MESSAGESECURITYMODE_SIGN);
+            retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
+                                    &config->securityPolicies[i], UA_MESSAGESECURITYMODE_SIGN);
             if(retval != UA_STATUSCODE_GOOD)
                 return retval;
             config->endpointsSize++;
 
             retval = createEndpoint(config, &config->endpoints[config->endpointsSize],
-                                    &config->securityPolicies[i],
-                                    UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
+                                    &config->securityPolicies[i], UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
             if(retval != UA_STATUSCODE_GOOD)
                 return retval;
             config->endpointsSize++;
@@ -416,7 +358,7 @@ UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNu
                                        const UA_ByteString *certificate,
                                        UA_UInt32 sendBufferSize,
                                        UA_UInt32 recvBufferSize) {
-    if(!config)
+    if (!config)
         return UA_STATUSCODE_BADINVALIDARGUMENT;
 
     UA_StatusCode retval = setDefaultConfig(config);
@@ -448,17 +390,12 @@ UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNu
     }
 
     /* Allocate the endpoint */
-    retval = UA_ServerConfig_addEndpoint(config, UA_SECURITY_POLICY_NONE_URI,
-                                         UA_MESSAGESECURITYMODE_NONE);
+    retval = UA_ServerConfig_addEndpoint(config, UA_SECURITY_POLICY_NONE_URI, UA_MESSAGESECURITYMODE_NONE);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_clean(config);
         return retval;
     }
 
-    UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
-                   "AcceptAll Certificate Verification. "
-                   "Any remote certificate will be accepted.");
-
     return UA_STATUSCODE_GOOD;
 }
 
@@ -468,10 +405,11 @@ UA_EXPORT UA_StatusCode
 UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config, 
                                                const UA_ByteString *certificate,
                                                const UA_ByteString *privateKey) {
+    UA_StatusCode retval;
+
     /* Allocate the SecurityPolicies */
     UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
-        UA_realloc(config->securityPolicies,
-                   sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+        UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     config->securityPolicies = tmp;
@@ -483,10 +421,9 @@ UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config,
         localCertificate = *certificate;
     if(privateKey)
        localPrivateKey = *privateKey;
-    UA_StatusCode retval =
-        UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
-                                        &config->certificateVerification,
-                                        localCertificate, localPrivateKey, &config->logger);
+    retval = UA_SecurityPolicy_Basic128Rsa15(&config->securityPolicies[config->securityPoliciesSize],
+                                             &config->certificateVerification,
+                                             localCertificate, localPrivateKey, &config->logger);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->securityPoliciesSize++;
@@ -498,10 +435,11 @@ UA_EXPORT UA_StatusCode
 UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config, 
                                           const UA_ByteString *certificate,
                                           const UA_ByteString *privateKey) {
+    UA_StatusCode retval;
+
     /* Allocate the SecurityPolicies */
     UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
-        UA_realloc(config->securityPolicies,
-                   sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+        UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     config->securityPolicies = tmp;
@@ -513,10 +451,9 @@ UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config,
         localCertificate = *certificate;
     if(privateKey)
        localPrivateKey = *privateKey;
-    UA_StatusCode retval =
-        UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
-                                   &config->certificateVerification,
-                                   localCertificate, localPrivateKey, &config->logger);
+    retval = UA_SecurityPolicy_Basic256(&config->securityPolicies[config->securityPoliciesSize],
+                                        &config->certificateVerification,
+                                        localCertificate, localPrivateKey, &config->logger);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->securityPoliciesSize++;
@@ -528,10 +465,11 @@ UA_EXPORT UA_StatusCode
 UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config, 
                                                 const UA_ByteString *certificate,
                                                 const UA_ByteString *privateKey) {
+    UA_StatusCode retval;
+
     /* Allocate the SecurityPolicies */
     UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
-        UA_realloc(config->securityPolicies,
-                   sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
+        UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     config->securityPolicies = tmp;
@@ -543,10 +481,9 @@ UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
         localCertificate = *certificate;
     if(privateKey)
        localPrivateKey = *privateKey;
-    UA_StatusCode retval =
-        UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
-                                         &config->certificateVerification,
-                                         localCertificate, localPrivateKey, &config->logger);
+    retval = UA_SecurityPolicy_Basic256Sha256(&config->securityPolicies[config->securityPoliciesSize],
+                                              &config->certificateVerification,
+                                              localCertificate, localPrivateKey, &config->logger);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->securityPoliciesSize++;
@@ -558,10 +495,11 @@ UA_EXPORT UA_StatusCode
 UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
                                        const UA_ByteString *certificate,
                                        const UA_ByteString *privateKey) {
+    UA_StatusCode retval;
+
     /* Allocate the SecurityPolicies */
     UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
-        UA_realloc(config->securityPolicies,
-                   sizeof(UA_SecurityPolicy) * (4 + config->securityPoliciesSize));
+        UA_realloc(config->securityPolicies, sizeof(UA_SecurityPolicy) * (4 + config->securityPoliciesSize));
     if(!tmp)
         return UA_STATUSCODE_BADOUTOFMEMORY;
     config->securityPolicies = tmp;
@@ -574,9 +512,8 @@ UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
     if(privateKey)
        localPrivateKey = *privateKey;
 
-    UA_StatusCode retval =
-        UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize],
-                               NULL, localCertificate, &config->logger);
+    retval = UA_SecurityPolicy_None(&config->securityPolicies[config->securityPoliciesSize], NULL,
+                                    localCertificate, &config->logger);
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     config->securityPoliciesSize++;
@@ -629,6 +566,11 @@ UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
     if (retval != UA_STATUSCODE_GOOD)
         return retval;
 
+    if(trustListSize == 0)
+        UA_LOG_WARNING(&conf->logger, UA_LOGCATEGORY_USERLAND,
+                       "No CA trust-list provided. "
+                       "Any remote certificate will be accepted.");
+
     retval = addDefaultNetworkLayers(conf, portNumber, 0, 0);
     if(retval != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_clean(conf);
@@ -664,15 +606,6 @@ UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
 /* Default Client Settings */
 /***************************/
 
-UA_Client * UA_Client_new() {
-    UA_ClientConfig config;
-    memset(&config, 0, sizeof(UA_ClientConfig));
-    config.logger.log = UA_Log_Stdout_log;
-    config.logger.context = NULL;
-    config.logger.clear = UA_Log_Stdout_clear;
-    return UA_Client_newWithConfig(&config);
-}
-
 static UA_INLINE void
 UA_ClientConnectionTCP_poll_callback(UA_Client *client, void *data) {
     UA_ClientConnectionTCP_poll(client, data);
@@ -683,20 +616,15 @@ UA_ClientConfig_setDefault(UA_ClientConfig *config) {
     config->timeout = 5000;
     config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */
 
-    if(!config->logger.log) {
-       config->logger.log = UA_Log_Stdout_log;
-       config->logger.context = NULL;
-       config->logger.clear = UA_Log_Stdout_clear;
-    }
+    config->logger.log = UA_Log_Stdout_log;
+    config->logger.context = NULL;
+    config->logger.clear = UA_Log_Stdout_clear;
 
     config->localConnectionConfig = UA_ConnectionConfig_default;
 
     /* Certificate Verification that accepts every certificate. Can be
      * overwritten when the policy is specialized. */
     UA_CertificateVerification_AcceptAll(&config->certificateVerification);
-    UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND,
-                   "AcceptAll Certificate Verification. "
-                   "Any remote certificate will be accepted.");
 
     /* With encryption enabled, the applicationUri needs to match the URI from
      * the certificate */

+ 3 - 3
plugins/ua_log_stdout.c

@@ -10,7 +10,7 @@
 
 #include <stdio.h>
 
-#if UA_MULTITHREADING >= 200
+#ifdef UA_ENABLE_MULTITHREADING
 #include <pthread.h>
 static pthread_mutex_t printf_mutex = PTHREAD_MUTEX_INITIALIZER;
 #endif
@@ -53,7 +53,7 @@ UA_Log_Stdout_log(void *_, UA_LogLevel level, UA_LogCategory category,
     UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
     UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset);
 
-#if UA_MULTITHREADING >= 200
+#ifdef UA_ENABLE_MULTITHREADING
     pthread_mutex_lock(&printf_mutex);
 #endif
 
@@ -64,7 +64,7 @@ UA_Log_Stdout_log(void *_, UA_LogLevel level, UA_LogCategory category,
     printf("\n");
     fflush(stdout);
 
-#if UA_MULTITHREADING >= 200
+#ifdef UA_ENABLE_MULTITHREADING
     pthread_mutex_unlock(&printf_mutex);
 #endif
 }

+ 0 - 304
plugins/ua_network_pubsub_mqtt.c

@@ -1,304 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright (c) 2018 Fraunhofer IOSB (Author: Lukas Meling)
- */
-
-/**
- * This uses the mqtt/ua_mqtt_adapter.h to call mqtt functions.
- * Currently only ua_mqtt_adapter.c implements this 
- * interface and maps them to the specific "MQTT-C" library functions. 
- * Another mqtt lib could be used.
- * "ua_mqtt_pal.c" forwards the network calls (send/recv) to UA_Connection (TCP).
- */
-
-#include "mqtt/ua_mqtt_adapter.h"
-#include "open62541/plugin/log_stdout.h"
-
-static UA_StatusCode
-UA_uaQos_toMqttQos(UA_BrokerTransportQualityOfService uaQos, UA_Byte *qos){
-    switch (uaQos){
-        case UA_BROKERTRANSPORTQUALITYOFSERVICE_BESTEFFORT:
-            *qos = 0;
-            break;
-        case UA_BROKERTRANSPORTQUALITYOFSERVICE_ATLEASTONCE:
-            *qos = 1;
-            break;
-        case UA_BROKERTRANSPORTQUALITYOFSERVICE_ATMOSTONCE:
-            *qos = 2;
-            break;
-        default:
-            break;
-    }
-    return UA_STATUSCODE_GOOD;
-}
-
-/**
- * Open mqtt connection based on the connectionConfig.
- * 
- *
- * @return ref to created channel, NULL on error
- */
-static UA_PubSubChannel *
-UA_PubSubChannelMQTT_open(const UA_PubSubConnectionConfig *connectionConfig) {
-    UA_NetworkAddressUrlDataType address;
-    memset(&address, 0, sizeof(UA_NetworkAddressUrlDataType));
-    if(UA_Variant_hasScalarType(&connectionConfig->address, &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE])){
-        address = *(UA_NetworkAddressUrlDataType *)connectionConfig->address.data;
-    } else {
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT Connection creation failed. Invalid Address.");
-        return NULL;
-    }
-    
-    /* allocate and init memory for the Mqtt specific internal data */
-    UA_PubSubChannelDataMQTT * channelDataMQTT =
-            (UA_PubSubChannelDataMQTT *) UA_calloc(1, (sizeof(UA_PubSubChannelDataMQTT)));
-    if(!channelDataMQTT){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT Connection creation failed. Out of memory.");
-        return NULL;
-    }
-    
-    /* set default values */
-    UA_String mqttClientId = UA_STRING("open62541_pub");
-    memcpy(channelDataMQTT, &(UA_PubSubChannelDataMQTT){address, 2000,2000, NULL, NULL,&mqttClientId, NULL, NULL, NULL}, sizeof(UA_PubSubChannelDataMQTT));
-    /* iterate over the given KeyValuePair paramters */
-    UA_String sendBuffer = UA_STRING("sendBufferSize"), recvBuffer = UA_STRING("recvBufferSize"), clientId = UA_STRING("mqttClientId");
-    for(size_t i = 0; i < connectionConfig->connectionPropertiesSize; i++){
-        if(UA_String_equal(&connectionConfig->connectionProperties[i].key.name, &sendBuffer)){
-            if(UA_Variant_hasScalarType(&connectionConfig->connectionProperties[i].value, &UA_TYPES[UA_TYPES_UINT32])){
-                channelDataMQTT->mqttSendBufferSize = *(UA_UInt32 *) connectionConfig->connectionProperties[i].value.data;
-            }
-        } else if(UA_String_equal(&connectionConfig->connectionProperties[i].key.name, &recvBuffer)){
-            if(UA_Variant_hasScalarType(&connectionConfig->connectionProperties[i].value, &UA_TYPES[UA_TYPES_UINT32])){
-                channelDataMQTT->mqttRecvBufferSize = *(UA_UInt32 *) connectionConfig->connectionProperties[i].value.data;
-            }
-        } else if(UA_String_equal(&connectionConfig->connectionProperties[i].key.name, &clientId)){
-            if(UA_Variant_hasScalarType(&connectionConfig->connectionProperties[i].value, &UA_TYPES[UA_TYPES_STRING])){
-                channelDataMQTT->mqttClientId = (UA_String *) connectionConfig->connectionProperties[i].value.data;
-            }
-        } else {
-            UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT Connection creation. Unknown connection parameter.");
-        }
-    }
-    
-    /* Create a new channel */
-    UA_PubSubChannel *newChannel = (UA_PubSubChannel *) UA_calloc(1, sizeof(UA_PubSubChannel));
-    if(!newChannel){
-        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT Connection creation failed. Out of memory.");
-        UA_free(channelDataMQTT);
-        return NULL;
-    }
-
-    /* Allocate memory for mqtt receive buffer */
-    if(channelDataMQTT->mqttRecvBufferSize > 0){
-        channelDataMQTT->mqttRecvBuffer = (uint8_t*)UA_calloc(channelDataMQTT->mqttRecvBufferSize, sizeof(uint8_t));
-        if(channelDataMQTT->mqttRecvBuffer == NULL){
-            UA_free(channelDataMQTT);
-            UA_free(newChannel);
-            return NULL;
-        }
-    }
-    
-    /* Allocate memory for mqtt send buffer */
-    if(channelDataMQTT->mqttSendBufferSize > 0){
-        channelDataMQTT->mqttSendBuffer = (uint8_t*)UA_calloc(channelDataMQTT->mqttSendBufferSize, sizeof(uint8_t));
-        if(channelDataMQTT->mqttSendBuffer == NULL){
-            if(channelDataMQTT->mqttRecvBufferSize > 0){
-                UA_free(channelDataMQTT->mqttRecvBuffer);
-            }
-            UA_free(channelDataMQTT);
-            UA_free(newChannel);
-            return NULL;
-        }
-    }
-    
-    /*link channel and internal channel data*/
-    newChannel->handle = channelDataMQTT;
-    
-    /* MQTT Client connect call. */
-    UA_StatusCode ret = connectMqtt(channelDataMQTT);
-    
-    if(ret != UA_STATUSCODE_GOOD){
-        /* try to disconnect tcp */
-        disconnectMqtt(channelDataMQTT);
-        UA_free(channelDataMQTT->mqttSendBuffer);
-        UA_free(channelDataMQTT->mqttRecvBuffer);
-        UA_free(channelDataMQTT);
-        UA_free(newChannel);
-        return NULL;
-    }
-    newChannel->state = UA_PUBSUB_CHANNEL_RDY;
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT Connection established.");
-    return newChannel;
-}
-
-/**
- * Subscribe to topic specified in brokerTransportSettings->queueName.
- *
- * @return UA_STATUSCODE_GOOD on success
- */
-static UA_StatusCode
-UA_PubSubChannelMQTT_regist(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings,
-                            void (*callback)(UA_ByteString *encodedBuffer, UA_ByteString *topic)) {
-    if(channel->state != UA_PUBSUB_CHANNEL_RDY){
-        UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT regist failed. Channel closed.");
-        return UA_STATUSCODE_BADCONNECTIONCLOSED;
-    }
-
-    UA_PubSubChannelDataMQTT *channelDataMQTT = (UA_PubSubChannelDataMQTT *) channel->handle;
-    channelDataMQTT->callback = callback;
-    
-    if(transportSettings != NULL && transportSettings->encoding == UA_EXTENSIONOBJECT_DECODED
-            && transportSettings->content.decoded.type->typeIndex == UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE){
-        UA_BrokerWriterGroupTransportDataType *brokerTransportSettings =
-                (UA_BrokerWriterGroupTransportDataType*)transportSettings->content.decoded.data;
-
-        UA_Byte qos = 0;
-        UA_uaQos_toMqttQos(brokerTransportSettings->requestedDeliveryGuarantee, &qos);
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: register");
-        return subscribeMqtt(channelDataMQTT, brokerTransportSettings->queueName, qos);
-    }else{
-         return UA_STATUSCODE_BADARGUMENTSMISSING;
-    }
-}
-
-/**
- * Remove subscription specified in brokerTransportSettings->queueName.
- *
- * @return UA_STATUSCODE_GOOD on success
- */
-static UA_StatusCode
-UA_PubSubChannelMQTT_unregist(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings) {
-    if(channel->state != UA_PUBSUB_CHANNEL_RDY){
-        UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: unregister failed. Channel closed.");
-        return UA_STATUSCODE_BADCONNECTIONCLOSED;
-    }
-
-    UA_PubSubChannelDataMQTT * channelDataMQTT = (UA_PubSubChannelDataMQTT *) channel->handle;
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: unregister");
-    if(transportSettings != NULL && transportSettings->encoding == UA_EXTENSIONOBJECT_DECODED
-            && transportSettings->content.decoded.type->typeIndex == UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE){
-        UA_BrokerWriterGroupTransportDataType *brokerTransportSettings =
-                (UA_BrokerWriterGroupTransportDataType*)transportSettings->content.decoded.data;
-
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: unregister");
-        return unSubscribeMqtt(channelDataMQTT, brokerTransportSettings->queueName);
-    }else{
-         return UA_STATUSCODE_BADARGUMENTSMISSING;
-    }
-}
-
-/**
- * Send a message.
- *
- * @return UA_STATUSCODE_GOOD if success
- */
-static UA_StatusCode
-UA_PubSubChannelMQTT_send(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings, const UA_ByteString *buf) {
-    if(channel->state != UA_PUBSUB_CHANNEL_RDY){
-        UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: sending failed. Invalid state.");
-        return UA_STATUSCODE_BADCONNECTIONCLOSED;
-    }
-
-    UA_PubSubChannelDataMQTT *channelDataMQTT = (UA_PubSubChannelDataMQTT *) channel->handle;
-    UA_StatusCode ret = UA_STATUSCODE_GOOD;
-    UA_Byte qos = 0;
-    
-    if(transportSettings != NULL && transportSettings->encoding == UA_EXTENSIONOBJECT_DECODED 
-            && transportSettings->content.decoded.type->typeIndex == UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE){
-        UA_BrokerWriterGroupTransportDataType *brokerTransportSettings = (UA_BrokerWriterGroupTransportDataType*)transportSettings->content.decoded.data;
-        UA_uaQos_toMqttQos(brokerTransportSettings->requestedDeliveryGuarantee, &qos);
-        
-        UA_String topic;
-        topic = brokerTransportSettings->queueName;
-        ret = publishMqtt(channelDataMQTT, topic, buf, qos);
-
-        if(ret){
-            channel->state = UA_PUBSUB_CHANNEL_ERROR;
-            UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Publish failed");
-        }else{
-            UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Publish");
-        }
-    }else{
-        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Transport settings not found.");
-    }
-    return ret;
-}
-
-/**
- * Close channel and free the channel data.
- *
- * @return UA_STATUSCODE_GOOD if success
- */
-static UA_StatusCode
-UA_PubSubChannelMQTT_close(UA_PubSubChannel *channel) {
-    /* already closed */
-    if(channel->state == UA_PUBSUB_CHANNEL_CLOSED)
-        return UA_STATUSCODE_GOOD;
-    UA_PubSubChannelDataMQTT *channelDataMQTT = (UA_PubSubChannelDataMQTT *) channel->handle;
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub MQTT: Closing PubSubChannel.");
-    disconnectMqtt(channelDataMQTT);
-    UA_free(channelDataMQTT);
-    UA_free(channel);
-    return UA_STATUSCODE_GOOD;
-}
-
-/**
- * Calls the send and receive functions of the mqtt network stack.
- *
- * @return UA_STATUSCODE_GOOD if success
- */
-static UA_StatusCode
-UA_PubSubChannelMQTT_yield(UA_PubSubChannel *channel, UA_UInt16 timeout){
-    UA_StatusCode ret = UA_STATUSCODE_BADINVALIDARGUMENT;
-    if(channel == NULL){
-        return ret;
-    }
-
-    if(channel->state == UA_PUBSUB_CHANNEL_ERROR){
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-
-    UA_PubSubChannelDataMQTT *channelDataMQTT = (UA_PubSubChannelDataMQTT *) channel->handle;
-    ret = yieldMqtt(channelDataMQTT, timeout);
-    if(ret != UA_STATUSCODE_GOOD){
-        channel->state = UA_PUBSUB_CHANNEL_ERROR;
-        return ret;
-    }
-
-    return ret;
-}
-
-/**
- * Generate a new MQTT channel. Based on the given configuration. Uses yield and no recv call.
- *
- * @param connectionConfig connection configuration
- * @return  ref to created channel, NULL on error
- */
-static UA_PubSubChannel *
-TransportLayerMQTT_addChannel(UA_PubSubConnectionConfig *connectionConfig) {
-    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "PubSub MQTT: channel requested.");
-    UA_PubSubChannel * pubSubChannel = UA_PubSubChannelMQTT_open(connectionConfig);
-    if(pubSubChannel){
-        pubSubChannel->regist = UA_PubSubChannelMQTT_regist;
-        pubSubChannel->unregist = UA_PubSubChannelMQTT_unregist;
-        pubSubChannel->send = UA_PubSubChannelMQTT_send;
-        pubSubChannel->close = UA_PubSubChannelMQTT_close;
-        pubSubChannel->yield = UA_PubSubChannelMQTT_yield;
-        
-        pubSubChannel->connectionConfig = connectionConfig;
-    }
-    return pubSubChannel;
-}
-
-//MQTT channel factory
-UA_PubSubTransportLayer
-UA_PubSubTransportLayerMQTT(){
-    UA_PubSubTransportLayer pubSubTransportLayer;
-    pubSubTransportLayer.transportProfileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt");
-    pubSubTransportLayer.createPubSubChannel = &TransportLayerMQTT_addChannel;
-    return pubSubTransportLayer;
-}
-
-#undef _POSIX_C_SOURCE

+ 0 - 47
plugins/ua_network_pubsub_mqtt.h

@@ -1,47 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- * 
- *    Copyright 2018 (c) Fraunhofer IOSB (Author: Lukas Meling)
- */
-
-#ifndef UA_NETWORK_MQTT_H_
-#define UA_NETWORK_MQTT_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "open62541/plugin/pubsub.h"
-#include "open62541/network_tcp.h"
-
-/* mqtt network layer specific internal data */
-typedef struct {
-    UA_NetworkAddressUrlDataType address;
-    UA_UInt32 mqttRecvBufferSize;
-    UA_UInt32 mqttSendBufferSize;
-    uint8_t *mqttSendBuffer; 
-    uint8_t *mqttRecvBuffer; 
-    UA_String *mqttClientId;
-    UA_Connection *connection;
-    void * mqttClient;
-    void (*callback)(UA_ByteString *encodedBuffer, UA_ByteString *topic);
-} UA_PubSubChannelDataMQTT;
-/* TODO:
- * will topic,
- * will message,
- * user name,
- * password,
- * keep alive
- * ssl: cert, flag
- */    
-
-
-UA_PubSubTransportLayer
-UA_PubSubTransportLayerMQTT(void);
-
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* UA_NETWORK_MQTT_H_ */

+ 98 - 65
plugins/ua_nodestore_ziptree.c

@@ -6,9 +6,20 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  */
 
-#include <open62541/plugin/nodestore_default.h>
+#include <open62541/plugin/nodestore.h>
 #include "ziptree.h"
 
+#ifndef UA_ENABLE_CUSTOM_NODESTORE
+
+#ifdef UA_ENABLE_MULTITHREADING
+#include <pthread.h>
+#define BEGIN_CRITSECT(NODEMAP) pthread_mutex_lock(&(NODEMAP)->mutex)
+#define END_CRITSECT(NODEMAP) pthread_mutex_unlock(&(NODEMAP)->mutex)
+#else
+#define BEGIN_CRITSECT(NODEMAP) do {} while(0)
+#define END_CRITSECT(NODEMAP) do {} while(0)
+#endif
+
 /* container_of */
 #define container_of(ptr, type, member) \
     (type *)((uintptr_t)ptr - offsetof(type,member))
@@ -48,7 +59,10 @@ typedef struct NodeTree NodeTree;
 
 typedef struct {
     NodeTree root;
-} ZipContext;
+#ifdef UA_ENABLE_MULTITHREADING
+    pthread_mutex_t mutex; /* Protect access */
+#endif
+} NodeMap;
 
 ZIP_PROTTYPE(NodeTree, NodeEntry, NodeEntry)
 ZIP_IMPL(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
@@ -94,7 +108,7 @@ newEntry(UA_NodeClass nodeClass) {
 
 static void
 deleteEntry(NodeEntry *entry) {
-    UA_Node_clear((UA_Node*)&entry->nodeId);
+    UA_Node_deleteMembers((UA_Node*)&entry->nodeId);
     UA_free(entry);
 }
 
@@ -108,63 +122,72 @@ cleanupEntry(NodeEntry *entry) {
 /* Interface functions */
 /***********************/
 
-/* Not yet inserted into the ZipContext */
-static UA_Node *
-zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
+/* Not yet inserted into the NodeMap */
+UA_Node *
+UA_Nodestore_newNode(void *nsCtx, UA_NodeClass nodeClass) {
     NodeEntry *entry = newEntry(nodeClass);
     if(!entry)
         return NULL;
     return (UA_Node*)&entry->nodeId;
 }
 
-/* Not yet inserted into the ZipContext */
-static void
-zipNsDeleteNode(void *nsCtx, UA_Node *node) {
+/* Not yet inserted into the NodeMap */
+void
+UA_Nodestore_deleteNode(void *nsCtx, UA_Node *node) {
     deleteEntry(container_of(node, NodeEntry, nodeId));
 }
 
-static const UA_Node *
-zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
-    ZipContext *ns = (ZipContext*)nsCtx;
+const UA_Node *
+UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId) {
+    NodeMap *ns = (NodeMap*)nsCtx;
+    BEGIN_CRITSECT(ns);
     NodeEntry dummy;
     dummy.nodeIdHash = UA_NodeId_hash(nodeId);
     dummy.nodeId = *nodeId;
     NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
-    if(!entry)
+    if(!entry) {
+        END_CRITSECT(ns);
         return NULL;
+    }
     ++entry->refCount;
+    END_CRITSECT(ns);
     return (const UA_Node*)&entry->nodeId;
 }
 
-static void
-zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
+void
+UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node) {
     if(!node)
         return;
+#ifdef UA_ENABLE_MULTITHREADING
+    NodeMap *ns = (NodeMap*)nsCtx;
+#endif
+    BEGIN_CRITSECT(ns);
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);
     UA_assert(entry->refCount > 0);
     --entry->refCount;
     cleanupEntry(entry);
+    END_CRITSECT(ns);
 }
 
-static UA_StatusCode
-zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
+UA_StatusCode
+UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
                          UA_Node **outNode) {
     /* Find the node */
-    const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
+    const UA_Node *node = UA_Nodestore_getNode(nsCtx, nodeId);
     if(!node)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
     /* Create the new entry */
     NodeEntry *ne = newEntry(node->nodeClass);
     if(!ne) {
-        zipNsReleaseNode(nsCtx, node);
+        UA_Nodestore_releaseNode(nsCtx, node);
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
 
     /* Copy the node content */
     UA_Node *nnode = (UA_Node*)&ne->nodeId;
     UA_StatusCode retval = UA_Node_copy(node, nnode);
-    zipNsReleaseNode(nsCtx, node);
+    UA_Nodestore_releaseNode(nsCtx, node);
     if(retval != UA_STATUSCODE_GOOD) {
         deleteEntry(ne);
         return retval;
@@ -175,10 +198,11 @@ zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode
-zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
+UA_StatusCode
+UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);
-    ZipContext *ns = (ZipContext*)nsCtx;
+    NodeMap *ns = (NodeMap*)nsCtx;
+    BEGIN_CRITSECT(ns);
 
     /* Ensure that the NodeId is unique */
     NodeEntry dummy;
@@ -194,6 +218,7 @@ zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
         dummy.nodeIdHash = UA_NodeId_hash(&node->nodeId);
         if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */
             deleteEntry(entry);
+            END_CRITSECT(ns);
             return UA_STATUSCODE_BADNODEIDEXISTS;
         }
     }
@@ -203,6 +228,7 @@ zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
         UA_StatusCode retval = UA_NodeId_copy(&node->nodeId, addedNodeId);
         if(retval != UA_STATUSCODE_GOOD) {
             deleteEntry(entry);
+            END_CRITSECT(ns);
             return retval;
         }
     }
@@ -210,17 +236,16 @@ zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
     /* Insert the node */
     entry->nodeIdHash = dummy.nodeIdHash;
     ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_FFS32(UA_UInt32_random()));
+    END_CRITSECT(ns);
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode
-zipNsReplaceNode(void *nsCtx, UA_Node *node) {
+UA_StatusCode
+UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node) {
     /* Find the node */
-    const UA_Node *oldNode = zipNsGetNode(nsCtx, &node->nodeId);
-    if(!oldNode) {
-        deleteEntry(container_of(node, NodeEntry, nodeId));
+    const UA_Node *oldNode = UA_Nodestore_getNode(nsCtx, &node->nodeId);
+    if(!oldNode)
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
-    }
 
     /* Test if the copy is current */
     NodeEntry *entry = container_of(node, NodeEntry, nodeId);
@@ -228,33 +253,39 @@ zipNsReplaceNode(void *nsCtx, UA_Node *node) {
     if(oldEntry != entry->orig) {
         /* The node was already updated since the copy was made */
         deleteEntry(entry);
-        zipNsReleaseNode(nsCtx, oldNode);
+        UA_Nodestore_releaseNode(nsCtx, oldNode);
         return UA_STATUSCODE_BADINTERNALERROR;
     }
 
     /* Replace */
-    ZipContext *ns = (ZipContext*)nsCtx;
+    NodeMap *ns = (NodeMap*)nsCtx;
+    BEGIN_CRITSECT(ns);
     ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
     entry->nodeIdHash = oldEntry->nodeIdHash;
     ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_RANK(entry, zipfields));
     oldEntry->deleted = true;
+    END_CRITSECT(ns);
 
-    zipNsReleaseNode(nsCtx, oldNode);
+    UA_Nodestore_releaseNode(nsCtx, oldNode);
     return UA_STATUSCODE_GOOD;
 }
 
-static UA_StatusCode
-zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
-    ZipContext *ns = (ZipContext*)nsCtx;
+UA_StatusCode
+UA_Nodestore_removeNode(void *nsCtx, const UA_NodeId *nodeId) {
+    NodeMap *ns = (NodeMap*)nsCtx;
+    BEGIN_CRITSECT(ns);
     NodeEntry dummy;
     dummy.nodeIdHash = UA_NodeId_hash(nodeId);
     dummy.nodeId = *nodeId;
     NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
-    if(!entry)
+    if(!entry) {
+        END_CRITSECT(ns);
         return UA_STATUSCODE_BADNODEIDUNKNOWN;
+    }
     ZIP_REMOVE(NodeTree, &ns->root, entry);
     entry->deleted = true;
     cleanupEntry(entry);
+    END_CRITSECT(ns);
     return UA_STATUSCODE_GOOD;
 }
 
@@ -269,14 +300,16 @@ nodeVisitor(NodeEntry *entry, void *data) {
     d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
 }
 
-static void
-zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
-             void *visitorCtx) {
+void
+UA_Nodestore_iterate(void *nsCtx, UA_NodestoreVisitor visitor,
+                     void *visitorCtx) {
     struct VisitorData d;
     d.visitor = visitor;
     d.visitorContext = visitorCtx;
-    ZipContext *ns = (ZipContext*)nsCtx;
+    NodeMap *ns = (NodeMap*)nsCtx;
+    BEGIN_CRITSECT(ns);
     ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
+    END_CRITSECT(ns);
 }
 
 static void
@@ -288,36 +321,36 @@ deleteNodeVisitor(NodeEntry *entry, void *data) {
 /* Nodestore Lifecycle */
 /***********************/
 
-static void
-zipNsClear(void *nsCtx) {
-    if (!nsCtx)
-        return;
-    ZipContext *ns = (ZipContext*)nsCtx;
-    ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
-    UA_free(ns);
-}
+const UA_Boolean inPlaceEditAllowed = true;
 
 UA_StatusCode
-UA_Nodestore_ZipTree(UA_Nodestore *ns) {
-    /* Allocate and initialize the context */
-    ZipContext *ctx = (ZipContext*)UA_malloc(sizeof(ZipContext));
-    if(!ctx)
+UA_Nodestore_new(void **nsCtx) {
+    /* Allocate and initialize the nodemap */
+    NodeMap *nodemap = (NodeMap*)UA_malloc(sizeof(NodeMap));
+    if(!nodemap)
         return UA_STATUSCODE_BADOUTOFMEMORY;
+#ifdef UA_ENABLE_MULTITHREADING
+    pthread_mutex_init(&nodemap->mutex, NULL);
+#endif
 
-    ZIP_INIT(&ctx->root);
+    ZIP_INIT(&nodemap->root);
 
     /* Populate the nodestore */
-    ns->context = (void*)ctx;
-    ns->clear = zipNsClear;
-    ns->newNode = zipNsNewNode;
-    ns->deleteNode = zipNsDeleteNode;
-    ns->getNode = zipNsGetNode;
-    ns->releaseNode = zipNsReleaseNode;
-    ns->getNodeCopy = zipNsGetNodeCopy;
-    ns->insertNode = zipNsInsertNode;
-    ns->replaceNode = zipNsReplaceNode;
-    ns->removeNode = zipNsRemoveNode;
-    ns->iterate = zipNsIterate;
-    
+    *nsCtx = (void*)nodemap;
     return UA_STATUSCODE_GOOD;
 }
+
+void
+UA_Nodestore_delete(void *nsCtx) {
+    if (!nsCtx)
+        return;
+
+    NodeMap *ns = (NodeMap*)nsCtx;
+#ifdef UA_ENABLE_MULTITHREADING
+    pthread_mutex_destroy(&ns->mutex);
+#endif
+    ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
+    UA_free(ns);
+}
+
+#endif /* UA_ENABLE_CUSTOM_NODESTORE */

+ 0 - 455
plugins/ua_nodestore_hashmap.c

@@ -1,455 +0,0 @@
-/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. 
- *
- *    Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- *    Copyright 2017 (c) Julian Grothoff
- *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
- */
-
-#include <open62541/plugin/nodestore_default.h>
-
-/* container_of */
-#define container_of(ptr, type, member) \
-    (type *)((uintptr_t)ptr - offsetof(type,member))
-
-/* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an
- * entry, iterate over candidate positions according to the NodeId hash.
- *
- * - Tombstone or non-matching NodeId: continue searching
- * - Matching NodeId: Return the entry
- * - NULL: Abort the search */
-
-typedef struct UA_NodeMapEntry {
-    struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */
-    UA_UInt16 refCount; /* How many consumers have a reference to the node? */
-    UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
-    UA_Node node;
-} UA_NodeMapEntry;
-
-#define UA_NODEMAP_MINSIZE 64
-#define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01)
-
-typedef struct {
-    UA_NodeMapEntry *entry;
-    UA_UInt32 nodeIdHash;
-} UA_NodeMapSlot;
-
-typedef struct {
-    UA_NodeMapSlot *slots;
-    UA_UInt32 size;
-    UA_UInt32 count;
-    UA_UInt32 sizePrimeIndex;
-} UA_NodeMap;
-
-/*********************/
-/* HashMap Utilities */
-/*********************/
-
-/* The size of the hash-map is always a prime number. They are chosen to be
- * close to the next power of 2. So the size ca. doubles with each prime. */
-static UA_UInt32 const primes[] = {
-    7,         13,         31,         61,         127,         251,
-    509,       1021,       2039,       4093,       8191,        16381,
-    32749,     65521,      131071,     262139,     524287,      1048573,
-    2097143,   4194301,    8388593,    16777213,   33554393,    67108859,
-    134217689, 268435399,  536870909,  1073741789, 2147483647,  4294967291
-};
-
-static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; }
-static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); }
-
-static UA_UInt16
-higher_prime_index(UA_UInt32 n) {
-    UA_UInt16 low  = 0;
-    UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32));
-    while(low != high) {
-        UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2));
-        if(n > primes[mid])
-            low = (UA_UInt16)(mid + 1);
-        else
-            high = mid;
-    }
-    return low;
-}
-
-/* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */
-static UA_NodeMapSlot *
-findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
-    UA_UInt32 h = UA_NodeId_hash(nodeid);
-    UA_UInt32 size = ns->size;
-    UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow  */
-    UA_UInt32 startIdx = (UA_UInt32)idx;
-    UA_UInt32 hash2 = mod2(h, size);
-
-    UA_NodeMapSlot *candidate = NULL;
-    do {
-        UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx];
-
-        if(slot->entry > UA_NODEMAP_TOMBSTONE) {
-            /* A Node with the NodeId does already exist */
-            if(slot->nodeIdHash == h &&
-               UA_NodeId_equal(&slot->entry->node.nodeId, nodeid))
-                return NULL;
-        } else {
-            /* Found a candidate node */
-            if(!candidate)
-                candidate = slot;
-            /* No matching node can come afterwards */
-            if(slot->entry == NULL)
-                return candidate;
-        }
-
-        idx += hash2;
-        if(idx >= size)
-            idx -= size;
-    } while((UA_UInt32)idx != startIdx);
-
-    return candidate;
-}
-
-/* The occupancy of the table after the call will be about 50% */
-static UA_StatusCode
-expand(UA_NodeMap *ns) {
-    UA_UInt32 osize = ns->size;
-    UA_UInt32 count = ns->count;
-    /* Resize only when table after removal of unused elements is either too
-       full or too empty */
-    if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE))
-        return UA_STATUSCODE_GOOD;
-
-    UA_NodeMapSlot *oslots = ns->slots;
-    UA_UInt32 nindex = higher_prime_index(count * 2);
-    UA_UInt32 nsize = primes[nindex];
-    UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nsize, sizeof(UA_NodeMapSlot));
-    if(!nslots)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    ns->slots = nslots;
-    ns->size = nsize;
-    ns->sizePrimeIndex = nindex;
-
-    /* recompute the position of every entry and insert the pointer */
-    for(size_t i = 0, j = 0; i < osize && j < count; ++i) {
-        if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE)
-            continue;
-        UA_NodeMapSlot *s = findFreeSlot(ns, &oslots[i].entry->node.nodeId);
-        UA_assert(s);
-        *s = oslots[i];
-        ++j;
-    }
-
-    UA_free(oslots);
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_NodeMapEntry *
-createEntry(UA_NodeClass nodeClass) {
-    size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node);
-    switch(nodeClass) {
-    case UA_NODECLASS_OBJECT:
-        size += sizeof(UA_ObjectNode);
-        break;
-    case UA_NODECLASS_VARIABLE:
-        size += sizeof(UA_VariableNode);
-        break;
-    case UA_NODECLASS_METHOD:
-        size += sizeof(UA_MethodNode);
-        break;
-    case UA_NODECLASS_OBJECTTYPE:
-        size += sizeof(UA_ObjectTypeNode);
-        break;
-    case UA_NODECLASS_VARIABLETYPE:
-        size += sizeof(UA_VariableTypeNode);
-        break;
-    case UA_NODECLASS_REFERENCETYPE:
-        size += sizeof(UA_ReferenceTypeNode);
-        break;
-    case UA_NODECLASS_DATATYPE:
-        size += sizeof(UA_DataTypeNode);
-        break;
-    case UA_NODECLASS_VIEW:
-        size += sizeof(UA_ViewNode);
-        break;
-    default:
-        return NULL;
-    }
-    UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(1, size);
-    if(!entry)
-        return NULL;
-    entry->node.nodeClass = nodeClass;
-    return entry;
-}
-
-static void
-deleteNodeMapEntry(UA_NodeMapEntry *entry) {
-    UA_Node_clear(&entry->node);
-    UA_free(entry);
-}
-
-static void
-cleanupNodeMapEntry(UA_NodeMapEntry *entry) {
-    if(entry->deleted && entry->refCount == 0)
-        deleteNodeMapEntry(entry);
-}
-
-static UA_NodeMapSlot *
-findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
-    UA_UInt32 h = UA_NodeId_hash(nodeid);
-    UA_UInt32 size = ns->size;
-    UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
-    UA_UInt32 hash2 = mod2(h, size);
-    UA_UInt32 startIdx = (UA_UInt32)idx;
-
-    do {
-        UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx];
-        if(slot->entry > UA_NODEMAP_TOMBSTONE) {
-            if(slot->nodeIdHash == h &&
-               UA_NodeId_equal(&slot->entry->node.nodeId, nodeid))
-                return slot;
-        } else {
-            if(slot->entry == NULL)
-                return NULL; /* No further entry possible */
-        }
-
-        idx += hash2;
-        if(idx >= size)
-            idx -= size;
-    } while((UA_UInt32)idx != startIdx);
-
-    return NULL;
-}
-
-/***********************/
-/* Interface functions */
-/***********************/
-
-static UA_Node *
-UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
-    UA_NodeMapEntry *entry = createEntry(nodeClass);
-    if(!entry)
-        return NULL;
-    return &entry->node;
-}
-
-static void
-UA_NodeMap_deleteNode(void *context, UA_Node *node) {
-    UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
-    UA_assert(&entry->node == node);
-    deleteNodeMapEntry(entry);
-}
-
-static const UA_Node *
-UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
-    if(!slot)
-        return NULL;
-    ++slot->entry->refCount;
-    return &slot->entry->node;
-}
-
-static void
-UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
-    if (!node)
-        return;
-    UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
-    UA_assert(&entry->node == node);
-    UA_assert(entry->refCount > 0);
-    --entry->refCount;
-    cleanupNodeMapEntry(entry);
-}
-
-static UA_StatusCode
-UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
-                       UA_Node **outNode) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
-    if(!slot)
-        return UA_STATUSCODE_BADNODEIDUNKNOWN;
-    UA_NodeMapEntry *entry = slot->entry;
-    UA_NodeMapEntry *newItem = createEntry(entry->node.nodeClass);
-    if(!newItem)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    UA_StatusCode retval = UA_Node_copy(&entry->node, &newItem->node);
-    if(retval == UA_STATUSCODE_GOOD) {
-        newItem->orig = entry; /* Store the pointer to the original */
-        *outNode = &newItem->node;
-    } else {
-        deleteNodeMapEntry(newItem);
-    }
-    return retval;
-}
-
-static UA_StatusCode
-UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
-    if(!slot)
-        return UA_STATUSCODE_BADNODEIDUNKNOWN;
-
-    UA_NodeMapEntry *entry = slot->entry;
-    slot->entry = UA_NODEMAP_TOMBSTONE;
-    UA_atomic_sync(); /* Set the tombstone before cleaning up. E.g. if the
-                       * nodestore is accessed from an interrupt. */
-    entry->deleted = true;
-    cleanupNodeMapEntry(entry);
-    --ns->count;
-    /* Downsize the hashmap if it is very empty */
-    if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE)
-        expand(ns); /* Can fail. Just continue with the bigger hashmap. */
-    return UA_STATUSCODE_GOOD;
-}
-
-static UA_StatusCode
-UA_NodeMap_insertNode(void *context, UA_Node *node,
-                      UA_NodeId *addedNodeId) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    if(ns->size * 3 <= ns->count * 4) {
-        if(expand(ns) != UA_STATUSCODE_GOOD)
-            return UA_STATUSCODE_BADINTERNALERROR;
-    }
-
-    UA_NodeMapSlot *slot;
-    if(node->nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
-       node->nodeId.identifier.numeric == 0) {
-        /* Create a random nodeid: Start at least with 50,000 to make sure we
-         * don not conflict with nodes from the spec. If we find a conflict, we
-         * just try another identifier until we have tried all possible
-         * identifiers. Since the size is prime and we don't change the increase
-         * val, we will reach the starting id again. E.g. adding a nodeset will
-         * create children while there are still other nodes which need to be
-         * created. Thus the node ids may collide. */
-        UA_UInt32 size = ns->size;
-        UA_UInt64 identifier = mod(50000 + size+1, UA_UINT32_MAX); /* Use 64bit to
-                                                                    * avoid overflow */
-        UA_UInt32 increase = mod2(ns->count+1, size);
-        UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id
-                                                    * is a valid 32 bit integer */
-
-        do {
-            node->nodeId.identifier.numeric = (UA_UInt32)identifier;
-            slot = findFreeSlot(ns, &node->nodeId);
-            if(slot)
-                break;
-            identifier += increase;
-            if(identifier >= size)
-                identifier -= size;
-        } while((UA_UInt32)identifier != startId);
-    } else {
-        slot = findFreeSlot(ns, &node->nodeId);
-    }
-
-    if(!slot) {
-        deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
-        return UA_STATUSCODE_BADNODEIDEXISTS;
-    }
-
-    /* Copy the NodeId */
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    if(addedNodeId) {
-        retval = UA_NodeId_copy(&node->nodeId, addedNodeId);
-        if(retval != UA_STATUSCODE_GOOD) {
-            deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
-            return retval;
-        }
-    }
-
-    /* Insert the node */
-    UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
-    slot->nodeIdHash = UA_NodeId_hash(&node->nodeId);
-    UA_atomic_sync(); /* Set the hash first */
-    slot->entry = newEntry;
-    ++ns->count;
-    return retval;
-}
-
-static UA_StatusCode
-UA_NodeMap_replaceNode(void *context, UA_Node *node) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
-
-    /* Find the node */
-    UA_NodeMapSlot *slot = findOccupiedSlot(ns, &node->nodeId);
-    if(!slot) {
-        deleteNodeMapEntry(newEntry);
-        return UA_STATUSCODE_BADNODEIDUNKNOWN;
-    }
-
-    /* The node was already updated since the copy was made? */
-    UA_NodeMapEntry *oldEntry = slot->entry;
-    if(oldEntry != newEntry->orig) {
-        deleteNodeMapEntry(newEntry);
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-
-    /* Replace the entry */
-    slot->entry = newEntry;
-    UA_atomic_sync();
-    oldEntry->deleted = true;
-    cleanupNodeMapEntry(oldEntry);
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor,
-                   void *visitorContext) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    for(UA_UInt32 i = 0; i < ns->size; ++i) {
-        UA_NodeMapSlot *slot = &ns->slots[i];
-        if(slot->entry > UA_NODEMAP_TOMBSTONE) {
-            /* The visitor can delete the node. So refcount here. */
-            slot->entry->refCount++;
-            visitor(visitorContext, &slot->entry->node);
-            slot->entry->refCount--;
-            cleanupNodeMapEntry(slot->entry);
-        }
-    }
-}
-
-static void
-UA_NodeMap_delete(void *context) {
-    UA_NodeMap *ns = (UA_NodeMap*)context;
-    UA_UInt32 size = ns->size;
-    UA_NodeMapSlot *slots = ns->slots;
-    for(UA_UInt32 i = 0; i < size; ++i) {
-        if(slots[i].entry > UA_NODEMAP_TOMBSTONE) {
-            /* On debugging builds, check that all nodes were release */
-            UA_assert(slots[i].entry->refCount == 0);
-            /* Delete the node */
-            deleteNodeMapEntry(slots[i].entry);
-        }
-    }
-    UA_free(ns->slots);
-    UA_free(ns);
-}
-
-UA_StatusCode
-UA_Nodestore_HashMap(UA_Nodestore *ns) {
-    /* Allocate and initialize the nodemap */
-    UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(sizeof(UA_NodeMap));
-    if(!nodemap)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE);
-    nodemap->size = primes[nodemap->sizePrimeIndex];
-    nodemap->count = 0;
-    nodemap->slots = (UA_NodeMapSlot*)
-        UA_calloc(nodemap->size, sizeof(UA_NodeMapSlot));
-    if(!nodemap->slots) {
-        UA_free(nodemap);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    /* Populate the nodestore */
-    ns->context = nodemap;
-    ns->clear = UA_NodeMap_delete;
-    ns->newNode = UA_NodeMap_newNode;
-    ns->deleteNode = UA_NodeMap_deleteNode;
-    ns->getNode = UA_NodeMap_getNode;
-    ns->releaseNode = UA_NodeMap_releaseNode;
-    ns->getNodeCopy = UA_NodeMap_getNodeCopy;
-    ns->insertNode = UA_NodeMap_insertNode;
-    ns->replaceNode = UA_NodeMap_replaceNode;
-    ns->removeNode = UA_NodeMap_removeNode;
-    ns->iterate = UA_NodeMap_iterate;
-    return UA_STATUSCODE_GOOD;
-}

+ 11 - 15
plugins/ua_pki_default.c

@@ -39,14 +39,14 @@ verifyApplicationURIAllowAll(void *verificationContext,
 }
 
 static void
-clearVerifyAllowAll(UA_CertificateVerification *cv) {
+deleteVerifyAllowAll(UA_CertificateVerification *cv) {
 
 }
 
 void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
     cv->verifyCertificate = verifyCertificateAllowAll;
     cv->verifyApplicationURI = verifyApplicationURIAllowAll;
-    cv->clear = clearVerifyAllowAll;
+    cv->deleteMembers = deleteVerifyAllowAll;
 }
 
 #ifdef UA_ENABLE_ENCRYPTION
@@ -89,11 +89,7 @@ fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **path
 
     struct dirent *ent;
     char buf2[PATH_MAX + 1];
-    char *res = realpath(buf, buf2);
-    if(!res) {
-        closedir(dir);
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
+    realpath(buf, buf2);
     size_t pathlen = strlen(buf2);
     *pathsSize = 0;
     while((ent = readdir (dir)) != NULL && *pathsSize < 256) {
@@ -214,16 +210,16 @@ certificateVerification_verify(void *verificationContext,
     mbedtls_x509_crt remoteCertificate;
 
     /* Temporary Object to parse the trustList */
-    mbedtls_x509_crt *tempCert = NULL;
+    mbedtls_x509_crt *tempCert;
 
     /* Temporary Object to parse the revocationList */
-    mbedtls_x509_crl *tempCrl = NULL;
+    mbedtls_x509_crl *tempCrl;
 
     /* Temporary Object to identify the parent CA when there is no intermediate CA */
-    mbedtls_x509_crt *parentCert = NULL;
+    mbedtls_x509_crt *parentCert;
 
     /* Temporary Object to identify the parent CA when there is intermediate CA */
-    mbedtls_x509_crt *parentCert_2 = NULL;
+    mbedtls_x509_crt *parentCert_2;
 
     /* Flag value to identify if the issuer certificate is found */
     int issuerKnown = 0;
@@ -490,7 +486,7 @@ certificateVerification_verifyApplicationURI(void *verificationContext,
 }
 
 static void
-certificateVerification_clear(UA_CertificateVerification *cv) {
+certificateVerification_deleteMembers(UA_CertificateVerification *cv) {
     CertInfo *ci = (CertInfo*)cv->context;
     if(!ci)
         return;
@@ -525,7 +521,7 @@ UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
         cv->verifyCertificate = certificateVerification_verify;
     else
         cv->verifyCertificate = verifyCertificateAllowAll;
-    cv->clear = certificateVerification_clear;
+    cv->deleteMembers = certificateVerification_deleteMembers;
     cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
 
     int err = 0;
@@ -553,7 +549,7 @@ UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
 
     return UA_STATUSCODE_GOOD;
 error:
-    certificateVerification_clear(cv);
+    certificateVerification_deleteMembers(cv);
     return UA_STATUSCODE_BADINTERNALERROR;
 }
 
@@ -582,7 +578,7 @@ UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
 
     cv->context = (void*)ci;
     cv->verifyCertificate = certificateVerification_verify;
-    cv->clear = certificateVerification_clear;
+    cv->deleteMembers = certificateVerification_deleteMembers;
     cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
 
     return UA_STATUSCODE_GOOD;

+ 10 - 19
src/client/ua_client.c

@@ -31,6 +31,7 @@
 
 static void
 UA_Client_init(UA_Client* client) {
+    memset(client, 0, sizeof(UA_Client));
     UA_SecureChannel_init(&client->channel);
     if(client->config.stateCallback)
         client->config.stateCallback(client, client->state);
@@ -41,15 +42,11 @@ UA_Client_init(UA_Client* client) {
     UA_WorkQueue_init(&client->workQueue);
 }
 
-UA_Client UA_EXPORT *
-UA_Client_newWithConfig(const UA_ClientConfig *config) {
-    if(!config)
-        return NULL;
+UA_Client *
+UA_Client_new() {
     UA_Client *client = (UA_Client*)UA_malloc(sizeof(UA_Client));
     if(!client)
         return NULL;
-    memset(client, 0, sizeof(UA_Client));
-    client->config = *config;
     UA_Client_init(client);
     return client;
 }
@@ -64,23 +61,16 @@ UA_ClientConfig_deleteMembers(UA_ClientConfig *config) {
     UA_EndpointDescription_deleteMembers(&config->endpoint);
     UA_UserTokenPolicy_deleteMembers(&config->userTokenPolicy);
 
-    if(config->certificateVerification.clear)
-        config->certificateVerification.clear(&config->certificateVerification);
+    if(config->certificateVerification.deleteMembers)
+        config->certificateVerification.deleteMembers(&config->certificateVerification);
 
     /* Delete the SecurityPolicies */
     if(config->securityPolicies == 0)
         return;
     for(size_t i = 0; i < config->securityPoliciesSize; i++)
-        config->securityPolicies[i].clear(&config->securityPolicies[i]);
+        config->securityPolicies[i].deleteMembers(&config->securityPolicies[i]);
     UA_free(config->securityPolicies);
     config->securityPolicies = 0;
-
-    if (config->logger.context && config->logger.clear) {
-        config->logger.clear(config->logger.context);
-        config->logger.context = NULL;
-        config->logger.log = NULL;
-        config->logger.clear = NULL;
-    }
 }
 
 static void
@@ -91,7 +81,7 @@ UA_Client_deleteMembers(UA_Client *client) {
     //UA_SecureChannel_deleteMembersCleanup(&client->channel);
     if (client->connection.free)
         client->connection.free(&client->connection);
-    UA_Connection_clear(&client->connection);
+    UA_Connection_deleteMembers(&client->connection);
     UA_NodeId_deleteMembers(&client->authenticationToken);
     UA_String_deleteMembers(&client->endpointUrl);
 
@@ -108,6 +98,8 @@ UA_Client_deleteMembers(UA_Client *client) {
 
     /* Clean up the work queue */
     UA_WorkQueue_cleanup(&client->workQueue);
+
+    UA_ClientConfig_deleteMembers(&client->config);
 }
 
 void
@@ -119,7 +111,6 @@ UA_Client_reset(UA_Client* client) {
 void
 UA_Client_delete(UA_Client* client) {
     UA_Client_deleteMembers(client);
-    UA_ClientConfig_deleteMembers(&client->config);
     UA_free(client);
 }
 
@@ -312,7 +303,7 @@ processServiceResponse(void *application, UA_SecureChannel *channel,
         goto finish;
     }
 
-#ifdef UA_ENABLE_TYPEDESCRIPTION
+#ifdef UA_ENABLE_TYPENAMES
     UA_LOG_DEBUG(&rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
                  "Decode a message of type %s", rd->responseType->typeName);
 #else

+ 16 - 27
src/client/ua_client_highlevel.c

@@ -753,11 +753,6 @@ cleanup:
 
 /* Async Functions */
 
-typedef struct {
-    UA_AttributeId attributeId;
-    const UA_DataType *outDataType;
-} AsyncReadData;
-
 static
 void ValueAttributeRead(UA_Client *client, void *userdata,
                         UA_UInt32 requestId, void *response) {
@@ -765,25 +760,28 @@ void ValueAttributeRead(UA_Client *client, void *userdata,
         return;
 
     /* Find the callback for the response */
-    CustomCallback *cc = UA_Client_findCustomCallback(client, requestId);
+    CustomCallback *cc;
+    LIST_FOREACH(cc, &client->customCallbacks, pointers) {
+        if(cc->callbackId == requestId)
+            break;
+    }
     if(!cc)
         return;
 
     UA_ReadResponse *rr = (UA_ReadResponse *) response;
     UA_DataValue *res = rr->results;
     UA_Boolean done = false;
-    AsyncReadData *data = (AsyncReadData *)cc->clientData;
     if(rr->resultsSize == 1 && res != NULL && res->hasValue) {
-        if(data->attributeId == UA_ATTRIBUTEID_VALUE) {
+        if(cc->attributeId == UA_ATTRIBUTEID_VALUE) {
             /* Call directly with the variant */
-            cc->userCallback(client, cc->userData, requestId, &res->value);
+            cc->callback(client, userdata, requestId, &res->value);
             done = true;
         } else if(UA_Variant_isScalar(&res->value) &&
-                  res->value.type == data->outDataType) {
+                  res->value.type == cc->outDataType) {
             /* Unpack the value */
-            UA_STACKARRAY(UA_Byte, value, data->outDataType->memSize);
-            memcpy(&value, res->value.data, data->outDataType->memSize);
-            cc->userCallback(client, cc->userData, requestId, &value);
+            UA_STACKARRAY(UA_Byte, value, cc->outDataType->memSize);
+            memcpy(&value, res->value.data, cc->outDataType->memSize);
+            cc->callback(client, userdata, requestId, &value);
             done = true;
         }
     }
@@ -794,7 +792,6 @@ void ValueAttributeRead(UA_Client *client, void *userdata,
                     "Cannot process the response to the async read "
                     "request %u", requestId);
 
-    UA_free(cc->clientData);
     LIST_REMOVE(cc, pointers);
     UA_free(cc);
 }
@@ -814,25 +811,17 @@ UA_StatusCode __UA_Client_readAttribute_async(UA_Client *client,
     request.nodesToReadSize = 1;
 
     __UA_Client_AsyncService(client, &request, &UA_TYPES[UA_TYPES_READREQUEST],
-                             ValueAttributeRead, &UA_TYPES[UA_TYPES_READRESPONSE], NULL,
-                             reqId);
+                             ValueAttributeRead, &UA_TYPES[UA_TYPES_READRESPONSE],
+                             userdata, reqId);
 
     CustomCallback *cc = (CustomCallback*) UA_malloc(sizeof(CustomCallback));
     if (!cc)
         return UA_STATUSCODE_BADOUTOFMEMORY;
-    memset(cc, 0, sizeof(CustomCallback));
-    cc->userCallback = callback;
-    cc->userData = userdata;
+    cc->callback = callback;
     cc->callbackId = *reqId;
 
-    cc->clientData = UA_malloc(sizeof(AsyncReadData));
-    if(!cc->clientData) {
-        UA_free(cc);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-    AsyncReadData *rd = (AsyncReadData *)cc->clientData;
-    rd->attributeId = attributeId;
-    rd->outDataType = outDataType;
+    cc->attributeId = attributeId;
+    cc->outDataType = outDataType;
 
     LIST_INSERT_HEAD(&client->customCallbacks, cc, pointers);
 

+ 3 - 14
src/client/ua_client_internal.h

@@ -118,11 +118,10 @@ typedef struct CustomCallback {
     //to find the correct callback
     UA_UInt32 callbackId;
 
-    UA_ClientAsyncServiceCallback userCallback;
-    void *userData;
+    UA_ClientAsyncServiceCallback callback;
 
-    bool isAsync;
-    void *clientData;
+    UA_AttributeId attributeId;
+    const UA_DataType *outDataType;
 } CustomCallback;
 
 struct UA_Client {
@@ -170,16 +169,6 @@ struct UA_Client {
     UA_Boolean pendingConnectivityCheck;
 };
 
-static UA_INLINE CustomCallback *
-UA_Client_findCustomCallback(UA_Client *client, UA_UInt32 requestId) {
-    CustomCallback *cc;
-    LIST_FOREACH(cc, &client->customCallbacks, pointers) {
-        if(cc->callbackId == requestId)
-            break;
-    }
-    return cc;
-}
-
 void
 setClientState(UA_Client *client, UA_ClientState state);
 

+ 119 - 575
src/client/ua_client_subscriptions.c

@@ -22,57 +22,7 @@
 /* Subscriptions */
 /*****************/
 
-static UA_StatusCode
-__Subscriptions_create_prepare(
-    CustomCallback *cc, const UA_CreateSubscriptionRequest *request,
-    void *subscriptionContext,
-    UA_Client_StatusChangeNotificationCallback statusChangeCallback,
-    UA_Client_DeleteSubscriptionCallback deleteCallback) {
-    UA_Client_Subscription *sub =
-        (UA_Client_Subscription *)(cc->clientData =
-                                       UA_malloc(sizeof(UA_Client_Subscription)));
-    if(!sub)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    sub->context = subscriptionContext;
-    sub->statusChangeCallback = statusChangeCallback;
-    sub->deleteCallback = deleteCallback;
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-__Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestId,
-                               void *r) {
-    UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
-    CustomCallback *cc = (CustomCallback *)data;
-    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
-        goto cleanup;
-    }
-
-    UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData;
-    cc->clientData = NULL;
-
-    /* Prepare the internal representation */
-    newSub->subscriptionId = response->subscriptionId;
-    newSub->sequenceNumber = 0;
-    newSub->lastActivity = UA_DateTime_nowMonotonic();
-    newSub->publishingInterval = response->revisedPublishingInterval;
-    newSub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
-
-    LIST_INIT(&newSub->monitoredItems);
-    LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
-
-cleanup:
-    if(cc->clientData)
-        UA_free(cc->clientData);
-
-    if(cc->isAsync) {
-        if(cc->userCallback)
-            cc->userCallback(client, cc->userData, requestId, response);
-        UA_free(cc);
-    }
-}
-
-UA_CreateSubscriptionResponse
+UA_CreateSubscriptionResponse UA_EXPORT
 UA_Client_Subscriptions_create(UA_Client *client,
                                const UA_CreateSubscriptionRequest request,
                                void *subscriptionContext,
@@ -80,17 +30,12 @@ UA_Client_Subscriptions_create(UA_Client *client,
                                UA_Client_DeleteSubscriptionCallback deleteCallback) {
     UA_CreateSubscriptionResponse response;
     UA_CreateSubscriptionResponse_init(&response);
-
-    CustomCallback cc;
-    memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
-    cc.isAsync = false;
-#endif
-
-    UA_StatusCode retval = __Subscriptions_create_prepare(
-        &cc, &request, subscriptionContext, statusChangeCallback, deleteCallback);
-    if(retval != UA_STATUSCODE_GOOD) {
-        response.responseHeader.serviceResult = retval;
+    
+    /* Allocate the internal representation */
+    UA_Client_Subscription *newSub = (UA_Client_Subscription*)
+        UA_malloc(sizeof(UA_Client_Subscription));
+    if(!newSub) {
+        response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return response;
     }
 
@@ -98,44 +43,24 @@ UA_Client_Subscriptions_create(UA_Client *client,
     __UA_Client_Service(client,
                         &request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
                         &response, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
-
-    __Subscriptions_create_handler(client, &cc, 0, &response);
-
-    return response;
-}
-
-UA_StatusCode
-UA_Client_Subscriptions_create_async(
-    UA_Client *client, const UA_CreateSubscriptionRequest request,
-    void *subscriptionContext,
-    UA_Client_StatusChangeNotificationCallback statusChangeCallback,
-    UA_Client_DeleteSubscriptionCallback deleteCallback,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
-    if(!cc) {
-        return UA_STATUSCODE_BADOUTOFMEMORY;
+    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
+        UA_free(newSub);
+        return response;
     }
-    cc->isAsync = true;
-    cc->userCallback = createCallback;
-    cc->userData = userdata;
 
-    retval = __Subscriptions_create_prepare(cc, &request, subscriptionContext,
-                                            statusChangeCallback, deleteCallback);
-    if(retval != UA_STATUSCODE_GOOD) {
-        goto cleanup;
-    }
+    /* Prepare the internal representation */
+    newSub->context = subscriptionContext;
+    newSub->subscriptionId = response.subscriptionId;
+    newSub->sequenceNumber = 0;
+    newSub->lastActivity = UA_DateTime_nowMonotonic();
+    newSub->statusChangeCallback = statusChangeCallback;
+    newSub->deleteCallback = deleteCallback;
+    newSub->publishingInterval = response.revisedPublishingInterval;
+    newSub->maxKeepAliveCount = response.revisedMaxKeepAliveCount;
+    LIST_INIT(&newSub->monitoredItems);
+    LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
 
-    /* Send the request as asynchronous service call */
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
-        __Subscriptions_create_handler, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE],
-        cc, requestId);
-cleanup:
-    if(cc->clientData)
-        UA_free(cc->clientData);
-    UA_free(cc);
-    return retval;
+    return response;
 }
 
 static UA_Client_Subscription *
@@ -148,24 +73,7 @@ findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) {
     return sub;
 }
 
-static void
-__Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId,
-                               void *r) {
-    UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r;
-    CustomCallback *cc = (CustomCallback *)data;
-    UA_Client_Subscription *sub = (UA_Client_Subscription *)cc->clientData;
-
-    sub->publishingInterval = response->revisedPublishingInterval;
-    sub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
-
-    if(cc->isAsync) {
-        if(cc->userCallback)
-            cc->userCallback(client, cc->userData, requestId, response);
-        UA_free(cc);
-    }
-}
-
-UA_ModifySubscriptionResponse
+UA_ModifySubscriptionResponse UA_EXPORT
 UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionRequest request) {
     UA_ModifySubscriptionResponse response;
     UA_ModifySubscriptionResponse_init(&response);
@@ -188,31 +96,6 @@ UA_Client_Subscriptions_modify(UA_Client *client, const UA_ModifySubscriptionReq
     return response;
 }
 
-UA_StatusCode
-UA_Client_Subscriptions_modify_async(UA_Client *client,
-                                     const UA_ModifySubscriptionRequest request,
-                                     UA_ClientAsyncServiceCallback callback,
-                                     void *userdata, UA_UInt32 *requestId) {
-    /* Find the internal representation */
-    UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
-    if(!sub)
-        return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
-
-    CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
-    if(!cc)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    cc->isAsync = true;
-    cc->clientData = sub;
-    cc->userData = userdata;
-    cc->userCallback = callback;
-
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
-        __Subscriptions_modify_handler, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
-        cc, requestId);
-}
-
 static void
 UA_Client_Subscription_deleteInternal(UA_Client *client, UA_Client_Subscription *sub) {
     /* Remove the MonitoredItems */
@@ -229,53 +112,35 @@ UA_Client_Subscription_deleteInternal(UA_Client *client, UA_Client_Subscription
     UA_free(sub);
 }
 
-typedef struct {
-    UA_DeleteSubscriptionsRequest *request;
-    UA_Client_Subscription **subs;
-} Subscriptions_DeleteData;
+UA_DeleteSubscriptionsResponse UA_EXPORT
+UA_Client_Subscriptions_delete(UA_Client *client, const UA_DeleteSubscriptionsRequest request) {
+    UA_STACKARRAY(UA_Client_Subscription*, subs, request.subscriptionIdsSize);
+    memset(subs, 0, sizeof(void*) * request.subscriptionIdsSize);
 
-static void
-__Subscriptions_DeleteData_free(Subscriptions_DeleteData *data) {
-    if(!data)
-        return;
-    if(data->subs)
-        UA_free(data->subs);
-    if(data->request)
-        UA_delete(data->request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]);
-    UA_free(data);
-}
-
-static UA_INLINE void
-__Subscriptions_delete_prepare(UA_Client *client, Subscriptions_DeleteData *data) {
     /* temporary remove the subscriptions from the list */
-    for(size_t i = 0; i < data->request->subscriptionIdsSize; i++) {
-        data->subs[i] = findSubscription(client, data->request->subscriptionIds[i]);
-        if(data->subs[i])
-            LIST_REMOVE(data->subs[i], listEntry);
+    for(size_t i = 0; i < request.subscriptionIdsSize; i++) {
+        subs[i] = findSubscription(client, request.subscriptionIds[i]);
+        if (subs[i])
+            LIST_REMOVE(subs[i], listEntry);
     }
-}
-
-static void
-__Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestId,
-                               void *r) {
-    UA_DeleteSubscriptionsResponse *response = (UA_DeleteSubscriptionsResponse *)r;
-    CustomCallback *cc = (CustomCallback *)data;
-    Subscriptions_DeleteData *delData = (Subscriptions_DeleteData *)cc->clientData;
-    UA_DeleteSubscriptionsRequest *request = delData->request;
-    UA_Client_Subscription **subs = delData->subs;
 
-    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+    /* Send the request */
+    UA_DeleteSubscriptionsResponse response;
+    __UA_Client_Service(client,
+                        &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
+                        &response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
+    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
         goto cleanup;
 
-    if(request->subscriptionIdsSize != response->resultsSize) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+    if(request.subscriptionIdsSize != response.resultsSize) {
+        response.responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
         goto cleanup;
     }
 
     /* Loop over the removed subscriptions and remove internally */
-    for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
-        if(response->results[i] != UA_STATUSCODE_GOOD &&
-           response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID) {
+    for(size_t i = 0; i < request.subscriptionIdsSize; i++) {
+        if(response.results[i] != UA_STATUSCODE_GOOD &&
+           response.results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID) {
             /* Something was wrong, reinsert the subscription in the list */
             if (subs[i])
                 LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
@@ -285,100 +150,26 @@ __Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestI
         if(!subs[i]) {
             UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
                         "No internal representation of subscription %u",
-                        delData->request->subscriptionIds[i]);
+                        request.subscriptionIds[i]);
             continue;
         }
-
+        
         LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
         UA_Client_Subscription_deleteInternal(client, subs[i]);
     }
 
+    return response;
+
 cleanup:
-    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
-        for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
-            if(subs[i]) {
-                LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
-            }
+    for(size_t i = 0; i < request.subscriptionIdsSize; i++) {
+        if (subs[i]) {
+            LIST_INSERT_HEAD(&client->subscriptions, subs[i], listEntry);
         }
     }
-
-    if(cc->isAsync) {
-        if(cc->userCallback)
-            cc->userCallback(client, cc->userData, requestId, response);
-        __Subscriptions_DeleteData_free(delData);
-        UA_free(cc);
-    }
-}
-
-UA_StatusCode
-UA_Client_Subscriptions_delete_async(UA_Client *client,
-                                     const UA_DeleteSubscriptionsRequest request,
-                                     UA_ClientAsyncServiceCallback callback,
-                                     void *userdata, UA_UInt32 *requestId) {
-    CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
-    if(!cc)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    Subscriptions_DeleteData *data =
-        (Subscriptions_DeleteData *)UA_calloc(1, sizeof(Subscriptions_DeleteData));
-    if(cc->clientData)
-        goto cleanup;
-    cc->clientData = data;
-    data->subs = (UA_Client_Subscription **)UA_calloc(request.subscriptionIdsSize,
-                                                      sizeof(UA_Client_Subscription *));
-    if(!data->subs)
-        goto cleanup;
-
-    data->request = UA_DeleteSubscriptionsRequest_new();
-    if(!data->request)
-        goto cleanup;
-    UA_DeleteSubscriptionsRequest_copy(&request, data->request);
-
-    __Subscriptions_delete_prepare(client, data);
-    cc->isAsync = true;
-    cc->userCallback = callback;
-    cc->userData = userdata;
-
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
-        __Subscriptions_delete_handler, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE],
-        cc, requestId);
-cleanup:
-    __Subscriptions_DeleteData_free(data);
-    UA_free(cc);
-    return UA_STATUSCODE_BADOUTOFMEMORY;
-}
-
-UA_DeleteSubscriptionsResponse
-UA_Client_Subscriptions_delete(UA_Client *client,
-                               const UA_DeleteSubscriptionsRequest request) {
-    UA_STACKARRAY(UA_Client_Subscription *, subs, request.subscriptionIdsSize);
-    memset(subs, 0, sizeof(void *) * request.subscriptionIdsSize);
-
-    CustomCallback cc;
-    memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
-    cc.isAsync = false;
-#endif
-
-    Subscriptions_DeleteData data;
-    cc.clientData = &data;
-    data.request = (UA_DeleteSubscriptionsRequest *)(uintptr_t)&request;
-    data.subs = subs;
-
-    __Subscriptions_delete_prepare(client, &data);
-
-    /* Send the request */
-    UA_DeleteSubscriptionsResponse response;
-
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
-
-    __Subscriptions_delete_handler(client, &cc, 0, &response);
     return response;
 }
 
-UA_StatusCode
+UA_StatusCode UA_EXPORT
 UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId) {
     UA_DeleteSubscriptionsRequest request;
     UA_DeleteSubscriptionsRequest_init(&request);
@@ -419,94 +210,66 @@ UA_Client_MonitoredItem_remove(UA_Client *client, UA_Client_Subscription *sub,
     UA_free(mon);
 }
 
-typedef struct {
-    UA_Client_Subscription *sub;
-
-    UA_Client_MonitoredItem **mis;
-    void **contexts;
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks;
-    void **handlingCallbacks;
-
-    UA_CreateMonitoredItemsRequest *request;
-} MonitoredItems_CreateData;
-
 static void
-MonitoredItems_CreateData_deleteItems(MonitoredItems_CreateData *data,
-                                      UA_Client *client) {
-    if(!data)
-        return;
+__UA_Client_MonitoredItems_create(UA_Client *client,
+                                  const UA_CreateMonitoredItemsRequest *request,
+                                  void **contexts, void **handlingCallbacks,
+                                  UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
+                                  UA_CreateMonitoredItemsResponse *response) {
+    UA_CreateMonitoredItemsResponse_init(response);
 
-#ifdef __clang_analyzer__
-    /* The clang analyzer requires the information that the loop below is executed
-       which is already checked in the __UA_Client_MonitoredItems_create */
-    assert(data->request->itemsToCreateSize);
-#endif
+    if (!request->itemsToCreateSize) {
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
+        return;
+    }
 
-    bool hasCallbacks = data->deleteCallbacks != NULL && data->contexts != NULL;
-    if(data->request && data->mis) {
-        for(size_t i = 0; i < data->request->itemsToCreateSize; i++) {
-            if(data->mis[i]) {
-                if(hasCallbacks && data->deleteCallbacks[i]) {
-                    if(data->sub)
-                        data->deleteCallbacks[i](client, data->sub->subscriptionId,
-                                                 data->sub->context, 0,
-                                                 data->contexts[i]);
-                    else
-                        data->deleteCallbacks[i](client, 0, NULL, 0, data->contexts[i]);
-                }
-                UA_free(data->mis[i]);
-            }
+    /* Fix clang warning */
+    size_t itemsToCreateSize = request->itemsToCreateSize;
+    UA_Client_Subscription *sub = NULL;
+    
+    /* Allocate the memory for internal representations */
+    UA_STACKARRAY(UA_Client_MonitoredItem*, mis, itemsToCreateSize);
+    memset(mis, 0, sizeof(void*) * itemsToCreateSize);
+    for(size_t i = 0; i < itemsToCreateSize; i++) {
+        mis[i] = (UA_Client_MonitoredItem*)UA_malloc(sizeof(UA_Client_MonitoredItem));
+        if(!mis[i]) {
+            response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+            goto cleanup;
         }
     }
-}
 
-static void
-MonitoredItems_CreateData_free(MonitoredItems_CreateData *data) {
-    if(!data)
-        return;
-    /* contains contexts, deleteCallbacs, handlingCallbacks as well */
-    if(data->mis)
-        UA_free(data->mis);
-    if(data->request)
-        UA_CreateMonitoredItemsRequest_delete(data->request);
-    UA_free(data);
-}
+    /* Get the subscription */
+    sub = findSubscription(client, request->subscriptionId);
+    if(!sub) {
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
+        goto cleanup;
+    }
 
-static void
-__MonitoredItems_create_handler(UA_Client *client, void *d, UA_UInt32 requestId,
-                                void *r) {
-    UA_CreateMonitoredItemsResponse *response = (UA_CreateMonitoredItemsResponse *)r;
-    CustomCallback *cc = (CustomCallback *)d;
-    MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)cc->clientData;
-
-    // introduce local pointers to the variables/parameters in the CreateData
-    // to keep the code completely intact
-    UA_CreateMonitoredItemsRequest *request = data->request;
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks = data->deleteCallbacks;
-    UA_Client_Subscription *sub = data->sub;
-    void **contexts = data->contexts;
-    UA_Client_MonitoredItem **mis = data->mis;
-    void **handlingCallbacks = data->handlingCallbacks;
+    /* Set the clientHandle */
+    for(size_t i = 0; i < itemsToCreateSize; i++)
+        request->itemsToCreate[i].requestedParameters.clientHandle = ++(client->monitoredItemHandles);
 
+    /* Call the service */
+    __UA_Client_Service(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
+                        response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
         goto cleanup;
 
-    if(response->resultsSize != request->itemsToCreateSize) {
+    if(response->resultsSize != itemsToCreateSize) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
         goto cleanup;
     }
 
     /* Add internally */
-    for(size_t i = 0; i < request->itemsToCreateSize; i++) {
+    for(size_t i = 0; i < itemsToCreateSize; i++) {
         if(response->results[i].statusCode != UA_STATUSCODE_GOOD) {
-            if(deleteCallbacks[i])
+            if (deleteCallbacks[i])
                 deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0, contexts[i]);
             UA_free(mis[i]);
             mis[i] = NULL;
             continue;
         }
-
-        UA_assert(mis[i] != NULL);
+            
         UA_Client_MonitoredItem *newMon = mis[i];
         newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
         newMon->monitoredItemId = response->results[i].monitoredItemId;
@@ -521,167 +284,24 @@ __MonitoredItems_create_handler(UA_Client *client, void *d, UA_UInt32 requestId,
         UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_CLIENT,
                     "Subscription %u | Added a MonitoredItem with handle %u",
                      sub->subscriptionId, newMon->clientHandle);
-        mis[i] = NULL;
-    }
-
-cleanup:
-    MonitoredItems_CreateData_deleteItems(data, client);
-    if(cc->isAsync) {
-        if(cc->userCallback)
-            cc->userCallback(client, cc->userData, requestId, response);
-        MonitoredItems_CreateData_free(data);
-        UA_free(cc);
-    }
-}
-
-static UA_StatusCode
-MonitoredItems_CreateData_prepare(MonitoredItems_CreateData *data, UA_Client *client) {
-    /* Allocate the memory for internal representations */
-    for(size_t i = 0; i < data->request->itemsToCreateSize; i++) {
-        data->mis[i] =
-            (UA_Client_MonitoredItem *)UA_malloc(sizeof(UA_Client_MonitoredItem));
-        if(!data->mis[i]) {
-            return UA_STATUSCODE_BADOUTOFMEMORY;
-        }
-    }
-
-    /* Set the clientHandle */
-    for(size_t i = 0; i < data->request->itemsToCreateSize; i++)
-        data->request->itemsToCreate[i].requestedParameters.clientHandle =
-            ++(client->monitoredItemHandles);
-
-    return UA_STATUSCODE_GOOD;
-}
-
-static void
-__UA_Client_MonitoredItems_create(UA_Client *client,
-                                  const UA_CreateMonitoredItemsRequest *request,
-                                  void **contexts, void **handlingCallbacks,
-                                  UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-                                  UA_CreateMonitoredItemsResponse *response) {
-    UA_CreateMonitoredItemsResponse_init(response);
-
-    if(!request->itemsToCreateSize) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
-        return;
     }
-    CustomCallback cc;
-    memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
-    cc.isAsync = false;
-#endif
 
-    /* Fix clang warning */
-    size_t itemsToCreateSize = request->itemsToCreateSize;
-    UA_STACKARRAY(UA_Client_MonitoredItem *, mis, itemsToCreateSize);
-    memset(mis, 0, sizeof(void *) * itemsToCreateSize);
-
-    MonitoredItems_CreateData data;
-    memset(&data, 0, sizeof(MonitoredItems_CreateData));
-    data.request = (UA_CreateMonitoredItemsRequest *)(uintptr_t)request;
-    data.contexts = contexts;
-    data.handlingCallbacks = handlingCallbacks;
-    data.deleteCallbacks = deleteCallbacks;
-    data.mis = mis;
-
-    cc.clientData = &data;
-
-    /* Get the subscription */
-    data.sub = findSubscription(client, request->subscriptionId);
-    if(!data.sub) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
-        goto cleanup;
-    }
-
-    UA_StatusCode retval = MonitoredItems_CreateData_prepare(&data, client);
-    if(retval != UA_STATUSCODE_GOOD) {
-        response->responseHeader.serviceResult = retval;
-        goto cleanup;
-    }
-
-    /* Call the service */
-    __UA_Client_Service(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
-                        response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
-
-    __MonitoredItems_create_handler(client, &cc, 0, response);
     return;
-cleanup:
-    MonitoredItems_CreateData_deleteItems(&data, client);
-}
-
-static UA_StatusCode
-__UA_Client_MonitoredItems_createDataChanges_async(
-    UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
-    void **callbacks, UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
-    UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
-    if(!cc)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    cc->userCallback = createCallback;
-    cc->userData = userdata;
-    MonitoredItems_CreateData *data =
-        (MonitoredItems_CreateData *)UA_calloc(1, sizeof(MonitoredItems_CreateData));
-    if(!data) {
-        retval = UA_STATUSCODE_BADOUTOFMEMORY;
-        goto cleanup;
-    }
-    cc->isAsync = true;
-    cc->clientData = data;
-
-    data->sub = findSubscription(client, request.subscriptionId);
-    if(!data->sub) {
-        retval = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
-        goto cleanup;
-    }
 
-    /* create a big array that holds the monitored items and parameters */
-    void **array = (void **)UA_calloc(4 * request.itemsToCreateSize, sizeof(void *));
-    if(!array) {
-        retval = UA_STATUSCODE_BADOUTOFMEMORY;
-        goto cleanup;
-    }
-    data->mis = (UA_Client_MonitoredItem **)array;
-    data->contexts =
-        (void **)((uintptr_t)array + (sizeof(void *) * request.itemsToCreateSize));
-    memcpy(data->contexts, contexts, request.itemsToCreateSize * sizeof(void *));
-    data->deleteCallbacks =
-        (UA_Client_DeleteMonitoredItemCallback *)((uintptr_t)array +
-                                                  (2 * request.itemsToCreateSize *
-                                                   sizeof(void *)));
-    memcpy(data->deleteCallbacks, deleteCallbacks,
-           request.itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback));
-    data->handlingCallbacks =
-        (void **)((uintptr_t)array + (3 * request.itemsToCreateSize * sizeof(void *)));
-    memcpy(data->handlingCallbacks, callbacks,
-           request.itemsToCreateSize * sizeof(void *));
-
-    data->request = UA_CreateMonitoredItemsRequest_new();
-    if(!data->request) {
-        retval = UA_STATUSCODE_BADOUTOFMEMORY;
-        goto cleanup;
+ cleanup:
+    for(size_t i = 0; i < itemsToCreateSize; i++) {
+        if (deleteCallbacks[i]) {
+            if (sub)
+                deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0, contexts[i]);
+            else
+                deleteCallbacks[i](client, 0, NULL, 0, contexts[i]);
+        }
+        if(mis[i])
+            UA_free(mis[i]);
     }
-    retval = UA_CreateMonitoredItemsRequest_copy(&request, data->request);
-    if(retval != UA_STATUSCODE_GOOD)
-        goto cleanup;
-
-    retval = MonitoredItems_CreateData_prepare(data, client);
-    if(retval != UA_STATUSCODE_GOOD)
-        goto cleanup;
-
-    return __UA_Client_AsyncService(
-        client, data->request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
-        __MonitoredItems_create_handler, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE],
-        cc, requestId);
-cleanup:
-    MonitoredItems_CreateData_deleteItems(data, client);
-    MonitoredItems_CreateData_free(data);
-    UA_free(cc);
-    return retval;
 }
 
-UA_CreateMonitoredItemsResponse
+UA_CreateMonitoredItemsResponse UA_EXPORT
 UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
             const UA_CreateMonitoredItemsRequest request, void **contexts,
             UA_Client_DataChangeNotificationCallback *callbacks,
@@ -692,18 +312,7 @@ UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
     return response;
 }
 
-UA_StatusCode
-UA_Client_MonitoredItems_createDataChanges_async(
-    UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
-    UA_Client_DataChangeNotificationCallback *callbacks,
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
-    return __UA_Client_MonitoredItems_createDataChanges_async(
-        client, request, contexts, (void **)(uintptr_t)callbacks, deleteCallbacks,
-        createCallback, userdata, requestId);
-}
-
-UA_MonitoredItemCreateResult
+UA_MonitoredItemCreateResult UA_EXPORT
 UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
           UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
           void *context, UA_Client_DataChangeNotificationCallback callback,
@@ -732,7 +341,7 @@ UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscript
     return result;
 }
 
-UA_CreateMonitoredItemsResponse
+UA_CreateMonitoredItemsResponse UA_EXPORT
 UA_Client_MonitoredItems_createEvents(UA_Client *client,
             const UA_CreateMonitoredItemsRequest request, void **contexts,
             UA_Client_EventNotificationCallback *callback,
@@ -743,19 +352,7 @@ UA_Client_MonitoredItems_createEvents(UA_Client *client,
     return response;
 }
 
-/* Monitor the EventNotifier attribute only */
-UA_StatusCode
-UA_Client_MonitoredItems_createEvents_async(
-    UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
-    UA_Client_EventNotificationCallback *callbacks,
-    UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
-    UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
-    return __UA_Client_MonitoredItems_createDataChanges_async(
-        client, request, contexts, (void **)(uintptr_t)callbacks, deleteCallbacks,
-        createCallback, userdata, requestId);
-}
-
-UA_MonitoredItemCreateResult
+UA_MonitoredItemCreateResult UA_EXPORT
 UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId,
           UA_TimestampsToReturn timestampsToReturn, const UA_MonitoredItemCreateRequest item,
           void *context, UA_Client_EventNotificationCallback callback,
@@ -782,28 +379,27 @@ UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId
     return result;
 }
 
-static void
-__MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
-                                void *r) {
-    UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r;
-    CustomCallback *cc = (CustomCallback *)d;
-    UA_DeleteMonitoredItemsRequest *request =
-        (UA_DeleteMonitoredItemsRequest *)cc->clientData;
-    if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
-        goto cleanup;
+UA_DeleteMonitoredItemsResponse UA_EXPORT
+UA_Client_MonitoredItems_delete(UA_Client *client, const UA_DeleteMonitoredItemsRequest request) {
+    /* Send the request */
+    UA_DeleteMonitoredItemsResponse response;
+    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
+                        &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
+    if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
+        return response;
 
-    UA_Client_Subscription *sub = findSubscription(client, request->subscriptionId);
+    UA_Client_Subscription *sub = findSubscription(client, request.subscriptionId);
     if(!sub) {
         UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_CLIENT,
                     "No internal representation of subscription %u",
-                    request->subscriptionId);
-        goto cleanup;
+                    request.subscriptionId);
+        return response;
     }
 
     /* Loop over deleted MonitoredItems */
-    for(size_t i = 0; i < response->resultsSize; i++) {
-        if(response->results[i] != UA_STATUSCODE_GOOD &&
-           response->results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) {
+    for(size_t i = 0; i < response.resultsSize; i++) {
+        if(response.results[i] != UA_STATUSCODE_GOOD &&
+           response.results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) {
             continue;
         }
 
@@ -812,71 +408,19 @@ __MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
         UA_Client_MonitoredItem *mon;
         LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
             // NOLINTNEXTLINE
-            if(mon->monitoredItemId == request->monitoredItemIds[i]) {
+            if (mon->monitoredItemId == request.monitoredItemIds[i]) {
                 UA_Client_MonitoredItem_remove(client, sub, mon);
                 break;
             }
         }
 #endif
     }
-cleanup:
-    if(cc->isAsync) {
-        if(cc->userCallback)
-            cc->userCallback(client, cc->userData, requestId, response);
-        UA_DeleteMonitoredItemsRequest_delete(request);
-        UA_free(cc);
-    }
-}
-
-UA_DeleteMonitoredItemsResponse
-UA_Client_MonitoredItems_delete(UA_Client *client,
-                                const UA_DeleteMonitoredItemsRequest request) {
-    /* Send the request */
-    UA_DeleteMonitoredItemsResponse response;
-    CustomCallback cc;
-    memset(&cc, 0, sizeof(CustomCallback));
-#ifdef __clang_analyzer__
-    cc.isAsync = false;
-#endif
-    cc.clientData = (void *)(uintptr_t)&request;
-
-    __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
-                        &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
 
-    __MonitoredItems_delete_handler(client, &cc, 0, &response);
     return response;
 }
 
-UA_StatusCode
-UA_Client_MonitoredItems_delete_async(UA_Client *client,
-                                      const UA_DeleteMonitoredItemsRequest request,
-                                      UA_ClientAsyncServiceCallback callback,
-                                      void *userdata, UA_UInt32 *requestId) {
-    /* Send the request */
-    CustomCallback *cc = (CustomCallback *)UA_calloc(1, sizeof(CustomCallback));
-    if(!cc)
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    UA_DeleteMonitoredItemsRequest *req_copy = UA_DeleteMonitoredItemsRequest_new();
-    if(!req_copy) {
-        UA_free(cc);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-    UA_DeleteMonitoredItemsRequest_copy(&request, req_copy);
-    cc->isAsync = true;
-    cc->clientData = req_copy;
-    cc->userCallback = callback;
-    cc->userData = userdata;
-
-    return __UA_Client_AsyncService(
-        client, &request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
-        __MonitoredItems_delete_handler, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE],
-        cc, requestId);
-}
-
-UA_StatusCode
-UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId,
-                                      UA_UInt32 monitoredItemId) {
+UA_StatusCode UA_EXPORT
+UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId, UA_UInt32 monitoredItemId) {
     UA_DeleteMonitoredItemsRequest request;
     UA_DeleteMonitoredItemsRequest_init(&request);
     request.subscriptionId = subscriptionId;

+ 1 - 1
src/client/ua_client_worker.c

@@ -138,7 +138,7 @@ UA_StatusCode UA_Client_run_iterate(UA_Client *client, UA_UInt16 timeout) {
 #endif
         asyncServiceTimeoutCheck(client);
 
-#if UA_MULTITHREADING < 200
+#ifndef UA_ENABLE_MULTITHREADING
         /* Process delayed callbacks when all callbacks and network events are
          * done */
         UA_WorkQueue_manuallyProcessDelayed(&client->workQueue);

File diff suppressed because it is too large
+ 911 - 809
src/pubsub/ua_pubsub_writer.c


+ 8 - 24
src/pubsub/ua_pubsub.h

@@ -33,15 +33,13 @@ typedef struct UA_ReaderGroup UA_ReaderGroup;
 /**********************************************/
 /*            PublishedDataSet                */
 /**********************************************/
-typedef struct UA_PublishedDataSet{
+typedef struct{
     UA_PublishedDataSetConfig config;
     UA_DataSetMetaDataType dataSetMetaData;
-    TAILQ_HEAD(UA_ListOfDataSetField, UA_DataSetField) fields;
+    LIST_HEAD(UA_ListOfDataSetField, UA_DataSetField) fields;
     UA_NodeId identifier;
     UA_UInt16 fieldSize;
     UA_UInt16 promotedFieldsCount;
-    UA_UInt16 configurationFreezeCounter;
-    TAILQ_ENTRY(UA_PublishedDataSet) listEntry;
 } UA_PublishedDataSet;
 
 UA_StatusCode
@@ -49,13 +47,13 @@ UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src, UA_Publishe
 UA_PublishedDataSet *
 UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier);
 void
-UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet);
+UA_PublishedDataSet_deleteMembers(UA_Server *server, UA_PublishedDataSet *publishedDataSet);
 
 /**********************************************/
 /*               Connection                   */
 /**********************************************/
 //the connection config (public part of connection) object is defined in include/ua_plugin_pubsub.h
-typedef struct UA_PubSubConnection{
+typedef struct{
     UA_PubSubConnectionConfig *config;
     //internal fields
     UA_PubSubChannel *channel;
@@ -63,8 +61,6 @@ typedef struct UA_PubSubConnection{
     LIST_HEAD(UA_ListOfWriterGroup, UA_WriterGroup) writerGroups;
     LIST_HEAD(UA_ListOfPubSubReaderGroup, UA_ReaderGroup) readerGroups;
     size_t readerGroupsSize;
-    TAILQ_ENTRY(UA_PubSubConnection) listEntry;
-    UA_UInt16 configurationFreezeCounter;
 } UA_PubSubConnection;
 
 UA_StatusCode
@@ -72,12 +68,9 @@ UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src, UA_PubSubCo
 UA_PubSubConnection *
 UA_PubSubConnection_findConnectionbyId(UA_Server *server, UA_NodeId connectionIdentifier);
 void
-UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig);
+UA_PubSubConnectionConfig_deleteMembers(UA_PubSubConnectionConfig *connectionConfig);
 void
-UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection);
-/* Register channel for given connectionIdentifier */
-UA_StatusCode
-UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier);
+UA_PubSubConnection_deleteMembers(UA_Server *server, UA_PubSubConnection *connection);
 
 /**********************************************/
 /*              DataSetWriter                 */
@@ -98,7 +91,6 @@ typedef struct UA_DataSetWriter{
     UA_NodeId linkedWriterGroup;
     UA_NodeId connectedDataSet;
     UA_ConfigurationVersionDataType connectedDataSetVersion;
-    UA_PubSubState state;
 #ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
     UA_UInt16 deltaFrameCounter;            //actual count of sent deltaFrames
     size_t lastSamplesCount;
@@ -111,8 +103,6 @@ UA_StatusCode
 UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src, UA_DataSetWriterConfig *dst);
 UA_DataSetWriter *
 UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier);
-UA_StatusCode
-UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state, UA_DataSetWriter *dataSetWriter);
 
 /**********************************************/
 /*               WriterGroup                  */
@@ -123,22 +113,17 @@ struct UA_WriterGroup{
     //internal fields
     LIST_ENTRY(UA_WriterGroup) listEntry;
     UA_NodeId identifier;
-    UA_PubSubConnection *linkedConnection;
+    UA_NodeId linkedConnection;
     LIST_HEAD(UA_ListOfDataSetWriter, UA_DataSetWriter) writers;
     UA_UInt32 writersCount;
     UA_UInt64 publishCallbackId;
     UA_Boolean publishCallbackIsRegistered;
-    UA_PubSubState state;
-    UA_NetworkMessageOffsetBuffer bufferedMessage;
-    UA_UInt16 sequenceNumber; /* Increased after every succressuly sent message */
 };
 
 UA_StatusCode
 UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src, UA_WriterGroupConfig *dst);
 UA_WriterGroup *
 UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier);
-UA_StatusCode
-UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state, UA_WriterGroup *writerGroup);
 
 /**********************************************/
 /*               DataSetField                 */
@@ -147,13 +132,12 @@ UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state, UA_Writer
 typedef struct UA_DataSetField{
     UA_DataSetFieldConfig config;
     //internal fields
-    TAILQ_ENTRY(UA_DataSetField) listEntry;
+    LIST_ENTRY(UA_DataSetField) listEntry;
     UA_NodeId identifier;
     UA_NodeId publishedDataSet;             //ref to parent pds
     UA_FieldMetaData fieldMetaData;
     UA_UInt64 sampleCallbackId;
     UA_Boolean sampleCallbackIsRegistered;
-
 } UA_DataSetField;
 
 UA_StatusCode

+ 117 - 114
src/pubsub/ua_pubsub_manager.c

@@ -2,7 +2,7 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
- * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
+ * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
  * Copyright (c) 2018 Fraunhofer IOSB (Author: Julius Pfrommer)
  */
 
@@ -50,45 +50,54 @@ UA_Server_addPubSubConnection(UA_Server *server,
 
     /* Create new connection and add to UA_PubSubManager */
     UA_PubSubConnection *newConnectionsField = (UA_PubSubConnection *)
-        UA_calloc(1, sizeof(UA_PubSubConnection));
+        UA_realloc(server->pubSubManager.connections,
+                   sizeof(UA_PubSubConnection) * (server->pubSubManager.connectionsSize + 1));
     if(!newConnectionsField) {
-        UA_PubSubConnectionConfig_clear(tmpConnectionConfig);
+        UA_PubSubConnectionConfig_deleteMembers(tmpConnectionConfig);
         UA_free(tmpConnectionConfig);
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
                      "PubSub Connection creation failed. Out of Memory.");
         return UA_STATUSCODE_BADOUTOFMEMORY;
     }
-    if (server->pubSubManager.connectionsSize != 0)
-        TAILQ_INSERT_TAIL(&server->pubSubManager.connections, newConnectionsField, listEntry);
-    else {
-        TAILQ_INIT(&server->pubSubManager.connections);
-        TAILQ_INSERT_HEAD(&server->pubSubManager.connections, newConnectionsField, listEntry);
-    }
-
+    server->pubSubManager.connections = newConnectionsField;
     server->pubSubManager.connectionsSize++;
 
-    LIST_INIT(&newConnectionsField->writerGroups);
-    newConnectionsField->config = tmpConnectionConfig;
+    UA_PubSubConnection *newConnection =
+        &server->pubSubManager.connections[server->pubSubManager.connectionsSize-1];
+
+    /* Initialize the new connection */
+    memset(newConnection, 0, sizeof(UA_PubSubConnection));
+    LIST_INIT(&newConnection->writerGroups);
+    //workaround - fixing issue with queue.h and realloc.
+    for(size_t n = 0; n < server->pubSubManager.connectionsSize; n++){
+        if(server->pubSubManager.connections[n].writerGroups.lh_first){
+            server->pubSubManager.connections[n].writerGroups.lh_first->listEntry.le_prev = &server->pubSubManager.connections[n].writerGroups.lh_first;
+        }
+    }
+    newConnection->config = tmpConnectionConfig;
 
     /* Open the channel */
-    newConnectionsField->channel = tl->createPubSubChannel(newConnectionsField->config);
-    if(!newConnectionsField->channel) {
-        UA_PubSubConnection_clear(server, newConnectionsField);
-        TAILQ_REMOVE(&server->pubSubManager.connections, newConnectionsField, listEntry);
+    newConnection->channel = tl->createPubSubChannel(newConnection->config);
+    if(!newConnection->channel) {
+        UA_PubSubConnection_deleteMembers(server, newConnection);
         server->pubSubManager.connectionsSize--;
-        UA_free(newConnectionsField);
+        /* Keep the realloced (longer) array if entries remain */
+        if(server->pubSubManager.connectionsSize == 0) {
+            UA_free(server->pubSubManager.connections);
+            server->pubSubManager.connections = NULL;
+        }
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
                      "PubSub Connection creation failed. Transport layer creation problem.");
         return UA_STATUSCODE_BADINTERNALERROR;
     }
 
-    UA_PubSubManager_generateUniqueNodeId(server, &newConnectionsField->identifier);
+    UA_PubSubManager_generateUniqueNodeId(server, &newConnection->identifier);
 
     if(connectionIdentifier)
-        UA_NodeId_copy(&newConnectionsField->identifier, connectionIdentifier);
+        UA_NodeId_copy(&newConnection->identifier, connectionIdentifier);
 
 #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
-    addPubSubConnectionRepresentation(server, newConnectionsField);
+    addPubSubConnectionRepresentation(server, newConnection);
 #endif
     return UA_STATUSCODE_GOOD;
 }
@@ -96,18 +105,46 @@ UA_Server_addPubSubConnection(UA_Server *server,
 UA_StatusCode
 UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection) {
     //search the identified Connection and store the Connection index
-    UA_PubSubConnection *currentConnection = UA_PubSubConnection_findConnectionbyId(server, connection);
+    size_t connectionIndex;
+    UA_PubSubConnection *currentConnection = NULL;
+    for(connectionIndex = 0; connectionIndex < server->pubSubManager.connectionsSize; connectionIndex++){
+        if(UA_NodeId_equal(&connection, &server->pubSubManager.connections[connectionIndex].identifier)){
+            currentConnection = &server->pubSubManager.connections[connectionIndex];
+            break;
+        }
+    }
     if(!currentConnection)
         return UA_STATUSCODE_BADNOTFOUND;
 
 #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
     removePubSubConnectionRepresentation(server, currentConnection);
 #endif
+    UA_PubSubConnection_deleteMembers(server, currentConnection);
     server->pubSubManager.connectionsSize--;
+    //remove the connection from the pubSubManager, move the last connection
+    //into the allocated memory of the deleted connection
+    if(server->pubSubManager.connectionsSize != connectionIndex){
+        memcpy(&server->pubSubManager.connections[connectionIndex],
+               &server->pubSubManager.connections[server->pubSubManager.connectionsSize],
+               sizeof(UA_PubSubConnection));
+    }
 
-    UA_PubSubConnection_clear(server, currentConnection);
-    TAILQ_REMOVE(&server->pubSubManager.connections, currentConnection, listEntry);
-    UA_free(currentConnection);
+    if(server->pubSubManager.connectionsSize <= 0){
+        UA_free(server->pubSubManager.connections);
+        server->pubSubManager.connections = NULL;
+    } else {
+        server->pubSubManager.connections = (UA_PubSubConnection *)
+                UA_realloc(server->pubSubManager.connections, sizeof(UA_PubSubConnection) * server->pubSubManager.connectionsSize);
+        if(!server->pubSubManager.connections){
+            return UA_STATUSCODE_BADINTERNALERROR;
+        }
+        //workaround - fixing issue with queue.h and realloc.
+        for(size_t n = 0; n < server->pubSubManager.connectionsSize; n++){
+            if(server->pubSubManager.connections[n].writerGroups.lh_first){
+                server->pubSubManager.connections[n].writerGroups.lh_first->listEntry.le_prev = &server->pubSubManager.connections[n].writerGroups.lh_first;
+            }
+        }
+    }
     return UA_STATUSCODE_GOOD;
 }
 
@@ -136,80 +173,42 @@ UA_Server_addPublishedDataSet(UA_Server *server, const UA_PublishedDataSetConfig
     }
     //create new PDS and add to UA_PubSubManager
     UA_PublishedDataSet *newPubSubDataSetField = (UA_PublishedDataSet *)
-            UA_calloc(1, sizeof(UA_PublishedDataSet));
+            UA_realloc(server->pubSubManager.publishedDataSets,
+                       sizeof(UA_PublishedDataSet) * (server->pubSubManager.publishedDataSetsSize + 1));
     if(!newPubSubDataSetField) {
-        UA_PublishedDataSetConfig_clear(&tmpPublishedDataSetConfig);
+        UA_PublishedDataSetConfig_deleteMembers(&tmpPublishedDataSetConfig);
         UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
                      "PublishedDataSet creation failed. Out of Memory.");
         result.addResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return result;
     }
-    memset(newPubSubDataSetField, 0, sizeof(UA_PublishedDataSet));
-    TAILQ_INIT(&newPubSubDataSetField->fields);
-    newPubSubDataSetField->config = tmpPublishedDataSetConfig;
-
-    if (server->pubSubManager.publishedDataSetsSize != 0)
-        TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets, newPubSubDataSetField, listEntry);
-    else {
-        TAILQ_INIT(&server->pubSubManager.publishedDataSets);
-        TAILQ_INSERT_HEAD(&server->pubSubManager.publishedDataSets, newPubSubDataSetField, listEntry);
+    server->pubSubManager.publishedDataSets = newPubSubDataSetField;
+    UA_PublishedDataSet *newPubSubDataSet = &server->pubSubManager.publishedDataSets[(server->pubSubManager.publishedDataSetsSize)];
+    memset(newPubSubDataSet, 0, sizeof(UA_PublishedDataSet));
+    LIST_INIT(&newPubSubDataSet->fields);
+    //workaround - fixing issue with queue.h and realloc.
+    for(size_t n = 0; n < server->pubSubManager.publishedDataSetsSize; n++){
+        if(server->pubSubManager.publishedDataSets[n].fields.lh_first){
+            server->pubSubManager.publishedDataSets[n].fields.lh_first->listEntry.le_prev = &server->pubSubManager.publishedDataSets[n].fields.lh_first;
+        }
     }
+    newPubSubDataSet->config = tmpPublishedDataSetConfig;
     if(tmpPublishedDataSetConfig.publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE){
         //parse template config and add fields (later PubSub batch)
     }
     //generate unique nodeId
-    UA_PubSubManager_generateUniqueNodeId(server, &newPubSubDataSetField->identifier);
+    UA_PubSubManager_generateUniqueNodeId(server, &newPubSubDataSet->identifier);
     if(pdsIdentifier != NULL){
-        UA_NodeId_copy(&newPubSubDataSetField->identifier, pdsIdentifier);
+        UA_NodeId_copy(&newPubSubDataSet->identifier, pdsIdentifier);
     }
-
+    server->pubSubManager.publishedDataSetsSize++;
     result.addResult = UA_STATUSCODE_GOOD;
     result.fieldAddResults = NULL;
     result.fieldAddResultsSize = 0;
-
-    //fill the DataSetMetaData
-    switch(tmpPublishedDataSetConfig.publishedDataSetType){
-        case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
-            if(UA_DataSetMetaDataType_copy(&tmpPublishedDataSetConfig.config.itemsTemplate.metaData,
-                    &newPubSubDataSetField->dataSetMetaData) != UA_STATUSCODE_GOOD){
-                UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
-                result.addResult = UA_STATUSCODE_BADINTERNALERROR;
-            }
-            break;
-        case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE:
-            if(UA_DataSetMetaDataType_copy(&tmpPublishedDataSetConfig.config.eventTemplate.metaData,
-                    &newPubSubDataSetField->dataSetMetaData) != UA_STATUSCODE_GOOD){
-                UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
-                result.addResult = UA_STATUSCODE_BADINTERNALERROR;
-            }
-            break;
-        case UA_PUBSUB_DATASET_PUBLISHEDEVENTS:
-            newPubSubDataSetField->dataSetMetaData.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
-            newPubSubDataSetField->dataSetMetaData.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
-            newPubSubDataSetField->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
-            if(UA_String_copy(&tmpPublishedDataSetConfig.name, &newPubSubDataSetField->dataSetMetaData.name) != UA_STATUSCODE_GOOD){
-                UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
-                result.addResult = UA_STATUSCODE_BADINTERNALERROR;
-            }
-            newPubSubDataSetField->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
-            break;
-        case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
-            newPubSubDataSetField->dataSetMetaData.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
-            newPubSubDataSetField->dataSetMetaData.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
-            if(UA_String_copy(&tmpPublishedDataSetConfig.name, &newPubSubDataSetField->dataSetMetaData.name) != UA_STATUSCODE_GOOD){
-                UA_Server_removeDataSetField(server, newPubSubDataSetField->identifier);
-                result.addResult = UA_STATUSCODE_BADINTERNALERROR;
-            }
-            newPubSubDataSetField->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
-            newPubSubDataSetField->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
-            break;
-    }
-
-    server->pubSubManager.publishedDataSetsSize++;
     result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
     result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
 #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
-    addPublishedDataItemsRepresentation(server, newPubSubDataSetField);
+    addPublishedDataItemsRepresentation(server, newPubSubDataSet);
 #endif
     return result;
 }
@@ -217,21 +216,21 @@ UA_Server_addPublishedDataSet(UA_Server *server, const UA_PublishedDataSetConfig
 UA_StatusCode
 UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
     //search the identified PublishedDataSet and store the PDS index
-    UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, pds);
+    UA_PublishedDataSet *publishedDataSet = NULL;
+    size_t publishedDataSetIndex;
+    for(publishedDataSetIndex = 0; publishedDataSetIndex < server->pubSubManager.publishedDataSetsSize; publishedDataSetIndex++){
+        if(UA_NodeId_equal(&server->pubSubManager.publishedDataSets[publishedDataSetIndex].identifier, &pds)){
+            publishedDataSet = &server->pubSubManager.publishedDataSets[publishedDataSetIndex];
+            break;
+        }
+    }
     if(!publishedDataSet){
         return UA_STATUSCODE_BADNOTFOUND;
     }
-    if(publishedDataSet->config.configurationFrozen){
-        UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
-                       "Remove PublishedDataSet failed. PublishedDataSet is frozen.");
-        return UA_STATUSCODE_BADCONFIGURATIONERROR;
-    }
-
     //search for referenced writers -> delete this writers. (Standard: writer must be connected with PDS)
-    UA_PubSubConnection *tmpConnectoin;
-    TAILQ_FOREACH(tmpConnectoin, &server->pubSubManager.connections, listEntry){
+    for(size_t i = 0; i < server->pubSubManager.connectionsSize; i++){
         UA_WriterGroup *writerGroup;
-        LIST_FOREACH(writerGroup, &tmpConnectoin->writerGroups, listEntry){
+        LIST_FOREACH(writerGroup, &server->pubSubManager.connections[i].writerGroups, listEntry){
             UA_DataSetWriter *currentWriter, *tmpWriterGroup;
             LIST_FOREACH_SAFE(currentWriter, &writerGroup->writers, listEntry, tmpWriterGroup){
                 if(UA_NodeId_equal(&currentWriter->connectedDataSet, &publishedDataSet->identifier)){
@@ -243,11 +242,30 @@ UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
 #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
     removePublishedDataSetRepresentation(server, publishedDataSet);
 #endif
-    UA_PublishedDataSet_clear(server, publishedDataSet);
+    UA_PublishedDataSet_deleteMembers(server, publishedDataSet);
     server->pubSubManager.publishedDataSetsSize--;
-
-    TAILQ_REMOVE(&server->pubSubManager.publishedDataSets, publishedDataSet, listEntry);
-    UA_free(publishedDataSet);
+    //copy the last PDS to the removed PDS inside the allocated memory block
+    if(server->pubSubManager.publishedDataSetsSize != publishedDataSetIndex){
+        memcpy(&server->pubSubManager.publishedDataSets[publishedDataSetIndex],
+               &server->pubSubManager.publishedDataSets[server->pubSubManager.publishedDataSetsSize],
+               sizeof(UA_PublishedDataSet));
+    }
+    if(server->pubSubManager.publishedDataSetsSize <= 0){
+        UA_free(server->pubSubManager.publishedDataSets);
+        server->pubSubManager.publishedDataSets = NULL;
+    } else {
+        server->pubSubManager.publishedDataSets = (UA_PublishedDataSet *)
+                UA_realloc(server->pubSubManager.publishedDataSets, sizeof(UA_PublishedDataSet) * server->pubSubManager.publishedDataSetsSize);
+        if(!server->pubSubManager.publishedDataSets){
+            return UA_STATUSCODE_BADINTERNALERROR;
+        }
+        //workaround - fixing issue with queue.h and realloc.
+        for(size_t n = 0; n < server->pubSubManager.publishedDataSetsSize; n++){
+            if(server->pubSubManager.publishedDataSets[n].fields.lh_first){
+                server->pubSubManager.publishedDataSets[n].fields.lh_first->listEntry.le_prev = &server->pubSubManager.publishedDataSets[n].fields.lh_first;
+            }
+        }
+    }
     return UA_STATUSCODE_GOOD;
 }
 
@@ -264,8 +282,8 @@ UA_PubSubConfigurationVersionTimeDifference() {
 void
 UA_PubSubManager_generateUniqueNodeId(UA_Server *server, UA_NodeId *nodeId) {
     UA_NodeId newNodeId = UA_NODEID_NUMERIC(0, 0);
-    UA_Node *newNode = UA_NODESTORE_NEW(server, UA_NODECLASS_OBJECT);
-    UA_NODESTORE_INSERT(server, newNode, &newNodeId);
+    UA_Node *newNode = UA_Nodestore_newNode(server->nsCtx, UA_NODECLASS_OBJECT);
+    UA_Nodestore_insertNode(server->nsCtx, newNode, &newNodeId);
     UA_NodeId_copy(&newNodeId, nodeId);
 }
 
@@ -274,31 +292,16 @@ UA_PubSubManager_generateUniqueNodeId(UA_Server *server, UA_NodeId *nodeId) {
 void
 UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) {
     UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "PubSub cleanup was called.");
-
-    /* Stop and unfreeze all WriterGroups */
-    UA_PubSubConnection *tmpConnection;
-    TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry){
-        for(size_t i = 0; i < pubSubManager->connectionsSize; i++) {
-            UA_WriterGroup *writerGroup;
-            LIST_FOREACH(writerGroup, &tmpConnection->writerGroups, listEntry) {
-                UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, writerGroup);
-                UA_Server_unfreezeWriterGroupConfiguration(server, writerGroup->identifier);
-            }
-        }
-    }
-
     //free the currently configured transport layers
     UA_free(server->config.pubsubTransportLayers);
     server->config.pubsubTransportLayersSize = 0;
 
     //remove Connections and WriterGroups
-    UA_PubSubConnection *tmpConnection1, *tmpConnection2;
-    TAILQ_FOREACH_SAFE(tmpConnection1, &server->pubSubManager.connections, listEntry, tmpConnection2){
-        UA_Server_removePubSubConnection(server, tmpConnection1->identifier);
+    while(pubSubManager->connectionsSize > 0){
+        UA_Server_removePubSubConnection(server, pubSubManager->connections[pubSubManager->connectionsSize-1].identifier);
     }
-    UA_PublishedDataSet *tmpPDS1, *tmpPDS2;
-    TAILQ_FOREACH_SAFE(tmpPDS1, &server->pubSubManager.publishedDataSets, listEntry, tmpPDS2){
-        UA_Server_removePublishedDataSet(server, tmpPDS1->identifier);
+    while(pubSubManager->publishedDataSetsSize > 0){
+        UA_Server_removePublishedDataSet(server, pubSubManager->publishedDataSets[pubSubManager->publishedDataSetsSize-1].identifier);
     }
 }
 

+ 3 - 3
src/pubsub/ua_pubsub_manager.h

@@ -2,7 +2,7 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
- * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
+ * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
  */
 
 #ifndef UA_PUBSUB_MANAGER_H_
@@ -19,9 +19,9 @@ _UA_BEGIN_DECLS
 typedef struct UA_PubSubManager{
     //Connections and PublishedDataSets can exist alone (own lifecycle) -> top level components
     size_t connectionsSize;
-    TAILQ_HEAD(UA_ListOfPubSubConnection, UA_PubSubConnection) connections;
+    UA_PubSubConnection *connections;
     size_t publishedDataSetsSize;
-    TAILQ_HEAD(UA_ListOfPublishedDataSet, UA_PublishedDataSet) publishedDataSets;
+    UA_PublishedDataSet *publishedDataSets;
 } UA_PubSubManager;
 
 void

+ 33 - 166
src/pubsub/ua_pubsub_networkmessage.c

@@ -3,7 +3,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
- * Copyright (c) 2019 Fraunhofer IOSB (Author: Andreas Ebner)
  */
 
 #include <open62541/types_generated_encoding_binary.h>
@@ -52,32 +51,6 @@ static UA_Boolean UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessag
 static UA_Boolean UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src);
 static UA_Boolean UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src);
 
-UA_StatusCode
-UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer){
-    UA_StatusCode rv = UA_STATUSCODE_GOOD;
-    for (size_t i = 0; i < buffer->offsetsSize; ++i) {
-        const UA_Byte *bufEnd = &buffer->buffer.data[buffer->buffer.length];
-        UA_Byte *bufPos = &buffer->buffer.data[buffer->offsets[i].offset];
-        switch (buffer->offsets[i].contentType) {
-            case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
-                rv = UA_UInt16_encodeBinary((UA_UInt16 *) buffer->offsets[i].offsetData.value.value->value.data, &bufPos, bufEnd);
-                break;
-            case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
-                rv = UA_UInt16_encodeBinary((UA_UInt16 *) buffer->offsets[i].offsetData.value.value->value.data, &bufPos, bufEnd);
-                break;
-            case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
-                rv = UA_DataValue_encodeBinary(buffer->offsets[i].offsetData.value.value, &bufPos, bufEnd);
-                break;
-            case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
-                rv = UA_Variant_encodeBinary(&buffer->offsets[i].offsetData.value.value->value, &bufPos, bufEnd);
-                break;
-            default:
-                return UA_STATUSCODE_BADNOTSUPPORTED;
-        }
-    }
-    return rv;
-}
-
 UA_StatusCode
 UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
                                const UA_Byte *bufEnd) {
@@ -323,8 +296,7 @@ UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
                    (src->payload.dataSetPayload.sizes[i] != 0)) {
                     sz = src->payload.dataSetPayload.sizes[i];
                 } else {
-                    sz = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&src->payload.dataSetPayload.dataSetMessages[i],
-                                                                      NULL, 0);
+                    sz = (UA_UInt16)UA_DataSetMessage_calcSizeBinary(&src->payload.dataSetPayload.dataSetMessages[i]);
                 }
 
                 rv = UA_UInt16_encodeBinary(&sz, bufPos, bufEnd);
@@ -684,19 +656,7 @@ UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Netw
     return retval;
 }
 
-static UA_Boolean
-increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) {
-    UA_NetworkMessageOffset *tmpOffsets = (UA_NetworkMessageOffset *)
-        UA_realloc(offsetBuffer->offsets, sizeof(UA_NetworkMessageOffset) * (offsetBuffer->offsetsSize + (size_t)1));
-    if(!tmpOffsets)
-        return false;
-    offsetBuffer->offsets = tmpOffsets;
-    offsetBuffer->offsetsSize++;
-    return true;
-}
-
-size_t
-UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer) {
+size_t UA_NetworkMessage_calcSizeBinary(const UA_NetworkMessage* p) {
     size_t retval = 0;
     UA_Byte byte;
     size_t size = UA_Byte_calcSizeBinary(&byte); // UADPVersion + UADPFlags
@@ -708,32 +668,32 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
 
     if(p->publisherIdEnabled) {
         switch (p->publisherIdType) {
-            case UA_PUBLISHERDATATYPE_BYTE:
-                size += UA_Byte_calcSizeBinary(&p->publisherId.publisherIdByte);
-                break;
+        case UA_PUBLISHERDATATYPE_BYTE:
+            size += UA_Byte_calcSizeBinary(&p->publisherId.publisherIdByte);
+            break;
 
-            case UA_PUBLISHERDATATYPE_UINT16:
-                size += UA_UInt16_calcSizeBinary(&p->publisherId.publisherIdUInt16);
-                break;
+        case UA_PUBLISHERDATATYPE_UINT16:
+            size += UA_UInt16_calcSizeBinary(&p->publisherId.publisherIdUInt16);
+            break;
 
-            case UA_PUBLISHERDATATYPE_UINT32:
-                size += UA_UInt32_calcSizeBinary(&p->publisherId.publisherIdUInt32);
-                break;
+        case UA_PUBLISHERDATATYPE_UINT32:
+            size += UA_UInt32_calcSizeBinary(&p->publisherId.publisherIdUInt32);
+            break;
 
-            case UA_PUBLISHERDATATYPE_UINT64:
-                size += UA_UInt64_calcSizeBinary(&p->publisherId.publisherIdUInt64);
-                break;
+        case UA_PUBLISHERDATATYPE_UINT64:
+            size += UA_UInt64_calcSizeBinary(&p->publisherId.publisherIdUInt64);
+            break;
 
-            case UA_PUBLISHERDATATYPE_STRING:
-                size += UA_String_calcSizeBinary(&p->publisherId.publisherIdString);
-                break;
+        case UA_PUBLISHERDATATYPE_STRING:
+            size += UA_String_calcSizeBinary(&p->publisherId.publisherIdString);
+            break;
         }
     }
 
     if(p->dataSetClassIdEnabled)
         size += UA_Guid_calcSizeBinary(&p->dataSetClassId);
 
-    // Group Header
+    // Group Header 
     if(p->groupHeaderEnabled) {
         size += UA_Byte_calcSizeBinary(&byte);
 
@@ -743,24 +703,11 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
         if(p->groupHeader.groupVersionEnabled)
             size += UA_UInt32_calcSizeBinary(&p->groupHeader.groupVersion);
 
-        if(p->groupHeader.networkMessageNumberEnabled) {
+        if(p->groupHeader.networkMessageNumberEnabled)
             size += UA_UInt16_calcSizeBinary(&p->groupHeader.networkMessageNumber);
-        }
 
-        if(p->groupHeader.sequenceNumberEnabled){
-            if(offsetBuffer){
-                size_t pos = offsetBuffer->offsetsSize;
-                if(!increaseOffsetArray(offsetBuffer))
-                    return 0;
-                offsetBuffer->offsets[pos].offset = size;
-                offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
-                UA_DataValue_init(offsetBuffer->offsets[pos].offsetData.value.value);
-                UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
-                                     &p->groupHeader.sequenceNumber, &UA_TYPES[UA_TYPES_UINT16]);
-                offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER;
-            }
+        if(p->groupHeader.sequenceNumberEnabled)
             size += UA_UInt16_calcSizeBinary(&p->groupHeader.sequenceNumber);
-        }
     }
 
     // Payload Header
@@ -769,7 +716,7 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
             size += UA_Byte_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.count);
             if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
                 size += UA_UInt16_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]) *
-                        p->payloadHeader.dataSetPayloadHeader.count;
+                    p->payloadHeader.dataSetPayloadHeader.count;
             } else {
                 return 0; /* no dataSetWriterIds given! */
             }
@@ -778,29 +725,13 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
         }
     }
 
-    if(p->timestampEnabled) {
-        if(offsetBuffer){
-            size_t pos = offsetBuffer->offsetsSize;
-            if(!increaseOffsetArray(offsetBuffer))
-                return 0;
-            offsetBuffer->offsets[pos].offset = size;
-            offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP;
-        }
+    if(p->timestampEnabled)
         size += UA_DateTime_calcSizeBinary(&p->timestamp);
-    }
 
-    if(p->picosecondsEnabled){
-        if (offsetBuffer) {
-            size_t pos = offsetBuffer->offsetsSize;
-            if(!increaseOffsetArray(offsetBuffer))
-                return 0;
-            offsetBuffer->offsets[pos].offset = size;
-            offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS;
-        }
+    if(p->picosecondsEnabled)
         size += UA_UInt16_calcSizeBinary(&p->picoseconds);
-    }
 
-    if(p->promotedFieldsEnabled) {
+    if(p->promotedFieldsEnabled) { 
         size += UA_UInt16_calcSizeBinary(&p->promotedFieldsSize);
         for (UA_UInt16 i = 0; i < p->promotedFieldsSize; i++)
             size += UA_Variant_calcSizeBinary(&p->promotedFields[i]);
@@ -815,7 +746,7 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
         if(p->securityHeader.securityFooterEnabled)
             size += UA_UInt16_calcSizeBinary(&p->securityHeader.securityFooterSize);
     }
-
+    
     if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
         UA_Byte count = 1;
         if(p->payloadHeaderEnabled) {
@@ -824,12 +755,8 @@ UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBu
                 size += UA_UInt16_calcSizeBinary(&(p->payload.dataSetPayload.sizes[0])) * count;
         }
 
-        for (size_t i = 0; i < count; i++) {
-            if (offsetBuffer)
-                UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), offsetBuffer,
-                                                 size);
-            size += UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), NULL, 0);
-        }
+        for (size_t i = 0; i < count; i++)
+            size += UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]));
     }
 
     if (p->securityEnabled) {
@@ -1292,84 +1219,23 @@ UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_Data
 }
 
 size_t
-UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBuffer *offsetBuffer, size_t currentOffset) {
-    size_t size = currentOffset;
-    UA_Byte byte;
-    size += UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
-    if(UA_DataSetMessageHeader_DataSetFlags2Enabled(&p->header))
-        size += UA_Byte_calcSizeBinary(&byte);
-
-    if(p->header.dataSetMessageSequenceNrEnabled) {
-        if (offsetBuffer) {
-            size_t pos = offsetBuffer->offsetsSize;
-            if(!increaseOffsetArray(offsetBuffer))
-                return 0;
-            offsetBuffer->offsets[pos].offset = size;
-            offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
-            UA_DataValue_init(offsetBuffer->offsets[pos].offsetData.value.value);
-            UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
-                                 &p->header.dataSetMessageSequenceNr, &UA_TYPES[UA_TYPES_UINT16]);
-            offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER;
-        }
-        size += UA_UInt16_calcSizeBinary(&p->header.dataSetMessageSequenceNr);
-    }
-
-    if(p->header.timestampEnabled)
-        size += UA_DateTime_calcSizeBinary(&p->header.timestamp); /* UtcTime */
-
-    if(p->header.picoSecondsIncluded)
-        size += UA_UInt16_calcSizeBinary(&p->header.picoSeconds);
-
-    if(p->header.statusEnabled)
-        size += UA_UInt16_calcSizeBinary(&p->header.status);
-
-    if(p->header.configVersionMajorVersionEnabled)
-        size += UA_UInt32_calcSizeBinary(&p->header.configVersionMajorVersion);
-
-    if(p->header.configVersionMinorVersionEnabled)
-        size += UA_UInt32_calcSizeBinary(&p->header.configVersionMinorVersion);
+UA_DataSetMessage_calcSizeBinary(const UA_DataSetMessage* p) {
+    size_t size = UA_DataSetMessageHeader_calcSizeBinary(&p->header);
 
     if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
-        if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA){
-            //TODO clarify RT and Rawdata behavior
+        if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA)
             size += UA_calcSizeBinary(&p->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
-        }
 
         if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
-            for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
-                if (offsetBuffer) {
-                    size_t pos = offsetBuffer->offsetsSize;
-                    if(!increaseOffsetArray(offsetBuffer))
-                        return 0;
-                    offsetBuffer->offsets[pos].offset = size;
-                    offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT;
-                    //TODO check value source and alloc!
-                    offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
-                    UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
-                                         p->data.keyFrameData.dataSetFields[i].value.data,
-                                         p->data.keyFrameData.dataSetFields[i].value.type);
-                    //offsetBuffer->offsets[pos].offsetData.value.value->value = p->data.keyFrameData.dataSetFields->value;
-                }
+            for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++)
                 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i].value, &UA_TYPES[UA_TYPES_VARIANT]);
-            }
         } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
             // not implemented
         } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
-            for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++) {
-                if (offsetBuffer) {
-                    size_t pos = offsetBuffer->offsetsSize;
-                    if(!increaseOffsetArray(offsetBuffer))
-                        return 0;
-                    offsetBuffer->offsets[pos].offset = size;
-                    offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE;
-                    //TODO check value source, change implementation to 'variant'
-                    offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
-                }
+            for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++)
                 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i], &UA_TYPES[UA_TYPES_DATAVALUE]);
-            }
         }
     } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
-        //TODO clarify how to handle DATADELTAFRAME messages with RT
         if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA)
             size += UA_calcSizeBinary(&p->data.deltaFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
 
@@ -1387,6 +1253,7 @@ UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBu
             }
         }
     }
+
     /* KeepAlive-Message contains no Payload Data */
     return size;
 }

+ 2 - 42
src/pubsub/ua_pubsub_networkmessage.h

@@ -3,7 +3,6 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
- * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
  */
 
 #ifndef UA_PUBSUB_NETWORKMESSAGE_H_
@@ -65,41 +64,6 @@ UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
 size_t
 UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p);
 
-/**********************************************/
-/*          Network Message Offsets           */
-/**********************************************/
-
-/* Offsets for buffered messages in the PubSub fast path. */
-typedef enum {
-    UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER,
-    UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER,
-    UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS,
-    UA_PUBSUB_OFFSETTYPE_TIMESTAMP,     /* source pointer */
-    UA_PUBSUB_OFFSETTYPE_TIMESTAMP_NOW, /* no source */
-    UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE,
-    UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT,
-    UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW
-    /* Add more offset types as needed */
-} UA_NetworkMessageOffsetType;
-
-typedef struct {
-    UA_NetworkMessageOffsetType contentType;
-    union {
-        union {
-            UA_DataValue *value;
-            size_t valueBinarySize;
-        } value;
-        UA_DateTime *timestamp;
-    } offsetData;
-    size_t offset;
-} UA_NetworkMessageOffset;
-
-typedef struct {
-    UA_ByteString buffer; /* The precomputed message buffer */
-    UA_NetworkMessageOffset *offsets; /* Offsets for changes in the message buffer */
-    size_t offsetsSize;
-} UA_NetworkMessageOffsetBuffer;
-
 /**
  * DataSetMessage
  * ^^^^^^^^^^^^^^ */
@@ -138,8 +102,7 @@ UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
                                UA_DataSetMessage* dst);
 
 size_t
-UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer,
-                                 size_t currentOffset);
+UA_DataSetMessage_calcSizeBinary(const UA_DataSetMessage* p);
 
 void UA_DataSetMessage_free(const UA_DataSetMessage* p);
 
@@ -239,9 +202,6 @@ typedef struct {
     UA_ByteString signature;
 } UA_NetworkMessage;
 
-UA_StatusCode
-UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer);
-
 UA_StatusCode
 UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src,
                                UA_Byte **bufPos, const UA_Byte *bufEnd);
@@ -251,7 +211,7 @@ UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
                                UA_NetworkMessage* dst);
 
 size_t
-UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer);
+UA_NetworkMessage_calcSizeBinary(const UA_NetworkMessage* p);
 
 void
 UA_NetworkMessage_deleteMembers(UA_NetworkMessage* p);

+ 7 - 8
src/pubsub/ua_pubsub_ns0.c

@@ -6,7 +6,6 @@
  * Copyright (c) 2019 Kalycito Infotech Private Limited
  */
 
-#include <open62541/types.h>
 #include "ua_pubsub_ns0.h"
 
 #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */
@@ -144,7 +143,7 @@ onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
                 UA_calloc(publishedDataSet->fieldSize, sizeof(UA_PublishedVariableDataType));
             size_t counter = 0;
             UA_DataSetField *field;
-            TAILQ_FOREACH(field, &publishedDataSet->fields, listEntry) {
+            LIST_FOREACH(field, &publishedDataSet->fields, listEntry) {
                 pvd[counter].attributeId = UA_ATTRIBUTEID_VALUE;
                 pvd[counter].publishedVariable = field->config.field.variable.publishParameters.publishedVariable;
                 //UA_NodeId_copy(&field->config.field.variable.publishParameters.publishedVariable, &pvd[counter].publishedVariable);
@@ -200,7 +199,7 @@ onWrite(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
                     writerGroupConfig.publishingInterval = *((UA_Duration *) data->value.data);
                     UA_Server_updateWriterGroupConfig(server, writerGroup->identifier, &writerGroupConfig);
                     UA_Variant_setScalar(&value, data->value.data, &UA_TYPES[UA_TYPES_DURATION]);
-                    UA_WriterGroupConfig_clear(&writerGroupConfig);
+                    UA_WriterGroupConfig_deleteMembers(&writerGroupConfig);
                     break;
                 default:
                     UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
@@ -232,7 +231,7 @@ addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connec
     memcpy(connectionName, connection->config->name.data, connection->config->name.length);
     connectionName[connection->config->name.length] = '\0';
     //This code block must use a lock
-    UA_NODESTORE_REMOVE(server, &connection->identifier);
+    UA_Nodestore_removeNode(server->nsCtx, &connection->identifier);
     UA_NodeId pubSubConnectionNodeId;
     UA_ObjectAttributes attr = UA_ObjectAttributes_default;
     attr.displayName = UA_LOCALIZEDTEXT("de-DE", connectionName);
@@ -532,7 +531,7 @@ addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publ
     memcpy(pdsName, publishedDataSet->config.name.data, publishedDataSet->config.name.length);
     pdsName[publishedDataSet->config.name.length] = '\0';
     //This code block must use a lock
-    UA_NODESTORE_REMOVE(server, &publishedDataSet->identifier);
+    UA_Nodestore_removeNode(server->nsCtx, &publishedDataSet->identifier);
     retVal |= addPubSubObjectNode(server, pdsName, publishedDataSet->identifier.identifier.numeric,
                                   UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS,
                                   UA_NS0ID_HASPROPERTY, UA_NS0ID_PUBLISHEDDATAITEMSTYPE);
@@ -748,9 +747,9 @@ addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
     memcpy(wgName, writerGroup->config.name.data, writerGroup->config.name.length);
     wgName[writerGroup->config.name.length] = '\0';
     //This code block must use a lock
-    UA_NODESTORE_REMOVE(server, &writerGroup->identifier);
+    UA_Nodestore_removeNode(server->nsCtx, &writerGroup->identifier);
     retVal |= addPubSubObjectNode(server, wgName, writerGroup->identifier.identifier.numeric,
-                                  writerGroup->linkedConnection->identifier.identifier.numeric,
+                                  writerGroup->linkedConnection.identifier.numeric,
                                   UA_NS0ID_HASCOMPONENT, UA_NS0ID_WRITERGROUPTYPE);
     //End lock zone
     UA_NodeId keepAliveNode =
@@ -916,7 +915,7 @@ addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWrite
     memcpy(dswName, dataSetWriter->config.name.data, dataSetWriter->config.name.length);
     dswName[dataSetWriter->config.name.length] = '\0';
     //This code block must use a lock
-    UA_NODESTORE_REMOVE(server, &dataSetWriter->identifier);
+    UA_Nodestore_removeNode(server->nsCtx, &dataSetWriter->identifier);
     retVal |= addPubSubObjectNode(server, dswName, dataSetWriter->identifier.identifier.numeric,
                                   dataSetWriter->linkedWriterGroup.identifier.numeric,
                                   UA_NS0ID_HASDATASETWRITER, UA_NS0ID_DATASETWRITERTYPE);

+ 0 - 0
src/pubsub/ua_pubsub_reader.c


Some files were not shown because too many files changed in this diff