Parcourir la source

Merge branch 'master' of https://github.com/acplt/open62541

Conflicts:
	examples/src/xml2ns0.c
	include/ua_basictypes.h
	src/ua_namespace.h
opcua il y a 10 ans
Parent
commit
de3240b878

+ 26 - 0
.coverity.sh

@@ -0,0 +1,26 @@
+#!/bin/bash
+
+#
+# This sciprt is run by travis-ci and pushes the first commit
+# of the day to the coverity scan service
+#
+
+COMMITS=`git log --since=today.midnight | grep commit | wc -l`
+
+if [[ "$COMMITS" == "1" ]]; then
+    #first commit a day - push changes to branch coverity_scan
+    git clone -b coverity_scan https://$GITAUTH@github.com/acplt/open62541
+    cd open62541
+    git fetch origin
+    git merge origin/master
+    git config --global user.email "open62541-travis-ci@users.noreply.github.com"
+    git config --global user.name "Open62541 travis-ci"
+    git config --global push.default simple
+    git add *
+    git commit -am "push to coverity scan by travis-ci"
+    git push https://$GITAUTH@github.com/acplt/open62541
+    cd ..
+    rm -rf open62541
+else
+    echo "Not the first commit of the day - no push to coverity required"
+fi

+ 1 - 0
.gitignore

@@ -36,6 +36,7 @@ config.log
 /autogen.sh
 /configure
 /missing
+/html
 *~
 GIT_REVISION
 SVN_REVISION

+ 35 - 22
.travis.yml

@@ -1,32 +1,45 @@
 language: c
 compiler:
-  - gcc
-
+- gcc
 env:
   global:
-   # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
-   #   via the "travis encrypt" command using the project repo's public key
-   - secure: "AgDJV7/ubjxZFcxuOlkOizWyo0VLve9Pdh5Xz+3Ec37SeYotfUWAupwMZdMXZdKiDyHkAo1R0GdHgpkJ+Tm12o8WdsxZvTi0JdNtXObrYstNnzleuzf9fTsaY74wRDC2Q2URhBrR+oNcD19Lp6mpoCk6asDBhn2+6CP+dLBtKOE="
-
+  - secure: AgDJV7/ubjxZFcxuOlkOizWyo0VLve9Pdh5Xz+3Ec37SeYotfUWAupwMZdMXZdKiDyHkAo1R0GdHgpkJ+Tm12o8WdsxZvTi0JdNtXObrYstNnzleuzf9fTsaY74wRDC2Q2URhBrR+oNcD19Lp6mpoCk6asDBhn2+6CP+dLBtKOE= 
+  - secure: Tp53B4vuTKhpMsyAFr5zIHzWtD9XoeLS4CzW3bSgUpuzdHUD+SVunwnjileleKzLY6Iqf3v02NK/TqGDNpehdlWGQf9TgSLSqG0GMohLUaipuVj6HS6LD0vAgU+3U1TdBfvDelDIppqK2CCph2g5Vtw0OXvopw6HQdXeBDSOUKE=
 addons:
   coverity_scan:
     project:
-      name: "acplt/open62541"
-      description: "Open-source OPC UA"
+      name: acplt/open62541
+      description: Open-source OPC UA
     notification_email: 
-    build_command_prepend: "./autogen.sh && ./configure"
-    build_command: "make"
+    build_command_prepend: ./autogen.sh && ./configure
+    build_command: make
     branch_pattern: coverity_scan
-
 before_install:
- - sudo apt-get update -qq
- - sudo apt-get install -qq build-essential subversion git autoconf libtool texinfo python-lxml valgrind
- - svn checkout https://svn.code.sf.net/p/check/code/trunk check-code
- - cd check-code
- - autoreconf --install
- - ./configure
- - make
- - sudo make install
- - sudo ldconfig
- - cd ..
-script: ./autogen.sh && ./configure && make && make check
+- sudo apt-get update -qq
+- sudo apt-get install -qq build-essential subversion git autoconf libtool texinfo
+  python-lxml graphviz doxygen
+- svn checkout https://svn.code.sf.net/p/check/code/trunk check-code
+- cd check-code
+- autoreconf --install
+- ./configure
+- make
+- sudo make install
+- sudo ldconfig
+- cd ..
+- rm -rf check-code
+script: ./autogen.sh && ./configure --enable-doxygen && make && make check
+after_success:
+   - git clone -b gh-pages https://$GITAUTH@github.com/acplt/open62541
+   - rm -rf open62541/doxygen
+   - cp -r doc/html open62541/doxygen
+   - cd open62541/doxygen
+   - git config --global user.email "open62541-travis-ci@users.noreply.github.com"
+   - git config --global user.name "Open62541 travis-ci"
+   - git config --global push.default simple
+   - git add *
+   - git commit -am "doxygen updated by travis-ci"
+   - git push https://$GITAUTH@github.com/acplt/open62541
+   - cd ..
+   - cd ..
+   - rm -rf open62541
+   - ./.coverity.sh

+ 3 - 1
README.md

@@ -3,9 +3,11 @@ Open62541
 
 An open-source communication stack implementation of OPC UA (OPC Unified Architecture) licensed under LGPL + static linking exception.
 
+[![Ohloh Project Status](https://www.ohloh.net/p/open62541/widgets/project_thin_badge.gif)](https://www.ohloh.net/p/open62541)
 [![Build Status](https://travis-ci.org/acplt/open62541.png?branch=master)](https://travis-ci.org/acplt/open62541)
 [![Coverity Scan Build Status](https://scan.coverity.com/projects/1864/badge.svg)](https://scan.coverity.com/projects/1864)
 
+
 ## Getting dependencies
 ### Ubuntu
 ##### Getting gcc toolchain:
@@ -14,7 +16,7 @@ sudo apt-get install build-essential subversion git autoconf libtool texinfo pyt
 ```
 ##### Getting toolchain for tools:
 ```bash
-sudo apt-get install gperf libexpat
+sudo apt-get install expat libexpat1-dev
 ```
 ##### Getting and installing *check* as unit test framework (http://check.sourceforge.net/):
 ```bash

+ 4 - 0
configure.ac

@@ -82,12 +82,16 @@ AS_HELP_STRING([--enable-doxygen],
 
 AM_CONDITIONAL(ENABLE_DOXYGEN, test x"$enabledoxygen" = x"true")
 AC_CHECK_PROGS([DOXYGEN], [doxygen])
+AC_CHECK_PROGS([DOT], [dot])
 
 #break if doxygen enabled but not present
 if test x"$enabledoxygen" = x"true"; then    
 	if test -z "$DOXYGEN"; then 
     		AC_MSG_ERROR([Doxygen not found])
 	fi
+	if test -z "$DOT"; then 
+    		AC_MSG_ERROR([Graphviz not found])
+	fi
 fi
 AM_COND_IF([ENABLE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])])
 #doxygen end

+ 1 - 1
doc/Doxyfile.in

@@ -2172,7 +2172,7 @@ INCLUDED_BY_GRAPH      = YES
 # The default value is: NO.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-CALL_GRAPH             = YES
+CALL_GRAPH             = NO
 
 # If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
 # dependency graph for every global function or class method.

+ 504 - 59
examples/src/xml2ns0.c

@@ -35,6 +35,42 @@ UA_Int32 UA_NodeSetAlias_new(UA_NodeSetAlias** p) {
 	UA_NodeSetAlias_init(*p);
 	return UA_SUCCESS;
 }
+/* References */
+typedef struct UA_NodeSetReferences_T {
+	UA_Int32 size;
+	UA_ReferenceNode** references;
+} UA_NodeSetReferences;
+UA_Int32 UA_NodeSetReferences_init(UA_NodeSetReferences* p) {
+	p->size = -1;
+	p->references = UA_NULL;
+	return UA_SUCCESS;
+}
+UA_Int32 UA_NodeSetReferences_new(UA_NodeSetReferences** p) {
+	UA_alloc((void** )p, sizeof(UA_NodeSetReferences));
+	UA_NodeSetReferences_init(*p);
+	return UA_SUCCESS;
+}
+UA_Int32 UA_ReferenceNode_println(cstring_t label, UA_ReferenceNode *a) {
+	printf("%s{referenceType=%d, target=%d, isInverse=%d}\n",
+			label,
+			a->referenceTypeId.identifier.numeric,
+			a->targetId.nodeId.identifier.numeric,
+			a->isInverse);
+	return UA_SUCCESS;
+}
+UA_Int32 UA_NodeSetReferences_println(cstring_t label, UA_NodeSetReferences *p) {
+	UA_Int32 i;
+	for (i = 0; i < p->size; i++) {
+		UA_ReferenceNode* a = p->references[i];
+		printf("References addr=%p, ", (void*) a);
+		if (a) {
+			UA_ReferenceNode_println("node=",a);
+		}
+		printf("\n");
+	}
+	return UA_SUCCESS;
+}
+
 /* The current set of aliases */
 typedef struct UA_NodeSetAliases_T {
 	UA_Int32 size;
@@ -54,9 +90,9 @@ UA_Int32 UA_NodeSetAliases_println(cstring_t label, UA_NodeSetAliases *p) {
 	UA_Int32 i;
 	for (i = 0; i < p->size; i++) {
 		UA_NodeSetAlias* a = p->aliases[i];
-		printf("Alias addr=%p", (void*)a);
+		printf("Alias addr=%p, ", (void*) a);
 		if (a) {
-			printf("'%.*s'='%.*s", a->alias.length, a->alias.data, a->value.length, a->value.data);
+			printf("alias='%.*s', value='%.*s'", a->alias.length, a->alias.data, a->value.length, a->value.data);
 		}
 		printf("\n");
 	}
@@ -65,11 +101,11 @@ UA_Int32 UA_NodeSetAliases_println(cstring_t label, UA_NodeSetAliases *p) {
 
 /* A nodeset consist of a namespace and a list of aliases */
 typedef struct T_UA_NodeSet {
-	namespace* ns;
+	Namespace* ns;
 	UA_NodeSetAliases aliases;
 } UA_NodeSet;
 UA_Int32 UA_NodeSet_init(UA_NodeSet* p) {
-	create_ns(&(p->ns), 100);
+	Namespace_create(&(p->ns), 100);
 	p->aliases.size = -1;
 	p->aliases.aliases = UA_NULL;
 	return UA_SUCCESS;
@@ -82,8 +118,31 @@ UA_Int32 UA_NodeSet_new(UA_NodeSet** p) {
 UA_Int32 UA_NodeId_copycstring(cstring_t src, UA_NodeId* dst, UA_NodeSetAliases* aliases) {
 	dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
 	dst->namespace = 0;
+	dst->identifier.numeric = 0;
+	// FIXME: assumes i=nnnn, does not care for aliases as of now
+	if (src[1] == '=') {
+		dst->identifier.numeric = atoi(&src[2]);
+	} else {
+		UA_Int32 i;
+		for (i = 0; i < aliases->size && dst->identifier.numeric == 0; ++i) {
+			if (0
+					== strncmp((char const*) src, (char const*) aliases->aliases[i]->alias.data,
+							aliases->aliases[i]->alias.length)) {
+				dst->identifier.numeric = atoi((char const*) &(aliases->aliases[i]->value.data[2]));
+			}
+		}
+	}
+	DBG_VERBOSE(printf("UA_NodeId_copycstring src=%s,id=%d\n", src, dst->identifier.numeric));
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_ExpandedNodeId_copycstring(cstring_t src, UA_ExpandedNodeId* dst, UA_NodeSetAliases* aliases) {
+	dst->nodeId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	dst->nodeId.namespace = 0;
+	dst->nodeId.identifier.numeric = 0;
 	// FIXME: assumes i=nnnn, does not care for aliases as of now
-	dst->identifier.numeric = atoi(&src[2]);
+	UA_NodeId_copycstring(src, &(dst->nodeId), aliases);
+	DBG_VERBOSE(printf("UA_ExpandedNodeId_copycstring src=%s,id=%d\n", src, dst->nodeId.identifier.numeric));
 	return UA_SUCCESS;
 }
 
@@ -141,7 +200,7 @@ void XML_Stack_print(XML_Stack_t* s) {
 }
 
 // FIXME: we might want to calculate textAttribIdx
-void XML_Stack_handleTextAs(XML_Stack_t* p, cstring_t textAttrib, unsigned int textAttribIdx) {
+void XML_Stack_handleTextAsElementOf(XML_Stack_t* p, cstring_t textAttrib, unsigned int textAttribIdx) {
 	p->parent[p->depth].textAttrib = textAttrib;
 	p->parent[p->depth].textAttribIdx = textAttribIdx;
 }
@@ -160,8 +219,55 @@ UA_Int32 UA_Array_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, void* dst, _Bool i
 	return UA_SUCCESS;
 }
 
+UA_Int32 UA_Boolean_copycstring(cstring_t src, UA_Boolean* dst) {
+	*dst = UA_FALSE;
+	if (0 == strncmp(src, "true", 4) || 0 == strncmp(src, "TRUE", 4)) {
+		*dst = UA_TRUE;
+	}
+	return UA_SUCCESS;
+}
+UA_Int32 UA_Boolean_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Boolean* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_Boolean entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_Boolean_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		UA_Boolean_copycstring((cstring_t) attr[1], dst);
+	} else {
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
+		UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_Int16_copycstring(cstring_t src, UA_Int16* dst) {
+	*dst = atoi(src);
+	return UA_SUCCESS;
+}
+UA_Int32 UA_UInt16_copycstring(cstring_t src, UA_UInt16* dst) {
+	*dst = atoi(src);
+	return UA_SUCCESS;
+}
+UA_Int32 UA_Int16_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Int16* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_Int16_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		UA_Int16_copycstring((cstring_t) attr[1], dst);
+	} else {
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
+		UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
 UA_Int32 UA_Int32_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Int32* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_Int32 entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
 			UA_Int32_new(&dst);
@@ -177,7 +283,7 @@ UA_Int32 UA_Int32_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Int32* dst, _Bo
 }
 
 UA_Int32 UA_String_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_String* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_String entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -187,26 +293,107 @@ UA_Int32 UA_String_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_String* dst, _
 		s->parent[s->depth].len = 0;
 		XML_Stack_addChildHandler(s, "Data", (XML_decoder) UA_Array_decodeXML, UA_BYTE, &(dst->data));
 		XML_Stack_addChildHandler(s, "Length", (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->length));
-		XML_Stack_handleTextAs(s, "Data", 0);
+		XML_Stack_handleTextAsElementOf(s, "Data", 0);
 
 		// set attributes
 		for (i = 0; attr[i]; i += 2) {
 			if (0 == strncmp("Data", attr[i], strlen("Data"))) {
 				UA_String_copycstring(attr[i + 1], dst);
 			} else {
-				perror("Unknown attribute");
+				printf("UA_String_decodeXML - Unknown attribute - name=%s, value=%s\n", attr[i], attr[i+1]);
 			}
 		}
 	} else {
 		// TODO: It is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_String clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
-		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =	 UA_NULL;
+		DBG_VERBOSE(
+				printf("UA_String clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_NodeId_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeId* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_NodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	UA_UInt32 i;
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_NodeId_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "Namespace", (XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->namespace));
+		XML_Stack_addChildHandler(s, "Numeric", (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->identifier.numeric));
+		XML_Stack_addChildHandler(s, "Id", (XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
+		XML_Stack_handleTextAsElementOf(s, "Data", 2);
+
+		// set attributes
+		for (i = 0; attr[i]; i += 2) {
+			if (0 == strncmp("Namespace", attr[i], strlen("Namespace"))) {
+				dst->namespace = atoi(attr[i + 1]);
+			} else if (0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
+				dst->identifier.numeric = atoi(attr[i + 1]);
+				dst->encodingByte = UA_NODEIDTYPE_FOURBYTE;
+			} else {
+				printf("UA_NodeId_decodeXML - Unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
+			}
+		}
+	} else {
+		switch (s->parent[s->depth - 1].activeChild) {
+		case 2:
+			UA_NodeId_copycstring((cstring_t)((UA_String*)attr)->data,dst,s->aliases);
+			break;
+		default:
+			break;
+		}
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_String clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+UA_Int32 UA_ExpandedNodeId_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_ExpandedNodeId* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_ExpandedNodeId entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	UA_UInt32 i;
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_ExpandedNodeId_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "NodeId", (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->nodeId));
+		XML_Stack_addChildHandler(s, "Namespace", (XML_decoder) UA_Int16_decodeXML, UA_INT16, &(dst->nodeId.namespace));
+		XML_Stack_addChildHandler(s, "Numeric", (XML_decoder) UA_Int32_decodeXML, UA_INT32,
+				&(dst->nodeId.identifier.numeric));
+		XML_Stack_addChildHandler(s, "Id", (XML_decoder) UA_String_decodeXML, UA_STRING, UA_NULL);
+		XML_Stack_handleTextAsElementOf(s, "Data", 3);
+
+		// set attributes
+		for (i = 0; attr[i]; i += 2) {
+			if (0 == strncmp("Namespace", attr[i], strlen("Namespace"))) {
+				UA_UInt16_copycstring((cstring_t) attr[i + 1], &(dst->nodeId.namespace));
+			} else if (0 == strncmp("Numeric", attr[i], strlen("Numeric"))) {
+				UA_NodeId_copycstring((cstring_t) attr[i + 1], &(dst->nodeId), s->aliases);
+			} else if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
+				UA_NodeId_copycstring((cstring_t) attr[i + 1], &(dst->nodeId), s->aliases);
+			} else {
+				printf("UA_ExpandedNodeId_decodeXML - unknown attribute name=%s, value=%s\n", attr[i], attr[i+1]);
+			}
+		}
+	} else {
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_String clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 	}
 	return UA_SUCCESS;
 }
 
 UA_Int32 UA_LocalizedText_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_LocalizedText* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_LocalizedText entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_LocalizedText entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 	if (isStart) {
 		if (dst == UA_NULL) {
@@ -216,7 +403,7 @@ UA_Int32 UA_LocalizedText_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Localiz
 		s->parent[s->depth].len = 0;
 		XML_Stack_addChildHandler(s, "Text", (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->text));
 		XML_Stack_addChildHandler(s, "Locale", (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->locale));
-		XML_Stack_handleTextAs(s, "Data", 0);
+		XML_Stack_handleTextAsElementOf(s, "Data", 0);
 
 		// set attributes
 		for (i = 0; attr[i]; i += 2) {
@@ -233,23 +420,136 @@ UA_Int32 UA_LocalizedText_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_Localiz
 	} else {
 		switch (s->parent[s->depth - 1].activeChild) {
 		case 0:
-			dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+		dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
 			break;
 		case 1:
-			dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
+		dst->encodingMask |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
 			break;
 		default:
 			break;
 		}
 		// TODO: I think it is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_LocalizedText clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		DBG_VERBOSE(
+				printf("UA_LocalizedText clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_QualifiedName_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_QualifiedName* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_QualifiedName entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	UA_UInt32 i;
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_QualifiedName_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "Name", (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->name));
+		XML_Stack_addChildHandler(s, "NamespaceIndex", (XML_decoder) UA_Int16_decodeXML, UA_STRING,
+				&(dst->namespaceIndex));
+		XML_Stack_handleTextAsElementOf(s, "Data", 0);
+
+		// set attributes
+		for (i = 0; attr[i]; i += 2) {
+			if (0 == strncmp("NamespaceIndex", attr[i], strlen("NamespaceIndex"))) {
+				dst->namespaceIndex = atoi(attr[i + 1]);
+			} else if (0 == strncmp("Name", attr[i], strlen("Name"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->name));
+			} else {
+				perror("Unknown attribute");
+			}
+		}
+	} else {
+		// TODO: I think it is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_LocalizedText clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_ReferenceNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_ReferenceNode* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_ReferenceNode_decodeXML entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	if (isStart) {
+		// create if necessary
+		if (dst == UA_NULL) {
+			UA_ReferenceNode_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		// set handlers
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "ReferenceType", (XML_decoder) UA_NodeId_decodeXML, UA_STRING,
+				&(dst->referenceTypeId));
+		XML_Stack_addChildHandler(s, "IsForward", (XML_decoder) UA_Boolean_decodeXML, UA_STRING, &(dst->isInverse));
+		XML_Stack_addChildHandler(s, "Target", (XML_decoder) UA_ExpandedNodeId_decodeXML, UA_STRING, &(dst->targetId));
+		XML_Stack_handleTextAsElementOf(s, "NodeId", 2);
+
+		// set attributes
+		UA_Int32 i;
+		for (i = 0; attr[i]; i += 2) {
+			if (0 == strncmp("ReferenceType", attr[i], strlen("ReferenceType"))) {
+				UA_NodeId_copycstring(attr[i + 1], &(dst->referenceTypeId), s->aliases);
+			} else if (0 == strncmp("IsForward", attr[i], strlen("IsForward"))) {
+				UA_Boolean_copycstring(attr[i + 1], &(dst->isInverse));
+			} else if (0 == strncmp("Target", attr[i], strlen("Target"))) {
+				UA_ExpandedNodeId_copycstring(attr[i + 1], &(dst->targetId), s->aliases);
+			} else {
+				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
+			}
+		}
+	} else {
+		// sub element is ready
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_ReferenceNode clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 	}
 	return UA_SUCCESS;
 }
 
+UA_Int32 UA_NodeSetReferences_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSetReferences* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_NodeSetReferences entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	if (isStart) {
+		if (dst == UA_NULL) {
+			UA_NodeSetReferences_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "Reference", (XML_decoder) UA_ReferenceNode_decodeXML, UA_REFERENCENODE, UA_NULL);
+	} else {
+		// sub element is ready, add to array
+		if (dst->size < 0 || dst->size == 0) {
+			dst->size = 1;
+			UA_alloc((void** )&(dst->references), dst->size * sizeof(UA_ReferenceNode*));
+			DBG_VERBOSE(
+					printf("allocate references:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->references),
+							dst->size));
+		} else {
+			dst->size++;
+			dst->references = realloc(dst->references, dst->size * sizeof(UA_NodeSetAlias*));
+			DBG_VERBOSE(
+					printf("reallocate references:dst=%p, aliases=%p, size=%d\n", (void* )dst,
+							(void* )(dst->references), dst->size));
+		}
+		// index starts with 0, therefore size-1
+		DBG_VERBOSE(printf("assign alias:dst=%p, src=%p\n", (void* )dst->references[dst->size - 1], (void* )attr));
+		dst->references[dst->size - 1] = (UA_ReferenceNode*) attr;
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_NodeSetReferences clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
+		UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
 UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_DataTypeNode* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_DataTypeNode entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_DataTypeNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	UA_UInt32 i;
 
 	if (isStart) {
@@ -260,8 +560,14 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_DataType
 		}
 
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "DisplayName", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->displayName));
-		XML_Stack_addChildHandler(s, "Description", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT, &(dst->description));
+		XML_Stack_addChildHandler(s, "DisplayName", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+				&(dst->displayName));
+		XML_Stack_addChildHandler(s, "Description", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+				&(dst->description));
+		XML_Stack_addChildHandler(s, "BrowseName", (XML_decoder) UA_QualifiedName_decodeXML, UA_QUALIFIEDNAME,
+				&(dst->description));
+		XML_Stack_addChildHandler(s, "References", (XML_decoder) UA_NodeSetReferences_decodeXML, UA_INVALIDTYPE,
+		UA_NULL);
 
 		// set missing default attributes
 		dst->nodeClass = UA_NODECLASS_DATATYPE;
@@ -280,12 +586,98 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_DataType
 				UA_String_copycstring(attr[i + 1], &(dst->description.text));
 				dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
 			} else {
-				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n",attr[i]));
+				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
 			}
 		}
 	} else {
+		switch (s->parent[s->depth - 1].activeChild) {
+		case 3: // References
+		if (attr != UA_NULL) {
+			UA_NodeSetReferences* references = (UA_NodeSetReferences*) attr;
+			DBG_VERBOSE(
+					printf("finished aliases: references=%p, size=%d\n",(void*)references,(references==UA_NULL)?-1:references->size));
+			dst->referencesSize = references->size;
+			dst->references = references->references;
+		}
+			break;
+		default:
+			break;
+		}
 		// TODO: It is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_DataTypeNode clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		DBG_VERBOSE(
+				printf("UA_DataTypeNode clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
+		UA_NULL;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_VariableNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_VariableNode* dst, _Bool isStart) {
+	DBG_VERBOSE(printf("UA_VariableNode entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
+	UA_UInt32 i;
+
+	if (isStart) {
+		// create a new object if called with UA_NULL
+		if (dst == UA_NULL) {
+			UA_VariableNode_new(&dst);
+			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
+		}
+
+		s->parent[s->depth].len = 0;
+		XML_Stack_addChildHandler(s, "DisplayName", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+				&(dst->displayName));
+		XML_Stack_addChildHandler(s, "Description", (XML_decoder) UA_LocalizedText_decodeXML, UA_LOCALIZEDTEXT,
+				&(dst->description));
+		// XML_Stack_addChildHandler(s, "DataType", (XML_decoder) UA_NodeId_decodeXML, UA_NODEID, &(dst->dataType));
+		XML_Stack_addChildHandler(s, "ValueRank", (XML_decoder) UA_Int32_decodeXML, UA_INT32, &(dst->valueRank));
+		XML_Stack_addChildHandler(s, "References", (XML_decoder) UA_NodeSetReferences_decodeXML, UA_INVALIDTYPE,
+		UA_NULL);
+
+		// set missing default attributes
+		dst->nodeClass = UA_NODECLASS_VARIABLE;
+
+		// set attributes
+		for (i = 0; attr[i]; i += 2) {
+			if (0 == strncmp("NodeId", attr[i], strlen("NodeId"))) {
+				UA_NodeId_copycstring(attr[i + 1], &(dst->nodeId), s->aliases);
+			} else if (0 == strncmp("DataType", attr[i], strlen("DataType"))) {
+				UA_NodeId_copycstring(attr[i + 1], &(dst->dataType), s->aliases);
+			} else if (0 == strncmp("ValueRank", attr[i], strlen("ValueRank"))) {
+				dst->valueRank = atoi(attr[i + 1]);
+			} else if (0 == strncmp("ParentNodeId", attr[i], strlen("ParentNodeId"))) {
+				// FIXME: I do not know what to do with this parameter
+			} else if (0 == strncmp("BrowseName", attr[i], strlen("BrowseName"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->browseName.name));
+				dst->browseName.namespaceIndex = 0;
+			} else if (0 == strncmp("DisplayName", attr[i], strlen("DisplayName"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->displayName.text));
+				dst->displayName.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+			} else if (0 == strncmp("Description", attr[i], strlen("Description"))) {
+				UA_String_copycstring(attr[i + 1], &(dst->description.text));
+				dst->description.encodingMask = UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
+			} else {
+				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
+			}
+		}
+	} else {
+		switch (s->parent[s->depth - 1].activeChild) {
+		case 3: // References
+		if (attr != UA_NULL) {
+			UA_NodeSetReferences* references = (UA_NodeSetReferences*) attr;
+			DBG_VERBOSE(
+					printf("finished aliases: references=%p, size=%d\n",(void*)references,(references==UA_NULL)?-1:references->size));
+			dst->referencesSize = references->size;
+			dst->references = references->references;
+		}
+			break;
+		default:
+			break;
+		}
+		// TODO: It is a design flaw that we need to do this here, isn't it?
+		DBG_VERBOSE(
+				printf("UA_DataTypeNode clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
 		UA_NULL;
 	}
@@ -294,13 +686,42 @@ UA_Int32 UA_DataTypeNode_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_DataType
 
 void print_node(UA_Node const * node) {
 	if (node != UA_NULL) {
-		UA_NodeId_printf("---------------------------\nnode.NodeId=", &(node->nodeId));
-		printf("node.browseName='%.*s'\n", node->browseName.name.length, node->browseName.name.data);
+		UA_NodeId_printf("--- node.nodeId=", &(node->nodeId));
+		printf("\t.browseName='%.*s'\n", node->browseName.name.length, node->browseName.name.data);
+		printf("\t.displayName='%.*s'\n", node->displayName.text.length, node->displayName.text.data);
+		printf("\t.description='%.*s%s'\n", node->description.text.length > 40 ? 40 : node->description.text.length,
+				node->description.text.data, node->description.text.length > 40 ? "..." : "");
+		printf("\t.nodeClass=%d\n", node->nodeClass);
+		printf("\t.writeMask=%d\n", node->writeMask);
+		printf("\t.userWriteMask=%d\n", node->userWriteMask);
+		printf("\t.referencesSize=%d\n", node->referencesSize);
+		UA_Int32 i;
+		for (i=0;i<node->referencesSize;i++) {
+			printf("\t   .references[%d]", i);
+			UA_ReferenceNode_println("=",node->references[i]);
+		}
+		switch (node->nodeClass) {
+		case UA_NODECLASS_VARIABLE: {
+			UA_VariableNode const * p = (UA_VariableNode const *) node;
+			printf("\t----- UA_VariableNode ----- \n");
+			UA_NodeId_printf("\t.dataType=", &(p->dataType));
+			printf("\t.valueRank=%d\n", p->valueRank);
+			printf("\t.accessLevel=%d\n", p->accessLevel);
+			printf("\t.userAccessLevel=%d\n", p->userAccessLevel);
+			printf("\t.arrayDimensionsSize=%d\n", p->arrayDimensionsSize);
+			printf("\t.minimumSamplingInterval=%f\n", p->minimumSamplingInterval);
+			printf("\t.historizing=%d\n", p->historizing);
+		}
+			break;
+		// case UA_NODECLASS_DATATYPE:
+		default:
+			break;
+		}
 	}
 }
 
 UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSetAlias* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_NodeSetAlias entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_NodeSetAlias entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		// create if necessary
 		if (dst == UA_NULL) {
@@ -311,7 +732,7 @@ UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSetA
 		s->parent[s->depth].len = 0;
 		XML_Stack_addChildHandler(s, "Alias", (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->alias));
 		XML_Stack_addChildHandler(s, "Value", (XML_decoder) UA_String_decodeXML, UA_STRING, &(dst->value));
-		XML_Stack_handleTextAs(s, "Data", 1);
+		XML_Stack_handleTextAsElementOf(s, "Data", 1);
 
 		// set attributes
 		UA_Int32 i;
@@ -321,20 +742,22 @@ UA_Int32 UA_NodeSetAlias_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSetA
 			} else if (0 == strncmp("Value", attr[i], strlen("Value"))) {
 				UA_String_copycstring(attr[i + 1], &(dst->value));
 			} else {
-				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n",attr[i]));
+				DBG_ERR(XML_Stack_print(s));DBG_ERR(printf("%s - unknown attribute\n", attr[i]));
 			}
 		}
 	} else {
 		// sub element is ready
 		// TODO: It is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_NodeSetAlias clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		DBG_VERBOSE(
+				printf("UA_NodeSetAlias clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 	}
 	return UA_SUCCESS;
 }
 
 UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSetAliases* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_NodeSetALiases entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_NodeSetALiases entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
 			UA_NodeSetAliases_new(&dst);
@@ -347,17 +770,23 @@ UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSe
 		if (dst->size < 0 || dst->size == 0) {
 			dst->size = 1;
 			UA_alloc((void** )&(dst->aliases), dst->size * sizeof(UA_NodeSetAlias*));
-			DBG_VERBOSE(printf("allocate aliases:dst=%p, aliases=%p, size=%d\n",(void*)dst,(void*)(dst->aliases),dst->size));
+			DBG_VERBOSE(
+					printf("allocate aliases:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->aliases),
+							dst->size));
 		} else {
 			dst->size++;
 			dst->aliases = realloc(dst->aliases, dst->size * sizeof(UA_NodeSetAlias*));
-			DBG_VERBOSE(printf("reallocate aliases:dst=%p, aliases=%p, size=%d\n",(void*)dst,(void*)(dst->aliases),dst->size));
+			DBG_VERBOSE(
+					printf("reallocate aliases:dst=%p, aliases=%p, size=%d\n", (void* )dst, (void* )(dst->aliases),
+							dst->size));
 		}
 		// index starts with 0, therefore size-1
-		DBG_VERBOSE(printf("assign alias:dst=%p, src=%p\n",(void*)dst->aliases[dst->size - 1],(void*)attr));
+		DBG_VERBOSE(printf("assign alias:dst=%p, src=%p\n", (void* )dst->aliases[dst->size - 1], (void* )attr));
 		dst->aliases[dst->size - 1] = (UA_NodeSetAlias*) attr;
 		// TODO: It is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_NodeSetAliases clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		DBG_VERBOSE(
+				printf("UA_NodeSetAliases clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj =
 		UA_NULL;
 	}
@@ -365,37 +794,43 @@ UA_Int32 UA_NodeSetAliases_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSe
 }
 
 UA_Int32 UA_NodeSet_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSet* dst, _Bool isStart) {
-	DBG_VERBOSE(printf("UA_NodeSet entered with dst=%p,isStart=%d\n", (void*) dst,isStart));
+	DBG_VERBOSE(printf("UA_NodeSet entered with dst=%p,isStart=%d\n", (void* ) dst, isStart));
 	if (isStart) {
 		if (dst == UA_NULL) {
 			UA_NodeSet_new(&dst);
 			s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = (void*) dst;
 		}
 		s->parent[s->depth].len = 0;
-		XML_Stack_addChildHandler(s, "Aliases", (XML_decoder) UA_NodeSetAliases_decodeXML, UA_INVALIDTYPE, &(dst->aliases));
+		XML_Stack_addChildHandler(s, "Aliases", (XML_decoder) UA_NodeSetAliases_decodeXML, UA_INVALIDTYPE,
+				&(dst->aliases));
 		XML_Stack_addChildHandler(s, "UADataType", (XML_decoder) UA_DataTypeNode_decodeXML, UA_DATATYPENODE, UA_NULL);
+		XML_Stack_addChildHandler(s, "UAVariable", (XML_decoder) UA_VariableNode_decodeXML, UA_VARIABLENODE, UA_NULL);
 	} else {
 		switch (s->parent[s->depth - 1].activeChild) {
 		case 0: // Aliases
-			if (attr != UA_NULL) {
-				UA_NodeSetAliases* aliases = (UA_NodeSetAliases*) attr;
-				DBG_VERBOSE(printf("finished aliases: aliases=%p, size=%d\n",(void*)aliases,(aliases==UA_NULL)?-1:aliases->size));
-				s->aliases = aliases;
-			}
+		if (attr != UA_NULL) {
+			UA_NodeSetAliases* aliases = (UA_NodeSetAliases*) attr;
+			DBG_VERBOSE(
+					printf("finished aliases: aliases=%p, size=%d\n",(void*)aliases,(aliases==UA_NULL)?-1:aliases->size));
+			s->aliases = aliases;
+		}
 			break;
 		case 1:
-			if (attr != UA_NULL) {
-				UA_Node* node = (UA_Node*) attr;
-				DBG_VERBOSE(printf("finished node: node=%p\n",(void*)node));
-				insert_node(dst->ns, node);
-				DBG_VERBOSE(printf("Inserting "));DBG_VERBOSE(print_node(node));
-			}
+		case 2:
+		if (attr != UA_NULL) {
+			UA_Node* node = (UA_Node*) attr;
+			DBG_VERBOSE(printf("finished node: node=%p\n", (void* )node));
+			Namespace_insert(dst->ns, node);
+			DBG_VERBOSE(printf("Inserting "));DBG_VERBOSE(print_node(node));
+		}
 			break;
 		default:
 			break;
 		}
 		// TODO: It is a design flaw that we need to do this here, isn't it?
-		DBG_VERBOSE(printf("UA_NodeSet clears %p\n", (void*) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
+		DBG_VERBOSE(
+				printf("UA_NodeSet clears %p\n",
+						(void* ) (s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj)));
 		s->parent[s->depth - 1].children[s->parent[s->depth - 1].activeChild].obj = UA_NULL;
 	}
 	return UA_SUCCESS;
@@ -410,7 +845,8 @@ void XML_Stack_startElement(void * data, const char *el, const char **attr) {
 	XML_Parent_t* cp = &s->parent[s->depth];
 	for (i = 0; i < cp->len; i++) {
 		if (0 == strncmp(cp->children[i].name, el, strlen(cp->children[i].name))) {
-			DBG_VERBOSE(XML_Stack_print(s));DBG_VERBOSE(printf("%s - processing\n",el));
+			DBG_VERBOSE(XML_Stack_print(s));
+			DBG_VERBOSE(printf("%s - processing\n", el));
 
 			cp->activeChild = i;
 
@@ -427,7 +863,8 @@ void XML_Stack_startElement(void * data, const char *el, const char **attr) {
 		}
 	}
 // if we come here we rejected the processing of el
-	DBG_VERBOSE(XML_Stack_print(s));DBG_VERBOSE(printf("%s - rejected\n",el));
+	DBG_VERBOSE(XML_Stack_print(s));
+	DBG_VERBOSE(printf("%s - rejected\n", el));
 	s->depth++;
 	s->parent[s->depth].name = el;
 // this should be sufficient to reject the children as well
@@ -456,14 +893,18 @@ void XML_Stack_handleText(void * data, const char *txt, int len) {
 			UA_alloc((void** )&buf, len + 1);
 			strncpy(buf, txt, len);
 			buf[len] = 0;
-	//		XML_Attr_t attr[3] = { cp->textAttrib, buf, UA_NULL };
-			DBG_VERBOSE(printf("handleText calls start elementHandler %s with dst=%p, attr=%p\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj, (void*) attr));
-			// cp->children[cp->activeChild].elementHandler(s, attr, cp->children[cp->activeChild].obj, TRUE);
-			DBG_VERBOSE(printf("handleText calls finish elementHandler %s with dst=%p, attr=(nil)\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj));
+			XML_Attr_t attr[3] = { cp->textAttrib, buf, UA_NULL };
+			DBG_VERBOSE(
+					printf("handleText calls start elementHandler %s with dst=%p, attr=%p\n",
+							cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj, (void* ) attr));
+			cp->children[cp->activeChild].elementHandler(s, attr, cp->children[cp->activeChild].obj, TRUE);
+			// FIXME: The indices of this call are simply wrong, so no finishing as of yet
+			// DBG_VERBOSE(printf("handleText calls finish elementHandler %s with dst=%p, attr=(nil)\n", cp->children[cp->activeChild].name, cp->children[cp->activeChild].obj));
 			// cp->children[cp->activeChild].elementHandler(s, UA_NULL, cp->children[cp->activeChild].obj, FALSE);
 			UA_free(buf);
 		} else {
-			DBG_VERBOSE(XML_Stack_print(s));DBG_VERBOSE(printf("textData - ignore text data '%.*s'\n",len,txt));
+			DBG_VERBOSE(XML_Stack_print(s));
+			DBG_VERBOSE(printf("textData - ignore text data '%.*s'\n", len, txt));
 		}
 	}
 }
@@ -478,8 +919,12 @@ void XML_Stack_endElement(void *data, const char *el) {
 		XML_Parent_t* cp = &(s->parent[s->depth - 1]);
 		XML_Parent_t* cpp = &(s->parent[s->depth - 2]);
 		if (cpp->activeChild >= 0 && cp->activeChild >= 0) {
-			DBG_VERBOSE(XML_Stack_print(s));DBG_VERBOSE(printf(" - inform pop %s, arg=%p\n", cpp->children[cpp->activeChild].name, (void*) cp->children[cp->activeChild].obj));
-			cpp->children[cpp->activeChild].elementHandler(s, (XML_Attr_t*) cp->children[cp->activeChild].obj, cpp->children[cpp->activeChild].obj, FALSE);
+			DBG_VERBOSE(XML_Stack_print(s));
+			DBG_VERBOSE(
+					printf(" - inform pop %s, arg=%p\n", cpp->children[cpp->activeChild].name,
+							(void* ) cp->children[cp->activeChild].obj));
+			cpp->children[cpp->activeChild].elementHandler(s, (XML_Attr_t*) cp->children[cp->activeChild].obj,
+					cpp->children[cpp->activeChild].obj, FALSE);
 		}
 		// reset
 		cp->activeChild = -1;
@@ -506,8 +951,8 @@ int main() {
 		}
 	}
 	XML_ParserFree(parser);
-	iterate_ns(n.ns, print_node);
-	DBG_VERBOSE(printf("aliases addr=%p\n",(void*)&(n.aliases)));
-	DBG_VERBOSE(UA_NodeSetAliases_println("aliases in nodeset: ",&n.aliases));
+	Namespace_iterate(n.ns, print_node);
+	printf("aliases addr=%p, size=%d\n", (void*) &(n.aliases), n.aliases.size);
+	UA_NodeSetAliases_println("aliases in nodeset: ", &n.aliases);
 	return 0;
 }

+ 6 - 4
src/ua_application.c

@@ -27,11 +27,13 @@ UA_Node* create_node_ns0(UA_Int32 class, UA_Int32 nodeClass, UA_Int32 const id,
 #define C2UA_STRING(s) (UA_String) { sizeof(s)-1, (UA_Byte*) s }
 void appMockup_init() {
 	// create namespaces
-	namespace* ns0; create_ns(&ns0,100);
+	Namespace* ns0;
+	Namespace_create(&ns0,100);
 	ns0->namespaceId = 0;
 	ns0->namespaceUri = C2UA_STRING("http://opcfoundation.org/UA/");
 
-	namespace* local; create_ns(&local,100);
+	Namespace* local;
+	Namespace_create(&local,100);
 	local->namespaceId = 1;
 	local->namespaceUri = C2UA_STRING("http://localhost:16664/open62541/");
 
@@ -42,7 +44,7 @@ void appMockup_init() {
 
 	UA_Node* np;
 	np = create_node_ns0(UA_OBJECTNODE, UA_NODECLASS_OBJECT, 2253, "Server", "open62541", "...");
-	insert_node(ns0,np);
+	Namespace_insert(ns0,np);
 	UA_ObjectNode* o = (UA_ObjectNode*)np;
 	o->eventNotifier = UA_FALSE;
 
@@ -60,7 +62,7 @@ void appMockup_init() {
 	v->minimumSamplingInterval = 1.0;
 	v->historizing = UA_FALSE;
 
-	insert_node(ns0,np);
+	Namespace_insert(ns0,np);
 
 #if defined(DEBUG) && defined(VERBOSE)
 	uint32_t i, j;

+ 319 - 287
src/ua_namespace.c

@@ -2,14 +2,19 @@
 #include <string.h>
 #include <stdio.h>
 
-UA_Int32 init_tc(transaction_context * tc) {
-	return UA_list_init((UA_list_List*) tc);
+/*****************************************/
+/* Internal (not exported) functionality */
+/*****************************************/
+
+UA_Int32 Namespace_TransactionContext_init(Namespace_TransactionContext * tc) {
+	return UA_list_init((UA_list_List *) tc);
 }
 
-/* The central data structure is a hash-map of UA_Node objects.
-   Entry lookup via Algorithm D from Knuth's TAOCP (no linked lists here).
-   Table of primes and mod-functions are from libiberty (licensed under LGPL) */
+/* The central data structure is a hash-map of UA_Node objects. Entry lookup via Algorithm D from
+   Knuth's TAOCP (no linked lists here). Table of primes and mod-functions are from libiberty
+   (licensed under LGPL) */
 
+typedef UA_UInt32 hash_t;
 struct prime_ent {
 	hash_t prime;
 	hash_t inv;
@@ -18,303 +23,175 @@ struct prime_ent {
 };
 
 static struct prime_ent const prime_tab[] = {
-  {          7, 0x24924925, 0x9999999b, 2 },
-  {         13, 0x3b13b13c, 0x745d1747, 3 },
-  {         31, 0x08421085, 0x1a7b9612, 4 },
-  {         61, 0x0c9714fc, 0x15b1e5f8, 5 },
-  {        127, 0x02040811, 0x0624dd30, 6 },
-  {        251, 0x05197f7e, 0x073260a5, 7 },
-  {        509, 0x01824366, 0x02864fc8, 8 },
-  {       1021, 0x00c0906d, 0x014191f7, 9 },
-  {       2039, 0x0121456f, 0x0161e69e, 10 },
-  {       4093, 0x00300902, 0x00501908, 11 },
-  {       8191, 0x00080041, 0x00180241, 12 },
-  {      16381, 0x000c0091, 0x00140191, 13 },
-  {      32749, 0x002605a5, 0x002a06e6, 14 },
-  {      65521, 0x000f00e2, 0x00110122, 15 },
-  {     131071, 0x00008001, 0x00018003, 16 },
-  {     262139, 0x00014002, 0x0001c004, 17 },
-  {     524287, 0x00002001, 0x00006001, 18 },
-  {    1048573, 0x00003001, 0x00005001, 19 },
-  {    2097143, 0x00004801, 0x00005801, 20 },
-  {    4194301, 0x00000c01, 0x00001401, 21 },
-  {    8388593, 0x00001e01, 0x00002201, 22 },
-  {   16777213, 0x00000301, 0x00000501, 23 },
-  {   33554393, 0x00001381, 0x00001481, 24 },
-  {   67108859, 0x00000141, 0x000001c1, 25 },
-  {  134217689, 0x000004e1, 0x00000521, 26 },
-  {  268435399, 0x00000391, 0x000003b1, 27 },
-  {  536870909, 0x00000019, 0x00000029, 28 },
-  { 1073741789, 0x0000008d, 0x00000095, 29 },
-  { 2147483647, 0x00000003, 0x00000007, 30 },
-  /* Avoid "decimal constant so large it is unsigned" for 4294967291.  */
-  { 0xfffffffb, 0x00000006, 0x00000008, 31 }
+	{7, 0x24924925, 0x9999999b, 2},
+	{13, 0x3b13b13c, 0x745d1747, 3},
+	{31, 0x08421085, 0x1a7b9612, 4},
+	{61, 0x0c9714fc, 0x15b1e5f8, 5},
+	{127, 0x02040811, 0x0624dd30, 6},
+	{251, 0x05197f7e, 0x073260a5, 7},
+	{509, 0x01824366, 0x02864fc8, 8},
+	{1021, 0x00c0906d, 0x014191f7, 9},
+	{2039, 0x0121456f, 0x0161e69e, 10},
+	{4093, 0x00300902, 0x00501908, 11},
+	{8191, 0x00080041, 0x00180241, 12},
+	{16381, 0x000c0091, 0x00140191, 13},
+	{32749, 0x002605a5, 0x002a06e6, 14},
+	{65521, 0x000f00e2, 0x00110122, 15},
+	{131071, 0x00008001, 0x00018003, 16},
+	{262139, 0x00014002, 0x0001c004, 17},
+	{524287, 0x00002001, 0x00006001, 18},
+	{1048573, 0x00003001, 0x00005001, 19},
+	{2097143, 0x00004801, 0x00005801, 20},
+	{4194301, 0x00000c01, 0x00001401, 21},
+	{8388593, 0x00001e01, 0x00002201, 22},
+	{16777213, 0x00000301, 0x00000501, 23},
+	{33554393, 0x00001381, 0x00001481, 24},
+	{67108859, 0x00000141, 0x000001c1, 25},
+	{134217689, 0x000004e1, 0x00000521, 26},
+	{268435399, 0x00000391, 0x000003b1, 27},
+	{536870909, 0x00000019, 0x00000029, 28},
+	{1073741789, 0x0000008d, 0x00000095, 29},
+	{2147483647, 0x00000003, 0x00000007, 30},
+	/* Avoid "decimal constant so large it is unsigned" for 4294967291.  */
+	{0xfffffffb, 0x00000006, 0x00000008, 31}
 };
 
-UA_Int32 create_ns(namespace **result, uint32_t size) {
-	namespace *ns = UA_NULL;
-	uint32_t sizePrimeIndex = higher_prime_index(size);
-	size = prime_tab[sizePrimeIndex].prime;
-
-	if (UA_alloc((void **)&ns, sizeof(namespace)) != UA_SUCCESS) return UA_ERR_NO_MEMORY;
-  
-	if (UA_alloc((void **)&ns->entries, sizeof(ns_entry) * size) != UA_SUCCESS) {
-		UA_free(ns);
-		return UA_ERR_NO_MEMORY;
-	}
-
-    /* set entries to zero	
-	ns->entries[i].lock = UA_NUll;
-	ns->entries[i].node = UA_NULL; */
-	memset(ns->entries, 0, size * sizeof(ns_entry));
-
-	ns->size = size;
-	ns->count = 0;
-	ns->sizePrimeIndex = sizePrimeIndex;
-	*result = ns;
-	return UA_SUCCESS;
-}
-
-void empty_ns(namespace *ns) {
-	clear_ns(ns);
-	
-	/* Downsize the table.  */
-	if (ns->size > 1024*1024 / sizeof (ns_entry)) {
-		int nindex = higher_prime_index (1024 / sizeof (ns_entry));
-		int nsize = prime_tab[nindex].prime;
-		UA_free(ns->entries);
-		UA_alloc((void **)&ns->entries, sizeof(ns_entry) * nsize); //FIXME: Check return value
-		ns->size = nsize;
-		ns->sizePrimeIndex = nindex;
-	}
-}
-
-/* This function frees all memory allocated for a namespace */
-void delete_ns (namespace *ns) {
-	clear_ns(ns);
-	UA_free(ns->entries);
-	UA_free(ns);
-}
-
-UA_Int32 insert_node(namespace *ns, UA_Node *node) {
-	if(ns->size * 3 <= ns->count*4) {
-		if(expand(ns) != UA_SUCCESS)
-			return UA_ERROR;
-	}
-		
-	hash_t h = hash(&node->nodeId);
-	ns_entry *slot = find_empty_slot(ns, h);
-#ifdef MULTITHREADING
-	if (UA_alloc((void **)&slot->lock, sizeof(pthread_rwlock_t)) != UA_SUCCESS)
-		return UA_ERR_NO_MEMORY;
-	pthread_rwlock_init((pthread_rwlock_t *)slot->lock, NULL);
-#endif
-	slot->node = node;
-	ns->count++;
-	return UA_SUCCESS;
-}
-
-UA_Int32 get_node(namespace const *ns, const UA_NodeId *nodeid, UA_Node const ** result, ns_lock ** lock) {
-	ns_entry *slot;
-	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
-#ifdef MULTITHREADING
-	if(pthread_rwlock_rdlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
-	*lock = slot->lock;
-#endif
-	*result = slot->node;
-	return UA_SUCCESS;
-}
-
-UA_Int32 get_writable_node(const namespace *ns, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
-	ns_entry *slot;
-	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
-#ifdef MULTITHREADING
-	if(pthread_rwlock_wrlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
-	*lock = slot->lock;
-#endif
-	*result = slot->node;
-	return UA_SUCCESS;
-}
-
-#ifdef MULTITHREADING
-static inline void release_context_walker(void * lock) { pthread_rwlock_unlock(lock); }
-#endif
-
-UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
-	ns_entry *slot;
-	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
-#ifdef MULTITHREADING
-	if(pthread_rwlock_tryrdlock((pthread_rwlock_t *)slot->lock) != 0) {
-		/* Transaction failed. Release all acquired locks and bail out. */
-		UA_list_destroy((UA_list_List*) tc, release_context_walker);
-		return UA_ERROR;
-	}
-	UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
-	*lock = slot->lock;
-#endif
-	*result = slot->node;
-	return UA_SUCCESS;
-}
-
-UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
-	ns_entry *slot;
-	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
-#ifdef MULTITHREADING
-	if(pthread_rwlock_trywrlock((pthread_rwlock_t *)slot->lock) != 0) {
-		/* Transaction failed. Release all acquired locks and bail out. */
-		UA_list_destroy((UA_list_List*) tc, release_context_walker);
-		return UA_ERROR;
-	}
-	UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
-	*lock = slot->lock;
-#endif
-	*result = slot->node;
-	return UA_SUCCESS;
-}
-
-void delete_node(namespace *ns, UA_NodeId *nodeid) {
-	ns_entry *slot;
-	if (find_slot(ns, &slot, nodeid) != UA_SUCCESS)
-		return;
-	// TODO: Check if deleting the node makes the namespace inconsistent.
-	clear_slot(ns, slot);
-
-	/* Downsize the hashmap if it is very empty */
-	if(ns->count*8 < ns->size && ns->size > 32)
-		expand(ns);
-}
-
-/* Hashing inspired by code from from
-   http://www.azillionmonkeys.com/qed/hash.html, licensed under the LGPL 2.1 */
+/* Hashing inspired by code from from http://www.azillionmonkeys.com/qed/hash.html, licensed under
+   the LGPL 2.1 */
 #undef get16bits
-#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || \
+	defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
 #define get16bits(d) (*((const uint16_t *) (d)))
 #endif
 
 #if !defined (get16bits)
-#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) +(uint32_t)(((const uint8_t *)(d))[0]) )
+#define get16bits(d) ((((UA_UInt32)(((const uint8_t *)(d))[1])) << 8) + \
+					  (UA_UInt32)(((const uint8_t *)(d))[0]) )
 #endif
 
-static hash_t hash_string (const UA_Byte * data, UA_Int32 len) {
+static inline hash_t hash_string(const UA_Byte * data, UA_Int32 len) {
 	hash_t hash = len;
 	hash_t tmp;
 	int rem;
 
-    if (len <= 0 || data == UA_NULL) return 0;
+	if(len <= 0 || data == UA_NULL)
+		return 0;
 
-    rem = len & 3;
-    len >>= 2;
+	rem = len & 3;
+	len >>= 2;
 
-    /* Main loop */
-    for (;len > 0; len--) {
-        hash  += get16bits (data);
-        tmp    = (get16bits (data+2) << 11) ^ hash;
-        hash   = (hash << 16) ^ tmp;
-        data  += 2*sizeof (uint16_t);
-        hash  += hash >> 11;
-    }
+	/* Main loop */
+	for(; len > 0; len--) {
+		hash += get16bits(data);
+		tmp = (get16bits(data + 2) << 11) ^ hash;
+		hash = (hash << 16) ^ tmp;
+		data += 2 * sizeof(uint16_t);
+		hash += hash >> 11;
+	}
 
-    /* Handle end cases */
-    switch (rem) {
-	case 3: hash += get16bits (data);
+	/* Handle end cases */
+	switch (rem) {
+	case 3:
+		hash += get16bits(data);
 		hash ^= hash << 16;
-		hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;
+		hash ^= ((signed char)data[sizeof(uint16_t)]) << 18;
 		hash += hash >> 11;
 		break;
-	case 2: hash += get16bits (data);
+	case 2:
+		hash += get16bits(data);
 		hash ^= hash << 11;
 		hash += hash >> 17;
 		break;
-	case 1: hash += (signed char)*data;
+	case 1:
+		hash += (signed char)*data;
 		hash ^= hash << 10;
 		hash += hash >> 1;
 		break;
-    }
+	}
 
-    /* Force "avalanching" of final 127 bits */
-    hash ^= hash << 3;
-    hash += hash >> 5;
-    hash ^= hash << 4;
-    hash += hash >> 17;
-    hash ^= hash << 25;
-    hash += hash >> 6;
+	/* Force "avalanching" of final 127 bits */
+	hash ^= hash << 3;
+	hash += hash >> 5;
+	hash ^= hash << 4;
+	hash += hash >> 17;
+	hash ^= hash << 25;
+	hash += hash >> 6;
 
-    return hash;
+	return hash;
 }
 
-static hash_t hash(const UA_NodeId *n) {
+static inline hash_t hash(const UA_NodeId * n) {
 	switch (n->encodingByte) {
 	case UA_NODEIDTYPE_TWOBYTE:
 	case UA_NODEIDTYPE_FOURBYTE:
 	case UA_NODEIDTYPE_NUMERIC:
-		return (n->identifier.numeric * 2654435761) % 2^32; // Knuth's multiplicative hashing
+		return (n->identifier.numeric * 2654435761) % 2 ^ 32;	// Knuth's multiplicative hashing
 	case UA_NODEIDTYPE_STRING:
 		return hash_string(n->identifier.string.data, n->identifier.string.length);
 	case UA_NODEIDTYPE_GUID:
-		return hash_string((UA_Byte*) &(n->identifier.guid), sizeof(UA_Guid));
+		return hash_string((UA_Byte *) & (n->identifier.guid), sizeof(UA_Guid));
 	case UA_NODEIDTYPE_BYTESTRING:
-		return hash_string((UA_Byte*) n->identifier.byteString.data, n->identifier.byteString.length);
+		return hash_string((UA_Byte *) n->identifier.byteString.data, n->identifier.byteString.length);
 	default:
 		return 0;
 	}
 }
 
-/* The following function returns an index into the above table of the nearest prime number which is greater than N, and near a power of two. */
-static unsigned int higher_prime_index (unsigned long n) {
+/* The following function returns an index into the above table of the nearest prime number which
+   is greater than N, and near a power of two. */
+static inline unsigned int higher_prime_index(unsigned long n) {
 	unsigned int low = 0;
 	unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
 
-	while (low != high) {
+	while(low != high) {
 		unsigned int mid = low + (high - low) / 2;
-		if (n > prime_tab[mid].prime)
+		if(n > prime_tab[mid].prime)
 			low = mid + 1;
 		else
 			high = mid;
 	}
 
-	/* if (n > prime_tab[low].prime) */
-	/* 	abort ();  */
 	return low;
 }
 
-/* Return X % Y. */
-static inline hash_t mod_1 (hash_t x, hash_t y, hash_t inv, int shift) {
-	/* The multiplicative inverses computed above are for 32-bit types, and requires that we are able to compute a highpart multiply.  */
+static inline hash_t mod_1(hash_t x, hash_t y, hash_t inv, int shift) {
+	/* The multiplicative inverses computed above are for 32-bit types, and requires that we are
+	   able to compute a highpart multiply.  */
 #ifdef UNSIGNED_64BIT_TYPE
 	__extension__ typedef UNSIGNED_64BIT_TYPE ull;
-	if (sizeof (hash_t) * CHAR_BIT <= 32) {
+	if(sizeof(hash_t) * CHAR_BIT <= 32) {
 		hash_t t1, t2, t3, t4, q, r;
-		t1 = ((ull)x * inv) >> 32;
+		t1 = ((ull) x * inv) >> 32;
 		t2 = x - t1;
 		t3 = t2 >> 1;
 		t4 = t1 + t3;
-		q  = t4 >> shift;
-		r  = x - (q * y);
+		q = t4 >> shift;
+		r = x - (q * y);
 		return r;
 	}
 #endif
-
-	return x % y; /* Otherwise just use the native division routines.  */
+	return x % y;
 }
 
-static inline hash_t mod (hash_t h, const namespace *ns) {
+static inline hash_t mod(hash_t h, const Namespace * ns) {
 	const struct prime_ent *p = &prime_tab[ns->sizePrimeIndex];
-	return mod_1 (h, p->prime, p->inv, p->shift);
+	return mod_1(h, p->prime, p->inv, p->shift);
 }
 
-static inline hash_t mod_m2 (hash_t h, const namespace *ns) {
+static inline hash_t mod_m2(hash_t h, const Namespace * ns) {
 	const struct prime_ent *p = &prime_tab[ns->sizePrimeIndex];
-	return 1 + mod_1 (h, p->prime - 2, p->inv_m2, p->shift);
+	return 1 + mod_1(h, p->prime - 2, p->inv_m2, p->shift);
 }
 
-static inline void clear_slot(namespace *ns, ns_entry *slot) {
+static inline void clear_slot(Namespace * ns, Namespace_Entry * slot) {
 	if(slot->node == UA_NULL)
 		return;
-	
+
 #ifdef MULTITHREADING
-	pthread_rwlock_wrlock((pthread_rwlock_t *) slot->lock); /* Get write lock. */
+	pthread_rwlock_wrlock((pthread_rwlock_t *) slot->lock);	/* Get write lock. */
 #endif
-	switch(slot->node->nodeClass) {
+
+	switch (slot->node->nodeClass) {
 	case UA_NODECLASS_OBJECT:
 		UA_ObjectNode_delete((UA_ObjectNode *) slot->node);
 		break;
@@ -343,129 +220,284 @@ static inline void clear_slot(namespace *ns, ns_entry *slot) {
 		break;
 	}
 	slot->node = UA_NULL;
+
 #ifdef MULTITHREADING
-	pthread_rwlock_destroy((pthread_rwlock_t *)slot->lock);
+	pthread_rwlock_destroy((pthread_rwlock_t *) slot->lock);
 	UA_free(slot->lock);
 #endif
-}
 
-/* Delete all entries */
-static void clear_ns(namespace *ns) {
-	uint32_t size = ns->size;
-	ns_entry *entries = ns->entries;
-	for (uint32_t i = 0; i < size; i++)
-		clear_slot(ns, &entries[i]);
-	ns->count = 0;
 }
 
-static UA_Int32 find_slot (const namespace *ns, ns_entry **slot, const UA_NodeId *nodeid) {
+static inline UA_Int32 find_slot(const Namespace * ns, Namespace_Entry ** slot, const UA_NodeId * nodeid) {
 	hash_t h = hash(nodeid);
 	hash_t index, hash2;
-	uint32_t size;
-	ns_entry *entry;
+	UA_UInt32 size;
+	Namespace_Entry *entry;
 
 	size = ns->size;
 	index = mod(h, ns);
 
 	entry = &ns->entries[index];
-	if (entry == UA_NULL)
+	if(entry == UA_NULL)
 		return UA_ERROR;
-	if (UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
+	if(UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
 		*slot = entry;
 		return UA_SUCCESS;
 	}
 
 	hash2 = mod_m2(h, ns);
-	for (;;) {
+	for(;;) {
 		index += hash2;
-		if (index >= size)
+		if(index >= size)
 			index -= size;
 
 		entry = &ns->entries[index];
-		if (entry == UA_NULL)
+		if(entry == UA_NULL)
 			return UA_ERROR;
-		if (UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
+		if(UA_NodeId_compare(&entry->node->nodeId, nodeid) == UA_EQUAL) {
 			*slot = entry;
 			return UA_SUCCESS;
 		}
-    }
-	return UA_SUCCESS;
-}
-
-UA_Int32 iterate_ns (const namespace *ns, node_visitor visitor) {
-	uint32_t i;
-	for (i=0;i<ns->size;i++) {
-		ns_entry* entry = &ns->entries[i];
-		if (entry != UA_NULL && visitor != UA_NULL)
-			visitor(entry->node);
-    }
+	}
 	return UA_SUCCESS;
 }
 
-/* Always returns an empty slot. This is inevitable if the entries are not
-   completely full. */
-static ns_entry * find_empty_slot(const namespace *ns, hash_t h) {
+/* Always returns an empty slot. This is inevitable if the entries are not completely full. */
+static Namespace_Entry *find_empty_slot(const Namespace * ns, hash_t h) {
 	hash_t index = mod(h, ns);
-	uint32_t size = ns->size;
-	ns_entry *slot = &ns->entries[index];
+	UA_UInt32 size = ns->size;
+	Namespace_Entry *slot = &ns->entries[index];
 
-	if (slot->node == UA_NULL)
+	if(slot->node == UA_NULL)
 		return slot;
 
 	hash_t hash2 = mod_m2(h, ns);
-	for (;;) {
+	for(;;) {
 		index += hash2;
-		if (index >= size)
+		if(index >= size)
 			index -= size;
 
 		slot = &ns->entries[index];
-		if (slot->node == UA_NULL)
+		if(slot->node == UA_NULL)
 			return slot;
 	}
 	return UA_NULL;
 }
 
-/* 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%. Naturally the hash table must already exist. Remember
-   also that the place of the table entries is changed. If memory allocation
-   failures are allowed, this function will return zero, indicating that the
-   table could not be expanded. If all goes well, it will return a non-zero
-   value. */
-static UA_Int32 expand (namespace *ns) {
-	ns_entry *nentries;
+/* 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%. Naturally the
+   hash table must already exist. Remember also that the place of the table entries is changed. If
+   memory allocation failures are allowed, this function will return zero, indicating that the
+   table could not be expanded. If all goes well, it will return a non-zero value. */
+static UA_Int32 expand(Namespace * ns) {
+	Namespace_Entry *nentries;
 	int32_t nsize;
-	uint32_t nindex;
+	UA_UInt32 nindex;
 
-	ns_entry *oentries = ns->entries;
+	Namespace_Entry *oentries = ns->entries;
 	int32_t osize = ns->size;
-	ns_entry *olimit = &oentries[osize];
+	Namespace_Entry *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)) {
+	if(count * 2 < osize && (count * 8 > osize || osize <= 32)) {
 		return UA_SUCCESS;
 	}
-	
-	nindex = higher_prime_index (count * 2);
+
+	nindex = higher_prime_index(count * 2);
 	nsize = prime_tab[nindex].prime;
 
-	if (UA_alloc((void **)&nentries, sizeof(ns_entry)*nsize) != UA_SUCCESS)
+	if(UA_alloc((void **)&nentries, sizeof(Namespace_Entry) * nsize) != UA_SUCCESS)
 		return UA_ERR_NO_MEMORY;
 	ns->entries = nentries;
 	ns->size = nsize;
 	ns->sizePrimeIndex = nindex;
 
-	ns_entry *p = oentries;
+	Namespace_Entry *p = oentries;
 	do {
-		if (p->node != UA_NULL) {
-			ns_entry *q = find_empty_slot(ns, hash(&p->node->nodeId));
+		if(p->node != UA_NULL) {
+			Namespace_Entry *q = find_empty_slot(ns, hash(&p->node->nodeId));
 			*q = *p;
 		}
 		p++;
-	}
-	while (p < olimit);
-	
+	} while(p < olimit);
+
 	UA_free(oentries);
 	return UA_SUCCESS;
 }
+
+/**********************/
+/* Exported functions */
+/**********************/
+
+UA_Int32 Namespace_create(Namespace ** result, UA_UInt32 size) {
+	Namespace *ns = UA_NULL;
+	UA_UInt32 sizePrimeIndex = higher_prime_index(size);
+	size = prime_tab[sizePrimeIndex].prime;
+
+	if(UA_alloc((void **)&ns, sizeof(Namespace)) != UA_SUCCESS)
+		return UA_ERR_NO_MEMORY;
+
+	if(UA_alloc((void **)&ns->entries, sizeof(Namespace_Entry) * size) != UA_SUCCESS) {
+		UA_free(ns);
+		return UA_ERR_NO_MEMORY;
+	}
+
+	/**
+	   set entries to zero:
+	   ns->entries[i].lock = UA_NUll;
+	   ns->entries[i].node = UA_NULL;
+	*/
+	memset(ns->entries, 0, size * sizeof(Namespace_Entry));
+
+	ns->size = size;
+	ns->count = 0;
+	ns->sizePrimeIndex = sizePrimeIndex;
+	*result = ns;
+	return UA_SUCCESS;
+}
+
+static void Namespace_clear(Namespace * ns) {
+	UA_UInt32 size = ns->size;
+	Namespace_Entry *entries = ns->entries;
+	for(UA_UInt32 i = 0; i < size; i++)
+		clear_slot(ns, &entries[i]);
+	ns->count = 0;
+}
+
+void Namespace_empty(Namespace * ns) {
+	Namespace_clear(ns);
+
+	/* Downsize the table.  */
+	if(ns->size > 1024 * 1024 / sizeof(Namespace_Entry)) {
+		int nindex = higher_prime_index(1024 / sizeof(Namespace_Entry));
+		int nsize = prime_tab[nindex].prime;
+		UA_free(ns->entries);
+		UA_alloc((void **)&ns->entries, sizeof(Namespace_Entry) * nsize);	// FIXME: Check return
+		// value
+		ns->size = nsize;
+		ns->sizePrimeIndex = nindex;
+	}
+}
+
+void Namespace_delete(Namespace * ns) {
+	Namespace_clear(ns);
+	UA_free(ns->entries);
+	UA_free(ns);
+}
+
+UA_Int32 Namespace_insert(Namespace * ns, UA_Node * node) {
+	if(ns->size * 3 <= ns->count * 4) {
+		if(expand(ns) != UA_SUCCESS)
+			return UA_ERROR;
+	}
+
+	hash_t h = hash(&node->nodeId);
+	Namespace_Entry *slot = find_empty_slot(ns, h);
+
+#ifdef MULTITHREADING
+	if(UA_alloc((void **)&slot->lock, sizeof(pthread_rwlock_t)) != UA_SUCCESS)
+		return UA_ERR_NO_MEMORY;
+	pthread_rwlock_init((pthread_rwlock_t *) slot->lock, NULL);
+#endif
+
+	slot->node = node;
+	ns->count++;
+	return UA_SUCCESS;
+}
+
+UA_Int32 Namespace_get(Namespace const *ns, const UA_NodeId * nodeid, UA_Node const **result, Namespace_Lock ** lock) {
+	Namespace_Entry *slot;
+	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)
+		return UA_ERROR;
+
+#ifdef MULTITHREADING
+	if(pthread_rwlock_rdlock((pthread_rwlock_t *) slot->lock) != 0)
+		return UA_ERROR;
+	*lock = slot->lock;
+#endif
+
+	*result = slot->node;
+	return UA_SUCCESS;
+}
+
+UA_Int32 Namespace_getWritable(const Namespace * ns, const UA_NodeId * nodeid, UA_Node ** result, Namespace_Lock ** lock) {
+	Namespace_Entry *slot;
+	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)
+		return UA_ERROR;
+
+#ifdef MULTITHREADING
+	if(pthread_rwlock_wrlock((pthread_rwlock_t *) slot->lock) != 0)
+		return UA_ERROR;
+	*lock = slot->lock;
+#endif
+
+	*result = slot->node;
+	return UA_SUCCESS;
+}
+
+#ifdef MULTITHREADING
+static inline void release_context_walker(void *lock) {
+	pthread_rwlock_unlock(lock);
+}
+#endif
+
+UA_Int32 Namespace_transactionGet(Namespace * ns, Namespace_TransactionContext * tc, const UA_NodeId * nodeid, UA_Node ** const result, Namespace_Lock ** lock) {
+	Namespace_Entry *slot;
+	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)
+		return UA_ERROR;
+
+#ifdef MULTITHREADING
+	if(pthread_rwlock_tryrdlock((pthread_rwlock_t *) slot->lock) != 0) {
+		/* Transaction failed. Release all acquired locks and bail out. */
+		UA_list_destroy((UA_list_List *) tc, release_context_walker);
+		return UA_ERROR;
+	}
+	UA_list_addPayloadToBack((UA_list_List *) tc, slot->lock);
+	*lock = slot->lock;
+#endif
+
+	*result = slot->node;
+	return UA_SUCCESS;
+}
+
+UA_Int32 Namespace_transactionGetWritable(Namespace * ns, Namespace_TransactionContext * tc, const UA_NodeId * nodeid, UA_Node ** result, Namespace_Lock ** lock) {
+	Namespace_Entry *slot;
+	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)
+		return UA_ERROR;
+
+#ifdef MULTITHREADING
+	if(pthread_rwlock_trywrlock((pthread_rwlock_t *) slot->lock) != 0) {
+		/* Transaction failed. Release all acquired locks and bail out. */
+		UA_list_destroy((UA_list_List *) tc, release_context_walker);
+		return UA_ERROR;
+	}
+	UA_list_addPayloadToBack((UA_list_List *) tc, slot->lock);
+	*lock = slot->lock;
+#endif
+
+	*result = slot->node;
+	return UA_SUCCESS;
+}
+
+void Namespace_remove(Namespace * ns, UA_NodeId * nodeid) {
+	Namespace_Entry *slot;
+	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS)
+		return;
+	// TODO: Check if deleting the node makes the Namespace inconsistent.
+	clear_slot(ns, slot);
+
+	/* Downsize the hashmap if it is very empty */
+	if(ns->count * 8 < ns->size && ns->size > 32)
+		expand(ns);
+}
+
+UA_Int32 Namespace_iterate(const Namespace * ns, Namespace_nodeVisitor visitor) {
+	UA_UInt32 i;
+	for(i = 0; i < ns->size; i++) {
+		Namespace_Entry *entry = &ns->entries[i];
+		if(entry != UA_NULL && visitor != UA_NULL)
+			visitor(entry->node);
+	}
+	return UA_SUCCESS;
+}

+ 66 - 69
src/ua_namespace.h

@@ -9,86 +9,83 @@
 #define _XOPEN_SOURCE 500
 #define __USE_UNIX98
 #include <pthread.h>
-typedef struct pthread_rwlock_t ns_lock;
+typedef struct pthread_rwlock_t Namespace_Lock;
 #else
-typedef void ns_lock;
+typedef void Namespace_Lock;
 #endif
 
-/* Poor-man's transactions: If we need multiple locks and at least one of them
-   is a writelock ("transaction"), a deadlock can be introduced in conjunction
-   with a second thread.
-
-   Convention: All nodes in a transaction (read and write) must be locked before
-   the first write. If one write-lock cannot be acquired immediately, bail out
-   and restart the transaction.
+static inline void Namespace_Lock_release(Namespace_Lock * lock) {
+#ifdef MULTITHREADING
+	pthread_rwlock_unlock((pthread_rwlock_t *) lock);
+#endif
+}
 
-   A transaction_context is currently only a linked list of the acquired locks.
+/* Poor-man's transactions: If we need multiple locks and at least one of them is a writelock
+   ("transaction"), a deadlock can be introduced in conjunction with a second thread.
 
-   More advanced transaction mechanisms will be established once the runtime
-   behavior can be observed. */
-typedef UA_list_List transaction_context;
-UA_Int32 init_tc(transaction_context * tc);
+   Convention: All nodes in a transaction (read and write) must be locked before the first write.
+   If one write-lock cannot be acquired immediately, bail out and restart the transaction. A
+   Namespace_TransactionContext is currently only a linked list of the acquired locks. More advanced
+   transaction mechanisms will be established once the runtime behavior can be observed. */
+typedef UA_list_List Namespace_TransactionContext;
+UA_Int32 Namespace_TransactionContext_init(Namespace_TransactionContext * tc);
 
-/* Each namespace is a hash-map of NodeIds to Nodes. Every entry in the hashmap
-   consists of a pointer to a read-write lock and a pointer to the Node. */
-typedef struct ns_entry_t {
+/* Each namespace is a hash-map of NodeIds to Nodes. Every entry in the hashmap consists of a
+   pointer to a read-write lock and a pointer to the Node. */
+typedef struct Namespace_Entry_T {
 #ifdef MULTITHREADING
-	ns_lock *lock; /* locks are heap-allocated, so we can resize the entry-array online */
+	Namespace_Lock *lock;	/* locks are heap-allocated */
 #endif
 	UA_Node *node;
-} ns_entry;
+} Namespace_Entry;
 
-typedef struct namespace_t {
+typedef struct Namespace_T {
 	UA_Int32 namespaceId;
 	UA_String namespaceUri;
-	ns_entry *entries;
-	uint32_t size;
-	uint32_t count;
-	uint32_t sizePrimeIndex; /* Current size, as an index into the table of primes.  */
-} namespace;
-
-UA_Int32 create_ns(namespace **result, uint32_t size);
-void empty_ns(namespace *ns);
-void delete_ns(namespace *ns);
-UA_Int32 insert_node(namespace *ns, UA_Node *node);
-UA_Int32 get_node(namespace const *ns, const UA_NodeId *nodeid, UA_Node const ** result, ns_lock ** lock);
-UA_Int32 get_writable_node(namespace const *ns, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
-UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
-UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
-
-typedef void (*node_visitor)(UA_Node const * node);
-UA_Int32 iterate_ns(const namespace *ns, node_visitor visitor);
-
-// inline void release_node(ns_lock *lock);
-// portable solution, see http://www.greenend.org.uk/rjk/tech/inline.html
-static inline void release_node(ns_lock *lock) {
-#ifdef MULTITHREADING
-	pthread_rwlock_unlock((pthread_rwlock_t *)lock);
-#endif
-}
-void delete_node(namespace *ns, UA_NodeId *nodeid);
-
-/* Internal */
-typedef UA_UInt32 hash_t;
-static hash_t hash_string(const UA_Byte * data, UA_Int32 len);
-static hash_t hash(const UA_NodeId *n);
-
-static unsigned int higher_prime_index (unsigned long n);
-static inline hash_t mod_1(hash_t x, hash_t y, hash_t inv, int shift);
-static inline hash_t mod(hash_t hash, const namespace *ns);
-static inline hash_t htab_mod_m2(hash_t hash, const namespace *ns);
-static inline void clear_slot(namespace *ns, ns_entry *slot);
-static void clear_ns(namespace *ns);
-static UA_Int32 find_slot(const namespace *ns, ns_entry **slot, const UA_NodeId *nodeid);
-static ns_entry * find_empty_slot(const namespace *ns, hash_t hash);
-static UA_Int32 expand(namespace *ns);
-
-/* We store UA_MethodNode_Callback instead of UA_MethodNode in the namespace.
-   Pointer casting to UA_MethodNode is possible since pointers point to the
-   first element anyway. */
-typedef struct UA_MethodNode_Callback_T {
-	UA_MethodNode *method_node;
-	UA_Int32 (*method_callback)(UA_list_List *input_args, UA_list_List *output_args);
-} UA_MethodNode_Callback;
+	Namespace_Entry *entries;
+	UA_UInt32 size;
+	UA_UInt32 count;
+	UA_UInt32 sizePrimeIndex;	/* Current size, as an index into the table of primes.  */
+} Namespace;
+
+/** @brief Create a new namespace */
+UA_Int32 Namespace_create(Namespace ** result, UA_UInt32 size);
+
+/** @brief Delete all nodes in the namespace */
+void Namespace_empty(Namespace * ns);
+
+/** @brief Delete the namespace and all nodes in it */
+void Namespace_delete(Namespace * ns);
+
+/** @brief Insert a new node into the namespace */
+UA_Int32 Namespace_insert(Namespace * ns, UA_Node * node);
+
+/** @brief Remove a node from the namespace */
+void Namespace_remove(Namespace * ns, UA_NodeId * nodeid);
+
+/** @brief Retrieve a node (read-only) from the namespace. Nodes are identified
+	by their NodeId. After the Node is no longer used, the lock needs to be
+	released. */
+UA_Int32 Namespace_get(Namespace const *ns, const UA_NodeId * nodeid, UA_Node const **result, Namespace_Lock ** lock);
+
+/** @brief Retrieve a node (read and write) from the namespace. Nodes are
+	identified by their NodeId. After the Node is no longer used, the lock needs
+	to be released. */
+UA_Int32 Namespace_getWritable(Namespace const *ns, const UA_NodeId * nodeid, UA_Node ** result, Namespace_Lock ** lock);
+
+/** @brief Retrieve a node (read-only) as part of a transaction. If multiples
+	nodes are to be retrieved as part of a transaction, the transaction context
+	needs to be specified. */
+UA_Int32 Namespace_transactionGet(Namespace * ns, Namespace_TransactionContext * tc, const UA_NodeId * nodeid, UA_Node ** const result, Namespace_Lock ** lock);
+
+/** @brief Retrieve a node (read and write) as part of a transaction. If
+	multiples nodes are to be retrieved as part of a transaction, the
+	transaction context needs to be specified. */
+UA_Int32 Namespace_transactionGetWritable(Namespace * ns, Namespace_TransactionContext * tc, const UA_NodeId * nodeid, UA_Node ** result, Namespace_Lock ** lock);
+
+typedef void (*Namespace_nodeVisitor) (UA_Node const *node);
+
+/** @brief Iterate over all nodes in a namespace */
+UA_Int32 Namespace_iterate(const Namespace * ns, Namespace_nodeVisitor visitor);
 
 #endif /* __NAMESPACE_H */

+ 159 - 12
src/ua_services.h

@@ -5,55 +5,201 @@
 #include "ua_application.h"
 #include "ua_transport_binary_secure.h"
 
-/* Part 4: 5.4 Discovery Service Set */
+/**
+ * @name Discovery Service Set
+ *
+ * This Service Set defines Services used to discover the Endpoints implemented
+ * by a Server and to read the security configuration for those Endpoints.
+ *
+ * @{
+ */
 // Service_FindServers
+
+/**
+ * @brief This Service returns the Endpoints supported by a Server and all of
+ * 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);
 // Service_RegisterServer
+/** @} */
+
+/**
+ * @name SecureChannel Service Set
+ *
+ * This Service Set defines Services used to open a communication channel that
+ * ensures the confidentiality and Integrity of all Messages exchanged with the
+ * Server.
+ *
+ * @{
+ */
 
-/* Part 4: 5.5 SecureChannel Service Set */
+/**
+ * @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 terminate a SecureChannel.
+ */
 UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureChannelRequest *request, UA_CloseSecureChannelResponse *response);
+/** @} */
 
-/* Part 4: 5.6 Session Service Set */
+/**
+ * @name Session Service Set
+ *
+ * This Service Set defines Services for an application layer connection
+ * establishment in the context of a Session.
+ *
+ * @{
+ */
+
+/**
+ * @brief This Service is used by an OPC UA Client to create a Session and the
+ * Server returns two values which uniquely identify the Session. The first
+ * value is the sessionId which is used to identify the Session in the audit
+ * 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);
+
+/**
+ * @brief This Service is used by the Client to submit its SoftwareCertificates
+ * to the Server for validation and to specify the identity of the user
+ * associated with the Session. This Service request shall be issued by the
+ * 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, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response);
+
+/**
+ * @brief This Service is used to terminate a Session.
+ */
 UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response);
 // Service_Cancel
+/** @} */
 
-/* Part 4: 5.7 NodeManagement Service Set */
+/**
+ * @name NodeManagement Service Set
+ *
+ * This Service Set defines Services to add and delete AddressSpace Nodes and References between
+ * them. All added Nodes continue to exist in the AddressSpace even if the Client that created them
+ * disconnects from the Server.
+ *
+ * @{
+ */
 // Service_AddNodes
 // Service_AddReferences
 // Service_DeleteNodes
 // Service_DeleteReferences
+/** @} */
+
+/**
+ * @name View Service Set
+ *
+ * Clients use the browse Services of the View Service Set to navigate through
+ * the AddressSpace or through a View which is a subset of the AddressSpace.
+ *
+ * @{
+ */
 
-/* Part 4: 5.8 View Service Set */
+/**
+ * @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(SL_Channel *channel, const UA_BrowseRequest *request, UA_BrowseResponse *response);
 // Service_BrowseNext
 // Service_TranslateBrowsePathsRoNodeIds
 // Service_RegisterNodes
 // Service_UnregisterNodes
+/** @} */
 
 /* Part 4: 5.9 Query Service Set */
+/**
+ * @name Query Service Set
+ *
+ * This Service Set is used to issue a Query to a Server. OPC UA Query is
+ * generic in that it provides an underlying storage mechanism independent Query
+ * capability that can be used to access a wide variety of OPC UA data stores
+ * and information management systems. OPC UA Query permits a Client to access
+ * data maintained by a Server without any knowledge of the logical schema used
+ * for internal storage of the data. Knowledge of the AddressSpace is
+ * sufficient.
+ *
+ * @{
+ */
 // Service_QueryFirst
 // Service_QueryNext
+/** @} */
 
 /* Part 4: 5.10 Attribute Service Set */
+/**
+ * @name Attribute Service Set
+ *
+ * This Service Set provides Services to access Attributes that are part of
+ * Nodes.
+ *
+ * @{
+ */
+
+/**
+ * @brief This Service is used to read one or more Attributes of one or more
+ * Nodes. For constructed Attribute values whose elements are indexed, such as
+ * an array, this Service allows Clients to read the entire set of indexed
+ * values as a composite, to read individual elements or to read ranges of
+ * elements of the composite.
+ */
 UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_ReadResponse *response);
-// Service_HistoryRead;
-// Service_Write;
-// Service_HistoryUpdate;
+// Service_HistoryRead
+// Service_Write
+// Service_HistoryUpdate
+/** @} */
 
-/* Part 4: 5.11 Method Service Set */
+/**
+ * @name Method Service Set
+ *
+ * The Method Service Set defines the means to invoke methods. A method shall be
+a component of an Object.
+ *
+ * @{
+ */
 // Service_Call
+/** @} */
+
+/**
+ * @name MonitoredItem Service Set
+ *
+ * Clients define MonitoredItems to subscribe to data and Events. Each
+ * MonitoredItem identifies the item to be monitored and the Subscription to use
+ * to send Notifications. The item to be monitored may be any Node Attribute.
+ *
+ * @{
+ */
 
-/* Part 4: 5.12 MonitoredItem Service Set */
-// UA_Int32 Service_CreateMonitoredItems(SL_Channel *channel, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response);
+/**
+ * @brief This Service is used to create and add one or more MonitoredItems to a
+ * Subscription. A MonitoredItem is deleted automatically by the Server when the
+ * Subscription is deleted. Deleting a MonitoredItem causes its entire set of
+ * triggered item links to be deleted, but has no effect on the MonitoredItems
+ * referenced by the triggered items.
+ */
+UA_Int32 Service_CreateMonitoredItems(SL_Channel *channel, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response);
 // Service_ModifyMonitoredItems
 // Service_SetMonitoringMode
 // Service_SetTriggering
 // Service_DeleteMonitoredItems
+/** @} */
 
-/* Part 4: 5.13 Subscription Service Set */
+/**
+ * @name Subscription Service Set
+ *
+ * Subscriptions are used to report Notifications to the Client.
+ *
+ * @{
+ */
 // Service_CreateSubscription
 // Service_ModifySubscription
 // Service_SetPublishingMode
@@ -61,5 +207,6 @@ UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_Rea
 // Service_Republish
 // Service_TransferSubscription
 // Service_DeleteSubscription
+/** @} */
 
 #endif

+ 4 - 4
src/ua_services_attribute.c

@@ -30,7 +30,7 @@ static UA_DataValue * service_read_node(Application *app, const UA_ReadValueId *
 	UA_DataValue *v; UA_DataValue_new(&v);
 	
 	DBG(printf("service_read_node - entered with ns=%d,id=%d,attr=%i\n",id->nodeId.namespace, id->nodeId.identifier.numeric, id->attributeId));
-	namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespace);
+	Namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespace);
 
 	if (ns == UA_NULL) {
 		DBG_VERBOSE(printf("service_read_node - unknown namespace %d\n",id->nodeId.namespace));
@@ -41,9 +41,9 @@ static UA_DataValue * service_read_node(Application *app, const UA_ReadValueId *
 	DBG_VERBOSE(UA_String_printf(",namespaceUri=",&(ns->namespaceUri)));
 	
 	UA_Node const *node = UA_NULL;
-	ns_lock *lock = UA_NULL;
+	Namespace_Lock *lock = UA_NULL;
 	DBG_VERBOSE(UA_NodeId_printf("service_read_node - search for ",&(id->nodeId)));
-	UA_Int32 result = get_node(ns, &(id->nodeId), &node, &lock);
+	UA_Int32 result = Namespace_get(ns, &(id->nodeId), &node, &lock);
 	if(result != UA_SUCCESS || node == UA_NULL) {
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
 		v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -167,7 +167,7 @@ static UA_DataValue * service_read_node(Application *app, const UA_ReadValueId *
 		v->status = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
 		break;
 	}
-	release_node(lock);
+	Namespace_Lock_release(lock);
 	return v;
 }
 

+ 1 - 1
src/ua_services_securechannel.c

@@ -62,7 +62,7 @@ UA_Int32 Service_OpenSecureChannel(SL_Channel *channel, const UA_OpenSecureChann
 
 	response->serverProtocolVersion = channel->tlConnection->localConf.protocolVersion;
 	response->securityToken.channelId = channel->securityToken.secureChannelId;
-	response->securityToken.tokenId = channel->securityToken.tokenId;
+	response->securityToken.tokenId = channel->securityToken.tokenId.tokenId;
 	response->securityToken.revisedLifetime = channel->securityToken.revisedLifetime;
 	UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
 	return retval;

+ 151 - 42
src/ua_transport.c

@@ -39,7 +39,7 @@ void UA_MessageType_printf(char *label, UA_MessageType* p) {
 UA_Int32 UA_OPCUATcpMessageHeader_calcSize(UA_OPCUATcpMessageHeader const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpMessageHeader);}
 	return 0
-	 + UA_MessageType_calcSize(&(ptr->messageType))
+	 + UA_MessageType_calcSize(&(ptr->messageType)) // messageType
 	 + sizeof(UA_Byte) // isFinal
 	 + sizeof(UA_UInt32) // messageSize
 	;
@@ -55,9 +55,10 @@ UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const *
 
 UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpMessageHeader* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_MessageType_decodeBinary(src,pos,&(dst->messageType));
-	retval |= UA_Byte_decodeBinary(src,pos,&(dst->isFinal));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->messageSize));
+	UA_OPCUATcpMessageHeader_init(dst);
+	CHECKED_DECODE(UA_MessageType_decodeBinary(src,pos,&(dst->messageType)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_Byte_decodeBinary(src,pos,&(dst->isFinal)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->messageSize)), UA_OPCUATcpMessageHeader_deleteMembers(dst));
 	return retval;
 }
 
@@ -72,6 +73,14 @@ UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader* p) {
 	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_METHOD_NEW_DEFAULT(UA_OPCUATcpMessageHeader)
 UA_Int32 UA_OPCUATcpHelloMessage_calcSize(UA_OPCUATcpHelloMessage const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpHelloMessage);}
 	return 0
@@ -97,12 +106,13 @@ UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const * sr
 
 UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpHelloMessage* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount));
-	retval |= UA_String_decodeBinary(src,pos,&(dst->endpointUrl));
+	UA_OPCUATcpHelloMessage_init(dst);
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_String_decodeBinary(src,pos,&(dst->endpointUrl)), UA_OPCUATcpHelloMessage_deleteMembers(dst));
 	return retval;
 }
 
@@ -118,6 +128,18 @@ UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage* p) {
 	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_METHOD_NEW_DEFAULT(UA_OPCUATcpHelloMessage)
 UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_OPCUATcpAcknowledgeMessage);}
 	return 0
@@ -141,11 +163,12 @@ UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessag
 
 UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpAcknowledgeMessage* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount));
+	UA_OPCUATcpAcknowledgeMessage_init(dst);
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->protocolVersion)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->receiveBufferSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sendBufferSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxMessageSize)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->maxChunkCount)), UA_OPCUATcpAcknowledgeMessage_deleteMembers(dst));
 	return retval;
 }
 
@@ -160,47 +183,67 @@ UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessa
 	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_METHOD_NEW_DEFAULT(UA_OPCUATcpAcknowledgeMessage)
 UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageHeader);}
 	return 0
-	 // + UA_OPCUATcpMessageHeader_calcSize(ptr->tcpMessageHeader)
+	 // + UA_OPCUATcpMessageHeader_calcSize(&(ptr->messageHeader))
 	 + sizeof(UA_UInt32) // secureChannelId
 	;
 }
 
 UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const * src, UA_Int32* pos, UA_ByteString* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	// retval |= UA_OPCUATcpMessageHeader_encode(src->tcpMessageHeader,pos,dst);
+	// retval |= UA_OPCUATcpMessageHeader_encodeBinary(&(src->messageHeader),pos,dst);
 	retval |= UA_UInt32_encodeBinary(&(src->secureChannelId),pos,dst);
 	return retval;
 }
 
 UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	//retval |= UA_alloc((void**)&(dst->tcpMessageHeader),UA_OPCUATcpMessageHeader_calcSize(UA_NULL));
-	//retval |= UA_OPCUATcpMessageHeader_decode(src,pos,dst->tcpMessageHeader);
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->secureChannelId));
+	UA_SecureConversationMessageHeader_init(dst);
+	// CHECKED_DECODE(UA_OPCUATcpMessageHeader_decodeBinary(src,pos,&(dst->messageHeader)), UA_SecureConversationMessageHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(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_SecureConversationMessageHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
     }
 UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader* p) {
 	UA_Int32 retval = UA_SUCCESS;
-	// retval |= UA_OPCUATcpMessageHeader_delete(p->tcpMessageHeader);
+	// retval |= UA_OPCUATcpMessageHeader_deleteMembers(&(p->messageHeader));
 	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_METHOD_NEW_DEFAULT(UA_SecureConversationMessageHeader)
 UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSize(UA_AsymmetricAlgorithmSecurityHeader const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_AsymmetricAlgorithmSecurityHeader);}
 	return 0
 	 + UA_ByteString_calcSize(&(ptr->securityPolicyUri))
 	 + UA_ByteString_calcSize(&(ptr->senderCertificate))
 	 + UA_ByteString_calcSize(&(ptr->receiverCertificateThumbprint))
+	 // + sizeof(UA_UInt32) // requestId
 	;
 }
 
@@ -209,14 +252,17 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorith
 	retval |= UA_ByteString_encodeBinary(&(src->securityPolicyUri),pos,dst);
 	retval |= UA_ByteString_encodeBinary(&(src->senderCertificate),pos,dst);
 	retval |= UA_ByteString_encodeBinary(&(src->receiverCertificateThumbprint),pos,dst);
+	// retval |= UA_UInt32_encodeBinary(&(src->requestId),pos,dst);
 	return retval;
 }
 
 UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_AsymmetricAlgorithmSecurityHeader* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_ByteString_decodeBinary(src,pos,&(dst->securityPolicyUri));
-	retval |= UA_ByteString_decodeBinary(src,pos,&(dst->senderCertificate));
-	retval |= UA_ByteString_decodeBinary(src,pos,&(dst->receiverCertificateThumbprint));
+	UA_AsymmetricAlgorithmSecurityHeader_init(dst);
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->securityPolicyUri)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->senderCertificate)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_ByteString_decodeBinary(src,pos,&(dst->receiverCertificateThumbprint)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
+	// CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->requestId)), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	return retval;
 }
 
@@ -233,21 +279,55 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorit
 	retval |= UA_ByteString_deleteMembers(&(p->receiverCertificateThumbprint));
 	return retval;
 }
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader* p) {
+
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader * p) {
 	UA_Int32 retval = UA_SUCCESS;
-	if(p==UA_NULL) return UA_ERROR;
 	retval |= UA_ByteString_init(&(p->securityPolicyUri));
 	retval |= UA_ByteString_init(&(p->senderCertificate));
 	retval |= UA_ByteString_init(&(p->receiverCertificateThumbprint));
+	// retval |= UA_UInt32_init(&(p->requestId));
 	return retval;
 }
 
-UA_TYPE_METHOD_DECODEBINARY_AS(UA_SymmetricAlgorithmSecurityHeader, UA_UInt32)
-UA_TYPE_METHOD_ENCODEBINARY_AS(UA_SymmetricAlgorithmSecurityHeader, UA_UInt32)
-UA_TYPE_METHOD_DELETE_AS(UA_SymmetricAlgorithmSecurityHeader, UA_UInt32)
-UA_TYPE_METHOD_DELETEMEMBERS_AS(UA_SymmetricAlgorithmSecurityHeader, UA_UInt32)
-UA_TYPE_METHOD_CALCSIZE_AS(UA_SymmetricAlgorithmSecurityHeader, UA_UInt32)
+UA_TYPE_METHOD_NEW_DEFAULT(UA_AsymmetricAlgorithmSecurityHeader)
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSize(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_Int32* pos, UA_ByteString* dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_UInt32_encodeBinary(&(src->tokenId),pos,dst);
+	return retval;
+}
+
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SymmetricAlgorithmSecurityHeader* dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_SymmetricAlgorithmSecurityHeader_init(dst);
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(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_METHOD_NEW_DEFAULT(UA_SymmetricAlgorithmSecurityHeader)
 UA_Int32 UA_SequenceHeader_calcSize(UA_SequenceHeader const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_SequenceHeader);}
 	return 0
@@ -265,8 +345,9 @@ UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const * src, UA_Int32*
 
 UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SequenceHeader* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->sequenceNumber));
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->requestId));
+	UA_SequenceHeader_init(dst);
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->sequenceNumber)), UA_SequenceHeader_deleteMembers(dst));
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->requestId)), UA_SequenceHeader_deleteMembers(dst));
 	return retval;
 }
 
@@ -281,6 +362,14 @@ UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader* p) {
 	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_METHOD_NEW_DEFAULT(UA_SequenceHeader)
 UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessageFooter const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageFooter);}
 	return 0
@@ -292,7 +381,7 @@ UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessag
 
 UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_Int32* pos, UA_ByteString* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Int32_encodeBinary(&(src->paddingSize),pos,dst); // encode size
+	//retval |= UA_Int32_encodeBinary(&(src->paddingSize),pos,dst); // encode size managed by UA_Array_encodeBinary
 	retval |= UA_Array_encodeBinary((void const**) (src->padding),src->paddingSize, UA_BYTE,pos,dst);
 	retval |= UA_Byte_encodeBinary(&(src->signature),pos,dst);
 	return retval;
@@ -300,10 +389,11 @@ UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMe
 
 UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageFooter* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Int32_decodeBinary(src,pos,&(dst->paddingSize)); // decode size
-	retval |= UA_Array_new((void***)&dst->padding,dst->paddingSize, UA_BYTE);
-	retval |= UA_Array_decodeBinary(src,dst->paddingSize, UA_BYTE,pos,(void *** const) &dst->padding);
-	retval |= UA_Byte_decodeBinary(src,pos,&(dst->signature));
+	UA_SecureConversationMessageFooter_init(dst);
+	CHECKED_DECODE(UA_Int32_decodeBinary(src,pos,&(dst->paddingSize)), UA_SecureConversationMessageFooter_deleteMembers(dst)); // decode size
+	CHECKED_DECODE(UA_Array_new((void***)&dst->padding, dst->paddingSize, UA_BYTE), dst->padding = UA_NULL; UA_SecureConversationMessageFooter_deleteMembers(dst));
+	CHECKED_DECODE(UA_Array_decodeBinary(src,dst->paddingSize, UA_BYTE,pos,(void *** const) (&dst->padding)), UA_SecureConversationMessageFooter_deleteMembers(dst));
+	CHECKED_DECODE(UA_Byte_decodeBinary(src,pos,&(dst->signature)), UA_SecureConversationMessageFooter_deleteMembers(dst));
 	return retval;
 }
 
@@ -315,10 +405,19 @@ UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageF
     }
 UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter* p) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_Array_delete((void***)&p->padding,p->paddingSize,UA_BYTE);
+	retval |= UA_Array_delete((void***)&p->padding,p->paddingSize,UA_BYTE); p->padding = UA_NULL;
 	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_METHOD_NEW_DEFAULT(UA_SecureConversationMessageFooter)
 UA_Int32 UA_SecureConversationMessageAbortBody_calcSize(UA_SecureConversationMessageAbortBody const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageAbortBody);}
 	return 0
@@ -336,8 +435,9 @@ UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversatio
 
 UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageAbortBody* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_UInt32_decodeBinary(src,pos,&(dst->error));
-	retval |= UA_String_decodeBinary(src,pos,&(dst->reason));
+	UA_SecureConversationMessageAbortBody_init(dst);
+	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&(dst->error)), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
+	CHECKED_DECODE(UA_String_decodeBinary(src,pos,&(dst->reason)), UA_SecureConversationMessageAbortBody_deleteMembers(dst));
 	return retval;
 }
 
@@ -352,3 +452,12 @@ UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversati
 	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_METHOD_NEW_DEFAULT(UA_SecureConversationMessageAbortBody)

+ 86 - 58
src/ua_transport.h

@@ -1,5 +1,5 @@
-#ifndef OPCUA_STACKINTERNALTYPES_H_
-#define OPCUA_STACKINTERNALTYPES_H_
+#ifndef UA_TRANSPORT_H_
+#define UA_TRANSPORT_H_
 
 #include "opcua.h"
 #include "ua_application.h"
@@ -46,22 +46,24 @@ UA_Int32 UA_MessageType_delete(UA_MessageType* p);
 UA_Int32 UA_MessageType_deleteMembers(UA_MessageType* p);
 void UA_MessageType_printf(char *label, UA_MessageType* p);
 
-/*** UA_OPCUATcpMessageHeader ***/
-/* TCP Header */
-typedef struct T_UA_OPCUATcpMessageHeader {
-	UA_MessageType messageType;
+/** @name UA_UA_OPCUATcpMessageHeader */
+/** @brief TCP Header */
+typedef struct UA_OPCUATcpMessageHeader_T {
+	UA_MessageType messageType; // MessageType instead of UInt32
 	UA_Byte isFinal;
 	UA_UInt32 messageSize;
 } UA_OPCUATcpMessageHeader;
-UA_Int32 UA_OPCUATcpMessageHeader_calcSize(UA_OPCUATcpMessageHeader const * ptr);
-UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpMessageHeader* dst);
+UA_Int32 UA_OPCUATcpMessageHeader_calcSize(UA_OPCUATcpMessageHeader const* ptr);
+UA_Int32 UA_OPCUATcpMessageHeader_encodeBinary(UA_OPCUATcpMessageHeader const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_OPCUATcpMessageHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpMessageHeader* dst);
 UA_Int32 UA_OPCUATcpMessageHeader_delete(UA_OPCUATcpMessageHeader* p);
 UA_Int32 UA_OPCUATcpMessageHeader_deleteMembers(UA_OPCUATcpMessageHeader* p);
+UA_Int32 UA_OPCUATcpMessageHeader_init(UA_OPCUATcpMessageHeader * p);
+UA_Int32 UA_OPCUATcpMessageHeader_new(UA_OPCUATcpMessageHeader ** p);
 
-/*** UA_OPCUATcpHelloMessage ***/
-/* Hello Message */
-typedef struct T_UA_OPCUATcpHelloMessage {
+/** @name UA_UA_OPCUATcpHelloMessage */
+/** @brief Hello Message */
+typedef struct UA_OPCUATcpHelloMessage_T {
 	UA_UInt32 protocolVersion;
 	UA_UInt32 receiveBufferSize;
 	UA_UInt32 sendBufferSize;
@@ -69,89 +71,115 @@ typedef struct T_UA_OPCUATcpHelloMessage {
 	UA_UInt32 maxChunkCount;
 	UA_String endpointUrl;
 } UA_OPCUATcpHelloMessage;
-UA_Int32 UA_OPCUATcpHelloMessage_calcSize(UA_OPCUATcpHelloMessage const * ptr);
-UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpHelloMessage* dst);
+UA_Int32 UA_OPCUATcpHelloMessage_calcSize(UA_OPCUATcpHelloMessage const* ptr);
+UA_Int32 UA_OPCUATcpHelloMessage_encodeBinary(UA_OPCUATcpHelloMessage const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_OPCUATcpHelloMessage_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpHelloMessage* dst);
 UA_Int32 UA_OPCUATcpHelloMessage_delete(UA_OPCUATcpHelloMessage* p);
 UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage* p);
+UA_Int32 UA_OPCUATcpHelloMessage_init(UA_OPCUATcpHelloMessage * p);
+UA_Int32 UA_OPCUATcpHelloMessage_new(UA_OPCUATcpHelloMessage ** p);
 
-/*** UA_OPCUATcpAcknowledgeMessage ***/
-/* Acknowledge Message */
-typedef struct T_UA_OPCUATcpAcknowledgeMessage {
+/** @name UA_UA_OPCUATcpAcknowledgeMessage */
+/** @brief Acknowledge Message */
+typedef struct UA_OPCUATcpAcknowledgeMessage_T {
 	UA_UInt32 protocolVersion;
 	UA_UInt32 receiveBufferSize;
 	UA_UInt32 sendBufferSize;
 	UA_UInt32 maxMessageSize;
 	UA_UInt32 maxChunkCount;
 } UA_OPCUATcpAcknowledgeMessage;
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage const * ptr);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_OPCUATcpAcknowledgeMessage* dst);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_calcSize(UA_OPCUATcpAcknowledgeMessage const* ptr);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_encodeBinary(UA_OPCUATcpAcknowledgeMessage const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_OPCUATcpAcknowledgeMessage* dst);
 UA_Int32 UA_OPCUATcpAcknowledgeMessage_delete(UA_OPCUATcpAcknowledgeMessage* p);
 UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessage* p);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_init(UA_OPCUATcpAcknowledgeMessage * p);
+UA_Int32 UA_OPCUATcpAcknowledgeMessage_new(UA_OPCUATcpAcknowledgeMessage ** p);
 
-/*** UA_SecureConversationMessageHeader ***/
-/* Secure Layer Sequence Header */
-typedef struct T_UA_SecureConversationMessageHeader {
-	// UA_OPCUATcpMessageHeader* tcpMessageHeader;
+/** @name UA_UA_SecureConversationMessageHeader */
+/** @brief Secure Layer Sequence Header */
+typedef struct UA_SecureConversationMessageHeader_T {
+	// UA_OPCUATcpMessageHeader messageHeader; // Treated with custom code
 	UA_UInt32 secureChannelId;
 } UA_SecureConversationMessageHeader;
-UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const * ptr);
-UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst);
+UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const* ptr);
+UA_Int32 UA_SecureConversationMessageHeader_encodeBinary(UA_SecureConversationMessageHeader const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_SecureConversationMessageHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst);
 UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader* p);
 UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader* p);
+UA_Int32 UA_SecureConversationMessageHeader_init(UA_SecureConversationMessageHeader * p);
+UA_Int32 UA_SecureConversationMessageHeader_new(UA_SecureConversationMessageHeader ** p);
 
-/*** UA_AsymmetricAlgorithmSecurityHeader ***/
-/* Security Header> */
-typedef struct T_UA_AsymmetricAlgorithmSecurityHeader {
+/** @name UA_UA_AsymmetricAlgorithmSecurityHeader */
+/** @brief Security Header> */
+typedef struct UA_AsymmetricAlgorithmSecurityHeader_T {
 	UA_ByteString securityPolicyUri;
 	UA_ByteString senderCertificate;
 	UA_ByteString receiverCertificateThumbprint;
+	// UA_UInt32 requestId; // Dealt with in the SequenceHeader
 } UA_AsymmetricAlgorithmSecurityHeader;
-UA_TYPE_METHOD_PROTOTYPES (UA_AsymmetricAlgorithmSecurityHeader)
-UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader* p);
-
-/*** UA_SymmetricAlgorithmSecurityHeader ***/
-/* Secure Layer Symmetric Algorithm Header */
-typedef UA_Int32 UA_SymmetricAlgorithmSecurityHeader;
-UA_TYPE_METHOD_PROTOTYPES(UA_SymmetricAlgorithmSecurityHeader)
-
-/*** UA_SequenceHeader ***/
-/* Secure Layer Sequence Header */
-typedef struct T_UA_SequenceHeader {
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSize(UA_AsymmetricAlgorithmSecurityHeader const* ptr);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorithmSecurityHeader const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_AsymmetricAlgorithmSecurityHeader* dst);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader* p);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader* p);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader * p);
+UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_new(UA_AsymmetricAlgorithmSecurityHeader ** p);
+
+/** @name UA_UA_SymmetricAlgorithmSecurityHeader */
+/** @brief Secure Layer Symmetric Algorithm Header */
+typedef struct UA_SymmetricAlgorithmSecurityHeader_T {
+	UA_UInt32 tokenId;
+} UA_SymmetricAlgorithmSecurityHeader;
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_calcSize(UA_SymmetricAlgorithmSecurityHeader const* ptr);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_encodeBinary(UA_SymmetricAlgorithmSecurityHeader const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SymmetricAlgorithmSecurityHeader* dst);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_delete(UA_SymmetricAlgorithmSecurityHeader* p);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_deleteMembers(UA_SymmetricAlgorithmSecurityHeader* p);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_init(UA_SymmetricAlgorithmSecurityHeader * p);
+UA_Int32 UA_SymmetricAlgorithmSecurityHeader_new(UA_SymmetricAlgorithmSecurityHeader ** p);
+
+/** @name UA_UA_SequenceHeader */
+/** @brief Secure Layer Sequence Header */
+typedef struct UA_SequenceHeader_T {
 	UA_UInt32 sequenceNumber;
 	UA_UInt32 requestId;
 } UA_SequenceHeader;
-UA_Int32 UA_SequenceHeader_calcSize(UA_SequenceHeader const * ptr);
-UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SequenceHeader* dst);
+UA_Int32 UA_SequenceHeader_calcSize(UA_SequenceHeader const* ptr);
+UA_Int32 UA_SequenceHeader_encodeBinary(UA_SequenceHeader const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_SequenceHeader_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SequenceHeader* dst);
 UA_Int32 UA_SequenceHeader_delete(UA_SequenceHeader* p);
 UA_Int32 UA_SequenceHeader_deleteMembers(UA_SequenceHeader* p);
+UA_Int32 UA_SequenceHeader_init(UA_SequenceHeader * p);
+UA_Int32 UA_SequenceHeader_new(UA_SequenceHeader ** p);
 
-/*** UA_SecureConversationMessageFooter ***/
-/* Secure Conversation Message Footer */
-typedef struct T_UA_SecureConversationMessageFooter {
+/** @name UA_UA_SecureConversationMessageFooter */
+/** @brief Secure Conversation Message Footer */
+typedef struct UA_SecureConversationMessageFooter_T {
 	UA_Int32 paddingSize;
 	UA_Byte** padding;
 	UA_Byte signature;
 } UA_SecureConversationMessageFooter;
-UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessageFooter const * ptr);
-UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageFooter* dst);
+UA_Int32 UA_SecureConversationMessageFooter_calcSize(UA_SecureConversationMessageFooter const* ptr);
+UA_Int32 UA_SecureConversationMessageFooter_encodeBinary(UA_SecureConversationMessageFooter const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_SecureConversationMessageFooter_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageFooter* dst);
 UA_Int32 UA_SecureConversationMessageFooter_delete(UA_SecureConversationMessageFooter* p);
 UA_Int32 UA_SecureConversationMessageFooter_deleteMembers(UA_SecureConversationMessageFooter* p);
+UA_Int32 UA_SecureConversationMessageFooter_init(UA_SecureConversationMessageFooter * p);
+UA_Int32 UA_SecureConversationMessageFooter_new(UA_SecureConversationMessageFooter ** p);
 
-/*** UA_SecureConversationMessageAbortBody ***/
-/* Secure Conversation Message Abort Body */
-typedef struct T_UA_SecureConversationMessageAbortBody {
+/** @name UA_UA_SecureConversationMessageAbortBody */
+/** @brief Secure Conversation Message Abort Body */
+typedef struct UA_SecureConversationMessageAbortBody_T {
 	UA_UInt32 error;
 	UA_String reason;
 } UA_SecureConversationMessageAbortBody;
-UA_Int32 UA_SecureConversationMessageAbortBody_calcSize(UA_SecureConversationMessageAbortBody const * ptr);
-UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const * src, UA_Int32* pos, UA_ByteString* dst);
-UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_SecureConversationMessageAbortBody* dst);
+UA_Int32 UA_SecureConversationMessageAbortBody_calcSize(UA_SecureConversationMessageAbortBody const* ptr);
+UA_Int32 UA_SecureConversationMessageAbortBody_encodeBinary(UA_SecureConversationMessageAbortBody const* src, UA_Int32* pos, UA_ByteString* dst);
+UA_Int32 UA_SecureConversationMessageAbortBody_decodeBinary(UA_ByteString const* src, UA_Int32* pos, UA_SecureConversationMessageAbortBody* dst);
 UA_Int32 UA_SecureConversationMessageAbortBody_delete(UA_SecureConversationMessageAbortBody* p);
 UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody* p);
+UA_Int32 UA_SecureConversationMessageAbortBody_init(UA_SecureConversationMessageAbortBody * p);
+UA_Int32 UA_SecureConversationMessageAbortBody_new(UA_SecureConversationMessageAbortBody ** p);
 
-#endif
+#endif /* UA_TRANSPORT_H_ */

+ 1 - 1
src/ua_transport_binary_secure.c

@@ -190,7 +190,7 @@ UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_
 	UA_String_init(&(channel->secureChannelId));
 	channel->securityMode = UA_SECURITYMODE_INVALID;
 	channel->securityToken.secureChannelId = 25; //TODO set a valid start secureChannelId number
-	channel->securityToken.tokenId = 1; //TODO set a valid start TokenId
+	channel->securityToken.tokenId.tokenId = 1; //TODO set a valid start TokenId
 
 	connection->secureChannel = channel;
 	connection->secureChannel->tlConnection = connection;

+ 26 - 20
tests/check_memory.c

@@ -111,17 +111,20 @@ START_TEST (decodeScalarBasicTypeFromRandomBufferShallSucceed)
 	UA_ByteString msg1;
 	UA_Int32 retval, buflen;
 	buflen = 256;
-	retval = UA_[_i].new(&obj1);
 	UA_ByteString_newMembers(&msg1,buflen); // fixed size
-	srandom(42); // use the same random number sequence throughout
-	UA_Int32 i; for(i=0;i<buflen;i++) { msg1.data[i] = (UA_Byte) random(); }
-	// when
-	UA_Int32 pos = 0;
-	retval = UA_[_i].decodeBinary(&msg1, &pos, obj1);
-	//then
-	ck_assert_msg(retval==UA_SUCCESS,"Decoding %s from random buffer",UA_[_i].name);
-	// finally
-	UA_[_i].delete(obj1);
+	srandom(42);
+	retval = UA_SUCCESS;
+	for(int n=0;n<100;n++) {
+		retval |= UA_[_i].new(&obj1);
+		UA_Int32 i; for(i=0;i<buflen;i++) { msg1.data[i] = (UA_Byte) random(); }
+		// when
+		UA_Int32 pos = 0;
+		retval |= UA_[_i].decodeBinary(&msg1, &pos, obj1);
+		//then
+		ck_assert_msg(retval==UA_SUCCESS,"Decoding %s from random buffer",UA_[_i].name);
+		// finally
+		UA_[_i].delete(obj1);
+	}
 	UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST
@@ -133,17 +136,20 @@ START_TEST (decodeComplexTypeFromRandomBufferShallSurvive)
 	UA_ByteString msg1;
 	UA_Int32 retval, buflen;
 	buflen = 256;
-	retval = UA_[_i].new(&obj1);
 	UA_ByteString_newMembers(&msg1,buflen); // fixed size
-	srandom(42); // use the same random number sequence throughout
-	UA_Int32 i; for(i=0;i<buflen;i++) { msg1.data[i] = (UA_Byte) random(); }
-	// when
-	UA_Int32 pos = 0;
-	retval = UA_[_i].decodeBinary(&msg1, &pos, obj1);
-	//then
-	ck_assert_msg(retval==UA_SUCCESS||retval==UA_ERROR,"Decoding %s from random buffer",UA_[_i].name);
-	// finally
-	UA_[_i].delete(obj1);
+	srandom(42);
+	retval = UA_SUCCESS;
+	for(int n=0;n<100;n++) {
+		retval |= UA_[_i].new(&obj1);
+		UA_Int32 i; for(i=0;i<buflen;i++) { msg1.data[i] = (UA_Byte) random(); }
+		// when
+		UA_Int32 pos = 0;
+		retval |= UA_[_i].decodeBinary(&msg1, &pos, obj1);
+		//then
+		ck_assert_msg(retval==UA_SUCCESS||retval==UA_ERROR,"Decoding %s from random buffer",UA_[_i].name);
+		// finally
+		UA_[_i].delete(obj1);
+	}
 	UA_ByteString_deleteMembers(&msg1);
 }
 END_TEST

+ 16 - 28
tests/check_namespace.c

@@ -1,13 +1,3 @@
-/*
- ============================================================================
- Name        : check_stack.c
- Author      :
- Version     :
- Copyright   : Your copyright notice
- Description :
- ============================================================================
- */
-
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -15,12 +5,10 @@
 #include "ua_namespace.h"
 #include "check.h"
 
-
-
 START_TEST(test_Namespace) {
-	namespace *ns = UA_NULL;
-	create_ns(&ns, 512);
-	delete_ns(ns);
+	Namespace *ns = UA_NULL;
+	Namespace_create(&ns, 512);
+	Namespace_delete(ns);
 }
 END_TEST
 
@@ -34,39 +22,39 @@ UA_Int32 createNode(UA_Node** p, UA_Int16 nsid, UA_Int32 id) {
 
 START_TEST(findNodeInNamespaceWithSingleEntry) {
 	// given
-	namespace *ns;
-	create_ns(&ns, 512);
-	UA_Node* n1; createNode(&n1,0,2253); insert_node(ns,n1);
+	Namespace *ns;
+	Namespace_create(&ns, 512);
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns,n1);
 	const UA_Node* nr = UA_NULL;
-	ns_lock* nl = UA_NULL;
+	Namespace_Lock* nl = UA_NULL;
 	UA_Int32 retval;
 	// when
-	retval = get_node(ns,&(n1->nodeId),&nr,&nl);
+	retval = Namespace_get(ns,&(n1->nodeId),&nr,&nl);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_ptr_eq(nr,n1);
 	// finally
-	delete_ns(ns);
+	Namespace_delete(ns);
 }
 END_TEST
 
 START_TEST(findNodeInNamespaceWithTwoEntries) {
 	// given
-	namespace *ns;
-	create_ns(&ns, 512);
-	UA_Node* n1; createNode(&n1,0,2253); insert_node(ns,n1);
-	UA_Node* n2; createNode(&n2,0,2255); insert_node(ns,n2);
+	Namespace *ns;
+	Namespace_create(&ns, 512);
+	UA_Node* n1; createNode(&n1,0,2253); Namespace_insert(ns,n1);
+	UA_Node* n2; createNode(&n2,0,2255); Namespace_insert(ns,n2);
 
 	const UA_Node* nr = UA_NULL;
-	ns_lock* nl = UA_NULL;
+	Namespace_Lock* nl = UA_NULL;
 	UA_Int32 retval;
 	// when
-	retval = get_node(ns,&(n2->nodeId),&nr,&nl);
+	retval = Namespace_get(ns,&(n2->nodeId),&nr,&nl);
 	// then
 	ck_assert_int_eq(retval, UA_SUCCESS);
 	ck_assert_ptr_eq(nr,n2);
 	// finally
-	delete_ns(ns);
+	Namespace_delete(ns);
 }
 END_TEST
 

+ 14 - 2
tools/UA_stackInternalTypes.bsd

@@ -1,4 +1,16 @@
+<opc:TypeDictionary
+  xmlns:opc="http://opcfoundation.org/BinarySchema/"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:ua="http://opcfoundation.org/UA/"
+  xmlns:tns="http://opcfoundation.org/UA/"
+  DefaultByteOrder="LittleEndian"
+  TargetNamespace="http://opcfoundation.org/UA/"
+>
+
+  <opc:Import Namespace="http://opcfoundation.org/BinarySchema/" />
+
 <!-- 	Types within the Stack Begin  -->
+
    <opc:StructuredType Name="OPCUATcpMessageHeader">
     <opc:Documentation>TCP Header</opc:Documentation>
     <opc:Field Name="MessageType" TypeName="opc:UInt32" />
@@ -64,5 +76,5 @@
     <opc:Field Name="Reason" TypeName="opc:String" />
   </opc:StructuredType>
  
-  
-<!-- Types within the Stack End -->
+<!-- Types within the Stack End -->
+</opc:TypeDictionary>

+ 7 - 7
tools/generate_builtin.py

@@ -73,10 +73,10 @@ def createEnumerated(element):
     valuemap = OrderedDict()
     name = "UA_" + element.get("Name")
     enum_types.append(name)
-    print("\n/*** " + name + " ***/", end='\n', file=fh)
+    print("\n/** @name UA_" + name + " */", end='\n', file=fh)
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/* " + child.text + " */", end='\n', file=fh)
+            print("/** @brief " + child.text + " */", end='\n', file=fh)
         if child.tag == "{http://opcfoundation.org/BinarySchema/}EnumeratedValue":
             valuemap[name + "_" + child.get("Name")] = child.get("Value")
     valuemap = OrderedDict(sorted(valuemap.iteritems(), key=lambda (k,v): int(v)))
@@ -96,7 +96,7 @@ def createEnumerated(element):
 def createStructured(element):
     valuemap = OrderedDict()
     name = "UA_" + element.get("Name")
-    print("\n/*** " + name + " ***/", end='\n', file=fh)
+    print("\n/** @name UA_" + name + " */", end='\n', file=fh)
 
     lengthfields = set()
     for child in element:
@@ -105,7 +105,7 @@ def createStructured(element):
     
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/* " + child.text + " */", end='\n', file=fh)
+            print("/** @brief " + child.text + " */", end='\n', file=fh)
         elif child.tag == "{http://opcfoundation.org/BinarySchema/}Field":
             if child.get("Name") in lengthfields:
                 continue
@@ -122,7 +122,7 @@ def createStructured(element):
     #    print ("type " + name + " is new Request_Base with "),
     # else:
     #    print ("type " + name + " is new UA_Builtin with "),
-    print("typedef struct T_" + name + " {", end='\n', file=fh)
+    print("typedef struct " + name + "_T {", end='\n', file=fh)
     if len(valuemap) == 0:
         typename = stripTypename(element.get("BaseType"))
         childname = camlCase2CCase(typename)
@@ -261,10 +261,10 @@ def createStructured(element):
     
 def createOpaque(element):
     name = "UA_" + element.get("Name")
-    print("\n/*** " + name + " ***/", end='\n', file=fh)
+    print("\n/** @name UA_" + name + " */", end='\n', file=fh)
     for child in element:
         if child.tag == "{http://opcfoundation.org/BinarySchema/}Documentation":
-            print("/* " + child.text + " */", end='\n', file=fh)
+            print("/** @brief " + child.text + " */", end='\n', file=fh)
 
     print("typedef UA_ByteString " + name + ";", end='\n', file=fh)
     print("UA_TYPE_METHOD_PROTOTYPES (" + name + ")", end='\n', file=fh)

+ 1 - 1
tools/indent.sh

@@ -12,7 +12,7 @@ fi
 # E.g. when indenting to the opening braces of an argument list.
 
 indent \
---line-length120 \
+--line-length160 \
 --comment-line-length100 \
 --indent-level4 \
 --use-tabs \