Browse Source

reworking the nodestore interface

FlorianPalm 10 years ago
parent
commit
6a46ef58eb

+ 1 - 0
CMakeLists.txt

@@ -37,6 +37,7 @@ set(lib_sources src/ua_types.c
                 src/server/ua_services_monitoreditems.c
 				src/server/nodestore/open62541_nodestore_view.c
 				src/server/nodestore/open62541_nodestore_attribute.c
+				src/server/nodestore/open62541_nodestore_nodemanagement.c
 				src/server/nodestore/open62541_nodestore.c
                 ${headers}
                 ${generated_headers})

+ 27 - 0
Makefile

@@ -284,6 +284,30 @@ src/server/nodestore/open62541_nodestore_attribute.c.s:
 	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/open62541_nodestore_attribute.c.s
 .PHONY : src/server/nodestore/open62541_nodestore_attribute.c.s
 
+src/server/nodestore/open62541_nodestore_nodemanagement.o: src/server/nodestore/open62541_nodestore_nodemanagement.c.o
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.o
+
+# target to build an object file
+src/server/nodestore/open62541_nodestore_nodemanagement.c.o:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/open62541_nodestore_nodemanagement.c.o
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.c.o
+
+src/server/nodestore/open62541_nodestore_nodemanagement.i: src/server/nodestore/open62541_nodestore_nodemanagement.c.i
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.i
+
+# target to preprocess a source file
+src/server/nodestore/open62541_nodestore_nodemanagement.c.i:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/open62541_nodestore_nodemanagement.c.i
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.c.i
+
+src/server/nodestore/open62541_nodestore_nodemanagement.s: src/server/nodestore/open62541_nodestore_nodemanagement.c.s
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.s
+
+# target to generate assembly for a file
+src/server/nodestore/open62541_nodestore_nodemanagement.c.s:
+	$(MAKE) -f CMakeFiles/open62541-objects.dir/build.make CMakeFiles/open62541-objects.dir/src/server/nodestore/open62541_nodestore_nodemanagement.c.s
+.PHONY : src/server/nodestore/open62541_nodestore_nodemanagement.c.s
+
 src/server/nodestore/open62541_nodestore_view.o: src/server/nodestore/open62541_nodestore_view.c.o
 .PHONY : src/server/nodestore/open62541_nodestore_view.o
 
@@ -913,6 +937,9 @@ help:
 	@echo "... src/server/nodestore/open62541_nodestore_attribute.o"
 	@echo "... src/server/nodestore/open62541_nodestore_attribute.i"
 	@echo "... src/server/nodestore/open62541_nodestore_attribute.s"
+	@echo "... src/server/nodestore/open62541_nodestore_nodemanagement.o"
+	@echo "... src/server/nodestore/open62541_nodestore_nodemanagement.i"
+	@echo "... src/server/nodestore/open62541_nodestore_nodemanagement.s"
 	@echo "... src/server/nodestore/open62541_nodestore_view.o"
 	@echo "... src/server/nodestore/open62541_nodestore_view.i"
 	@echo "... src/server/nodestore/open62541_nodestore_view.s"

+ 11 - 6
examples/opcuaServer.c

@@ -16,10 +16,11 @@
 #include "logger_stdout.h"
 #include "networklayer_tcp.h"
 
-#include "nodestoreAccessExample.h"
+
 #include "../src/server/nodestore/ua_nodestore.h"
 #include "../src/server/ua_namespace_manager.h"
 #include "../src/server/nodestore/open62541_nodestore.h"
+#include "../src/server/nodestore/ua_nodestoreExample.h"
 UA_Boolean running = UA_TRUE;
 
 
@@ -53,6 +54,7 @@ UA_ByteString loadCertificate() {
 
     return certificate;
 }
+UA_StatusCode UA_EXPORT UA_NodeStoreExample_new(UA_NodeStoreExample **result);
 
 int main(int argc, char** argv) {
 	signal(SIGINT, stopHandler); /* catches ctrl-c */
@@ -60,16 +62,19 @@ int main(int argc, char** argv) {
 	UA_Server server;
 	UA_String endpointUrl;
 	UA_String_copycstring("no endpoint url",&endpointUrl);
-	UA_Server_init(&server, &endpointUrl);
 	UA_NodeStore newNodeStore;
+	UA_NodeStoreExample_new(&server.nodestore);
 
-	UA_Server_addNamespace(&server,0,&newNodeStore);
-
-	initMyNode();
+	Nodestore_set(server.nodestore);
+	UA_NamespaceManager_new(&server.namespaceManager);
+	UA_NamespaceManager_addNamespace(server.namespaceManager,0, &newNodeStore);
 	UA_NodeStore_registerReadNodesOperation(&newNodeStore,open62541NodeStore_ReadNodes);
 	UA_NodeStore_registerBrowseNodesOperation(&newNodeStore,open62541NodeStore_BrowseNodes);
+	UA_NodeStore_registerAddNodesOperation(&newNodeStore,open62541Nodestore_addNodes);
+	//UA_NodeStore_registerWriteNodesOperation(&newNodeStore,writeNodes);
+	UA_Server_init(&server, &endpointUrl);
 
-	UA_NodeStore_registerWriteNodesOperation(&newNodeStore,writeNodes);
+	//initMyNode();
 
 	Logger_Stdout_init(&server.logger);
     server.serverCertificate = loadCertificate();

+ 18 - 34
include/ua_server.h

@@ -25,7 +25,6 @@ extern "C" {
 #include "ua_connection.h"
 #include "ua_log.h"
 
-
 /** @defgroup server Server */
 
 //identifier numbers are different for XML and binary, so we have to substract an offset for comparison
@@ -38,16 +37,12 @@ typedef struct UA_SecureChannelManager UA_SecureChannelManager;
 struct UA_SessionManager;
 typedef struct UA_SessionManager UA_SessionManager;
 
-
-
-
 struct UA_NodeStore;
 typedef struct UA_NodeStore UA_NodeStore;
 
 struct UA_NodeStoreExample;
 typedef struct UA_NodeStoreExample UA_NodeStoreExample;
 
-
 //struct UA_Namespace;
 //typedef struct UA_Namespace UA_Namespace;
 typedef struct UA_Namespace
@@ -59,22 +54,17 @@ typedef struct UA_Namespace
 struct UA_NamespaceManager;
 typedef struct UA_NamespaceManager UA_NamespaceManager;
 
-
 typedef UA_Int32 (*UA_NodeStore_addNodes)(UA_AddNodesItem *nodesToAdd,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_AddNodesResult* addNodesResults, UA_DiagnosticInfo *diagnosticInfos);
-typedef UA_Int32 (*UA_NodeStore_addReferences)(UA_AddReferencesItem* referencesToAdd,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_StatusCode *addReferencesResults, UA_DiagnosticInfo diagnosticInfos);
+typedef UA_Int32 (*UA_NodeStore_addReferences)(UA_AddReferencesItem* referencesToAdd,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_StatusCode *addReferencesResults, UA_DiagnosticInfo *diagnosticInfos);
 
 typedef UA_Int32 (*UA_NodeStore_deleteNodes)(UA_DeleteNodesItem *nodesToDelete,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_StatusCode *deleteNodesResults, UA_DiagnosticInfo *diagnosticInfos);
-typedef UA_Int32 (*UA_NodeStore_deleteReferences)(UA_DeleteReferencesItem *referenceToDelete,UA_UInt32 *indices, UA_UInt32 indicesSize,UA_StatusCode deleteReferencesresults, UA_DiagnosticInfo diagnosticInfos);
-
+typedef UA_Int32 (*UA_NodeStore_deleteReferences)(UA_DeleteReferencesItem *referenceToDelete,UA_UInt32 *indices, UA_UInt32 indicesSize,UA_StatusCode deleteReferencesresults, UA_DiagnosticInfo *diagnosticInfos);
 
 typedef UA_Int32 (*UA_NodeStore_readNodes)(UA_ReadValueId *readValueIds,UA_UInt32 *indices,UA_UInt32 indicesSize,UA_DataValue *readNodesResults, UA_Boolean timeStampToReturn, UA_DiagnosticInfo *diagnosticInfos);
 typedef UA_Int32 (*UA_NodeStore_writeNodes)(UA_WriteValue *writeValues,UA_UInt32 *indices ,UA_UInt32 indicesSize, UA_StatusCode *writeNodesResults, UA_DiagnosticInfo *diagnosticInfo);
 typedef UA_Int32 (*UA_NodeStore_browseNodes)(UA_BrowseDescription *browseDescriptions,UA_UInt32 *indices,UA_UInt32 indicesSize, UA_UInt32 requestedMaxReferencesPerNode, UA_BrowseResult *browseResults, UA_DiagnosticInfo *diagnosticInfos);
 
-
-
-
-struct  UA_NodeStore{
+struct UA_NodeStore {
 	//new, set, get, remove,
 	UA_NodeStore_addNodes addNodes;
 	UA_NodeStore_deleteNodes deleteNodes;
@@ -85,25 +75,20 @@ struct  UA_NodeStore{
 	UA_NodeStore_deleteReferences deleteReferences;
 };
 
-
-
-
 typedef struct UA_Server {
-    UA_ApplicationDescription description;
-    UA_SecureChannelManager *secureChannelManager;
-    UA_SessionManager *sessionManager;
-    UA_NamespaceManager* namespaceManager;
-    UA_NodeStoreExample *nodestore;
-    UA_Logger logger;
-    UA_ByteString serverCertificate;
-
+	UA_ApplicationDescription description;
+	UA_SecureChannelManager *secureChannelManager;
+	UA_SessionManager *sessionManager;
+	UA_NamespaceManager* namespaceManager;
+	UA_NodeStoreExample *nodestore;
+	UA_Logger logger;
+	UA_ByteString serverCertificate;
 
-    // todo: move these somewhere sane
-    UA_ExpandedNodeId objectsNodeId;
-    UA_NodeId hasComponentReferenceTypeId;
+	// todo: move these somewhere sane
+	UA_ExpandedNodeId objectsNodeId;
+	UA_NodeId hasComponentReferenceTypeId;
 
-
-} UA_Server;
+}UA_Server;
 
 void UA_EXPORT UA_Server_init(UA_Server *server, UA_String *endpointUrl);
 UA_StatusCode UA_EXPORT UA_Server_deleteMembers(UA_Server *server);
@@ -111,13 +96,12 @@ void UA_EXPORT UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *
 
 /* Services for local use */
 UA_AddNodesResult UA_EXPORT UA_Server_addScalarVariableNode(UA_Server *server, UA_String *browseName, void *value,
-                                                            const UA_VTable_Entry *vt, UA_ExpandedNodeId *parentNodeId,
-                                                            UA_NodeId *referenceTypeId );
+		const UA_VTable_Entry *vt, UA_ExpandedNodeId *parentNodeId,
+		UA_NodeId *referenceTypeId );
 UA_AddNodesResult UA_EXPORT UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,
-                                              UA_NodeId *referenceTypeId);
+		UA_NodeId *referenceTypeId);
 void UA_EXPORT UA_Server_addReferences(UA_Server *server, const UA_AddReferencesRequest *request,
-                                       UA_AddReferencesResponse *response);
-
+		UA_AddReferencesResponse *response);
 
 UA_Int32 UA_EXPORT UA_Server_addNamespace(UA_Server *server, UA_UInt16 namespaceIndex, UA_NodeStore *nodeStore);
 

+ 2 - 2
src/server/nodestore/ua_nodestore.h

@@ -1,12 +1,12 @@
 #ifndef UA_NODESTORE_H_
 #define UA_NODESTORE_H_
 
-#include "ua_server.h"
 
 
+#include "ua_server.h"
 
 
-UA_StatusCode UA_EXPORT UA_NodeStore_registerAddNodesOperation(UA_NodeStore *nodeStore, UA_NodeStore_addNodes addNode);
+UA_StatusCode UA_EXPORT UA_NodeStore_registerAddNodesOperation(UA_NodeStore *nodeStore, UA_NodeStore_addNodes addNodes);
 UA_StatusCode UA_EXPORT UA_NodeStore_registerAddReferenceOperation(UA_NodeStore *nodeStore, UA_NodeStore_addReferences addReference);
 UA_StatusCode UA_EXPORT UA_NodeStore_registerDeleteNodesOperation(UA_NodeStore *nodeStore, UA_NodeStore_deleteNodes deleteNode);
 UA_StatusCode UA_EXPORT UA_NodeStore_registerDeleteReferencesOperation(UA_NodeStore *nodeStore, UA_NodeStore_deleteReferences deleteReference);

+ 2 - 2
src/server/nodestore/ua_nodestoreExample.h

@@ -2,7 +2,7 @@
 #define UA_NODESTORE_H_
 
 #include "ua_server.h"
-
+#include "ua_config.h"
 /**
    @ingroup server
 
@@ -22,7 +22,7 @@
  */
 
 /** @brief Create a new namespace */
-UA_StatusCode UA_NodeStoreExample_new(UA_NodeStoreExample **result);
+UA_StatusCode UA_EXPORT UA_NodeStoreExample_new(UA_NodeStoreExample **result);
 
 /** @brief Delete the namespace and all nodes in it */
 void UA_NodeStoreExample_delete(UA_NodeStoreExample *ns);

+ 5 - 5
src/server/ua_namespace_manager.h

@@ -11,15 +11,15 @@
 #include "nodestore/ua_nodestore.h"
 
 
-void UA_NamespaceManager_new(UA_NamespaceManager** namespaceManager);
+void UA_EXPORT UA_NamespaceManager_new(UA_NamespaceManager** namespaceManager);
 
-UA_Int32 UA_NamespaceManager_addNamespace(UA_NamespaceManager *namespaceManager, UA_UInt16 index, UA_NodeStore *nodeStore);
+UA_Int32 UA_EXPORT UA_NamespaceManager_addNamespace(UA_NamespaceManager *namespaceManager, UA_UInt16 index, UA_NodeStore *nodeStore);
 
-UA_Int32 UA_NamespaceManager_removeNamespace(UA_NamespaceManager *namespaceManager,UA_UInt16 index);
+UA_Int32 UA_EXPORT UA_NamespaceManager_removeNamespace(UA_NamespaceManager *namespaceManager,UA_UInt16 index);
 
-UA_Int32 UA_NamespaceManager_getNamespace(UA_NamespaceManager *namespaceManager, UA_UInt16 index, UA_Namespace **ns);
+UA_Int32 UA_EXPORT UA_NamespaceManager_getNamespace(UA_NamespaceManager *namespaceManager, UA_UInt16 index, UA_Namespace **ns);
 
-UA_Int32 UA_NamespaceManager_setNodeStore(UA_NamespaceManager *namespaceManager,UA_UInt16 index, UA_NodeStore *nodeStore);
+UA_Int32 UA_EXPORT UA_NamespaceManager_setNodeStore(UA_NamespaceManager *namespaceManager,UA_UInt16 index, UA_NodeStore *nodeStore);
 
 
 

+ 157 - 3
src/server/ua_server.c

@@ -16,14 +16,29 @@ UA_StatusCode UA_Server_deleteMembers(UA_Server *server) {
     UA_ByteString_deleteMembers(&server->serverCertificate);
     return UA_STATUSCODE_GOOD;
 }
-
+void addSingleReference(UA_Namespace *namespace,UA_AddReferencesItem *addReferencesItem){
+	UA_UInt32 indices = 1;
+	UA_UInt32 indicesSize = 1;
+	UA_DiagnosticInfo diagnosticInfo;
+	UA_StatusCode result;
+	namespace->nodeStore->addReferences(addReferencesItem,&indices,indicesSize,&result,&diagnosticInfo);
+}
+void addSingleNode(UA_Namespace *namespace, UA_AddNodesItem *addNodesItem){
+	UA_UInt32 indices = 0;
+	UA_UInt32 indicesSize = 1;
+	UA_DiagnosticInfo diagnosticInfo;
+	UA_AddNodesResult result;
+	namespace->nodeStore->addNodes(addNodesItem, &indices, indicesSize, &result, &diagnosticInfo);
+}
 void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_ExpandedNodeId_init(&server->objectsNodeId);
     server->objectsNodeId.nodeId.identifier.numeric = 85;
 
     UA_NodeId_init(&server->hasComponentReferenceTypeId);
     server->hasComponentReferenceTypeId.identifier.numeric = 47;
-    UA_NamespaceManager_new(&server->namespaceManager);
+
+
+
     UA_ApplicationDescription_init(&server->description);
     UA_ByteString_init(&server->serverCertificate);
 #define MAXCHANNELCOUNT 100
@@ -39,7 +54,7 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_SessionManager_new(&server->sessionManager, MAXSESSIONCOUNT, SESSIONLIFETIME,
                           STARTSESSIONID);
 
-    UA_NodeStoreExample_new(&server->nodestore);
+
     //ns0: C2UA_STRING("http://opcfoundation.org/UA/"));
     //ns1: C2UA_STRING("http://localhost:16664/open62541/"));
 
@@ -72,6 +87,43 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_ExpandedNodeId RefTypeId_HasEffect; NS0EXPANDEDNODEID(RefTypeId_HasEffect, 54);
     UA_ExpandedNodeId RefTypeId_HasHistoricalConfiguration; NS0EXPANDEDNODEID(RefTypeId_HasHistoricalConfiguration, 56);
 
+
+
+#define ADD_REFTYPENODE_NS0(REFTYPE_NODEID,REQ_NODEID_NUMERIC_IDENTIFIER,PARENTNODEID_NUMERIC_IDENTIFIER,REFTYPE_BROWSENAME,REFTYPE_DISPLAYNAME,REFTYPE_DESCRIPTION, IS_ABSTRACT, IS_SYMMETRIC) do{\
+	UA_AddNodesItem addNodesItem; \
+    UA_Namespace *ns0; \
+    UA_NamespaceManager_getNamespace(server->namespaceManager,0,&ns0); \
+	UA_ReferenceTypeAttributes refTypeAttr; \
+    addNodesItem.parentNodeId.nodeId.identifier.numeric = PARENTNODEID_NUMERIC_IDENTIFIER;\
+    addNodesItem.parentNodeId.nodeId.namespaceIndex = 0; \
+    addNodesItem.parentNodeId.nodeId.identifierType = UA_NODEIDTYPE_NUMERIC; \
+    addNodesItem.requestedNewNodeId.nodeId.identifier.numeric = REQ_NODEID_NUMERIC_IDENTIFIER; \
+    addNodesItem.requestedNewNodeId.nodeId.namespaceIndex = 0; \
+    addNodesItem.requestedNewNodeId.nodeId.identifierType = UA_NODEIDTYPE_NUMERIC; \
+    addNodesItem.referenceTypeId = REFTYPE_NODEID; \
+    addNodesItem.nodeClass = UA_NODECLASS_REFERENCETYPE; \
+    UA_QualifiedName_copycstring(REFTYPE_BROWSENAME, &addNodesItem.browseName); \
+    UA_LocalizedText_copycstring(REFTYPE_DISPLAYNAME, &refTypeAttr.displayName); \
+    UA_LocalizedText_copycstring(REFTYPE_DESCRIPTION, &refTypeAttr.description); \
+    refTypeAttr.isAbstract = IS_ABSTRACT; \
+    refTypeAttr.symmetric  = IS_SYMMETRIC; \
+    refTypeAttr.userWriteMask = 0; \
+    refTypeAttr.writeMask = 0; \
+    refTypeAttr.inverseName.locale.length = 0; \
+    refTypeAttr.inverseName.text.length = 0; \
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_BROWSENAME; \
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_DISPLAYNAME; \
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_DESCRIPTION; \
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_ISABSTRACT; \
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_SYMMETRIC; \
+    UA_UInt32 offset = 0; \
+    UA_ByteString_newMembers(&addNodesItem.nodeAttributes.body,UA_ReferenceTypeAttributes_calcSizeBinary(&refTypeAttr));\
+    UA_ReferenceTypeAttributes_encodeBinary(&refTypeAttr,&addNodesItem.nodeAttributes.body,&offset); \
+    addSingleNode(ns0,&addNodesItem);\
+}while(1==0);
+
+
+
 #define ADDREFERENCE(NODE, REFTYPE, INVERSE, TARGET_NODEID) do { \
     static struct UA_ReferenceNode NODE##REFTYPE##TARGET_NODEID;    \
     UA_ReferenceNode_init(&NODE##REFTYPE##TARGET_NODEID);       \
@@ -81,6 +133,13 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     AddReference(server->nodestore, (UA_Node *)NODE, &NODE##REFTYPE##TARGET_NODEID); \
     } while(0)
 
+
+
+
+
+    ADD_REFTYPENODE_NS0(RefTypeId_HasSubtype.nodeId,32,84,"NonHierarchicalReferences","NonHierarchicalReferences","NonHierarchicalReferences",UA_TRUE,UA_FALSE);
+    ADD_REFTYPENODE_NS0(RefTypeId_HasSubtype.nodeId,33,32,"HierarchicalReferences","HierarchicalReferences","HierarchicalReferences",UA_TRUE,UA_FALSE);
+
     UA_ReferenceTypeNode *references;
     UA_ReferenceTypeNode_new(&references);
     references->nodeId    = RefTypeId_References.nodeId;
@@ -92,6 +151,10 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     references->symmetric  = UA_TRUE;
     UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&references, UA_NODESTORE_INSERT_UNIQUE);
 
+
+
+    //addSingleNode()
+
     UA_ReferenceTypeNode *hierarchicalreferences;
     UA_ReferenceTypeNode_new(&hierarchicalreferences);
     hierarchicalreferences->nodeId    = RefTypeId_HierarchicalReferences.nodeId;
@@ -101,7 +164,10 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_LocalizedText_copycstring("HierarchicalReferences", &hierarchicalreferences->description);
     hierarchicalreferences->isAbstract = UA_TRUE;
     hierarchicalreferences->symmetric  = UA_FALSE;
+
     ADDREFERENCE(hierarchicalreferences, RefTypeId_HasSubtype, UA_TRUE, RefTypeId_References);
+
+
     UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&hierarchicalreferences, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_ReferenceTypeNode *nonhierarchicalreferences;
@@ -414,6 +480,8 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     /* root becomes a managed node. we need to release it at the end.*/
     UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&root, UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED);
 
+
+
     // Objects
     UA_ObjectNode *objects;
     UA_ObjectNode_new(&objects);
@@ -528,6 +596,92 @@ void UA_Server_init(UA_Server *server, UA_String *endpointUrl) {
     UA_NodeStoreExample_insert(server->nodestore, (UA_Node**)&state, UA_NODESTORE_INSERT_UNIQUE);
 
     UA_NodeStoreExample_releaseManagedNode((const UA_Node *)root);
+
+
+
+    UA_Namespace *namespace;
+    UA_NamespaceManager_getNamespace(server->namespaceManager,0,&namespace);
+
+
+
+
+
+/*****
+     UA_Namespace *namespace;
+    UA_NamespaceManager_getNamespace(server->namespaceManager,0,&namespace);
+
+    UA_AddNodesItem addNodesItem;
+    UA_ReferenceTypeAttributes refTypeAttr;
+
+
+    addNodesItem.parentNodeId.nodeId = root->nodeId;
+
+    addNodesItem.requestedNewNodeId.nodeId.identifier.numeric = 999;
+    addNodesItem.requestedNewNodeId.nodeId.namespaceIndex = 0;
+    addNodesItem.requestedNewNodeId.nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
+    addNodesItem.referenceTypeId = RefTypeId_Organizes.nodeId;
+    addNodesItem.nodeClass = UA_NODECLASS_REFERENCETYPE;
+
+    UA_QualifiedName_copycstring("myNewNode", &addNodesItem.browseName);
+    UA_LocalizedText_copycstring("myNewNode", &refTypeAttr.displayName);
+    UA_LocalizedText_copycstring("myNewNode", &refTypeAttr.description);
+    refTypeAttr.isAbstract = UA_TRUE;
+    refTypeAttr.symmetric  = UA_TRUE;
+    refTypeAttr.userWriteMask = 0;
+    refTypeAttr.writeMask = 0;
+
+    refTypeAttr.inverseName.locale.length = 0;
+    refTypeAttr.inverseName.text.length = 0;
+
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_BROWSENAME;
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_DISPLAYNAME;
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_DESCRIPTION;
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_ISABSTRACT;
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_SYMMETRIC;
+    refTypeAttr.specifiedAttributes |= UA_ATTRIBUTEID_INVERSENAME;
+
+    UA_UInt32 offset = 0;
+
+    UA_ByteString_newMembers(&addNodesItem.nodeAttributes.body,UA_ReferenceTypeAttributes_calcSizeBinary(&refTypeAttr));
+
+    UA_ReferenceTypeAttributes_encodeBinary(&refTypeAttr,&addNodesItem.nodeAttributes.body,&offset);
+
+    addSingleNode(namespace,&addNodesItem);
+ */
+    UA_ObjectAttributes objAttr;
+    UA_AddNodesItem addNodesItem;
+    addNodesItem.parentNodeId.nodeId = root->nodeId;
+    addNodesItem.requestedNewNodeId.nodeId.identifier.numeric = 222;
+    addNodesItem.requestedNewNodeId.nodeId.namespaceIndex = 0;
+    addNodesItem.requestedNewNodeId.nodeId.identifierType = UA_NODEIDTYPE_NUMERIC;
+    addNodesItem.referenceTypeId = RefTypeId_Organizes.nodeId;
+    addNodesItem.nodeClass = UA_NODECLASS_OBJECT;
+
+    UA_QualifiedName_copycstring("myNewNodeObject", &addNodesItem.browseName);
+    UA_LocalizedText_copycstring("myNewNodeObject", &objAttr.displayName);
+    UA_LocalizedText_copycstring("myNewNodeObject", &objAttr.description);
+
+    objAttr.userWriteMask = 0;
+    objAttr.writeMask = 0;
+
+    objAttr.specifiedAttributes |= UA_ATTRIBUTEID_BROWSENAME;
+    objAttr.specifiedAttributes |= UA_ATTRIBUTEID_DISPLAYNAME;
+    objAttr.specifiedAttributes |= UA_ATTRIBUTEID_DESCRIPTION;
+    UA_UInt32 offset = 0;
+
+    UA_ByteString_newMembers(&addNodesItem.nodeAttributes.body,UA_ObjectAttributes_calcSizeBinary(&objAttr));
+
+    UA_ObjectAttributes_encodeBinary(&objAttr, &addNodesItem.nodeAttributes.body,&offset);
+
+    UA_Namespace *ns0;
+    UA_NamespaceManager_getNamespace(server->namespaceManager,0,&ns0);
+    addSingleNode(ns0,&addNodesItem);
+
+
+
+
+
+
 }
 
 UA_AddNodesResult UA_Server_addNode(UA_Server *server, UA_Node **node, UA_ExpandedNodeId *parentNodeId,

+ 25 - 2
src/server/ua_services.h

@@ -31,8 +31,31 @@ enum UA_AttributeId {
     UA_ATTRIBUTEID_EXECUTABLE              = 21,
     UA_ATTRIBUTEID_USEREXECUTABLE          = 22
 };
-
-
+/*
+UA_ExpandedNodeId RefTypeId_References; NS0EXPANDEDNODEID(RefTypeId_References, 31);
+UA_ExpandedNodeId RefTypeId_NonHierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_NonHierarchicalReferences, 32);
+UA_ExpandedNodeId RefTypeId_HierarchicalReferences; NS0EXPANDEDNODEID(RefTypeId_HierarchicalReferences, 33);
+UA_ExpandedNodeId RefTypeId_HasChild; NS0EXPANDEDNODEID(RefTypeId_HasChild, 34);
+UA_ExpandedNodeId RefTypeId_Organizes; NS0EXPANDEDNODEID(RefTypeId_Organizes, 35);
+UA_ExpandedNodeId RefTypeId_HasEventSource; NS0EXPANDEDNODEID(RefTypeId_HasEventSource, 36);
+UA_ExpandedNodeId RefTypeId_HasModellingRule; NS0EXPANDEDNODEID(RefTypeId_HasModellingRule, 37);
+UA_ExpandedNodeId RefTypeId_HasEncoding; NS0EXPANDEDNODEID(RefTypeId_HasEncoding, 38);
+UA_ExpandedNodeId RefTypeId_HasDescription; NS0EXPANDEDNODEID(RefTypeId_HasDescription, 39);
+UA_ExpandedNodeId RefTypeId_HasTypeDefinition; NS0EXPANDEDNODEID(RefTypeId_HasTypeDefinition, 40);
+UA_ExpandedNodeId RefTypeId_GeneratesEvent; NS0EXPANDEDNODEID(RefTypeId_GeneratesEvent, 41);
+UA_ExpandedNodeId RefTypeId_Aggregates; NS0EXPANDEDNODEID(RefTypeId_Aggregates, 44);
+UA_ExpandedNodeId RefTypeId_HasSubtype; NS0EXPANDEDNODEID(RefTypeId_HasSubtype, 45);
+UA_ExpandedNodeId RefTypeId_HasProperty; NS0EXPANDEDNODEID(RefTypeId_HasProperty, 46);
+UA_ExpandedNodeId RefTypeId_HasComponent; NS0EXPANDEDNODEID(RefTypeId_HasComponent, 47);
+UA_ExpandedNodeId RefTypeId_HasNotifier; NS0EXPANDEDNODEID(RefTypeId_HasNotifier, 48);
+UA_ExpandedNodeId RefTypeId_HasOrderedComponent; NS0EXPANDEDNODEID(RefTypeId_HasOrderedComponent, 49);
+UA_ExpandedNodeId RefTypeId_HasModelParent; NS0EXPANDEDNODEID(RefTypeId_HasModelParent, 50);
+UA_ExpandedNodeId RefTypeId_FromState; NS0EXPANDEDNODEID(RefTypeId_FromState, 51);
+UA_ExpandedNodeId RefTypeId_ToState; NS0EXPANDEDNODEID(RefTypeId_ToState, 52);
+UA_ExpandedNodeId RefTypeId_HasCause; NS0EXPANDEDNODEID(RefTypeId_HasCause, 53);
+UA_ExpandedNodeId RefTypeId_HasEffect; NS0EXPANDEDNODEID(RefTypeId_HasEffect, 54);
+UA_ExpandedNodeId RefTypeId_HasHistoricalConfiguration; NS0EXPANDEDNODEID(RefTypeId_HasHistoricalConfiguration, 56);
+*/
 /**
  * @defgroup services Services
  *

+ 1 - 1
src/server/ua_services_attribute.c

@@ -266,7 +266,7 @@ void Service_Read(UA_Server *server, UA_Session *session,
     				numberOfFoundIndices[i],
     				response->results,
     				request->timestampsToReturn,
-    				&response->diagnosticInfos[i]);
+    				response->diagnosticInfos);
 
 			//	response->results[i] = service_read_node(server, &request->nodesToRead[i]);
     	}

+ 412 - 210
src/server/ua_services_nodemanagement.c

@@ -3,6 +3,7 @@
 #include "ua_statuscodes.h"
 #include "nodestore/ua_nodestoreExample.h"
 #include "ua_services_internal.h"
+#include "ua_namespace_manager.h"
 #include "ua_session.h"
 #include "ua_util.h"
 
@@ -21,232 +22,433 @@
         vnode->userWriteMask = attr.userWriteMask;                      \
     } while(0)
 
-static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node **new_node,
-                                       const UA_VTable_Entry **vt) {
-    if(attributes->typeId.identifier.numeric != 357) // VariableAttributes_Encoding_DefaultBinary,357,Object
-        return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
-
-    UA_VariableAttributes attr;
-    UA_UInt32 pos = 0;
-    // todo return more informative error codes from decodeBinary
-    if(UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
-        return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
-
-    UA_VariableNode *vnode;
-    if(UA_VariableNode_new(&vnode) != UA_STATUSCODE_GOOD) {
-        UA_VariableAttributes_deleteMembers(&attr);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    // now copy all the attributes. This potentially removes them from the decoded attributes.
-    COPY_STANDARDATTRIBUTES;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
-        vnode->accessLevel = attr.accessLevel;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
-        vnode->userAccessLevel = attr.userAccessLevel;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
-        vnode->historizing = attr.historizing;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
-        vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
-        vnode->valueRank = attr.valueRank;
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
-        vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
-        vnode->arrayDimensions = attr.arrayDimensions;
-        attr.arrayDimensionsSize = -1;
-        attr.arrayDimensions = UA_NULL;
-    }
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE ||
-       attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE) {
-        vnode->dataType = attr.dataType;
-        UA_NodeId_init(&attr.dataType);
-    }
-
-    if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
-        vnode->value = attr.value;
-        UA_Variant_init(&attr.value);
-    }
-
-    UA_VariableAttributes_deleteMembers(&attr);
-
-    *new_node = (UA_Node*)vnode;
-    *vt = &UA_[UA_VARIABLENODE];
-    return UA_STATUSCODE_GOOD;
+static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes,
+		UA_Node **new_node, const UA_VTable_Entry **vt) {
+	if (attributes->typeId.identifier.numeric != 357) // VariableAttributes_Encoding_DefaultBinary,357,Object
+		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+
+	UA_VariableAttributes attr;
+	UA_UInt32 pos = 0;
+	// todo return more informative error codes from decodeBinary
+	if (UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr)
+			!= UA_STATUSCODE_GOOD)
+		return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
+
+	UA_VariableNode *vnode;
+	if (UA_VariableNode_new(&vnode) != UA_STATUSCODE_GOOD) {
+		UA_VariableAttributes_deleteMembers(&attr);
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+	}
+
+	// now copy all the attributes. This potentially removes them from the decoded attributes.
+	COPY_STANDARDATTRIBUTES;
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
+		vnode->accessLevel = attr.accessLevel;
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
+		vnode->userAccessLevel = attr.userAccessLevel;
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
+		vnode->historizing = attr.historizing;
+
+	if (attr.specifiedAttributes
+			& UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
+		vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
+		vnode->valueRank = attr.valueRank;
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
+		vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
+		vnode->arrayDimensions = attr.arrayDimensions;
+		attr.arrayDimensionsSize = -1;
+		attr.arrayDimensions = UA_NULL;
+	}
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE
+			|| attr.specifiedAttributes
+					& UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE) {
+		vnode->dataType = attr.dataType;
+		UA_NodeId_init(&attr.dataType);
+	}
+
+	if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
+		vnode->value = attr.value;
+		UA_Variant_init(&attr.value);
+	}
+
+	UA_VariableAttributes_deleteMembers(&attr);
+
+	*new_node = (UA_Node*) vnode;
+	*vt = &UA_[UA_VARIABLENODE];
+	return UA_STATUSCODE_GOOD;
 }
 
-UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node, UA_ReferenceNode *reference);
+UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
+		UA_ReferenceNode *reference);
 
 /**
-   If adding the node succeeds, the pointer will be set to zero. If the nodeid
-   of the node is null (ns=0,i=0), a unique new nodeid will be assigned and
-   returned in the AddNodesResult.
+ If adding the node succeeds, the pointer will be set to zero. If the nodeid
+ of the node is null (ns=0,i=0), a unique new nodeid will be assigned and
+ returned in the AddNodesResult.
  */
-UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session, UA_Node **node,
-                          UA_ExpandedNodeId *parentNodeId, UA_NodeId *referenceTypeId) {
-    UA_AddNodesResult result;
-    UA_AddNodesResult_init(&result);
-
-    const UA_Node *parent;
-    if(UA_NodeStoreExample_get(server->nodestore, &parentNodeId->nodeId, &parent) != UA_STATUSCODE_GOOD) {
-        result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
-        return result;
-    }
-
-    const UA_ReferenceTypeNode *referenceType;
-    if(UA_NodeStoreExample_get(server->nodestore, referenceTypeId, (const UA_Node**)&referenceType) != UA_STATUSCODE_GOOD) {
-        result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-        goto ret;
-    }
-
-    if(referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
-        result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
-        goto ret2;
-    }
-
-    if(referenceType->isAbstract == UA_TRUE) {
-        result.statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
-        goto ret2;
-    }
-
-    // todo: test if the referenetype is hierarchical
-
-    if(UA_NodeId_isNull(&(*node)->nodeId)) {
-        if(UA_NodeStoreExample_insert(server->nodestore, node,
-                               UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED) != UA_STATUSCODE_GOOD) {
-            result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
-            goto ret2;
-        }
-        result.addedNodeId = (*node)->nodeId; // cannot fail as unique nodeids are numeric
-    } else {
-        if(UA_NodeId_copy(&(*node)->nodeId, &result.addedNodeId) != UA_STATUSCODE_GOOD) {
-            result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
-            goto ret2;
-        }
-
-        if(UA_NodeStoreExample_insert(server->nodestore, node, UA_NODESTORE_INSERT_GETMANAGED) != UA_STATUSCODE_GOOD) {
-            result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS;  // todo: differentiate out of memory
-            UA_NodeId_deleteMembers(&result.addedNodeId);
-            goto ret2;
-        }
-    }
-    
-    UA_ReferenceNode ref;
-    UA_ReferenceNode_init(&ref);
-    ref.referenceTypeId = referenceType->nodeId; // is numeric
-    ref.isInverse = UA_TRUE; // todo: check if they are all not inverse..
-    ref.targetId.nodeId = parent->nodeId;
-    AddReference(server->nodestore, *node, &ref);
-
-    // todo: error handling. remove new node from nodestore
-
-    UA_NodeStoreExample_releaseManagedNode(*node);
-    *node = UA_NULL;
-
- ret2:
-    UA_NodeStoreExample_releaseManagedNode((UA_Node*)referenceType);
- ret:
-    UA_NodeStoreExample_releaseManagedNode(parent);
-
-    return result;
+UA_AddNodesResult AddNode(UA_Server *server, UA_Session *session,
+		UA_Node **node, UA_ExpandedNodeId *parentNodeId,
+		UA_NodeId *referenceTypeId) {
+	UA_AddNodesResult result;
+	UA_AddNodesResult_init(&result);
+
+	const UA_Node *parent;
+	if (UA_NodeStoreExample_get(server->nodestore, &parentNodeId->nodeId,
+			&parent) != UA_STATUSCODE_GOOD) {
+		result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+		return result;
+	}
+
+	const UA_ReferenceTypeNode *referenceType;
+	if (UA_NodeStoreExample_get(server->nodestore, referenceTypeId,
+			(const UA_Node**) &referenceType) != UA_STATUSCODE_GOOD) {
+		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+		goto ret;
+	}
+
+	if (referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
+		result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
+		goto ret2;
+	}
+
+	if (referenceType->isAbstract == UA_TRUE) {
+		result.statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
+		goto ret2;
+	}
+
+	// todo: test if the referenetype is hierarchical
+
+	if (UA_NodeId_isNull(&(*node)->nodeId)) {
+		if (UA_NodeStoreExample_insert(server->nodestore, node,
+		UA_NODESTORE_INSERT_UNIQUE | UA_NODESTORE_INSERT_GETMANAGED)
+				!= UA_STATUSCODE_GOOD) {
+			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+			goto ret2;
+		}
+		result.addedNodeId = (*node)->nodeId; // cannot fail as unique nodeids are numeric
+	} else {
+		if (UA_NodeId_copy(&(*node)->nodeId, &result.addedNodeId)
+				!= UA_STATUSCODE_GOOD) {
+			result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
+			goto ret2;
+		}
+
+		if (UA_NodeStoreExample_insert(server->nodestore, node,
+				UA_NODESTORE_INSERT_GETMANAGED) != UA_STATUSCODE_GOOD) {
+			result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; // todo: differentiate out of memory
+			UA_NodeId_deleteMembers(&result.addedNodeId);
+			goto ret2;
+		}
+	}
+
+	UA_ReferenceNode ref;
+	UA_ReferenceNode_init(&ref);
+	ref.referenceTypeId = referenceType->nodeId; // is numeric
+	ref.isInverse = UA_TRUE; // todo: check if they are all not inverse..
+	ref.targetId.nodeId = parent->nodeId;
+	AddReference(server->nodestore, *node, &ref);
+
+	// todo: error handling. remove new node from nodestore
+
+	UA_NodeStoreExample_releaseManagedNode(*node);
+	*node = UA_NULL;
+
+	ret2: UA_NodeStoreExample_releaseManagedNode((UA_Node*) referenceType);
+	ret: UA_NodeStoreExample_releaseManagedNode(parent);
+
+	return result;
 }
 
-static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
-                                  UA_AddNodesResult *result) {
-    if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
-        // adding nodes to ns0 is not allowed over the wire
-        result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
-        return;
-    }
-
-    UA_Node *newNode;
-    const UA_VTable_Entry *newNodeVT = UA_NULL;
-    if(item->nodeClass == UA_NODECLASS_VARIABLE)
-        result->statusCode = parseVariableNode(&item->nodeAttributes, &newNode, &newNodeVT);
-    else // add more node types here..
-        result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
-
-    if(result->statusCode != UA_STATUSCODE_GOOD)
-        return;
-
-    *result = AddNode(server, session, &newNode, &item->parentNodeId, &item->referenceTypeId);
-    if(result->statusCode != UA_STATUSCODE_GOOD)
-        newNodeVT->delete(newNode);
+static void addNodeFromAttributes(UA_Server *server, UA_Session *session,
+		UA_AddNodesItem *item, UA_AddNodesResult *result) {
+	if (item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
+		// adding nodes to ns0 is not allowed over the wire
+		result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+		return;
+	}
+
+	UA_Node *newNode;
+	const UA_VTable_Entry *newNodeVT = UA_NULL;
+	if (item->nodeClass == UA_NODECLASS_VARIABLE)
+		result->statusCode = parseVariableNode(&item->nodeAttributes, &newNode,
+				&newNodeVT);
+	else
+		// add more node types here..
+		result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
+
+	if (result->statusCode != UA_STATUSCODE_GOOD)
+		return;
+
+	*result = AddNode(server, session, &newNode, &item->parentNodeId,
+			&item->referenceTypeId);
+	if (result->statusCode != UA_STATUSCODE_GOOD)
+		newNodeVT->delete(newNode);
 }
 
 void Service_AddNodes(UA_Server *server, UA_Session *session,
-                      const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
-    UA_assert(server != UA_NULL && session != UA_NULL);
-
-    if(request->nodesToAddSize <= 0) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
-        return;
-    }
-
-    if(UA_Array_new((void **)&response->results, request->nodesToAddSize, &UA_[UA_ADDNODESRESULT])
-       != UA_STATUSCODE_GOOD) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
-        return;
-    }
-    
-    response->resultsSize = request->nodesToAddSize;
-    for(int i = 0;i < request->nodesToAddSize;i++)
-        addNodeFromAttributes(server, session, &request->nodesToAdd[i], &response->results[i]);
+		const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
+	UA_assert(server != UA_NULL && session != UA_NULL);
+
+	if (request->nodesToAddSize <= 0) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+		return;
+	}
+
+	if (UA_Array_new((void **) &response->results, request->nodesToAddSize,
+			&UA_[UA_ADDNODESRESULT]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	if (UA_Array_new((void **) &response->diagnosticInfos,
+			request->nodesToAddSize, &UA_[UA_DIAGNOSTICINFO])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+	response->resultsSize = request->nodesToAddSize;
+
+	UA_Int32 *numberOfFoundIndices;
+	UA_UInt16 *associatedIndices;
+	UA_UInt32 differentNamespaceIndexCount = 0;
+	if (UA_Array_new((void **) &numberOfFoundIndices,
+			request->nodesToAddSize, &UA_[UA_UINT32])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	if (UA_Array_new((void **) &associatedIndices, request->nodesToAddSize,
+			&UA_[UA_UINT16]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+	// find out count of different namespace indices
+
+	for (UA_Int32 i = 0; i < request->nodesToAddSize; i++) {
+
+		for (UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++) {
+			if (associatedIndices[j]
+					== request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex) {
+				if (j == 0) {
+					differentNamespaceIndexCount++;
+				}
+				numberOfFoundIndices[j]++;
+				break;
+			} else if (j == (differentNamespaceIndexCount - 1)) {
+				associatedIndices[j] =
+						request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex;
+				associatedIndices[j] = 1;
+				differentNamespaceIndexCount++;
+			}
+		}
+	}
+
+	UA_UInt32 *addNodesIndices;
+	if (UA_Array_new((void **) &addNodesIndices,
+			request->nodesToAddSize, &UA_[UA_UINT32])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	for (UA_UInt32 i = 0; i < differentNamespaceIndexCount; i++) {
+		UA_Namespace *tmpNamespace;
+		UA_NamespaceManager_getNamespace(server->namespaceManager,
+				associatedIndices[i], &tmpNamespace);
+		if (tmpNamespace != UA_NULL) {
+			//build up index array for each read operation onto a different namespace
+			UA_UInt32 n = 0;
+			for (UA_Int32 j = 0; j < request->nodesToAddSize; j++) {
+				if (request->nodesToAdd[j].requestedNewNodeId.nodeId.namespaceIndex
+						== associatedIndices[i]) {
+					addNodesIndices[n] = j;
+				}
+			}
+			//call read for every namespace
+			tmpNamespace->nodeStore->addNodes(request->nodesToAdd,
+					addNodesIndices, numberOfFoundIndices[i],
+					response->results, response->diagnosticInfos);
+
+			//	response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+		}
+	}
+	UA_free(addNodesIndices);
+	UA_free(numberOfFoundIndices);
+	UA_free(associatedIndices);
+
+/*	if (request->nodesToAddSize <= 0) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+		return;
+	}
+
+	if (UA_Array_new((void **) &response->results, request->nodesToAddSize,
+			&UA_[UA_ADDNODESRESULT]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	response->resultsSize = request->nodesToAddSize;
+	for (int i = 0; i < request->nodesToAddSize; i++)
+		addNodeFromAttributes(server, session, &request->nodesToAdd[i],
+				&response->results[i]);
+				*/
 }
 
 static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
-    // TODO: Check if reference already exists
-    UA_Int32 count = node->referencesSize;
-    UA_ReferenceNode *old_refs = node->references;
-    UA_ReferenceNode *new_refs;
-
-    if(count < 0) count = 0;
-
-    if(!(new_refs = UA_alloc(sizeof(UA_ReferenceNode)*(count+1))))
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-
-    UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
-    if(UA_ReferenceNode_copy(reference, &new_refs[count]) != UA_STATUSCODE_GOOD) {
-        UA_free(new_refs);
-        return UA_STATUSCODE_BADOUTOFMEMORY;
-    }
-
-    node->references     = new_refs;
-    node->referencesSize = count+1;
-    UA_free(old_refs);
-    return UA_STATUSCODE_GOOD;
+	// TODO: Check if reference already exists
+	UA_Int32 count = node->referencesSize;
+	UA_ReferenceNode *old_refs = node->references;
+	UA_ReferenceNode *new_refs;
+
+	if (count < 0)
+		count = 0;
+
+	if (!(new_refs = UA_alloc(sizeof(UA_ReferenceNode) * (count + 1))))
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+
+	UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode) * count);
+	if (UA_ReferenceNode_copy(reference, &new_refs[count])
+			!= UA_STATUSCODE_GOOD) {
+		UA_free(new_refs);
+		return UA_STATUSCODE_BADOUTOFMEMORY;
+	}
+
+	node->references = new_refs;
+	node->referencesSize = count + 1;
+	UA_free(old_refs);
+	return UA_STATUSCODE_GOOD;
 }
 
-UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node, UA_ReferenceNode *reference) {
-    UA_Int32 retval = AddSingleReference(node, reference);
-    UA_Node *targetnode;
-    UA_ReferenceNode inversereference;
-    if(retval != UA_STATUSCODE_GOOD || nodestore == UA_NULL)
-        return retval;
-
-    // Do a copy every time?
-    if(UA_NodeStoreExample_get(nodestore, &reference->targetId.nodeId, (const UA_Node **)&targetnode) != UA_STATUSCODE_GOOD)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
-    inversereference.referenceTypeId       = reference->referenceTypeId;
-    inversereference.isInverse             = !reference->isInverse;
-    inversereference.targetId.nodeId       = node->nodeId;
-    inversereference.targetId.namespaceUri = UA_STRING_NULL;
-    inversereference.targetId.serverIndex  = 0;
-    retval = AddSingleReference(targetnode, &inversereference);
-    UA_NodeStoreExample_releaseManagedNode(targetnode);
-
-    return retval;
+UA_Int32 AddReference(UA_NodeStoreExample *nodestore, UA_Node *node,
+		UA_ReferenceNode *reference) {
+	UA_Int32 retval = AddSingleReference(node, reference);
+	UA_Node *targetnode;
+	UA_ReferenceNode inversereference;
+	if (retval != UA_STATUSCODE_GOOD || nodestore == UA_NULL)
+		return retval;
+
+	// Do a copy every time?
+	if (UA_NodeStoreExample_get(nodestore, &reference->targetId.nodeId,
+			(const UA_Node **) &targetnode) != UA_STATUSCODE_GOOD)
+		return UA_STATUSCODE_BADINTERNALERROR;
+
+	inversereference.referenceTypeId = reference->referenceTypeId;
+	inversereference.isInverse = !reference->isInverse;
+	inversereference.targetId.nodeId = node->nodeId;
+	inversereference.targetId.namespaceUri = UA_STRING_NULL;
+	inversereference.targetId.serverIndex = 0;
+	retval = AddSingleReference(targetnode, &inversereference);
+	UA_NodeStoreExample_releaseManagedNode(targetnode);
+
+	return retval;
 }
 
 void Service_AddReferences(UA_Server *server, UA_Session *session,
-                           const UA_AddReferencesRequest *request,
-                           UA_AddReferencesResponse *response) {
-    response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED;
+		const UA_AddReferencesRequest *request,
+		UA_AddReferencesResponse *response) {
+
+	if (request->referencesToAddSize <= 0) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+		return;
+	}
+
+	if (UA_Array_new((void **) &response->results, request->referencesToAddSize,
+			&UA_[UA_STATUSCODE]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	if (UA_Array_new((void **) &response->diagnosticInfos,
+			request->referencesToAddSize, &UA_[UA_DIAGNOSTICINFO])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+	response->resultsSize = request->referencesToAddSize;
+
+	UA_Int32 *numberOfFoundIndices;
+	UA_UInt16 *associatedIndices;
+	UA_UInt32 differentNamespaceIndexCount = 0;
+	if (UA_Array_new((void **) &numberOfFoundIndices,
+			request->referencesToAddSize, &UA_[UA_UINT32])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	if (UA_Array_new((void **) &associatedIndices, request->referencesToAddSize,
+			&UA_[UA_UINT16]) != UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+	// find out count of different namespace indices
+
+	for (UA_Int32 i = 0; i < request->referencesToAddSize; i++) {
+
+		for (UA_UInt32 j = 0; j <= differentNamespaceIndexCount; j++) {
+			if (associatedIndices[j]
+					== request->referencesToAdd[i].sourceNodeId.namespaceIndex) {
+				if (j == 0) {
+					differentNamespaceIndexCount++;
+				}
+				numberOfFoundIndices[j]++;
+				break;
+			} else if (j == (differentNamespaceIndexCount - 1)) {
+				associatedIndices[j] =
+						request->referencesToAdd[i].sourceNodeId.namespaceIndex;
+				associatedIndices[j] = 1;
+				differentNamespaceIndexCount++;
+			}
+		}
+	}
+
+	UA_UInt32 *readValueIdIndices;
+	if (UA_Array_new((void **) &readValueIdIndices,
+			request->referencesToAddSize, &UA_[UA_UINT32])
+			!= UA_STATUSCODE_GOOD) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
+		return;
+	}
+
+	for (UA_UInt32 i = 0; i < differentNamespaceIndexCount; i++) {
+		UA_Namespace *tmpNamespace;
+		UA_NamespaceManager_getNamespace(server->namespaceManager,
+				associatedIndices[i], &tmpNamespace);
+		if (tmpNamespace != UA_NULL) {
+			//build up index array for each read operation onto a different namespace
+			UA_UInt32 n = 0;
+			for (UA_Int32 j = 0; j < request->referencesToAddSize; j++) {
+				if (request->referencesToAdd[j].sourceNodeId.namespaceIndex
+						== associatedIndices[i]) {
+					readValueIdIndices[n] = j;
+				}
+			}
+			//call read for every namespace
+			tmpNamespace->nodeStore->addReferences(request->referencesToAdd,
+					readValueIdIndices, numberOfFoundIndices[i],
+					response->results, response->diagnosticInfos);
+
+			//	response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+		}
+	}
+	UA_free(readValueIdIndices);
+	UA_free(numberOfFoundIndices);
+	UA_free(associatedIndices);
+	/*
+	 for(UA_Int32 i = 0;i < response->resultsSize;i++){
+	 response->results[i] = service_read_node(server, &request->nodesToRead[i]);
+	 }
+	 }
+	 */
+
+
+	//response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED;
 }