ua_services_nodemanagement.c 5.0 KB

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