open62541_nodestore_nodemanagement.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * open62541_nodestore_nodemanagement.c
  3. *
  4. * Created on: Oct 27, 2014
  5. * Author: opcua
  6. */
  7. #include "../ua_services.h"
  8. #include "open62541_nodestore.h"
  9. #include "ua_namespace_0.h"
  10. #include "ua_util.h"
  11. static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
  12. // TODO: Check if reference already exists
  13. UA_Int32 count = node->referencesSize;
  14. UA_ReferenceNode *old_refs = node->references;
  15. UA_ReferenceNode *new_refs;
  16. if (count < 0)
  17. count = 0;
  18. if (!(new_refs = UA_alloc(sizeof(UA_ReferenceNode) * (count + 1))))
  19. return UA_STATUSCODE_BADOUTOFMEMORY;
  20. UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode) * count);
  21. if (UA_ReferenceNode_copy(reference, &new_refs[count])
  22. != UA_STATUSCODE_GOOD) {
  23. UA_free(new_refs);
  24. return UA_STATUSCODE_BADOUTOFMEMORY;
  25. }
  26. node->references = new_refs;
  27. node->referencesSize = count + 1;
  28. UA_free(old_refs);
  29. return UA_STATUSCODE_GOOD;
  30. }
  31. static UA_Int32 AddReference(open62541NodeStore *nodestore, UA_Node *node,
  32. UA_ReferenceNode *reference) {
  33. UA_Int32 retval = AddSingleReference(node, reference);
  34. UA_Node *targetnode;
  35. UA_ReferenceNode inversereference;
  36. if (retval != UA_STATUSCODE_GOOD || nodestore == UA_NULL)
  37. return retval;
  38. // Do a copy every time?
  39. if (open62541NodeStore_get(nodestore, &reference->targetId.nodeId,
  40. (const UA_Node **) &targetnode) != UA_STATUSCODE_GOOD)
  41. return UA_STATUSCODE_BADINTERNALERROR;
  42. inversereference.referenceTypeId = reference->referenceTypeId;
  43. inversereference.isInverse = !reference->isInverse;
  44. inversereference.targetId.nodeId = node->nodeId;
  45. inversereference.targetId.namespaceUri = UA_STRING_NULL;
  46. inversereference.targetId.serverIndex = 0;
  47. retval = AddSingleReference(targetnode, &inversereference);
  48. open62541NodeStore_release(targetnode);
  49. return retval;
  50. }
  51. #define COPY_STANDARDATTRIBUTES do { \
  52. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME) { \
  53. vnode->displayName = attr.displayName; \
  54. UA_LocalizedText_init(&attr.displayName); \
  55. } \
  56. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DESCRIPTION) { \
  57. vnode->description = attr.description; \
  58. UA_LocalizedText_init(&attr.description); \
  59. } \
  60. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_WRITEMASK) \
  61. vnode->writeMask = attr.writeMask; \
  62. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK) \
  63. vnode->userWriteMask = attr.userWriteMask; \
  64. } while(0)
  65. static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes,
  66. UA_Node **new_node, const UA_VTable_Entry **vt) {
  67. if (attributes->typeId.identifier.numeric != 357) // VariableAttributes_Encoding_DefaultBinary,357,Object
  68. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  69. UA_VariableAttributes attr;
  70. UA_UInt32 pos = 0;
  71. // todo return more informative error codes from decodeBinary
  72. if (UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr)
  73. != UA_STATUSCODE_GOOD)
  74. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  75. UA_VariableNode *vnode = UA_VariableNode_new();
  76. if (!vnode) {
  77. UA_VariableAttributes_deleteMembers(&attr);
  78. return UA_STATUSCODE_BADOUTOFMEMORY;
  79. }
  80. // now copy all the attributes. This potentially removes them from the decoded attributes.
  81. COPY_STANDARDATTRIBUTES;
  82. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
  83. vnode->accessLevel = attr.accessLevel;
  84. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
  85. vnode->userAccessLevel = attr.userAccessLevel;
  86. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
  87. vnode->historizing = attr.historizing;
  88. if (attr.specifiedAttributes
  89. & UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
  90. vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
  91. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
  92. vnode->valueRank = attr.valueRank;
  93. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
  94. vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
  95. vnode->arrayDimensions = attr.arrayDimensions;
  96. attr.arrayDimensionsSize = -1;
  97. attr.arrayDimensions = UA_NULL;
  98. }
  99. if ((attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE)
  100. || (attr.specifiedAttributes
  101. & UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE)) {
  102. vnode->dataType = attr.dataType;
  103. UA_NodeId_init(&attr.dataType);
  104. }
  105. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
  106. vnode->value = attr.value;
  107. UA_Variant_init(&attr.value);
  108. }
  109. UA_VariableAttributes_deleteMembers(&attr);
  110. *new_node = (UA_Node*) vnode;
  111. *vt = &UA_TYPES[UA_VARIABLENODE];
  112. return UA_STATUSCODE_GOOD;
  113. }
  114. static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes,
  115. UA_Node **new_node, const UA_VTable_Entry **vt) {
  116. if (attributes->typeId.identifier.numeric != 354) // VariableAttributes_Encoding_DefaultBinary,357,Object
  117. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  118. UA_ObjectAttributes attr;
  119. UA_UInt32 pos = 0;
  120. // todo return more informative error codes from decodeBinary
  121. if (UA_ObjectAttributes_decodeBinary(&attributes->body, &pos, &attr)
  122. != UA_STATUSCODE_GOOD)
  123. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  124. UA_ObjectNode *vnode = UA_ObjectNode_new();
  125. if (!vnode) {
  126. UA_ObjectAttributes_deleteMembers(&attr);
  127. return UA_STATUSCODE_BADOUTOFMEMORY;
  128. }
  129. // now copy all the attributes. This potentially removes them from the decoded attributes.
  130. COPY_STANDARDATTRIBUTES;
  131. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER) {
  132. vnode->eventNotifier = attr.eventNotifier;
  133. }
  134. UA_ObjectAttributes_deleteMembers(&attr);
  135. *new_node = (UA_Node*) vnode;
  136. *vt = &UA_TYPES[UA_OBJECTNODE];
  137. return UA_STATUSCODE_GOOD;
  138. }
  139. static UA_StatusCode parseReferenceTypeNode(UA_ExtensionObject *attributes,
  140. UA_Node **new_node, const UA_VTable_Entry **vt) {
  141. UA_ReferenceTypeAttributes attr;
  142. UA_UInt32 pos = 0;
  143. // todo return more informative error codes from decodeBinary
  144. if (UA_ReferenceTypeAttributes_decodeBinary(&attributes->body, &pos, &attr)
  145. != UA_STATUSCODE_GOOD)
  146. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  147. UA_ReferenceTypeNode *vnode = UA_ReferenceTypeNode_new();
  148. if (!vnode) {
  149. UA_ReferenceTypeAttributes_deleteMembers(&attr);
  150. return UA_STATUSCODE_BADOUTOFMEMORY;
  151. }
  152. // now copy all the attributes. This potentially removes them from the decoded attributes.
  153. COPY_STANDARDATTRIBUTES;
  154. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT) {
  155. vnode->isAbstract = attr.isAbstract;
  156. }
  157. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_SYMMETRIC) {
  158. vnode->symmetric = attr.symmetric;
  159. }
  160. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_INVERSENAME) {
  161. vnode->inverseName = attr.inverseName;
  162. attr.inverseName.text.length = -1;
  163. attr.inverseName.text.data = UA_NULL;
  164. attr.inverseName.locale.length = -1;
  165. attr.inverseName.locale.data = UA_NULL;
  166. }
  167. UA_ReferenceTypeAttributes_deleteMembers(&attr);
  168. *new_node = (UA_Node*) vnode;
  169. *vt = &UA_TYPES[UA_REFERENCETYPENODE];
  170. return UA_STATUSCODE_GOOD;
  171. }
  172. static UA_StatusCode parseObjectTypeNode(UA_ExtensionObject *attributes,
  173. UA_Node **new_node, const UA_VTable_Entry **vt) {
  174. UA_ObjectTypeAttributes attr;
  175. UA_UInt32 pos = 0;
  176. // todo return more informative error codes from decodeBinary
  177. if (UA_ObjectTypeAttributes_decodeBinary(&attributes->body, &pos, &attr)
  178. != UA_STATUSCODE_GOOD)
  179. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  180. UA_ObjectTypeNode *vnode = UA_ObjectTypeNode_new();
  181. if (!vnode) {
  182. UA_ObjectTypeAttributes_deleteMembers(&attr);
  183. return UA_STATUSCODE_BADOUTOFMEMORY;
  184. }
  185. // now copy all the attributes. This potentially removes them from the decoded attributes.
  186. COPY_STANDARDATTRIBUTES;
  187. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT) {
  188. vnode->isAbstract = attr.isAbstract;
  189. }
  190. UA_ObjectTypeAttributes_deleteMembers(&attr);
  191. *new_node = (UA_Node*) vnode;
  192. *vt = &UA_TYPES[UA_OBJECTTYPENODE];
  193. return UA_STATUSCODE_GOOD;
  194. }
  195. static UA_StatusCode parseViewNode(UA_ExtensionObject *attributes,
  196. UA_Node **new_node, const UA_VTable_Entry **vt) {
  197. UA_ViewAttributes attr;
  198. UA_UInt32 pos = 0;
  199. // todo return more informative error codes from decodeBinary
  200. if (UA_ViewAttributes_decodeBinary(&attributes->body, &pos, &attr)
  201. != UA_STATUSCODE_GOOD)
  202. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  203. UA_ViewNode *vnode = UA_ViewNode_new();
  204. if (!vnode) {
  205. UA_ViewAttributes_deleteMembers(&attr);
  206. return UA_STATUSCODE_BADOUTOFMEMORY;
  207. }
  208. // now copy all the attributes. This potentially removes them from the decoded attributes.
  209. COPY_STANDARDATTRIBUTES;
  210. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_CONTAINSNOLOOPS) {
  211. vnode->containsNoLoops = attr.containsNoLoops;
  212. }
  213. if (attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER) {
  214. vnode->eventNotifier = attr.eventNotifier;
  215. }
  216. UA_ViewAttributes_deleteMembers(&attr);
  217. *new_node = (UA_Node*) vnode;
  218. *vt = &UA_TYPES[UA_VIEWNODE];
  219. return UA_STATUSCODE_GOOD;
  220. }
  221. void open62541Nodestore_getNewNodeId(UA_ExpandedNodeId *requestedNodeId) {
  222. //check nodeId here
  223. return;
  224. }
  225. UA_Int32 open62541NodeStore_AddReferences(const UA_RequestHeader *requestHeader,
  226. UA_AddReferencesItem* referencesToAdd, UA_UInt32 *indices,
  227. UA_UInt32 indicesSize, UA_StatusCode *addReferencesResults,
  228. UA_DiagnosticInfo *diagnosticInfos) {
  229. for (UA_UInt32 i = 0; i < indicesSize; i++) {
  230. UA_Node *node = UA_NULL;
  231. open62541NodeStore *ns = open62541NodeStore_getNodeStore();
  232. open62541NodeStore_get((const open62541NodeStore*) ns,
  233. (const UA_NodeId*) &referencesToAdd[indices[i]].sourceNodeId,
  234. (const UA_Node**) &node);
  235. if (node == UA_NULL) {
  236. addReferencesResults[indices[i]] =
  237. UA_STATUSCODE_BADSOURCENODEIDINVALID;
  238. continue;
  239. }
  240. // TODO: Check if reference already exists
  241. UA_Int32 count = node->referencesSize;
  242. UA_ReferenceNode *old_refs = node->references;
  243. UA_ReferenceNode *new_refs;
  244. if (count < 0)
  245. count = 0;
  246. if (!(new_refs = UA_alloc(sizeof(UA_ReferenceNode) * (count + 1))))
  247. return UA_STATUSCODE_BADOUTOFMEMORY;
  248. UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode) * count);
  249. //UA_ReferenceNode *reference = UA_ReferenceNode_new();
  250. UA_ReferenceNode reference;
  251. UA_ReferenceNode_init(&reference);
  252. reference.isInverse = !referencesToAdd[indices[i]].isForward;
  253. UA_NodeId_copy(&referencesToAdd[indices[i]].referenceTypeId,
  254. &reference.referenceTypeId);
  255. UA_ExpandedNodeId_copy(&referencesToAdd[indices[i]].targetNodeId,
  256. &reference.targetId);
  257. addReferencesResults[indices[i]] = AddReference(ns, node, &reference);
  258. //TODO fill diagnostic info if needed
  259. UA_free(new_refs);
  260. }
  261. return UA_STATUSCODE_GOOD;
  262. }
  263. UA_Boolean isRootNode(UA_NodeId *nodeId) {
  264. return nodeId->identifierType == UA_NODEIDTYPE_NUMERIC
  265. && nodeId->namespaceIndex == 0 && nodeId->identifier.numeric == 84;
  266. }
  267. UA_Int32 open62541NodeStore_AddNodes(const UA_RequestHeader *requestHeader,
  268. UA_AddNodesItem *nodesToAdd, UA_UInt32 *indices, UA_UInt32 indicesSize,
  269. UA_AddNodesResult* addNodesResults, UA_DiagnosticInfo *diagnosticInfos) {
  270. UA_Node *node = UA_NULL;
  271. for (UA_UInt32 i = 0; i < indicesSize; i++) {
  272. const UA_Node *parent = UA_NULL;
  273. //todo what if node is in another namespace, readrequest to test, if it exists?
  274. open62541NodeStore *ns = open62541NodeStore_getNodeStore();
  275. if (open62541NodeStore_get(ns, &nodesToAdd->parentNodeId.nodeId,
  276. &parent) != UA_STATUSCODE_GOOD
  277. && !isRootNode(&nodesToAdd->requestedNewNodeId.nodeId)) {
  278. addNodesResults[indices[i]].statusCode =
  279. UA_STATUSCODE_BADPARENTNODEIDINVALID;
  280. continue;
  281. }
  282. open62541NodeStore_get((const open62541NodeStore*) ns,
  283. (const UA_NodeId*) &nodesToAdd[indices[i]].requestedNewNodeId.nodeId,
  284. (const UA_Node**) &node);
  285. if (node != UA_NULL) {
  286. //todo or overwrite existing node?
  287. continue;
  288. }
  289. UA_Node *newNode = UA_NULL;
  290. const UA_VTable_Entry *newNodeVT = UA_NULL;
  291. switch (nodesToAdd[indices[i]].nodeClass) {
  292. case UA_NODECLASS_DATATYPE: {
  293. addNodesResults[indices[i]].statusCode =
  294. UA_STATUSCODE_BADNOTIMPLEMENTED;
  295. continue;
  296. break;
  297. }
  298. case UA_NODECLASS_METHOD: {
  299. addNodesResults[indices[i]].statusCode =
  300. UA_STATUSCODE_BADNOTIMPLEMENTED;
  301. continue;
  302. break;
  303. }
  304. case UA_NODECLASS_OBJECT: {
  305. parseObjectNode(&nodesToAdd[indices[i]].nodeAttributes, &newNode,
  306. &newNodeVT);
  307. newNode->nodeClass = UA_NODECLASS_OBJECT;
  308. break;
  309. }
  310. case UA_NODECLASS_OBJECTTYPE: {
  311. parseObjectTypeNode(&nodesToAdd[indices[i]].nodeAttributes,
  312. &newNode, &newNodeVT);
  313. newNode->nodeClass = UA_NODECLASS_OBJECTTYPE;
  314. break;
  315. }
  316. case UA_NODECLASS_REFERENCETYPE: {
  317. parseReferenceTypeNode(&nodesToAdd[indices[i]].nodeAttributes,
  318. &newNode, &newNodeVT);
  319. newNode->nodeClass = UA_NODECLASS_REFERENCETYPE;
  320. break;
  321. }
  322. case UA_NODECLASS_VARIABLE: {
  323. parseVariableNode(&nodesToAdd[indices[i]].nodeAttributes, &newNode,
  324. &newNodeVT);
  325. newNode->nodeClass = UA_NODECLASS_VARIABLE;
  326. break;
  327. }
  328. case UA_NODECLASS_VARIABLETYPE: {
  329. addNodesResults[indices[i]].statusCode =
  330. UA_STATUSCODE_BADNOTIMPLEMENTED;
  331. continue;
  332. break;
  333. }
  334. default: {
  335. addNodesResults[indices[i]].statusCode =
  336. UA_STATUSCODE_BADNOTIMPLEMENTED;
  337. continue;
  338. break;
  339. }
  340. }
  341. open62541Nodestore_getNewNodeId(
  342. &nodesToAdd[indices[i]].requestedNewNodeId);
  343. newNode->nodeId = nodesToAdd[indices[i]].requestedNewNodeId.nodeId;
  344. UA_QualifiedName_copy(&nodesToAdd[indices[i]].browseName,
  345. &newNode->browseName);
  346. UA_AddReferencesItem addRefItem;
  347. UA_AddReferencesItem_init(&addRefItem);
  348. addRefItem.isForward = UA_TRUE;
  349. addRefItem.referenceTypeId = nodesToAdd[indices[i]].referenceTypeId;
  350. addRefItem.sourceNodeId = nodesToAdd[indices[i]].parentNodeId.nodeId;
  351. addRefItem.targetNodeId.nodeId = newNode->nodeId;
  352. addRefItem.targetNodeId.namespaceUri.length = 0;
  353. addRefItem.targetServerUri.length = 0;
  354. addRefItem.targetNodeClass = newNode->nodeClass;
  355. open62541NodeStore_insert(ns, (UA_Node**) &newNode,
  356. UA_NODESTORE_INSERT_UNIQUE);
  357. if (!isRootNode(&nodesToAdd[indices[i]].requestedNewNodeId.nodeId)) {
  358. UA_UInt32 ind = 0;
  359. UA_UInt32 indSize = 1;
  360. UA_StatusCode result;
  361. UA_DiagnosticInfo diagnosticInfo;
  362. open62541NodeStore_AddReferences(requestHeader, &addRefItem, &ind,
  363. indSize, &result, &diagnosticInfo);
  364. }
  365. UA_AddReferencesItem_deleteMembers(&addRefItem);
  366. }
  367. return UA_STATUSCODE_GOOD;
  368. }