Ver código fonte

Merge pull request #111 from acplt/connection_secureChannel

Connection secure channel
FlorianPalm 10 anos atrás
pai
commit
e67b5cd005
41 arquivos alterados com 2545 adições e 507 exclusões
  1. 1 0
      Makefile.am
  2. 5 5
      examples/src/Makefile.am
  3. 73 36
      examples/src/networklayer.c
  4. 6 3
      examples/src/networklayer.h
  5. 8 4
      examples/src/opcuaServer.c
  6. 45 14
      examples/src/opcuaServerACPLT.c
  7. 1 0
      examples/src/opcuaServerMini.c
  8. 1 1
      examples/src/xml2ns0.c
  9. 0 1
      schema/Custom.Opc.Ua.Transport.bsd
  10. 20 17
      src/Makefile.am
  11. 1 0
      src/ua_namespace_concurrent.c
  12. 21 16
      src/ua_services.h
  13. 14 7
      src/ua_services_attribute.c
  14. 4 2
      src/ua_services_discovery.c
  15. 1 1
      src/ua_services_monitoreditems.c
  16. 11 6
      src/ua_services_nodemanagement.c
  17. 19 72
      src/ua_services_securechannel.c
  18. 33 18
      src/ua_services_session.c
  19. 10 2
      src/ua_services_subscription.c
  20. 14 3
      src/ua_services_view.c
  21. 415 0
      src/ua_stack_channel.c
  22. 79 0
      src/ua_stack_channel.h
  23. 204 0
      src/ua_stack_channel_manager.c
  24. 38 0
      src/ua_stack_channel_manager.h
  25. 220 0
      src/ua_stack_session.c
  26. 125 0
      src/ua_stack_session.h
  27. 205 0
      src/ua_stack_session_manager.c
  28. 77 0
      src/ua_stack_session_manager.h
  29. 1 4
      src/ua_transport.c
  30. 3 4
      src/ua_transport.h
  31. 71 45
      src/ua_transport_binary.c
  32. 12 14
      src/ua_transport_binary.h
  33. 379 170
      src/ua_transport_binary_secure.c
  34. 25 21
      src/ua_transport_binary_secure.h
  35. 178 0
      src/ua_transport_connection.c
  36. 51 0
      src/ua_transport_connection.h
  37. 84 0
      src/ua_transport_connection_manager.c
  38. 20 0
      src/ua_transport_connection_manager.h
  39. 3 0
      src/ua_types.c
  40. 17 8
      src/ua_types.h
  41. 50 33
      tests/check_stack.c

+ 1 - 0
Makefile.am

@@ -39,6 +39,7 @@ export GLOBAL_AM_CFLAGS = $(AM_CFLAGS)
 export GLOBAL_AM_LDADD = $(AM_LDADD)
 
 SUBDIRS=src
+
 if HAVE_CHECK
 	SUBDIRS += tests
 endif

+ 5 - 5
examples/src/Makefile.am

@@ -20,8 +20,8 @@ __top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_build
 __top_builddir__bin_exampleServerMT_SOURCES = opcuaServerMT.c networklayer.c
 __top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
 else
-bin_PROGRAMS += $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerACPLT $(top_builddir)/bin/exampleServerMini
-
+#bin_PROGRAMS += $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerACPLT $(top_builddir)/bin/exampleServerMini
+bin_PROGRAMS += $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerACPLT
 __top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c networklayer.c
 __top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
@@ -30,8 +30,8 @@ __top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_bu
 __top_builddir__bin_exampleServerACPLT_SOURCES = opcuaServerACPLT.c networklayer.c
 __top_builddir__bin_exampleServerACPLT_LDADD= $(top_builddir)/lib/libopen62541.a $(GLOBAL_AM_LDADD)
 
-__top_builddir__bin_exampleServerMini_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
-__top_builddir__bin_exampleServerMini_SOURCES = opcuaServerMini.c 
-__top_builddir__bin_exampleServerMini_LDADD= $(GLOBAL_AM_LDADD)
+#__top_builddir__bin_exampleServerMini_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
+#__top_builddir__bin_exampleServerMini_SOURCES = opcuaServerMini.c 
+#__top_builddir__bin_exampleServerMini_LDADD= $(GLOBAL_AM_LDADD)
 
 endif

+ 73 - 36
examples/src/networklayer.c

@@ -11,7 +11,7 @@
 #include <fcntl.h> // fcntl
 
 #include "networklayer.h"
-
+#include "ua_transport_connection.h"
 NL_Description NL_Description_TcpBinary  = {
 	NL_UA_ENCODING_BINARY,
 	NL_CONNECTIONTYPE_TCPV4,
@@ -28,7 +28,9 @@ NL_Description NL_Description_TcpBinary  = {
 _Bool NL_ConnectionComparer(void *p1, void* p2) {
 	NL_Connection* c1 = (NL_Connection*) p1;
 	NL_Connection* c2 = (NL_Connection*) p2;
-	return (c1->connection.connectionHandle == c2->connection.connectionHandle);
+
+	return (c1->connectionHandle == c2->connectionHandle);
+
 }
 int NL_TCP_SetNonBlocking(int sock) {
 	int opts = fcntl(sock,F_GETFL);
@@ -46,7 +48,7 @@ int NL_TCP_SetNonBlocking(int sock) {
 
 void NL_Connection_printf(void* payload) {
   NL_Connection* c = (NL_Connection*) payload;
-  printf("ListElement connectionHandle = %d\n",c->connection.connectionHandle);
+  printf("ListElement connectionHandle = %d\n",c->connectionHandle);
 }
 void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
 	FD_SET(handle, &(nl->readerHandles));
@@ -54,11 +56,11 @@ void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
 }
 void NL_setFdSet(void* payload) {
   NL_Connection* c = (NL_Connection*) payload;
-  NL_addHandleToSet(c->connection.connectionHandle, c->networkLayer);
+  NL_addHandleToSet(c->connectionHandle, c->networkLayer);
 }
 void NL_checkFdSet(void* payload) {
   NL_Connection* c = (NL_Connection*) payload;
-  if (FD_ISSET(c->connection.connectionHandle, &(c->networkLayer->readerHandles))) {
+  if (FD_ISSET(c->connectionHandle, &(c->networkLayer->readerHandles))) {
 	  c->reader((void*)c);
   }
 }
@@ -76,7 +78,7 @@ UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), v
 
 		// and wait
 		DBG_VERBOSE(printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
-		result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL,&tmptv);
+		result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL, &tmptv);
 		DBG_VERBOSE(printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
 		if (result == 0) {
 			int err = errno;
@@ -110,31 +112,54 @@ UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), v
 void* NL_TCP_reader(NL_Connection *c) {
 
 	UA_ByteString readBuffer;
-	UA_alloc((void**)&(readBuffer.data),c->connection.localConf.recvBufferSize);
 
-	if (c->connection.connectionState != CONNECTIONSTATE_CLOSE) {
+	TL_Buffer localBuffers;
+	UA_Int32 connectionState;
+
+	UA_TL_Connection_getLocalConfig(c->connection, &localBuffers);
+	UA_alloc((void**)&(readBuffer.data),localBuffers.recvBufferSize);
+
+
+	if (c->state  != CONNECTIONSTATE_CLOSE) {
 		DBG_VERBOSE(printf("NL_TCP_reader - enter read\n"));
-		readBuffer.length = read(c->connection.connectionHandle, readBuffer.data, c->connection.localConf.recvBufferSize);
+
+
+		readBuffer.length = read(c->connectionHandle, readBuffer.data, localBuffers.recvBufferSize);
 		DBG_VERBOSE(printf("NL_TCP_reader - leave read\n"));
 
 		DBG_VERBOSE(printf("NL_TCP_reader - src={%*.s}, ",c->connection.remoteEndpointUrl.length,c->connection.remoteEndpointUrl.data));
 		DBG(UA_ByteString_printx("NL_TCP_reader - received=",&readBuffer));
 
 		if (readBuffer.length  > 0) {
-			TL_Process(&(c->connection),&readBuffer);
+
+#ifdef DEBUG
+#include "ua_transport_binary_secure.h"
+			UA_UInt32 pos = 0;
+			UA_OPCUATcpMessageHeader header;
+			UA_OPCUATcpMessageHeader_decodeBinary(&readBuffer, &pos, &header);
+			pos = 24;
+			if(header.messageType == UA_MESSAGETYPE_MSG)
+			{
+				UA_NodeId serviceRequestType;
+				UA_NodeId_decodeBinary(&readBuffer, &pos,&serviceRequestType);
+				UA_NodeId_printf("Service Type\n",&serviceRequestType);
+			}
+#endif
+
+			TL_Process((c->connection),&readBuffer);
 		} else {
-			c->connection.connectionState = CONNECTIONSTATE_CLOSE;
+//TODO close connection - what does close do?
+			c->state = CONNECTIONSTATE_CLOSE;
+			//c->connection.connectionState = CONNECTIONSTATE_CLOSE;
 			perror("ERROR reading from socket1");
 		}
 	}
+	UA_TL_Connection_getState(c->connection, &connectionState);
+	if (connectionState == CONNECTIONSTATE_CLOSE) {
+		UA_TL_Connection_close(c->connection);
+
+		//c->state  = CONNECTIONSTATE_CLOSED;
 
-	if (c->connection.connectionState == CONNECTIONSTATE_CLOSE) {
-		DBG_VERBOSE(printf("NL_TCP_reader - enter shutdown\n"));
-		shutdown(c->connection.connectionHandle,2);
-		DBG_VERBOSE(printf("NL_TCP_reader - enter close\n"));
-		close(c->connection.connectionHandle);
-		DBG_VERBOSE(printf("NL_TCP_reader - leave close\n"));
-		c->connection.connectionState = CONNECTIONSTATE_CLOSED;
 
 #ifndef MULTITHREADING
 		DBG_VERBOSE(printf("NL_TCP_reader - search element to remove\n"));
@@ -164,7 +189,7 @@ void* NL_TCP_readerThread(NL_Connection *c) {
 #endif
 
 /** write message provided in the gather buffers to a tcp transport layer connection */
-UA_Int32 NL_TCP_writer(struct TL_Connection const * c, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len) {
+UA_Int32 NL_TCP_writer(UA_Int32 connectionHandle, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len) {
 
 	struct iovec iov[gather_len];
 	UA_UInt32 total_len = 0;
@@ -172,8 +197,8 @@ UA_Int32 NL_TCP_writer(struct TL_Connection const * c, UA_ByteString const * con
 		iov[i].iov_base = gather_buf[i]->data;
 		iov[i].iov_len = gather_buf[i]->length;
 		total_len += gather_buf[i]->length;
-		DBG(printf("NL_TCP_writer - gather_buf[%i]",i));
-		DBG(UA_ByteString_printx("=", gather_buf[i]));
+//		DBG(printf("NL_TCP_writer - gather_buf[%i]",i));
+//		DBG(UA_ByteString_printx("=", gather_buf[i]));
 	}
 
 	struct msghdr message;
@@ -190,7 +215,7 @@ UA_Int32 NL_TCP_writer(struct TL_Connection const * c, UA_ByteString const * con
 		int n=0;
 		do {
 			DBG_VERBOSE(printf("NL_TCP_writer - enter write with %d bytes to write\n",total_len));
-			n = sendmsg(c->connectionHandle, &message, 0);
+			n = sendmsg(connectionHandle, &message, 0);
 			DBG_VERBOSE(printf("NL_TCP_writer - leave write with n=%d,errno={%d,%s}\n",n,(n>0)?0:errno,(n>0)?"":strerror(errno)));
 		} while (n == -1L && errno == EINTR);
 		if (n >= 0) {
@@ -204,19 +229,30 @@ UA_Int32 NL_TCP_writer(struct TL_Connection const * c, UA_ByteString const * con
 	}
 	return UA_SUCCESS;
 }
-
+//callback function which is called when the UA_TL_Connection_close() function is initiated
+UA_Int32 NL_Connection_close(UA_TL_Connection connection)
+{
+	NL_Connection *networkLayerData = UA_NULL;
+	UA_TL_Connection_getNetworkLayerData(connection, (void**)&networkLayerData);
+	if(networkLayerData != UA_NULL){
+		DBG_VERBOSE(printf("NL_Connection_close - enter shutdown\n"));
+		shutdown(networkLayerData->connectionHandle,2);
+		DBG_VERBOSE(printf("NL_Connection_close - enter close\n"));
+		close(networkLayerData->connectionHandle);
+		DBG_VERBOSE(printf("NL_Connection_close - leave close\n"));
+		return UA_SUCCESS;
+	}
+    DBG_VERBOSE(printf("NL_Connection_close - ERROR: connection object invalid \n"));
+	return UA_ERROR;
+}
 void* NL_Connection_init(NL_Connection* c, NL_data* tld, UA_Int32 connectionHandle, NL_Reader reader, TL_Writer writer)
 {
-	// connection layer of UA stackwriteLock
-	c->connection.connectionHandle = connectionHandle;
-	c->connection.connectionState = CONNECTIONSTATE_CLOSED;
-	c->connection.writerCallback = writer;
-
-	memcpy(&(c->connection.localConf),&(tld->tld->localConf),sizeof(TL_Buffer));
-
-	memset(&(c->connection.remoteConf),0,sizeof(TL_Buffer));
-	UA_String_copy(&(tld->endpointUrl), &(c->connection.localEndpointUrl));
+	UA_TL_Connection connection = UA_NULL;
+	//create new connection object
+	UA_TL_Connection_new(&connection, tld->tld->localConf, writer, NL_Connection_close,connectionHandle,c);
 
+	c->connection = connection;
+	c->connectionHandle = connectionHandle;
 	// network layer
 	c->reader = reader;
 #ifdef MULTITHREADING
@@ -231,7 +267,8 @@ void* NL_TCP_listen(NL_Connection* c) {
 	NL_data* tld = c->networkLayer;
 
 	DBG_VERBOSE(printf("NL_TCP_listen - enter listen\n"));
-	int retval = listen(c->connection.connectionHandle, tld->tld->maxConnections);
+
+	int retval = listen(c->connectionHandle, tld->tld->maxConnections);
 	DBG_VERBOSE(printf("NL_TCP_listen - leave listen, retval=%d\n",retval));
 
 	if (retval < 0) {
@@ -243,7 +280,7 @@ void* NL_TCP_listen(NL_Connection* c) {
 		struct sockaddr_in cli_addr;
 		socklen_t cli_len = sizeof(cli_addr);
 		DBG_VERBOSE(printf("NL_TCP_listen - enter accept\n"));
-		int newsockfd = accept(c->connection.connectionHandle, (struct sockaddr *) &cli_addr, &cli_len);
+		int newsockfd = accept(c->connectionHandle, (struct sockaddr *) &cli_addr, &cli_len);
 		DBG_VERBOSE(printf("NL_TCP_listen - leave accept\n"));
 		if (newsockfd < 0) {
 			DBG_ERR(printf("TL_TCP_listen - accept returns errno={%d,%s}\n",errno,strerror(errno)));
@@ -258,7 +295,7 @@ void* NL_TCP_listen(NL_Connection* c) {
 			pthread_create( &(cclient->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_readerThread, (void*) cclient);
 #else
 			UA_list_addPayloadToBack(&(tld->connections),cclient);
-			NL_TCP_SetNonBlocking(cclient->connection.connectionHandle);
+			NL_TCP_SetNonBlocking(cclient->connectionHandle);
 #endif
 		}
 	} else {
@@ -321,7 +358,7 @@ UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
 		pthread_create( &(c->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_listenThread, (void*) c);
 #else
 		UA_list_addPayloadToBack(&(tld->connections),c);
-		NL_TCP_SetNonBlocking(c->connection.connectionHandle);
+		NL_TCP_SetNonBlocking(c->connectionHandle);
 #endif
 	}
 	return retval;

+ 6 - 3
examples/src/networklayer.h

@@ -44,7 +44,9 @@ typedef struct NL_data {
 struct NL_Connection;
 typedef void* (*NL_Reader)(struct NL_Connection *c);
 typedef struct NL_Connection {
-	TL_Connection connection;
+	UA_TL_Connection connection;
+	UA_Int32 state;
+	UA_UInt32 connectionHandle;
 	NL_Reader reader;
 #ifdef MULTITHREADING
 	pthread_t readerThreadHandle;
@@ -53,7 +55,8 @@ typedef struct NL_Connection {
 } NL_Connection;
 
 NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port);
-UA_Int32 NL_msgLoop(NL_data* nl, struct timeval* tv,UA_Int32 (*timeoutCallBack)(void*),void *arg, UA_Boolean *running);
-UA_Int32 NL_TCP_writer(struct TL_Connection const * c, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len);
+UA_Int32 NL_Connection_close(UA_TL_Connection connection);
+UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg, UA_Boolean *running);
+UA_Int32 NL_TCP_writer(UA_Int32 connectionHandle, UA_ByteString const * const * gather_buf, UA_UInt32 gather_len);
 
 #endif /* NETWORKLAYER_H_ */

+ 8 - 4
examples/src/opcuaServer.c

@@ -12,6 +12,8 @@
 #include <fcntl.h>
 
 #include <signal.h>
+#include "ua_stack_channel_manager.h"
+#include "ua_stack_session_manager.h"
 
 UA_Boolean running = UA_TRUE;
 
@@ -35,6 +37,7 @@ UA_Int32 serverCallback(void * arg) {
 	return UA_SUCCESS;
 }
 
+
 int main(int argc, char** argv) {
 
 	/* gets called at ctrl-c */
@@ -42,10 +45,11 @@ int main(int argc, char** argv) {
 	
 	appMockup_init();
 	NL_data* nl = NL_init(&NL_Description_TcpBinary, 16664);
-
+	UA_String endpointUrl;
+	UA_String_copycstring("no endpoint url",&endpointUrl);
+	SL_ChannelManager_init(4,36000,244,2,&endpointUrl);
+	UA_SessionManager_init(10,3600000,25);
 	struct timeval tv = {1, 0}; // 1 second
-  	NL_msgLoop(nl, &tv, serverCallback, argv[0], &running);
+	NL_msgLoop(nl, &tv, serverCallback, argv[0], &running);
 
-	printf("Shutting down after Ctrl-C.\n");
-	exit(0);
 }

+ 45 - 14
examples/src/opcuaServerACPLT.c

@@ -6,6 +6,10 @@
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 #include "networklayer.h"
+#include "ua_stack_channel_manager.h"
+#include "ua_transport_connection.h"
+#include "ua_transport_connection_manager.h"
+#include "ua_stack_session_manager.h"
 
 #ifdef LINUX
 
@@ -23,6 +27,8 @@ void server_run();
 #define MAXMSG 512
 #define BUFFER_SIZE 8192
 
+
+
 int main(void) {
 
 #ifdef LINUX
@@ -36,20 +42,31 @@ 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;
-	connection.localConf.maxChunkCount = 1;
-	connection.localConf.maxMessageSize = BUFFER_SIZE;
-	connection.localConf.protocolVersion = 0;
-	connection.localConf.recvBufferSize = BUFFER_SIZE;
-	connection.localConf.recvBufferSize = BUFFER_SIZE;
+	UA_TL_Connection connection;// = UA_NULL;
+	TL_Buffer localBuffers;
+	UA_Int32 connectionState;
+	//connection.connectionState = CONNECTIONSTATE_CLOSED;
+	//connection.writerCallback = (TL_Writer) NL_TCP_writer;
+	localBuffers.maxChunkCount = 1;
+	localBuffers.maxMessageSize = BUFFER_SIZE;
+	localBuffers.protocolVersion = 0;
+	localBuffers.recvBufferSize = BUFFER_SIZE;
+	localBuffers.recvBufferSize = BUFFER_SIZE;
+
+	/*init secure Channel manager, which handles more than one channel */
+	UA_String endpointUrl;
+	UA_String_copycstring("open62541.org",&endpointUrl);
+	SL_ChannelManager_init(2,3600000, 873, 23, &endpointUrl);
+	UA_SessionManager_init(2,300000,5);
 
 	UA_ByteString slMessage = { -1, UA_NULL };
 
@@ -87,6 +104,8 @@ void server_run() {
 	/* Now start listening for the clients, here process will
 	 * go in sleep mode and will wait for the incoming connection
 	 */
+	UA_TL_Connection tmpConnection;
+
 	while (listen(sockfd, 5) != -1) {
 		clilen = sizeof(cli_addr);
 		/* Accept actual connection from the client */
@@ -96,8 +115,17 @@ void server_run() {
 			exit(1);
 		}
 
-		printf("server_run - connection accepted: %i, state: %i\n", newsockfd, connection.connectionState);
-		connection.connectionHandle = newsockfd;
+		UA_TL_ConnectionManager_getConnectionByHandle(newsockfd, &tmpConnection);
+		if(tmpConnection == UA_NULL)
+		{
+			UA_TL_Connection_new(&connection, localBuffers, (TL_Writer)NL_TCP_writer,NL_Connection_close,newsockfd,UA_NULL);
+		}
+		UA_TL_Connection_getState(connection, &connectionState);
+
+		printf("server_run - connection accepted: %i, state: %i\n", newsockfd, connectionState);
+
+		UA_TL_Connection_bind(connection, newsockfd);
+		//connection.connectionHandle = newsockfd;
 		do {
             memset(buffer, 0, BUFFER_SIZE);
 			n = read(newsockfd, buffer, BUFFER_SIZE);
@@ -107,18 +135,21 @@ void server_run() {
 #ifdef DEBUG
 				UA_ByteString_printx("server_run - received=",&slMessage);
 #endif
-				TL_Process(&connection, &slMessage);
+				TL_Process(connection, &slMessage);
 			} else if (n <= 0) {
 				perror("ERROR reading from socket1");
-				exit(1);
+		//		exit(1);
 			}
-		} while(connection.connectionState != CONNECTIONSTATE_CLOSE);
+			UA_TL_Connection_getState(connection, &connectionState);
+		} while(connectionState != CONNECTIONSTATE_CLOSE);
 		shutdown(newsockfd,2);
 		close(newsockfd);
-		connection.connectionState = CONNECTIONSTATE_CLOSED;
+		UA_TL_ConnectionManager_getConnectionByHandle(newsockfd, &tmpConnection);
+		UA_TL_ConnectionManager_removeConnection(tmpConnection);
 	}
 	shutdown(sockfd,2);
 	close(sockfd);
 }
 
+
 #endif

+ 1 - 0
examples/src/opcuaServerMini.c

@@ -10,6 +10,7 @@
  * quite small and memory allocation capabilities is not needed
  * as long as features are consequently minimized.
  ****************************************************************/
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <memory.h>

+ 1 - 1
examples/src/xml2ns0.c

@@ -1,6 +1,6 @@
 #include <fcntl.h> // open, O_RDONLY
 #include "ua_types.h"
-#include "ua_types_generated.h"
+//#include "ua_types_generated.h"
 #include "ua_namespace.h"
 #include "ua_xml.h"
 #include "ua_namespace_xml.h"

+ 0 - 1
schema/Custom.Opc.Ua.Transport.bsd

@@ -49,7 +49,6 @@
     <opc:Field Name="SecurityPolicyUri" TypeName="opc:ByteString" />
     <opc:Field Name="SenderCertificate" TypeName="opc:ByteString" />
     <opc:Field Name="ReceiverCertificateThumbprint" TypeName="opc:ByteString" />
-    <opc:Field Name="RequestId" TypeName="opc:UInt32"/>
   </opc:StructuredType>
   
   <opc:StructuredType Name="SymmetricAlgorithmSecurityHeader">

+ 20 - 17
src/Makefile.am

@@ -1,15 +1,17 @@
 AM_CFLAGS = $(GLOBAL_AM_CFLAGS) -I$(top_builddir)/src -I. -I$(top_builddir)/src/util
 TOOL_DIR = $(top_builddir)/tools
 SCHEMA_DIR = $(top_builddir)/schema
-STRUCTURE_GENERATE_OPTIONS =
 lib_LTLIBRARIES = libopen62541.la
 lib_LTLIBRARIES: generate_types generate_namespace_0
 libopen62541_la_LDFLAGS = -avoid-version -no-undefined
 libopen62541_la_SOURCES = ua_types.c \
 						  ua_types_encoding_binary.c \
 						  ua_types_generated.c \
-						  ua_application.c \
 						  ua_namespace_0.c \
+						  util/ua_util.c \
+						  util/ua_list.c \
+						  util/ua_indexedList.c \
+						  util/ua_base64.c \
 						  ua_transport.c \
 						  ua_transport_binary.c \
 						  ua_transport_binary_secure.c \
@@ -19,12 +21,15 @@ libopen62541_la_SOURCES = ua_types.c \
 						  ua_services_securechannel.c \
 						  ua_services_nodemanagement.c \
 						  ua_services_view.c \
-						  ua_services_subscription.c \
-						  ua_services_monitoreditems.c \
-						  util/ua_util.c \
-						  util/ua_list.c \
-						  util/ua_indexedList.c \
-						  util/ua_base64.c
+						  ua_services_subscription.c\
+						  ua_services_monitoreditems.c\
+						  ua_application.c \
+			              ua_stack_session.c\
+			              ua_stack_session_manager.c\
+			              ua_stack_channel.c \
+						  ua_stack_channel_manager.c \
+						  ua_transport_connection_manager.c \
+						  ua_transport_connection.c
 
 if MULTITHREADING
 libopen62541_la_SOURCES += ua_namespace_concurrent.c
@@ -32,24 +37,22 @@ else
 libopen62541_la_SOURCES += ua_namespace.c
 endif
 
+WITH_XML =
 if UA_ENCODING_XML
-libopen62541_la_SOURCES += ua_types_encoding_xml.c ua_namespace_xml.c ua_xml.c
-STRUCTURE_GENERATE_OPTIONS += --with-xml
-endif
-
-if UA_ENCODING_JSON
-libopen62541_la_SOURCES += ua_types_encoding_json.c
-STRUCTURE_GENERATE_OPTIONS += --with-json
+libopen62541_la_SOURCES += ua_types_encoding_xml.c \
+						   ua_namespace_xml.c \
+						   ua_xml.c
+WITH_XML = --with-xml
 endif
 
 ua_types.c: ua_namespace_0.h
 ua_namespace_0.h: ua_types_generated.h
 
 ua_types_generated.c ua_types_generated.h: $(SCHEMA_DIR)/Opc.Ua.Types.bsd $(TOOL_DIR)/generate_builtin.py
-	python $(TOOL_DIR)/generate_builtin.py $(STRUCTURE_GENERATE_OPTIONS) $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated
+	python $(TOOL_DIR)/generate_builtin.py $(SCHEMA_DIR)/Opc.Ua.Types.bsd ua_types_generated $(WITH_XML)
 
 ua_namespace_0.c ua_namespace_0.h: $(SCHEMA_DIR)/NodeIds.csv $(TOOL_DIR)/generate_namespace.py
-	python $(TOOL_DIR)/generate_namespace.py $(STRUCTURE_GENERATE_OPTIONS) $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0
+	python $(TOOL_DIR)/generate_namespace.py $(SCHEMA_DIR)/NodeIds.csv ua_namespace_0 $(WITH_XML)
 
 .PHONY: convenience-link clean-convenience-link
 

+ 1 - 0
src/ua_namespace_concurrent.c

@@ -5,6 +5,7 @@
 #include <urcu/uatomic.h>
 #include <urcu/rculfhash.h>
 
+
 #define ALIVE_BIT (1 << 15) /* Alive bit in the readcount */
 typedef struct Namespace_Entry {
 	struct cds_lfht_node htn; /* contains next-ptr for urcu-hashmap */

+ 21 - 16
src/ua_services.h

@@ -8,9 +8,11 @@
 #define UA_SERVICES_H_
 
 #include "ua_types.h"
+#include "ua_types_generated.h"
 #include "ua_application.h"
 #include "ua_transport_binary_secure.h"
-
+#include "ua_stack_session_manager.h"
+#include "ua_stack_channel_manager.h"
 /**
  * @defgroup services Services
  *
@@ -34,7 +36,7 @@
  * the configuration information required to establish a SecureChannel and a
  * Session.
  */
-UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response);
+UA_Int32 Service_GetEndpoints(SL_Channel channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response);
 // Service_RegisterServer
 /** @} */
 
@@ -53,12 +55,12 @@ UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest*
  * 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);
+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);
+UA_Int32 Service_CloseSecureChannel(SL_Channel channel, const UA_CloseSecureChannelRequest *request, UA_CloseSecureChannelResponse *response);
 /** @} */
 
 /**
@@ -77,7 +79,7 @@ UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureCha
  * logs and in the Server’s address space. The second is the authenticationToken
  * which is used to associate an incoming request with a Session.
  */
-UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response);
+UA_Int32 Service_CreateSession(SL_Channel channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response);
 
 /**
  * @brief This Service is used by the Client to submit its SoftwareCertificates
@@ -86,12 +88,12 @@ UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionReques
  * Client before it issues any other Service request after CreateSession.
  * Failure to do so shall cause the Server to close the Session.
  */
-UA_Int32 Service_ActivateSession(SL_Channel *channel, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response);
+UA_Int32 Service_ActivateSession(SL_Channel channel, UA_Session session, 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);
+UA_Int32 Service_CloseSession(UA_Session session, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response);
 // Service_Cancel
 /** @} */
 
@@ -108,12 +110,12 @@ UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest
 /**
  * @brief This Service is used to add one or more Nodes into the AddressSpace hierarchy.
  */
-UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
+UA_Int32 Service_AddNodes(UA_Session session, const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
 
 /**
  * @brief This Service is used to add one or more References to one or more Nodes
  */
-UA_Int32 Service_AddReferences(SL_Channel *channel, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response);
+UA_Int32 Service_AddReferences(UA_Session session, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response);
 
 // Service_DeleteNodes
 // Service_DeleteReferences
@@ -133,12 +135,12 @@ UA_Int32 Service_AddReferences(SL_Channel *channel, const UA_AddReferencesReques
  * 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);
+UA_Int32 Service_Browse(UA_Session session, const UA_BrowseRequest *request, UA_BrowseResponse *response);
 
 /**
  * @brief This Service is used to translate textual node paths to their respective ids.
  */
-UA_Int32 Service_TranslateBrowsePathsToNodeIds(SL_Channel *channel, const UA_TranslateBrowsePathsToNodeIdsRequest *request, UA_TranslateBrowsePathsToNodeIdsResponse *response);
+UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Session session, const UA_TranslateBrowsePathsToNodeIdsRequest *request, UA_TranslateBrowsePathsToNodeIdsResponse *response);
 // Service_BrowseNext
 // Service_TranslateBrowsePathsToNodeIds
 // Service_RegisterNodes
@@ -181,7 +183,7 @@ UA_Int32 Service_TranslateBrowsePathsToNodeIds(SL_Channel *channel, const UA_Tra
  * 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);
+UA_Int32 Service_Read(UA_Session session, const UA_ReadRequest *request, UA_ReadResponse *response);
 // Service_HistoryRead
 /**
  * @brief This Service is used to write one or more Attributes of one or more
@@ -190,7 +192,7 @@ UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_Rea
  *  values as a composite, to write individual elements or to write ranges of
  *  elements of the composite.
  */
-UA_Int32 Service_Write(SL_Channel *channel, const UA_WriteRequest *request,UA_WriteResponse *response);
+UA_Int32 Service_Write(UA_Session session, const UA_WriteRequest *request,UA_WriteResponse *response);
 // Service_HistoryUpdate
 /** @} */
 
@@ -222,7 +224,7 @@ a component of an Object.
  * triggered item links to be deleted, but has no effect on the MonitoredItems
  * referenced by the triggered items.
  */
-UA_Int32 Service_CreateMonitoredItems(SL_Channel *channel, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response);
+UA_Int32 Service_CreateMonitoredItems(UA_Session session, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response);
 // Service_ModifyMonitoredItems
 // Service_SetMonitoringMode
 // Service_SetTriggering
@@ -237,11 +239,14 @@ UA_Int32 Service_CreateMonitoredItems(SL_Channel *channel, const UA_CreateMonito
  * @{
  */
 // Service_CreateSubscription
-UA_Int32 Service_CreateSubscription(SL_Channel *channel, const UA_CreateSubscriptionRequest *request,
+UA_Int32 Service_CreateSubscription(UA_Session session, const UA_CreateSubscriptionRequest *request,
                                    UA_CreateSubscriptionResponse *response);
 // Service_ModifySubscription
 // Service_SetPublishingMode
-UA_Int32 Service_Publish(SL_Channel *channel, const UA_PublishRequest *request,
+UA_Int32 Service_SetPublishingMode(UA_Session session, const UA_SetPublishingModeRequest *request,
+                                   UA_SetPublishingModeResponse *response);
+
+UA_Int32 Service_Publish(UA_Session session, const UA_PublishRequest *request,
                                    UA_PublishResponse *response);
 
 // Service_Republish

+ 14 - 7
src/ua_services_attribute.c

@@ -223,10 +223,15 @@ static UA_DataValue service_read_node(Application *app, const UA_ReadValueId *id
 
 	return v;
 }
-
-UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request,
+UA_Int32 Service_Read(UA_Session session, const UA_ReadRequest *request,
                       UA_ReadResponse *response) {
-	if(channel->session == UA_NULL || channel->session->application == UA_NULL)
+	Application *application = UA_NULL;
+	if(session == UA_NULL)
+	{
+		return UA_ERROR;
+	}
+	UA_Session_getApplicationPointer(session,&application);
+	if( application == UA_NULL)
 		return UA_ERROR;    // TODO: Return error message
 
 	UA_Int32 readsize = request->nodesToReadSize;
@@ -242,7 +247,7 @@ UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request,
 	for(UA_Int32 i = 0;i < readsize;i++) {
 		DBG_VERBOSE(printf("service_read - attributeId=%d\n", request->nodesToRead[i].attributeId));
 		DBG_VERBOSE(UA_NodeId_printf("service_read - nodeId=", &(request->nodesToRead[i].nodeId)));
-		response->results[i] = service_read_node(channel->session->application,
+		response->results[i] = service_read_node(application,
 		                                         &request->nodesToRead[i]);
 	}
 	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
@@ -438,17 +443,19 @@ UA_Int32 Service_Write_writeNode(Application *app, UA_WriteValue *writeValue, UA
 	return retval;
 
 }
-UA_Int32 Service_Write(SL_Channel *channel, const UA_WriteRequest *request,
+UA_Int32 Service_Write(UA_Session session, const UA_WriteRequest *request,
                       UA_WriteResponse *response) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 i;
-	if(channel->session == UA_NULL || channel->session->application == UA_NULL)
+	Application *application = UA_NULL;
+	UA_Session_getApplicationPointer(session, &application);
+	if(session == UA_NULL || application == UA_NULL)
 		return UA_ERROR;    // TODO: Return error message
 	response->resultsSize = request->nodesToWriteSize;
 	//TODO evalutate diagnostic info within the request
 	UA_Array_new((void**)&response->results,response->resultsSize,&UA_.types[UA_STATUSCODE]);
 	for(i=0; i < request->nodesToWriteSize; i++){
-		retval |= Service_Write_writeNode(channel->session->application, &request->nodesToWrite[i], &response->results[i]);
+		retval |= Service_Write_writeNode(application, &request->nodesToWrite[i], &response->results[i]);
 	}
 
 	return retval;

+ 4 - 2
src/ua_services_discovery.c

@@ -1,5 +1,5 @@
 #include "ua_services.h"
-UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response) {
+UA_Int32 Service_GetEndpoints(SL_Channel channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response) {
 #ifdef DEBUG
 	UA_String_printx("endpointUrl=", &request->endpointUrl);
 #endif
@@ -10,7 +10,9 @@ UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest*
 	//Security issues:
 	//The policy should be 'http://opcfoundation.org/UA/SecurityPolicy#None'
 	//FIXME String or ByteString
-	UA_String_copy((UA_String *)&channel->localAsymAlgSettings.securityPolicyUri, &response->endpoints[0].securityPolicyUri);
+	UA_AsymmetricAlgorithmSecurityHeader *asymSettings;
+	SL_Channel_getLocalAsymAlgSettings(channel, &asymSettings);
+	UA_String_copy((UA_String *)&(asymSettings->securityPolicyUri), &response->endpoints[0].securityPolicyUri);
 	//FIXME hard-coded code
 	response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
 	UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary", &response->endpoints[0].transportProfileUri);

+ 1 - 1
src/ua_services_monitoreditems.c

@@ -4,7 +4,7 @@
 //#if 0
 /* Activate once the infrastructure for pushing events is in place. */
 
-UA_Int32 Service_CreateMonitoredItems(SL_Channel *channel, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response) {
+UA_Int32 Service_CreateMonitoredItems(UA_Session session, const UA_CreateMonitoredItemsRequest *request, UA_CreateMonitoredItemsResponse *response) {
 	if (request->itemsToCreateSize > 0) {
 		response->resultsSize = request->itemsToCreateSize;
 

+ 11 - 6
src/ua_services_nodemanagement.c

@@ -2,7 +2,7 @@
 #include "ua_statuscodes.h"
 #include "ua_namespace.h"
 #include "ua_services_internal.h"
-
+#include "ua_stack_session.h"
 #define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do {	\
 	status |= ACTION; \
 	if(status != UA_SUCCESS) { \
@@ -65,11 +65,16 @@ static UA_AddNodesResult addSingleNode(Application *app, UA_AddNodesItem *item)
 	return result;
 }
 
-UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
-	if(channel->session == UA_NULL || channel->session->application == UA_NULL)
+UA_Int32 Service_AddNodes(UA_Session session, const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
+
+	Application *application;
+	if(session == UA_NULL)
 		return UA_ERROR;	// TODO: Return error message
+	UA_Session_getApplicationPointer(session,&application);
+	if(application == UA_NULL)
+		return UA_ERROR;
 
-	int nodestoaddsize = request->nodesToAddSize;
+	UA_Int32 nodestoaddsize = request->nodesToAddSize;
 	if(nodestoaddsize <= 0) {
 		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
 		response->resultsSize = 0;
@@ -80,7 +85,7 @@ UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request
 	UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
 	for(int i = 0; i < nodestoaddsize; i++) {
 		DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i].browseName)));
-		response->results[i] = addSingleNode(channel->session->application, &request->nodesToAdd[i]);
+		response->results[i] = addSingleNode(application, &request->nodesToAdd[i]);
 	}
 	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
 	response->diagnosticInfosSize = -1;
@@ -133,6 +138,6 @@ UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, Namespace *tar
 	return retval;
 }
 
-UA_Int32 Service_AddReferences(SL_Channel *channel, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response) {
+UA_Int32 Service_AddReferences(UA_Session session, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response) {
 	return UA_ERROR;
 }

+ 19 - 72
src/ua_services_securechannel.c

@@ -1,79 +1,26 @@
 #include "ua_services.h"
 #include "ua_transport_binary_secure.h"
 
-UA_Int32 Service_OpenSecureChannel(SL_Channel *channel, const UA_OpenSecureChannelRequest *request,
-                                   UA_OpenSecureChannelResponse *response) {
-
-	if(request->clientProtocolVersion != channel->tlConnection->remoteConf.protocolVersion) {
-		printf("SL_processMessage - error protocol version \n");
-		//TODO ERROR_Bad_ProtocolVersionUnsupported
-	}
-
-	UA_UInt32 retval = UA_SUCCESS;
-	switch(request->requestType) {
-	case UA_SECURITYTOKEN_ISSUE:
-		if(channel->connectionState == CONNECTIONSTATE_ESTABLISHED) {
-			printf("SL_processMessage - multiple security token request");
-			//TODO return ERROR
-			retval = UA_ERROR;
-			break;
-		}
-		printf("SL_processMessage - TODO: create new token for a new SecureChannel\n");
-		//	SL_createNewToken(connection);
-		break;
-
-	case UA_SECURITYTOKEN_RENEW:
-		if(channel->connectionState == CONNECTIONSTATE_CLOSED) {
-			printf(
-			    "SL_processMessage - renew token request received, but no secureChannel was established before");
-			//TODO return ERROR
-			retval = UA_ERROR;
-			break;
-		}
-		printf("TODO: create new token for an existing SecureChannel\n");
-		break;
-	}
-
-	switch(request->securityMode) {
-	case UA_SECURITYMODE_INVALID:
-		channel->remoteNonce.data   = UA_NULL;
-		channel->remoteNonce.length = -1;
-		printf("SL_processMessage - client demands no security \n");
-		break;
-
-	case UA_SECURITYMODE_SIGN:
-		printf("SL_processMessage - client demands signed \n");
-		//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-		break;
-
-	case UA_SECURITYMODE_SIGNANDENCRYPT:
-		printf("SL_processMessage - client demands signed & encrypted \n");
-		//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-		break;
-	}
-
-	channel->connectionState = CONNECTIONSTATE_ESTABLISHED;
-
-	if(request->requestHeader.returnDiagnostics != 0) {
-		printf("SL_openSecureChannel - diagnostics demanded by the client\n");
-		printf("SL_openSecureChannel - retrieving diagnostics not implemented!\n");
-		//TODO fill with demanded information part 4, 7.8 - Table 123
-		response->responseHeader.serviceDiagnostics.encodingMask = 0;
-	} else
-		response->responseHeader.serviceDiagnostics.encodingMask = 0;
-
-	response->serverProtocolVersion = channel->tlConnection->localConf.protocolVersion;
-	response->securityToken.channelId       = channel->securityToken.secureChannelId;
-	response->securityToken.tokenId         = channel->securityToken.tokenId.tokenId;
-	response->securityToken.revisedLifetime = channel->securityToken.revisedLifetime;
-	UA_ByteString_copy(&channel->localNonce, &response->serverNonce);
+UA_Int32 Service_OpenSecureChannel(SL_Channel channel,
+const UA_OpenSecureChannelRequest* request,
+UA_OpenSecureChannelResponse* response)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	SL_channelState channelState;
+	//channel takes care of opening process
+	retval |= SL_Channel_processOpenRequest(channel, request,response);
+	retval |= SL_Channel_getState(channel, &channelState);
 	return retval;
 }
 
-UA_Int32 Service_CloseSecureChannel(SL_Channel                         *channel,
-                                    const UA_CloseSecureChannelRequest *request,
-                                    UA_CloseSecureChannelResponse      *response) {
-	// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
-	channel->connectionState = CONNECTIONSTATE_CLOSE;
-	return UA_SUCCESS;
+UA_Int32 Service_CloseSecureChannel(SL_Channel channel, const UA_CloseSecureChannelRequest *request,
+UA_CloseSecureChannelResponse *response)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_UInt32 channelId;
+	SL_Channel_getChannelId(channel,&channelId);
+	SL_ChannelManager_removeChannel(channelId);
+// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
+
+return retval;
 }

+ 33 - 18
src/ua_services_session.c

@@ -1,39 +1,54 @@
 #include "ua_services.h"
 #include "ua_application.h"
 
-Session sessionMockup = {
-		(UA_Int32) 0,
-		&appMockup
-};
 
-UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
+UA_Int32 Service_CreateSession(SL_Channel channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
 #ifdef DEBUG
 	UA_String_printf("CreateSession Service - endpointUrl=", &(request->endpointUrl));
 #endif
-	// FIXME: create session
+	UA_Session *newSession;
+	UA_Int64 timeout;
 
-	response->sessionId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
-	response->sessionId.namespace = 1;
-	response->sessionId.identifier.numeric = 666;
+	UA_SessionManager_getSessionTimeout(&timeout);
+	UA_Session_new(&newSession);
+	//TODO get maxResponseMessageSize
+	UA_Session_init(*newSession, (UA_String*)&request->sessionName,
+	request->requestedSessionTimeout,
+	request->maxResponseMessageSize,
+	9999,
+	(UA_Session_idProvider)UA_SessionManager_generateSessionId,
+	timeout);
+
+	UA_SessionManager_addSession(newSession);
+	UA_Session_getId(*newSession, &response->sessionId);
+	UA_Session_getToken(*newSession, &(response->authenticationToken));
+	response->revisedSessionTimeout = timeout;
+	//TODO fill results
 	return UA_SUCCESS;
 }
 
-UA_Int32 Service_ActivateSession(SL_Channel *channel, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response) {
-	// FIXME: activate session
+UA_Int32 Service_ActivateSession(SL_Channel channel,UA_Session session,
+		const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response)
+{
+
+	UA_Session_bind(session, channel);
+
+	UA_Session_setApplicationPointer(session, &appMockup);
 #ifdef DEBUG
 	UA_NodeId_printf("ActivateSession - authToken=", &(request->requestHeader.authenticationToken));
 	// 321 == AnonymousIdentityToken_Encoding_DefaultBinary
 	UA_NodeId_printf("ActivateSession - uIdToken.type=", &(request->userIdentityToken.typeId));
 	UA_ByteString_printx_hex("ActivateSession - uIdToken.body=", &(request->userIdentityToken.body));
 #endif
-
-	// FIXME: channel->session->application = <Application Ptr>
-	channel->session = &sessionMockup;
+	//TODO fill results
 	return UA_SUCCESS;
 }
 
-UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response) {
-	channel->session = UA_NULL;
-	// FIXME: set response
-	return UA_SUCCESS;
+UA_Int32 Service_CloseSession(UA_Session session, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response) {
+	UA_NodeId sessionId;
+	UA_Session_getId(session,&sessionId);
+
+	UA_SessionManager_removeSession(&sessionId);
+// FIXME: set response
+return UA_SUCCESS;
 }

+ 10 - 2
src/ua_services_subscription.c

@@ -7,7 +7,7 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 
-UA_Int32 Service_CreateSubscription(SL_Channel *channel, const UA_CreateSubscriptionRequest *request,
+UA_Int32 Service_CreateSubscription(UA_Session session, const UA_CreateSubscriptionRequest *request,
                                    UA_CreateSubscriptionResponse *response)
 {
 
@@ -18,7 +18,7 @@ UA_Int32 Service_CreateSubscription(SL_Channel *channel, const UA_CreateSubscrip
 	return UA_SUCCESS;
 }
 
-UA_Int32 Service_Publish(SL_Channel *channel, const UA_PublishRequest *request,
+UA_Int32 Service_Publish(UA_Session session, const UA_PublishRequest *request,
                                    UA_PublishResponse *response)
 {
 
@@ -28,3 +28,11 @@ UA_Int32 Service_Publish(SL_Channel *channel, const UA_PublishRequest *request,
 	return UA_SUCCESS;
 }
 
+UA_Int32 Service_SetPublishingMode(UA_Session session, const UA_SetPublishingModeRequest *request,
+                                   UA_SetPublishingModeResponse *response)
+{
+	response->diagnosticInfos = UA_NULL;
+	response->results = UA_NULL;
+	response->resultsSize = 0;
+	return UA_SUCCESS;
+}

+ 14 - 3
src/ua_services_view.c

@@ -183,8 +183,18 @@ static void Service_Browse_getBrowseResult(Namespace *ns, UA_BrowseDescription *
 	UA_Array_delete(relevantReferenceTypes, relevantReferenceTypesCount, &UA_.types[UA_NODEID]);
 }
 
-UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA_BrowseResponse *response) {
+UA_Int32 Service_Browse(UA_Session session, const UA_BrowseRequest *request, UA_BrowseResponse *response) {
 	UA_Int32 retval = UA_SUCCESS;
+	Application *application;
+	if(session == UA_NULL)
+	{
+		return UA_ERROR;
+	}
+	UA_Session_getApplicationPointer(session, &application);
+	if(application == UA_NULL)
+	{
+		return UA_ERROR;
+	}
 	DBG_VERBOSE(UA_NodeId_printf("BrowseService - view=", &request->view.viewId));
 
 	//TODO request->view not used atm
@@ -192,7 +202,7 @@ UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA
 	response->resultsSize = request->nodesToBrowseSize;
 
 	for(UA_Int32 i=0; i < request->nodesToBrowseSize; i++) {
-		Namespace *ns = UA_indexedList_findValue(channel->session->application->namespaces,
+		Namespace *ns = UA_indexedList_findValue(application->namespaces,
 												 request->nodesToBrowse[i].nodeId.namespace);
 		if(ns == UA_NULL) {
 			response->results[i].statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -210,7 +220,8 @@ UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA
 	return retval;
 }
 
-UA_Int32 Service_TranslateBrowsePathsToNodeIds(SL_Channel *channel, const UA_TranslateBrowsePathsToNodeIdsRequest *request,
+
+UA_Int32 Service_TranslateBrowsePathsToNodeIds(UA_Session session, const UA_TranslateBrowsePathsToNodeIdsRequest *request,
 											   UA_TranslateBrowsePathsToNodeIdsResponse *response) {
 	UA_Int32 retval = UA_SUCCESS;
 	DBG_VERBOSE(printf("TranslateBrowsePathsToNodeIdsService - %i path(s)", request->browsePathsSize));

+ 415 - 0
src/ua_stack_channel.c

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

+ 79 - 0
src/ua_stack_channel.h

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

+ 204 - 0
src/ua_stack_channel_manager.c

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

+ 38 - 0
src/ua_stack_channel_manager.h

@@ -0,0 +1,38 @@
+/*
+ * ua_stack_channel_manager.h
+ *
+ *  Created on: 09.05.2014
+ *      Author: root
+ */
+
+#ifndef UA_STACK_CHANNEL_MANAGER_H_
+#define UA_STACK_CHANNEL_MANAGER_H_
+
+#include "ua_stack_channel.h"
+
+
+
+
+
+
+
+UA_Int32 SL_ChannelManager_init(UA_UInt32 maxChannelCount,UA_UInt32 tokenLifetime, UA_UInt32 startChannelId, UA_UInt32 startTokenId, UA_String *endpointUrl);
+UA_Int32 SL_ChannelManager_addChannel(SL_Channel *channel);
+//UA_Int32 SL_ChannelManager_renewChannelToken(UA_Int32 channelId, UA_DateTime requestedLifeTime);
+//UA_Int32 SL_ChannelManager_createChannelToken(SL_secureChannel channel);
+//UA_Int32 SL_ChannelManager_renewChannelToken(SL_secureChannel channel);
+
+//UA_Int32 SL_ChannelManager_bindChannel(UA_Int32 channelId, TL_Connection *connection);
+UA_Int32 SL_ChannelManager_removeChannel(UA_Int32 channelId);
+UA_Int32 SL_ChannelManager_getChannel(UA_UInt32 channelId, SL_Channel *channel);
+
+UA_Int32 SL_ChannelManager_updateChannels();
+
+UA_Int32 SL_ChannelManager_getChannelLifeTime(UA_DateTime *lifeTime);
+
+UA_Int32 SL_ChannelManager_generateToken(SL_Channel channel, UA_Int32 requestedLifeTime, SecurityTokenRequestType requestType, UA_ChannelSecurityToken* newToken);
+
+UA_Int32 SL_ChannelManager_generateChannelId(UA_UInt32 *newChannelId);
+
+
+#endif /* UA_STACK_CHANNEL_MANAGER_H_ */

+ 220 - 0
src/ua_stack_session.c

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

+ 125 - 0
src/ua_stack_session.h

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

+ 205 - 0
src/ua_stack_session_manager.c

@@ -0,0 +1,205 @@
+/*
+ * ua_stack_session_manager.c
+ *
+ *  Created on: 05.06.2014
+ *      Author: root
+ */
+
+#include "ua_stack_session_manager.h"
+
+
+typedef struct UA_SessionManagerType
+{
+	UA_list_List sessions;
+	UA_UInt32 maxSessionCount;
+	UA_Int32 lastSessionId;
+	UA_UInt32 currentSessionCount;
+	UA_DateTime maxSessionLifeTime;
+
+	UA_DateTime sessionTimeout;
+}UA_SessionManagerType;
+
+static UA_SessionManagerType *sessionManager;
+
+UA_Int32 UA_SessionManager_generateSessionId(UA_NodeId *sessionId)
+{
+	sessionId->encodingByte = 0x00;
+	sessionId->namespace = 0;
+	sessionId->identifier.numeric = sessionManager->lastSessionId++;
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_SessionManager_init(UA_UInt32 maxSessionCount,UA_UInt32 sessionTimeout, UA_UInt32 startSessionId)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	retval |= UA_alloc((void**)&sessionManager,sizeof(UA_SessionManagerType));
+
+	retval |= UA_list_init(&sessionManager->sessions);
+
+	sessionManager->maxSessionCount = maxSessionCount;
+	sessionManager->lastSessionId = startSessionId;
+	sessionManager->sessionTimeout = sessionTimeout;
+	return retval;
+}
+
+UA_Boolean UA_SessionManager_sessionExists(UA_Session *session)
+{
+
+	if(sessionManager == UA_NULL)
+	{
+		return UA_FALSE;
+	}
+
+	if(UA_list_search(&sessionManager->sessions,(UA_list_PayloadComparer)UA_Session_compare,(void*)session))
+	{
+		UA_Double pendingLifetime;
+		UA_Session_getPendingLifetime(*session,&pendingLifetime);
+		if(pendingLifetime>0){
+			return UA_TRUE;
+		}
+		//timeout of session reached so remove it
+		UA_NodeId sessionId;
+		UA_Session_getId(*session,&sessionId);
+		UA_SessionManager_removeSession(&sessionId);
+	}
+	return UA_FALSE;
+}
+
+UA_Int32 UA_SessionManager_getSessionById(UA_NodeId *sessionId, UA_Session *session)
+{
+	if(sessionManager != UA_NULL)
+	{
+		*session = UA_NULL;
+		return UA_ERROR;
+	}
+
+	UA_list_Element* current = sessionManager->sessions.first;
+	while (current)
+	{
+		if (current->payload)
+		{
+			UA_list_Element* elem = (UA_list_Element*) current;
+			*session = *((UA_Session*) (elem->payload));
+			if(UA_Session_compareById(*session,sessionId) == UA_EQUAL){
+				UA_Double pendingLifetime;
+				UA_Session_getPendingLifetime(*session, &pendingLifetime);
+				if(pendingLifetime > 0){
+					return UA_SUCCESS;
+				}
+				//session not valid anymore -> remove it
+				UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
+				*session = UA_NULL;
+				return UA_ERROR;
+			}
+		}
+		current = current->next;
+	}
+	*session = UA_NULL;
+	return UA_ERROR;
+}
+
+UA_Int32 UA_SessionManager_getSessionByToken(UA_NodeId *token, UA_Session *session)
+{
+	if(sessionManager == UA_NULL)
+	{
+		*session = UA_NULL;
+		return UA_ERROR;
+	}
+
+	UA_list_Element* current = sessionManager->sessions.first;
+	while (current)
+	{
+		if (current->payload)
+		{
+			UA_list_Element* elem = (UA_list_Element*) current;
+			*session = *((UA_Session*) (elem->payload));
+
+			if(UA_Session_compareByToken(*session,token) == UA_EQUAL){
+				UA_Double pendingLifetime;
+				UA_Session_getPendingLifetime(*session, &pendingLifetime);
+				if(pendingLifetime > 0){
+					return UA_SUCCESS;
+				}
+				//session not valid anymore -> remove it
+				UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
+				*session = UA_NULL;
+				return UA_ERROR;
+			}
+		}
+		current = current->next;
+	}
+	*session = UA_NULL;
+	return UA_ERROR;
+}
+
+UA_Int32 UA_SessionManager_addSession(UA_Session *session)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_NodeId sessionId;
+	if(!UA_SessionManager_sessionExists(session))
+	{
+		retval |= UA_list_addPayloadToBack(&sessionManager->sessions,(void*)session);
+		UA_Session_getId(*session, &sessionId);
+
+		printf("UA_SessionManager_addSession - added session with id = %d \n",sessionId.identifier.numeric);
+		printf("UA_SessionManager_addSession - current session count: %i \n",sessionManager->sessions.size);
+
+		return retval;
+	}
+	printf("UA_SessionManager_addSession - session already in list");
+	return UA_ERROR;
+
+}
+
+UA_Int32 UA_SessionManager_removeSession(UA_NodeId *sessionId)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_list_Element *element = UA_list_search(&sessionManager->sessions,(UA_list_PayloadComparer)UA_Session_compare,sessionId);
+	if(element)
+	{
+		retval |= UA_list_removeElement(element,(UA_list_PayloadVisitor)UA_Session_delete);
+		printf("UA_SessionManager_removeSession - session removed, current count: %i \n",sessionManager->sessions.size);
+	}
+
+	return retval;
+}
+
+UA_Int32 UA_SessionManager_updateSessions()
+{
+	if(sessionManager == UA_NULL)
+	{
+		return UA_ERROR;
+	}
+	UA_list_Element* current = sessionManager->sessions.first;
+	while (current)
+	{
+		if (current->payload)
+		{
+			UA_list_Element* elem = (UA_list_Element*) current;
+			UA_Session session = *((UA_Session*) (elem->payload));
+			UA_Double pendingLifetime;
+			UA_Session_getPendingLifetime(session, &pendingLifetime);
+
+			if(pendingLifetime <= 0){
+				UA_NodeId sessionId;
+				UA_Session_getId(session,&sessionId);
+				UA_SessionManager_removeSession(&sessionId);
+			}
+		}
+		current = current->next;
+	}
+	return UA_SUCCESS;
+}
+
+UA_Int32 UA_SessionManager_getSessionTimeout(UA_Int64 *timeout_ms)
+{
+	if(sessionManager)
+	{
+		*timeout_ms = sessionManager->sessionTimeout;
+		return UA_SUCCESS;
+	}
+	*timeout_ms = 0;
+	return UA_ERROR;
+}
+
+

+ 77 - 0
src/ua_stack_session_manager.h

@@ -0,0 +1,77 @@
+/*
+ * ua_stack_session_manager.h
+ *
+ *  Created on: 05.06.2014
+ *      Author: root
+ */
+
+#ifndef UA_STACK_SESSION_MANAGER_H_
+#define UA_STACK_SESSION_MANAGER_H_
+
+
+
+#include "ua_stack_session.h"
+
+
+
+//hide internal data of channelManager
+typedef struct UA_SessionManagerType *UA_SessionManager;
+
+/**
+ * @brief initializes the session manager
+ * @param maxSessionCount maximum amount of sessions which should be allowed to be created
+ * @param sessionLifetime lifetime of a session, after this time the session must be renewed
+ * @param startSessionId the start id of the session identifiers, newer sessions get higher ids
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_init(UA_UInt32 maxSessionCount,UA_UInt32 sessionLifetime,
+		UA_UInt32 startSessionId);
+
+/**
+ * @brief adds a session to the manager list
+ * @param session session object which should be added to the manager list
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_addSession(UA_Session *session);
+
+/**
+ * @brief removes a session from the manager list
+ * @param sessionId id which assign to a session
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_removeSession(UA_NodeId *sessionId);
+
+/**
+ * @brief finds the session which is identified by the sessionId
+ * @param sessionId the session id is used to identify the unknown session
+ * @param session the session object is returned if no error occurs
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_getSessionById(UA_NodeId *sessionId, UA_Session *session);
+
+/**
+ * @brief
+ * @param token authentication token which is used to get the session object
+ * @param session output, session object which is identified by the authentication token
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_getSessionByToken(UA_NodeId *token, UA_Session *session);
+
+
+/**
+ * @brief gets the session timeout value which should be assigned to
+ * all sessions handled by the manager
+ * @param timeout_ms timeout in milliseconds
+ * @return error code
+ */
+UA_Int32 UA_SessionManager_getSessionTimeout(UA_Int64 *timeout_ms);
+
+
+//UA_Int32 UA_SessionManager_updateSessions();
+
+
+//UA_Int32 UA_SessionManager_generateToken(UA_Session session, UA_Int32 requestedLifeTime, SecurityTokenRequestType requestType, UA_ChannelSecurityToken* newToken);
+
+UA_Int32 UA_SessionManager_generateSessionId(UA_NodeId *newSessionId);
+
+#endif /* UA_STACK_SESSION_MANAGER_H_ */

+ 1 - 4
src/ua_transport.c

@@ -276,7 +276,6 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(UA_AsymmetricAlgori
 	 + UA_ByteString_calcSizeBinary(&ptr->securityPolicyUri)
 	 + UA_ByteString_calcSizeBinary(&ptr->senderCertificate)
 	 + UA_ByteString_calcSizeBinary(&ptr->receiverCertificateThumbprint)
-			//	 + sizeof(UA_UInt32) // requestId
 	;
 }
 
@@ -285,7 +284,6 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(UA_AsymmetricAlgorith
 	retval |= UA_ByteString_encodeBinary(&src->securityPolicyUri,dst,offset);
 	retval |= UA_ByteString_encodeBinary(&src->senderCertificate,dst,offset);
 	retval |= UA_ByteString_encodeBinary(&src->receiverCertificateThumbprint,dst,offset);
-	//	retval |= UA_UInt32_encodeBinary(&src->requestId,dst,offset);
 	return retval;
 }
 
@@ -295,7 +293,6 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(UA_ByteString const *
 	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->securityPolicyUri), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->senderCertificate), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	CHECKED_DECODE(UA_ByteString_decodeBinary(src,offset,&dst->receiverCertificateThumbprint), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
-	//	CHECKED_DECODE(UA_UInt32_decodeBinary(src,offset,&dst->requestId), UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(dst));
 	return retval;
 }
 
@@ -319,7 +316,6 @@ UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurit
 	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;
 }
 
@@ -482,6 +478,7 @@ UA_Int32 UA_SecureConversationMessageFooter_copy(const UA_SecureConversationMess
     	UA_Int32 retval = UA_SUCCESS;
 	memcpy(dst, src, sizeof(UA_SecureConversationMessageFooter));
 
+
 	retval |= UA_Array_copy(src->padding, src->paddingSize,&UA_.types[UA_BYTE],(void**)&dst->padding);
 	return retval;
 }

+ 3 - 4
src/ua_transport.h

@@ -7,19 +7,19 @@
 
 static const UA_Int32 SL_HEADER_LENGTH = 0;
 
-enum ConnectionState {
+typedef enum UA_ConnectionState {
 	CONNECTIONSTATE_CLOSED,
 	CONNECTIONSTATE_OPENING,
 	CONNECTIONSTATE_ESTABLISHED,
 	CONNECTIONSTATE_CLOSE
-};
+}UA_ConnectionState;
 
 typedef struct Session {
 	UA_Int32 sessionId;
 	Application *application;
 } Session;
 
-typedef enum {
+typedef enum SecurityTokenRequestType{
 	UA_SECURITYTOKEN_ISSUE = 0,
 	UA_SECURITYTOKEN_RENEW = 1
 } SecurityTokenRequestType;
@@ -89,7 +89,6 @@ typedef struct UA_AsymmetricAlgorithmSecurityHeader {
 	UA_ByteString securityPolicyUri;
 	UA_ByteString senderCertificate;
 	UA_ByteString receiverCertificateThumbprint;
-	UA_UInt32 requestId;
 } UA_AsymmetricAlgorithmSecurityHeader;
 UA_TYPE_PROTOTYPES(UA_AsymmetricAlgorithmSecurityHeader)
 UA_TYPE_BINARY_ENCODING(UA_AsymmetricAlgorithmSecurityHeader)

+ 71 - 45
src/ua_transport_binary.c

@@ -2,61 +2,51 @@
 #include "ua_transport_binary.h"
 #include "ua_transport.h"
 #include "ua_transport_binary_secure.h"
+#include "ua_transport_connection.h"
 
-static UA_Int32 TL_check(TL_Connection* connection, UA_ByteString* msg) {
-	if(msg->length > (UA_Int32) connection->localConf.maxMessageSize || msg->length > (UA_Int32) connection->remoteConf.maxMessageSize) {
-		DBG_ERR(printf("TL_check - length error \n"));
-		return UA_ERR_INCONSISTENT;
-	}
-	return UA_SUCCESS;
-}
 
-static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* offset) {
+static UA_Int32 TL_handleHello(UA_TL_Connection connection, const UA_ByteString* msg, UA_UInt32* pos){
 	UA_Int32 retval = UA_SUCCESS;
+	UA_UInt32 tmpPos = 0;
+	UA_Int32 connectionState;
 	UA_OPCUATcpHelloMessage helloMessage;
-
-	if (connection->connectionState == CONNECTIONSTATE_CLOSED) {
+	UA_TL_Connection_getState(connection, &connectionState);
+	if (connectionState == CONNECTIONSTATE_CLOSED){
 		DBG_VERBOSE(printf("TL_handleHello - extracting header information \n"));
-		UA_OPCUATcpHelloMessage_decodeBinary(msg,offset,&helloMessage);
-
-		// memorize buffer info and change mode to established
-		connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
-		connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
-		connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
-		connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
-		connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
-		UA_String_copy(&(helloMessage.endpointUrl), &(connection->remoteEndpointUrl));
-		UA_OPCUATcpHelloMessage_deleteMembers(&helloMessage);
+		UA_OPCUATcpHelloMessage_decodeBinary(msg,pos,&helloMessage);
 
+		UA_TL_Connection_configByHello(connection, &helloMessage);
 		DBG_VERBOSE(printf("TL_handleHello - protocolVersion = %d \n",connection->remoteConf.protocolVersion));
 		DBG_VERBOSE(printf("TL_handleHello - recvBufferSize = %d \n",connection->remoteConf.recvBufferSize));
 		DBG_VERBOSE(printf("TL_handleHello - sendBufferSize = %d \n",connection->remoteConf.sendBufferSize));
 		DBG_VERBOSE(printf("TL_handleHello - maxMessageSize = %d \n",connection->remoteConf.maxMessageSize));
 		DBG_VERBOSE(printf("TL_handleHello - maxChunkCount = %d \n",connection->remoteConf.maxChunkCount));
-		connection->connectionState = CONNECTIONSTATE_ESTABLISHED;
 
 		// build acknowledge response
 		UA_OPCUATcpAcknowledgeMessage ackMessage;
-		ackMessage.protocolVersion = connection->localConf.protocolVersion;
-		ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
-		ackMessage.sendBufferSize = connection->localConf.sendBufferSize;
-		ackMessage.maxMessageSize = connection->localConf.maxMessageSize;
-		ackMessage.maxChunkCount = connection->localConf.maxChunkCount;
+		TL_Buffer localConfig;
+		UA_TL_Connection_getLocalConfig(connection, &localConfig);
+		ackMessage.protocolVersion = localConfig.protocolVersion;
+		ackMessage.receiveBufferSize = localConfig.recvBufferSize;
+		ackMessage.sendBufferSize = localConfig.sendBufferSize;
+		ackMessage.maxMessageSize = localConfig.maxMessageSize;
+		ackMessage.maxChunkCount = localConfig.maxChunkCount;
 
 		UA_OPCUATcpMessageHeader ackHeader;
 		ackHeader.messageType = UA_MESSAGETYPE_ACK;
 		ackHeader.isFinal = 'F';
 
 		// encode header and message to buffer
-		UA_UInt32 tmpOffset = 0;
+		tmpPos = 0;
+
 		ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(&ackMessage) + UA_OPCUATcpMessageHeader_calcSizeBinary(&ackHeader);
 		UA_ByteString *ack_msg;
 		UA_alloc((void **)&ack_msg, sizeof(UA_ByteString));
 		UA_ByteString_newMembers(ack_msg, ackHeader.messageSize);
-		UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader,ack_msg,&tmpOffset);
-		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage,ack_msg,&tmpOffset);
+		UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader,ack_msg,&tmpPos);
+		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage, ack_msg,&tmpPos);
 
-		DBG_VERBOSE(printf("TL_handleHello - Size messageToSend = %d, offset=%d\n",ackHeader.messageSize, tmpOffset));
+		DBG_VERBOSE(printf("TL_handleHello - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos));
 		DBG_VERBOSE(UA_ByteString_printx("_handleHello - ack=", ack_msg));
 		TL_Send(connection, (const UA_ByteString **) &ack_msg, 1);
 		DBG_VERBOSE(printf("TL_handleHello - finished writing\n"));
@@ -68,33 +58,55 @@ static UA_Int32 TL_handleHello(TL_Connection* connection, const UA_ByteString* m
 	return retval;
 }
 
-static UA_Int32 TL_handleOpen(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	if (connection->connectionState == CONNECTIONSTATE_ESTABLISHED) {
-		return SL_Channel_new(connection, msg, pos);
+static UA_Int32 TL_handleOpen(UA_TL_Connection connection, const UA_ByteString* msg, UA_UInt32* pos) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 state;
+	SL_Channel *channel;
+
+	retval |= UA_TL_Connection_getState(connection,&state);
+	if (state == CONNECTIONSTATE_ESTABLISHED) {
+		retval |= SL_Channel_new(&channel);//just create channel
+		retval |= SL_Channel_init(*channel,connection,
+				SL_ChannelManager_generateChannelId,
+			SL_ChannelManager_generateToken);
+		retval |= SL_Channel_bind(*channel,connection);
+		retval |= SL_ProcessOpenChannel(*channel, msg, pos);
+		retval |= SL_ChannelManager_addChannel(channel);
+		return retval;
+	}else{
+		printf("TL_handleOpen - ERROR: could not create new secureChannel");
 	}
+
 	return UA_ERR_INVALID_VALUE;
 }
 
-static UA_Int32 TL_handleMsg(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	SL_Channel* slc = connection->secureChannel;
-	return SL_Process(slc,msg,pos);
+static UA_Int32 TL_handleMsg(UA_TL_Connection connection, const UA_ByteString* msg, UA_UInt32* pos) {
+	UA_Int32 state;
+	UA_TL_Connection_getState(connection,&state);
+	if (state == CONNECTIONSTATE_ESTABLISHED) {
+		return SL_Process(msg, pos);
+	}
+	return UA_ERR_INVALID_VALUE;
 }
 
-static UA_Int32 TL_handleClo(TL_Connection* connection, const UA_ByteString* msg, UA_UInt32* pos) {
-	SL_Channel* slc = connection->secureChannel;
-	connection->connectionState = CONNECTIONSTATE_CLOSE;
-    connection->secureChannel = UA_NULL;
-    slc->tlConnection = UA_NULL;
-	return UA_SUCCESS;
+static UA_Int32 TL_handleClo(UA_TL_Connection connection, const UA_ByteString* msg, UA_UInt32* pos) {
+	UA_Int32 retval = UA_SUCCESS;
+	SL_Process(msg,pos);
+
+	UA_TL_Connection_close(connection);
+	return retval;
 }
 
-UA_Int32 TL_Process(TL_Connection* connection, const UA_ByteString* msg) {
+UA_Int32 TL_Process(UA_TL_Connection connection, const UA_ByteString* msg) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_UInt32 pos = 0;
 	UA_OPCUATcpMessageHeader tcpMessageHeader;
 
 	DBG_VERBOSE(printf("TL_Process - entered \n"));
+	UA_Int32 messageCounter = 0;
+
 	do{
+
 		if ((retval = UA_OPCUATcpMessageHeader_decodeBinary(msg,&pos,&tcpMessageHeader)) == UA_SUCCESS) {
 			printf("TL_Process - messageType=%.*s\n",3,msg->data);
 			switch(tcpMessageHeader.messageType) {
@@ -111,10 +123,21 @@ UA_Int32 TL_Process(TL_Connection* connection, const UA_ByteString* msg) {
 				retval = TL_handleClo(connection, msg, &pos);
 				break;
 			default: // dispatch processing to secureLayer
+				//Invalid packet was received which could have led to a wrong offset (pos).
+				//It was not possible to extract the following packet from the buffer
 				retval = UA_ERR_INVALID_VALUE;
 				break;
 			}
 		}
+		else
+		{
+			printf("TL_Process - ERROR:decoding of header failed \n");
+		}
+
+		messageCounter++;
+		printf("TL_Process - multipleMessage in Buffer: %i \n",messageCounter);
+
+
 	}while(msg->length > (UA_Int32)pos);
 	/* if (retval != UA_SUCCESS) { */
 	/* 	// FIXME: compose real error message */
@@ -129,11 +152,14 @@ UA_Int32 TL_Process(TL_Connection* connection, const UA_ByteString* msg) {
 }
 
 /** respond to client request */
-UA_Int32 TL_Send(TL_Connection* connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len) {
+UA_Int32 TL_Send(UA_TL_Connection connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len) {
 	UA_Int32 retval = UA_SUCCESS;
+
+
 	DBG_VERBOSE(printf("TL_send - entered \n"));
 	//	if (TL_check(connection,msg,TL_CHECK_REMOTE) == UA_SUCCESS) {
-	retval = connection->writerCallback(connection, gather_buf, gather_len);
+
+	retval = UA_TL_Connection_callWriter(connection, gather_buf, gather_len);
 	DBG_VERBOSE(printf("TL_send - exited \n"));
 		//}
 	/* else */

+ 12 - 14
src/ua_transport_binary.h

@@ -2,7 +2,9 @@
 #define OPCUA_TRANSPORT_BINARY_H_
 #include <stdio.h>
 
-#include "ua_types.h"
+
+#include "ua_transport_binary.h"
+#include "ua_transport_connection.h"
 
 //transport errors begin at 1000
 #define UA_ERROR_MULTIPLE_HEL 1000
@@ -13,19 +15,14 @@
 #define TL_SERVER_MAX_CHUNK_COUNT 1
 #define TL_SERVER_MAX_MESSAGE_SIZE  8192
 
-typedef struct TL_Buffer {
-	UA_UInt32 protocolVersion;
-	UA_UInt32 sendBufferSize;
-	UA_UInt32 recvBufferSize;
-	UA_UInt32 maxMessageSize;
-	UA_UInt32 maxChunkCount;
-} TL_Buffer;
+
 
 /* Transport Layer Connection */
-struct TL_Connection; // forward declaration
-typedef UA_Int32 (*TL_Writer)(struct TL_Connection* connection, const UA_ByteString** gather_bufs, UA_Int32 gather_len); // send mutiple buffer concatenated into one msg (zero copy)
+//struct TL_Connection_T; // forward declaration
 
-typedef struct TL_Connection {
+//typedef UA_Int32 (*TL_Writer)(struct TL_Connection_T* connection, const UA_ByteString** gather_bufs, UA_Int32 gather_len); // send mutiple buffer concatenated into one msg (zero copy)
+/*
+typedef struct TL_Connection_T {
 	UA_Int32 connectionHandle;
 	UA_UInt32 connectionState;
 	TL_Buffer localConf;
@@ -33,10 +30,11 @@ typedef struct TL_Connection {
 	TL_Writer writerCallback;
 	UA_String localEndpointUrl;
 	UA_String remoteEndpointUrl;
-	struct SL_Channel* secureChannel;
+	struct SL_Channel_T* secureChannel;
 } TL_Connection;
+*/
 
-UA_Int32 TL_Send(TL_Connection* connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len);
-UA_Int32 TL_Process(TL_Connection *connection, const UA_ByteString *packet);
+UA_Int32 TL_Send(UA_TL_Connection connection, const UA_ByteString** gather_buf, UA_UInt32 gather_len);
+UA_Int32 TL_Process(UA_TL_Connection connection, const UA_ByteString* msg);
 
 #endif /* OPCUA_TRANSPORT_BINARY_H_ */

+ 379 - 170
src/ua_transport_binary_secure.c

@@ -1,74 +1,106 @@
 #include <stdio.h>
 #include <memory.h> // memcpy
+
 #include "ua_transport_binary.h"
 #include "ua_transport_binary_secure.h"
 #include "ua_transport.h"
 #include "ua_statuscodes.h"
 #include "ua_services.h"
+#include "ua_stack_session_manager.h"
+#include "ua_stack_session.h"
 
 #define SIZE_SECURECHANNEL_HEADER 12
 #define SIZE_SEQHEADER_HEADER 8
 
-SL_Channel slc;
+static UA_Int32 SL_Send(SL_Channel channel,
+		const UA_ByteString * responseMessage, UA_Int32 type)
+{
+	UA_UInt32 pos = 0;
+	UA_Int32 isAsym = (type == UA_OPENSECURECHANNELRESPONSE_NS0); // FIXME: this is a to dumb method to determine asymmetric algorithm setting
+	UA_UInt32 channelId;
+	UA_UInt32 sequenceNumber;
+	UA_UInt32 requestId;
+	UA_TL_Connection connection;
+	UA_NodeId resp_nodeid;
+	UA_AsymmetricAlgorithmSecurityHeader *asymAlgSettings = UA_NULL;
 
-static UA_Int32 SL_Send(SL_Channel *channel, const UA_ByteString *responseMessage, UA_Int32 type) {
-	UA_UInt32 offset = 0;
-	// FIXME: this is a to dumb method to determine asymmetric algorithm setting
-	UA_Int32  isAsym = (type == UA_OPENSECURECHANNELRESPONSE_NS0);
+	resp_nodeid.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	resp_nodeid.namespace = 0;
+	resp_nodeid.identifier.numeric = type + 2; // binary encoding
 
-	UA_NodeId resp_nodeid;
-	resp_nodeid.encodingByte       = UA_NODEIDTYPE_FOURBYTE;
-	resp_nodeid.namespace          = 0;
-	resp_nodeid.identifier.numeric = type+2; // binary encoding
-
-	const UA_ByteString *response_gather[2];
-	UA_alloc((void **)&response_gather[0], sizeof(UA_ByteString));
-	if(isAsym) {
-	UA_ByteString_newMembers(
-	    (UA_ByteString *)response_gather[0], SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER +
-	    UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&channel->localAsymAlgSettings) +
-	    UA_NodeId_calcSizeBinary(&resp_nodeid));
-	}else {
-		UA_ByteString_newMembers((UA_ByteString *)response_gather[0], 8 +
-		                         16 + // normal header + 4*32bit secure channel information
-		                         UA_NodeId_calcSizeBinary(&resp_nodeid));
-	}
+	const UA_ByteString *response_gather[2]; // securechannel_header, seq_header, security_encryption_header, message_length (eventually + padding + size_signature);
+	UA_alloc((void ** )&response_gather[0], sizeof(UA_ByteString));
+	if (isAsym)
+	{
 
+		SL_Channel_getLocalAsymAlgSettings(channel, &asymAlgSettings);
+		UA_ByteString_newMembers((UA_ByteString *) response_gather[0],
+				SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
+						+ UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(
+								asymAlgSettings)
+						+ UA_NodeId_calcSizeBinary(&resp_nodeid));
+	}
+	else
+	{
+		UA_ByteString_newMembers((UA_ByteString *) response_gather[0], 8 + 16 + // normal header + 4*32bit secure channel information
+				UA_NodeId_calcSizeBinary(&resp_nodeid));
+	}
 
 	// sizePadding = 0;
 	// sizeSignature = 0;
-	UA_ByteString *header = (UA_ByteString *)response_gather[0];
+	UA_ByteString *header = (UA_ByteString *) response_gather[0];
 
-	/*---encode Secure Conversation Message Header ---*/
-	if(isAsym) {
+	/*---encode Secure Conversation Message Header  ---*/
+	if (isAsym)
+	{
 		header->data[0] = 'O';
 		header->data[1] = 'P';
 		header->data[2] = 'N';
-	} else {
+	}
+	else
+	{
 		header->data[0] = 'M';
 		header->data[1] = 'S';
 		header->data[2] = 'G';
 	}
-	offset += 3;
-	header->data[offset] = 'F';
-	offset += 1;
+	pos += 3;
+	header->data[pos] = 'F';
+	pos += 1;
 
 	UA_Int32 packetSize = response_gather[0]->length + responseMessage->length;
-	UA_Int32_encodeBinary(&packetSize, header, &offset);
-	UA_UInt32_encodeBinary(&channel->securityToken.secureChannelId, header, &offset);
+	UA_Int32_encodeBinary(&packetSize, header,&pos);
+
+	//use get accessor to read the channel Id
+	SL_Channel_getChannelId(channel, &channelId);
+
+	UA_UInt32_encodeBinary(&channelId, header,&pos);
 
 	/*---encode Algorithm Security Header ---*/
-	if(isAsym)
-		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&channel->localAsymAlgSettings, header, &offset);
+	if (isAsym)
+	{
+
+
+		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(asymAlgSettings,
+				header,&pos);
+		UA_free(asymAlgSettings);
+	}
 	else
-		UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&channel->securityToken.tokenId, header, &offset);
+	{
+
+		UA_UInt32 tokenId = 0;
+		SL_Channel_getTokenId(channel, &tokenId);
+
+		UA_UInt32_encodeBinary(&tokenId, header,&pos);
+	}
 
 	/*---encode Sequence Header ---*/
-	UA_UInt32_encodeBinary(&channel->sequenceHeader.sequenceNumber, header, &offset);
-	UA_UInt32_encodeBinary(&channel->sequenceHeader.requestId, header, &offset);
+	SL_Channel_getSequenceNumber(channel, &sequenceNumber);
+	UA_UInt32_encodeBinary(&sequenceNumber, header, &pos);
+	SL_Channel_getRequestId(channel, &requestId);
+	UA_UInt32_encodeBinary(&requestId, header,&pos);
 
 	/*---add payload type---*/
-	UA_NodeId_encodeBinary(&resp_nodeid, header, &offset);
+	UA_NodeId_encodeBinary(&resp_nodeid, header,&pos);
 
 	/*---add encoded Message ---*/
 	response_gather[1] = responseMessage; // is deleted in the calling function
@@ -78,180 +110,357 @@ static UA_Int32 SL_Send(SL_Channel *channel, const UA_ByteString *responseMessag
 	/* encrypt Data*/
 
 	/* send Data */
-	TL_Send(channel->tlConnection, response_gather, 2);
+	SL_Channel_getConnection(channel, &connection);
+	TL_Send(connection, response_gather, 2);
 
-	UA_ByteString_delete((UA_ByteString *)response_gather[0]);
+	UA_ByteString_delete((UA_ByteString *) response_gather[0]);
 	return UA_SUCCESS;
 }
 
-static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r) {
-	memset((void *)r, 0, sizeof(UA_ResponseHeader));
-	r->requestHandle   = p->requestHandle;
-	r->serviceResult   = UA_STATUSCODE_GOOD;
+static void init_response_header(UA_RequestHeader const * p,
+		UA_ResponseHeader * r)
+{
+	memset((void*) r, 0, sizeof(UA_ResponseHeader));
+	r->requestHandle = p->requestHandle;
+	r->serviceResult = UA_STATUSCODE_GOOD;
 	r->stringTableSize = 0;
-	r->timestamp       = UA_DateTime_now();
+	r->timestamp = UA_DateTime_now();
 }
-
-#define INVOKE_SERVICE(TYPE)                                                         \
-    UA_##TYPE##Request p;                                                            \
-    UA_##TYPE##Response r;                                                           \
-    UA_##TYPE##Request_decodeBinary(msg, offset, &p);                                \
-    UA_##TYPE##Response_init(&r);                                                    \
-    init_response_header(&p.requestHeader, &r.responseHeader);                       \
-    DBG_VERBOSE(printf("Invoke Service: %s\n", # TYPE));                             \
-    Service_##TYPE(channel, &p, &r);                                                 \
-    DBG_VERBOSE(printf("Finished Service: %s\n", # TYPE));                           \
-    UA_UInt32 sending_offset = 0;													 \
-    UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
-    UA_##TYPE##Response_encodeBinary(&r, &response_msg, &sending_offset);            \
-    UA_##TYPE##Request_deleteMembers(&p);                                            \
-    UA_##TYPE##Response_deleteMembers(&r);                                           \
-
-/** this function manages all the generic stuff for the request-response game */
-UA_Int32 SL_handleRequest(SL_Channel *channel, const UA_ByteString *msg, UA_UInt32 *offset) {
+#define RESPONSE_PREPARE(TYPE) \
+	UA_##TYPE##Request p; \
+	UA_##TYPE##Response r; \
+	UA_Session session = UA_NULL; \
+	UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
+	UA_##TYPE##Response_init(&r); \
+	init_response_header(&p.requestHeader, &r.responseHeader); \
+	UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
+	DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
+
+#define INVOKE_SERVICE(TYPE) \
+	UA_##TYPE##Request p; \
+	UA_##TYPE##Response r; \
+	UA_Session session = UA_NULL; \
+	UA_##TYPE##Request_decodeBinary(msg, &recvOffset, &p); \
+	UA_##TYPE##Response_init(&r); \
+	init_response_header(&p.requestHeader, &r.responseHeader); \
+	UA_SessionManager_getSessionByToken(&p.requestHeader.authenticationToken, &session); \
+	DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
+	Service_##TYPE(session, &p, &r); \
+	DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
+    sendOffset = 0; \
+	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
+	UA_##TYPE##Response_encodeBinary(&r, &sendOffset, &response_msg); \
+	UA_##TYPE##Request_deleteMembers(&p); \
+	UA_##TYPE##Response_deleteMembers(&r); \
+/*
+#define INVOKE_SERVICE(TYPE) \
+		DBG_VERBOSE(printf("Invoke Service: %s\n", #TYPE)); \
+		Service_##TYPE(session, &p, &r); \
+		DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
+*/
+#define RESPONSE_CLEANUP(TYPE) \
+	DBG_VERBOSE(printf("Finished Service: %s\n", #TYPE)); \
+	sendOffset = 0; \
+	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSizeBinary(&r)); \
+	UA_##TYPE##Response_encodeBinary(&r, &response_msg,&sendOffset); \
+	UA_##TYPE##Request_deleteMembers(&p); \
+	UA_##TYPE##Response_deleteMembers(&r); \
+
+
+UA_Int32 SL_handleRequest(SL_Channel channel, const UA_ByteString* msg,
+		UA_UInt32 *pos)
+{
 	UA_Int32 retval = UA_SUCCESS;
-
+	UA_UInt32 recvOffset = *pos;
+	UA_UInt32 sendOffset = 0;
 	// Every Message starts with a NodeID which names the serviceRequestType
 	UA_NodeId serviceRequestType;
-	UA_NodeId_decodeBinary(msg, offset, &serviceRequestType);
+	UA_NodeId_decodeBinary(msg, &recvOffset,&serviceRequestType);
 #ifdef DEBUG
-	UA_NodeId_printf("SL_processMessage - serviceRequestType=", &serviceRequestType);
+	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
+			&serviceRequestType);
 #endif
-
 	UA_ByteString response_msg;
-	int serviceid = serviceRequestType.identifier.numeric-2; // binary encoding has 2 added to the id
-	UA_Int32      responsetype;
-	if(serviceid == UA_GETENDPOINTSREQUEST_NS0) {
-		INVOKE_SERVICE(GetEndpoints);
+	UA_Int32 serviceid = serviceRequestType.identifier.numeric - 2; // binary encoding has 2 added to the id
+	UA_Int32 responsetype;
+/* stack related services which only need information about the secure Channel */
+	if (serviceid == UA_GETENDPOINTSREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(GetEndpoints);
+		Service_GetEndpoints(channel,&p, &r);
+		RESPONSE_CLEANUP(GetEndpoints);
+		//INVOKE_SERVICE(GetEndpoints);
 		responsetype = UA_GETENDPOINTSRESPONSE_NS0;
-	}else if(serviceid == UA_OPENSECURECHANNELREQUEST_NS0) {
-		INVOKE_SERVICE(OpenSecureChannel);
+	}
+	else if (serviceid == UA_OPENSECURECHANNELREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(OpenSecureChannel);
+		Service_OpenSecureChannel(channel,&p, &r);
+		RESPONSE_CLEANUP(OpenSecureChannel);
 		responsetype = UA_OPENSECURECHANNELRESPONSE_NS0;
-	}else if(serviceid == UA_CLOSESECURECHANNELREQUEST_NS0) {
-		INVOKE_SERVICE(CloseSecureChannel);
+	}
+	else if (serviceid == UA_CLOSESECURECHANNELREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(CloseSecureChannel);
+		Service_CloseSecureChannel(channel,&p,&r);
+		RESPONSE_CLEANUP(CloseSecureChannel);
 		responsetype = UA_CLOSESECURECHANNELRESPONSE_NS0;
-	}else if(serviceid == UA_CREATESESSIONREQUEST_NS0) {
-		INVOKE_SERVICE(CreateSession);
+	}
+
+	else if (serviceid == UA_CREATESESSIONREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(CreateSession);
+		Service_CreateSession(channel,&p, &r);
+		RESPONSE_CLEANUP(CreateSession);
 		responsetype = UA_CREATESESSIONRESPONSE_NS0;
-	}else if(serviceid == UA_ACTIVATESESSIONREQUEST_NS0) {
-		INVOKE_SERVICE(ActivateSession);
+	}
+/* services which need a session object */
+	else if (serviceid == UA_ACTIVATESESSIONREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(ActivateSession);
+		UA_Session_updateLifetime(session); //renew session timeout
+		Service_ActivateSession(channel, session,&p, &r);
+		RESPONSE_CLEANUP(ActivateSession);
+
 		responsetype = UA_ACTIVATESESSIONRESPONSE_NS0;
-	}else if(serviceid == UA_CLOSESESSIONREQUEST_NS0) {
-		INVOKE_SERVICE(CloseSession);
+	}
+	else if (serviceid == UA_CLOSESESSIONREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(CloseSession);
+		if (UA_Session_verifyChannel(session,channel)){
+			UA_Session_updateLifetime(session); //renew session timeout
+			Service_CloseSession(session,&p, &r);
+		RESPONSE_CLEANUP(CloseSession);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
 		responsetype = UA_CLOSESESSIONRESPONSE_NS0;
-	}else if(serviceid == UA_READREQUEST_NS0) {
-		INVOKE_SERVICE(Read);
+	}
+	else if (serviceid == UA_READREQUEST_NS0)
+	{
+
+		RESPONSE_PREPARE(Read);
+		UA_Session_updateLifetime(session); //renew session timeout
+		DBG_VERBOSE(printf("Finished Service: %s\n", Read));
+		if (UA_Session_verifyChannel(session,channel)){
+			UA_Session_updateLifetime(session); //renew session timeout
+			Service_Read(session,&p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", Read));
+		RESPONSE_CLEANUP(Read);
+
 		responsetype = UA_READRESPONSE_NS0;
-	}else if(serviceid == UA_WRITEREQUEST_NS0)
+	}
+	else if (serviceid == UA_WRITEREQUEST_NS0)
 	{
-		INVOKE_SERVICE(Write);
+
+		RESPONSE_PREPARE(Write);
+		DBG_VERBOSE(printf("Finished Service: %s\n", Write));
+		if (UA_Session_verifyChannel(session,channel)){
+			UA_Session_updateLifetime(session); //renew session timeout
+			Service_Write(session,&p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", Write));
+		RESPONSE_CLEANUP(Write);
+
+
 		responsetype = UA_WRITERESPONSE_NS0;
-	}else if(serviceid == UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0) {
-		INVOKE_SERVICE(TranslateBrowsePathsToNodeIds);
-		responsetype = UA_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE_NS0;
-	}else if(serviceid == UA_BROWSEREQUEST_NS0) {
-		INVOKE_SERVICE(Browse);
+	}
+	else if (serviceid == UA_BROWSEREQUEST_NS0)
+	{
+
+		RESPONSE_PREPARE(Browse);
+		DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_Browse(session,&p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", Browse));
+		RESPONSE_CLEANUP(Browse);
+
+
 		responsetype = UA_BROWSERESPONSE_NS0;
-	}else if(serviceid == UA_CREATESUBSCRIPTIONREQUEST_NS0) {
-		INVOKE_SERVICE(CreateSubscription);
+	}
+	else if (serviceid == UA_CREATESUBSCRIPTIONREQUEST_NS0)
+	{
+
+		RESPONSE_PREPARE(CreateSubscription);
+		DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_CreateSubscription(session, &p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", CreateSubscription));
+		RESPONSE_CLEANUP(CreateSubscription);
 		responsetype = UA_CREATESUBSCRIPTIONRESPONSE_NS0;
-	}else if(serviceid == UA_CREATEMONITOREDITEMSREQUEST_NS0) {
-		INVOKE_SERVICE(CreateMonitoredItems);
-		responsetype = UA_CREATEMONITOREDITEMSRESPONSE_NS0;
-	}else if(serviceid == UA_PUBLISHREQUEST_NS0) {
-		INVOKE_SERVICE(Publish);
+	}
+	else if (serviceid == UA_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_NS0)
+	{
+
+		RESPONSE_PREPARE(TranslateBrowsePathsToNodeIds);
+		DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_TranslateBrowsePathsToNodeIds(session, &p, &r);
+		}
+		else
+		{
+				DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", TranslateBrowsePathsToNodeIds));
+		RESPONSE_CLEANUP(TranslateBrowsePathsToNodeIds);
+		responsetype = UA_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE_NS0;
+	}
+	else if (serviceid == UA_PUBLISHREQUEST_NS0)
+	{
+
+		RESPONSE_PREPARE(Publish);
+		DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_Publish(session, &p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", Publish));
+		RESPONSE_CLEANUP(Publish);
 		responsetype = UA_PUBLISHRESPONSE_NS0;
-	}else{
-		printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
-		       serviceRequestType.namespace,
-		       serviceRequestType.identifier.numeric);
+	}
+	else if (serviceid == UA_CREATEMONITOREDITEMSREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(CreateMonitoredItems);
+		DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_CreateMonitoredItems(session, &p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", CreateMonitoredItems));
+		RESPONSE_CLEANUP(CreateMonitoredItems);
+		responsetype = UA_CREATEMONITOREDITEMSRESPONSE_NS0;
+	}
+	else if (serviceid == UA_SETPUBLISHINGMODEREQUEST_NS0)
+	{
+		RESPONSE_PREPARE(SetPublishingMode);
+		DBG_VERBOSE(printf("Finished Service: %s\n",SetPublishingMode));
+		if (UA_Session_verifyChannel(session,channel)){
+			Service_SetPublishingMode(session, &p, &r);
+		}
+		else
+		{
+			DBG_VERBOSE(printf("session does not match secure channel"));
+		}
+		DBG_VERBOSE(printf("Finished Service: %s\n", SetPublishingMode));
+		RESPONSE_CLEANUP(SetPublishingMode);
+		responsetype = UA_SETPUBLISHINGMODERESPONSE_NS0;
+	}
+	else
+	{
+		printf(
+				"SL_processMessage - unknown request, namespace=%d, request=%d\n",
+				serviceRequestType.namespace,
+				serviceRequestType.identifier.numeric);
 		retval = UA_ERROR;
-		UA_RequestHeader  p;
+		UA_RequestHeader p;
 		UA_ResponseHeader r;
-		UA_RequestHeader_decodeBinary(msg, offset, &p);
+
+		UA_RequestHeader_decodeBinary(msg, &recvOffset, &p);
 		UA_ResponseHeader_init(&r);
 		r.requestHandle = p.requestHandle;
 		r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
-		*offset = 0;
+		sendOffset = 0;
 		UA_ByteString_newMembers(&response_msg, UA_ResponseHeader_calcSizeBinary(&r));
-		UA_ResponseHeader_encodeBinary(&r, &response_msg, offset);
+		UA_ResponseHeader_encodeBinary(&r, &response_msg,&sendOffset);
 		responsetype = UA_RESPONSEHEADER_NS0;
 	}
-
-	SL_Send(channel, &response_msg, responsetype);
+	if(serviceid != UA_CLOSESECURECHANNELREQUEST_NS0){
+		SL_Send(channel, &response_msg, responsetype);
+	}
 	UA_ByteString_deleteMembers(&response_msg);
-
+	*pos = recvOffset;
 	return retval;
 }
-/**
- *
- * @param connection
- * @param msg
- * @param offset
- * @return
- */
-UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString *msg, UA_UInt32 *offset) {
-	DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
-	UA_Int32 retval = UA_SUCCESS;
 
-	/* Create New Channel*/
-	SL_Channel *channel = &slc; // FIXME: generate new secure channel
-	UA_AsymmetricAlgorithmSecurityHeader_init(&(channel->localAsymAlgSettings));
-	UA_ByteString_copy(&UA_ByteString_securityPoliceNone,
-	                   &(channel->localAsymAlgSettings.securityPolicyUri));
-	UA_alloc((void **)&(channel->localNonce.data), sizeof(UA_Byte));
-	channel->localNonce.length = 1;
-	channel->connectionState   = CONNECTIONSTATE_CLOSED; // the state of the channel will be opened in the service
-	channel->sequenceHeader.requestId      = 0;
-	channel->sequenceHeader.sequenceNumber = 1;
-	UA_String_init(&(channel->secureChannelId));
-	channel->securityMode = UA_SECURITYMODE_INVALID;
-	channel->securityToken.secureChannelId = 25; //TODO set a valid start secureChannelId number
-	channel->securityToken.tokenId.tokenId = 1;  //TODO set a valid start TokenId
-
-	connection->secureChannel = channel;
-	connection->secureChannel->tlConnection = connection;
-
-	/* Read the OPN message headers */
-	*offset += 4; // skip the securechannelid
-	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(
-	    msg, offset, &connection->secureChannel->remoteAsymAlgSettings);
-	UA_SequenceHeader_decodeBinary(msg, offset, &connection->secureChannel->sequenceHeader);
-	//TODO check that the sequence number is smaller than MaxUInt32 - 1024
-	//TODO check if a OpenSecureChannelRequest follows
-
-	retval |= SL_handleRequest(channel, msg, offset);
-	return retval;
-
-	// FIXME: reject
+UA_Int32 SL_ProcessOpenChannel(SL_Channel channel, const UA_ByteString* msg,
+		UA_UInt32 *pos)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_SequenceHeader sequenceHeader;
+	UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+	*pos+=4; //skip secure channel id
+	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg,pos,&asymHeader);
+	UA_SequenceHeader_decodeBinary(msg,pos,&sequenceHeader);
+
+	//init remote security settings from the security header
+	SL_Channel_setRemoteSecuritySettings(channel,&asymHeader,&sequenceHeader);
+	return SL_handleRequest(channel, msg, pos) | retval;
 }
-
-/**
- * process the rest of the header. TL already processed MessageType
- * (OPN,MSG,...), isFinal and MessageSize. SL_process cares for
- * secureChannelId, XASHeader and sequenceHeader
- * */
-UA_Int32 SL_Process(SL_Channel *connection, const UA_ByteString *msg, UA_UInt32 *offset) {
+UA_Int32 SL_ProcessCloseChannel(SL_Channel channel, const UA_ByteString* msg,
+		UA_UInt32 *pos)
+{
+	return SL_handleRequest(channel, msg, pos);
+}
+UA_Int32 SL_Process(const UA_ByteString* msg,
+		UA_UInt32* pos)
+{
 
 	DBG_VERBOSE(printf("SL_process - entered \n"));
 	UA_UInt32 secureChannelId;
+	UA_UInt32 foundChannelId;
+	SL_Channel channel;
+	UA_SequenceHeader sequenceHeader;
 
-	if(connection->connectionState == CONNECTIONSTATE_ESTABLISHED) {
-		UA_UInt32_decodeBinary(msg, offset, &secureChannelId);
-
-		//FIXME: we assume SAS, need to check if AAS or SAS
-		UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
-		// if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
-		UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, offset, &symAlgSecHeader);
-
-		printf("SL_process - securityToken received=%d, expected=%d\n", secureChannelId,
-		       connection->securityToken.secureChannelId);
-		if(secureChannelId == connection->securityToken.secureChannelId) {
-			UA_SequenceHeader_decodeBinary(msg, offset, &(connection->sequenceHeader));
-			SL_handleRequest(&slc, msg, offset);
-		} else {
-			//TODO generate ERROR_Bad_SecureChannelUnkown
-		}
+
+	UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
+
+	//FIXME: we assume SAS, need to check if AAS or SAS
+	UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
+	// if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
+	UA_SymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos,
+			&symAlgSecHeader);
+
+ 	if (SL_ChannelManager_getChannel(secureChannelId,
+			&channel) == UA_SUCCESS)
+	{
+
+		SL_Channel_getChannelId(channel, &foundChannelId);
+		printf("SL_process - received msg, with channel id: %i \n",
+				foundChannelId);
+
+		//sequence number processing
+		UA_SequenceHeader_decodeBinary(msg, pos,
+				&sequenceHeader);
+		SL_Channel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
+		SL_Channel_checkRequestId(channel,sequenceHeader.requestId);
+		//request id processing
+
+
+		SL_handleRequest(channel, msg, pos);
 	}
+	else
+	{
+		printf("SL_process - ERROR could not find channel with id: %i \n",
+				secureChannelId);
+		//TODO generate ERROR_Bad_SecureChannelUnkown
+	}
+
 	return UA_SUCCESS;
 }

+ 25 - 21
src/ua_transport_binary_secure.h

@@ -3,29 +3,33 @@
 #include "ua_types.h"
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
+#include "ua_stack_channel.h"
+#include "ua_stack_channel_manager.h"
 
-typedef struct {
-	UA_UInt32 secureChannelId;
-	UA_SymmetricAlgorithmSecurityHeader tokenId;
-	UA_DateTime createdAt;
-	UA_Int32 revisedLifetime;
-} SL_ChannelSecurityToken;
+/*inputs for secure Channel which must be provided once
+endPointUrl
+securityPolicyUrl
+securityMode
+revisedLifetime
+*/
 
-typedef struct SL_Channel {
-	UA_String secureChannelId;
-	TL_Connection* tlConnection;
-	Session *session; // equals UA_Null iff no session is active
-	UA_AsymmetricAlgorithmSecurityHeader remoteAsymAlgSettings;
-	UA_AsymmetricAlgorithmSecurityHeader localAsymAlgSettings;
-	UA_SequenceHeader sequenceHeader;
-	UA_UInt32 securityMode;
-	UA_ByteString remoteNonce;
-	UA_ByteString localNonce;
-	UA_UInt32 connectionState;
-	SL_ChannelSecurityToken securityToken;
-} SL_Channel;
+/*inputs for secure Channel Manager which must be provided once
+ maxChannelCount
 
-UA_Int32 SL_Process(SL_Channel* channel, const UA_ByteString* msg, UA_UInt32* offset);
-UA_Int32 SL_Channel_new(TL_Connection *connection, const UA_ByteString* msg, UA_UInt32* offset); // this function is called from the OpenSecureChannel service
+ */
 
+UA_Int32 SL_Process(const UA_ByteString* msg, UA_UInt32* pos);
+
+/**
+ * @brief Wrapper function, to encapsulate handleRequest for openSecureChannel requests
+ * @param channel A secure Channel structure, which receives the information for the new created secure channel
+ * @param msg Message which holds the binary encoded request
+ * @param pos Position in the message at which the request begins
+ * @return Returns UA_SUCCESS if successful executed, UA_ERROR in any other case
+
+ */
+UA_Int32 SL_ProcessOpenChannel(SL_Channel channel, const UA_ByteString* msg,
+		UA_UInt32 *pos);
+UA_Int32 SL_ProcessCloseChannel(SL_Channel channel, const UA_ByteString* msg,
+		UA_UInt32 *pos);
 #endif /* OPCUA_TRANSPORT_BINARY_SECURE_H_ */

+ 178 - 0
src/ua_transport_connection.c

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

+ 51 - 0
src/ua_transport_connection.h

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

+ 84 - 0
src/ua_transport_connection_manager.c

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

+ 20 - 0
src/ua_transport_connection_manager.h

@@ -0,0 +1,20 @@
+/*
+ * ua_connection_manager.h
+ *
+ *  Created on: 11.05.2014
+ *      Author: open62541
+ */
+
+#ifndef UA_CONNECTION_MANAGER_H_
+#define UA_CONNECTION_MANAGER_H_
+#include "stdio.h"
+#include "ua_transport_connection.h"
+
+
+UA_Int32 UA_TL_ConnectionManager_init(UA_UInt32 maxConnectionCount);
+UA_Int32 UA_TL_ConnectionManager_addConnection(UA_TL_Connection *connection);
+UA_Int32 UA_TL_ConnectionManager_removeConnection(UA_TL_Connection connection);
+//getter
+UA_Int32 UA_TL_ConnectionManager_getConnectionByHandle(UA_UInt32 connectionId, UA_TL_Connection *connection);
+
+#endif /* UA_CONNECTION_MANAGER_H_ */

+ 3 - 0
src/ua_types.c

@@ -61,6 +61,8 @@ void UA_Int16_print(const UA_Int16 *p, FILE *stream) {
 }
 #endif
 
+
+
 /* UInt16 */
 UA_TYPE_DEFAULT(UA_UInt16)
 #ifdef DEBUG
@@ -77,6 +79,7 @@ void UA_Int32_print(const UA_Int32 *p, FILE *stream) {
 	if(p == UA_NULL || stream == UA_NULL) return;
 	fprintf(stream, "%d", *p);
 }
+
 #endif
 
 /* UInt32 */

+ 17 - 8
src/ua_types.h

@@ -54,30 +54,39 @@
 /** @brief A two-state logical value (true or false). */
 typedef _Bool UA_Boolean;
 
+
 /** @brief An integer value between −128 and 127. */
 typedef int8_t UA_SByte;
-
+#define UA_SBYTE_MAX -128
+#define UA_SBYTE_MIN 127
 /** @brief An integer value between 0 and 256. */
 typedef uint8_t UA_Byte;
-
+#define UA_BYTE_MAX 256
+#define UA_BYTE_MIN 0
 /** @brief An integer value between −32 768 and 32 767. */
 typedef int16_t UA_Int16;
-
+#define UA_INT16_MAX 32767
+#define UA_INT16_MIN -32768
 /** @brief An integer value between 0 and 65 535. */
 typedef uint16_t UA_UInt16;
-
+#define UA_UINT16_MAX  65535
+#define UA_UINT16_MIN  0
 /** @brief An integer value between −2 147 483 648 and 2 147 483 647. */
 typedef int32_t UA_Int32;
-
+#define UA_INT32_MAX  2147483647
+#define UA_INT32_MIN  −2147483648
 /** @brief An integer value between 0 and 429 4967 295. */
 typedef uint32_t UA_UInt32;
-
+#define UA_UINT32_MAX  4294967295;
+#define UA_UINT32_MIN  0;
 /** @brief An integer value between −9 223 372 036 854 775 808 and 9 223 372 036 854 775 807 */
 typedef int64_t UA_Int64;
-
+#define UA_INT64_MAX  9223372036854775807
+#define UA_INT64_MIN  −9223372036854775808
 /** @brief An integer value between 0 and 18 446 744 073 709 551 615. */
 typedef uint64_t UA_UInt64;
-
+#define UA_UINT64_MAX = 18446744073709551615
+#define UA_UINT64_MIN = 0
 /** @brief An IEEE single precision (32 bit) floating point value. */
 typedef float UA_Float;
 

+ 50 - 33
tests/check_stack.c

@@ -5,6 +5,9 @@
 #include "ua_transport.h"
 #include "ua_transport_binary.h"
 #include "ua_transport_binary_secure.h"
+#include "ua_transport_connection.h"
+#include "ua_stack_channel_manager.h"
+#include "ua_stack_session_manager.h"
 #include "check.h"
 
 #define MAXMSG 512
@@ -17,7 +20,8 @@ typedef struct stackTestFixture {
 	/** @brief the management structure (initialized to point to respMsgBuffer in create */
 	UA_ByteString respMsg;
 	/** @brief the management data structure for the fake connection */
-	TL_Connection connection;
+	UA_TL_Connection connection;
+
 } stackTestFixture;
 
 
@@ -50,23 +54,31 @@ UA_Int32 stackTestFixture_markHandleAsFree(UA_Int32 fixtureHandle) {
 	}
 	return UA_ERR_INVALID_VALUE;
 }
-
+UA_Int32 closerCallback(UA_TL_Connection connection)
+{
+	return UA_SUCCESS;
+}
 /** @brief get a handle to a free slot and create a new stackTestFixture */
-UA_Int32 stackTestFixture_create(TL_Writer writerCallback) {
+UA_Int32 stackTestFixture_create(TL_Writer writerCallback, TL_Closer closerCallback) {
+	UA_String endpointUrl;
+	UA_String_copycstring("no url",&endpointUrl);
+	SL_ChannelManager_init(4,36000,25,22,&endpointUrl);
+	UA_SessionManager_init(4,220000,222);
+
 	UA_UInt32 fixtureHandle = stackTestFixture_getAndMarkFreeHandle();
 	if(fixtureHandle < MAX_FIXTURES) {
 		UA_alloc((void **)&fixtures[fixtureHandle], sizeof(stackTestFixture));
 		stackTestFixture *fixture = fixtures[fixtureHandle];
 		fixture->respMsg.data   = fixture->respMsgBuffer;
 		fixture->respMsg.length = 0;
-		fixture->connection.connectionState = CONNECTIONSTATE_CLOSED;
-		fixture->connection.writerCallback  = writerCallback;
-		fixture->connection.localConf.maxChunkCount   = 1;
-		fixture->connection.localConf.maxMessageSize  = BUFFER_SIZE;
-		fixture->connection.localConf.protocolVersion = 0;
-		fixture->connection.localConf.recvBufferSize  = BUFFER_SIZE;
-		fixture->connection.localConf.recvBufferSize  = BUFFER_SIZE;
-		fixture->connection.connectionHandle = fixtureHandle;
+		TL_Buffer buffer;
+		buffer.maxChunkCount   = 1;
+		buffer.maxMessageSize  = BUFFER_SIZE;
+		buffer.protocolVersion = 0;
+		buffer.recvBufferSize  = BUFFER_SIZE;
+		buffer.recvBufferSize  = BUFFER_SIZE;
+		UA_TL_Connection_new(&fixture->connection,buffer,writerCallback,closerCallback,fixtureHandle,UA_NULL);
+
 	}
 	return fixtureHandle;
 }
@@ -88,8 +100,9 @@ stackTestFixture *stackTestFixture_getFixture(UA_UInt32 fixtureHandle) {
 }
 
 /** @brief write message provided in the gather buffers to the buffer of the fixture */
-UA_Int32 responseMsg(struct TL_Connection *c, UA_ByteString const **gather_buf, UA_Int32 gather_len) {
-	stackTestFixture *fixture = stackTestFixture_getFixture(c->connectionHandle);
+UA_Int32 responseMsg(UA_Int32 connectionHandle, UA_ByteString const **gather_buf, UA_Int32 gather_len) {
+
+	stackTestFixture *fixture = stackTestFixture_getFixture(connectionHandle);
 	UA_Int32  retval    = UA_SUCCESS;
 	UA_UInt32 total_len = 0;
 
@@ -105,7 +118,8 @@ UA_Int32 responseMsg(struct TL_Connection *c, UA_ByteString const **gather_buf,
 }
 
 void indicateMsg(UA_Int32 handle, UA_ByteString *slMessage) {
-	printf("indicate: %d", TL_Process(&(stackTestFixture_getFixture(handle)->connection), slMessage));
+
+	printf("indicate: %d", TL_Process((stackTestFixture_getFixture(handle)->connection), slMessage));
 }
 
 UA_Byte pkt_HEL[] = {
@@ -333,7 +347,7 @@ UA_Byte pkt_MSG_CreateSession[] = {
 
 START_TEST(emptyIndicationShallYieldNoResponse) {
 	// given
-	UA_Int32 handle = stackTestFixture_create(responseMsg);
+	UA_Int32 handle = stackTestFixture_create(responseMsg, closerCallback);
 	UA_ByteString message = { -1, (UA_Byte *)UA_NULL };
 
 	// when
@@ -350,7 +364,7 @@ END_TEST
 
 START_TEST(validHELIndicationShallYieldACKResponse) {
 	// given
-	UA_Int32 handle = stackTestFixture_create(responseMsg);
+	UA_Int32 handle = stackTestFixture_create(responseMsg, closerCallback);
 	UA_ByteString message_001 = { sizeof(pkt_HEL), pkt_HEL };
 
 	// when
@@ -369,20 +383,20 @@ END_TEST
 
 START_TEST(validOpeningSequenceShallCreateChannel) {
 	// given
-	UA_Int32 handle = stackTestFixture_create(responseMsg);
+	UA_Int32 handle = stackTestFixture_create(responseMsg,closerCallback);
 
 	UA_ByteString message_001 = { sizeof(pkt_HEL), pkt_HEL };
 	UA_ByteString message_002 = { sizeof(pkt_OPN), pkt_OPN };
-
+	UA_Int32 connectionState;
 	// when
 	indicateMsg(handle, &message_001);
 	indicateMsg(handle, &message_002);
-
+	UA_TL_Connection_getState(stackTestFixture_getFixture(handle)->connection, &connectionState);
 	// then
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[0], 'O');
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[1], 'P');
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[2], 'N');
-	ck_assert_int_eq(stackTestFixture_getFixture(handle)->connection.connectionState, CONNECTIONSTATE_ESTABLISHED);
+	ck_assert_int_eq(connectionState, CONNECTIONSTATE_ESTABLISHED);
 
 	// finally
 	stackTestFixture_delete(handle);
@@ -391,19 +405,19 @@ END_TEST
 
 START_TEST(validOpeningCloseSequence) {
 	// given
-	UA_Int32 handle = stackTestFixture_create(responseMsg);
+	UA_Int32 handle = stackTestFixture_create(responseMsg,closerCallback);
 
 	UA_ByteString message_001 = { sizeof(pkt_HEL), pkt_HEL };
 	UA_ByteString message_002 = { sizeof(pkt_OPN), pkt_OPN };
 	UA_ByteString message_003 = { sizeof(pkt_CLO), pkt_CLO };
-
+	UA_Int32 connectionState;
 	// when
 	indicateMsg(handle, &message_001);
 	indicateMsg(handle, &message_002);
 	indicateMsg(handle, &message_003);
-
+	UA_TL_Connection_getState(stackTestFixture_getFixture(handle)->connection, &connectionState);
 	// then
-	ck_assert_int_eq(stackTestFixture_getFixture(handle)->connection.connectionState, CONNECTIONSTATE_CLOSE);
+	ck_assert_int_eq(connectionState, CONNECTIONSTATE_CLOSE);
 
 	// finally
 	stackTestFixture_delete(handle);
@@ -412,8 +426,8 @@ END_TEST
 
 START_TEST(validCreateSessionShallCreateSession) {
 	// given
-	UA_Int32 handle = stackTestFixture_create(responseMsg);
-
+	UA_Int32 handle = stackTestFixture_create(responseMsg,closerCallback);
+	SL_Channel channel;
 	UA_ByteString message_001 = { sizeof(pkt_HEL), pkt_HEL };
 	UA_ByteString message_002 = { sizeof(pkt_OPN), pkt_OPN };
 	UA_ByteString message_003 = { sizeof(pkt_MSG_CreateSession), pkt_MSG_CreateSession };
@@ -421,19 +435,21 @@ START_TEST(validCreateSessionShallCreateSession) {
 	// when
 	indicateMsg(handle, &message_001);
 	indicateMsg(handle, &message_002);
-	UA_UInt32 pos = 8;
-	UA_UInt32 secureChannelId =
-	    stackTestFixture_getFixture(handle)->connection.secureChannel->securityToken.secureChannelId;
-	UA_UInt32_encodeBinary(&secureChannelId, &message_003, &pos);
 	indicateMsg(handle, &message_003);
 
 	// then
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[0], 'M');
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[1], 'S');
 	ck_assert_int_eq(stackTestFixture_getFixture(handle)->respMsg.data[2], 'G');
-	ck_assert_ptr_ne(stackTestFixture_getFixture(handle)->connection.secureChannel, UA_NULL);
+
+
+	SL_ChannelManager_getChannel(25,&channel);
+	ck_assert_ptr_ne(channel,UA_NULL);
+
+
 
 	// finally
+	SL_ChannelManager_removeChannel(25);
 	stackTestFixture_delete(handle);
 }
 END_TEST
@@ -466,7 +482,7 @@ START_TEST(UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample) {
 	src.receiverCertificateThumbprint = (UA_String){10, (UA_Byte*)"thumbprint"};
 	src.securityPolicyUri = (UA_String){6, (UA_Byte*)"policy"};
 	src.senderCertificate = (UA_String){8, (UA_Byte*)"tEsT123!"};
-	src.requestId = 99;
+
 	const UA_AsymmetricAlgorithmSecurityHeader srcConst = src;
 
 	UA_AsymmetricAlgorithmSecurityHeader dst;
@@ -482,7 +498,7 @@ START_TEST(UA_AsymmetricAlgorithmSecurityHeader_copyShallWorkOnInputExample) {
 	ck_assert_int_eq(6, dst.securityPolicyUri.length);
 	ck_assert_int_eq('t', dst.senderCertificate.data[0]);
 	ck_assert_int_eq(8, dst.senderCertificate.length);
-	ck_assert_int_eq(99, dst.requestId);
+
 }
 END_TEST
 START_TEST(UA_SecureConversationMessageHeader_copyShallWorkOnInputExample) {
@@ -653,6 +669,7 @@ int main(void) {
 	s  = testSuite();
 	sr = srunner_create(s);
 	//srunner_set_fork_status (sr, CK_NOFORK);
+	//srunner_run_all(sr, CK_NOFORK);
 	srunner_run_all(sr, CK_NORMAL);
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);