Browse Source

stack redesign for issue #33

Leon Urbas 11 years ago
parent
commit
c22b9bc519

+ 5 - 1
examples/src/Makefile.am

@@ -1,8 +1,12 @@
 
-bin_PROGRAMS= $(top_builddir)/bin/exampleServer
+bin_PROGRAMS= $(top_builddir)/bin/exampleServer $(top_builddir)/bin/simpleTest
 #__top_builddir__bin_exampleServer_LDFLAGS = -all-static
 __top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c
 __top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a
 
+__top_builddir__bin_simpleTest_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
+__top_builddir__bin_simpleTest_SOURCES = simpleTest.c
+__top_builddir__bin_simpleTest_LDADD= $(top_builddir)/lib/libopen62541.a
+
 AM_CFLAGS = $(GLOBAL_AM_CFLAGS)

+ 0 - 149
examples/src/opcuaServer.c

@@ -1,149 +0,0 @@
-/*
- ============================================================================
- Name        : opcuaServer.c
- Author      :
- Version     :
- Copyright   : Your copyright notice
- Description :
- ============================================================================
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h> // bzero
-
-#include "opcua.h"
-#include "opcua_transportLayer.h"
-
-#ifdef LINUX
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <sys/socketvar.h>
-
-void server_init();
-void server_run();
-
-#endif
-
-#define PORT    16664
-#define MAXMSG  512
-#define BUFFER_SIZE 8192
-
-int main(void) {
-
-#ifdef LINUX
-	server_init();
-	server_run();
-#endif
-
-	return EXIT_SUCCESS;
-
-}
-
-#ifdef LINUX
-
-void server_init() {
-	printf("Starting open62541 demo server on port %d\n", PORT);
-	//call listen
-
-}
-
-void server_run() {
-	UA_connection connection;
-
-	UA_ByteString slMessage = { -1, UA_NULL };
-
-	int optval = 1;
-	int sockfd, newsockfd, portno, clilen;
-	char buffer[BUFFER_SIZE];
-	struct sockaddr_in serv_addr, cli_addr;
-	int n;
-
-	TL_initConnectionObject(&connection);
-	SL_initConnectionObject(&connection);
-
-	/* First call to socket() function */
-	// sockfd = socket(AF_INET, SOCK_STREAM, 0);
-	sockfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (sockfd < 0) {
-		perror("ERROR opening socket");
-		exit(1);
-	}
-
-	/* Initialize socket structure */
-	bzero((void *) &serv_addr, sizeof(serv_addr));
-	portno = PORT;
-	serv_addr.sin_family = AF_INET;
-	serv_addr.sin_addr.s_addr = INADDR_ANY;
-	serv_addr.sin_port = htons(portno);
-
-	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval)
-			== -1) {
-		perror("setsockopt");
-		exit(1);
-	}
-	/* Now bind the host address using bind() call.*/
-	if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
-		perror("ERROR on binding");
-		exit(1);
-	}
-
-	/* Now start listening for the clients, here process will
-	 * go in sleep mode and will wait for the incoming connection
-	 */
-	listen(sockfd, 5);
-	clilen = sizeof(cli_addr);
-
-	/* Accept actual connection from the client */
-	while (1) {
-		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
-		if (newsockfd < 0) {
-			perror("ERROR on accept");
-			exit(1);
-		}
-
-		printf("One connection accepted\n");
-		while (connection.transportLayer.connectionState != connectionState_CLOSE) {
-			/* If connection is established then start communicating */
-			bzero(buffer, BUFFER_SIZE);
-
-			n = read(newsockfd, buffer, BUFFER_SIZE);
-
-			if (n > 0) {
-				connection.readData.data = buffer;
-				connection.readData.length = n;
-				connection.newDataToRead = 1;
-				UA_ByteString_printx("server_run - received=",
-						&connection.readData);
-
-				//TL_receive(&connection, &slMessage);
-				SL_receive(&connection, &slMessage);
-			} else if (n < 0) {
-				perror("ERROR reading from socket1");
-				exit(1);
-			}
-
-			if (connection.newDataToWrite) {
-				UA_ByteString_printx("Send data:", &connection.writeData);
-				n = write(newsockfd, connection.writeData.data,
-						connection.writeData.length);
-				printf("written %d bytes \n", n);
-				connection.newDataToWrite = 0;
-				UA_ByteString_deleteMembers(&connection.writeData);
-
-				connection.writeData.data = NULL;
-				connection.writeData.length = 0;
-			}
-
-			connection.readData.data = NULL;
-			connection.readData.length = 0;
-			connection.newDataToRead = 0;
-		}
-		close(newsockfd);
-		connection.transportLayer.connectionState = connectionState_CLOSED;
-	}
-}
-
-#endif

+ 9 - 0
include/opcua_basictypes.h

@@ -10,6 +10,15 @@
 
 #include <stdint.h>
 
+// FIXME: check debug printfs
+#if defined(DEBUG) || 1
+#define DBG_VERBOSE_printf printf
+#define DBG_ERR_printf printf
+#else
+#define DBG_VERBOSE_printf(...) //
+#define DBG_ERR_printf(...) //
+#endif
+
 /* Basic types */
 typedef _Bool UA_Boolean;
 typedef uint8_t UA_Byte;

+ 2 - 1
src/Makefile.am

@@ -62,7 +62,8 @@ libopen62541_la_SOURCES = opcua.c\
 						opcua_secureLayer.c\
 						util/UA_list.c\
 						util/UA_indexedList.c\
-						opcua_namespace.c
+						opcua_namespace.c\
+						UA_stack.c
 						
 						
 

+ 24 - 18
src/UA_connection.h

@@ -10,6 +10,8 @@
 #include "opcua.h"
 #include "UA_stackInternalTypes.h"
 
+#include <pthread.h>
+
 enum UA_MessageType
 {
 	UA_MESSAGETYPE_HEL = 0x48454C, // H E L
@@ -44,17 +46,20 @@ typedef struct
 	UA_UInt32 maxChunkCount;
 }TL_buffer;
 
-struct TL_connection
+typedef struct T_TL_connection
 {
 	UA_Int32 socket;
 	UA_UInt32 connectionState;
-	TL_buffer remoteConf;
+	pthread_t readerThread;
 	TL_buffer localConf;
-	UA_String endpointURL;
-};
+	UA_Int32 (*UA_TL_writer)(struct T_TL_connection* c, UA_ByteString* msg);
+	TL_buffer remoteConf;
+	UA_String endpointUrl;
+} TL_connection;
 
 
-struct SL_connection
+/* Secure Layer Channel */
+typedef struct T_SL_Channel
 {
 	UA_AsymmetricAlgorithmSecurityHeader remoteAsymAlgSettings;
 	UA_AsymmetricAlgorithmSecurityHeader localAsymAlgSettings;
@@ -70,25 +75,26 @@ struct SL_connection
 
 	SL_ChannelSecurityToken securityToken;
 	UA_UInt32 requestId; // request Id of the current request
-};
+	TL_connection* tlc;
+} UA_SL_Channel;
 
 struct SS_connection
 {
 	UA_Int32 dummy;
 };
 
-typedef struct T_UA_connection
-{
-	struct TL_connection transportLayer;
-	struct SL_connection secureLayer;
-	struct SS_connection serviceLayer;
-
-	UA_Boolean newDataToRead;
-	UA_ByteString readData;
-	UA_Boolean newDataToWrite;
-	UA_ByteString writeData;
-}UA_connection;
-
+//typedef struct T_UA_connection
+//{
+//	TL_connection transportLayer;
+//	struct SL_connection secureLayer;
+//	struct SS_connection serviceLayer;
+//
+//	UA_Boolean newDataToRead;
+//	UA_ByteString readData;
+//	UA_Boolean newDataToWrite;
+//	UA_ByteString writeData;
+//} UA_SL_connection;
+//
 
 
 #endif /* OPCUA_CONNECTIONHELPER_H_ */

+ 93 - 108
src/opcua_secureLayer.c

@@ -17,35 +17,35 @@
 /*
  * inits a connection object for secure channel layer
  */
-UA_Int32 SL_initConnectionObject(UA_connection *connection) {
+UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection) {
 	UA_AsymmetricAlgorithmSecurityHeader_init(
-			&(connection->secureLayer.localAsymAlgSettings));
+			&(connection->localAsymAlgSettings));
 	UA_ByteString_copy(&UA_ByteString_securityPoliceNone,
-			&(connection->secureLayer.localAsymAlgSettings.securityPolicyUri));
+			&(connection->localAsymAlgSettings.securityPolicyUri));
 
-	UA_alloc((void**)&(connection->secureLayer.localNonce.data),
+	UA_alloc((void**)&(connection->localNonce.data),
 			sizeof(UA_Byte));
-	connection->secureLayer.localNonce.length = 1;
+	connection->localNonce.length = 1;
 
-	connection->secureLayer.connectionState = connectionState_CLOSED;
+	connection->connectionState = connectionState_CLOSED;
 
-	connection->secureLayer.requestId = 0;
-	connection->secureLayer.requestType = 0;
+	connection->requestId = 0;
+	connection->requestType = 0;
 
-	UA_String_init(&(connection->secureLayer.secureChannelId));
+	UA_String_init(&(connection->secureChannelId));
 
-	connection->secureLayer.securityMode = UA_SECURITYMODE_INVALID;
+	connection->securityMode = UA_SECURITYMODE_INVALID;
 	//TODO set a valid start secureChannelId number
-	connection->secureLayer.securityToken.secureChannelId = 25;
+	connection->securityToken.secureChannelId = 25;
 
 	//TODO set a valid start TokenId
-	connection->secureLayer.securityToken.tokenId = 1;
-	connection->secureLayer.sequenceNumber = 1;
+	connection->securityToken.tokenId = 1;
+	connection->sequenceNumber = 1;
 
-	return UA_NO_ERROR;
+	return UA_SUCCESS;
 }
 
-UA_Int32 SL_send(UA_connection* connection,
+UA_Int32 SL_send(UA_SL_Channel* channel,
 		UA_ByteString const * responseMessage, UA_Int32 type) {
 	UA_UInt32 sequenceNumber;
 	UA_UInt32 requestId;
@@ -60,8 +60,8 @@ UA_Int32 SL_send(UA_connection* connection,
 
 	pos = 0;
 	//sequence header
-	sequenceNumber = connection->secureLayer.sequenceNumber;
-	requestId = connection->secureLayer.requestId;
+	sequenceNumber = channel->sequenceNumber;
+	requestId = channel->requestId;
 
 	sizePadding = 0;
 	sizeSignature = 0;
@@ -69,9 +69,9 @@ UA_Int32 SL_send(UA_connection* connection,
 	packetSize = SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
 			+ (isAsym ?
 					UA_AsymmetricAlgorithmSecurityHeader_calcSize(
-							&(connection->secureLayer.localAsymAlgSettings)) :
+							&(channel->localAsymAlgSettings)) :
 					UA_SymmetricAlgorithmSecurityHeader_calcSize(
-							&(connection->secureLayer.securityToken.tokenId)))
+							&(channel->securityToken.tokenId)))
 			+ responseMessage->length + sizePadding + sizeSignature;
 
 	//get memory for response
@@ -94,17 +94,17 @@ UA_Int32 SL_send(UA_connection* connection,
 	responsePacket.data[3] = 'F';
 	pos += 1;
 	UA_Int32_encode(&packetSize, &pos, responsePacket.data);
-	UA_UInt32_encode(&(connection->secureLayer.securityToken.secureChannelId),
+	UA_UInt32_encode(&(channel->securityToken.secureChannelId),
 			&pos, responsePacket.data);
 
 	/*---encode Algorithm Security Header ---*/
 	if (isAsym) {
 		UA_AsymmetricAlgorithmSecurityHeader_encode(
-				&(connection->secureLayer.localAsymAlgSettings), &pos,
+				&(channel->localAsymAlgSettings), &pos,
 				responsePacket.data);
 	} else {
 		UA_SymmetricAlgorithmSecurityHeader_encode(
-				&(connection->secureLayer.securityToken.tokenId), &pos,
+				&(channel->securityToken.tokenId), &pos,
 				responsePacket.data);
 	}
 
@@ -121,15 +121,15 @@ UA_Int32 SL_send(UA_connection* connection,
 	/* encrypt Data*/
 
 	/* send Data */
-	TL_send(connection, &responsePacket);
-	// responsePackage will be deleted by top-level procedure
-	return UA_NO_ERROR;
+	TL_send(channel->tlc, &responsePacket);
+	UA_ByteString_deleteMembers(&responsePacket);
+	return UA_SUCCESS;
 }
 
 /*
  * opens a secure channel
  */
-UA_Int32 SL_openSecureChannel(UA_connection *connection,
+UA_Int32 SL_openSecureChannel(UA_SL_Channel *connection,
 		UA_RequestHeader *requestHeader, UA_StatusCode serviceResult) {
 
 	UA_OpenSecureChannelResponse* r;
@@ -166,16 +166,16 @@ UA_Int32 SL_openSecureChannel(UA_connection *connection,
 	r->responseHeader.stringTable = UA_NULL;
 
 	r->serverProtocolVersion =
-			connection->transportLayer.localConf.protocolVersion;
+			connection->tlc->localConf.protocolVersion;
 
 	r->securityToken.channelId =
-			connection->secureLayer.securityToken.secureChannelId;
-	r->securityToken.tokenId = connection->secureLayer.securityToken.tokenId;
+			connection->securityToken.secureChannelId;
+	r->securityToken.tokenId = connection->securityToken.tokenId;
 	r->securityToken.createdAt = UA_DateTime_now();
 	r->securityToken.revisedLifetime =
-			connection->secureLayer.securityToken.revisedLifetime;
+			connection->securityToken.revisedLifetime;
 
-	UA_ByteString_copy(&(connection->secureLayer.localNonce), &(r->serverNonce));
+	UA_ByteString_copy(&(connection->localNonce), &(r->serverNonce));
 
 	//get memory for response
 	response.length = UA_NodeId_calcSize(&responseType) + UA_OpenSecureChannelResponse_calcSize(r);
@@ -193,23 +193,24 @@ UA_Int32 SL_openSecureChannel(UA_connection *connection,
 /*
  * closes a secureChannel (server side)
  */
-void SL_secureChannel_close(UA_connection *connection) {
+void SL_secureChannel_close(UA_SL_Channel *channel) {
 
 }
-UA_Int32 SL_check(UA_connection *connection, UA_ByteString secureChannelPacket) {
+UA_Int32 SL_check(UA_SL_Channel* channel, UA_ByteString* msg) {
 	return UA_NO_ERROR;
 }
-UA_Int32 SL_createSecurityToken(UA_connection *connection, UA_Int32 lifeTime) {
+UA_Int32 SL_createSecurityToken(UA_SL_Channel* channel, UA_Int32 lifeTime) {
 	return UA_NO_ERROR;
 }
 
-UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
+UA_Int32 SL_processMessage(UA_SL_Channel *sc, UA_ByteString* msg) {
 	UA_Int32 retval = UA_SUCCESS;
+
 	UA_Int32 pos = 0;
-	UA_NodeId serviceRequestType;
 
 	// Every Message starts with a NodeID which names the serviceRequestType
-	UA_NodeId_decode(message.data, &pos, &serviceRequestType);
+	UA_NodeId serviceRequestType;
+	UA_NodeId_decode(msg->data, &pos, &serviceRequestType);
 	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
 			&serviceRequestType);
 
@@ -243,7 +244,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 		} else {
 			void * obj;
 			UA_[namespace_index].new(&obj);
-			UA_[namespace_index].decode(message.data, &pos, obj);
+			UA_[namespace_index].decode(msg->data, &pos, obj);
 
 			// FXIME: we need a more clever response/request architecture
 			switch (serviceRequestType.identifier.numeric) {
@@ -293,7 +294,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 				UA_NodeId_encode(&responseType, &pos, response.data);
 				UA_GetEndpointsResponse_encode(r, &pos, response.data);
 
-				SL_send(connection, &response, 431);
+				SL_send(sc, &response, 431);
 
 				UA_ByteString_deleteMembers(&response);
 				UA_GetEndpointsResponse_delete(r);
@@ -331,7 +332,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 				UA_NodeId_encode(&responseType, &pos, response.data);
 				UA_CreateSessionResponse_encode(r, &pos, response.data);
 
-				SL_send(connection, &response, responseType.identifier.numeric);
+				SL_send(sc, &response, responseType.identifier.numeric);
 
 				UA_ByteString_deleteMembers(&response);
 				UA_CreateSessionResponse_delete(r);
@@ -344,7 +345,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 				puts("UA_CLOSESECURECHANNELREQUEST");
 
 				// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
-				connection->transportLayer.connectionState = connectionState_CLOSE;
+				sc->tlc->connectionState = connectionState_CLOSE;
 				retval = UA_SUCCESS;
 			}
 				break;
@@ -355,14 +356,14 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 						(UA_OpenSecureChannelRequest*) obj;
 
 				if (p->clientProtocolVersion
-						!= connection->transportLayer.remoteConf.protocolVersion) {
+						!= sc->tlc->remoteConf.protocolVersion) {
 					printf("SL_processMessage - error protocol version \n");
 					//TODO error protocol version
 					//TODO ERROR_Bad_ProtocolVersionUnsupported
 				}
 				switch (p->requestType) {
 				case UA_SECURITYTOKEN_ISSUE:
-					if (connection->secureLayer.connectionState
+					if (sc->connectionState
 							== connectionState_ESTABLISHED) {
 						printf("SL_processMessage - multiply security token request");
 						//TODO return ERROR
@@ -374,7 +375,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 					//	SL_createNewToken(connection);
 					break;
 				case UA_SECURITYTOKEN_RENEW:
-					if (connection->secureLayer.connectionState
+					if (sc->connectionState
 							== connectionState_CLOSED) {
 						printf(
 								"SL_processMessage - renew token request received, but no secureChannel was established before");
@@ -389,8 +390,8 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 
 				switch (p->securityMode) {
 				case UA_SECURITYMODE_INVALID:
-					connection->secureLayer.remoteNonce.data = NULL;
-					connection->secureLayer.remoteNonce.length = -1;
+					sc->remoteNonce.data = NULL;
+					sc->remoteNonce.length = -1;
 					printf("SL_processMessage - client demands no security \n");
 					break;
 
@@ -406,7 +407,7 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 					break;
 				}
 
-				retval |= SL_openSecureChannel(connection, &(p->requestHeader),
+				retval |= SL_openSecureChannel(sc, &(p->requestHeader),
 						UA_STATUSCODE_GOOD);
 			}
 				break;
@@ -422,78 +423,67 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 	}
 	return retval;
 }
-/*
- * receive and process data from underlying layer
- */
-void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
-	UA_ByteString secureChannelPacket;
-	UA_ByteString message;
+
+// FIXME: we need to associate secure channels with the connection
+UA_SL_Channel slc;
+
+/** process data as we've got it from the transport layer */
+void SL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType) {
 	UA_SecureConversationMessageHeader secureConvHeader;
 	UA_AsymmetricAlgorithmSecurityHeader asymAlgSecHeader;
 	UA_SequenceHeader sequenceHeader;
-	// UA_Int32 packetType = 0;
 	UA_Int32 pos = 0;
-	UA_Int32 iTmp;
-	//TODO Error Handling, length checking
-	//get data from transport layer
-	printf("SL_receive - entered \n");
-
-	TL_receive(connection, &secureChannelPacket);
-
-	if (secureChannelPacket.length > 0 && secureChannelPacket.data != NULL) {
 
-		printf("SL_receive - data received \n");
-		//packetType = TL_getPacketType(&secureChannelPacket, &pos);
+	DBG_VERBOSE_printf("SL_receive - entered \n");
+	switch (messageType) {
+		case UA_MESSAGETYPE_OPN:
+			DBG_VERBOSE_printf("SL_receive - process OPN\n");
 
-		UA_SecureConversationMessageHeader_decode(secureChannelPacket.data,
-				&pos, &secureConvHeader);
+			UA_SecureConversationMessageHeader_decode(msg->data, &pos, &secureConvHeader);
 
-		switch (secureConvHeader.tcpMessageHeader->messageType) {
-
-		case UA_MESSAGETYPE_OPN: /* openSecureChannel Message received */
-			printf("SL_receive - process OPN\n");
 			UA_AsymmetricAlgorithmSecurityHeader_decode(
-					secureChannelPacket.data, &pos, &asymAlgSecHeader);
+					msg->data, &pos, &asymAlgSecHeader);
 			UA_ByteString_printf("SL_receive - AAS_Header.ReceiverThumbprint=",
 					&(asymAlgSecHeader.receiverCertificateThumbprint));
 			UA_ByteString_printf("SL_receive - AAS_Header.SecurityPolicyUri=",
 					&(asymAlgSecHeader.securityPolicyUri));
 			UA_ByteString_printf("SL_receive - AAS_Header.SenderCertificate=",
 					&(asymAlgSecHeader.senderCertificate));
-			if (secureConvHeader.secureChannelId != 0) {
-				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_SequenceHeader_decode(secureChannelPacket.data, &pos,
+//			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_SequenceHeader_decode(msg->data, &pos,
 					&sequenceHeader);
-			printf("SL_receive - SequenceHeader.RequestId=%d\n",
+			DBG_VERBOSE_printf("SL_receive - SequenceHeader.RequestId=%d\n",
 					sequenceHeader.requestId);
-			printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
+			DBG_VERBOSE_printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
 					sequenceHeader.sequenceNumber);
-			//save request id to return it to client
-			connection->secureLayer.requestId = sequenceHeader.requestId;
+			//
+			slc.requestId = sequenceHeader.requestId;
 			//TODO check that the sequence number is smaller than MaxUInt32 - 1024
-			connection->secureLayer.sequenceNumber =
-					sequenceHeader.sequenceNumber;
+			slc.sequenceNumber = sequenceHeader.sequenceNumber;
 
-			message.data = &secureChannelPacket.data[pos];
-			message.length = secureChannelPacket.length - pos;
-			UA_ByteString_printx("SL_receive - message=", &message);
+			UA_ByteString slMessage;
+			slMessage.data  = &(msg->data[pos]);
+			slMessage.length = msg->length - pos;
+			UA_ByteString_printx("SL_receive - message=", &slMessage);
 
-			SL_processMessage(connection, message);
+			SL_processMessage(&slc, &slMessage);
 			// Clean up
 			UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(
 					&asymAlgSecHeader);
 
+			UA_SecureConversationMessageHeader_deleteMembers(&secureConvHeader);
 			break;
 		case UA_MESSAGETYPE_MSG:
 		case UA_MESSAGETYPE_CLO:
@@ -501,37 +491,32 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 //			if (connection->secureLayer.connectionState
 //					== connectionState_ESTABLISHED) {
 			if (secureConvHeader.secureChannelId
-					== connection->secureLayer.securityToken.secureChannelId) {
+					== slc.securityToken.secureChannelId) {
 				UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
 
 				//FIXME: we assume SAS, need to check if AAS or SAS
 				UA_SymmetricAlgorithmSecurityHeader_decode(
-						secureChannelPacket.data, &pos, &symAlgSecHeader);
+						msg->data, &pos, &symAlgSecHeader);
 
 				// decode sequenceHeader and remember
-				UA_SequenceHeader_decode(secureChannelPacket.data, &pos,
+				UA_SequenceHeader_decode(msg->data, &pos,
 						&sequenceHeader);
 				printf("SL_receive - SequenceHeader.RequestId=%d\n",
 						sequenceHeader.requestId);
 				printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
 						sequenceHeader.sequenceNumber);
-				connection->secureLayer.requestId = sequenceHeader.requestId;
-				connection->secureLayer.sequenceNumber =
-						sequenceHeader.sequenceNumber;
+				slc.requestId = sequenceHeader.requestId;
+				slc.sequenceNumber = sequenceHeader.sequenceNumber;
 				// process message
-				message.data = &secureChannelPacket.data[pos];
-				message.length = secureChannelPacket.length - pos;
-				SL_processMessage(connection, message);
+				UA_ByteString slMessage;
+				slMessage.data = &(msg->data[pos]);
+				slMessage.length = msg->length - pos;
+				SL_processMessage(&slc, &slMessage);
 			} else {
 				//TODO generate ERROR_Bad_SecureChannelUnkown
 			}
 //			} // check connection state
 			break;
-		}
-		// Clean up
-		UA_SecureConversationMessageHeader_deleteMembers(&secureConvHeader);
-	} else {
-		printf("SL_receive - no data received \n");
 	}
 }
 

+ 3 - 3
src/opcua_secureLayer.h

@@ -15,7 +15,7 @@
 * @param connection
 * @return
 */
-UA_Int32 SL_initConnectionObject(UA_connection *connection);
+UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection);
 
 /**
 *
@@ -24,9 +24,9 @@ UA_Int32 SL_initConnectionObject(UA_connection *connection);
 * @param sizeInOut
 * @return
 */
-UA_Int32 SL_openSecureChannel_responseMessage_get(UA_connection *connection,
+UA_Int32 SL_openSecureChannel_responseMessage_get(UA_SL_Channel *connection,
 UA_SL_Response *response, UA_Int32* sizeInOut);
 
-void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage);
+void SL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType);
 
 #endif /* OPCUA_SECURECHANNELLAYER_H_ */

+ 78 - 151
src/opcua_transportLayer.c

@@ -4,170 +4,106 @@
  *  Created on: Dec 19, 2013
  *      Author: opcua
  */
-
+#include <memory.h> // memset, memcpy
+#include "UA_stack.h"
+#include "UA_connection.h"
 #include "opcua_transportLayer.h"
 
 
-UA_Int32 TL_initConnectionObject(UA_connection *connection)
+UA_Int32 TL_Connection_init(TL_connection *c, UA_TL_Description* tld)
 {
-
-	connection->newDataToRead = 0;
-	connection->readData.data = UA_NULL;
-	connection->readData.length = 0;
-	connection->transportLayer.connectionState = connectionState_CLOSED;
-	connection->transportLayer.localConf.maxChunkCount = 1;
-	connection->transportLayer.localConf.maxMessageSize = 16384;
-	connection->transportLayer.localConf.sendBufferSize = 8192;
-	connection->transportLayer.localConf.recvBufferSize = 8192;
-	return UA_NO_ERROR;
+	c->socket = -1;
+	c->connectionState = connectionState_CLOSED;
+	c->readerThread = -1;
+	c->UA_TL_writer = UA_NULL;
+	memcpy(&(c->localConf),&(tld->localConf),sizeof(TL_buffer));
+	memset(&(c->remoteConf),0,sizeof(TL_buffer));
+	UA_String_init(&(c->endpointUrl));
+	return UA_SUCCESS;
 }
 
-UA_Int32 TL_check(UA_connection *connection)
+UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg, int checkLocal)
 {
-	UA_Int32 position = 4;
-	UA_Int32 messageLength = 0;
 	UA_Int32 retval = UA_SUCCESS;
 
+	UA_Int32 position = 4;
+	UA_Int32 messageLength;
 
-	printf("TL_check - entered \n");
+	DBG_VERBOSE_printf("TL_check - entered \n");
 
-	UA_Int32_decode(connection->readData.data,&position,&messageLength);
-	printf("TL_check - messageLength = %d \n",messageLength);
+	UA_Int32_decode(msg,&position,&messageLength);
+	DBG_VERBOSE_printf("TL_check - messageLength = %d \n",messageLength);
 
-	if (messageLength == -1 || messageLength != connection->readData.length ||
-			messageLength > (UA_Int32) connection->transportLayer.localConf.maxMessageSize)
+	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))
 	{
-		printf("TL_check - length error \n");
+		DBG_ERR_printf("TL_check - length error \n");
 		retval = UA_ERR_INCONSISTENT;
 	}
 	return retval;
 }
 
-
-UA_Int32 TL_receive(UA_connection *connection, UA_ByteString *packet)
-{
-	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 pos = 0;
-	UA_OPCUATcpMessageHeader *tcpMessageHeader;
-
-	UA_alloc((void**)&tcpMessageHeader,UA_OPCUATcpMessageHeader_calcSize(UA_NULL));
-
-	printf("TL_receive - entered \n");
-
-	packet->data = NULL;
-	packet->length = 0;
-
-
-	UA_OPCUATcpMessageHeader_decode(connection->readData.data, &pos,tcpMessageHeader);
-
-	if(TL_check(connection) == UA_NO_ERROR)
-	{
-
-		printf("TL_receive - no error \n");
-		printf("TL_receive - connection->readData.length %d \n",connection->readData.length);
-
-
-		UA_MessageType_printf("TL_receive - messageType=",&(tcpMessageHeader->messageType));
-		switch(tcpMessageHeader->messageType)
-		{
-		case UA_MESSAGETYPE_MSG:
-		case UA_MESSAGETYPE_OPN:
-		case UA_MESSAGETYPE_CLO:
-		{
-			packet->data = connection->readData.data;
-			packet->length = connection->readData.length;
-
-			printf("TL_receive - received MSG or OPN or CLO message\n");
-			break;
-		}
-		case UA_MESSAGETYPE_HEL:
-		case UA_MESSAGETYPE_ACK:
-		{
-			puts("TL_receive - received HEL or ACK message");
-			TL_process(connection, tcpMessageHeader->messageType, &pos);
-			break;
-		}
-		case UA_MESSAGETYPE_ERR:
-		{
-			printf("TL_receive - received ERR message\n");
-
-			//TODO ERROR HANDLING
-
-			retval = UA_ERROR_RCV_ERROR;
-			break;
-		}
-
-		}
-	}
-	else
-	{
-		//length error: send error message to communication partner
-		//TL_send()
-	}
-	// Clean Up
-	UA_OPCUATcpMessageHeader_delete(tcpMessageHeader);
-	return retval;
-}
-
 #define Cmp3Byte(data,pos,a,b,c) (*((Int32*) ((data)+(pos))) & 0xFFFFFF) == (Int32)(((Byte)(a))|((Byte)(b))<<8|((Byte)(c))<<16)
 
-
-UA_Int32 TL_process(UA_connection *connection,UA_Int32 packetType, UA_Int32 *pos)
+UA_Int32 TL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 packetType, UA_Int32 *pos)
 {
+	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 tmpPos = 0;
 	UA_ByteString tmpMessage;
+	UA_OPCUATcpMessageHeader tcpMessageHeader;
 	UA_OPCUATcpHelloMessage helloMessage;
 	UA_OPCUATcpAcknowledgeMessage ackMessage;
 	UA_OPCUATcpMessageHeader ackHeader;
 
-	printf("TL_process - entered \n");
+	DBG_VERBOSE_printf("TL_process - entered \n");
 
-	switch(packetType)
+	retval = UA_OPCUATcpMessageHeader_decode(&msg, &pos, &tcpMessageHeader);
+
+	if (retval == UA_SUCCESS) {
+	switch(tcpMessageHeader.messageType)
 	{
-	case UA_MESSAGETYPE_HEL :
-		if(connection->transportLayer.connectionState == connectionState_CLOSED)
+	case UA_MESSAGETYPE_HEL:
+		if (connection->connectionState == connectionState_CLOSED)
 		{
-			printf("TL_process - extracting header information \n");
-			printf("TL_process - pos = %d \n",*pos);
+			DBG_VERBOSE_printf("TL_process - extracting header information \n");
 
-			UA_OPCUATcpHelloMessage_decode(connection->readData.data,pos,&helloMessage);
+			UA_OPCUATcpHelloMessage_decode(&msg->data,pos,&helloMessage);
 
 			/* extract information from received header */
-			//UA_UInt32_decode(connection->readData.data,pos,(&(connection->transportLayer.remoteConf.protocolVersion)));
-			connection->transportLayer.remoteConf.protocolVersion = helloMessage.protocolVersion;
-			printf("TL_process - protocolVersion = %d \n",connection->transportLayer.remoteConf.protocolVersion);
+			connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
+			DBG_VERBOSE_printf("TL_process - protocolVersion = %d \n",connection->remoteConf.protocolVersion);
 
-			connection->transportLayer.remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
-			printf("TL_process - recvBufferSize = %d \n",connection->transportLayer.remoteConf.recvBufferSize);
+			connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
+			DBG_VERBOSE_printf("TL_process - recvBufferSize = %d \n",connection->remoteConf.recvBufferSize);
 
-			connection->transportLayer.remoteConf.sendBufferSize = helloMessage.sendBufferSize;
-			printf("TL_process - sendBufferSize = %d \n",connection->transportLayer.remoteConf.sendBufferSize);
+			connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
+			DBG_VERBOSE_printf("TL_process - sendBufferSize = %d \n",connection->remoteConf.sendBufferSize);
 
-			connection->transportLayer.remoteConf.maxMessageSize = helloMessage.maxMessageSize;
-			printf("TL_process - maxMessageSize = %d \n",connection->transportLayer.remoteConf.maxMessageSize);
+			connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
+			DBG_VERBOSE_printf("TL_process - maxMessageSize = %d \n",connection->remoteConf.maxMessageSize);
 
-			connection->transportLayer.remoteConf.maxChunkCount = helloMessage.maxChunkCount;
-			printf("TL_process - maxChunkCount = %d \n",connection->transportLayer.remoteConf.maxChunkCount);
+			connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
+			DBG_VERBOSE_printf("TL_process - maxChunkCount = %d \n",connection->remoteConf.maxChunkCount);
 
-			// FIXME: This memory needs to be cleaned up in the server!
-			UA_String_copy(&(helloMessage.endpointUrl), &(connection->transportLayer.endpointURL));
+			UA_String_copy(&(helloMessage.endpointUrl), &(connection->endpointUrl));
 
 			// Clean up
 			UA_OPCUATcpHelloMessage_deleteMembers(&helloMessage);
 
-			/* send back acknowledge */
-			ackMessage.protocolVersion = connection->transportLayer.localConf.protocolVersion;
-			ackMessage.receiveBufferSize = connection->transportLayer.localConf.recvBufferSize;
-			ackMessage.sendBufferSize = connection->transportLayer.localConf.sendBufferSize;
-			ackMessage.maxMessageSize = connection->transportLayer.localConf.maxMessageSize;
-			ackMessage.maxChunkCount = connection->transportLayer.localConf.maxChunkCount;
+			// build acknowledge response
+			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;
 
 			ackHeader.messageType = UA_MESSAGETYPE_ACK;
 			ackHeader.isFinal = 'F';
 			ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSize(&ackMessage)
 			+ UA_OPCUATcpMessageHeader_calcSize(&ackHeader);
 
-			//allocate memory in stream
+			// allocate memory for encoding
 			UA_alloc((void**)&(tmpMessage.data),ackHeader.messageSize);
 			tmpMessage.length = ackHeader.messageSize;
 
@@ -175,56 +111,47 @@ UA_Int32 TL_process(UA_connection *connection,UA_Int32 packetType, UA_Int32 *pos
 			UA_OPCUATcpMessageHeader_encode(&ackHeader,&tmpPos,tmpMessage.data);
 			UA_OPCUATcpAcknowledgeMessage_encode(&ackMessage,&tmpPos,tmpMessage.data);
 
-			printf("TL_process - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos);
-			/* ------------------------ Body ------------------------ */
-			// protocol version
-			printf("TL_process - localConf.protocolVersion = %d \n",connection->transportLayer.localConf.protocolVersion);
-			//receive buffer size
-			printf("TL_process - localConf.recvBufferSize = %d \n", connection->transportLayer.localConf.recvBufferSize);
-			//send buffer size
-			printf("TL_process - localConf.sendBufferSize = %d \n", connection->transportLayer.localConf.sendBufferSize);
-			//maximum message size
-			printf("TL_process - localConf.maxMessageSize = %d \n", connection->transportLayer.localConf.maxMessageSize);
-			//maximum chunk count
-			printf("TL_process - localConf.maxChunkCount = %d \n", connection->transportLayer.localConf.maxChunkCount);
+			DBG_VERBOSE_printf("TL_process - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos);
+			connection->connectionState = connectionState_OPENING;
 			TL_send(connection, &tmpMessage);
-			// do not delete tmpMessage - this is the responsibility of the send thread
+			UA_ByteString_delete(&tmpMessage);
 		}
 		else
 		{
-			printf("TL_process - wrong connection state \n");
-			return UA_ERROR_MULTIPLY_HEL;
+			DBG_ERR_printf("TL_process - wrong connection state \n");
+			retval = UA_ERROR_MULTIPLY_HEL;
 		}
 		break;
 	default:
-		return UA_ERROR;
+		if ((connection->connectionState != connectionState_CLOSED)) {
+			retval = SL_process(connection, msg, tcpMessageHeader.messageType);
+		} else {
+			retval = UA_ERROR;
+		}
+		break;
 	}
-	return UA_SUCCESS;
+	}
+	if (retval != UA_SUCCESS) {
+		UA_ByteString errorMsg;
+		UA_ByteString_init(&errorMsg);
+		TL_send(connection,&errorMsg);
+		UA_ByteString_deleteMembers(&errorMsg);
+	}
+	return retval;
 }
-/*
- * respond to client request
- */
-
-
-UA_Int32 TL_send(UA_connection* connection, UA_ByteString* packet)
+/** respond to client request */
+UA_Int32 TL_send(TL_connection* connection, UA_ByteString* msg)
 {
 	UA_Int32 retval = UA_SUCCESS;
-	printf("TL_send - entered \n");
-	connection->newDataToWrite = 1;
-	if(packet->length != -1 && packet->length < (UA_Int32) connection->transportLayer.remoteConf.maxMessageSize)
-	{
-		UA_ByteString_printx("TL_send - data=", packet);
-		connection->writeData.data = packet->data;
-		connection->writeData.length = packet->length;
+	DBG_VERBOSE_printf("TL_send - entered \n");
+
+	if (TL_check(connection,msg,UA_TL_CHECK_REMOTE)) {
+		connection->UA_TL_writer(connection,msg);
 	}
 	else
 	{
-		printf("TL_send - ERROR: packet size greater than remote buffer size");
+		DBG_ERR_printf("TL_send - ERROR: packet size greater than remote buffer size");
 		retval = UA_ERROR;
 	}
 	return retval;
 }
-
-
-
-

+ 8 - 4
src/opcua_transportLayer.h

@@ -89,16 +89,20 @@ struct TL_messageBodyERR
  * @param TL_message
  * @return
  */
-UA_Int32 TL_check(UA_connection *connection);
+enum UA_TL_CHECK_enum {
+	UA_TL_CHECK_LOCAL = 0,
+	UA_TL_CHECK_REMOTE = 1
+};
+UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg, UA_Int32 local);
 /**
  *
  * @param connection
  * @param TL_message
  */
-UA_Int32 TL_receive(UA_connection *connection,UA_ByteString *packet);
-UA_Int32 TL_send(UA_connection *connection, UA_ByteString *packet);
+UA_Int32 TL_receive(TL_connection *connection,UA_ByteString *packet);
+UA_Int32 TL_send(TL_connection *connection, UA_ByteString *packet);
 UA_Int32 TL_getPacketType(UA_ByteString *packet, UA_Int32 *pos);
-UA_Int32 TL_process(UA_connection *connection,UA_Int32 packetType, UA_Int32 *pos);
+UA_Int32 TL_process(TL_connection *connection, UA_ByteString *packet, UA_Int32 packetType, UA_Int32 *pos);
 
 
 #endif /* OPCUA_TRANSPORTLAYER_H_ */

+ 15 - 0
tests/check_builtin.c

@@ -731,6 +731,20 @@ START_TEST(UA_Variant_decodeWithArrayFlagSetShallSetVTAndAllocateMemoryForArray)
 	UA_Variant_deleteMembers(&dst);
 }
 END_TEST
+START_TEST(UA_Variant_decodeWithOutDeleteMembersShallFailInCheckMem)
+{
+	// given
+	UA_Int32 pos = 0;
+	UA_Byte src[] = { UA_INT32_NS0 | UA_VARIANT_ENCODINGMASKTYPE_ARRAY, 0x02, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
+	UA_Variant dst;
+	// when
+	UA_Int32 retval = UA_Variant_decode(src, &pos, &dst);
+	// then
+	ck_assert_int_eq(retval,UA_SUCCESS);
+	// finally - unfortunately we cannot express that not freeing three chunks is what we expect
+	// UA_Variant_deleteMembers(&dst);
+}
+END_TEST
 
 START_TEST(UA_Byte_encode_test)
 {
@@ -811,6 +825,7 @@ Suite *testSuite_builtin(void)
 	tcase_add_test(tc_calcSize, UA_Variant_calcSizeFixedSizeArrayShallReturnEncodingSize);
 	tcase_add_test(tc_calcSize, UA_Variant_calcSizeVariableSizeArrayShallReturnEncodingSize);
 	tcase_add_test(tc_calcSize, UA_Variant_calcSizeVariableSizeArrayWithNullPtrWillReturnWrongButLargeEnoughEncodingSize);
+	tcase_add_test(tc_calcSize, UA_Variant_decodeWithOutDeleteMembersShallFailInCheckMem);
 	suite_add_tcase(s,tc_calcSize);