Browse Source

Some refactoring.
- Only UA-defined types have UA prefix
- Tcp writer takes array of bytestrings (zero copy gathering)
- Refinement of service layer

Julius Pfrommer 11 years ago
parent
commit
7c41554d0c

+ 3 - 5
examples/src/Makefile.am

@@ -6,16 +6,14 @@ endif
 
 bin_PROGRAMS= $(top_builddir)/bin/exampleServer $(top_builddir)/bin/exampleServerMT $(top_builddir)/bin/exampleServerACPLT
 #__top_builddir__bin_exampleServer_LDFLAGS = -all-static
-__top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
+__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 $(MT_LDADD)
 
-__top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
+__top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerMT_SOURCES = opcuaServerMT.c networklayer.c
 __top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
 
-__top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
+__top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include $(GLOBAL_AM_CFLAGS)
 __top_builddir__bin_exampleServerACPLT_SOURCES = opcuaServerACPLT.c 
 __top_builddir__bin_exampleServerACPLT_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
-
-AM_CFLAGS = $(GLOBAL_AM_CFLAGS)

+ 41 - 30
examples/src/networklayer.c

@@ -14,10 +14,10 @@
 #include "networklayer.h"
 
 NL_Description NL_Description_TcpBinary  = {
-		NL_THREADINGTYPE_SINGLE,
-		NL_CONNECTIONTYPE_TCPV4,
-		NL_MAXCONNECTIONS_DEFAULT,
-		{-1,8192,8192,16384,1}
+	NL_UA_ENCODING_BINARY,
+	NL_CONNECTIONTYPE_TCPV4,
+	NL_MAXCONNECTIONS_DEFAULT,
+	{-1,8192,8192,16384,1}
 };
 
 _Bool NL_connectionComparer(void *p1, void* p2) {
@@ -67,7 +67,7 @@ void* NL_TCP_reader(NL_connection *c) {
 				c->connection.connectionState = connectionState_CLOSE;
 				perror("ERROR reading from socket1");
 			}
-		} while (c->connection.connectionState != connectionState_CLOSE && c->networkLayer->threaded == NL_THREADINGTYPE_PTHREAD);
+		} while (c->connection.connectionState != connectionState_CLOSE);
 	}
 	if (c->connection.connectionState == connectionState_CLOSE) {
 		DBG_VERBOSE(printf("NL_TCP_reader - enter shutdown\n"));
@@ -89,18 +89,37 @@ void* NL_TCP_reader(NL_connection *c) {
 }
 
 /** write to a tcp transport layer connection */
-UA_Int32 NL_TCP_writer(UA_TL_connection* c, UA_ByteString* msg) {
-	DBG_VERBOSE(UA_ByteString_printx("NL_TCP_writer - msg=", msg));
-	int nWritten = 0;
-	while (nWritten < msg->length) {
+UA_Int32 NL_TCP_writer(TL_connection* c, UA_ByteString** gather_buf, UA_UInt32 gather_len) {
+
+	struct iovec iov[gather_len];
+	UA_UInt32 total_len = 0;
+	for(UA_UInt32 i=0;i<gather_len;i++) {
+		iov[i].iov_base = gather_buf[i]->data;
+		iov[i].iov_len = gather_buf[i]->length;
+		total_len += gather_buf[i]->length;
+		DBG_VERBOSE(UA_ByteString_printx("NL_TCP_writer - msg=", gather_buf[i]));
+	}
+
+	struct msghdr message;
+	message.msg_name = 0;
+	message.msg_namelen = 0;
+	message.msg_iov = iov;
+	message.msg_iovlen = gather_len;
+	message.msg_control = 0;
+	message.msg_controllen = 0;
+	
+	UA_UInt32 nWritten = 0;
+	while (nWritten < total_len) {
 		int n=0;
 		do {
 			DBG_VERBOSE(printf("NL_TCP_writer - enter write\n"));
-			n = write(c->connectionHandle, &(msg->data[nWritten]), msg->length-nWritten);
+			n = write(c->connectionHandle, &message, 0);
 			DBG_VERBOSE(printf("NL_TCP_writer - leave write with n=%d,errno={%d,%s}\n",n,errno,strerror(errno)));
 		} while (n == -1L && errno == EINTR);
 		if (n >= 0) {
 			nWritten += n;
+			break;
+			// TODO: handle incompletely send messages
 		} else {
 			// TODO: error handling
 		}
@@ -108,7 +127,7 @@ UA_Int32 NL_TCP_writer(UA_TL_connection* c, UA_ByteString* msg) {
 	return UA_SUCCESS;
 }
 
-void* NL_Connection_init(NL_connection* c, NL_data* tld, UA_Int32 connectionHandle, NL_reader reader, UA_TL_writer writer)
+void* NL_Connection_init(NL_connection* c, NL_data* tld, UA_Int32 connectionHandle, NL_reader reader, TL_writer writer)
 {
 	// connection layer of UA stack
 	c->connection.connectionHandle = connectionHandle;
@@ -132,7 +151,6 @@ void* NL_Connection_init(NL_connection* c, NL_data* tld, UA_Int32 connectionHand
 void* NL_TCP_listen(NL_connection* c) {
 	NL_data* tld = c->networkLayer;
 
-	// UA_String_printf("open62541-server listening at endpoint ",&(tld->endpointUrl));
 	do {
 		DBG_VERBOSE(printf("NL_TCP_listen - enter listen\n"));
 		int retval = listen(c->connection.connectionHandle, tld->tld->maxConnections);
@@ -150,28 +168,25 @@ void* NL_TCP_listen(NL_connection* c) {
 			int newsockfd = accept(c->connection.connectionHandle, (struct sockaddr *) &cli_addr, &cli_len);
 			DBG_VERBOSE(printf("NL_TCP_listen - leave accept\n"));
 			if (newsockfd < 0) {
-				DBG_ERR(printf("UA_TL_TCP_listen - accept returns errno={%d,%s}\n",errno,strerror(errno)));
+				DBG_ERR(printf("TL_TCP_listen - accept returns errno={%d,%s}\n",errno,strerror(errno)));
 				perror("ERROR on accept");
 			} else {
 				DBG_VERBOSE(printf("NL_TCP_listen - new connection on %d\n",newsockfd));
 				NL_connection* cclient;
 				UA_Int32 retval = UA_SUCCESS;
 				retval |= UA_alloc((void**)&cclient,sizeof(NL_connection));
-				NL_Connection_init(cclient, tld, newsockfd, NL_TCP_reader, NL_TCP_writer);
+				NL_Connection_init(cclient, tld, newsockfd, NL_TCP_reader, (TL_writer) NL_TCP_writer);
 				UA_list_addPayloadToBack(&(tld->connections),cclient);
-				if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
-					// TODO: handle retval of pthread_create
 #ifdef MULTITHREADING
 					pthread_create( &(cclient->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_reader, (void*) cclient);
-#endif
-				} else {
+#else
 					NL_TCP_SetNonBlocking(cclient->connection.connectionHandle);
-				}
+#endif
 			}
 		} else {
 			// no action necessary to reject connection
 		}
-	} while (tld->threaded == NL_THREADINGTYPE_PTHREAD);
+	} while (1);
 	return UA_NULL;
 }
 
@@ -269,31 +284,27 @@ UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
 		NL_connection* c;
 		UA_Int32 retval = UA_SUCCESS;
 		retval |= UA_alloc((void**)&c,sizeof(NL_connection));
-		NL_Connection_init(c, tld, newsockfd, NL_TCP_listen, (UA_TL_writer) UA_NULL);
+		NL_Connection_init(c, tld, newsockfd, NL_TCP_listen, (TL_writer) UA_NULL);
 		UA_list_addPayloadToBack(&(tld->connections),c);
-		if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
-			// TODO: handle retval of pthread_create
 #ifdef MULTITHREADING
 			pthread_create( &(c->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_listen, (void*) c);
-#endif
-		} else {
+#else
 			NL_TCP_SetNonBlocking(c->connection.connectionHandle);
-		}
+#endif
 	}
 	return retval;
 }
 
 
 /** checks arguments and dispatches to worker or refuses to init */
-NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded) {
+NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port) {
 	NL_data* nl = UA_NULL;
 	if (tlDesc->connectionType == NL_CONNECTIONTYPE_TCPV4 && tlDesc->encoding == NL_UA_ENCODING_BINARY) {
-		UA_alloc((void**)&nl,sizeof(NL_data));
+		UA_alloc((void**)&nl, sizeof(NL_data));
 		nl->tld = tlDesc;
-		nl->threaded = threaded;
 		FD_ZERO(&(nl->readerHandles));
 		UA_list_init(&(nl->connections));
-		NL_TCP_init(nl,port);
+		NL_TCP_init(nl, port);
 	}
 	return nl;
 }

+ 9 - 19
examples/src/networklayer.h

@@ -1,16 +1,9 @@
-/*
- * networklayer.h
- *
- *  Created on: 04.04.2014
- *      Author: mrt
- */
-
 #ifndef NETWORKLAYER_H_
 #define NETWORKLAYER_H_
 
 #include "opcua.h"
-#include "ua_connection.h"
-#include "ua_transportLayer.h"
+#include "ua_transport.h"
+#include "ua_transport_binary.h"
 #include "ua_list.h"
 
 #ifdef MULTITHREADING
@@ -24,10 +17,12 @@ enum NL_UA_ENCODING_enum {
 	NL_UA_ENCODING_BINARY = 0,
 	NL_UA_ENCODING_XML = 1,
 };
+
 enum NL_CONNECTIONTYPE_enum {
 	NL_CONNECTIONTYPE_TCPV4 = 0,
 	NL_CONNECTIONTYPE_TCPV6 = 1,
 };
+
 typedef struct T_NL_Description {
 	UA_Int32 encoding;
 	UA_Int32 connectionType;
@@ -37,17 +32,11 @@ typedef struct T_NL_Description {
 
 extern NL_Description NL_Description_TcpBinary;
 
-enum NL_THREADINGTYPE_enum {
-	NL_THREADINGTYPE_SINGLE = 0,
-	NL_THREADINGTYPE_PTHREAD = 1,
-};
-
 typedef struct T_NL_data {
 	NL_Description* tld;
 	UA_String endpointUrl;
 	int listenerHandle;
 	pthread_t listenerThreadHandle;
-	UA_Int32 threaded;	// NL_THREADINGTYPE_enum
 	UA_list_List connections;
 	fd_set readerHandles;
 	int maxReaderHandle;
@@ -56,12 +45,13 @@ typedef struct T_NL_data {
 struct T_NL_connection;
 typedef void* (*NL_reader)(struct T_NL_connection *c);
 typedef struct T_NL_connection {
-	UA_TL_connection connection;
+	TL_connection connection;
 	NL_reader reader;
-	pthread_t 	readerThreadHandle;
-	NL_data*    networkLayer;
+	pthread_t readerThreadHandle;
+	NL_data* networkLayer;
 } NL_connection;
 
-NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded);
+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);
+
 #endif /* NETWORKLAYER_H_ */

+ 1 - 1
examples/src/opcuaServer.c

@@ -26,7 +26,7 @@ int pthread_create(pthread_t* newthread, const pthread_attr_t* attr, void *(*sta
 }
 
 int main(int argc, char** argv) {
-	NL_data* nl = NL_init(&NL_Description_TcpBinary,16664,NL_THREADINGTYPE_SINGLE);
+	NL_data* nl = NL_init(&NL_Description_TcpBinary,16664);
 	struct timeval tv = {2, 0}; // 2 seconds
 	NL_msgLoop(nl, &tv,serverCallback,argv[0]);
 }

+ 30 - 25
examples/src/opcuaServerACPLT.c

@@ -1,19 +1,10 @@
-/*
- ============================================================================
- Name : opcuaServer.c
- Author :
- Version :
- Copyright : Your copyright notice
- Description :
- ============================================================================
- */
-
 #include <stdio.h>
 #include <stdlib.h>
-#include <memory.h> // bzero
+#include <memory.h>
 
 #include "opcua.h"
-#include "ua_connection.h"
+#include "ua_transport.h"
+#include "ua_transport_binary.h"
 
 #ifdef LINUX
 
@@ -21,6 +12,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <sys/socketvar.h>
+#include <unistd.h>
 
 void server_init();
 void server_run();
@@ -34,11 +26,11 @@ void server_run();
 int main(void) {
 
 #ifdef LINUX
-	server_init();
-	server_run();
+    server_init();
+    server_run();
 #endif
 
-	return EXIT_SUCCESS;
+return EXIT_SUCCESS;
 
 }
 
@@ -52,19 +44,32 @@ typedef struct T_Server {
 	int newDataToWrite;
 	UA_ByteString writeData;
 } Server;
-
 Server server;
-UA_Int32 server_writer(UA_TL_connection* connection, UA_ByteString* msg) {
-	UA_ByteString_copy(msg,&server.writeData);
+
+UA_Int32 server_writer(TL_connection* connection, UA_ByteString** gather_buf, UA_UInt32 gather_len) {
+	UA_UInt32 total_len = 0;
+	for(UA_UInt32 i=0;i<gather_len;i++) {
+		total_len += gather_buf[i]->length;
+	}
+    UA_ByteString *msg;
+	UA_alloc((void **)&msg, sizeof(UA_ByteString));
+	UA_ByteString_newMembers(msg, total_len);
+
+	UA_UInt32 pos = 0;
+	for(UA_UInt32 i=0;i<gather_len;i++) {
+		memcpy(msg->data+pos, gather_buf[i]->data, gather_buf[i]->length);
+		pos += gather_buf[i]->length;
+	}
+	server.writeData = *msg;
 	server.newDataToWrite = 1;
+	UA_free(msg);
 	return UA_SUCCESS;
 }
 
 void server_run() {
-
-	UA_TL_connection connection;
+	TL_connection connection;
 	connection.connectionState = connectionState_CLOSE;
-	connection.writerCallback = server_writer;
+	connection.writerCallback = (TL_writer)server_writer;
 	connection.localConf.maxChunkCount = 1;
 	connection.localConf.maxMessageSize = BUFFER_SIZE;
 	connection.localConf.protocolVersion = 0;
@@ -87,7 +92,7 @@ void server_run() {
 	}
 
 	/* Initialize socket structure */
-	bzero((void *) &serv_addr, sizeof(serv_addr));
+    memset((void *) &serv_addr, 0, sizeof(serv_addr));
 	portno = PORT;
 	serv_addr.sin_family = AF_INET;
 	serv_addr.sin_addr.s_addr = INADDR_ANY;
@@ -110,7 +115,7 @@ void server_run() {
 	while (listen(sockfd, 5) != -1) {
 		clilen = sizeof(cli_addr);
 		/* Accept actual connection from the client */
-		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
+		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t*) &clilen);
 		if (newsockfd < 0) {
 			perror("ERROR on accept");
 			exit(1);
@@ -120,12 +125,12 @@ void server_run() {
 		/* communication loop */
 		while (connection.connectionState != connectionState_CLOSE) {
 			/* If connection is established then start communicating */
-			bzero(buffer, BUFFER_SIZE);
+            memset(buffer, 0, BUFFER_SIZE);
 
 			n = read(newsockfd, buffer, BUFFER_SIZE);
 
 			if (n > 0) {
-				slMessage.data = buffer;
+                slMessage.data = (UA_Byte*) buffer;
 				slMessage.length = n;
 				UA_ByteString_printx("server_run - received=",&slMessage);
 				TL_process(&connection, &slMessage);

+ 2 - 3
examples/src/opcuaServerMT.c

@@ -10,12 +10,11 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-
+#include <unistd.h>
 #include "networklayer.h"
 
-
 int main(int argc, char** argv) {
-	NL_init(&NL_Description_TcpBinary,16664,NL_THREADINGTYPE_PTHREAD);
+	NL_init(&NL_Description_TcpBinary,16664);
 	while (UA_TRUE) {
 		printf("%s does whatever servers do\n",argv[0]);
 		sleep(2);

+ 1 - 0
include/ua_basictypes.h

@@ -219,6 +219,7 @@ UA_String;
 UA_TYPE_METHOD_PROTOTYPES (UA_String)
 UA_Int32 UA_String_copy(UA_String const * src, UA_String* dst);
 UA_Int32 UA_String_copycstring(char const * src, UA_String* dst);
+UA_Int32 UA_String_copyprintf(char const * fmt, UA_String* dst, ...);
 UA_Int32 UA_String_compare(const UA_String *string1, const UA_String *string2);
 void UA_String_printf(char* label, const UA_String* string);
 void UA_String_printx(char* label, const UA_String* string);

+ 7 - 4
src/Makefile.am

@@ -57,14 +57,17 @@ libopen62541_la_LDFLAGS = -avoid-version -no-undefined
 libopen62541_la_SOURCES = opcua.c\
 						ua_basictypes.c\
 						ua_namespace_0.c\
-						ua_stackInternalTypes.c\
-						ua_transportLayer.c\
-						ua_secureLayer.c\
 						util/ua_list.c\
 						util/ua_indexedList.c\
+						ua_transport.c\
+						ua_transport_binary.c\
+						ua_transport_binary_secure.c\
 						ua_namespace.c\
 						ua_services_attribute.c\
-						ua_services_session.c
+						ua_services_session.c\
+						ua_services_discovery.c\
+						ua_services_securechannel.c
+						ua_services_view.c
 
 #bin_PROGRAMS= $(top_builddir)/bin/open62541.out
 #__top_builddir__bin_libOpen62541_out_SOURCES = opcuaServer.c

+ 0 - 84
src/ua_connection.h

@@ -1,84 +0,0 @@
-#ifndef OPCUA_CONNECTIONHELPER_H_
-#define OPCUA_CONNECTIONHELPER_H_
-
-#include "opcua.h"
-#include "ua_stackInternalTypes.h"
-#include "ua_application.h"
-
-enum UA_MessageType
-{
-	UA_MESSAGETYPE_HEL = 0x48454C, // H E L
-	UA_MESSAGETYPE_ACK = 0x41434B, // A C k
-	UA_MESSAGETYPE_ERR = 0x455151, // E R R
-	UA_MESSAGETYPE_OPN = 0x4F504E, // O P N
-	UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
-	UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
-};
-enum connectionState
-{
-	connectionState_CLOSED,
-	connectionState_OPENING,
-	connectionState_ESTABLISHED,
-	connectionState_CLOSE,
-};
-
-typedef struct
-{
-	UA_UInt32 secureChannelId;
-	UA_SymmetricAlgorithmSecurityHeader tokenId;
-	UA_DateTime createdAt;
-	UA_Int32 revisedLifetime;
-}SL_ChannelSecurityToken;
-
-typedef struct
-{
-	UA_UInt32 protocolVersion;
-	UA_UInt32 sendBufferSize;
-	UA_UInt32 recvBufferSize;
-	UA_UInt32 maxMessageSize;
-	UA_UInt32 maxChunkCount;
-}TL_buffer;
-
-/* Transport Layer Connection */
-struct T_UA_TL_connection;		// forward declaration
-typedef UA_Int32 (*UA_TL_writer)(struct T_UA_TL_connection* c, UA_ByteString* msg);
-
-typedef struct T_UA_TL_connection
-{
-	UA_Int32 connectionHandle;
-	UA_UInt32 connectionState;
-	TL_buffer localConf;
-	UA_TL_writer writerCallback;
-	TL_buffer remoteConf;
-	UA_String localEndpointUrl;
-	UA_String remoteEndpointUrl;
-	struct T_SL_Channel* secureChannel;
-} UA_TL_connection;
-
-typedef struct UA_Session_T {
-	UA_Int32 dummy;
-	UA_Application *application;
-} UA_Session;
-
-/* Secure Layer Channel */
-typedef struct T_SL_Channel
-{
-	UA_String secureChannelId;
-	UA_TL_connection* tlConnection;
-	UA_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;
-	UA_UInt32 requestId; // request Id of the current request
-
-} UA_SL_Channel;
-
-#endif /* OPCUA_CONNECTIONHELPER_H_ */

+ 5 - 5
src/ua_namespace.c

@@ -113,7 +113,7 @@ UA_Int32 insert_node(namespace *ns, UA_Node *node) {
 	return UA_SUCCESS;
 }
 
-UA_Int32 get_node(namespace *ns, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
+UA_Int32 get_node(namespace *ns, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) == UA_SUCCESS) return UA_ERROR;
 #ifdef MULTITHREADING
@@ -124,7 +124,7 @@ UA_Int32 get_node(namespace *ns, UA_NodeId *nodeid, UA_Node ** const result, ns_
 	return UA_SUCCESS;
 }
 
-UA_Int32 get_writable_node(namespace *ns, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
+UA_Int32 get_writable_node(namespace *ns, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
 #ifdef MULTITHREADING
@@ -139,7 +139,7 @@ UA_Int32 get_writable_node(namespace *ns, UA_NodeId *nodeid, UA_Node **result, n
 static inline void release_context_walker(void * lock) { pthread_rwlock_unlock(lock); }
 #endif
 
-UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
+UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
 #ifdef MULTITHREADING
@@ -155,7 +155,7 @@ UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid,
 	return UA_SUCCESS;
 }
 
-UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
+UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
 #ifdef MULTITHREADING
@@ -356,7 +356,7 @@ static void clear_ns(namespace *ns) {
 	ns->count = 0;
 }
 
-static UA_Int32 find_slot (const namespace *ns, ns_entry **slot, UA_NodeId *nodeid) {
+static UA_Int32 find_slot (const namespace *ns, ns_entry **slot, const UA_NodeId *nodeid) {
 	hash_t h = hash(nodeid);
 	hash_t index, hash2;
 	uint32_t size;

+ 13 - 5
src/ua_namespace.h

@@ -51,10 +51,10 @@ UA_Int32 create_ns(namespace **result, uint32_t size);
 void empty_ns(namespace *ns);
 void delete_ns(namespace *ns);
 UA_Int32 insert_node(namespace *ns, UA_Node *node);
-UA_Int32 get_node(namespace *ns, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
-UA_Int32 get_writable_node(namespace *ns, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
-UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
-UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
+UA_Int32 get_node(namespace *ns, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
+UA_Int32 get_writable_node(namespace *ns, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
+UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock);
+UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, const UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock); // use only for _single_ writes.
 
 // inline void release_node(ns_lock *lock);
 // portable solution, see http://www.greenend.org.uk/rjk/tech/inline.html
@@ -76,8 +76,16 @@ static inline hash_t mod(hash_t hash, const namespace *ns);
 static inline hash_t htab_mod_m2(hash_t hash, const namespace *ns);
 static inline void clear_slot(namespace *ns, ns_entry *slot);
 static void clear_ns(namespace *ns);
-static UA_Int32 find_slot(const namespace *ns, ns_entry **slot, UA_NodeId *nodeid);
+static UA_Int32 find_slot(const namespace *ns, ns_entry **slot, const UA_NodeId *nodeid);
 static ns_entry * find_empty_slot(const namespace *ns, hash_t hash);
 static UA_Int32 expand(namespace *ns);
 
+/* We store UA_MethodNode_Callback instead of UA_MethodNode in the namespace.
+   Pointer casting to UA_MethodNode is possible since pointers point to the
+   first element anyway. */
+typedef struct UA_MethodNode_Callback_T {
+	UA_MethodNode *method_node;
+	UA_Int32 (*method_callback)(UA_list_List *input_args, UA_list_List *output_args);
+} UA_MethodNode_Callback;
+
 #endif /* __NAMESPACE_H */

+ 0 - 492
src/ua_secureLayer.c

@@ -1,492 +0,0 @@
-#include <stdio.h>
-#include <memory.h> // memcpy
-#include "opcua.h"
-#include "ua_transportLayer.h"
-#include "ua_secureLayer.h"
-#include "ua_stackInternalTypes.h"
-#include "ua_statuscodes.h"
-#include "ua_services.h"
-
-#define SIZE_SECURECHANNEL_HEADER 12
-#define SIZE_SEQHEADER_HEADER 8
-
-UA_Int32 SL_send(UA_SL_Channel* channel, UA_ByteString const * responseMessage, UA_Int32 type) {
-	UA_UInt32 sequenceNumber;
-	UA_UInt32 requestId;
-	UA_Int32 pos;
-	UA_ByteString responsePacket;
-	UA_Int32 packetSize;
-	UA_Int32 sizePadding;
-	UA_Int32 sizeSignature;
-
-	// FIXME: this is a to dumb method to determine asymmetric algorithm setting
-	UA_Int32 isAsym = (type == 449);
-
-	pos = 0;
-	//sequence header
-	sequenceNumber = channel->sequenceHeader.sequenceNumber;
-	requestId = channel->sequenceHeader.requestId;
-
-	sizePadding = 0;
-	sizeSignature = 0;
-
-	packetSize = SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
-			+ (isAsym ?
-					UA_AsymmetricAlgorithmSecurityHeader_calcSize(
-							&(channel->localAsymAlgSettings)) :
-					UA_SymmetricAlgorithmSecurityHeader_calcSize(
-							&(channel->securityToken.tokenId)))
-			+ responseMessage->length + sizePadding + sizeSignature;
-
-	//get memory for response
-	UA_alloc((void**)&(responsePacket.data), packetSize);
-	responsePacket.length = packetSize;
-
-	/*---encode Secure Conversation Message Header ---*/
-	if (isAsym) {
-		//encode MessageType - OPN message
-		responsePacket.data[0] = 'O';
-		responsePacket.data[1] = 'P';
-		responsePacket.data[2] = 'N';
-	} else {
-		//encode MessageType - MSG message
-		responsePacket.data[0] = 'M';
-		responsePacket.data[1] = 'S';
-		responsePacket.data[2] = 'G';
-	}
-	pos += 3;
-	responsePacket.data[3] = 'F';
-	pos += 1;
-	UA_Int32_encodeBinary(&packetSize, &pos, &responsePacket);
-	UA_UInt32_encodeBinary(&(channel->securityToken.secureChannelId),
-			&pos, &responsePacket);
-
-	/*---encode Algorithm Security Header ---*/
-	if (isAsym) {
-		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(
-				&(channel->localAsymAlgSettings), &pos,
-				&responsePacket);
-	} else {
-		UA_SymmetricAlgorithmSecurityHeader_encodeBinary(
-				&(channel->securityToken.tokenId), &pos,
-				&responsePacket);
-	}
-
-	/*---encode Sequence Header ---*/
-	UA_UInt32_encodeBinary(&sequenceNumber, &pos, &responsePacket);
-	UA_UInt32_encodeBinary(&requestId, &pos, &responsePacket);
-
-	/*---add encoded Message ---*/
-	UA_memcpy(&(responsePacket.data[pos]), responseMessage->data,
-			responseMessage->length);
-
-	/* sign Data*/
-
-	/* encrypt Data*/
-
-	/* send Data */
-	TL_send(channel->tlConnection, &responsePacket);
-	UA_ByteString_deleteMembers(&responsePacket);
-	return UA_SUCCESS;
-}
-
-
-UA_Int32 SL_check(UA_SL_Channel* channel, UA_ByteString* msg) {
-	return UA_NO_ERROR;
-}
-UA_Int32 SL_createSecurityToken(UA_SL_Channel* channel, UA_Int32 lifeTime) {
-	return UA_NO_ERROR;
-}
-
-#define START_HANDLER(TYPE) \
-UA_Int32 UA_SL_handle##TYPE##Request(UA_SL_Channel *channel, void const* request, void* response) { \
-	UA_Int32 retval = UA_SUCCESS; \
-	printf("UA_SL_handle%sRequest\n",#TYPE ); \
-	UA_##TYPE##Request* p = (UA_##TYPE##Request*) request; \
-	UA_##TYPE##Response* r = (UA_##TYPE##Response*) response; \
-
-
-#define END_HANDLER \
-	return retval;	\
-} \
-
-
-START_HANDLER(GetEndpoints)
-	UA_String_printx("endpointUrl=", &(p->endpointUrl));
-
-	r->endpointsSize = 1;
-	UA_Array_new((void**) &(r->endpoints),r->endpointsSize,UA_ENDPOINTDESCRIPTION);
-
-	//Security issues:
-	//The policy should be 'http://opcfoundation.org/UA/SecurityPolicy#None'
-	//FIXME String or ByteString
-	UA_String_copy((UA_String*)&(channel->localAsymAlgSettings.securityPolicyUri),&(r->endpoints[0]->securityPolicyUri));
-	//FIXME hard-coded code
-	r->endpoints[0]->securityMode = UA_MESSAGESECURITYMODE_NONE;
-
-	UA_String_copy(&(channel->tlConnection->localEndpointUrl),&(r->endpoints[0]->endpointUrl));
-	UA_String_copycstring("http://open62541.info/product/release",&(r->endpoints[0]->server.productUri));
-	// FIXME: This information should be provided by the application, preferably in the address space
-	UA_String_copycstring("http://open62541.info/applications/4711",&(r->endpoints[0]->server.applicationUri));
-	UA_LocalizedText_copycstring("The open62541 application",&(r->endpoints[0]->server.applicationName));
-	// FIXME: This should be a feature of the application and an enum
-	r->endpoints[0]->server.applicationType = 0; // Server
-	// all the other strings are empty by initialization
-END_HANDLER
-
-START_HANDLER(CreateSession)
-	 service_createsession(channel, p, r);
-END_HANDLER
-
-START_HANDLER(ActivateSession)
-	 service_activatesession(channel, p, r);
-END_HANDLER
-
-START_HANDLER(CloseSession)
-	 service_closesession(channel, p, r);
-END_HANDLER
-
-START_HANDLER(Browse)
-#pragma GCC diagnostic ignored "-Wunused-variable"
-	UA_NodeId_printf("BrowseService - view=",&(p->view.viewId));
-
-	UA_Int32 i = 0;
-	for (i=0;p->nodesToBrowseSize > 0 && i<p->nodesToBrowseSize;i++) {
-		UA_NodeId_printf("BrowseService - nodesToBrowse=", &(p->nodesToBrowse[i]->nodeId));
-	}
-END_HANDLER
-
-START_HANDLER(Read)
-     // FIXME: Check if session is active 
-	 service_read(channel->session->application, p, r);
-END_HANDLER
-
-START_HANDLER(CreateSubscription)
-
-	// FIXME: Subscription
-#pragma GCC diagnostic ignored "-Wunused-variable"
-
-END_HANDLER
-
-START_HANDLER(CreateMonitoredItems)
-	UA_Int32 i;
-
-	if (p->itemsToCreateSize > 0) {
-		r->resultsSize = p->itemsToCreateSize;
-		UA_Array_new((void**)&(r->results),r->resultsSize,UA_MONITOREDITEMCREATERESULT);
-		for (i=0;p->itemsToCreateSize > 0 && i < p->itemsToCreateSize;i++) {
-			UA_NodeId_printf("CreateMonitoredItems - itemToCreate=",&(p->itemsToCreate[i]->itemToMonitor.nodeId));
-			//FIXME: search the object in the namespace
-			if (p->itemsToCreate[i]->itemToMonitor.nodeId.identifier.numeric == 2253) { // server
-				r->results[i]->statusCode = UA_STATUSCODE_GOOD;
-				r->results[i]->monitoredItemId = 1024;
-			} else {
-				// r->results[i]->statusCode = UA_STATUSCODE_BAD_NODEIDUNKNOWN;
-				r->results[i]->statusCode = -1;
-			}
-		}
-	}
-END_HANDLER
-
-START_HANDLER(SetPublishingMode)
-
-	// FIXME: SetPublishingMode
-#pragma GCC diagnostic ignored "-Wunused-variable"
-
-END_HANDLER
-
-START_HANDLER(Publish)
-
-	// FIXME: Publish
-#pragma GCC diagnostic ignored "-Wunused-variable"
-	UA_Int32 i;
-	for (i = 0; p->subscriptionAcknowledgementsSize >0 && i < p->subscriptionAcknowledgementsSize; i++) {
-		printf("UA_handlePublishRequest - subsAck[%d]={sequence=%d,is=%d}\n", i,
-				p->subscriptionAcknowledgements[i]->sequenceNumber,
-				p->subscriptionAcknowledgements[i]->subscriptionId);
-	}
-END_HANDLER
-
-UA_Int32 UA_SL_handleCloseSecureChannelRequest(UA_SL_Channel *channel, void const * request, void* response) {
-	UA_Int32 retval = UA_SUCCESS;
-	// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
-	channel->connectionState = connectionState_CLOSE;
-	return retval;
-}
-
-START_HANDLER(OpenSecureChannel)
-	if (p->clientProtocolVersion != channel->tlConnection->remoteConf.protocolVersion) {
-		printf("SL_processMessage - error protocol version \n");
-		//TODO ERROR_Bad_ProtocolVersionUnsupported
-	}
-	switch (p->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 (p->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 (p->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
-		r->responseHeader.serviceDiagnostics.encodingMask = 0;
-	} else {
-		r->responseHeader.serviceDiagnostics.encodingMask = 0;
-	}
-
-	r->serverProtocolVersion = channel->tlConnection->localConf.protocolVersion;
-	r->securityToken.channelId = channel->securityToken.secureChannelId;
-	r->securityToken.tokenId = channel->securityToken.tokenId;
-	r->securityToken.revisedLifetime = channel->securityToken.revisedLifetime;
-
-	UA_ByteString_copy(&(channel->localNonce), &(r->serverNonce));
-
-END_HANDLER
-
-typedef struct T_UA_SL_handleRequestTableEntry {
-	UA_Int32 requestNodeId;
-	UA_Int32 requestDataTypeId;
-	UA_Int32 responseNodeId;
-	UA_Int32 responseDataTypeId;
-	UA_Int32 (*handleRequest)(UA_SL_Channel*,void const*,void*);
-} UA_SL_handleRequestTableEntry;
-
-UA_SL_handleRequestTableEntry hrt[] = {
-		{452, UA_CLOSESECURECHANNELREQUEST, 0,   0                            , UA_SL_handleCloseSecureChannelRequest},
-		{446, UA_OPENSECURECHANNELREQUEST , 449, UA_OPENSECURECHANNELRESPONSE , UA_SL_handleOpenSecureChannelRequest},
-		{428, UA_GETENDPOINTSREQUEST      , 431, UA_GETENDPOINTSRESPONSE      , UA_SL_handleGetEndpointsRequest},
-		{461, UA_CREATESESSIONREQUEST     , 464, UA_CREATESESSIONRESPONSE     , UA_SL_handleCreateSessionRequest},
-		{467, UA_ACTIVATESESSIONREQUEST   , 470, UA_ACTIVATESESSIONRESPONSE   , UA_SL_handleActivateSessionRequest},
-		{473, UA_CLOSESESSIONREQUEST      , 476, UA_CLOSESESSIONRESPONSE      , UA_SL_handleCloseSessionRequest},
-		{527, UA_BROWSEREQUEST            , 530, UA_BROWSERESPONSE            , UA_SL_handleBrowseRequest},
-		{631, UA_READREQUEST              , 634, UA_READRESPONSE              , UA_SL_handleReadRequest},
-		{787, UA_CREATESUBSCRIPTIONREQUEST, 790, UA_CREATESUBSCRIPTIONRESPONSE, UA_SL_handleCreateSubscriptionRequest},
-		{751, UA_CREATEMONITOREDITEMSREQUEST,754,UA_CREATEMONITOREDITEMSRESPONSE, UA_SL_handleCreateMonitoredItemsRequest},
-		{799, UA_SETPUBLISHINGMODEREQUEST , 802, UA_SETPUBLISHINGMODERESPONSE , UA_SL_handleSetPublishingModeRequest},
-		{826, UA_PUBLISHREQUEST           , 829, UA_PUBLISHRESPONSE           , UA_SL_handlePublishRequest}
-};
-
-UA_SL_handleRequestTableEntry* getHRTEntry(UA_Int32 methodNodeId) {
-	UA_UInt32 i = 0;
-	for (i=0;i< sizeof(hrt)/sizeof(UA_SL_handleRequestTableEntry);i++) {
-		if (methodNodeId == hrt[i].requestNodeId) {
-			return &hrt[i];
-		}
-	}
-	return UA_NULL;
-}
-
-UA_Int32 UA_ResponseHeader_initFromRequest(UA_RequestHeader const * p, UA_ResponseHeader * r) {
-	r->requestHandle = p->requestHandle;
-	r->serviceResult = UA_STATUSCODE_GOOD;
-	r->stringTableSize = 0;
-	r->timestamp = UA_DateTime_now();
-	return UA_SUCCESS;
-}
-
-/** this function manages all the generic stuff for the request-response game */
-UA_Int32 UA_SL_handleRequest(UA_SL_Channel *channel, UA_ByteString* msg) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 pos = 0;
-
-	// Every Message starts with a NodeID which names the serviceRequestType
-	UA_NodeId serviceRequestType;
-	UA_NodeId_decodeBinary(msg, &pos, &serviceRequestType);
-	UA_NodeId_printf("SL_processMessage - serviceRequestType=", &serviceRequestType);
-
-	UA_SL_handleRequestTableEntry* hrte = getHRTEntry(serviceRequestType.identifier.numeric);
-	if (hrte == UA_NULL) {
-			printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
-					serviceRequestType.namespace,serviceRequestType.identifier.numeric);
-			retval = UA_ERROR;
-	} else {
-		void * requestObj = UA_NULL;
-		void * responseObj = UA_NULL;
-		UA_[hrte->requestDataTypeId].new(&requestObj);
-		UA_[hrte->requestDataTypeId].decodeBinary(msg, &pos, requestObj);
-		if (hrte->responseDataTypeId > 0) {
-			UA_[hrte->responseDataTypeId].new(&responseObj);
-			UA_ResponseHeader_initFromRequest((UA_RequestHeader*)requestObj, (UA_ResponseHeader*)responseObj);
-		}
-		if ((retval = hrte->handleRequest(channel, requestObj, responseObj)) == UA_SUCCESS) {
-			if (hrte->responseDataTypeId > 0) {
-				UA_NodeId responseType;
-				responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
-				responseType.namespace = 0;
-				responseType.identifier.numeric = hrte->responseNodeId;
-
-				UA_ByteString response;
-				UA_ByteString_newMembers(&response, UA_NodeId_calcSize(&responseType) + UA_[hrte->responseDataTypeId].calcSize(responseObj));
-				UA_Int32 pos = 0;
-
-				UA_NodeId_encodeBinary(&responseType, &pos, &response);
-				UA_[hrte->responseDataTypeId].encodeBinary(responseObj, &pos, &response);
-				SL_send(channel, &response, responseType.identifier.numeric);
-
-				UA_NodeId_deleteMembers(&responseType);
-				UA_ByteString_deleteMembers(&response);
-			}
-		} else {
-			// FIXME: send error message
-		}
-		// finally
-		retval |= UA_[hrte->requestDataTypeId].delete(requestObj);
-		if (hrte->responseDataTypeId > 0) {
-			UA_[hrte->responseDataTypeId].delete(responseObj);
-		}
-	}
-	return retval;
-}
-
-// FIXME: we need to associate secure channels with the connection
-UA_SL_Channel slc;
-
-/* inits a connection object for secure channel layer */
-UA_Int32 UA_SL_Channel_init(UA_SL_Channel *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;
-
-	channel->sequenceHeader.requestId = 0;
-	channel->sequenceHeader.sequenceNumber = 1;
-
-	UA_String_init(&(channel->secureChannelId));
-
-	channel->securityMode = UA_SECURITYMODE_INVALID;
-	//TODO set a valid start secureChannelId number
-	channel->securityToken.secureChannelId = 25;
-
-	//TODO set a valid start TokenId
-	channel->securityToken.tokenId = 1;
-
-	return UA_SUCCESS;
-}
-
-UA_Int32 UA_SL_Channel_new(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-
-	UA_SecureConversationMessageHeader secureConvHeader;
-	DBG_VERBOSE(printf("UA_SL_Channel_new - entered\n"));
-
-	// FIXME: generate new secure channel
-	UA_SL_Channel_init(&slc);
-	connection->secureChannel = &slc;
-	connection->secureChannel->tlConnection = connection;
-
-	UA_SecureConversationMessageHeader_decodeBinary(msg, pos, &secureConvHeader);
-	// connection->secureChannel->secureChannelId = secureConvHeader.secureChannelId;
-	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &(connection->secureChannel->remoteAsymAlgSettings));
-	//TODO check that the sequence number is smaller than MaxUInt32 - 1024
-	UA_SequenceHeader_decodeBinary(msg, pos, &(connection->secureChannel->sequenceHeader));
-
-	connection->secureChannel->securityToken.tokenId = 4711;
-
-	UA_ByteString_printf("SL_receive - AAS_Header.ReceiverThumbprint=",
-			&(connection->secureChannel->remoteAsymAlgSettings.receiverCertificateThumbprint));
-	UA_ByteString_printf("SL_receive - AAS_Header.SecurityPolicyUri=",
-			&(connection->secureChannel->remoteAsymAlgSettings.securityPolicyUri));
-	UA_ByteString_printf("SL_receive - AAS_Header.SenderCertificate=",
-			&(connection->secureChannel->remoteAsymAlgSettings.senderCertificate));
-	printf("UA_SL_Channel_new - SequenceHeader.RequestId=%d\n",connection->secureChannel->sequenceHeader.requestId);
-	printf("UA_SL_Channel_new - SequenceHeader.SequenceNr=%d\n",connection->secureChannel->sequenceHeader.sequenceNumber);
-	printf("UA_SL_Channel_new - SecurityToken.tokenID=%d\n",connection->secureChannel->securityToken.tokenId);
-
-// FIXME: reject
-//	if (secureConvHeader.secureChannelId != 0) {
-//		UA_Int32 iTmp = UA_ByteString_compare(
-//								&(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
-//								&(asymAlgSecHeader.senderCertificate));
-//				if (iTmp != UA_EQUAL) {
-//					printf("SL_receive - UA_ERROR_BadSecureChannelUnknown \n");
-//					//TODO return UA_ERROR_BadSecureChannelUnknown
-//				}
-//			} else {
-//				//TODO invalid securechannelId
-//			}
-
-	UA_ByteString slMessage;
-	slMessage.data  = &(msg->data[*pos]);
-	slMessage.length = msg->length - *pos;
-	retval |= UA_SL_handleRequest(connection->secureChannel, &slMessage);
-	return retval;
-}
-
-/**
- * process the rest of the header. TL already processed
- * MessageType (OPN,MSG,...), isFinal and MessageSize.
- * UA_SL_process cares for secureChannelId, XASHeader and sequenceHeader
- *
- * */
-UA_Int32 UA_SL_process(UA_SL_Channel* connection, UA_ByteString* msg, UA_Int32* pos) {
-
-	DBG_VERBOSE(printf("UA_SL_process - entered \n"));
-	UA_UInt32 secureChannelId;
-
-	if (connection->connectionState == connectionState_ESTABLISHED) {
-		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);
-//		} else {
-//			// FIXME:
-//		}
-
-		printf("UA_SL_process - securityToken received=%d, expected=%d\n",secureChannelId,connection->securityToken.secureChannelId);
-		if (secureChannelId == connection->securityToken.secureChannelId) {
-			UA_SequenceHeader_decodeBinary(msg, pos, &(connection->sequenceHeader));
-			// process message
-			UA_ByteString slMessage;
-			slMessage.data = &(msg->data[*pos]);
-			slMessage.length = msg->length - *pos;
-			UA_SL_handleRequest(&slc, &slMessage);
-		} else {
-			//TODO generate ERROR_Bad_SecureChannelUnkown
-		}
-	}
-	return UA_SUCCESS;
-}

+ 0 - 13
src/ua_secureLayer.h

@@ -1,13 +0,0 @@
-#ifndef OPCUA_SECURECHANNELLAYER_H_
-#define OPCUA_SECURECHANNELLAYER_H_
-#include "opcua.h"
-#include "ua_connection.h"
-#include "ua_stackInternalTypes.h"
-
-UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection);
-UA_Int32 SL_openSecureChannel_responseMessage_get(UA_SL_Channel *connection,
-UA_SL_Response *response, UA_Int32* sizeInOut);
-UA_Int32 UA_SL_process(UA_SL_Channel* channel, UA_ByteString* msg, UA_Int32* pos);
-UA_Int32 UA_SL_Channel_new(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32* pos);
-
-#endif /* OPCUA_SECURECHANNELLAYER_H_ */

+ 38 - 38
src/ua_services.h

@@ -4,63 +4,63 @@
 #include "opcua.h"
 #include "ua_application.h"
 #include "ua_statuscodes.h"
-#include "ua_transportLayer.h"
+#include "ua_transport_binary_secure.h"
 
 /* Part 4: 5.4 Discovery Service Set */
-// service_findservers
-// service_getendpoints
-// service_registerserver
+// Service_FindServers
+UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response);
+// Service_RegisterServer
 
 /* Part 4: 5.5 SecureChannel Service Set */
-// service_opensecurechannel
-// service_closesecurechannel
+UA_Int32 Service_OpenSecureChannel(SL_Channel *channel, const UA_OpenSecureChannelRequest* request, UA_OpenSecureChannelResponse* response);
+UA_Int32 Service_CloseSecureChannel(SL_Channel *channel, const UA_CloseSecureChannelRequest *request, UA_CloseSecureChannelResponse *response);
 
 /* Part 4: 5.6 Session Service Set */
-UA_Int32 service_createsession(UA_SL_Channel *channel, UA_CreateSessionRequest *request, UA_CreateSessionResponse *response);
-UA_Int32 service_activatesession(UA_SL_Channel *channel, UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response);
-UA_Int32 service_closesession(UA_SL_Channel *channel, UA_CloseSessionRequest *request, UA_CloseSessionResponse *response);
-// service_cancel
+UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response);
+UA_Int32 Service_ActivateSession(SL_Channel *channel, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response);
+UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response);
+// Service_Cancel
 
 /* Part 4: 5.7 NodeManagement Service Set */
-// service_addnodes
-// service_addreferences
-// service_deletenodes
-// service_deletereferences
+// Service_AddNodes
+// Service_AddReferences
+// Service_DeleteNodes
+// Service_DeleteReferences
 
 /* Part 4: 5.8 View Service Set */
-// service_browse
-// service_browsenext
-// service_translatebrowsepathstonodeids
-// service_registernodes
-// service_unregisternodes
+UA_Int32 Service_Browse(SL_Channel *channel, const UA_BrowseRequest *request, UA_BrowseResponse *response);
+// Service_BrowseNext
+// Service_TranslateBrowsePathsRoNodeIds
+// Service_RegisterNodes
+// Service_UnregisterNodes
 
 /* Part 4: 5.9 Query Service Set */
-// service_queryfirst
-// service_querynext
+// Service_QueryFirst
+// Service_QueryNext
 
 /* Part 4: 5.10 Attribute Service Set */
-UA_Int32 service_read(UA_Application *app, UA_ReadRequest *request, UA_ReadResponse *response);
-// service_historyread;
-// service_write;
-// service_historyupdate;
+UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_ReadResponse *response);
+// Service_HistoryRead;
+// Service_Write;
+// Service_HistoryUpdate;
 
 /* Part 4: 5.11 Method Service Set */
-// service_call
+// Service_Call
 
 /* Part 4: 5.12 MonitoredItem Service Set */
-// service_createmonitoreditems
-// service_modifymonitoreditems
-// service_setmonitoringmode
-// service_settriggering
-// service_deletemonitoreditems
+// Service_CreateMonitoredItems
+// Service_ModifyMonitoredItems
+// Service_SetMonitoringMode
+// Service_SetTriggering
+// Service_DeleteMonitoredItems
 
 /* Part 4: 5.13 Subscription Service Set */
-// service_createsubscription
-// service_modifysubscription
-// service_setpublishingmode
-// service_publish
-// service_republish
-// service_transfersubscription
-// service_deletesubscription
+// Service_CreateSubscription
+// Service_ModifySubscription
+// Service_SetPublishingMode
+// Service_Publish
+// Service_Republish
+// Service_TransferSubscription
+// Service_DeleteSubscription
 
 #endif

+ 6 - 10
src/ua_services_attribute.c

@@ -25,12 +25,11 @@ enum UA_AttributeId {
 	UA_ATTRIBUTEID_USEREXECUTABLE = 22
 };
 
-static UA_DataValue * service_read_node(UA_Application *app, UA_ReadValueId *id) {
+static UA_DataValue * service_read_node(UA_Application *app, const UA_ReadValueId *id) {
 	UA_DataValue *v;
 	UA_alloc((void **) &v, sizeof(UA_DataValue));
 	
-	UA_NodeId *nodeid = &id->nodeId;
-	namespace *ns = UA_indexedList_findValue(app->namespaces, nodeid->namespace);
+	namespace *ns = UA_indexedList_findValue(app->namespaces, id->nodeId.namespace);
 
 	if (ns == UA_NULL) {
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
@@ -40,7 +39,7 @@ static UA_DataValue * service_read_node(UA_Application *app, UA_ReadValueId *id)
 	
 	UA_Node *node = UA_NULL;
 	ns_lock *lock = UA_NULL;
-	UA_Int32 result = get_node(ns, nodeid, &node, &lock);
+	UA_Int32 result = get_node(ns, &id->nodeId, &node, &lock);
 	if(result != UA_SUCCESS) {
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
 		v->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
@@ -151,17 +150,14 @@ static UA_DataValue * service_read_node(UA_Application *app, UA_ReadValueId *id)
 	return v;
 }
 
-UA_Int32 service_read(UA_Application *app, UA_ReadRequest *request, UA_ReadResponse *response ) {
-	if(app == UA_NULL) {
-		return UA_ERROR; // TODO: Return error message
-	}
+UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_ReadResponse *response ) {
+	if(channel->application == UA_NULL) return UA_ERROR; // TODO: Return error message
 
-	UA_alloc((void **)response, sizeof(UA_ReadResponse));
 	int readsize = request->nodesToReadSize > 0 ? request->nodesToReadSize : 0;
 	response->resultsSize = readsize;
 	UA_alloc((void **)&response->results, sizeof(void *)*readsize);
 	for(int i=0;i<readsize;i++) {
-		response->results[i] = service_read_node(app, request->nodesToRead[i]);
+		response->results[i] = service_read_node(channel->application, request->nodesToRead[i]);
 	}
 	response->diagnosticInfosSize = -1;
 	return UA_SUCCESS;

+ 25 - 0
src/ua_services_discovery.c

@@ -0,0 +1,25 @@
+#include "ua_services.h"
+UA_Int32 Service_GetEndpoints(SL_Channel *channel, const UA_GetEndpointsRequest* request, UA_GetEndpointsResponse *response) {
+	UA_String_printx("endpointUrl=", &(request->endpointUrl));
+
+	response->endpointsSize = 1;
+	UA_Array_new((void**) &(response->endpoints),response->endpointsSize,UA_ENDPOINTDESCRIPTION);
+
+	//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));
+	//FIXME hard-coded code
+	response->endpoints[0]->securityMode = UA_MESSAGESECURITYMODE_NONE;
+
+	UA_String_copy(&(channel->tlConnection->localEndpointUrl),&(response->endpoints[0]->endpointUrl));
+	UA_String_copycstring("http://open62541.info/product/release",&(response->endpoints[0]->server.productUri));
+	// FIXME: This information should be provided by the application, preferably in the address space
+	UA_String_copycstring("http://open62541.info/applications/4711",&(response->endpoints[0]->server.applicationUri));
+	UA_LocalizedText_copycstring("The open62541 application",&(response->endpoints[0]->server.applicationName));
+	// FIXME: This should be a feature of the application and an enum
+	response->endpoints[0]->server.applicationType = UA_APPLICATIONTYPE_SERVER;
+	// all the other strings are empty by initialization
+	
+	return UA_SUCCESS;
+}

+ 74 - 0
src/ua_services_securechannel.c

@@ -0,0 +1,74 @@
+#include "ua_services.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;
+	response->securityToken.revisedLifetime = channel->securityToken.revisedLifetime;
+
+	UA_ByteString_copy(&(channel->localNonce), &(response->serverNonce));
+	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;
+}

+ 3 - 7
src/ua_services_session.c

@@ -1,6 +1,6 @@
 #include "ua_services.h"
 
-UA_Int32 service_createsession(UA_SL_Channel *channel, UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
+UA_Int32 Service_CreateSession(SL_Channel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) {
 	UA_String_printf("CreateSession Service - endpointUrl=", &(request->endpointUrl));
 	// FIXME: create session
 	response->sessionId.encodingByte = UA_NODEIDTYPE_FOURBYTE;
@@ -9,22 +9,18 @@ UA_Int32 service_createsession(UA_SL_Channel *channel, UA_CreateSessionRequest *
 	return UA_SUCCESS;
 }
 
-UA_Int32 service_activatesession(UA_SL_Channel *channel, UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response) {
+UA_Int32 Service_ActivateSession(SL_Channel *channel, const UA_ActivateSessionRequest *request, UA_ActivateSessionResponse *response) {
 	// FIXME: activate session
 	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));
-
 	// FIXME: channel->application = <Application Ptr>
-	
 	return UA_SUCCESS;
 }
 
-UA_Int32 service_closesession(UA_SL_Channel *channel, UA_CloseSessionRequest *request, UA_CloseSessionResponse *response) {
-
+UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest *request, UA_CloseSessionResponse *response) {
 	channel->session = UA_NULL;
 	// FIXME: set response
-	
 	return UA_SUCCESS;
 }

+ 9 - 0
src/ua_services_view.c

@@ -0,0 +1,9 @@
+#include "ua_services.h"
+
+UA_Int32 Service_Read(SL_Channel *channel, const UA_ReadRequest *request, UA_ReadResponse *response) {
+	UA_NodeId_printf("BrowseService - view=",&(p->view.viewId));
+	UA_Int32 i = 0;
+	for (i=0;p->nodesToBrowseSize > 0 && i<p->nodesToBrowseSize;i++) {
+		UA_NodeId_printf("BrowseService - nodesToBrowse=", &(p->nodesToBrowse[i]->nodeId));
+	}
+}

+ 1 - 1
src/ua_stackInternalTypes.c

@@ -1,4 +1,4 @@
-#include "ua_stackInternalTypes.h"
+#include "ua_transport.h"
 #include "stdio.h"
 
 UA_Int32 UA_MessageType_calcSize(UA_MessageType const * ptr){

+ 26 - 5
src/ua_stackInternalTypes.h

@@ -1,10 +1,23 @@
 #ifndef OPCUA_STACKINTERNALTYPES_H_
 #define OPCUA_STACKINTERNALTYPES_H_
 
+#include "ua_application.h"
 #include "opcua.h"
 
 static const UA_Int32 SL_HEADER_LENGTH = 0;
 
+enum connectionState {
+	connectionState_CLOSED,
+	connectionState_OPENING,
+	connectionState_ESTABLISHED,
+	connectionState_CLOSE,
+};
+
+typedef struct Session_T {
+	UA_Int32 dummy;
+	UA_Application *application;
+} UA_Session;
+
 /* Enums */
 typedef enum {
 	UA_SECURITYTOKEN_ISSUE = 0,
@@ -15,19 +28,27 @@ typedef enum {
 	UA_SECURITYMODE_INVALID = 0,
 	UA_SECURITYMODE_SIGN = 1,
 	UA_SECURITYMODE_SIGNANDENCRYPT = 2
-
-} securityMode;
+} SecurityMode;
 
 /* Structures */
-typedef struct T_SL_Response {
+typedef struct SL_Response_T {
 	UA_UInt32 serverProtocolVersion;
 	UA_ChannelSecurityToken securityToken;
 	UA_String serverNonce;
-}UA_SL_Response;
-UA_TYPE_METHOD_PROTOTYPES(UA_SL_Response)
+} SL_Response;
+UA_TYPE_METHOD_PROTOTYPES(SL_Response)
 
 /* MessageType */
 typedef UA_Int32 UA_MessageType;
+enum UA_MessageType
+{
+	UA_MESSAGETYPE_HEL = 0x48454C, // H E L
+	UA_MESSAGETYPE_ACK = 0x41434B, // A C k
+	UA_MESSAGETYPE_ERR = 0x455151, // E R R
+	UA_MESSAGETYPE_OPN = 0x4F504E, // O P N
+	UA_MESSAGETYPE_MSG = 0x4D5347, // M S G
+	UA_MESSAGETYPE_CLO = 0x434C4F  // C L O
+};
 UA_Int32 UA_MessageType_calcSize(UA_MessageType const * ptr);
 UA_Int32 UA_MessageType_encodeBinary(UA_MessageType const * src, UA_Int32* pos, UA_ByteString* dst);
 UA_Int32 UA_MessageType_decodeBinary(UA_ByteString const * src, UA_Int32* pos, UA_MessageType* dst);

+ 0 - 106
src/ua_transportLayer.h

@@ -1,106 +0,0 @@
-/*
- * ua_transportLayer.h
- *
- *  Created on: Dec 19, 2013
- *      Author: opcua
- */
-
-#ifndef OPCUA_TRANSPORTLAYER_H_
-#define OPCUA_TRANSPORTLAYER_H_
-#include <stdio.h>
-
-#include "opcua.h"
-#include "ua_connection.h"
-#include "ua_stackInternalTypes.h"
-
-/*------------------Defined Error Codes------------------*/
-//transport errors begin at 1000
-#define UA_ERROR_MULTIPLE_HEL 1000
-#define UA_ERROR_RCV_ERROR 1001
-
-
-/*------------------Defined Lengths------------------*/
-#define SIZE_OF_ACKNOWLEDGE_MESSAGE 28
-
-//constants
-static const UA_UInt32 TL_HEADER_LENGTH = 8;
-static const UA_UInt32 TL_MESSAGE_TYPE_LEN = 3;
-static const UA_UInt32 TL_RESERVED_LEN = 1;
-
-//variables which belong to layer
-#define TL_SERVER_PROTOCOL_VERSION  0
-#define TL_SERVER_MAX_CHUNK_COUNT 1
-#define  TL_SERVER_MAX_MESSAGE_SIZE  8192
-
-enum TL_messageType_td
-{
-	TL_MESSAGETYPE_HEL = 1,
-	TL_MESSAGETYPE_ACK = 2,
-	TL_MESSAGETYPE_ERR = 3,
-	TL_MESSAGETYPE_OPN = 4,
-	TL_MESSAGETYPE_CLO = 5,
-	TL_MESSAGETYPE_MSG = 6
-}TL_messageType;
-
-struct TL_header
-{
-	UA_UInt32 MessageType;
-	UA_Byte Reserved;
-	UA_UInt32 MessageSize;
-};
-struct TL_message
-{
-	struct TL_header Header;
-	char *message;
-};
-
-struct TL_messageBodyHEL
-{
-	UA_UInt32 ProtocolVersion;
-	UA_UInt32 ReceiveBufferSize;
-	UA_UInt32 SendBufferSize;
-	UA_UInt32 MaxMessageSize;
-	UA_UInt32 MaxChunkCount;
-	UA_String EndpointUrl;
-};
-
-struct TL_messageBodyACK
-{
-	UA_UInt32 ProtocolVersion;
-	UA_UInt32 ReceiveBufferSize;
-	UA_UInt32 SendBufferSize;
-	UA_UInt32 MaxMessageSize;
-	UA_UInt32 MaxChunkCount;
-	UA_String EndpointUrl;
-};
-
-struct TL_messageBodyERR
-{
-	UA_UInt32 Error;
-	UA_String Reason;
-
-};
-//functions
-/**
- *
- * @param connection connection object
- * @param TL_message
- * @return
- */
-enum UA_TL_CHECK_enum {
-	UA_TL_CHECK_LOCAL = 0,
-	UA_TL_CHECK_REMOTE = 1
-};
-UA_Int32 TL_check(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 local);
-/**
- *
- * @param connection
- * @param TL_message
- */
-UA_Int32 TL_receive(UA_TL_connection *connection,UA_ByteString *packet);
-UA_Int32 TL_send(UA_TL_connection *connection, UA_ByteString *packet);
-UA_Int32 TL_getPacketType(UA_ByteString *packet, UA_Int32 *pos);
-UA_Int32 TL_process(UA_TL_connection *connection, UA_ByteString *packet);
-
-
-#endif /* OPCUA_TRANSPORTLAYER_H_ */

+ 37 - 65
src/ua_transportLayer.c

@@ -1,38 +1,22 @@
-#include <memory.h> // memset, memcpy
-#include "ua_connection.h"
-#include "ua_transportLayer.h"
+#include <memory.h>
+#include "ua_transport_binary.h"
+#include "ua_transport.h"
+#include "ua_transport_binary_secure.h"
 
-#include "ua_secureLayer.h" // SL_process
-
-UA_Int32 TL_check(UA_TL_connection* connection, UA_ByteString* msg, int checkLocal)
-{
-	UA_Int32 retval = UA_SUCCESS;
-
-	UA_Int32 position = 4;
-	UA_Int32 messageLength;
-
-	DBG_VERBOSE(printf("TL_check - entered \n"));
-
-	UA_Int32_decodeBinary(msg,&position,&messageLength);
-	DBG_VERBOSE(printf("TL_check - messageLength = %d \n",messageLength));
-
-	if (messageLength == -1 || messageLength != msg->length ||
-			( ( checkLocal == UA_TL_CHECK_LOCAL) && messageLength > (UA_Int32) connection->localConf.maxMessageSize) ||
-			( ( checkLocal == UA_TL_CHECK_REMOTE) && messageLength > (UA_Int32) connection->remoteConf.maxMessageSize))
-	{
+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"));
-		retval = UA_ERR_INCONSISTENT;
+		return UA_ERR_INCONSISTENT;
 	}
-	return retval;
+	return UA_SUCCESS;
 }
 
-#define Cmp3Byte(data,pos,a,b,c) (*((Int32*) ((data)+(pos))) & 0xFFFFFF) == (Int32)(((Byte)(a))|((Byte)(b))<<8|((Byte)(c))<<16)
-
-UA_Int32 UA_TL_handleHello(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
+UA_Int32 TL_handleHello(TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
 	UA_Int32 retval = UA_SUCCESS;
 
 	UA_Int32 tmpPos = 0;
 	UA_ByteString tmpMessage;
+	UA_ByteString *tmpMessage_ptr = &tmpMessage;
 	UA_OPCUATcpHelloMessage helloMessage;
 	UA_OPCUATcpAcknowledgeMessage ackMessage;
 	UA_OPCUATcpMessageHeader ackHeader;
@@ -76,46 +60,34 @@ UA_Int32 UA_TL_handleHello(UA_TL_connection* connection, UA_ByteString* msg, UA_
 		UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage,&tmpPos,&tmpMessage);
 
 		DBG_VERBOSE(printf("TL_process - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos));
-		TL_send(connection, &tmpMessage);
+		TL_send(connection, &tmpMessage_ptr, 1);
 		UA_ByteString_deleteMembers(&tmpMessage);
-	}
-	else
-	{
+	} else {
 		DBG_ERR(printf("TL_process - wrong connection state \n"));
 		retval = UA_ERROR_MULTIPLE_HEL;
 	}
 	return retval;
 }
 
-UA_Int32 UA_TL_handleOpen(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-
+UA_Int32 TL_handleOpen(TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
 	if (connection->connectionState == connectionState_ESTABLISHED) {
-		// create new secure channel and associate with this TL connection
-		retval |= UA_SL_Channel_new(connection,msg,pos);
-	} else {
-		retval = UA_ERR_INVALID_VALUE;
+		return SL_Channel_new(connection,msg,pos); // create new secure channel and associate with this TL connection
 	}
-	return retval;
+	return UA_ERR_INVALID_VALUE;
 }
 
-UA_Int32 UA_TL_handleMsg(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_SL_Channel* slc = connection->secureChannel;
-	retval |= UA_SL_process(slc,msg,pos);
-	return retval;
+UA_Int32 TL_handleMsg(TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
+	SL_Channel* slc = connection->secureChannel;
+	return SL_process(slc,msg,pos);
 }
 
-UA_Int32 UA_TL_handleClo(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
-	UA_Int32 retval = UA_SUCCESS;
-	UA_SL_Channel* slc = connection->secureChannel;
-	retval |= UA_SL_process(slc,msg,pos);
+UA_Int32 TL_handleClo(TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
+	SL_Channel* slc = connection->secureChannel;
 	connection->connectionState = connectionState_CLOSE;
-	return retval;
+	return SL_process(slc,msg,pos);
 }
 
-UA_Int32 TL_process(UA_TL_connection* connection, UA_ByteString* msg)
-{
+UA_Int32 TL_process(TL_connection* connection, UA_ByteString* msg) {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 pos = 0;
 	UA_OPCUATcpMessageHeader tcpMessageHeader;
@@ -126,16 +98,16 @@ UA_Int32 TL_process(UA_TL_connection* connection, UA_ByteString* msg)
 		printf("TL_process - messageType=%.*s\n",3,msg->data);
 		switch(tcpMessageHeader.messageType) {
 		case UA_MESSAGETYPE_HEL:
-			retval = UA_TL_handleHello(connection, msg, &pos);
+			retval = TL_handleHello(connection, msg, &pos);
 			break;
 		case UA_MESSAGETYPE_OPN:
-			retval = UA_TL_handleOpen(connection, msg, &pos);
+			retval = TL_handleOpen(connection, msg, &pos);
 			break;
 		case UA_MESSAGETYPE_MSG:
-			retval = UA_TL_handleMsg(connection, msg, &pos);
+			retval = TL_handleMsg(connection, msg, &pos);
 			break;
 		case UA_MESSAGETYPE_CLO:
-			retval = UA_TL_handleClo(connection, msg, &pos);
+			retval = TL_handleClo(connection, msg, &pos);
 			break;
 		default: // dispatch processing to secureLayer
 			retval = UA_ERR_INVALID_VALUE;
@@ -145,8 +117,9 @@ UA_Int32 TL_process(UA_TL_connection* connection, UA_ByteString* msg)
 	if (retval != UA_SUCCESS) {
 		// FIXME: compose real error message
 		UA_ByteString errorMsg;
+		UA_ByteString *errorMsg_ptr = &errorMsg;
 		UA_ByteString_newMembers(&errorMsg,10);
-		TL_send(connection,&errorMsg);
+		TL_send(connection,&errorMsg_ptr, 1);
 		UA_ByteString_deleteMembers(&errorMsg);
 	}
 	UA_OPCUATcpMessageHeader_deleteMembers(&tcpMessageHeader);
@@ -154,18 +127,17 @@ UA_Int32 TL_process(UA_TL_connection* connection, UA_ByteString* msg)
 }
 
 /** respond to client request */
-UA_Int32 TL_send(UA_TL_connection* connection, UA_ByteString* msg)
-{
+UA_Int32 TL_send(TL_connection* connection, 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,UA_TL_CHECK_REMOTE) == UA_SUCCESS) {
-		connection->writerCallback(connection,msg);
-	}
-	else
-	{
-		DBG_ERR(printf("TL_send - ERROR: packet size greater than remote buffer size"));
-		retval = UA_ERROR;
-	}
+	//	if (TL_check(connection,msg,TL_CHECK_REMOTE) == UA_SUCCESS) {
+	retval = connection->writerCallback(connection, gather_buf, gather_len);
+		//}
+	/* else */
+	/* { */
+	/* 	DBG_ERR(printf("TL_send - ERROR: packet size greater than remote buffer size")); */
+	/* 	retval = UA_ERROR; */
+	/* } */
 	return retval;
 }

+ 44 - 0
src/ua_transport_binary.h

@@ -0,0 +1,44 @@
+#ifndef OPCUA_TRANSPORT_BINARY_H_
+#define OPCUA_TRANSPORT_BINARY_H_
+#include <stdio.h>
+
+#include "opcua.h"
+#include "ua_transport_binary.h"
+
+//transport errors begin at 1000
+#define UA_ERROR_MULTIPLE_HEL 1000
+#define UA_ERROR_RCV_ERROR 1001
+
+//variables which belong to layer
+#define TL_SERVER_PROTOCOL_VERSION  0
+#define TL_SERVER_MAX_CHUNK_COUNT 1
+#define TL_SERVER_MAX_MESSAGE_SIZE  8192
+
+typedef struct {
+	UA_UInt32 protocolVersion;
+	UA_UInt32 sendBufferSize;
+	UA_UInt32 recvBufferSize;
+	UA_UInt32 maxMessageSize;
+	UA_UInt32 maxChunkCount;
+} TL_buffer;
+
+/* Transport Layer Connection */
+struct TL_connection_T; // forward declaration
+typedef UA_Int32 (*TL_writer)(struct TL_connection_T* connection, UA_ByteString** gather_bufs, UA_Int32 gather_len); // send mutiple buffer concatenated into one msg (zero copy)
+
+typedef struct TL_connection_T {
+	UA_Int32 connectionHandle;
+	UA_UInt32 connectionState;
+	TL_buffer localConf;
+	TL_writer writerCallback;
+	TL_buffer remoteConf;
+	UA_String localEndpointUrl;
+	UA_String remoteEndpointUrl;
+	struct SL_Channel_T* secureChannel;
+} TL_connection;
+
+UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg);
+UA_Int32 TL_send(TL_connection* connection, UA_ByteString** gather_buf, UA_UInt32 gather_len);
+UA_Int32 TL_process(TL_connection *connection, UA_ByteString *packet);
+
+#endif /* OPCUA_TRANSPORT_BINARY_H_ */

+ 250 - 0
src/ua_transport_binary_secure.c

@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <memory.h> // memcpy
+#include "opcua.h"
+#include "ua_transport_binary.h"
+#include "ua_transport_binary_secure.h"
+#include "ua_transport.h"
+#include "ua_statuscodes.h"
+#include "ua_services.h"
+
+#define SIZE_SECURECHANNEL_HEADER 12
+#define SIZE_SEQHEADER_HEADER 8
+
+SL_Channel slc;
+
+static UA_Int32 SL_send(SL_Channel* channel, UA_ByteString const * responseMessage, UA_Int32 type) {
+	UA_Int32 pos = 0;
+	UA_Int32 isAsym = (type == 449); // FIXME: this is a to dumb method to determine asymmetric algorithm setting
+
+	UA_ByteString response_gather[2]; // securechannel_header, seq_header, security_encryption_header, message_length (eventually + padding + size_signature);
+	UA_ByteString_newMembers(&response_gather[0], SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER +
+							 + (isAsym ? UA_AsymmetricAlgorithmSecurityHeader_calcSize(&(channel->localAsymAlgSettings)) :
+								UA_AsymmetricAlgorithmSecurityHeader_calcSize(&(channel->localAsymAlgSettings))));
+	
+	// sizePadding = 0;
+	// sizeSignature = 0;
+    UA_ByteString *header = &response_gather[0];
+
+	/*---encode Secure Conversation Message Header ---*/
+	if (isAsym) {
+		header->data[0] = 'O';
+		header->data[1] = 'P';
+		header->data[2] = 'N';
+	} else {
+		header->data[0] = 'M';
+		header->data[1] = 'S';
+		header->data[2] = 'G';
+	}
+	pos += 3;
+	header->data[pos] = 'F';
+	pos += 1;
+
+    UA_Int32 packetSize = response_gather[0].length + responseMessage->length;
+	UA_Int32_encodeBinary(&packetSize, &pos, header);
+	UA_UInt32_encodeBinary(&channel->securityToken.secureChannelId, &pos, header);
+
+	/*---encode Algorithm Security Header ---*/
+	if (isAsym) {
+		UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&channel->localAsymAlgSettings, &pos, header);
+	} else {
+		UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&channel->securityToken.tokenId, &pos, header);
+	}
+
+	/*---encode Sequence Header ---*/
+	UA_UInt32_encodeBinary(&channel->sequenceHeader.sequenceNumber, &pos, header);
+	UA_UInt32_encodeBinary(&channel->sequenceHeader.requestId, &pos, header);
+
+	/*---add encoded Message ---*/
+    response_gather[1] = *responseMessage;
+
+	/* sign Data*/
+
+	/* encrypt Data*/
+
+	/* send Data */
+    TL_send(channel->tlConnection, (UA_ByteString **) &response_gather, 2);
+
+	UA_ByteString_deleteMembers(&response_gather[0]);
+	return UA_SUCCESS;
+}
+
+static void init_response_header(UA_RequestHeader const * p, UA_ResponseHeader * r) {
+	r->requestHandle = p->requestHandle;
+	r->serviceResult = UA_STATUSCODE_GOOD;
+	r->stringTableSize = 0;
+	r->timestamp = UA_DateTime_now();
+}
+
+#define INVOKE_SERVICE(TYPE) \
+	UA_##TYPE##Request p; \
+	UA_##TYPE##Response r; \
+	UA_##TYPE##Request_decodeBinary(msg, &pos, &p); \
+	init_response_header((UA_RequestHeader*)&p, (UA_ResponseHeader*)&r); \
+	Service_##TYPE(channel, &p, &r); \
+	UA_ByteString_newMembers(&response_msg, UA_##TYPE##Response_calcSize(&r)+pos); \
+	UA_##TYPE##Response_encodeBinary(&r, &pos, &response_msg); \
+
+/** this function manages all the generic stuff for the request-response game */
+UA_Int32 SL_handleRequest(SL_Channel *channel, UA_ByteString* msg) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 pos = 0;
+
+	// Every Message starts with a NodeID which names the serviceRequestType
+	UA_NodeId serviceRequestType;
+	UA_NodeId_decodeBinary(msg, &pos, &serviceRequestType);
+	UA_NodeId_printf("SL_processMessage - serviceRequestType=", &serviceRequestType);
+
+	UA_ByteString response_msg;
+	UA_NodeId responseType;
+	responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	responseType.namespace = 0;
+
+    pos = UA_NodeId_calcSize(&responseType); // skip nodeid
+	int serviceid = serviceRequestType.identifier.numeric-2; // binary encoding has 2 added to the id
+	if(serviceid == UA_GETENDPOINTSREQUEST_NS0) {
+		INVOKE_SERVICE(GetEndpoints);
+		responseType.identifier.numeric = UA_GETENDPOINTSRESPONSE_NS0;
+	}
+	else if(serviceid == UA_OPENSECURECHANNELREQUEST_NS0) {
+		INVOKE_SERVICE(OpenSecureChannel);
+		responseType.identifier.numeric = UA_OPENSECURECHANNELRESPONSE_NS0;
+	}
+	else if(serviceid == UA_CLOSESECURECHANNELREQUEST_NS0) {
+		INVOKE_SERVICE(CloseSecureChannel);
+		responseType.identifier.numeric = UA_CLOSESECURECHANNELRESPONSE_NS0;
+	}
+	else if(serviceid == UA_CREATESESSIONREQUEST_NS0) {
+		INVOKE_SERVICE(CreateSession);
+		responseType.identifier.numeric = UA_CREATESESSIONRESPONSE_NS0;
+	}
+	else if(serviceid == UA_ACTIVATESESSIONREQUEST_NS0) {
+		INVOKE_SERVICE(ActivateSession);
+		responseType.identifier.numeric = UA_ACTIVATESESSIONRESPONSE_NS0;
+	}
+	else if(serviceid == UA_CLOSESESSIONREQUEST_NS0) {
+		INVOKE_SERVICE(CloseSession);
+		responseType.identifier.numeric = UA_CLOSESESSIONRESPONSE_NS0;
+	}
+	else if(serviceid == UA_READREQUEST_NS0) {
+		INVOKE_SERVICE(Read);
+	    responseType.identifier.numeric = UA_READRESPONSE_NS0;
+	}
+	else {
+		printf("SL_processMessage - unknown request, namespace=%d, request=%d\n", serviceRequestType.namespace,serviceRequestType.identifier.numeric);
+		retval = UA_ERROR;
+		responseType.identifier.numeric = 0; //FIXME
+	}
+
+	pos = 0; // reset
+	UA_NodeId_encodeBinary(&responseType, &pos, &response_msg);
+	SL_send(channel, &response_msg, responseType.identifier.numeric);
+
+	return retval;
+}
+
+/* inits a connection object for secure channel layer */
+UA_Int32 SL_Channel_init(SL_Channel *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;
+
+	channel->sequenceHeader.requestId = 0;
+	channel->sequenceHeader.sequenceNumber = 1;
+
+	UA_String_init(&(channel->secureChannelId));
+
+	channel->securityMode = UA_SECURITYMODE_INVALID;
+	//TODO set a valid start secureChannelId number
+	channel->securityToken.secureChannelId = 25;
+
+	//TODO set a valid start TokenId
+	channel->securityToken.tokenId = 1;
+
+	return UA_SUCCESS;
+}
+
+UA_Int32 SL_Channel_new(TL_connection *connection, UA_ByteString* msg, UA_Int32* pos) {
+	UA_Int32 retval = UA_SUCCESS;
+
+	UA_SecureConversationMessageHeader secureConvHeader;
+	DBG_VERBOSE(printf("SL_Channel_new - entered\n"));
+
+	// FIXME: generate new secure channel
+	SL_Channel_init(&slc);
+	connection->secureChannel = &slc;
+	connection->secureChannel->tlConnection = connection;
+
+	UA_SecureConversationMessageHeader_decodeBinary(msg, pos, &secureConvHeader);
+	// connection->secureChannel->secureChannelId = secureConvHeader.secureChannelId;
+	UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &(connection->secureChannel->remoteAsymAlgSettings));
+	//TODO check that the sequence number is smaller than MaxUInt32 - 1024
+	UA_SequenceHeader_decodeBinary(msg, pos, &(connection->secureChannel->sequenceHeader));
+
+	connection->secureChannel->securityToken.tokenId = 4711;
+
+	UA_ByteString_printf("SL_receive - AAS_Header.ReceiverThumbprint=", &(connection->secureChannel->remoteAsymAlgSettings.receiverCertificateThumbprint));
+	UA_ByteString_printf("SL_receive - AAS_Header.SecurityPolicyUri=", &(connection->secureChannel->remoteAsymAlgSettings.securityPolicyUri));
+	UA_ByteString_printf("SL_receive - AAS_Header.SenderCertificate=", &(connection->secureChannel->remoteAsymAlgSettings.senderCertificate));
+	printf("SL_Channel_new - SequenceHeader.RequestId=%d\n",connection->secureChannel->sequenceHeader.requestId);
+	printf("SL_Channel_new - SequenceHeader.SequenceNr=%d\n",connection->secureChannel->sequenceHeader.sequenceNumber);
+	printf("SL_Channel_new - SecurityToken.tokenID=%d\n",connection->secureChannel->securityToken.tokenId);
+
+// FIXME: reject
+//	if (secureConvHeader.secureChannelId != 0) {
+//		UA_Int32 iTmp = UA_ByteString_compare(
+//								&(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
+//								&(asymAlgSecHeader.senderCertificate));
+//				if (iTmp != UA_EQUAL) {
+//					printf("SL_receive - UA_ERROR_BadSecureChannelUnknown \n");
+//					//TODO return UA_ERROR_BadSecureChannelUnknown
+//				}
+//			} else {
+//				//TODO invalid securechannelId
+//			}
+
+	UA_ByteString slMessage;
+	slMessage.data  = &(msg->data[*pos]);
+	slMessage.length = msg->length - *pos;
+	retval |= SL_handleRequest(connection->secureChannel, &slMessage);
+	return 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, UA_ByteString* msg, UA_Int32* pos) {
+
+	DBG_VERBOSE(printf("SL_process - entered \n"));
+	UA_UInt32 secureChannelId;
+
+	if (connection->connectionState == connectionState_ESTABLISHED) {
+		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);
+//		} else {
+//			// FIXME:
+//		}
+
+		printf("SL_process - securityToken received=%d, expected=%d\n",secureChannelId,connection->securityToken.secureChannelId);
+		if (secureChannelId == connection->securityToken.secureChannelId) {
+			UA_SequenceHeader_decodeBinary(msg, pos, &(connection->sequenceHeader));
+			// process message
+			UA_ByteString slMessage;
+			slMessage.data = &(msg->data[*pos]);
+			slMessage.length = msg->length - *pos;
+			SL_handleRequest(&slc, &slMessage);
+		} else {
+			//TODO generate ERROR_Bad_SecureChannelUnkown
+		}
+	}
+	return UA_SUCCESS;
+}

+ 36 - 0
src/ua_transport_binary_secure.h

@@ -0,0 +1,36 @@
+#ifndef OPCUA_TRANSPORT_BINARY_SECURE_H_
+#define OPCUA_TRANSPORT_BINARY_SECURE_H_
+#include "opcua.h"
+#include "ua_transport.h"
+#include "ua_transport_binary.h"
+#include "ua_transport_binary_secure.h"
+#include "ua_application.h"
+
+typedef struct {
+	UA_UInt32 secureChannelId;
+	UA_SymmetricAlgorithmSecurityHeader tokenId;
+	UA_DateTime createdAt;
+	UA_Int32 revisedLifetime;
+} SL_ChannelSecurityToken;
+
+typedef struct SL_Channel_T {
+	UA_String secureChannelId;
+	TL_connection* tlConnection;
+	UA_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;
+
+	UA_Application *application;
+} SL_Channel;
+
+UA_Int32 SL_initConnectionObject(SL_Channel *connection);
+UA_Int32 SL_process(SL_Channel* channel, UA_ByteString* msg, UA_Int32* pos);
+UA_Int32 SL_Channel_new(TL_connection *connection, UA_ByteString* msg, UA_Int32* pos);
+
+#endif /* OPCUA_TRANSPORT_BINARY_SECURE_H_ */