Explorar el Código

Structure and first features for service_addnodes

This is a half-finished service. I commit it for comparison with
the other services that are currently implemented. Maybe there is
some commonality we can exploit.
Julius Pfrommer hace 10 años
padre
commit
399bf8929a
Se han modificado 2 ficheros con 95 adiciones y 1 borrados
  1. 5 1
      src/ua_services.h
  2. 90 0
      src/ua_services_nodemanagement.c

+ 5 - 1
src/ua_services.h

@@ -104,7 +104,11 @@ UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest
  *
  * @{
  */
-// Service_AddNodes
+
+/**
+ * @brief This Service is used to add one or more Nodes into the AddressSpace hierarchy.
+ */
+UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
 // Service_AddReferences
 // Service_DeleteNodes
 // Service_DeleteReferences

+ 90 - 0
src/ua_services_nodemanagement.c

@@ -0,0 +1,90 @@
+#include "ua_services.h"
+#include "ua_statuscodes.h"
+#include "ua_namespace.h"
+
+#define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do {	\
+	status |= ACTION; \
+	if(status != UA_SUCCESS) { \
+		CLEAN_UP; \
+		goto GOTO; \
+	} } while(0) \
+
+static UA_AddNodesResult * addSingleNode(Application *app, UA_AddNodesItem *item) {
+	UA_AddNodesResult *result;
+	UA_AddNodesResult_new(&result);
+
+	Namespace *parent_ns = UA_indexedList_findValue(app->namespaces, item->parentNodeId.nodeId.namespace);
+	// TODO: search for namespaceUris and not only ns-ids.
+	if(parent_ns == UA_NULL) {
+		result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID;
+		return result;
+	}
+
+	Namespace *ns = UA_NULL;
+	UA_Boolean nodeid_isnull = UA_NodeId_isNull(&item->requestedNewNodeId.nodeId);
+
+	if(nodeid_isnull) ns = parent_ns;
+	else ns = UA_indexedList_findValue(app->namespaces, item->requestedNewNodeId.nodeId.namespace);
+
+	if(ns == UA_NULL || ns->namespaceId == 0) {
+		result->statusCode = UA_STATUSCODE_BADNODEIDREJECTED;
+		return result;
+	}
+
+	UA_Int32 status = UA_SUCCESS;
+	UA_Node *parent;
+	Namespace_Lock *parent_lock = UA_NULL;
+
+	CHECKED_ACTION(Namespace_getWritable(parent_ns, &item->parentNodeId.nodeId, &parent, &parent_lock),
+				   result->statusCode = UA_STATUSCODE_BADPARENTNODEIDINVALID, ret);
+
+	if(!nodeid_isnull && Namespace_contains(ns, &item->requestedNewNodeId.nodeId)) {
+		result->statusCode = UA_STATUSCODE_BADNODEIDEXISTS;
+		goto ret;
+	}
+
+	/**
+	   TODO:
+
+	   1) Check for the remaining conditions 
+	   Bad_ReferenceTypeIdInvalid  See Table 166 for the description of this result code.
+	   Bad_ReferenceNotAllowed  The reference could not be created because it violates constraints imposed by the data model.
+	   Bad_NodeClassInvalid  See Table 166 for the description of this result code.
+	   Bad_BrowseNameInvalid  See Table 166 for the description of this result code.
+	   Bad_BrowseNameDuplicated  The browse name is not unique among nodes that share the same relationship with the parent.
+	   Bad_NodeAttributesInvalid  The node Attributes are not valid for the node class.
+	   Bad_TypeDefinitionInvalid  See Table 166 for the description of this result code.
+	   Bad_UserAccessDenied  See Table 165 for the description of this result code
+
+	   2) Parse the UA_Node from the ExtensionObject
+	   3) Create a new entry in the namespace
+	   4) Add the reference to the parent.
+	 */
+
+ ret:
+	Namespace_Lock_release(parent_lock);
+	return result;
+}
+
+UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request, UA_AddNodesResponse *response) {
+	if(channel->session == UA_NULL || channel->session->application == UA_NULL)
+		return UA_ERROR;	// TODO: Return error message
+
+	int nodestoaddsize = request->nodesToAddSize;
+	if(nodestoaddsize <= 0) {
+		response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
+		response->resultsSize = 0;
+		return UA_SUCCESS;
+	}
+
+	response->resultsSize = nodestoaddsize;
+	UA_alloc((void **)&response->results, sizeof(void *) * nodestoaddsize);
+	for(int i = 0; i < nodestoaddsize; i++) {
+		DBG_VERBOSE(UA_QualifiedName_printf("service_addnodes - name=", &(request->nodesToAdd[i]->browseName)));
+		response->results[i] = addSingleNode(channel->session->application, request->nodesToAdd[i]);
+	}
+	response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
+	response->diagnosticInfosSize = -1;
+	return UA_SUCCESS;
+	
+}