Kaynağa Gözat

Merge branch 'master' of https://github.com/Stasik0/Open62541

Conflicts:
	examples/src/opcuaServer.c
	src/opcua_binaryEncDec.c
	src/opcua_secureChannelLayer.c
	src/opcua_time.c
	tests/check_stack.c
FlorianPalm 11 yıl önce
ebeveyn
işleme
f62b2baf4a

+ 2 - 1
examples/src/Makefile.am

@@ -1,8 +1,9 @@
 
 bin_PROGRAMS= $(top_builddir)/bin/exampleServer
 __top_builddir__bin_exampleServer_LDFLAGS = -all-static
+__top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c
-__top_builddir__bin_exampleServer_LDADD= ../../lib/libopen62541.a
+__top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a
 
 #optimization levels depending on debug
 if DEBUG

+ 5 - 8
examples/src/opcuaServer.c

@@ -13,11 +13,10 @@
 
 
 
-#include "../../src/opcua_binaryEncDec.h"
-#include "../../src/opcua_builtInDatatypes.h"
-#include "../../src/opcua_transportLayer.h"
-#include "../../src/opcua_types.h"
-#include "../../src/opcua_time.h"
+#include "opcua_binaryEncDec.h"
+#include "opcua_builtInDatatypes.h"
+#include "opcua_transportLayer.h"
+#include "opcua_types.h"
 
 #ifdef LINUX
 
@@ -51,9 +50,7 @@ int main(void)
 
 void server_init()
 {
-	puts("Starting Demo Server");
-	Int64 now = opcua_time_now();
-	printf("now");
+	puts("starting demo Server");
 	//call listen
 
 }

+ 7 - 0
include/UA_abbr.h

@@ -0,0 +1,7 @@
+#ifndef UA_ABBR_H_
+#define UA_ABBR_H_
+
+
+
+#endif /* UA_ABBR_H_ */
+

+ 12 - 0
include/UA_config.h

@@ -0,0 +1,12 @@
+#ifndef UA_CONFIG_H_
+#define UA_CONFIG_H_
+
+//TODO: include all other header files
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "opcua_builtInDatatypes.h"
+#include "UA_abbr.h"
+
+
+#endif /* UA_CONFIG_H_ */

+ 40 - 0
include/UA_indexedList.h

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

+ 61 - 0
include/UA_list.h

@@ -0,0 +1,61 @@
+#ifndef UA_LIST_H_
+#define UA_LIST_H_
+
+#include "opcua_builtInDatatypes.h"
+
+/*
+ * Double Linked Lists
+ */
+
+typedef void (*UA_list_PayloadVisitor)(void* payload);
+
+typedef struct T_UA_list_Element {
+	struct T_UA_list_List* father;
+	void *payload;
+    struct T_UA_list_Element* next;
+    struct T_UA_list_Element* prev;
+}UA_list_Element;
+
+typedef struct T_UA_list_List {
+   struct T_UA_list_Element* first;
+   struct T_UA_list_Element* last;
+   Int32 size;
+}UA_list_List;
+
+typedef void (*UA_list_ElementVisitor)(UA_list_Element* payload);
+
+typedef Boolean (*UA_list_PayloadMatcher)(void* payload);
+
+void UA_list_defaultFreer(void* payload);
+
+Int32 UA_list_initElement(UA_list_Element* const element);
+
+Int32 UA_list_init(UA_list_List* const list);
+
+Int32 UA_list_addElementToFront(UA_list_List* const list, UA_list_Element* const element);
+
+Int32 UA_list_addPayloadToFront(UA_list_List* const list, void* const payload);
+
+Int32 UA_list_addElementToBack(UA_list_List* const list, UA_list_Element* const element);
+
+Int32 UA_list_addPayloadToBack(UA_list_List* const list, void* const payload);
+
+Int32 UA_list_removeFirst(UA_list_List* const list, UA_list_PayloadVisitor visitor);
+
+Int32 UA_list_removeLast(UA_list_List* const list, UA_list_PayloadVisitor visitor);
+
+Int32 UA_list_removeElement(UA_list_Element* const elem, UA_list_PayloadVisitor visitor);
+
+Int32 UA_list_destroy(UA_list_List* const list, UA_list_PayloadVisitor visitor);
+
+Int32 UA_list_iterateElement(UA_list_List* const list, UA_list_ElementVisitor visitor);
+
+Int32 UA_list_iteratePayload(UA_list_List* const list, UA_list_PayloadVisitor visitor);
+
+UA_list_Element* UA_list_find(UA_list_List* const list, UA_list_PayloadMatcher matcher);
+
+UA_list_Element* UA_list_getFirst(UA_list_List* const list);
+
+UA_list_Element* UA_list_getLast(UA_list_List* const list);
+
+#endif /* UA_LIST_H_ */

+ 4 - 1
src/Makefile.am

@@ -36,7 +36,10 @@ libopen62541_la_SOURCES = opcua_builtInDatatypes.c\
 						opcua_secureChannelLayer.h\
 						opcua_memory.h\
 						opcua_time.h\
-						tcp_layer.h						
+						tcp_layer.h\
+						util/UA_list.c\
+						util/UA_indexedList.c						
+libopen62541_la_CFLAGS = -I $(top_builddir)/include
 
 #bin_PROGRAMS= $(top_builddir)/bin/open62541.out
 #__top_builddir__bin_libOpen62541_out_SOURCES = opcuaServer.c

+ 5 - 4
src/opcua_binaryEncDec.c

@@ -553,6 +553,7 @@ Int32 encoder_encodeBuiltInDatatypeArray(void **data, Int32 size, Int32 arrayTyp
 
 			break;
 		}
+		encoder_encodeBuiltInDatatype(data[i], type, pos, dstBuf);
 	}
 	return UA_NO_ERROR;
 }
@@ -1193,7 +1194,7 @@ Int32 encodeVariant(UA_Variant *variant, Int32 *pos, char *dstBuf) {
 				pos, dstBuf);
 		if (variant->ArrayLength > 0) {
 			//encode array as given by variant type
-			encoder_encodeBuiltInDatatypeArray((void*) variant->Value,
+			encode_builtInDatatypeArray((void*) variant->Value,
 					variant->ArrayLength, (variant->EncodingMask & 31), pos,
 					dstBuf);
 		}
@@ -1388,13 +1389,13 @@ Int32 decodeDiagnosticInfo(char const * buf, Int32 *pos,
 Int32 encodeDiagnosticInfo(UA_DiagnosticInfo *diagnosticInfo, Int32 *pos,
 		char *dstbuf) {
 	Byte mask;
-	mask = 0;
+	int i;
 
 	encoder_encodeBuiltInDatatype((void*) (&(diagnosticInfo->EncodingMask)),
 			BYTE, pos, dstbuf);
-	for (mask = 1; mask <= 0x40; mask = mask << 1) {
+	for (i = 0; i < 7; i++) {
 
-		switch (mask & (diagnosticInfo->EncodingMask)) {
+		switch ( (0x01 << i) & diagnosticInfo->EncodingMask)  {
 		case DIEMT_SYMBOLIC_ID:
 			//	puts("diagnosticInfo symbolic id");
 			encoder_encodeBuiltInDatatype((void*) &(diagnosticInfo->SymbolicId),

+ 2 - 0
src/opcua_builtInDatatypes.c

@@ -8,6 +8,7 @@
 #include <stdio.h>
 
 UA_ExtensionObject the_empty_UA_ExtensionObject = { { NIEVT_TWO_BYTE, 0 }, NO_BODY_IS_ENCODED};
+UA_DiagnosticInfo the_empty_UA_DiagnosticInfo = { 0x00 };
 
 Int32 UA_String_compare(UA_String *string1, UA_String *string2) {
 	Int32 i;
@@ -46,6 +47,7 @@ void UA_ByteString_printx(char* label, UA_ByteString* string) {
 	if (string->Length > 0) {
 		for (i = 0; i < string->Length; i++) {
 			printf("%c%d", i == 0 ? '{' : ',', (string->Data)[i]);
+			if (i > 0 && !(i%20)) { printf("\n\t"); }
 		}
 	} else {
 		printf("{");

+ 4 - 0
src/opcua_builtInDatatypes.h

@@ -9,6 +9,9 @@
 #ifndef OPCUA_BUILTINDATATYPES_H_
 #define OPCUA_BUILTINDATATYPES_H_
 
+#define TRUE (42==42)
+#define FALSE (!TRUE)
+
 /**
 * Enumerations:
 *	All Enumerations should be encoded as Int32 values
@@ -327,6 +330,7 @@ typedef struct UA_DiagnosticInfo
 	struct UA_DiagnosticInfo* InnerDiagnosticInfo;
 }
 UA_DiagnosticInfo;
+extern UA_DiagnosticInfo the_empty_UA_DiagnosticInfo;
 
 typedef enum UA_DiagnosticInfoEncodingMaskType
 {

+ 4 - 0
src/opcua_secureChannelLayer.c

@@ -234,6 +234,9 @@ Int32 SL_openSecureChannel(UA_connection *connection,
 	//                  secureChannelId + TokenId + CreatedAt + RevisedLifetime
 	sizeSecurityToken = sizeof(UInt32) + sizeof(UInt32) + sizeof(UA_DateTime) + sizeof(Int32);
 
+	//ignore server nonce
+	serverNonce.Length = -1;
+	serverNonce.Data = NULL;
 
 	serverNonce.Length = connection->secureLayer.localNonce.Length;
 	serverNonce.Data = connection->secureLayer.localNonce.Data;
@@ -648,6 +651,7 @@ Int32 decodeSequenceHeader(UA_ByteString *rawMessage, Int32 *pos,
 		SL_SequenceHeader *SequenceHeader) {
 	decodeUInt32(rawMessage->Data, pos, &(SequenceHeader->SequenceNumber));
 	decodeUInt32(rawMessage->Data, pos, &(SequenceHeader->RequestId));
+	decodeUInt32(rawMessage->Data, pos, &(SequenceHeader->SequenceNumber));
 	return UA_NO_ERROR;
 }
 

+ 18 - 13
src/opcua_time.c

@@ -3,24 +3,29 @@
  *
  *  Created on: Feb 5, 2014
  *      Author: opcua
+ *
+ * code inspired by
+ * http://stackoverflow.com/questions/3585583/convert-unix-linux-time-to-windows-filetime
  */
 #include "opcua_builtInDatatypes.h"
 #include "opcua_advancedDatatypes.h"
-#include <time.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdarg.h>
-
-
-//get the current Server Time
-UA_DateTime opcua_time_now()
-{
-	Int64 time1970 = 621356004000000000;
+#include <sys/time.h>
 
-	time_t now = time(NULL);
-	Int64 now_nano_ticks = ((Int64)now) * 10 * 1000 * 1000;
-	return now_nano_ticks + time1970;
+// Number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC
+#define FILETIME_UNIXTIME_BIAS_SEC 11644473600LL
+// Factors
+#define HUNDRED_NANOSEC_PER_USEC 10LL
+#define HUNDRED_NANOSEC_PER_SEC (HUNDRED_NANOSEC_PER_USEC * 1000000LL)
 
+// IEC 62541-6 §5.2.2.5  A DateTime value shall be encoded as a 64-bit signed integer
+// which represents the number of 100 nanosecond intervals since January 1, 1601 (UTC).
+UA_DateTime opcua_getTime() {
+	UA_DateTime dateTime;
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	dateTime = (tv.tv_sec + FILETIME_UNIXTIME_BIAS_SEC)
+			* HUNDRED_NANOSEC_PER_SEC + tv.tv_usec * HUNDRED_NANOSEC_PER_USEC;
+	return dateTime;
 }
 
 

+ 1 - 1
src/opcua_transportLayer.c

@@ -288,7 +288,7 @@ TL_send(UA_connection *connection, UA_ByteString *packet)
 	}
 	else
 	{
-		printf("TL_send - ERROR: packet size greater than remote buffer size", packet->Length);
+		printf("TL_send - ERROR: packet size greater than remote buffer size");
 		//server error
 	}
 

+ 115 - 0
src/util/UA_indexedList.c

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

+ 216 - 0
src/util/UA_list.c

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

+ 9 - 7
tests/Makefile.am

@@ -1,13 +1,15 @@
-TESTS = check_stack
-check_PROGRAMS = check_stack
-check_stack_SOURCES = check_stack.c
+TESTS = check_stack check_list check_indexedList
 
-check_stack_CFLAGS = @CHECK_CFLAGS@
-check_stack_LDADD = $(top_builddir)/src/libopen62541.la @CHECK_LIBS@
+# --- no changes beyond this line needed ---
+INCLUDE = @CHECK_CFLAGS@ -I$(top_builddir)/src -I$(top_builddir)/include
+LDADD = $(top_builddir)/lib/libopen62541.a @CHECK_LIBS@
+
+check_PROGRAMS = $(TESTS)
+AM_LDFLAGS = $(LDADD)
 
 #optimization levels depending on debug
 if DEBUG
-        AM_CFLAGS = -O0
+        AM_CFLAGS = -O0 $(INCLUDE)
 else
-        AM_CFLAGS = -O2
+        AM_CFLAGS = -O2 $(INCLUDE)
 endif

+ 104 - 0
tests/check_indexedList.c

@@ -0,0 +1,104 @@
+#include "UA_config.h"
+#include "UA_indexedList.h"
+
+#include "check.h"
+
+/* global test counters */
+Int32 visit_count = 0;
+Int32 free_count = 0;
+
+void visitor(void* payload){
+	visit_count++;
+}
+
+void freer(void* payload){
+	if(payload){
+		free_count++;
+		opcua_free(payload);
+	}
+}
+
+Boolean matcher(void* payload){
+	if(payload == NULL){
+		return FALSE;
+	}
+	if(*((Int32*)payload) == 42){
+		return TRUE;
+	}
+	return FALSE;
+}
+
+START_TEST(linkedList_test_basic)
+{
+
+	UA_indexedList_List list;
+	UA_indexedList_init(&list);
+
+	ck_assert_int_eq(list.size, 0);
+
+	Int32* payload = (Int32*)malloc(sizeof(*payload));
+	*payload = 10;
+	UA_indexedList_addValue(&list, 1, payload);
+	payload = (Int32*)malloc(sizeof(*payload));
+	*payload = 20;
+	UA_indexedList_addValueToFront(&list, 2, payload);
+	payload = (Int32*)malloc(sizeof(*payload));
+	*payload = 30;
+	UA_indexedList_addValue(&list, 3, payload);
+
+	ck_assert_int_eq(list.size, 3);
+
+	UA_indexedList_iterateValues(&list, visitor);
+	ck_assert_int_eq(visit_count, 3);
+	visit_count = 0;
+
+	payload = (Int32*)UA_indexedList_findValue(&list, 2);
+	if(payload){
+		ck_assert_int_eq(*payload, 20);
+	}else{
+		fail("Element 20 not found");
+	}
+
+	UA_indexedList_removeElement(&list, UA_indexedList_find(&list, 2), freer);
+	ck_assert_int_eq(free_count, 1);
+	free_count=0;
+	ck_assert_int_eq(list.size, 2);
+
+	payload = (Int32*)UA_indexedList_findValue(&list, 2);
+	if(payload){
+		fail("Previously removed element 20 found");
+	}
+
+	UA_indexedList_iterateValues(&list, visitor);
+	ck_assert_int_eq(visit_count, 2);
+
+	UA_indexedList_destroy(&list, freer);
+
+	ck_assert_int_eq(free_count, 2);
+	ck_assert_int_eq(list.size, 0);
+}
+END_TEST
+
+Suite*linkedList_testSuite(void)
+{
+	Suite *s = suite_create("linkedList_test");
+	TCase *tc_core = tcase_create("Core");
+	tcase_add_test(tc_core, linkedList_test_basic);
+	suite_add_tcase(s,tc_core);
+	return s;
+}
+
+int main (void)
+{
+	int number_failed = 0;
+
+	Suite* s = linkedList_testSuite();
+	SRunner* sr = srunner_create(s);
+	srunner_run_all(sr,CK_NORMAL);
+	number_failed += srunner_ntests_failed(sr);
+	srunner_free(sr);
+
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+}
+

+ 97 - 0
tests/check_list.c

@@ -0,0 +1,97 @@
+#include "UA_config.h"
+#include "UA_list.h"
+
+#include "check.h"
+
+/* global test counters */
+Int32 visit_count = 0;
+Int32 free_count = 0;
+
+void visitor(void* payload){
+	visit_count++;
+}
+
+void freer(void* payload){
+	if(payload){
+		free_count++;
+		opcua_free(payload);
+	}
+}
+
+Boolean matcher(void* payload){
+	if(payload == NULL){
+		return FALSE;
+	}
+	if(*((Int32*)payload) == 42){
+		return TRUE;
+	}
+	return FALSE;
+}
+
+START_TEST(list_test_basic)
+{
+
+	UA_list_List list;
+	UA_list_init(&list);
+
+	ck_assert_int_eq(list.size, 0);
+
+	Int32* payload = (Int32*)opcua_malloc(sizeof(*payload));
+	*payload = 42;
+	UA_list_addPayloadToFront(&list, payload);
+	payload = (Int32*)opcua_malloc(sizeof(*payload));
+	*payload = 24;
+	UA_list_addPayloadToFront(&list, payload);
+	payload = (Int32*)opcua_malloc(sizeof(*payload));
+	*payload = 1;
+	UA_list_addPayloadToBack(&list, payload);
+
+	ck_assert_int_eq(list.size, 3);
+
+	UA_list_iteratePayload(&list, visitor);
+
+	ck_assert_int_eq(visit_count, 3);
+
+	UA_list_Element* elem = NULL;
+	elem = UA_list_find(&list, matcher);
+	if(elem){
+		ck_assert_int_eq((*((Int32*)elem->payload)), 42);
+		UA_list_removeElement(elem, freer);
+		ck_assert_int_eq(free_count, 1);
+		free_count = 0; //reset free counter
+		ck_assert_int_eq(list.size, 2);
+	}else{
+		fail("Element 42 not found");
+	}
+	UA_list_destroy(&list, freer);
+
+	ck_assert_int_eq(free_count, 2);
+
+	ck_assert_int_eq(list.size, 0);
+
+}
+END_TEST
+
+Suite*list_testSuite(void)
+{
+	Suite *s = suite_create("list_test");
+	TCase *tc_core = tcase_create("Core");
+	tcase_add_test(tc_core, list_test_basic);
+	suite_add_tcase(s,tc_core);
+	return s;
+}
+
+int main (void)
+{
+	int number_failed = 0;
+
+	Suite* s = list_testSuite();
+	SRunner* sr = srunner_create(s);
+	srunner_run_all(sr,CK_NORMAL);
+	number_failed += srunner_ntests_failed(sr);
+	srunner_free(sr);
+
+	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+
+}
+

+ 46 - 72
tests/check_stack.c

@@ -10,10 +10,11 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "../src/opcua_transportLayer.h"
-#include "../src/opcua_binaryEncDec.h"
-#include "../src/opcua_encodingLayer.h"
-#include "../src/opcua_advancedDatatypes.h"
+#include "UA_config.h"
+#include "opcua_transportLayer.h"
+#include "opcua_binaryEncDec.h"
+#include "opcua_encodingLayer.h"
+#include "opcua_advancedDatatypes.h"
 //#include "check_stdint.h"
 #include "check.h"
 
@@ -489,6 +490,7 @@ START_TEST(diagnosticInfo_calcSize_test)
 
 }
 END_TEST
+
 START_TEST(extensionObject_calcSize_test)
 {
 
@@ -498,23 +500,19 @@ START_TEST(extensionObject_calcSize_test)
 	UA_ExtensionObject extensionObject;
 
 	// empty ExtensionObject
-	valcalc = extensionObject_calcSize(&the_empty_UA_ExtensionObject);
-	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+	ck_assert_int_eq(extensionObject_calcSize(&the_empty_UA_ExtensionObject), 1 + 1 + 1);
 
 	// empty ExtensionObject, handcoded
 	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;
 	extensionObject.TypeId.Identifier.Numeric = 0;
 	extensionObject.Encoding = NO_BODY_IS_ENCODED;
-
-	valcalc = extensionObject_calcSize(&extensionObject);
-	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+	ck_assert_int_eq(extensionObject_calcSize(&extensionObject), 1 + 1 + 1);
 
 	// ExtensionObject with ByteString-Body
 	extensionObject.Encoding = BODY_IS_BYTE_STRING;
 	extensionObject.Body.Data = data;
 	extensionObject.Body.Length = 3;
-	valcalc = extensionObject_calcSize(&extensionObject);
-	ck_assert_int_eq(valcalc, 3 + 4 + 3);
+	ck_assert_int_eq(extensionObject_calcSize(&extensionObject), 3 + 4 + 3);
 
 }
 END_TEST
@@ -543,6 +541,9 @@ START_TEST(responseHeader_calcSize_test)
 
 	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;	//		    3
 	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+26+4+3);
+
+	responseHeader.serviceDiagnostics = &the_empty_UA_DiagnosticInfo;
+	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+1+4+3);
 }
 END_TEST
 
@@ -625,38 +626,29 @@ START_TEST(DataValue_calcSize_test)
 }
 END_TEST
 
-START_TEST(encoder_encodeBuiltInDatatypeArray_test)
+START_TEST(encode_builtInDatatypeArray_test_String)
 {
-	Int32 position = 0;
-	Int32 i;
-	char vals[9];
-	char *pVals[9];
-
-	//generate data, numbers from 0-9
-	for(i = 0; i < 9; i++){
-		vals[i] = i;
-		pVals[i] = &vals[i];
-	}
-
-	Int32 len = 9;
-	Int32 ret;
-
-	char *mem = malloc(13 * sizeof(Byte));
+	Int32 noElements = 2;
+	UA_ByteString s1 = { 6, "OPC UA" };
+	UA_ByteString s2 = { -1, NULL };
+	UA_ByteString* array[] = { &s1, &s2	};
+	Int32 pos = 0, i;
+	char buf[256];
+	char result[] = {
+			0x02, 0x00, 0x00, 0x00,		// noElements
+			0x06, 0x00, 0x00, 0x00,		// s1.Length
+			'O', 'P', 'C', ' ', 'U', 'A', // s1.Data
+			0xFF, 0xFF, 0xFF, 0xFF		// s2.Length
+	};
 
-	ret = encoder_encodeBuiltInDatatypeArray((void*)pVals,len, BYTE_ARRAY,
-			&position, mem);
+	encode_builtInDatatypeArray(array, noElements, BYTE_STRING, &pos, buf);
 
-	for(i = 0; i < 9; i++){
-		ck_assert_int_eq(mem[i+sizeof(Int32)], i);
+	// check size
+	ck_assert_int_eq(pos, 4 + 4 + 6 + 4);
+	// check result
+	for (i=0; i< sizeof(result); i++) {
+		ck_assert_int_eq(buf[i],result[i]);
 	}
-
-
-
-	ck_assert_int_eq(position, sizeof(Int32) + 9);
-	ck_assert_int_eq(ret, UA_NO_ERROR);
-
-
-	free(mem);
 }
 END_TEST
 
@@ -669,15 +661,6 @@ Suite *testSuite_getPacketType(void)
 	return s;
 }
 
-Suite *testSuite_decodeByte(void)
-{
-	Suite *s = suite_create("decodeByte_test");
-	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, decodeByte_test);
-	suite_add_tcase(s,tc_core);
-	return s;
-}
-
 Suite *testSuite_encodeByte(void)
 {
 	Suite *s = suite_create("encodeByte_test");
@@ -854,6 +837,15 @@ Suite* testSuite_encodeDataValue()
 	return s;
 }
 
+Suite* testSuite_encode_builtInDatatypeArray()
+{
+	Suite *s = suite_create("encode_builtInDatatypeArray");
+	TCase *tc_core = tcase_create("Core");
+	tcase_add_test(tc_core, encode_builtInDatatypeArray_test_String);
+	suite_add_tcase(s,tc_core);
+	return s;
+}
+
 Suite* testSuite_expandedNodeId_calcSize(void)
 {
 	Suite *s = suite_create("expandedNodeId_calcSize");
@@ -906,15 +898,6 @@ Suite* testSuite_dataValue_calcSize(void)
 	return s;
 }
 
-Suite *testSuite_encoder_encodeBuiltInDatatypeArray_test(void)
-{
-	Suite *s = suite_create("encoder_encodeBuiltInDatatypeArray_test");
-	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, encoder_encodeBuiltInDatatypeArray_test);
-	suite_add_tcase(s,tc_core);
-	return s;
-}
-
 int main (void)
 {
 	int number_failed = 0;
@@ -925,19 +908,6 @@ int main (void)
 	number_failed = srunner_ntests_failed(sr);
 	srunner_free(sr);
 
-
-	s = testSuite_encoder_encodeBuiltInDatatypeArray_test();
-	sr = srunner_create(s);
-	srunner_run_all(sr,CK_NORMAL);
-	number_failed += srunner_ntests_failed(sr);
-	srunner_free(sr);
-
-	s = testSuite_decodeByte();
-	sr = srunner_create(s);
-	srunner_run_all(sr,CK_NORMAL);
-	number_failed = srunner_ntests_failed(sr);
-	srunner_free(sr);
-
 	s = testSuite_decodeInt16();
 	sr = srunner_create(s);
 	srunner_run_all(sr,CK_NORMAL);
@@ -1066,6 +1036,12 @@ int main (void)
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);
 
+	s = testSuite_encode_builtInDatatypeArray();
+	sr = srunner_create(s);
+	srunner_run_all(sr,CK_NORMAL);
+	number_failed += srunner_ntests_failed(sr);
+	srunner_free(sr);
+
 	s = testSuite_expandedNodeId_calcSize();
 	sr = srunner_create(s);
 	srunner_run_all(sr,CK_NORMAL);
@@ -1078,8 +1054,6 @@ int main (void)
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);
 
-
-
 	/* <TESTSUITE_TEMPLATE>
 	s =  <TESTSUITENAME>;
 	sr = srunner_create(s);