Commit 4b0b7f81 authored by inspektor-scherlein's avatar inspektor-scherlein Committed by Julius Pfrommer
Browse files

Server: Two new callbacks to UA_GlobalNodeLifecycle

1. generateChildNodeId: Used to define NodeIds for automatically generated nodes during recursive node instantiation
2. createOptionalChild: Used to define whether an optional child should be created during recursive node instantiation
parent 2ef7baf4
Showing with 77 additions and 4 deletions
+77 -4
......@@ -670,7 +670,50 @@ typedef struct {
void (*destructor)(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *nodeId, void *nodeContext);
} UA_GlobalNodeLifecycle;
/* Can be NULL. Called during recursive node instantiation. While mandatory
* child nodes are automatically created if not already present, optional child
* nodes are not. This callback can be used to define whether an optional child
* node should be created.
*
* @param server The server executing the callback
* @param sessionId The identifier of the session
* @param sessionContext Additional data attached to the session in the
* access control layer
* @param sourceNodeId Source node from the type definition. If the new node
* shall be created, it will be a copy of this node.
* @param targetParentNodeId Parent of the potential new child node
* @param referenceTypeId Identifies the reference type which that the parent
* node has to the new node.
* @return Return UA_TRUE if the child node shall be instantiatet,
* UA_FALSE otherwise. */
UA_Boolean (*createOptionalChild)(UA_Server *server,
const UA_NodeId *sessionId,
void *sessionContext,
const UA_NodeId *sourceNodeId,
const UA_NodeId *targetParentNodeId,
const UA_NodeId *referenceTypeId);
/* Can be NULL. Called when a node is to be copied during recursive
* node instantiation. Allows definition of the NodeId for the new node.
* If the callback is set to NULL or the resulting NodeId is UA_NODEID_NULL,
* then a random NodeId will be generated.
*
* @param server The server executing the callback
* @param sessionId The identifier of the session
* @param sessionContext Additional data attached to the session in the
* access control layer
* @param sourceNodeId Source node of the copy operation
* @param targetParentNodeId Parent node of the new node
* @param referenceTypeId Identifies the reference type which that the parent
* node has to the new node. */
UA_StatusCode (*generateChildNodeId)(UA_Server *server,
const UA_NodeId *sessionId, void *sessionContext,
const UA_NodeId *sourceNodeId,
const UA_NodeId *targetParentNodeId,
const UA_NodeId *referenceTypeId,
UA_NodeId *targetNodeId);
} UA_GlobalNodeLifecycle;
typedef struct {
/* Can be NULL. May replace the nodeContext */
......
......@@ -161,6 +161,8 @@ setDefaultConfig(UA_ServerConfig *conf) {
/* Global Node Lifecycle */
conf->nodeLifecycle.constructor = NULL;
conf->nodeLifecycle.destructor = NULL;
conf->nodeLifecycle.createOptionalChild = NULL;
conf->nodeLifecycle.generateChildNodeId = NULL;
/* Relax constraints for the InformationModel */
conf->relaxEmptyValueConstraint = true; /* Allow empty values */
......
......@@ -445,9 +445,21 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
return retval;
}
/* Is the child mandatory? If not, skip */
if(!isMandatoryChild(server, session, &rd->nodeId.nodeId))
return UA_STATUSCODE_GOOD;
/* Is the child mandatory? If not, ask callback whether child should be instantiated.
* If not, skip. */
if(!isMandatoryChild(server, session, &rd->nodeId.nodeId)) {
if(!server->config.nodeLifecycle.createOptionalChild)
return UA_STATUSCODE_GOOD;
if(server->config.nodeLifecycle.createOptionalChild(server,
&session->sessionId,
session->sessionHandle,
&rd->nodeId.nodeId,
destinationNodeId,
&rd->referenceTypeId) == UA_FALSE) {
return UA_STATUSCODE_GOOD;
}
}
/* Child is a method -> create a reference */
if(rd->nodeClass == UA_NODECLASS_METHOD) {
......@@ -479,6 +491,20 @@ copyChild(UA_Server *server, UA_Session *session, const UA_NodeId *destinationNo
UA_NodeId_deleteMembers(&node->nodeId);
node->nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
if (server->config.nodeLifecycle.generateChildNodeId) {
retval = server->config.nodeLifecycle.generateChildNodeId(server,
&session->sessionId, session->sessionHandle,
&rd->nodeId.nodeId,
destinationNodeId,
&rd->referenceTypeId,
&node->nodeId);
if(retval != UA_STATUSCODE_GOOD) {
UA_Nodestore_deleteNode(server->nsCtx, node);
return retval;
}
}
/* Remove references, they are re-created from scratch in addnode_finish */
/* TODO: Be more clever in removing references that are re-added during
* addnode_finish. That way, we can call addnode_finish also on children that were
......
......@@ -31,6 +31,8 @@ static void setup(void) {
UA_GlobalNodeLifecycle lifecycle;
lifecycle.constructor = globalInstantiationMethod;
lifecycle.destructor = NULL;
lifecycle.createOptionalChild = NULL;
lifecycle.generateChildNodeId = NULL;
config->nodeLifecycle = lifecycle;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment