ua_services_nodemanagement.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include "ua_services.h"
  2. #include "ua_statuscodes.h"
  3. #include "ua_namespace.h"
  4. #include "ua_services_internal.h"
  5. #include "ua_session.h"
  6. #define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do { \
  7. status |= ACTION; \
  8. if(status != UA_SUCCESS) { \
  9. CLEAN_UP; \
  10. goto GOTO; \
  11. } } while(0) \
  12. static UA_AddNodesResult addSingleNode(UA_Server *server, UA_AddNodesItem *item) {
  13. UA_AddNodesResult result;
  14. UA_AddNodesResult_init(&result);
  15. // TODO: search for namespaceUris and not only ns-ids.
  16. UA_Namespace *parent_ns = UA_NULL;
  17. for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
  18. if(server->namespaces[i].namespaceIndex == item->parentNodeId.nodeId.namespaceIndex) {
  19. parent_ns = server->namespaces[i].namespace;
  20. break;
  21. }
  22. }
  23. if(parent_ns == UA_NULL) {
  24. result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
  25. return result;
  26. }
  27. UA_Namespace *ns = UA_NULL;
  28. UA_Boolean nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId);
  29. if(nodeid_isnull) ns = parent_ns;
  30. else {
  31. for(UA_UInt32 i = 0;i < server->namespacesSize;i++) {
  32. if(server->namespaces[i].namespaceIndex == item->requestedNewNodeId.nodeId.namespaceIndex) {
  33. parent_ns = server->namespaces[i].namespace;
  34. break;
  35. }
  36. }
  37. }
  38. if(ns == UA_NULL || item->requestedNewNodeId.nodeId.namespaceIndex == 0) {
  39. result.statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
  40. return result;
  41. }
  42. UA_Int32 status = UA_SUCCESS;
  43. const UA_Node *parent;
  44. CHECKED_ACTION(UA_Namespace_get(parent_ns, &item->parentNodeId.nodeId, &parent),
  45. result.statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
  46. /* if(!nodeid_isnull && Namespace_contains(ns, &item->requestedNewNodeId.nodeId)) { */
  47. /* result.statusCode = UA_STATUSCODE_BADNODEIDEXISTS; */
  48. /* goto ret; */
  49. /* } */
  50. /**
  51. TODO:
  52. 1) Check for the remaining conditions
  53. Bad_ReferenceTypeIdInvalid See Table 166 for the description of this result code.
  54. Bad_ReferenceNotAllowed The reference could not be created because it violates constraints imposed by the data model.
  55. Bad_NodeClassInvalid See Table 166 for the description of this result code.
  56. Bad_BrowseNameInvalid See Table 166 for the description of this result code.
  57. Bad_BrowseNameDuplicated The browse name is not unique among nodes that share the same relationship with the parent.
  58. Bad_NodeAttributesInvalid The node Attributes are not valid for the node class.
  59. Bad_TypeDefinitionInvalid See Table 166 for the description of this result code.
  60. Bad_UserAccessDenied See Table 165 for the description of this result code
  61. 2) Parse the UA_Node from the ExtensionObject
  62. 3) Create a new entry in the namespace
  63. 4) Add the reference to the parent.
  64. */
  65. ret:
  66. UA_Namespace_releaseManagedNode(parent);
  67. return result;
  68. }
  69. UA_Int32 Service_AddNodes(UA_Server *server, UA_Session *session,
  70. const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
  71. if(session == UA_NULL)
  72. return UA_ERROR; // TODO: Return error message
  73. UA_Int32 nodestoaddsize = request->nodesToAddSize;
  74. if(nodestoaddsize <= 0) {
  75. response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
  76. response->resultsSize = 0;
  77. return UA_SUCCESS;
  78. }
  79. response->resultsSize = nodestoaddsize;
  80. UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
  81. for(int i = 0;i < nodestoaddsize;i++) {
  82. DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i].browseName)));
  83. response->results[i] = addSingleNode(server, &request->nodesToAdd[i]);
  84. }
  85. response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
  86. response->diagnosticInfosSize = -1;
  87. return UA_SUCCESS;
  88. }
  89. static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
  90. // TODO: Check if reference already exists
  91. UA_Int32 retval;
  92. UA_Int32 count = node->referencesSize;
  93. UA_ReferenceNode *old_refs = node->references;
  94. UA_ReferenceNode *new_refs;
  95. if(count < 0) count = 0;
  96. retval = UA_alloc((void **)&new_refs, sizeof(UA_ReferenceNode)*(count+1));
  97. if(retval != UA_SUCCESS)
  98. return UA_ERROR;
  99. UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
  100. retval |= UA_ReferenceNode_copy(reference, &new_refs[count]);
  101. if(retval != UA_SUCCESS) {
  102. UA_free(new_refs);
  103. return retval;
  104. }
  105. node->references = new_refs;
  106. node->referencesSize = count+1;
  107. UA_free(old_refs);
  108. return retval;
  109. }
  110. UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, UA_Namespace *targetns) {
  111. UA_Int32 retval = AddSingleReference(node, reference);
  112. UA_Node *targetnode;
  113. UA_ReferenceNode inversereference;
  114. if(retval != UA_SUCCESS || targetns == UA_NULL)
  115. return retval;
  116. // Do a copy every time?
  117. if(UA_Namespace_get(targetns, &reference->targetId.nodeId, (const UA_Node **)&targetnode) != UA_SUCCESS)
  118. return UA_ERROR;
  119. inversereference.referenceTypeId = reference->referenceTypeId;
  120. inversereference.isInverse = !reference->isInverse;
  121. inversereference.targetId.nodeId = node->nodeId;
  122. inversereference.targetId.namespaceUri = UA_STRING_NULL;
  123. inversereference.targetId.serverIndex = 0;
  124. retval = AddSingleReference(targetnode, &inversereference);
  125. UA_Namespace_releaseManagedNode(targetnode);
  126. return retval;
  127. }
  128. UA_Int32 Service_AddReferences(UA_Server *server, UA_Session *session,
  129. const UA_AddReferencesRequest *request,
  130. UA_AddReferencesResponse *response) {
  131. return UA_ERROR;
  132. }