浏览代码

Merge branch 'master' into dev

Conflicts:
	src/client/ua_client.c
	src/server/ua_server_binary.c
Julius Pfrommer 9 年之前
父节点
当前提交
59cbd74b76

+ 2 - 1
include/ua_server.h

@@ -132,7 +132,8 @@ typedef struct {
 UA_UInt16 UA_EXPORT UA_Server_addNamespace(UA_Server *server, const char* name);
 
 /** Add a reference to the server's address space */
-UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item);
+UA_StatusCode UA_EXPORT UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
+                                               const UA_NodeId refTypeId, const UA_ExpandedNodeId targetId);
 
 UA_StatusCode UA_EXPORT
 UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_QualifiedName browseName, 

+ 120 - 175
src/client/ua_client.c

@@ -1,29 +1,19 @@
-#include <ua_types_generated.h>
+#include "ua_types_generated.h"
 #include "ua_client.h"
 #include "ua_nodeids.h"
-#include "ua_types.h"
+#include "ua_securechannel.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_transport_generated.h"
 
 struct UA_Client {
     /* Connection */
     UA_Connection connection;
+    UA_SecureChannel channel;
     UA_String endpointUrl;
-
-    UA_UInt32 sequenceNumber;
     UA_UInt32 requestId;
 
-    /* Secure Channel */
-    UA_ChannelSecurityToken securityToken;
-    UA_ByteString clientNonce;
-    UA_ByteString serverNonce;
-    /* UA_SequenceHeader sequenceHdr; */
-    /* UA_NodeId authenticationToken; */
-
-    /* IdentityToken */
-    UA_UserTokenPolicy token;
-
     /* Session */
+    UA_UserTokenPolicy token;
     UA_NodeId sessionId;
     UA_NodeId authenticationToken;
 
@@ -42,37 +32,27 @@ UA_Client * UA_Client_new(UA_ClientConfig config, UA_Logger logger) {
     UA_Client *client = UA_malloc(sizeof(UA_Client));
     if(!client)
         return UA_NULL;
-    client->config = config;
-    client->logger = logger;
-    UA_String_init(&client->endpointUrl);
-    UA_Connection_init(&client->connection);
 
-    client->sequenceNumber = 0;
+    UA_Connection_init(&client->connection);
+    UA_SecureChannel_init(&client->channel);
+    client->channel.connection = &client->connection;
+    UA_String_init(&client->endpointUrl);
     client->requestId = 0;
 
-    client->scExpiresAt = 0;
-
-    /* Secure Channel */
-    UA_ChannelSecurityToken_deleteMembers(&client->securityToken);
-    UA_ByteString_init(&client->clientNonce);
-    UA_ByteString_init(&client->serverNonce);
-    
     UA_NodeId_init(&client->authenticationToken);
 
+    client->logger = logger;
+    client->config = config;
+    client->scExpiresAt = 0;
+    
     return client;
 }
 
 void UA_Client_delete(UA_Client* client){
     UA_Connection_deleteMembers(&client->connection);
-    UA_Connection_deleteMembers(&client->connection);
+    UA_SecureChannel_deleteMembersCleanup(&client->channel);
     UA_String_deleteMembers(&client->endpointUrl);
-
-    /* Secure Channel */
-    UA_ByteString_deleteMembers(&client->clientNonce);
-    UA_ByteString_deleteMembers(&client->serverNonce);
-
     UA_UserTokenPolicy_deleteMembers(&client->token);
-
     free(client);
 }
 
@@ -132,16 +112,12 @@ static UA_StatusCode HelAckHandshake(UA_Client *c) {
 }
 
 static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) {
-    UA_ByteString_deleteMembers(&client->clientNonce); // if the handshake is repeated
-    UA_ByteString_newMembers(&client->clientNonce, 1);
-    client->clientNonce.data[0] = 0;
-
     UA_SecureConversationMessageHeader messageHeader;
     messageHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
     messageHeader.secureChannelId = 0;
 
     UA_SequenceHeader seqHeader;
-    seqHeader.sequenceNumber = ++client->sequenceNumber;
+    seqHeader.sequenceNumber = ++client->channel.sequenceNumber;
     seqHeader.requestId = ++client->requestId;
 
     UA_AsymmetricAlgorithmSecurityHeader asymHeader;
@@ -160,7 +136,8 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
         opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
     } else {
         opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
-        UA_ByteString_copy(&client->clientNonce, &opnSecRq.clientNonce);
+        UA_SecureChannel_generateNonce(&client->channel.clientNonce);
+        UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce);
         opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
     }
 
@@ -225,9 +202,9 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     retval = response.responseHeader.serviceResult;
 
     if(!renew && retval == UA_STATUSCODE_GOOD) {
-        UA_ChannelSecurityToken_copy(&response.securityToken, &client->securityToken);
-        UA_ByteString_deleteMembers(&client->serverNonce); // if the handshake is repeated
-        UA_ByteString_copy(&response.serverNonce, &client->serverNonce);
+        UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken);
+        UA_ByteString_deleteMembers(&client->channel.serverNonce); // if the handshake is repeated
+        UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce);
     }
 
     UA_OpenSecureChannelResponse_deleteMembers(&response);
@@ -238,78 +215,28 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
 
 /** If the request fails, then the response is cast to UA_ResponseHeader (at the beginning of every
     response) and filled with the appropriate error code */
-static void sendReceiveRequest(UA_RequestHeader *request, const UA_DataType *requestType,
-                               void *response, const UA_DataType *responseType, UA_Client *client,
-                               UA_Boolean sendOnly) {
-
-    //check if sc needs to be renewed
-    if(client->scExpiresAt-UA_DateTime_now() <= client->config.timeToRenewSecureChannel * 10000){ //less than 3 seconds left to expire -> renew
+static void synchronousRequest(UA_Client *client, const void *request, const UA_DataType *requestType,
+                               void *response, const UA_DataType *responseType) {
+    /* Check if sc needs to be renewed */
+    if(client->scExpiresAt - UA_DateTime_now() <= client->config.timeToRenewSecureChannel * 10000 )
         UA_Client_renewSecureChannel(client);
-    }
 
-    if(response)
-        UA_init(response, responseType);
-    else
+    if(!response)
         return;
+    UA_init(response, responseType);
 
-    UA_NodeId_copy(&client->authenticationToken, &request->authenticationToken);
-
-    UA_SecureConversationMessageHeader msgHeader;
-    if(sendOnly)
-        msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF;
-    else
-        msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
-    msgHeader.secureChannelId = client->securityToken.channelId;
-
-    UA_SymmetricAlgorithmSecurityHeader symHeader;
-    symHeader.tokenId = client->securityToken.tokenId;
-    
-    UA_SequenceHeader seqHeader;
-    seqHeader.sequenceNumber = ++client->sequenceNumber;
-    seqHeader.requestId = ++client->requestId;
-
-    UA_NodeId requestId = UA_NODEID_NUMERIC(0, requestType->typeId.identifier.numeric +
-                                           UA_ENCODINGOFFSET_BINARY);
-
-    msgHeader.messageHeader.messageSize =
-        UA_SecureConversationMessageHeader_calcSizeBinary(&msgHeader) +
-        UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(&symHeader) +
-        UA_SequenceHeader_calcSizeBinary(&seqHeader) +
-        UA_NodeId_calcSizeBinary(&requestId) +
-        UA_calcSizeBinary(request, requestType);
-
-    UA_ByteString message;
-    UA_StatusCode retval = client->connection.getBuffer(&client->connection, &message, msgHeader.messageHeader.messageSize);
-    if(retval != UA_STATUSCODE_GOOD) {
-        // todo: print error message
-        return;
-    }
-
-    size_t offset = 0;
-    retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset);
-    retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
-    retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
-
-    retval |= UA_NodeId_encodeBinary(&requestId, &message, &offset);
-    retval |= UA_encodeBinary(request, requestType, &message, &offset);
-
-    retval |= client->connection.write(&client->connection, &message);
-
+    /* Send the request */
+    UA_UInt32 requestId = ++client->requestId;
+    UA_StatusCode retval = UA_SecureChannel_sendBinaryMessage(&client->channel, requestId,
+                                                              request, requestType);
     UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
-
-    client->connection.releaseBuffer(&client->connection, &message);
-
-    if(retval != UA_STATUSCODE_GOOD) {
-        //send failed
+    if(retval) {
         respHeader->serviceResult = retval;
         return;
     }
 
-    //TODO: rework to get return value
-    if(sendOnly)
-        return;
-
-    /* Response */
+    /* Retrieve the response */
+    // Todo: push this into the generic securechannel implementation for client and server
     UA_ByteString reply;
     UA_ByteString_init(&reply);
     do {
@@ -320,18 +247,22 @@ static void sendReceiveRequest(UA_RequestHeader *request, const UA_DataType *req
         }
     } while(retval != UA_STATUSCODE_GOOD);
 
-    offset = 0;
+    size_t offset = 0;
+    UA_SecureConversationMessageHeader msgHeader;
     retval |= UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &msgHeader);
+    UA_SymmetricAlgorithmSecurityHeader symHeader;
     retval |= UA_SymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &symHeader);
+    UA_SequenceHeader seqHeader;
     retval |= UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
     UA_NodeId responseId;
     retval |= UA_NodeId_decodeBinary(&reply, &offset, &responseId);
     UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, responseType->typeId.identifier.numeric +
                                                  UA_ENCODINGOFFSET_BINARY);
-    if(!UA_NodeId_equal(&responseId, &expectedNodeId)) {
+    if(!UA_NodeId_equal(&responseId, &expectedNodeId) || seqHeader.requestId != requestId) {
+        // Todo: we need to demux responses since a publish responses may come at any time
         client->connection.releaseBuffer(&client->connection, &reply);
         UA_SymmetricAlgorithmSecurityHeader_deleteMembers(&symHeader);
-        respHeader->serviceResult = retval;
+        respHeader->serviceResult = UA_STATUSCODE_BADINTERNALERROR;
         return;
     }
 
@@ -341,11 +272,6 @@ static void sendReceiveRequest(UA_RequestHeader *request, const UA_DataType *req
         respHeader->serviceResult = retval;
 }
 
-static void synchronousRequest(void *request, const UA_DataType *requestType, void *response,
-                               const UA_DataType *responseType, UA_Client *client) {
-    sendReceiveRequest(request, requestType, response, responseType, client, UA_FALSE);
-}
-
 static UA_StatusCode ActivateSession(UA_Client *client) {
     UA_ActivateSessionRequest request;
     UA_ActivateSessionRequest_init(&request);
@@ -369,9 +295,8 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
     UA_ByteString_encodeBinary(&identityToken.policyId,&request.userIdentityToken.body,&offset);
 
     UA_ActivateSessionResponse response;
-    synchronousRequest(&request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
-                       &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE],
-                       client);
+    synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
 
     UA_AnonymousIdentityToken_deleteMembers(&identityToken);
     UA_ActivateSessionRequest_deleteMembers(&request);
@@ -382,41 +307,37 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
 static UA_StatusCode EndpointsHandshake(UA_Client *client) {
     UA_GetEndpointsRequest request;
     UA_GetEndpointsRequest_init(&request);
-
-    // todo: is this needed for all requests?
     UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
-
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
     UA_String_copy(&client->endpointUrl, &request.endpointUrl);
-
     request.profileUrisSize = 1;
     request.profileUris = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], request.profileUrisSize);
-    request.profileUris[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+    *request.profileUris = UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
 
     UA_GetEndpointsResponse response;
     UA_GetEndpointsResponse_init(&response);
-    synchronousRequest(&request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
-                       &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE],
-                       client);
+    synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
 
     UA_Boolean endpointFound = UA_FALSE;
     UA_Boolean tokenFound = UA_FALSE;
     for(UA_Int32 i=0; i<response.endpointsSize; ++i){
         UA_EndpointDescription* endpoint = &response.endpoints[i];
         /* look out for an endpoint without security */
-        if(UA_String_equal(&endpoint->securityPolicyUri, &UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None"))){
-            endpointFound = UA_TRUE;
-            /* endpoint with no security found */
-            /* look for a user token policy with an anonymous token */
-            for(UA_Int32 j=0; j<endpoint->userIdentityTokensSize; ++j){
-                UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
-                if(userToken->tokenType == UA_USERTOKENTYPE_ANONYMOUS){
-                    tokenFound = UA_TRUE;
-                    UA_UserTokenPolicy_copy(userToken, &client->token);
-                    break;
-                }
-            }
+        if(!UA_String_equal(&endpoint->securityPolicyUri,
+                            &UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None")))
+            continue;
+        endpointFound = UA_TRUE;
+        /* endpoint with no security found */
+        /* look for a user token policy with an anonymous token */
+        for(UA_Int32 j=0; j<endpoint->userIdentityTokensSize; ++j) {
+            UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
+            if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
+                continue;
+            tokenFound = UA_TRUE;
+            UA_UserTokenPolicy_copy(userToken, &client->token);
+            break;
         }
     }
 
@@ -424,15 +345,14 @@ static UA_StatusCode EndpointsHandshake(UA_Client *client) {
     UA_GetEndpointsResponse_deleteMembers(&response);
 
     if(!endpointFound){
-        printf("No suitable endpoint found\n");
+        UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No suitable endpoint found");
         return UA_STATUSCODE_BADINTERNALERROR;
     }
     if(!tokenFound){
-        printf("No anonymous token found\n");
+        UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No anonymous token found");
         return UA_STATUSCODE_BADINTERNALERROR;
     }
-
-    return response.responseHeader.serviceResult; // not deleted
+    return response.responseHeader.serviceResult;
 }
 
 static UA_StatusCode SessionHandshake(UA_Client *client) {
@@ -441,22 +361,16 @@ static UA_StatusCode SessionHandshake(UA_Client *client) {
 
     // todo: is this needed for all requests?
     UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
-
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
-    UA_ByteString_copy(&client->clientNonce, &request.clientNonce);
+    UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce);
     request.requestedSessionTimeout = 1200000;
     request.maxResponseMessageSize = UA_INT32_MAX;
 
-    /* UA_String_copy(endpointUrl, &rq.endpointUrl); */
-    /* UA_String_copycstring("mysession", &rq.sessionName); */
-    /* UA_String_copycstring("abcd", &rq.clientCertificate); */
-
     UA_CreateSessionResponse response;
     UA_CreateSessionResponse_init(&response);
-    synchronousRequest(&request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
-                       &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE],
-                       client);
+    synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
 
     UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
 
@@ -474,9 +388,8 @@ static UA_StatusCode CloseSession(UA_Client *client) {
     request.deleteSubscriptions = UA_TRUE;
     UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
     UA_CreateSessionResponse response;
-    synchronousRequest(&request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
-                       &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE],
-                       client);
+    synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
 
     UA_CloseSessionRequest_deleteMembers(&request);
     UA_CloseSessionResponse_deleteMembers(&response);
@@ -484,18 +397,50 @@ static UA_StatusCode CloseSession(UA_Client *client) {
 }
 
 static UA_StatusCode CloseSecureChannel(UA_Client *client) {
+    UA_SecureChannel *channel = &client->channel;
     UA_CloseSecureChannelRequest request;
     UA_CloseSecureChannelRequest_init(&request);
-
     request.requestHeader.requestHandle = 1; //TODO: magic number?
     request.requestHeader.timestamp = UA_DateTime_now();
     request.requestHeader.timeoutHint = 10000;
     request.requestHeader.authenticationToken = client->authenticationToken;
-    sendReceiveRequest(&request.requestHeader, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], UA_NULL, UA_NULL,
-                       client, UA_TRUE);
 
-    return UA_STATUSCODE_GOOD;
+    UA_SecureConversationMessageHeader msgHeader;
+    msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF;
+    msgHeader.secureChannelId = client->channel.securityToken.channelId;
+
+    UA_SymmetricAlgorithmSecurityHeader symHeader;
+    symHeader.tokenId = channel->securityToken.tokenId;
+    
+    UA_SequenceHeader seqHeader;
+    seqHeader.sequenceNumber = ++channel->sequenceNumber;
+    seqHeader.requestId = ++client->requestId;
+
+    UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
 
+    msgHeader.messageHeader.messageSize =
+        UA_SecureConversationMessageHeader_calcSizeBinary(&msgHeader) +
+        UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(&symHeader) +
+        UA_SequenceHeader_calcSizeBinary(&seqHeader) +
+        UA_NodeId_calcSizeBinary(&typeId) +
+        UA_calcSizeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
+
+    UA_ByteString message;
+    UA_StatusCode retval = client->connection.getBuffer(&client->connection, &message,
+                                                        msgHeader.messageHeader.messageSize);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
+
+    size_t offset = 0;
+    retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset);
+    retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
+    retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
+    retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset);
+    retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], &message, &offset);
+    if(retval == UA_STATUSCODE_GOOD)
+        retval = client->connection.write(&client->connection, &message);
+    client->connection.releaseBuffer(&client->connection, &message);
+    return retval;
 }
 
 /*************************/
@@ -538,29 +483,29 @@ UA_StatusCode UA_Client_renewSecureChannel(UA_Client *client) {
 
 UA_ReadResponse UA_Client_read(UA_Client *client, UA_ReadRequest *request) {
     UA_ReadResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_READREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_READRESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_READREQUEST], &response,
+                       &UA_TYPES[UA_TYPES_READRESPONSE]);
     return response;
 }
 
 UA_WriteResponse UA_Client_write(UA_Client *client, UA_WriteRequest *request) {
     UA_WriteResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_WRITEREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_WRITERESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_WRITEREQUEST], &response,
+                       &UA_TYPES[UA_TYPES_WRITERESPONSE]);
     return response;
 }
 
 UA_BrowseResponse UA_Client_browse(UA_Client *client, UA_BrowseRequest *request) {
     UA_BrowseResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_BROWSEREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_BROWSERESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_BROWSEREQUEST], &response,
+                       &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
     return response;
 }
 
 UA_BrowseNextResponse UA_Client_browseNext(UA_Client *client, UA_BrowseNextRequest *request) {
     UA_BrowseNextResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], &response,
+                       &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
     return response;
 }
 
@@ -568,35 +513,35 @@ UA_TranslateBrowsePathsToNodeIdsResponse
     UA_Client_translateTranslateBrowsePathsToNodeIds(UA_Client *client,
                                                      UA_TranslateBrowsePathsToNodeIdsRequest *request) {
     UA_TranslateBrowsePathsToNodeIdsResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_BROWSEREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_BROWSERESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
     return response;
 }
 
 UA_AddNodesResponse UA_Client_addNodes(UA_Client *client, UA_AddNodesRequest *request) {
     UA_AddNodesResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_ADDNODESREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_ADDNODESREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
     return response;
 }
 
 UA_AddReferencesResponse UA_Client_addReferences(UA_Client *client, UA_AddReferencesRequest *request) {
     UA_AddReferencesResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]);
     return response;
 }
 
 UA_DeleteNodesResponse UA_Client_deleteNodes(UA_Client *client, UA_DeleteNodesRequest *request) {
     UA_DeleteNodesResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_DELETENODESREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_DELETENODESRESPONSE], client);
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETENODESREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
     return response;
 }
 
 UA_DeleteReferencesResponse UA_Client_deleteReferences(UA_Client *client, UA_DeleteReferencesRequest *request) {
     UA_DeleteReferencesResponse response;
-    synchronousRequest(request, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST], &response,
-                       &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE], client);
-    return response;;
+    synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST],
+                       &response, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
+    return response;
 }

+ 220 - 215
src/server/ua_server.c

@@ -15,6 +15,31 @@ const UA_EXPORT UA_ServerConfig UA_ServerConfig_standard = {
     .Application_applicationURI = "urn:unconfigured:open62541:open62541Server",
     .Application_applicationName = "open62541" };
 
+static const UA_NodeId nodeIdHasSubType = {
+    .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+    .identifier.numeric = UA_NS0ID_HASSUBTYPE};
+static const UA_NodeId nodeIdHasTypeDefinition = {
+    .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+    .identifier.numeric = UA_NS0ID_HASTYPEDEFINITION};
+static const UA_NodeId nodeIdHasComponent = {
+    .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+    .identifier.numeric = UA_NS0ID_HASCOMPONENT};
+static const UA_NodeId nodeIdHasProperty = {
+    .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+    .identifier.numeric = UA_NS0ID_HASPROPERTY};
+static const UA_NodeId nodeIdOrganizes = {
+    .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+    .identifier.numeric = UA_NS0ID_ORGANIZES};
+
+static const UA_ExpandedNodeId expandedNodeIdBaseDataVariabletype = {
+    .nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+               .identifier.numeric = UA_NS0ID_HASTYPEDEFINITION},
+    .namespaceUri = {.length = -1, .data = UA_NULL}, .serverIndex = 0};
+static const UA_ExpandedNodeId expandedNodeIdNonHierarchicalReferences = {
+    .nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
+               .identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES},
+    .namespaceUri = {.length = -1, .data = UA_NULL}, .serverIndex = 0};
+
 /**********************/
 /* Namespace Handling */
 /**********************/
@@ -40,7 +65,8 @@ UA_StatusCode UA_EXPORT UA_Server_addExternalNamespace(UA_Server *server, UA_UIn
 		if(server->externalNamespaces[i].index == namespaceIndex)
 			return UA_STATUSCODE_BADINDEXRANGEINVALID;
 	}
-    server->externalNamespaces = UA_realloc(server->externalNamespaces, sizeof(UA_ExternalNamespace) * (server->externalNamespacesSize+1));
+    server->externalNamespaces = UA_realloc(server->externalNamespaces,
+                                            sizeof(UA_ExternalNamespace) * (server->externalNamespacesSize+1));
     server->externalNamespaces[server->externalNamespacesSize].externalNodeStore = *nodeStore;
     server->externalNamespaces[server->externalNamespacesSize].index = namespaceIndex;
     UA_String_copy(url,&server->externalNamespaces[server->externalNamespacesSize].url);
@@ -255,9 +281,7 @@ static void addDataTypeNode(UA_Server *server, char* name, UA_UInt32 datatypeid,
     UA_DataTypeNode *datatype = UA_DataTypeNode_new();
     copyNames((UA_Node*)datatype, name);
     datatype->nodeId.identifier.numeric = datatypeid;
-    UA_Server_addNode(server, (UA_Node*)datatype,
-                      UA_EXPANDEDNODEID_NUMERIC(0, parent),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)datatype, UA_EXPANDEDNODEID_NUMERIC(0, parent), nodeIdOrganizes);
 }
 
 static void addObjectTypeNode(UA_Server *server, char* name, UA_UInt32 objecttypeid, UA_Int32 parent,
@@ -265,8 +289,7 @@ static void addObjectTypeNode(UA_Server *server, char* name, UA_UInt32 objecttyp
     UA_ObjectTypeNode *objecttype = UA_ObjectTypeNode_new();
     copyNames((UA_Node*)objecttype, name);
     objecttype->nodeId.identifier.numeric = objecttypeid;
-    UA_Server_addNode(server, (UA_Node*)objecttype,
-                      UA_EXPANDEDNODEID_NUMERIC(0, parent),
+    UA_Server_addNode(server, (UA_Node*)objecttype, UA_EXPANDEDNODEID_NUMERIC(0, parent),
                       UA_NODEID_NUMERIC(0, parentreference));
 }
 
@@ -284,9 +307,7 @@ createVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
 static void addVariableTypeNode_organized(UA_Server *server, char* name, UA_UInt32 variabletypeid,
                                           UA_Int32 parent, UA_Boolean abstract) {
     UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
-    UA_Server_addNode(server, (UA_Node*)variabletype,
-                      UA_EXPANDEDNODEID_NUMERIC(0, parent),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)variabletype, UA_EXPANDEDNODEID_NUMERIC(0, parent), nodeIdOrganizes);
 }
 
 static void addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32 variabletypeid,
@@ -294,7 +315,7 @@ static void addVariableTypeNode_subtype(UA_Server *server, char* name, UA_UInt32
     UA_VariableTypeNode *variabletype = createVariableTypeNode(server, name, variabletypeid, parent, abstract);
     UA_Server_addNode(server, (UA_Node*)variabletype,
                       UA_EXPANDEDNODEID_NUMERIC(0, parent),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      nodeIdHasSubType);
 }
 
 UA_Server * UA_Server_new(UA_ServerConfig config) {
@@ -349,8 +370,10 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     UA_EndpointDescription *endpoint = UA_EndpointDescription_new(); // todo: check return code
     if(endpoint) {
         endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
-        endpoint->securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
-        endpoint->transportProfileUri = UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
+        endpoint->securityPolicyUri =
+            UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
+        endpoint->transportProfileUri =
+            UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
 
         int size = 0;
         if(server->config.Login_enableAnonymous){
@@ -377,13 +400,12 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
             currentIndex++;
         }
 
+        /* The standard says "the HostName specified in the Server Certificate is the
+           same as the HostName contained in the endpointUrl provided in the
+           EndpointDescription */
         /* UA_String_copy(endpointUrl, &endpoint->endpointUrl); */
-        /* /\* The standard says "the HostName specified in the Server Certificate is the */
-        /*    same as the HostName contained in the endpointUrl provided in the */
-        /*    EndpointDescription *\/ */
         /* UA_String_copy(&server->serverCertificate, &endpoint->serverCertificate); */
         UA_ApplicationDescription_copy(&server->description, &endpoint->server);
-
         server->endpointDescriptions = endpoint;
         server->endpointDescriptionsSize = 1;
     } 
@@ -451,14 +473,14 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     /* References */
     /**************/
     
-    /* bootstrap by manually inserting "references" and "hassubtype" */
+    /* Bootstrap by manually inserting "references" and "hassubtype" */
     UA_ReferenceTypeNode *references = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)references, "References");
     references->nodeId.identifier.numeric = UA_NS0ID_REFERENCES;
     references->isAbstract = UA_TRUE;
     references->symmetric  = UA_TRUE;
     references->inverseName = UA_LOCALIZEDTEXT_ALLOC("", "References");
-    // this node has no parent??
+    /* The reference to root is later inserted */
     UA_NodeStore_insert(server->nodestore, (UA_Node*)references, UA_NULL);
 
     UA_ReferenceTypeNode *hassubtype = UA_ReferenceTypeNode_new();
@@ -467,17 +489,17 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hassubtype->nodeId.identifier.numeric = UA_NS0ID_HASSUBTYPE;
     hassubtype->isAbstract = UA_FALSE;
     hassubtype->symmetric  = UA_FALSE;
+    /* The reference to root is later inserted */
     UA_NodeStore_insert(server->nodestore, (UA_Node*)hassubtype, UA_NULL);
 
-    /* continue adding reference types with normal "addnode" */
+    /* Continue adding reference types with normal "addnode" */
     UA_ReferenceTypeNode *hierarchicalreferences = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hierarchicalreferences, "Hierarchicalreferences");
     hierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_HIERARCHICALREFERENCES;
     hierarchicalreferences->isAbstract = UA_TRUE;
     hierarchicalreferences->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)hierarchicalreferences,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *nonhierarchicalreferences = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)nonhierarchicalreferences, "NonHierarchicalReferences");
@@ -485,8 +507,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     nonhierarchicalreferences->isAbstract = UA_TRUE;
     nonhierarchicalreferences->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)nonhierarchicalreferences,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *haschild = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)haschild, "HasChild");
@@ -494,8 +515,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     haschild->isAbstract = UA_TRUE;
     haschild->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)haschild,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)organizes, "Organizes");
@@ -504,8 +524,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     organizes->isAbstract = UA_FALSE;
     organizes->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)organizes,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *haseventsource = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)haseventsource, "HasEventSource");
@@ -514,8 +533,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     haseventsource->isAbstract = UA_FALSE;
     haseventsource->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)haseventsource,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasmodellingrule = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasmodellingrule, "HasModellingRule");
@@ -523,9 +541,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasmodellingrule->nodeId.identifier.numeric = UA_NS0ID_HASMODELLINGRULE;
     hasmodellingrule->isAbstract = UA_FALSE;
     hasmodellingrule->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasmodellingrule,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasmodellingrule, expandedNodeIdNonHierarchicalReferences,
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasencoding = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasencoding, "HasEncoding");
@@ -533,9 +550,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasencoding->nodeId.identifier.numeric = UA_NS0ID_HASENCODING;
     hasencoding->isAbstract = UA_FALSE;
     hasencoding->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasencoding,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasencoding, expandedNodeIdNonHierarchicalReferences, nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasdescription = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasdescription, "HasDescription");
@@ -543,9 +558,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasdescription->nodeId.identifier.numeric = UA_NS0ID_HASDESCRIPTION;
     hasdescription->isAbstract = UA_FALSE;
     hasdescription->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasdescription,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasdescription, expandedNodeIdNonHierarchicalReferences,
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hastypedefinition = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hastypedefinition, "HasTypeDefinition");
@@ -553,9 +567,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hastypedefinition->nodeId.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION;
     hastypedefinition->isAbstract = UA_FALSE;
     hastypedefinition->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hastypedefinition,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hastypedefinition, expandedNodeIdNonHierarchicalReferences,
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *generatesevent = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)generatesevent, "GeneratesEvent");
@@ -563,9 +576,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     generatesevent->nodeId.identifier.numeric = UA_NS0ID_GENERATESEVENT;
     generatesevent->isAbstract = UA_FALSE;
     generatesevent->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)generatesevent,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)generatesevent, expandedNodeIdNonHierarchicalReferences,
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *aggregates = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)aggregates, "Aggregates");
@@ -573,13 +585,12 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     aggregates->nodeId.identifier.numeric = UA_NS0ID_AGGREGATES;
     aggregates->isAbstract = UA_TRUE;
     aggregates->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)aggregates,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASCHILD),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)aggregates, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASCHILD),
+                      nodeIdHasSubType);
 
     // complete bootstrap of hassubtype
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
-                 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
 
     UA_ReferenceTypeNode *hasproperty = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasproperty, "HasProperty");
@@ -587,9 +598,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasproperty->nodeId.identifier.numeric = UA_NS0ID_HASPROPERTY;
     hasproperty->isAbstract = UA_FALSE;
     hasproperty->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasproperty,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasproperty, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES),
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hascomponent = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hascomponent, "HasComponent");
@@ -597,9 +607,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hascomponent->nodeId.identifier.numeric = UA_NS0ID_HASCOMPONENT;
     hascomponent->isAbstract = UA_FALSE;
     hascomponent->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hascomponent,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hascomponent, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES),
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasnotifier = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasnotifier, "HasNotifier");
@@ -607,9 +616,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
     hasnotifier->isAbstract = UA_FALSE;
     hasnotifier->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasnotifier,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasnotifier, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE),
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasorderedcomponent = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
@@ -618,8 +626,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasorderedcomponent->isAbstract = UA_FALSE;
     hasorderedcomponent->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)hasorderedcomponent,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hasmodelparent = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hasmodelparent, "HasModelParent");
@@ -627,9 +634,8 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hasmodelparent->nodeId.identifier.numeric = UA_NS0ID_HASMODELPARENT;
     hasmodelparent->isAbstract = UA_FALSE;
     hasmodelparent->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hasmodelparent,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hasmodelparent, expandedNodeIdNonHierarchicalReferences,
+                      nodeIdHasSubType);
 
     UA_ReferenceTypeNode *fromstate = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)fromstate, "FromState");
@@ -637,9 +643,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     fromstate->nodeId.identifier.numeric = UA_NS0ID_FROMSTATE;
     fromstate->isAbstract = UA_FALSE;
     fromstate->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)fromstate,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)fromstate, expandedNodeIdNonHierarchicalReferences, nodeIdHasSubType);
 
     UA_ReferenceTypeNode *tostate = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)tostate, "ToState");
@@ -647,9 +651,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     tostate->nodeId.identifier.numeric = UA_NS0ID_TOSTATE;
     tostate->isAbstract = UA_FALSE;
     tostate->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)tostate,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)tostate, expandedNodeIdNonHierarchicalReferences, nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hascause = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hascause, "HasCause");
@@ -657,9 +659,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hascause->nodeId.identifier.numeric = UA_NS0ID_HASCAUSE;
     hascause->isAbstract = UA_FALSE;
     hascause->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)hascause,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)hascause, expandedNodeIdNonHierarchicalReferences, nodeIdHasSubType);
     
     UA_ReferenceTypeNode *haseffect = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)haseffect, "HasEffect");
@@ -667,9 +667,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     haseffect->nodeId.identifier.numeric = UA_NS0ID_HASEFFECT;
     haseffect->isAbstract = UA_FALSE;
     haseffect->symmetric  = UA_FALSE;
-    UA_Server_addNode(server, (UA_Node*)haseffect,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+    UA_Server_addNode(server, (UA_Node*)haseffect, expandedNodeIdNonHierarchicalReferences, nodeIdHasSubType);
 
     UA_ReferenceTypeNode *hashistoricalconfiguration = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)hashistoricalconfiguration, "HasHistoricalConfiguration");
@@ -678,8 +676,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     hashistoricalconfiguration->isAbstract = UA_FALSE;
     hashistoricalconfiguration->symmetric  = UA_FALSE;
     UA_Server_addNode(server, (UA_Node*)hashistoricalconfiguration,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
 
     /*****************/
     /* Basic Folders */
@@ -693,33 +690,29 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     UA_ObjectNode *objects = UA_ObjectNode_new();
     copyNames((UA_Node*)objects, "Objects");
     objects->nodeId.identifier.numeric = UA_NS0ID_OBJECTSFOLDER;
-    UA_Server_addNode(server, (UA_Node*)objects,
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)objects, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
+                      nodeIdOrganizes);
 
     UA_ObjectNode *types = UA_ObjectNode_new();
     copyNames((UA_Node*)types, "Types");
     types->nodeId.identifier.numeric = UA_NS0ID_TYPESFOLDER;
-    UA_Server_addNode(server, (UA_Node*)types,
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)types, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
+                      nodeIdOrganizes);
 
     UA_ObjectNode *views = UA_ObjectNode_new();
     copyNames((UA_Node*)views, "Views");
     views->nodeId.identifier.numeric = UA_NS0ID_VIEWSFOLDER;
-    UA_Server_addNode(server, (UA_Node*)views,
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)views, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
+                      nodeIdOrganizes);
 
     UA_ObjectNode *referencetypes = UA_ObjectNode_new();
     copyNames((UA_Node*)referencetypes, "ReferenceTypes");
     referencetypes->nodeId.identifier.numeric = UA_NS0ID_REFERENCETYPESFOLDER;
-    UA_Server_addNode(server, (UA_Node*)referencetypes,
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+    UA_Server_addNode(server, (UA_Node*)referencetypes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
+                      nodeIdOrganizes);
 
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdOrganizes,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES));
 
     /**********************/
     /* Basic Object Types */
@@ -730,27 +723,32 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     objecttypes->nodeId.identifier.numeric = UA_NS0ID_OBJECTTYPESFOLDER;
     UA_Server_addNode(server, (UA_Node*)objecttypes,
         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+        nodeIdOrganizes);
 
-    addObjectTypeNode(server, "BaseObjectType", UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_ORGANIZES);
+    addObjectTypeNode(server, "BaseObjectType", UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
+                      UA_NS0ID_ORGANIZES);
     addObjectTypeNode(server, "FolderType", UA_NS0ID_FOLDERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VIEWSFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
     addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    addObjectTypeNode(server, "ServerCapatilitiesType", UA_NS0ID_SERVERCAPABILITIESTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    addObjectTypeNode(server, "ServerStatusType", UA_NS0ID_SERVERSTATUSTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
-    addObjectTypeNode(server, "BuildInfoType", UA_NS0ID_BUILDINFOTYPE, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
+    addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
+                      UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
+    addObjectTypeNode(server, "ServerCapatilitiesType", UA_NS0ID_SERVERCAPABILITIESTYPE,
+                      UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
+    addObjectTypeNode(server, "ServerStatusType", UA_NS0ID_SERVERSTATUSTYPE, UA_NS0ID_BASEOBJECTTYPE,
+                      UA_NS0ID_HASSUBTYPE);
+    addObjectTypeNode(server, "BuildInfoType", UA_NS0ID_BUILDINFOTYPE, UA_NS0ID_BASEOBJECTTYPE,
+                      UA_NS0ID_HASSUBTYPE);
 
     /**************/
     /* Data Types */
@@ -759,11 +757,10 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     UA_ObjectNode *datatypes = UA_ObjectNode_new();
     copyNames((UA_Node*)datatypes, "DataTypes");
     datatypes->nodeId.identifier.numeric = UA_NS0ID_DATATYPESFOLDER;
-    UA_Server_addNode(server, (UA_Node*)datatypes,
-                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
-                      UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+    UA_Server_addNode(server, (UA_Node*)datatypes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
+                      nodeIdOrganizes);
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER),
+                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
 
     addDataTypeNode(server, "BaseDataType", UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER);
     addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, UA_NS0ID_BASEDATATYPE);
@@ -801,14 +798,16 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
    UA_ObjectNode *variabletypes = UA_ObjectNode_new();
    copyNames((UA_Node*)variabletypes, "VariableTypes");
    variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
-   UA_Server_addNode(server, (UA_Node*)variabletypes,
-                     UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
-                     UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
-   addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE, UA_NS0ID_VARIABLETYPESFOLDER, UA_TRUE);
-   addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE, UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
-   addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE, UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
+   UA_Server_addNode(server, (UA_Node*)variabletypes, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
+                     nodeIdOrganizes);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER), nodeIdHasTypeDefinition,
+                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+   addVariableTypeNode_organized(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE,
+                                 UA_NS0ID_VARIABLETYPESFOLDER, UA_TRUE);
+   addVariableTypeNode_subtype(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE,
+                               UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
+   addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE,
+                               UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
 
    /*********************/
    /* The Server Object */
@@ -817,28 +816,25 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
    UA_ObjectNode *servernode = UA_ObjectNode_new();
    copyNames((UA_Node*)servernode, "Server");
    servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
-   UA_Server_addNode(server, (UA_Node*)servernode,
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
-       UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-       UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE));
+   UA_Server_addNode(server, (UA_Node*)servernode, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                     nodeIdOrganizes);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasTypeDefinition,
+                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE));
 
    UA_VariableNode *namespaceArray = UA_VariableNode_new();
    copyNames((UA_Node*)namespaceArray, "NamespaceArray");
    namespaceArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_NAMESPACEARRAY;
    namespaceArray->valueSource = UA_VALUESOURCE_DATASOURCE;
-   namespaceArray->value.dataSource = (UA_DataSource) {.handle = server, .read = readNamespaces,
+   namespaceArray->value.dataSource = (UA_DataSource) {
+       .handle = server, .read = readNamespaces,
        .release = releaseNamespaces, .write = UA_NULL};
    namespaceArray->valueRank = 1;
    namespaceArray->minimumSamplingInterval = 1.0;
    namespaceArray->historizing = UA_FALSE;
-   UA_Server_addNode(server, (UA_Node*)namespaceArray,
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
-           UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
-                UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
+   UA_Server_addNode(server, (UA_Node*)namespaceArray, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
+                     nodeIdHasProperty);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), nodeIdHasTypeDefinition,
+                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
 
    UA_VariableNode *serverArray = UA_VariableNode_new();
    copyNames((UA_Node*)serverArray, "ServerArray");
@@ -850,21 +846,19 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
    serverArray->valueRank = 1;
    serverArray->minimumSamplingInterval = 1.0;
    serverArray->historizing = UA_FALSE;
-   UA_Server_addNode(server, (UA_Node*)serverArray,
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
-           UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY),
-                UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
+   UA_Server_addNode(server, (UA_Node*)serverArray, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
+                     nodeIdHasProperty);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY),
+                          nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
 
    UA_ObjectNode *servercapablities = UA_ObjectNode_new();
    copyNames((UA_Node*)servercapablities, "ServerCapabilities");
    servercapablities->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES;
-   UA_Server_addNode(server, (UA_Node*)servercapablities,
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
-           UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-       UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE));
+   UA_Server_addNode(server, (UA_Node*)servercapablities, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
+                     nodeIdHasComponent);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
+                          nodeIdHasTypeDefinition,
+                          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE));
 
    UA_VariableNode *localeIdArray = UA_VariableNode_new();
    copyNames((UA_Node*)localeIdArray, "LocaleIdArray");
@@ -877,56 +871,56 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
    localeIdArray->minimumSamplingInterval = 1.0;
    localeIdArray->historizing = UA_FALSE;
    UA_Server_addNode(server, (UA_Node*)localeIdArray,
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
-           UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY));
-   ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
+                     UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
+   UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY),
+                          nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
 
    UA_VariableNode *maxBrowseContinuationPoints = UA_VariableNode_new();
     copyNames((UA_Node*)maxBrowseContinuationPoints, "MaxBrowseContinuationPoints");
-    maxBrowseContinuationPoints->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS;
+    maxBrowseContinuationPoints->nodeId.identifier.numeric =
+        UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS;
     maxBrowseContinuationPoints->value.variant.data = UA_UInt16_new();
     *((UA_UInt16*)maxBrowseContinuationPoints->value.variant.data) = MAXCONTINUATIONPOINTS;
     maxBrowseContinuationPoints->value.variant.type = &UA_TYPES[UA_TYPES_UINT16];
     UA_Server_addNode(server, (UA_Node*)maxBrowseContinuationPoints,
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS),
-        UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty);
+    UA_Server_addReference(server,
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS),
+                           nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
 
     UA_ObjectNode *serverdiagnostics = UA_ObjectNode_new();
     copyNames((UA_Node*)serverdiagnostics, "ServerDiagnostics");
     serverdiagnostics->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS;
     UA_Server_addNode(server, (UA_Node*)serverdiagnostics,
-            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
-            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-    ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE));
+                      UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent);
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
+                           nodeIdHasTypeDefinition,
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE));
 
     UA_VariableNode *enabledFlag = UA_VariableNode_new();
      copyNames((UA_Node*)enabledFlag, "EnabledFlag");
      enabledFlag->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG;
-     enabledFlag->value.variant.data = UA_Boolean_new(); //itialized as false
+     enabledFlag->value.variant.data = UA_Boolean_new(); //initialized as false
      enabledFlag->value.variant.type = &UA_TYPES[UA_TYPES_BOOLEAN];
      enabledFlag->valueRank = 1;
      enabledFlag->minimumSamplingInterval = 1.0;
      enabledFlag->historizing = UA_FALSE;
      UA_Server_addNode(server, (UA_Node*)enabledFlag,
-             UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
-             UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY));
-     ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-             UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
+                       UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS), nodeIdHasProperty);
+     UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
+                            nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
 
      UA_VariableNode *serverstatus = UA_VariableNode_new();
       copyNames((UA_Node*)serverstatus, "ServerStatus");
       serverstatus->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS);
       serverstatus->valueSource = UA_VALUESOURCE_DATASOURCE;
-      serverstatus->value.dataSource = (UA_DataSource) {.handle = server, .read = readStatus,
+      serverstatus->value.dataSource = (UA_DataSource) {
+          .handle = server, .read = readStatus,
           .release = releaseStatus, .write = UA_NULL};
       UA_Server_addNode(server, (UA_Node*)serverstatus, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER),
-              UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-      ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSTYPE));
+                        nodeIdHasComponent);
+      UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
+                             nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSTYPE));
 
       UA_VariableNode *starttime = UA_VariableNode_new();
       copyNames((UA_Node*)starttime, "StartTime");
@@ -935,20 +929,22 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
       starttime->value.variant.data = &server->startTime;
       starttime->value.variant.type = &UA_TYPES[UA_TYPES_DATETIME];
       UA_Server_addNode(server, (UA_Node*)starttime, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-              UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-      ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+                        nodeIdHasComponent);
+      UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
+                             nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
       UA_VariableNode *currenttime = UA_VariableNode_new();
       copyNames((UA_Node*)currenttime, "CurrentTime");
       currenttime->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
       currenttime->valueSource = UA_VALUESOURCE_DATASOURCE;
-      currenttime->value.dataSource = (UA_DataSource) {.handle = NULL, .read = readCurrentTime,
+      currenttime->value.dataSource = (UA_DataSource) {
+          .handle = NULL, .read = readCurrentTime,
           .release = releaseCurrentTime, .write = UA_NULL};
-      UA_Server_addNode(server, (UA_Node*)currenttime, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-              UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-      ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+      UA_Server_addNode(server, (UA_Node*)currenttime,
+                        UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
+                        nodeIdHasComponent);
+      UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME),
+                             nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
       UA_VariableNode *state = UA_VariableNode_new();
       UA_ServerState *stateEnum = UA_ServerState_new();
@@ -959,9 +955,9 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
       state->value.variant.arrayLength = -1;
       state->value.variant.data = stateEnum; // points into the other object.
       UA_Server_addNode(server, (UA_Node*)state, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-              UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-      ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-          UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+                        nodeIdHasComponent);
+      UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
+                             nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
       UA_VariableNode *buildinfo = UA_VariableNode_new();
        copyNames((UA_Node*)buildinfo, "BuildInfo");
@@ -969,10 +965,11 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        buildinfo->value.variant.data = UA_BuildInfo_new();
        buildinfo->value.variant.type = &UA_TYPES[UA_TYPES_BUILDINFO];
        getBulidInfo(server, (UA_BuildInfo*)buildinfo->value.variant.data);
-       UA_Server_addNode(server, (UA_Node*)buildinfo, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE));
+       UA_Server_addNode(server, (UA_Node*)buildinfo,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                              nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE));
 
        UA_VariableNode *producturi = UA_VariableNode_new();
        copyNames((UA_Node*)producturi, "ProductUri");
@@ -980,10 +977,11 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        producturi->value.variant.data = UA_String_new();
        *((UA_String*)producturi->value.variant.data) = UA_STRING_ALLOC(PRODUCT_URI);
        producturi->value.variant.type = &UA_TYPES[UA_TYPES_STRING];
-       UA_Server_addNode(server, (UA_Node*)producturi, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)producturi,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *manufacturername = UA_VariableNode_new();
        copyNames((UA_Node*)manufacturername, "ManufacturererName");
@@ -991,10 +989,12 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        manufacturername->value.variant.data = UA_String_new();
        *((UA_String*)manufacturername->value.variant.data) = UA_STRING_ALLOC(MANUFACTURER_NAME);
        manufacturername->value.variant.type = &UA_TYPES[UA_TYPES_STRING];
-       UA_Server_addNode(server, (UA_Node*)manufacturername, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)manufacturername,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server,
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *productname = UA_VariableNode_new();
        copyNames((UA_Node*)productname, "ProductName");
@@ -1002,10 +1002,11 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        productname->value.variant.data = UA_String_new();
        *((UA_String*)productname->value.variant.data) = UA_STRING_ALLOC(PRODUCT_NAME);
        productname->value.variant.type = &UA_TYPES[UA_TYPES_STRING];
-       UA_Server_addNode(server, (UA_Node*)productname, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)productname,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *softwareversion = UA_VariableNode_new();
        copyNames((UA_Node*)softwareversion, "SoftwareVersion");
@@ -1013,10 +1014,12 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        softwareversion->value.variant.data = UA_String_new();
        *((UA_String*)softwareversion->value.variant.data) = UA_STRING_ALLOC(SOFTWARE_VERSION);
        softwareversion->value.variant.type = &UA_TYPES[UA_TYPES_STRING];
-       UA_Server_addNode(server, (UA_Node*)softwareversion, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)softwareversion,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server,
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *buildnumber = UA_VariableNode_new();
        copyNames((UA_Node*)buildnumber, "BuildNumber");
@@ -1024,10 +1027,11 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        buildnumber->value.variant.data = UA_String_new();
        *((UA_String*)buildnumber->value.variant.data) = UA_STRING_ALLOC(BUILD_NUMBER);
        buildnumber->value.variant.type = &UA_TYPES[UA_TYPES_STRING];
-       UA_Server_addNode(server, (UA_Node*)buildnumber, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)buildnumber,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *builddate = UA_VariableNode_new();
        copyNames((UA_Node*)builddate, "BuildDate");
@@ -1035,30 +1039,31 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
        builddate->value.variant.storageType = UA_VARIANT_DATA_NODELETE;
        builddate->value.variant.data = &server->buildDate;
        builddate->value.variant.type = &UA_TYPES[UA_TYPES_DATETIME];
-       UA_Server_addNode(server, (UA_Node*)builddate, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)builddate,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
+                         nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *secondstillshutdown = UA_VariableNode_new();
        copyNames((UA_Node*)secondstillshutdown, "SecondsTillShutdown");
        secondstillshutdown->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN);
        secondstillshutdown->value.variant.data = UA_UInt32_new();
        secondstillshutdown->value.variant.type = &UA_TYPES[UA_TYPES_UINT32];
-       UA_Server_addNode(server, (UA_Node*)secondstillshutdown, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)secondstillshutdown,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
        UA_VariableNode *shutdownreason = UA_VariableNode_new();
        copyNames((UA_Node*)shutdownreason, "ShutdownReason");
        shutdownreason->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON);
        shutdownreason->value.variant.data = UA_LocalizedText_new();
        shutdownreason->value.variant.type = &UA_TYPES[UA_TYPES_LOCALIZEDTEXT];
-       UA_Server_addNode(server, (UA_Node*)shutdownreason, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
-               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT));
-       ADDREFERENCE(UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON), UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+       UA_Server_addNode(server, (UA_Node*)shutdownreason,
+                         UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS), nodeIdHasComponent);
+       UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON),
+                              nodeIdHasTypeDefinition, expandedNodeIdBaseDataVariabletype);
 
    return server;
 }

+ 21 - 15
src/server/ua_server_addressspace.c

@@ -15,8 +15,8 @@ UA_Server_addVariableNode(UA_Server *server, UA_Variant *value, const UA_Qualifi
     UA_NodeId_copy(&parentNodeId, &parentId.nodeId);
     UA_AddNodesResult res =
         UA_Server_addNodeWithSession(server, &adminSession, (UA_Node*)node, parentId, referenceTypeId);
-    ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                 UA_EXPANDEDNODEID_NUMERIC(0, value->type->typeId.identifier.numeric));
+    UA_Server_addReference(server, res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
+                           UA_EXPANDEDNODEID_NUMERIC(0, value->type->typeId.identifier.numeric));
     if(res.statusCode != UA_STATUSCODE_GOOD) {
         UA_Variant_init(&node->value.variant);
         UA_VariableNode_delete(node);
@@ -48,7 +48,8 @@ UA_Server_addObjectNode(UA_Server *server, const UA_QualifiedName browseName,
         UA_ExpandedNodeId typeDefid; // we need an expandednodeid
         UA_ExpandedNodeId_init(&typeDefid);
         UA_NodeId_copy(&typeDefinition, &typeDefid.nodeId);
-        ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION), typeDefid);
+        UA_Server_addReference(server, res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
+                               typeDefid);
     }
     return res.statusCode;
 }
@@ -69,8 +70,8 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
     UA_NodeId_copy(&parentNodeId, &parentId.nodeId);
     UA_AddNodesResult res =
         UA_Server_addNodeWithSession(server, &adminSession, (UA_Node*)node, parentId, referenceTypeId);
-    ADDREFERENCE(res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
-                 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
+    UA_Server_addReference(server, res.addedNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION),
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
     if(res.statusCode != UA_STATUSCODE_GOOD)
         UA_VariableNode_delete(node);
     UA_AddNodesResult_deleteMembers(&res);
@@ -197,18 +198,22 @@ addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, const UA_A
 }
 
 /* userland version of addReferenceWithSession */
-UA_StatusCode
-UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item)
-{
-    return UA_Server_addReferenceWithSession(server, &adminSession, item);
+UA_StatusCode UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId,
+                                     const UA_ExpandedNodeId targetId) {
+    UA_AddReferencesItem item;
+    UA_AddReferencesItem_init(&item);
+    item.sourceNodeId = sourceId;
+    item.referenceTypeId = refTypeId;
+    item.isForward = UA_TRUE;
+    item.targetNodeId = targetId;
+    return UA_Server_addReferenceWithSession(server, &adminSession, &item);
 }
 
-UA_StatusCode
-UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item)
-{
+UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session,
+                                                const UA_AddReferencesItem *item) {
     if(item->targetServerUri.length > 0)
         return UA_STATUSCODE_BADNOTIMPLEMENTED; // currently no expandednodeids are allowed
-    
+
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
 
 #ifdef UA_EXTERNAL_NAMESPACES
@@ -227,7 +232,8 @@ UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session, const
 #endif
         retval = addOneWayReferenceWithSession(server, session, item);
 
-    if(retval) return retval;
+    if(retval)
+        return retval;
 
     UA_AddReferencesItem secondItem;
     secondItem = *item;
@@ -316,7 +322,7 @@ UA_Server_addNodeWithSession(UA_Server *server, UA_Session *session, UA_Node *no
     item.referenceTypeId = referenceType->nodeId;
     item.isForward = UA_FALSE;
     item.targetNodeId.nodeId = parent->nodeId;
-    UA_Server_addReference(server, &item);
+    UA_Server_addReferenceWithSession(server, session, &item);
 
     // todo: error handling. remove new node from nodestore
 

+ 71 - 132
src/server/ua_server_binary.c

@@ -90,6 +90,17 @@ static void processOPN(UA_Connection *connection, UA_Server *server, const UA_By
     Service_OpenSecureChannel(server, connection, &r, &p);
     UA_OpenSecureChannelRequest_deleteMembers(&r);
 
+    UA_SecureChannel *channel = connection->channel;
+    if(!channel) {
+        connection->close(connection);
+        UA_OpenSecureChannelResponse_deleteMembers(&p);
+        UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
+        return;
+    }
+
+    /* send the response with an asymmetric security header */
+    seqHeader.sequenceNumber = channel->sequenceNumber;
+
     UA_SecureConversationMessageHeader respHeader;
     respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
     respHeader.messageHeader.messageSize = 0;
@@ -134,63 +145,57 @@ static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r
 
 /* The request/response are casted to the header (first element of their struct) */
 static void invoke_service(UA_Server *server, UA_SecureChannel *channel,
-                           UA_RequestHeader *request, UA_ResponseHeader *response,
+                           UA_UInt32 requestId, UA_RequestHeader *request, const UA_DataType *responseType,
                            void (*service)(UA_Server*, UA_Session*, void*, void*)) {
+    UA_ResponseHeader *response = UA_alloca(responseType->memSize);
+    UA_init(response, responseType);
     init_response_header(request, response);
     /* try to get the session from the securechannel first */
     UA_Session *session = UA_SecureChannel_getSession(channel, &request->authenticationToken);
     if(!session || session->channel != channel) {
         response->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
-        return;
-    }
-    else if(session->activated == UA_FALSE) {
+    } else if(session->activated == UA_FALSE) {
         response->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
-        /* the session is invalidated */
+        /* the session is invalidated FIXME: do this delayed*/
         UA_SessionManager_removeSession(&server->sessionManager, &request->authenticationToken);
-        return;
+    } else {
+        UA_Session_updateLifetime(session);
+        service(server, session, request, response);
     }
-    UA_Session_updateLifetime(session);
-    service(server, session, request, response);
+    UA_SecureChannel_sendBinaryMessage(channel, requestId, response, responseType);
+    UA_deleteMembers(response, responseType);
 }
 
-#define INVOKE_SERVICE(TYPE) do {                                       \
-        UA_##TYPE##Request p;                                           \
-        UA_##TYPE##Response r;                                          \
-        if(UA_##TYPE##Request_decodeBinary(msg, pos, &p))               \
-            return;                                                     \
-        UA_##TYPE##Response_init(&r);                                   \
-        invoke_service(server, clientChannel, &p.requestHeader,         \
-                       &r.responseHeader,                               \
-                       (void (*)(UA_Server*, UA_Session*, void*,void*))Service_##TYPE); \
-        UA_##TYPE##Request_deleteMembers(&p);                           \
-        retval = connection->getBuffer(connection, &message,            \
-                     headerSize + UA_##TYPE##Response_calcSizeBinary(&r)); \
-        if(retval != UA_STATUSCODE_GOOD) {                              \
-            UA_##TYPE##Response_deleteMembers(&r);                      \
+#define INVOKE_SERVICE(REQUEST, RESPONSETYPE) do {                      \
+        UA_##REQUEST##Request p;                                        \
+        if(UA_##REQUEST##Request_decodeBinary(msg, pos, &p))            \
             return;                                                     \
-        }                                                               \
-        UA_##TYPE##Response_encodeBinary(&r, &message, &messagePos);    \
-        UA_##TYPE##Response_deleteMembers(&r);                          \
+        invoke_service(server, clientChannel, sequenceHeader.requestId, \
+                       &p.requestHeader, &UA_TYPES[RESPONSETYPE],       \
+                       (void (*)(UA_Server*, UA_Session*, void*,void*))Service_##REQUEST); \
+        UA_##REQUEST##Request_deleteMembers(&p);                        \
 } while(0)
 
 static void processMSG(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
-    // 1) Read in the securechannel
+    /* Read in the securechannel */
     UA_UInt32 secureChannelId;
     UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
     if(retval != UA_STATUSCODE_GOOD)
         return;
 
+    /* the anonymous channel is used e.g. to allow getEndpoints without a channel */
     UA_SecureChannel *clientChannel = connection->channel;
-#ifdef EXTENSION_STATELESS
     UA_SecureChannel anonymousChannel;
     if(!clientChannel) {
         UA_SecureChannel_init(&anonymousChannel);
-        anonymousChannel.session = &anonymousSession;
+        anonymousChannel.connection = connection;
         clientChannel = &anonymousChannel;
-    }
+#ifdef EXTENSION_STATELESS
+        anonymousChannel.session = &anonymousSession;
 #endif
+    }
 
-    // 2) Read the security header
+    /* Read the security header */
     UA_UInt32 tokenId;
     UA_SequenceHeader sequenceHeader;
     retval = UA_UInt32_decodeBinary(msg, pos, &tokenId);
@@ -198,45 +203,18 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
     if(retval != UA_STATUSCODE_GOOD)
         return;
 
-    //UA_SecureChannel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
-    //UA_SecureChannel_checkRequestId(channel,sequenceHeader.requestId);
-    clientChannel->sequenceNumber = sequenceHeader.sequenceNumber;
-    clientChannel->requestId = sequenceHeader.requestId;
-
-    // 3) Build the header and compute the header size
-    UA_SecureConversationMessageHeader respHeader;
-    respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
-    respHeader.messageHeader.messageSize = 0;
-    respHeader.secureChannelId = clientChannel->securityToken.channelId;
-
-    UA_SymmetricAlgorithmSecurityHeader symSecHeader;
-    symSecHeader.tokenId = clientChannel->securityToken.tokenId;
-
-    UA_SequenceHeader seqHeader;
-    seqHeader.sequenceNumber = clientChannel->sequenceNumber;
-    seqHeader.requestId = clientChannel->requestId;
-
-    // 4) process the request
-    UA_ByteString message;
+    /* Read the request type */
     UA_NodeId requestType;
-    if(UA_NodeId_decodeBinary(msg, pos, &requestType))
+    if(UA_NodeId_decodeBinary(msg, pos, &requestType) != UA_STATUSCODE_GOOD)
         return;
     if(requestType.identifierType != UA_NODEIDTYPE_NUMERIC) {
         UA_NodeId_deleteMembers(&requestType);
         return;
     }
 
-    UA_NodeId response_nodeid = UA_NODEID_NUMERIC(0, requestType.identifier.numeric + 3);
-    UA_UInt32 headerSize = UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader)
-        + UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(&symSecHeader)
-        + UA_SequenceHeader_calcSizeBinary(&seqHeader)
-        + UA_NodeId_calcSizeBinary(&response_nodeid);
-    size_t messagePos = headerSize;
-
-    //subtract UA_ENCODINGOFFSET_BINARY for binary encoding
     switch(requestType.identifier.numeric - UA_ENCODINGOFFSET_BINARY) {
     case UA_NS0ID_GETENDPOINTSREQUEST: {
-        UA_GetEndpointsRequest  p;
+        UA_GetEndpointsRequest p;
         UA_GetEndpointsResponse r;
         if(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p))
             return;
@@ -244,12 +222,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         init_response_header(&p.requestHeader, &r.responseHeader);
         Service_GetEndpoints(server, &p, &r);
         UA_GetEndpointsRequest_deleteMembers(&p);
-        retval = connection->getBuffer(connection, &message, headerSize + UA_GetEndpointsResponse_calcSizeBinary(&r));
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_GetEndpointsResponse_deleteMembers(&r);
-            return;
-        }
-        UA_GetEndpointsResponse_encodeBinary(&r, &message, &messagePos);
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
+                                           &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
         UA_GetEndpointsResponse_deleteMembers(&r);
         break;
     }
@@ -263,12 +237,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         init_response_header(&p.requestHeader, &r.responseHeader);
         Service_FindServers(server, &p, &r);
         UA_FindServersRequest_deleteMembers(&p);
-        retval = connection->getBuffer(connection, &message, headerSize + UA_FindServersResponse_calcSizeBinary(&r));
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_FindServersResponse_deleteMembers(&r);
-            return;
-        }
-        UA_FindServersResponse_encodeBinary(&r, &message, &messagePos);
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
+                                           &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
         UA_FindServersResponse_deleteMembers(&r);
         break;
     }
@@ -282,12 +252,8 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         init_response_header(&p.requestHeader, &r.responseHeader);
         Service_CreateSession(server, clientChannel, &p, &r);
         UA_CreateSessionRequest_deleteMembers(&p);
-        retval = connection->getBuffer(connection, &message, headerSize + UA_CreateSessionResponse_calcSizeBinary(&r));
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_CreateSessionResponse_deleteMembers(&r);
-            return;
-        }
-        UA_CreateSessionResponse_encodeBinary(&r, &message, &messagePos);
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
+                                           &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
         UA_CreateSessionResponse_deleteMembers(&r);
         break;
     }
@@ -301,71 +267,66 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         init_response_header(&p.requestHeader, &r.responseHeader);
         Service_ActivateSession(server, clientChannel, &p, &r);
         UA_ActivateSessionRequest_deleteMembers(&p);
-        retval = connection->getBuffer(connection, &message, headerSize + UA_ActivateSessionResponse_calcSizeBinary(&r));
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_ActivateSessionResponse_deleteMembers(&r);
-            return;
-        }
-        UA_ActivateSessionResponse_encodeBinary(&r, &message, &messagePos);
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
+                                           &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
         UA_ActivateSessionResponse_deleteMembers(&r);
         break;
     }
     
     case UA_NS0ID_CLOSESESSIONREQUEST:
-        INVOKE_SERVICE(CloseSession);
+        INVOKE_SERVICE(CloseSession, UA_TYPES_CLOSESESSIONRESPONSE);
         break;
     case UA_NS0ID_READREQUEST:
-        INVOKE_SERVICE(Read);
+        INVOKE_SERVICE(Read, UA_TYPES_READRESPONSE);
         break;
     case UA_NS0ID_WRITEREQUEST:
-        INVOKE_SERVICE(Write);
+        INVOKE_SERVICE(Write, UA_TYPES_WRITERESPONSE);
         break;
     case UA_NS0ID_BROWSEREQUEST:
-        INVOKE_SERVICE(Browse);
+        INVOKE_SERVICE(Browse, UA_TYPES_BROWSERESPONSE);
         break;
     case UA_NS0ID_BROWSENEXTREQUEST:
-        INVOKE_SERVICE(BrowseNext);
+        INVOKE_SERVICE(BrowseNext, UA_TYPES_BROWSENEXTRESPONSE);
         break;
     case UA_NS0ID_ADDREFERENCESREQUEST:
-        INVOKE_SERVICE(AddReferences);
+        INVOKE_SERVICE(AddReferences, UA_TYPES_ADDREFERENCESRESPONSE);
         break;
     case UA_NS0ID_REGISTERNODESREQUEST:
-        INVOKE_SERVICE(RegisterNodes);
+        INVOKE_SERVICE(RegisterNodes, UA_TYPES_REGISTERNODESRESPONSE);
         break;
     case UA_NS0ID_UNREGISTERNODESREQUEST:
-        INVOKE_SERVICE(UnregisterNodes);
+        INVOKE_SERVICE(UnregisterNodes, UA_TYPES_UNREGISTERNODESRESPONSE);
         break;
     case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST:
-        INVOKE_SERVICE(TranslateBrowsePathsToNodeIds);
+        INVOKE_SERVICE(TranslateBrowsePathsToNodeIds, UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE);
         break;
 
 #ifdef ENABLE_SUBSCRIPTIONS    
     case UA_NS0ID_CREATESUBSCRIPTIONREQUEST:
-        INVOKE_SERVICE(CreateSubscription);
+        INVOKE_SERVICE(CreateSubscription, UA_TYPES_CREATESUBSCRIPTIONRESPONSE);
         break;
     case UA_NS0ID_PUBLISHREQUEST:
-        INVOKE_SERVICE(Publish);
+        INVOKE_SERVICE(Publish, UA_TYPES_PUBLISHRESPONSE);
         break;
     case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST:
-        INVOKE_SERVICE(DeleteSubscriptions);
+        INVOKE_SERVICE(DeleteSubscriptions, UA_TYPES_DELETESUBSCRIPTIONSRESPONSE);
         break;
     case UA_NS0ID_CREATEMONITOREDITEMSREQUEST:
-        INVOKE_SERVICE(CreateMonitoredItems);
+        INVOKE_SERVICE(CreateMonitoredItems, UA_TYPES_CREATEMONITOREDITEMSRESPONSE);
         break;
     case UA_NS0ID_DELETEMONITOREDITEMSREQUEST:
-        INVOKE_SERVICE(DeleteMonitoredItems);
+        INVOKE_SERVICE(DeleteMonitoredItems, UA_TYPES_DELETEMONITOREDITEMSRESPONSE);
         break;
 #endif
 
     default: {
-        if(requestType.namespaceIndex == 0 && requestType.identifier.numeric==787){
+        if(requestType.namespaceIndex == 0 && requestType.identifier.numeric==787)
             UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION,
                         "Client requested a subscription that are not supported, the message will be skipped");
-        }else{
+        else
             UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION, "Unknown request: NodeId(ns=%d, i=%d)",
                         requestType.namespaceIndex, requestType.identifier.numeric);
-        }
-        UA_RequestHeader  p;
+        UA_RequestHeader p;
         UA_ResponseHeader r;
         if(UA_RequestHeader_decodeBinary(msg, pos, &p) != UA_STATUSCODE_GOOD)
             return;
@@ -377,30 +338,11 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
             r.serviceResult = retval;
 #endif
         UA_RequestHeader_deleteMembers(&p);
-        retval = connection->getBuffer(connection, &message, headerSize + UA_ResponseHeader_calcSizeBinary(&r));
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_ResponseHeader_deleteMembers(&r);
-            return;
-        }
-        UA_ResponseHeader_encodeBinary(&r, &message, &messagePos);
-        UA_ResponseHeader_deleteMembers(&r);
-        response_nodeid = UA_NODEID_NUMERIC(0, UA_NS0ID_RESPONSEHEADER + UA_ENCODINGOFFSET_BINARY);
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId,
+            &r, &UA_TYPES[UA_TYPES_RESPONSEHEADER]);
         break;
     }
     }
-
-    messagePos = 0;
-    respHeader.messageHeader.messageSize = message.length;
-    UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &message, &messagePos);
-    UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, &message, &messagePos);
-    UA_SequenceHeader_encodeBinary(&seqHeader, &message, &messagePos);
-    UA_NodeId_encodeBinary(&response_nodeid, &message, &messagePos);
-
-    // todo: sign & encrypt
-
-    // 5) Send it over the wire.
-    connection->write(connection, &message);
-    connection->releaseBuffer(connection, &message);
 }
 
 static void processCLO(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) {
@@ -418,7 +360,7 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
     size_t pos = 0;
     UA_TcpMessageHeader tcpMessageHeader;
     do {
-        if(UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader) != UA_STATUSCODE_GOOD) {
+        if(UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader)) {
             UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION, "Decoding of message header failed");
             connection->close(connection);
             break;
@@ -434,15 +376,12 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
             processOPN(connection, server, msg, &pos);
             break;
         case UA_MESSAGETYPEANDFINAL_MSGF & 0xffffff:
-#ifdef EXTENSION_STATELESS
-            processMSG(connection, server, msg, &pos);
-            break;
-#endif
-            if(connection->state != UA_CONNECTION_ESTABLISHED) {
+#ifndef EXTENSION_STATELESS
+            if(connection->state != UA_CONNECTION_ESTABLISHED)
                 connection->close(connection);
-                break;
-            }
-            processMSG(connection, server, msg, &pos);
+            else
+#endif
+                processMSG(connection, server, msg, &pos);
             break;
         case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff:
             processCLO(connection, server, msg, &pos);

+ 2 - 11
src/server/ua_server_internal.h

@@ -83,20 +83,11 @@ UA_AddNodesResult UA_Server_addNodeWithSession(UA_Server *server, UA_Session *se
 UA_AddNodesResult UA_Server_addNode(UA_Server *server, UA_Node *node, const UA_ExpandedNodeId parentNodeId,
                                     const UA_NodeId referenceTypeId);
 
-UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item);
+UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session,
+                                                const UA_AddReferencesItem *item);
 
 UA_StatusCode UA_Server_addDelayedJob(UA_Server *server, UA_Job job);
 
 void UA_Server_deleteAllRepeatedJobs(UA_Server *server);
 
-#define ADDREFERENCE(NODEID, REFTYPE_NODEID, TARGET_EXPNODEID) do {     \
-        UA_AddReferencesItem item;                                      \
-        UA_AddReferencesItem_init(&item);                               \
-        item.sourceNodeId = NODEID;                                     \
-        item.referenceTypeId = REFTYPE_NODEID;                          \
-        item.isForward = UA_TRUE;                                       \
-        item.targetNodeId = TARGET_EXPNODEID;                           \
-        UA_Server_addReference(server, &item);                          \
-    } while(0)
-
 #endif /* UA_SERVER_INTERNAL_H_ */

+ 1 - 1
src/server/ua_services_nodemanagement.c

@@ -333,7 +333,7 @@ void Service_AddReferences(UA_Server *server, UA_Session *session, const UA_AddR
 #ifdef UA_EXTERNAL_NAMESPACES
 		if(!isExternal[i])
 #endif
-			UA_Server_addReference(server, &request->referencesToAdd[i]);
+			UA_Server_addReferenceWithSession(server, session, &request->referencesToAdd[i]);
 	}
 }
 

+ 57 - 20
src/ua_securechannel.c

@@ -2,6 +2,7 @@
 #include "ua_securechannel.h"
 #include "ua_session.h"
 #include "ua_statuscodes.h"
+#include "ua_types_encoding_binary.h"
 
 void UA_SecureChannel_init(UA_SecureChannel *channel) {
     UA_MessageSecurityMode_init(&channel->securityMode);
@@ -10,7 +11,6 @@ void UA_SecureChannel_init(UA_SecureChannel *channel) {
     UA_AsymmetricAlgorithmSecurityHeader_init(&channel->serverAsymAlgSettings);
     UA_ByteString_init(&channel->clientNonce);
     UA_ByteString_init(&channel->serverNonce);
-    channel->requestId = 0;
     channel->sequenceNumber = 0;
     channel->connection = UA_NULL;
     LIST_INIT(&channel->sessions);
@@ -43,22 +43,6 @@ UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce) {
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId) {
-    //TODO review checking of request id
-    if(channel->requestId+1 != requestId)
-        return UA_STATUSCODE_BADINTERNALERROR;
-    channel->requestId++;
-    return UA_STATUSCODE_GOOD;
-}
-
-UA_StatusCode UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
-    //TODO review checking of sequence
-    if(channel->sequenceNumber+1  != sequenceNumber)
-        return UA_STATUSCODE_BADINTERNALERROR;
-    channel->sequenceNumber++;
-    return UA_STATUSCODE_GOOD;
-}
-
 void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
     struct SessionEntry *se = UA_malloc(sizeof(struct SessionEntry));
     if(!se)
@@ -98,8 +82,61 @@ UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *t
         if(UA_NodeId_equal(&se->session->authenticationToken, token))
             break;
     }
-    if(se)
-        return se->session;
-    else
+    if(!se)
         return UA_NULL;
+    return se->session;
+}
+
+UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+                                                  const void *content,
+                                                  const UA_DataType *contentType) {
+    UA_Connection *connection = channel->connection;
+    if(!connection)
+        return UA_STATUSCODE_BADINTERNALERROR;
+
+    UA_NodeId typeId = contentType->typeId;
+    if(typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
+        return UA_STATUSCODE_BADINTERNALERROR;
+    typeId.identifier.numeric += UA_ENCODINGOFFSET_BINARY;
+
+    UA_SecureConversationMessageHeader respHeader;
+    respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF;
+    respHeader.messageHeader.messageSize = 0;
+    respHeader.secureChannelId = channel->securityToken.channelId;
+
+    UA_SymmetricAlgorithmSecurityHeader symSecHeader;
+    symSecHeader.tokenId = channel->securityToken.tokenId;
+
+    UA_SequenceHeader seqHeader;
+    seqHeader.requestId = requestId;
+
+    respHeader.messageHeader.messageSize =
+        UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader)
+        + UA_SymmetricAlgorithmSecurityHeader_calcSizeBinary(&symSecHeader)
+        + UA_SequenceHeader_calcSizeBinary(&seqHeader)
+        + UA_NodeId_calcSizeBinary(&typeId)
+        + UA_calcSizeBinary(content, contentType);
+
+    UA_ByteString message;
+    UA_StatusCode retval = connection->getBuffer(connection, &message, respHeader.messageHeader.messageSize);
+    if(retval)
+        return retval;
+
+    /* do this only now, so the sequence number does not increase if sth fails */
+#ifndef UA_MULTITHREADING
+    seqHeader.sequenceNumber = ++channel->sequenceNumber;
+#else
+    seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1);
+#endif
+
+    size_t messagePos = 0;
+    UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &message, &messagePos);
+    UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, &message, &messagePos);
+    UA_SequenceHeader_encodeBinary(&seqHeader, &message, &messagePos);
+    UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
+    UA_encodeBinary(content, contentType, &message, &messagePos);
+    
+    connection->write(connection, &message);
+    connection->releaseBuffer(connection, &message);
+    return UA_STATUSCODE_GOOD;
 }

+ 3 - 3
src/ua_securechannel.h

@@ -27,7 +27,6 @@ struct UA_SecureChannel {
     UA_AsymmetricAlgorithmSecurityHeader serverAsymAlgSettings;
     UA_ByteString  clientNonce;
     UA_ByteString  serverNonce;
-    UA_UInt32      requestId;
     UA_UInt32      sequenceNumber;
     UA_Connection *connection;
     LIST_HEAD(session_pointerlist, SessionEntry) sessions;
@@ -37,13 +36,14 @@ void UA_SecureChannel_init(UA_SecureChannel *channel);
 void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel);
 
 UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce);
-UA_StatusCode UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId);
-UA_StatusCode UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, UA_UInt32 sequenceNumber);
 
 void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session);
 void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session);
 UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token);
 
+UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
+                                                  const void *content, const UA_DataType *contentType);
+
 /** @} */
 
 #endif /* UA_SECURECHANNEL_H_ */

+ 1 - 1
src/ua_types.c

@@ -1240,7 +1240,7 @@ UA_StatusCode UA_Array_copy(const void *src, void **dst, const UA_DataType *data
     uintptr_t ptrd = (uintptr_t)*dst;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
     for(int i = 0; i < noElements; i++) {
-        retval = UA_copy((void*)ptrs, (void*)ptrd, dataType);
+        retval |= UA_copy((void*)ptrs, (void*)ptrd, dataType);
         ptrs += dataType->memSize;
         ptrd += dataType->memSize;
     }