ua_services_nodemanagement.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #include "ua_server_internal.h"
  2. #include "ua_services.h"
  3. #include "ua_namespace_0.h"
  4. #include "ua_statuscodes.h"
  5. #include "ua_nodestore.h"
  6. #include "ua_session.h"
  7. #include "ua_util.h"
  8. #define COPY_STANDARDATTRIBUTES do { \
  9. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DISPLAYNAME) { \
  10. vnode->displayName = attr.displayName; \
  11. UA_LocalizedText_init(&attr.displayName); \
  12. } \
  13. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DESCRIPTION) { \
  14. vnode->description = attr.description; \
  15. UA_LocalizedText_init(&attr.description); \
  16. } \
  17. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_WRITEMASK) \
  18. vnode->writeMask = attr.writeMask; \
  19. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERWRITEMASK) \
  20. vnode->userWriteMask = attr.userWriteMask; \
  21. } while(0)
  22. static UA_StatusCode parseVariableNode(UA_ExtensionObject *attributes, UA_Node **new_node,
  23. const UA_TypeVTable **vt) {
  24. if(attributes->typeId.identifier.numeric !=
  25. UA_NODEIDS[UA_VARIABLEATTRIBUTES].identifier.numeric + UA_ENCODINGOFFSET_BINARY)
  26. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  27. UA_VariableAttributes attr;
  28. UA_UInt32 pos = 0;
  29. // todo return more informative error codes from decodeBinary
  30. if(UA_VariableAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
  31. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  32. UA_VariableNode *vnode = UA_VariableNode_new();
  33. if(!vnode) {
  34. UA_VariableAttributes_deleteMembers(&attr);
  35. return UA_STATUSCODE_BADOUTOFMEMORY;
  36. }
  37. // now copy all the attributes. This potentially removes them from the decoded attributes.
  38. COPY_STANDARDATTRIBUTES;
  39. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ACCESSLEVEL)
  40. vnode->accessLevel = attr.accessLevel;
  41. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_USERACCESSLEVEL)
  42. vnode->userAccessLevel = attr.userAccessLevel;
  43. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_HISTORIZING)
  44. vnode->historizing = attr.historizing;
  45. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL)
  46. vnode->minimumSamplingInterval = attr.minimumSamplingInterval;
  47. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUERANK)
  48. vnode->valueRank = attr.valueRank;
  49. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS) {
  50. vnode->arrayDimensionsSize = attr.arrayDimensionsSize;
  51. vnode->arrayDimensions = attr.arrayDimensions;
  52. attr.arrayDimensionsSize = -1;
  53. attr.arrayDimensions = UA_NULL;
  54. }
  55. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_DATATYPE ||
  56. attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_OBJECTTYPEORDATATYPE) {
  57. vnode->dataType = attr.dataType;
  58. UA_NodeId_init(&attr.dataType);
  59. }
  60. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_VALUE) {
  61. vnode->value = attr.value;
  62. UA_Variant_init(&attr.value);
  63. }
  64. UA_VariableAttributes_deleteMembers(&attr);
  65. *new_node = (UA_Node*)vnode;
  66. *vt = &UA_TYPES[UA_VARIABLENODE];
  67. return UA_STATUSCODE_GOOD;
  68. }
  69. static UA_StatusCode parseObjectNode(UA_ExtensionObject *attributes,
  70. UA_Node **new_node, const UA_TypeVTable **vt) {
  71. if(attributes->typeId.identifier.numeric !=
  72. UA_NODEIDS[UA_OBJECTATTRIBUTES].identifier.numeric + UA_ENCODINGOFFSET_BINARY) // VariableAttributes_Encoding_DefaultBinary
  73. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  74. UA_ObjectAttributes attr;
  75. UA_UInt32 pos = 0;
  76. // todo return more informative error codes from decodeBinary
  77. if (UA_ObjectAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
  78. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  79. UA_ObjectNode *vnode = UA_ObjectNode_new();
  80. if(!vnode) {
  81. UA_ObjectAttributes_deleteMembers(&attr);
  82. return UA_STATUSCODE_BADOUTOFMEMORY;
  83. }
  84. // now copy all the attributes. This potentially removes them from the decoded attributes.
  85. COPY_STANDARDATTRIBUTES;
  86. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER)
  87. vnode->eventNotifier = attr.eventNotifier;
  88. UA_ObjectAttributes_deleteMembers(&attr);
  89. *new_node = (UA_Node*) vnode;
  90. *vt = &UA_TYPES[UA_OBJECTNODE];
  91. return UA_STATUSCODE_GOOD;
  92. }
  93. static UA_StatusCode parseReferenceTypeNode(UA_ExtensionObject *attributes,
  94. UA_Node **new_node, const UA_TypeVTable **vt) {
  95. UA_ReferenceTypeAttributes attr;
  96. UA_UInt32 pos = 0;
  97. // todo return more informative error codes from decodeBinary
  98. if(UA_ReferenceTypeAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
  99. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  100. UA_ReferenceTypeNode *vnode = UA_ReferenceTypeNode_new();
  101. if(!vnode) {
  102. UA_ReferenceTypeAttributes_deleteMembers(&attr);
  103. return UA_STATUSCODE_BADOUTOFMEMORY;
  104. }
  105. // now copy all the attributes. This potentially removes them from the decoded attributes.
  106. COPY_STANDARDATTRIBUTES;
  107. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT)
  108. vnode->isAbstract = attr.isAbstract;
  109. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_SYMMETRIC)
  110. vnode->symmetric = attr.symmetric;
  111. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_INVERSENAME) {
  112. vnode->inverseName = attr.inverseName;
  113. attr.inverseName.text.length = -1;
  114. attr.inverseName.text.data = UA_NULL;
  115. attr.inverseName.locale.length = -1;
  116. attr.inverseName.locale.data = UA_NULL;
  117. }
  118. UA_ReferenceTypeAttributes_deleteMembers(&attr);
  119. *new_node = (UA_Node*) vnode;
  120. *vt = &UA_TYPES[UA_REFERENCETYPENODE];
  121. return UA_STATUSCODE_GOOD;
  122. }
  123. static UA_StatusCode parseObjectTypeNode(UA_ExtensionObject *attributes,
  124. UA_Node **new_node, const UA_TypeVTable **vt) {
  125. UA_ObjectTypeAttributes attr;
  126. UA_UInt32 pos = 0;
  127. // todo return more informative error codes from decodeBinary
  128. if(UA_ObjectTypeAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
  129. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  130. UA_ObjectTypeNode *vnode = UA_ObjectTypeNode_new();
  131. if(!vnode) {
  132. UA_ObjectTypeAttributes_deleteMembers(&attr);
  133. return UA_STATUSCODE_BADOUTOFMEMORY;
  134. }
  135. // now copy all the attributes. This potentially removes them from the decoded attributes.
  136. COPY_STANDARDATTRIBUTES;
  137. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_ISABSTRACT) {
  138. vnode->isAbstract = attr.isAbstract;
  139. }
  140. UA_ObjectTypeAttributes_deleteMembers(&attr);
  141. *new_node = (UA_Node*) vnode;
  142. *vt = &UA_TYPES[UA_OBJECTTYPENODE];
  143. return UA_STATUSCODE_GOOD;
  144. }
  145. static UA_StatusCode parseViewNode(UA_ExtensionObject *attributes, UA_Node **new_node,
  146. const UA_TypeVTable **vt) {
  147. UA_ViewAttributes attr;
  148. UA_UInt32 pos = 0;
  149. // todo return more informative error codes from decodeBinary
  150. if(UA_ViewAttributes_decodeBinary(&attributes->body, &pos, &attr) != UA_STATUSCODE_GOOD)
  151. return UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  152. UA_ViewNode *vnode = UA_ViewNode_new();
  153. if(!vnode) {
  154. UA_ViewAttributes_deleteMembers(&attr);
  155. return UA_STATUSCODE_BADOUTOFMEMORY;
  156. }
  157. // now copy all the attributes. This potentially removes them from the decoded attributes.
  158. COPY_STANDARDATTRIBUTES;
  159. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_CONTAINSNOLOOPS)
  160. vnode->containsNoLoops = attr.containsNoLoops;
  161. if(attr.specifiedAttributes & UA_NODEATTRIBUTESMASK_EVENTNOTIFIER)
  162. vnode->eventNotifier = attr.eventNotifier;
  163. UA_ViewAttributes_deleteMembers(&attr);
  164. *new_node = (UA_Node*) vnode;
  165. *vt = &UA_TYPES[UA_VIEWNODE];
  166. return UA_STATUSCODE_GOOD;
  167. }
  168. static void addNodeFromAttributes(UA_Server *server, UA_Session *session, UA_AddNodesItem *item,
  169. UA_AddNodesResult *result) {
  170. // adding nodes to ns0 is not allowed over the wire
  171. if(item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
  172. result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
  173. return;
  174. }
  175. // parse the node
  176. UA_Node *node;
  177. const UA_TypeVTable *nodeVT = UA_NULL;
  178. switch (item->nodeClass) {
  179. case UA_NODECLASS_OBJECT:
  180. result->statusCode = parseObjectNode(&item->nodeAttributes, &node, &nodeVT);
  181. break;
  182. case UA_NODECLASS_OBJECTTYPE:
  183. result->statusCode = parseObjectTypeNode(&item->nodeAttributes, &node, &nodeVT);
  184. break;
  185. case UA_NODECLASS_REFERENCETYPE:
  186. result->statusCode = parseReferenceTypeNode(&item->nodeAttributes, &node, &nodeVT);
  187. break;
  188. case UA_NODECLASS_VARIABLE:
  189. result->statusCode = parseVariableNode(&item->nodeAttributes, &node, &nodeVT);
  190. break;
  191. default:
  192. result->statusCode = UA_STATUSCODE_BADNOTIMPLEMENTED;
  193. }
  194. if(result->statusCode != UA_STATUSCODE_GOOD)
  195. return;
  196. // add the node
  197. *result = UA_Server_addNodeWithSession(server, session, (const UA_Node **)&node,
  198. &item->parentNodeId, &item->referenceTypeId);
  199. if(result->statusCode != UA_STATUSCODE_GOOD)
  200. nodeVT->delete(node);
  201. }
  202. void Service_AddNodes(UA_Server *server, UA_Session *session, const UA_AddNodesRequest *request,
  203. UA_AddNodesResponse *response) {
  204. if(request->nodesToAddSize <= 0) {
  205. response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
  206. return;
  207. }
  208. UA_StatusCode retval = UA_Array_new((void**)&response->results, request->nodesToAddSize,
  209. &UA_TYPES[UA_ADDNODESRESULT]);
  210. if(retval) {
  211. response->responseHeader.serviceResult = retval;
  212. return;
  213. }
  214. /* ### Begin External Namespaces */
  215. UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * request->nodesToAddSize);
  216. UA_memset(isExternal, UA_FALSE, sizeof(UA_Boolean)*request->nodesToAddSize);
  217. UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * request->nodesToAddSize);
  218. for(UA_Int32 j = 0;j<server->externalNamespacesSize;j++) {
  219. UA_UInt32 indexSize = 0;
  220. for(UA_Int32 i = 0;i < request->nodesToAddSize;i++) {
  221. if(request->nodesToAdd[i].requestedNewNodeId.nodeId.namespaceIndex != server->externalNamespaces[j].index)
  222. continue;
  223. isExternal[i] = UA_TRUE;
  224. indices[indexSize] = i;
  225. indexSize++;
  226. }
  227. if(indexSize == 0)
  228. continue;
  229. UA_ExternalNodeStore *ens = &server->externalNamespaces[j].externalNodeStore;
  230. ens->addNodes(ens->ensHandle, &request->requestHeader, request->nodesToAdd,
  231. indices, indexSize, response->results, response->diagnosticInfos);
  232. }
  233. /* ### End External Namespaces */
  234. response->resultsSize = request->nodesToAddSize;
  235. for(int i = 0;i < request->nodesToAddSize;i++) {
  236. if(!isExternal[i])
  237. addNodeFromAttributes(server, session, &request->nodesToAdd[i], &response->results[i]);
  238. }
  239. }
  240. void Service_AddReferences(UA_Server *server, UA_Session *session,
  241. const UA_AddReferencesRequest *request,
  242. UA_AddReferencesResponse *response) {
  243. if (request->referencesToAddSize <= 0) {
  244. response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
  245. return;
  246. }
  247. response->results = UA_malloc(
  248. sizeof(UA_StatusCode) * request->referencesToAddSize);
  249. if (!response->results) {
  250. response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
  251. return;
  252. }
  253. response->resultsSize = request->referencesToAddSize;
  254. UA_memset(response->results, UA_STATUSCODE_GOOD,
  255. sizeof(UA_StatusCode) * response->resultsSize);
  256. /* ### Begin External Namespaces */
  257. //UA_Boolean isExternal[MAX_ADDREFERENCES_SIZE];
  258. UA_Boolean *isExternal = UA_alloca(sizeof(UA_Boolean) * request->referencesToAddSize);
  259. UA_memset(isExternal, UA_FALSE,
  260. sizeof(UA_Boolean) * request->referencesToAddSize);
  261. UA_UInt32 *indices = UA_alloca(sizeof(UA_UInt32) * request->referencesToAddSize);
  262. for (UA_Int32 j = 0; j < server->externalNamespacesSize; j++) {
  263. UA_UInt32 indexSize = 0;
  264. for (UA_Int32 i = 0; i < request->referencesToAddSize; i++) {
  265. if (request->referencesToAdd[i].sourceNodeId.namespaceIndex
  266. != server->externalNamespaces[j].index)
  267. continue;
  268. isExternal[i] = UA_TRUE;
  269. indices[indexSize] = i;
  270. indexSize++;
  271. }
  272. if (indexSize == 0)
  273. continue;
  274. UA_ExternalNodeStore *ens =
  275. &server->externalNamespaces[j].externalNodeStore;
  276. ens->addReferences(ens->ensHandle, &request->requestHeader,
  277. request->referencesToAdd, indices, indexSize, response->results,
  278. response->diagnosticInfos);
  279. }
  280. /* ### End External Namespaces */
  281. response->resultsSize = request->referencesToAddSize;
  282. for (UA_Int32 i = 0; i < response->resultsSize; i++) {
  283. if (!isExternal[i])
  284. UA_Server_addReference(server, &request->referencesToAdd[i]);
  285. }
  286. }
  287. void Service_DeleteNodes(UA_Server *server, UA_Session *session, const UA_DeleteNodesRequest *request,
  288. UA_DeleteNodesResponse *response) {
  289. }
  290. void Service_DeleteReferences(UA_Server *server, UA_Session *session,
  291. const UA_DeleteReferencesRequest *request,
  292. UA_DeleteReferencesResponse *response) {
  293. }