Explorar o código

Merge pull request #124 from acplt/noglobal

Refactoring without global variables
Julius Pfrommer %!s(int64=10) %!d(string=hai) anos
pai
achega
9b6b9a2b35
Modificáronse 89 ficheiros con 6023 adicións e 8155 borrados
  1. 27 24
      CMakeLists.txt
  2. 110 0
      LICENSE-CC0
  3. 7 3
      examples/logger_stdout.c
  4. 8 1
      examples/logger_stdout.h
  5. 0 511
      examples/networklayer.c
  6. 0 67
      examples/networklayer.h
  7. 325 0
      examples/networklayer_tcp.c
  8. 25 0
      examples/networklayer_tcp.h
  9. 46 33
      examples/opcuaServer.c
  10. 0 156
      examples/opcuaServerACPLT.c
  11. 0 51
      examples/opcuaServerMT.c
  12. 5 0
      examples/opcuaServerMini.c
  13. 8 8
      schema/Custom.Opc.Ua.Transport.bsd
  14. 0 0
      src/ongoing/generateSam.c
  15. 0 0
      src/ongoing/ua_namespace_xml.c
  16. 0 0
      src/ongoing/ua_namespace_xml.h
  17. 0 0
      src/ongoing/ua_types_encoding_json.c
  18. 0 0
      src/ongoing/ua_types_encoding_json.h
  19. 0 0
      src/ongoing/ua_types_encoding_xml.c
  20. 0 0
      src/ongoing/ua_types_encoding_xml.h
  21. 0 0
      src/ongoing/ua_xml.c
  22. 0 0
      src/ongoing/ua_xml.h
  23. 0 0
      src/ongoing/xml2ns0.c
  24. 0 571
      src/server/ua_application.c
  25. 0 15
      src/server/ua_application.h
  26. 0 139
      src/server/ua_channel_manager.c
  27. 0 17
      src/server/ua_channel_manager.h
  28. 0 339
      src/server/ua_namespace.c
  29. 0 372
      src/server/ua_namespace_concurrent.c
  30. 355 0
      src/server/ua_nodestore.c
  31. 26 24
      src/server/ua_namespace.h
  32. 372 0
      src/server/ua_nodestore_concurrent.c
  33. 144 0
      src/server/ua_securechannel_manager.c
  34. 24 0
      src/server/ua_securechannel_manager.h
  35. 540 6
      src/server/ua_server.c
  36. 24 2
      src/server/ua_server.h
  37. 354 0
      src/server/ua_server_binary.c
  38. 50 38
      src/server/ua_services.h
  39. 384 410
      src/server/ua_services_attribute.c
  40. 36 79
      src/server/ua_services_discovery.c
  41. 2 3
      src/server/ua_services_internal.h
  42. 24 20
      src/server/ua_services_monitoreditems.c
  43. 119 131
      src/server/ua_services_nodemanagement.c
  44. 15 21
      src/server/ua_services_securechannel.c
  45. 39 47
      src/server/ua_services_session.c
  46. 22 22
      src/server/ua_services_subscription.c
  47. 220 214
      src/server/ua_services_view.c
  48. 140 149
      src/server/ua_session_manager.c
  49. 16 19
      src/server/ua_session_manager.h
  50. 0 65
      src/server/ua_transport_connection_manager.c
  51. 0 14
      src/server/ua_transport_connection_manager.h
  52. 0 0
      src/tokenType
  53. 0 382
      src/ua_channel.c
  54. 0 65
      src/ua_channel.h
  55. 3 4
      src/ua_config.h.in
  56. 41 0
      src/ua_connection.c
  57. 55 0
      src/ua_connection.h
  58. 63 0
      src/ua_securechannel.c
  59. 39 0
      src/ua_securechannel.h
  60. 67 156
      src/ua_session.c
  61. 23 115
      src/ua_session.h
  62. 29 526
      src/ua_transport.c
  63. 16 107
      src/ua_transport.h
  64. 0 181
      src/ua_transport_binary.c
  65. 0 40
      src/ua_transport_binary.h
  66. 0 378
      src/ua_transport_binary_secure.c
  67. 0 35
      src/ua_transport_binary_secure.h
  68. 0 143
      src/ua_transport_connection.c
  69. 0 39
      src/ua_transport_connection.h
  70. 700 707
      src/ua_types.c
  71. 177 164
      src/ua_types.h
  72. 751 715
      src/ua_types_encoding_binary.c
  73. 16 14
      src/ua_types_encoding_binary.h
  74. 113 117
      src/util/ua_base64.c
  75. 2 2
      src/util/ua_base64.h
  76. 0 126
      src/util/ua_indexedList.c
  77. 0 40
      src/util/ua_indexedList.h
  78. 228 245
      src/util/ua_list.c
  79. 28 51
      src/util/ua_list.h
  80. 24 35
      src/util/ua_log.h
  81. 7 7
      src/util/ua_util.c
  82. 28 20
      src/util/ua_util.h
  83. 12 16
      tests/CMakeLists.txt
  84. 3 2
      tests/check_builtin.c
  85. 87 87
      tests/check_namespace.c
  86. 4 14
      tests/check_services_view.c
  87. 32 49
      tests/check_stack.c
  88. 7 1
      tools/generate_builtin.py
  89. 1 1
      tools/uncrustify.cfg

+ 27 - 24
CMakeLists.txt

@@ -7,8 +7,6 @@ set(open62541_VERSION_MINOR 1)
 
 # main sources of libopen62541
 include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src")
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/server")
-include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/util")
 file(GLOB_RECURSE headers "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h")
 file(GLOB generated_headers "${PROJECT_BINARY_DIR}/src_generated/*.h")
 set(lib_sources src/ua_types.c
@@ -16,11 +14,17 @@ set(lib_sources src/ua_types.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
                 ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0.c
                 src/ua_transport.c
-                src/ua_transport_binary.c
-                src/ua_transport_binary_secure.c
-                src/ua_channel.c
+                ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
+				src/ua_connection.c
+                src/ua_securechannel.c
                 src/ua_session.c
-                src/ua_transport_connection.c
+                src/util/ua_util.c
+                src/util/ua_list.c
+                #src/util/ua_base64.c
+                src/server/ua_server.c
+                src/server/ua_securechannel_manager.c
+                src/server/ua_session_manager.c
+                src/server/ua_server_binary.c
                 src/server/ua_services_attribute.c
                 src/server/ua_services_session.c
                 src/server/ua_services_discovery.c
@@ -29,15 +33,6 @@ set(lib_sources src/ua_types.c
                 src/server/ua_services_view.c
                 src/server/ua_services_subscription.c
                 src/server/ua_services_monitoreditems.c
-                src/server/ua_channel_manager.c
-                src/server/ua_session_manager.c
-                src/server/ua_transport_connection_manager.c
-                src/server/ua_server.c
-                src/server/ua_application.c
-                src/util/ua_util.c
-                src/util/ua_list.c
-                src/util/ua_indexedList.c
-                src/util/ua_base64.c
                 ${headers}
                 ${generated_headers})
 
@@ -90,9 +85,10 @@ if(ENABLE_XML_ENCODING)
     else(EXPAT_FOUND)
         message(FATAL_ERROR "Expat library not found.")
     endif(EXPAT_FOUND)
-    list(APPEND lib_sources src/ua_types_encoding_xml.c
-                            src/server/ua_namespace_xml.c
-                            src/ua_xml.c)
+	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/ongoing")
+    list(APPEND lib_sources src/ongoing/ua_types_encoding_xml.c
+                            src/ongoing/ua_namespace_xml.c
+                            src/ongoing/ua_xml.c)
     list(APPEND generate_src_options "--with-xml")
 endif(ENABLE_XML_ENCODING)
 
@@ -100,19 +96,18 @@ endif(ENABLE_XML_ENCODING)
 option(ENABLE_JSON_ENCODING "Enable JSON-encoding of the UA types" OFF)
 if(ENABLE_JSON_ENCODING)
     MATH(EXPR UA_ENCODING_AMOUNT "${UA_ENCODING_AMOUNT}+1")
-    list(APPEND lib_sources src/ua_types_encoding_json.c)
+	include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/ongoing")
+    list(APPEND lib_sources src/ongoing/ua_types_encoding_json.c)
     list(APPEND generate_src_options "--with-json")
 endif(ENABLE_JSON_ENCODING)
 
-configure_file("src/ua_config.h.in" "${PROJECT_BINARY_DIR}/src_generated/ua_config.h")
-
 ## multithreading
 option(ENABLE_MULTITHREADING "Enable multithreading" OFF)
 if(ENABLE_MULTITHREADING)
     find_package(Threads REQUIRED)
-    list(APPEND lib_sources src/server/ua_namespace_concurrent.c)
+    list(APPEND lib_sources src/server/ua_nodestore_concurrent.c)
 else()
-    list(APPEND lib_sources src/server/ua_namespace.c)
+    list(APPEND lib_sources src/server/ua_nodestore.c)
 endif(ENABLE_MULTITHREADING)
 
 add_library(open62541 ${lib_sources}) # we can add more files to lib_sources later on
@@ -130,6 +125,8 @@ if(ENABLE_COVERAGE)
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
 endif(ENABLE_COVERAGE)
 
+configure_file("src/ua_config.h.in" "${PROJECT_BINARY_DIR}/src_generated/ua_config.h")
+
 # build generated code
 file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/src_generated")
 include_directories("${PROJECT_BINARY_DIR}/src_generated") 
@@ -145,10 +142,16 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_0.c
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_namespace.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/schema/NodeIds.csv)
 
+add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
+                          ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
+                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_builtin.py --additional-includes=ua_transport.h ${PROJECT_SOURCE_DIR}/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated
+                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_namespace.py
+                           ${CMAKE_CURRENT_SOURCE_DIR}/schema/Custom.Opc.Ua.Transport.bsd)
+
 # build example server
 add_executable(exampleServer examples/opcuaServer.c
                              examples/logger_stdout.c
-                             examples/networklayer.c)
+                             examples/networklayer_tcp.c)
 target_link_libraries(exampleServer open62541)
 if(WIN32)
     target_link_libraries(exampleServer ws2_32)

+ 110 - 0
LICENSE-CC0

@@ -0,0 +1,110 @@
+Creative Commons CCZero 1.0 Universal
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+  i. the right to reproduce, adapt, distribute, perform, display,
+     communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+     likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+     subject to the limitations in paragraph 4(a), below;
+  v. rights protecting the extraction, dissemination, use and reuse of data
+     in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+     European Parliament and of the Council of 11 March 1996 on the legal
+     protection of databases, and under any national implementation
+     thereof, including any amended or successor version of such
+     directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+     world based on applicable law or treaty, and any national
+     implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+    surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+    warranties of any kind concerning the Work, express, implied,
+    statutory or otherwise, including without limitation warranties of
+    title, merchantability, fitness for a particular purpose, non
+    infringement, or the absence of latent or other defects, accuracy, or
+    the present or absence of errors, whether or not discoverable, all to
+    the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+    that may apply to the Work or any use thereof, including without
+    limitation any person's Copyright and Related Rights in the Work.
+    Further, Affirmer disclaims responsibility for obtaining any necessary
+    consents, permissions or other rights required for any use of the
+    Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+    party to this document and has no duty or obligation with respect to
+    this CC0 or use of the Work.

+ 7 - 3
examples/logger_stdout.c

@@ -1,8 +1,12 @@
+/*
+ * 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 <stdio.h>
 #include <stdarg.h>
 
 #include "logger_stdout.h"
-#include "ua_log.h"
 #include "ua_types.h"
 
 void print_time() {
@@ -32,8 +36,8 @@ LOG_FUNCTION(warning)
 LOG_FUNCTION(error)
 LOG_FUNCTION(fatal)
 
-void Logger_Stdout_init(void *config) {
-	logger = (UA_Logger){
+void Logger_Stdout_init(UA_Logger *logger) {
+	*logger = (UA_Logger){
 		.log_trace = log_trace,
 		.log_debug = log_debug,
 		.log_info = log_info,

+ 8 - 1
examples/logger_stdout.h

@@ -1,7 +1,14 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
 #ifndef LOGGER_STDOUT_H_
 #define LOGGER_STDOUT_H_
 
+#include "util/ua_log.h"
+
 /** Initialises the logger for the current thread. */
-void Logger_Stdout_init(void *config);
+void Logger_Stdout_init(UA_Logger *logger);
 
 #endif /* LOGGER_STDOUT_H_ */

+ 0 - 511
examples/networklayer.c

@@ -1,511 +0,0 @@
-#include "networklayer.h"
-#include "ua_transport_connection.h"
-
-#ifdef WIN32
-#include <sys/types.h>
-#include <Windows.h>
-#include <ws2tcpip.h>
-#define CLOSESOCKET(S) closesocket(S)
-#define IOCTLSOCKET ioctlsocket
-#else
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/socketvar.h>
-#include <unistd.h> // read, write, close
-#define CLOSESOCKET(S) close(S)
-#define IOCTLSOCKET ioctl
-#endif /* WIN32 */
-
-#include <stdlib.h> // exit
-#include <errno.h> // errno, EINTR
-
-#include <memory.h> // memset
-#include <fcntl.h> // fcntl
-
-#ifdef ENABLE_MULTITHREADING
-#include <pthread.h>
-#endif
-
-NL_Description NL_Description_TcpBinary  = {
-	NL_UA_ENCODING_BINARY,
-	NL_CONNECTIONTYPE_TCPV4,
-	NL_MAXCONNECTIONS_DEFAULT,
-	{0,8192,8192,16384,1}
-};
-
-/* If we do not have multitasking, we implement a dispatcher-Pattern. All Connections
- * are collected in a list. From this list a fd_set is prepared and select then waits
- * for activities. We then iterate over the list, check if we've got some activites
- * and call the corresponding callback (reader, listener).
- */
-#ifndef ENABLE_MULTITHREADING
-_Bool NL_ConnectionComparer(void *p1, void* p2) {
-	NL_Connection* c1 = (NL_Connection*) p1;
-	NL_Connection* c2 = (NL_Connection*) p2;
-
-	return (c1->connectionHandle == c2->connectionHandle);
-
-}
-
-int NL_TCP_SetNonBlocking(int sock) {
-#ifdef WIN32
-	u_long iMode = 1;
-	int opts = IOCTLSOCKET(sock, FIONBIO, &iMode);
-	if (opts != NO_ERROR){
-		printf("ioctlsocket failed with error: %ld\n", opts);
-		return - 1;
-	}
-#else
-	int opts = fcntl(sock,F_GETFL);
-	if (opts < 0) {
-		perror("fcntl(F_GETFL)");
-		return -1;
-	}
-	opts = (opts | O_NONBLOCK);
-	if (fcntl(sock,F_SETFL,opts) < 0) {
-		perror("fcntl(F_SETFL)");
-		return -1;
-	}
-#endif
-	return 0;
-}
-
-void NL_Connection_printf(void* payload) {
-  NL_Connection* c = (NL_Connection*) payload;
-  printf("ListElement connectionHandle = %d\n",c->connectionHandle);
-}
-void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
-	FD_SET(handle, &(nl->readerHandles));
-#ifdef WIN32
-	// int err = WSAGetLastError();
-#endif
-	nl->maxReaderHandle = (handle > nl->maxReaderHandle) ? handle : nl->maxReaderHandle;
-}
-void NL_setFdSet(void* payload) {
-  NL_Connection* c = (NL_Connection*) payload;
-  NL_addHandleToSet(c->connectionHandle, c->networkLayer);
-}
-void NL_checkFdSet(void* payload) {
-  NL_Connection* c = (NL_Connection*) payload;
-  if (FD_ISSET(c->connectionHandle, &(c->networkLayer->readerHandles))) {
-	  c->reader((void*)c);
-  }
-}
-
-#if 0 
-char _str_error[256];
-char* strerror(int errno) {
-	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-		NULL, errno,
-		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-		&_str_error[0], 256, NULL);
-	return &_str_error[0];
-}
-#endif
-
-UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg, UA_Boolean *running)  {
-	UA_Int32 result;
-	UA_Int32 err;
-	while (*running) {
-		// determine the largest handle
-		nl->maxReaderHandle = 0;
-		UA_list_iteratePayload(&(nl->connections),NL_setFdSet);
-		DBG_VERBOSE(printf("\n------------\nUA_Stack_msgLoop - maxHandle=%d\n", nl->maxReaderHandle));
-
-		// copy tv, some unixes do overwrite and return the remaining time
-		// FIXME: actually we might want to do this ourselves to call the
-		// worker on a more regular cyclic basis
-		struct timeval tmptv;
-		memcpy(&tmptv,tv,sizeof(struct timeval));
-
-		// and wait
-		DBG_VERBOSE(printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
-		result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL, &tmptv);
-		DBG_VERBOSE(printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
-
-		// handle timeout (winsock: result=0, unix: result=0,errno=0||EAGAIN) 
-		// and errors (winsock: result=SOCKET_ERROR (-1), unix: result = 0)
-		if (result <= 0) {
-#ifdef WIN32
-			err = (result == SOCKET_ERROR) ? WSAGetLastError() : 0;
-#else
-			err = errno;
-#endif
-			switch (err) {
-				// handle known errors
-#ifdef WIN32
-			case WSANOTINITIALISED:
-			case WSAEFAULT:
-			case WSAENETDOWN:
-			case WSAEINVAL:
-			case WSAEINTR:
-			case WSAEINPROGRESS:
-			case WSAENOTSOCK:
-#else
-			case EBADF:
-			case EINTR:
-			case EINVAL:
-#endif
-				// FIXME: handle errors
-				printf("UA_Stack_msgLoop - result=%d, errno={%d,%s}\n", result, errno, strerror(errno));
-				break;
-			// otherwise we've got a timeout and call the worker
-#ifndef WIN32
-	        case EAGAIN:
-#endif
-			default:
-					DBG_VERBOSE(printf("UA_Stack_msgLoop - result=%d, errno={%d,%s}\n", result, errno, strerror(errno)));
-					worker(arg);
-			}
-		} else { // activity on listener or client ports
-			DBG_VERBOSE(printf("UA_Stack_msgLoop - activities on %d handles\n",result));
-			UA_list_iteratePayload(&(nl->connections),NL_checkFdSet);
-			// FIXME: Thought it would be a conceptional flaw to call the worker
-			// here. However, there is no guarantee that the timeout would be
-			// triggered, so we call it in this branch as well.
-			worker(arg);
-		}
-	}
-#ifdef WIN32
-	// finally we should clean up the winsock.dll
-	WSACleanup();
-#endif
-	return UA_SUCCESS;
-}
-#endif /* ENABLE_MULTITHREADING */
-
-
-/** the tcp reader function */
-void* NL_TCP_reader(NL_Connection *c) {
-
-	UA_ByteString readBuffer;
-
-	TL_Buffer localBuffers;
-	UA_Int32 connectionState;
-
-	UA_TL_Connection_getLocalConfig(c->connection, &localBuffers);
-	UA_alloc((void**)&(readBuffer.data),localBuffers.recvBufferSize);
-
-	UA_TL_Connection_getState(c->connection, &connectionState);
-	if (connectionState  != CONNECTIONSTATE_CLOSE) {
-		DBG_VERBOSE(printf("NL_TCP_reader - enter read\n"));
-
-#ifdef WIN32
-		readBuffer.length = recv(c->connectionHandle, (char *)readBuffer.data, localBuffers.recvBufferSize, 0);
-#else
-		readBuffer.length = read(c->connectionHandle, readBuffer.data, localBuffers.recvBufferSize);
-#endif
-		DBG_VERBOSE(printf("NL_TCP_reader - leave read\n"));
-
-		DBG_VERBOSE(printf("NL_TCP_reader - src={%*.s}, ",c->connection.remoteEndpointUrl.length,c->connection.remoteEndpointUrl.data));
-		DBG(UA_ByteString_printx("NL_TCP_reader - received=",&readBuffer));
-
-		if (errno != 0) {
-			perror("NL_TCP_reader - ERROR reading from socket1");
-			UA_TL_Connection_setState(c->connection, CONNECTIONSTATE_CLOSE);
-		} else if (readBuffer.length  > 0) {
-#ifdef DEBUG
-#include "ua_transport_binary_secure.h"
-			UA_UInt32 pos = 0;
-			UA_OPCUATcpMessageHeader header;
-			UA_OPCUATcpMessageHeader_decodeBinary(&readBuffer, &pos, &header);
-			pos = 24;
-			if(header.messageType == UA_MESSAGETYPE_MSG)
-			{
-				UA_NodeId serviceRequestType;
-				UA_NodeId_decodeBinary(&readBuffer, &pos,&serviceRequestType);
-				UA_NodeId_printf("NL_TCP_reader - Service Type\n",&serviceRequestType);
-			}
-#endif
-			TL_Process((c->connection),&readBuffer);
-		} else {
-			perror("NL_TCP_reader - ERROR reading from socket");
-			UA_TL_Connection_setState(c->connection, CONNECTIONSTATE_CLOSE);
-		}
-	}
-
-	UA_TL_Connection_getState(c->connection, &connectionState);
-	DBG_VERBOSE(printf("NL_TCP_reader - connectionState=%d\n",connectionState));
-	if (connectionState == CONNECTIONSTATE_CLOSE) {
-		// set connection's state to CONNECTIONSTATE_CLOSED and call callback to actually close
-		UA_TL_Connection_close(c->connection);
-#ifndef ENABLE_MULTITHREADING
-		DBG_VERBOSE(printf("NL_TCP_reader - search element to remove\n"));
-		UA_list_Element* lec = UA_list_search(&(c->networkLayer->connections),NL_ConnectionComparer,c);
-		DBG_VERBOSE(printf("NL_TCP_reader - remove connection for handle=%d\n",((NL_Connection*)lec->payload)->connection.connectionHandle));
-		UA_list_removeElement(lec,UA_NULL);
-		DBG_VERBOSE(UA_list_iteratePayload(&(c->networkLayer->connections),NL_Connection_printf));
-		UA_free(c);
-#endif
-	}
-	UA_ByteString_deleteMembers(&readBuffer);
-	return UA_NULL;
-}
-
-#ifdef ENABLE_MULTITHREADING
-/** the tcp reader thread */
-void* NL_TCP_readerThread(NL_Connection *c) {
-	// just loop, NL_TCP_Reader will call the stack
-	UA_Int32 connectionState;
-	do {
-		NL_TCP_reader(c);
-		UA_TL_Connection_getState(c->connection, &connectionState);
-	} while (connectionState != CONNECTIONSTATE_CLOSED);
-	// clean up
-	UA_free(c);
-	pthread_exit(UA_NULL);
-}
-#endif
-
-/** write message provided in the gather buffers to a tcp transport layer connection */
-UA_Int32 NL_TCP_writer(UA_Int32 connectionHandle, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len) {
-
-	UA_UInt32 total_len = 0;
-#ifdef WIN32
-	WSABUF *buf = malloc(gather_len * sizeof(WSABUF));
-	int result = 0;
-	for (UA_UInt32 i = 0; i<gather_len; i++) {
-		buf[i].buf = (char*)gather_buf[i]->data;
-		buf[i].len = gather_buf[i]->length;
-		total_len += gather_buf[i]->length;
-		//		DBG(printf("NL_TCP_writer - gather_buf[%i]",i));
-		//		DBG(UA_ByteString_printx("=", gather_buf[i]));
-	}
-#else
-	struct iovec iov[gather_len];
-	for(UA_UInt32 i=0;i<gather_len;i++) {
-		iov[i].iov_base = gather_buf[i]->data;
-		iov[i].iov_len = gather_buf[i]->length;
-		total_len += gather_buf[i]->length;
-//		DBG(printf("NL_TCP_writer - gather_buf[%i]",i));
-//		DBG(UA_ByteString_printx("=", gather_buf[i]));
-	}
-	struct msghdr message;
-	message.msg_name = UA_NULL;
-	message.msg_namelen = 0;
-	message.msg_iov = iov;
-	message.msg_iovlen = gather_len;
-	message.msg_control = UA_NULL;
-	message.msg_controllen = 0;
-	message.msg_flags = 0;
-#endif
-
-
-	UA_UInt32 nWritten = 0;
-#ifdef WIN32
-	while (nWritten < total_len) {
-		UA_UInt32 n=0;
-		do {
-			DBG_VERBOSE(printf("NL_TCP_writer - enter write with %d bytes to write\n",total_len));
-
-			//result = WSASendMsg(connectionHandle,&message,0,&n,UA_NULL,UA_NULL);
-			result = WSASend(connectionHandle, buf, gather_len , (LPDWORD)&n, 0, NULL, NULL);
-			if(result != 0)
-				printf("NL_TCP_Writer - Error WSASend, code: %d \n", WSAGetLastError());
-			DBG_VERBOSE(printf("NL_TCP_writer - leave write with n=%d,errno={%d,%s}\n",n,(n>0)?0:errno,(n>0)?"":strerror(errno)));
-		} while (errno == EINTR);
-		nWritten += n;
-#else
-	while (nWritten < total_len) {
-		UA_Int32 n=0;
-		do {
-			DBG_VERBOSE(printf("NL_TCP_writer - enter write with %d bytes to write\n",total_len));
-			n = sendmsg(connectionHandle, &message, 0);
-			DBG_VERBOSE(printf("NL_TCP_writer - leave write with n=%d,errno={%d,%s}\n",n,(n>0)?0:errno,(n>0)?"":strerror(errno)));
-		} while (n == -1L && errno == EINTR);
-
-		if (n >= 0) {
-			nWritten += n;
-			break;
-			// TODO: handle incompletely send messages
-		} else {
-			// TODO: error handling
-			break;
-		}
-#endif
-	}
-#ifdef WIN32
-	free(buf);
-#endif
-	return UA_SUCCESS;
-}
-//callback function which is called when the UA_TL_Connection_close() function is initiated
-UA_Int32 NL_Connection_close(UA_TL_Connection *connection)
-{
-	NL_Connection *networkLayerData = UA_NULL;
-	UA_TL_Connection_getNetworkLayerData(connection, (void**)&networkLayerData);
-	if(networkLayerData != UA_NULL){
-		DBG_VERBOSE(printf("NL_Connection_close - enter shutdown\n"));
-		shutdown(networkLayerData->connectionHandle,2);
-		DBG_VERBOSE(printf("NL_Connection_close - enter close\n"));
-		CLOSESOCKET(networkLayerData->connectionHandle);
-		FD_CLR(networkLayerData->connectionHandle, &networkLayerData->networkLayer->readerHandles);
-		DBG_VERBOSE(printf("NL_Connection_close - leave close\n"));
-		return UA_SUCCESS;
-	}
-    DBG_VERBOSE(printf("NL_Connection_close - ERROR: connection object invalid \n"));
-	return UA_ERROR;
-}
-void* NL_Connection_init(NL_Connection* c, NL_data* tld, UA_Int32 connectionHandle, NL_Reader reader, TL_Writer writer)
-{
-	UA_TL_Connection *connection = UA_NULL;
-	//create new connection object
-	UA_TL_Connection_new(&connection, tld->tld->localConf, writer, NL_Connection_close,connectionHandle,c);
-
-	c->connection = connection;
-	c->connectionHandle = connectionHandle;
-	// network layer
-	c->reader = reader;
-#ifdef MULTITHREADING
-	c->readerThreadHandle = -1;
-#endif
-	c->networkLayer = tld;
-	return UA_NULL;
-}
-
-/** the tcp accept routine */
-void* NL_TCP_accept(NL_Connection* c) {
-	NL_data* tld = c->networkLayer;
-
-	if (tld->tld->maxConnections == -1 || tld->connections.size < tld->tld->maxConnections) {
-		// accept only if not max number of connections exceeded
-		struct sockaddr_in cli_addr;
-		socklen_t cli_len = sizeof(cli_addr);
-		DBG_VERBOSE(printf("NL_TCP_listen - enter accept\n"));
-		int newsockfd = accept(c->connectionHandle, (struct sockaddr *) &cli_addr, &cli_len);
-		DBG_VERBOSE(printf("NL_TCP_listen - leave accept\n"));
-		if (newsockfd < 0) {
-			DBG_ERR(printf("TL_TCP_listen - accept returns errno={%d,%s}\n",errno,strerror(errno)));
-			perror("ERROR on accept");
-		} else {
-			DBG_VERBOSE(printf("NL_TCP_listen - new connection on %d\n",newsockfd));
-			NL_Connection* cclient;
-			UA_Int32 retval = UA_SUCCESS;
-			retval |= UA_alloc((void**)&cclient,sizeof(NL_Connection));
-			NL_Connection_init(cclient, tld, newsockfd, NL_TCP_reader, (TL_Writer) NL_TCP_writer);
-#ifdef ENABLE_MULTITHREADING
-			pthread_create( &(cclient->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_readerThread, (void*) cclient);
-#else
-			UA_list_addPayloadToBack(&(tld->connections),cclient);
-			NL_TCP_SetNonBlocking(cclient->connectionHandle);
-#endif
-		}
-	} else {
-		// no action necessary to reject connection
-	}
-	return UA_NULL;
-}
-
-#ifdef ENABLE_MULTITHREADING
-void* NL_TCP_listenThread(NL_Connection* c) {
-	NL_data* tld = c->networkLayer;
-
-	DBG_VERBOSE(printf("NL_TCP_listenThread - enter listen\n"));
-	int retval = listen(c->connectionHandle, tld->tld->maxConnections);
-	DBG_VERBOSE(printf("NL_TCP_listenThread - leave listen, retval=%d\n", retval));
-	if (retval < 0) {
-		// TODO: Error handling
-		perror("NL_TCP_listen");
-		DBG_ERR(printf("NL_TCP_listen retval=%d, errno={%d,%s}\n", retval, errno, strerror(errno)));
-	} else {
-		do {
-			NL_TCP_accept(c);
-		}
-	} while (UA_TRUE);
-	UA_free(c);
-	pthread_exit(UA_NULL);
-}
-#endif
-
-
-UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
-	UA_Int32 retval = UA_SUCCESS;
-	// socket variables
-#ifdef WIN32
-	unsigned int newsockfd;
-#else
-	int newsockfd;
-#endif
-
-	struct sockaddr_in serv_addr;
-
-
-	// create socket for listening to incoming connections
-#ifdef WIN32
-	WORD wVersionRequested;
-	WSADATA wsaData;
-
-	/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
-	wVersionRequested = MAKEWORD(2, 2);
-
-	WSAStartup(wVersionRequested, &wsaData);
-	newsockfd = socket(PF_INET, SOCK_STREAM,0);
-	if (newsockfd == INVALID_SOCKET){
-		//UA_Int32 lasterror = WSAGetLastError();
-		printf("ERROR opening socket, code: %d\n",WSAGetLastError());
-#else
-	newsockfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (newsockfd < 0) {
-#endif
-		perror("ERROR opening socket");
-		retval = UA_ERROR;
-	}
-	else {
-		// set port number, options and bind
-		memset((void *)&serv_addr, sizeof(serv_addr), 1);
-		serv_addr.sin_family = AF_INET;
-		serv_addr.sin_addr.s_addr = INADDR_ANY;
-		serv_addr.sin_port = htons(port);
-
-		int  optval = 1;
-
-		if (setsockopt(newsockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
-			perror("setsockopt");
-			close(newsockfd);
-			retval = UA_ERROR;
-		}
-		else {
-			// bind to port
-			if (bind(newsockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
-				perror("ERROR on binding");
-				close(newsockfd);
-				retval = UA_ERROR;
-			}
-			else {
-				UA_String_copyprintf("opc.tcp://localhost:%d/", &(tld->endpointUrl), port);
-			}
-//#ifdef WIN32
-		}
-//#endif
-	}
-	// finally
-	if (retval == UA_SUCCESS) {
-		DBG_VERBOSE(printf("NL_TCP_init - new listener on %d\n",newsockfd));
-		NL_Connection* c;
-		UA_Int32 retval = UA_SUCCESS;
-		retval |= UA_alloc((void**)&c,sizeof(NL_Connection));
-		NL_Connection_init(c, tld, newsockfd, NL_TCP_accept, (TL_Writer) NL_TCP_writer);
-#ifdef MULTITHREADING
-		pthread_create( &(c->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_listenThread, (void*) c);
-#else
-		UA_list_addPayloadToBack(&(tld->connections),c);
-		NL_TCP_SetNonBlocking(c->connectionHandle);
-		listen(c->connectionHandle, tld->tld->maxConnections);
-#endif
-	}
-	return retval;
-}
-
-
-/** checks arguments and dispatches to worker or refuses to init */
-NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port) {
-	NL_data* nl = UA_NULL;
-	if (tlDesc->connectionType == NL_CONNECTIONTYPE_TCPV4 && tlDesc->encoding == NL_UA_ENCODING_BINARY) {
-		UA_alloc((void**)&nl, sizeof(NL_data));
-		nl->tld = tlDesc;
-		FD_ZERO(&(nl->readerHandles));
-		UA_list_init(&(nl->connections));
-		NL_TCP_init(nl, port);
-	}
-	return nl;
-}

+ 0 - 67
examples/networklayer.h

@@ -1,67 +0,0 @@
-#ifndef NETWORKLAYER_H_
-#define NETWORKLAYER_H_
-
-#include "ua_types.h"
-#include "ua_transport.h"
-#include "ua_transport_binary.h"
-#include "util/ua_list.h"
-
-#ifdef MULTITHREADING
-#include <pthread.h> // pthreadcreate, pthread_t
-#endif
-
-// fd_set, FD_ZERO, FD_SET
-#ifdef WIN32
-#include <winsock2.h>
-#else
-#include <sys/select.h> 
-#endif
-
-#define NL_MAXCONNECTIONS_DEFAULT 10
-
-enum NL_UA_ENCODING_enum {
-	NL_UA_ENCODING_BINARY = 0,
-	NL_UA_ENCODING_XML = 1,
-};
-
-enum NL_CONNECTIONTYPE_enum {
-	NL_CONNECTIONTYPE_TCPV4 = 0,
-	NL_CONNECTIONTYPE_TCPV6 = 1,
-};
-
-typedef struct NL_Description {
-	UA_Int32 encoding;
-	UA_Int32 connectionType;
-	UA_Int32 maxConnections;
-	TL_Buffer localConf;
-} NL_Description;
-
-extern NL_Description NL_Description_TcpBinary;
-
-typedef struct NL_data {
-	NL_Description* tld;
-	UA_String endpointUrl;
-	UA_list_List connections;
-	fd_set readerHandles;
-	int maxReaderHandle;
-} NL_data;
-
-struct NL_Connection;
-typedef void* (*NL_Reader)(struct NL_Connection *c);
-typedef struct NL_Connection {
-	UA_TL_Connection *connection;
-	UA_Int32 state;
-	UA_UInt32 connectionHandle;
-	NL_Reader reader;
-#ifdef MULTITHREADING
-	pthread_t readerThreadHandle;
-#endif
-	NL_data* networkLayer;
-} NL_Connection;
-
-NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port);
-UA_Int32 NL_Connection_close(UA_TL_Connection *connection);
-UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg, UA_Boolean *running);
-UA_Int32 NL_TCP_writer(UA_Int32 connectionHandle, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len);
-
-#endif /* NETWORKLAYER_H_ */

+ 325 - 0
examples/networklayer_tcp.c

@@ -0,0 +1,325 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <sys/types.h>
+#include <Windows.h>
+#include <ws2tcpip.h>
+#define CLOSESOCKET(S) closesocket(S)
+#define IOCTLSOCKET ioctlsocket
+#else
+#include <sys/select.h> 
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/socketvar.h>
+#include <unistd.h> // read, write, close
+#define CLOSESOCKET(S) close(S)
+#define IOCTLSOCKET ioctl
+#endif /* WIN32 */
+
+#include <stdlib.h> // exit
+#include <errno.h> // errno, EINTR
+#include <memory.h> // memset
+#include <fcntl.h> // fcntl
+
+#include "networklayer_tcp.h"
+#include "ua_transport.h"
+
+typedef struct TCPConnection {
+	UA_Int32 sockfd;
+	UA_Connection connection;
+} TCPConnection;
+
+struct NetworklayerTCP {
+	UA_ConnectionConfig localConf;
+	UA_UInt32 port;
+	fd_set fdset;
+	UA_Int32 serversockfd;
+	UA_Int32 highestfd;
+	UA_UInt32 connectionsSize;
+	TCPConnection *connections;
+};
+
+/** This structure is stored in the UA_Connection for callbacks into the
+	network layer. */
+typedef struct TCPConnectionHandle {
+	UA_Int32 sockfd;
+	NetworklayerTCP *layer;
+} TCPConnectionHandle;
+
+UA_Int32 NetworklayerTCP_new(NetworklayerTCP **newlayer, UA_ConnectionConfig localConf,
+							 UA_UInt32 port) {
+    UA_UInt32 retval = UA_SUCCESS;
+    retval |= UA_alloc((void**)newlayer, sizeof(NetworklayerTCP));
+    if(retval != UA_SUCCESS)
+        return UA_ERROR;
+	(*newlayer)->localConf = localConf;
+	(*newlayer)->port = port;
+	(*newlayer)->connectionsSize = 0;
+	(*newlayer)->connections = UA_NULL;
+	return UA_SUCCESS;
+}
+
+// copy the array of connections, but _loose_ one. This does not close the
+// actual socket.
+UA_Int32 NetworklayerTCP_remove(NetworklayerTCP *layer, UA_Int32 sockfd) {
+	UA_UInt32 index;
+	for(index = 0;index < layer->connectionsSize;index++) {
+		if(layer->connections[index].sockfd == sockfd)
+			break;
+	}
+	UA_Connection_deleteMembers(&layer->connections[index].connection);
+
+	TCPConnection *newconnections;
+	UA_alloc((void**)&newconnections, sizeof(TCPConnection) * (layer->connectionsSize-1));
+	UA_memcpy(newconnections, &layer->connections, sizeof(TCPConnection) * index);
+	UA_memcpy(&newconnections[index], &layer->connections[index+1],
+			  sizeof(TCPConnection) * (layer->connectionsSize - index - 1));
+	layer->connections = newconnections;
+	layer->connectionsSize--;
+	return UA_SUCCESS;
+}
+
+void NetworklayerTCP_delete(NetworklayerTCP *layer) {
+	for(UA_UInt32 index = 0;index < layer->connectionsSize;index++) {
+		shutdown(layer->connections[index].sockfd, 2);
+        UA_Connection_deleteMembers(&layer->connections[index].connection);
+		CLOSESOCKET(layer->connections[index].sockfd);
+	}
+	UA_free(layer->connections);
+	UA_free(layer);
+}
+
+/** Callback function */
+void closeCallback(TCPConnectionHandle *handle) {
+	shutdown(handle->sockfd,2);
+	CLOSESOCKET(handle->sockfd);
+	NetworklayerTCP_remove(handle->layer, handle->sockfd);
+}
+
+/** Callback function */
+UA_Int32 writeCallback(TCPConnectionHandle *handle, UA_ByteStringArray gather_buf) {
+	UA_UInt32 total_len = 0;
+	UA_UInt32 nWritten = 0;
+#ifdef WIN32
+	LPWSABUF buf = malloc(gather_buf.stringsSize * sizeof(WSABUF));
+	int result = 0;
+	for(UA_UInt32 i = 0; i<gather_buf.stringsSize; i++) {
+		buf[i].buf = gather_buf.strings[i].data;
+		buf[i].len = gather_buf.strings[i].length;
+		total_len += gather_buf.strings[i].length;
+	}
+	while (nWritten < total_len) {
+		UA_UInt32 n=0;
+		do {
+			result = WSASend(handle->sockfd, buf, gather_len , (LPDWORD)&n, 0, NULL, NULL);
+			if(result != 0)
+				printf("NL_TCP_Writer - Error WSASend, code: %d \n", WSAGetLastError());
+		} while (errno == EINTR);
+		nWritten += n;
+	}
+	free(buf);
+#else
+	struct iovec iov[gather_buf.stringsSize];
+	for(UA_UInt32 i=0;i<gather_buf.stringsSize;i++) {
+		iov[i].iov_base = gather_buf.strings[i].data;
+		iov[i].iov_len = gather_buf.strings[i].length;
+		total_len += gather_buf.strings[i].length;
+	}
+	struct msghdr message = {.msg_name = UA_NULL, .msg_namelen = 0, .msg_iov = iov,
+							 .msg_iovlen = gather_buf.stringsSize, .msg_control = UA_NULL,
+							 .msg_controllen = 0, .msg_flags = 0};
+	while (nWritten < total_len) {
+		UA_Int32 n = 0;
+		do {
+			n = sendmsg(handle->sockfd, &message, 0);
+		} while (n == -1L && errno == EINTR);
+
+		if (n >= 0) {
+			// TODO: handle incompletely send messages
+			/* nWritten += n; */
+			break;
+		} else {
+			// TODO: error handling
+			break;
+		}
+	}
+#endif
+	return UA_SUCCESS;
+}
+
+UA_Int32 NetworklayerTCP_add(NetworklayerTCP *layer, UA_Int32 newsockfd) {
+    layer->connectionsSize++;
+	layer->connections = realloc(layer->connections, sizeof(TCPConnection) * layer->connectionsSize);
+	TCPConnection *newconnection = &layer->connections[layer->connectionsSize-1];
+	newconnection->sockfd = newsockfd;
+
+	struct TCPConnectionHandle *callbackhandle;
+	UA_alloc((void**)&callbackhandle, sizeof(struct TCPConnectionHandle));
+	callbackhandle->layer = layer;
+	callbackhandle->sockfd = newsockfd;
+	UA_Connection_init(&newconnection->connection, layer->localConf, callbackhandle,
+					   (UA_Connection_closeCallback)closeCallback, (UA_Connection_writeCallback)writeCallback);
+	return UA_SUCCESS;
+}
+
+UA_Int32 setNonBlocking(int sockid) {
+#ifdef WIN32
+	u_long iMode = 1;
+	int opts = IOCTLSOCKET(sockid, FIONBIO, &iMode);
+	if (opts != NO_ERROR){
+		printf("ioctlsocket failed with error: %ld\n", opts);
+		return - 1;
+	}
+	return 0;
+#else
+	int opts = fcntl(sockid,F_GETFL);
+	if (opts < 0) {
+		perror("fcntl(F_GETFL)");
+		return -1;
+	}
+	opts = (opts | O_NONBLOCK);
+	if (fcntl(sockid,F_SETFL,opts) < 0) {
+		perror("fcntl(F_SETFL)");
+		return -1;
+	}
+	return 0;
+#endif
+}
+
+void readConnection(NetworklayerTCP *layer, UA_Server *server, TCPConnection *entry) {
+	UA_ByteString readBuffer;
+	UA_alloc((void**)&readBuffer.data, layer->localConf.recvBufferSize);
+#ifdef WIN32
+	readBuffer.length = recv(entry->sockfd, (char *)readBuffer.data,
+							 layer->localConf.recvBufferSize, 0);
+#else
+	readBuffer.length = read(entry->sockfd, readBuffer.data, layer->localConf.recvBufferSize);
+#endif
+	if (errno != 0) {
+		shutdown(entry->sockfd,2);
+		CLOSESOCKET(entry->sockfd);
+		NetworklayerTCP_remove(layer, entry->sockfd);
+	} else {
+		UA_Server_processBinaryMessage(server, &entry->connection, &readBuffer);
+	}
+	UA_ByteString_deleteMembers(&readBuffer);
+}
+
+void worksocks(NetworklayerTCP *layer, UA_Server *server, UA_UInt32 workamount) {
+	// accept new connections
+	if(FD_ISSET(layer->serversockfd,&layer->fdset)) {
+		struct sockaddr_in cli_addr;
+		socklen_t cli_len = sizeof(cli_addr);
+		int newsockfd = accept(layer->serversockfd, (struct sockaddr *) &cli_addr, &cli_len);
+		if (newsockfd >= 0) {
+			setNonBlocking(newsockfd);
+			NetworklayerTCP_add(layer, newsockfd);
+		}
+		workamount--;
+	}
+
+	// read from established sockets
+	for(UA_UInt32 i=0;i<layer->connectionsSize && workamount > 0;i++) {
+		if(FD_ISSET(layer->connections[i].sockfd, &layer->fdset)) {
+			readConnection(layer, server, &layer->connections[i]);
+			workamount--;
+		}
+	}
+}
+
+// after every select, reset the set of sockets we want to listen on
+void setFDSet(NetworklayerTCP *layer) {
+	FD_ZERO(&layer->fdset);
+	FD_SET(layer->serversockfd, &layer->fdset);
+	layer->highestfd = layer->serversockfd;
+	for(UA_UInt32 i=0;i<layer->connectionsSize;i++) {
+		FD_SET(layer->connections[i].sockfd, &layer->fdset);
+		if(layer->connections[i].sockfd > layer->highestfd)
+			layer->highestfd = layer->connections[i].sockfd;
+	}
+    layer->highestfd++;
+}
+
+UA_Int32 NetworkLayerTCP_run(NetworklayerTCP *layer, UA_Server *server, struct timeval tv,
+							   void(*worker)(UA_Server*), UA_Boolean *running) {
+#ifdef WIN32
+	WORD wVersionRequested;
+	WSADATA wsaData;
+	wVersionRequested = MAKEWORD(2, 2);
+	WSAStartup(wVersionRequested, &wsaData);
+	if((layer->serversockfd = socket(PF_INET, SOCK_STREAM,0)) == INVALID_SOCKET) {
+		printf("ERROR opening socket, code: %d\n", WSAGetLastError());
+		return UA_ERROR;
+	}
+#else
+    if((layer->serversockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+		perror("ERROR opening socket");
+		return UA_ERROR;
+	} 
+#endif
+	struct sockaddr_in serv_addr;
+	memset((void *)&serv_addr, sizeof(serv_addr), 1);
+	serv_addr.sin_family = AF_INET;
+	serv_addr.sin_addr.s_addr = INADDR_ANY;
+	serv_addr.sin_port = htons(layer->port);
+
+	int optval = 1;
+	if(setsockopt(layer->serversockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
+		perror("setsockopt");
+		close(layer->serversockfd);
+		return UA_ERROR;
+	}
+		
+	if(bind(layer->serversockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+		perror("binding");
+		close(layer->serversockfd);
+		return UA_ERROR;
+	}
+
+#define MAXBACKLOG 10
+	setNonBlocking(layer->serversockfd);
+	listen(layer->serversockfd, MAXBACKLOG);
+
+	while (*running) {
+		setFDSet(layer);
+		struct timeval tmptv = tv;
+		UA_Int32 resultsize = select(layer->highestfd, &layer->fdset, UA_NULL, UA_NULL, &tmptv);
+		if (resultsize <= 0) {
+#ifdef WIN32
+			UA_Int32 err = (result == SOCKET_ERROR) ? WSAGetLastError() : 0;
+			switch (err) {
+			case WSANOTINITIALISED:
+			case WSAEFAULT:
+			case WSAENETDOWN:
+			case WSAEINVAL:
+			case WSAEINTR:
+			case WSAEINPROGRESS:
+			case WSAENOTSOCK:
+#else
+			UA_Int32 err = errno;
+			switch (err) {
+			case EBADF:
+			case EINTR:
+			case EINVAL:
+#endif
+				// todo: handle errors
+				printf("UA_Stack_msgLoop - result=%d, errno={%d,%s}\n", resultsize, errno, strerror(errno));
+				break;
+			default:
+				// timeout
+				worker(server);
+			}
+		} else { // activity on listener or client socket
+			worksocks(layer, server, resultsize);
+			worker(server);
+		}
+	}
+#ifdef WIN32
+	WSACleanup();
+#endif
+	return UA_SUCCESS;
+}

+ 25 - 0
examples/networklayer_tcp.h

@@ -0,0 +1,25 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
+#ifndef NETWORKLAYERTCP_H_
+#define NETWORKLAYERTCP_H_
+
+#include <time.h>
+#include "server/ua_server.h"
+
+struct NetworklayerTCP;
+typedef struct NetworklayerTCP NetworklayerTCP;
+
+#define BINARYCONNECTION_PROTOCOL_VERSION  0
+#define BINARYCONNECTION_MAX_CHUNK_COUNT 1
+#define BINARYCONNECTION_MAX_MESSAGE_SIZE 8192
+
+UA_Int32 NetworklayerTCP_new(NetworklayerTCP **newlayer, UA_ConnectionConfig localConf,
+							 UA_UInt32 port);
+void NetworklayerTCP_delete(NetworklayerTCP *layer);
+UA_Int32 NetworkLayerTCP_run(NetworklayerTCP *layer, UA_Server *server, struct timeval tv,
+							   void(*worker)(UA_Server*), UA_Boolean *running);
+
+#endif /* NETWORKLAYERTCP_H_ */

+ 46 - 33
examples/opcuaServer.c

@@ -1,22 +1,23 @@
-#include <stdio.h>
-#include <stdlib.h>
+/*
+ * 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 <stdio.h>
 #ifndef WIN32
 #include <sys/mman.h>
 #include <sys/wait.h>
 #include <unistd.h>
 #endif
 #include <sys/types.h>
-#include <time.h>
+#include <sys/time.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <errno.h> // errno, EINTR
 
+#include "server/ua_server.h"
 #include "logger_stdout.h"
-#include "networklayer.h"
-#include "ua_application.h"
-#include "ua_channel_manager.h"
-#include "ua_session_manager.h"
-#include "ua_server.h"
+#include "networklayer_tcp.h"
 
 UA_Boolean running = UA_TRUE;
 
@@ -24,37 +25,49 @@ void stopHandler(int sign) {
 	running = UA_FALSE;
 }
 
-UA_Int32 serverCallback(void * arg) {
-	char *name = (char *) arg;
-	printf("%s does whatever servers do\n",name);
+void serverCallback(UA_Server *server) {
+	printf("does whatever servers do\n");
+}
+
+UA_ByteString loadCertificate() {
+    UA_ByteString certificate = UA_STRING_NULL;
+	FILE *fp = UA_NULL;
+	//FIXME: a potiential bug of locating the certificate, we need to get the path from the server's config
+	fp=fopen("localhost.der", "rb");
 
-	Namespace* ns0 = (Namespace*)UA_indexedList_find(appMockup.namespaces, 0)->payload;
-	UA_Int32 retval;
-	const UA_Node * node;
-	UA_ExpandedNodeId serverStatusNodeId; NS0EXPANDEDNODEID(serverStatusNodeId, 2256);
-	retval = Namespace_get(ns0, &serverStatusNodeId.nodeId, &node);
-	if(retval == UA_SUCCESS){
-		((UA_ServerStatusDataType*)(((UA_VariableNode*)node)->value.data))->currentTime = UA_DateTime_now();
-	}
+	if(!fp) {
+        errno = 0; // otherwise we think sth went wrong on the tcp socket level
+        return certificate;
+    }
 
-	return UA_SUCCESS;
-}
+    fseek(fp, 0, SEEK_END);
+    certificate.length = ftell(fp);
+    UA_alloc((void**)&certificate.data, certificate.length*sizeof(UA_Byte));
+
+    fseek(fp, 0, SEEK_SET);
+    if(fread(certificate.data, sizeof(UA_Byte), certificate.length, fp) < (size_t)certificate.length)
+        UA_ByteString_deleteMembers(&certificate); // error reading the cert
+    fclose(fp);
 
+    return certificate;
+}
 
 int main(int argc, char** argv) {
-	UA_Int32 retval;
-	/* gets called at ctrl-c */
-	signal(SIGINT, stopHandler);
-	
-	appMockup_init();
-	NL_data* nl = NL_init(&NL_Description_TcpBinary, 16664);
+	signal(SIGINT, stopHandler); /* catches ctrl-c */
+
+	UA_Server server;
 	UA_String endpointUrl;
 	UA_String_copycstring("no endpoint url",&endpointUrl);
-	SL_ChannelManager_init(10,36000,244,2,&endpointUrl);
-	UA_SessionManager_init(10,3600000,25);
-	struct timeval tv = {1, 0}; // 1 second
-
-	retval = NL_msgLoop(nl, &tv, serverCallback, argv[0], &running);
-
+	UA_Server_init(&server, &endpointUrl);
+	Logger_Stdout_init(&server.logger);
+    server.serverCertificate = loadCertificate();
+	
+	NetworklayerTCP* nl;
+	NetworklayerTCP_new(&nl, UA_ConnectionConfig_standard, 16664);
+	struct timeval callback_interval = {1, 0}; // 1 second
+	UA_Int32 retval = NetworkLayerTCP_run(nl, &server, callback_interval,
+										  serverCallback, &running);
+	NetworklayerTCP_delete(nl);
+	UA_Server_deleteMembers(&server);
 	return retval == UA_SUCCESS ? 0 : retval;
 }

+ 0 - 156
examples/opcuaServerACPLT.c

@@ -1,156 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-
-#include "ua_types.h"
-#include "ua_transport.h"
-#include "ua_transport_binary.h"
-#include "networklayer.h"
-#include "ua_stack_channel_manager.h"
-#include "ua_transport_connection.h"
-#include "ua_transport_connection_manager.h"
-#include "ua_stack_session_manager.h"
-
-#ifdef LINUX
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/socketvar.h>
-#include <unistd.h>
-
-void server_run();
-
-#endif
-
-#define PORT 16664
-#define MAXMSG 512
-#define BUFFER_SIZE 8192
-
-
-
-int main(void) {
-
-#ifdef LINUX
-	printf("Starting open62541 demo server on port %d\n", PORT);
-	server_run();
-#endif
-
-	return EXIT_SUCCESS;
-}
-
-#ifdef LINUX
-void tmpTestFunction()
-{
-
-}
-void server_run() {
-	//just for debugging
-#ifdef DEBUG
-
-
-	tmpTestFunction();
-#endif
-//	UA_TL_Connection connection;// = UA_NULL;
-	TL_Buffer localBuffers;
-	UA_Int32 connectionState;
-	//connection.connectionState = CONNECTIONSTATE_CLOSED;
-	//connection.writerCallback = (TL_Writer) NL_TCP_writer;
-	localBuffers.maxChunkCount = 1;
-	localBuffers.maxMessageSize = BUFFER_SIZE;
-	localBuffers.protocolVersion = 0;
-	localBuffers.recvBufferSize = BUFFER_SIZE;
-	localBuffers.recvBufferSize = BUFFER_SIZE;
-
-	/*init secure Channel manager, which handles more than one channel */
-	UA_String endpointUrl;
-	UA_String_copycstring("open62541.org",&endpointUrl);
-	SL_ChannelManager_init(2,3600000, 873, 23, &endpointUrl);
-	UA_SessionManager_init(2,300000,5);
-
-	UA_ByteString slMessage = { -1, UA_NULL };
-
-	int optval = 1;
-	int sockfd, newsockfd, portno, clilen;
-	char buffer[BUFFER_SIZE];
-	struct sockaddr_in serv_addr, cli_addr;
-	int n;
-
-	/* First call to socket() function */
-	sockfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (sockfd < 0) {
-		perror("ERROR opening socket");
-		exit(1);
-	}
-
-	/* Initialize socket structure */
-    memset((void *) &serv_addr, 0, sizeof(serv_addr));
-	portno = PORT;
-	serv_addr.sin_family = AF_INET;
-	serv_addr.sin_addr.s_addr = INADDR_ANY;
-	serv_addr.sin_port = htons(portno);
-
-	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1) {
-		perror("setsockopt");
-		exit(1);
-	}
-
-	/* Now bind the host address using bind() call.*/
-	if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
-		perror("ERROR on binding");
-		exit(1);
-	}
-
-	/* Now start listening for the clients, here process will
-	 * go in sleep mode and will wait for the incoming connection
-	 */
-	UA_TL_Connection tmpConnection;
-
-	while (listen(sockfd, 5) != -1) {
-		clilen = sizeof(cli_addr);
-		/* Accept actual connection from the client */
-		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen);
-		if (newsockfd < 0) {
-			perror("ERROR on accept");
-			exit(1);
-		}
-
-		UA_TL_ConnectionManager_getConnectionByHandle(newsockfd, &tmpConnection);
-		if(tmpConnection == UA_NULL)
-		{
-			UA_TL_Connection_new(&tmpConnection, localBuffers, (TL_Writer)NL_TCP_writer,NL_Connection_close,newsockfd,UA_NULL);
-		}
-
-		UA_TL_Connection_getState(tmpConnection, &connectionState);
-
-		printf("server_run - connection accepted: %i, state: %i\n", newsockfd, connectionState);
-
-		UA_TL_Connection_bind(tmpConnection, newsockfd);
-
-		do {
-            memset(buffer, 0, BUFFER_SIZE);
-			n = read(newsockfd, buffer, BUFFER_SIZE);
-			if (n > 0) {
-                slMessage.data = (UA_Byte*) buffer;
-				slMessage.length = n;
-#ifdef DEBUG
-				UA_ByteString_printx("server_run - received=",&slMessage);
-#endif
-				TL_Process(tmpConnection, &slMessage);
-			} else if (n <= 0) {
-				perror("ERROR reading from socket1");
-		//		exit(1);
-			}
-			UA_TL_Connection_getState(tmpConnection, &connectionState);
-		} while(connectionState != CONNECTIONSTATE_CLOSE);
-		shutdown(newsockfd,2);
-		close(newsockfd);
-		UA_TL_ConnectionManager_getConnectionByHandle(newsockfd, &tmpConnection);
-		UA_TL_ConnectionManager_removeConnection(tmpConnection);
-	}
-	shutdown(sockfd,2);
-	close(sockfd);
-}
-
-
-#endif

+ 0 - 51
examples/opcuaServerMT.c

@@ -1,51 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "networklayer.h"
-#include "ua_application.h"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <time.h>
-#include <fcntl.h>
-
-#include <signal.h>
-
-UA_Boolean running = UA_TRUE;
-
-void stopHandler(int sign) {
-	running = UA_FALSE;
-}
-
-UA_Int32 serverCallback(void * arg) {
-	char *name = (char *) arg;
-	printf("%s does whatever servers do\n",name);
-
-	Namespace* ns0 = (Namespace*)UA_indexedList_find(appMockup.namespaces, 0)->payload;
-	UA_Int32 retval;
-	const UA_Node * node;
-	UA_ExpandedNodeId serverStatusNodeId = NS0EXPANDEDNODEID(2256);
-	retval = Namespace_get(ns0, &serverStatusNodeId.nodeId, &node);
-	if(retval == UA_SUCCESS){
-		((UA_ServerStatusDataType*)(((UA_VariableNode*)node)->value.data))->currentTime = UA_DateTime_now();
-	}
-
-	return UA_SUCCESS;
-}
-
-int main(int argc, char** argv) {
-
-	/* gets called at ctrl-c */
-	signal(SIGINT, stopHandler);
-	
-	appMockup_init();
-	NL_data* nl = NL_init(&NL_Description_TcpBinary, 16664);
-
-	struct timeval tv = {1, 0}; // 1 second
-  	NL_msgLoop(nl, &tv, serverCallback, argv[0], &running);
-
-	printf("Shutting down after Ctrl-C.\n");
-	exit(0);
-}

+ 5 - 0
examples/opcuaServerMini.c

@@ -1,3 +1,8 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
 /**************************************************************
  * opcuaServerMini is a pathologically unstructured bare bone
  * implementation of the 62541 communications w/o any structures

+ 8 - 8
schema/Custom.Opc.Ua.Transport.bsd

@@ -9,16 +9,16 @@
 
   <opc:Import Namespace="http://opcfoundation.org/BinarySchema/" />
 
-<!-- 	Types within the Stack Begin  -->
+<!-- Transport types begin  -->
 
-   <opc:StructuredType Name="OPCUATcpMessageHeader">
+   <opc:StructuredType Name="TcpMessageHeader">
     <opc:Documentation>TCP Header</opc:Documentation>
-    <opc:Field Name="MessageType" TypeName="opc:UInt32" />
+    <opc:Field Name="MessageType" TypeName="opc:MessageType" /> <!-- The MessageType type is custom and implemented by hand -->
     <opc:Field Name="IsFinal" TypeName="opc:Byte" />
     <opc:Field Name="MessageSize" TypeName="opc:UInt32" />
   </opc:StructuredType>
   
-   <opc:StructuredType Name="OPCUATcpHelloMessage">
+   <opc:StructuredType Name="TcpHelloMessage">
     <opc:Documentation>Hello Message</opc:Documentation>
     <opc:Field Name="ProtocolVersion" TypeName="opc:UInt32" />
     <opc:Field Name="ReceiveBufferSize" TypeName="opc:UInt32" />
@@ -28,7 +28,7 @@
     <opc:Field Name="EndpointUrl" TypeName="opc:String" />
   </opc:StructuredType>
   
-   <opc:StructuredType Name="OPCUATcpAcknowledgeMessage">
+   <opc:StructuredType Name="TcpAcknowledgeMessage">
     <opc:Documentation>Acknowledge Message</opc:Documentation>
     <opc:Field Name="ProtocolVersion" TypeName="opc:UInt32" />
     <opc:Field Name="ReceiveBufferSize" TypeName="opc:UInt32" />
@@ -37,10 +37,9 @@
 	<opc:Field Name="MaxChunkCount" TypeName="opc:UInt32" />
   </opc:StructuredType>
   
-  
   <opc:StructuredType Name="SecureConversationMessageHeader">
     <opc:Documentation>Secure Layer Sequence Header</opc:Documentation>
-    <opc:Field Name="MessageHeader" TypeName="opc:OPCUATcpMessageHeader" />
+    <opc:Field Name="MessageHeader" TypeName="opc:TcpMessageHeader" />
     <opc:Field Name="SecureChannelId" TypeName="opc:UInt32" />
   </opc:StructuredType>
   
@@ -75,5 +74,6 @@
     <opc:Field Name="Reason" TypeName="opc:String" />
   </opc:StructuredType>
  
-<!-- Types within the Stack End -->
+<!-- Transport types end -->
+
 </opc:TypeDictionary>

examples/generateSam.c → src/ongoing/generateSam.c


src/server/ua_namespace_xml.c → src/ongoing/ua_namespace_xml.c


src/server/ua_namespace_xml.h → src/ongoing/ua_namespace_xml.h


src/ua_types_encoding_json.c → src/ongoing/ua_types_encoding_json.c


src/ua_types_encoding_json.h → src/ongoing/ua_types_encoding_json.h


src/ua_types_encoding_xml.c → src/ongoing/ua_types_encoding_xml.c


src/ua_types_encoding_xml.h → src/ongoing/ua_types_encoding_xml.h


src/ua_xml.c → src/ongoing/ua_xml.c


src/ua_xml.h → src/ongoing/ua_xml.h


examples/xml2ns0.c → src/ongoing/xml2ns0.c


+ 0 - 571
src/server/ua_application.c

@@ -1,571 +0,0 @@
-#include "ua_application.h"
-#include "ua_namespace.h"
-#include "ua_services_internal.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-UA_indexedList_List nsMockup;
-Application appMockup = {
-		( UA_ApplicationDescription*) UA_NULL,
-		&nsMockup
-};
-
-UA_Node* create_node_ns0(UA_Int32 class, UA_Int32 nodeClass, UA_Int32 const id, char const * qn, char const * dn, char const * desc) {
-	UA_Node* n; UA_.types[class].new((void **)&n);
-	n->nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
-	n->nodeId.namespaceIndex = 0;
-	n->nodeId.identifier.numeric = id;
-	UA_String_copycstring(qn,&(n->browseName.name));
-	UA_String_copycstring(dn,&n->displayName.text);
-	UA_String_copycstring(desc,&n->description.text);
-	n->nodeClass = nodeClass;
-	return n;
-}
-
-void appMockup_init() {
-	//fill the UA_borrowed_ table that has been declaed in ua_namespace.c
-	for(UA_Int32 i=0;i<SIZE_UA_VTABLE;i++){
-		UA_borrowed_.types[i] = UA_.types[i];
-		UA_borrowed_.types[i].delete=(UA_Int32(*)(void *))phantom_delete;
-		UA_borrowed_.types[i].deleteMembers=(UA_Int32(*)(void *))phantom_delete;
-	}
-
-	// create namespaces
-	// TODO: A table that maps the namespaceUris to Ids
-	Namespace* ns0;
-	Namespace_new(&ns0, 0); //C2UA_STRING("http://opcfoundation.org/UA/"));
-
-	Namespace* local;
-	Namespace_new(&local, 1); //C2UA_STRING("http://localhost:16664/open62541/"));
-
-	// add to list of namespaces
-	UA_indexedList_init(appMockup.namespaces);
-	UA_indexedList_addValueToFront(appMockup.namespaces,0,ns0);
-	UA_indexedList_addValueToFront(appMockup.namespaces,1,local);
-
-	/**************/
-	/* References */
-	/**************/
-
-	// ReferenceType Ids
-	UA_NodeId RefTypeId_References = NS0NODEID(31);
-	UA_NodeId RefTypeId_NonHierarchicalReferences = NS0NODEID(32);
-	UA_NodeId RefTypeId_HierarchicalReferences = NS0NODEID(33);
-	UA_NodeId RefTypeId_HasChild = NS0NODEID(34);
-	UA_NodeId RefTypeId_Organizes = NS0NODEID(35);
-	UA_NodeId RefTypeId_HasEventSource = NS0NODEID(36);
-	UA_NodeId RefTypeId_HasModellingRule = NS0NODEID(37);
-	UA_NodeId RefTypeId_HasEncoding = NS0NODEID(38);
-	UA_NodeId RefTypeId_HasDescription = NS0NODEID(39);
-	UA_NodeId RefTypeId_HasTypeDefinition = NS0NODEID(40);
-	UA_NodeId RefTypeId_GeneratesEvent = NS0NODEID(41);
-	UA_NodeId RefTypeId_Aggregates = NS0NODEID(44);
-	UA_NodeId RefTypeId_HasSubtype = NS0NODEID(45);
-	UA_NodeId RefTypeId_HasProperty = NS0NODEID(46);
-	UA_NodeId RefTypeId_HasComponent = NS0NODEID(47);
-	UA_NodeId RefTypeId_HasNotifier = NS0NODEID(48);
-	UA_NodeId RefTypeId_HasOrderedComponent = NS0NODEID(49);
-	UA_NodeId RefTypeId_HasModelParent = NS0NODEID(50);
-	UA_NodeId RefTypeId_FromState = NS0NODEID(51);
-	UA_NodeId RefTypeId_ToState = NS0NODEID(52);
-	UA_NodeId RefTypeId_HasCause = NS0NODEID(53);
-	UA_NodeId RefTypeId_HasEffect = NS0NODEID(54);
-	UA_NodeId RefTypeId_HasHistoricalConfiguration = NS0NODEID(56);
-
-#define ADDINVERSEREFERENCE(NODE,REFTYPE,TARGET_NODEID) \
-	static struct UA_ReferenceNode NODE##ReferenceNode; \
-	UA_ReferenceNode_init(&NODE##ReferenceNode); \
-	NODE##ReferenceNode.referenceTypeId = REFTYPE; \
-	NODE##ReferenceNode.isInverse = UA_TRUE; \
-	NODE##ReferenceNode.targetId.nodeId = TARGET_NODEID; \
-	NODE##ReferenceNode.targetId.namespaceUri = UA_STRING_NULL; \
-	NODE##ReferenceNode.targetId.serverIndex = 0; \
-	AddReference((UA_Node*)NODE, &NODE##ReferenceNode, ns0)
-
-	UA_ReferenceTypeNode *references;
-	UA_ReferenceTypeNode_new(&references);
-	references->nodeId = RefTypeId_References;
-	references->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(references->browseName, "References");
-	UA_LOCALIZEDTEXT_STATIC(references->displayName, "References");
-	UA_LOCALIZEDTEXT_STATIC(references->description, "References");
-	references->isAbstract = UA_TRUE;
-	references->symmetric = UA_TRUE;
-	Namespace_insert(ns0,(UA_Node**)&references, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hierarchicalreferences;
-	UA_ReferenceTypeNode_new(&hierarchicalreferences);
-	hierarchicalreferences->nodeId = RefTypeId_HierarchicalReferences;
-	hierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hierarchicalreferences->browseName, "HierarchicalReferences");
-	UA_LOCALIZEDTEXT_STATIC(hierarchicalreferences->displayName, "HierarchicalReferences");
-	UA_LOCALIZEDTEXT_STATIC(hierarchicalreferences->description, "HierarchicalReferences");
-	hierarchicalreferences->isAbstract = UA_TRUE;
-	hierarchicalreferences->symmetric = UA_FALSE;
-	ADDINVERSEREFERENCE(hierarchicalreferences, RefTypeId_HasSubtype, RefTypeId_References);
-	Namespace_insert(ns0,(UA_Node**)&hierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *nonhierarchicalreferences;
-	UA_ReferenceTypeNode_new(&nonhierarchicalreferences);
-	nonhierarchicalreferences->nodeId = RefTypeId_NonHierarchicalReferences;
-	nonhierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(nonhierarchicalreferences->browseName, "NonHierarchicalReferences");
-	UA_LOCALIZEDTEXT_STATIC(nonhierarchicalreferences->displayName, "NonHierarchicalReferences");
-	UA_LOCALIZEDTEXT_STATIC(nonhierarchicalreferences->description, "NonHierarchicalReferences");
-	nonhierarchicalreferences->isAbstract = UA_TRUE;
-	nonhierarchicalreferences->symmetric = UA_FALSE;
-	ADDINVERSEREFERENCE(nonhierarchicalreferences, RefTypeId_HasSubtype, RefTypeId_References);
-	Namespace_insert(ns0,(UA_Node**)&nonhierarchicalreferences, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *haschild;
-	UA_ReferenceTypeNode_new(&haschild);
-	haschild->nodeId = RefTypeId_HasChild;
-	haschild->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(haschild->browseName, "HasChild");
-	UA_LOCALIZEDTEXT_STATIC(haschild->displayName, "HasChild");
-	UA_LOCALIZEDTEXT_STATIC(haschild->description, "HasChild");
-	haschild->isAbstract = UA_TRUE;
-	haschild->symmetric = UA_FALSE;
-	ADDINVERSEREFERENCE(haschild, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&haschild, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *organizes;
-	UA_ReferenceTypeNode_new(&organizes);
-	organizes->nodeId = RefTypeId_Organizes;
-	organizes->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(organizes->browseName, "Organizes");
-	UA_LOCALIZEDTEXT_STATIC(organizes->displayName, "Organizes");
-	UA_LOCALIZEDTEXT_STATIC(organizes->description, "Organizes");
-	organizes->isAbstract = UA_FALSE;
-	organizes->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(organizes->inverseName, "OrganizedBy");
-	ADDINVERSEREFERENCE(organizes, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&organizes, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *haseventsource;
-	UA_ReferenceTypeNode_new(&haseventsource);
-	haseventsource->nodeId = RefTypeId_HasEventSource;
-	haseventsource->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(haseventsource->browseName, "HasEventSource");
-	UA_LOCALIZEDTEXT_STATIC(haseventsource->displayName, "HasEventSource");
-	UA_LOCALIZEDTEXT_STATIC(haseventsource->description, "HasEventSource");
-	haseventsource->isAbstract = UA_FALSE;
-	haseventsource->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(haseventsource->inverseName, "EventSourceOf");
-	ADDINVERSEREFERENCE(haseventsource, RefTypeId_HasSubtype, RefTypeId_HierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&haseventsource, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasmodellingrule;
-	UA_ReferenceTypeNode_new(&hasmodellingrule);
-	hasmodellingrule->nodeId = RefTypeId_HasModellingRule;
-	hasmodellingrule->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasmodellingrule->browseName, "HasModellingRule");
-	UA_LOCALIZEDTEXT_STATIC(hasmodellingrule->displayName, "HasModellingRule");
-	UA_LOCALIZEDTEXT_STATIC(hasmodellingrule->description, "HasModellingRule");
-	hasmodellingrule->isAbstract = UA_FALSE;
-	hasmodellingrule->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasmodellingrule->inverseName, "ModellingRuleOf");
-	ADDINVERSEREFERENCE(hasmodellingrule, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hasmodellingrule, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasencoding;
-	UA_ReferenceTypeNode_new(&hasencoding);
-	hasencoding->nodeId = RefTypeId_HasEncoding;
-	hasencoding->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasencoding->browseName, "HasEncoding");
-	UA_LOCALIZEDTEXT_STATIC(hasencoding->displayName, "HasEncoding");
-	UA_LOCALIZEDTEXT_STATIC(hasencoding->description, "HasEncoding");
-	hasencoding->isAbstract = UA_FALSE;
-	hasencoding->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasencoding->inverseName, "EncodingOf");
-	ADDINVERSEREFERENCE(hasencoding, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hasencoding, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasdescription;
-	UA_ReferenceTypeNode_new(&hasdescription);
-	hasdescription->nodeId = RefTypeId_HasDescription;
-	hasdescription->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasdescription->browseName, "HasDescription");
-	UA_LOCALIZEDTEXT_STATIC(hasdescription->displayName, "HasDescription");
-	UA_LOCALIZEDTEXT_STATIC(hasdescription->description, "HasDescription");
-	hasdescription->isAbstract = UA_FALSE;
-	hasdescription->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasdescription->inverseName, "DescriptionOf");
-	ADDINVERSEREFERENCE(hasdescription, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hasdescription, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hastypedefinition;
-	UA_ReferenceTypeNode_new(&hastypedefinition);
-	hastypedefinition->nodeId = RefTypeId_HasTypeDefinition;
-	hastypedefinition->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hastypedefinition->browseName, "HasTypeDefinition");
-	UA_LOCALIZEDTEXT_STATIC(hastypedefinition->displayName, "HasTypeDefinition");
-	UA_LOCALIZEDTEXT_STATIC(hastypedefinition->description, "HasTypeDefinition");
-	hastypedefinition->isAbstract = UA_FALSE;
-	hastypedefinition->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hastypedefinition->inverseName, "TypeDefinitionOf");
-	ADDINVERSEREFERENCE(hastypedefinition, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hastypedefinition, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *generatesevent;
-	UA_ReferenceTypeNode_new(&generatesevent);
-	generatesevent->nodeId = RefTypeId_GeneratesEvent;
-	generatesevent->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(generatesevent->browseName, "GeneratesEvent");
-	UA_LOCALIZEDTEXT_STATIC(generatesevent->displayName, "GeneratesEvent");
-	UA_LOCALIZEDTEXT_STATIC(generatesevent->description, "GeneratesEvent");
-	generatesevent->isAbstract = UA_FALSE;
-	generatesevent->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(generatesevent->inverseName, "GeneratedBy");
-	ADDINVERSEREFERENCE(generatesevent, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&generatesevent, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *aggregates;
-	UA_ReferenceTypeNode_new(&aggregates);
-	aggregates->nodeId = RefTypeId_Aggregates;
-	aggregates->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(aggregates->browseName, "Aggregates");
-	UA_LOCALIZEDTEXT_STATIC(aggregates->displayName, "Aggregates");
-	UA_LOCALIZEDTEXT_STATIC(aggregates->description, "Aggregates");
-	aggregates->isAbstract = UA_TRUE;
-	aggregates->symmetric = UA_FALSE;
-	ADDINVERSEREFERENCE(aggregates, RefTypeId_HasSubtype, RefTypeId_HasChild);
-	Namespace_insert(ns0,(UA_Node**)&aggregates, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hassubtype;
-	UA_ReferenceTypeNode_new(&hassubtype);
-	hassubtype->nodeId = RefTypeId_HasSubtype;
-	hassubtype->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hassubtype->browseName, "HasSubtype");
-	UA_LOCALIZEDTEXT_STATIC(hassubtype->displayName, "HasSubtype");
-	UA_LOCALIZEDTEXT_STATIC(hassubtype->description, "HasSubtype");
-	hassubtype->isAbstract = UA_FALSE;
-	hassubtype->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hassubtype->inverseName, "SubtypeOf");
-	ADDINVERSEREFERENCE(hassubtype, RefTypeId_HasSubtype, RefTypeId_HasChild);
-	Namespace_insert(ns0,(UA_Node**)&hassubtype, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasproperty;
-	UA_ReferenceTypeNode_new(&hasproperty);
-	hasproperty->nodeId = RefTypeId_HasProperty;
-	hasproperty->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasproperty->browseName, "HasProperty");
-	UA_LOCALIZEDTEXT_STATIC(hasproperty->displayName, "HasProperty");
-	UA_LOCALIZEDTEXT_STATIC(hasproperty->description, "HasProperty");
-	hasproperty->isAbstract = UA_FALSE;
-	hasproperty->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasproperty->inverseName, "PropertyOf");
-	ADDINVERSEREFERENCE(hasproperty, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-	Namespace_insert(ns0,(UA_Node**)&hasproperty, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hascomponent;
-	UA_ReferenceTypeNode_new(&hascomponent);
-	hascomponent->nodeId = RefTypeId_HasComponent;
-	hascomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hascomponent->browseName, "HasComponent");
-	UA_LOCALIZEDTEXT_STATIC(hascomponent->displayName, "HasComponent");
-	UA_LOCALIZEDTEXT_STATIC(hascomponent->description, "HasComponent");
-	hascomponent->isAbstract = UA_FALSE;
-	hascomponent->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hascomponent->inverseName, "ComponentOf");
-	ADDINVERSEREFERENCE(hascomponent, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-	Namespace_insert(ns0,(UA_Node**)&hascomponent, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasnotifier;
-	UA_ReferenceTypeNode_new(&hasnotifier);
-	hasnotifier->nodeId = RefTypeId_HasNotifier;
-	hasnotifier->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasnotifier->browseName, "HasNotifier");
-	UA_LOCALIZEDTEXT_STATIC(hasnotifier->displayName, "HasNotifier");
-	UA_LOCALIZEDTEXT_STATIC(hasnotifier->description, "HasNotifier");
-	hasnotifier->isAbstract = UA_FALSE;
-	hasnotifier->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasnotifier->inverseName, "NotifierOf");
-	ADDINVERSEREFERENCE(hasnotifier, RefTypeId_HasSubtype, RefTypeId_HasEventSource);
-	Namespace_insert(ns0,(UA_Node**)&hasnotifier, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasorderedcomponent;
-	UA_ReferenceTypeNode_new(&hasorderedcomponent);
-	hasorderedcomponent->nodeId = RefTypeId_HasOrderedComponent;
-	hasorderedcomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasorderedcomponent->browseName, "HasOrderedComponent");
-	UA_LOCALIZEDTEXT_STATIC(hasorderedcomponent->displayName, "HasOrderedComponent");
-	UA_LOCALIZEDTEXT_STATIC(hasorderedcomponent->description, "HasOrderedComponent");
-	hasorderedcomponent->isAbstract = UA_FALSE;
-	hasorderedcomponent->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasorderedcomponent->inverseName, "OrderedComponentOf");
-	ADDINVERSEREFERENCE(hasorderedcomponent, RefTypeId_HasSubtype, RefTypeId_HasComponent);
-	Namespace_insert(ns0,(UA_Node**)&hasorderedcomponent, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hasmodelparent;
-	UA_ReferenceTypeNode_new(&hasmodelparent);
-	hasmodelparent->nodeId = RefTypeId_HasModelParent;
-	hasmodelparent->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hasmodelparent->browseName, "HasModelParent");
-	UA_LOCALIZEDTEXT_STATIC(hasmodelparent->displayName, "HasModelParent");
-	UA_LOCALIZEDTEXT_STATIC(hasmodelparent->description, "HasModelParent");
-	hasmodelparent->isAbstract = UA_FALSE;
-	hasmodelparent->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hasmodelparent->inverseName, "ModelParentOf");
-	ADDINVERSEREFERENCE(hasmodelparent, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hasmodelparent, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *fromstate;
-	UA_ReferenceTypeNode_new(&fromstate);
-	fromstate->nodeId = RefTypeId_FromState;
-	fromstate->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(fromstate->browseName, "FromState");
-	UA_LOCALIZEDTEXT_STATIC(fromstate->displayName, "FromState");
-	UA_LOCALIZEDTEXT_STATIC(fromstate->description, "FromState");
-	fromstate->isAbstract = UA_FALSE;
-	fromstate->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(fromstate->inverseName, "ToTransition");
-	ADDINVERSEREFERENCE(fromstate, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&fromstate, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *tostate;
-	UA_ReferenceTypeNode_new(&tostate);
-	tostate->nodeId = RefTypeId_ToState;
-	tostate->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(tostate->browseName, "ToState");
-	UA_LOCALIZEDTEXT_STATIC(tostate->displayName, "ToState");
-	UA_LOCALIZEDTEXT_STATIC(tostate->description, "ToState");
-	tostate->isAbstract = UA_FALSE;
-	tostate->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(tostate->inverseName, "FromTransition");
-	ADDINVERSEREFERENCE(tostate, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&tostate, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hascause;
-	UA_ReferenceTypeNode_new(&hascause);
-	hascause->nodeId = RefTypeId_HasCause;
-	hascause->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hascause->browseName, "HasCause");
-	UA_LOCALIZEDTEXT_STATIC(hascause->displayName, "HasCause");
-	UA_LOCALIZEDTEXT_STATIC(hascause->description, "HasCause");
-	hascause->isAbstract = UA_FALSE;
-	hascause->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hascause->inverseName, "MayBeCausedBy");
-	ADDINVERSEREFERENCE(hascause, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&hascause, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *haseffect;
-	UA_ReferenceTypeNode_new(&haseffect);
-	haseffect->nodeId = RefTypeId_HasEffect;
-	haseffect->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(haseffect->browseName, "HasEffect");
-	UA_LOCALIZEDTEXT_STATIC(haseffect->displayName, "HasEffect");
-	UA_LOCALIZEDTEXT_STATIC(haseffect->description, "HasEffect");
-	haseffect->isAbstract = UA_FALSE;
-	haseffect->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(haseffect->inverseName, "MayBeEffectedBy");
-	ADDINVERSEREFERENCE(haseffect, RefTypeId_HasSubtype, RefTypeId_NonHierarchicalReferences);
-	Namespace_insert(ns0,(UA_Node**)&haseffect, NAMESPACE_INSERT_UNIQUE);
-
-	UA_ReferenceTypeNode *hashistoricalconfiguration;
-	UA_ReferenceTypeNode_new(&hashistoricalconfiguration);
-	hashistoricalconfiguration->nodeId = RefTypeId_HasHistoricalConfiguration;
-	hashistoricalconfiguration->nodeClass = UA_NODECLASS_REFERENCETYPE;
-	UA_QUALIFIEDNAME_STATIC(hashistoricalconfiguration->browseName, "HasHistoricalConfiguration");
-	UA_LOCALIZEDTEXT_STATIC(hashistoricalconfiguration->displayName, "HasHistoricalConfiguration");
-	UA_LOCALIZEDTEXT_STATIC(hashistoricalconfiguration->description, "HasHistoricalConfiguration");
-	hashistoricalconfiguration->isAbstract = UA_FALSE;
-	hashistoricalconfiguration->symmetric = UA_FALSE;
-	UA_LOCALIZEDTEXT_STATIC(hashistoricalconfiguration->inverseName, "HistoricalConfigurationOf");
-	ADDINVERSEREFERENCE(hashistoricalconfiguration, RefTypeId_HasSubtype, RefTypeId_Aggregates);
-	Namespace_insert(ns0,(UA_Node**)&hashistoricalconfiguration, NAMESPACE_INSERT_UNIQUE);
-
-
-	// ObjectTypes (Ids only)
-	UA_ExpandedNodeId ObjTypeId_FolderType; NS0EXPANDEDNODEID(ObjTypeId_FolderType, 61);
-
-	// Objects (Ids only)
-	UA_ExpandedNodeId ObjId_ObjectsFolder; NS0EXPANDEDNODEID(ObjId_ObjectsFolder, 85);
-	UA_ExpandedNodeId ObjId_TypesFolder; NS0EXPANDEDNODEID(ObjId_TypesFolder, 86);
-	UA_ExpandedNodeId ObjId_ViewsFolder; NS0EXPANDEDNODEID(ObjId_ViewsFolder, 87);
-	UA_ExpandedNodeId ObjId_Server; NS0EXPANDEDNODEID(ObjId_Server, 2253);
-	UA_ExpandedNodeId ObjId_ServerArray; NS0EXPANDEDNODEID(ObjId_ServerArray, 2254);
-	UA_ExpandedNodeId ObjId_NamespaceArray; NS0EXPANDEDNODEID(ObjId_NamespaceArray, 2255);
-	UA_ExpandedNodeId ObjId_ServerStatus; NS0EXPANDEDNODEID(ObjId_ServerStatus, 2256);
-	UA_ExpandedNodeId ObjId_ServerCapabilities; NS0EXPANDEDNODEID(ObjId_ServerCapabilities, 2268);
-	UA_ExpandedNodeId ObjId_State; NS0EXPANDEDNODEID(ObjId_State, 2259);
-
-	// FolderType
-	UA_ObjectNode *folderType;
-	UA_ObjectNode_new(&folderType);
-	folderType->nodeId = NS0NODEID(61);
-	folderType->nodeClass = UA_NODECLASS_OBJECTTYPE; // I should not have to set this manually
-	UA_QUALIFIEDNAME_STATIC(folderType->browseName, "FolderType");
-	UA_LOCALIZEDTEXT_STATIC(folderType->displayName, "FolderType");
-	UA_LOCALIZEDTEXT_STATIC(folderType->description, "FolderType");
-	Namespace_insert(ns0,(UA_Node**)&folderType, NAMESPACE_INSERT_UNIQUE);
-
-#define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID) \
-	static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID; \
-	UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID); \
-	NODE##REFTYPE##TARGET_NODEID.referenceTypeId = REFTYPE; \
-	NODE##REFTYPE##TARGET_NODEID.isInverse = INVERSE; \
-	NODE##REFTYPE##TARGET_NODEID.targetId = TARGET_NODEID; \
-	AddReference((UA_Node*)NODE, &NODE##REFTYPE##TARGET_NODEID, ns0)
-
-	// Root
-	UA_ObjectNode *root;
-	UA_ObjectNode_new(&root);
-	root->nodeId = NS0NODEID(84);
-	root->nodeClass = UA_NODECLASS_OBJECT; // I should not have to set this manually
-	UA_QUALIFIEDNAME_STATIC(root->browseName, "Root");
-	UA_LOCALIZEDTEXT_STATIC(root->displayName, "Root");
-	UA_LOCALIZEDTEXT_STATIC(root->description, "Root");
-	ADDREFERENCE(root, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-	ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ObjectsFolder);
-	ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder);
-	ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder);
-	/* root becomes a managed node. we need to release it at the end.*/
-	Namespace_insert(ns0,(UA_Node**)&root, NAMESPACE_INSERT_UNIQUE | NAMESPACE_INSERT_GETMANAGED);
-
-	// Objects
-	UA_ObjectNode *objects;
-	UA_ObjectNode_new(&objects);
-	objects->nodeId = ObjId_ObjectsFolder.nodeId;
-	objects->nodeClass = UA_NODECLASS_OBJECT;
-	UA_QUALIFIEDNAME_STATIC(objects->browseName, "Objects");
-	UA_LOCALIZEDTEXT_STATIC(objects->displayName, "Objects");
-	UA_LOCALIZEDTEXT_STATIC(objects->description, "Objects");
-	ADDREFERENCE(objects, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-	ADDREFERENCE(objects, RefTypeId_Organizes, UA_FALSE, ObjId_Server);
-	Namespace_insert(ns0,(UA_Node**)&objects, NAMESPACE_INSERT_UNIQUE);
-
-	// Types
-	UA_ObjectNode *types;
-	UA_ObjectNode_new(&types);
-	types->nodeId = ObjId_TypesFolder.nodeId;
-	types->nodeClass = UA_NODECLASS_OBJECT;
-	UA_QUALIFIEDNAME_STATIC(types->browseName, "Types");
-	UA_LOCALIZEDTEXT_STATIC(types->displayName, "Types");
-	UA_LOCALIZEDTEXT_STATIC(types->description, "Types");
-	ADDREFERENCE(types, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-	Namespace_insert(ns0,(UA_Node**)&types, NAMESPACE_INSERT_UNIQUE);
-
-	// Views
-	UA_ObjectNode *views;
-	UA_ObjectNode_new(&views);
-	views->nodeId = ObjId_ViewsFolder.nodeId;
-	views->nodeClass = UA_NODECLASS_OBJECT;
-	UA_QUALIFIEDNAME_STATIC(views->browseName, "Views");
-	UA_LOCALIZEDTEXT_STATIC(views->displayName, "Views");
-	UA_LOCALIZEDTEXT_STATIC(views->description, "Views");
-	ADDREFERENCE(views, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
-	Namespace_insert(ns0,(UA_Node**)&views, NAMESPACE_INSERT_UNIQUE);
-
-	// Server
-	UA_ObjectNode *server;
-	UA_ObjectNode_new(&server);
-	server->nodeId = ObjId_Server.nodeId;
-	server->nodeClass = UA_NODECLASS_OBJECT;
-	UA_QUALIFIEDNAME_STATIC(server->browseName, "Server");
-	UA_LOCALIZEDTEXT_STATIC(server->displayName, "Server");
-	UA_LOCALIZEDTEXT_STATIC(server->description, "Server");
-	ADDREFERENCE(server, RefTypeId_HasComponent, UA_FALSE, ObjId_ServerCapabilities);
-	ADDREFERENCE(server, RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray);
-	ADDREFERENCE(server, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus);
-	ADDREFERENCE(server, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray);
-	Namespace_insert(ns0,(UA_Node**)&server, NAMESPACE_INSERT_UNIQUE);
-
-	// NamespaceArray
-	UA_VariableNode *namespaceArray;
-	UA_VariableNode_new(&namespaceArray);
-	namespaceArray->nodeId = ObjId_NamespaceArray.nodeId;
-	namespaceArray->nodeClass = UA_NODECLASS_VARIABLE; //FIXME: this should go into _new?
-	UA_QUALIFIEDNAME_STATIC(namespaceArray->browseName, "NamespaceArray");
-	UA_LOCALIZEDTEXT_STATIC(namespaceArray->displayName, "NamespaceArray");
-	UA_LOCALIZEDTEXT_STATIC(namespaceArray->description, "NamespaceArray");
-	UA_Array_new((void**)&namespaceArray->value.data, 2, &UA_.types[UA_STRING]);
-	namespaceArray->value.vt = &UA_.types[UA_STRING];
-	namespaceArray->value.arrayLength = 2;
-	UA_String_copycstring("http://opcfoundation.org/UA/",&((UA_String *)((namespaceArray->value).data))[0]);
-	UA_String_copycstring("http://localhost:16664/open62541/",&((UA_String *)(((namespaceArray)->value).data))[1]);
-	namespaceArray->arrayDimensionsSize = 1;
-	UA_UInt32* dimensions = UA_NULL;
-	UA_alloc((void**)&dimensions, sizeof(UA_UInt32));
-	*dimensions = 2;
-	namespaceArray->arrayDimensions = dimensions;
-	namespaceArray->dataType = NS0NODEID(UA_STRING_NS0);
-	namespaceArray->valueRank = 1;
-	namespaceArray->minimumSamplingInterval = 1.0;
-	namespaceArray->historizing = UA_FALSE;
-	Namespace_insert(ns0,(UA_Node**)&namespaceArray, NAMESPACE_INSERT_UNIQUE);
-
-	// ServerStatus
-	UA_VariableNode *serverstatus;
-	UA_VariableNode_new(&serverstatus);
-	serverstatus->nodeId = ObjId_ServerStatus.nodeId;
-	serverstatus->nodeClass = UA_NODECLASS_VARIABLE;
-	UA_QUALIFIEDNAME_STATIC(serverstatus->browseName, "ServerStatus");
-	UA_LOCALIZEDTEXT_STATIC(serverstatus->displayName, "ServerStatus");
-	UA_LOCALIZEDTEXT_STATIC(serverstatus->description, "ServerStatus");
-	UA_ServerStatusDataType *status;
-	UA_ServerStatusDataType_new(&status);
-	status->startTime = UA_DateTime_now();
-	status->currentTime = UA_DateTime_now();
-	status->state = UA_SERVERSTATE_RUNNING;
-	UA_STRING_STATIC(status->buildInfo.productUri, "open62541.org");
-	UA_STRING_STATIC(status->buildInfo.manufacturerName, "open62541");
-	UA_STRING_STATIC(status->buildInfo.productName, "open62541");
-	UA_STRING_STATIC(status->buildInfo.softwareVersion, "0.0");
-	UA_STRING_STATIC(status->buildInfo.buildNumber, "0.0");
-	status->buildInfo.buildDate = UA_DateTime_now();
-	status->secondsTillShutdown = 99999999;
-	UA_LOCALIZEDTEXT_STATIC(status->shutdownReason, "because");
-	serverstatus->value.vt = &UA_.types[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
-	serverstatus->value.arrayLength = 1;
-	serverstatus->value.data = status;
-	Namespace_insert(ns0,(UA_Node**)&serverstatus, NAMESPACE_INSERT_UNIQUE);
-
-	// State (Component of ServerStatus)
-	UA_VariableNode *state;
-	UA_VariableNode_new(&state);
-	state->nodeId = ObjId_State.nodeId;
-	state->nodeClass = UA_NODECLASS_VARIABLE;
-	UA_QUALIFIEDNAME_STATIC(state->browseName, "State");
-	UA_LOCALIZEDTEXT_STATIC(state->displayName, "State");
-	UA_LOCALIZEDTEXT_STATIC(state->description, "State");
-	state->value.vt = &UA_borrowed_.types[UA_SERVERSTATE];
-	state->value.arrayDimensionsLength = 1; // added to ensure encoding in readreponse
-	state->value.arrayLength = 1;
-	state->value.data = &status->state; // points into the other object.
-	Namespace_insert(ns0,(UA_Node**)&state, NAMESPACE_INSERT_UNIQUE);
-
-	//TODO: free(namespaceArray->value.data) later or forget it
-
-
-	/* UA_VariableNode* v = (UA_VariableNode*)np; */
-	/* UA_Array_new((void**)&v->value.data, 2, &UA_.types[UA_STRING]); */
-	/* v->value.vt = &UA_.types[UA_STRING]; */
-	/* v->value.arrayLength = 2; */
-	/* UA_String_copycstring("http://opcfoundation.org/UA/",&((UA_String *)((v->value).data))[0]); */
-	/* UA_String_copycstring("http://localhost:16664/open62541/",&((UA_String *)(((v)->value).data))[1]); */
-	/* v->dataType.identifierType = UA_NODEIDTYPE_FOURBYTE; */
-	/* v->dataType.identifier.numeric = UA_STRING_NS0; */
-	/* v->valueRank = 1; */
-	/* v->minimumSamplingInterval = 1.0; */
-	/* v->historizing = UA_FALSE; */
-	/* Namespace_insert(ns0,np); */
-
-	/*******************/
-	/* Namespace local */
-	/*******************/
-	
-	Namespace_releaseManagedNode((const UA_Node*)root);
-
-#if defined(DEBUG) && defined(VERBOSE)
-	uint32_t i;
-	for (i=0;i < ns0->size;i++) {
-		if (ns0->entries[i].node != UA_NULL) {
-			printf("appMockup_init - entries[%d]={",i);
-			UA_Node_print(ns0->entries[i].node, stdout);
-			printf("}\n");
-		}
-	}
-#endif
-}

+ 0 - 15
src/server/ua_application.h

@@ -1,15 +0,0 @@
-#ifndef OPCUA_APPLICATION_H_
-#define OPCUA_APPLICATION_H_
-
-#include "ua_types.h"
-#include "ua_namespace.h"
-#include "util/ua_indexedList.h"
-
-typedef struct Application {
-	UA_ApplicationDescription *description;
-	UA_indexedList_List *namespaces; // each entry is a namespace
-} Application;
-
-extern Application appMockup;
-void appMockup_init();
-#endif

+ 0 - 139
src/server/ua_channel_manager.c

@@ -1,139 +0,0 @@
-#include "ua_channel_manager.h"
-
-struct SL_ChannelManager {
-	UA_Int32 maxChannelCount;
-	UA_Int32 lastChannelId;
-	UA_DateTime maxChannelLifeTime;
-	UA_list_List channels;
-	UA_MessageSecurityMode securityMode;
-	UA_String endpointUrl;
-	UA_DateTime channelLifeTime;
-	UA_UInt32 lastTokenId;
-};
-
-static SL_ChannelManager *channelManager;
-
-UA_Int32 SL_ChannelManager_init(UA_UInt32 maxChannelCount, UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
-								UA_UInt32 startTokenId, UA_String *endpointUrl) {
-	UA_alloc((void**)&channelManager,sizeof(SL_ChannelManager));
-	UA_list_init(&(channelManager->channels));
-	channelManager->lastChannelId = startChannelId;
-	channelManager->lastTokenId = startTokenId;
-	UA_String_copy(endpointUrl,&channelManager->endpointUrl);
-	channelManager->maxChannelLifeTime = tokenLifetime;
-	channelManager->maxChannelCount = maxChannelCount;
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_ChannelManager_addChannel(SL_Channel *channel) {
-	if (!channelManager || (channelManager->maxChannelCount <= channelManager->channels.size))
-		return UA_ERROR;
-
-	//TODO lock access (mulitthreading)------------
-	UA_list_addPayloadToBack(&channelManager->channels,(void*)channel);
-	return UA_SUCCESS;
-	//TODO lock access------------
-}
-
-UA_Int32 generateNewTokenId() {
-	//TODO lock accesss
-	return channelManager->lastTokenId++;
-}
-
-UA_Int32 SL_ChannelManager_generateChannelId(UA_UInt32 *newChannelId) {
-	if(channelManager) {
-		*newChannelId = channelManager->lastChannelId++;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_UInt32 SL_ChannelManager_generateNewTokenId() {
-	return channelManager->lastTokenId++;
-}
-
-UA_Int32 SL_ChannelManager_generateToken(SL_Channel *channel, UA_Int32 requestedLifeTime,
-		SecurityTokenRequestType requestType,
-		UA_ChannelSecurityToken* newToken) {
-	UA_UInt32 tokenId;
-	if(channel){
-		SL_Channel_getTokenId(channel,&tokenId);
-		if(requestType==UA_SECURITYTOKEN_ISSUE) {
-			SL_Channel_getChannelId(channel,&newToken->channelId);
-			newToken->createdAt = UA_DateTime_now();
-			newToken->revisedLifetime = requestedLifeTime > channelManager->maxChannelLifeTime ? channelManager->maxChannelLifeTime : requestedLifeTime;
-			newToken->tokenId = SL_ChannelManager_generateNewTokenId();
-			return UA_SUCCESS;
-		} else if(requestType==UA_SECURITYTOKEN_RENEW) {
-			SL_Channel_getChannelId(channel,&newToken->channelId);
-			newToken->createdAt = UA_DateTime_now();
-			newToken->revisedLifetime = requestedLifeTime > channelManager->maxChannelLifeTime ? channelManager->maxChannelLifeTime : requestedLifeTime;
-			return UA_SUCCESS;
-		}
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_ChannelManager_removeChannel(UA_Int32 channelId) {
-	//TODO lock access
-	SL_Channel *channel;
-	UA_Int32 retval = UA_SUCCESS;
-	SL_ChannelManager_getChannel(channelId, &channel);
-
-	UA_list_Element *element =  UA_list_search(&channelManager->channels, (UA_list_PayloadComparer)SL_Channel_compare, &channel);
-	if(element) {
-		retval |= UA_list_removeElement(element,(UA_list_PayloadVisitor)SL_Channel_delete);
-		return retval;
-	}
-		//TODO notify server application that secureChannel has been closed part 6 - §7.1.4
-
-	return UA_ERROR;
-}
-
-UA_Int32 SL_ChannelManager_getChannelLifeTime(UA_DateTime *lifeTime) {
-	*lifeTime = channelManager->channelLifeTime;
-	return UA_SUCCESS;
-}
-
-/*UA_Int32 SL_ChannelManager_getChannelsByConnectionId(UA_Int32 connectionId,
-		SL_secureChannel **channels, UA_Int32 *noOfChannels)
-{
-	return UA_SUCCESS;UA_list_Element
-}
-*/
-
-UA_Int32 SL_ChannelManager_getChannel(UA_UInt32 channelId, SL_Channel **channel) {
-	UA_UInt32 tmpChannelId;
-	if(channelManager==UA_NULL){
-		*channel = UA_NULL;
-		return UA_ERROR;
-	}
-
- 	UA_list_Element* current = channelManager->channels.first;
-	while (current) {
-		if (current->payload) {
-			UA_list_Element* elem = (UA_list_Element*) current;
-			*channel = ((SL_Channel*) (elem->payload));
-			SL_Channel_getChannelId(*channel, &tmpChannelId);
-		 	if(tmpChannelId == channelId)
-		 		return UA_SUCCESS;
-		}
-		current = current->next;
-	}
-#ifdef DEBUG
-
-//	SL_Channel c1 = *(SL_Channel*)(channelManager->channels.first->payload);
-//	SL_Channel c2 = *(SL_Channel*)(channelManager->channels.last->payload);
-//	UA_UInt32 id1,id2;
-
-//	SL_Channel_getChannelId(c1,&id1);
-//	SL_Channel_getChannelId(c2,&id2);
-//
-//	printf("SL_ChannelManager_getChannel c1: %i \n",id1);
-//	printf("SL_ChannelManager_getChannel c2: %i \n",id2);
-#endif
-	*channel = UA_NULL;
-	return UA_ERROR;
-}
-

+ 0 - 17
src/server/ua_channel_manager.h

@@ -1,17 +0,0 @@
-#ifndef UA_CHANNEL_MANAGER_H_
-#define UA_CHANNEL_MANAGER_H_
-
-#include "ua_channel.h"
-
-struct SL_ChannelManager;
-typedef struct SL_ChannelManager SL_ChannelManager;
-
-UA_Int32 SL_ChannelManager_init(UA_UInt32 maxChannelCount,UA_UInt32 tokenLifetime, UA_UInt32 startChannelId, UA_UInt32 startTokenId, UA_String *endpointUrl);
-UA_Int32 SL_ChannelManager_addChannel(SL_Channel *channel);
-UA_Int32 SL_ChannelManager_removeChannel(UA_Int32 channelId);
-UA_Int32 SL_ChannelManager_getChannel(UA_UInt32 channelId, SL_Channel **channel);
-UA_Int32 SL_ChannelManager_getChannelLifeTime(UA_DateTime *lifeTime);
-UA_Int32 SL_ChannelManager_generateToken(SL_Channel *channel, UA_Int32 requestedLifeTime, SecurityTokenRequestType requestType, UA_ChannelSecurityToken* newToken);
-UA_Int32 SL_ChannelManager_generateChannelId(UA_UInt32 *newChannelId);
-
-#endif /* UA_CHANNEL_MANAGER_H_ */

+ 0 - 339
src/server/ua_namespace.c

@@ -1,339 +0,0 @@
-#include "ua_namespace.h"
-#include <string.h>
-#include <stdio.h>
-
-struct Namespace {
-	UA_UInt32 namespaceIndex;
-	const UA_Node ** entries;
-	UA_UInt32 size;
-	UA_UInt32 count;
-	UA_UInt32 sizePrimeIndex;
-};
-
-typedef UA_UInt32 hash_t;
-/* 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 hash_t 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 INLINE hash_t mod(hash_t h, hash_t size) { return h % size; }
-static INLINE hash_t mod2(hash_t h, hash_t size) { return 1 + (h % (size - 2)); }
-
-static INLINE UA_Int16 higher_prime_index(hash_t n) {
-	UA_UInt16 low  = 0;
-	UA_UInt16 high = sizeof(primes) / sizeof(hash_t);
-	while(low != high) {
-		UA_UInt16 mid = low + (high - low) / 2;
-		if(n > primes[mid])
-			low = mid + 1;
-		else
-			high = mid;
-	}
-	return low;
-}
-
-/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
-static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len) {
-	const int32_t nblocks = len / 4;
-	const uint32_t *blocks;
-
-	static const uint32_t c1 = 0xcc9e2d51;
-	static const uint32_t c2 = 0x1b873593;
-	static const uint32_t r1 = 15;
-	static const uint32_t r2 = 13;
-	static const uint32_t m  = 5;
-	static const uint32_t n  = 0xe6546b64;
-	hash_t hash = len;
-
-	if(data == UA_NULL)
-		return 0;
-
-	blocks  = (const uint32_t *)data;
-	for(int32_t i = 0;i < nblocks;i++) {
-		uint32_t k = blocks[i];
-		k    *= c1;
-		k     = (k << r1) | (k >> (32 - r1));
-		k    *= c2;
-		hash ^= k;
-		hash  = ((hash << r2) | (hash >> (32 - r2))) * m + n;
-	}
-
-	const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
-	uint32_t       k1   = 0;
-
-	switch(len & 3) {
-	case 3:
-		k1 ^= tail[2] << 16;
-	case 2:
-		k1 ^= tail[1] << 8;
-	case 1:
-		k1   ^= tail[0];
-		k1   *= c1;
-		k1    = (k1 << r1) | (k1 >> (32 - r1));
-		k1   *= c2;
-		hash ^= k1;
-	}
-
-	hash ^= len;
-	hash ^= (hash >> 16);
-	hash *= 0x85ebca6b;
-	hash ^= (hash >> 13);
-	hash *= 0xc2b2ae35;
-	hash ^= (hash >> 16);
-
-	return hash;
-}
-
-static INLINE hash_t hash(const UA_NodeId *n) {
-	switch(n->identifierType) {
-	case UA_NODEIDTYPE_NUMERIC:
-		/*  Knuth's multiplicative hashing */
-		return n->identifier.numeric * 2654435761;   // mod(2^32) is implicit
-	case UA_NODEIDTYPE_STRING:
-		return hash_array(n->identifier.string.data, n->identifier.string.length);
-	case UA_NODEIDTYPE_GUID:
-		return hash_array((UA_Byte *)&(n->identifier.guid), sizeof(UA_Guid));
-	case UA_NODEIDTYPE_BYTESTRING:
-		return hash_array((UA_Byte *)n->identifier.byteString.data, n->identifier.byteString.length);
-	default:
-		return 0;
-	}
-}
-
-static INLINE void clear_entry(Namespace * ns, const UA_Node ** entry) {
-	const UA_Node *node;
-	if(entry == UA_NULL || *entry == UA_NULL)
-		return;
-
-	node = *entry;
-	switch (node->nodeClass) {
-	case UA_NODECLASS_OBJECT:
-		UA_ObjectNode_delete((UA_ObjectNode *) node);
-		break;
-	case UA_NODECLASS_VARIABLE:
-		UA_VariableNode_delete((UA_VariableNode *) node);
-		break;
-	case UA_NODECLASS_METHOD:
-		UA_MethodNode_delete((UA_MethodNode *) node);
-		break;
-	case UA_NODECLASS_OBJECTTYPE:
-		UA_ObjectTypeNode_delete((UA_ObjectTypeNode *) node);
-		break;
-	case UA_NODECLASS_VARIABLETYPE:
-		UA_VariableTypeNode_delete((UA_VariableTypeNode *) node);
-		break;
-	case UA_NODECLASS_REFERENCETYPE:
-		UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *) node);
-		break;
-	case UA_NODECLASS_DATATYPE:
-		UA_DataTypeNode_delete((UA_DataTypeNode *) node);
-		break;
-	case UA_NODECLASS_VIEW:
-		UA_ViewNode_delete((UA_ViewNode *) node);
-		break;
-	default:
-		break;
-	}
-	entry = UA_NULL;
-	ns->count--;
-}
-
-/* Returns UA_SUCCESS if an entry was found. Otherwise, UA_ERROR is returned and the "entry"
-   argument points to the first free entry under the NodeId. */
-static INLINE UA_Int32 find_entry(const Namespace * ns, const UA_NodeId * nodeid, const UA_Node *** entry) {
-	hash_t h = hash(nodeid);
-	UA_UInt32 size = ns->size;
-	hash_t index = mod(h, size);
-	const UA_Node **e = &ns->entries[index];
-
-	if(*e == UA_NULL) {
-		*entry = e;
-		return UA_ERROR;
-	}
-
-	if(UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
-		*entry = e;
-		return UA_SUCCESS;
-	}
-
-	hash_t hash2 = mod2(h, size);
-	for(;;) {
-		index += hash2;
-		if(index >= size)
-			index -= size;
-
-		e = &ns->entries[index];
-
-		if(*e == UA_NULL) {
-			*entry = e;
-			return UA_ERROR;
-		}
-
-		if(UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
-			*entry = e;
-			return UA_SUCCESS;
-		}
-	}
-
-	/* NOTREACHED */
-	return UA_SUCCESS;
-}
-
-/* The following function changes size of memory allocated for the entries and
-   repeatedly inserts the table elements. The occupancy of the table after the
-   call will be about 50%. If memory allocation failures occur, this function
-   will return UA_ERROR. */
-static UA_Int32 expand(Namespace * ns) {
-	const UA_Node **nentries;
-	int32_t nsize;
-	UA_UInt32 nindex;
-
-	const UA_Node **oentries = ns->entries;
-	int32_t osize = ns->size;
-	const UA_Node **olimit = &oentries[osize];
-	int32_t 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 <= 32)) {
-		return UA_SUCCESS;
-	}
-
-	nindex = higher_prime_index(count * 2);
-	nsize = primes[nindex];
-
-	if(UA_alloc((void **)&nentries, sizeof(UA_Node *) * nsize) != UA_SUCCESS)
-		return UA_ERR_NO_MEMORY;
-
-	memset(nentries, 0, nsize * sizeof(UA_Node *));
-	ns->entries = nentries;
-	ns->size = nsize;
-	ns->sizePrimeIndex = nindex;
-
-	const UA_Node **p = oentries;
-	do {
-		if(*p != UA_NULL) {
-			const UA_Node **e;
-			find_entry(ns, &(*p)->nodeId, &e);	/* We know this returns an empty entry here */
-			*e = *p;
-		}
-		p++;
-	} while(p < olimit);
-
-	UA_free(oentries);
-	return UA_SUCCESS;
-}
-
-/**********************/
-/* Exported functions */
-/**********************/
-
-UA_Int32 Namespace_new(Namespace ** result, UA_UInt32 namespaceIndex) {
-	Namespace *ns;
-	UA_UInt32 sizePrimeIndex, size;
-	if(UA_alloc((void **)&ns, sizeof(Namespace)) != UA_SUCCESS)
-		return UA_ERR_NO_MEMORY;
-
-	sizePrimeIndex = higher_prime_index(32);
-	size = primes[sizePrimeIndex];
-	if(UA_alloc((void **)&ns->entries, sizeof(UA_Node *) * size) != UA_SUCCESS) {
-		UA_free(ns);
-		return UA_ERR_NO_MEMORY;
-	}
-
-	/* set entries to zero */
-	memset(ns->entries, 0, size * sizeof(UA_Node *));
-
-	*ns = (Namespace) {namespaceIndex, ns->entries, size, 0, sizePrimeIndex};
-	*result = ns;
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_delete(Namespace * ns) {
-	UA_UInt32 size = ns->size;
-	const UA_Node **entries = ns->entries;
-
-	for(UA_UInt32 i = 0; i < size; i++)
-		clear_entry(ns, &entries[i]);
-	
-	UA_free(ns->entries);
-	UA_free(ns);
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_insert(Namespace *ns, UA_Node **node, UA_Byte flags) {
-	if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL)
-		return UA_ERROR;
-	
-	if(ns->size * 3 <= ns->count * 4) {
-		if(expand(ns) != UA_SUCCESS)
-			return UA_ERROR;
-	}
-
-	const UA_Node ** entry;
-	UA_Int32 found = find_entry(ns, &(*node)->nodeId, &entry);
-
-	if(flags & NAMESPACE_INSERT_UNIQUE) {
-		if(found == UA_SUCCESS)
-			return UA_ERROR;	/* There is already an entry for that nodeid */
-		else
-			*entry = *node;
-	} else {
-		if(found == UA_SUCCESS)
-			clear_entry(ns, entry);
-		*entry = *node;
-	}
-
-	if(!(flags & NAMESPACE_INSERT_GETMANAGED))
-		*node = UA_NULL;
-	
-	ns->count++;
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_get(const Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
-	const UA_Node **entry;
-	if(ns == UA_NULL || nodeid == UA_NULL || managedNode == UA_NULL)
-		return UA_ERROR;
-
-	if(find_entry(ns, nodeid, &entry) != UA_SUCCESS)
-		return UA_ERROR;
-
-	*managedNode = *entry;
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_remove(Namespace * ns, const UA_NodeId * nodeid) {
-	const UA_Node **entry;
-	if(find_entry(ns, nodeid, &entry) != UA_SUCCESS)
-		return UA_ERROR;
-
-	// Check before if deleting the node makes the Namespace inconsistent.
-	clear_entry(ns, entry);
-
-	/* Downsize the hashmap if it is very empty */
-	if(ns->count * 8 < ns->size && ns->size > 32)
-		expand(ns);
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_iterate(const Namespace * ns, Namespace_nodeVisitor visitor) {
-	if(ns == UA_NULL || visitor == UA_NULL)
-		return UA_ERROR;
-	
-	for(UA_UInt32 i = 0; i < ns->size; i++) {
-		const UA_Node *node = ns->entries[i];
-		if(node != UA_NULL)
-			visitor(node);
-	}
-	return UA_SUCCESS;
-}
-
-void Namespace_releaseManagedNode(const UA_Node *managed) {
-	;
-}

+ 0 - 372
src/server/ua_namespace_concurrent.c

@@ -1,372 +0,0 @@
-#include "ua_namespace.h"
-
-#include <urcu.h>
-#include <urcu/compiler.h> // for caa_container_of
-#include <urcu/uatomic.h>
-#include <urcu/rculfhash.h>
-
-
-#define ALIVE_BIT (1 << 15) /* Alive bit in the readcount */
-typedef struct Namespace_Entry {
-	struct cds_lfht_node htn; /* contains next-ptr for urcu-hashmap */
-	struct rcu_head rcu_head; /* For call-rcu */
-	UA_UInt16 readcount;      /* Counts the amount of readers on it [alive-bit, 15 counter-bits] */
-	UA_Node   node;           /* Might be cast from any _bigger_ UA_Node* type. Allocate enough memory! */
-} Namespace_Entry;
-
-struct Namespace {
-	UA_UInt32       namespaceIndex;
-	struct cds_lfht *ht; /* Hash table */
-};
-
-/********/
-/* Hash */
-/********/
-
-typedef UA_UInt32 hash_t;
-
-/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
-static inline hash_t hash_array(const UA_Byte *data, UA_UInt32 len) {
-	static const uint32_t c1 = 0xcc9e2d51;
-	static const uint32_t c2 = 0x1b873593;
-	static const uint32_t r1 = 15;
-	static const uint32_t r2 = 13;
-	static const uint32_t m  = 5;
-	static const uint32_t n  = 0xe6546b64;
-	hash_t hash = len;
-
-	if(data == UA_NULL) return 0;
-
-	const int32_t   nblocks = len / 4;
-	const uint32_t *blocks  = (const uint32_t *)data;
-	for(int32_t i = 0;i < nblocks;i++) {
-		uint32_t k = blocks[i];
-		k    *= c1;
-		k     = (k << r1) | (k >> (32 - r1));
-		k    *= c2;
-		hash ^= k;
-		hash  = ((hash << r2) | (hash >> (32 - r2))) * m + n;
-	}
-
-	const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
-	uint32_t       k1   = 0;
-
-	switch(len & 3) {
-	case 3:
-		k1 ^= tail[2] << 16;
-
-	case 2:
-		k1 ^= tail[1] << 8;
-
-	case 1:
-		k1   ^= tail[0];
-		k1   *= c1;
-		k1    = (k1 << r1) | (k1 >> (32 - r1));
-		k1   *= c2;
-		hash ^= k1;
-	}
-
-	hash ^= len;
-	hash ^= (hash >> 16);
-	hash *= 0x85ebca6b;
-	hash ^= (hash >> 13);
-	hash *= 0xc2b2ae35;
-	hash ^= (hash >> 16);
-
-	return hash;
-}
-
-static inline hash_t hash(const UA_NodeId *n) {
-	switch(n->identifierType) {
-	case UA_NODEIDTYPE_NUMERIC:
-		/*  Knuth's multiplicative hashing */
-		return n->identifier.numeric * 2654435761;   // mod(2^32) is implicit
-
-	case UA_NODEIDTYPE_STRING:
-		return hash_array(n->identifier.string.data, n->identifier.string.length);
-
-	case UA_NODEIDTYPE_GUID:
-		return hash_array((UA_Byte *)&(n->identifier.guid), sizeof(UA_Guid));
-
-	case UA_NODEIDTYPE_BYTESTRING:
-		return hash_array((UA_Byte *)n->identifier.byteString.data, n->identifier.byteString.length);
-
-	default:
-		return 0;
-	}
-}
-
-/*************/
-/* Namespace */
-/*************/
-
-static inline void node_deleteMembers(const UA_Node *node) {
-	switch(node->nodeClass) {
-	case UA_NODECLASS_OBJECT:
-		UA_ObjectNode_deleteMembers((UA_ObjectNode *)node);
-		break;
-
-	case UA_NODECLASS_VARIABLE:
-		UA_VariableNode_deleteMembers((UA_VariableNode *)node);
-		break;
-
-	case UA_NODECLASS_METHOD:
-		UA_MethodNode_deleteMembers((UA_MethodNode *)node);
-		break;
-
-	case UA_NODECLASS_OBJECTTYPE:
-		UA_ObjectTypeNode_deleteMembers((UA_ObjectTypeNode *)node);
-		break;
-
-	case UA_NODECLASS_VARIABLETYPE:
-		UA_VariableTypeNode_deleteMembers((UA_VariableTypeNode *)node);
-		break;
-
-	case UA_NODECLASS_REFERENCETYPE:
-		UA_ReferenceTypeNode_deleteMembers((UA_ReferenceTypeNode *)node);
-		break;
-
-	case UA_NODECLASS_DATATYPE:
-		UA_DataTypeNode_deleteMembers((UA_DataTypeNode *)node);
-		break;
-
-	case UA_NODECLASS_VIEW:
-		UA_ViewNode_deleteMembers((UA_ViewNode *)node);
-		break;
-
-	default:
-		break;
-	}
-}
-
-/* We are in a rcu_read lock. So the node will not be freed under our feet. */
-static int compare(struct cds_lfht_node *htn, const void *orig) {
-	UA_NodeId *origid = (UA_NodeId*)orig;
-	UA_NodeId   *newid  = &((Namespace_Entry *)htn)->node.nodeId; /* The htn is first in the entry structure. */
-
-	return UA_NodeId_equal(newid, origid) == UA_EQUAL;
-}
-
-/* The entry was removed from the hashtable. No more readers can get it. Since
-   all readers using the node for a longer time (outside the rcu critical
-   section) increased the readcount, we only need to wait for the readcount
-   to reach zero. */
-static void markDead(struct rcu_head *head) {
-	Namespace_Entry *entry = caa_container_of(head, Namespace_Entry, rcu_head);
-	if(uatomic_sub_return(&entry->readcount, ALIVE_BIT) > 0)
-		return;
-
-	node_deleteMembers(&entry->node);
-	UA_free(entry);
-	return;
-}
-
-/* Free the entry if it is dead and nobody uses it anymore */
-void Namespace_releaseManagedNode(const UA_Node *managed) {
-	if(managed == UA_NULL)
-		return;
-	
-	Namespace_Entry *entry = caa_container_of(managed, Namespace_Entry, node); // pointer to the first entry
-	if(uatomic_sub_return(&entry->readcount, 1) > 0)
-		return;
-
-	node_deleteMembers(managed);
-	UA_free(entry);
-	return;
-}
-
-UA_Int32 Namespace_new(Namespace **result, UA_UInt32 namespaceIndex) {
-	Namespace *ns;
-	if(UA_alloc((void **)&ns, sizeof(Namespace)) != UA_SUCCESS)
-		return UA_ERR_NO_MEMORY;
-
-	/* 32 is the minimum size for the hashtable. */
-	ns->ht = cds_lfht_new(32, 32, 0, CDS_LFHT_AUTO_RESIZE, NULL);
-	if(!ns->ht) {
-		UA_free(ns);
-		return UA_ERR_NO_MEMORY;
-	}
-
-	ns->namespaceIndex = namespaceIndex;
-	*result = ns;
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_delete(Namespace *ns) {
-	if(ns == UA_NULL)
-		return UA_ERROR;
-
-	struct cds_lfht *ht = ns->ht;
-	struct cds_lfht_iter iter;
-	struct cds_lfht_node *found_htn;
-
-	rcu_read_lock();
-	cds_lfht_first(ht, &iter);
-	while(iter.node != UA_NULL) {
-		found_htn = cds_lfht_iter_get_node(&iter);
-		if(!cds_lfht_del(ht, found_htn)) {
-			Namespace_Entry *entry = caa_container_of(found_htn, Namespace_Entry, htn);
-			call_rcu(&entry->rcu_head, markDead);
-		}
-		cds_lfht_next(ht, &iter);
-	}
-	rcu_read_unlock();
-
-	if(!cds_lfht_destroy(ht, UA_NULL)) {
-		UA_free(ns);
-		return UA_SUCCESS;
-	}
-	else
-		return UA_ERROR;
-}
-
-UA_Int32 Namespace_insert(Namespace *ns, UA_Node **node, UA_Byte flags) {
-	if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL || (*node)->nodeId.namespaceIndex != ns->namespaceIndex)
-		return UA_ERROR;
-
-	UA_UInt32 nodesize;
-	/* Copy the node into the entry. Then reset the original node. It shall no longer be used. */
-	switch((*node)->nodeClass) {
-	case UA_NODECLASS_OBJECT:
-		nodesize = sizeof(UA_ObjectNode);
-		break;
-
-	case UA_NODECLASS_VARIABLE:
-		nodesize = sizeof(UA_VariableNode);
-		break;
-
-	case UA_NODECLASS_METHOD:
-		nodesize = sizeof(UA_MethodNode);
-		break;
-
-	case UA_NODECLASS_OBJECTTYPE:
-		nodesize = sizeof(UA_ObjectTypeNode);
-		break;
-
-	case UA_NODECLASS_VARIABLETYPE:
-		nodesize = sizeof(UA_VariableTypeNode);
-		break;
-
-	case UA_NODECLASS_REFERENCETYPE:
-		nodesize = sizeof(UA_ReferenceTypeNode);
-		break;
-
-	case UA_NODECLASS_DATATYPE:
-		nodesize = sizeof(UA_DataTypeNode);
-		break;
-
-	case UA_NODECLASS_VIEW:
-		nodesize = sizeof(UA_ViewNode);
-		break;
-
-	default:
-		return UA_ERROR;
-	}
-
-	Namespace_Entry *entry;
-	if(UA_alloc((void **)&entry, sizeof(Namespace_Entry) - sizeof(UA_Node) + nodesize))
-		return UA_ERR_NO_MEMORY;
-	memcpy(&entry->node, *node, nodesize);
-
-	cds_lfht_node_init(&entry->htn);
-	entry->readcount = ALIVE_BIT;
-	if(flags & NAMESPACE_INSERT_GETMANAGED)
-		entry->readcount++;
-
-	hash_t nhash = hash(&(*node)->nodeId);
-	struct cds_lfht_node *result;
-	if(flags & NAMESPACE_INSERT_UNIQUE) {
-		rcu_read_lock();
-		result = cds_lfht_add_unique(ns->ht, nhash, compare, &entry->node.nodeId, &entry->htn);
-		rcu_read_unlock();
-
-		/* If the nodeid exists already */
-		if(result != &entry->htn) {
-			UA_free(entry);
-			return UA_ERROR;     // TODO: define a UA_EXISTS_ALREADY
-		}
-	} else {
-		rcu_read_lock();
-		result = cds_lfht_add_replace(ns->ht, nhash, compare, &(*node)->nodeId, &entry->htn);
-		/* If an entry got replaced, mark it as dead. */
-		if(result) {
-			Namespace_Entry *entry = caa_container_of(result, Namespace_Entry, htn);
-			call_rcu(&entry->rcu_head, markDead);      /* Queue this for the next time when no readers are on the entry.*/
-		}
-		rcu_read_unlock();
-	}
-
-	UA_free((UA_Node*)*node);     /* The old node is replaced by a managed node. */
-	if(flags & NAMESPACE_INSERT_GETMANAGED)
-		*node = &entry->node;
-	else
-		*node = UA_NULL;
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_remove(Namespace *ns, const UA_NodeId *nodeid) {
-	hash_t nhash = hash(nodeid);
-	struct cds_lfht_iter iter;
-
-	rcu_read_lock();
-	cds_lfht_lookup(ns->ht, nhash, compare, &nodeid, &iter);
-	struct cds_lfht_node *found_htn = cds_lfht_iter_get_node(&iter);
-
-	/* If this fails, then the node has already been removed. */
-	if(!found_htn || cds_lfht_del(ns->ht, found_htn) != 0) {
-		rcu_read_unlock();
-		return UA_ERROR;
-	}
-	
-	Namespace_Entry *entry = caa_container_of(found_htn, Namespace_Entry, htn);
-	call_rcu(&entry->rcu_head, markDead);
-	rcu_read_unlock();
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_get(const Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
-	hash_t nhash     = hash(nodeid);
-	struct cds_lfht_iter iter;
-
-	rcu_read_lock();
-	cds_lfht_lookup(ns->ht, nhash, compare, nodeid, &iter);
-	Namespace_Entry *found_entry = (Namespace_Entry *)cds_lfht_iter_get_node(&iter);
-
-	if(!found_entry) {
-		rcu_read_unlock();
-		return UA_ERROR;  // TODO: UA_NOTFOUND
-	}
-
-	/* This is done within a read-lock. The node will not be marked dead within a read-lock. */
-	uatomic_inc(&found_entry->readcount);
-	rcu_read_unlock();
-
-	*managedNode = &found_entry->node;
-	return UA_SUCCESS;
-}
-
-UA_Int32 Namespace_iterate(const Namespace *ns, Namespace_nodeVisitor visitor) {
-	if(ns == UA_NULL || visitor == UA_NULL)
-		return UA_ERROR;
-	
-	struct cds_lfht *ht = ns->ht;
-	struct cds_lfht_iter iter;
-
-	rcu_read_lock();
-	cds_lfht_first(ht, &iter);
-	while(iter.node != UA_NULL) {
-		Namespace_Entry *found_entry = (Namespace_Entry *)cds_lfht_iter_get_node(&iter);
-		uatomic_inc(&found_entry->readcount);
-		const UA_Node *node = &found_entry->node;
-		rcu_read_unlock();
-		visitor(node);
-		Namespace_releaseManagedNode((UA_Node *)node);
-		rcu_read_lock();
-		cds_lfht_next(ht, &iter);
-	}
-	rcu_read_unlock();
-
-	return UA_SUCCESS;
-}

+ 355 - 0
src/server/ua_nodestore.c

@@ -0,0 +1,355 @@
+#include "ua_nodestore.h"
+
+struct UA_NodeStore {
+    const UA_Node **entries;
+    UA_UInt32       size;
+    UA_UInt32       count;
+    UA_UInt32       sizePrimeIndex;
+};
+
+typedef UA_UInt32 hash_t;
+/* 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 hash_t 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 INLINE hash_t mod(hash_t h, hash_t size) {
+    return h % size;
+}
+static INLINE hash_t mod2(hash_t h, hash_t size) {
+    return 1 + (h % (size - 2));
+}
+
+static INLINE UA_Int16 higher_prime_index(hash_t n) {
+    UA_UInt16 low  = 0;
+    UA_UInt16 high = sizeof(primes) / sizeof(hash_t);
+    while(low != high) {
+        UA_UInt16 mid = low + (high - low) / 2;
+        if(n > primes[mid])
+            low = mid + 1;
+        else
+            high = mid;
+    }
+    return low;
+}
+
+/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
+static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len, UA_UInt32 seed) {
+    const int32_t   nblocks = len / 4;
+    const uint32_t *blocks;
+
+    static const uint32_t c1 = 0xcc9e2d51;
+    static const uint32_t c2 = 0x1b873593;
+    static const uint32_t r1 = 15;
+    static const uint32_t r2 = 13;
+    static const uint32_t m  = 5;
+    static const uint32_t n  = 0xe6546b64;
+    hash_t hash = seed;
+
+    if(data == UA_NULL)
+        return 0;
+
+    blocks = (const uint32_t *)data;
+    for(int32_t i = 0;i < nblocks;i++) {
+        uint32_t k = blocks[i];
+        k    *= c1;
+        k     = (k << r1) | (k >> (32 - r1));
+        k    *= c2;
+        hash ^= k;
+        hash  = ((hash << r2) | (hash >> (32 - r2))) * m + n;
+    }
+
+    const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+    uint32_t       k1   = 0;
+
+    switch(len & 3) {
+    case 3:
+        k1 ^= tail[2] << 16;
+
+    case 2:
+        k1 ^= tail[1] << 8;
+
+    case 1:
+        k1   ^= tail[0];
+        k1   *= c1;
+        k1    = (k1 << r1) | (k1 >> (32 - r1));
+        k1   *= c2;
+        hash ^= k1;
+    }
+
+    hash ^= len;
+    hash ^= (hash >> 16);
+    hash *= 0x85ebca6b;
+    hash ^= (hash >> 13);
+    hash *= 0xc2b2ae35;
+    hash ^= (hash >> 16);
+
+    return hash;
+}
+
+static INLINE hash_t hash(const UA_NodeId *n) {
+    switch(n->identifierType) {
+    case UA_NODEIDTYPE_NUMERIC:
+        /*  Knuth's multiplicative hashing */
+        return (n->identifier.numeric + n->namespaceIndex) * 2654435761;   // mod(2^32) is implicit
+
+    case UA_NODEIDTYPE_STRING:
+        return hash_array(n->identifier.string.data, n->identifier.string.length, n->namespaceIndex);
+
+    case UA_NODEIDTYPE_GUID:
+        return hash_array((UA_Byte *)&(n->identifier.guid), sizeof(UA_Guid), n->namespaceIndex);
+
+    case UA_NODEIDTYPE_BYTESTRING:
+        return hash_array((UA_Byte *)n->identifier.byteString.data, n->identifier.byteString.length, n->namespaceIndex);
+
+    default:
+        UA_assert(UA_FALSE);
+        return 0;
+    }
+}
+
+static INLINE void clear_entry(UA_NodeStore *ns, const UA_Node **entry) {
+    const UA_Node *node;
+    if(entry == UA_NULL || *entry == UA_NULL)
+        return;
+
+    node = *entry;
+    switch(node->nodeClass) {
+    case UA_NODECLASS_OBJECT:
+        UA_ObjectNode_delete((UA_ObjectNode *)node);
+        break;
+
+    case UA_NODECLASS_VARIABLE:
+        UA_VariableNode_delete((UA_VariableNode *)node);
+        break;
+
+    case UA_NODECLASS_METHOD:
+        UA_MethodNode_delete((UA_MethodNode *)node);
+        break;
+
+    case UA_NODECLASS_OBJECTTYPE:
+        UA_ObjectTypeNode_delete((UA_ObjectTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_VARIABLETYPE:
+        UA_VariableTypeNode_delete((UA_VariableTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_REFERENCETYPE:
+        UA_ReferenceTypeNode_delete((UA_ReferenceTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_DATATYPE:
+        UA_DataTypeNode_delete((UA_DataTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_VIEW:
+        UA_ViewNode_delete((UA_ViewNode *)node);
+        break;
+
+    default:
+        UA_assert(UA_FALSE);
+        break;
+    }
+    entry = UA_NULL;
+    ns->count--;
+}
+
+/* Returns UA_SUCCESS if an entry was found. Otherwise, UA_ERROR is returned and the "entry"
+   argument points to the first free entry under the NodeId. */
+static INLINE UA_Int32 find_entry(const UA_NodeStore *ns, const UA_NodeId *nodeid, const UA_Node ***entry) {
+    hash_t          h     = hash(nodeid);
+    UA_UInt32       size  = ns->size;
+    hash_t          index = mod(h, size);
+    const UA_Node **e     = &ns->entries[index];
+
+    if(*e == UA_NULL) {
+        *entry = e;
+        return UA_ERROR;
+    }
+
+    if(UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
+        *entry = e;
+        return UA_SUCCESS;
+    }
+
+    hash_t hash2 = mod2(h, size);
+    for(;;) {
+        index += hash2;
+        if(index >= size)
+            index -= size;
+
+        e = &ns->entries[index];
+
+        if(*e == UA_NULL) {
+            *entry = e;
+            return UA_ERROR;
+        }
+
+        if(UA_NodeId_equal(&(*e)->nodeId, nodeid) == UA_EQUAL) {
+            *entry = e;
+            return UA_SUCCESS;
+        }
+    }
+
+    /* NOTREACHED */
+    return UA_SUCCESS;
+}
+
+/* The following function changes size of memory allocated for the entries and
+   repeatedly inserts the table elements. The occupancy of the table after the
+   call will be about 50%. If memory allocation failures occur, this function
+   will return UA_ERROR. */
+static UA_Int32 expand(UA_NodeStore *ns) {
+    const UA_Node **nentries;
+    int32_t nsize;
+    UA_UInt32       nindex;
+
+    const UA_Node **oentries = ns->entries;
+    int32_t osize = ns->size;
+    const UA_Node **olimit   = &oentries[osize];
+    int32_t 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 <= 32))
+        return UA_SUCCESS;
+
+    nindex = higher_prime_index(count * 2);
+    nsize  = primes[nindex];
+
+    if(UA_alloc((void **)&nentries, sizeof(UA_Node *) * nsize) != UA_SUCCESS)
+        return UA_ERR_NO_MEMORY;
+
+    memset(nentries, 0, nsize * sizeof(UA_Node *));
+    ns->entries = nentries;
+    ns->size    = nsize;
+    ns->sizePrimeIndex = nindex;
+
+    const UA_Node **p = oentries;
+    do {
+        if(*p != UA_NULL) {
+            const UA_Node **e;
+            find_entry(ns, &(*p)->nodeId, &e);  /* We know this returns an empty entry here */
+            *e = *p;
+        }
+        p++;
+    } while(p < olimit);
+
+    UA_free(oentries);
+    return UA_SUCCESS;
+}
+
+/**********************/
+/* Exported functions */
+/**********************/
+
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result) {
+    UA_NodeStore *ns;
+    UA_UInt32     sizePrimeIndex, size;
+    if(UA_alloc((void **)&ns, sizeof(UA_NodeStore)) != UA_SUCCESS)
+        return UA_ERR_NO_MEMORY;
+
+    sizePrimeIndex = higher_prime_index(32);
+    size = primes[sizePrimeIndex];
+    if(UA_alloc((void **)&ns->entries, sizeof(UA_Node *) * size) != UA_SUCCESS) {
+        UA_free(ns);
+        return UA_ERR_NO_MEMORY;
+    }
+
+    /* set entries to zero */
+    memset(ns->entries, 0, size * sizeof(UA_Node *));
+
+    *ns     = (UA_NodeStore) {ns->entries, size, 0, sizePrimeIndex };
+    *result = ns;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns) {
+    UA_UInt32       size    = ns->size;
+    const UA_Node **entries = ns->entries;
+
+    for(UA_UInt32 i = 0;i < size;i++)
+        clear_entry(ns, &entries[i]);
+
+    UA_free(ns->entries);
+    UA_free(ns);
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags) {
+    if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL)
+        return UA_ERROR;
+
+    if(ns->size * 3 <= ns->count * 4) {
+        if(expand(ns) != UA_SUCCESS)
+            return UA_ERROR;
+    }
+
+    const UA_Node **entry;
+    UA_Int32 found = find_entry(ns, &(*node)->nodeId, &entry);
+
+    if(flags & UA_NODESTORE_INSERT_UNIQUE) {
+        if(found == UA_SUCCESS)
+            return UA_ERROR;    /* There is already an entry for that nodeid */
+        else
+            *entry = *node;
+    } else {
+        if(found == UA_SUCCESS)
+            clear_entry(ns, entry);
+        *entry = *node;
+    }
+
+    if(!(flags & UA_NODESTORE_INSERT_GETMANAGED))
+        *node = UA_NULL;
+
+    ns->count++;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
+    const UA_Node **entry;
+    if(ns == UA_NULL || nodeid == UA_NULL || managedNode == UA_NULL)
+        return UA_ERROR;
+
+    if(find_entry(ns, nodeid, &entry) != UA_SUCCESS)
+        return UA_ERROR;
+
+    *managedNode = *entry;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
+    const UA_Node **entry;
+    if(find_entry(ns, nodeid, &entry) != UA_SUCCESS)
+        return UA_ERROR;
+
+    // Check before if deleting the node makes the UA_NodeStore inconsistent.
+    clear_entry(ns, entry);
+
+    /* Downsize the hashmap if it is very empty */
+    if(ns->count * 8 < ns->size && ns->size > 32)
+        expand(ns);
+
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
+    if(ns == UA_NULL || visitor == UA_NULL)
+        return UA_ERROR;
+
+    for(UA_UInt32 i = 0;i < ns->size;i++) {
+        const UA_Node *node = ns->entries[i];
+        if(node != UA_NULL)
+            visitor(node);
+    }
+    return UA_SUCCESS;
+}
+
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed) {
+    ;
+}

+ 26 - 24
src/server/ua_namespace.h

@@ -1,18 +1,19 @@
-#ifndef __NAMESPACE_H__
-#define __NAMESPACE_H__
+#ifndef UA_NODESTORE_H_
+#define UA_NODESTORE_H_
 
 #include "ua_types.h"
 #include "ua_types_generated.h"
-#include "util/ua_list.h"
 
 /**
-   @defgroup namespace Namespace
+   @ingroup server
 
-   @brief The namespace is the central storage for nodes in the UA address
-   space. Internally, the namespace is realised as hash-map where nodes are
+   @defgroup nodestore NodeStore
+
+   @brief The nodestore is the central storage for nodes in the UA address
+   space. Internally, the nodestore is realised as hash-map where nodes are
    stored and retrieved with their nodeid.
 
-   The nodes in the namespace are immutable. To change the content of a node, it
+   The nodes in the nodestore are immutable. To change the content of a node, it
    needs to be replaced as a whole. When a node is inserted into the namespace,
    it gets replaced with a pointer to a managed node. Managed nodes shall never
    be freed by the user. This is done by the namespace when the node is removed
@@ -21,45 +22,46 @@
    @{
  */
 
-/** @brief Namespace datastructure. Mainly a hashmap to UA_Nodes */
-struct Namespace;
-typedef struct Namespace Namespace;
+/** @brief UA_NodeStore datastructure. Mainly a hashmap to UA_Nodes */
+struct UA_NodeStore;
+typedef struct UA_NodeStore UA_NodeStore;
 
 /** @brief Create a new namespace */
-UA_Int32 Namespace_new(Namespace **result, UA_UInt32 namespaceIndex);
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result);
 
 /** @brief Delete the namespace and all nodes in it */
-UA_Int32 Namespace_delete(Namespace *ns);
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns);
 
-#define NAMESPACE_INSERT_UNIQUE 1
-#define NAMESPACE_INSERT_GETMANAGED 2
+#define UA_NODESTORE_INSERT_UNIQUE 1
+#define UA_NODESTORE_INSERT_GETMANAGED 2
 /** @brief Insert a new node into the namespace
 
     With the UNIQUE flag, the node is only inserted if the nodeid does not
     already exist. With the GETMANAGED flag, the node pointer is replaced with
     the managed pointer. Otherwise, it is set to UA_NULL. */
-UA_Int32 Namespace_insert(Namespace *ns, UA_Node **node, UA_Byte flags);
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags);
 
 /** @brief Remove a node from the namespace. Always succeeds, even if the node
-	was not found. */
-UA_Int32 Namespace_remove(Namespace *ns, const UA_NodeId *nodeid);
+    was not found. */
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid);
 
 /** @brief Retrieve a node (read-only) from the namespace. Nodes are immutable.
     They can only be replaced. After the Node is no longer used, the locked
     entry needs to be released. */
-UA_Int32 Namespace_get(const Namespace *ns, const UA_NodeId *nodeid, const UA_Node **managedNode);
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid,
+                          const UA_Node **managedNode);
 
 /** @brief Release a managed node. Do never insert a node that isn't stored in a
-	namespace. */
-void Namespace_releaseManagedNode(const UA_Node *managed);
+    namespace. */
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed);
 
 /** @brief A function that can be evaluated on all entries in a namespace via
-	Namespace_iterate. Note that the visitor is read-only on the nodes. */
-typedef void (*Namespace_nodeVisitor)(const UA_Node *node);
+    UA_NodeStore_iterate. Note that the visitor is read-only on the nodes. */
+typedef void (*UA_NodeStore_nodeVisitor)(const UA_Node *node);
 
 /** @brief Iterate over all nodes in a namespace. */
-UA_Int32 Namespace_iterate(const Namespace *ns, Namespace_nodeVisitor visitor);
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor);
 
 /// @} /* end of group */
 
-#endif /* __NAMESPACE_H */
+#endif /* UA_NODESTORE_H_ */

+ 372 - 0
src/server/ua_nodestore_concurrent.c

@@ -0,0 +1,372 @@
+#include "ua_nodestore.h"
+
+#include <urcu.h>
+#include <urcu/compiler.h> // for caa_container_of
+#include <urcu/uatomic.h>
+#include <urcu/rculfhash.h>
+
+#define ALIVE_BIT (1 << 15) /* Alive bit in the readcount */
+typedef struct UA_NodeStore_Entry {
+    struct cds_lfht_node htn;      /* contains next-ptr for urcu-hashmap */
+    struct rcu_head      rcu_head; /* For call-rcu */
+    UA_UInt16 readcount;           /* Counts the amount of readers on it [alive-bit, 15 counter-bits] */
+    UA_Node   node;                /* Might be cast from any _bigger_ UA_Node* type. Allocate enough memory! */
+} UA_NodeStore_Entry;
+
+struct UA_NodeStore {
+    struct cds_lfht *ht; /* Hash table */
+};
+
+/********/
+/* Hash */
+/********/
+
+typedef UA_UInt32 hash_t;
+
+/* Based on Murmur-Hash 3 by Austin Appleby (public domain, freely usable) */
+static INLINE hash_t hash_array(const UA_Byte *data, UA_UInt32 len, UA_UInt32 seed) {
+    static const uint32_t c1 = 0xcc9e2d51;
+    static const uint32_t c2 = 0x1b873593;
+    static const uint32_t r1 = 15;
+    static const uint32_t r2 = 13;
+    static const uint32_t m  = 5;
+    static const uint32_t n  = 0xe6546b64;
+    hash_t hash = seed;
+
+    if(data == UA_NULL) return 0;
+
+    const int32_t   nblocks = len / 4;
+    const uint32_t *blocks  = (const uint32_t *)data;
+    for(int32_t i = 0;i < nblocks;i++) {
+        uint32_t k = blocks[i];
+        k    *= c1;
+        k     = (k << r1) | (k >> (32 - r1));
+        k    *= c2;
+        hash ^= k;
+        hash  = ((hash << r2) | (hash >> (32 - r2))) * m + n;
+    }
+
+    const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
+    uint32_t       k1   = 0;
+
+    switch(len & 3) {
+    case 3:
+        k1 ^= tail[2] << 16;
+
+    case 2:
+        k1 ^= tail[1] << 8;
+
+    case 1:
+        k1   ^= tail[0];
+        k1   *= c1;
+        k1    = (k1 << r1) | (k1 >> (32 - r1));
+        k1   *= c2;
+        hash ^= k1;
+    }
+
+    hash ^= len;
+    hash ^= (hash >> 16);
+    hash *= 0x85ebca6b;
+    hash ^= (hash >> 13);
+    hash *= 0xc2b2ae35;
+    hash ^= (hash >> 16);
+
+    return hash;
+}
+
+static INLINE hash_t hash(const UA_NodeId *n) {
+    switch(n->identifierType) {
+    case UA_NODEIDTYPE_NUMERIC:
+        /*  Knuth's multiplicative hashing */
+        return (n->identifier.numeric + n->namespaceIndex) * 2654435761;   // mod(2^32) is implicit
+
+    case UA_NODEIDTYPE_STRING:
+        return hash_array(n->identifier.string.data, n->identifier.string.length, n->namespaceIndex);
+
+    case UA_NODEIDTYPE_GUID:
+        return hash_array((UA_Byte *)&(n->identifier.guid), sizeof(UA_Guid), n->namespaceIndex);
+
+    case UA_NODEIDTYPE_BYTESTRING:
+        return hash_array((UA_Byte *)n->identifier.byteString.data, n->identifier.byteString.length, n->namespaceIndex);
+
+    default:
+        UA_assert(UA_FALSE);
+        return 0;
+    }
+}
+
+/****************/
+/* UA_NodeStore */
+/****************/
+
+static inline void node_deleteMembers(const UA_Node *node) {
+    switch(node->nodeClass) {
+    case UA_NODECLASS_OBJECT:
+        UA_ObjectNode_deleteMembers((UA_ObjectNode *)node);
+        break;
+
+    case UA_NODECLASS_VARIABLE:
+        UA_VariableNode_deleteMembers((UA_VariableNode *)node);
+        break;
+
+    case UA_NODECLASS_METHOD:
+        UA_MethodNode_deleteMembers((UA_MethodNode *)node);
+        break;
+
+    case UA_NODECLASS_OBJECTTYPE:
+        UA_ObjectTypeNode_deleteMembers((UA_ObjectTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_VARIABLETYPE:
+        UA_VariableTypeNode_deleteMembers((UA_VariableTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_REFERENCETYPE:
+        UA_ReferenceTypeNode_deleteMembers((UA_ReferenceTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_DATATYPE:
+        UA_DataTypeNode_deleteMembers((UA_DataTypeNode *)node);
+        break;
+
+    case UA_NODECLASS_VIEW:
+        UA_ViewNode_deleteMembers((UA_ViewNode *)node);
+        break;
+
+    default:
+        UA_assert(UA_FALSE);
+        break;
+    }
+}
+
+/* We are in a rcu_read lock. So the node will not be freed under our feet. */
+static int compare(struct cds_lfht_node *htn, const void *orig) {
+    UA_NodeId *origid = (UA_NodeId *)orig;
+    UA_NodeId *newid  = &((UA_NodeStore_Entry *)htn)->node.nodeId;   /* The htn is first in the entry structure. */
+
+    return UA_NodeId_equal(newid, origid) == UA_EQUAL;
+}
+
+/* The entry was removed from the hashtable. No more readers can get it. Since
+   all readers using the node for a longer time (outside the rcu critical
+   section) increased the readcount, we only need to wait for the readcount
+   to reach zero. */
+static void markDead(struct rcu_head *head) {
+    UA_NodeStore_Entry *entry = caa_container_of(head, UA_NodeStore_Entry, rcu_head);
+    if(uatomic_sub_return(&entry->readcount, ALIVE_BIT) > 0)
+        return;
+
+    node_deleteMembers(&entry->node);
+    UA_free(entry);
+    return;
+}
+
+/* Free the entry if it is dead and nobody uses it anymore */
+void UA_NodeStore_releaseManagedNode(const UA_Node *managed) {
+    if(managed == UA_NULL)
+        return;
+
+    UA_NodeStore_Entry *entry = caa_container_of(managed, UA_NodeStore_Entry, node); // pointer to the first entry
+    if(uatomic_sub_return(&entry->readcount, 1) > 0)
+        return;
+
+    node_deleteMembers(managed);
+    UA_free(entry);
+    return;
+}
+
+UA_Int32 UA_NodeStore_new(UA_NodeStore **result, UA_UInt32 namespaceIndex) {
+    UA_NodeStore *ns;
+    if(UA_alloc((void **)&ns, sizeof(UA_NodeStore)) != UA_SUCCESS)
+        return UA_ERR_NO_MEMORY;
+
+    /* 32 is the minimum size for the hashtable. */
+    ns->ht = cds_lfht_new(32, 32, 0, CDS_LFHT_AUTO_RESIZE, NULL);
+    if(!ns->ht) {
+        UA_free(ns);
+        return UA_ERR_NO_MEMORY;
+    }
+
+    ns->namespaceIndex = namespaceIndex;
+    *result = ns;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_delete(UA_NodeStore *ns) {
+    if(ns == UA_NULL)
+        return UA_ERROR;
+
+    struct cds_lfht      *ht = ns->ht;
+    struct cds_lfht_iter  iter;
+    struct cds_lfht_node *found_htn;
+
+    rcu_read_lock();
+    cds_lfht_first(ht, &iter);
+    while(iter.node != UA_NULL) {
+        found_htn = cds_lfht_iter_get_node(&iter);
+        if(!cds_lfht_del(ht, found_htn)) {
+            UA_NodeStore_Entry *entry = caa_container_of(found_htn, UA_NodeStore_Entry, htn);
+            call_rcu(&entry->rcu_head, markDead);
+        }
+        cds_lfht_next(ht, &iter);
+    }
+    rcu_read_unlock();
+
+    if(!cds_lfht_destroy(ht, UA_NULL)) {
+        UA_free(ns);
+        return UA_SUCCESS;
+    }else
+        return UA_ERROR;
+}
+
+UA_Int32 UA_NodeStore_insert(UA_NodeStore *ns, UA_Node **node, UA_Byte flags) {
+    if(ns == UA_NULL || node == UA_NULL || *node == UA_NULL || (*node)->nodeId.namespaceIndex !=
+       ns->namespaceIndex)
+        return UA_ERROR;
+
+    UA_UInt32 nodesize;
+    /* Copy the node into the entry. Then reset the original node. It shall no longer be used. */
+    switch((*node)->nodeClass) {
+    case UA_NODECLASS_OBJECT:
+        nodesize = sizeof(UA_ObjectNode);
+        break;
+
+    case UA_NODECLASS_VARIABLE:
+        nodesize = sizeof(UA_VariableNode);
+        break;
+
+    case UA_NODECLASS_METHOD:
+        nodesize = sizeof(UA_MethodNode);
+        break;
+
+    case UA_NODECLASS_OBJECTTYPE:
+        nodesize = sizeof(UA_ObjectTypeNode);
+        break;
+
+    case UA_NODECLASS_VARIABLETYPE:
+        nodesize = sizeof(UA_VariableTypeNode);
+        break;
+
+    case UA_NODECLASS_REFERENCETYPE:
+        nodesize = sizeof(UA_ReferenceTypeNode);
+        break;
+
+    case UA_NODECLASS_DATATYPE:
+        nodesize = sizeof(UA_DataTypeNode);
+        break;
+
+    case UA_NODECLASS_VIEW:
+        nodesize = sizeof(UA_ViewNode);
+        break;
+
+    default:
+        return UA_ERROR;
+    }
+
+    UA_NodeStore_Entry *entry;
+    if(UA_alloc((void **)&entry, sizeof(UA_NodeStore_Entry) - sizeof(UA_Node) + nodesize))
+        return UA_ERR_NO_MEMORY;
+    memcpy(&entry->node, *node, nodesize);
+
+    cds_lfht_node_init(&entry->htn);
+    entry->readcount = ALIVE_BIT;
+    if(flags & UA_NODESTORE_INSERT_GETMANAGED)
+        entry->readcount++;
+
+    hash_t nhash = hash(&(*node)->nodeId);
+    struct cds_lfht_node *result;
+    if(flags & UA_NODESTORE_INSERT_UNIQUE) {
+        rcu_read_lock();
+        result = cds_lfht_add_unique(ns->ht, nhash, compare, &entry->node.nodeId, &entry->htn);
+        rcu_read_unlock();
+
+        /* If the nodeid exists already */
+        if(result != &entry->htn) {
+            UA_free(entry);
+            return UA_ERROR;     // TODO: define a UA_EXISTS_ALREADY
+        }
+    } else {
+        rcu_read_lock();
+        result = cds_lfht_add_replace(ns->ht, nhash, compare, &(*node)->nodeId, &entry->htn);
+        /* If an entry got replaced, mark it as dead. */
+        if(result) {
+            UA_NodeStore_Entry *entry = caa_container_of(result, UA_NodeStore_Entry, htn);
+            call_rcu(&entry->rcu_head, markDead);      /* Queue this for the next time when no readers are on the entry.*/
+        }
+        rcu_read_unlock();
+    }
+
+    UA_free((UA_Node *)*node);     /* The old node is replaced by a managed node. */
+    if(flags & UA_NODESTORE_INSERT_GETMANAGED)
+        *node = &entry->node;
+    else
+        *node = UA_NULL;
+
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid) {
+    hash_t nhash = hash(nodeid);
+    struct cds_lfht_iter iter;
+
+    rcu_read_lock();
+    cds_lfht_lookup(ns->ht, nhash, compare, &nodeid, &iter);
+    struct cds_lfht_node *found_htn = cds_lfht_iter_get_node(&iter);
+
+    /* If this fails, then the node has already been removed. */
+    if(!found_htn || cds_lfht_del(ns->ht, found_htn) != 0) {
+        rcu_read_unlock();
+        return UA_ERROR;
+    }
+
+    UA_NodeStore_Entry *entry = caa_container_of(found_htn, UA_NodeStore_Entry, htn);
+    call_rcu(&entry->rcu_head, markDead);
+    rcu_read_unlock();
+
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_get(const UA_NodeStore *ns, const UA_NodeId *nodeid, const UA_Node **managedNode) {
+    hash_t nhash = hash(nodeid);
+    struct cds_lfht_iter iter;
+
+    rcu_read_lock();
+    cds_lfht_lookup(ns->ht, nhash, compare, nodeid, &iter);
+    UA_NodeStore_Entry *found_entry = (UA_NodeStore_Entry *)cds_lfht_iter_get_node(&iter);
+
+    if(!found_entry) {
+        rcu_read_unlock();
+        return UA_ERROR;  // TODO: UA_NOTFOUND
+    }
+
+    /* This is done within a read-lock. The node will not be marked dead within a read-lock. */
+    uatomic_inc(&found_entry->readcount);
+    rcu_read_unlock();
+
+    *managedNode = &found_entry->node;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeStore_iterate(const UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor) {
+    if(ns == UA_NULL || visitor == UA_NULL)
+        return UA_ERROR;
+
+    struct cds_lfht     *ht = ns->ht;
+    struct cds_lfht_iter iter;
+
+    rcu_read_lock();
+    cds_lfht_first(ht, &iter);
+    while(iter.node != UA_NULL) {
+        UA_NodeStore_Entry *found_entry = (UA_NodeStore_Entry *)cds_lfht_iter_get_node(&iter);
+        uatomic_inc(&found_entry->readcount);
+        const UA_Node      *node = &found_entry->node;
+        rcu_read_unlock();
+        visitor(node);
+        UA_NodeStore_releaseManagedNode((UA_Node *)node);
+        rcu_read_lock();
+        cds_lfht_next(ht, &iter);
+    }
+    rcu_read_unlock();
+
+    return UA_SUCCESS;
+}

+ 144 - 0
src/server/ua_securechannel_manager.c

@@ -0,0 +1,144 @@
+#include "ua_securechannel_manager.h"
+
+struct channel_list_entry {
+    UA_SecureChannel channel;
+    LIST_ENTRY(channel_list_entry) pointers;
+};
+
+struct UA_SecureChannelManager {
+    UA_Int32    maxChannelCount;
+    UA_DateTime maxChannelLifetime;
+    LIST_HEAD(channel_list, channel_list_entry) channels;
+    UA_MessageSecurityMode securityMode;
+    UA_String   endpointUrl;
+    UA_DateTime channelLifeTime;
+    UA_Int32    lastChannelId;
+    UA_UInt32   lastTokenId;
+};
+
+UA_Int32 UA_SecureChannelManager_new(UA_SecureChannelManager **cm, UA_UInt32 maxChannelCount,
+                                     UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
+                                     UA_UInt32 startTokenId, UA_String *endpointUrl) {
+    UA_alloc((void **)cm, sizeof(UA_SecureChannelManager));
+    UA_SecureChannelManager *channelManager = *cm;
+    LIST_INIT(&channelManager->channels);
+    channelManager->lastChannelId      = startChannelId;
+    channelManager->lastTokenId        = startTokenId;
+    UA_String_copy(endpointUrl, &channelManager->endpointUrl);
+    channelManager->maxChannelLifetime = tokenLifetime;
+    channelManager->maxChannelCount    = maxChannelCount;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannelManager_delete(UA_SecureChannelManager *cm) {
+    struct channel_list_entry *entry;
+    LIST_FOREACH(entry, &cm->channels, pointers) {
+        // deleting a securechannel means closing the connection
+        // delete the binaryconnction beforehand. so there is no pointer
+        // todo: unbind entry->channel.connection;
+        LIST_REMOVE(entry, pointers);
+        UA_SecureChannel_deleteMembers(&entry->channel);
+        UA_free(entry);
+    }
+    UA_String_deleteMembers(&cm->endpointUrl);
+    UA_free(cm);
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannelManager_open(UA_SecureChannelManager           *cm,
+                                      UA_Connection                     *conn,
+                                      const UA_OpenSecureChannelRequest *request,
+                                      UA_OpenSecureChannelResponse      *response) {
+    struct channel_list_entry *entry;
+    UA_alloc((void **)&entry, sizeof(struct channel_list_entry));
+
+    entry->channel.connection = conn;
+    entry->channel.securityToken.channelId       = cm->lastChannelId++;
+    entry->channel.securityToken.tokenId         = cm->lastTokenId++;
+    entry->channel.securityToken.createdAt       = UA_DateTime_now();
+    entry->channel.securityToken.revisedLifetime =
+        request->requestedLifetime > cm->maxChannelLifetime ?
+        cm->maxChannelLifetime : request->requestedLifetime;
+
+    switch(request->securityMode) {
+    case UA_SECURITYMODE_INVALID:
+        printf("UA_SecureChannel_processOpenRequest - client demands invalid \n");
+        break;
+
+    case UA_SECURITYMODE_NONE:
+        UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
+        entry->channel.clientAsymAlgSettings.receiverCertificateThumbprint.data   = UA_NULL;
+        entry->channel.clientAsymAlgSettings.receiverCertificateThumbprint.length = -1;
+        entry->channel.clientAsymAlgSettings.senderCertificate.data   = UA_NULL;
+        entry->channel.clientAsymAlgSettings.senderCertificate.length = -1;
+        break;
+
+    case UA_SECURITYMODE_SIGNANDENCRYPT:
+        printf("UA_SecureChannel_processOpenRequest - client demands signed & encrypted \n");
+        //TODO check if senderCertificate and ReceiverCertificateThumbprint are present
+        break;
+    }
+
+    UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",
+                          (UA_String *)&entry->channel.serverAsymAlgSettings.securityPolicyUri);
+    LIST_INSERT_HEAD(&cm->channels, entry, pointers);
+
+    response->serverProtocolVersion = 0;
+    UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
+    UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
+    UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
+
+    conn->channel = &entry->channel;
+
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannelManager_renew(UA_SecureChannelManager           *cm,
+                                       UA_Connection                     *conn,
+                                       const UA_OpenSecureChannelRequest *request,
+                                       UA_OpenSecureChannelResponse      *response) {
+
+    UA_SecureChannel *channel = conn->channel;
+    if(channel == UA_NULL)
+        return UA_ERROR;
+
+    channel->securityToken.tokenId         = cm->lastTokenId++;
+    channel->securityToken.createdAt       = UA_DateTime_now(); // todo: is wanted?
+    channel->securityToken.revisedLifetime = request->requestedLifetime > cm->maxChannelLifetime ?
+                                             cm->maxChannelLifetime : request->requestedLifetime;
+
+    UA_SecureChannel_generateNonce(&channel->serverNonce);
+    UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
+    UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
+
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId,
+                                     UA_SecureChannel **channel) {
+    struct channel_list_entry *entry;
+    LIST_FOREACH(entry, &cm->channels, pointers) {
+        if(entry->channel.securityToken.channelId == channelId) {
+            *channel = &entry->channel;
+            return UA_SUCCESS;
+        }
+    }
+    *channel = UA_NULL;
+    return UA_ERROR;
+}
+
+UA_Int32 UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
+    //TODO lock access
+    // TODO: close the binaryconnection if it is still open. So we dö not have stray pointers..
+    struct channel_list_entry *entry;
+    LIST_FOREACH(entry, &cm->channels, pointers) {
+        if(entry->channel.securityToken.channelId == channelId) {
+            UA_SecureChannel_deleteMembers(&entry->channel);
+            LIST_REMOVE(entry, pointers);
+            UA_free(entry);
+            return UA_SUCCESS;
+        }
+    }
+    //TODO notify server application that secureChannel has been closed part 6 - §7.1.4
+    return UA_ERROR;
+}

+ 24 - 0
src/server/ua_securechannel_manager.h

@@ -0,0 +1,24 @@
+#ifndef UA_CHANNEL_MANAGER_H_
+#define UA_CHANNEL_MANAGER_H_
+
+#include "ua_types_generated.h"
+#include "ua_securechannel.h"
+
+struct UA_SecureChannelManager;
+typedef struct UA_SecureChannelManager UA_SecureChannelManager;
+
+UA_Int32 UA_SecureChannelManager_new(UA_SecureChannelManager **cm, UA_UInt32 maxChannelCount,
+                                     UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
+                                     UA_UInt32 startTokenId, UA_String *endpointUrl);
+UA_Int32 UA_SecureChannelManager_delete(UA_SecureChannelManager *cm);
+UA_Int32 UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
+                                      const UA_OpenSecureChannelRequest *request,
+                                      UA_OpenSecureChannelResponse *response);
+UA_Int32 UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
+                                       const UA_OpenSecureChannelRequest *request,
+                                       UA_OpenSecureChannelResponse *response);
+UA_Int32 UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId,
+                                     UA_SecureChannel **channel);
+UA_Int32 UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId);
+
+#endif /* UA_CHANNEL_MANAGER_H_ */

+ 540 - 6
src/server/ua_server.c

@@ -1,8 +1,542 @@
 #include "ua_server.h"
-#include "ua_application.h"
+#include "ua_services_internal.h" // AddReferences
+#include "ua_namespace_0.h"
 
-struct UA_Server {
-	// SL_ChannelManager *cm;
-	// UA_SessionManager sm;
-	Application application;
-};
+UA_Int32 UA_Server_deleteMembers(UA_Server *server) {
+    UA_ApplicationDescription_deleteMembers(&server->description);
+    UA_SecureChannelManager_delete(server->secureChannelManager);
+    UA_SessionManager_delete(server->sessionManager);
+    UA_NodeStore_delete(server->nodestore);
+    UA_ByteString_deleteMembers(&server->serverCertificate);
+    return UA_SUCCESS;
+}
+
+void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
+    UA_ApplicationDescription_init(&server->description);
+    UA_ByteString_init(&server->serverCertificate);
+#define MAXCHANNELCOUNT 100
+#define STARTCHANNELID 1
+#define TOKENLIFETIME 10000
+#define STARTTOKENID 1
+    UA_SecureChannelManager_new(&server->secureChannelManager, MAXCHANNELCOUNT,
+                                TOKENLIFETIME, STARTCHANNELID, STARTTOKENID, endpointUrl);
+
+#define MAXSESSIONCOUNT 1000
+#define SESSIONLIFETIME 10000
+#define STARTSESSIONID 1
+    UA_SessionManager_new(&server->sessionManager, MAXSESSIONCOUNT, SESSIONLIFETIME,
+                          STARTSESSIONID);
+
+    // todo: get this out of here!!!
+    // fill the UA_borrowed_ table that has been declaed in ua_namespace.c
+    for(UA_Int32 i = 0;i < SIZE_UA_VTABLE;i++) {
+        UA_borrowed_.types[i] = UA_.types[i];
+        UA_borrowed_.types[i].delete = (UA_Int32 (*)(void *))phantom_delete;
+        UA_borrowed_.types[i].deleteMembers = (UA_Int32 (*)(void *))phantom_delete;
+    }
+
+    UA_NodeStore_new(&server->nodestore);
+    //ns0: C2UA_STRING("http://opcfoundation.org/UA/"));
+    //ns1: C2UA_STRING("http://localhost:16664/open62541/"));
+
+    /**************/
+    /* References */
+    /**************/
+
+    // ReferenceType Ids
+    UA_ExpandedNodeId RefTypeId_References; NS0EXPANDEDNODEID(RefTypeId_References, 31);
+    UA_ExpandedNodeId RefTypeId_NonHierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_NonHierarchicalReferences, 32);
+    UA_ExpandedNodeId RefTypeId_HierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_HierarchicalReferences, 33);
+    UA_ExpandedNodeId RefTypeId_HasChild; NS0EXPANDEDNODEID(RefTypeId_HasChild, 34);
+    UA_ExpandedNodeId RefTypeId_Organizes; NS0EXPANDEDNODEID(RefTypeId_Organizes, 35);
+    UA_ExpandedNodeId RefTypeId_HasEventSource; NS0EXPANDEDNODEID(RefTypeId_HasEventSource, 36);
+    UA_ExpandedNodeId RefTypeId_HasModellingRule; NS0EXPANDEDNODEID(RefTypeId_HasModellingRule, 37);
+    UA_ExpandedNodeId RefTypeId_HasEncoding; NS0EXPANDEDNODEID(RefTypeId_HasEncoding, 38);
+    UA_ExpandedNodeId RefTypeId_HasDescription; NS0EXPANDEDNODEID(RefTypeId_HasDescription, 39);
+    UA_ExpandedNodeId RefTypeId_HasTypeDefinition; NS0EXPANDEDNODEID(RefTypeId_HasTypeDefinition, 40);
+    UA_ExpandedNodeId RefTypeId_GeneratesEvent; NS0EXPANDEDNODEID(RefTypeId_GeneratesEvent, 41);
+    UA_ExpandedNodeId RefTypeId_Aggregates; NS0EXPANDEDNODEID(RefTypeId_Aggregates, 44);
+    UA_ExpandedNodeId RefTypeId_HasSubtype; NS0EXPANDEDNODEID(RefTypeId_HasSubtype, 45);
+    UA_ExpandedNodeId RefTypeId_HasProperty; NS0EXPANDEDNODEID(RefTypeId_HasProperty, 46);
+    UA_ExpandedNodeId RefTypeId_HasComponent; NS0EXPANDEDNODEID(RefTypeId_HasComponent, 47);
+    UA_ExpandedNodeId RefTypeId_HasNotifier; NS0EXPANDEDNODEID(RefTypeId_HasNotifier, 48);
+    UA_ExpandedNodeId RefTypeId_HasOrderedComponent; NS0EXPANDEDNODEID(RefTypeId_HasOrderedComponent, 49);
+    UA_ExpandedNodeId RefTypeId_HasModelParent; NS0EXPANDEDNODEID(RefTypeId_HasModelParent, 50);
+    UA_ExpandedNodeId RefTypeId_FromState; NS0EXPANDEDNODEID(RefTypeId_FromState, 51);
+    UA_ExpandedNodeId RefTypeId_ToState; NS0EXPANDEDNODEID(RefTypeId_ToState, 52);
+    UA_ExpandedNodeId RefTypeId_HasCause; NS0EXPANDEDNODEID(RefTypeId_HasCause, 53);
+    UA_ExpandedNodeId RefTypeId_HasEffect; NS0EXPANDEDNODEID(RefTypeId_HasEffect, 54);
+    UA_ExpandedNodeId RefTypeId_HasHistoricalConfiguration; NS0EXPANDEDNODEID(RefTypeId_HasHistoricalConfiguration, 56);
+
+#define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID) do { \
+    static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID;    \
+    UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID);       \
+    NODE##REFTYPE##TARGET_NODEID.referenceTypeId = REFTYPE.nodeId;     \
+    NODE##REFTYPE##TARGET_NODEID.isInverse       = INVERSE; \
+    NODE##REFTYPE##TARGET_NODEID.targetId = TARGET_NODEID; \
+    AddReference(server->nodestore, (UA_Node *)NODE, &NODE##REFTYPE##TARGET_NODEID); \
+    } while(0)
+    
+    UA_ReferenceTypeNode *references;
+    UA_ReferenceTypeNode_new(&references);
+    references->nodeId    = RefTypeId_References.nodeId;
+    references->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("References", &references->browseName);
+    UA_LocalizedText_copycstring("References", &references->displayName);
+    UA_LocalizedText_copycstring("References", &references->description);
+    references->isAbstract = UA_TRUE;
+    references->symmetric  = UA_TRUE;
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&references, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hierarchicalreferences;
+    UA_ReferenceTypeNode_new(&hierarchicalreferences);
+    hierarchicalreferences->nodeId    = RefTypeId_HierarchicalReferences.nodeId;
+    hierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HierarchicalReferences", &hierarchicalreferences->browseName);
+    UA_LocalizedText_copycstring("HierarchicalReferences", &hierarchicalreferences->displayName);
+    UA_LocalizedText_copycstring("HierarchicalReferences", &hierarchicalreferences->description);
+    hierarchicalreferences->isAbstract = UA_TRUE;
+    hierarchicalreferences->symmetric  = UA_FALSE;
+    ADDREFERENCE(hierarchicalreferences, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_References);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hierarchicalreferences, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *nonhierarchicalreferences;
+    UA_ReferenceTypeNode_new(&nonhierarchicalreferences);
+    nonhierarchicalreferences->nodeId    = RefTypeId_NonHierarchicalReferences.nodeId;
+    nonhierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("NonHierarchicalReferences", &nonhierarchicalreferences->browseName);
+    UA_LocalizedText_copycstring("NonHierarchicalReferences", &nonhierarchicalreferences->displayName);
+    UA_LocalizedText_copycstring("NonHierarchicalReferences", &nonhierarchicalreferences->description);
+    nonhierarchicalreferences->isAbstract = UA_TRUE;
+    nonhierarchicalreferences->symmetric  = UA_FALSE;
+    ADDREFERENCE(nonhierarchicalreferences, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_References);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&nonhierarchicalreferences, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *haschild;
+    UA_ReferenceTypeNode_new(&haschild);
+    haschild->nodeId    = RefTypeId_HasChild.nodeId;
+    haschild->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasChild", &haschild->browseName);
+    UA_LocalizedText_copycstring("HasChild", &haschild->displayName);
+    UA_LocalizedText_copycstring("HasChild", &haschild->description);
+    haschild->isAbstract = UA_TRUE;
+    haschild->symmetric  = UA_FALSE;
+    ADDREFERENCE(haschild, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haschild, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *organizes;
+    UA_ReferenceTypeNode_new(&organizes);
+    organizes->nodeId    = RefTypeId_Organizes.nodeId;
+    organizes->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("Organizes", &organizes->browseName);
+    UA_LocalizedText_copycstring("Organizes", &organizes->displayName);
+    UA_LocalizedText_copycstring("Organizes", &organizes->description);
+    organizes->isAbstract = UA_FALSE;
+    organizes->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("OrganizedBy", &organizes->inverseName);
+    ADDREFERENCE(organizes, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&organizes, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *haseventsource;
+    UA_ReferenceTypeNode_new(&haseventsource);
+    haseventsource->nodeId    = RefTypeId_HasEventSource.nodeId;
+    haseventsource->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasEventSource", &haseventsource->browseName);
+    UA_LocalizedText_copycstring("HasEventSource", &haseventsource->displayName);
+    UA_LocalizedText_copycstring("HasEventSource", &haseventsource->description);
+    haseventsource->isAbstract = UA_FALSE;
+    haseventsource->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("EventSourceOf", &haseventsource->inverseName);
+    ADDREFERENCE(haseventsource, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haseventsource, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasmodellingrule;
+    UA_ReferenceTypeNode_new(&hasmodellingrule);
+    hasmodellingrule->nodeId    = RefTypeId_HasModellingRule.nodeId;
+    hasmodellingrule->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasModellingRule", &hasmodellingrule->browseName);
+    UA_LocalizedText_copycstring("HasModellingRule", &hasmodellingrule->displayName);
+    UA_LocalizedText_copycstring("HasModellingRule", &hasmodellingrule->description);
+    hasmodellingrule->isAbstract = UA_FALSE;
+    hasmodellingrule->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("ModellingRuleOf", &hasmodellingrule->inverseName);
+    ADDREFERENCE(hasmodellingrule, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasmodellingrule, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasencoding;
+    UA_ReferenceTypeNode_new(&hasencoding);
+    hasencoding->nodeId    = RefTypeId_HasEncoding.nodeId;
+    hasencoding->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasEncoding", &hasencoding->browseName);
+    UA_LocalizedText_copycstring("HasEncoding", &hasencoding->displayName);
+    UA_LocalizedText_copycstring("HasEncoding", &hasencoding->description);
+    hasencoding->isAbstract = UA_FALSE;
+    hasencoding->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("EncodingOf", &hasencoding->inverseName);
+    ADDREFERENCE(hasencoding, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasencoding, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasdescription;
+    UA_ReferenceTypeNode_new(&hasdescription);
+    hasdescription->nodeId    = RefTypeId_HasDescription.nodeId;
+    hasdescription->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasDescription", &hasdescription->browseName);
+    UA_LocalizedText_copycstring("HasDescription", &hasdescription->displayName);
+    UA_LocalizedText_copycstring("HasDescription", &hasdescription->description);
+    hasdescription->isAbstract = UA_FALSE;
+    hasdescription->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("DescriptionOf", &hasdescription->inverseName);
+    ADDREFERENCE(hasdescription, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasdescription, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hastypedefinition;
+    UA_ReferenceTypeNode_new(&hastypedefinition);
+    hastypedefinition->nodeId    = RefTypeId_HasTypeDefinition.nodeId;
+    hastypedefinition->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasTypeDefinition", &hastypedefinition->browseName);
+    UA_LocalizedText_copycstring("HasTypeDefinition", &hastypedefinition->displayName);
+    UA_LocalizedText_copycstring("HasTypeDefinition", &hastypedefinition->description);
+    hastypedefinition->isAbstract = UA_FALSE;
+    hastypedefinition->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("TypeDefinitionOf", &hastypedefinition->inverseName);
+    ADDREFERENCE(hastypedefinition, RefTypeId_HasSubtype, UA_TRUE,  RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hastypedefinition, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *generatesevent;
+    UA_ReferenceTypeNode_new(&generatesevent);
+    generatesevent->nodeId    = RefTypeId_GeneratesEvent.nodeId;
+    generatesevent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("GeneratesEvent", &generatesevent->browseName);
+    UA_LocalizedText_copycstring("GeneratesEvent", &generatesevent->displayName);
+    UA_LocalizedText_copycstring("GeneratesEvent", &generatesevent->description);
+    generatesevent->isAbstract = UA_FALSE;
+    generatesevent->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("GeneratedBy", &generatesevent->inverseName);
+    ADDREFERENCE(generatesevent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&generatesevent, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *aggregates;
+    UA_ReferenceTypeNode_new(&aggregates);
+    aggregates->nodeId    = RefTypeId_Aggregates.nodeId;
+    aggregates->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("Aggregates", &aggregates->browseName);
+    UA_LocalizedText_copycstring("Aggregates", &aggregates->displayName);
+    UA_LocalizedText_copycstring("Aggregates", &aggregates->description);
+    aggregates->isAbstract = UA_TRUE;
+    aggregates->symmetric  = UA_FALSE;
+    ADDREFERENCE(aggregates, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasChild);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&aggregates, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hassubtype;
+    UA_ReferenceTypeNode_new(&hassubtype);
+    hassubtype->nodeId    = RefTypeId_HasSubtype.nodeId;
+    hassubtype->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasSubtype", &hassubtype->browseName);
+    UA_LocalizedText_copycstring("HasSubtype", &hassubtype->displayName);
+    UA_LocalizedText_copycstring("HasSubtype", &hassubtype->description);
+    hassubtype->isAbstract = UA_FALSE;
+    hassubtype->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("SubtypeOf", &hassubtype->inverseName);
+    ADDREFERENCE(hassubtype, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasChild);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hassubtype, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasproperty;
+    UA_ReferenceTypeNode_new(&hasproperty);
+    hasproperty->nodeId    = RefTypeId_HasProperty.nodeId;
+    hasproperty->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasProperty", &hasproperty->browseName);
+    UA_LocalizedText_copycstring("HasProperty", &hasproperty->displayName);
+    UA_LocalizedText_copycstring("HasProperty", &hasproperty->description);
+    hasproperty->isAbstract = UA_FALSE;
+    hasproperty->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("PropertyOf", &hasproperty->inverseName);
+    ADDREFERENCE(hasproperty, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasproperty, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hascomponent;
+    UA_ReferenceTypeNode_new(&hascomponent);
+    hascomponent->nodeId    = RefTypeId_HasComponent.nodeId;
+    hascomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasComponent", &hascomponent->browseName);
+    UA_LocalizedText_copycstring("HasComponent", &hascomponent->displayName);
+    UA_LocalizedText_copycstring("HasComponent", &hascomponent->description);
+    hascomponent->isAbstract = UA_FALSE;
+    hascomponent->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("ComponentOf", &hascomponent->inverseName);
+    ADDREFERENCE(hascomponent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hascomponent, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasnotifier;
+    UA_ReferenceTypeNode_new(&hasnotifier);
+    hasnotifier->nodeId    = RefTypeId_HasNotifier.nodeId;
+    hasnotifier->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasNotifier", &hasnotifier->browseName);
+    UA_LocalizedText_copycstring("HasNotifier", &hasnotifier->displayName);
+    UA_LocalizedText_copycstring("HasNotifier", &hasnotifier->description);
+    hasnotifier->isAbstract = UA_FALSE;
+    hasnotifier->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("NotifierOf", &hasnotifier->inverseName);
+    ADDREFERENCE(hasnotifier, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasEventSource);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasnotifier, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasorderedcomponent;
+    UA_ReferenceTypeNode_new(&hasorderedcomponent);
+    hasorderedcomponent->nodeId    = RefTypeId_HasOrderedComponent.nodeId;
+    hasorderedcomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasOrderedComponent", &hasorderedcomponent->browseName);
+    UA_LocalizedText_copycstring("HasOrderedComponent", &hasorderedcomponent->displayName);
+    UA_LocalizedText_copycstring("HasOrderedComponent", &hasorderedcomponent->description);
+    hasorderedcomponent->isAbstract = UA_FALSE;
+    hasorderedcomponent->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("OrderedComponentOf", &hasorderedcomponent->inverseName);
+    ADDREFERENCE(hasorderedcomponent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_HasComponent);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasorderedcomponent, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hasmodelparent;
+    UA_ReferenceTypeNode_new(&hasmodelparent);
+    hasmodelparent->nodeId    = RefTypeId_HasModelParent.nodeId;
+    hasmodelparent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasModelParent", &hasmodelparent->browseName);
+    UA_LocalizedText_copycstring("HasModelParent", &hasmodelparent->displayName);
+    UA_LocalizedText_copycstring("HasModelParent", &hasmodelparent->description);
+    hasmodelparent->isAbstract = UA_FALSE;
+    hasmodelparent->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("ModelParentOf", &hasmodelparent->inverseName);
+    ADDREFERENCE(hasmodelparent, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hasmodelparent, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *fromstate;
+    UA_ReferenceTypeNode_new(&fromstate);
+    fromstate->nodeId    = RefTypeId_FromState.nodeId;
+    fromstate->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("FromState", &fromstate->browseName);
+    UA_LocalizedText_copycstring("FromState", &fromstate->displayName);
+    UA_LocalizedText_copycstring("FromState", &fromstate->description);
+    fromstate->isAbstract = UA_FALSE;
+    fromstate->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("ToTransition", &fromstate->inverseName);
+    ADDREFERENCE(fromstate, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&fromstate, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *tostate;
+    UA_ReferenceTypeNode_new(&tostate);
+    tostate->nodeId    = RefTypeId_ToState.nodeId;
+    tostate->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("ToState", &tostate->browseName);
+    UA_LocalizedText_copycstring("ToState", &tostate->displayName);
+    UA_LocalizedText_copycstring("ToState", &tostate->description);
+    tostate->isAbstract = UA_FALSE;
+    tostate->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("FromTransition", &tostate->inverseName);
+    ADDREFERENCE(tostate, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&tostate, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hascause;
+    UA_ReferenceTypeNode_new(&hascause);
+    hascause->nodeId    = RefTypeId_HasCause.nodeId;
+    hascause->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasCause", &hascause->browseName);
+    UA_LocalizedText_copycstring("HasCause", &hascause->displayName);
+    UA_LocalizedText_copycstring("HasCause", &hascause->description);
+    hascause->isAbstract = UA_FALSE;
+    hascause->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("MayBeCausedBy", &hascause->inverseName);
+    ADDREFERENCE(hascause, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hascause, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *haseffect;
+    UA_ReferenceTypeNode_new(&haseffect);
+    haseffect->nodeId    = RefTypeId_HasEffect.nodeId;
+    haseffect->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasEffect", &haseffect->browseName);
+    UA_LocalizedText_copycstring("HasEffect", &haseffect->displayName);
+    UA_LocalizedText_copycstring("HasEffect", &haseffect->description);
+    haseffect->isAbstract = UA_FALSE;
+    haseffect->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("MayBeEffectedBy", &haseffect->inverseName);
+    ADDREFERENCE(haseffect, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_NonHierarchicalReferences);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&haseffect, UA_NODESTORE_INSERT_UNIQUE);
+
+    UA_ReferenceTypeNode *hashistoricalconfiguration;
+    UA_ReferenceTypeNode_new(&hashistoricalconfiguration);
+    hashistoricalconfiguration->nodeId    = RefTypeId_HasHistoricalConfiguration.nodeId;
+    hashistoricalconfiguration->nodeClass = UA_NODECLASS_REFERENCETYPE;
+    UA_QualifiedName_copycstring("HasHistoricalConfiguration", &hashistoricalconfiguration->browseName);
+    UA_LocalizedText_copycstring("HasHistoricalConfiguration", &hashistoricalconfiguration->displayName);
+    UA_LocalizedText_copycstring("HasHistoricalConfiguration", &hashistoricalconfiguration->description);
+    hashistoricalconfiguration->isAbstract = UA_FALSE;
+    hashistoricalconfiguration->symmetric  = UA_FALSE;
+    UA_LocalizedText_copycstring("HistoricalConfigurationOf", &hashistoricalconfiguration->inverseName);
+    ADDREFERENCE(hashistoricalconfiguration, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_Aggregates);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&hashistoricalconfiguration, UA_NODESTORE_INSERT_UNIQUE);
+
+
+    // ObjectTypes (Ids only)
+    UA_ExpandedNodeId ObjTypeId_FolderType; NS0EXPANDEDNODEID(ObjTypeId_FolderType, 61);
+
+    // Objects (Ids only)
+    UA_ExpandedNodeId ObjId_ObjectsFolder; NS0EXPANDEDNODEID(ObjId_ObjectsFolder, 85);
+    UA_ExpandedNodeId ObjId_TypesFolder; NS0EXPANDEDNODEID(ObjId_TypesFolder, 86);
+    UA_ExpandedNodeId ObjId_ViewsFolder; NS0EXPANDEDNODEID(ObjId_ViewsFolder, 87);
+    UA_ExpandedNodeId ObjId_Server; NS0EXPANDEDNODEID(ObjId_Server, 2253);
+    UA_ExpandedNodeId ObjId_ServerArray; NS0EXPANDEDNODEID(ObjId_ServerArray, 2254);
+    UA_ExpandedNodeId ObjId_NamespaceArray; NS0EXPANDEDNODEID(ObjId_NamespaceArray, 2255);
+    UA_ExpandedNodeId ObjId_ServerStatus; NS0EXPANDEDNODEID(ObjId_ServerStatus, 2256);
+    UA_ExpandedNodeId ObjId_ServerCapabilities; NS0EXPANDEDNODEID(ObjId_ServerCapabilities, 2268);
+    UA_ExpandedNodeId ObjId_State; NS0EXPANDEDNODEID(ObjId_State, 2259);
+
+    // FolderType
+    UA_ObjectNode *folderType;
+    UA_ObjectNode_new(&folderType);
+    folderType->nodeId    = NS0NODEID(61);
+    folderType->nodeClass = UA_NODECLASS_OBJECTTYPE; // I should not have to set this manually
+    UA_QualifiedName_copycstring("FolderType", &folderType->browseName);
+    UA_LocalizedText_copycstring("FolderType", &folderType->displayName);
+    UA_LocalizedText_copycstring("FolderType", &folderType->description);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&folderType, UA_NODESTORE_INSERT_UNIQUE);
+
+    // Root
+    UA_ObjectNode *root;
+    UA_ObjectNode_new(&root);
+    root->nodeId    = NS0NODEID(84);
+    root->nodeClass = UA_NODECLASS_OBJECT; // I should not have to set this manually
+    UA_QualifiedName_copycstring("Root", &root->browseName);
+    UA_LocalizedText_copycstring("Root", &root->displayName);
+    UA_LocalizedText_copycstring("Root", &root->description);
+    ADDREFERENCE(root, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
+    ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ObjectsFolder);
+    ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder);
+    ADDREFERENCE(root, RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder);
+    /* root becomes a managed node. we need to release it at the end.*/
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&root, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
+
+    // Objects
+    UA_ObjectNode *objects;
+    UA_ObjectNode_new(&objects);
+    objects->nodeId    = ObjId_ObjectsFolder.nodeId;
+    objects->nodeClass = UA_NODECLASS_OBJECT;
+    UA_QualifiedName_copycstring("Objects", &objects->browseName);
+    UA_LocalizedText_copycstring("Objects", &objects->displayName);
+    UA_LocalizedText_copycstring("Objects", &objects->description);
+    ADDREFERENCE(objects, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
+    ADDREFERENCE(objects, RefTypeId_Organizes, UA_FALSE, ObjId_Server);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&objects, UA_NODESTORE_INSERT_UNIQUE);
+
+    // Types
+    UA_ObjectNode *types;
+    UA_ObjectNode_new(&types);
+    types->nodeId    = ObjId_TypesFolder.nodeId;
+    types->nodeClass = UA_NODECLASS_OBJECT;
+    UA_QualifiedName_copycstring("Types", &types->browseName);
+    UA_LocalizedText_copycstring("Types", &types->displayName);
+    UA_LocalizedText_copycstring("Types", &types->description);
+    ADDREFERENCE(types, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&types, UA_NODESTORE_INSERT_UNIQUE);
+
+    // Views
+    UA_ObjectNode *views;
+    UA_ObjectNode_new(&views);
+    views->nodeId    = ObjId_ViewsFolder.nodeId;
+    views->nodeClass = UA_NODECLASS_OBJECT;
+    UA_QualifiedName_copycstring("Views", &views->browseName);
+    UA_LocalizedText_copycstring("Views", &views->displayName);
+    UA_LocalizedText_copycstring("Views", &views->description);
+    ADDREFERENCE(views, RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&views, UA_NODESTORE_INSERT_UNIQUE);
+
+    // Server
+    UA_ObjectNode *servernode;
+    UA_ObjectNode_new(&servernode);
+    servernode->nodeId    = ObjId_Server.nodeId;
+    servernode->nodeClass = UA_NODECLASS_OBJECT;
+    UA_QualifiedName_copycstring("Server", &servernode->browseName);
+    UA_LocalizedText_copycstring("Server", &servernode->displayName);
+    UA_LocalizedText_copycstring("Server", &servernode->description);
+    ADDREFERENCE(servernode, RefTypeId_HasComponent, UA_FALSE, ObjId_ServerCapabilities);
+    ADDREFERENCE(servernode, RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray);
+    ADDREFERENCE(servernode, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus);
+    ADDREFERENCE(servernode, RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray);
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&servernode, UA_NODESTORE_INSERT_UNIQUE);
+
+    // NamespaceArray
+    UA_VariableNode *namespaceArray;
+    UA_VariableNode_new(&namespaceArray);
+    namespaceArray->nodeId    = ObjId_NamespaceArray.nodeId;
+    namespaceArray->nodeClass = UA_NODECLASS_VARIABLE; //FIXME: this should go into _new?
+    UA_QualifiedName_copycstring("NodeStoreArray", &namespaceArray->browseName);
+    UA_LocalizedText_copycstring("NodeStoreArray", &namespaceArray->displayName);
+    UA_LocalizedText_copycstring("NodeStoreArray", &namespaceArray->description);
+    UA_Array_new((void **)&namespaceArray->value.data, 2, &UA_.types[UA_STRING]);
+    namespaceArray->value.vt = &UA_.types[UA_STRING];
+    namespaceArray->value.arrayLength = 2;
+    UA_String_copycstring("http://opcfoundation.org/UA/", &((UA_String *)((namespaceArray->value).data))[0]);
+    UA_String_copycstring("http://localhost:16664/open62541/",
+                          &((UA_String *)(((namespaceArray)->value).data))[1]);
+    namespaceArray->arrayDimensionsSize = 1;
+    UA_UInt32 *dimensions = UA_NULL;
+    UA_alloc((void **)&dimensions, sizeof(UA_UInt32));
+    *dimensions = 2;
+    namespaceArray->arrayDimensions = dimensions;
+    namespaceArray->dataType = NS0NODEID(UA_STRING_NS0);
+    namespaceArray->valueRank       = 1;
+    namespaceArray->minimumSamplingInterval = 1.0;
+    namespaceArray->historizing     = UA_FALSE;
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&namespaceArray, UA_NODESTORE_INSERT_UNIQUE);
+
+    // ServerStatus
+    UA_VariableNode *serverstatus;
+    UA_VariableNode_new(&serverstatus);
+    serverstatus->nodeId    = ObjId_ServerStatus.nodeId;
+    serverstatus->nodeClass = UA_NODECLASS_VARIABLE;
+    UA_QualifiedName_copycstring("ServerStatus", &serverstatus->browseName);
+    UA_LocalizedText_copycstring("ServerStatus", &serverstatus->displayName);
+    UA_LocalizedText_copycstring("ServerStatus", &serverstatus->description);
+    UA_ServerStatusDataType *status;
+    UA_ServerStatusDataType_new(&status);
+    status->startTime   = UA_DateTime_now();
+    status->currentTime = UA_DateTime_now();
+    status->state       = UA_SERVERSTATE_RUNNING;
+    UA_String_copycstring("open62541.org", &status->buildInfo.productUri);
+    UA_String_copycstring("open62541", &status->buildInfo.manufacturerName);
+    UA_String_copycstring("open62541", &status->buildInfo.productName);
+    UA_String_copycstring("0.0", &status->buildInfo.softwareVersion);
+    UA_String_copycstring("0.0", &status->buildInfo.buildNumber);
+    status->buildInfo.buildDate     = UA_DateTime_now();
+    status->secondsTillShutdown     = 99999999;
+    UA_LocalizedText_copycstring("because", &status->shutdownReason);
+    serverstatus->value.vt          = &UA_.types[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
+    serverstatus->value.arrayLength = 1;
+    serverstatus->value.data        = status;
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&serverstatus, UA_NODESTORE_INSERT_UNIQUE);
+
+    // State (Component of ServerStatus)
+    UA_VariableNode *state;
+    UA_VariableNode_new(&state);
+    state->nodeId    = ObjId_State.nodeId;
+    state->nodeClass = UA_NODECLASS_VARIABLE;
+    UA_QualifiedName_copycstring("State", &state->browseName);
+    UA_LocalizedText_copycstring("State", &state->displayName);
+    UA_LocalizedText_copycstring("State", &state->description);
+    state->value.vt = &UA_borrowed_.types[UA_SERVERSTATE];
+    state->value.arrayDimensionsLength = 1; // added to ensure encoding in readreponse
+    state->value.arrayLength = 1;
+    state->value.data = &status->state; // points into the other object.
+    UA_NodeStore_insert(server->nodestore, (UA_Node**)&state, UA_NODESTORE_INSERT_UNIQUE);
+
+    //TODO: free(namespaceArray->value.data) later or forget it
+
+    /* UA_VariableNode* v = (UA_VariableNode*)np; */
+    /* UA_Array_new((void**)&v->value.data, 2, &UA_.types[UA_STRING]); */
+    /* v->value.vt = &UA_.types[UA_STRING]; */
+    /* v->value.arrayLength = 2; */
+    /* UA_String_copycstring("http://opcfoundation.org/UA/",&((UA_String *)((v->value).data))[0]); */
+    /* UA_String_copycstring("http://localhost:16664/open62541/",&((UA_String *)(((v)->value).data))[1]); */
+    /* v->dataType.identifierType = UA_NODEIDTYPE_FOURBYTE; */
+    /* v->dataType.identifier.numeric = UA_STRING_NS0; */
+    /* v->valueRank = 1; */
+    /* v->minimumSamplingInterval = 1.0; */
+    /* v->historizing = UA_FALSE; */
+    /* UA_NodeStore_insert(server->nodestore,np); */
+
+    UA_NodeStore_releaseManagedNode((const UA_Node *)root);
+}

+ 24 - 2
src/server/ua_server.h

@@ -1,7 +1,29 @@
 #ifndef UA_SERVER_H_
 #define UA_SERVER_H_
 
-struct UA_Server;
-typedef struct UA_Server UA_Server;
+#include "ua_types.h"
+#include "ua_types_generated.h"
+#include "ua_nodestore.h"
+#include "ua_securechannel_manager.h"
+#include "ua_session_manager.h"
+#include "util/ua_log.h"
+
+/**
+   @defgroup server Server
+ */
+
+typedef struct UA_Server {
+    UA_ApplicationDescription description;
+    UA_SecureChannelManager *secureChannelManager;
+    UA_SessionManager *sessionManager;
+    UA_NodeStore *nodestore;
+    UA_Logger logger;
+    UA_ByteString serverCertificate;
+} UA_Server;
+
+void UA_Server_init(UA_Server *server, UA_String *endpointUrl);
+UA_Int32 UA_Server_deleteMembers(UA_Server *server);
+UA_Int32 UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
+                                        const UA_ByteString *msg);
 
 #endif /* UA_SERVER_H_ */

+ 354 - 0
src/server/ua_server_binary.c

@@ -0,0 +1,354 @@
+#include "ua_server.h"
+#include "ua_services.h"
+#include "ua_statuscodes.h"
+
+static void processHello(UA_Connection *connection, const UA_ByteString *msg,
+                         UA_UInt32 *pos) {
+    UA_TcpHelloMessage helloMessage;
+    if(UA_TcpHelloMessage_decodeBinary(msg, pos, &helloMessage) != UA_SUCCESS) {
+        connection->close(connection->callbackHandle);
+        return;
+    }
+    connection->remoteConf.maxChunkCount   = helloMessage.maxChunkCount;
+    connection->remoteConf.maxMessageSize  = helloMessage.maxMessageSize;
+    connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
+    connection->remoteConf.recvBufferSize  = helloMessage.receiveBufferSize;
+    connection->remoteConf.sendBufferSize  = helloMessage.sendBufferSize;
+
+    connection->state = UA_CONNECTION_ESTABLISHED;
+
+    // build acknowledge response
+    UA_TcpAcknowledgeMessage ackMessage;
+    ackMessage.protocolVersion   = connection->localConf.protocolVersion;
+    ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
+    ackMessage.sendBufferSize    = connection->localConf.sendBufferSize;
+    ackMessage.maxMessageSize    = connection->localConf.maxMessageSize;
+    ackMessage.maxChunkCount     = connection->localConf.maxChunkCount;
+
+    UA_TcpMessageHeader ackHeader;
+    ackHeader.messageType = UA_MESSAGETYPE_ACK;
+    ackHeader.isFinal     = 'F';
+    ackHeader.messageSize = UA_TcpAcknowledgeMessage_calcSizeBinary(&ackMessage) +
+                            UA_TcpMessageHeader_calcSizeBinary(&ackHeader);
+
+    UA_ByteString ack_msg;
+    UA_UInt32 tmpPos = 0;
+    UA_ByteString_newMembers(&ack_msg, ackHeader.messageSize);
+    UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos);
+    UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos);
+    UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &ack_msg };
+    connection->write(connection->callbackHandle, answer_buf);
+    UA_ByteString_deleteMembers(&ack_msg);
+}
+
+static void processOpen(UA_Connection *connection, UA_Server *server,
+                        const UA_ByteString *msg, UA_UInt32 *pos) {
+    if(connection->state != UA_CONNECTION_ESTABLISHED) {
+        // was hello exchanged before?
+        if(connection->state == UA_CONNECTION_OPENING)
+            connection->close(connection->callbackHandle);
+        return;
+    }
+
+    UA_UInt32 secureChannelId;
+    UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
+
+    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+    UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader);
+
+    UA_SequenceHeader seqHeader;
+    UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader);
+
+    UA_ExpandedNodeId requestType;
+    UA_ExpandedNodeId_decodeBinary(msg, pos, &requestType);
+
+    if(requestType.nodeId.identifier.numeric != 446) {
+        // todo: handle error
+    }
+
+    UA_OpenSecureChannelRequest r;
+    UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r);
+
+    // perform request
+    UA_OpenSecureChannelResponse p;
+    UA_OpenSecureChannelResponse_init(&p);
+    Service_OpenSecureChannel(server, connection, &r, &p);
+
+    // response
+    UA_TcpMessageHeader respHeader;
+    respHeader.messageType = UA_MESSAGETYPE_OPN;
+    respHeader.isFinal     = 'F';
+    respHeader.messageSize = 8+4; //header + securechannelid
+
+    UA_ExpandedNodeId responseType;
+    NS0EXPANDEDNODEID(responseType, 449);
+
+    respHeader.messageSize += UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader);
+    respHeader.messageSize += UA_SequenceHeader_calcSizeBinary(&seqHeader);
+    respHeader.messageSize += UA_ExpandedNodeId_calcSizeBinary(&responseType);
+    respHeader.messageSize += UA_OpenSecureChannelResponse_calcSizeBinary(&p);
+
+    UA_ByteString resp_msg;
+    UA_UInt32 tmpPos = 0;
+    UA_ByteString_newMembers(&resp_msg, respHeader.messageSize);
+    UA_TcpMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos);
+    UA_UInt32_encodeBinary(&p.securityToken.channelId, &resp_msg, &tmpPos);
+    UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back
+    UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back
+    UA_ExpandedNodeId_encodeBinary(&responseType, &resp_msg, &tmpPos);
+    UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos);
+    
+    UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &resp_msg };
+    connection->write(connection->callbackHandle, answer_buf);
+    UA_ByteString_deleteMembers(&resp_msg);
+}
+
+static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r) {
+    r->requestHandle   = p->requestHandle;
+    r->serviceResult   = UA_STATUSCODE_GOOD;
+    r->stringTableSize = 0;
+    r->timestamp       = UA_DateTime_now();
+}
+
+#define CHECK_PROCESS(CODE, CLEANUP) \
+    do {                             \
+        if(CODE != UA_SUCCESS) {     \
+            CLEANUP;                 \
+            goto clean_up;           \
+        } } while(0)
+
+#define INVOKE_SERVICE(TYPE) do {                                                                         \
+        UA_##TYPE##Request p;                                                                             \
+        UA_##TYPE##Response r;                                                                            \
+        CHECK_PROCESS(UA_##TYPE##Request_decodeBinary(msg, pos, &p),; );                                  \
+        UA_##TYPE##Response_init(&r);                                                                     \
+        init_response_header(&p.requestHeader, &r.responseHeader);                                        \
+        DBG_VERBOSE(printf("Invoke Service: %s\n", # TYPE));                                              \
+        Service_##TYPE(server, channel->session, &p, &r);                                                 \
+        DBG_VERBOSE(printf("Finished Service: %s\n", # TYPE));                                            \
+        UA_ByteString_newMembers(&responseBuf.strings[1], UA_##TYPE##Response_calcSizeBinary(&r));        \
+        UA_##TYPE##Response_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);                       \
+        UA_##TYPE##Request_deleteMembers(&p);                                                             \
+        UA_##TYPE##Response_deleteMembers(&r);                                                            \
+        responseType = requestType.nodeId.identifier.numeric + 3;                                         \
+} while(0)
+
+static void processMessage(UA_Connection *connection, UA_Server *server,
+                           const UA_ByteString *msg, UA_UInt32 *pos) {
+    // 1) Read in the securechannel
+    UA_UInt32 secureChannelId;
+    UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
+    UA_SecureChannel *channel;
+    UA_SecureChannelManager_get(server->secureChannelManager, secureChannelId, &channel);
+
+    // 2) Read the security header
+    UA_UInt32 tokenId;
+    UA_UInt32_decodeBinary(msg, pos, &tokenId);
+    UA_SequenceHeader sequenceHeader;
+    CHECK_PROCESS(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader),; );
+
+    channel->sequenceNumber = sequenceHeader.sequenceNumber;
+    channel->requestId = sequenceHeader.requestId;
+    // todo
+    //UA_SecureChannel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
+    //UA_SecureChannel_checkRequestId(channel,sequenceHeader.requestId);
+
+    // 3) Read the nodeid of the request
+    UA_ExpandedNodeId requestType;
+    CHECK_PROCESS(UA_ExpandedNodeId_decodeBinary(msg, pos, &requestType),; );
+    if(requestType.nodeId.identifierType != UA_NODEIDTYPE_NUMERIC)
+        goto close_connection;
+
+    // 4) process the request
+    UA_ByteStringArray responseBuf;
+    UA_ByteStringArray_init(&responseBuf, 2);
+
+    UA_UInt32 responseType;
+
+    //subtract 2 for binary encoding
+    UA_UInt32 sendOffset = 0;
+    switch(requestType.nodeId.identifier.numeric - 2) {
+    case UA_GETENDPOINTSREQUEST_NS0: {
+        UA_GetEndpointsRequest  p;
+        UA_GetEndpointsResponse r;
+        CHECK_PROCESS(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p),; );
+        UA_GetEndpointsResponse_init(&r);
+        init_response_header(&p.requestHeader, &r.responseHeader);
+        Service_GetEndpoints(server, &p, &r);
+        UA_ByteString_newMembers(&responseBuf.strings[1],
+                                 UA_GetEndpointsResponse_calcSizeBinary(&r));
+        UA_GetEndpointsResponse_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
+        UA_GetEndpointsRequest_deleteMembers(&p);
+        UA_GetEndpointsResponse_deleteMembers(&r);
+        responseType = requestType.nodeId.identifier.numeric + 3;
+        break;
+    }
+
+    case UA_CREATESESSIONREQUEST_NS0: {
+        UA_CreateSessionRequest  p;
+        UA_CreateSessionResponse r;
+        CHECK_PROCESS(UA_CreateSessionRequest_decodeBinary(msg, pos, &p),; );
+        UA_CreateSessionResponse_init(&r);
+        init_response_header(&p.requestHeader, &r.responseHeader);
+        Service_CreateSession(server, channel,  &p, &r);
+        UA_ByteString_newMembers(&responseBuf.strings[1],
+                                 UA_CreateSessionResponse_calcSizeBinary(&r));
+        UA_CreateSessionResponse_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
+        UA_CreateSessionRequest_deleteMembers(&p);
+        UA_CreateSessionResponse_deleteMembers(&r);
+        responseType = requestType.nodeId.identifier.numeric + 3;
+        break;
+    }
+
+    case UA_ACTIVATESESSIONREQUEST_NS0:
+        INVOKE_SERVICE(ActivateSession);
+        break;
+
+    case UA_READREQUEST_NS0:
+        INVOKE_SERVICE(Read);
+        break;
+
+    case UA_WRITEREQUEST_NS0:
+        INVOKE_SERVICE(Write);
+        break;
+
+    case UA_BROWSEREQUEST_NS0:
+        INVOKE_SERVICE(Browse);
+        break;
+
+    case UA_CREATESUBSCRIPTIONREQUEST_NS0:
+        INVOKE_SERVICE(CreateSubscription);
+        break;
+
+    case UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0:
+        INVOKE_SERVICE(TranslateBrowsePathsToNodeIds);
+        break;
+
+    case UA_PUBLISHREQUEST_NS0:
+        INVOKE_SERVICE(Publish);
+        break;
+
+    case UA_CREATEMONITOREDITEMSREQUEST_NS0:
+        INVOKE_SERVICE(CreateMonitoredItems);
+        break;
+
+    case UA_SETPUBLISHINGMODEREQUEST_NS0:
+        INVOKE_SERVICE(SetPublishingMode);
+        break;
+
+    default: {
+        printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
+               requestType.nodeId.namespaceIndex, requestType.nodeId.identifier.numeric);
+        UA_RequestHeader  p;
+        UA_ResponseHeader r;
+        CHECK_PROCESS(UA_RequestHeader_decodeBinary(msg, pos, &p),; );
+        UA_ResponseHeader_init(&r);
+        r.requestHandle = p.requestHandle;
+        r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
+        UA_ByteString_newMembers(&responseBuf.strings[1], UA_ResponseHeader_calcSizeBinary(&r));
+        UA_ResponseHeader_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);
+        UA_RequestHeader_deleteMembers(&p);
+        UA_ResponseHeader_deleteMembers(&r);
+        responseType = UA_RESPONSEHEADER_NS0 + 2;
+        }
+    }
+
+    // 5) Build the header
+    UA_NodeId response_nodeid = { .namespaceIndex     = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+                                  .identifier.numeric = responseType }; // add 2 for binary encoding
+
+    UA_ByteString_newMembers(&responseBuf.strings[0],
+                             8 + 16 + // normal header + 4*32bit secure channel information
+                             UA_NodeId_calcSizeBinary(&response_nodeid));
+
+    UA_ByteString *header = &responseBuf.strings[0];
+    UA_UInt32 rpos = 0;
+
+    // header
+    UA_TcpMessageHeader respHeader;
+    respHeader.messageType = UA_MESSAGETYPE_MSG;
+    respHeader.isFinal     = 'F';
+    respHeader.messageSize = header->length + responseBuf.strings[1].length;
+    UA_TcpMessageHeader_encodeBinary(&respHeader, header, &rpos);
+
+    // channel id
+    UA_UInt32_encodeBinary(&channel->securityToken.channelId, header, &rpos);
+
+    // algorithm security header
+    UA_UInt32_encodeBinary(&channel->securityToken.tokenId, header, &rpos);
+
+    // encode sequence header
+    UA_UInt32_encodeBinary(&channel->sequenceNumber, header, &rpos);
+    UA_UInt32_encodeBinary(&channel->requestId, header, &rpos);
+
+    // add payload type
+    UA_NodeId_encodeBinary(&response_nodeid, header, &rpos);
+
+    // sign data
+
+    // encrypt data
+
+    // 6) Send it over the wire.
+    connection->write(connection->callbackHandle, responseBuf);
+
+clean_up:
+    UA_ExpandedNodeId_deleteMembers(&requestType);
+    UA_ByteStringArray_deleteMembers(&responseBuf);
+    return;
+
+close_connection:
+    // make sure allocated data has been freed
+    connection->state = UA_CONNECTION_CLOSING;
+    connection->close(connection->callbackHandle);
+    return;
+}
+
+static void processClose(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, UA_UInt32 *pos) {
+    // just read in the sequenceheader
+
+}
+
+UA_Int32 UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
+                                        const UA_ByteString *msg) {
+    UA_Int32  retval = UA_SUCCESS;
+    UA_UInt32 pos    = 0;
+    UA_TcpMessageHeader tcpMessageHeader;
+    // todo: test how far pos advanced must be equal to what is said in the messageheader
+    do {
+        retval = UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader);
+        if(retval == UA_SUCCESS) {
+            // none of the process-functions returns an error its all contained inside.
+            switch(tcpMessageHeader.messageType) {
+            case UA_MESSAGETYPE_HEL:
+                processHello(connection, msg, &pos);
+                break;
+
+            case UA_MESSAGETYPE_OPN:
+                processOpen(connection, server, msg, &pos);
+                break;
+
+            case UA_MESSAGETYPE_MSG:
+                // if this fails, the connection is closed (no break on the case)
+                if(connection->state == UA_CONNECTION_ESTABLISHED &&
+                   connection->channel != UA_NULL) {
+                    processMessage(connection, server, msg, &pos);
+                    break;
+                }
+
+            case UA_MESSAGETYPE_CLO:
+                connection->state = UA_CONNECTION_CLOSING;
+                processClose(connection, server, msg, &pos);
+                connection->close(connection->callbackHandle);
+                return retval;
+            }
+            UA_TcpMessageHeader_deleteMembers(&tcpMessageHeader);
+        } else {
+            printf("TL_Process - ERROR: decoding of header failed \n");
+            connection->state = UA_CONNECTION_CLOSING;
+            //processClose(connection, server, msg, &pos);
+            connection->close(connection->callbackHandle);
+        }
+        // todo: more than one message at once..
+    } while(msg->length > (UA_Int32)pos);
+    return retval;
+}

+ 50 - 38
src/server/ua_services.h

@@ -1,18 +1,9 @@
-/**
- * @file ua_services.h
- *
- * @brief Defines the method signatures for all the standard defined services.
- */
-
 #ifndef UA_SERVICES_H_
 #define UA_SERVICES_H_
 
 #include "ua_types.h"
 #include "ua_types_generated.h"
-#include "ua_application.h"
-#include "ua_transport_binary_secure.h"
-#include "ua_session_manager.h"
-#include "ua_channel_manager.h"
+#include "ua_server.h"
 
 /**
  * @defgroup services Services
@@ -37,7 +28,9 @@
  * the configuration information required to establish a SecureChannel and a
  * Session.
  */
-UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response);
+UA_Int32 Service_GetEndpoints(UA_Server                    *server,
+                              const UA_GetEndpointsRequest *request,
+                              UA_GetEndpointsResponse      *response);
 // Service_RegisterServer
 /** @} */
 
@@ -51,17 +44,17 @@ UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest*
  * @{
  */
 
-/**
- * @brief This Service is used to open or renew a SecureChannel that can be used
- * to ensure Confidentiality and Integrity for Message exchange during a
- * Session.
- */
-UA_Int32 Service_OpenSecureChannel(SL_Channel *channel, const UA_OpenSecureChannelRequest* request, UA_OpenSecureChannelResponse* response);
+/** @brief This Service is used to open or renew a SecureChannel that can be
+   used to ensure Confidentiality and Integrity for Message exchange during a
+   Session. */
+UA_Int32 Service_OpenSecureChannel(UA_Server *server, UA_Connection *connection,
+                                   const UA_OpenSecureChannelRequest *request,
+                                   UA_OpenSecureChannelResponse *response);
 
-/**
- * @brief This Service is used to terminate a SecureChannel.
- */
-UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureChannelRequest *request, UA_CloseSecureChannelResponse *response);
+/** @brief This Service is used to terminate a SecureChannel. */
+UA_Int32 Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel,
+                                    const UA_CloseSecureChannelRequest *request,
+                                    UA_CloseSecureChannelResponse *response);
 /** @} */
 
 /**
@@ -80,7 +73,9 @@ UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureCha
  * logs and in the Server’s address space. The second is the authenticationToken
  * which is used to associate an incoming request with a Session.
  */
-UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response);
+UA_Int32 Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
+                               const UA_CreateSessionRequest *request,
+                               UA_CreateSessionResponse *response);
 
 /**
  * @brief This Service is used by the Client to submit its SoftwareCertificates
@@ -89,12 +84,16 @@ UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionReques
  * Client before it issues any other Service request after CreateSession.
  * Failure to do so shall cause the Server to close the Session.
  */
-UA_Int32 Service_ActivateSession(SL_Channel *channel, UA_Session *session, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response);
+UA_Int32 Service_ActivateSession(UA_Server *server, UA_Session *session,
+                                 const UA_ActivateSessionRequest *request,
+                                 UA_ActivateSessionResponse *response);
 
 /**
  * @brief This Service is used to terminate a Session.
  */
-UA_Int32 Service_CloseSession(UA_Session *session, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response);
+UA_Int32 Service_CloseSession(UA_Server *server, UA_Session *session,
+                              const UA_CloseSessionRequest *request,
+                              UA_CloseSessionResponse *response);
 // Service_Cancel
 /** @} */
 
@@ -111,12 +110,15 @@ UA_Int32 Service_CloseSession(UA_Session *session, const UA_CloseSessionRequest
 /**
  * @brief This Service is used to add one or more Nodes into the AddressSpace hierarchy.
  */
-UA_Int32 Service_AddNodes(UA_Session *session, const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
+UA_Int32 Service_AddNodes(UA_Server *server, UA_Session *session,
+                          const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
 
 /**
  * @brief This Service is used to add one or more References to one or more Nodes
  */
-UA_Int32 Service_AddReferences(UA_Session *session, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response);
+UA_Int32 Service_AddReferences(UA_Server *server, UA_Session *session,
+                               const UA_AddReferencesRequest *request,
+                               UA_AddReferencesResponse *response);
 
 // Service_DeleteNodes
 // Service_DeleteReferences
@@ -135,13 +137,16 @@ UA_Int32 Service_AddReferences(UA_Session *session, const UA_AddReferencesReques
  * @brief This Service is used to discover the References of a specified Node.
  * The browse can be further limited by the use of a View. This Browse Service
  * also supports a primitive filtering capability.
- */ 
-UA_Int32 Service_Browse(UA_Session *session, const UA_BrowseRequest *request, UA_BrowseResponse *response);
+ */
+UA_Int32 Service_Browse(UA_Server *server, UA_Session *session,
+                        const UA_BrowseRequest *request, UA_BrowseResponse *response);
 
 /**
  * @brief This Service is used to translate textual node paths to their respective ids.
  */
-UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Session *session, const UA_TranslateBrowsePathsToNodeIdsRequest *request, UA_TranslateBrowsePathsToNodeIdsResponse *response);
+UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
+                                               const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+                                               UA_TranslateBrowsePathsToNodeIdsResponse *response);
 // Service_BrowseNext
 // Service_TranslateBrowsePathsToNodeIds
 // Service_RegisterNodes
@@ -184,7 +189,8 @@ UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Session *session, const UA_Tra
  * values as a composite, to read individual elements or to read ranges of
  * elements of the composite.
  */
-UA_Int32 Service_Read(UA_Session *session, const UA_ReadRequest *request, UA_ReadResponse *response);
+UA_Int32 Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *request,
+                      UA_ReadResponse *response);
 // Service_HistoryRead
 /**
  * @brief This Service is used to write one or more Attributes of one or more
@@ -193,7 +199,8 @@ UA_Int32 Service_Read(UA_Session *session, const UA_ReadRequest *request, UA_Rea
  *  values as a composite, to write individual elements or to write ranges of
  *  elements of the composite.
  */
-UA_Int32 Service_Write(UA_Session *session, const UA_WriteRequest *request,UA_WriteResponse *response);
+UA_Int32 Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest *request,
+                       UA_WriteResponse *response);
 // Service_HistoryUpdate
 /** @} */
 
@@ -201,7 +208,7 @@ UA_Int32 Service_Write(UA_Session *session, const UA_WriteRequest *request,UA_Wr
  * @name Method Service Set
  *
  * The Method Service Set defines the means to invoke methods. A method shall be
-a component of an Object.
+   a component of an Object.
  *
  * @{
  */
@@ -225,7 +232,9 @@ a component of an Object.
  * triggered item links to be deleted, but has no effect on the MonitoredItems
  * referenced by the triggered items.
  */
-UA_Int32 Service_CreateMonitoredItems(UA_Session *session, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response);
+UA_Int32 Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
+                                      const UA_CreateMonitoredItemsRequest *request,
+                                      UA_CreateMonitoredItemsResponse *response);
 // Service_ModifyMonitoredItems
 // Service_SetMonitoringMode
 // Service_SetTriggering
@@ -240,15 +249,18 @@ UA_Int32 Service_CreateMonitoredItems(UA_Session *session, const UA_CreateMonito
  * @{
  */
 // Service_CreateSubscription
-UA_Int32 Service_CreateSubscription(UA_Session *session, const UA_CreateSubscriptionRequest *request,
-                                   UA_CreateSubscriptionResponse *response);
+UA_Int32 Service_CreateSubscription(UA_Server *server, UA_Session *session,
+                                    const UA_CreateSubscriptionRequest *request,
+                                    UA_CreateSubscriptionResponse *response);
 // Service_ModifySubscription
 // Service_SetPublishingMode
-UA_Int32 Service_SetPublishingMode(UA_Session *session, const UA_SetPublishingModeRequest *request,
+UA_Int32 Service_SetPublishingMode(UA_Server *server, UA_Session *session,
+                                   const UA_SetPublishingModeRequest *request,
                                    UA_SetPublishingModeResponse *response);
 
-UA_Int32 Service_Publish(UA_Session *session, const UA_PublishRequest *request,
-                                   UA_PublishResponse *response);
+UA_Int32 Service_Publish(UA_Server *server, UA_Session *session,
+                         const UA_PublishRequest *request,
+                         UA_PublishResponse *response);
 
 // Service_Republish
 // Service_TransferSubscription

+ 384 - 410
src/server/ua_services_attribute.c

@@ -2,422 +2,396 @@
 #include "ua_statuscodes.h"
 
 enum UA_AttributeId {
-	UA_ATTRIBUTEID_NODEID                  = 1,
-	UA_ATTRIBUTEID_NODECLASS               = 2,
-	UA_ATTRIBUTEID_BROWSENAME              = 3,
-	UA_ATTRIBUTEID_DISPLAYNAME             = 4,
-	UA_ATTRIBUTEID_DESCRIPTION             = 5,
-	UA_ATTRIBUTEID_WRITEMASK               = 6,
-	UA_ATTRIBUTEID_USERWRITEMASK           = 7,
-	UA_ATTRIBUTEID_ISABSTRACT              = 8,
-	UA_ATTRIBUTEID_SYMMETRIC               = 9,
-	UA_ATTRIBUTEID_INVERSENAME             = 10,
-	UA_ATTRIBUTEID_CONTAINSNOLOOPS         = 11,
-	UA_ATTRIBUTEID_EVENTNOTIFIER           = 12,
-	UA_ATTRIBUTEID_VALUE                   = 13,
-	UA_ATTRIBUTEID_DATATYPE                = 14,
-	UA_ATTRIBUTEID_VALUERANK               = 15,
-	UA_ATTRIBUTEID_ARRAYDIMENSIONS         = 16,
-	UA_ATTRIBUTEID_ACCESSLEVEL             = 17,
-	UA_ATTRIBUTEID_USERACCESSLEVEL         = 18,
-	UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL = 19,
-	UA_ATTRIBUTEID_HISTORIZING             = 20,
-	UA_ATTRIBUTEID_EXECUTABLE              = 21,
-	UA_ATTRIBUTEID_USEREXECUTABLE          = 22
+    UA_ATTRIBUTEID_NODEID = 1,
+    UA_ATTRIBUTEID_NODECLASS = 2,
+    UA_ATTRIBUTEID_BROWSENAME = 3,
+    UA_ATTRIBUTEID_DISPLAYNAME             = 4,
+    UA_ATTRIBUTEID_DESCRIPTION             = 5,
+    UA_ATTRIBUTEID_WRITEMASK               = 6,
+    UA_ATTRIBUTEID_USERWRITEMASK           = 7,
+    UA_ATTRIBUTEID_ISABSTRACT              = 8,
+    UA_ATTRIBUTEID_SYMMETRIC               = 9,
+    UA_ATTRIBUTEID_INVERSENAME             = 10,
+    UA_ATTRIBUTEID_CONTAINSNOLOOPS         = 11,
+    UA_ATTRIBUTEID_EVENTNOTIFIER           = 12,
+    UA_ATTRIBUTEID_VALUE                   = 13,
+    UA_ATTRIBUTEID_DATATYPE                = 14,
+    UA_ATTRIBUTEID_VALUERANK               = 15,
+    UA_ATTRIBUTEID_ARRAYDIMENSIONS         = 16,
+    UA_ATTRIBUTEID_ACCESSLEVEL             = 17,
+    UA_ATTRIBUTEID_USERACCESSLEVEL         = 18,
+    UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL = 19,
+    UA_ATTRIBUTEID_HISTORIZING             = 20,
+    UA_ATTRIBUTEID_EXECUTABLE              = 21,
+    UA_ATTRIBUTEID_USEREXECUTABLE          = 22
 };
 
-#define CHECK_NODECLASS(CLASS)									   \
-	if(!(node->nodeClass & (CLASS))) {							   \
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;	   \
-		v.status       = UA_STATUSCODE_BADNOTREADABLE;			   \
-		break;													   \
-	}															   \
-
-static UA_DataValue service_read_node(Application *app, const UA_ReadValueId *id) {
-	UA_DataValue v;
-	UA_DataValue_init(&v);
-
-	DBG(printf("service_read_node - entered with ns=%d,id=%d,attr=%i\n", id->nodeId.namespaceIndex,
-	           id->nodeId.identifier.numeric, id->attributeId));
-	Namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespaceIndex);
-
-	if(ns == UA_NULL) {
-		DBG_VERBOSE(printf("service_read_node - unknown namespace %d\n", id->nodeId.namespaceIndex));
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
-		return v;
-	}
-
-	UA_Node const *node = UA_NULL;
-	DBG_VERBOSE(UA_NodeId_printf("service_read_node - search for ", &(id->nodeId)));
-	UA_Int32 result = Namespace_get(ns, &(id->nodeId), &node);
-	if(result != UA_SUCCESS || node == UA_NULL) {
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
-		return v;
-	}
-	DBG_VERBOSE(UA_NodeId_printf("service_read_node - found node=", &(node->nodeId)));
-
-	UA_Int32 retval = UA_SUCCESS;
-
-	switch(id->attributeId) {
-	case UA_ATTRIBUTEID_NODEID:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_NODEID], &node->nodeId);
-		break;
-
-	case UA_ATTRIBUTEID_NODECLASS:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_INT32], &node->nodeClass);
-		break;
-
-	case UA_ATTRIBUTEID_BROWSENAME:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_QUALIFIEDNAME], &node->browseName);
-		break;
-
-	case UA_ATTRIBUTEID_DISPLAYNAME:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
-		                                  &node->displayName);
-		break;
-
-	case UA_ATTRIBUTEID_DESCRIPTION:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
-		                                  &node->description);
-		break;
-
-	case UA_ATTRIBUTEID_WRITEMASK:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_UINT32], &node->writeMask);
-		break;
-
-	case UA_ATTRIBUTEID_USERWRITEMASK:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_UINT32], &node->userWriteMask);
-		break;
-
-	case UA_ATTRIBUTEID_ISABSTRACT:
-		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE | UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE | UA_NODECLASS_DATATYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |=
-		    UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                            &((UA_ReferenceTypeNode *)node)->isAbstract);
-		break;
-
-	case UA_ATTRIBUTEID_SYMMETRIC:
-		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                                  &((UA_ReferenceTypeNode *)node)->symmetric);
-		break;
-
-	case UA_ATTRIBUTEID_INVERSENAME:
-		CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
-		                                  &((UA_ReferenceTypeNode *)node)->inverseName);
-		break;
-
-	case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
-		CHECK_NODECLASS(UA_NODECLASS_VIEW);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                                  &((UA_ViewNode *)node)->containsNoLoops);
-		break;
-
-	case UA_ATTRIBUTEID_EVENTNOTIFIER:
-		CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
-		                                  &((UA_ViewNode *)node)->eventNotifier);
-		break;
-
-	case UA_ATTRIBUTEID_VALUE:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		// TODO: Ensure that the borrowed value is not freed prematurely (multithreading)
-		/* retval |= UA_Variant_borrowSetValue(&v.value, &UA_.types[UA_VARIANT], */
-		/*                                     &((UA_VariableNode *)node)->value); */
-		retval |= UA_Variant_copy(&((UA_VariableNode *)node)->value, &v.value);
-		break;
-
-	case UA_ATTRIBUTEID_DATATYPE:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_NODEID],
-		                                  &((UA_VariableTypeNode *)node)->dataType);
-		break;
-
-	case UA_ATTRIBUTEID_VALUERANK:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_INT32],
-		                                  &((UA_VariableTypeNode *)node)->valueRank);
-		break;
-
-	case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		UA_Variant_copySetArray(&v.value, &UA_.types[UA_UINT32],
-		                        ((UA_VariableTypeNode *)node)->arrayDimensionsSize,
-		                        &((UA_VariableTypeNode *)node)->arrayDimensions);
-		break;
-
-	case UA_ATTRIBUTEID_ACCESSLEVEL:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
-		                                  &((UA_VariableNode *)node)->accessLevel);
-		break;
-
-	case UA_ATTRIBUTEID_USERACCESSLEVEL:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
-		                                  &((UA_VariableNode *)node)->userAccessLevel);
-		break;
-
-	case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_DOUBLE],
-		                                  &((UA_VariableNode *)node)->minimumSamplingInterval);
-		break;
-
-	case UA_ATTRIBUTEID_HISTORIZING:
-		CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                                  &((UA_VariableNode *)node)->historizing);
-		break;
-
-	case UA_ATTRIBUTEID_EXECUTABLE:
-		CHECK_NODECLASS(UA_NODECLASS_METHOD);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                                  &((UA_MethodNode *)node)->executable);
-		break;
-
-	case UA_ATTRIBUTEID_USEREXECUTABLE:
-		CHECK_NODECLASS(UA_NODECLASS_METHOD);
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
-		retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
-		                                  &((UA_MethodNode *)node)->userExecutable);
-		break;
-
-	default:
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v.status       = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
-		break;
-	}
-
-	Namespace_releaseManagedNode(node);
-
-	if(retval != UA_SUCCESS) {
-		v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
-		v.status       = UA_STATUSCODE_BADNOTREADABLE;
-	}
-
-	return v;
+#define CHECK_NODECLASS(CLASS)                                 \
+    if(!(node->nodeClass & (CLASS))) {                         \
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE; \
+        v.status       = UA_STATUSCODE_BADNOTREADABLE;         \
+        break;                                                 \
+    }                                                          \
+
+static UA_DataValue service_read_node(UA_Server *server, const UA_ReadValueId *id) {
+    UA_DataValue v;
+    UA_DataValue_init(&v);
+
+    UA_Node const *node   = UA_NULL;
+    UA_Int32       result = UA_NodeStore_get(server->nodestore, &(id->nodeId), &node);
+    if(result != UA_SUCCESS || node == UA_NULL) {
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+        v.status       = UA_STATUSCODE_BADNODEIDUNKNOWN;
+        return v;
+    }
+    UA_Int32 retval = UA_SUCCESS;
+
+    switch(id->attributeId) {
+    case UA_ATTRIBUTEID_NODEID:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_NODEID], &node->nodeId);
+        break;
+
+    case UA_ATTRIBUTEID_NODECLASS:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_INT32], &node->nodeClass);
+        break;
+
+    case UA_ATTRIBUTEID_BROWSENAME:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_QUALIFIEDNAME], &node->browseName);
+        break;
+
+    case UA_ATTRIBUTEID_DISPLAYNAME:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
+                                          &node->displayName);
+        break;
+
+    case UA_ATTRIBUTEID_DESCRIPTION:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
+                                          &node->description);
+        break;
+
+    case UA_ATTRIBUTEID_WRITEMASK:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_UINT32], &node->writeMask);
+        break;
+
+    case UA_ATTRIBUTEID_USERWRITEMASK:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_UINT32], &node->userWriteMask);
+        break;
+
+    case UA_ATTRIBUTEID_ISABSTRACT:
+        CHECK_NODECLASS(
+            UA_NODECLASS_REFERENCETYPE | UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE |
+            UA_NODECLASS_DATATYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |=
+            UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                    &((UA_ReferenceTypeNode *)node)->isAbstract);
+        break;
+
+    case UA_ATTRIBUTEID_SYMMETRIC:
+        CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                          &((UA_ReferenceTypeNode *)node)->symmetric);
+        break;
+
+    case UA_ATTRIBUTEID_INVERSENAME:
+        CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_LOCALIZEDTEXT],
+                                          &((UA_ReferenceTypeNode *)node)->inverseName);
+        break;
+
+    case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+        CHECK_NODECLASS(UA_NODECLASS_VIEW);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                          &((UA_ViewNode *)node)->containsNoLoops);
+        break;
+
+    case UA_ATTRIBUTEID_EVENTNOTIFIER:
+        CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
+                                          &((UA_ViewNode *)node)->eventNotifier);
+        break;
+
+    case UA_ATTRIBUTEID_VALUE:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        // TODO: Ensure that the borrowed value is not freed prematurely (multithreading)
+        /* retval |= UA_Variant_borrowSetValue(&v.value, &UA_.types[UA_VARIANT], */
+        /*                                     &((UA_VariableNode *)node)->value); */
+        retval |= UA_Variant_copy(&((UA_VariableNode *)node)->value, &v.value);
+        break;
+
+    case UA_ATTRIBUTEID_DATATYPE:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_NODEID],
+                                          &((UA_VariableTypeNode *)node)->dataType);
+        break;
+
+    case UA_ATTRIBUTEID_VALUERANK:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_INT32],
+                                          &((UA_VariableTypeNode *)node)->valueRank);
+        break;
+
+    case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        UA_Variant_copySetArray(&v.value, &UA_.types[UA_UINT32],
+                                ((UA_VariableTypeNode *)node)->arrayDimensionsSize,
+                                &((UA_VariableTypeNode *)node)->arrayDimensions);
+        break;
+
+    case UA_ATTRIBUTEID_ACCESSLEVEL:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
+                                          &((UA_VariableNode *)node)->accessLevel);
+        break;
+
+    case UA_ATTRIBUTEID_USERACCESSLEVEL:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BYTE],
+                                          &((UA_VariableNode *)node)->userAccessLevel);
+        break;
+
+    case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_DOUBLE],
+                                          &((UA_VariableNode *)node)->minimumSamplingInterval);
+        break;
+
+    case UA_ATTRIBUTEID_HISTORIZING:
+        CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                          &((UA_VariableNode *)node)->historizing);
+        break;
+
+    case UA_ATTRIBUTEID_EXECUTABLE:
+        CHECK_NODECLASS(UA_NODECLASS_METHOD);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                          &((UA_MethodNode *)node)->executable);
+        break;
+
+    case UA_ATTRIBUTEID_USEREXECUTABLE:
+        CHECK_NODECLASS(UA_NODECLASS_METHOD);
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_VARIANT;
+        retval |= UA_Variant_copySetValue(&v.value, &UA_.types[UA_BOOLEAN],
+                                          &((UA_MethodNode *)node)->userExecutable);
+        break;
+
+    default:
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+        v.status       = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+        break;
+    }
+
+    UA_NodeStore_releaseManagedNode(node);
+
+    if(retval != UA_SUCCESS) {
+        v.encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+        v.status       = UA_STATUSCODE_BADNOTREADABLE;
+    }
+
+
+    return v;
 }
-UA_Int32 Service_Read(UA_Session *session, const UA_ReadRequest *request,
+UA_Int32 Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *request,
                       UA_ReadResponse *response) {
-	Application *application = UA_NULL;
-	UA_Int32 readsize;
-	if(session == UA_NULL)
-		return UA_ERROR;
-
-	UA_Session_getApplicationPointer(session,&application);
-
-	if( application == UA_NULL)
-		return UA_ERROR;    // TODO: Return error message
-
-	readsize = request->nodesToReadSize;
-	/* NothingTodo */
-	if(readsize <= 0) {
-		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
-		response->resultsSize = 0;
-		return UA_SUCCESS;
-	}
-
-	response->resultsSize = readsize;
-	UA_alloc((void **)&response->results, sizeof(UA_DataValue) * readsize);
-	for(UA_Int32 i = 0;i < readsize;i++) {
-		DBG_VERBOSE(printf("service_read - attributeId=%d\n", request->nodesToRead[i].attributeId));
-		DBG_VERBOSE(UA_NodeId_printf("service_read - nodeId=", &(request->nodesToRead[i].nodeId)));
-		response->results[i] = service_read_node(application, &request->nodesToRead[i]);
-	}
-	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
-	response->diagnosticInfosSize = 0;
-	return UA_SUCCESS;
+    UA_Int32 readsize;
+    if(server == UA_NULL || session == UA_NULL)
+        return UA_ERROR;
+
+    readsize = request->nodesToReadSize;
+    /* NothingTodo */
+    if(readsize <= 0) {
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+        response->resultsSize = 0;
+        return UA_SUCCESS;
+    }
+
+    response->resultsSize = readsize;
+    UA_alloc((void **)&response->results, sizeof(UA_DataValue) * readsize);
+    for(UA_Int32 i = 0;i < readsize;i++) {
+        DBG_VERBOSE(printf("service_read - attributeId=%d\n", request->nodesToRead[i].attributeId));
+        DBG_VERBOSE(UA_NodeId_printf("service_read - nodeId=", &(request->nodesToRead[i].nodeId)));
+        response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+    }
+    response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
+    response->diagnosticInfosSize = 0;
+    return UA_SUCCESS;
 }
 
-UA_Int32 Service_Write_writeNode(Application *app, UA_WriteValue *writeValue, UA_StatusCode *result)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	Namespace *ns = UA_indexedList_findValue(app->namespaces, writeValue->nodeId.namespaceIndex);
-	if(ns==UA_NULL) {
-		*result = UA_STATUSCODE_BADNODEIDINVALID;
-		return UA_ERROR;
-	}
-
-	const UA_Node *node;
-	if(Namespace_get(ns, &writeValue->nodeId, &node) != UA_SUCCESS) {
-		return UA_ERROR;
-	}
-
-	switch(writeValue->attributeId) {
-	case UA_ATTRIBUTEID_NODEID:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_NODECLASS:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_BROWSENAME:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_DISPLAYNAME:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_DESCRIPTION:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_WRITEMASK:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		break;
-
-	case UA_ATTRIBUTEID_USERWRITEMASK:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_ISABSTRACT:
-
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-
-		break;
-
-	case UA_ATTRIBUTEID_SYMMETRIC:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_INVERSENAME:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_EVENTNOTIFIER:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_VALUE:
-		if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT) {
-			// TODO: Ensure that the borrowed value is not freed prematurely (multithreading)
-			/* retval |= UA_Variant_borrowSetValue(&v.value, &UA_.types[UA_VARIANT], */
-			/*                                     &((UA_VariableNode *)node)->value); */
-			retval |= UA_Variant_copy(&writeValue->value.value, &((UA_VariableNode *)node)->value);
-			*result = UA_STATUSCODE_GOOD;
-		}
-
-		break;
-
-	case UA_ATTRIBUTEID_DATATYPE:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_VALUERANK:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_ACCESSLEVEL:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_USERACCESSLEVEL:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		return UA_ERROR;
-		break;
-
-	case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_HISTORIZING:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_EXECUTABLE:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	case UA_ATTRIBUTEID_USEREXECUTABLE:
-		/* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
-		*result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-		break;
-
-	default:
-		*result      = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
-		break;
-	}
-
-	Namespace_releaseManagedNode(node);
-	return retval;
+UA_Int32 Service_Write_writeNode(UA_Server *server, UA_WriteValue *writeValue,
+                                 UA_StatusCode *result) {
+    UA_Int32 retval = UA_SUCCESS;
+    const UA_Node *node;
+    if(UA_NodeStore_get(server->nodestore, &writeValue->nodeId, &node) != UA_SUCCESS)
+        return UA_ERROR;
+
+    switch(writeValue->attributeId) {
+    case UA_ATTRIBUTEID_NODEID:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_NODECLASS:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){ } */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_BROWSENAME:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_DISPLAYNAME:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_DESCRIPTION:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_WRITEMASK:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        break;
+
+    case UA_ATTRIBUTEID_USERWRITEMASK:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_ISABSTRACT:
+
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+
+        break;
+
+    case UA_ATTRIBUTEID_SYMMETRIC:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_INVERSENAME:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_EVENTNOTIFIER:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_VALUE:
+        if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT) {
+            // TODO: Ensure that the borrowed value is not freed prematurely (multithreading)
+            /* retval |= UA_Variant_borrowSetValue(&v.value, &UA_.types[UA_VARIANT], */
+            /*                                     &((UA_VariableNode *)node)->value); */
+            retval |= UA_Variant_copy(&writeValue->value.value, &((UA_VariableNode *)node)->value);
+            *result = UA_STATUSCODE_GOOD;
+        }
+
+        break;
+
+    case UA_ATTRIBUTEID_DATATYPE:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_VALUERANK:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_ACCESSLEVEL:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_USERACCESSLEVEL:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        return UA_ERROR;
+        break;
+
+    case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_HISTORIZING:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_EXECUTABLE:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    case UA_ATTRIBUTEID_USEREXECUTABLE:
+        /* if(writeValue->value.encodingMask == UA_DATAVALUE_ENCODINGMASK_VARIANT){} */
+        *result = UA_STATUSCODE_BADWRITENOTSUPPORTED;
+        break;
+
+    default:
+        *result = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
+        break;
+    }
+
+    UA_NodeStore_releaseManagedNode(node);
+    return retval;
 
 }
-UA_Int32 Service_Write(UA_Session *session, const UA_WriteRequest *request,
-                      UA_WriteResponse *response) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 i;
-	Application *application = UA_NULL;
-	UA_Session_getApplicationPointer(session, &application);
-	if(session == UA_NULL || application == UA_NULL)
-		return UA_ERROR;    // TODO: Return error message
-	response->resultsSize = request->nodesToWriteSize;
-	//TODO evalutate diagnostic info within the request
-	UA_Array_new((void**)&response->results,response->resultsSize,&UA_.types[UA_STATUSCODE]);
-	for(i=0; i < request->nodesToWriteSize; i++){
-		retval |= Service_Write_writeNode(application, &request->nodesToWrite[i], &response->results[i]);
-	}
-
-	return retval;
+
+UA_Int32 Service_Write(UA_Server *server, UA_Session *session, const UA_WriteRequest *request,
+                       UA_WriteResponse *response) {
+    UA_Int32 retval = UA_SUCCESS;
+    UA_Int32 i;
+    if(session == UA_NULL || server == UA_NULL)
+        return UA_ERROR;    // TODO: Return error message
+    response->resultsSize = request->nodesToWriteSize;
+    //TODO evalutate diagnostic info within the request
+    UA_Array_new((void **)&response->results, response->resultsSize, &UA_.types[UA_STATUSCODE]);
+    for(i = 0;i < request->nodesToWriteSize;i++)
+        retval |= Service_Write_writeNode(server, &request->nodesToWrite[i], &response->results[i]);
+
+    return retval;
 }

+ 36 - 79
src/server/ua_services_discovery.c

@@ -1,84 +1,41 @@
 #include "ua_services.h"
-#include "errno.h"
 
-UA_Int32 Service_GetEndpoints(SL_Channel *channel,
-		const UA_GetEndpointsRequest* request,
-		UA_GetEndpointsResponse *response) {
-#define RETURN free(certificate_base64_without_lb); fclose(fp); return
-
-#ifdef DEBUG
-	UA_String_printx("endpointUrl=", &request->endpointUrl);
-#endif
-
-	response->endpointsSize = 1;
-	UA_Array_new((void**) &response->endpoints, response->endpointsSize,
-			&UA_.types[UA_ENDPOINTDESCRIPTION]);
-
-	//Security issues:
-	//The policy should be 'http://opcfoundation.org/UA/SecurityPolicy#None'
-	//FIXME String or ByteString
-	UA_AsymmetricAlgorithmSecurityHeader *asymSettings;
-	SL_Channel_getLocalAsymAlgSettings(channel, &asymSettings);
-	UA_String_copy((UA_String *) &(asymSettings->securityPolicyUri),
-			&response->endpoints[0].securityPolicyUri);
-	//FIXME hard-coded code
-	response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
-	UA_String_copycstring(
-			"http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
-			&response->endpoints[0].transportProfileUri);
-
-	response->endpoints[0].userIdentityTokensSize = 1;
-	UA_Array_new((void**) &response->endpoints[0].userIdentityTokens,
-			response->endpoints[0].userIdentityTokensSize,
-			&UA_.types[UA_USERTOKENPOLICY]);
-	UA_UserTokenPolicy *token = &response->endpoints[0].userIdentityTokens[0];
-	UA_String_copycstring("my-anonymous-policy", &token->policyId); // defined per server
-	token->tokenType = UA_USERTOKENTYPE_ANONYMOUS;
-	token->issuerEndpointUrl = (UA_String ) { -1, UA_NULL };
-	token->issuedTokenType = (UA_String ) { -1, UA_NULL };
-	token->securityPolicyUri = (UA_String ) { -1, UA_NULL };
-
-	UA_String_copy(&request->endpointUrl, &response->endpoints[0].endpointUrl);
-	UA_String_copycstring("http://open62541.org/product/release",
-			&(response->endpoints[0].server.productUri));
-	// FIXME: This information should be provided by the application, preferably in the address space
-	UA_String_copycstring("urn:localhost:open6251:open62541Server",
-			&(response->endpoints[0].server.applicationUri));
-	UA_LocalizedText_copycstring("The open62541 application",
-			&(response->endpoints[0].server.applicationName));
-	// FIXME: This should be a feature of the application and an enum
-	response->endpoints[0].server.applicationType = UA_APPLICATIONTYPE_SERVER;
-	// all the other strings are empty by initialization
-
-	FILE *fp = UA_NULL;
-	UA_UInt32 certificate_size=0;
-	UA_Byte* certificate= UA_NULL;
-	//FIXME: a potiential bug of locating the certificate, we need to get the path from the server's config
-	//FIXME: we need to read file only once
-	fp=fopen("localhost.der", "rb");
-	if (fp == NULL) {
-			//printf("Opening the certificate file failed, errno = %d\n", errno);
-	        //RETURN UA_ERROR;
-	}else{
-		fseek(fp, 0, SEEK_END);
-		certificate_size = ftell(fp);
-
-		UA_alloc((void**)&certificate, certificate_size*sizeof(UA_Byte));
-		//read certificate without linebreaks
-		fseek(fp, 0, SEEK_SET);
-		fread(certificate, sizeof(UA_Byte), certificate_size, fp);
-
-		UA_String certificate_binary;
-		certificate_binary.length = certificate_size;
-		certificate_binary.data = certificate;
-
-		fclose(fp);
-		//The standard says "the HostName specified in the Server Certificate is the same as the HostName contained in the
-		//endpointUrl provided in the EndpointDescription;"
-
-		UA_String_copy(&certificate_binary, &response->endpoints[0].serverCertificate);
-		UA_String_deleteMembers(&certificate_binary);
-	}
+UA_Int32 Service_GetEndpoints(UA_Server                    *server,
+                              const UA_GetEndpointsRequest *request,
+                              UA_GetEndpointsResponse      *response) {
+    UA_GetEndpointsResponse_init(response);
+    response->endpointsSize = 1;
+    UA_Array_new((void **)&response->endpoints, response->endpointsSize, &UA_.types[UA_ENDPOINTDESCRIPTION]);
+
+    // security policy
+    response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
+    UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",
+                          &response->endpoints[0].securityPolicyUri);
+    UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
+                          &response->endpoints[0].transportProfileUri);
+
+    // usertoken policy
+    response->endpoints[0].userIdentityTokensSize = 1;
+    UA_Array_new((void **)&response->endpoints[0].userIdentityTokens,
+                 response->endpoints[0].userIdentityTokensSize, &UA_.types[UA_USERTOKENPOLICY]);
+    UA_UserTokenPolicy *token = &response->endpoints[0].userIdentityTokens[0];
+    UA_UserTokenPolicy_init(token);
+    UA_String_copycstring("my-anonymous-policy", &token->policyId); // defined per server
+    token->tokenType         = UA_USERTOKENTYPE_ANONYMOUS;
+
+    // server description
+    UA_String_copy(&request->endpointUrl, &response->endpoints[0].endpointUrl);
+    /* The standard says "the HostName specified in the Server Certificate is the
+       same as the HostName contained in the endpointUrl provided in the
+       EndpointDescription */
+    UA_String_copy(&server->serverCertificate, &response->endpoints[0].serverCertificate);
+    UA_String_copycstring("http://open62541.info/product/release", &(response->endpoints[0].server.productUri));
+    // FIXME: This information should be provided by the application, preferably in the address space
+    UA_String_copycstring("http://open62541.info/applications/4711",
+                          &(response->endpoints[0].server.applicationUri));
+    UA_LocalizedText_copycstring("The open62541 application", &(response->endpoints[0].server.applicationName));
+    // FIXME: This should be a feature of the application and an enum
+    response->endpoints[0].server.applicationType = UA_APPLICATIONTYPE_SERVER;
 
 	return UA_SUCCESS;
 }

+ 2 - 3
src/server/ua_services_internal.h

@@ -3,8 +3,7 @@
  * internally as well (with a simplified API as no access rights are checked).
  */
 
-#include "ua_namespace.h"
-#include "ua_types.h"
+#include "ua_nodestore.h"
 #include "ua_types_generated.h"
 
 /* @brief Add a reference (and the inverse reference to the target node).
@@ -13,4 +12,4 @@
  * @param The reference itself
  * @param The namespace where the target node is looked up for the reverse reference (this is omitted if targetns is UA_NULL)
  */
-UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, Namespace *targetns);
+UA_Int32 AddReference(UA_NodeStore *targetns, UA_Node *node, UA_ReferenceNode *reference);

+ 24 - 20
src/server/ua_services_monitoreditems.c

@@ -4,32 +4,36 @@
 //#if 0
 /* Activate once the infrastructure for pushing events is in place. */
 
-UA_Int32 Service_CreateMonitoredItems(UA_Session *session, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response) {
-	if (request->itemsToCreateSize > 0) {
-		response->resultsSize = request->itemsToCreateSize;
+UA_Int32 Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
+                                      const UA_CreateMonitoredItemsRequest *request,
+                                      UA_CreateMonitoredItemsResponse *response) {
+    if(request->itemsToCreateSize > 0) {
+        response->resultsSize = request->itemsToCreateSize;
 
-		UA_Array_new((void**)&(response->results),response->resultsSize,&UA_.types[UA_MONITOREDITEMCREATERESULT]);
-		for (int i=0;request->itemsToCreateSize > 0 && i < request->itemsToCreateSize;i++) {
+        UA_Array_new((void **)&(response->results), response->resultsSize,
+                     &UA_.types[UA_MONITOREDITEMCREATERESULT]);
+        for(int i = 0;request->itemsToCreateSize > 0 && i < request->itemsToCreateSize;i++) {
 #ifdef DEBUG
-			UA_NodeId_printf("CreateMonitoredItems - itemToCreate=",&(request->itemsToCreate[i].itemToMonitor.nodeId));
+            UA_NodeId_printf("CreateMonitoredItems - itemToCreate=",
+                             &(request->itemsToCreate[i].itemToMonitor.nodeId));
 #endif
-			//FIXME: search the object in the namespace
+            //FIXME: search the object in the namespace
 
-			if (request->itemsToCreate[i].itemToMonitor.nodeId.identifier.numeric == 2253) { // server
+            if(request->itemsToCreate[i].itemToMonitor.nodeId.identifier.numeric == 2253) {  // server
 
-				response->results[i].statusCode = UA_STATUSCODE_GOOD;
-				response->results[i].monitoredItemId = 1;
-				response->results[i].revisedSamplingInterval = 4294967295;
-				response->results[i].revisedQueueSize = 0;
-			} else {
-				// response->results[i]->statusCode = UA_STATUSCODE_BAD_NODEIDUNKNOWN;
+                response->results[i].statusCode       = UA_STATUSCODE_GOOD;
+                response->results[i].monitoredItemId  = 1;
+                response->results[i].revisedSamplingInterval = 4294967295;
+                response->results[i].revisedQueueSize = 0;
+            } else {
+                // response->results[i]->statusCode = UA_STATUSCODE_BAD_NODEIDUNKNOWN;
 
-				response->results[i].statusCode = -1;
-			}
-		}
-	}
-	//mock up
-	return UA_SUCCESS;
+                response->results[i].statusCode = -1;
+            }
+        }
+    }
+    //mock up
+    return UA_SUCCESS;
 }
 
 //#endif

+ 119 - 131
src/server/ua_services_nodemanagement.c

@@ -1,146 +1,134 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
-#include "ua_namespace.h"
+#include "ua_nodestore.h"
 #include "ua_services_internal.h"
 #include "ua_session.h"
 
-#define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do {	\
-	status |= ACTION; \
-	if(status != UA_SUCCESS) { \
-		CLEAN_UP; \
-		goto GOTO; \
-	} } while(0) \
-
-static UA_AddNodesResult addSingleNode(Application *app, UA_AddNodesItem *item) {
-	UA_AddNodesResult result;
-	UA_AddNodesResult_init(&result);
-
-	Namespace *parent_ns = UA_indexedList_findValue(app->namespaces, item->parentNodeId.nodeId.namespaceIndex);
-	// TODO: search for namespaceUris and not only ns-ids.
-	if(parent_ns == UA_NULL) {
-		result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
-		return result;
-	}
-
-	Namespace *ns = UA_NULL;
-	UA_Boolean nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId);
-
-	if(nodeid_isnull) ns = parent_ns;
-	else ns = UA_indexedList_findValue(app->namespaces, item->requestedNewNodeId.nodeId.namespaceIndex);
-
-	if(ns == UA_NULL || item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
-		result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
-		return result;
-	}
-
-	UA_Int32 status = UA_SUCCESS;
-	const UA_Node *parent;
-	CHECKED_ACTION(Namespace_get(parent_ns, &item->parentNodeId.nodeId, &parent),
-				   result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
-
-	/* if(!nodeid_isnull && Namespace_contains(ns, &item->requestedNewNodeId.nodeId)) { */
-	/* 	result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; */
-	/* 	goto ret; */
-	/* } */
-
-	/**
-	   TODO:
-
-	   1) Check for the remaining conditions 
-	   Bad_ReferenceTypeIdInvalid  See Table 166 for the description of this result code.
-	   Bad_ReferenceNotAllowed  The reference could not be created because it violates constraints imposed by the data model.
-	   Bad_NodeClassInvalid  See Table 166 for the description of this result code.
-	   Bad_BrowseNameInvalid  See Table 166 for the description of this result code.
-	   Bad_BrowseNameDuplicated  The browse name is not unique among nodes that share the same relationship with the parent.
-	   Bad_NodeAttributesInvalid  The node Attributes are not valid for the node class.
-	   Bad_TypeDefinitionInvalid  See Table 166 for the description of this result code.
-	   Bad_UserAccessDenied  See Table 165 for the description of this result code
-
-	   2) Parse the UA_Node from the ExtensionObject
-	   3) Create a new entry in the namespace
-	   4) Add the reference to the parent.
-	 */
-
- ret:
-	Namespace_releaseManagedNode(parent);
-	return result;
+#define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do { \
+        status |= ACTION;                           \
+        if(status != UA_SUCCESS) {                  \
+            CLEAN_UP;                               \
+            goto GOTO;                              \
+        } } while(0)                                \
+
+static UA_AddNodesResult addSingleNode(UA_Server *server, UA_AddNodesItem *item) {
+    UA_AddNodesResult result;
+    UA_AddNodesResult_init(&result);
+
+    // TODO: search for namespaceUris and not only ns-ids.
+    /* UA_Boolean    nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId); */
+
+    if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
+        result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+        return result;
+    }
+
+    UA_Int32       status = UA_SUCCESS;
+    const UA_Node *parent;
+    CHECKED_ACTION(UA_NodeStore_get(server->nodestore, &item->parentNodeId.nodeId, &parent),
+                   result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
+
+    /* if(!nodeid_isnull && NodeStore_contains(ns, &item->requestedNewNodeId.nodeId)) { */
+    /*  result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; */
+    /*  goto ret; */
+    /* } */
+
+    /**
+       TODO:
+
+       1) Check for the remaining conditions
+       Bad_ReferenceTypeIdInvalid  See Table 166 for the description of this result code.
+       Bad_ReferenceNotAllowed  The reference could not be created because it violates constraints imposed by the data model.
+       Bad_NodeClassInvalid  See Table 166 for the description of this result code.
+       Bad_BrowseNameInvalid  See Table 166 for the description of this result code.
+       Bad_BrowseNameDuplicated  The browse name is not unique among nodes that share the same relationship with the parent.
+       Bad_NodeAttributesInvalid  The node Attributes are not valid for the node class.
+       Bad_TypeDefinitionInvalid  See Table 166 for the description of this result code.
+       Bad_UserAccessDenied  See Table 165 for the description of this result code
+
+       2) Parse the UA_Node from the ExtensionObject
+       3) Create a new entry in the namespace
+       4) Add the reference to the parent.
+     */
+
+ret:
+    UA_NodeStore_releaseManagedNode(parent);
+    return result;
 }
 
-UA_Int32 Service_AddNodes(UA_Session *session, const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
-
-	Application *application;
-	if(session == UA_NULL)
-		return UA_ERROR;	// TODO: Return error message
-	UA_Session_getApplicationPointer(session,&application);
-	if(application == UA_NULL)
-		return UA_ERROR;
-
-	UA_Int32 nodestoaddsize = request->nodesToAddSize;
-	if(nodestoaddsize <= 0) {
-		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
-		response->resultsSize = 0;
-		return UA_SUCCESS;
-	}
-
-	response->resultsSize = nodestoaddsize;
-	UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
-	for(int i = 0; i < nodestoaddsize; i++) {
-		DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i].browseName)));
-		response->results[i] = addSingleNode(application, &request->nodesToAdd[i]);
-	}
-	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
-	response->diagnosticInfosSize = -1;
-	return UA_SUCCESS;
-	
+UA_Int32 Service_AddNodes(UA_Server *server, UA_Session *session,
+                          const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
+    if(session == UA_NULL)
+        return UA_ERROR;    // TODO: Return error message
+
+    UA_Int32 nodestoaddsize = request->nodesToAddSize;
+    if(nodestoaddsize <= 0) {
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+        response->resultsSize = 0;
+        return UA_SUCCESS;
+    }
+
+    response->resultsSize = nodestoaddsize;
+    UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
+    for(int i = 0;i < nodestoaddsize;i++) {
+        DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i].browseName)));
+        response->results[i] = addSingleNode(server, &request->nodesToAdd[i]);
+    }
+    response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
+    response->diagnosticInfosSize = -1;
+    return UA_SUCCESS;
+
 }
 
 static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
-	// TODO: Check if reference already exists
-	UA_Int32 retval;
-	UA_Int32 count = node->referencesSize;
-	UA_ReferenceNode *old_refs = node->references;
-	UA_ReferenceNode *new_refs;
-	if(count < 0) count = 0; 
-
-	retval = UA_alloc((void **)&new_refs, sizeof(UA_ReferenceNode)*(count+1));
-	if(retval != UA_SUCCESS)
-		return UA_ERROR;
-	UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
-	retval |= UA_ReferenceNode_copy(reference, &new_refs[count]);
-
-	if(retval != UA_SUCCESS) {
-		UA_free(new_refs);
-		return retval;
-	}
-	
-	node->references = new_refs;
-	node->referencesSize = count+1;
-	UA_free(old_refs);
-	return retval;
+    // TODO: Check if reference already exists
+    UA_Int32 retval;
+    UA_Int32 count = node->referencesSize;
+    UA_ReferenceNode *old_refs = node->references;
+    UA_ReferenceNode *new_refs;
+    if(count < 0) count = 0;
+
+    retval = UA_alloc((void **)&new_refs, sizeof(UA_ReferenceNode)*(count+1));
+    if(retval != UA_SUCCESS)
+        return UA_ERROR;
+    UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
+    retval |= UA_ReferenceNode_copy(reference, &new_refs[count]);
+
+    if(retval != UA_SUCCESS) {
+        UA_free(new_refs);
+        return retval;
+    }
+
+    node->references     = new_refs;
+    node->referencesSize = count+1;
+    UA_free(old_refs);
+    return retval;
 }
 
-UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, Namespace *targetns) {
-	UA_Int32 retval = AddSingleReference(node, reference);
-	UA_Node *targetnode;
-	UA_ReferenceNode inversereference;
-	if(retval != UA_SUCCESS || targetns == UA_NULL)
-		return retval;
-
-	// Do a copy every time?
-	if(Namespace_get(targetns, &reference->targetId.nodeId, (const UA_Node**)&targetnode) != UA_SUCCESS)
-		return UA_ERROR;
-
-	inversereference.referenceTypeId = reference->referenceTypeId;
-	inversereference.isInverse = !reference->isInverse;
-	inversereference.targetId.nodeId = node->nodeId;
-	inversereference.targetId.namespaceUri = UA_STRING_NULL;
-	inversereference.targetId.serverIndex = 0;
-	retval = AddSingleReference(targetnode, &inversereference);
-	Namespace_releaseManagedNode(targetnode);
-
-	return retval;
+UA_Int32 AddReference(UA_NodeStore *targetns, UA_Node *node, UA_ReferenceNode *reference) {
+    UA_Int32 retval = AddSingleReference(node, reference);
+    UA_Node *targetnode;
+    UA_ReferenceNode inversereference;
+    if(retval != UA_SUCCESS || targetns == UA_NULL)
+        return retval;
+
+    // Do a copy every time?
+    if(UA_NodeStore_get(targetns, &reference->targetId.nodeId, (const UA_Node **)&targetnode) != UA_SUCCESS)
+        return UA_ERROR;
+
+    inversereference.referenceTypeId       = reference->referenceTypeId;
+    inversereference.isInverse             = !reference->isInverse;
+    inversereference.targetId.nodeId       = node->nodeId;
+    inversereference.targetId.namespaceUri = UA_STRING_NULL;
+    inversereference.targetId.serverIndex  = 0;
+    retval = AddSingleReference(targetnode, &inversereference);
+    UA_NodeStore_releaseManagedNode(targetnode);
+
+    return retval;
 }
 
-UA_Int32 Service_AddReferences(UA_Session *session, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response) {
-	return UA_ERROR;
+UA_Int32 Service_AddReferences(UA_Server *server, UA_Session *session,
+                               const UA_AddReferencesRequest *request,
+                               UA_AddReferencesResponse *response) {
+    return UA_ERROR;
 }

+ 15 - 21
src/server/ua_services_securechannel.c

@@ -1,26 +1,20 @@
 #include "ua_services.h"
-#include "ua_transport_binary_secure.h"
 
-UA_Int32 Service_OpenSecureChannel(SL_Channel *channel,
-const UA_OpenSecureChannelRequest* request,
-UA_OpenSecureChannelResponse* response)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	SL_channelState channelState;
-	//channel takes care of opening process
-	retval |= SL_Channel_processOpenRequest(channel, request,response);
-	retval |= SL_Channel_getState(channel, &channelState);
-	return retval;
+UA_Int32 Service_OpenSecureChannel(UA_Server *server, UA_Connection *connection,
+                                   const UA_OpenSecureChannelRequest *request,
+                                   UA_OpenSecureChannelResponse *response) {
+    UA_Int32 retval = UA_SUCCESS;
+    // todo: if(request->clientProtocolVersion != protocolVersion)
+    if(request->requestType == UA_SECURITYTOKEN_ISSUE)
+        retval |= UA_SecureChannelManager_open(server->secureChannelManager, connection, request, response);
+    else
+        retval |= UA_SecureChannelManager_renew(server->secureChannelManager, connection, request, response);
+    return retval;
 }
 
-UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureChannelRequest *request,
-UA_CloseSecureChannelResponse *response)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	UA_UInt32 channelId;
-	SL_Channel_getChannelId(channel,&channelId);
-	SL_ChannelManager_removeChannel(channelId);
-// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
-
-return retval;
+UA_Int32 Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel,
+                                    const UA_CloseSecureChannelRequest *request,
+                                    UA_CloseSecureChannelResponse *response) {
+    return UA_SecureChannelManager_close(server->secureChannelManager, channel->securityToken.channelId);
+    // 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
 }

+ 39 - 47
src/server/ua_services_session.c

@@ -1,54 +1,46 @@
 #include "ua_services.h"
-#include "ua_application.h"
-
-
-UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
-#ifdef DEBUG
-	UA_String_printf("CreateSession Service - endpointUrl=", &(request->endpointUrl));
-#endif
-	UA_Session *newSession;
-	UA_Int64 timeout;
-
-	UA_SessionManager_getSessionTimeout(&timeout);
-	UA_Session_new(&newSession);
-	//TODO get maxResponseMessageSize
-	UA_Session_init(newSession, (UA_String*)&request->sessionName,
-	request->requestedSessionTimeout,
-	request->maxResponseMessageSize,
-	9999,
-	(UA_Session_idProvider)UA_SessionManager_generateSessionId,
-	timeout);
-
-	UA_SessionManager_addSession(newSession);
-	UA_Session_getId(newSession, &response->sessionId);
-	UA_Session_getToken(newSession, &(response->authenticationToken));
-	response->revisedSessionTimeout = timeout;
-	//TODO fill results
-	return UA_SUCCESS;
+#include "ua_server.h"
+
+UA_Int32 Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
+                               const UA_CreateSessionRequest *request,
+                               UA_CreateSessionResponse *response) {
+    /* UA_Session *newSession;
+       UA_Int64 timeout;
+
+       UA_SessionManager_getSessionTimeout(&timeout);
+       UA_Session_new(&newSession);
+       //TODO get maxResponseMessageSize
+       UA_Session_setApplicationPointer(newSession, &server->applications[0]); // todo: select application according to the endpointurl in the request
+       UA_Session_init(newSession, (UA_String*)&request->sessionName,
+       request->requestedSessionTimeout,
+       request->maxResponseMessageSize,
+       9999,
+       (UA_Session_idProvider)UA_SessionManager_generateSessionId,
+       timeout);
+
+       UA_SessionManager_addSession(newSession);
+       UA_Session_getId(newSession, &response->sessionId);
+       UA_Session_getToken(newSession, &(response->authenticationToken));
+       response->revisedSessionTimeout = timeout; */
+    //TODO fill results
+    return UA_SUCCESS;
 }
 
-UA_Int32 Service_ActivateSession(SL_Channel *channel, UA_Session *session,
-		const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response)
-{
-
-	UA_Session_bind(session, channel);
-
-	UA_Session_setApplicationPointer(session, &appMockup);
-#ifdef DEBUG
-	UA_NodeId_printf("ActivateSession - authToken=", &(request->requestHeader.authenticationToken));
-	// 321 == AnonymousIdentityToken_Encoding_DefaultBinary
-	UA_NodeId_printf("ActivateSession - uIdToken.type=", &(request->userIdentityToken.typeId));
-	UA_ByteString_printx_hex("ActivateSession - uIdToken.body=", &(request->userIdentityToken.body));
-#endif
-	//TODO fill results
-	return UA_SUCCESS;
+UA_Int32 Service_ActivateSession(UA_Server *server, UA_Session *session,
+                                 const UA_ActivateSessionRequest *request,
+                                 UA_ActivateSessionResponse *response) {
+    //UA_Session_bind(session, channel);
+    //TODO fill results
+    return UA_SUCCESS;
 }
 
-UA_Int32 Service_CloseSession(UA_Session *session, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response) {
-	UA_NodeId sessionId;
-	UA_Session_getId(session,&sessionId);
+UA_Int32 Service_CloseSession(UA_Server *server, UA_Session *session,
+                              const UA_CloseSessionRequest *request,
+                              UA_CloseSessionResponse *response) {
+    /* UA_NodeId sessionId; */
+    /* UA_Session_getId(session,&sessionId); */
 
-	UA_SessionManager_removeSession(&sessionId);
-// FIXME: set response
-return UA_SUCCESS;
+    /* UA_SessionManager_removeSession(&sessionId); */
+    // FIXME: set response
+    return UA_SUCCESS;
 }

+ 22 - 22
src/server/ua_services_subscription.c

@@ -7,32 +7,32 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 
-UA_Int32 Service_CreateSubscription(UA_Session *session, const UA_CreateSubscriptionRequest *request,
-                                   UA_CreateSubscriptionResponse *response)
-{
+UA_Int32 Service_CreateSubscription(UA_Server *server, UA_Session *session,
+                                    const UA_CreateSubscriptionRequest *request,
+                                    UA_CreateSubscriptionResponse *response) {
 
-	response->subscriptionId = 42;
-	response->revisedPublishingInterval = 100000;
-	response->revisedLifetimeCount = 120000;
-	response->revisedMaxKeepAliveCount = 50;
-	return UA_SUCCESS;
+    response->subscriptionId            = 42;
+    response->revisedPublishingInterval = 100000;
+    response->revisedLifetimeCount      = 120000;
+    response->revisedMaxKeepAliveCount  = 50;
+    return UA_SUCCESS;
 }
 
-UA_Int32 Service_Publish(UA_Session *session, const UA_PublishRequest *request,
-                                   UA_PublishResponse *response)
-{
+UA_Int32 Service_Publish(UA_Server *server, UA_Session *session,
+                         const UA_PublishRequest *request,
+                         UA_PublishResponse *response) {
 
-	response->subscriptionId = 42;
-	response->notificationMessage.sequenceNumber = 1;
-	response->notificationMessage.publishTime = UA_DateTime_now();
-	return UA_SUCCESS;
+    response->subscriptionId = 42;
+    response->notificationMessage.sequenceNumber = 1;
+    response->notificationMessage.publishTime    = UA_DateTime_now();
+    return UA_SUCCESS;
 }
 
-UA_Int32 Service_SetPublishingMode(UA_Session *session, const UA_SetPublishingModeRequest *request,
-                                   UA_SetPublishingModeResponse *response)
-{
-	response->diagnosticInfos = UA_NULL;
-	response->results = UA_NULL;
-	response->resultsSize = 0;
-	return UA_SUCCESS;
+UA_Int32 Service_SetPublishingMode(UA_Server *server, UA_Session *session,
+                                   const UA_SetPublishingModeRequest *request,
+                                   UA_SetPublishingModeResponse *response) {
+    response->diagnosticInfos = UA_NULL;
+    response->results = UA_NULL;
+    response->resultsSize     = 0;
+    return UA_SUCCESS;
 }

+ 220 - 214
src/server/ua_services_view.c

@@ -1,240 +1,246 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 
-UA_Int32 Service_Browse_getReferenceDescription(Namespace *ns, UA_ReferenceNode* reference, UA_UInt32 nodeClassMask,
-												UA_UInt32 resultMask, UA_ReferenceDescription* referenceDescription) {
-	const UA_Node* foundNode;
-	if(Namespace_get(ns,&reference->targetId.nodeId,&foundNode) != UA_SUCCESS)
-		return UA_ERROR;
-
-	UA_NodeId_copy(&foundNode->nodeId, &referenceDescription->nodeId.nodeId);
-	//TODO ExpandedNodeId is a mockup
-	referenceDescription->nodeId.serverIndex = 0;
-	referenceDescription->nodeId.namespaceUri.length = -1;
-
-	UA_UInt32 mask = 0;
-	for (mask = 0x01; mask <= 0x40; mask *= 2) {
-		switch (mask & (resultMask)) {
-		case UA_BROWSERESULTMASK_REFERENCETYPEID:
-			UA_NodeId_copy(&reference->referenceTypeId, &referenceDescription->referenceTypeId);
-			break;
-		case UA_BROWSERESULTMASK_ISFORWARD:
-			referenceDescription->isForward = !reference->isInverse;
-			break;
-		case UA_BROWSERESULTMASK_NODECLASS:
-			UA_NodeClass_copy(&foundNode->nodeClass, &referenceDescription->nodeClass);
-			break;
-		case UA_BROWSERESULTMASK_BROWSENAME:
-			UA_QualifiedName_copy(&foundNode->browseName, &referenceDescription->browseName);
-			break;
-		case UA_BROWSERESULTMASK_DISPLAYNAME:
-			UA_LocalizedText_copy(&foundNode->displayName, &referenceDescription->displayName);
-			break;
-		case UA_BROWSERESULTMASK_TYPEDEFINITION:
-			if (foundNode->nodeClass != UA_NODECLASS_OBJECT &&
-				foundNode->nodeClass != UA_NODECLASS_VARIABLE)
-				break;
-
-			for(UA_Int32 i = 0;i<foundNode->referencesSize;i++) {
-				UA_ReferenceNode *ref = &foundNode->references[i];
-				if(ref->referenceTypeId.identifier.numeric == 40 /* hastypedefinition */) {
-					UA_ExpandedNodeId_copy(&ref->targetId, &referenceDescription->typeDefinition);
-					break;
-				}
-			}
-			break;
-		}
-	}
-	
-	Namespace_releaseManagedNode(foundNode);
-	return UA_SUCCESS;
+UA_Int32 Service_Browse_getReferenceDescription(UA_NodeStore *ns, UA_ReferenceNode *reference,
+                                                UA_UInt32 nodeClassMask, UA_UInt32 resultMask,
+                                                UA_ReferenceDescription *referenceDescription) {
+    const UA_Node *foundNode;
+    if(UA_NodeStore_get(ns, &reference->targetId.nodeId, &foundNode) != UA_SUCCESS)
+        return UA_ERROR;
+
+    UA_NodeId_copy(&foundNode->nodeId, &referenceDescription->nodeId.nodeId);
+    //TODO ExpandedNodeId is a mockup
+    referenceDescription->nodeId.serverIndex = 0;
+    referenceDescription->nodeId.namespaceUri.length = -1;
+
+    UA_UInt32 mask = 0;
+    for(mask = 0x01;mask <= 0x40;mask *= 2) {
+        switch(mask & (resultMask)) {
+        case UA_BROWSERESULTMASK_REFERENCETYPEID:
+            UA_NodeId_copy(&reference->referenceTypeId, &referenceDescription->referenceTypeId);
+            break;
+
+        case UA_BROWSERESULTMASK_ISFORWARD:
+            referenceDescription->isForward = !reference->isInverse;
+            break;
+
+        case UA_BROWSERESULTMASK_NODECLASS:
+            UA_NodeClass_copy(&foundNode->nodeClass, &referenceDescription->nodeClass);
+            break;
+
+        case UA_BROWSERESULTMASK_BROWSENAME:
+            UA_QualifiedName_copy(&foundNode->browseName, &referenceDescription->browseName);
+            break;
+
+        case UA_BROWSERESULTMASK_DISPLAYNAME:
+            UA_LocalizedText_copy(&foundNode->displayName, &referenceDescription->displayName);
+            break;
+
+        case UA_BROWSERESULTMASK_TYPEDEFINITION:
+            if(foundNode->nodeClass != UA_NODECLASS_OBJECT &&
+               foundNode->nodeClass != UA_NODECLASS_VARIABLE)
+                break;
+
+            for(UA_Int32 i = 0;i < foundNode->referencesSize;i++) {
+                UA_ReferenceNode *ref = &foundNode->references[i];
+                if(ref->referenceTypeId.identifier.numeric == 40 /* hastypedefinition */) {
+                    UA_ExpandedNodeId_copy(&ref->targetId, &referenceDescription->typeDefinition);
+                    break;
+                }
+            }
+            break;
+        }
+    }
+
+    UA_NodeStore_releaseManagedNode(foundNode);
+    return UA_SUCCESS;
 }
 
 /* singly-linked list */
 struct SubRefTypeId {
-	UA_NodeId id;
-	UA_SLIST_ENTRY(SubRefTypeId) next;
+    UA_NodeId id;
+    SLIST_ENTRY(SubRefTypeId) next;
 };
-UA_SLIST_HEAD(SubRefTypeIdList, SubRefTypeId);
-
-UA_UInt32 walkReferenceTree(Namespace *ns, const UA_ReferenceTypeNode *current, struct SubRefTypeIdList *list) {
-	// insert the current referencetype
-	struct SubRefTypeId *element;
-	UA_alloc((void**)&element, sizeof(struct SubRefTypeId));
-	element->id = current->nodeId;
-	UA_SLIST_INSERT_HEAD(list, element, next);
-
-	UA_UInt32 count = 1; // the current element
-
-	// walk the tree
-	for(UA_Int32 i = 0;i < current->referencesSize;i++) {
-		if(current->references[i].referenceTypeId.identifier.numeric == 45 /* HasSubtype */ &&
-		   current->references[i].isInverse == UA_FALSE) {
-			const UA_Node *node;
-			if(Namespace_get(ns, &current->references[i].targetId.nodeId, &node) == UA_SUCCESS &&
-			   node->nodeClass == UA_NODECLASS_REFERENCETYPE) {
-				count += walkReferenceTree(ns,(UA_ReferenceTypeNode*)node, list);
-				Namespace_releaseManagedNode(node);
-			}
-		}
-	}
-	return count;
+SLIST_HEAD(SubRefTypeIdList, SubRefTypeId);
+
+UA_UInt32 walkReferenceTree(UA_NodeStore *ns, const UA_ReferenceTypeNode *current,
+                            struct SubRefTypeIdList *list) {
+    // insert the current referencetype
+    struct SubRefTypeId *element;
+    UA_alloc((void **)&element, sizeof(struct SubRefTypeId));
+    element->id = current->nodeId;
+    SLIST_INSERT_HEAD(list, element, next);
+
+    UA_UInt32 count = 1; // the current element
+
+    // walk the tree
+    for(UA_Int32 i = 0;i < current->referencesSize;i++) {
+        if(current->references[i].referenceTypeId.identifier.numeric == 45 /* HasSubtype */ &&
+           current->references[i].isInverse == UA_FALSE) {
+            const UA_Node *node;
+            if(UA_NodeStore_get(ns, &current->references[i].targetId.nodeId, &node) == UA_SUCCESS
+               && node->nodeClass == UA_NODECLASS_REFERENCETYPE) {
+                count += walkReferenceTree(ns, (UA_ReferenceTypeNode *)node, list);
+                UA_NodeStore_releaseManagedNode(node);
+            }
+        }
+    }
+    return count;
 }
 
 /* We do not search across namespaces so far. The id of the father-referencetype is returned in the array also. */
-static UA_Int32 findSubReferenceTypes(Namespace *ns, UA_NodeId *rootReferenceType, UA_NodeId **ids, UA_UInt32 *idcount) {
-	struct SubRefTypeIdList list;
-	UA_UInt32 count;
-	UA_SLIST_INIT(&list);
-
-	// walk the tree
-	const UA_ReferenceTypeNode *root;
-	if(Namespace_get(ns, rootReferenceType, (const UA_Node**)&root) != UA_SUCCESS ||
-	   root->nodeClass != UA_NODECLASS_REFERENCETYPE)
-		return UA_ERROR;
-	count = walkReferenceTree(ns, root, &list);
-	Namespace_releaseManagedNode((const UA_Node*) root);
-
-	// copy results into an array
-	UA_alloc((void**) ids, sizeof(UA_NodeId)*count);
-	for(UA_UInt32 i = 0; i < count;i++) {
-		struct SubRefTypeId *element = UA_SLIST_FIRST(&list);
-		UA_NodeId_copy(&element->id, &(*ids)[i]);
-		UA_SLIST_REMOVE_HEAD(&list, next);
-		UA_free(element);
-	}
-	*idcount = count;
-
-	return UA_SUCCESS;
+static UA_Int32 findSubReferenceTypes(UA_NodeStore *ns, UA_NodeId *rootReferenceType,
+                                      UA_NodeId **ids, UA_UInt32 *idcount) {
+    struct SubRefTypeIdList list;
+    UA_UInt32 count;
+    SLIST_INIT(&list);
+
+    // walk the tree
+    const UA_ReferenceTypeNode *root;
+    if(UA_NodeStore_get(ns, rootReferenceType, (const UA_Node **)&root) != UA_SUCCESS ||
+       root->nodeClass != UA_NODECLASS_REFERENCETYPE)
+        return UA_ERROR;
+    count = walkReferenceTree(ns, root, &list);
+    UA_NodeStore_releaseManagedNode((const UA_Node *)root);
+
+    // copy results into an array
+    UA_alloc((void **)ids, sizeof(UA_NodeId)*count);
+    for(UA_UInt32 i = 0;i < count;i++) {
+        struct SubRefTypeId *element = SLIST_FIRST(&list);
+        UA_NodeId_copy(&element->id, &(*ids)[i]);
+        SLIST_REMOVE_HEAD(&list, next);
+        UA_free(element);
+    }
+    *idcount = count;
+
+    return UA_SUCCESS;
 }
 
 /* is this a relevant reference? */
-static INLINE UA_Boolean Service_Browse_returnReference(UA_BrowseDescription *browseDescription, UA_ReferenceNode* reference,
-														UA_NodeId *relevantRefTypes, UA_UInt32 relevantRefTypesCount) {
-	if (reference->isInverse == UA_TRUE && browseDescription->browseDirection == UA_BROWSEDIRECTION_FORWARD)
-		return UA_FALSE;
-	else if (reference->isInverse == UA_FALSE && browseDescription->browseDirection == UA_BROWSEDIRECTION_INVERSE)
-		return UA_FALSE;
-	for(UA_UInt32 i = 0; i<relevantRefTypesCount;i++) {
-		if(UA_NodeId_equal(&browseDescription->referenceTypeId, &relevantRefTypes[i]) == UA_EQUAL)
-			return UA_TRUE;
-	}
-	return UA_FALSE;
+static INLINE UA_Boolean Service_Browse_returnReference(UA_BrowseDescription *browseDescription,
+                                                        UA_ReferenceNode     *reference,
+                                                        UA_NodeId            *relevantRefTypes,
+                                                        UA_UInt32             relevantRefTypesCount) {
+    if(reference->isInverse == UA_TRUE &&
+       browseDescription->browseDirection == UA_BROWSEDIRECTION_FORWARD)
+        return UA_FALSE;
+    else if(reference->isInverse == UA_FALSE &&
+            browseDescription->browseDirection == UA_BROWSEDIRECTION_INVERSE)
+        return UA_FALSE;
+    for(UA_UInt32 i = 0;i < relevantRefTypesCount;i++) {
+        if(UA_NodeId_equal(&browseDescription->referenceTypeId, &relevantRefTypes[i]) == UA_EQUAL)
+            return UA_TRUE;
+    }
+    return UA_FALSE;
 }
 
 /* Return results to a single browsedescription. */
-static void Service_Browse_getBrowseResult(Namespace *ns, UA_BrowseDescription *browseDescription,
-										   UA_UInt32 maxReferences, UA_BrowseResult *browseResult) {
-	const UA_Node* node;
-	UA_NodeId *relevantReferenceTypes;
-	UA_UInt32 relevantReferenceTypesCount = 0;
-	if(Namespace_get(ns, &browseDescription->nodeId, &node) != UA_SUCCESS) {
-		browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-		return;
-	}
-
-	// 0 => unlimited references
-	if(maxReferences == 0)
-		maxReferences = node->referencesSize;
-
-	// discover the relevant subtypes
-	if(!browseDescription->includeSubtypes ||
-	   findSubReferenceTypes(ns, &browseDescription->referenceTypeId, &relevantReferenceTypes, &relevantReferenceTypesCount) != UA_SUCCESS) {
-		UA_alloc((void**)&relevantReferenceTypes, sizeof(UA_NodeId));
-		UA_NodeId_copy(&browseDescription->referenceTypeId, relevantReferenceTypes);
-		relevantReferenceTypesCount = 1;
-	}
-
-	/* We do not use a linked list but traverse the nodes references list twice
-	 * (once for counting, once for generating the referencedescriptions). That
-	 * is much faster than using a linked list, since the references are
-	 * allocated in a continuous blob and RAM access is predictible/does not
-	 * miss cache lines so often. TODO: measure with some huge objects! */
-	UA_UInt32 refs = 0;
-	for(UA_Int32 i=0;i < node->referencesSize && refs <= maxReferences;i++) {
-		if(Service_Browse_returnReference(browseDescription, &node->references[i], relevantReferenceTypes, relevantReferenceTypesCount))
-			refs++;
-	}
-
-	// can we return all relevant references at once?
-	UA_Boolean finished = UA_TRUE;
-	if(refs > maxReferences) {
-		refs--;
-		finished = UA_FALSE;
-	}
-	
-	browseResult->referencesSize = refs;
-	UA_Array_new((void**) &browseResult->references, refs, &UA_.types[UA_REFERENCEDESCRIPTION]);
-	
-	for(UA_UInt32 i = 0, j=0; j < refs; i++) {
-		if(!Service_Browse_returnReference(browseDescription, &node->references[i], relevantReferenceTypes, relevantReferenceTypesCount))
-			continue;
-		
-		if(Service_Browse_getReferenceDescription(ns, &node->references[i], browseDescription->nodeClassMask,
-												  browseDescription->resultMask, &browseResult->references[j]) != UA_SUCCESS)
-			browseResult->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
-		j++;
-	}
-
-	if(!finished) {
-		// Todo. Set the Statuscode and the continuation point.
-	}
-	
-	Namespace_releaseManagedNode(node);
-	UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesCount, &UA_.types[UA_NODEID]);
+static void Service_Browse_getBrowseResult(UA_NodeStore         *ns,
+                                           UA_BrowseDescription *browseDescription,
+                                           UA_UInt32             maxReferences,
+                                           UA_BrowseResult      *browseResult) {
+    const UA_Node *node;
+    UA_NodeId     *relevantReferenceTypes;
+    UA_UInt32      relevantReferenceTypesCount = 0;
+    if(UA_NodeStore_get(ns, &browseDescription->nodeId, &node) != UA_SUCCESS) {
+        browseResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
+        return;
+    }
+
+    // 0 => unlimited references
+    if(maxReferences == 0)
+        maxReferences = node->referencesSize;
+
+    // discover the relevant subtypes
+    if(!browseDescription->includeSubtypes ||
+       findSubReferenceTypes(ns, &browseDescription->referenceTypeId, &relevantReferenceTypes,
+                             &relevantReferenceTypesCount) != UA_SUCCESS) {
+        UA_alloc((void **)&relevantReferenceTypes, sizeof(UA_NodeId));
+        UA_NodeId_copy(&browseDescription->referenceTypeId, relevantReferenceTypes);
+        relevantReferenceTypesCount = 1;
+    }
+
+    /* We do not use a linked list but traverse the nodes references list twice
+     * (once for counting, once for generating the referencedescriptions). That
+     * is much faster than using a linked list, since the references are
+     * allocated in a continuous blob and RAM access is predictible/does not
+     * miss cache lines so often. TODO: measure with some huge objects! */
+    UA_UInt32 refs = 0;
+    for(UA_Int32 i = 0;i < node->referencesSize && refs <= maxReferences;i++) {
+        if(Service_Browse_returnReference(browseDescription, &node->references[i], relevantReferenceTypes,
+                                          relevantReferenceTypesCount))
+            refs++;
+    }
+
+    // can we return all relevant references at once?
+    UA_Boolean finished = UA_TRUE;
+    if(refs > maxReferences) {
+        refs--;
+        finished = UA_FALSE;
+    }
+
+    browseResult->referencesSize = refs;
+    UA_Array_new((void **)&browseResult->references, refs, &UA_.types[UA_REFERENCEDESCRIPTION]);
+
+    for(UA_UInt32 i = 0, j = 0;j < refs;i++) {
+        if(!Service_Browse_returnReference(browseDescription, &node->references[i], relevantReferenceTypes,
+                                           relevantReferenceTypesCount))
+            continue;
+
+        if(Service_Browse_getReferenceDescription(ns, &node->references[i], browseDescription->nodeClassMask,
+                                                  browseDescription->resultMask,
+                                                  &browseResult->references[j]) != UA_SUCCESS)
+            browseResult->statusCode = UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE;
+        j++;
+    }
+
+    if(!finished) {
+        // Todo. Set the Statuscode and the continuation point.
+    }
+
+    UA_NodeStore_releaseManagedNode(node);
+    UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesCount, &UA_.types[UA_NODEID]);
 }
 
-UA_Int32 Service_Browse(UA_Session *session, const UA_BrowseRequest *request, UA_BrowseResponse *response) {
-	UA_Int32 retval = UA_SUCCESS;
-	Application *application;
-	if(session == UA_NULL)
-	{
-		return UA_ERROR;
-	}
-	UA_Session_getApplicationPointer(session, &application);
-	if(application == UA_NULL)
-	{
-		return UA_ERROR;
-	}
-	DBG_VERBOSE(UA_NodeId_printf("BrowseService - view=", &request->view.viewId));
-
-	//TODO request->view not used atm
-	UA_Array_new((void**) &(response->results), request->nodesToBrowseSize, &UA_.types[UA_BROWSERESULT]);
-	response->resultsSize = request->nodesToBrowseSize;
-
-	for(UA_Int32 i=0; i < request->nodesToBrowseSize; i++) {
-		Namespace *ns = UA_indexedList_findValue(application->namespaces, request->nodesToBrowse[i].nodeId.namespaceIndex);
-		if(ns == UA_NULL) {
-			response->results[i].statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
-			continue;
-		}
-		
-		// Service_Browse_getBrowseResult has no return value. All errors are resolved internally.
-		Service_Browse_getBrowseResult(ns, &request->nodesToBrowse[i],
-									   request->requestedMaxReferencesPerNode, &response->results[i]);
-	}
-
-	//TODO fill Diagnostic info array
-	response->diagnosticInfosSize = 0;
-	response->diagnosticInfos = UA_NULL;
-	return retval;
+UA_Int32 Service_Browse(UA_Server *server, UA_Session *session,
+                        const UA_BrowseRequest *request, UA_BrowseResponse *response) {
+    UA_Int32 retval = UA_SUCCESS;
+    if(server == UA_NULL || session == UA_NULL)
+        return UA_ERROR;
+
+    //TODO request->view not used atm
+    UA_Array_new((void **)&(response->results), request->nodesToBrowseSize, &UA_.types[UA_BROWSERESULT]);
+    response->resultsSize = request->nodesToBrowseSize;
+
+    for(UA_Int32 i = 0;i < request->nodesToBrowseSize;i++) {
+        // Service_Browse_getBrowseResult has no return value. All errors are resolved internally.
+        Service_Browse_getBrowseResult(server->nodestore, &request->nodesToBrowse[i],
+                                       request->requestedMaxReferencesPerNode,
+                                       &response->results[i]);
+    }
+
+    //TODO fill Diagnostic info array
+    response->diagnosticInfosSize = 0;
+    response->diagnosticInfos     = UA_NULL;
+    return retval;
 }
 
 
-UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Session *session, const UA_TranslateBrowsePathsToNodeIdsRequest *request,
-											   UA_TranslateBrowsePathsToNodeIdsResponse *response) {
-	UA_Int32 retval = UA_SUCCESS;
-	DBG_VERBOSE(printf("TranslateBrowsePathsToNodeIdsService - %i path(s)", request->browsePathsSize));
+UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
+                                               const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+                                               UA_TranslateBrowsePathsToNodeIdsResponse *response) {
+    UA_Int32 retval = UA_SUCCESS;
+    DBG_VERBOSE(printf("TranslateBrowsePathsToNodeIdsService - %i path(s)", request->browsePathsSize));
 
-	// Allocate space for a correct answer
-	response->resultsSize = request->browsePathsSize;
-	// _init of the elements is done in Array_new
-	UA_Array_new((void**) &response->results, request->browsePathsSize, &UA_.types[UA_BROWSEPATHRESULT]);
+    // Allocate space for a correct answer
+    response->resultsSize = request->browsePathsSize;
+    // _init of the elements is done in Array_new
+    UA_Array_new((void **)&response->results, request->browsePathsSize, &UA_.types[UA_BROWSEPATHRESULT]);
 
-	for (UA_Int32 i = 0; i < request->browsePathsSize; i++) {
-		//FIXME: implement
-		response->results[i].statusCode = UA_STATUSCODE_BADNOMATCH;
-	}
+    for(UA_Int32 i = 0;i < request->browsePathsSize;i++) {
+        //FIXME: implement
+        response->results[i].statusCode = UA_STATUSCODE_BADNOMATCH;
+    }
 
-	return retval;
+    return retval;
 }

+ 140 - 149
src/server/ua_session_manager.c

@@ -1,171 +1,162 @@
 #include "ua_session_manager.h"
+#include "util/ua_list.h"
 
 struct UA_SessionManager {
-	UA_list_List sessions;
-	UA_UInt32 maxSessionCount;
-	UA_Int32 lastSessionId;
-	UA_UInt32 currentSessionCount;
-	UA_DateTime maxSessionLifeTime;
-	UA_DateTime sessionTimeout;
+    UA_list_List sessions;
+    UA_UInt32    maxSessionCount;
+    UA_Int32     lastSessionId;
+    UA_UInt32    currentSessionCount;
+    UA_DateTime  maxSessionLifeTime;
+    UA_DateTime  sessionTimeout;
 };
+UA_Int32 UA_SessionManager_new(UA_SessionManager **sessionManager, UA_UInt32 maxSessionCount,
+                               UA_UInt32 sessionTimeout, UA_UInt32 startSessionId) {
+    UA_Int32 retval = UA_SUCCESS;
+    retval |= UA_alloc((void **)sessionManager, sizeof(UA_SessionManager));
+    if(retval != UA_SUCCESS)
+        return UA_ERROR;
+    retval |= UA_list_init(&(*sessionManager)->sessions);
+    (*sessionManager)->maxSessionCount = maxSessionCount;
+    (*sessionManager)->lastSessionId   = startSessionId;
+    (*sessionManager)->sessionTimeout  = sessionTimeout;
+    return retval;
+}
 
-static UA_SessionManager *sessionManager;
-
-UA_Int32 UA_SessionManager_generateSessionId(UA_NodeId *sessionId) {
-	sessionId->namespaceIndex = 0;
-	sessionId->identifierType = UA_NODEIDTYPE_NUMERIC;
-	sessionId->identifier.numeric = sessionManager->lastSessionId++;
-	return UA_SUCCESS;
+UA_Int32 UA_SessionManager_delete(UA_SessionManager *sessionManager) {
+    // todo
+    return UA_SUCCESS;
 }
 
-UA_Int32 UA_SessionManager_init(UA_UInt32 maxSessionCount,UA_UInt32 sessionTimeout, UA_UInt32 startSessionId) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_alloc((void**)&sessionManager,sizeof(UA_SessionManager));
-	retval |= UA_list_init(&sessionManager->sessions);
-	sessionManager->maxSessionCount = maxSessionCount;
-	sessionManager->lastSessionId = startSessionId;
-	sessionManager->sessionTimeout = sessionTimeout;
-	return retval;
+
+UA_Int32 UA_SessionManager_generateSessionId(UA_SessionManager *sessionManager,
+                                             UA_NodeId         *sessionId) {
+    sessionId->namespaceIndex     = 0;
+    sessionId->identifierType     = UA_NODEIDTYPE_NUMERIC;
+    sessionId->identifier.numeric = sessionManager->lastSessionId++;
+    return UA_SUCCESS;
 }
 
-UA_Boolean UA_SessionManager_sessionExists(UA_Session *session) {
-	if(sessionManager == UA_NULL)
-		return UA_FALSE;
+UA_Boolean UA_SessionManager_sessionExists(UA_SessionManager *sessionManager,
+                                           UA_Session        *session) {
+    if(sessionManager == UA_NULL)
+        return UA_FALSE;
 
-	if(UA_list_search(&sessionManager->sessions,(UA_list_PayloadComparer)UA_Session_compare,(void*)session)) {
-		UA_Double pendingLifetime;
-		UA_Session_getPendingLifetime(session,&pendingLifetime);
+    if(UA_list_search(&sessionManager->sessions,
+                      (UA_list_PayloadComparer)UA_Session_compare, (void *)session)) {
+        UA_Double pendingLifetime;
+        UA_Session_getPendingLifetime(session, &pendingLifetime);
 
-		if(pendingLifetime>0)
-			return UA_TRUE;
+        if(pendingLifetime > 0)
+            return UA_TRUE;
 
-		//timeout of session reached so remove it
-		UA_NodeId sessionId;
-		UA_Session_getId(session,&sessionId);
-		UA_SessionManager_removeSession(&sessionId);
-	}
-	return UA_FALSE;
+        //timeout of session reached so remove it
+        UA_NodeId *sessionId = &session->sessionId;
+        UA_SessionManager_removeSession(sessionManager, sessionId);
+    }
+    return UA_FALSE;
 }
 
-UA_Int32 UA_SessionManager_getSessionById(UA_NodeId *sessionId, UA_Session **session) {
-	if(sessionManager == UA_NULL) {
-		*session = UA_NULL;
-		return UA_ERROR;
-	}
-
-	UA_list_Element* current = sessionManager->sessions.first;
-	while (current) {
-		if (current->payload) {
-			UA_list_Element* elem = (UA_list_Element*) current;
-			*session = ((UA_Session*) (elem->payload));
-			if(UA_Session_compareById(*session,sessionId) == UA_EQUAL){
-				UA_Double pendingLifetime;
-				UA_Session_getPendingLifetime(*session, &pendingLifetime);
-
-				if(pendingLifetime > 0)
-					return UA_SUCCESS;
-
-				//session not valid anymore -> remove it
-				UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
-				*session = UA_NULL;
-				return UA_ERROR;
-			}
-		}
-		current = current->next;
-	}
-	*session = UA_NULL;
-	return UA_ERROR;
+UA_Int32 UA_SessionManager_getSessionById(UA_SessionManager *sessionManager,
+                                          UA_NodeId *sessionId, UA_Session **session) {
+    if(sessionManager == UA_NULL) {
+        *session = UA_NULL;
+        return UA_ERROR;
+    }
+
+    UA_list_Element *current = sessionManager->sessions.first;
+    while(current) {
+        if(current->payload) {
+            UA_list_Element *elem = (UA_list_Element *)current;
+            *session = ((UA_Session *)(elem->payload));
+            if(UA_NodeId_equal(&(*session)->sessionId, sessionId) == UA_EQUAL) {
+                UA_Double pendingLifetime;
+                UA_Session_getPendingLifetime(*session, &pendingLifetime);
+
+                if(pendingLifetime > 0)
+                    return UA_SUCCESS;
+
+                //session not valid anymore -> remove it
+                UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
+                *session = UA_NULL;
+                return UA_ERROR;
+            }
+        }
+        current = current->next;
+    }
+    *session = UA_NULL;
+    return UA_ERROR;
 }
 
-UA_Int32 UA_SessionManager_getSessionByToken(UA_NodeId *token, UA_Session **session) {
-	if(sessionManager == UA_NULL) {
-		*session = UA_NULL;
-		return UA_ERROR;
-	}
-
-	UA_list_Element* current = sessionManager->sessions.first;
-	while (current) {
-		if (current->payload) {
-			UA_list_Element* elem = (UA_list_Element*) current;
-			*session = ((UA_Session*) (elem->payload));
-
-			if(UA_Session_compareByToken(*session,token) == UA_EQUAL) {
-				UA_Double pendingLifetime;
-				UA_Session_getPendingLifetime(*session, &pendingLifetime);
-
-				if(pendingLifetime > 0)
-					return UA_SUCCESS;
-
-				//session not valid anymore -> remove it
-				UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
-				*session = UA_NULL;
-				return UA_ERROR;
-			}
-		}
-		current = current->next;
-	}
-	*session = UA_NULL;
-	return UA_ERROR;
+UA_Int32 UA_SessionManager_getSessionByToken(UA_SessionManager *sessionManager,
+                                             UA_NodeId *token, UA_Session **session) {
+    if(sessionManager == UA_NULL) {
+        *session = UA_NULL;
+        return UA_ERROR;
+    }
+
+    UA_list_Element *current = sessionManager->sessions.first;
+    while(current) {
+        if(current->payload) {
+            UA_list_Element *elem = (UA_list_Element *)current;
+            *session = ((UA_Session *)(elem->payload));
+
+            if(UA_NodeId_equal(&(*session)->authenticationToken, token) == UA_EQUAL) {
+                UA_Double pendingLifetime;
+                UA_Session_getPendingLifetime(*session, &pendingLifetime);
+
+                if(pendingLifetime > 0)
+                    return UA_SUCCESS;
+
+                //session not valid anymore -> remove it
+                UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
+                *session = UA_NULL;
+                return UA_ERROR;
+            }
+        }
+        current = current->next;
+    }
+    *session = UA_NULL;
+    return UA_ERROR;
 }
 
-UA_Int32 UA_SessionManager_addSession(UA_Session *session) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_NodeId sessionId;
-	if(!UA_SessionManager_sessionExists(session)) {
-		retval |= UA_list_addPayloadToBack(&sessionManager->sessions,(void*)session);
-		UA_Session_getId(session, &sessionId);
-		printf("UA_SessionManager_addSession - added session with id = %d \n",sessionId.identifier.numeric);
-		printf("UA_SessionManager_addSession - current session count: %i \n",sessionManager->sessions.size);
-
-		return retval;
-	}
-	printf("UA_SessionManager_addSession - session already in list");
-	return UA_ERROR;
+/** Creates and adds a session. */
+UA_Int32 UA_SessionManager_addSession(UA_SessionManager *sessionManager,
+                                      UA_SecureChannel *channel, UA_Session **session) {
+    UA_Int32 retval = UA_SUCCESS;
+    if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
+        return UA_ERROR;
+    UA_Session_new(session);
+    (*session)->sessionId = (UA_NodeId) {.namespaceIndex     = 1, .identifierType = UA_NODEIDTYPE_NUMERIC,
+                                         .identifier.numeric = sessionManager->lastSessionId++ };
+    (*session)->channel   = channel;
+    channel->session      = *session;
+
+    sessionManager->currentSessionCount++;
+    return retval;
 }
 
-UA_Int32 UA_SessionManager_removeSession(UA_NodeId *sessionId) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_list_Element *element = UA_list_search(&sessionManager->sessions,(UA_list_PayloadComparer)UA_Session_compare,sessionId);
-	if(element) {
-		retval |= UA_list_removeElement(element,(UA_list_PayloadVisitor)UA_Session_delete);
-		printf("UA_SessionManager_removeSession - session removed, current count: %i \n",sessionManager->sessions.size);
-	}
-	return retval;
+UA_Int32 UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
+                                         UA_NodeId         *sessionId) {
+    UA_Int32 retval = UA_SUCCESS;
+    UA_list_Element *element =
+        UA_list_search(&sessionManager->sessions, (UA_list_PayloadComparer)UA_Session_compare,
+                       sessionId);
+    if(element) {
+        UA_Session *session = element->payload;
+        session->channel->session = UA_NULL;
+        retval |= UA_list_removeElement(element, (UA_list_PayloadVisitor)UA_Session_delete);
+        printf("UA_SessionManager_removeSession - session removed, current count: %i \n",
+               sessionManager->sessions.size);
+    }
+    return retval;
 }
-/*
-UA_Int32 UA_SessionManager_updateSessions()
-{
-	if(sessionManager == UA_NULL)
-	{
-		return UA_ERROR;
-	}
-	UA_list_Element* current = sessionManager->sessions.first;
-	while (current)
-	{
-		if (current->payload)
-		{
-			UA_list_Element* elem = (UA_list_Element*) current;
-			UA_Session *session = ((UA_Session*) (elem->payload));
-			UA_Double pendingLifetime;
-			UA_Session_getPendingLifetime(session, &pendingLifetime);
-
-			if(pendingLifetime <= 0){
-				UA_NodeId sessionId;
-				UA_Session_getId(session,&sessionId);
-				UA_SessionManager_removeSession(&sessionId);
-			}
-		}
-		current = current->next;
-	}
-	return UA_SUCCESS;
-}
-*/
-
-UA_Int32 UA_SessionManager_getSessionTimeout(UA_Int64 *timeout_ms) {
-	if(sessionManager) {
-		*timeout_ms = sessionManager->sessionTimeout;
-		return UA_SUCCESS;
-	}
-	*timeout_ms = 0;
-	return UA_ERROR;
+
+UA_Int32 UA_SessionManager_getSessionTimeout(UA_SessionManager *sessionManager,
+                                             UA_Int64          *timeout_ms) {
+    if(sessionManager) {
+        *timeout_ms = sessionManager->sessionTimeout;
+        return UA_SUCCESS;
+    }
+    *timeout_ms = 0;
+    return UA_ERROR;
 }

+ 16 - 19
src/server/ua_session_manager.h

@@ -6,28 +6,21 @@
 struct UA_SessionManager;
 typedef struct UA_SessionManager UA_SessionManager;
 
-/**
- * @brief initializes the session manager
- * @param maxSessionCount maximum amount of sessions which should be allowed to be created
- * @param sessionLifetime lifetime of a session, after this time the session must be renewed
- * @param startSessionId the start id of the session identifiers, newer sessions get higher ids
- * @return error code
- */
-UA_Int32 UA_SessionManager_init(UA_UInt32 maxSessionCount,UA_UInt32 sessionLifetime, UA_UInt32 startSessionId);
+UA_Int32 UA_SessionManager_new(UA_SessionManager **sessionManager, UA_UInt32 maxSessionCount,
+                               UA_UInt32 sessionLifetime, UA_UInt32 startSessionId);
 
-/**
- * @brief adds a session to the manager list
- * @param session session object which should be added to the manager list
- * @return error code
- */
-UA_Int32 UA_SessionManager_addSession(UA_Session *session);
+UA_Int32 UA_SessionManager_delete(UA_SessionManager *sessionManager);
+
+UA_Int32 UA_SessionManager_addSession(UA_SessionManager *sessionManager,
+                                      UA_SecureChannel *channel, UA_Session **session);
 
 /**
  * @brief removes a session from the manager list
  * @param sessionId id which assign to a session
  * @return error code
  */
-UA_Int32 UA_SessionManager_removeSession(UA_NodeId *sessionId);
+UA_Int32 UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
+                                         UA_NodeId         *sessionId);
 
 /**
  * @brief finds the session which is identified by the sessionId
@@ -35,7 +28,8 @@ UA_Int32 UA_SessionManager_removeSession(UA_NodeId *sessionId);
  * @param session the session object is returned if no error occurs
  * @return error code
  */
-UA_Int32 UA_SessionManager_getSessionById(UA_NodeId *sessionId, UA_Session **session);
+UA_Int32 UA_SessionManager_getSessionById(UA_SessionManager *sessionManager,
+                                          UA_NodeId *sessionId, UA_Session **session);
 
 /**
  * @brief
@@ -43,7 +37,8 @@ UA_Int32 UA_SessionManager_getSessionById(UA_NodeId *sessionId, UA_Session **ses
  * @param session output, session object which is identified by the authentication token
  * @return error code
  */
-UA_Int32 UA_SessionManager_getSessionByToken(UA_NodeId *token, UA_Session **session);
+UA_Int32 UA_SessionManager_getSessionByToken(UA_SessionManager *sessionManager,
+                                             UA_NodeId *token, UA_Session **session);
 
 /**
  * @brief gets the session timeout value which should be assigned to
@@ -51,10 +46,12 @@ UA_Int32 UA_SessionManager_getSessionByToken(UA_NodeId *token, UA_Session **sess
  * @param timeout_ms timeout in milliseconds
  * @return error code
  */
-UA_Int32 UA_SessionManager_getSessionTimeout(UA_Int64 *timeout_ms);
+UA_Int32 UA_SessionManager_getSessionTimeout(UA_SessionManager *sessionManager,
+                                             UA_Int64          *timeout_ms);
 
 //UA_Int32 UA_SessionManager_updateSessions();
 //UA_Int32 UA_SessionManager_generateToken(UA_Session session, UA_Int32 requestedLifeTime, SecurityTokenRequestType requestType, UA_ChannelSecurityToken* newToken);
-UA_Int32 UA_SessionManager_generateSessionId(UA_NodeId *newSessionId);
+UA_Int32 UA_SessionManager_generateSessionId(UA_SessionManager *sessionManager,
+                                             UA_NodeId         *newSessionId);
 
 #endif /* UA_SESSION_MANAGER_H_ */

+ 0 - 65
src/server/ua_transport_connection_manager.c

@@ -1,65 +0,0 @@
-/*
- * ua_connection_manager.c
- *
- *  Created on: 11.05.2014
- *      Author: open62541
- */
-
-#include "ua_transport_connection_manager.h"
-#include "ua_indexedList.h"
-
-typedef struct UA_TL_ConnectionManager {
-	UA_list_List connections;
-	UA_UInt32 maxConnectionCount;
-	UA_UInt32 currentConnectionCount;
-} UA_TL_ConnectionManager;
-
-static UA_TL_ConnectionManager *connectionManager = UA_NULL;
-
-UA_Int32 UA_TL_ConnectionManager_init(UA_UInt32 maxConnectionCount) {
-	UA_Int32 retval = UA_SUCCESS;
-	if(connectionManager != UA_NULL)
-		return UA_ERROR; //connection Manager already exists
-
-	retval |= UA_alloc((void**)&connectionManager,sizeof(UA_TL_ConnectionManager));
-	connectionManager->maxConnectionCount = maxConnectionCount;
-	connectionManager->currentConnectionCount = 0;
-	retval |= UA_indexedList_init(&connectionManager->connections);
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_ConnectionManager_addConnection(UA_TL_Connection *connection) {
-	UA_UInt32 connectionId;
-	UA_TL_Connection_getHandle(connection, &connectionId);
-	printf("UA_TL_ConnectionManager_addConnection - added connection with handle = %d \n", connectionId);
-	return UA_list_addPayloadToBack(&(connectionManager->connections), (void*)connection);
-}
-
-UA_Int32 UA_TL_ConnectionManager_removeConnection(UA_TL_Connection *connection) {
-	UA_list_Element *element =  UA_list_find(&connectionManager->connections, (UA_list_PayloadMatcher)UA_TL_Connection_compare);
-	if(element) {
-		UA_list_removeElement(element, (UA_list_PayloadVisitor)UA_TL_Connection_delete);
-	}
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_ConnectionManager_getConnectionByHandle(UA_UInt32 connectionId, UA_TL_Connection **connection) {
-	UA_UInt32 tmpConnectionHandle;
-	if(connectionManager) {
-		UA_list_Element* current = connectionManager->connections.first;
-		while (current) {
-			if (current->payload) {
-				UA_list_Element* elem = (UA_list_Element*) current;
-				*connection = ((UA_TL_Connection*) (elem->payload));
-				UA_TL_Connection_getHandle(*connection, &tmpConnectionHandle);
-
-				if(tmpConnectionHandle == connectionId)
-					return UA_SUCCESS;
-			}
-			current = current->next;
-		}
-	}
-
-	*connection = UA_NULL;
-	return UA_ERROR;
-}

+ 0 - 14
src/server/ua_transport_connection_manager.h

@@ -1,14 +0,0 @@
-#ifndef UA_CONNECTION_MANAGER_H_
-#define UA_CONNECTION_MANAGER_H_
-
-#include "stdio.h"
-#include "ua_transport_connection.h"
-
-UA_Int32 UA_TL_ConnectionManager_init(UA_UInt32 maxConnectionCount);
-UA_Int32 UA_TL_ConnectionManager_addConnection(UA_TL_Connection *connection);
-UA_Int32 UA_TL_ConnectionManager_removeConnection(UA_TL_Connection *connection);
-
-//getter
-UA_Int32 UA_TL_ConnectionManager_getConnectionByHandle(UA_UInt32 connectionId, UA_TL_Connection **connection);
-
-#endif /* UA_CONNECTION_MANAGER_H_ */

+ 0 - 0
src/tokenType


+ 0 - 382
src/ua_channel.c

@@ -1,382 +0,0 @@
-#include "ua_channel.h"
-#include <time.h>
-#include <stdlib.h>
-
-struct SL_Channel {
-	SL_channelState state;
-	UA_UInt32 channelId;
-	//TL_Connection* tlConnection;
-
-	UA_TL_Connection *connection;
-	UA_UInt32 requestId;
-	//UA_UInt32 lastRequestId;
-
-	UA_UInt32 sequenceNumber;
-	//UA_UInt32 lastSequenceNumber;
-
-	UA_AsymmetricAlgorithmSecurityHeader remoteAsymAlgSettings;
-	UA_AsymmetricAlgorithmSecurityHeader localAsymAlgSettings;
-
-	UA_ChannelSecurityToken securityToken;
-
-	UA_MessageSecurityMode securityMode;
-	UA_ByteString remoteNonce;
-	UA_ByteString localNonce;
-	SL_ChannelSecurityTokenProvider tokenProvider;
-	SL_ChannelIdProvider channelIdProvider;
-};
-
-UA_Int32 SL_Channel_setRemoteSecuritySettings(SL_Channel *channel,
-		UA_AsymmetricAlgorithmSecurityHeader *asymSecHeader,
-		UA_SequenceHeader *sequenceHeader) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_AsymmetricAlgorithmSecurityHeader_copy(asymSecHeader,
-			&channel->remoteAsymAlgSettings);
-	//set starting sequence number from remote partner
-	channel->sequenceNumber =
-			sequenceHeader->sequenceNumber;
-	//set starting request id from remote partner
-	channel->requestId = sequenceHeader->requestId;
-	return retval;
-}
-
-/* UA_Int32 SL_Channel_initLocalSecuritySettings(SL_Channel *channel)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	channel->localAsymAlgSettings.receiverCertificateThumbprint.data = UA_NULL;
-	channel->localAsymAlgSettings.receiverCertificateThumbprint.length = 0;
-
-	retval |= UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",(UA_String*)&channel->localAsymAlgSettings.securityPolicyUri);
-
-	channel->localAsymAlgSettings.senderCertificate.data = UA_NULL;
-	channel->localAsymAlgSettings.senderCertificate.length = 0;
-	return retval;
-} */
-
-UA_Int32 SL_Channel_new(SL_Channel **channel) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_alloc((void** )channel, sizeof(SL_Channel));
-	SL_Channel *thisChannel = UA_NULL;
-	retval |= UA_alloc((void** )&thisChannel, sizeof(SL_Channel));
-	*channel = thisChannel;
-	return retval;
-}
-
-//TODO implement real nonce generator - DUMMY function
-UA_Int32 SL_Channel_generateNonce(UA_ByteString *nonce) {
-	//UA_ByteString_new(&nonce);
-	UA_alloc((void** )&(nonce->data), 1);
-	nonce->length = 1;
-	nonce->data[0] = 'a';
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_Channel_init(SL_Channel *channel, UA_TL_Connection *connection,
-		SL_ChannelIdProvider channelIdProvider,
-		SL_ChannelSecurityTokenProvider tokenProvider) {
-
-	UA_Int32 retval = UA_SUCCESS;
-
-	channel->channelIdProvider = channelIdProvider;
-	channel->tokenProvider = tokenProvider;
-
-	channel->connection = connection;
-	//generate secure channel id
-	channel->channelIdProvider(
-			&channel->channelId);
-
-	//generate local nonce
-	SL_Channel_generateNonce(&channel->localNonce);
-	//TODO get this from the local configuration file MOCK UP ---start
-	channel->localAsymAlgSettings.receiverCertificateThumbprint.data = UA_NULL;
-	channel->localAsymAlgSettings.receiverCertificateThumbprint.length = 0;
-
-	retval |= UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",(UA_String*)&channel->localAsymAlgSettings.securityPolicyUri);
-
-	channel->localAsymAlgSettings.senderCertificate.data = UA_NULL;
-	channel->localAsymAlgSettings.senderCertificate.length = 0;
-	// MOCK UP ---end
-
-
-	channel->state = UA_SL_CHANNEL_CLOSED;
-	return retval;
-}
-
-UA_Int32 SL_Channel_registerTokenProvider(SL_Channel *channel,
-		SL_ChannelSecurityTokenProvider provider) {
-	channel->tokenProvider = provider;
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_Channel_getRemainingLifetime(SL_Channel *channel, UA_Int32 *lifetime) {
-	if (channel) {
-		UA_Int64 diffInMS = (channel->securityToken.createdAt - UA_DateTime_now()) / 1e7;
-		if (diffInMS > UA_INT32_MAX) {
-			*lifetime = UA_INT32_MAX;
-		} else {
-			*lifetime = (UA_Int32) diffInMS;
-		}
-		return UA_SUCCESS;
-	} else {
-		printf(
-				"SL_Channel_getRemainingLifetime - no valid channel object, null pointer");
-		return UA_ERROR;
-	}
-}
-
-UA_Int32 SL_Channel_getChannelId(SL_Channel *channel, UA_UInt32 *channelId) {
-	if (channel) {
-		*channelId = channel->channelId;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getTokenId(SL_Channel *channel, UA_UInt32 *tokenId) {
-	if (channel) {
-		*tokenId = channel->securityToken.tokenId;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getLocalAsymAlgSettings(SL_Channel *channel,
-		UA_AsymmetricAlgorithmSecurityHeader **asymAlgSettings) {
-	UA_Int32 retval = 0;
-
-	retval |= UA_alloc((void** )asymAlgSettings,
-			UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_NULL));
-
-	retval |=
-			UA_ByteString_copy(
-					&(channel->localAsymAlgSettings.receiverCertificateThumbprint),
-					&(*asymAlgSettings)->receiverCertificateThumbprint);
-	retval |=
-			UA_ByteString_copy(
-					&(channel->localAsymAlgSettings.securityPolicyUri),
-					&(*asymAlgSettings)->securityPolicyUri);
-	retval |=
-			UA_ByteString_copy(
-					&(channel->localAsymAlgSettings.senderCertificate),
-					&(*asymAlgSettings)->senderCertificate);
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_Channel_getConnection(SL_Channel *channel,
-		UA_TL_Connection **connection) {
-	if (channel) {
-		*connection = channel->connection;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getRequestId(SL_Channel *channel, UA_UInt32 *requestId) {
-	if (channel) {
-		*requestId = channel->requestId;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getSequenceNumber(SL_Channel *channel,
-		UA_UInt32 *sequenceNumber) {
-	if (channel) {
-		*sequenceNumber = channel->sequenceNumber;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getState(SL_Channel *channel, SL_channelState *channelState) {
-	if (channel) {
-		*channelState = channel->state;
-		return UA_SUCCESS;
-	}
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_getRevisedLifetime(SL_Channel *channel, UA_UInt32 *revisedLifetime) {
-	if(!channel)
-		return UA_ERROR;
-
-	*revisedLifetime = channel->securityToken.revisedLifetime;
-	return UA_SUCCESS;
-}
-
-//setters
-UA_Int32 SL_Channel_setId(SL_Channel *channel, UA_UInt32 id) {
-	channel->channelId = id;
-	return UA_SUCCESS;
-}
-
-//private function
-UA_Int32 SL_Channel_setState(SL_Channel *channel, SL_channelState channelState) {
-	channel->state = channelState;
-	return UA_SUCCESS;
-}
-
-
-
-UA_Boolean SL_Channel_compare(SL_Channel *channel1, SL_Channel *channel2) {
-	return (((SL_Channel*) channel1)->channelId == ((SL_Channel*) channel2)->channelId) ?
-			UA_TRUE : UA_FALSE;
-}
-
-UA_Int32 SL_Channel_bind(SL_Channel *channel, UA_TL_Connection *connection) {
-	if (!channel || !connection)
-		return UA_ERROR;
-
-	channel->connection = connection;
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_Channel_deleteMembers(SL_Channel *channel) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->localAsymAlgSettings);
-	retval |= UA_ByteString_deleteMembers(&channel->localNonce);
-	retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->remoteAsymAlgSettings);
-	retval |= UA_ByteString_deleteMembers(&channel->remoteNonce);
-	retval |= UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
-	return retval;
-}
-UA_Int32 SL_Channel_delete(SL_Channel *channel) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval = SL_Channel_deleteMembers(channel);
-	retval = UA_free(channel);
-	return retval;
-}
-
-UA_Int32 SL_Channel_processTokenRequest(SL_Channel *channel, UA_UInt32 requestedLifetime, UA_SecurityTokenRequestType requestType) {
-	if (channel->tokenProvider)
-		return channel->tokenProvider(channel, requestedLifetime, requestType, &channel->securityToken);
-	printf("SL_Channel_processTokenRequest - no Token provider registered");
-	return UA_ERROR;
-}
-UA_Int32 SL_Channel_renewToken(SL_Channel *channel, UA_UInt32 tokenId,
-		UA_DateTime revisedLifetime, UA_DateTime createdAt) {
-	channel->securityToken.tokenId = tokenId;
-	channel->securityToken.createdAt = createdAt;
-	channel->securityToken.revisedLifetime = revisedLifetime;
-	return UA_SUCCESS;
-}
-
-UA_Int32 SL_Channel_checkSequenceNumber(SL_Channel *channel, UA_UInt32 sequenceNumber) {
-	//TODO review checking of sequence
-	if (channel->sequenceNumber+1  == sequenceNumber) {
-		channel->sequenceNumber++;
-		return UA_SUCCESS;
-	}
-	printf("SL_Channel_checkSequenceNumber - ERROR, wrong SequenceNumber expected: %i, received: %i",
-			channel->sequenceNumber + 1, sequenceNumber);
-	return UA_ERROR;
-
-}
-
-UA_Int32 SL_Channel_checkRequestId(SL_Channel *channel, UA_UInt32 requestId) {
-	//TODO review checking of request id
-	if (channel->requestId+1  == requestId) {
-		channel->requestId++;
-		return UA_SUCCESS;
-	}
-	printf("SL_Channel_requestId - ERROR, wrong requestId expected: %i, received: %i",
-			channel->requestId + 1, requestId);
-	return UA_ERROR;
-}
-
-UA_Int32 SL_Channel_processOpenRequest(SL_Channel *channel, const UA_OpenSecureChannelRequest* request,
-									   UA_OpenSecureChannelResponse* response) {
-	UA_UInt32 protocolVersion;
-	SL_Channel* thisChannel = channel;
-	UA_Int32 retval = UA_SUCCESS;
-
-	UA_TL_Connection_getProtocolVersion(thisChannel->connection, &protocolVersion);
-
-	if (request->clientProtocolVersion != protocolVersion) {
-		printf("SL_Channel_processOpenRequest - error protocol version \n");
-		//TODO ERROR_Bad_ProtocolVersionUnsupported
-	}
-
-	switch (request->requestType) {
-	case UA_SECURITYTOKEN_ISSUE:
-		if (thisChannel->state == UA_SL_CHANNEL_OPEN) {
-			printf(
-					"SL_Channel_processOpenRequest - multiple security token request");
-			//TODO return ERROR
-			retval = UA_ERROR;
-			break;
-		}
-		printf(
-				"SL_Channel_processOpenRequest - creating new token for a new SecureChannel\n");
-		SL_Channel_processTokenRequest(channel, request->requestedLifetime,
-				request->requestType);
-		//	SL_createNewToken(connection);
-		break;
-	case UA_SECURITYTOKEN_RENEW:
-		if (thisChannel->state == UA_SL_CHANNEL_CLOSED) {
-			printf(
-					"SL_Channel_processOpenRequest - renew token request received, but no secureChannel was established before");
-			//TODO return ERROR
-			retval = UA_ERROR;
-			break;
-		} else {
-			//generate new SecurityToken
-			retval = SL_Channel_processTokenRequest(channel,
-					request->requestedLifetime, request->requestType);
-			if (retval != UA_SUCCESS) {
-				printf(
-						"SL_Channel_processOpenRequest - cannot create new token for an existing SecureChannel\n");
-
-			} else {
-				printf(
-						"SL_Channel_processOpenRequest - creating new token for an existing SecureChannel\n");
-			}
-
-			break;
-		}
-	}
-	switch (request->securityMode) {
-	case UA_SECURITYMODE_INVALID:
-		thisChannel->remoteNonce.data = UA_NULL;
-		thisChannel->remoteNonce.length = -1;
-		printf("SL_Channel_processOpenRequest - client demands no security \n");
-		break;
-
-	case UA_SECURITYMODE_SIGN:
-		printf("SL_Channel_processOpenRequest - client demands signed \n");
-		//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-		break;
-
-	case UA_SECURITYMODE_SIGNANDENCRYPT:
-		printf(
-				"SL_Channel_processOpenRequest - client demands signed & encrypted \n");
-		//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-		break;
-	}
-	UA_ByteString_copy(&request->clientNonce, &thisChannel->remoteNonce);
-	thisChannel->state = UA_SL_CHANNEL_OPEN;
-
-	if (request->requestHeader.returnDiagnostics != 0) {
-		printf("SL_openSecureChannel - diagnostics demanded by the client\n");
-		printf(
-				"SL_openSecureChannel - retrieving diagnostics not implemented!\n");
-		//TODO fill with demanded information part 4, 7.8 - Table 123
-		response->responseHeader.serviceDiagnostics.encodingMask = 0;
-	} else {
-		response->responseHeader.serviceDiagnostics.encodingMask = 0;
-	}
-
-	response->serverProtocolVersion = protocolVersion;
-	UA_ChannelSecurityToken_copy(&channel->securityToken, &(response->securityToken));
-	UA_ByteString_copy(&thisChannel->localNonce, &response->serverNonce);
-
-	return retval;
-}
-
-UA_Int32 SL_Channel_processCloseRequest(SL_Channel *channel,
-		const UA_CloseSecureChannelRequest* request) {
-	SL_Channel_setState(channel, UA_SL_CHANNEL_CLOSED);
-	return UA_SUCCESS;
-}
-

+ 0 - 65
src/ua_channel.h

@@ -1,65 +0,0 @@
-#ifndef UA_CHANNEL_H_
-#define UA_CHANNEL_H_
-
-#include <stdio.h>
-#include <memory.h> // memcpy
-
-#include "ua_transport_connection.h"
-
-typedef enum ChannelState {
-	UA_SL_CHANNEL_CLOSING,
-	UA_SL_CHANNEL_CLOSED,
-	UA_SL_CHANNEL_OPENING,
-	UA_SL_CHANNEL_OPEN
-} SL_channelState;
-
-//hide object behind typedef
-struct SL_Channel;
-typedef struct SL_Channel SL_Channel;
-
-typedef UA_Int32 (*SL_ChannelSecurityTokenProvider)(SL_Channel*, UA_Int32,
-		         SecurityTokenRequestType, UA_ChannelSecurityToken*);
-typedef UA_Int32 (*SL_ChannelIdProvider)(UA_UInt32*);
-UA_Int32 SL_Channel_new(SL_Channel **channel);
-
-UA_Int32 SL_Channel_init(SL_Channel *channel, UA_TL_Connection *connection,
-		SL_ChannelIdProvider channelIdProvider,
-		SL_ChannelSecurityTokenProvider tokenProvider);
-
-UA_Int32 SL_Channel_bind(SL_Channel *channel, UA_TL_Connection *connection);
-UA_Int32 SL_Channel_setRemoteSecuritySettings(SL_Channel *channel,
-		UA_AsymmetricAlgorithmSecurityHeader *asymSecHeader,
-		UA_SequenceHeader *sequenceHeader);
-
-UA_Int32 SL_Channel_initLocalSecuritySettings(SL_Channel *channel);
-UA_Int32 SL_Channel_delete(SL_Channel *channel);
-UA_Int32 SL_Channel_deleteMembers(SL_Channel *channel);
-UA_Int32 SL_Channel_renewToken(SL_Channel *channel, UA_UInt32 tokenId,
-		UA_DateTime revisedLifetime, UA_DateTime createdAt);
-
-UA_Int32 SL_Channel_processOpenRequest(SL_Channel *channel, const UA_OpenSecureChannelRequest* request,
-									   UA_OpenSecureChannelResponse* response);
-UA_Int32 SL_Channel_processCloseRequest(SL_Channel *channel, const UA_CloseSecureChannelRequest* request);
-UA_Int32 SL_Channel_registerTokenProvider(SL_Channel *channel, SL_ChannelSecurityTokenProvider provider);
-UA_Int32 SL_Channel_registerChannelIdProvider(SL_ChannelIdProvider provider);
-UA_Int32 SL_Channel_checkRequestId(SL_Channel *channel, UA_UInt32 requestId);
-UA_Int32 SL_Channel_checkSequenceNumber(SL_Channel *channel, UA_UInt32 sequenceNumber);
-UA_Boolean SL_Channel_compare(SL_Channel *channel1, SL_Channel *channel2);
-
-//getters
-UA_Int32 SL_Channel_getChannelId(SL_Channel *channel, UA_UInt32 *channelId);
-UA_Int32 SL_Channel_getTokenId(SL_Channel *channel, UA_UInt32 *tokenlId);
-UA_Int32 SL_Channel_getSequenceNumber(SL_Channel *channel, UA_UInt32 *sequenceNumber);
-UA_Int32 SL_Channel_getRequestId(SL_Channel *channel, UA_UInt32 *requestId);
-UA_Int32 SL_Channel_getConnectionId(SL_Channel *channel, UA_UInt32 *connectionId);
-UA_Int32 SL_Channel_getConnection(SL_Channel *channel, UA_TL_Connection **connection);
-UA_Int32 SL_Channel_getState(SL_Channel *channel, SL_channelState *channelState);
-UA_Int32 SL_Channel_getLocalAsymAlgSettings(SL_Channel *channel,
-		UA_AsymmetricAlgorithmSecurityHeader **asymAlgSettings);
-UA_Int32 SL_Channel_getRemainingLifetime(SL_Channel *channel, UA_Int32 *lifetime);
-UA_Int32 SL_Channel_getRevisedLifetime(SL_Channel *channel, UA_UInt32 *revisedLifetime);
-
-//setters
-UA_Int32 SL_Channel_setId(SL_Channel *channel, UA_UInt32 id);
-
-#endif /* UA_CHANNEL_H_ */

+ 3 - 4
src/ua_config.h.in

@@ -1,9 +1,8 @@
 /* Buid options and configuration (set by cmake) */
-#define UA_ENCODING_AMOUNT @UA_ENCODING_AMOUNT@
-#cmakedefine ENABLE_MULTITHREADING
-#cmakedefine ENABLE_LOGGING
-#define UA_LOGLEVEL @UA_LOGLEVEL@
+#define UA_ENCODING_AMOUNT ${UA_ENCODING_AMOUNT}
+#define UA_LOGLEVEL ${UA_LOGLEVEL}
 
+#cmakedefine ENABLE_MULTITHREADING
 #cmakedefine MSVC
 #cmakedefine WIN32
 

+ 41 - 0
src/ua_connection.c

@@ -0,0 +1,41 @@
+#include "ua_connection.h"
+#include "util/ua_util.h"
+
+UA_ConnectionConfig UA_ConnectionConfig_standard = { .protocolVersion = 0,    .sendBufferSize = 8192,
+                                                     .recvBufferSize  = 8192, .maxMessageSize = 8192,
+                                                     .maxChunkCount   = 1 };
+
+UA_Int32 UA_ByteStringArray_init(UA_ByteStringArray *stringarray, UA_UInt32 length) {
+    if(!stringarray || length == 0)
+        return UA_ERROR;
+    if(UA_alloc((void **)&stringarray->strings, sizeof(UA_String) * length) != UA_SUCCESS)
+        return UA_ERROR;
+    for(UA_UInt32 i = 0;i < length;i++)
+        UA_String_init(&stringarray->strings[i]);
+    stringarray->stringsSize = length;
+    return UA_ERROR;
+}
+
+UA_Int32 UA_ByteStringArray_deleteMembers(UA_ByteStringArray *stringarray) {
+    if(!stringarray)
+        return UA_ERROR;
+    for(UA_UInt32 i = 0;i < stringarray->stringsSize;i++)
+        UA_String_deleteMembers(&stringarray->strings[i]);
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_Connection_init(UA_Connection *connection, UA_ConnectionConfig localConf, void *callbackHandle,
+                            UA_Connection_closeCallback close, UA_Connection_writeCallback write) {
+    connection->state          = UA_CONNECTION_OPENING;
+    connection->localConf      = localConf;
+    connection->channel        = UA_NULL;
+    connection->callbackHandle = callbackHandle;
+    connection->close          = close;
+    connection->write          = write;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_Connection_deleteMembers(UA_Connection *connection) {
+    UA_free(connection->callbackHandle);
+    return UA_SUCCESS;
+}

+ 55 - 0
src/ua_connection.h

@@ -0,0 +1,55 @@
+#ifndef UA_CONNECTION_H_
+#define UA_CONNECTION_H_
+
+#include "ua_transport.h"
+
+/* used for zero-copy communication. the array of bytestrings is sent over the
+   network as a single buffer. */
+typedef struct UA_ByteStringArray {
+    UA_UInt32      stringsSize;
+    UA_ByteString *strings;
+} UA_ByteStringArray;
+
+UA_Int32 UA_ByteStringArray_init(UA_ByteStringArray *stringarray, UA_UInt32 length);
+UA_Int32 UA_ByteStringArray_deleteMembers(UA_ByteStringArray *stringarray);
+
+typedef enum UA_ConnectionState {
+    UA_CONNECTION_OPENING,
+    UA_CONNECTION_CLOSING,
+    UA_CONNECTION_ESTABLISHED
+} UA_ConnectionState;
+
+typedef struct UA_ConnectionConfig {
+    UA_UInt32 protocolVersion;
+    UA_UInt32 sendBufferSize;
+    UA_UInt32 recvBufferSize;
+    UA_UInt32 maxMessageSize;
+    UA_UInt32 maxChunkCount;
+} UA_ConnectionConfig;
+
+extern UA_ConnectionConfig UA_ConnectionConfig_standard;
+
+/* Forward declaration */
+struct UA_SecureChannel;
+typedef struct UA_SecureChannel UA_SecureChannel;
+
+typedef UA_Int32 (*UA_Connection_writeCallback)(void *handle, UA_ByteStringArray buf);
+typedef UA_Int32 (*UA_Connection_closeCallback)(void *handle);
+
+typedef struct UA_Connection {
+    UA_ConnectionState  state;
+    UA_ConnectionConfig localConf;
+    UA_ConnectionConfig remoteConf;
+    UA_SecureChannel   *channel;
+    void *callbackHandle;
+    UA_Connection_writeCallback write;
+    UA_Connection_closeCallback close;
+} UA_Connection;
+
+UA_Int32 UA_Connection_init(UA_Connection *connection, UA_ConnectionConfig localConf, void *callbackHandle,
+                            UA_Connection_closeCallback close, UA_Connection_writeCallback write);
+UA_Int32 UA_Connection_deleteMembers(UA_Connection *connection);
+
+// todo: closing a binaryconnection that was closed on the network level
+
+#endif /* UA_CONNECTION_H_ */

+ 63 - 0
src/ua_securechannel.c

@@ -0,0 +1,63 @@
+#include <time.h>
+#include <stdlib.h>
+#include "ua_securechannel.h"
+
+UA_Int32 UA_SecureChannel_init(UA_SecureChannel *channel) {
+    UA_AsymmetricAlgorithmSecurityHeader_init(&channel->clientAsymAlgSettings);
+    UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
+    UA_ByteString_init(&channel->clientNonce);
+    UA_ByteString_init(&channel->serverNonce);
+    channel->connection = UA_NULL;
+    channel->session    = UA_NULL;
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannel_deleteMembers(UA_SecureChannel *channel) {
+    UA_Int32 retval = UA_SUCCESS;
+    retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
+    retval |= UA_ByteString_deleteMembers(&channel->serverNonce);
+    retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
+    retval |= UA_ByteString_deleteMembers(&channel->clientNonce);
+    retval |= UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
+    return retval;
+}
+UA_Int32 UA_SecureChannel_delete(UA_SecureChannel *channel) {
+    UA_Int32 retval = UA_SUCCESS;
+    retval |= UA_SecureChannel_deleteMembers(channel);
+    retval |= UA_free(channel);
+    return retval;
+}
+
+UA_Boolean UA_SecureChannel_compare(UA_SecureChannel *sc1, UA_SecureChannel *sc2) {
+    return (sc1->securityToken.channelId == sc2->securityToken.channelId) ?
+           UA_TRUE : UA_FALSE;
+}
+
+//TODO implement real nonce generator - DUMMY function
+UA_Int32 UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
+    //UA_ByteString_new(&nonce);
+    UA_alloc((void ** )&nonce->data, 1);
+    nonce->length  = 1;
+    nonce->data[0] = 'a';
+    return UA_SUCCESS;
+}
+
+UA_Int32 UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId) {
+    //TODO review checking of request id
+    if(channel->requestId+1  == requestId) {
+        channel->requestId++;
+        return UA_SUCCESS;
+    }
+    return UA_ERROR;
+}
+
+UA_Int32 UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel,
+                                               UA_UInt32         sequenceNumber) {
+    //TODO review checking of sequence
+    if(channel->sequenceNumber+1  == sequenceNumber) {
+        channel->sequenceNumber++;
+        return UA_SUCCESS;
+    }
+    return UA_ERROR;
+
+}

+ 39 - 0
src/ua_securechannel.h

@@ -0,0 +1,39 @@
+#ifndef UA_SECURECHANNEL_H_
+#define UA_SECURECHANNEL_H_
+
+#include "ua_types_generated.h"
+#include "ua_transport.h"
+#include "ua_connection.h"
+
+/**
+ *  @ingroup internal
+ *
+ *  @defgroup securechannel SecureChannel
+ */
+
+struct UA_Session;
+typedef struct UA_Session UA_Session;
+
+struct UA_SecureChannel {
+    UA_MessageSecurityMode  securityMode;
+    UA_ChannelSecurityToken securityToken; // the channelId is contained in the securityToken
+    UA_AsymmetricAlgorithmSecurityHeader clientAsymAlgSettings;
+    UA_AsymmetricAlgorithmSecurityHeader serverAsymAlgSettings;
+    UA_ByteString  clientNonce;
+    UA_ByteString  serverNonce;
+    UA_UInt32      requestId;
+    UA_UInt32      sequenceNumber;
+    UA_Connection *connection; // make this more generic when http connections exist
+    UA_Session    *session;
+};
+
+UA_Int32 UA_SecureChannel_init(UA_SecureChannel *channel);
+UA_Int32 UA_SecureChannel_deleteMembers(UA_SecureChannel *channel);
+UA_Int32 UA_SecureChannel_delete(UA_SecureChannel *channel);
+UA_Boolean UA_SecureChannel_compare(UA_SecureChannel *sc1, UA_SecureChannel *sc2);
+
+UA_Int32 UA_SecureChannel_generateNonce(UA_ByteString *nonce);
+UA_Int32 UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId);
+UA_Int32 UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, UA_UInt32 sequenceNumber);
+
+#endif /* UA_SECURECHANNEL_H_ */

+ 67 - 156
src/ua_session.c

@@ -3,180 +3,91 @@
 
 #include "ua_session.h"
 
-struct UA_Session {
-	UA_NodeId authenticationToken;
-	UA_NodeId sessionId;
-	UA_String name;
-	Application *application;
-//	UA_list_List pendingRequests;
-	SL_Channel *channel;
-	UA_UInt32 maxRequestMessageSize;
-	UA_UInt32 maxResponseMessageSize;
-	UA_Int64 timeout;
-	UA_DateTime validTill;
-};
+UA_Int32 UA_Session_new(UA_Session **session) {
+    UA_Int32 retval = UA_SUCCESS;
+    retval |= UA_alloc((void **)session, sizeof(UA_Session));
+    if(retval == UA_SUCCESS)
+        UA_Session_init(*session);
+    return retval;
+}
 
 /* mock up function to generate tokens for authentication */
 UA_Int32 UA_Session_generateToken(UA_NodeId *newToken) {
-	//Random token generation
-	UA_Int32 retval = UA_SUCCESS;
-	srand(time(NULL));
-
-	UA_Int32 i = 0;
-	UA_Int32 r = 0;
-	//retval |= UA_NodeId_new(newToken);
-
-	newToken->namespaceIndex = 0; // where else?
-	newToken->identifierType = UA_NODEIDTYPE_GUID;
-	newToken->identifier.guid.data1 = rand();
-	r = rand();
-	newToken->identifier.guid.data2 = (UA_UInt16)((r>>16) );
-	r = rand();
-	UA_Int32 r1 = (r>>16);
-	UA_Int32 r2 = r1 & 0xFFFF;
-	r2 = r2 * 1;
-	newToken->identifier.guid.data3 = (UA_UInt16)((r>>16) );
-	for(i=0;i<8;i++) {
-		r = rand();
-		newToken->identifier.guid.data4[i] = (UA_Byte)((r>>28) );
-	}
-	return retval;
-}
-
-UA_Int32 UA_Session_bind(UA_Session *session, SL_Channel *channel) {
-	if(!channel || !session)
-		return UA_ERROR;
-
-	session->channel = channel;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_Session_new(UA_Session **newSession) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Session *session;
-
-	retval |= UA_alloc((void**)&session,sizeof(UA_Session));
-	retval |= UA_alloc((void**)session,sizeof(UA_Session));
-	*newSession = session;
-	**newSession = *session;
-	//get memory for request list
-	return retval;
+    //Random token generation
+    UA_Int32 retval = UA_SUCCESS;
+    srand(time(NULL));
+
+    UA_Int32 i = 0;
+    UA_Int32 r = 0;
+    //retval |= UA_NodeId_new(newToken);
+
+    newToken->namespaceIndex = 0; // where else?
+    newToken->identifierType = UA_NODEIDTYPE_GUID;
+    newToken->identifier.guid.data1 = rand();
+    r = rand();
+    newToken->identifier.guid.data2 = (UA_UInt16)((r>>16) );
+    r = rand();
+    /* UA_Int32 r1 = (r>>16); */
+    /* UA_Int32 r2 = r1 & 0xFFFF; */
+    /* r2 = r2 * 1; */
+    newToken->identifier.guid.data3 = (UA_UInt16)((r>>16) );
+    for(i = 0;i < 8;i++) {
+        r = rand();
+        newToken->identifier.guid.data4[i] = (UA_Byte)((r>>28) );
+    }
+    return retval;
+}
+
+UA_Int32 UA_Session_init(UA_Session *session) {
+    if(!session)
+        return UA_ERROR;
+
+    UA_NodeId_init(&session->authenticationToken);
+    UA_NodeId_init(&session->sessionId);
+    UA_String_init(&session->sessionName);
+    session->maxRequestMessageSize  = 0;
+    session->maxResponseMessageSize = 0;
+    session->timeout = 0;
+    UA_DateTime_init(&session->validTill);
+    session->channel = UA_NULL;
+    return UA_SUCCESS;
 }
 
 UA_Int32 UA_Session_deleteMembers(UA_Session *session) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_NodeId_deleteMembers(&session->authenticationToken);
-	retval |= UA_String_deleteMembers(&session->name);
-	retval |= UA_NodeId_deleteMembers(&session->sessionId);
-	return retval;
+    UA_Int32 retval = UA_SUCCESS;
+    retval |= UA_NodeId_deleteMembers(&session->authenticationToken);
+    retval |= UA_NodeId_deleteMembers(&session->sessionId);
+    retval |= UA_String_deleteMembers(&session->sessionName);
+    session->channel = UA_NULL;
+    return retval;
 }
 
 UA_Int32 UA_Session_delete(UA_Session *session) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Session_deleteMembers(session);
-	retval |= UA_free(session);
-	return retval;
-}
-
-UA_Int32 UA_Session_init(UA_Session *session, UA_String *sessionName, UA_Double requestedSessionTimeout,
-		UA_UInt32 maxRequestMessageSize,
-		UA_UInt32 maxResponseMessageSize,
-		UA_Session_idProvider idProvider,
-		UA_Int64 timeout){
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_String_copy(sessionName, &session->name);
-	session->maxRequestMessageSize = maxRequestMessageSize;
-	session->maxResponseMessageSize = maxResponseMessageSize;
-
-	UA_Session_generateToken(&session->authenticationToken);
-
-	idProvider(&session->sessionId);
-	session->timeout = requestedSessionTimeout > timeout ? timeout : requestedSessionTimeout;
-
-	UA_Session_updateLifetime(session);
-	return retval;
+    UA_Int32 retval = UA_SUCCESS;
+    UA_Session_deleteMembers(session);
+    retval |= UA_free(session);
+    return retval;
 }
 
 UA_Boolean UA_Session_compare(UA_Session *session1, UA_Session *session2) {
-	if(session1 && session2) {
-		if (UA_NodeId_equal(&session1->sessionId, &session2->sessionId) == UA_EQUAL) {
-			return UA_TRUE;
-		}
-	}
-	return UA_FALSE;
-}
-
-UA_Boolean UA_Session_compareByToken(UA_Session *session, UA_NodeId *token) {
-	if(session && token) {
-		return UA_NodeId_equal(&session->authenticationToken, token);
-	}
-	return UA_NOT_EQUAL;
-}
-
-UA_Boolean UA_Session_compareById(UA_Session *session, UA_NodeId *sessionId) {
-	if(session && sessionId) {
-		return UA_NodeId_equal(&session->sessionId, sessionId);
-	}
-	return UA_NOT_EQUAL;
-}
-
-UA_Int32 UA_Session_getId(UA_Session *session, UA_NodeId *sessionId) {
-	if(!session)
-		return UA_ERROR;
-	return UA_NodeId_copy(&session->sessionId, sessionId);
-}
-
-UA_Int32 UA_Session_getToken(UA_Session *session, UA_NodeId *authenticationToken) {
-	if(!session)
-		return UA_ERROR;
-	return UA_NodeId_copy(&session->authenticationToken, authenticationToken);
+    if(session1 && session2 &&
+       UA_NodeId_equal(&session1->sessionId, &session2->sessionId) == UA_EQUAL)
+        return UA_TRUE;
+    return UA_FALSE;
 }
 
 UA_Int32 UA_Session_updateLifetime(UA_Session *session) {
-	if(!session)
-		return UA_ERROR;
+    if(!session)
+        return UA_ERROR;
 
-	session->validTill = UA_DateTime_now() + session->timeout * 100000; //timeout in ms
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_Session_getChannel(UA_Session *session, SL_Channel **channel) {
-	if(!session)
-		return UA_ERROR;
-
-	*channel = session->channel;
-	return UA_SUCCESS;
+    session->validTill = UA_DateTime_now() + session->timeout * 100000; //timeout in ms
+    return UA_SUCCESS;
 }
 
 UA_Int32 UA_Session_getPendingLifetime(UA_Session *session, UA_Double *pendingLifetime_ms) {
-	if(!session)
-		return UA_ERROR;
-
-	*pendingLifetime_ms = (session->validTill- UA_DateTime_now() ) / 10000000; //difference in ms
-	return UA_SUCCESS;
-}
-
-UA_Boolean UA_Session_verifyChannel(UA_Session *session, SL_Channel *channel) {
-	if(!session || !channel)
-		return UA_FALSE;
-
-	return SL_Channel_compare(session->channel, channel);
-}
-
-UA_Int32 UA_Session_getApplicationPointer(UA_Session *session, Application** application) {
-	if(!session) {
-		*application = UA_NULL;
-		return UA_ERROR;
-	}
-
-	*application = session->application;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_Session_setApplicationPointer(UA_Session *session, Application* application) {
-	if(!session)
-		return UA_ERROR;
+    if(!session)
+        return UA_ERROR;
 
-	session->application = application;
-	return UA_SUCCESS;
+    *pendingLifetime_ms = (session->validTill - UA_DateTime_now())/10000000; //difference in ms
+    return UA_SUCCESS;
 }

+ 23 - 115
src/ua_session.h

@@ -1,131 +1,39 @@
 #ifndef UA_SESSION_H_
 #define UA_SESSION_H_
 
-#include "ua_channel.h"
-
-struct UA_Session;
-typedef struct UA_Session UA_Session;
-typedef UA_Int32(*UA_Session_idProvider)(UA_NodeId *newSessionId);
+#include "ua_types.h"
+#include "ua_securechannel.h"
 
 /**
- * @brief creates a session object
- * @param newSession
- * @return error code
+ *  @ingroup internal
+ *
+ *  @defgroup session Session
  */
-UA_Int32 UA_Session_new(UA_Session **newSession);
 
-/**
- * @brief inits a session object
- * @param session
- * @param sessionName
- * @param requestedSessionTimeout
- * @param maxRequestMessageSize
- * @param maxResponseMessageSize
- * @param idProvider
- * @param timeout
- * @return error code
- */
-UA_Int32 UA_Session_init(UA_Session *session, UA_String *sessionName, UA_Double requestedSessionTimeout,
-		UA_UInt32 maxRequestMessageSize,
-		UA_UInt32 maxResponseMessageSize,
-		UA_Session_idProvider idProvider,
-		UA_Int64 timeout);
+struct UA_Session {
+    UA_ApplicationDescription clientDescription;
+    UA_String         sessionName;
+    UA_NodeId         authenticationToken;
+    UA_NodeId         sessionId;
+    UA_UInt32         maxRequestMessageSize;
+    UA_UInt32         maxResponseMessageSize;
+    UA_Int64          timeout;
+    UA_DateTime       validTill;
+    UA_SecureChannel *channel;
+};
 
+UA_Int32 UA_Session_new(UA_Session **session);
+UA_Int32 UA_Session_init(UA_Session *session);
 UA_Int32 UA_Session_delete(UA_Session *session);
+UA_Int32 UA_Session_deleteMembers(UA_Session *session);
 
-/**
- * @brief compares two session objects
- * @param session1
- * @param session2
- * @return UA_TRUE if it is the same session, UA_FALSE else
- */
+/** Compares two session objects */
 UA_Boolean UA_Session_compare(UA_Session *session1, UA_Session *session2);
 
-/**
- * @brief compares two sessions by their authentication token
- * @param session
- * @param token
- * @return UA_EQUAL if the session token matches the session UA_NOT_EQUAL
- */
-UA_Boolean UA_Session_compareByToken(UA_Session *session, UA_NodeId *token);
-
-/**
- * @brief compares two sessions by their session id
- * @param session
- * @param sessionId
- * @return UA_EQUAL if the session identifier matches the session UA_NOT_EQUAL
- */
-UA_Boolean UA_Session_compareById(UA_Session *session, UA_NodeId *sessionId);
-
-/**
- * @brief binds a channel to a session
- * @param session
- * @param channel
- * @return error code
- */
-UA_Int32 UA_Session_bind(UA_Session *session, SL_Channel *channel);
-
-/**
- * @brief checks if the given channel is related to the session
- * @param session
- * @param channel
- * @return UA_TRUE if there is a relation between session and given channel
- */
-UA_Boolean UA_Session_verifyChannel(UA_Session *session, SL_Channel *channel);
-
-/**
- * @brief If any activity on a session happens, the timeout must be extended
- * @param session
- * @return error code
- */
+/** If any activity on a session happens, the timeout must be extended */
 UA_Int32 UA_Session_updateLifetime(UA_Session *session);
 
-/**
- * @brief Gets the session identifier (UA_NodeId)
- * @param session session from which the identifier should be returned
- * @param sessionId return value
- * @return error code
- */
-UA_Int32 UA_Session_getId(UA_Session *session, UA_NodeId *sessionId);
-
-/**
- * @brief Gets the session authentication token
- * @param session session from which the token should be returned
- * @param authenticationToken return value
- * @return error code
- */
-UA_Int32 UA_Session_getToken(UA_Session *session, UA_NodeId *authenticationToken);
-
-/**
- * @brief Gets the channel on which the session is currently running
- * @param session session from which the channel should be returned
- * @param channel return value
- * @return
- */
-UA_Int32 UA_Session_getChannel(UA_Session *session, SL_Channel **channel);
-
-/**
- * @brief Gets the sessions pending lifetime (calculated from the timeout which was set)
- * @param session session from which the lifetime should be returned
- * @param pendingLifetime return value
- * @return error code
- */
-UA_Int32 UA_Session_getPendingLifetime(UA_Session *session,UA_Double *pendingLifetime);
-
-/**
- * @brief Gets the pointer to the application
- * @param session session from which the application pointer should be returned
- * @param application return value
- * @return  error code
- */
-UA_Int32 UA_Session_getApplicationPointer(UA_Session *session, Application** application);
-
-/**
- * @brief Sets the application pointer to the application
- * @param session session of which the application pointer should be set
- * @param application return value
- * @return error code
- */
-UA_Int32 UA_Session_setApplicationPointer(UA_Session *session, Application* application);
+/** Gets the sessions pending lifetime (calculated from the timeout which was set) */
+UA_Int32 UA_Session_getPendingLifetime(UA_Session *session, UA_Double *pendingLifetime);
 
 #endif /* UA_SESSION_H_ */

+ 29 - 526
src/ua_transport.c

@@ -1,537 +1,40 @@
+#ifdef DEBUG
+#include <stdio.h>
+#endif
 #include "ua_transport.h"
-#include "ua_types_encoding_binary.h"
-#include "stdio.h"
 
 UA_TYPE_DEFAULT(UA_MessageType)
-UA_Int32 UA_MessageType_calcSize(UA_MessageType const * ptr){
-	if(ptr==UA_NULL){return sizeof(UA_MessageType);}
-	return 0
-	 + 3 * sizeof(UA_Byte);
+UA_Int32 UA_MessageType_calcSizeBinary(UA_MessageType const *ptr) {
+    if(ptr == UA_NULL) return sizeof(UA_MessageType);
+    return 3 * sizeof(UA_Byte);
 }
 
-UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const * src, UA_ByteString* dst, UA_UInt32 *offset){
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Byte tmpBuf[3];
-	tmpBuf[0] = (UA_Byte)((((UA_Int32)*src) >> 16) );
-	tmpBuf[1] = (UA_Byte)((((UA_Int32)*src) >> 8));
-	tmpBuf[2] = (UA_Byte)(((UA_Int32)*src));
+UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const *src, UA_ByteString *dst, UA_UInt32 *offset) {
+    UA_Int32 retval = UA_SUCCESS;
+    UA_Byte  tmpBuf[3];
+    tmpBuf[0] = (UA_Byte)((((UA_Int32)*src) >> 16) );
+    tmpBuf[1] = (UA_Byte)((((UA_Int32)*src) >> 8));
+    tmpBuf[2] = (UA_Byte)(((UA_Int32)*src));
 
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[0]),dst,offset);
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[1]),dst,offset);
-	retval |= UA_Byte_encodeBinary(&(tmpBuf[2]),dst,offset);
-	return retval;
+    retval   |= UA_Byte_encodeBinary(&(tmpBuf[0]), dst, offset);
+    retval   |= UA_Byte_encodeBinary(&(tmpBuf[1]), dst, offset);
+    retval   |= UA_Byte_encodeBinary(&(tmpBuf[2]), dst, offset);
+    return retval;
 }
 
-UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_MessageType* dst){
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Byte tmpBuf[3];
-	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[0])); //messageType to Byte representation
-	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[1]));
-	retval |= UA_Byte_decodeBinary(src,offset,&(tmpBuf[2]));
-	*dst = (UA_MessageType)((UA_Int32)(tmpBuf[0]<<16) + (UA_Int32)(tmpBuf[1]<<8) + (UA_Int32)(tmpBuf[2]));
-	return retval;
+UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, UA_MessageType *dst) {
+    UA_Int32 retval = UA_SUCCESS;
+    UA_Byte  tmpBuf[3];
+    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[0])); //messageType to Byte representation
+    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[1]));
+    retval |= UA_Byte_decodeBinary(src, offset, &(tmpBuf[2]));
+    *dst    = (UA_MessageType)((UA_Int32)(tmpBuf[0]<<16) + (UA_Int32)(tmpBuf[1]<<8) + (UA_Int32)(tmpBuf[2]));
+    return retval;
 }
 
-void UA_MessageType_printf(char *label, UA_MessageType* p) {
-	UA_Byte* b = (UA_Byte*) p;
-	printf("%s{%c%c%c}\n", label, b[2],b[1],b[0]);
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_calcSizeBinary(UA_OPCUATcpMessageHeader const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpMessageHeader);
-    	return 0
-	 + 3 // messageType
-	 + sizeof(UA_Byte) // isFinal
-	 + sizeof(UA_UInt32) // messageSize
-	;
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_MessageType_encodeBinary(&src->messageType,dst,offset);
-	retval |= UA_Byte_encodeBinary(&src->isFinal,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->messageSize,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpMessageHeader * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_OPCUATcpMessageHeader_init(dst);
-	CHECKED_DECODE(UA_MessageType_decodeBinary(src,offset,&dst->messageType), UA_OPCUATcpMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_Byte_decodeBinary(src,offset,&dst->isFinal), UA_OPCUATcpMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->messageSize), UA_OPCUATcpMessageHeader_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_delete(UA_OPCUATcpMessageHeader *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpMessageHeader_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpMessageHeader_init(UA_OPCUATcpMessageHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Byte_init(&p->isFinal);
-	retval |= UA_UInt32_init(&p->messageSize);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_OPCUATcpMessageHeader)
-UA_Int32 UA_OPCUATcpMessageHeader_copy(const UA_OPCUATcpMessageHeader *src,UA_OPCUATcpMessageHeader *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL)
-		return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_OPCUATcpMessageHeader));
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_calcSizeBinary(UA_OPCUATcpHelloMessage const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpHelloMessage);
-    	return 0
-	 + sizeof(UA_UInt32) // protocolVersion
-	 + sizeof(UA_UInt32) // receiveBufferSize
-	 + sizeof(UA_UInt32) // sendBufferSize
-	 + sizeof(UA_UInt32) // maxMessageSize
-	 + sizeof(UA_UInt32) // maxChunkCount
-	 + UA_String_calcSizeBinary(&ptr->endpointUrl)
-	;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&src->protocolVersion,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->receiveBufferSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->sendBufferSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->maxMessageSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->maxChunkCount,dst,offset);
-	retval |= UA_String_encodeBinary(&src->endpointUrl,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpHelloMessage * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_OPCUATcpHelloMessage_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->protocolVersion), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->receiveBufferSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sendBufferSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxMessageSize), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxChunkCount), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_String_decodeBinary(src,offset,&dst->endpointUrl), UA_OPCUATcpHelloMessage_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_delete(UA_OPCUATcpHelloMessage *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpHelloMessage_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_String_deleteMembers(&p->endpointUrl);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpHelloMessage_init(UA_OPCUATcpHelloMessage *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&p->protocolVersion);
-	retval |= UA_UInt32_init(&p->receiveBufferSize);
-	retval |= UA_UInt32_init(&p->sendBufferSize);
-	retval |= UA_UInt32_init(&p->maxMessageSize);
-	retval |= UA_UInt32_init(&p->maxChunkCount);
-	retval |= UA_String_init(&p->endpointUrl);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_OPCUATcpHelloMessage)
-UA_Int32 UA_OPCUATcpHelloMessage_copy(const UA_OPCUATcpHelloMessage *src,UA_OPCUATcpHelloMessage *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_OPCUATcpHelloMessage));
-	retval |= UA_String_copy(&src->endpointUrl,&dst->endpointUrl);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(UA_OPCUATcpAcknowledgeMessage const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_OPCUATcpAcknowledgeMessage);
-    	return 0
-	 + sizeof(UA_UInt32) // protocolVersion
-	 + sizeof(UA_UInt32) // receiveBufferSize
-	 + sizeof(UA_UInt32) // sendBufferSize
-	 + sizeof(UA_UInt32) // maxMessageSize
-	 + sizeof(UA_UInt32) // maxChunkCount
-	;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&src->protocolVersion,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->receiveBufferSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->sendBufferSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->maxMessageSize,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->maxChunkCount,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_OPCUATcpAcknowledgeMessage * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_OPCUATcpAcknowledgeMessage_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->protocolVersion), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->receiveBufferSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sendBufferSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxMessageSize), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->maxChunkCount), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_delete(UA_OPCUATcpAcknowledgeMessage *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpAcknowledgeMessage_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessage *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	return retval;
-}
-
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_init(UA_OPCUATcpAcknowledgeMessage *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&p->protocolVersion);
-	retval |= UA_UInt32_init(&p->receiveBufferSize);
-	retval |= UA_UInt32_init(&p->sendBufferSize);
-	retval |= UA_UInt32_init(&p->maxMessageSize);
-	retval |= UA_UInt32_init(&p->maxChunkCount);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_OPCUATcpAcknowledgeMessage)
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_copy(const UA_OPCUATcpAcknowledgeMessage *src,UA_OPCUATcpAcknowledgeMessage *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_OPCUATcpAcknowledgeMessage));
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_calcSizeBinary(UA_SecureConversationMessageHeader const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageHeader);
-    	return 0
-	 + sizeof(UA_OPCUATcpMessageHeader) // messageHeader CHECK: delete this or use in binary_secure.c
-	 + sizeof(UA_UInt32) // secureChannelId
-	;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpMessageHeader_encodeBinary(&src->messageHeader,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->secureChannelId,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageHeader * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_SecureConversationMessageHeader_init(dst);
-	CHECKED_DECODE(UA_OPCUATcpMessageHeader_decodeBinary(src,offset,&dst->messageHeader), UA_SecureConversationMessageHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->secureChannelId), UA_SecureConversationMessageHeader_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SecureConversationMessageHeader_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpMessageHeader_init(&p->messageHeader);
-	retval |= UA_UInt32_init(&p->secureChannelId);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageHeader)
-UA_Int32 UA_SecureConversationMessageHeader_copy(const UA_SecureConversationMessageHeader *src,UA_SecureConversationMessageHeader *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_SecureConversationMessageHeader));
-	return retval;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_AsymmetricAlgorithmSecurityHeader const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_AsymmetricAlgorithmSecurityHeader);
-    	return 0
-	 + UA_ByteString_calcSizeBinary(&ptr->securityPolicyUri)
-	 + UA_ByteString_calcSizeBinary(&ptr->senderCertificate)
-	 + UA_ByteString_calcSizeBinary(&ptr->receiverCertificateThumbprint)
-	;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorithmSecurityHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_encodeBinary(&src->securityPolicyUri,dst,offset);
-	retval |= UA_ByteString_encodeBinary(&src->senderCertificate,dst,offset);
-	retval |= UA_ByteString_encodeBinary(&src->receiverCertificateThumbprint,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_AsymmetricAlgorithmSecurityHeader * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_AsymmetricAlgorithmSecurityHeader_init(dst);
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->securityPolicyUri), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->senderCertificate), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->receiverCertificateThumbprint), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_deleteMembers(&p->securityPolicyUri);
-	retval |= UA_ByteString_deleteMembers(&p->senderCertificate);
-	retval |= UA_ByteString_deleteMembers(&p->receiverCertificateThumbprint);
-	return retval;
-}
-
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_init(&p->securityPolicyUri);
-	retval |= UA_ByteString_init(&p->senderCertificate);
-	retval |= UA_ByteString_init(&p->receiverCertificateThumbprint);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_AsymmetricAlgorithmSecurityHeader)
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHeader *src,UA_AsymmetricAlgorithmSecurityHeader *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_AsymmetricAlgorithmSecurityHeader));
-	retval |= UA_ByteString_copy(&src->securityPolicyUri,&dst->securityPolicyUri);
-	retval |= UA_ByteString_copy(&src->senderCertificate,&dst->senderCertificate);
-	retval |= UA_ByteString_copy(&src->receiverCertificateThumbprint,&dst->receiverCertificateThumbprint);
-	return retval;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_SymmetricAlgorithmSecurityHeader const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_SymmetricAlgorithmSecurityHeader);
-    	return 0
-	 + sizeof(UA_UInt32) // tokenId
-	;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_encodeBinary(UA_SymmetricAlgorithmSecurityHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&src->tokenId,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SymmetricAlgorithmSecurityHeader * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_SymmetricAlgorithmSecurityHeader_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->tokenId), UA_SymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SymmetricAlgorithmSecurityHeader_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	return retval;
-}
-
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&p->tokenId);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_SymmetricAlgorithmSecurityHeader)
-UA_Int32 UA_SymmetricAlgorithmSecurityHeader_copy(const UA_SymmetricAlgorithmSecurityHeader *src,UA_SymmetricAlgorithmSecurityHeader *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_SymmetricAlgorithmSecurityHeader));
-	return retval;
-}
-
-UA_Int32 UA_SequenceHeader_calcSizeBinary(UA_SequenceHeader const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_SequenceHeader);
-    	return 0
-	 + sizeof(UA_UInt32) // sequenceNumber
-	 + sizeof(UA_UInt32) // requestId
-	;
-}
-
-UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&src->sequenceNumber,dst,offset);
-	retval |= UA_UInt32_encodeBinary(&src->requestId,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SequenceHeader * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_SequenceHeader_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->sequenceNumber), UA_SequenceHeader_deleteMembers(dst));
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->requestId), UA_SequenceHeader_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_SequenceHeader_delete(UA_SequenceHeader *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SequenceHeader_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	return retval;
-}
-
-UA_Int32 UA_SequenceHeader_init(UA_SequenceHeader *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&p->sequenceNumber);
-	retval |= UA_UInt32_init(&p->requestId);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_SequenceHeader)
-UA_Int32 UA_SequenceHeader_copy(const UA_SequenceHeader *src,UA_SequenceHeader *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_SequenceHeader));
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_calcSizeBinary(UA_SecureConversationMessageFooter const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageFooter);
-    	return 0
-		+ UA_Array_calcSizeBinary(ptr->paddingSize,&UA_.types[UA_BYTE],ptr->padding)
-	 + sizeof(UA_Byte) // signature
-	;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_encodeBinary(src->padding,src->paddingSize,&UA_.types[UA_BYTE],dst,offset);
-	retval |= UA_Byte_encodeBinary(&src->signature,dst,offset);
-
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageFooter * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_SecureConversationMessageFooter_init(dst);
-	CHECKED_DECODE(UA_Int32_decodeBinary(src,offset,&dst->paddingSize),UA_SecureConversationMessageFooter_deleteMembers(dst));
-	CHECKED_DECODE(UA_Array_decodeBinary(src,offset,dst->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding), UA_SecureConversationMessageFooter_deleteMembers(dst));
-	CHECKED_DECODE(UA_Byte_decodeBinary(src,offset,&dst->signature), UA_SecureConversationMessageFooter_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SecureConversationMessageFooter_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_delete((void*)p->padding,p->paddingSize,&UA_.types[UA_BYTE]);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	p->paddingSize = 0;
-	p->padding = UA_NULL;
-	retval |= UA_Byte_init(&p->signature);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageFooter)
-UA_Int32 UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMessageFooter *src,UA_SecureConversationMessageFooter *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_SecureConversationMessageFooter));
-
-
-	retval |= UA_Array_copy(src->padding, src->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_calcSizeBinary(UA_SecureConversationMessageAbortBody const * ptr) {
-    	if(ptr==UA_NULL) return sizeof(UA_SecureConversationMessageAbortBody);
-    	return 0
-	 + sizeof(UA_UInt32) // error
-	 + UA_String_calcSizeBinary(&ptr->reason)
-	;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const * src, UA_ByteString* dst, UA_UInt32 *offset) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_encodeBinary(&src->error,dst,offset);
-	retval |= UA_String_encodeBinary(&src->reason,dst,offset);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const * src, UA_UInt32 *offset, UA_SecureConversationMessageAbortBody * dst) {
-    	UA_Int32 retval = UA_SUCCESS;
-	UA_SecureConversationMessageAbortBody_init(dst);
-	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->error), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
-	CHECKED_DECODE(UA_String_decodeBinary(src,offset,&dst->reason), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody *p) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SecureConversationMessageAbortBody_deleteMembers(p);
-	retval |= UA_free(p);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_String_deleteMembers(&p->reason);
-	return retval;
-}
-
-UA_Int32 UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody *p) {
-    	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_init(&p->error);
-	retval |= UA_String_init(&p->reason);
-	return retval;
-}
-
-UA_TYPE_NEW_DEFAULT(UA_SecureConversationMessageAbortBody)
-UA_Int32 UA_SecureConversationMessageAbortBody_copy(const UA_SecureConversationMessageAbortBody *src,UA_SecureConversationMessageAbortBody *dst) {
-	UA_Int32 retval = UA_SUCCESS;
-    if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;
-	memcpy(dst, src, sizeof(UA_SecureConversationMessageAbortBody));
-	retval |= UA_String_copy(&src->reason,&dst->reason);
-	return retval;
+#ifdef DEBUG
+void UA_MessageType_printf(char *label, UA_MessageType *p) {
+    UA_Byte *b = (UA_Byte *)p;
+    printf("%s{%c%c%c}\n", label, b[2], b[1], b[0]);
 }
+#endif

+ 16 - 107
src/ua_transport.h

@@ -3,126 +3,35 @@
 
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
-#include "ua_application.h"
-
-static const UA_Int32 SL_HEADER_LENGTH = 0;
-
-typedef enum UA_ConnectionState {
-	CONNECTIONSTATE_CLOSED,
-	CONNECTIONSTATE_OPENING,
-	CONNECTIONSTATE_ESTABLISHED,
-	CONNECTIONSTATE_CLOSE
-} UA_ConnectionState;
-
-typedef struct Session {
-	UA_Int32 sessionId;
-	Application *application;
-} Session;
 
 typedef enum SecurityTokenRequestType {
-	UA_SECURITYTOKEN_ISSUE = 0,
-	UA_SECURITYTOKEN_RENEW = 1
+    UA_SECURITYTOKEN_ISSUE = 0,
+    UA_SECURITYTOKEN_RENEW = 1
 } SecurityTokenRequestType;
 
 typedef enum {
-	UA_SECURITYMODE_INVALID = 0,
-	UA_SECURITYMODE_SIGN = 1,
-	UA_SECURITYMODE_SIGNANDENCRYPT = 2
+    UA_SECURITYMODE_INVALID        = 0,
+    UA_SECURITYMODE_NONE           = 1,
+    UA_SECURITYMODE_SIGNANDENCRYPT = 2
 } SecurityMode;
 
 /* MessageType */
 typedef UA_Int32 UA_MessageType;
 enum UA_MessageType {
-	UA_MESSAGETYPE_HEL = 0x48454C, // H E L
-	UA_MESSAGETYPE_ACK = 0x41434B, // A C k
-	UA_MESSAGETYPE_ERR = 0x455151, // E R R
-	UA_MESSAGETYPE_OPN = 0x4F504E, // O P N
-	UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
-	UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
+    UA_MESSAGETYPE_HEL = 0x48454C, // H E L
+    UA_MESSAGETYPE_ACK = 0x41434B, // A C k
+    UA_MESSAGETYPE_ERR = 0x455151, // E R R
+    UA_MESSAGETYPE_OPN = 0x4F504E, // O P N
+    UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
+    UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
 };
 UA_TYPE_PROTOTYPES(UA_MessageType)
 UA_TYPE_BINARY_ENCODING(UA_MessageType)
-void UA_MessageType_printf(char *label, UA_MessageType* p);
-
-/** @brief TCP Header */
-typedef struct UA_OPCUATcpMessageHeader {
-	UA_MessageType messageType;
-	UA_Byte isFinal;
-	UA_UInt32 messageSize;
-} UA_OPCUATcpMessageHeader;
-UA_TYPE_PROTOTYPES(UA_OPCUATcpMessageHeader)
-UA_TYPE_BINARY_ENCODING(UA_OPCUATcpMessageHeader)
-
-/** @brief Hello Message */
-typedef struct UA_OPCUATcpHelloMesage {
-	UA_UInt32 protocolVersion;
-	UA_UInt32 receiveBufferSize;
-	UA_UInt32 sendBufferSize;
-	UA_UInt32 maxMessageSize;
-	UA_UInt32 maxChunkCount;
-	UA_String endpointUrl;
-} UA_OPCUATcpHelloMessage;
-UA_TYPE_PROTOTYPES(UA_OPCUATcpHelloMessage)
-UA_TYPE_BINARY_ENCODING(UA_OPCUATcpHelloMessage)
-
-/** @brief Acknowledge Message */
-typedef struct UA_OPCUATcpAcknowledgeMessage {
-	UA_UInt32 protocolVersion;
-	UA_UInt32 receiveBufferSize;
-	UA_UInt32 sendBufferSize;
-	UA_UInt32 maxMessageSize;
-	UA_UInt32 maxChunkCount;
-} UA_OPCUATcpAcknowledgeMessage;
-UA_TYPE_PROTOTYPES(UA_OPCUATcpAcknowledgeMessage)
-UA_TYPE_BINARY_ENCODING(UA_OPCUATcpAcknowledgeMessage)
-
-/** @brief Secure Layer Sequence Header */
-typedef struct UA_SecureConversationMessageHeader {
-	UA_OPCUATcpMessageHeader messageHeader;
-	UA_UInt32 secureChannelId;
-} UA_SecureConversationMessageHeader;
-UA_TYPE_PROTOTYPES(UA_SecureConversationMessageHeader)
-UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageHeader)
-
-/** @brief Security Header> */
-typedef struct UA_AsymmetricAlgorithmSecurityHeader {
-	UA_ByteString securityPolicyUri;
-	UA_ByteString senderCertificate;
-	UA_ByteString receiverCertificateThumbprint;
-} UA_AsymmetricAlgorithmSecurityHeader;
-UA_TYPE_PROTOTYPES(UA_AsymmetricAlgorithmSecurityHeader)
-UA_TYPE_BINARY_ENCODING(UA_AsymmetricAlgorithmSecurityHeader)
-
-/** @brief Secure Layer Symmetric Algorithm Header */
-typedef struct UA_SymmetricAlgorithmSecurityHeader {
-	UA_UInt32 tokenId;
-} UA_SymmetricAlgorithmSecurityHeader;
-UA_TYPE_PROTOTYPES(UA_SymmetricAlgorithmSecurityHeader)
-UA_TYPE_BINARY_ENCODING(UA_SymmetricAlgorithmSecurityHeader)
-
-/** @brief Secure Layer Sequence Header */
-typedef struct UA_SequenceHeader {
-	UA_UInt32 sequenceNumber;
-	UA_UInt32 requestId;
-} UA_SequenceHeader;
-UA_TYPE_PROTOTYPES(UA_SequenceHeader)
-UA_TYPE_BINARY_ENCODING(UA_SequenceHeader)
-
-/** @brief Secure Conversation Message Footer */
-typedef struct UA_SecureConversationMessageFooter {
-	UA_Int32 paddingSize;
-	UA_Byte* padding;
-	UA_Byte signature;
-} UA_SecureConversationMessageFooter;
-UA_TYPE_PROTOTYPES(UA_SecureConversationMessageFooter)
-UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageFooter)
+#ifdef DEBUG
+void UA_MessageType_printf(char *label, UA_MessageType *p);
+#endif
 
-/** @brief Secure Conversation Message Abort Body */
-typedef struct UA_SecureConversationMessageAbortBody {
-	UA_UInt32 error;
-	UA_String reason;
-} UA_SecureConversationMessageAbortBody;
-UA_TYPE_PROTOTYPES(UA_SecureConversationMessageAbortBody)
-UA_TYPE_BINARY_ENCODING(UA_SecureConversationMessageAbortBody)
+/* All other transport types are auto-generated from a schema definition. */
+#include "ua_transport_generated.h"
 
 #endif /* UA_TRANSPORT_H_ */

+ 0 - 181
src/ua_transport_binary.c

@@ -1,181 +0,0 @@
-#include "ua_transport_connection.h"
-#include <memory.h>
-#include "ua_transport_binary.h"
-#include "ua_transport.h"
-#include "ua_transport_binary_secure.h"
-
-
-static UA_Int32 TL_handleHello(UA_TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* pos){
-	UA_Int32 retval = UA_SUCCESS;
-	UA_UInt32 tmpPos = 0;
-	UA_Int32 connectionState;
-	UA_OPCUATcpHelloMessage helloMessage;
-
-	UA_TL_Connection_getState(connection, &connectionState);
-	if (connectionState == CONNECTIONSTATE_CLOSED){
-		DBG_VERBOSE(printf("TL_handleHello - extracting header information \n"));
-		UA_OPCUATcpHelloMessage_decodeBinary(msg,pos,&helloMessage);
-
-		UA_TL_Connection_configByHello(connection, &helloMessage);
-		DBG_VERBOSE(printf("TL_handleHello - protocolVersion = %d \n",connection->remoteConf.protocolVersion));
-		DBG_VERBOSE(printf("TL_handleHello - recvBufferSize = %d \n",connection->remoteConf.recvBufferSize));
-		DBG_VERBOSE(printf("TL_handleHello - sendBufferSize = %d \n",connection->remoteConf.sendBufferSize));
-		DBG_VERBOSE(printf("TL_handleHello - maxMessageSize = %d \n",connection->remoteConf.maxMessageSize));
-		DBG_VERBOSE(printf("TL_handleHello - maxChunkCount = %d \n",connection->remoteConf.maxChunkCount));
-
-		// build acknowledge response
-		UA_OPCUATcpAcknowledgeMessage ackMessage;
-		TL_Buffer localConfig;
-		UA_TL_Connection_getLocalConfig(connection, &localConfig);
-		ackMessage.protocolVersion = localConfig.protocolVersion;
-		ackMessage.receiveBufferSize = localConfig.recvBufferSize;
-		ackMessage.sendBufferSize = localConfig.sendBufferSize;
-		ackMessage.maxMessageSize = localConfig.maxMessageSize;
-		ackMessage.maxChunkCount = localConfig.maxChunkCount;
-
-		UA_OPCUATcpMessageHeader ackHeader;
-		ackHeader.messageType = UA_MESSAGETYPE_ACK;
-		ackHeader.isFinal = 'F';
-
-		// encode header and message to buffer
-		tmpPos = 0;
-
-		ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(&ackMessage) + UA_OPCUATcpMessageHeader_calcSizeBinary(&ackHeader);
-		UA_ByteString *ack_msg;
-		UA_alloc((void **)&ack_msg, sizeof(UA_ByteString));
-		UA_ByteString_newMembers(ack_msg, ackHeader.messageSize);
-		UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader,ack_msg,&tmpPos);
-		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage, ack_msg,&tmpPos);
-
-		DBG_VERBOSE(printf("TL_handleHello - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos));
-		DBG_VERBOSE(UA_ByteString_printx("_handleHello - ack=", ack_msg));
-		TL_Send(connection, (const UA_ByteString **) &ack_msg, 1);
-		DBG_VERBOSE(printf("TL_handleHello - finished writing\n"));
-		UA_ByteString_delete(ack_msg);
-	} else {
-		DBG_ERR(printf("TL_handleHello - wrong connection state \n"));
-		retval = UA_ERROR_MULTIPLE_HEL;
-	}
-	return retval;
-}
-
-static UA_Int32 TL_handleOpen(UA_TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 state;
-	SL_Channel *channel;
-	UA_UInt32 secureChannelId;
-	retval |= UA_TL_Connection_getState(connection, &state);
-	if (state == CONNECTIONSTATE_ESTABLISHED) {
-		UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
-		SL_ChannelManager_getChannel(secureChannelId, &channel);
-		if(channel == UA_NULL)
-		{
-			SL_Channel *newChannel;
-			//create new channel
-			retval |= SL_Channel_new(&newChannel);//just create channel
-			retval |= SL_Channel_init(newChannel, connection,SL_ChannelManager_generateChannelId, SL_ChannelManager_generateToken);
-			retval |= SL_Channel_bind(newChannel,connection);
-			retval |= SL_ProcessOpenChannel(newChannel, msg, pos);
-			retval |= SL_ChannelManager_addChannel(newChannel);
-			return retval;
-		}
-		// channel already exists, renew token?
-		retval |= SL_ProcessOpenChannel(channel, msg, pos);
-		return retval;
-	}else{
-		printf("TL_handleOpen - ERROR: could not create new secureChannel");
-	}
-
-	return UA_ERR_INVALID_VALUE;
-}
-
-static UA_Int32 TL_handleMsg(UA_TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	UA_Int32 state;
-	UA_TL_Connection_getState(connection,&state);
-	if (state == CONNECTIONSTATE_ESTABLISHED) {
-		return SL_Process(msg, pos);
-	}
-	return UA_ERR_INVALID_VALUE;
-}
-
-static UA_Int32 TL_handleClo(UA_TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	SL_Process(msg,pos);
-	// just prepare closing, closing and freeing structures is done elsewhere
-	// UA_TL_Connection_close(connection);
-	UA_TL_Connection_setState(connection, CONNECTIONSTATE_CLOSE);
-	return retval;
-}
-
-UA_Int32 TL_Process(UA_TL_Connection *connection, const UA_ByteString* msg) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_UInt32 pos = 0;
-	UA_OPCUATcpMessageHeader tcpMessageHeader;
-
-	DBG_VERBOSE(printf("TL_Process - entered \n"));
-	UA_Int32 messageCounter = 0;
-
-	do{
-
-		if ((retval = UA_OPCUATcpMessageHeader_decodeBinary(msg,&pos,&tcpMessageHeader)) == UA_SUCCESS) {
-			printf("TL_Process - messageType=%.*s\n",3,msg->data);
-			switch(tcpMessageHeader.messageType) {
-			case UA_MESSAGETYPE_HEL:
-				retval = TL_handleHello(connection, msg, &pos);
-				break;
-			case UA_MESSAGETYPE_OPN:
-				retval = TL_handleOpen(connection, msg, &pos);
-				break;
-			case UA_MESSAGETYPE_MSG:
-				retval = TL_handleMsg(connection, msg, &pos);
-				break;
-			case UA_MESSAGETYPE_CLO:
-				retval = TL_handleClo(connection, msg, &pos);
-				break;
-			default: // dispatch processing to secureLayer
-				//Invalid packet was received which could have led to a wrong offset (pos).
-				//It was not possible to extract the following packet from the buffer
-				retval = UA_ERR_INVALID_VALUE;
-				break;
-			}
-		}
-		else
-		{
-			printf("TL_Process - ERROR:decoding of header failed \n");
-		}
-
-		messageCounter++;
-		printf("TL_Process - multipleMessage in Buffer: %i \n",messageCounter);
-
-
-	}while(msg->length > (UA_Int32)pos);
-	/* if (retval != UA_SUCCESS) { */
-	/* 	// FIXME: compose real error message */
-	/* 	UA_ByteString errorMsg; */
-	/* 	UA_ByteString *errorMsg_ptr = &errorMsg; */
-	/* 	UA_ByteString_newMembers(&errorMsg,10); */
-	/* 	TL_Send(connection,(const UA_ByteString **)&errorMsg_ptr, 1); */
-	/* 	UA_ByteString_deleteMembers(&errorMsg); */
-	/* } */
-	UA_OPCUATcpMessageHeader_deleteMembers(&tcpMessageHeader);
-	return retval;
-}
-
-/** respond to client request */
-UA_Int32 TL_Send(UA_TL_Connection *connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len) {
-	UA_Int32 retval = UA_SUCCESS;
-
-
-	DBG_VERBOSE(printf("TL_send - entered \n"));
-	//	if (TL_check(connection,msg,TL_CHECK_REMOTE) == UA_SUCCESS) {
-
-	retval = UA_TL_Connection_callWriter(connection, gather_buf, gather_len);
-	DBG_VERBOSE(printf("TL_send - exited \n"));
-		//}
-	/* else */
-	/* { */
-	/* 	DBG_ERR(printf("TL_send - ERROR: packet size greater than remote buffer size")); */
-	/* 	retval = UA_ERROR; */
-	/* } */
-	return retval;
-}

+ 0 - 40
src/ua_transport_binary.h

@@ -1,40 +0,0 @@
-#ifndef OPCUA_TRANSPORT_BINARY_H_
-#define OPCUA_TRANSPORT_BINARY_H_
-#include <stdio.h>
-
-
-#include "ua_transport_binary.h"
-#include "ua_transport_connection.h"
-
-//transport errors begin at 1000
-#define UA_ERROR_MULTIPLE_HEL 1000
-#define UA_ERROR_RCV_ERROR 1001
-
-//variables which belong to layer
-#define TL_SERVER_PROTOCOL_VERSION  0
-#define TL_SERVER_MAX_CHUNK_COUNT 1
-#define TL_SERVER_MAX_MESSAGE_SIZE  8192
-
-
-
-/* Transport Layer Connection */
-//struct TL_Connection_T; // forward declaration
-
-//typedef UA_Int32 (*TL_Writer)(struct TL_Connection_T* connection, const UA_ByteString** gather_bufs, UA_Int32 gather_len); // send mutiple buffer concatenated into one msg (zero copy)
-/*
-typedef struct TL_Connection_T {
-	UA_Int32 connectionHandle;
-	UA_UInt32 connectionState;
-	TL_Buffer localConf;
-	TL_Buffer remoteConf;
-	TL_Writer writerCallback;
-	UA_String localEndpointUrl;
-	UA_String remoteEndpointUrl;
-	struct SL_Channel_T* secureChannel;
-} TL_Connection;
-*/
-
-UA_Int32 TL_Send(UA_TL_Connection *connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len);
-UA_Int32 TL_Process(UA_TL_Connection *connection, const UA_ByteString* msg);
-
-#endif /* OPCUA_TRANSPORT_BINARY_H_ */

+ 0 - 378
src/ua_transport_binary_secure.c

@@ -1,378 +0,0 @@
-#include <stdio.h>
-#include <memory.h> // memcpy
-
-#include "ua_transport_binary.h"
-#include "ua_transport_binary_secure.h"
-#include "ua_transport.h"
-#include "ua_statuscodes.h"
-#include "ua_services.h"
-#include "ua_session_manager.h"
-#include "ua_session.h"
-
-#define SIZE_SECURECHANNEL_HEADER 12
-#define SIZE_SEQHEADER_HEADER 8
-
-static UA_Int32 SL_Send(SL_Channel *channel, const UA_ByteString * responseMessage, UA_Int32 type) {
-	UA_UInt32 pos = 0;
-	UA_Int32 isAsym = (type == UA_OPENSECURECHANNELRESPONSE_NS0); // FIXME: this is a to dumb method to determine asymmetric algorithm setting
-	UA_UInt32 channelId;
-	UA_UInt32 sequenceNumber;
-	UA_UInt32 requestId;
-	UA_NodeId resp_nodeid;
-	UA_TL_Connection *connection;
-	UA_AsymmetricAlgorithmSecurityHeader *asymAlgSettings = UA_NULL;
-
-	resp_nodeid.namespaceIndex = 0;
-	resp_nodeid.identifierType = UA_NODEIDTYPE_NUMERIC;
-	resp_nodeid.identifier.numeric = type + 2; // binary encoding
-
-	const UA_ByteString *response_gather[2]; // securechannel_header, seq_header, security_encryption_header, message_length (eventually + padding + size_signature);
-	UA_alloc((void ** )&response_gather[0], sizeof(UA_ByteString));
-	if (isAsym) {
-		SL_Channel_getLocalAsymAlgSettings(channel, &asymAlgSettings);
-		UA_ByteString_newMembers((UA_ByteString *) response_gather[0],
-				SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
-						+ UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(
-								asymAlgSettings)
-						+ UA_NodeId_calcSizeBinary(&resp_nodeid));
-	} else {
-		UA_ByteString_newMembers((UA_ByteString *) response_gather[0], 8 + 16 + // normal header + 4*32bit secure channel information
-				UA_NodeId_calcSizeBinary(&resp_nodeid));
-	}
-
-	// sizePadding = 0;
-	// sizeSignature = 0;
-	UA_ByteString *header = (UA_ByteString *) response_gather[0];
-
-	/*---encode Secure Conversation Message Header  ---*/
-	if (isAsym) {
-		header->data[0] = 'O';
-		header->data[1] = 'P';
-		header->data[2] = 'N';
-	} else {
-		header->data[0] = 'M';
-		header->data[1] = 'S';
-		header->data[2] = 'G';
-	}
-	pos += 3;
-	header->data[pos] = 'F';
-	pos += 1;
-
-	UA_Int32 packetSize = response_gather[0]->length + responseMessage->length;
-	UA_Int32_encodeBinary(&packetSize, header,&pos);
-
-	//use get accessor to read the channel Id
-	SL_Channel_getChannelId(channel, &channelId);
-
-	UA_UInt32_encodeBinary(&channelId, header,&pos);
-
-	/*---encode Algorithm Security Header ---*/
-	if (isAsym) {
-		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(asymAlgSettings, header,&pos);
-		UA_free(asymAlgSettings);
-	} else {
-		UA_UInt32 tokenId = 0;
-		SL_Channel_getTokenId(channel, &tokenId);
-		UA_UInt32_encodeBinary(&tokenId, header,&pos);
-	}
-
-	/*---encode Sequence Header ---*/
-	SL_Channel_getSequenceNumber(channel, &sequenceNumber);
-	UA_UInt32_encodeBinary(&sequenceNumber, header, &pos);
-	SL_Channel_getRequestId(channel, &requestId);
-	UA_UInt32_encodeBinary(&requestId, header,&pos);
-
-	/*---add payload type---*/
-	UA_NodeId_encodeBinary(&resp_nodeid, header,&pos);
-
-	/*---add encoded Message ---*/
-	response_gather[1] = responseMessage; // is deleted in the calling function
-
-	/* sign Data*/
-
-	/* encrypt Data*/
-
-	/* send Data */
-	SL_Channel_getConnection(channel, &connection);
-	TL_Send(connection, response_gather, 2);
-
-	UA_ByteString_delete((UA_ByteString *) response_gather[0]);
-	return UA_SUCCESS;
-}
-
-static void init_response_header(UA_RequestHeader const * p, UA_ResponseHeader * r) {
-	r->requestHandle = p->requestHandle;
-	r->serviceResult = UA_STATUSCODE_GOOD;
-	r->stringTableSize = 0;
-	r->timestamp = UA_DateTime_now();
-}
-
-#define RESPONSE_PREPARE(TYPE) \
-	UA_##TYPE##Request p; \
-	UA_##TYPE##Response r; \
-	UA_Session *session = UA_NULL; \
-	UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
-	UA_##TYPE##Response_init(&r); \
-	init_response_header(&p.requestHeader, &r.responseHeader); \
-	UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
-	DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
-
-#define INVOKE_SERVICE(TYPE) \
-	UA_##TYPE##Request p; \
-	UA_##TYPE##Response r; \
-	UA_Session session = UA_NULL; \
-	UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
-	UA_##TYPE##Response_init(&r); \
-	init_response_header(&p.requestHeader, &r.responseHeader); \
-	UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
-	DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
-	Service_##TYPE(session, &p, &r); \
-	DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
-    sendOffset = 0; \
-	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
-	UA_##TYPE##Response_encodeBinary(&r, &sendOffset, &response_msg); \
-	UA_##TYPE##Request_deleteMembers(&p); \
-	UA_##TYPE##Response_deleteMembers(&r); \
-/*
-#define INVOKE_SERVICE(TYPE) \
-		DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
-		Service_##TYPE(session, &p, &r); \
-		DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
-*/
-#define RESPONSE_CLEANUP(TYPE) \
-	DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
-	sendOffset = 0; \
-	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
-	UA_##TYPE##Response_encodeBinary(&r, &response_msg,&sendOffset); \
-	UA_##TYPE##Request_deleteMembers(&p); \
-	UA_##TYPE##Response_deleteMembers(&r); \
-
-
-UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_UInt32 *pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_UInt32 recvOffset = *pos;
-	UA_UInt32 sendOffset = 0;
-	// Every Message starts with a NodeID which names the serviceRequestType
-	UA_NodeId serviceRequestType;
-	UA_NodeId_decodeBinary(msg, &recvOffset,&serviceRequestType);
-#ifdef DEBUG
-	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
-			&serviceRequestType);
-#endif
-	UA_ByteString response_msg;
-	UA_Int32 serviceid = serviceRequestType.identifier.numeric - 2; // binary encoding has 2 added to the id
-	UA_Int32 responsetype;
-/* stack related services which only need information about the secure Channel */
-	if (serviceid == UA_GETENDPOINTSREQUEST_NS0) {
-		RESPONSE_PREPARE(GetEndpoints);
-		Service_GetEndpoints(channel,&p, &r);
-		RESPONSE_CLEANUP(GetEndpoints);
-		//INVOKE_SERVICE(GetEndpoints);
-		responsetype = UA_GETENDPOINTSRESPONSE_NS0;
-	} else if (serviceid == UA_OPENSECURECHANNELREQUEST_NS0) {
-		RESPONSE_PREPARE(OpenSecureChannel);
-		Service_OpenSecureChannel(channel,&p, &r);
-		RESPONSE_CLEANUP(OpenSecureChannel);
-		responsetype = UA_OPENSECURECHANNELRESPONSE_NS0;
-	} else if (serviceid == UA_CLOSESECURECHANNELREQUEST_NS0) {
-		RESPONSE_PREPARE(CloseSecureChannel);
-		Service_CloseSecureChannel(channel,&p,&r);
-		RESPONSE_CLEANUP(CloseSecureChannel);
-		responsetype = UA_CLOSESECURECHANNELRESPONSE_NS0;
-	} else if (serviceid == UA_CREATESESSIONREQUEST_NS0) {
-		RESPONSE_PREPARE(CreateSession);
-		Service_CreateSession(channel,&p, &r);
-		RESPONSE_CLEANUP(CreateSession);
-		responsetype = UA_CREATESESSIONRESPONSE_NS0;
-	}
-/* services which need a session object */
-	else if (serviceid == UA_ACTIVATESESSIONREQUEST_NS0) {
-		RESPONSE_PREPARE(ActivateSession);
-		UA_Session_updateLifetime(session); //renew session timeout
-		Service_ActivateSession(channel, session,&p, &r);
-		RESPONSE_CLEANUP(ActivateSession);
-		responsetype = UA_ACTIVATESESSIONRESPONSE_NS0;
-	} else if (serviceid == UA_CLOSESESSIONREQUEST_NS0) {
-		RESPONSE_PREPARE(CloseSession);
-		if (UA_Session_verifyChannel(session,channel)){
-			UA_Session_updateLifetime(session); //renew session timeout
-			Service_CloseSession(session,&p, &r);
-		RESPONSE_CLEANUP(CloseSession);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		responsetype = UA_CLOSESESSIONRESPONSE_NS0;
-	} else if (serviceid == UA_READREQUEST_NS0) {
-
-		RESPONSE_PREPARE(Read);
-		UA_Session_updateLifetime(session); //renew session timeout
-		DBG_VERBOSE(printf("Finished Service: %s\n", Read));
-		if (UA_Session_verifyChannel(session,channel)){
-			UA_Session_updateLifetime(session); //renew session timeout
-			Service_Read(session,&p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", Read));
-		RESPONSE_CLEANUP(Read);
-
-		responsetype = UA_READRESPONSE_NS0;
-	} else if (serviceid == UA_WRITEREQUEST_NS0) {
-
-		RESPONSE_PREPARE(Write);
-		DBG_VERBOSE(printf("Finished Service: %s\n", Write));
-		if (UA_Session_verifyChannel(session,channel)){
-			UA_Session_updateLifetime(session); //renew session timeout
-			Service_Write(session,&p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", Write));
-		RESPONSE_CLEANUP(Write);
-		responsetype = UA_WRITERESPONSE_NS0;
-	} else if (serviceid == UA_BROWSEREQUEST_NS0) {
-		RESPONSE_PREPARE(Browse);
-		DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
-		if (UA_Session_verifyChannel(session,channel)){
-			Service_Browse(session,&p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
-		RESPONSE_CLEANUP(Browse);
-		responsetype = UA_BROWSERESPONSE_NS0;
-	} else if (serviceid == UA_CREATESUBSCRIPTIONREQUEST_NS0) {
-		RESPONSE_PREPARE(CreateSubscription);
-		DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
-		if (UA_Session_verifyChannel(session,channel)){
-			Service_CreateSubscription(session, &p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
-		RESPONSE_CLEANUP(CreateSubscription);
-		responsetype = UA_CREATESUBSCRIPTIONRESPONSE_NS0;
-	} else if (serviceid == UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0) {
-		RESPONSE_PREPARE(TranslateBrowsePathsToNodeIds);
-		DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
-		if (UA_Session_verifyChannel(session,channel)){
-			Service_TranslateBrowsePathsToNodeIds(session, &p, &r);
-		} else {
-				DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
-		RESPONSE_CLEANUP(TranslateBrowsePathsToNodeIds);
-		responsetype = UA_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE_NS0;
-	} else if (serviceid == UA_PUBLISHREQUEST_NS0) {
-
-		RESPONSE_PREPARE(Publish);
-		DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
-		if (UA_Session_verifyChannel(session,channel)) {
-			Service_Publish(session, &p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
-		RESPONSE_CLEANUP(Publish);
-		responsetype = UA_PUBLISHRESPONSE_NS0;
-	} else if (serviceid == UA_CREATEMONITOREDITEMSREQUEST_NS0) {
-		RESPONSE_PREPARE(CreateMonitoredItems);
-		DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
-		if (UA_Session_verifyChannel(session,channel)) {
-			Service_CreateMonitoredItems(session, &p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
-		RESPONSE_CLEANUP(CreateMonitoredItems);
-		responsetype = UA_CREATEMONITOREDITEMSRESPONSE_NS0;
-	} else if (serviceid == UA_SETPUBLISHINGMODEREQUEST_NS0) {
-		RESPONSE_PREPARE(SetPublishingMode);
-		DBG_VERBOSE(printf("Finished Service: %s\n",SetPublishingMode));
-		if (UA_Session_verifyChannel(session,channel)) {
-			Service_SetPublishingMode(session, &p, &r);
-		} else {
-			DBG_VERBOSE(printf("session does not match secure channel"));
-		}
-		DBG_VERBOSE(printf("Finished Service: %s\n", SetPublishingMode));
-		RESPONSE_CLEANUP(SetPublishingMode);
-		responsetype = UA_SETPUBLISHINGMODERESPONSE_NS0;
-	} else {
-		printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
-			   serviceRequestType.namespaceIndex, serviceRequestType.identifier.numeric);
-		retval = UA_ERROR;
-		UA_RequestHeader p;
-		UA_ResponseHeader r;
-
-		UA_RequestHeader_decodeBinary(msg, &recvOffset, &p);
-		UA_ResponseHeader_init(&r);
-		r.requestHandle = p.requestHandle;
-		r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
-		sendOffset = 0;
-		UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSizeBinary(&r));
-		UA_ResponseHeader_encodeBinary(&r, &response_msg,&sendOffset);
-		responsetype = UA_RESPONSEHEADER_NS0;
-	}
-
-	if(serviceid != UA_CLOSESECURECHANNELREQUEST_NS0)
-		SL_Send(channel, &response_msg, responsetype);
-
-	UA_ByteString_deleteMembers(&response_msg);
-	*pos = recvOffset;
-	return retval;
-}
-
-UA_Int32 SL_ProcessOpenChannel(SL_Channel *channel, const UA_ByteString* msg, UA_UInt32 *pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_SequenceHeader sequenceHeader;
-	UA_AsymmetricAlgorithmSecurityHeader asymHeader;
-	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg,pos,&asymHeader);
-	UA_SequenceHeader_decodeBinary(msg,pos,&sequenceHeader);
-
-	//init remote security settings from the security header
-	SL_Channel_setRemoteSecuritySettings(channel,&asymHeader,&sequenceHeader);
-	return SL_handleRequest(channel, msg, pos) | retval;
-}
-
-/* not used anymore */
-//UA_Int32 SL_ProcessCloseChannel(SL_Channel *channel, const UA_ByteString* msg,
-//		UA_UInt32 *pos)
-//{
-//	return SL_handleRequest(channel, msg, pos);
-//}
-
-UA_Int32 SL_Process(const UA_ByteString* msg, UA_UInt32* pos) {
-	DBG_VERBOSE(printf("SL_process - entered \n"));
-	UA_UInt32 secureChannelId;
-	UA_UInt32 foundChannelId;
-	SL_Channel *channel;
-	UA_SequenceHeader sequenceHeader;
-
-	UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
-
-	//FIXME: we assume SAS, need to check if AAS or SAS
-	UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
-	// if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
-	UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos,
-			&symAlgSecHeader);
-
- 	if (SL_ChannelManager_getChannel(secureChannelId, &channel) == UA_SUCCESS) {
-		SL_Channel_getChannelId(channel, &foundChannelId);
-		printf("SL_process - received msg, with channel id: %i \n", foundChannelId);
-
-		//sequence number processing
-		UA_SequenceHeader_decodeBinary(msg, pos,
-				&sequenceHeader);
-		SL_Channel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
-		SL_Channel_checkRequestId(channel,sequenceHeader.requestId);
-		//request id processing
-
-		SL_handleRequest(channel, msg, pos);
-	} else {
-		printf("SL_process - ERROR could not find channel with id: %i \n",
-				secureChannelId);
-		//TODO generate ERROR_Bad_SecureChannelUnkown
-	}
-
-	return UA_SUCCESS;
-}

+ 0 - 35
src/ua_transport_binary_secure.h

@@ -1,35 +0,0 @@
-#ifndef OPCUA_TRANSPORT_BINARY_SECURE_H_
-#define OPCUA_TRANSPORT_BINARY_SECURE_H_
-#include "ua_types.h"
-#include "ua_transport.h"
-#include "ua_transport_binary.h"
-#include "ua_channel.h"
-#include "ua_channel_manager.h"
-
-/*inputs for secure Channel which must be provided once
-endPointUrl
-securityPolicyUrl
-securityMode
-revisedLifetime
-*/
-
-/*inputs for secure Channel Manager which must be provided once
- maxChannelCount
-
- */
-
-UA_Int32 SL_Process(const UA_ByteString* msg, UA_UInt32* pos);
-
-/**
- * @brief Wrapper function, to encapsulate handleRequest for openSecureChannel requests
- * @param channel A secure Channel structure, which receives the information for the new created secure channel
- * @param msg Message which holds the binary encoded request
- * @param pos Position in the message at which the request begins
- * @return Returns UA_SUCCESS if successful executed, UA_ERROR in any other case
-
- */
-UA_Int32 SL_ProcessOpenChannel(SL_Channel *channel, const UA_ByteString* msg,
-		UA_UInt32 *pos);
-UA_Int32 SL_ProcessCloseChannel(SL_Channel *channel, const UA_ByteString* msg,
-		UA_UInt32 *pos);
-#endif /* OPCUA_TRANSPORT_BINARY_SECURE_H_ */

+ 0 - 143
src/ua_transport_connection.c

@@ -1,143 +0,0 @@
-#include "ua_transport_connection.h"
-#include "ua_transport.h"
-
-struct UA_TL_Connection {
-	UA_Int32 connectionHandle;
-	UA_UInt32 state;
-	TL_Buffer localConf;
-	TL_Buffer remoteConf;
-	TL_Writer writer;
-	UA_String localEndpointUrl;
-	UA_String remoteEndpointUrl;
-	TL_Closer closeCallback;
-	void *networkLayerData;
-};
-
-UA_Int32 UA_TL_Connection_new(UA_TL_Connection **connection, TL_Buffer localBuffers,TL_Writer writer,
-		                      TL_Closer closeCallback,UA_Int32 handle, void* networkLayerData) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_alloc((void**)connection,sizeof(UA_TL_Connection));
-	if(retval == UA_SUCCESS) {
-		(*connection)->connectionHandle = handle;
-		(*connection)->localConf = localBuffers;
-		(*connection)->writer = writer;
-		(*connection)->closeCallback = closeCallback;
-		(*connection)->state = CONNECTIONSTATE_CLOSED;
-		(*connection)->networkLayerData = networkLayerData;
-	}
-	return retval;
-}
-
-UA_Int32 UA_TL_Connection_delete(UA_TL_Connection *connection) {
-	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_free((void*)connection);
-	return retval;
-}
-
-UA_Int32 UA_TL_Connection_close(UA_TL_Connection *connection) {
-	connection->state = CONNECTIONSTATE_CLOSED;
-	connection->closeCallback(connection);
-	return UA_SUCCESS;
-}
-
-UA_Boolean UA_TL_Connection_compare(UA_TL_Connection *connection1, UA_TL_Connection *connection2) {
-	if(!connection1 || !connection2)
-		return UA_FALSE;
-	return ((*(UA_TL_Connection**)connection1)->connectionHandle == (*(UA_TL_Connection**)connection2)->connectionHandle);
-}
-
-
-UA_Int32 UA_TL_Connection_configByHello(UA_TL_Connection *connection, UA_OPCUATcpHelloMessage *helloMessage) {
-	UA_Int32 retval = UA_SUCCESS;
-	connection->remoteConf.maxChunkCount = helloMessage->maxChunkCount;
-	connection->remoteConf.maxMessageSize = helloMessage->maxMessageSize;
-	connection->remoteConf.protocolVersion = helloMessage->protocolVersion;
-	connection->remoteConf.recvBufferSize = helloMessage->receiveBufferSize;
-	connection->remoteConf.sendBufferSize = helloMessage->sendBufferSize;
-	connection->state = CONNECTIONSTATE_ESTABLISHED;
-	retval |= UA_String_copy(&helloMessage->endpointUrl,&connection->remoteEndpointUrl);
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_Connection_callWriter(UA_TL_Connection *connection, const UA_ByteString** gather_bufs, UA_Int32 gather_len) {
-	return connection->writer(connection->connectionHandle,gather_bufs, gather_len);
-}
-
-//setters
-UA_Int32 UA_TL_Connection_setWriter(UA_TL_Connection *connection, TL_Writer writer) {
-	connection->writer = writer;
-	return UA_SUCCESS;
-}
-
-/* UA_Int32 UA_TL_Connection_setConnectionHandle(UA_TL_Connection *connection, UA_Int32 connectionHandle)
-{
-	connection->connectionHandle = connectionHandle;
-	return UA_SUCCESS;
-} */
-
-UA_Int32 UA_TL_Connection_setState(UA_TL_Connection *connection, UA_Int32 connectionState) {
-	if(!connection)
-		return UA_ERROR;
-
-	connection->state = connectionState;
-	return UA_SUCCESS;
-}
-
-//getters
-UA_Int32 UA_TL_Connection_getState(UA_TL_Connection *connection, UA_Int32 *connectionState) {
-	if(!connection) {
-		*connectionState = -1;
-		return UA_ERROR;
-	}
-
-	*connectionState = connection->state;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_Connection_getNetworkLayerData(UA_TL_Connection *connection,void** networkLayerData) {
-	if(!connection) {
-		*networkLayerData = UA_NULL;
-		return UA_ERROR;
-	}
-
-	*networkLayerData = connection->networkLayerData;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_Connection_getProtocolVersion(UA_TL_Connection *connection, UA_UInt32 *protocolVersion) {
-	if(!connection) {
-		*protocolVersion = 0xFF;
-		return UA_ERROR;
-	}
-
-	*protocolVersion = connection->localConf.protocolVersion;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_Connection_getLocalConfig(UA_TL_Connection *connection, TL_Buffer *localConfiguration) {
-	if(!connection) {
-		localConfiguration = UA_NULL;
-		return UA_ERROR;
-	}
-
-	return UA_memcpy(localConfiguration,&connection->localConf, sizeof(TL_Buffer));
-}
-
-UA_Int32 UA_TL_Connection_getHandle(UA_TL_Connection *connection, UA_UInt32 *connectionHandle) {
-	if(!connection) {
-		connectionHandle = 0;
-		return UA_ERROR;
-	}
-
-	*connectionHandle = connection->connectionHandle;
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_TL_Connection_bind(UA_TL_Connection *connection, UA_Int32 handle) {
-	if(!connection)
-		return UA_ERROR;
-
-	connection->connectionHandle = handle;
-	return UA_SUCCESS;
-}

+ 0 - 39
src/ua_transport_connection.h

@@ -1,39 +0,0 @@
-#ifndef UA_TRANSPORT_CONNECTION_H_
-#define UA_TRANSPORT_CONNECTION_H_
-
-#include "ua_transport.h"
-
-typedef struct TL_Buffer{
-	UA_UInt32 protocolVersion;
-	UA_UInt32 sendBufferSize;
-	UA_UInt32 recvBufferSize;
-	UA_UInt32 maxMessageSize;
-	UA_UInt32 maxChunkCount;
-} TL_Buffer;
-struct UA_TL_Connection;
-typedef struct UA_TL_Connection UA_TL_Connection;
-
-typedef UA_Int32 (*TL_Closer)(UA_TL_Connection*);
-typedef UA_Int32 (*TL_Writer)(UA_Int32 connectionHandle, const UA_ByteString** gather_bufs, UA_Int32 gather_len); // send mutiple buffer concatenated into one msg (zero copy)
-
-UA_Int32 UA_TL_Connection_configByHello(UA_TL_Connection *connection, UA_OPCUATcpHelloMessage *helloMessage);
-UA_Int32 UA_TL_Connection_delete(UA_TL_Connection *connection);
-UA_Int32 UA_TL_Connection_callWriter(UA_TL_Connection *connection, const UA_ByteString** gather_bufs, UA_Int32 gather_len);
-UA_Int32 UA_TL_Connection_close(UA_TL_Connection *connection);
-UA_Int32 UA_TL_Connection_new(UA_TL_Connection **connection, TL_Buffer localBuffers,TL_Writer writer, TL_Closer closeCallback,UA_Int32 handle, void* networkLayerData);
-UA_Int32 UA_TL_Connection_bind(UA_TL_Connection *connection, UA_Int32 handle);
-UA_Boolean UA_TL_Connection_compare(UA_TL_Connection *connection1, UA_TL_Connection *connection2);
-
-//setters
-UA_Int32 UA_TL_Connection_setState(UA_TL_Connection *connection, UA_Int32 connectionState);
-UA_Int32 UA_TL_Connection_setWriter(UA_TL_Connection *connection, TL_Writer writer);
-//UA_Int32 UA_TL_Connection_setConnectionHandle(UA_TL_Connection *connection, UA_Int32 connectionHandle);
-
-//getters
-UA_Int32 UA_TL_Connection_getHandle(UA_TL_Connection *connection, UA_UInt32 *connectionId);
-UA_Int32 UA_TL_Connection_getProtocolVersion(UA_TL_Connection *connection, UA_UInt32 *protocolVersion);
-UA_Int32 UA_TL_Connection_getState(UA_TL_Connection *connection, UA_Int32 *connectionState);
-UA_Int32 UA_TL_Connection_getLocalConfig(UA_TL_Connection *connection, TL_Buffer *localConfiguration);
-UA_Int32 UA_TL_Connection_getNetworkLayerData(UA_TL_Connection *connection,void** networkLayerData);
-
-#endif /* UA_TRANSPORT_CONNECTION_H_ */

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 700 - 707
src/ua_types.c


+ 177 - 164
src/ua_types.h

@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 {contributors}
+ *
+ * This file is part of open62541. open62541 is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License, version 3 (as published by the Free Software Foundation) with
+ * a static linking exception as stated in the LICENSE file provided with
+ * open62541.
+ *
+ * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ */
+
 #ifndef UA_TYPES_H_
 #define UA_TYPES_H_
 
@@ -72,23 +87,23 @@ typedef int16_t UA_Int16;
 
 /** @brief An integer value between 0 and 65 535. */
 typedef uint16_t UA_UInt16;
-#define UA_UINT16_MAX  65535
-#define UA_UINT16_MIN  0
+#define UA_UINT16_MAX 65535
+#define UA_UINT16_MIN 0
 
 /** @brief An integer value between -2 147 483 648 and 2 147 483 647. */
 typedef int32_t UA_Int32;
-#define UA_INT32_MAX  2147483647
-#define UA_INT32_MIN  −2147483648
+#define UA_INT32_MAX 2147483647
+#define UA_INT32_MIN −2147483648
 
 /** @brief An integer value between 0 and 429 4967 295. */
 typedef uint32_t UA_UInt32;
-#define UA_UINT32_MAX  4294967295;
-#define UA_UINT32_MIN  0;
+#define UA_UINT32_MAX 4294967295
+#define UA_UINT32_MIN 0
 
 /** @brief An integer value between -10 223 372 036 854 775 808 and 9 223 372 036 854 775 807 */
 typedef int64_t UA_Int64;
-#define UA_INT64_MAX  9223372036854775807
-#define UA_INT64_MIN  −9223372036854775808
+#define UA_INT64_MAX 9223372036854775807
+#define UA_INT64_MIN −9223372036854775808
 
 /** @brief An integer value between 0 and 18 446 744 073 709 551 615. */
 typedef uint64_t UA_UInt64;
@@ -103,8 +118,8 @@ typedef double UA_Double;
 
 /** @brief A sequence of Unicode characters. */
 typedef struct UA_String {
-	UA_Int32 length;
-	UA_Byte *data;
+    UA_Int32 length;
+    UA_Byte *data;
 } UA_String;
 
 /** @brief An instance in time. */
@@ -112,10 +127,10 @@ typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
 
 /** @brief A 16 byte value that can be used as a globally unique identifier. */
 typedef struct UA_Guid {
-	UA_UInt32 data1;
-	UA_UInt16 data2;
-	UA_UInt16 data3;
-	UA_Byte   data4[8];
+    UA_UInt32 data1;
+    UA_UInt16 data2;
+    UA_UInt16 data3;
+    UA_Byte   data4[8];
 } UA_Guid;
 
 /** @brief A sequence of octets. */
@@ -125,30 +140,28 @@ typedef struct UA_String UA_ByteString;
 typedef struct UA_String UA_XmlElement;
 
 /** @brief An identifier for a node in the address space of an OPC UA Server. */
+/* The shortened numeric types are introduced during encoding. */
 typedef struct UA_NodeId {
-	UA_UInt16 namespaceIndex;
-	enum {
-		/* The shortened numeric types are introduced during encoding.
-		   UA_NODEIDTYPE_TWOBYTE = 0,
-		   UA_NODEIDTYPE_FOURBYTE = 1, */
-		UA_NODEIDTYPE_NUMERIC = 2,
-		UA_NODEIDTYPE_STRING = 3,
-		UA_NODEIDTYPE_GUID = 4,
-		UA_NODEIDTYPE_BYTESTRING = 5
-	} identifierType;
-	union {
-		UA_UInt32     numeric;
-		UA_String     string;
-		UA_Guid       guid;
-		UA_ByteString byteString;
-	} identifier;
+    UA_UInt16 namespaceIndex;
+    enum {
+        UA_NODEIDTYPE_NUMERIC    = 2,
+        UA_NODEIDTYPE_STRING     = 3,
+        UA_NODEIDTYPE_GUID       = 4,
+        UA_NODEIDTYPE_BYTESTRING = 5
+    } identifierType;
+    union {
+        UA_UInt32     numeric;
+        UA_String     string;
+        UA_Guid       guid;
+        UA_ByteString byteString;
+    } identifier;
 } UA_NodeId;
 
 /** @brief A NodeId that allows the namespace URI to be specified instead of an index. */
 typedef struct UA_ExpandedNodeId {
-	UA_NodeId nodeId;
-	UA_String namespaceUri; // not encoded if length=-1
-	UA_UInt32 serverIndex; // not encoded if 0
+    UA_NodeId nodeId;
+    UA_String namespaceUri; // not encoded if length=-1
+    UA_UInt32 serverIndex;  // not encoded if 0
 } UA_ExpandedNodeId;
 
 /** @brief A numeric identifier for a error or condition that is associated with a value or an operation. */
@@ -156,26 +169,26 @@ typedef UA_UInt32 UA_StatusCode; // StatusCodes aren't an enum(=int) since 32 un
 
 /** @brief A name qualified by a namespace. */
 typedef struct UA_QualifiedName {
-	UA_UInt16 namespaceIndex;
-	UA_String name;
+    UA_UInt16 namespaceIndex;
+    UA_String name;
 } UA_QualifiedName;
 
 /** @brief Human readable text with an optional locale identifier. */
 typedef struct UA_LocalizedText {
-	UA_String locale;
-	UA_String text;
+    UA_String locale;
+    UA_String text;
 } UA_LocalizedText;
 
 /** @brief A structure that contains an application specific data type that may
     not be recognized by the receiver. */
 typedef struct UA_ExtensionObject {
-	UA_NodeId typeId;
-	enum {
-		UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED  = 0,
-		UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING = 1,
-		UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML        = 2
-	} encoding;
-	UA_ByteString body; // contains either the bytestring or a pointer to the memory-object
+    UA_NodeId typeId;
+    enum {
+        UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED  = 0,
+        UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING = 1,
+        UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISXML        = 2
+    } encoding;
+    UA_ByteString body; // contains either the bytestring or a pointer to the memory-object
 } UA_ExtensionObject;
 
 struct UA_VTable_Entry; // forwards declaration
@@ -186,60 +199,60 @@ typedef struct UA_VTable_Entry UA_VTable_Entry;
  * Variants store (arrays of) built-in types. If you want to store a more
  * complex (or self-defined) type, you have to use an UA_ExtensionObject.*/
 typedef struct UA_Variant {
-	UA_VTable_Entry *vt;          // internal entry into vTable
-	UA_Int32  arrayLength;        // total number of elements
-	void     *data;
-	UA_Int32  arrayDimensionsLength;
-	UA_Int32 *arrayDimensions;
+    UA_VTable_Entry *vt;          // internal entry into vTable
+    UA_Int32  arrayLength;        // total number of elements
+    void     *data;
+    UA_Int32  arrayDimensionsLength;
+    UA_Int32 *arrayDimensions;
 } UA_Variant;
 
 /* VariantBinaryEncoding - Part: 6, Chapter: 5.2.2.16, Page: 22 */
 enum UA_VARIANT_ENCODINGMASKTYPE_enum {
-	UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F,            // bits 0:5
-	UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS  = (0x01 << 6),     // bit 6
-	UA_VARIANT_ENCODINGMASKTYPE_ARRAY       = (0x01 << 7)      // bit 7
+    UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3F,            // bits 0:5
+    UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS  = (0x01 << 6),     // bit 6
+    UA_VARIANT_ENCODINGMASKTYPE_ARRAY       = (0x01 << 7)      // bit 7
 };
 
 /** @brief A data value with an associated status code and timestamps. */
 typedef struct UA_DataValue {
-	UA_Byte       encodingMask;
-	UA_Variant    value;
-	UA_StatusCode status;
-	UA_DateTime   sourceTimestamp;
-	UA_Int16      sourcePicoseconds;
-	UA_DateTime   serverTimestamp;
-	UA_Int16      serverPicoseconds;
+    UA_Byte       encodingMask;
+    UA_Variant    value;
+    UA_StatusCode status;
+    UA_DateTime   sourceTimestamp;
+    UA_Int16      sourcePicoseconds;
+    UA_DateTime   serverTimestamp;
+    UA_Int16      serverPicoseconds;
 } UA_DataValue;
 
 enum UA_DATAVALUE_ENCODINGMASKTYPE_enum {
-	UA_DATAVALUE_ENCODINGMASK_VARIANT           = 0x01,
-	UA_DATAVALUE_ENCODINGMASK_STATUSCODE        = 0x02,
-	UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP   = 0x04,
-	UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP   = 0x08,
-	UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS = 0x10,
-	UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS = 0x20
+    UA_DATAVALUE_ENCODINGMASK_VARIANT           = 0x01,
+    UA_DATAVALUE_ENCODINGMASK_STATUSCODE        = 0x02,
+    UA_DATAVALUE_ENCODINGMASK_SOURCETIMESTAMP   = 0x04,
+    UA_DATAVALUE_ENCODINGMASK_SERVERTIMESTAMP   = 0x08,
+    UA_DATAVALUE_ENCODINGMASK_SOURCEPICOSECONDS = 0x10,
+    UA_DATAVALUE_ENCODINGMASK_SERVERPICOSECONDS = 0x20
 };
 
 /** @brief A structure that contains detailed error and diagnostic information associated with a StatusCode. */
 typedef struct UA_DiagnosticInfo {
-	UA_Byte       encodingMask;     // Type of the Enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE
-	UA_Int32      symbolicId;
-	UA_Int32      namespaceUri;
-	UA_Int32      localizedText;
-	UA_Int32      locale;
-	UA_String     additionalInfo;
-	UA_StatusCode innerStatusCode;
-	struct UA_DiagnosticInfo *innerDiagnosticInfo;
+    UA_Byte       encodingMask;     // Type of the Enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE
+    UA_Int32      symbolicId;
+    UA_Int32      namespaceUri;
+    UA_Int32      localizedText;
+    UA_Int32      locale;
+    UA_String     additionalInfo;
+    UA_StatusCode innerStatusCode;
+    struct UA_DiagnosticInfo *innerDiagnosticInfo;
 } UA_DiagnosticInfo;
 
 enum UA_DIAGNOSTICINFO_ENCODINGMASKTYPE_enum {
-	UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID          = 0x01,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE           = 0x02,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT       = 0x04,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE              = 0x08,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO      = 0x10,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE     = 0x20,
-	UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
+    UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID          = 0x01,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE           = 0x02,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT       = 0x04,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_LOCALE              = 0x08,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO      = 0x10,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE     = 0x20,
+    UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO = 0x40
 };
 
 /** @brief Type use internally to denote an invalid datatype. */
@@ -250,13 +263,13 @@ typedef void UA_InvalidType;
 /*************/
 
 #ifdef DEBUG
-#define UA_TYPE_PROTOTYPES(TYPE)             \
-    UA_Int32 TYPE##_new(TYPE **p);           \
-    UA_Int32 TYPE##_init(TYPE * p);          \
-    UA_Int32 TYPE##_delete(TYPE * p);        \
-    UA_Int32 TYPE##_deleteMembers(TYPE * p); \
+#define UA_TYPE_PROTOTYPES(TYPE)                      \
+    UA_Int32 TYPE##_new(TYPE **p);                    \
+    UA_Int32 TYPE##_init(TYPE * p);                   \
+    UA_Int32 TYPE##_delete(TYPE * p);                 \
+    UA_Int32 TYPE##_deleteMembers(TYPE * p);          \
     UA_Int32 TYPE##_copy(const TYPE *src, TYPE *dst); \
-	void TYPE##_print(const TYPE *p, FILE *stream);
+    void     TYPE##_print(const TYPE *p, FILE *stream);
 #else
 #define UA_TYPE_PROTOTYPES(TYPE)             \
     UA_Int32 TYPE##_new(TYPE **p);           \
@@ -295,10 +308,10 @@ UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
 UA_TYPE_PROTOTYPES(UA_InvalidType)
 
 /* String */
-#define UA_STRING_NULL (UA_String){-1, UA_NULL}
+#define UA_STRING_NULL (UA_String) {-1, UA_NULL }
 #define UA_STRING_STATIC(VARIABLE, STRING) do { \
-	VARIABLE.length = sizeof(STRING)-1; \
-	VARIABLE.data = (UA_Byte*)STRING; } while (0)
+        VARIABLE.length = sizeof(STRING)-1;     \
+        VARIABLE.data   = (UA_Byte *)STRING; } while(0)
 
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst);
 UA_Int32 UA_String_copyprintf(char const *fmt, UA_String *dst, ...);
@@ -312,15 +325,15 @@ void UA_String_printx_hex(char const *label, const UA_String *string);
 /* DateTime */
 UA_DateTime UA_DateTime_now();
 typedef struct UA_DateTimeStruct {
-	UA_Int16 nanoSec;
-	UA_Int16 microSec;
-	UA_Int16 milliSec;
-	UA_Int16 sec;
-	UA_Int16 min;
-	UA_Int16 hour;
-	UA_Int16 day;
-	UA_Int16 mounth;
-	UA_Int16 year;
+    UA_Int16 nanoSec;
+    UA_Int16 microSec;
+    UA_Int16 milliSec;
+    UA_Int16 sec;
+    UA_Int16 min;
+    UA_Int16 hour;
+    UA_Int16 day;
+    UA_Int16 mounth;
+    UA_Int16 year;
 } UA_DateTimeStruct;
 UA_DateTimeStruct UA_DateTime_toStruct(UA_DateTime time);
 UA_Int32 UA_DateTime_toString(UA_DateTime time, UA_String *timeString);
@@ -342,29 +355,31 @@ UA_Int32 UA_NodeId_equal(const UA_NodeId *n1, const UA_NodeId *n2);
 UA_Boolean UA_NodeId_isNull(const UA_NodeId *p);
 UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id);
 
-#define NS0NODEID(NUMERIC_ID) \
-	(UA_NodeId){ .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = NUMERIC_ID }
+#define NS0NODEID(NUMERIC_ID)                                                                        \
+    (UA_NodeId) {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC, .identifier.numeric = \
+                     NUMERIC_ID }
 
 /* ExpandedNodeId */
 UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p);
 
-#define NS0EXPANDEDNODEID(VARIABLE, NUMERIC_ID) do { \
-	VARIABLE.nodeId = NS0NODEID(NUMERIC_ID); \
-	VARIABLE.namespaceUri = UA_STRING_NULL; \
-	VARIABLE.serverIndex = 0; } while(0)
+#define NS0EXPANDEDNODEID(VARIABLE, NUMERIC_ID) do {   \
+        VARIABLE.nodeId       = NS0NODEID(NUMERIC_ID); \
+        VARIABLE.namespaceUri = UA_STRING_NULL;        \
+        VARIABLE.serverIndex  = 0; } while(0)
 
 /* QualifiedName */
 #define UA_QUALIFIEDNAME_STATIC(VARIABLE, STRING) do { \
-	VARIABLE.namespaceIndex = 0; \
-	UA_STRING_STATIC(VARIABLE.name, STRING); } while (0)
+        VARIABLE.namespaceIndex = 0;                   \
+        UA_STRING_STATIC(VARIABLE.name, STRING); } while(0)
+UA_Int32 UA_QualifiedName_copycstring(char const *src, UA_QualifiedName *dst);
 #ifdef DEBUG
 void UA_QualifiedName_printf(char const *label, const UA_QualifiedName *qn);
 #endif
 
 /* LocalizedText */
 #define UA_LOCALIZEDTEXT_STATIC(VARIABLE, STRING) do { \
-	UA_STRING_STATIC(VARIABLE.locale, "en"); \
-	UA_STRING_STATIC(VARIABLE.text, STRING); } while (0)
+        UA_STRING_STATIC(VARIABLE.locale, "en");       \
+        UA_STRING_STATIC(VARIABLE.text, STRING); } while(0)
 
 UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 
@@ -372,13 +387,11 @@ UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 UA_Int32 UA_Variant_copySetValue(UA_Variant *v, UA_VTable_Entry *vt, const void *value);
 UA_Int32 UA_Variant_copySetArray(UA_Variant *v, UA_VTable_Entry *vt, UA_Int32 arrayLength, const void *array);
 
-/** @brief Functions UA_Variant_borrowSetValue and ..Array allow to define
-   variants whose payload will not be deleted. This is achieved by a second
-   vtable. The functionality can be used e.g. when UA_VariableNodes point into a
-   "father" structured object that is stored in an UA_VariableNode itself. */
+/** @brief Allows to define variants whose payload will not be deleted. This is
+   achieved by a second vtable. The functionality can be used e.g. when
+   UA_VariableNodes point into a "father" structured object that is stored in an
+   UA_VariableNode itself. This is not possible for arrays so far. */
 UA_Int32 UA_Variant_borrowSetValue(UA_Variant *v, UA_VTable_Entry *vt, const void *value);
-UA_Int32 UA_Variant_borrowSetArray(UA_Variant *v, UA_VTable_Entry *vt, UA_Int32 arrayLength,
-                                   const void *array);
 
 /* Array operations */
 UA_Int32 UA_Array_new(void **p, UA_Int32 noElements, UA_VTable_Entry *vt);
@@ -396,38 +409,38 @@ void UA_Array_print(const void *p, UA_Int32 noElements, UA_VTable_Entry *vt, FIL
 /**********/
 
 typedef struct UA_Encoding {
-	/**  Returns the size of the encoded element.*/
-	UA_Int32 (*calcSize)(const void *p);
-	/** Encodes the type into the destination bytestring. */
-	UA_Int32 (*encode)(const void *src, UA_ByteString *dst, UA_UInt32 *offset);
-	/** Decodes a ByteString into an UA datatype. */
-	UA_Int32 (*decode)(const UA_ByteString *src, UA_UInt32 *offset, void *dst);
+    /**  Returns the size of the encoded element.*/
+    UA_Int32 (*calcSize)(const void *p);
+    /** Encodes the type into the destination bytestring. */
+    UA_Int32 (*encode)(const void *src, UA_ByteString *dst, UA_UInt32 *offset);
+    /** Decodes a ByteString into an UA datatype. */
+    UA_Int32 (*decode)(const UA_ByteString *src, UA_UInt32 *offset, void *dst);
 } UA_Encoding;
 
 #define UA_ENCODING_BINARY 0 // Binary encoding is always available
 
 struct UA_VTable_Entry {
-	UA_NodeId  typeId;
-	UA_Byte   *name;
-	UA_Int32   (*new)(void **p);
-	UA_Int32   (*init)(void *p);
-	UA_Int32   (*copy)(void const *src, void *dst);
-	UA_Int32   (*delete)(void *p);
-	UA_Int32   (*deleteMembers)(void *p);
+    UA_NodeId  typeId;
+    UA_Byte   *name;
+    UA_Int32   (*new)(void **p);
+    UA_Int32   (*init)(void *p);
+    UA_Int32   (*copy)(void const *src, void *dst);
+    UA_Int32   (*delete)(void *p);
+    UA_Int32   (*deleteMembers)(void *p);
 #ifdef DEBUG
-	void       (*print)(const void *p, FILE *stream);
+    void       (*print)(const void *p, FILE *stream);
 #endif
-	UA_UInt32  memSize;       // size of the struct only in memory (no dynamic components)
-	UA_Boolean dynMembers;    // does the type contain members that are dynamically
-	                          // allocated (strings, ..)? Otherwise, the size on
-	                          // the wire == size in memory.
-	UA_Encoding encodings[UA_ENCODING_AMOUNT]; // binary, xml, ... UA_ENCODING_AMOUNT is set by the build script
+    UA_UInt32  memSize;                        // size of the struct only in memory (no dynamic components)
+    UA_Boolean dynMembers;                     // does the type contain members that are dynamically
+                                               // allocated (strings, ..)? Otherwise, the size on
+                                               // the wire == size in memory.
+    UA_Encoding encodings[UA_ENCODING_AMOUNT]; // binary, xml, ... UA_ENCODING_AMOUNT is set by the build script
 };
 
 typedef UA_Int32 (*UA_nodeIdToVTableIndex)(const UA_NodeId *id);
 typedef struct UA_VTable {
-	UA_nodeIdToVTableIndex getTypeIndex;
-	UA_VTable_Entry       *types;
+    UA_nodeIdToVTableIndex getTypeIndex;
+    UA_VTable_Entry       *types;
 } UA_VTable;
 
 /***********************************/
@@ -443,31 +456,31 @@ typedef struct UA_VTable {
 
 #define UA_TYPE_NEW_DEFAULT(TYPE)                     \
     UA_Int32 TYPE##_new(TYPE **p) {                   \
-		UA_Int32 retval = UA_SUCCESS;                 \
-		retval |= UA_alloc((void **)p, sizeof(TYPE)); \
-		retval |= TYPE##_init(*p);                    \
-		return retval;                                \
-	}
+        UA_Int32 retval = UA_SUCCESS;                 \
+        retval |= UA_alloc((void **)p, sizeof(TYPE)); \
+        retval |= TYPE##_init(*p);                    \
+        return retval;                                \
+    }
 
 #define UA_TYPE_INIT_DEFAULT(TYPE)         \
     UA_Int32 TYPE##_init(TYPE * p) {       \
-		if(p == UA_NULL) return UA_ERROR;  \
-		*p = (TYPE)0;                      \
-		return UA_SUCCESS;                 \
-	}
+        if(p == UA_NULL) return UA_ERROR;  \
+        *p = (TYPE)0;                      \
+        return UA_SUCCESS;                 \
+    }
 
 #define UA_TYPE_INIT_AS(TYPE, TYPE_AS)       \
     UA_Int32 TYPE##_init(TYPE * p) {         \
-		return TYPE_AS##_init((TYPE_AS *)p); \
-	}
+        return TYPE_AS##_init((TYPE_AS *)p); \
+    }
 
 #define UA_TYPE_DELETE_DEFAULT(TYPE)       \
     UA_Int32 TYPE##_delete(TYPE *p) {      \
-		UA_Int32 retval = UA_SUCCESS;      \
-		retval |= TYPE##_deleteMembers(p); \
-		retval |= UA_free(p);              \
-		return retval;                     \
-	}
+        UA_Int32 retval = UA_SUCCESS;      \
+        retval |= TYPE##_deleteMembers(p); \
+        retval |= UA_free(p);              \
+        return retval;                     \
+    }
 
 #define UA_TYPE_DELETE_AS(TYPE, TYPE_AS) \
     UA_Int32 TYPE##_delete(TYPE * p) { return TYPE_AS##_delete((TYPE_AS *)p); }
@@ -481,21 +494,21 @@ typedef struct UA_VTable {
 /* Use only when the type has no arrays. Otherwise, implement deep copy */
 #define UA_TYPE_COPY_DEFAULT(TYPE)                             \
     UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {         \
-		if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;  \
-{UA_Int32 retval = UA_SUCCESS;                          \
-	retval |= UA_memcpy(dst, src, sizeof(TYPE));           \
-	return retval;    }                                     \
-	}
+        if(src == UA_NULL || dst == UA_NULL) return UA_ERROR;  \
+        { UA_Int32 retval = UA_SUCCESS;                        \
+          retval |= UA_memcpy(dst, src, sizeof(TYPE));         \
+          return retval;    }                                  \
+    }
 
 #define UA_TYPE_COPY_AS(TYPE, TYPE_AS)                         \
     UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {         \
-		return TYPE_AS##_copy((TYPE_AS *)src, (TYPE_AS *)dst); \
-	}
+        return TYPE_AS##_copy((TYPE_AS *)src, (TYPE_AS *)dst); \
+    }
 
-#define UA_TYPE_PRINT_AS(TYPE, TYPE_AS)                        \
-    void TYPE##_print(TYPE const *p, FILE *stream) {		   \
-		TYPE_AS##_print((TYPE_AS *)p, stream);				   \
-	}														   \
+#define UA_TYPE_PRINT_AS(TYPE, TYPE_AS)              \
+    void TYPE##_print(TYPE const *p, FILE *stream) { \
+        TYPE_AS##_print((TYPE_AS *)p, stream);       \
+    }                                                \
 
 #ifdef DEBUG //print functions only in debug mode
 #define UA_TYPE_AS(TYPE, TYPE_AS)           \
@@ -503,8 +516,8 @@ typedef struct UA_VTable {
     UA_TYPE_INIT_AS(TYPE, TYPE_AS)          \
     UA_TYPE_DELETE_AS(TYPE, TYPE_AS)        \
     UA_TYPE_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-    UA_TYPE_COPY_AS(TYPE, TYPE_AS)			\
-	UA_TYPE_PRINT_AS(TYPE, TYPE_AS)
+    UA_TYPE_COPY_AS(TYPE, TYPE_AS)          \
+    UA_TYPE_PRINT_AS(TYPE, TYPE_AS)
 #else
 #define UA_TYPE_AS(TYPE, TYPE_AS)           \
     UA_TYPE_NEW_DEFAULT(TYPE)               \

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 751 - 715
src/ua_types_encoding_binary.c


+ 16 - 14
src/ua_types_encoding_binary.h

@@ -1,7 +1,6 @@
 #ifndef UA_TYPES_ENCODING_BINARY_H_
 #define UA_TYPES_ENCODING_BINARY_H_
 
-#include "util/ua_util.h"
 #include "ua_types.h"
 
 /**
@@ -35,26 +34,26 @@
 /* Stop decoding at the first failure. Free members that were already allocated.
    It is assumed that retval is already defined. */
 #define CHECKED_DECODE(DECODE, CLEAN_UP) do { \
-		retval |= DECODE;                     \
-		if(retval != UA_SUCCESS) {            \
-			CLEAN_UP;                         \
-			return retval;                    \
-		} } while(0)
+        retval |= DECODE;                     \
+        if(retval != UA_SUCCESS) {            \
+            CLEAN_UP;                         \
+            return retval;                    \
+        } } while(0)
 
 #define UA_TYPE_CALCSIZEBINARY_AS(TYPE, TYPE_AS)       \
     UA_Int32 TYPE##_calcSizeBinary(TYPE const *p) {    \
-		return TYPE_AS##_calcSizeBinary((TYPE_AS *)p); \
-	}
+        return TYPE_AS##_calcSizeBinary((TYPE_AS *)p); \
+    }
 
 #define UA_TYPE_ENCODEBINARY_AS(TYPE, TYPE_AS)                                             \
     UA_Int32 TYPE##_encodeBinary(TYPE const *src, UA_ByteString *dst, UA_UInt32 *offset) { \
-		return TYPE_AS##_encodeBinary((TYPE_AS *)src, dst, offset);                        \
-	}
+        return TYPE_AS##_encodeBinary((TYPE_AS *)src, dst, offset);                        \
+    }
 
 #define UA_TYPE_DECODEBINARY_AS(TYPE, TYPE_AS)                                             \
     UA_Int32 TYPE##_decodeBinary(UA_ByteString const *src, UA_UInt32 *offset, TYPE *dst) { \
-		return TYPE_AS##_decodeBinary(src, offset, (TYPE_AS *)dst);                        \
-	}
+        return TYPE_AS##_decodeBinary(src, offset, (TYPE_AS *)dst);                        \
+    }
 #define UA_TYPE_BINARY_ENCODING_AS(TYPE, TYPE_AS) \
     UA_TYPE_CALCSIZEBINARY_AS(TYPE, TYPE_AS)      \
     UA_TYPE_ENCODEBINARY_AS(TYPE, TYPE_AS)        \
@@ -102,10 +101,13 @@ UA_TYPE_BINARY_ENCODING(UA_InvalidType)
 UA_Int32 UA_Array_calcSizeBinary(UA_Int32 nElements, UA_VTable_Entry *vt, const void *data);
 
 /* @brief Encodes an array into a binary blob. The array size is printed as well. */
-UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, UA_ByteString *dst, UA_UInt32 *offset);
+UA_Int32 UA_Array_encodeBinary(const void *src, UA_Int32 noElements, UA_VTable_Entry *vt, UA_ByteString *dst,
+                               UA_UInt32 *offset);
 
 /* @brief Decodes an array from a binary blob. The array is allocated automatically before decoding. */
-UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 * offset, UA_Int32 noElements, UA_VTable_Entry *vt, void **dst);
+UA_Int32 UA_Array_decodeBinary(const UA_ByteString *src, UA_UInt32 *offset, UA_Int32 noElements,
+                               UA_VTable_Entry *vt,
+                               void **dst);
 
 /// @} /* end of group */
 

+ 113 - 117
src/util/ua_base64.c

@@ -1,153 +1,149 @@
 /*
-begin library headers
-*/
+   begin library headers
+ */
 
 /*
-cdecode.h - c header for a base64 decoding algorithm
+   cdecode.h - c header for a base64 decoding algorithm
 
-This is part of the libb64 project, and has been placed in the public domain.
-For details, see http://sourceforge.net/projects/libb64
-*/
+   This is part of the libb64 project, and has been placed in the public domain.
+   For details, see http://sourceforge.net/projects/libb64
+ */
 #ifndef BASE64_CDECODE_H
 #define BASE64_CDECODE_H
 
-typedef enum
-{
-	step_a, step_b, step_c, step_d
+typedef enum {
+    step_a, step_b, step_c, step_d
 } base64_decodestep;
 
-typedef struct
-{
-	base64_decodestep step;
-	char plainchar;
+typedef struct {
+    base64_decodestep step;
+    char plainchar;
 } base64_decodestate;
 
-void base64_init_decodestate(base64_decodestate* state_in);
+void base64_init_decodestate(base64_decodestate *state_in);
 
 int base64_decode_value(char value_in);
 
-int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
+int base64_decode_block(const char *code_in, const int length_in, char *plaintext_out,
+                        base64_decodestate *state_in);
 
 #endif /* BASE64_CDECODE_H */
 
 /*
-end library headers
-*/
+   end library headers
+ */
 
 #include "ua_base64.h"
 
-UA_Int32 UA_base64_getDecodedSize(UA_String* const base64EncodedData){
-	//note that base64-encoded data length is always divisible by 4
-	UA_Int32 temp = base64EncodedData->length * 3 / 4;
+UA_Int32 UA_base64_getDecodedSize(UA_String *const base64EncodedData) {
+    //note that base64-encoded data length is always divisible by 4
+    UA_Int32 temp = base64EncodedData->length * 3 / 4;
 
-	//subtract padding
-	if(base64EncodedData->data[base64EncodedData->length-1] == '=') {
-		temp--;
-		if(base64EncodedData->data[base64EncodedData->length-2] == '=') {
-			temp--;
-		}
-	}
+    //subtract padding
+    if(base64EncodedData->data[base64EncodedData->length-1] == '=') {
+        temp--;
+        if(base64EncodedData->data[base64EncodedData->length-2] == '=')
+            temp--;
+    }
 
-	return temp;
+    return temp;
 }
 
-UA_Int32 UA_base64_decode(UA_String* const base64EncodedData, UA_Byte* target){
-	if(target == UA_NULL){
-		return UA_ERROR;
-	}
-	base64_decodestate state;
-	base64_init_decodestate(&state);
-	base64_decode_block((char*)(base64EncodedData->data), base64EncodedData->length, (char*)target, &state);
-	return UA_NO_ERROR;
+UA_Int32 UA_base64_decode(UA_String *const base64EncodedData, UA_Byte *target) {
+    if(target == UA_NULL)
+        return UA_ERROR;
+    base64_decodestate state;
+    base64_init_decodestate(&state);
+    base64_decode_block((char *)(base64EncodedData->data), base64EncodedData->length, (char *)target, &state);
+    return UA_NO_ERROR;
 }
 
 /*
-begin library code
-*/
+   begin library code
+ */
 
 /*
-cdecoder.c - c source to a base64 decoding algorithm implementation
-
-This is part of the libb64 project, and has been placed in the public domain.
-For details, see http://sourceforge.net/projects/libb64
-*/
-
-int base64_decode_value(char value_in)
-{
-	static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51};
-	static const char decoding_size = sizeof(decoding);
-	value_in -= 43;
-	if (value_in > decoding_size) return -1;
-	return decoding[(int)value_in];
+   cdecoder.c - c source to a base64 decoding algorithm implementation
+
+   This is part of the libb64 project, and has been placed in the public domain.
+   For details, see http://sourceforge.net/projects/libb64
+ */
+
+int base64_decode_value(char value_in) {
+    static const char decoding[]    =
+    { 62, -1,   -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0,  1,  2,  3,
+      4,  5,
+      6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
+      27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
+    static const char decoding_size = sizeof(decoding);
+    value_in -= 43;
+    if(value_in > decoding_size) return -1;
+    return decoding[(int)value_in];
 }
 
-void base64_init_decodestate(base64_decodestate* state_in)
-{
-	state_in->step = step_a;
-	state_in->plainchar = 0;
+void base64_init_decodestate(base64_decodestate *state_in) {
+    state_in->step      = step_a;
+    state_in->plainchar = 0;
 }
 
-int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in)
-{
-	const char* codechar = code_in;
-	char* plainchar = plaintext_out;
-	signed char fragment;
-	
-	*plainchar = state_in->plainchar;
-	
-	switch (state_in->step)
-	{
-		while (1)
-		{
-	case step_a:
-			do {
-				if (codechar == code_in+length_in)
-				{
-					state_in->step = step_a;
-					state_in->plainchar = *plainchar;
-					return plainchar - plaintext_out;
-				}
-				fragment = (char)base64_decode_value(*codechar++);
-			} while (fragment < 0);
-			*plainchar    = (fragment & 0x03f) << 2;
-	case step_b:
-			do {
-				if (codechar == code_in+length_in)
-				{
-					state_in->step = step_b;
-					state_in->plainchar = *plainchar;
-					return plainchar - plaintext_out;
-				}
-				fragment = (char)base64_decode_value(*codechar++);
-			} while (fragment < 0);
-			*plainchar++ |= (fragment & 0x030) >> 4;
-			*plainchar    = (fragment & 0x00f) << 4;
-	case step_c:
-			do {
-				if (codechar == code_in+length_in)
-				{
-					state_in->step = step_c;
-					state_in->plainchar = *plainchar;
-					return plainchar - plaintext_out;
-				}
-				fragment = (char)base64_decode_value(*codechar++);
-			} while (fragment < 0);
-			*plainchar++ |= (fragment & 0x03c) >> 2;
-			*plainchar    = (fragment & 0x003) << 6;
-	case step_d:
-			do {
-				if (codechar == code_in+length_in)
-				{
-					state_in->step = step_d;
-					state_in->plainchar = *plainchar;
-					return plainchar - plaintext_out;
-				}
-				fragment = (char)base64_decode_value(*codechar++);
-			} while (fragment < 0);
-			*plainchar++   |= (fragment & 0x03f);
-		}
-	}
-	/* control should not reach here */
-	return plainchar - plaintext_out;
+int base64_decode_block(const char *code_in, const int length_in, char *plaintext_out,
+                        base64_decodestate *state_in) {
+    const char *codechar  = code_in;
+    char       *plainchar = plaintext_out;
+    signed char fragment;
+
+    *plainchar = state_in->plainchar;
+
+    switch(state_in->step) {
+        while(1) {
+        case step_a:
+            do {
+                if(codechar == code_in+length_in) {
+                    state_in->step      = step_a;
+                    state_in->plainchar = *plainchar;
+                    return plainchar - plaintext_out;
+                }
+                fragment = (char)base64_decode_value(*codechar++);
+            } while(fragment < 0);
+            *plainchar = (fragment & 0x03f) << 2;
+
+        case step_b:
+            do {
+                if(codechar == code_in+length_in) {
+                    state_in->step      = step_b;
+                    state_in->plainchar = *plainchar;
+                    return plainchar - plaintext_out;
+                }
+                fragment = (char)base64_decode_value(*codechar++);
+            } while(fragment < 0);
+            *plainchar++ |= (fragment & 0x030) >> 4;
+            *plainchar    = (fragment & 0x00f) << 4;
+
+        case step_c:
+            do {
+                if(codechar == code_in+length_in) {
+                    state_in->step      = step_c;
+                    state_in->plainchar = *plainchar;
+                    return plainchar - plaintext_out;
+                }
+                fragment = (char)base64_decode_value(*codechar++);
+            } while(fragment < 0);
+            *plainchar++ |= (fragment & 0x03c) >> 2;
+            *plainchar    = (fragment & 0x003) << 6;
+
+        case step_d:
+            do {
+                if(codechar == code_in+length_in) {
+                    state_in->step      = step_d;
+                    state_in->plainchar = *plainchar;
+                    return plainchar - plaintext_out;
+                }
+                fragment = (char)base64_decode_value(*codechar++);
+            } while(fragment < 0);
+            *plainchar++ |= (fragment & 0x03f);
+        }
+    }
+    /* control should not reach here */
+    return plainchar - plaintext_out;
 }
 

+ 2 - 2
src/util/ua_base64.h

@@ -12,9 +12,9 @@
 #include "ua_util.h"
 
 /** @brief calculates the exact size for the binary data that is encoded in base64 encoded string */
-UA_Int32 UA_base64_getDecodedSize(UA_String* const base64EncodedData);
+UA_Int32 UA_base64_getDecodedSize(UA_String *const base64EncodedData);
 
 /** @brief decodes base64 encoded string into target, target should be at least of the size returned by UA_base64_getDecodedSizeUB */
-UA_Int32 UA_base64_decode(UA_String* const base64EncodedData, UA_Byte* target);
+UA_Int32 UA_base64_decode(UA_String *const base64EncodedData, UA_Byte *target);
 
 #endif /* UA_BASE64_H_ */

+ 0 - 126
src/util/ua_indexedList.c

@@ -1,126 +0,0 @@
-#include "ua_indexedList.h"
-#include "ua_util.h"
-
-void UA_indexedList_defaultFreer(void* payload){
-	UA_list_defaultFreer(payload);
-}
-
-UA_Int32 UA_indexedList_init(UA_indexedList_List* list){
-	if(list==UA_NULL)return UA_ERROR;
-	return UA_list_init((UA_list_List*)list);
-}
-
-UA_Int32 UA_indexedList_destroy(UA_indexedList_List* list, UA_indexedList_PayloadVisitor visitor) {
-	UA_list_Element* current = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	current=list->first;
-	while(current){
-		UA_list_Element* next = current->next;
-		UA_indexedList_Element* elem = (UA_indexedList_Element*)current->payload;
-		if(visitor){
-			(*visitor)(elem->payload);
-		}
-		if(elem){
-			UA_free(elem);
-		}
-		UA_free(current);
-		current = next;
-	}
-	UA_list_init(list);
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_indexedList_initElement(UA_indexedList_Element* elem){
-	if(elem==UA_NULL)return UA_ERROR;
-	elem->father = UA_NULL;
-	elem->index = -1;
-	elem->payload = UA_NULL;
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_indexedList_addValue(UA_indexedList_List* list, UA_Int32 index, void* payload){
-	UA_list_Element* dllElem;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	UA_alloc((void**)&dllElem, sizeof(UA_list_Element));
-	UA_list_initElement(dllElem);
-	UA_indexedList_Element* iilElem;
-	UA_alloc((void**)&iilElem, sizeof(UA_indexedList_Element));
-	UA_indexedList_initElement(iilElem);
-	iilElem->index = index;
-	iilElem->father = dllElem;
-	iilElem->payload = payload;
-	dllElem->payload = iilElem;
-	return UA_list_addElementToBack((UA_list_List*)list, dllElem);
-}
-
-UA_Int32 UA_indexedList_addValueToFront(UA_indexedList_List* list, UA_Int32 index, void* payload) {
-	UA_list_Element* dllElem;
-	UA_indexedList_Element* iilElem;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	UA_alloc((void**)&dllElem, sizeof(UA_list_Element));
-	UA_list_initElement(dllElem);
-	UA_alloc((void**)&iilElem, sizeof(UA_indexedList_Element));
-	UA_indexedList_initElement(iilElem);
-	iilElem->index = index;
-	iilElem->father = dllElem;
-	iilElem->payload = payload;
-	dllElem->payload = iilElem;
-	return UA_list_addElementToFront((UA_list_List*)list, dllElem);
-}
-
-UA_indexedList_Element* UA_indexedList_find(UA_indexedList_List* const list, UA_Int32 index) {
-	UA_list_Element* current;
-	if(list==UA_NULL)
-		return UA_NULL;
-	current = list->first;
-	while(current){
-		if(current->payload){
-			UA_indexedList_Element* elem = (UA_indexedList_Element*)current->payload;
-			if(elem->index == index){
-				return elem;
-			}
-		}
-		current=current->next;
-	}
-	return UA_NULL;
-}
-
-void* UA_indexedList_findValue(UA_indexedList_List* const list, UA_Int32 index) {
-	UA_indexedList_Element* iilElem;
-	if(list==UA_NULL)return UA_NULL;
-	iilElem = UA_indexedList_find(list, index);
-	if(iilElem){
-		return iilElem->payload;
-	}
-	return UA_NULL;
-}
-
-UA_Int32 UA_indexedList_iterateValues(UA_indexedList_List* const list, UA_indexedList_PayloadVisitor visitor) {
-	UA_list_Element* current;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	current = list->first;
-	while(current){
-		if(current->payload){
-			UA_indexedList_Element* elem = (UA_indexedList_Element*)current->payload;
-			if(visitor){
-				(*visitor)(elem->payload);
-			}
-		}
-		current=current->next;
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_indexedList_removeElement(UA_indexedList_List* list, UA_indexedList_Element* elem, UA_indexedList_PayloadVisitor visitor){
-	if(list==UA_NULL || elem==UA_NULL)return UA_ERROR;
-	if(visitor){
-		(*visitor)(elem->payload);
-	}
-	UA_list_Element* father = elem->father;
-	UA_free(elem);
-	return UA_list_removeElement(father, UA_NULL);
-}

+ 0 - 40
src/util/ua_indexedList.h

@@ -1,40 +0,0 @@
-#ifndef UA_INDEXEDLIST_H_
-#define UA_INDEXEDLIST_H_
-
-#include "ua_types.h"
-/* UA_indexedList reuses many types of UA_list */
-#include "ua_list.h"
-
-/*
- * Integer Indexed List
- */
-typedef struct UA_indexedList_Element {
-	struct UA_list_Element* father;
-	UA_Int32 index;
-	void* payload;
-}UA_indexedList_Element;
-
-typedef UA_list_List UA_indexedList_List;
-typedef UA_list_PayloadVisitor UA_indexedList_PayloadVisitor;
-
-void UA_indexedList_defaultFreer(void* payload);
-
-UA_Int32 UA_indexedList_init(UA_indexedList_List* list);
-
-UA_Int32 UA_indexedList_destroy(UA_indexedList_List* list, UA_indexedList_PayloadVisitor visitor);
-
-UA_Int32 UA_indexedList_initElement(UA_indexedList_Element* elem);
-
-UA_Int32 UA_indexedList_addValue(UA_indexedList_List* list, UA_Int32 index, void* payload);
-
-UA_Int32 UA_indexedList_addValueToFront(UA_indexedList_List* list, UA_Int32 index, void* payload);
-
-UA_indexedList_Element* UA_indexedList_find(UA_indexedList_List* const list, UA_Int32 index);
-
-void* UA_indexedList_findValue(UA_indexedList_List* const list, UA_Int32 index);
-
-UA_Int32 UA_indexedList_iterateValues(UA_indexedList_List* const list, UA_indexedList_PayloadVisitor visitor);
-
-UA_Int32 UA_indexedList_removeElement(UA_indexedList_List* list, UA_indexedList_Element* elem, UA_indexedList_PayloadVisitor visitor);
-
-#endif /* UA_INDEXEDLIST_H_ */

+ 228 - 245
src/util/ua_list.c

@@ -1,253 +1,236 @@
 #include "ua_list.h"
 #include "ua_util.h"
 
-void UA_list_defaultFreer(void* payload){
-	if(payload){
-		UA_free(payload);
-	}
-}
-
-UA_Int32 UA_list_initElement(UA_list_Element* element){
-	if(element==UA_NULL) return UA_ERROR;
-	element->next=UA_NULL;
-	element->prev=UA_NULL;
-	element->father=UA_NULL;
-	element->payload=UA_NULL;
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_init(UA_list_List* list){
-	if(list==UA_NULL) return UA_ERROR;
-	list->first = UA_NULL;
-	list->last = UA_NULL;
-	list->size = 0;
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_addElementToFront(UA_list_List* list, UA_list_Element* element){
-	UA_list_Element* second = UA_NULL;
-	if(list==UA_NULL || element==UA_NULL) return UA_ERROR;
-	second = list->first;
-	list->first = element;
-	element->prev = UA_NULL;
-	element->next = second;
-	element->father = list;
-	if(second){
-		second->prev=element;
-	}
-	list->size++;
-	if(list->size==1){
-		list->last=element;
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_addPayloadToFront(UA_list_List* list, void* const payload) {
-	UA_list_Element* elem;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	UA_alloc((void**)&elem, sizeof(*elem));
-	UA_list_initElement(elem);
-	elem->payload = payload;
-	UA_list_addElementToFront(list, elem);
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_addElementToBack(UA_list_List* list, UA_list_Element* element) {
-	UA_list_Element* secondLast = UA_NULL;
-	if(list==UA_NULL || element == UA_NULL)
-		return UA_ERROR;
-	secondLast = list->last;
-	list->last = element;
-	element->prev = secondLast;
-	element->next = UA_NULL;
-	element->father = list;
-	if(secondLast){
-		secondLast->next = element;
-	}
-	list->size++;
-	if(list->size==1){
-		list->first=element;
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_addPayloadToBack(UA_list_List* list, void* const payload) {
-	UA_list_Element* elem;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	UA_alloc((void**)&elem, sizeof(*elem));
-	UA_list_initElement(elem);
-	elem->payload = payload;
-	UA_list_addElementToBack(list, elem);
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_removeFirst(UA_list_List* list, UA_list_PayloadVisitor visitor) {
-	UA_list_Element* temp = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	if(list->first){
-		temp = list->first->next;
-		if(visitor){
-			(*visitor)(list->first->payload);
-		}
-		UA_free(list->first);
-		list->first = temp;
-		if(temp){
-			temp->prev = UA_NULL;
-		}
-		list->size--;
-		if(list->size == 1){
-			list->last = temp;
-		}else if(list->size==0){
-			list->last = UA_NULL;
-		}
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_removeLast(UA_list_List* list, UA_list_PayloadVisitor visitor) {
-	UA_list_Element* temp = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	if(list->last){
-		temp = list->last->prev;
-		if(visitor){
-			(*visitor)(list->last->payload);
-		}
-		UA_free(list->last);
-		list->last = temp;
-		if(temp){
-			temp->next = UA_NULL;
-		}
-		list->size--;
-		if(list->size == 1){
-			list->first = temp;
-		}else if(list->size==0){
-			list->first = UA_NULL;
-		}
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_removeElement(UA_list_Element* const elem, UA_list_PayloadVisitor visitor) {
-	if(elem==UA_NULL)
-		return UA_ERROR;
-	if(elem==elem->father->first){
-		return UA_list_removeFirst(elem->father, visitor);
-	}else if(elem==elem->father->last){
-		return UA_list_removeLast(elem->father, visitor);
-	}else{
-		UA_list_Element* prev = elem->prev;
-		UA_list_Element* next = elem->next;
-		prev->next = next;
-		next->prev = prev;
-		if(visitor){
-			(*visitor)(elem->payload);
-		}
-		(elem->father)->size--;
-		UA_free(elem);
-	}
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_destroy(UA_list_List* list, UA_list_PayloadVisitor visitor) {
-	UA_list_Element* current = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	current=list->first;
-	while(current){
-		UA_list_Element* next = current->next;
-		if(visitor){
-			(*visitor)(current->payload);
-		}
-		UA_free(current);
-		current = next;
-	}
-	UA_list_init(list);
-	return UA_NO_ERROR;
-}
-
-UA_Int32 UA_list_iterateElement(UA_list_List* const list, UA_list_ElementVisitor visitor) {
-	UA_list_Element* current;
-	UA_list_Element* next = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	current = list->first;
-	while(current){
-		next=current->next;
-		if(visitor){
-			(*visitor)(current);
-		}
-		current = next;
-	}
-	return UA_NO_ERROR;
+void UA_list_defaultFreer(void *payload) {
+    if(payload)
+        UA_free(payload);
+}
+
+UA_Int32 UA_list_initElement(UA_list_Element *element) {
+    if(element == UA_NULL) return UA_ERROR;
+    element->next    = UA_NULL;
+    element->prev    = UA_NULL;
+    element->father  = UA_NULL;
+    element->payload = UA_NULL;
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_init(UA_list_List *list) {
+    if(list == UA_NULL) return UA_ERROR;
+    list->first = UA_NULL;
+    list->last  = UA_NULL;
+    list->size  = 0;
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_addElementToFront(UA_list_List *list, UA_list_Element *element) {
+    UA_list_Element *second = UA_NULL;
+    if(list == UA_NULL || element == UA_NULL) return UA_ERROR;
+    second          = list->first;
+    list->first     = element;
+    element->prev   = UA_NULL;
+    element->next   = second;
+    element->father = list;
+    if(second)
+        second->prev = element;
+    list->size++;
+    if(list->size == 1)
+        list->last = element;
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_addPayloadToFront(UA_list_List *list, void *const payload) {
+    UA_list_Element *elem;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    UA_alloc((void **)&elem, sizeof(*elem));
+    UA_list_initElement(elem);
+    elem->payload = payload;
+    UA_list_addElementToFront(list, elem);
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_addElementToBack(UA_list_List *list, UA_list_Element *element) {
+    UA_list_Element *secondLast = UA_NULL;
+    if(list == UA_NULL || element == UA_NULL)
+        return UA_ERROR;
+    secondLast      = list->last;
+    list->last      = element;
+    element->prev   = secondLast;
+    element->next   = UA_NULL;
+    element->father = list;
+    if(secondLast)
+        secondLast->next = element;
+    list->size++;
+    if(list->size == 1)
+        list->first = element;
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_addPayloadToBack(UA_list_List *list, void *const payload) {
+    UA_list_Element *elem;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    UA_alloc((void **)&elem, sizeof(*elem));
+    UA_list_initElement(elem);
+    elem->payload = payload;
+    UA_list_addElementToBack(list, elem);
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_removeFirst(UA_list_List *list, UA_list_PayloadVisitor visitor) {
+    UA_list_Element *temp = UA_NULL;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    if(list->first) {
+        temp = list->first->next;
+        if(visitor)
+            (*visitor)(list->first->payload);
+        UA_free(list->first);
+        list->first = temp;
+        if(temp)
+            temp->prev = UA_NULL;
+        list->size--;
+        if(list->size == 1)
+            list->last = temp;
+        else if(list->size == 0)
+            list->last = UA_NULL;
+    }
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_removeLast(UA_list_List *list, UA_list_PayloadVisitor visitor) {
+    UA_list_Element *temp = UA_NULL;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    if(list->last) {
+        temp = list->last->prev;
+        if(visitor)
+            (*visitor)(list->last->payload);
+        UA_free(list->last);
+        list->last = temp;
+        if(temp)
+            temp->next = UA_NULL;
+        list->size--;
+        if(list->size == 1)
+            list->first = temp;
+        else if(list->size == 0)
+            list->first = UA_NULL;
+    }
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_removeElement(UA_list_Element *const elem, UA_list_PayloadVisitor visitor) {
+    if(elem == UA_NULL)
+        return UA_ERROR;
+    if(elem == elem->father->first)
+        return UA_list_removeFirst(elem->father, visitor);
+    else if(elem == elem->father->last)
+        return UA_list_removeLast(elem->father, visitor);
+    else{
+        UA_list_Element *prev = elem->prev;
+        UA_list_Element *next = elem->next;
+        prev->next = next;
+        next->prev = prev;
+        if(visitor)
+            (*visitor)(elem->payload);
+        (elem->father)->size--;
+        UA_free(elem);
+    }
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_destroy(UA_list_List *list, UA_list_PayloadVisitor visitor) {
+    UA_list_Element *current = UA_NULL;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    current = list->first;
+    while(current) {
+        UA_list_Element *next = current->next;
+        if(visitor)
+            (*visitor)(current->payload);
+        UA_free(current);
+        current = next;
+    }
+    UA_list_init(list);
+    return UA_NO_ERROR;
+}
+
+UA_Int32 UA_list_iterateElement(UA_list_List *const list, UA_list_ElementVisitor visitor) {
+    UA_list_Element *current;
+    UA_list_Element *next = UA_NULL;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    current = list->first;
+    while(current) {
+        next = current->next;
+        if(visitor)
+            (*visitor)(current);
+        current = next;
+    }
+    return UA_NO_ERROR;
 }
 
 /*Int32 UA_list_iteratePayload(UA_list_list* const list, UA_payloadVisitor visitor){
-	void visitorTemp(UA_list_element* element){
-		if(visitor){
-			(*visitor)(element->payload);
-		}
-	}
-	if(list==NULL)return UA_ERROR;
-	UA_list_iterateElement(list, visitorTemp);
-	return UA_NO_ERROR;
-}*/
+    void visitorTemp(UA_list_element* element){
+        if(visitor){
+            (*visitor)(element->payload);
+        }
+    }
+    if(list==NULL)return UA_ERROR;
+    UA_list_iterateElement(list, visitorTemp);
+    return UA_NO_ERROR;
+   }*/
 /** ANSI C forbids function nesting - reworked ugly version **/
-UA_Int32 UA_list_iteratePayload(UA_list_List* const list, UA_list_PayloadVisitor visitor){
-	UA_list_Element* current;
-	UA_list_Element* next = UA_NULL;
-	if(list==UA_NULL)
-		return UA_ERROR;
-	current = list->first;
-	while(current){
-		next = current->next;
-		if(visitor){
-			(*visitor)(current->payload);
-		}
-		current = next;
-	}
-	return UA_NO_ERROR;
-}
-
-UA_list_Element* UA_list_find(UA_list_List* const list, UA_list_PayloadMatcher matcher){
-	if(list==UA_NULL)return UA_NULL;
-	if(matcher){
-		UA_list_Element* current = list->first;
-		while(current){
-			if(matcher && (*matcher)(current->payload)==TRUE){
-				return current;
-			}
-			current=current->next;
-		}
-	}
-	/* nothing found */
-	return UA_NULL;
-}
-
-UA_list_Element* UA_list_search(UA_list_List* const list, UA_list_PayloadComparer compare, void* payload){
-	if(list==UA_NULL)return UA_NULL;
-	if(compare){
-		UA_list_Element* current = list->first;
-		while(current){
-			if(compare && (*compare)(current->payload, payload)==TRUE){
-				return current;
-			}
-			current=current->next;
-		}
-	}
-	/* nothing found */
-	return UA_NULL;
-}
-
-UA_list_Element* UA_list_getFirst(UA_list_List* const list){
-	if(list==UA_NULL)return UA_NULL;
-	return list->first;
-}
-
-UA_list_Element* UA_list_getLast(UA_list_List* const list){
-	if(list==UA_NULL)return UA_NULL;
-	return list->last;
+UA_Int32 UA_list_iteratePayload(UA_list_List *const list, UA_list_PayloadVisitor visitor) {
+    UA_list_Element *current;
+    UA_list_Element *next = UA_NULL;
+    if(list == UA_NULL)
+        return UA_ERROR;
+    current = list->first;
+    while(current) {
+        next = current->next;
+        if(visitor)
+            (*visitor)(current->payload);
+        current = next;
+    }
+    return UA_NO_ERROR;
+}
+
+UA_list_Element *UA_list_find(UA_list_List *const list, UA_list_PayloadMatcher matcher) {
+    if(list == UA_NULL) return UA_NULL;
+    if(matcher) {
+        UA_list_Element *current = list->first;
+        while(current) {
+            if(matcher && (*matcher)(current->payload) == TRUE)
+                return current;
+            current = current->next;
+        }
+    }
+    /* nothing found */
+    return UA_NULL;
+}
+
+UA_list_Element *UA_list_search(UA_list_List *const list, UA_list_PayloadComparer compare, void *payload) {
+    if(list == UA_NULL) return UA_NULL;
+    if(compare) {
+        UA_list_Element *current = list->first;
+        while(current) {
+            if(compare && (*compare)(current->payload, payload) == TRUE)
+                return current;
+            current = current->next;
+        }
+    }
+    /* nothing found */
+    return UA_NULL;
+}
+
+UA_list_Element *UA_list_getFirst(UA_list_List *const list) {
+    if(list == UA_NULL) return UA_NULL;
+    return list->first;
+}
+
+UA_list_Element *UA_list_getLast(UA_list_List *const list) {
+    if(list == UA_NULL) return UA_NULL;
+    return list->last;
 }

+ 28 - 51
src/util/ua_list.h

@@ -2,87 +2,64 @@
 #define UA_LIST_H_
 
 #include "ua_types.h"
-#include <stddef.h> /* Needed for sys/queue.h */
-#ifndef MSVC
-#include <sys/queue.h>
-#else
-#include "queue.h"
-#endif
-
-/**********************/
-/* Singly Linked List */
-/**********************/
-
-#define UA_SLIST_HEAD(name, type) SLIST_HEAD(name, type)
-#define UA_SLIST_HEAD_INITIALIZER(head) SLIST_HEAD_INITILIZER(head)
-#define UA_SLIST_ENTRY(type) SLIST_ENTRY(type)
-#define UA_SLIST_INIT(head) SLIST_INIT(head)
-#define UA_SLIST_INSERT_AFTER(slistelm, elm, field) SLIST_INSERT_AFTER(slistelm, elm, field)
-#define UA_SLIST_INSERT_HEAD(head, elm, field) SLIST_INSERT_HEAD(head, elm, field)
-#define UA_SLIST_REMOVE_HEAD(head, field) SLIST_REMOVE_HEAD(head, field)
-#define UA_SLIST_REMOVE(head, elm, type, field) SLIST_REMOVE(head, elm, type, field)
-#define UA_SLIST_FOREACH(var, head, field) SLIST_FOREACH(var, head, field)
-#define UA_SLIST_EMPTY(head) SLIST_EMPTY(head)
-#define UA_SLIST_FIRST(head) SLIST_FIRST(head)
-#define UA_SLIST_NEXT(elm, field) SLIST_NEXT(elm, field)
 
 /**********************/
 /* Doubly Linked List */
 /**********************/
 
-typedef void (*UA_list_PayloadVisitor)(void* payload);
+typedef void (*UA_list_PayloadVisitor)(void *payload);
 
 typedef struct UA_list_Element {
-	struct UA_list_List* father;
-	void *payload;
-    struct UA_list_Element* next;
-    struct UA_list_Element* prev;
+    struct UA_list_List    *father;
+    void *payload;
+    struct UA_list_Element *next;
+    struct UA_list_Element *prev;
 }UA_list_Element;
 
 typedef struct UA_list_List {
-   struct UA_list_Element* first;
-   struct UA_list_Element* last;
-   UA_Int32 size;
+    struct UA_list_Element *first;
+    struct UA_list_Element *last;
+    UA_Int32 size;
 }UA_list_List;
 
-typedef void (*UA_list_ElementVisitor)(UA_list_Element* payload);
+typedef void (*UA_list_ElementVisitor)(UA_list_Element *payload);
 
 //typedef Boolean (*UA_list_PayloadMatcher)(void* payload);
-typedef _Bool (*UA_list_PayloadMatcher)(void* payload);
-typedef _Bool (*UA_list_PayloadComparer)(void* payload, void* otherPayload);
+typedef _Bool (*UA_list_PayloadMatcher)(void *payload);
+typedef _Bool (*UA_list_PayloadComparer)(void *payload, void *otherPayload);
 
-void UA_list_defaultFreer(void* payload);
+void UA_list_defaultFreer(void *payload);
 
-UA_Int32 UA_list_initElement(UA_list_Element* element);
+UA_Int32 UA_list_initElement(UA_list_Element *element);
 
-UA_Int32 UA_list_init(UA_list_List* list);
+UA_Int32 UA_list_init(UA_list_List *list);
 
-UA_Int32 UA_list_addElementToFront(UA_list_List* list, UA_list_Element* element);
+UA_Int32 UA_list_addElementToFront(UA_list_List *list, UA_list_Element *element);
 
-UA_Int32 UA_list_addPayloadToFront(UA_list_List* list, void* const payload);
+UA_Int32 UA_list_addPayloadToFront(UA_list_List *list, void *const payload);
 
-UA_Int32 UA_list_addElementToBack(UA_list_List* list, UA_list_Element* element);
+UA_Int32 UA_list_addElementToBack(UA_list_List *list, UA_list_Element *element);
 
-UA_Int32 UA_list_addPayloadToBack(UA_list_List* list, void* const payload);
+UA_Int32 UA_list_addPayloadToBack(UA_list_List *list, void *const payload);
 
-UA_Int32 UA_list_removeFirst(UA_list_List* list, UA_list_PayloadVisitor visitor);
+UA_Int32 UA_list_removeFirst(UA_list_List *list, UA_list_PayloadVisitor visitor);
 
-UA_Int32 UA_list_removeLast(UA_list_List* list, UA_list_PayloadVisitor visitor);
+UA_Int32 UA_list_removeLast(UA_list_List *list, UA_list_PayloadVisitor visitor);
 
-UA_Int32 UA_list_removeElement(UA_list_Element* const elem, UA_list_PayloadVisitor visitor);
+UA_Int32 UA_list_removeElement(UA_list_Element *const elem, UA_list_PayloadVisitor visitor);
 
-UA_Int32 UA_list_destroy(UA_list_List* list, UA_list_PayloadVisitor visitor);
+UA_Int32 UA_list_destroy(UA_list_List *list, UA_list_PayloadVisitor visitor);
 
-UA_Int32 UA_list_iterateElement(UA_list_List* const list, UA_list_ElementVisitor visitor);
+UA_Int32 UA_list_iterateElement(UA_list_List *const list, UA_list_ElementVisitor visitor);
 
-UA_Int32 UA_list_iteratePayload(UA_list_List* const list, UA_list_PayloadVisitor visitor);
+UA_Int32 UA_list_iteratePayload(UA_list_List *const list, UA_list_PayloadVisitor visitor);
 
-UA_list_Element* UA_list_find(UA_list_List* const list, UA_list_PayloadMatcher matcher);
+UA_list_Element *UA_list_find(UA_list_List *const list, UA_list_PayloadMatcher matcher);
 
-UA_list_Element* UA_list_search(UA_list_List* const list, UA_list_PayloadComparer compare, void* payload);
+UA_list_Element *UA_list_search(UA_list_List *const list, UA_list_PayloadComparer compare, void *payload);
 
-UA_list_Element* UA_list_getFirst(UA_list_List* const list);
+UA_list_Element *UA_list_getFirst(UA_list_List *const list);
 
-UA_list_Element* UA_list_getLast(UA_list_List* const list);
+UA_list_Element *UA_list_getLast(UA_list_List *const list);
 
 #endif /* UA_LIST_H_ */

+ 24 - 35
src/util/ua_log.h

@@ -5,70 +5,59 @@
    @defgroup logging Logging
 
    @brief Logging functionality is externally provided to the open62541 libary.
-   That is, every thread that wants logging to take place fills a global
-   variable "logger" with the appropriate callback functions. The UA_LOGLEVEL
-   preprocessor definition indicates which severity of events (trance, debug,
-   info, warning, error, fatal) shall be reported. Enabling logs at a certain
-   level enables all logs at the higher levels also. Furthermore, every
-   log-message has a category that can be used for filtering or to select the
-   output medium (file, stdout, ..).
-*/
+   The server contains a logger-struct with function callbacks
+ */
 
 typedef enum UA_LoggerCategory {
-	UA_LOGGERCATEGORY_CONNECTION,
-	UA_LOGGERCATEGORY_SESSION,
-	UA_LOGGERCATEGORY_SUBSCRIPTION,
-	UA_LOGGERCATEGORY_MAINTENANCE,
-	UA_LOGGERCATEGORY_LOAD,
+    UA_LOGGINGCATEGORY_CONNECTION,
+    UA_LOGGINGCATEGORY_SESSION,
+    UA_LOGGINGCATEGORY_SUBSCRIPTION,
+    UA_LOGGINGCATEGORY_SERVER
 } UA_LoggerCategory;
 
 typedef struct UA_Logger {
-	void (*log_trace)(UA_LoggerCategory category, const char *msg, ...);
-	void (*log_debug)(UA_LoggerCategory category, const char *msg, ...);
-	void (*log_info)(UA_LoggerCategory category, const char *msg, ...);
-	void (*log_warning)(UA_LoggerCategory category, const char *msg, ...);
-	void (*log_error)(UA_LoggerCategory category, const char *msg, ...);
-	void (*log_fatal)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_trace)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_debug)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_info)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_warning)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_error)(UA_LoggerCategory category, const char *msg, ...);
+    void (*log_fatal)(UA_LoggerCategory category, const char *msg, ...);
 } UA_Logger;
 
-/** The logger is a global variable on the stack. So every thread needs to
-	initialise its own logger. */
-static UA_Logger logger;
-
 #if UA_LOGLEVEL <= 100
-#define LOG_TRACE(CATEGORY, MSG, ...) do{ logger.log_trace(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_TRACE(CATEGORY, MSG, ...) do { logger.log_trace(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_TRACE(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_TRACE(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #if UA_LOGLEVEL <= 200
-#define LOG_DEBUG(CATEGORY, MSG, ...) do{ logger.log_debug(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_DEBUG(CATEGORY, MSG, ...) do { logger.log_debug(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_DEBUG(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_DEBUG(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #if UA_LOGLEVEL <= 300
-#define LOG_INFO(CATEGORY, MSG, ...) do{ logger.log_info(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_INFO(CATEGORY, MSG, ...) do { logger.log_info(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_INFO(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_INFO(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #if UA_LOGLEVEL <= 400
-#define LOG_WARNING(CATEGORY, MSG, ...) do{ logger.log_warning(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_WARNING(CATEGORY, MSG, ...) do { logger.log_warning(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_WARNING(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_WARNING(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #if UA_LOGLEVEL <= 500
-#define LOG_ERROR(CATEGORY, MSG, ...) do{ logger.log_error(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_ERROR(CATEGORY, MSG, ...) do { logger.log_error(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_ERROR(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_ERROR(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #if UA_LOGLEVEL <= 600
-#define LOG_FATAL(CATEGORY, MSG, ...) do{ logger.log_fatal(CATEGORY, MSG, __VA_ARGS__); } while
+#define UA_LOG_FATAL(CATEGORY, MSG, ...) do { logger.log_fatal(CATEGORY, MSG, __VA_ARGS__); } while(0)
 #else
-#define LOG_FATAL(CATEGORY, MSG, ...) do {} while;
+#define UA_LOG_FATAL(CATEGORY, MSG, ...) do {} while(0)
 #endif
 
 #endif /* UA_LOG_H_ */

+ 7 - 7
src/util/ua_util.c

@@ -7,14 +7,14 @@ extern INLINE UA_Int32 _UA_alloc(void **ptr, UA_Int32 size, char *pname, char *s
 extern INLINE UA_Int32 _UA_alloca(void **ptr, UA_Int32 size, char *pname, char *sname, char *f, UA_Int32 l);
 
 UA_Int32 UA_memcpy(void *dst, void const *src, UA_Int32 size) {
-	if(dst == UA_NULL) return UA_ERR_INVALID_VALUE;
-	DBG_VERBOSE(printf("UA_memcpy - %p;%p;%d\n", dst, src, size));
-	memcpy(dst, src, size);
-	return UA_SUCCESS;
+    if(dst == UA_NULL) return UA_ERR_INVALID_VALUE;
+    DBG_VERBOSE(printf("UA_memcpy - %p;%p;%d\n", dst, src, size));
+    memcpy(dst, src, size);
+    return UA_SUCCESS;
 }
 
 UA_Int32 UA_VTable_isValidType(UA_Int32 type) {
-	if(type < 0 /* UA_BOOLEAN */ || type > 271 /* UA_INVALID */)
-		return UA_ERR_INVALID_VALUE;
-	return UA_SUCCESS;
+    if(type < 0 /* UA_BOOLEAN */ || type > 271 /* UA_INVALID */)
+        return UA_ERR_INVALID_VALUE;
+    return UA_SUCCESS;
 }

+ 28 - 20
src/util/ua_util.h

@@ -13,6 +13,14 @@
 #include <malloc.h> // MinGW alloca
 #endif
 #endif
+
+#include <stddef.h> /* Needed for sys/queue.h */
+#ifndef MSVC
+#include <sys/queue.h>
+#else
+#include "queue.h"
+#endif
+
 #include "ua_types.h"
 
 /* Debug macros */
@@ -44,31 +52,31 @@ void const *UA_alloc_lastptr;
 #define UA_NULL ((void *)0)
 
 INLINE UA_Int32 _UA_free(void *ptr, char *pname, char *f, UA_Int32 l) {
-	DBG_VERBOSE(printf("UA_free;%p;;%s;;%s;%d\n", ptr, pname, f, l); fflush(stdout));
-	free(ptr); // checks if ptr != NULL in the background
-	return UA_SUCCESS;
+    DBG_VERBOSE(printf("UA_free;%p;;%s;;%s;%d\n", ptr, pname, f, l); fflush(stdout));
+    free(ptr); // checks if ptr != NULL in the background
+    return UA_SUCCESS;
 }
 
 INLINE UA_Int32 _UA_alloc(void **ptr, UA_Int32 size, char *pname, char *sname, char *f, UA_Int32 l) {
-	if(ptr == UA_NULL)
-		return UA_ERR_INVALID_VALUE;
-	UA_alloc_lastptr = *ptr = malloc(size);
-	DBG_VERBOSE(printf("UA_alloc - %p;%d;%s;%s;%s;%d\n", *ptr, size, pname, sname, f, l); fflush(stdout));
-	if(*ptr == UA_NULL)
-		return UA_ERR_NO_MEMORY;
-	return UA_SUCCESS;
+    if(ptr == UA_NULL)
+        return UA_ERR_INVALID_VALUE;
+    UA_alloc_lastptr = *ptr = malloc(size);
+    DBG_VERBOSE(printf("UA_alloc - %p;%d;%s;%s;%s;%d\n", *ptr, size, pname, sname, f, l); fflush(stdout));
+    if(*ptr == UA_NULL)
+        return UA_ERR_NO_MEMORY;
+    return UA_SUCCESS;
 }
 
 INLINE UA_Int32 _UA_alloca(void **ptr, UA_Int32 size, char *pname, char *sname, char *f, UA_Int32 l) {
-	if(ptr == UA_NULL)
-		return UA_ERR_INVALID_VALUE;
+    if(ptr == UA_NULL)
+        return UA_ERR_INVALID_VALUE;
 #ifdef MSVC
-	*ptr = _alloca(size);
+    *ptr = _alloca(size);
 #else
-	*ptr = alloca(size);
+    *ptr = alloca(size);
 #endif
-	DBG_VERBOSE(printf("UA_alloca - %p;%d;%s;%s;%s;%d\n", *ptr, size, pname, sname, f, l); fflush(stdout));
-	return UA_SUCCESS;
+    DBG_VERBOSE(printf("UA_alloca - %p;%d;%s;%s;%s;%d\n", *ptr, size, pname, sname, f, l); fflush(stdout));
+    return UA_SUCCESS;
 }
 
 UA_Int32 UA_memcpy(void *dst, void const *src, UA_Int32 size);
@@ -78,10 +86,10 @@ UA_Int32 UA_VTable_isValidType(UA_Int32 type);
 #define UA_alloc(ptr, size) _UA_alloc(ptr, size, # ptr, # size, __FILE__, __LINE__)
 
 /** @brief UA_alloca assigns memory on the stack instead of the heap. It is a
-	very fast alternative to standard malloc. The memory is automatically
-	returned ('freed') when the current function returns. Use this only for
-	small temporary values. For more than 100Byte, it is more reasonable to use
-	proper UA_alloc. */
+    very fast alternative to standard malloc. The memory is automatically
+    returned ('freed') when the current function returns. Use this only for
+    small temporary values. For more than 100Byte, it is more reasonable to use
+    proper UA_alloc. */
 #define UA_alloca(ptr, size) _UA_alloca(ptr, size, # ptr, # size, __FILE__, __LINE__)
 
 #define UA_assert(ignore) assert(ignore)

+ 12 - 16
tests/CMakeLists.txt

@@ -17,30 +17,26 @@ add_executable(check_memory check_memory.c)
 target_link_libraries(check_memory ${LIBS})
 add_test(memory ${CMAKE_CURRENT_BINARY_DIR}/check_memory)
 
-add_executable(check_stack check_stack.c)
-target_link_libraries(check_stack ${LIBS})
-add_test(stack ${CMAKE_CURRENT_BINARY_DIR}/check_stack)
+# add_executable(check_stack check_stack.c)
+# target_link_libraries(check_stack ${LIBS})
+# add_test(stack ${CMAKE_CURRENT_BINARY_DIR}/check_stack)
 
 add_executable(check_list check_list.c)
 target_link_libraries(check_list ${LIBS})
 add_test(list ${CMAKE_CURRENT_BINARY_DIR}/check_list)
 
-add_executable(check_indexedList check_indexedList.c)
-target_link_libraries(check_indexedList ${LIBS})
-add_test(indexedList ${CMAKE_CURRENT_BINARY_DIR}/check_indexedList)
-
-add_executable(check_base64 check_base64.c)
-target_link_libraries(check_base64 ${LIBS})
-add_test(base64 ${CMAKE_CURRENT_BINARY_DIR}/check_base64)
+# add_executable(check_base64 check_base64.c)
+# target_link_libraries(check_base64 ${LIBS})
+# add_test(base64 ${CMAKE_CURRENT_BINARY_DIR}/check_base64)
 
 add_executable(check_services_view check_services_view.c)
 target_link_libraries(check_services_view ${LIBS})
 add_test(services_view ${CMAKE_CURRENT_BINARY_DIR}/check_services_view)
 
-add_executable(check_namespace check_namespace.c)
-target_link_libraries(check_namespace ${LIBS})
-add_test(namespace ${CMAKE_CURRENT_BINARY_DIR}/check_namespace)
+add_executable(check_nodestore check_nodestore.c)
+target_link_libraries(check_nodestore ${LIBS})
+add_test(namespace ${CMAKE_CURRENT_BINARY_DIR}/check_nodestore)
 
-add_executable(check_startup check_startup.c)
-target_link_libraries(check_startup ${LIBS})
-add_test(startup ${CMAKE_CURRENT_BINARY_DIR}/check_startup)
+# add_executable(check_startup check_startup.c)
+# target_link_libraries(check_startup ${LIBS})
+# add_test(startup ${CMAKE_CURRENT_BINARY_DIR}/check_startup)

+ 3 - 2
tests/check_builtin.c

@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include "ua_types.h"
 #include "ua_types_encoding_binary.h"
+#include "ua_namespace_0.h"
 #include "ua_transport.h"
 #include "check.h"
 
@@ -1632,8 +1633,8 @@ START_TEST(UA_LocalizedText_copycstringShallWorkOnInputExample) {
 	ret = UA_LocalizedText_copycstring(src, &dst);
 	// then
 	ck_assert_int_eq(ret, UA_SUCCESS);
-	ck_assert_int_eq('E', dst.locale.data[0]);
-	ck_assert_int_eq('N', dst.locale.data[1]);
+	ck_assert_int_eq('e', dst.locale.data[0]);
+	ck_assert_int_eq('n', dst.locale.data[1]);
 	ck_assert_int_eq('1', dst.text.data[4]);
 	ck_assert_int_eq(2, dst.locale.length);
 	ck_assert_int_eq(7, dst.text.length);

+ 87 - 87
tests/check_namespace.c

@@ -3,7 +3,7 @@
 #include <time.h>
 
 #include "ua_types.h"
-#include "ua_namespace.h"
+#include "server/ua_nodestore.h"
 #include "check.h"
 
 #ifdef MULTITHREADING
@@ -22,10 +22,10 @@ void printVisitor(const UA_Node* node) {
 	printf("%d\n", node->nodeId.identifier.numeric);
 }
 
-START_TEST(test_Namespace) {
-	Namespace *ns = UA_NULL;
-	Namespace_new(&ns, 0);
-	Namespace_delete(ns);
+START_TEST(test_UA_NodeStore) {
+	UA_NodeStore *ns = UA_NULL;
+	UA_NodeStore_new(&ns);
+	UA_NodeStore_delete(ns);
 }
 END_TEST
 
@@ -38,115 +38,115 @@ UA_Int32 createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
 	return UA_SUCCESS;
 }
 
-START_TEST(findNodeInNamespaceWithSingleEntry) {
+START_TEST(findNodeInUA_NodeStoreWithSingleEntry) {
 #ifdef MULTITHREADING
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
 	UA_Node* n1; createNode(&n1,0,2253);
-	Namespace_insert(ns, &n1, NAMESPACE_INSERT_UNIQUE | NAMESPACE_INSERT_GETMANAGED);
+	UA_NodeStore_insert(ns, &n1, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
 	// when
-	retval = Namespace_get(ns,&n1->nodeId,&nr);
+	retval = UA_NodeStore_get(ns,&n1->nodeId,&nr);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_ptr_eq(nr,n1);
 	// finally
-	Namespace_releaseManagedNode(n1);
-	Namespace_releaseManagedNode(nr);
-	Namespace_delete(ns);
+	UA_NodeStore_releaseManagedNode(n1);
+	UA_NodeStore_releaseManagedNode(nr);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
 }
 END_TEST
 
-START_TEST(failToFindNodeInOtherNamespace) {
+START_TEST(failToFindNodeInOtherUA_NodeStore) {
 #ifdef MULTITHREADING
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns = UA_NULL;
-	Namespace_new(&ns, 0);
+	UA_NodeStore *ns = UA_NULL;
+	UA_NodeStore_new(&ns);
 
-	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
-	UA_Node* n2; createNode(&n2,0,2253); Namespace_insert(ns, &n2, 0);
+	UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2253); UA_NodeStore_insert(ns, &n2, 0);
 
 	const UA_Node* nr = UA_NULL;
 	// when
 	UA_Node* n; createNode(&n,1,2255);
-	UA_Int32 retval = Namespace_get(ns,&n->nodeId, &nr);
+	UA_Int32 retval = UA_NodeStore_get(ns,&n->nodeId, &nr);
 	// then
 	ck_assert_int_ne(retval, UA_SUCCESS);
 	// finally
 	UA_Node_delete(n);
-	Namespace_releaseManagedNode(nr);
-	Namespace_delete(ns);
+	UA_NodeStore_releaseManagedNode(nr);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
 }
 END_TEST
 
-START_TEST(findNodeInNamespaceWithSeveralEntries) {
+START_TEST(findNodeInUA_NodeStoreWithSeveralEntries) {
 #ifdef MULTITHREADING
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
-	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
-	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
-	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, NAMESPACE_INSERT_GETMANAGED);
-	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
-	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
-	UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
+	UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, UA_NODESTORE_INSERT_GETMANAGED);
+	UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
+	UA_Node* n6; createNode(&n6,0,12); UA_NodeStore_insert(ns, &n6, 0);
 
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
 	// when
-	retval = Namespace_get(ns,&(n3->nodeId),&nr);
+	retval = UA_NodeStore_get(ns,&(n3->nodeId),&nr);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_ptr_eq(nr,n3);
 	// finally
-	Namespace_releaseManagedNode(n3);
-	Namespace_releaseManagedNode(nr);
-	Namespace_delete(ns);
+	UA_NodeStore_releaseManagedNode(n3);
+	UA_NodeStore_releaseManagedNode(nr);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
 }
 END_TEST
 
-START_TEST(iterateOverNamespaceShallNotVisitEmptyNodes) {
+START_TEST(iterateOverUA_NodeStoreShallNotVisitEmptyNodes) {
 #ifdef MULTITHREADING
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
-	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
-	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
-	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
-	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
-	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
-	UA_Node* n6; createNode(&n6,0,12); Namespace_insert(ns, &n6, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
+	UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, 0);
+	UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
+	UA_Node* n6; createNode(&n6,0,12); UA_NodeStore_insert(ns, &n6, 0);
 
 	UA_Int32 retval;
 	// when
 	zeroCnt = 0;
 	visitCnt = 0;
-	retval = Namespace_iterate(ns,checkZeroVisitor);
+	retval = UA_NodeStore_iterate(ns,checkZeroVisitor);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(zeroCnt, 0);
 	ck_assert_int_eq(visitCnt, 6);
 	// finally
-	Namespace_delete(ns);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
@@ -158,25 +158,25 @@ START_TEST(findNodeInExpandedNamespace) {
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
 	UA_Node* n;
 	UA_Int32 i=0;
 	for (; i<200; i++) {
-		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
+		createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
 	}
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
 	// when
 	createNode(&n,0,25);
-	retval = Namespace_get(ns,&(n->nodeId),&nr);
+	retval = UA_NodeStore_get(ns,&(n->nodeId),&nr);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(nr->nodeId.identifier.numeric,n->nodeId.identifier.numeric);
 	// finally
 	UA_free((void*)n);
-	Namespace_releaseManagedNode(nr);
-	Namespace_delete(ns);
+	UA_NodeStore_releaseManagedNode(nr);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
@@ -188,53 +188,53 @@ START_TEST(iterateOverExpandedNamespaceShallNotVisitEmptyNodes) {
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
 	UA_Node* n;
 	UA_Int32 i=0;
 	for (; i<200; i++) {
-		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
+		createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
 	}
 	// when
 	UA_Int32 retval;
 	zeroCnt = 0;
 	visitCnt = 0;
-	retval = Namespace_iterate(ns,checkZeroVisitor);
+	retval = UA_NodeStore_iterate(ns,checkZeroVisitor);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_int_eq(zeroCnt, 0);
 	ck_assert_int_eq(visitCnt, 200);
 	// finally
-	Namespace_delete(ns);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
 }
 END_TEST
 
-START_TEST(failToFindNonExistantNodeInNamespaceWithSeveralEntries) {
+START_TEST(failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries) {
 #ifdef MULTITHREADING
    	rcu_register_thread();
 #endif
 	// given
-	Namespace *ns;
-	Namespace_new(&ns, 0);
-	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns, &n1, 0);
-	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns, &n2, 0);
-	UA_Node* n3; createNode(&n3,0,2257); Namespace_insert(ns, &n3, 0);
-	UA_Node* n4; createNode(&n4,0,2200); Namespace_insert(ns, &n4, 0);
-	UA_Node* n5; createNode(&n5,0,1); Namespace_insert(ns, &n5, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
+	UA_Node* n1; createNode(&n1,0,2253); UA_NodeStore_insert(ns, &n1, 0);
+	UA_Node* n2; createNode(&n2,0,2255); UA_NodeStore_insert(ns, &n2, 0);
+	UA_Node* n3; createNode(&n3,0,2257); UA_NodeStore_insert(ns, &n3, 0);
+	UA_Node* n4; createNode(&n4,0,2200); UA_NodeStore_insert(ns, &n4, 0);
+	UA_Node* n5; createNode(&n5,0,1); UA_NodeStore_insert(ns, &n5, 0);
 	UA_Node* n6; createNode(&n6,0,12); 
 
 	const UA_Node* nr = UA_NULL;
 	UA_Int32 retval;
 	// when
-	retval = Namespace_get(ns, &(n6->nodeId), &nr);
+	retval = UA_NodeStore_get(ns, &(n6->nodeId), &nr);
 	// then
 	ck_assert_int_ne(retval, UA_SUCCESS);
 	// finally
 	UA_free((void *)n6);
-	Namespace_delete(ns);
+	UA_NodeStore_delete(ns);
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
 #endif
@@ -246,8 +246,8 @@ END_TEST
 /************************************/
 
 #ifdef MULTITHREADING
-struct NamespaceProfileTest {
-	Namespace *ns;
+struct UA_NodeStoreProfileTest {
+	UA_NodeStore *ns;
 	UA_Int32 min_val;
 	UA_Int32 max_val;
 	UA_Int32 rounds;
@@ -255,16 +255,16 @@ struct NamespaceProfileTest {
 
 void *profileGetThread(void *arg) {
    	rcu_register_thread();
-	struct NamespaceProfileTest *test = (struct NamespaceProfileTest*) arg;
+	struct UA_NodeStoreProfileTest *test = (struct UA_NodeStoreProfileTest*) arg;
 	UA_NodeId id = NS0NODEID(0);
 	const UA_Node *cn;
 	UA_Int32 max_val = test->max_val;
-	Namespace *ns = test->ns;
+	UA_NodeStore *ns = test->ns;
 	for(UA_Int32 x = 0; x<test->rounds; x++) {
 		for (UA_Int32 i=test->min_val; i<max_val; i++) {
 			id.identifier.numeric = i;
-			Namespace_get(ns,&id, &cn);
-			Namespace_releaseManagedNode(cn);
+			UA_NodeStore_get(ns,&id, &cn);
+			UA_NodeStore_releaseManagedNode(cn);
 		}
 	}
 	rcu_unregister_thread();
@@ -279,21 +279,21 @@ START_TEST(profileGetDelete) {
 #endif
 
 #define N 1000000
-	Namespace *ns;
-	Namespace_new(&ns, 0);
+	UA_NodeStore *ns;
+	UA_NodeStore_new(&ns);
 	UA_Int32 i=0;
 	UA_Node *n;
 	for (; i<N; i++) {
-		createNode(&n,0,i); Namespace_insert(ns, &n, 0);
+		createNode(&n,0,i); UA_NodeStore_insert(ns, &n, 0);
 	}
 	clock_t begin, end;
 	begin = clock();
 #ifdef MULTITHREADING
 #define THREADS 4
     pthread_t t[THREADS];
-	struct NamespaceProfileTest p[THREADS];
+	struct UA_NodeStoreProfileTest p[THREADS];
 	for (int i = 0; i < THREADS; i++) {
-		p[i] = (struct NamespaceProfileTest){ns, i*(N/THREADS), (i+1)*(N/THREADS), 50};
+		p[i] = (struct UA_NodeStoreProfileTest){ns, i*(N/THREADS), (i+1)*(N/THREADS), 50};
 		pthread_create(&t[i], NULL, profileGetThread, &p[i]);
 	}
 	for (int i = 0; i < THREADS; i++)
@@ -306,15 +306,15 @@ START_TEST(profileGetDelete) {
 	for(UA_Int32 x = 0; x<50; x++) {
 	    for(i=0; i<N; i++) {
 	        id.identifier.numeric = i;
-			Namespace_get(ns,&id, &cn);
-			Namespace_releaseManagedNode(cn);
+			UA_NodeStore_get(ns,&id, &cn);
+			UA_NodeStore_releaseManagedNode(cn);
         }
     }
 	end = clock();
 	printf("Time for single-threaded %d create/get/delete in a namespace: %fs.\n", N, (double)(end - begin) / CLOCKS_PER_SEC);
 #endif
 
-	Namespace_delete(ns);
+	UA_NodeStore_delete(ns);
 
 #ifdef MULTITHREADING
 	rcu_unregister_thread();
@@ -323,22 +323,22 @@ START_TEST(profileGetDelete) {
 END_TEST
 
 Suite * namespace_suite (void) {
-	Suite *s = suite_create ("Namespace");
+	Suite *s = suite_create ("UA_NodeStore");
 
 	TCase *tc_cd = tcase_create ("Create/Delete");
-	tcase_add_test (tc_cd, test_Namespace);
+	tcase_add_test (tc_cd, test_UA_NodeStore);
 	suite_add_tcase (s, tc_cd);
 
 	TCase* tc_find = tcase_create ("Find");
-	tcase_add_test (tc_find, findNodeInNamespaceWithSingleEntry);
-	tcase_add_test (tc_find, findNodeInNamespaceWithSeveralEntries);
+	tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSingleEntry);
+	tcase_add_test (tc_find, findNodeInUA_NodeStoreWithSeveralEntries);
 	tcase_add_test (tc_find, findNodeInExpandedNamespace);
-	tcase_add_test (tc_find, failToFindNonExistantNodeInNamespaceWithSeveralEntries);
-	tcase_add_test (tc_find, failToFindNodeInOtherNamespace);
+	tcase_add_test (tc_find, failToFindNonExistantNodeInUA_NodeStoreWithSeveralEntries);
+	tcase_add_test (tc_find, failToFindNodeInOtherUA_NodeStore);
 	suite_add_tcase (s, tc_find);
 
 	TCase* tc_iterate = tcase_create ("Iterate");
-	tcase_add_test (tc_iterate, iterateOverNamespaceShallNotVisitEmptyNodes);
+	tcase_add_test (tc_iterate, iterateOverUA_NodeStoreShallNotVisitEmptyNodes);
 	tcase_add_test (tc_iterate, iterateOverExpandedNamespaceShallNotVisitEmptyNodes);
 	suite_add_tcase (s, tc_iterate);
 	

+ 4 - 14
tests/check_services_view.c

@@ -1,22 +1,12 @@
-/*
- ============================================================================
- Name        : check_stack.c
- Author      :
- Version     :
- Copyright   : Your copyright notice
- Description :
- ============================================================================
- */
-
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "ua_types.h"
-#include "ua_services.h"
+#include "server/ua_services.h"
 #include "ua_statuscodes.h"
 #include "check.h"
 
-START_TEST(Service_TranslateBrowsePathsToNodeIds_SmokeTest)
+/* START_TEST(Service_TranslateBrowsePathsToNodeIds_SmokeTest)
 {
 	UA_TranslateBrowsePathsToNodeIdsRequest request;
 	UA_TranslateBrowsePathsToNodeIdsRequest_init(&request);
@@ -36,13 +26,13 @@ START_TEST(Service_TranslateBrowsePathsToNodeIds_SmokeTest)
 	UA_TranslateBrowsePathsToNodeIdsRequest_deleteMembers(&request);
 	UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers(&response);
 }
-END_TEST
+END_TEST */
 
 Suite* testSuite_Service_TranslateBrowsePathsToNodeIds()
 {
 	Suite *s = suite_create("Service_TranslateBrowsePathsToNodeIds");
 	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, Service_TranslateBrowsePathsToNodeIds_SmokeTest);
+	//tcase_add_test(tc_core, Service_TranslateBrowsePathsToNodeIds_SmokeTest);
 	suite_add_tcase(s,tc_core);
 	return s;
 }

+ 32 - 49
tests/check_stack.c

@@ -3,11 +3,9 @@
 
 #include "ua_types.h"
 #include "ua_transport.h"
-#include "ua_transport_binary.h"
-#include "ua_transport_binary_secure.h"
-#include "ua_transport_connection.h"
-#include "ua_channel_manager.h"
-#include "ua_session_manager.h"
+#include "ua_connection.h"
+#include "server/ua_securechannel_manager.h"
+#include "server/ua_session_manager.h"
 #include "check.h"
 
 #define MAXMSG 512
@@ -20,11 +18,9 @@ typedef struct stackTestFixture {
 	/** @brief the management structure (initialized to point to respMsgBuffer in create */
 	UA_ByteString respMsg;
 	/** @brief the management data structure for the fake connection */
-	UA_TL_Connection *connection;
-
+	UA_Connection *connection;
 } stackTestFixture;
 
-
 /** @brief the maximum number of parallel fixtures.
  * ( MAX_FIXTURES needs to match the number of bytes of fixturesMap )*/
 #define MAX_FIXTURES 32
@@ -35,9 +31,8 @@ stackTestFixture *fixtures[MAX_FIXTURES];
 
 /** @brief search first free handle, set and return */
 UA_Int32 stackTestFixture_getAndMarkFreeHandle() {
-	UA_Int32 freeFixtureHandle = 0;
-
-	for(freeFixtureHandle = 0;freeFixtureHandle < MAX_FIXTURES;++freeFixtureHandle) {
+	UA_UInt32 freeFixtureHandle = 0;
+	for(freeFixtureHandle = 0;freeFixtureHandle < MAX_FIXTURES;freeFixtureHandle++) {
 		if(!(fixturesMap & (1 << freeFixtureHandle))) { // when free
 			fixturesMap |= (1 << freeFixtureHandle);    // then set
 			return freeFixtureHandle;
@@ -54,34 +49,22 @@ UA_Int32 stackTestFixture_markHandleAsFree(UA_Int32 fixtureHandle) {
 	}
 	return UA_ERR_INVALID_VALUE;
 }
-UA_Int32 closerCallback(UA_TL_Connection *connection)
-{
+
+UA_Int32 closerCallback(UA_Connection *connection) {
 	return UA_SUCCESS;
 }
-/** @brief get a handle to a free slot and create a new stackTestFixture */
-UA_Int32 stackTestFixture_create(TL_Writer writerCallback, TL_Closer closerCallback) {
-	UA_String endpointUrl;
-	UA_String_copycstring("no url",&endpointUrl);
-	SL_ChannelManager_init(4,36000,25,22,&endpointUrl);
-	UA_SessionManager_init(4,220000,222);
 
+/** @brief get a handle to a free slot and create a new stackTestFixture */
+UA_Int32 stackTestFixture_create(UA_Connection_writeCallback write, UA_Connection_closeCallback close) {
 	UA_UInt32 fixtureHandle = stackTestFixture_getAndMarkFreeHandle();
-	if(fixtureHandle < MAX_FIXTURES) {
-		UA_alloc((void **)&fixtures[fixtureHandle], sizeof(stackTestFixture));
-		stackTestFixture *fixture = fixtures[fixtureHandle];
-		fixture->respMsg.data   = fixture->respMsgBuffer;
-		fixture->respMsg.length = 0;
-		TL_Buffer buffer;
-		buffer.maxChunkCount   = 1;
-		buffer.maxMessageSize  = BUFFER_SIZE;
-		buffer.protocolVersion = 0;
-		buffer.recvBufferSize  = BUFFER_SIZE;
-		buffer.recvBufferSize  = BUFFER_SIZE;
-		UA_TL_Connection_new(&fixture->connection,buffer,writerCallback,closerCallback,fixtureHandle,UA_NULL);
-
-	}
+	stackTestFixture *fixture = fixtures[fixtureHandle];
+	UA_alloc((void**)&fixture->connection, sizeof(UA_Connection));
+	fixture->respMsg.data   = fixture->respMsgBuffer;
+	fixture->respMsg.length = 0;
+	UA_Connection_init(fixture->connection, UA_ConnectionConfig_standard, fixture, close, write);
 	return fixtureHandle;
 }
+
 /** @brief free the allocated memory of the stackTestFixture associated with the handle */
 UA_Int32 stackTestFixture_delete(UA_UInt32 fixtureHandle) {
 	if(fixtureHandle < MAX_FIXTURES) {
@@ -101,7 +84,6 @@ stackTestFixture *stackTestFixture_getFixture(UA_UInt32 fixtureHandle) {
 
 /** @brief write message provided in the gather buffers to the buffer of the fixture */
 UA_Int32 responseMsg(UA_Int32 connectionHandle, UA_ByteString const **gather_buf, UA_Int32 gather_len) {
-
 	stackTestFixture *fixture = stackTestFixture_getFixture(connectionHandle);
 	UA_Int32  retval    = UA_SUCCESS;
 	UA_UInt32 total_len = 0;
@@ -118,7 +100,6 @@ UA_Int32 responseMsg(UA_Int32 connectionHandle, UA_ByteString const **gather_buf
 }
 
 void indicateMsg(UA_Int32 handle, UA_ByteString *slMessage) {
-
 	printf("indicate: %d", TL_Process((stackTestFixture_getFixture(handle)->connection), slMessage));
 }
 
@@ -361,7 +342,6 @@ START_TEST(emptyIndicationShallYieldNoResponse) {
 }
 END_TEST
 
-
 START_TEST(validHELIndicationShallYieldACKResponse) {
 	// given
 	UA_Int32 handle = stackTestFixture_create(responseMsg, closerCallback);
@@ -454,20 +434,20 @@ START_TEST(validCreateSessionShallCreateSession) {
 }
 END_TEST
 
-START_TEST(UA_OPCUATcpMessageHeader_copyShallWorkOnInputExample) {
+START_TEST(UA_TcpMessageHeader_copyShallWorkOnInputExample) {
 	// given
-	UA_OPCUATcpMessageHeader src;
-	UA_OPCUATcpMessageHeader_init(&src);
+	UA_TcpMessageHeader src;
+	UA_TcpMessageHeader_init(&src);
 	src.isFinal = 2;
 	src.messageSize = 43;
 	src.messageType = UA_MESSAGETYPE_MSG;
-	const UA_OPCUATcpMessageHeader srcConst = src;
+	const UA_TcpMessageHeader srcConst = src;
 
-	UA_OPCUATcpMessageHeader dst;
+	UA_TcpMessageHeader dst;
 	UA_Int32 ret;
 
 	// when
-	ret = UA_OPCUATcpMessageHeader_copy(&srcConst, &dst);
+	ret = UA_TcpMessageHeader_copy(&srcConst, &dst);
 	// then
 	ck_assert_int_eq(ret, UA_SUCCESS);
 	ck_assert_int_eq(UA_MESSAGETYPE_MSG, dst.messageType);
@@ -475,6 +455,7 @@ START_TEST(UA_OPCUATcpMessageHeader_copyShallWorkOnInputExample) {
 	ck_assert_int_eq(2, dst.isFinal);
 }
 END_TEST
+
 START_TEST(UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample) {
 	// given
 	UA_AsymmetricAlgorithmSecurityHeader src;
@@ -501,13 +482,14 @@ START_TEST(UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample) {
 
 }
 END_TEST
+
 START_TEST(UA_SecureConversationMessageHeader_copyShallWorkOnInputExample) {
 	// given
 	UA_SecureConversationMessageHeader src;
 	UA_SecureConversationMessageHeader_init(&src);
 	src.secureChannelId = 84;
-	UA_OPCUATcpMessageHeader srcHeader;
-	UA_OPCUATcpMessageHeader_init(&srcHeader);
+	UA_TcpMessageHeader srcHeader;
+	UA_TcpMessageHeader_init(&srcHeader);
 	srcHeader.isFinal = 4;
 	srcHeader.messageSize = 765;
 	srcHeader.messageType = UA_MESSAGETYPE_CLO;
@@ -528,6 +510,7 @@ START_TEST(UA_SecureConversationMessageHeader_copyShallWorkOnInputExample) {
 	ck_assert_int_eq(UA_MESSAGETYPE_CLO, dst.messageHeader.messageType);
 }
 END_TEST
+
 START_TEST(UA_SequenceHeader_copyShallWorkOnInputExample) {
 	// given
 	UA_SequenceHeader src;
@@ -548,6 +531,7 @@ START_TEST(UA_SequenceHeader_copyShallWorkOnInputExample) {
 	ck_assert_int_eq(1345, dst.sequenceNumber);
 }
 END_TEST
+
 START_TEST(UA_SecureConversationMessageFooter_copyShallWorkOnInputExample) {
 	// given
 	UA_SecureConversationMessageFooter src;
@@ -573,6 +557,7 @@ START_TEST(UA_SecureConversationMessageFooter_copyShallWorkOnInputExample) {
 	ck_assert_int_eq(87, dst.padding[2]);
 }
 END_TEST
+
 START_TEST(UA_SecureConversationMessageFooter_calcSizeBinaryShallWorkOnInputExample) {
 	// given
 	UA_SecureConversationMessageFooter src;
@@ -592,6 +577,7 @@ START_TEST(UA_SecureConversationMessageFooter_calcSizeBinaryShallWorkOnInputExam
 	ck_assert_int_eq(ret, 8);
 }
 END_TEST
+
 START_TEST(UA_SecureConversationMessageFooter_encodeBinaryShallWorkOnInputExample) {
 //	// given
 //	UA_SecureConversationMessageFooter src = {3, (UA_Byte*)"447", 5};;
@@ -615,6 +601,7 @@ START_TEST(UA_SecureConversationMessageFooter_encodeBinaryShallWorkOnInputExampl
 //	ck_assert_int_eq(dst.data[7], 6);
 }
 END_TEST
+
 START_TEST(UA_SecureConversationMessageAbortBody_copyShallWorkOnInputExample) {
 	// given
 	UA_SecureConversationMessageAbortBody src;
@@ -623,7 +610,6 @@ START_TEST(UA_SecureConversationMessageAbortBody_copyShallWorkOnInputExample) {
 	src.reason = (UA_String){6, (UA_Byte*)"reAson"};
 
 	const UA_SecureConversationMessageAbortBody srcConst = src;
-
 	UA_SecureConversationMessageAbortBody dst;
 	UA_Int32 ret;
 
@@ -648,7 +634,7 @@ Suite *testSuite() {
 	suite_add_tcase(s, tc_core);
 
 	TCase *tc_transport = tcase_create("Transport");
-	tcase_add_test(tc_transport, UA_OPCUATcpMessageHeader_copyShallWorkOnInputExample);
+	tcase_add_test(tc_transport, UA_TcpMessageHeader_copyShallWorkOnInputExample);
 	tcase_add_test(tc_transport, UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample);
 	tcase_add_test(tc_transport, UA_SecureConversationMessageHeader_copyShallWorkOnInputExample);
 	tcase_add_test(tc_transport, UA_SequenceHeader_copyShallWorkOnInputExample);
@@ -662,7 +648,6 @@ Suite *testSuite() {
 
 int main(void) {
 	int      number_failed = 0;
-
 	Suite   *s;
 	SRunner *sr;
 
@@ -676,5 +661,3 @@ int main(void) {
 
 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-
-

+ 7 - 1
tools/generate_builtin.py

@@ -14,6 +14,7 @@ parser.add_argument('--with-xml', action='store_true', help='generate xml encodi
 parser.add_argument('--with-json', action='store_true', help='generate json encoding')
 parser.add_argument('--only-nano', action='store_true', help='generate only the types for the nano profile')
 parser.add_argument('--only-needed', action='store_true', help='generate only types needed for compile')
+parser.add_argument('--additional-includes', action='store', help='include additional header files (separated by comma)')
 parser.add_argument('types', help='path/to/Opc.Ua.Types.bsd')
 parser.add_argument('outfile', help='outfile w/o extension')
 args = parser.parse_args()
@@ -232,6 +233,7 @@ UA_TYPE_METHOD_DECODEXML_NOTIMPL(%(name)s)''')
 
     # 10) Init
     printc('''UA_Int32 %(name)s_init(%(name)s *p) {
+    if(!p) return UA_ERROR;
     UA_Int32 retval = UA_SUCCESS;''')
     for n,t in membermap.iteritems():
         if t.find("*") != -1:
@@ -293,7 +295,11 @@ printh('''/**
 #include "ua_types_encoding_binary.h"''')
 if args.with_xml:
 	printh('#include "ua_types_encoding_xml.h"')
-printh('#include "ua_namespace_0.h"\n')
+printh('#include "ua_namespace_0.h"')
+if args.additional_includes:
+    for incl in args.additional_includes.split(","):
+        printh("#include \"" + incl + "\"")
+printh("") # newline
 
 printc('''/**
  * @file '''+sys.argv[2]+'''.c

+ 1 - 1
tools/uncrustify.cfg

@@ -1,6 +1,6 @@
 # Basics
 code_width		= 110
-indent_with_tabs	= 1		# 1=indent to level only, 2=indent with tabs
+indent_with_tabs	= 0		# 1=indent to level only, 2=indent with tabs
 input_tab_size		= 4		# original tab size
 output_tab_size		= 4		# new tab size
 indent_columns		= output_tab_size