Browse Source

unified message handling

Leon Urbas 11 years ago
parent
commit
95e9aef999
4 changed files with 382 additions and 421 deletions
  1. 59 69
      examples/src/opcuaServer.c
  2. 1 1
      src/UA_connection.h
  3. 321 350
      src/opcua_secureLayer.c
  4. 1 1
      tool/generate_namespace.py

+ 59 - 69
examples/src/opcuaServer.c

@@ -12,7 +12,6 @@
 #include <stdlib.h>
 #include <memory.h> // bzero
 
-
 #include "opcua.h"
 #include "opcua_transportLayer.h"
 
@@ -32,8 +31,7 @@ void server_run();
 #define MAXMSG  512
 #define BUFFER_SIZE 8192
 
-int main(void)
-{
+int main(void) {
 
 #ifdef LINUX
 	server_init();
@@ -46,24 +44,22 @@ int main(void)
 
 #ifdef LINUX
 
-void server_init()
-{
+void server_init() {
 	printf("Starting open62541 demo server on port %d\n", PORT);
 	//call listen
 
 }
 
-void server_run()
-{
+void server_run() {
 	UA_connection connection;
 
-        UA_ByteString slMessage = {-1,UA_NULL};
+	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;
+	int n;
 
 	TL_initConnectionObject(&connection);
 	SL_initConnectionObject(&connection);
@@ -71,8 +67,7 @@ void server_run()
 	/* First call to socket() function */
 	// sockfd = socket(AF_INET, SOCK_STREAM, 0);
 	sockfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (sockfd < 0)
-	{
+	if (sockfd < 0) {
 		perror("ERROR opening socket");
 		exit(1);
 	}
@@ -84,76 +79,71 @@ void server_run()
 	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);
+	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);
+	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);
+	 * go in sleep mode and will wait for the incoming connection
+	 */
+	listen(sockfd, 5);
 	clilen = sizeof(cli_addr);
 
 	/* Accept actual connection from the client */
-	newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr,
-								&clilen);
-	if (newsockfd < 0)
-	{
-		perror("ERROR on accept");
-		exit(1);
-	}
-
-	printf("One connection accepted\n");
-	while(1)
-	{
-		/* 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");
+	while (1) {
+		newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
+		if (newsockfd < 0) {
+			perror("ERROR on accept");
 			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;
+		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;
 		}
-
-		connection.readData.data = NULL;
-		connection.readData.length = 0;
-		connection.newDataToRead = 0;
-
+		close(newsockfd);
+		connection.transportLayer.connectionState = connectionState_CLOSED;
 	}
-  }
-
-
+}
 
 #endif

+ 1 - 1
src/UA_connection.h

@@ -24,7 +24,7 @@ enum connectionState
 	connectionState_CLOSED,
 	connectionState_OPENING,
 	connectionState_ESTABLISHED,
-
+	connectionState_CLOSE,
 };
 
 typedef struct

+ 321 - 350
src/opcua_secureLayer.c

@@ -6,6 +6,7 @@
  */
 #include <stdio.h>
 #include <memory.h> // memcpy
+#include "opcua.h"
 #include "opcua_transportLayer.h"
 #include "opcua_secureLayer.h"
 #include "UA_stackInternalTypes.h"
@@ -13,16 +14,17 @@
 #define SIZE_SECURECHANNEL_HEADER 12
 #define SIZE_SEQHEADER_HEADER 8
 
-
 /*
  * inits a connection object for secure channel layer
  */
-UA_Int32 SL_initConnectionObject(UA_connection *connection)
-{
-	UA_AsymmetricAlgorithmSecurityHeader_init(&(connection->secureLayer.localAsymAlgSettings));
-	UA_ByteString_copy(&UA_ByteString_securityPoliceNone, &(connection->secureLayer.localAsymAlgSettings.securityPolicyUri));
-
-	UA_alloc((void**)&(connection->secureLayer.localNonce.data),sizeof(UA_Byte));
+UA_Int32 SL_initConnectionObject(UA_connection *connection) {
+	UA_AsymmetricAlgorithmSecurityHeader_init(
+			&(connection->secureLayer.localAsymAlgSettings));
+	UA_ByteString_copy(&UA_ByteString_securityPoliceNone,
+			&(connection->secureLayer.localAsymAlgSettings.securityPolicyUri));
+
+	UA_alloc((void**)&(connection->secureLayer.localNonce.data),
+			sizeof(UA_Byte));
 	connection->secureLayer.localNonce.length = 1;
 
 	connection->secureLayer.connectionState = connectionState_CLOSED;
@@ -43,8 +45,8 @@ UA_Int32 SL_initConnectionObject(UA_connection *connection)
 	return UA_NO_ERROR;
 }
 
-UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessage, UA_Int32 type)
-{
+UA_Int32 SL_send(UA_connection* connection,
+		UA_ByteString const * responseMessage, UA_Int32 type) {
 	UA_UInt32 sequenceNumber;
 	UA_UInt32 requestId;
 	UA_Int32 pos;
@@ -56,24 +58,24 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
 	// FIXME: this is a to dump method to determine asymmetric algorithm setting
 	UA_Int32 isAsym = (type == 449);
 
-
 	pos = 0;
 	//sequence header
 	sequenceNumber = connection->secureLayer.sequenceNumber;
-    requestId = connection->secureLayer.requestId;
+	requestId = connection->secureLayer.requestId;
 
-    sizePadding = 0;
+	sizePadding = 0;
 	sizeSignature = 0;
 
-	packetSize = SIZE_SECURECHANNEL_HEADER +
-				SIZE_SEQHEADER_HEADER +
-				( isAsym ? UA_AsymmetricAlgorithmSecurityHeader_calcSize(&(connection->secureLayer.localAsymAlgSettings)) : UA_SymmetricAlgorithmSecurityHeader_calcSize(&(connection->secureLayer.securityToken.tokenId)) )+
-				responseMessage->length +
-				sizePadding +
-				sizeSignature;
+	packetSize = SIZE_SECURECHANNEL_HEADER + SIZE_SEQHEADER_HEADER
+			+ (isAsym ?
+					UA_AsymmetricAlgorithmSecurityHeader_calcSize(
+							&(connection->secureLayer.localAsymAlgSettings)) :
+					UA_SymmetricAlgorithmSecurityHeader_calcSize(
+							&(connection->secureLayer.securityToken.tokenId)))
+			+ responseMessage->length + sizePadding + sizeSignature;
 
 	//get memory for response
-	UA_alloc((void**)&(responsePacket.data),packetSize);
+	UA_alloc((void**)&(responsePacket.data), packetSize);
 	responsePacket.length = packetSize;
 
 	/*---encode Secure Conversation Message Header ---*/
@@ -91,29 +93,35 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
 	pos += 3;
 	responsePacket.data[3] = 'F';
 	pos += 1;
-	UA_Int32_encode(&packetSize,&pos,responsePacket.data);
-	UA_UInt32_encode(&(connection->secureLayer.securityToken.secureChannelId),&pos,responsePacket.data);
+	UA_Int32_encode(&packetSize, &pos, responsePacket.data);
+	UA_UInt32_encode(&(connection->secureLayer.securityToken.secureChannelId),
+			&pos, responsePacket.data);
 
 	/*---encode Algorithm Security Header ---*/
-	if (isAsym)	{
-		UA_AsymmetricAlgorithmSecurityHeader_encode(&(connection->secureLayer.localAsymAlgSettings),&pos,responsePacket.data);
+	if (isAsym) {
+		UA_AsymmetricAlgorithmSecurityHeader_encode(
+				&(connection->secureLayer.localAsymAlgSettings), &pos,
+				responsePacket.data);
 	} else {
-		UA_SymmetricAlgorithmSecurityHeader_encode(&(connection->secureLayer.securityToken.tokenId),&pos,responsePacket.data);
+		UA_SymmetricAlgorithmSecurityHeader_encode(
+				&(connection->secureLayer.securityToken.tokenId), &pos,
+				responsePacket.data);
 	}
 
 	/*---encode Sequence Header ---*/
-	UA_UInt32_encode(&sequenceNumber,&pos,responsePacket.data);
-	UA_UInt32_encode(&requestId,&pos,responsePacket.data);
+	UA_UInt32_encode(&sequenceNumber, &pos, responsePacket.data);
+	UA_UInt32_encode(&requestId, &pos, responsePacket.data);
 
 	/*---add encoded Message ---*/
-	UA_memcpy(&(responsePacket.data[pos]), responseMessage->data, responseMessage->length);
+	UA_memcpy(&(responsePacket.data[pos]), responseMessage->data,
+			responseMessage->length);
 
 	/* sign Data*/
 
 	/* encrypt Data*/
 
 	/* send Data */
-	TL_send(connection,&responsePacket);
+	TL_send(connection, &responsePacket);
 	// responsePackage will be deleted by top-level procedure
 	return UA_NO_ERROR;
 }
@@ -122,38 +130,27 @@ UA_Int32 SL_send(UA_connection* connection, UA_ByteString const * responseMessag
  * opens a secure channel
  */
 UA_Int32 SL_openSecureChannel(UA_connection *connection,
-		UA_RequestHeader *requestHeader,
-		UA_StatusCode serviceResult)
-{
-
+		UA_RequestHeader *requestHeader, UA_StatusCode serviceResult) {
 
-
-	UA_ResponseHeader responseHeader;
-	UA_ExtensionObject additionalHeader;
-	UA_ChannelSecurityToken securityToken;
-	UA_ByteString serverNonce;
+	UA_OpenSecureChannelResponse* r;
 	UA_NodeId responseType;
-	//sizes for memory allocation
-	// UA_Int32 sizeResponse;
-	UA_Int32 sizeRespHeader;
-	UA_Int32 sizeResponseType;
-	UA_Int32 sizeRespMessage;
-	// UA_Int32 sizeSecurityToken;
 	UA_ByteString response;
-	UA_UInt32 serverProtocolVersion;
 	UA_Int32 pos;
-	UA_DiagnosticInfo serviceDiagnostics;
 
-	if(requestHeader->returnDiagnostics != 0)
-	{
+	UA_OpenSecureChannelResponse_new(&r);
+	UA_ResponseHeader_new(&(r->responseHeader));
+	UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
+	UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
+	UA_ChannelSecurityToken_new(&(r->securityToken));
+
+	if (requestHeader->returnDiagnostics != 0) {
 		printf("SL_openSecureChannel - diagnostics demanded by the client\n");
-		printf("SL_openSecureChannel - retrieving diagnostics not implemented!\n");
+		printf(
+				"SL_openSecureChannel - retrieving diagnostics not implemented!\n");
 		//TODO fill with demanded information part 4, 7.8 - Table 123
-		serviceDiagnostics.encodingMask = 0;
-	}
-	else
-	{
-		serviceDiagnostics.encodingMask = 0;
+		r->responseHeader->serviceDiagnostics->encodingMask = 0;
+	} else {
+		r->responseHeader->serviceDiagnostics->encodingMask = 0;
 	}
 	/*--------------type ----------------------*/
 
@@ -164,103 +161,36 @@ UA_Int32 SL_openSecureChannel(UA_connection *connection,
 	responseType.namespace = 0;
 
 	/*--------------responseHeader-------------*/
-
-	/* 	Res-1) ResponseHeader responseHeader
-	 * 		timestamp UtcTime
-	 * 		requestHandle IntegerId
-	 * 		serviceResult StatusCode
-	 * 		serviceDiagnostics DiagnosticInfo
-	 * 		stringTable[] String
-	 * 		addtionalHeader Extensible Parameter
-	 */
-	//current time
-
-	responseHeader.timestamp = UA_DateTime_now();
-	//request Handle which client sent
-	responseHeader.requestHandle = requestHeader->requestHandle;
-	// StatusCode which informs client about quality of response
-	responseHeader.serviceResult = serviceResult;
-	//retrieve diagnosticInfo if client demands
-	responseHeader.serviceDiagnostics = &serviceDiagnostics;
+	r->responseHeader->timestamp = UA_DateTime_now();
+	r->responseHeader->requestHandle = requestHeader->requestHandle;
+	r->responseHeader->serviceResult = serviceResult;
 
 	//text of fields defined in the serviceDiagnostics
-	responseHeader.stringTableSize = 0;
-	responseHeader.stringTable = NULL;
+	r->responseHeader->stringTableSize = 0;
+	r->responseHeader->stringTable = UA_NULL;
 
+	r->serverProtocolVersion =
+			connection->transportLayer.localConf.protocolVersion;
 
-	// no additional header
-	additionalHeader.encoding = 0;
-
-	additionalHeader.body.data = NULL;
-	additionalHeader.body.length = 0;
-
-	additionalHeader.typeId.encodingByte = 0;
-	additionalHeader.typeId.namespace = 0;
-	additionalHeader.typeId.identifier.numeric = 0;
-
-	responseHeader.additionalHeader = &additionalHeader;
-	printf("SL_openSecureChannel - built response header\n");
-
-	//calculate the size
-	sizeRespHeader = UA_ResponseHeader_calcSize(&responseHeader);
-	printf("SL_openSecureChannel - size response header =%d\n",sizeRespHeader);
-	/*--------------responseMessage-------------*/
-	/* 	Res-2) UInt32 ServerProtocolVersion
-	 * 	Res-3) SecurityToken channelSecurityToken
-	 *  Res-5) ByteString ServerNonce
-	*/
-	serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
-
-	securityToken.channelId = connection->secureLayer.securityToken.secureChannelId;
-	securityToken.tokenId = connection->secureLayer.securityToken.tokenId;
-	securityToken.createdAt = UA_DateTime_now();
-	securityToken.revisedLifetime = connection->secureLayer.securityToken.revisedLifetime;
-
-	serverNonce.length = connection->secureLayer.localNonce.length;
-	serverNonce.data = connection->secureLayer.localNonce.data;
-
-	// ProtocolVersion + SecurityToken + ServerNonce
-	sizeRespMessage = sizeof(UA_UInt32) +
-			UA_ChannelSecurityToken_calcSize(&securityToken) +
-			UA_ByteString_calcSize(&serverNonce);
-	printf("SL_openSecureChannel - size of response message=%d\n",sizeRespMessage);
-
-	//get memory for response
-	sizeResponseType = UA_NodeId_calcSize(&responseType);
-	printf("SL_openSecureChannel - size response type =%d\n",sizeResponseType);
+	r->securityToken->channelId =
+			connection->secureLayer.securityToken.secureChannelId;
+	r->securityToken->tokenId = connection->secureLayer.securityToken.tokenId;
+	r->securityToken->createdAt = UA_DateTime_now();
+	r->securityToken->revisedLifetime =
+			connection->secureLayer.securityToken.revisedLifetime;
 
-	response.length = sizeResponseType + sizeRespHeader + sizeRespMessage;
+	UA_ByteString_copy(&(connection->secureLayer.localNonce), &(r->serverNonce));
 
 	//get memory for response
+	response.length = UA_NodeId_calcSize(&responseType) + UA_OpenSecureChannelResponse_calcSize(r);
 	UA_alloc((void*)&(response.data), response.length);
 	pos = 0;
-	//encode responseType (NodeId)
-	UA_NodeId_printf("SL_openSecureChannel - TypeId =",&responseType);
-
 	UA_NodeId_encode(&responseType, &pos, response.data);
+	UA_OpenSecureChannelResponse_encode(r, &pos, response.data);
 
-	//encode header
-	printf("SL_openSecureChannel - encoding response header \n");
-
-	UA_ResponseHeader_encode(&responseHeader, &pos, response.data);
-	printf("SL_openSecureChannel - response header encoded \n");
-
-	//encode message
-	printf("SL_openSecureChannel - serverProtocolVersion = %d \n",serverProtocolVersion);
-	UA_UInt32_encode(&serverProtocolVersion, &pos,response.data);
-
-	UA_ChannelSecurityToken_encode(&securityToken,&pos,response.data);
-
-	UA_ByteString_encode(&serverNonce, &pos,response.data);
-
-	printf("SL_openSecureChannel - response.length = %d \n",response.length);
-
-	printf("-----> reserved: %i\n", response.length);
-	printf("-----> encoded: %i\n", pos);
-
-	//449 = openSecureChannelResponse
 	SL_send(connection, &response, 449);
 	UA_ByteString_deleteMembers(&response);
+	UA_OpenSecureChannelResponse_delete(r);
 
 	return UA_SUCCESS;
 }
@@ -283,196 +213,238 @@ UA_Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 	UA_NodeId serviceRequestType;
 
 	// Every Message starts with a NodeID which names the serviceRequestType
-	UA_NodeId_decode(message.data, &pos,
-			&serviceRequestType);
+	UA_NodeId_decode(message.data, &pos, &serviceRequestType);
 	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
 			&serviceRequestType);
 
-	if (serviceRequestType.encodingByte == UA_NODEIDTYPE_FOURBYTE
-			&& serviceRequestType.identifier.numeric == 446) {
-		/* OpenSecureChannelService, defined in 62541-6 §6.4.4, Table 34.
-		 * Note that part 6 adds ClientProtocolVersion and ServerProtocolVersion
-		 * to the definition in part 4 */
-		// 	Req-1) RequestHeader requestHeader
-		UA_RequestHeader requestHeader;
-		// 	Req-2) UInt32 ClientProtocolVersion
-		UA_UInt32 clientProtocolVersion;
-		// 	Req-3) Enum SecurityTokenRequestType requestType
-		UA_Int32 requestType;
-		// 	Req-4) Enum MessageSecurityMode SecurityMode
-		UA_Int32 securityMode;
-		//  Req-5) ByteString ClientNonce
-		UA_ByteString clientNonce = {0, NULL};
-		//  Req-6) Int32 RequestLifetime
-		UA_Int32 requestedLifetime;
-
-		UA_ByteString_printx("SL_processMessage - message=", &message);
-		// Req-1) RequestHeader requestHeader
-		UA_RequestHeader_decode(message.data, &pos, &requestHeader);
-		UA_String_printf("SL_processMessage - requestHeader.auditEntryId=",
-				&(requestHeader.auditEntryId));
-		UA_NodeId_printf(
-				"SL_processMessage - requestHeader.authenticationToken=",
-				&(requestHeader.authenticationToken));
-
-		// 	Req-2) UInt32 ClientProtocolVersion
-		UA_UInt32_decode(message.data, &pos,
-				&clientProtocolVersion);
-		printf("SL_processMessage - clientProtocolVersion=%d\n",
-				clientProtocolVersion);
-
-		if (clientProtocolVersion
-				!= connection->transportLayer.remoteConf.protocolVersion) {
-			printf("SL_processMessage - error protocol version \n");
-			//TODO error protocol version
-			//TODO ERROR_Bad_ProtocolVersionUnsupported
-
+	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;
+			break;
 		}
 
-		// 	Req-3) SecurityTokenRequestType requestType
-		UA_Int32_decode(message.data, &pos, &requestType);
-		printf("SL_processMessage - requestType=%d\n", requestType);
-		switch (requestType) {
-		case UA_SECURITYTOKEN_ISSUE:
-			if (connection->secureLayer.connectionState
-					== connectionState_ESTABLISHED) {
-				printf("SL_processMessage - multiply security token request");
-				//TODO return ERROR
-				return UA_ERROR;
-			}
+		UA_Int32 namespace_index = UA_toIndex(
+				serviceRequestType.identifier.numeric);
+		if (namespace_index == -1) {
 			printf(
-					"SL_processMessage - TODO: create new token for a new SecureChannel\n");
-			//	SL_createNewToken(connection);
-			break;
-		case UA_SECURITYTOKEN_RENEW:
-			if (connection->secureLayer.connectionState
-					== connectionState_CLOSED) {
-				printf(
-						"SL_processMessage - renew token request received, but no secureChannel was established before");
-				//TODO return ERROR
-				return UA_ERROR;
+					"SL_processMessage - unknown request, namespace=%d, request=%d\n",
+					serviceRequestType.namespace,
+					serviceRequestType.identifier.numeric);
+			retval = UA_ERROR;
+		} else {
+			// decode message
+			void * obj;
+			UA_alloc(&obj, UA_[namespace_index].calcSize(UA_NULL));
+			UA_[namespace_index].decode(message.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);
+				UA_ResponseHeader_new(&(r->responseHeader));
+				r->responseHeader->requestHandle =
+						p->requestHeader->requestHandle;
+				r->responseHeader->serviceResult = SC_Good;
+				r->responseHeader->stringTableSize = 0;
+				r->responseHeader->timestamp = UA_DateTime_now();
+				UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
+				UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
+
+				// TODO: Arrays need to be redesigned, this is crap
+				r->endpointsSize = 1;
+				UA_alloc((void**) &(r->endpoints), sizeof(void*));
+				UA_EndpointDescription *epd;
+				UA_EndpointDescription_new(&epd);
+				*(r->endpoints) = epd;
+
+				// FIXME: this memory gets lost
+				UA_String_copycstring("tcp.opc://localhost:16664/",
+						&(r->endpoints[0]->endpointUrl));
+				// FIXME: this memory gets lost
+				UA_ApplicationDescription_new(&(r->endpoints[0]->server));
+				// 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(connection, &response, 431);
+
+				UA_ByteString_deleteMembers(&response);
+				UA_GetEndpointsResponse_delete(r);
+				UA_GetEndpointsRequest_delete(p);
+
+				retval = UA_SUCCESS;
 			}
-			printf("TODO: create new token for an existing SecureChannel\n");
-			break;
-		}
+				break;
 
-		// 	Req-4) MessageSecurityMode SecurityMode
-		UA_Int32_decode(message.data, &pos, &securityMode);
-		printf("SL_processMessage - securityMode=%d\n", securityMode);
-		switch (securityMode) {
-		case UA_SECURITYMODE_INVALID:
-			connection->secureLayer.remoteNonce.data = NULL;
-			connection->secureLayer.remoteNonce.length = -1;
-			printf("SL_processMessage - client demands no security \n");
-			break;
+			case UA_CREATESESSIONREQUEST_NS0: {
+				puts("UA_CREATESESSIONREQUEST");
 
-		case UA_SECURITYMODE_SIGN:
-			printf("SL_processMessage - client demands signed \n");
-			//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-			break;
+				UA_CreateSessionRequest* p = (UA_CreateSessionRequest*) obj;
+				UA_NodeId responseType;
+				UA_CreateSessionResponse* r;
 
-		case UA_SECURITYMODE_SIGNANDENCRYPT:
-			printf("SL_processMessage - client demands signed & encrypted \n");
-			//TODO check if senderCertificate and ReceiverCertificateThumbprint are present
-			break;
-		}
+				UA_CreateSessionResponse_new(&r);
+				// Header
+				UA_ResponseHeader_new(&(r->responseHeader));
+				r->responseHeader->requestHandle =
+						p->requestHeader->requestHandle;
+				r->responseHeader->serviceResult = SC_Good;
+				r->responseHeader->stringTableSize = 0;
+				r->responseHeader->timestamp = UA_DateTime_now();
+				UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
+				UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
 
-		//  Req-5) ByteString ClientNonce
-		UA_ByteString_decode(message.data, &pos,
-				&clientNonce);
-		UA_ByteString_printf("SL_processMessage - clientNonce=", &clientNonce);
+				// FIXME: create session
 
-		//deleteMembers is important since clientNonce is on stack
-		UA_ByteString_deleteMembers(&clientNonce);
+				// Now let's build the response
+				UA_ByteString response;
+				responseType.encodingByte = UA_NODEIDTYPE_FOURBYTE;
+				responseType.namespace = 0;
+				responseType.identifier.numeric = 464; // CreateSessionResponse_Encoding_DefaultBinary
 
-		//  Req-6) Int32 RequestLifetime
-		UA_Int32_decode(message.data, &pos,
-				&requestedLifetime);
-		printf("SL_processMessage - requestedLifeTime=%d\n", requestedLifetime);
-		//TODO process requestedLifetime
+				response.length = UA_NodeId_calcSize(&responseType)
+						+ UA_CreateSessionResponse_calcSize(r);
+				UA_alloc((void**)&(response.data), response.length);
+				pos = 0;
 
-		// 62541-4 §7.27 "The requestHandle given by the Client to the request."
-		retval = SL_openSecureChannel(connection, &requestHeader, SC_Good);
-		UA_RequestHeader_deleteMembers(&requestHeader);
-	} else {
-		if (serviceRequestType.namespace == 0) {
-			// FIXME: quick hack
-			switch (serviceRequestType.identifier.numeric) {
-			case 428:
-				serviceRequestType.identifier.numeric = 426;
+				UA_NodeId_encode(&responseType, &pos, response.data);
+				UA_CreateSessionResponse_encode(r, &pos, response.data);
+
+				SL_send(connection, &response, responseType.identifier.numeric);
+
+				UA_ByteString_deleteMembers(&response);
+				UA_CreateSessionResponse_delete(r);
+				UA_CreateSessionRequest_delete(p);
+
+				retval = UA_SUCCESS;
+			}
 				break;
+
+			case UA_CLOSESECURECHANNELREQUEST_NS0: {
+				puts("UA_CLOSESECURECHANNELREQUEST");
+
+				UA_CloseSecureChannelRequest* p =
+						(UA_CloseSecureChannelRequest*) obj;
+				// 62451 Part 6 Chapter 7.1.4 - The server does not send a CloseSecureChannel response
+				connection->transportLayer.connectionState = connectionState_CLOSE;
+				retval = UA_SUCCESS;
 			}
-			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);
-				retval = UA_ERROR;
-			} else {
-				void * obj;
-				UA_alloc(&obj,UA_[namespace_index].calcSize(UA_NULL));
-				UA_[namespace_index].decode(message.data,&pos,obj);
-
-				// FXIME: we need a more clever response/request architecture
-				if (serviceRequestType.identifier.numeric  == 426 ) {
-					UA_GetEndpointsRequest *p = (UA_GetEndpointsRequest*) obj;
-					UA_GetEndpointsResponse *r;
-					UA_NodeId responseType;
-
-					UA_String_printx("endpointUrl=",&(p->endpointUrl));
-					UA_GetEndpointsResponse_new(&r);
-					UA_ResponseHeader_new(&(r->responseHeader));
-					r->responseHeader->requestHandle = p->requestHeader->requestHandle;
-					r->responseHeader->serviceResult = SC_Good;
-					r->responseHeader->stringTableSize = 0;
-					r->responseHeader->timestamp = UA_DateTime_now();
-					UA_DiagnosticInfo_new(&(r->responseHeader->serviceDiagnostics));
-					UA_ExtensionObject_new(&(r->responseHeader->additionalHeader));
-
-					// TODO: Arrays need to be redesigned, this is crap
-					r->endpointsSize = 1;
-					UA_alloc((void**) &(r->endpoints), sizeof(void*));
-					UA_EndpointDescription *epd;
-					UA_EndpointDescription_new(&epd);
-					*(r->endpoints) = epd;
-
-					// FIXME: this memory gets lost
-					UA_String_copycstring("http://localhost:16664/",&(r->endpoints[0]->endpointUrl));
-					// FIXME: this memory gets lost
-					UA_ApplicationDescription_new(&(r->endpoints[0]->server));
-					// FIXME: This should be a feature of the application
-					UA_String_copycstring("open62541.com/applications/4711",&(r->endpoints[0]->server->applicationUri));
-					UA_String_copycstring("open62541.com/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;
-
-					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(connection, &response, 431);
-
-					UA_ByteString_deleteMembers(&response);
-					UA_GetEndpointsResponse_delete(r);
-					UA_GetEndpointsRequest_delete(p);
-
-					return UA_SUCCESS;
+				break;
+			case UA_OPENSECURECHANNELREQUEST_NS0: {
+				puts("UA_OPENSECURECHANNELREQUEST");
+
+				UA_OpenSecureChannelRequest* p =
+						(UA_OpenSecureChannelRequest*) obj;
+				UA_NodeId responseType;
+				UA_OpenSecureChannelResponse* r;
+
+				if (p->clientProtocolVersion
+						!= connection->transportLayer.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
+							== 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 (connection->secureLayer.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:
+					connection->secureLayer.remoteNonce.data = NULL;
+					connection->secureLayer.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(connection, p->requestHeader,
+						SC_Good);
+				UA_OpenSecureChannelRequest_delete(p);
+			}
+				break;
 			}
-		} else {
-			printf("SL_processMessage - unknown request, namespace=%d, request=%d\n", serviceRequestType.namespace, serviceRequestType.identifier.numeric);
-			retval = UA_ERROR;
 		}
+	} else {
+		printf(
+				"SL_processMessage - unknown request, namespace=%d, request=%d\n",
+				serviceRequestType.namespace,
+				serviceRequestType.identifier.numeric);
+		retval = UA_ERROR;
 	}
 	return retval;
 }
@@ -499,13 +471,15 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 		printf("SL_receive - data received \n");
 		//packetType = TL_getPacketType(&secureChannelPacket, &pos);
 
-		UA_SecureConversationMessageHeader_decode(secureChannelPacket.data, &pos, &secureConvHeader);
+		UA_SecureConversationMessageHeader_decode(secureChannelPacket.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);
+			UA_AsymmetricAlgorithmSecurityHeader_decode(
+					secureChannelPacket.data, &pos, &asymAlgSecHeader);
 			UA_ByteString_printf("SL_receive - AAS_Header.ReceiverThumbprint=",
 					&(asymAlgSecHeader.receiverCertificateThumbprint));
 			UA_ByteString_printf("SL_receive - AAS_Header.SecurityPolicyUri=",
@@ -513,20 +487,20 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 			UA_ByteString_printf("SL_receive - AAS_Header.SenderCertificate=",
 					&(asymAlgSecHeader.senderCertificate));
 			if (secureConvHeader.secureChannelId != 0) {
-				iTmp = UA_ByteString_compare(
-						&(connection->secureLayer.remoteAsymAlgSettings.senderCertificate),
-						&(asymAlgSecHeader.senderCertificate));
+				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
-			{
+			} else {
 				//TODO invalid securechannelId
 			}
 
-			UA_SequenceHeader_decode(secureChannelPacket.data, &pos, &sequenceHeader);
+			UA_SequenceHeader_decode(secureChannelPacket.data, &pos,
+					&sequenceHeader);
 			printf("SL_receive - SequenceHeader.RequestId=%d\n",
 					sequenceHeader.requestId);
 			printf("SL_receive - SequenceHeader.SequenceNr=%d\n",
@@ -539,46 +513,45 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 
 			message.data = &secureChannelPacket.data[pos];
 			message.length = secureChannelPacket.length - pos;
-			UA_ByteString_printx("SL_receive - message=",&message);
+			UA_ByteString_printx("SL_receive - message=", &message);
 
 			SL_processMessage(connection, message);
 			// Clean up
-			UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymAlgSecHeader);
+			UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(
+					&asymAlgSecHeader);
 
 			break;
-		case UA_MESSAGETYPE_MSG: /* secure Channel Message received */
-			printf("SL_receive - process MSG\n");
+		case UA_MESSAGETYPE_MSG:
+		case UA_MESSAGETYPE_CLO:
 // FIXME: check connection state
 //			if (connection->secureLayer.connectionState
 //					== connectionState_ESTABLISHED) {
-				if (secureConvHeader.secureChannelId
-						== connection->secureLayer.securityToken.secureChannelId) {
-					UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
-
-					//FIXME: we assume SAS, need to check if AAS or SAS
-					UA_SymmetricAlgorithmSecurityHeader_decode(secureChannelPacket.data, &pos, &symAlgSecHeader);
-
-					// decode sequenceHeader and remember
-					UA_SequenceHeader_decode(secureChannelPacket.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;
-					// process message
-					message.data = &secureChannelPacket.data[pos];
-					message.length = secureChannelPacket.length - pos;
-					UA_ByteString_printx("SL_receive - message=",&message);
-					SL_processMessage(connection, message);
-				} else {
-					//TODO generate ERROR_Bad_SecureChannelUnkown
-				}
-//			} // check connection state
-
-			break;
-		case UA_MESSAGETYPE_CLO: /* closeSecureChannel Message received */
-			if (SL_check(connection, secureChannelPacket) == UA_NO_ERROR) {
-
+			if (secureConvHeader.secureChannelId
+					== connection->secureLayer.securityToken.secureChannelId) {
+				UA_SymmetricAlgorithmSecurityHeader symAlgSecHeader;
+
+				//FIXME: we assume SAS, need to check if AAS or SAS
+				UA_SymmetricAlgorithmSecurityHeader_decode(
+						secureChannelPacket.data, &pos, &symAlgSecHeader);
+
+				// decode sequenceHeader and remember
+				UA_SequenceHeader_decode(secureChannelPacket.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;
+				// process message
+				message.data = &secureChannelPacket.data[pos];
+				message.length = secureChannelPacket.length - pos;
+				SL_processMessage(connection, message);
+			} else {
+				//TODO generate ERROR_Bad_SecureChannelUnkown
 			}
+//			} // check connection state
 			break;
 		}
 		// Clean up
@@ -588,5 +561,3 @@ void SL_receive(UA_connection *connection, UA_ByteString *serviceMessage) {
 	}
 }
 
-
-

+ 1 - 1
tool/generate_namespace.py

@@ -107,7 +107,7 @@ for row in rows2:
     else:	
 	name = "UA_" + row[0]
 
-    print('#define '+name.upper()+'_NS0 (UA_['+name.upper()+'].Id)', file=fh)
+    print('#define '+name.upper()+'_NS0 '+row[1], file=fh)
 
     print("\t{" + row[1] + ", (UA_Int32(*)(void const*)) " + name + "_calcSize, (UA_Int32(*)(UA_Byte const*,UA_Int32*,void*)) " + name + "_decode, (UA_Int32(*)(void const*,UA_Int32*,UA_Byte*))" + name + "_encode},",end='\n',file=fc)