Bladeren bron

coming close, answer to OPN however still corrupted

Leon Urbas 11 jaren geleden
bovenliggende
commit
fec890393b

+ 9 - 6
include/opcua_basictypes.h

@@ -10,13 +10,15 @@
 
 #include <stdint.h>
 
-// FIXME: check debug printfs
+#define DBG_VERBOSE(expression) //
+#define DBG_ERR(expression) //
 #if defined(DEBUG) || 1
-#define DBG_VERBOSE_printf printf
-#define DBG_ERR_printf printf
-#else
-#define DBG_VERBOSE_printf(...) //
-#define DBG_ERR_printf(...) //
+# undef DBG_ERR
+# define DBG_ERR(expression) expression
+# if defined(VERBOSE)
+#  undef DB_VERBOSE
+#  define DBG_VERBOSE(expression) expression
+# endif
 #endif
 
 /* Basic types */
@@ -217,6 +219,7 @@ UA_ByteString;
 UA_TYPE_METHOD_PROTOTYPES (UA_ByteString)
 UA_Int32 UA_ByteString_compare(UA_ByteString *string1, UA_ByteString *string2);
 UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst);
+UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length);
 extern UA_ByteString UA_ByteString_securityPoliceNone;
 
 /** LocalizedTextBinaryEncoding - Part: 6, Chapter: 5.2.2.14, Page: 21 */

+ 10 - 7
src/UA_connection.h

@@ -46,27 +46,30 @@ typedef struct
 	UA_UInt32 maxChunkCount;
 }TL_buffer;
 
+/* Transport Layer Connection */
 typedef struct T_TL_connection
 {
-	UA_Int32 socket;
+	UA_Int32 connectionHandle;
 	UA_UInt32 connectionState;
 	pthread_t readerThread;
 	TL_buffer localConf;
 	UA_Int32 (*UA_TL_writer)(struct T_TL_connection* c, UA_ByteString* msg);
 	TL_buffer remoteConf;
-	UA_String endpointUrl;
+	UA_String localEndpointUrl;
+	UA_String remoteEndpointUrl;
+	struct T_SL_Channel* secureChannel;
 } UA_TL_connection;
 
 
 /* Secure Layer Channel */
 typedef struct T_SL_Channel
 {
+	UA_String secureChannelId;
+	UA_TL_connection* tlConnection;
+
 	UA_AsymmetricAlgorithmSecurityHeader remoteAsymAlgSettings;
 	UA_AsymmetricAlgorithmSecurityHeader localAsymAlgSettings;
-
-	UA_UInt32 sequenceNumber;
-	UA_UInt32 requestType;
-	UA_String secureChannelId;
+	UA_SequenceHeader sequenceHeader;
 
 	UA_UInt32 securityMode;
 	UA_ByteString remoteNonce;
@@ -75,7 +78,7 @@ typedef struct T_SL_Channel
 
 	SL_ChannelSecurityToken securityToken;
 	UA_UInt32 requestId; // request Id of the current request
-	UA_TL_connection* tlc;
+
 } UA_SL_Channel;
 
 struct SS_connection

+ 11 - 11
src/UA_stack.c

@@ -39,29 +39,29 @@ void* UA_TL_TCP_reader(void *p) {
 	UA_alloc((void**)&(readBuffer.data),c->localConf.recvBufferSize);
 
 	while (c->connectionState != connectionState_CLOSE) {
-		readBuffer.length = read(c->socket, readBuffer.data, c->localConf.recvBufferSize);
+		readBuffer.length = read(c->connectionHandle, readBuffer.data, c->localConf.recvBufferSize);
 
-		UA_ByteString_printx("server_run - received=",&readBuffer);
+		printf("UA_TL_TCP_reader - %*.s ",c->remoteEndpointUrl.length,c->remoteEndpointUrl.data);
+		UA_ByteString_printx("received=",&readBuffer);
 
 		if (readBuffer.length  > 0) {
 			TL_process(c,&readBuffer);
-		} else if (readBuffer.length < 0) {
+		} else {
+			c->connectionState = connectionState_CLOSE;
 			perror("ERROR reading from socket1");
-			break;
 		}
 	}
 	// clean up: socket, buffer, connection
-	// not really necessary?
-	c->connectionState = connectionState_CLOSE;
 	// free resources allocated with socket
-	close(c->socket);
+	close(c->connectionHandle);
+	c->connectionState = connectionState_CLOSED;
 	UA_ByteString_deleteMembers(&readBuffer);
-	// FIXME: C has no lambdas, we need a matcher with two arguments
+	// FIXME: standard C has no lambdas, we need a matcher with two arguments
 	// UA_list_Element* lec = UA_list_findFirst(theTL,c,compare);
 	// TODO: can we get get rid of reference to theTL?
 	UA_list_Element* lec = UA_list_find(&theTL.connections,UA_NULL);
 	UA_list_removeElement(lec,UA_NULL);
-	UA_free(lec->payload);
+	UA_free(c);
 	return UA_NULL;
 }
 
@@ -72,7 +72,7 @@ void* UA_TL_TCP_write(UA_TL_connection* c, UA_ByteString* msg) {
 	while (nWritten < msg->length) {
 		int n;
 		do {
-			n = write(c->socket, &(msg->data[n]), msg->length-n);
+			n = write(c->connectionHandle, &(msg->data[n]), msg->length-n);
 		} while (n == -1L && errno == EINTR);
 		if (n >= 0) {
 			nWritten += n;
@@ -103,7 +103,7 @@ void* UA_TL_TCP_listen(void *p) {
 				UA_Int32 retval = UA_SUCCESS;
 				retval |= UA_alloc((void**)&c,sizeof(UA_TL_connection));
 				TL_Connection_init(c, tld->tld);
-				c->socket = newsockfd;
+				c->connectionHandle = newsockfd;
 				c->UA_TL_writer = UA_TL_TCP_write;
 				// add to list
 				UA_list_addPayloadToBack(&(tld->connections),c);

+ 6 - 6
src/UA_stackInternalTypes.c

@@ -169,35 +169,35 @@ UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessa
 UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const * ptr) {
 	if(ptr==UA_NULL){return sizeof(UA_SecureConversationMessageHeader);}
 	return 0
-	 + UA_OPCUATcpMessageHeader_calcSize(ptr->tcpMessageHeader)
+	 // + UA_OPCUATcpMessageHeader_calcSize(ptr->tcpMessageHeader)
 	 + sizeof(UA_UInt32) // secureChannelId
 	;
 }
 
 UA_Int32 UA_SecureConversationMessageHeader_encode(UA_SecureConversationMessageHeader const * src, UA_Int32* pos, UA_Byte* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpMessageHeader_encode(src->tcpMessageHeader,pos,dst);
+	// retval |= UA_OPCUATcpMessageHeader_encode(src->tcpMessageHeader,pos,dst);
 	retval |= UA_UInt32_encode(&(src->secureChannelId),pos,dst);
 	return retval;
 }
 
 UA_Int32 UA_SecureConversationMessageHeader_decode(UA_Byte const * src, UA_Int32* pos, UA_SecureConversationMessageHeader* dst) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_alloc((void**)&(dst->tcpMessageHeader),UA_OPCUATcpMessageHeader_calcSize(UA_NULL));
-	retval |= UA_OPCUATcpMessageHeader_decode(src,pos,dst->tcpMessageHeader);
+	//retval |= UA_alloc((void**)&(dst->tcpMessageHeader),UA_OPCUATcpMessageHeader_calcSize(UA_NULL));
+	//retval |= UA_OPCUATcpMessageHeader_decode(src,pos,dst->tcpMessageHeader);
 	retval |= UA_UInt32_decode(src,pos,&(dst->secureChannelId));
 	return retval;
 }
 
 UA_Int32 UA_SecureConversationMessageHeader_delete(UA_SecureConversationMessageHeader* p) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_SecureConversationMessageHeader_deleteMembers(p);
+	// retval |= UA_SecureConversationMessageHeader_deleteMembers(p);
 	retval |= UA_free(p);
 	return retval;
     }
 UA_Int32 UA_SecureConversationMessageHeader_deleteMembers(UA_SecureConversationMessageHeader* p) {
 	UA_Int32 retval = UA_SUCCESS;
-	retval |= UA_OPCUATcpMessageHeader_delete(p->tcpMessageHeader);
+	// retval |= UA_OPCUATcpMessageHeader_delete(p->tcpMessageHeader);
 	return retval;
 }
 

+ 1 - 1
src/UA_stackInternalTypes.h

@@ -93,7 +93,7 @@ UA_Int32 UA_OPCUATcpAcknowledgeMessage_deleteMembers(UA_OPCUATcpAcknowledgeMessa
 /*** UA_SecureConversationMessageHeader ***/
 /* Secure Layer Sequence Header */
 typedef struct T_UA_SecureConversationMessageHeader {
-	UA_OPCUATcpMessageHeader* tcpMessageHeader;
+	// UA_OPCUATcpMessageHeader* tcpMessageHeader;
 	UA_UInt32 secureChannelId;
 } UA_SecureConversationMessageHeader;
 UA_Int32 UA_SecureConversationMessageHeader_calcSize(UA_SecureConversationMessageHeader const * ptr);

+ 14 - 3
src/opcua_basictypes.c

@@ -97,7 +97,7 @@ UA_Int32 UA_Array_new(void **p,UA_Int32 noElements, UA_Int32 type) {
 }
 
 UA_Int32 _UA_free(void * ptr,char* f,int l){
-	printf("UA_free;%p;;%s;%d\n",ptr,f,l); fflush(stdout);
+	DBG_VERBOSE(printf("UA_free;%p;;%s;%d\n",ptr,f,l); fflush(stdout));
 	if (UA_NULL != ptr) {
 		free(ptr);
 	}
@@ -107,13 +107,13 @@ UA_Int32 _UA_free(void * ptr,char* f,int l){
 void const * UA_alloc_lastptr;
 UA_Int32 _UA_alloc(void ** ptr, int size,char* f,int l){
 	UA_alloc_lastptr = *ptr = malloc(size);
-	printf("UA_alloc;%p;%d;%s;%d\n",*ptr,size,f,l); fflush(stdout);
+	DBG_VERBOSE(printf("UA_alloc;%p;%d;%s;%d\n",*ptr,size,f,l); fflush(stdout));
 	if(*ptr == UA_NULL) return UA_ERR_NO_MEMORY;
 	return UA_SUCCESS;
 }
 
 UA_Int32 UA_memcpy(void * dst, void const * src, int size){
-	printf("UA_memcpy;%p;%p;%d\n",dst,src,size);
+	DBG_VERBOSE(printf("UA_memcpy;%p;%p;%d\n",dst,src,size));
 	memcpy(dst, src, size);
 	return UA_SUCCESS;
 }
@@ -474,6 +474,17 @@ UA_ByteString UA_ByteString_securityPoliceNone = { sizeof(UA_Byte_securityPolice
 UA_Int32 UA_ByteString_copy(UA_ByteString const * src, UA_ByteString* dst) {
 	return UA_String_copy((UA_String const*)src,(UA_String*)dst);
 }
+UA_Int32 UA_ByteString_newMembers(UA_ByteString* p, UA_Int32 length) {
+	UA_Int32 retval = UA_SUCCESS;
+	if ((retval |= UA_alloc((void**)&(p->data),length)) == UA_SUCCESS) {
+		p->length = length;
+	} else {
+		p->length = length;
+		p->data = UA_NULL;
+	}
+	return retval;
+}
+
 
 UA_Int32 UA_Guid_calcSize(UA_Guid const * p) {
 	if (p == UA_NULL) {

+ 237 - 293
src/opcua_secureLayer.c

@@ -14,9 +14,7 @@
 #define SIZE_SECURECHANNEL_HEADER 12
 #define SIZE_SEQHEADER_HEADER 8
 
-/*
- * inits a connection object for secure channel layer
- */
+/* inits a connection object for secure channel layer */
 UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection) {
 	UA_AsymmetricAlgorithmSecurityHeader_init(
 			&(connection->localAsymAlgSettings));
@@ -29,8 +27,8 @@ UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection) {
 
 	connection->connectionState = connectionState_CLOSED;
 
-	connection->requestId = 0;
-	connection->requestType = 0;
+	connection->sequenceHeader.requestId = 0;
+	connection->sequenceHeader.sequenceNumber = 1;
 
 	UA_String_init(&(connection->secureChannelId));
 
@@ -40,7 +38,6 @@ UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection) {
 
 	//TODO set a valid start TokenId
 	connection->securityToken.tokenId = 1;
-	connection->sequenceNumber = 1;
 
 	return UA_SUCCESS;
 }
@@ -60,8 +57,8 @@ UA_Int32 SL_send(UA_SL_Channel* channel,
 
 	pos = 0;
 	//sequence header
-	sequenceNumber = channel->sequenceNumber;
-	requestId = channel->requestId;
+	sequenceNumber = channel->sequenceHeader.sequenceNumber;
+	requestId = channel->sequenceHeader.requestId;
 
 	sizePadding = 0;
 	sizeSignature = 0;
@@ -121,7 +118,7 @@ UA_Int32 SL_send(UA_SL_Channel* channel,
 	/* encrypt Data*/
 
 	/* send Data */
-	TL_send(channel->tlc, &responsePacket);
+	TL_send(channel->tlConnection, &responsePacket);
 	UA_ByteString_deleteMembers(&responsePacket);
 	return UA_SUCCESS;
 }
@@ -166,7 +163,7 @@ UA_Int32 SL_openSecureChannel(UA_SL_Channel *connection,
 	r->responseHeader.stringTable = UA_NULL;
 
 	r->serverProtocolVersion =
-			connection->tlc->localConf.protocolVersion;
+			connection->tlConnection->localConf.protocolVersion;
 
 	r->securityToken.channelId =
 			connection->securityToken.secureChannelId;
@@ -203,255 +200,225 @@ UA_Int32 SL_createSecurityToken(UA_SL_Channel* channel, UA_Int32 lifeTime) {
 	return UA_NO_ERROR;
 }
 
-UA_Int32 SL_processMessage(UA_SL_Channel *sc, UA_ByteString* msg) {
+UA_Int32 UA_SL_handleGetEndpointsRequest(UA_SL_Channel *channel, void* obj) {
+	puts("UA_GETENDPOINTSREQUEST");
 	UA_Int32 retval = UA_SUCCESS;
 
+	UA_GetEndpointsRequest* p = (UA_GetEndpointsRequest*) obj;
+	UA_NodeId responseType;
+	UA_GetEndpointsResponse* r;
+
+	UA_String_printx("endpointUrl=", &(p->endpointUrl));
+	UA_GetEndpointsResponse_new(&r);
+	r->responseHeader.requestHandle = p->requestHeader.requestHandle;
+	r->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
+	r->responseHeader.stringTableSize = 0;
+	r->responseHeader.timestamp = UA_DateTime_now();
+
+	r->endpointsSize = 1;
+	UA_Array_new((void**) &(r->endpoints),r->endpointsSize,UA_ENDPOINTDESCRIPTION);
+	UA_String_copy(&(channel->tlConnection->localEndpointUrl),&(r->endpoints[0]->endpointUrl));
+	UA_String_copycstring("http://open62541.info/applications/4711",&(r->endpoints[0]->server.applicationUri));
+	UA_String_copycstring("http://open62541.info/product/release",&(r->endpoints[0]->server.productUri));
+	// FIXME: This should be a feature of the application
+	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
+
+	// Now let's build the response
+	UA_ByteString response;
+	responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	responseType.namespace = 0;
+	responseType.identifier.numeric = 431; // GetEndpointsResponse_Encoding_DefaultBinary
+
+	UA_ByteString_newMembers(&response, UA_NodeId_calcSize(&responseType) + UA_GetEndpointsResponse_calcSize(r));
+
 	UA_Int32 pos = 0;
+	UA_NodeId_encode(&responseType, &pos, response.data);
+	UA_GetEndpointsResponse_encode(r, &pos, response.data);
 
-	// Every Message starts with a NodeID which names the serviceRequestType
-	UA_NodeId serviceRequestType;
-	UA_NodeId_decode(msg->data, &pos, &serviceRequestType);
-	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
-			&serviceRequestType);
-
-	if (serviceRequestType.namespace == 0) {
-		// FIXME: quick hack to map DataType to Object
-		switch (serviceRequestType.identifier.numeric) {
-		case 452: //
-			serviceRequestType.identifier.numeric =
-					UA_CLOSESECURECHANNELREQUEST_NS0;
-			break;
-		case 446: //
-			serviceRequestType.identifier.numeric =
-					UA_OPENSECURECHANNELREQUEST_NS0;
-			break;
-		case 428: //
-			serviceRequestType.identifier.numeric = UA_GETENDPOINTSREQUEST_NS0;
-			break;
-		case 461: //
-			serviceRequestType.identifier.numeric = UA_CREATESESSIONREQUEST_NS0;
+	SL_send(channel, &response, 431);
+	UA_ByteString_deleteMembers(&response);
+	UA_GetEndpointsResponse_delete(r);
+	return retval;
+}
+
+UA_Int32 UA_SL_handleCreateSessionRequest(UA_SL_Channel *channel, void* obj) {
+	UA_Int32 retval = UA_SUCCESS;
+	puts("UA_CREATESESSIONREQUEST");
+
+	UA_CreateSessionRequest* p = (UA_CreateSessionRequest*) obj;
+	UA_NodeId responseType;
+	UA_CreateSessionResponse* r;
+
+	UA_CreateSessionResponse_new(&r);
+	r->responseHeader.requestHandle = p->requestHeader.requestHandle;
+	r->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
+	r->responseHeader.stringTableSize = 0;
+	r->responseHeader.timestamp = UA_DateTime_now();
+
+	// FIXME: create session
+
+	// Now let's build the response
+	UA_ByteString response;
+	responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+	responseType.namespace = 0;
+	responseType.identifier.numeric = 464; // CreateSessionResponse_Encoding_DefaultBinary
+
+	UA_ByteString_newMembers(&response, UA_NodeId_calcSize(&responseType) + UA_CreateSessionResponse_calcSize(r));
+	UA_Int32 pos = 0;
+
+	UA_NodeId_encode(&responseType, &pos, response.data);
+	UA_CreateSessionResponse_encode(r, &pos, response.data);
+	SL_send(channel, &response, responseType.identifier.numeric);
+
+	UA_ByteString_deleteMembers(&response);
+	UA_CreateSessionResponse_delete(r);
+
+	return retval;
+}
+
+UA_Int32 UA_SL_handleCloseSecureChannelRequest(UA_SL_Channel *channel, void* obj) {
+	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;
+}
+
+UA_Int32 UA_SL_handleOpenSecureChannelRequest(UA_SL_Channel *channel, void* obj) {
+	UA_Int32 retval;
+	puts("UA_OPENSECURECHANNELREQUEST");
+
+	UA_OpenSecureChannelRequest* p = (UA_OpenSecureChannelRequest*) obj;
+
+	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;
 		}
-
-		UA_Int32 namespace_index = UA_toIndex(
-				serviceRequestType.identifier.numeric);
-		if (namespace_index == -1) {
-			printf(
-					"SL_processMessage - unknown request, namespace=%d, request=%d\n",
-					serviceRequestType.namespace,
-					serviceRequestType.identifier.numeric);
+		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;
-		} else {
-			void * obj;
-			UA_[namespace_index].new(&obj);
-			UA_[namespace_index].decode(msg->data, &pos, obj);
-
-			// FXIME: we need a more clever response/request architecture
-			switch (serviceRequestType.identifier.numeric) {
-			case UA_GETENDPOINTSREQUEST_NS0: {
-				puts("UA_GETENDPOINTSREQUEST");
-
-				UA_GetEndpointsRequest* p = (UA_GetEndpointsRequest*) obj;
-				UA_NodeId responseType;
-				UA_GetEndpointsResponse* r;
-
-				UA_String_printx("endpointUrl=", &(p->endpointUrl));
-				UA_GetEndpointsResponse_new(&r);
-				r->responseHeader.requestHandle =
-						p->requestHeader.requestHandle;
-				r->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
-				r->responseHeader.stringTableSize = 0;
-				r->responseHeader.timestamp = UA_DateTime_now();
-
-				r->endpointsSize = 1;
-				UA_Array_new((void**) &(r->endpoints),r->endpointsSize,UA_ENDPOINTDESCRIPTION);
-
-				UA_String_copycstring("tcp.opc://localhost:16664/",
-						&(r->endpoints[0]->endpointUrl));
-				// FIXME: This should be a feature of the application
-				UA_String_copycstring("http://open62541.info/applications/4711",
-						&(r->endpoints[0]->server.applicationUri));
-				UA_String_copycstring("http://open62541.info/product/release",
-						&(r->endpoints[0]->server.productUri));
-				// FIXME: This should be a feature of the application
-				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
-
-				// Now let's build the response
-				UA_ByteString response;
-				responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
-				responseType.namespace = 0;
-				responseType.identifier.numeric = 431; // GetEndpointsResponse_Encoding_DefaultBinary
-
-				response.length = UA_NodeId_calcSize(&responseType)
-						+ UA_GetEndpointsResponse_calcSize(r);
-				UA_alloc((void**)&(response.data), response.length);
-				pos = 0;
-
-				UA_NodeId_encode(&responseType, &pos, response.data);
-				UA_GetEndpointsResponse_encode(r, &pos, response.data);
-
-				SL_send(sc, &response, 431);
-
-				UA_ByteString_deleteMembers(&response);
-				UA_GetEndpointsResponse_delete(r);
-				retval = UA_SUCCESS;
-			}
-				break;
-
-			case UA_CREATESESSIONREQUEST_NS0: {
-				puts("UA_CREATESESSIONREQUEST");
-
-				UA_CreateSessionRequest* p = (UA_CreateSessionRequest*) obj;
-				UA_NodeId responseType;
-				UA_CreateSessionResponse* r;
-
-				UA_CreateSessionResponse_new(&r);
-				r->responseHeader.requestHandle =
-						p->requestHeader.requestHandle;
-				r->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
-				r->responseHeader.stringTableSize = 0;
-				r->responseHeader.timestamp = UA_DateTime_now();
-
-				// FIXME: create session
-
-				// Now let's build the response
-				UA_ByteString response;
-				responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
-				responseType.namespace = 0;
-				responseType.identifier.numeric = 464; // CreateSessionResponse_Encoding_DefaultBinary
-
-				response.length = UA_NodeId_calcSize(&responseType)
-						+ UA_CreateSessionResponse_calcSize(r);
-				UA_alloc((void**)&(response.data), response.length);
-				pos = 0;
-
-				UA_NodeId_encode(&responseType, &pos, response.data);
-				UA_CreateSessionResponse_encode(r, &pos, response.data);
-
-				SL_send(sc, &response, responseType.identifier.numeric);
-
-				UA_ByteString_deleteMembers(&response);
-				UA_CreateSessionResponse_delete(r);
-
-				retval = UA_SUCCESS;
-			}
-				break;
-
-			case UA_CLOSESECURECHANNELREQUEST_NS0: {
-				puts("UA_CLOSESECURECHANNELREQUEST");
-
-				// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
-				sc->tlc->connectionState = connectionState_CLOSE;
-				retval = UA_SUCCESS;
-			}
-				break;
-			case UA_OPENSECURECHANNELREQUEST_NS0: {
-				puts("UA_OPENSECURECHANNELREQUEST");
-
-				UA_OpenSecureChannelRequest* p =
-						(UA_OpenSecureChannelRequest*) obj;
-
-				if (p->clientProtocolVersion
-						!= 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 (sc->connectionState
-							== connectionState_ESTABLISHED) {
-						printf("SL_processMessage - multiply 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 (sc->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:
-					sc->remoteNonce.data = NULL;
-					sc->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;
-				}
-
-				retval |= SL_openSecureChannel(sc, &(p->requestHeader),
-						UA_STATUSCODE_GOOD);
-			}
-				break;
-			} // end switch over known messages
-			retval |= UA_[namespace_index].delete(obj);
+			break;
 		}
-	} else {
-		printf(
-				"SL_processMessage - unknown request, namespace=%d, request=%d\n",
-				serviceRequestType.namespace,
-				serviceRequestType.identifier.numeric);
-		retval = UA_ERROR;
+		printf("TODO: create new token for an existing SecureChannel\n");
+	break;
 	}
+
+	switch (p->securityMode) {
+	case UA_SECURITYMODE_INVALID:
+		channel->remoteNonce.data = 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;
+	}
+
+	retval |= SL_openSecureChannel(channel, &(p->requestHeader), UA_STATUSCODE_GOOD);
 	return retval;
 }
 
-// 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 */
-UA_Int32 SL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType) {
-	UA_SecureConversationMessageHeader secureConvHeader;
-	UA_AsymmetricAlgorithmSecurityHeader asymAlgSecHeader;
-	UA_SequenceHeader sequenceHeader;
+typedef struct T_UA_SL_handleRequestTableEntry {
+	UA_Int32 methodNodeId;
+	UA_Int32 dataTypeId;
+	UA_Int32 (*handleRequest)(UA_SL_Channel*,void*);
+} UA_SL_handleRequestTableEntry;
+
+UA_SL_handleRequestTableEntry hrt[] = {
+		{452, UA_CLOSESECURECHANNELREQUEST, UA_SL_handleCloseSecureChannelRequest},
+		{446, UA_OPENSECURECHANNELREQUEST, UA_SL_handleOpenSecureChannelRequest},
+		{428, UA_GETENDPOINTSREQUEST, UA_SL_handleGetEndpointsRequest},
+		{461, UA_CREATESESSIONREQUEST, UA_SL_handleCreateSessionRequest}
+};
+
+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].methodNodeId) {
+			return &hrt[i];
+		}
+	}
+	return UA_NULL;
+}
+
+UA_Int32 UA_SL_handleRequest(UA_SL_Channel *channel, UA_ByteString* msg) {
+	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 pos = 0;
 
-	DBG_VERBOSE_printf("SL_receive - entered \n");
-	switch (messageType) {
-		case UA_MESSAGETYPE_OPN:
-			DBG_VERBOSE_printf("SL_receive - process OPN\n");
+	// Every Message starts with a NodeID which names the serviceRequestType
+	UA_NodeId serviceRequestType;
+	UA_NodeId_decode(msg->data, &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 * obj;
+		UA_[hrte->dataTypeId].new(&obj);
+		UA_[hrte->dataTypeId].decode(msg->data, &pos, obj);
+		hrte->handleRequest(channel, obj);
+		retval |= UA_[hrte->dataTypeId].delete(obj);
+	}
+	return retval;
+}
 
-			UA_SecureConversationMessageHeader_decode(msg->data, &pos, &secureConvHeader);
+// FIXME: we need to associate secure channels with the connection
+UA_SL_Channel slc;
 
-			UA_AsymmetricAlgorithmSecurityHeader_decode(
-					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));
+UA_Int32 UA_SL_Channel_new(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32* pos) {
+	UA_Int32 retval = UA_SUCCESS;
 
-//			if (secureConvHeader.secureChannelId != 0) {
-//				UA_Int32 iTmp = UA_ByteString_compare(
+	UA_SecureConversationMessageHeader secureConvHeader;
+	DBG_VERBOSE(printf("UA_SL_Channel_new - entered\n"));
+
+	// FIXME: generate new secure channel
+	connection->secureChannel = &slc;
+	connection->secureChannel->tlConnection = connection;
+
+	UA_SecureConversationMessageHeader_decode(msg->data, pos, &secureConvHeader);
+	// connection->secureChannel->secureChannelId = secureConvHeader.secureChannelId;
+	UA_AsymmetricAlgorithmSecurityHeader_decode(msg->data, pos, &(connection->secureChannel->remoteAsymAlgSettings));
+	//TODO check that the sequence number is smaller than MaxUInt32 - 1024
+	UA_SequenceHeader_decode(msg->data, pos, &(connection->secureChannel->sequenceHeader));
+
+	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));
+	DBG_VERBOSE(printf("SL_receive - SequenceHeader.RequestId=%d\n",connection->secureChannel->sequenceHeader.requestId));
+	DBG_VERBOSE(printf("SL_receive - SequenceHeader.SequenceNr=%d\n",connection->secureChannel->sequenceHeader.sequenceNumber));
+
+// FIXME: reject
+//	if (secureConvHeader.secureChannelId != 0) {
+//		UA_Int32 iTmp = UA_ByteString_compare(
 //								&(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
 //								&(asymAlgSecHeader.senderCertificate));
 //				if (iTmp != UA_EQUAL) {
@@ -462,62 +429,39 @@ UA_Int32 SL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 m
 //				//TODO invalid securechannelId
 //			}
 
-			UA_SequenceHeader_decode(msg->data, &pos,
-					&sequenceHeader);
-			DBG_VERBOSE_printf("SL_receive - SequenceHeader.RequestId=%d\n",
-					sequenceHeader.requestId);
-			DBG_VERBOSE_printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
-					sequenceHeader.sequenceNumber);
-			//
-			slc.requestId = sequenceHeader.requestId;
-			//TODO check that the sequence number is smaller than MaxUInt32 - 1024
-			slc.sequenceNumber = sequenceHeader.sequenceNumber;
+	UA_ByteString slMessage;
+	slMessage.data  = &(msg->data[*pos]);
+	slMessage.length = msg->length - *pos;
+	retval |= UA_SL_handleRequest(connection->secureChannel, &slMessage);
+	return retval;
+}
 
-			UA_ByteString slMessage;
-			slMessage.data  = &(msg->data[pos]);
-			slMessage.length = msg->length - pos;
-			UA_ByteString_printx("SL_receive - message=", &slMessage);
+/** process data as we've got it from the transport layer */
+UA_Int32 UA_SL_process(UA_SL_Channel* connection, UA_ByteString* msg, UA_Int32* pos) {
 
-			SL_processMessage(&slc, &slMessage);
-			// Clean up
-			UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(
-					&asymAlgSecHeader);
+	DBG_VERBOSE(printf("UA_SL_process - entered \n"));
 
-			UA_SecureConversationMessageHeader_deleteMembers(&secureConvHeader);
-			break;
-		case UA_MESSAGETYPE_MSG:
-		case UA_MESSAGETYPE_CLO:
 // FIXME: check connection state
-//			if (connection->secureLayer.connectionState
-//					== connectionState_ESTABLISHED) {
-			if (secureConvHeader.secureChannelId
-					== slc.securityToken.secureChannelId) {
-				UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
-
-				//FIXME: we assume SAS, need to check if AAS or SAS
-				UA_SymmetricAlgorithmSecurityHeader_decode(
-						msg->data, &pos, &symAlgSecHeader);
-
-				// decode sequenceHeader and remember
-				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);
-				slc.requestId = sequenceHeader.requestId;
-				slc.sequenceNumber = sequenceHeader.sequenceNumber;
-				// process 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;
+	if (connection->connectionState == connectionState_ESTABLISHED) {
+		UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
+
+		//FIXME: we assume SAS, need to check if AAS or SAS
+		if (connection->securityMode == UA_MESSAGESECURITYMODE_NONE) {
+			UA_SymmetricAlgorithmSecurityHeader_decode(msg->data, pos, &symAlgSecHeader);
+		} else {
+			// FIXME:
+		}
+
+		if (symAlgSecHeader == connection->securityToken.tokenId) {
+			UA_SequenceHeader_decode(msg->data, 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;
 }
-

+ 2 - 2
src/opcua_secureLayer.h

@@ -27,6 +27,6 @@ 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 SL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType);
-
+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_ */

+ 110 - 80
src/opcua_transportLayer.c

@@ -11,35 +11,35 @@
 
 #include "opcua_secureLayer.h" // SL_process
 
-UA_Int32 TL_Connection_init(UA_TL_connection *c, UA_TL_Description* tld)
+UA_Int32 TL_Connection_init(UA_TL_connection* c, UA_TL_Description* tld)
 {
-	c->socket = -1;
+	c->connectionHandle = -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));
+	UA_String_init(&(c->localEndpointUrl));
 	return UA_SUCCESS;
 }
 
-UA_Int32 TL_check(UA_TL_connection *connection, UA_ByteString* msg, int checkLocal)
+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");
+	DBG_VERBOSE(printf("TL_check - entered \n"));
 
 	UA_Int32_decode(msg->data,&position,&messageLength);
-	DBG_VERBOSE_printf("TL_check - messageLength = %d \n",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))
 	{
-		DBG_ERR_printf("TL_check - length error \n");
+		DBG_ERR(printf("TL_check - length error \n"));
 		retval = UA_ERR_INCONSISTENT;
 	}
 	return retval;
@@ -47,112 +47,142 @@ UA_Int32 TL_check(UA_TL_connection *connection, UA_ByteString* msg, int checkLoc
 
 #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_TL_connection *connection, UA_ByteString* msg)
-{
+UA_Int32 UA_TL_handleHello(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
 	UA_Int32 retval = UA_SUCCESS;
-	UA_Int32 pos = 0;
+
 	UA_Int32 tmpPos = 0;
 	UA_ByteString tmpMessage;
-	UA_OPCUATcpMessageHeader tcpMessageHeader;
 	UA_OPCUATcpHelloMessage helloMessage;
 	UA_OPCUATcpAcknowledgeMessage ackMessage;
 	UA_OPCUATcpMessageHeader ackHeader;
 
-	DBG_VERBOSE_printf("TL_process - entered \n");
-
-	retval = UA_OPCUATcpMessageHeader_decode(msg->data, &pos, &tcpMessageHeader);
-
-	if (retval == UA_SUCCESS) {
-	switch(tcpMessageHeader.messageType)
+	if (connection->connectionState == connectionState_CLOSED) {
+		DBG_VERBOSE(printf("TL_process - extracting header information \n"));
+		UA_OPCUATcpHelloMessage_decode(msg->data,pos,&helloMessage);
+
+		// memorize buffer info and change mode to established
+		connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
+		connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
+		connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
+		connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
+		connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
+		UA_String_copy(&(helloMessage.endpointUrl), &(connection->remoteEndpointUrl));
+		connection->connectionState = connectionState_ESTABLISHED;
+		// clean up
+		UA_OPCUATcpHelloMessage_deleteMembers(&helloMessage);
+
+		DBG_VERBOSE(printf("TL_process - protocolVersion = %d \n",connection->remoteConf.protocolVersion));
+		DBG_VERBOSE(printf("TL_process - recvBufferSize = %d \n",connection->remoteConf.recvBufferSize));
+		DBG_VERBOSE(printf("TL_process - sendBufferSize = %d \n",connection->remoteConf.sendBufferSize));
+		DBG_VERBOSE(printf("TL_process - maxMessageSize = %d \n",connection->remoteConf.maxMessageSize));
+		DBG_VERBOSE(printf("TL_process - maxChunkCount = %d \n",connection->remoteConf.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';
+
+		// encode header and message to buffer
+		ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSize(&ackMessage)
+		+ UA_OPCUATcpMessageHeader_calcSize(&ackHeader);
+		UA_ByteString_newMembers(&tmpMessage, ackHeader.messageSize);
+		UA_OPCUATcpMessageHeader_encode(&ackHeader,&tmpPos,tmpMessage.data);
+		UA_OPCUATcpAcknowledgeMessage_encode(&ackMessage,&tmpPos,tmpMessage.data);
+
+		DBG_VERBOSE(printf("TL_process - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos));
+		TL_send(connection, &tmpMessage);
+		UA_ByteString_deleteMembers(&tmpMessage);
+	}
+	else
 	{
-	case UA_MESSAGETYPE_HEL:
-		if (connection->connectionState == connectionState_CLOSED)
-		{
-			DBG_VERBOSE_printf("TL_process - extracting header information \n");
-
-			UA_OPCUATcpHelloMessage_decode(msg->data,&pos,&helloMessage);
-
-			/* extract information from received header */
-			connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
-			DBG_VERBOSE_printf("TL_process - protocolVersion = %d \n",connection->remoteConf.protocolVersion);
-
-			connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
-			DBG_VERBOSE_printf("TL_process - recvBufferSize = %d \n",connection->remoteConf.recvBufferSize);
-
-			connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
-			DBG_VERBOSE_printf("TL_process - sendBufferSize = %d \n",connection->remoteConf.sendBufferSize);
-
-			connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
-			DBG_VERBOSE_printf("TL_process - maxMessageSize = %d \n",connection->remoteConf.maxMessageSize);
-
-			connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
-			DBG_VERBOSE_printf("TL_process - maxChunkCount = %d \n",connection->remoteConf.maxChunkCount);
-
-			UA_String_copy(&(helloMessage.endpointUrl), &(connection->endpointUrl));
+		DBG_ERR(printf("TL_process - wrong connection state \n"));
+		retval = UA_ERROR_MULTIPLE_HEL;
+	}
+	return retval;
+}
 
-			// Clean up
-			UA_OPCUATcpHelloMessage_deleteMembers(&helloMessage);
+UA_Int32 UA_TL_handleOpen(UA_TL_connection* connection, UA_ByteString* msg, UA_Int32* pos) {
+	UA_Int32 retval = UA_SUCCESS;
 
-			// 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;
+	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 retval;
+}
 
-			ackHeader.messageType = UA_MESSAGETYPE_ACK;
-			ackHeader.isFinal = 'F';
-			ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSize(&ackMessage)
-			+ UA_OPCUATcpMessageHeader_calcSize(&ackHeader);
+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;
+}
 
-			// allocate memory for encoding
-			UA_alloc((void**)&(tmpMessage.data),ackHeader.messageSize);
-			tmpMessage.length = ackHeader.messageSize;
+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);
+	connection->connectionState = connectionState_CLOSE;
+	return retval;
+}
 
-			//encode header and message
-			UA_OPCUATcpMessageHeader_encode(&ackHeader,&tmpPos,tmpMessage.data);
-			UA_OPCUATcpAcknowledgeMessage_encode(&ackMessage,&tmpPos,tmpMessage.data);
+UA_Int32 TL_process(UA_TL_connection* connection, UA_ByteString* msg)
+{
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 pos = 0;
+	UA_OPCUATcpMessageHeader tcpMessageHeader;
 
-			DBG_VERBOSE_printf("TL_process - Size messageToSend = %d, pos=%d\n",ackHeader.messageSize, tmpPos);
-			connection->connectionState = connectionState_OPENING;
-			TL_send(connection, &tmpMessage);
-			UA_ByteString_deleteMembers(&tmpMessage);
+	DBG_VERBOSE(printf("TL_process - entered \n"));
+
+	if ((retval = UA_OPCUATcpMessageHeader_decode(msg->data, &pos, &tcpMessageHeader)) == UA_SUCCESS) {
+		switch(tcpMessageHeader.messageType) {
+		case UA_MESSAGETYPE_HEL:
+			retval = UA_TL_handleHello(connection, msg, &pos);
+			break;
+		case UA_MESSAGETYPE_OPN:
+			retval = UA_TL_handleOpen(connection, msg, &pos);
+			break;
+		case UA_MESSAGETYPE_MSG:
+			retval = UA_TL_handleMsg(connection, msg, &pos);
+			break;
+		case UA_MESSAGETYPE_CLO:
+			retval = UA_TL_handleClo(connection, msg, &pos);
+			break;
+		default: // dispatch processing to secureLayer
+			retval = UA_ERR_INVALID_VALUE;
+			break;
 		}
-		else
-		{
-			DBG_ERR_printf("TL_process - wrong connection state \n");
-			retval = UA_ERROR_MULTIPLY_HEL;
-		}
-		break;
-	default: // dispatch processing to secureLayer
-		if ((connection->connectionState != connectionState_CLOSED)) {
-			retval = SL_process(connection, msg, tcpMessageHeader.messageType);
-		} else {
-			retval = UA_ERROR;
-		}
-		break;
-	}
 	}
 	if (retval != UA_SUCCESS) {
+		// FIXME: compose real error message
 		UA_ByteString errorMsg;
-		UA_ByteString_init(&errorMsg);
+		UA_ByteString_newMembers(&errorMsg,10);
 		TL_send(connection,&errorMsg);
 		UA_ByteString_deleteMembers(&errorMsg);
 	}
+	UA_OPCUATcpMessageHeader_deleteMembers(&tcpMessageHeader);
 	return retval;
 }
+
 /** respond to client request */
 UA_Int32 TL_send(UA_TL_connection* connection, UA_ByteString* msg)
 {
 	UA_Int32 retval = UA_SUCCESS;
-	DBG_VERBOSE_printf("TL_send - entered \n");
+	DBG_VERBOSE(printf("TL_send - entered \n"));
 
 	if (TL_check(connection,msg,UA_TL_CHECK_REMOTE) == UA_SUCCESS) {
 		connection->UA_TL_writer(connection,msg);
 	}
 	else
 	{
-		DBG_ERR_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;

+ 1 - 1
src/opcua_transportLayer.h

@@ -18,7 +18,7 @@
 #include "tcp_layer.h"
 /*------------------Defined Error Codes------------------*/
 //transport errors begin at 1000
-#define UA_ERROR_MULTIPLY_HEL 1000
+#define UA_ERROR_MULTIPLE_HEL 1000
 #define UA_ERROR_RCV_ERROR 1001