ua_server_addressspace.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #include "ua_server.h"
  2. #include "ua_server_internal.h"
  3. #include "ua_namespace_0.h"
  4. const UA_TypeVTable * UA_Node_getTypeVT(const UA_Node *node) {
  5. switch(node->nodeClass) {
  6. case UA_NODECLASS_OBJECT:
  7. return &UA_TYPES[UA_OBJECTNODE];
  8. case UA_NODECLASS_VARIABLE:
  9. return &UA_TYPES[UA_VARIABLENODE];
  10. case UA_NODECLASS_METHOD:
  11. return &UA_TYPES[UA_METHODNODE];
  12. case UA_NODECLASS_OBJECTTYPE:
  13. return &UA_TYPES[UA_OBJECTTYPENODE];
  14. case UA_NODECLASS_VARIABLETYPE:
  15. return &UA_TYPES[UA_VARIABLETYPENODE];
  16. case UA_NODECLASS_REFERENCETYPE:
  17. return &UA_TYPES[UA_REFERENCETYPENODE];
  18. case UA_NODECLASS_DATATYPE:
  19. return &UA_TYPES[UA_DATATYPENODE];
  20. case UA_NODECLASS_VIEW:
  21. return &UA_TYPES[UA_VIEWNODE];
  22. default: break;
  23. }
  24. return &UA_TYPES[UA_INVALIDTYPE];
  25. }
  26. void UA_Server_addScalarVariableNode(UA_Server *server, UA_QualifiedName *browseName, void *value,
  27. const UA_TypeVTable *vt, const UA_ExpandedNodeId *parentNodeId,
  28. const UA_NodeId *referenceTypeId) {
  29. UA_VariableNode *tmpNode = UA_VariableNode_new();
  30. UA_QualifiedName_copy(browseName, &tmpNode->browseName);
  31. UA_String_copy(&browseName->name, &tmpNode->displayName.text);
  32. /* UA_LocalizedText_copycstring("integer value", &tmpNode->description); */
  33. tmpNode->nodeClass = UA_NODECLASS_VARIABLE;
  34. tmpNode->valueRank = -1;
  35. tmpNode->value.vt = vt;
  36. tmpNode->value.storage.data.dataPtr = value;
  37. tmpNode->value.storageType = UA_VARIANT_DATA;
  38. tmpNode->value.storage.data.arrayLength = 1;
  39. UA_Server_addNode(server, (const UA_Node**)&tmpNode, parentNodeId, referenceTypeId);
  40. }
  41. /* Adds a one-way reference to the local nodestore */
  42. UA_StatusCode addOneWayReferenceWithSession (UA_Server *server, UA_Session *session,
  43. const UA_AddReferencesItem *item) {
  44. // use the servers nodestore
  45. const UA_Node *node = UA_NodeStore_get(server->nodestore, &item->sourceNodeId);
  46. // todo differentiate between error codes
  47. if(!node)
  48. return UA_STATUSCODE_BADINTERNALERROR;
  49. const UA_TypeVTable *nodeVT = UA_Node_getTypeVT(node);
  50. UA_Node *newNode = nodeVT->new();
  51. nodeVT->copy(node, newNode);
  52. UA_Int32 count = node->referencesSize;
  53. if(count < 0)
  54. count = 0;
  55. UA_ReferenceNode *old_refs = newNode->references;
  56. UA_ReferenceNode *new_refs = UA_alloc(sizeof(UA_ReferenceNode)*(count+1));
  57. if(!new_refs) {
  58. nodeVT->delete(newNode);
  59. UA_NodeStore_release(node);
  60. return UA_STATUSCODE_BADOUTOFMEMORY;
  61. }
  62. // insert the new reference
  63. UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
  64. UA_ReferenceNode_init(&new_refs[count]);
  65. UA_StatusCode retval = UA_NodeId_copy(&item->referenceTypeId, &new_refs[count].referenceTypeId);
  66. new_refs[count].isInverse = !item->isForward;
  67. retval |= UA_ExpandedNodeId_copy(&item->targetNodeId, &new_refs[count].targetId);
  68. if(retval != UA_STATUSCODE_GOOD) {
  69. UA_Array_delete(new_refs, ++count, &UA_TYPES[UA_REFERENCENODE]);
  70. newNode->references = UA_NULL;
  71. newNode->referencesSize = 0;
  72. nodeVT->delete(newNode);
  73. UA_NodeStore_release(node);
  74. return UA_STATUSCODE_BADOUTOFMEMORY;
  75. }
  76. UA_free(old_refs);
  77. newNode->references = new_refs;
  78. newNode->referencesSize = ++count;
  79. retval = UA_NodeStore_replace(server->nodestore, (const UA_Node **)&newNode, UA_FALSE);
  80. if(retval)
  81. nodeVT->delete(newNode);
  82. UA_NodeStore_release(node);
  83. return retval;
  84. }
  85. UA_StatusCode UA_Server_addReference(UA_Server *server, const UA_AddReferencesItem *item) {
  86. return UA_Server_addReferenceWithSession(server, &adminSession, item);
  87. }
  88. UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session,
  89. const UA_AddReferencesItem *item) {
  90. // todo: we don't support references to other servers (expandednodeid) for now
  91. if(item->targetServerUri.length > 0)
  92. return UA_STATUSCODE_BADNOTIMPLEMENTED;
  93. // Is this for an external nodestore?
  94. UA_ExternalNodeStore *ensFirst = UA_NULL;
  95. UA_ExternalNodeStore *ensSecond = UA_NULL;
  96. for(UA_Int32 j = 0;j<server->externalNamespacesSize && (!ensFirst || !ensSecond);j++) {
  97. if(item->sourceNodeId.namespaceIndex == server->externalNamespaces[j].index)
  98. ensFirst = &server->externalNamespaces[j].externalNodeStore;
  99. if(item->targetNodeId.nodeId.namespaceIndex == server->externalNamespaces[j].index)
  100. ensSecond = &server->externalNamespaces[j].externalNodeStore;
  101. }
  102. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  103. if(ensFirst) {
  104. // todo: use external nodestore
  105. } else
  106. retval = addOneWayReferenceWithSession (server, session, item);
  107. if(retval) return retval;
  108. UA_AddReferencesItem secondItem;
  109. secondItem = *item;
  110. secondItem.targetNodeId.nodeId = item->sourceNodeId;
  111. secondItem.sourceNodeId = item->targetNodeId.nodeId;
  112. secondItem.isForward = !item->isForward;
  113. if(ensSecond) {
  114. // todo: use external nodestore
  115. } else
  116. retval = addOneWayReferenceWithSession (server, session, &secondItem);
  117. // todo: remove reference if the second direction failed
  118. return retval;
  119. }
  120. UA_AddNodesResult UA_Server_addNode(UA_Server *server, const UA_Node **node,
  121. const UA_ExpandedNodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
  122. return UA_Server_addNodeWithSession(server, &adminSession, node, parentNodeId, referenceTypeId);
  123. }
  124. UA_AddNodesResult UA_Server_addNodeWithSession(UA_Server *server, UA_Session *session, const UA_Node **node,
  125. const UA_ExpandedNodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
  126. UA_AddNodesResult result;
  127. UA_AddNodesResult_init(&result);
  128. const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId->nodeId);
  129. if(!parent) {
  130. result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
  131. return result;
  132. }
  133. const UA_ReferenceTypeNode *referenceType =
  134. (const UA_ReferenceTypeNode *)UA_NodeStore_get(server->nodestore, referenceTypeId);
  135. if(!referenceType) {
  136. result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
  137. goto ret;
  138. }
  139. if(referenceType->nodeClass != UA_NODECLASS_REFERENCETYPE) {
  140. result.statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
  141. goto ret2;
  142. }
  143. if(referenceType->isAbstract == UA_TRUE) {
  144. result.statusCode = UA_STATUSCODE_BADREFERENCENOTALLOWED;
  145. goto ret2;
  146. }
  147. // todo: test if the referencetype is hierarchical
  148. if(UA_NodeId_isNull(&(*node)->nodeId)) {
  149. if(UA_NodeStore_insert(server->nodestore, node, UA_TRUE) != UA_STATUSCODE_GOOD) {
  150. result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
  151. goto ret2;
  152. }
  153. result.addedNodeId = (*node)->nodeId; // cannot fail as unique nodeids are numeric
  154. } else {
  155. if(UA_NodeId_copy(&(*node)->nodeId, &result.addedNodeId) != UA_STATUSCODE_GOOD) {
  156. result.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
  157. goto ret2;
  158. }
  159. if(UA_NodeStore_insert(server->nodestore, node, UA_TRUE) != UA_STATUSCODE_GOOD) {
  160. result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; // todo: differentiate out of memory
  161. UA_NodeId_deleteMembers(&result.addedNodeId);
  162. goto ret2;
  163. }
  164. }
  165. // reference back to the parent
  166. UA_AddReferencesItem item;
  167. UA_AddReferencesItem_init(&item);
  168. item.sourceNodeId = (*node)->nodeId;
  169. item.referenceTypeId = referenceType->nodeId;
  170. item.isForward = UA_FALSE;
  171. item.targetNodeId.nodeId = parent->nodeId;
  172. UA_Server_addReference(server, &item);
  173. // todo: error handling. remove new node from nodestore
  174. UA_NodeStore_release(*node);
  175. *node = UA_NULL;
  176. ret2:
  177. UA_NodeStore_release((UA_Node*)referenceType);
  178. ret:
  179. UA_NodeStore_release(parent);
  180. return result;
  181. }