open62541_nodestore_nodemanagement.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  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_releaseManagedNode(targetnode);
  49. return retval;
  50. }
  51. //TODO export to types, maybe?
  52. void UA_String_setToNULL(UA_String* string){
  53. string->data = NULL;
  54. string->length = -1;
  55. }
  56. void UA_Node_setAttributes(UA_NodeAttributes *nodeAttributes, UA_Node *node){
  57. if(nodeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME){
  58. node->displayName = nodeAttributes->displayName;
  59. UA_String_setToNULL(&nodeAttributes->displayName.locale);
  60. UA_String_setToNULL(&nodeAttributes->displayName.text);
  61. }
  62. if(nodeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_DESCRIPTION){
  63. node->description = nodeAttributes->description;
  64. UA_String_setToNULL(&nodeAttributes->description.locale);
  65. UA_String_setToNULL(&nodeAttributes->description.text);
  66. }
  67. if(nodeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_WRITEMASK){
  68. node->writeMask = nodeAttributes->writeMask;
  69. }
  70. if(nodeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK){
  71. node->userWriteMask = nodeAttributes->userWriteMask;
  72. }
  73. }
  74. void UA_ObjectNode_setAttributes(UA_ObjectAttributes *objectAttributes, UA_ObjectNode *node){
  75. UA_Node_setAttributes((UA_NodeAttributes*)objectAttributes,(UA_Node*)node);
  76. if(objectAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER){
  77. node->eventNotifier = objectAttributes->eventNotifier;
  78. }
  79. }
  80. void UA_ReferenceTypeNode_setAttributes(UA_ReferenceTypeAttributes *referenceTypeAttributes, UA_ReferenceTypeNode *node){
  81. UA_Node_setAttributes((UA_NodeAttributes*)referenceTypeAttributes,(UA_Node*)node);
  82. if(referenceTypeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT){
  83. node->isAbstract = referenceTypeAttributes->isAbstract;
  84. }
  85. if(referenceTypeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_SYMMETRIC){
  86. node->symmetric = referenceTypeAttributes->symmetric;
  87. }
  88. if(referenceTypeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_INVERSENAME){
  89. node->inverseName = referenceTypeAttributes->inverseName;
  90. UA_String_setToNULL(&referenceTypeAttributes->inverseName.locale);
  91. UA_String_setToNULL(&referenceTypeAttributes->inverseName.text);
  92. }
  93. }
  94. void UA_ObjectTypeNode_setAttributes(UA_ObjectTypeAttributes *objectTypeAttributes, UA_ObjectTypeNode *node){
  95. UA_Node_setAttributes((UA_NodeAttributes*)objectTypeAttributes,(UA_Node*)node);
  96. if(objectTypeAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT){
  97. node->isAbstract = objectTypeAttributes->isAbstract;
  98. }
  99. }
  100. void UA_VariableNode_setAttributes(UA_VariableAttributes *variableAttributes, UA_VariableNode *node){
  101. UA_Node_setAttributes((UA_NodeAttributes*)variableAttributes,(UA_Node*)node);
  102. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE){
  103. UA_Variant_copy(&variableAttributes->value,&node->value);
  104. }
  105. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE){
  106. UA_NodeId_copy(&variableAttributes->dataType,&node->dataType);
  107. }
  108. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK){
  109. node->valueRank = variableAttributes->valueRank;
  110. }
  111. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS){
  112. node->arrayDimensions = variableAttributes->arrayDimensions;
  113. variableAttributes->arrayDimensions = NULL;
  114. }
  115. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL){
  116. node->accessLevel = variableAttributes->accessLevel;
  117. }
  118. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL){
  119. node->userAccessLevel = variableAttributes->userAccessLevel;
  120. }
  121. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL){
  122. node->minimumSamplingInterval = variableAttributes->minimumSamplingInterval;
  123. }
  124. if(variableAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING){
  125. node->historizing = variableAttributes->historizing;
  126. }
  127. }
  128. void UA_ViewNode_setAttributes(UA_ViewAttributes *viewAttributes, UA_ViewNode *node){
  129. UA_Node_setAttributes((UA_NodeAttributes*)viewAttributes,(UA_Node*)node);
  130. if(viewAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_CONTAINSNOLOOPS){
  131. node->containsNoLoops = viewAttributes->containsNoLoops;
  132. }
  133. if(viewAttributes->specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER){
  134. node->eventNotifier = viewAttributes->eventNotifier;
  135. }
  136. }
  137. void open62541Nodestore_getNewNodeId(UA_ExpandedNodeId *requestedNodeId){
  138. //check nodeId here
  139. return;
  140. }
  141. UA_Int32 open62541NodeStore_AddReferences(const UA_RequestHeader *requestHeader, UA_AddReferencesItem* referencesToAdd,
  142. UA_UInt32 *indices,UA_UInt32 indicesSize, UA_StatusCode *addReferencesResults,
  143. UA_DiagnosticInfo *diagnosticInfos)
  144. {
  145. for(UA_UInt32 i = 0;i<indicesSize;i++){
  146. UA_Node *node = UA_NULL;
  147. open62541NodeStore *ns = open62541NodeStore_getNodeStore();
  148. open62541NodeStore_get((const open62541NodeStore*)ns,(const UA_NodeId*)&referencesToAdd[indices[i]].sourceNodeId, (const UA_Node**)&node);
  149. if(node == UA_NULL){
  150. addReferencesResults[indices[i]] = UA_STATUSCODE_BADSOURCENODEIDINVALID;
  151. continue;
  152. }
  153. // TODO: Check if reference already exists
  154. UA_Int32 count = node->referencesSize;
  155. UA_ReferenceNode *old_refs = node->references;
  156. UA_ReferenceNode *new_refs;
  157. if(count < 0) count = 0;
  158. if(!(new_refs = UA_alloc(sizeof(UA_ReferenceNode)*(count+1))))
  159. return UA_STATUSCODE_BADOUTOFMEMORY;
  160. UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
  161. UA_ReferenceNode *reference = UA_ReferenceNode_new();
  162. reference->isInverse = !referencesToAdd[indices[i]].isForward;
  163. UA_NodeId_copy(&referencesToAdd[indices[i]].referenceTypeId,&reference->referenceTypeId);
  164. UA_ExpandedNodeId_copy(&referencesToAdd[indices[i]].targetNodeId,&reference->targetId);
  165. addReferencesResults[indices[i]] = AddReference(ns,node,reference);
  166. UA_ReferenceNode_delete(reference); //FIXME to be removed
  167. //TODO fill diagnostic info if needed
  168. }
  169. return UA_STATUSCODE_GOOD;
  170. }
  171. UA_Boolean isRootNode(UA_NodeId *nodeId){
  172. return nodeId->identifierType == UA_NODEIDTYPE_NUMERIC && nodeId->namespaceIndex == 0 && nodeId->identifier.numeric == 84;
  173. }
  174. UA_Int32 open62541NodeStore_AddNodes(const UA_RequestHeader *requestHeader,UA_AddNodesItem *nodesToAdd,UA_UInt32 *indices,
  175. UA_UInt32 indicesSize, UA_AddNodesResult* addNodesResults,
  176. UA_DiagnosticInfo *diagnosticInfos){
  177. UA_Node *node = UA_NULL;
  178. for(UA_UInt32 i=0;i<indicesSize;i++){
  179. const UA_Node *parent;
  180. //todo what if node is in another namespace, readrequest to test, if it exists?
  181. open62541NodeStore *ns = open62541NodeStore_getNodeStore();
  182. if (open62541NodeStore_get(ns, &nodesToAdd->parentNodeId.nodeId,
  183. &parent) != UA_STATUSCODE_GOOD && !isRootNode(&nodesToAdd->requestedNewNodeId.nodeId)) {
  184. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
  185. continue;
  186. }
  187. open62541NodeStore_get((const open62541NodeStore*)ns, (const UA_NodeId*)&nodesToAdd[indices[i]].requestedNewNodeId.nodeId , (const UA_Node**)&node);
  188. if(node!=UA_NULL){
  189. //todo or overwrite existing node?
  190. continue;
  191. }
  192. UA_Node *newNode = UA_NULL;
  193. UA_UInt32 offset = 0;
  194. switch(nodesToAdd[indices[i]].nodeClass){
  195. case UA_NODECLASS_DATATYPE:
  196. {
  197. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  198. continue;
  199. break;
  200. }
  201. case UA_NODECLASS_METHOD:
  202. {
  203. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  204. continue;
  205. break;
  206. }
  207. case UA_NODECLASS_OBJECT:
  208. {
  209. UA_ObjectAttributes attributes;
  210. newNode = (UA_Node*)UA_ObjectNode_new();
  211. newNode->nodeClass = UA_NODECLASS_OBJECT;
  212. UA_ObjectAttributes_decodeBinary(&nodesToAdd[indices[i]].nodeAttributes.body,&offset,&attributes);
  213. UA_ObjectNode_setAttributes((UA_ObjectAttributes*)&attributes, (UA_ObjectNode*)newNode);
  214. break;
  215. }
  216. case UA_NODECLASS_OBJECTTYPE:
  217. {
  218. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  219. continue;
  220. break;
  221. }
  222. case UA_NODECLASS_REFERENCETYPE:
  223. {
  224. UA_ReferenceTypeAttributes attributes;
  225. newNode = (UA_Node*)UA_ReferenceTypeNode_new();
  226. newNode->nodeClass = UA_NODECLASS_REFERENCETYPE;
  227. UA_ReferenceTypeAttributes_decodeBinary(&nodesToAdd[indices[i]].nodeAttributes.body,&offset,&attributes);
  228. UA_ReferenceTypeNode_setAttributes((UA_ReferenceTypeAttributes*)&attributes,(UA_ReferenceTypeNode*)newNode);
  229. break;
  230. }
  231. case UA_NODECLASS_VARIABLE:
  232. {
  233. UA_VariableAttributes attributes;
  234. newNode = (UA_Node*)UA_VariableNode_new();
  235. newNode->nodeClass = UA_NODECLASS_VARIABLE;
  236. UA_VariableAttributes_decodeBinary(&nodesToAdd[indices[i]].nodeAttributes.body,&offset,&attributes);
  237. UA_VariableNode_setAttributes((UA_VariableAttributes*)&attributes,(UA_VariableNode*)newNode);
  238. break;
  239. }
  240. case UA_NODECLASS_VARIABLETYPE:
  241. {
  242. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  243. continue;
  244. break;
  245. }
  246. default:
  247. {
  248. addNodesResults[indices[i]].statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  249. continue;
  250. break;
  251. }
  252. }
  253. open62541Nodestore_getNewNodeId(&nodesToAdd[indices[i]].requestedNewNodeId);
  254. newNode->nodeId = nodesToAdd[indices[i]].requestedNewNodeId.nodeId;
  255. UA_QualifiedName_copy(&nodesToAdd[indices[i]].browseName,
  256. &newNode->browseName);
  257. UA_AddReferencesItem addRefItem;
  258. addRefItem.isForward = UA_TRUE;
  259. addRefItem.referenceTypeId = nodesToAdd[indices[i]].referenceTypeId;
  260. addRefItem.sourceNodeId = nodesToAdd[indices[i]].parentNodeId.nodeId;
  261. addRefItem.targetNodeId.nodeId = newNode->nodeId;
  262. addRefItem.targetNodeId.namespaceUri.length = 0;
  263. addRefItem.targetServerUri.length = 0;
  264. addRefItem.targetNodeClass = newNode->nodeClass;
  265. open62541NodeStore_insert(ns, (UA_Node**) &newNode,
  266. UA_NODESTORE_INSERT_UNIQUE);
  267. if (!isRootNode(&nodesToAdd[indices[i]].requestedNewNodeId.nodeId)) {
  268. UA_UInt32 ind = 0;
  269. UA_UInt32 indSize = 1;
  270. UA_StatusCode result;
  271. UA_DiagnosticInfo diagnosticInfo;
  272. open62541NodeStore_AddReferences(requestHeader, &addRefItem, &ind, indSize,
  273. &result, &diagnosticInfo);
  274. }
  275. }
  276. return UA_STATUSCODE_GOOD;
  277. }