소스 검색

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

Leon Urbas 10 년 전
부모
커밋
50cf6eb1c3

+ 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

+ 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

+ 1 - 1
README.md

@@ -16,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

+ 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.

+ 7 - 1
examples/src/opcuaServerACPLT.c

@@ -34,8 +34,14 @@ int main(void) {
 }
 
 #ifdef LINUX
-
+void tmpTestFunction()
+{
+}
 void server_run() {
+	//just for debugging
+#ifdef DEBUG
+	tmpTestFunction();
+#endif
 	TL_Connection connection;
 	connection.connectionState = CONNECTIONSTATE_CLOSED;
 	connection.writerCallback = (TL_Writer) NL_TCP_writer;

+ 4 - 4
examples/src/xml2ns0.c

@@ -101,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;
@@ -820,7 +820,7 @@ UA_Int32 UA_NodeSet_decodeXML(XML_Stack_t* s, XML_Attr_t* attr, UA_NodeSet* dst,
 		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);
+			Namespace_insert(dst->ns, node);
 			DBG_VERBOSE(printf("Inserting "));DBG_VERBOSE(print_node(node));
 		}
 			break;
@@ -951,7 +951,7 @@ int main() {
 		}
 	}
 	XML_ParserFree(parser);
-	iterate_ns(n.ns, print_node);
+	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;

+ 29 - 6
include/ua_basictypes.h

@@ -98,8 +98,8 @@ UA_Int32 UA_Array_copy(void const * const *src,UA_Int32 noElements, UA_Int32 typ
 	UA_Int32 TYPE##_delete(TYPE * p);									\
 	UA_Int32 TYPE##_deleteMembers(TYPE * p);							\
 	UA_Int32 TYPE##_init(TYPE * p);										\
-	UA_Int32 TYPE##_new(TYPE ** p);
-
+	UA_Int32 TYPE##_new(TYPE ** p); 									\
+	UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
 
 #define UA_TYPE_METHOD_CALCSIZE_SIZEOF(TYPE) \
 UA_Int32 TYPE##_calcSize(TYPE const * p) { return sizeof(TYPE); }
@@ -121,6 +121,14 @@ UA_Int32 TYPE##_delete(TYPE *p) { \
 	return retval; \
 }
 
+#define UA_TYPE_METHOD_COPY(TYPE) \
+UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst){ \
+	UA_Int32 retval = UA_SUCCESS; \
+	retval |= UA_memcpy(dst, src, TYPE##_calcSize(UA_NULL)); \
+	return retval; \
+}
+
+
 #define UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(TYPE) \
 UA_Int32 TYPE##_deleteMembers(TYPE * p) { return UA_SUCCESS; }
 
@@ -141,6 +149,10 @@ UA_Int32 TYPE##_encodeBinary(TYPE const * src, UA_Int32* pos, UA_ByteString *dst
 UA_Int32 TYPE##_init(TYPE * p){ \
 	return TYPE_AS##_init((TYPE_AS*)p); \
 }
+#define UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS) \
+UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst) {return TYPE_AS##_copy((TYPE_AS*) src,(TYPE_AS*)dst); \
+}
+
 
 #define UA_TYPE_METHOD_PROTOTYPES_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_CALCSIZE_AS(TYPE, TYPE_AS) \
@@ -148,7 +160,8 @@ UA_TYPE_METHOD_ENCODEBINARY_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DECODEBINARY_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DELETE_AS(TYPE, TYPE_AS) \
 UA_TYPE_METHOD_DELETEMEMBERS_AS(TYPE, TYPE_AS) \
-UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS)
+UA_TYPE_METHOD_INIT_AS(TYPE, TYPE_AS) \
+UA_TYPE_METHOD_COPY_AS(TYPE, TYPE_AS)
 
 
 #define UA_TYPE_METHOD_NEW_DEFAULT(TYPE) \
@@ -165,6 +178,9 @@ UA_Int32 TYPE##_init(TYPE * p){ \
 	*p = (TYPE)0;\
 	return UA_SUCCESS;\
 }
+//#define UA_TYPE_COPY_METHOD_PROTOTYPE(TYPE) \  UA_Int32 TYPE##_copy(TYPE const *src, TYPE *dst);
+
+
 
 /*** Prototypes for basic types **/
 UA_TYPE_METHOD_PROTOTYPES (UA_Boolean)
@@ -178,7 +194,6 @@ UA_TYPE_METHOD_PROTOTYPES (UA_Int64)
 UA_TYPE_METHOD_PROTOTYPES (UA_UInt64)
 UA_TYPE_METHOD_PROTOTYPES (UA_Float)
 UA_TYPE_METHOD_PROTOTYPES (UA_Double)
-
 /**
 * StatusCodeBinaryEncoding
 * Part: 6
@@ -202,6 +217,7 @@ typedef struct T_UA_VTable {
 	UA_Int32 (*encodeBinary)(void const * src, UA_Int32* pos, UA_ByteString* dst);
 	UA_Int32 (*init)(void * p);
 	UA_Int32 (*new)(void ** p);
+	UA_Int32 (*copy)(void const *src,void *dst);
 	UA_Int32 (*delete)(void * p);
 	UA_Byte* name;
 } UA_VTable;
@@ -218,6 +234,8 @@ typedef struct T_UA_Variant {
 	UA_VTable* vt;		// internal entry into vTable
 	UA_Byte encodingMask; 	// Type of UA_Variant_EncodingMaskType_enum
 	UA_Int32 arrayLength;	// total number of elements
+	UA_Int32 arrayDimensionsLength;
+	UA_Int32 **arrayDimensions;
 	void** data;
 } UA_Variant;
 UA_TYPE_METHOD_PROTOTYPES (UA_Variant)
@@ -230,7 +248,7 @@ typedef struct T_UA_String
 }
 UA_String;
 UA_TYPE_METHOD_PROTOTYPES (UA_String)
-UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
+//UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
 UA_Int32 UA_String_copycstring(char const * src, UA_String* dst);
 UA_Int32 UA_String_copyprintf(char const * fmt, UA_String* dst, ...);
 UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2);
@@ -241,7 +259,7 @@ void UA_String_printx_hex(char const * label, const UA_String* string);
 /* ByteString - Part: 6, Chapter: 5.2.2.7, Page: 17 */
 UA_TYPE_METHOD_PROTOTYPES (UA_ByteString)
 UA_Int32 UA_ByteString_compare(const UA_ByteString *string1, const UA_ByteString *string2);
-UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
+//UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
 UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length);
 extern UA_ByteString UA_ByteString_securityPoliceNone;
 
@@ -259,6 +277,7 @@ typedef struct T_UA_LocalizedText
 }
 UA_LocalizedText;
 UA_TYPE_METHOD_PROTOTYPES (UA_LocalizedText)
+
 UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst);
 void UA_ByteString_printf(char* label, const UA_ByteString* string);
 void UA_ByteString_printx(char* label, const UA_ByteString* string);
@@ -278,6 +297,7 @@ UA_Int32 UA_Guid_compare(const UA_Guid *g1, const UA_Guid *g2);
 /* DateTime - Part: 6, Chapter: 5.2.2.5, Page: 16 */
 typedef UA_Int64 UA_DateTime; //100 nanosecond resolution
 UA_TYPE_METHOD_PROTOTYPES (UA_DateTime)
+
 UA_DateTime UA_DateTime_now();
 typedef struct T_UA_DateTimeStruct
 {
@@ -310,6 +330,7 @@ typedef struct T_UA_NodeId
     identifier;
 } UA_NodeId;
 UA_TYPE_METHOD_PROTOTYPES (UA_NodeId)
+
 UA_Int32 UA_NodeId_compare(const UA_NodeId *n1, const UA_NodeId *n2);
 void UA_NodeId_printf(char* label, const UA_NodeId* node);
 
@@ -321,6 +342,7 @@ typedef struct T_UA_XmlElement
 } UA_XmlElement;
 UA_TYPE_METHOD_PROTOTYPES (UA_XmlElement)
 
+
 /* ExpandedNodeId - Part: 6, Chapter: 5.2.2.10, Page: 19 */
 // 62541-6 Chapter 5.2.2.9, Table 5
 #define UA_NODEIDTYPE_NAMESPACE_URI_FLAG 0x80
@@ -339,6 +361,7 @@ UA_TYPE_METHOD_PROTOTYPES(UA_ExpandedNodeId)
 typedef UA_Int32 UA_IdentifierType;
 UA_TYPE_METHOD_PROTOTYPES(UA_IdentifierType)
 
+
 /* ExtensionObjectBinaryEncoding - Part: 6, Chapter: 5.2.2.15, Page: 21 */
 typedef struct T_UA_ExtensionObject {
 	UA_NodeId typeId;

+ 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;

+ 195 - 38
src/ua_basictypes.c

@@ -30,8 +30,8 @@ UA_Int32 UA_calcSize(void const * data, UA_UInt32 type) {
 
 UA_Int32 UA_Array_calcSize(UA_Int32 nElements, UA_Int32 type, void const * const * data) {
 	if(UA_VTable_isValidType(type) != UA_SUCCESS) return 0;
-	int length = sizeof(UA_Int32);
-	int i;
+	UA_Int32 length = sizeof(UA_Int32);
+	UA_Int32 i;
 
 	if (nElements > 0) {
 		for(i=0; i<nElements;i++) {
@@ -58,7 +58,7 @@ UA_Int32 UA_Array_delete(void *** p, UA_Int32 noElements, UA_Int32 type) {
 
 	void ** arr = *p;
 	if(arr != UA_NULL) {
-		for(int i=0; i<noElements; i++) {
+		for(UA_Int32 i=0; i<noElements; i++) {
 			retval |= UA_[type].delete(arr[i]);
 		}
 	}
@@ -115,26 +115,26 @@ UA_Int32 UA_Array_copy(void const * const * src, UA_Int32 noElements, UA_Int32 t
 	// Get memory for the pointers
 	CHECKED_DECODE(UA_Array_new(dst, noElements, type), dst = UA_NULL;);
 	void **arr = *dst;
+	//void *srcArr = *src;
+
+	//only namespace zero types atm
+	if(UA_VTable_isValidType(type) != UA_SUCCESS)
+		return UA_ERROR;
+
 	for(UA_Int32 i=0; i<noElements; i++) {
-		// FIXME: we only have code to do this for strings yet
-		if (type == UA_STRING || type == UA_BYTESTRING) {
-			UA_String_copy((UA_String *)src[i], (UA_String *)arr[i]);
-		} else {
-			retval = UA_ERR_INVALID_VALUE;
-			break;
-		}
+		UA_[type].copy(src[i], arr[i]);
 	}
 	return retval;
 }
 
-UA_Int32 _UA_free(void * ptr,char *pname,char* f,int l){
+UA_Int32 _UA_free(void * ptr,char *pname,char* f,UA_Int32 l){
 	DBG_VERBOSE(printf("UA_free;%p;;%s;;%s;%d\n",ptr,pname,f,l); fflush(stdout));
 	free(ptr); // checks if ptr != NULL in the background
 	return UA_SUCCESS;
 }
 
 void const * UA_alloc_lastptr;
-UA_Int32 _UA_alloc(void ** ptr, int size,char*pname,char*sname,char* f,int l){
+UA_Int32 _UA_alloc(void ** ptr, UA_Int32 size,char*pname,char*sname,char* f,UA_Int32 l){
 	if(ptr == UA_NULL) return UA_ERR_INVALID_VALUE;
 	UA_alloc_lastptr = *ptr = malloc(size);
 	DBG_VERBOSE(printf("UA_alloc - %p;%d;%s;%s;%s;%d\n",*ptr,size,pname,sname,f,l); fflush(stdout));
@@ -142,7 +142,7 @@ UA_Int32 _UA_alloc(void ** ptr, int size,char*pname,char*sname,char* f,int l){
 	return UA_SUCCESS;
 }
 
-UA_Int32 UA_memcpy(void * dst, void const * src, int size){
+UA_Int32 UA_memcpy(void * dst, void const * src, UA_Int32 size){
 	if(dst == UA_NULL) return UA_ERR_INVALID_VALUE;
 	DBG_VERBOSE(printf("UA_memcpy - %p;%p;%d\n",dst,src,size));
 	memcpy(dst, src, size);
@@ -186,6 +186,8 @@ UA_Int32 UA_Boolean_init(UA_Boolean * p){
 UA_TYPE_METHOD_DELETE_FREE(UA_Boolean)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Boolean)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Boolean)
+UA_TYPE_METHOD_COPY(UA_Boolean)
+
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Byte)
 UA_TYPE_START_ENCODEBINARY(UA_Byte)
 	dst->data[(*pos)++] = *src;
@@ -198,6 +200,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_Byte)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Byte)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_Byte)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Byte)
+UA_TYPE_METHOD_COPY(UA_Byte)
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_SByte)
 UA_TYPE_START_ENCODEBINARY(UA_SByte)
 	dst->data[(*pos)++] = *src;
@@ -209,6 +212,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_SByte)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_SByte)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_SByte)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_SByte)
+UA_TYPE_METHOD_COPY(UA_SByte)
 
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt16)
 UA_TYPE_START_ENCODEBINARY(UA_UInt16)
@@ -223,6 +227,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_UInt16)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_UInt16)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_UInt16)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_UInt16)
+UA_TYPE_METHOD_COPY(UA_UInt16)
 
 /** UA_Int16 - signed integer, 2 bytes */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int16)
@@ -237,6 +242,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_Int16)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Int16)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_Int16)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Int16)
+UA_TYPE_METHOD_COPY(UA_Int16)
 
 /** UA_Int32 - signed integer, 4 bytes */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int32)
@@ -256,6 +262,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_Int32)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Int32)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_Int32)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Int32)
+UA_TYPE_METHOD_COPY(UA_Int32)
 
 /** UA_UInt32 - unsigned integer, 4 bytes */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt32)
@@ -273,6 +280,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_UInt32)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_UInt32)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_UInt32)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_UInt32)
+UA_TYPE_METHOD_COPY(UA_UInt32)
 
 /** UA_Int64 - signed integer, 8 bytes */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Int64)
@@ -300,6 +308,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_Int64)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Int64)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_Int64)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Int64)
+UA_TYPE_METHOD_COPY(UA_Int64)
 
 /** UA_UInt64 - unsigned integer, 8 bytes */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_UInt64)
@@ -321,6 +330,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_UInt64)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_UInt64)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_UInt64)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_UInt64)
+UA_TYPE_METHOD_COPY(UA_UInt64)
 
 /** UA_Float - IEE754 32bit float with biased exponent */
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Float)
@@ -357,6 +367,7 @@ UA_Int32 UA_Float_init(UA_Float * p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Float)
+UA_TYPE_METHOD_COPY(UA_Float)
 
 /** UA_Float - IEEE754 64bit float with biased exponent*/
 UA_TYPE_METHOD_CALCSIZE_SIZEOF(UA_Double)
@@ -396,6 +407,7 @@ UA_TYPE_METHOD_DELETE_FREE(UA_Double)
 UA_TYPE_METHOD_DELETEMEMBERS_NOACTION(UA_Double)
 UA_TYPE_METHOD_INIT_DEFAULT(UA_Double)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Double)
+UA_TYPE_METHOD_COPY(UA_Double)
 
 /** UA_String */
 UA_Int32 UA_String_calcSize(UA_String const * string) {
@@ -531,7 +543,7 @@ void UA_String_printf(char const * label, const UA_String* string) {
 			string->length, (char*)string->data);
 }
 void UA_String_printx(char const * label, const UA_String* string) {
-	int i;
+	UA_Int32 i;
 	if (string == UA_NULL) { printf("%s {NULL}\n", label); return; }
 	printf("%s {Length=%d, Data=", label, string->length);
 	if (string->length > 0) {
@@ -545,7 +557,7 @@ void UA_String_printx(char const * label, const UA_String* string) {
 	printf("}}\n");
 }
 void UA_String_printx_hex(char const * label, const UA_String* string) {
-	int i;
+	UA_Int32 i;
 	printf("%s {Length=%d, Data=", label, string->length);
 	if (string->length > 0) {
 		for (i = 0; i < string->length; i++) {
@@ -578,9 +590,6 @@ UA_Byte UA_Byte_securityPoliceNoneData[] = "http://opcfoundation.org/UA/Security
 // sizeof()-1 : discard the implicit null-terminator of the c-char-string
 UA_ByteString UA_ByteString_securityPoliceNone = { sizeof(UA_Byte_securityPoliceNoneData)-1, UA_Byte_securityPoliceNoneData };
 
-UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst) {
-	return UA_String_copy((UA_String const*)src,(UA_String*)dst);
-}
 UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length) {
 	UA_Int32 retval = UA_SUCCESS;
 	if ((retval |= UA_alloc((void**)&(p->data),length)) == UA_SUCCESS) {
@@ -601,7 +610,7 @@ UA_Int32 UA_Guid_calcSize(UA_Guid const * p) {
 }
 
 UA_TYPE_START_ENCODEBINARY(UA_Guid)
-	int i=0;
+	UA_Int32 i=0;
 	retval |= UA_UInt32_encodeBinary(&(src->data1), pos, dst);
 	retval |= UA_UInt16_encodeBinary(&(src->data2), pos, dst);
 	retval |= UA_UInt16_encodeBinary(&(src->data3), pos, dst);
@@ -612,7 +621,7 @@ UA_TYPE_END_XXCODEBINARY
 
 UA_Int32 UA_Guid_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_Guid *dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	int i=0;
+	UA_Int32 i=0;
 	// TODO: This could be done with a single memcpy (if the compiler does no fancy realigning of structs)
 	CHECKED_DECODE(UA_UInt32_decodeBinary(src,pos,&dst->data1), ;);
 	CHECKED_DECODE(UA_UInt16_decodeBinary(src,pos,&dst->data2), ;);
@@ -627,6 +636,7 @@ UA_Int32 UA_Guid_deleteMembers(UA_Guid* p) { return UA_SUCCESS; }
 UA_Int32 UA_Guid_compare(const UA_Guid *g1, const UA_Guid *g2) {
 	return memcmp(g1, g2, sizeof(UA_Guid));
 }
+
 UA_Int32 UA_Guid_init(UA_Guid* p){
 	if(p==UA_NULL)return UA_ERROR;
 	p->data1 = 0;
@@ -636,7 +646,13 @@ UA_Int32 UA_Guid_init(UA_Guid* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Guid)
-
+UA_Int32 UA_Guid_copy(UA_Guid const *src, UA_Guid *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)&dst,UA_Guid_calcSize(UA_NULL));
+	retval |= UA_memcpy((void*)dst,(void*)src,UA_Guid_calcSize(UA_NULL));
+	return retval;
+}
 UA_Int32 UA_LocalizedText_calcSize(UA_LocalizedText const * p) {
 	UA_Int32 length = 0;
 	if (p==UA_NULL) {
@@ -654,6 +670,7 @@ UA_Int32 UA_LocalizedText_calcSize(UA_LocalizedText const * p) {
 	}
 	return length;
 }
+
 UA_TYPE_START_ENCODEBINARY(UA_LocalizedText)
 	retval |= UA_Byte_encodeBinary(&(src->encodingMask),pos,dst);
 	if (src->encodingMask & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE) {
@@ -679,10 +696,12 @@ UA_Int32 UA_LocalizedText_decodeBinary(UA_ByteString const * src, UA_Int32 *pos,
 	}
 	return retval;
 }
+
 UA_TYPE_METHOD_DELETE_STRUCT(UA_LocalizedText)
 UA_Int32 UA_LocalizedText_deleteMembers(UA_LocalizedText* p) {
 	return UA_SUCCESS | UA_String_deleteMembers(&p->locale) | UA_String_deleteMembers(&p->text);
 }
+
 UA_Int32 UA_LocalizedText_init(UA_LocalizedText* p){
 	if(p==UA_NULL) return UA_ERROR;
 	p->encodingMask = 0;
@@ -690,7 +709,9 @@ UA_Int32 UA_LocalizedText_init(UA_LocalizedText* p){
 	UA_String_init(&(p->text));
 	return UA_SUCCESS;
 }
+
 UA_TYPE_METHOD_NEW_DEFAULT(UA_LocalizedText)
+
 UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst) {
 	UA_Int32 retval = UA_SUCCESS;
 	if(dst==UA_NULL) return UA_ERROR;
@@ -699,7 +720,15 @@ UA_Int32 UA_LocalizedText_copycstring(char const * src, UA_LocalizedText* dst) {
 	retval |= UA_String_copycstring(src,&(dst->text));
 	return retval;
 }
-
+UA_Int32 UA_LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText* dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)dst,UA_LocalizedText_calcSize(UA_NULL));
+	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+	retval |= UA_String_copy(&(src->locale), &(dst->locale));
+	retval |= UA_String_copy(&(src->text), &(dst->text));
+	return retval;
+}
 /* Serialization of UA_NodeID is specified in 62541-6, §5.2.2.9 */
 UA_Int32 UA_NodeId_calcSize(UA_NodeId const *p) {
 	UA_Int32 length = 0;
@@ -736,7 +765,7 @@ UA_TYPE_START_ENCODEBINARY(UA_NodeId)
 	UA_Byte srcByte;
 	UA_UInt16 srcUInt16;
 
-	int retval = UA_SUCCESS;
+	UA_Int32 retval = UA_SUCCESS;
 	retval |= UA_Byte_encodeBinary(&(src->encodingByte),pos,dst);
 	switch (src->encodingByte & UA_NODEIDTYPE_MASK) {
 	case UA_NODEIDTYPE_TWOBYTE:
@@ -769,7 +798,7 @@ UA_TYPE_START_ENCODEBINARY(UA_NodeId)
 UA_TYPE_END_XXCODEBINARY
 
 UA_Int32 UA_NodeId_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_NodeId *dst) {
-	int retval = UA_SUCCESS;
+	UA_Int32 retval = UA_SUCCESS;
 	UA_NodeId_init(dst);
 	// temporary variables to overcome decoder's non-endian-saveness for datatypes with different length
 	UA_Byte   dstByte = 0;
@@ -810,7 +839,7 @@ UA_Int32 UA_NodeId_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_Nod
 
 UA_TYPE_METHOD_DELETE_STRUCT(UA_NodeId)
 UA_Int32 UA_NodeId_deleteMembers(UA_NodeId* p) {
-	int retval = UA_SUCCESS;
+	UA_Int32 retval = UA_SUCCESS;
 	switch (p->encodingByte & UA_NODEIDTYPE_MASK) {
 	case UA_NODEIDTYPE_TWOBYTE:
 	case UA_NODEIDTYPE_FOURBYTE:
@@ -831,7 +860,7 @@ UA_Int32 UA_NodeId_deleteMembers(UA_NodeId* p) {
 }
 
 void UA_NodeId_printf(char* label, const UA_NodeId* node) {
-	int l;
+	UA_Int32 l;
 
 	printf("%s {encodingByte=%d, namespace=%d,", label,
 			(int)( node->encodingByte), (int) (node->namespace));
@@ -841,7 +870,7 @@ void UA_NodeId_printf(char* label, const UA_NodeId* node) {
 	case UA_NODEIDTYPE_TWOBYTE:
 	case UA_NODEIDTYPE_FOURBYTE:
 	case UA_NODEIDTYPE_NUMERIC:
-		printf("identifier=%d", node->identifier.numeric);
+		printf("identifier=%d\n", node->identifier.numeric);
 		break;
 	case UA_NODEIDTYPE_STRING:
 		l = ( node->identifier.string.length < 0 ) ? 0 : node->identifier.string.length;
@@ -899,7 +928,31 @@ UA_Int32 UA_NodeId_init(UA_NodeId* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_NodeId)
+UA_Int32 UA_NodeId_copy(UA_NodeId const *src, UA_NodeId *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_Byte_copy(&(src->encodingByte), &(dst->encodingByte));
 
+	switch (src->encodingByte & UA_NODEIDTYPE_MASK) {
+	case UA_NODEIDTYPE_TWOBYTE:
+	case UA_NODEIDTYPE_FOURBYTE:
+	case UA_NODEIDTYPE_NUMERIC:
+		// nothing to do
+		retval |= UA_UInt16_copy(&(src->namespace),&(dst->namespace));
+		retval |= UA_UInt32_copy(&(src->identifier.numeric),&(dst->identifier.numeric));
+		break;
+	case UA_NODEIDTYPE_STRING: // Table 6, second entry
+		retval |= UA_String_copy(&(src->identifier.string),&(dst->identifier.string));
+		break;
+	case UA_NODEIDTYPE_GUID: // Table 6, third entry
+		retval |= UA_Guid_copy(&(src->identifier.guid),&(dst->identifier.guid));
+		break;
+	case UA_NODEIDTYPE_BYTESTRING: // Table 6, "OPAQUE"
+		retval |= UA_ByteString_copy(&(src->identifier.byteString),&(dst->identifier.byteString));
+		break;
+	}
+	return retval;
+}
 UA_Int32 UA_ExpandedNodeId_calcSize(UA_ExpandedNodeId const * p) {
 	UA_Int32 length = 0;
 	if (p == UA_NULL) {
@@ -955,6 +1008,14 @@ UA_Int32 UA_ExpandedNodeId_init(UA_ExpandedNodeId* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_ExpandedNodeId)
+UA_Int32 UA_ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_String_copy(&(src->namespaceUri), &(dst->namespaceUri));
+	UA_NodeId_copy(&(src->nodeId), &(dst->nodeId));
+	UA_UInt32_copy(&(src->serverIndex), &(dst->serverIndex));
+	return retval;
+}
 
 UA_Int32 UA_ExtensionObject_calcSize(UA_ExtensionObject const * p) {
 	UA_Int32 length = 0;
@@ -974,6 +1035,7 @@ UA_Int32 UA_ExtensionObject_calcSize(UA_ExtensionObject const * p) {
 	}
 	return length;
 }
+
 UA_TYPE_START_ENCODEBINARY(UA_ExtensionObject)
 	retval |= UA_NodeId_encodeBinary(&(src->typeId),pos,dst);
 	retval |= UA_Byte_encodeBinary(&(src->encoding),pos,dst);
@@ -1018,7 +1080,15 @@ UA_Int32 UA_ExtensionObject_init(UA_ExtensionObject* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_ExtensionObject)
-
+UA_Int32 UA_ExtensionObject_copy(UA_ExtensionObject const  *src, UA_ExtensionObject *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_ExtensionObject_calcSize(UA_NULL);
+	retval |= UA_Byte_copy(&(src->encoding),&(dst->encoding));
+	retval |= UA_ByteString_copy(&(src->body),&(dst->body));
+	retval |= UA_NodeId_copy(&(src->typeId),&(dst->typeId));
+	return retval;
+}
 
 /** DiagnosticInfo - Part: 4, Chapter: 7.9, Page: 116 */
 UA_Int32 UA_DiagnosticInfo_calcSize(UA_DiagnosticInfo const * ptr) {
@@ -1065,7 +1135,7 @@ UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const * src, UA_Int32 *pos
 	UA_DiagnosticInfo_init(dst);
 	CHECKED_DECODE(UA_Byte_decodeBinary(src, pos, &(dst->encodingMask)), ;);
 
-	for (int i = 0; i < 7; i++) {
+	for (UA_Int32 i = 0; i < 7; i++) {
 		switch ( (0x01 << i) & dst->encodingMask)  {
 
 		case UA_DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID:
@@ -1096,7 +1166,7 @@ UA_Int32 UA_DiagnosticInfo_decodeBinary(UA_ByteString const * src, UA_Int32 *pos
 	return retval;
 }
 UA_TYPE_START_ENCODEBINARY(UA_DiagnosticInfo)
-	int i;
+	UA_Int32 i;
 	retval |= UA_Byte_encodeBinary(&(src->encodingMask), pos, dst);
 	for (i = 0; i < 7; i++) {
 		switch ( (0x01 << i) & src->encodingMask)  {
@@ -1147,9 +1217,31 @@ UA_Int32 UA_DiagnosticInfo_init(UA_DiagnosticInfo* p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DiagnosticInfo)
+UA_Int32 UA_DiagnosticInfo_copy(UA_DiagnosticInfo const  *src, UA_DiagnosticInfo *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_String_copy(&(src->additionalInfo), &(dst->additionalInfo));
+	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+	retval |= UA_StatusCode_copy(&(src->innerStatusCode), &(dst->innerStatusCode));
+	if(src->innerDiagnosticInfo){
+		retval |= UA_alloc((void**)&(dst->innerDiagnosticInfo),UA_DiagnosticInfo_calcSize(UA_NULL));
+		if(retval == UA_SUCCESS){
+			retval |= UA_DiagnosticInfo_copy(src->innerDiagnosticInfo, dst->innerDiagnosticInfo);
+		}
+	}
+	else{
+		dst->innerDiagnosticInfo = UA_NULL;
+	}
+	retval |= UA_Int32_copy(&(src->locale), &(dst->locale));
+	retval |= UA_Int32_copy(&(src->localizedText), &(dst->localizedText));
+	retval |= UA_Int32_copy(&(src->namespaceUri), &(dst->namespaceUri));
+	retval |= UA_Int32_copy(&(src->symbolicId), &(dst->symbolicId));
 
+	return retval;
+}
 UA_TYPE_METHOD_PROTOTYPES_AS(UA_DateTime,UA_Int64)
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DateTime)
+
 #include <sys/time.h>
 
 // Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
@@ -1259,7 +1351,16 @@ UA_Int32 UA_QualifiedName_init(UA_QualifiedName * p){
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_QualifiedName)
+UA_Int32 UA_QualifiedName_copy(UA_QualifiedName const *src, UA_QualifiedName *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)&dst,UA_QualifiedName_calcSize(UA_NULL));
+	retval |= UA_String_copy(&(src->name),&(dst->name));
+	retval |= UA_UInt16_copy(&(src->namespaceIndex),&(dst->namespaceIndex));
+	retval |= UA_UInt16_copy(&(src->reserved),&(dst->reserved));
+	return retval;
 
+}
 
 UA_Int32 UA_Variant_calcSize(UA_Variant const * p) {
 	UA_Int32 length = 0;
@@ -1267,7 +1368,7 @@ UA_Int32 UA_Variant_calcSize(UA_Variant const * p) {
 	UA_UInt32 ns0Id = p->encodingMask & 0x1F; // Bits 1-5
 	UA_Boolean isArray = p->encodingMask & (0x01 << 7); // Bit 7
 	UA_Boolean hasDimensions = p->encodingMask & (0x01 << 6); // Bit 6
-	int i;
+	UA_Int32 i;
 
 	if (p->vt == UA_NULL || ns0Id != p->vt->ns0Id) {
 		return UA_ERR_INCONSISTENT;
@@ -1294,6 +1395,7 @@ UA_Int32 UA_Variant_calcSize(UA_Variant const * p) {
 			}
 		} else {
 			length += p->vt->calcSize(p->data[0]);
+
 		}
 	}
 	if (hasDimensions) {
@@ -1302,7 +1404,7 @@ UA_Int32 UA_Variant_calcSize(UA_Variant const * p) {
 	return length;
 }
 UA_TYPE_START_ENCODEBINARY(UA_Variant)
-	int i = 0;
+	UA_Int32 i = 0;
 
 	if (src->vt == UA_NULL || ( src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) != src->vt->ns0Id) {
 		return UA_ERR_INCONSISTENT;
@@ -1328,9 +1430,16 @@ UA_TYPE_START_ENCODEBINARY(UA_Variant)
 			retval |= src->vt->encodeBinary(src->data[i],pos,dst);
 		}
 	}
-	if (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) { // encode array dimension field
-		// FIXME: encode array dimension field
-		printf("shit happens - encode array dimension field wanted");
+
+	if (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+		//encode dimension field
+		UA_Int32_encodeBinary(&(src->arrayDimensionsLength), pos, dst);
+		if(src->arrayDimensionsLength >0){
+			for (i=0;i<src->arrayDimensionsLength;i++) {
+				retval |= UA_Int32_encodeBinary(src->arrayDimensions[i], pos, dst);
+			}
+		}
+
 	}
 UA_TYPE_END_XXCODEBINARY
 
@@ -1361,10 +1470,11 @@ UA_Int32 UA_Variant_decodeBinary(UA_ByteString const * src, UA_Int32 *pos, UA_Va
 		CHECKED_DECODE(UA_Array_new(&dst->data, dst->arrayLength, uaIdx), dst->data = UA_NULL);
 		CHECKED_DECODE(UA_Array_decodeBinary(src, dst->arrayLength, uaIdx, pos, &dst->data), UA_Variant_deleteMembers(dst));
 	}
-
+	//decode the dimension field array if present
 	if (dst->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
-		// TODO: decode array dimension field
-		printf("shit happens - decode array dimension field wanted");
+		UA_Int32_decodeBinary(src, pos, &dst->arrayDimensionsLength);
+		CHECKED_DECODE(UA_Array_new((void***)&dst->arrayDimensions, dst->arrayDimensionsLength, UA_INT32), dst->arrayDimensions = UA_NULL);
+		CHECKED_DECODE(UA_Array_decodeBinary(src, dst->arrayLength, uaIdx, pos, &dst->data), UA_Variant_deleteMembers(dst));
 	}
 	return retval;
 }
@@ -1374,6 +1484,7 @@ UA_Int32 UA_Variant_deleteMembers(UA_Variant  * p) {
 	UA_Int32 retval = UA_SUCCESS;
 	if(p->data != UA_NULL) {
 		retval |= UA_Array_delete(&p->data,p->arrayLength,UA_toIndex(p->vt->ns0Id));
+		retval |= UA_Array_delete(&p->data,p->arrayDimensionsLength,UA_INT32_NS0);
 	}
 	return retval;
 }
@@ -1382,11 +1493,41 @@ UA_Int32 UA_Variant_init(UA_Variant * p){
 	p->arrayLength = -1; // no element, p->data == UA_NULL
 	p->data = UA_NULL;
 	p->encodingMask = 0;
+	p->arrayDimensions = 0;
+	p->arrayDimensionsLength = 0;
 	p->vt = &UA_[UA_INVALIDTYPE];
 	return UA_SUCCESS;
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_Variant)
 
+UA_Int32 UA_Variant_copy(UA_Variant const *src, UA_Variant *dst)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 ns0Id = src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK;
+	UA_Int32 uaIdx = UA_toIndex(ns0Id);
+	void * pData;
+	if(UA_VTable_isValidType(uaIdx) != UA_SUCCESS){
+		return UA_ERROR;
+	}
+	dst->vt = &UA_[uaIdx];
+	retval |= UA_Int32_copy(&(src->arrayLength), &(dst->arrayLength));
+	retval |= UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+	retval |= UA_Int32_copy(&(src->arrayDimensionsLength), &(dst->arrayDimensionsLength));
+
+	if (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_ARRAY) {
+		retval |=  UA_Array_copy((const void * const *)(src->data),src->arrayLength, uaIdx,(void***)&(dst->data));
+	}
+	else {
+		UA_alloc((void**)&pData,UA_[uaIdx].calcSize(UA_NULL));
+		dst->data = &pData;
+		UA_[uaIdx].copy(src->data[0], dst->data[0]);
+	}
+
+	if (src->encodingMask & UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) {
+		retval |=  UA_Array_copy((const void * const *)(src->arrayDimensions),src->arrayDimensionsLength, UA_toIndex(UA_INT32_NS0),(void***)&(dst->arrayDimensions));
+	}
+	return retval;
+}
 
 //TODO: place this define at the server configuration
 #define MAX_PICO_SECONDS 1000
@@ -1490,6 +1631,19 @@ UA_Int32 UA_DataValue_init(UA_DataValue * p){
 }
 UA_TYPE_METHOD_NEW_DEFAULT(UA_DataValue)
 
+UA_Int32 UA_DataValue_copy(UA_DataValue const *src, UA_DataValue *dst){
+	UA_Int32 retval = UA_SUCCESS;
+	//TODO can be optimized by direct UA_memcpy call
+	UA_Byte_copy(&(src->encodingMask), &(dst->encodingMask));
+	UA_Int16_copy(&(src->serverPicoseconds),&(dst->serverPicoseconds));
+	UA_DateTime_copy(&(src->serverTimestamp),&(dst->serverTimestamp));
+	UA_Int16_copy(&(src->sourcePicoseconds), &(dst->sourcePicoseconds));
+	UA_DateTime_copy(&(src->sourceTimestamp),&(dst->sourceTimestamp));
+	UA_StatusCode_copy(&(src->status),&(dst->status));
+	UA_Variant_copy(&(src->value),&(dst->value));
+
+	return retval;
+}
 /* UA_InvalidType - internal type necessary to handle inited Variants correctly */
 UA_Int32 UA_InvalidType_calcSize(UA_InvalidType const * p) {
 	return 0;
@@ -1513,6 +1667,9 @@ UA_Int32 UA_InvalidType_deleteMembers(UA_InvalidType* p) {
 UA_Int32 UA_InvalidType_init(UA_InvalidType* p) {
 	return UA_ERR_INVALID_VALUE;
 }
+UA_Int32 UA_InvalidType_copy(UA_InvalidType const* src, UA_InvalidType *dst) {
+	return UA_ERR_INVALID_VALUE;
+}
 UA_Int32 UA_InvalidType_new(UA_InvalidType** p) {
 	return UA_ERR_INVALID_VALUE;
 }

+ 206 - 227
src/ua_namespace.c

@@ -2,26 +2,11 @@
 #include <string.h>
 #include <stdio.h>
 
-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; */
-
-UA_Int32 init_tc(transaction_context * tc) {
+/*****************************************/
+/* Internal (not exported) functionality */
+/*****************************************/
+
+UA_Int32 Namespace_TransactionContext_init(Namespace_TransactionContext * tc) {
 	return UA_list_init((UA_list_List *) tc);
 }
 
@@ -29,6 +14,7 @@ UA_Int32 init_tc(transaction_context * tc) {
    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;
@@ -70,164 +56,6 @@ static struct prime_ent const prime_tab[] = {
 	{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 */
 #undef get16bits
@@ -237,11 +65,11 @@ void delete_node(namespace * ns, UA_NodeId * nodeid) {
 #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;
@@ -292,7 +120,7 @@ static hash_t hash_string(const UA_Byte * data, UA_Int32 len) {
 	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:
@@ -303,8 +131,7 @@ static hash_t hash(const UA_NodeId * n) {
 	case UA_NODEIDTYPE_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;
 	}
@@ -312,7 +139,7 @@ static hash_t hash(const UA_NodeId * 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 unsigned int higher_prime_index(unsigned long n) {
+static inline unsigned int higher_prime_index(unsigned long n) {
 	unsigned int low = 0;
 	unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
 
@@ -324,14 +151,10 @@ static unsigned int higher_prime_index(unsigned long n) {
 			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.  */
 #ifdef UNSIGNED_64BIT_TYPE
@@ -347,21 +170,20 @@ static inline hash_t mod_1(hash_t x, hash_t y, hash_t inv, int shift) {
 		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);
 }
 
-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);
 }
 
-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;
 
@@ -406,20 +228,11 @@ static inline void clear_slot(namespace * ns, ns_entry * slot) {
 
 }
 
-/* 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);
@@ -449,21 +262,11 @@ static UA_Int32 find_slot(const namespace * ns, ns_entry ** slot, const UA_NodeI
 	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) {
+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)
 		return slot;
@@ -486,14 +289,14 @@ static ns_entry *find_empty_slot(const namespace * ns, hash_t h) {
    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;
+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.  */
@@ -504,16 +307,16 @@ static UA_Int32 expand(namespace * ns) {
 	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));
+			Namespace_Entry *q = find_empty_slot(ns, hash(&p->node->nodeId));
 			*q = *p;
 		}
 		p++;
@@ -522,3 +325,179 @@ static UA_Int32 expand(namespace * ns) {
 	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;
+}

+ 61 - 46
src/ua_namespace.h

@@ -9,68 +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
 
+static inline void Namespace_Lock_release(Namespace_Lock * lock) {
+#ifdef MULTITHREADING
+	pthread_rwlock_unlock((pthread_rwlock_t *) 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.
-
-   A transaction_context 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 transaction_context;
-UA_Int32 init_tc(transaction_context * tc);
+   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 {
+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);
-
-// use only for _single_ writes.
-UA_Int32 get_writable_node(namespace const *ns, const UA_NodeId * nodeid, UA_Node ** result,
-						   ns_lock ** lock);
-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);
-typedef void (*node_visitor) (UA_Node const *node);
-UA_Int32 iterate_ns(const namespace * ns, node_visitor visitor);
-void delete_node(namespace * ns, UA_NodeId * nodeid);
-
-// 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
-}
+	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);
 
-typedef uint32_t hash_t;
+/** @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_ */

+ 8 - 2
src/ua_transport_binary_secure.c

@@ -167,7 +167,13 @@ UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString* msg, UA_Int3
 
 	return retval;
 }
-
+/**
+ *
+ * @param connection
+ * @param msg
+ * @param pos
+ * @return
+ */
 UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_Int32* pos) {
 	DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
 	UA_Int32 retval = UA_SUCCESS;
@@ -184,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;

+ 338 - 3
tests/check_builtin.c

@@ -1,6 +1,6 @@
 /*
  ============================================================================
- Name        : check_stack.c
+ Name        : check_builtin.c
  Author      :
  Copyright   : Your copyright notice
  Description :
@@ -1448,7 +1448,7 @@ START_TEST(UA_DateTime_toStructShallWorkOnExample)
 	ck_assert_int_eq(dst.year, 2014);
 }
 END_TEST
-START_TEST(UA_DateTime_toStingShallWorkOnExample)
+START_TEST(UA_DateTime_toStringShallWorkOnExample)
 {
 	// given
 	UA_DateTime src = 13974671891234567;
@@ -1472,6 +1472,330 @@ START_TEST(UA_DateTime_toStingShallWorkOnExample)
 	ck_assert_int_eq(dst.data[4], '4');
 }
 END_TEST
+START_TEST(UA_ExtensionObject_copyShallWorkOnExample)
+{
+	UA_ExtensionObject *value = UA_NULL;
+	UA_ExtensionObject *valueCopied = UA_NULL;
+	UA_Int32 i = 0;
+
+	// given
+	UA_Byte data[3] = {1,2,3};
+
+
+	UA_ExtensionObject_new(&value);
+	UA_ExtensionObject_new(&valueCopied);
+
+
+	// empty ExtensionObject, handcoded
+	// when
+	value->typeId.encodingByte = UA_NODEIDTYPE_TWOBYTE;
+	value->typeId.identifier.numeric = 0;
+	value->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_NOBODYISENCODED;
+	value->encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
+	value->body.data = data;
+	value->body.length = 3;
+
+	//when
+	UA_ExtensionObject_copy(value,valueCopied);
+
+	for(i=0; i<3; i++){
+		ck_assert_int_eq(valueCopied->body.data[i],value->body.data[i]);
+	}
+
+	ck_assert_int_eq(valueCopied->encoding, value->encoding);
+	ck_assert_int_eq(valueCopied->typeId.encodingByte,value->typeId.encodingByte);
+	ck_assert_int_eq(valueCopied->typeId.identifier.numeric,value->typeId.identifier.numeric);
+	//finally
+	UA_free(value);
+	UA_free(valueCopied);
+}
+END_TEST
+
+START_TEST(UA_Array_copyByteArrayShallWorkOnExample)
+{
+	//given
+	UA_String testString;
+	UA_Byte* *srcArray = UA_NULL;
+	UA_Byte** dstArray;
+	UA_Int32 size = 5;
+	UA_Int32 i = 0;
+	testString.data = UA_NULL;
+	UA_alloc((void**)&testString.data, size);
+	UA_alloc((void*)&srcArray,sizeof(UA_Byte*)*5);
+	testString.data[0] = 'O';
+	testString.data[1] = 'P';
+	testString.data[2] = 'C';
+	testString.data[3] = 'U';
+	testString.data[4] = 'A';
+
+	testString.length = 5;
+
+	srcArray[0] = &(testString.data[0]);
+	srcArray[1] = &testString.data[1];
+	srcArray[2] = &testString.data[2];
+	srcArray[3] = &testString.data[3];
+	srcArray[4] = &testString.data[4];
+	//when
+	UA_Array_copy((const void* const*)srcArray,5,UA_BYTE,(void***)&dstArray);
+	//then
+	for(i=0;i<size;i++){
+		ck_assert_int_eq(*srcArray[i], *dstArray[i]);
+	}
+
+	//finally
+	UA_free(*srcArray);
+	UA_free(*dstArray);
+
+}
+END_TEST
+
+START_TEST(UA_Array_copyUA_StringShallWorkOnExample)
+{
+	// given
+	UA_Int32 i,j;
+	UA_String **srcArray; UA_Array_new((void***)&srcArray,3,UA_STRING);
+	UA_String **dstArray;
+
+	UA_String_copycstring("open",srcArray[0]);
+	UA_String_copycstring("62541",srcArray[1]);
+	UA_String_copycstring("opc ua",srcArray[2]);
+	//when
+	UA_Array_copy((void const*const*)srcArray,3,UA_STRING,(void ***)&dstArray);
+	//then
+	for(i=0;i<3;i++){
+		for(j=0;j<3;j++){
+			ck_assert_int_eq(srcArray[i]->data[j], dstArray[i]->data[j]);
+		}
+		ck_assert_int_eq(srcArray[i]->length, dstArray[i]->length);
+	}
+	//finally
+	UA_free(*srcArray);
+	UA_free(*dstArray);
+
+}
+END_TEST
+
+
+START_TEST(UA_DiagnosticInfo_copyShallWorkOnExample)
+{
+	//given
+	UA_DiagnosticInfo *value = UA_NULL;
+	UA_DiagnosticInfo *innerValue = UA_NULL;
+	UA_DiagnosticInfo *copiedValue = UA_NULL;
+	UA_String testString;
+	UA_Int32 size = 5;
+	UA_Int32 i = 0;
+	testString.data = UA_NULL;
+
+	UA_alloc((void**)&testString.data,size);
+	testString.data[0] = 'O';
+	testString.data[1] = 'P';
+	testString.data[2] = 'C';
+	testString.data[3] = 'U';
+	testString.data[4] = 'A';
+	testString.length = size;
+
+	UA_DiagnosticInfo_new(&value);
+	UA_DiagnosticInfo_new(&innerValue);
+	value->encodingMask |= UA_DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO;
+	value->innerDiagnosticInfo = innerValue;
+
+	UA_alloc((void**)&copiedValue,UA_DiagnosticInfo_calcSize(UA_NULL));
+	value->additionalInfo.length = testString.length;
+	value->additionalInfo.data = testString.data;
+	//when
+	UA_DiagnosticInfo_copy(value, copiedValue);
+
+	//then
+	for(i=0; i<size; i++){
+		ck_assert_int_eq(copiedValue->additionalInfo.data[i],value->additionalInfo.data[i]);
+	}
+	ck_assert_int_eq(copiedValue->additionalInfo.length, value->additionalInfo.length);
+
+	ck_assert_int_eq(copiedValue->encodingMask, value->encodingMask);
+	ck_assert_int_eq(copiedValue->innerDiagnosticInfo->locale,value->innerDiagnosticInfo->locale);
+	ck_assert_int_eq(copiedValue->innerStatusCode,value->innerStatusCode);
+	ck_assert_int_eq(copiedValue->locale,value->locale);
+	ck_assert_int_eq(copiedValue->localizedText,value->localizedText);
+	ck_assert_int_eq(copiedValue->namespaceUri,value->namespaceUri);
+	ck_assert_int_eq(copiedValue->symbolicId,value->symbolicId);
+	//finally
+	UA_free(copiedValue);
+	UA_free(value);
+
+}
+END_TEST
+
+START_TEST(UA_Variant_copyShallWorkOnSingleValueExample)
+{
+	//given
+	UA_Variant *value = UA_NULL;
+	UA_Variant *copiedValue = UA_NULL;
+
+	UA_Int32 i = 0;
+	UA_String testString;
+	UA_String* ptestString;
+	UA_String* pCopiedString;
+	testString.length = 5;
+	UA_alloc((void**)&(testString.data),testString.length);
+
+	testString.data[0] = 'O';
+	testString.data[1] = 'P';
+	testString.data[2] = 'C';
+	testString.data[3] = 'U';
+	testString.data[4] = 'A';
+
+	UA_Variant_new(&value);
+	UA_Variant_new(&copiedValue);
+	ptestString = &testString;
+	value->data = (void**)&ptestString;
+	value->encodingMask |= UA_STRING_NS0;
+
+	//value->encodingMask |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
+
+	//when
+	UA_Variant_copy(value,copiedValue);
+
+
+	//then
+	pCopiedString = *(UA_String**)copiedValue->data;
+	for(i=0;i<3;i++){
+		ck_assert_int_eq(pCopiedString->data[i], pCopiedString->data[i]);
+	}
+	ck_assert_int_eq(pCopiedString->length, pCopiedString->length);
+
+	ck_assert_int_eq(value->encodingMask,copiedValue->encodingMask);
+	ck_assert_int_eq(value->arrayDimensionsLength, copiedValue->arrayDimensionsLength);
+	ck_assert_int_eq(value->arrayLength, copiedValue->arrayLength);
+	//finally
+	UA_free(value);
+	UA_free(copiedValue);
+}
+END_TEST
+
+START_TEST(UA_Variant_copyShallWorkOn1DArrayExample)
+{
+	// given
+	UA_Variant *value = UA_NULL;
+	UA_Variant *copiedValue = UA_NULL;
+	UA_Int32 *dimensions;
+	UA_Int32 i,j,i1,i2;
+	UA_String **srcArray; UA_Array_new((void***)&srcArray,3,UA_STRING);
+
+	UA_alloc((void**)&dimensions,UA_Int32_calcSize(UA_NULL));
+	UA_String_copycstring("__open",srcArray[0]);
+	UA_String_copycstring("_62541",srcArray[1]);
+	UA_String_copycstring("opc ua",srcArray[2]);
+
+	dimensions[0]=3;
+	UA_Variant_new(&value);
+	UA_Variant_new(&copiedValue);
+
+	value->arrayLength = 3;
+	value->data = (void**)srcArray;
+	value->arrayDimensionsLength = 1;
+	value->arrayDimensions = &dimensions;
+	value->encodingMask |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	value->encodingMask |= UA_STRING_NS0;
+	value->encodingMask |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
+
+	//when
+	UA_Variant_copy(value,copiedValue);
+
+	//then
+	i1 = *(value->arrayDimensions)[0],
+	i2 = *(copiedValue->arrayDimensions)[0];
+	ck_assert_int_eq(i1,i2);
+
+	for(i=0;i<3;i++){
+		for(j=0;j<6;j++){
+			ck_assert_int_eq(((UA_String*)(value->data[i]))->data[j],((UA_String*)(copiedValue->data[i]))->data[j]);
+		}
+		ck_assert_int_eq(((UA_String*)(value->data[i]))->length,((UA_String*)(copiedValue->data[i]))->length);
+	}
+	ck_assert_int_eq(((UA_String*)(copiedValue->data[0]))->data[2],'o');
+	ck_assert_int_eq(((UA_String*)(copiedValue->data[0]))->data[3],'p');
+
+
+	ck_assert_int_eq(value->encodingMask,copiedValue->encodingMask);
+	ck_assert_int_eq(value->arrayDimensionsLength, copiedValue->arrayDimensionsLength);
+	ck_assert_int_eq(value->arrayLength, copiedValue->arrayLength);
+	//finally
+	UA_free(value);
+	UA_free(copiedValue);
+}
+END_TEST
+
+START_TEST(UA_Variant_copyShallWorkOn2DArrayExample)
+{
+	// given
+	UA_Variant *value = UA_NULL;
+	UA_Variant *copiedValue = UA_NULL;
+	UA_Int32 **dimensions;
+	UA_Int32 i,i1,i2;
+	UA_Int32 dim1,dim2;
+	UA_Int32 **srcArray;
+	UA_Array_new((void***)&srcArray,6,UA_INT32);
+
+	dim1 = 3;
+	dim2 = 2;
+	*srcArray[0] = 0;
+	*srcArray[1] = 1;
+	*srcArray[2] = 2;
+	*srcArray[3] = 3;
+	*srcArray[4] = 4;
+	*srcArray[5] = 5;
+
+	UA_Array_new((void***)&dimensions,2,UA_INT32);
+
+	*(dimensions)[0] = dim1;
+	*(dimensions)[1] = dim2;
+
+	UA_Variant_new(&value);
+	UA_Variant_new(&copiedValue);
+
+	value->arrayLength = 6;
+	value->data = (void**)srcArray;
+	value->arrayDimensionsLength = 2;
+	value->arrayDimensions = dimensions;
+	value->encodingMask |= UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
+	value->encodingMask |= UA_INT32_NS0;
+	value->encodingMask |= UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
+
+	//when
+	UA_Variant_copy(value, copiedValue);
+
+	//then
+	//1st dimension
+	i1 = *(value->arrayDimensions)[0],
+	i2 = *(copiedValue->arrayDimensions)[0];
+	ck_assert_int_eq(i1,i2);
+	ck_assert_int_eq(i1, dim1);
+
+
+	//2nd dimension
+	i1 = *(value->arrayDimensions)[1];
+	i2 = *(copiedValue->arrayDimensions)[1];
+	ck_assert_int_eq(i1,i2);
+	ck_assert_int_eq(i1, dim2);
+
+
+	for(i=0;i<6;i++){
+		i1 = *((UA_Int32*)(value->data[i]));
+		i2 = *((UA_Int32*)(copiedValue->data[i]));
+		ck_assert_int_eq(i1,i2);
+		ck_assert_int_eq(i2,i);
+	}
+
+	ck_assert_int_eq(value->encodingMask,copiedValue->encodingMask);
+	ck_assert_int_eq(value->arrayDimensionsLength, copiedValue->arrayDimensionsLength);
+	ck_assert_int_eq(value->arrayLength, copiedValue->arrayLength);
+	//finally
+	UA_free(value);
+	UA_free(copiedValue);
+
+}
+END_TEST
 
 Suite *testSuite_builtin(void)
 {
@@ -1582,9 +1906,20 @@ Suite *testSuite_builtin(void)
 
 	TCase *tc_convert = tcase_create("convert");
 	tcase_add_test(tc_convert, UA_DateTime_toStructShallWorkOnExample);
-	tcase_add_test(tc_convert, UA_DateTime_toStingShallWorkOnExample);
+	tcase_add_test(tc_convert, UA_DateTime_toStringShallWorkOnExample);
 	suite_add_tcase(s,tc_convert);
 
+	TCase *tc_copy = tcase_create("copy");
+	tcase_add_test(tc_copy,UA_Array_copyByteArrayShallWorkOnExample);
+	tcase_add_test(tc_copy,UA_Array_copyUA_StringShallWorkOnExample);
+	tcase_add_test(tc_copy, UA_ExtensionObject_copyShallWorkOnExample);
+
+	tcase_add_test(tc_copy, UA_Variant_copyShallWorkOnSingleValueExample);
+	tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn1DArrayExample);
+	tcase_add_test(tc_copy, UA_Variant_copyShallWorkOn2DArrayExample);
+
+	tcase_add_test(tc_copy, UA_DiagnosticInfo_copyShallWorkOnExample);
+	suite_add_tcase(s,tc_copy);
 	return s;
 }
 

+ 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>

+ 28 - 9
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)))
@@ -89,14 +89,14 @@ def createEnumerated(element):
     print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_UInt32)", end='\n', file=fc)
     print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_UInt32)", end='\n', file=fc)
     print("UA_TYPE_METHOD_INIT_AS("+name+", UA_UInt32)", end='\n', file=fc)
+    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_UInt32)",'\n', file=fc)  
     print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
-    
     return
     
 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)
@@ -140,6 +140,7 @@ def createStructured(element):
     print("UA_Int32 " + name + "_deleteMembers(" + name + "* p);", end='\n', file=fh)
     print("UA_Int32 " + name + "_init("+ name + " * p);", end='\n', file=fh)
     print("UA_Int32 " + name + "_new(" + name + " ** p);", end='\n', file=fh)
+    print("UA_Int32 " + name + "_copy(" + name + "* src, " + name + "* dst);", end='\n', file=fh)
 
     print("UA_Int32 "  + name + "_calcSize(" + name + " const * ptr) {", end='', file=fc)
     print("\n\tif(ptr==UA_NULL){return sizeof("+ name +");}", end='', file=fc)
@@ -241,13 +242,29 @@ def createStructured(element):
 
     # code _new
     print("UA_TYPE_METHOD_NEW_DEFAULT(" + name + ")", end='\n', file=fc)
-        
+    # code _copy
+    print("UA_Int32 "+name+"_copy(" + name + " * src," + name + " * dst) {\n\tUA_Int32 retval = UA_SUCCESS;", end='\n', file=fc)
+    for n,t in valuemap.iteritems():
+        if t in elementary_size:
+            print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
+        else:
+            if t in enum_types:
+                print('\tretval |= UA_'+t+'_copy(&(src->'+n+'),&(dst->'+n+'));', end='\n', file=fc)
+            elif t.find("**") != -1:
+                print('\tretval |= UA_Int32_copy(&(src->'+n+'Size),&(dst->'+n+'Size)); // size of following array', end='\n', file=fc)
+		print("\tretval |= UA_Array_copy((void const* const*) (src->"+n+"), src->"+n+"Size," + "UA_toIndex(UA_"+t[0:t.find("*")].upper()+")"+",(void***)&(dst->"+n+"));", end='\n', file=fc)
+            elif t.find("*") != -1:
+                print('\tretval |= UA_' + t[0:t.find("*")] + '_copy(src->' + n + ',dst->' + n + ');', end='\n', file=fc)
+            else:
+                print('\tretval |= UA_'+t+"_copy(&(src->"+n+"),&(dst->" + n + '));', end='\n', file=fc)
+    print("\treturn retval;\n}\n", end='\n', file=fc)
+    
 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)
@@ -257,7 +274,9 @@ def createOpaque(element):
     print("UA_TYPE_METHOD_DELETE_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_DELETEMEMBERS_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_INIT_AS("+name+", UA_ByteString)", end='\n', file=fc)
+    print("UA_TYPE_METHOD_COPY_AS("+name+", UA_ByteString)", end='\n', file=fc)
     print("UA_TYPE_METHOD_NEW_DEFAULT("+name+")\n", end='\n', file=fc)
+
     return
 
 ns = {"opc": "http://opcfoundation.org/BinarySchema/"}

+ 2 - 0
tools/generate_namespace.py

@@ -129,6 +129,7 @@ for row in rows2:
           ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
           ",(UA_Int32(*)(void *))"+name+"_init"+
           ",(UA_Int32(*)(void **))"+name+"_new"+
+	  ",(UA_Int32(*)(void const * ,void*))"+name+"_copy"+
           ",(UA_Int32(*)(void *))"+name+"_delete"+
           ',(UA_Byte*)"'+name+'"},',end='\n',file=fc) 
 name = "UA_InvalidType"
@@ -138,6 +139,7 @@ print("\t{0" +
           ",(UA_Int32(*)(void const*,UA_Int32*,UA_ByteString*))"+name+"_encodeBinary"+
           ",(UA_Int32(*)(void *))"+name+"_init"+
           ",(UA_Int32(*)(void **))"+name+"_new"+
+	  ",(UA_Int32(*)(void const *, void *))"+name+"_copy"+
           ",(UA_Int32(*)(void *))"+name+"_delete"+
           ',(UA_Byte*)"'+name+'"}',end='\n',file=fc)
 print("};", end='\n', file=fc) 

+ 2 - 1
tools/indent.sh

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