* add include files and static library due to problems with AMALGAM'ED
distri and nodeset feature * add UaModeler project including XML export * add nodeset using test server
This commit is contained in:
145
include/server/ua_nodes.h
Normal file
145
include/server/ua_nodes.h
Normal file
@ -0,0 +1,145 @@
|
||||
#ifndef UA_NODES_H_
|
||||
#define UA_NODES_H_
|
||||
|
||||
#include "ua_server.h"
|
||||
#include "ua_types_generated.h"
|
||||
#include "ua_types_encoding_binary.h"
|
||||
|
||||
/*
|
||||
* Most APIs take and return UA_EditNode and UA_ConstNode. By looking up the
|
||||
* nodeclass, nodes can be cast to their "true" class, i.e. UA_VariableNode,
|
||||
* UA_ObjectNode, and so on.
|
||||
*/
|
||||
|
||||
#define UA_STANDARD_NODEMEMBERS \
|
||||
UA_NodeId nodeId; \
|
||||
UA_NodeClass nodeClass; \
|
||||
UA_QualifiedName browseName; \
|
||||
UA_LocalizedText displayName; \
|
||||
UA_LocalizedText description; \
|
||||
UA_UInt32 writeMask; \
|
||||
UA_UInt32 userWriteMask; \
|
||||
size_t referencesSize; \
|
||||
UA_ReferenceNode *references;
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
} UA_Node;
|
||||
|
||||
void UA_Node_deleteMembersAnyNodeClass(UA_Node *node);
|
||||
UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst);
|
||||
|
||||
/**************/
|
||||
/* ObjectNode */
|
||||
/**************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Byte eventNotifier;
|
||||
void *instanceHandle;
|
||||
} UA_ObjectNode;
|
||||
|
||||
/******************/
|
||||
/* ObjectTypeNode */
|
||||
/******************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Boolean isAbstract;
|
||||
UA_ObjectLifecycleManagement lifecycleManagement;
|
||||
} UA_ObjectTypeNode;
|
||||
|
||||
typedef enum {
|
||||
UA_VALUESOURCE_VARIANT,
|
||||
UA_VALUESOURCE_DATASOURCE
|
||||
} UA_ValueSource;
|
||||
|
||||
/****************/
|
||||
/* VariableNode */
|
||||
/****************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Int32 valueRank; /**< n >= 1: the value is an array with the specified number of dimensions.
|
||||
n = 0: the value is an array with one or more dimensions.
|
||||
n = -1: the value is a scalar.
|
||||
n = -2: the value can be a scalar or an array with any number of dimensions.
|
||||
n = -3: the value can be a scalar or a one dimensional array. */
|
||||
UA_ValueSource valueSource;
|
||||
union {
|
||||
struct {
|
||||
UA_Variant value;
|
||||
UA_ValueCallback callback;
|
||||
} variant;
|
||||
UA_DataSource dataSource;
|
||||
} value;
|
||||
/* <--- similar to variabletypenodes up to there--->*/
|
||||
UA_Byte accessLevel;
|
||||
UA_Byte userAccessLevel;
|
||||
UA_Double minimumSamplingInterval;
|
||||
UA_Boolean historizing;
|
||||
} UA_VariableNode;
|
||||
|
||||
/********************/
|
||||
/* VariableTypeNode */
|
||||
/********************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Int32 valueRank;
|
||||
UA_ValueSource valueSource;
|
||||
union {
|
||||
struct {
|
||||
UA_Variant value;
|
||||
UA_ValueCallback callback;
|
||||
} variant;
|
||||
UA_DataSource dataSource;
|
||||
} value;
|
||||
/* <--- similar to variablenodes up to there--->*/
|
||||
UA_Boolean isAbstract;
|
||||
} UA_VariableTypeNode;
|
||||
|
||||
/*********************/
|
||||
/* ReferenceTypeNode */
|
||||
/*********************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Boolean isAbstract;
|
||||
UA_Boolean symmetric;
|
||||
UA_LocalizedText inverseName;
|
||||
} UA_ReferenceTypeNode;
|
||||
|
||||
/**************/
|
||||
/* MethodNode */
|
||||
/**************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Boolean executable;
|
||||
UA_Boolean userExecutable;
|
||||
void *methodHandle;
|
||||
UA_MethodCallback attachedMethod;
|
||||
} UA_MethodNode;
|
||||
|
||||
/************/
|
||||
/* ViewNode */
|
||||
/************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Byte eventNotifier;
|
||||
/* <-- the same as objectnode until here --> */
|
||||
UA_Boolean containsNoLoops;
|
||||
} UA_ViewNode;
|
||||
|
||||
/****************/
|
||||
/* DataTypeNode */
|
||||
/****************/
|
||||
|
||||
typedef struct {
|
||||
UA_STANDARD_NODEMEMBERS
|
||||
UA_Boolean isAbstract;
|
||||
} UA_DataTypeNode;
|
||||
|
||||
#endif /* UA_NODES_H_ */
|
88
include/server/ua_nodestore.h
Normal file
88
include/server/ua_nodestore.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef UA_NODESTORE_H_
|
||||
#define UA_NODESTORE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ua_types_generated.h"
|
||||
#include "ua_nodes.h"
|
||||
|
||||
/**
|
||||
* Nodestore
|
||||
* =========
|
||||
* Stores nodes that can be indexed by their NodeId. Internally, it is based on
|
||||
* a hash-map implementation. */
|
||||
struct UA_NodeStore;
|
||||
typedef struct UA_NodeStore UA_NodeStore;
|
||||
|
||||
/**
|
||||
* Nodestore Lifecycle
|
||||
* ------------------- */
|
||||
/* Create a new nodestore */
|
||||
UA_NodeStore * UA_NodeStore_new(void);
|
||||
|
||||
/* Delete the nodestore and all nodes in it. Do not call from a read-side
|
||||
critical section (multithreading). */
|
||||
void UA_NodeStore_delete(UA_NodeStore *ns);
|
||||
|
||||
/**
|
||||
* Node Lifecycle
|
||||
* ---------------
|
||||
*
|
||||
* The following definitions are used to create empty nodes of the different
|
||||
* node types. The memory is managed by the nodestore. Therefore, the node has
|
||||
* to be removed via a special deleteNode function. (If the new node is not
|
||||
* added to the nodestore.) */
|
||||
/* Create an editable node of the given NodeClass. */
|
||||
UA_Node * UA_NodeStore_newNode(UA_NodeClass nodeClass);
|
||||
#define UA_NodeStore_newObjectNode() (UA_ObjectNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECT)
|
||||
#define UA_NodeStore_newVariableNode() (UA_VariableNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLE)
|
||||
#define UA_NodeStore_newMethodNode() (UA_MethodNode*)UA_NodeStore_newNode(UA_NODECLASS_METHOD)
|
||||
#define UA_NodeStore_newObjectTypeNode() (UA_ObjectTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_OBJECTTYPE)
|
||||
#define UA_NodeStore_newVariableTypeNode() (UA_VariableTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_VARIABLETYPE)
|
||||
#define UA_NodeStore_newReferenceTypeNode() (UA_ReferenceTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_REFERENCETYPE)
|
||||
#define UA_NodeStore_newDataTypeNode() (UA_DataTypeNode*)UA_NodeStore_newNode(UA_NODECLASS_DATATYPE)
|
||||
#define UA_NodeStore_newViewNode() (UA_ViewNode*)UA_NodeStore_newNode(UA_NODECLASS_VIEW)
|
||||
|
||||
/* Delete an editable node. */
|
||||
void UA_NodeStore_deleteNode(UA_Node *node);
|
||||
|
||||
/**
|
||||
* Insert / Get / Replace / Remove
|
||||
* ------------------------------- */
|
||||
/* Inserts a new node into the nodestore. If the nodeid is zero, then a fresh
|
||||
* numeric nodeid from namespace 1 is assigned. If insertion fails, the node is
|
||||
* deleted. */
|
||||
UA_StatusCode UA_NodeStore_insert(UA_NodeStore *ns, UA_Node *node);
|
||||
|
||||
/* The returned node is immutable. */
|
||||
const UA_Node * UA_NodeStore_get(UA_NodeStore *ns, const UA_NodeId *nodeid);
|
||||
|
||||
/* Returns an editable copy of a node (needs to be deleted with the deleteNode
|
||||
function or inserted / replaced into the nodestore). */
|
||||
UA_Node * UA_NodeStore_getCopy(UA_NodeStore *ns, const UA_NodeId *nodeid);
|
||||
|
||||
/* To replace a node, get an editable copy of the node, edit and replace with
|
||||
* this function. If the node was already replaced since the copy was made,
|
||||
* UA_STATUSCODE_BADINTERNALERROR is returned. If the nodeid is not found,
|
||||
* UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases, the editable
|
||||
* node is deleted. */
|
||||
UA_StatusCode UA_NodeStore_replace(UA_NodeStore *ns, UA_Node *node);
|
||||
|
||||
/* Remove a node in the nodestore. */
|
||||
UA_StatusCode UA_NodeStore_remove(UA_NodeStore *ns, const UA_NodeId *nodeid);
|
||||
|
||||
/**
|
||||
* Iteration
|
||||
* ---------
|
||||
* The following definitions are used to call a callback for every node in the
|
||||
* nodestore. */
|
||||
typedef void (*UA_NodeStore_nodeVisitor)(const UA_Node *node);
|
||||
void UA_NodeStore_iterate(UA_NodeStore *ns, UA_NodeStore_nodeVisitor visitor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* UA_NODESTORE_H_ */
|
51
include/server/ua_securechannel_manager.h
Normal file
51
include/server/ua_securechannel_manager.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef UA_CHANNEL_MANAGER_H_
|
||||
#define UA_CHANNEL_MANAGER_H_
|
||||
|
||||
#include "ua_util.h"
|
||||
#include "ua_server.h"
|
||||
#include "ua_securechannel.h"
|
||||
#include "queue.h"
|
||||
|
||||
typedef struct channel_list_entry {
|
||||
UA_SecureChannel channel;
|
||||
LIST_ENTRY(channel_list_entry) pointers;
|
||||
} channel_list_entry;
|
||||
|
||||
typedef struct UA_SecureChannelManager {
|
||||
LIST_HEAD(channel_list, channel_list_entry) channels; // doubly-linked list of channels
|
||||
size_t maxChannelCount;
|
||||
size_t currentChannelCount;
|
||||
UA_UInt32 maxChannelLifetime;
|
||||
UA_MessageSecurityMode securityMode;
|
||||
UA_DateTime channelLifeTime;
|
||||
UA_UInt32 lastChannelId;
|
||||
UA_UInt32 lastTokenId;
|
||||
UA_Server *server;
|
||||
} UA_SecureChannelManager;
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
|
||||
UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
|
||||
UA_UInt32 startTokenId, UA_Server *server);
|
||||
|
||||
void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm);
|
||||
|
||||
void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
|
||||
const UA_OpenSecureChannelRequest *request,
|
||||
UA_OpenSecureChannelResponse *response);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
|
||||
const UA_OpenSecureChannelRequest *request,
|
||||
UA_OpenSecureChannelResponse *response);
|
||||
|
||||
UA_SecureChannel *
|
||||
UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId);
|
||||
|
||||
#endif /* UA_CHANNEL_MANAGER_H_ */
|
93
include/server/ua_server_internal.h
Normal file
93
include/server/ua_server_internal.h
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef UA_SERVER_INTERNAL_H_
|
||||
#define UA_SERVER_INTERNAL_H_
|
||||
|
||||
#include "ua_util.h"
|
||||
#include "ua_server.h"
|
||||
#include "ua_server_external_ns.h"
|
||||
#include "ua_connection_internal.h"
|
||||
#include "ua_session_manager.h"
|
||||
#include "ua_securechannel_manager.h"
|
||||
#include "ua_nodestore.h"
|
||||
|
||||
#define ANONYMOUS_POLICY "open62541-anonymous-policy"
|
||||
#define USERNAME_POLICY "open62541-username-policy"
|
||||
|
||||
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
|
||||
/** Mapping of namespace-id and url to an external nodestore. For namespaces
|
||||
that have no mapping defined, the internal nodestore is used by default. */
|
||||
typedef struct UA_ExternalNamespace {
|
||||
UA_UInt16 index;
|
||||
UA_String url;
|
||||
UA_ExternalNodeStore externalNodeStore;
|
||||
} UA_ExternalNamespace;
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_MULTITHREADING
|
||||
typedef struct {
|
||||
UA_Server *server;
|
||||
pthread_t thr;
|
||||
UA_UInt32 counter;
|
||||
volatile UA_Boolean running;
|
||||
char padding[64 - sizeof(void*) - sizeof(pthread_t) -
|
||||
sizeof(UA_UInt32) - sizeof(UA_Boolean)]; // separate cache lines
|
||||
} UA_Worker;
|
||||
#endif
|
||||
|
||||
struct UA_Server {
|
||||
/* Meta */
|
||||
UA_DateTime startTime;
|
||||
size_t endpointDescriptionsSize;
|
||||
UA_EndpointDescription *endpointDescriptions;
|
||||
|
||||
/* Security */
|
||||
UA_SecureChannelManager secureChannelManager;
|
||||
UA_SessionManager sessionManager;
|
||||
|
||||
/* Address Space */
|
||||
UA_NodeStore *nodestore;
|
||||
|
||||
size_t namespacesSize;
|
||||
UA_String *namespaces;
|
||||
|
||||
#ifdef UA_ENABLE_EXTERNAL_NAMESPACES
|
||||
size_t externalNamespacesSize;
|
||||
UA_ExternalNamespace *externalNamespaces;
|
||||
#endif
|
||||
|
||||
/* Jobs with a repetition interval */
|
||||
LIST_HEAD(RepeatedJobsList, RepeatedJobs) repeatedJobs;
|
||||
|
||||
#ifdef UA_ENABLE_MULTITHREADING
|
||||
/* Dispatch queue head for the worker threads (the tail should not be in the same cache line) */
|
||||
struct cds_wfcq_head dispatchQueue_head;
|
||||
UA_Worker *workers; /* there are nThread workers in a running server */
|
||||
struct cds_lfs_stack mainLoopJobs; /* Work that shall be executed only in the main loop and not
|
||||
by worker threads */
|
||||
struct DelayedJobs *delayedJobs;
|
||||
pthread_cond_t dispatchQueue_condition; /* so the workers don't spin if the queue is empty */
|
||||
struct cds_wfcq_tail dispatchQueue_tail; /* Dispatch queue tail for the worker threads */
|
||||
#endif
|
||||
|
||||
/* Config is the last element so that MSVC allows the usernamePasswordLogins
|
||||
field with zero-sized array */
|
||||
UA_ServerConfig config;
|
||||
};
|
||||
|
||||
typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*, UA_Node*, const void*);
|
||||
|
||||
/* Calls callback on the node. In the multithreaded case, the node is copied before and replaced in
|
||||
the nodestore. */
|
||||
UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
|
||||
UA_EditNodeCallback callback, const void *data);
|
||||
|
||||
void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg);
|
||||
|
||||
UA_StatusCode UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data);
|
||||
UA_StatusCode UA_Server_delayedFree(UA_Server *server, void *data);
|
||||
void UA_Server_deleteAllRepeatedJobs(UA_Server *server);
|
||||
|
||||
#ifdef UA_BUILD_UNIT_TESTS
|
||||
UA_StatusCode parse_numericrange(const UA_String *str, UA_NumericRange *range);
|
||||
#endif
|
||||
|
||||
#endif /* UA_SERVER_INTERNAL_H_ */
|
339
include/server/ua_services.h
Normal file
339
include/server/ua_services.h
Normal file
@ -0,0 +1,339 @@
|
||||
#ifndef UA_SERVICES_H_
|
||||
#define UA_SERVICES_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ua_util.h"
|
||||
#include "ua_types.h"
|
||||
#include "ua_types_generated.h"
|
||||
#include "ua_server.h"
|
||||
#include "ua_session.h"
|
||||
#include "ua_nodes.h"
|
||||
|
||||
/**
|
||||
* .. _services:
|
||||
*
|
||||
* Services
|
||||
* ========
|
||||
* The services defined in the OPC UA standard. */
|
||||
/* Most services take as input the server, the current session and pointers to
|
||||
the request and response. The possible error codes are returned as part of
|
||||
the response. */
|
||||
typedef void (*UA_Service)(UA_Server*, UA_Session*, const void*, void*);
|
||||
|
||||
/**
|
||||
* Discovery Service Set
|
||||
* ---------------------
|
||||
* This Service Set defines Services used to discover the Endpoints implemented
|
||||
* by a Server and to read the security configuration for those Endpoints. */
|
||||
void Service_FindServers(UA_Server *server, UA_Session *session,
|
||||
const UA_FindServersRequest *request,
|
||||
UA_FindServersResponse *response);
|
||||
|
||||
/* Returns the Endpoints supported by a Server and all of the configuration
|
||||
* information required to establish a SecureChannel and a Session. */
|
||||
void Service_GetEndpoints(UA_Server *server, UA_Session *session,
|
||||
const UA_GetEndpointsRequest *request,
|
||||
UA_GetEndpointsResponse *response);
|
||||
|
||||
/* Not Implemented: Service_RegisterServer */
|
||||
|
||||
/**
|
||||
* SecureChannel Service Set
|
||||
* -------------------------
|
||||
* This Service Set defines Services used to open a communication channel that
|
||||
* ensures the confidentiality and Integrity of all Messages exchanged with the
|
||||
* Server. */
|
||||
|
||||
/* Open or renew a SecureChannel that can be used to ensure Confidentiality and
|
||||
* Integrity for Message exchange during a Session. */
|
||||
void Service_OpenSecureChannel(UA_Server *server, UA_Connection *connection,
|
||||
const UA_OpenSecureChannelRequest *request,
|
||||
UA_OpenSecureChannelResponse *response);
|
||||
|
||||
/** Used to terminate a SecureChannel. */
|
||||
void Service_CloseSecureChannel(UA_Server *server, UA_UInt32 channelId);
|
||||
|
||||
/**
|
||||
* Session Service Set
|
||||
* -------------------
|
||||
* This Service Set defines Services for an application layer connection
|
||||
* establishment in the context of a Session. */
|
||||
|
||||
/* Used by an OPC UA Client to create a Session and the Server returns two
|
||||
* values which uniquely identify the Session. The first value is the sessionId
|
||||
* which is used to identify the Session in the audit logs and in the Server's
|
||||
* address space. The second is the authenticationToken which is used to
|
||||
* associate an incoming request with a Session. */
|
||||
void Service_CreateSession(UA_Server *server, UA_Session *session,
|
||||
const UA_CreateSessionRequest *request,
|
||||
UA_CreateSessionResponse *response);
|
||||
|
||||
/* Used by the Client to submit its SoftwareCertificates to the Server for
|
||||
* validation and to specify the identity of the user associated with the
|
||||
* Session. This Service request shall be issued by the Client before it issues
|
||||
* any other Service request after CreateSession. Failure to do so shall cause
|
||||
* the Server to close the Session. */
|
||||
void Service_ActivateSession(UA_Server *server, UA_Session *session,
|
||||
const UA_ActivateSessionRequest *request,
|
||||
UA_ActivateSessionResponse *response);
|
||||
|
||||
/* Used to terminate a Session. */
|
||||
void Service_CloseSession(UA_Server *server, UA_Session *session,
|
||||
const UA_CloseSessionRequest *request,
|
||||
UA_CloseSessionResponse *response);
|
||||
|
||||
/* Not Implemented: Service_Cancel */
|
||||
|
||||
/**
|
||||
* NodeManagement Service Set
|
||||
* --------------------------
|
||||
* This Service Set defines Services to add and delete AddressSpace Nodes and
|
||||
* References between them. All added Nodes continue to exist in the
|
||||
* AddressSpace even if the Client that created them disconnects from the
|
||||
* Server. */
|
||||
|
||||
/* Used to add one or more Nodes into the AddressSpace hierarchy. */
|
||||
void Service_AddNodes(UA_Server *server, UA_Session *session,
|
||||
const UA_AddNodesRequest *request,
|
||||
UA_AddNodesResponse *response);
|
||||
|
||||
void Service_AddNodes_single(UA_Server *server, UA_Session *session,
|
||||
const UA_AddNodesItem *item, UA_AddNodesResult *result,
|
||||
UA_InstantiationCallback *instantiationCallback);
|
||||
|
||||
/* Add an existing node. The node is assumed to be "finished", i.e. no
|
||||
* instantiation from inheritance is necessary */
|
||||
void Service_AddNodes_existing(UA_Server *server, UA_Session *session, UA_Node *node,
|
||||
const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
|
||||
UA_AddNodesResult *result);
|
||||
|
||||
/* Used to add one or more References to one or more Nodes. */
|
||||
void Service_AddReferences(UA_Server *server, UA_Session *session,
|
||||
const UA_AddReferencesRequest *request,
|
||||
UA_AddReferencesResponse *response);
|
||||
|
||||
UA_StatusCode Service_AddReferences_single(UA_Server *server, UA_Session *session,
|
||||
const UA_AddReferencesItem *item);
|
||||
|
||||
/* Used to delete one or more Nodes from the AddressSpace. */
|
||||
void Service_DeleteNodes(UA_Server *server, UA_Session *session,
|
||||
const UA_DeleteNodesRequest *request,
|
||||
UA_DeleteNodesResponse *response);
|
||||
|
||||
UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
|
||||
const UA_NodeId *nodeId,
|
||||
UA_Boolean deleteReferences);
|
||||
|
||||
/* Used to delete one or more References of a Node. */
|
||||
void Service_DeleteReferences(UA_Server *server, UA_Session *session,
|
||||
const UA_DeleteReferencesRequest *request,
|
||||
UA_DeleteReferencesResponse *response);
|
||||
|
||||
UA_StatusCode Service_DeleteReferences_single(UA_Server *server, UA_Session *session,
|
||||
const UA_DeleteReferencesItem *item);
|
||||
|
||||
/**
|
||||
* View Service Set
|
||||
* ----------------
|
||||
* Clients use the browse Services of the View Service Set to navigate through
|
||||
* the AddressSpace or through a View which is a subset of the AddressSpace. */
|
||||
|
||||
/* Used to discover the References of a specified Node. The browse can be
|
||||
* further limited by the use of a View. This Browse Service also supports a
|
||||
* primitive filtering capability. */
|
||||
void Service_Browse(UA_Server *server, UA_Session *session,
|
||||
const UA_BrowseRequest *request,
|
||||
UA_BrowseResponse *response);
|
||||
|
||||
void Service_Browse_single(UA_Server *server, UA_Session *session,
|
||||
struct ContinuationPointEntry *cp, const UA_BrowseDescription *descr,
|
||||
UA_UInt32 maxrefs, UA_BrowseResult *result);
|
||||
|
||||
/* Used to request the next set of Browse or BrowseNext response information
|
||||
* that is too large to be sent in a single response. "Too large" in this
|
||||
* context means that the Server is not able to return a larger response or that
|
||||
* the number of results to return exceeds the maximum number of results to
|
||||
* return that was specified by the Client in the original Browse request. */
|
||||
void Service_BrowseNext(UA_Server *server, UA_Session *session,
|
||||
const UA_BrowseNextRequest *request,
|
||||
UA_BrowseNextResponse *response);
|
||||
|
||||
void UA_Server_browseNext_single(UA_Server *server, UA_Session *session,
|
||||
UA_Boolean releaseContinuationPoint,
|
||||
const UA_ByteString *continuationPoint,
|
||||
UA_BrowseResult *result);
|
||||
|
||||
/* Used to translate textual node paths to their respective ids. */
|
||||
void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
|
||||
const UA_TranslateBrowsePathsToNodeIdsRequest *request,
|
||||
UA_TranslateBrowsePathsToNodeIdsResponse *response);
|
||||
|
||||
void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session *session,
|
||||
const UA_BrowsePath *path,
|
||||
UA_BrowsePathResult *result);
|
||||
|
||||
/* Used by Clients to register the Nodes that they know they will access
|
||||
* repeatedly (e.g. Write, Call). It allows Servers to set up anything needed so
|
||||
* that the access operations will be more efficient. */
|
||||
void Service_RegisterNodes(UA_Server *server, UA_Session *session,
|
||||
const UA_RegisterNodesRequest *request,
|
||||
UA_RegisterNodesResponse *response);
|
||||
|
||||
/* This Service is used to unregister NodeIds that have been obtained via the
|
||||
* RegisterNodes service. */
|
||||
void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
|
||||
const UA_UnregisterNodesRequest *request,
|
||||
UA_UnregisterNodesResponse *response);
|
||||
/**
|
||||
* Query Service Set
|
||||
* -----------------
|
||||
* This Service Set is used to issue a Query to a Server. OPC UA Query is
|
||||
* generic in that it provides an underlying storage mechanism independent Query
|
||||
* capability that can be used to access a wide variety of OPC UA data stores
|
||||
* and information management systems. OPC UA Query permits a Client to access
|
||||
* data maintained by a Server without any knowledge of the logical schema used
|
||||
* for internal storage of the data. Knowledge of the AddressSpace is
|
||||
* sufficient. */
|
||||
/* Not Implemented: Service_QueryFirst */
|
||||
/* Not Impelemented: Service_QueryNext */
|
||||
|
||||
/**
|
||||
* Attribute Service Set
|
||||
* ---------------------
|
||||
* This Service Set provides Services to access Attributes that are part of
|
||||
* Nodes. */
|
||||
|
||||
/* Used to read one or more Attributes of one or more Nodes. For constructed
|
||||
* Attribute values whose elements are indexed, such as an array, this Service
|
||||
* allows Clients to read the entire set of indexed values as a composite, to
|
||||
* read individual elements or to read ranges of elements of the composite. */
|
||||
void Service_Read(UA_Server *server, UA_Session *session,
|
||||
const UA_ReadRequest *request,
|
||||
UA_ReadResponse *response);
|
||||
|
||||
void Service_Read_single(UA_Server *server, UA_Session *session,
|
||||
UA_TimestampsToReturn timestamps,
|
||||
const UA_ReadValueId *id, UA_DataValue *v);
|
||||
|
||||
/* Used to write one or more Attributes of one or more Nodes. For constructed
|
||||
* Attribute values whose elements are indexed, such as an array, this Service
|
||||
* allows Clients to write the entire set of indexed values as a composite, to
|
||||
* write individual elements or to write ranges of elements of the composite. */
|
||||
void Service_Write(UA_Server *server, UA_Session *session,
|
||||
const UA_WriteRequest *request,
|
||||
UA_WriteResponse *response);
|
||||
|
||||
UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
|
||||
const UA_WriteValue *wvalue);
|
||||
|
||||
/* Not Implemented: Service_HistoryRead */
|
||||
/* Not Implemented: Service_HistoryUpdate */
|
||||
|
||||
/**
|
||||
* Method Service Set
|
||||
* ------------------
|
||||
* The Method Service Set defines the means to invoke methods. A method shall be
|
||||
* a component of an Object. */
|
||||
#ifdef UA_ENABLE_METHODCALLS
|
||||
/* Used to call (invoke) a list of Methods. Each method call is invoked within
|
||||
* the context of an existing Session. If the Session is terminated, the results
|
||||
* of the method's execution cannot be returned to the Client and are
|
||||
* discarded. */
|
||||
void Service_Call(UA_Server *server, UA_Session *session,
|
||||
const UA_CallRequest *request,
|
||||
UA_CallResponse *response);
|
||||
|
||||
void Service_Call_single(UA_Server *server, UA_Session *session,
|
||||
const UA_CallMethodRequest *request,
|
||||
UA_CallMethodResult *result);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MonitoredItem Service Set
|
||||
* -------------------------
|
||||
* Clients define MonitoredItems to subscribe to data and Events. Each
|
||||
* MonitoredItem identifies the item to be monitored and the Subscription to use
|
||||
* to send Notifications. The item to be monitored may be any Node Attribute. */
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
|
||||
/* Used to create and add one or more MonitoredItems to a Subscription. A
|
||||
* MonitoredItem is deleted automatically by the Server when the Subscription is
|
||||
* deleted. Deleting a MonitoredItem causes its entire set of triggered item
|
||||
* links to be deleted, but has no effect on the MonitoredItems referenced by
|
||||
* the triggered items. */
|
||||
void Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
|
||||
const UA_CreateMonitoredItemsRequest *request,
|
||||
UA_CreateMonitoredItemsResponse *response);
|
||||
|
||||
/* Used to remove one or more MonitoredItems of a Subscription. When a
|
||||
* MonitoredItem is deleted, its triggered item links are also deleted. */
|
||||
void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
|
||||
const UA_DeleteMonitoredItemsRequest *request,
|
||||
UA_DeleteMonitoredItemsResponse *response);
|
||||
|
||||
void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
|
||||
const UA_ModifyMonitoredItemsRequest *request,
|
||||
UA_ModifyMonitoredItemsResponse *response);
|
||||
/* Not Implemented: Service_SetMonitoringMode */
|
||||
/* Not Implemented: Service_SetTriggering */
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Subscription Service Set
|
||||
* ------------------------
|
||||
* Subscriptions are used to report Notifications to the Client. */
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
|
||||
/* Used to create a Subscription. Subscriptions monitor a set of MonitoredItems
|
||||
* for Notifications and return them to the Client in response to Publish
|
||||
* requests. */
|
||||
void Service_CreateSubscription(UA_Server *server, UA_Session *session,
|
||||
const UA_CreateSubscriptionRequest *request,
|
||||
UA_CreateSubscriptionResponse *response);
|
||||
|
||||
/* Used to modify a Subscription. */
|
||||
void Service_ModifySubscription(UA_Server *server, UA_Session *session,
|
||||
const UA_ModifySubscriptionRequest *request,
|
||||
UA_ModifySubscriptionResponse *response);
|
||||
|
||||
/* Used to enable sending of Notifications on one or more Subscriptions. */
|
||||
void Service_SetPublishingMode(UA_Server *server, UA_Session *session,
|
||||
const UA_SetPublishingModeRequest *request,
|
||||
UA_SetPublishingModeResponse *response);
|
||||
|
||||
/* Used for two purposes. First, it is used to acknowledge the receipt of
|
||||
* NotificationMessages for one or more Subscriptions. Second, it is used to
|
||||
* request the Server to return a NotificationMessage or a keep-alive
|
||||
* Message.
|
||||
*
|
||||
* Note that the service signature is an exception and does not contain a
|
||||
* pointer to a PublishResponse. That is because the service queues up publish
|
||||
* requests internally and sends responses asynchronously based on timeouts. */
|
||||
void Service_Publish(UA_Server *server, UA_Session *session,
|
||||
const UA_PublishRequest *request, UA_UInt32 requestId);
|
||||
|
||||
/* Requests the Subscription to republish a NotificationMessage from its
|
||||
* retransmission queue. */
|
||||
void Service_Republish(UA_Server *server, UA_Session *session,
|
||||
const UA_RepublishRequest *request,
|
||||
UA_RepublishResponse *response);
|
||||
|
||||
/* Invoked to delete one or more Subscriptions that belong to the Client's
|
||||
* Session. */
|
||||
void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
|
||||
const UA_DeleteSubscriptionsRequest *request,
|
||||
UA_DeleteSubscriptionsResponse *response);
|
||||
|
||||
/* Not Implemented: Service_TransferSubscription */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* UA_SERVICES_H_ */
|
41
include/server/ua_session_manager.h
Normal file
41
include/server/ua_session_manager.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef UA_SESSION_MANAGER_H_
|
||||
#define UA_SESSION_MANAGER_H_
|
||||
|
||||
#include "queue.h"
|
||||
#include "ua_server.h"
|
||||
#include "ua_util.h"
|
||||
#include "ua_session.h"
|
||||
|
||||
typedef struct session_list_entry {
|
||||
LIST_ENTRY(session_list_entry) pointers;
|
||||
UA_Session session;
|
||||
} session_list_entry;
|
||||
|
||||
typedef struct UA_SessionManager {
|
||||
LIST_HEAD(session_list, session_list_entry) sessions; // doubly-linked list of sessions
|
||||
UA_UInt32 maxSessionCount;
|
||||
UA_UInt32 lastSessionId;
|
||||
UA_UInt32 currentSessionCount;
|
||||
UA_UInt32 maxSessionLifeTime; // time in [ms]
|
||||
UA_Server *server;
|
||||
} UA_SessionManager;
|
||||
|
||||
UA_StatusCode
|
||||
UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
|
||||
UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId, UA_Server *server);
|
||||
|
||||
void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager);
|
||||
|
||||
void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_DateTime now);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
|
||||
const UA_CreateSessionRequest *request, UA_Session **session);
|
||||
|
||||
UA_StatusCode
|
||||
UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
|
||||
|
||||
UA_Session *
|
||||
UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
|
||||
|
||||
#endif /* UA_SESSION_MANAGER_H_ */
|
118
include/server/ua_subscription.h
Normal file
118
include/server/ua_subscription.h
Normal file
@ -0,0 +1,118 @@
|
||||
#ifndef UA_SUBSCRIPTION_H_
|
||||
#define UA_SUBSCRIPTION_H_
|
||||
|
||||
#include "ua_util.h"
|
||||
#include "ua_types.h"
|
||||
#include "ua_types_generated.h"
|
||||
#include "ua_nodes.h"
|
||||
#include "ua_session.h"
|
||||
|
||||
/*****************/
|
||||
/* MonitoredItem */
|
||||
/*****************/
|
||||
|
||||
typedef enum {
|
||||
UA_MONITOREDITEMTYPE_CHANGENOTIFY = 1,
|
||||
UA_MONITOREDITEMTYPE_STATUSNOTIFY = 2,
|
||||
UA_MONITOREDITEMTYPE_EVENTNOTIFY = 4
|
||||
} UA_MonitoredItemType;
|
||||
|
||||
typedef struct MonitoredItem_queuedValue {
|
||||
TAILQ_ENTRY(MonitoredItem_queuedValue) listEntry;
|
||||
UA_UInt32 clientHandle;
|
||||
UA_DataValue value;
|
||||
} MonitoredItem_queuedValue;
|
||||
|
||||
typedef struct UA_MonitoredItem {
|
||||
LIST_ENTRY(UA_MonitoredItem) listEntry;
|
||||
|
||||
/* Settings */
|
||||
UA_Subscription *subscription;
|
||||
UA_UInt32 itemId;
|
||||
UA_MonitoredItemType monitoredItemType;
|
||||
UA_TimestampsToReturn timestampsToReturn;
|
||||
UA_MonitoringMode monitoringMode;
|
||||
UA_NodeId monitoredNodeId;
|
||||
UA_UInt32 attributeID;
|
||||
UA_UInt32 clientHandle;
|
||||
UA_Double samplingInterval; // [ms]
|
||||
UA_UInt32 currentQueueSize;
|
||||
UA_UInt32 maxQueueSize;
|
||||
UA_Boolean discardOldest;
|
||||
UA_String indexRange;
|
||||
// TODO: dataEncoding is hardcoded to UA binary
|
||||
|
||||
/* Sample Job */
|
||||
UA_Guid sampleJobGuid;
|
||||
UA_Boolean sampleJobIsRegistered;
|
||||
|
||||
/* Sample Queue */
|
||||
UA_ByteString lastSampledValue;
|
||||
TAILQ_HEAD(QueueOfQueueDataValues, MonitoredItem_queuedValue) queue;
|
||||
} UA_MonitoredItem;
|
||||
|
||||
UA_MonitoredItem *UA_MonitoredItem_new(void);
|
||||
void MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *monitoredItem);
|
||||
UA_StatusCode MonitoredItem_registerSampleJob(UA_Server *server, UA_MonitoredItem *mon);
|
||||
UA_StatusCode MonitoredItem_unregisterSampleJob(UA_Server *server, UA_MonitoredItem *mon);
|
||||
|
||||
/****************/
|
||||
/* Subscription */
|
||||
/****************/
|
||||
|
||||
typedef struct UA_NotificationMessageEntry {
|
||||
LIST_ENTRY(UA_NotificationMessageEntry) listEntry;
|
||||
UA_NotificationMessage message;
|
||||
} UA_NotificationMessageEntry;
|
||||
|
||||
/* We use only a subset of the states defined in the standard */
|
||||
typedef enum {
|
||||
/* UA_SUBSCRIPTIONSTATE_CLOSED */
|
||||
/* UA_SUBSCRIPTIONSTATE_CREATING */
|
||||
UA_SUBSCRIPTIONSTATE_NORMAL,
|
||||
UA_SUBSCRIPTIONSTATE_LATE,
|
||||
UA_SUBSCRIPTIONSTATE_KEEPALIVE
|
||||
} UA_SubscriptionState;
|
||||
|
||||
struct UA_Subscription {
|
||||
LIST_ENTRY(UA_Subscription) listEntry;
|
||||
|
||||
/* Settings */
|
||||
UA_Session *session;
|
||||
UA_UInt32 lifeTimeCount;
|
||||
UA_UInt32 maxKeepAliveCount;
|
||||
UA_Double publishingInterval; // [ms]
|
||||
UA_UInt32 subscriptionID;
|
||||
UA_UInt32 notificationsPerPublish;
|
||||
UA_Boolean publishingEnabled;
|
||||
UA_UInt32 priority;
|
||||
UA_UInt32 sequenceNumber;
|
||||
|
||||
/* Runtime information */
|
||||
UA_SubscriptionState state;
|
||||
UA_UInt32 currentKeepAliveCount;
|
||||
UA_UInt32 currentLifetimeCount;
|
||||
|
||||
/* Publish Job */
|
||||
UA_Guid publishJobGuid;
|
||||
UA_Boolean publishJobIsRegistered;
|
||||
|
||||
LIST_HEAD(UA_ListOfUAMonitoredItems, UA_MonitoredItem) MonitoredItems;
|
||||
LIST_HEAD(UA_ListOfNotificationMessages, UA_NotificationMessageEntry) retransmissionQueue;
|
||||
};
|
||||
|
||||
UA_Subscription *UA_Subscription_new(UA_Session *session, UA_UInt32 subscriptionID);
|
||||
void UA_Subscription_deleteMembers(UA_Subscription *subscription, UA_Server *server);
|
||||
UA_StatusCode Subscription_registerPublishJob(UA_Server *server, UA_Subscription *sub);
|
||||
UA_StatusCode Subscription_unregisterPublishJob(UA_Server *server, UA_Subscription *sub);
|
||||
|
||||
UA_StatusCode
|
||||
UA_Subscription_deleteMonitoredItem(UA_Server *server, UA_Subscription *sub,
|
||||
UA_UInt32 monitoredItemID);
|
||||
|
||||
UA_MonitoredItem *
|
||||
UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemID);
|
||||
|
||||
void UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub);
|
||||
|
||||
#endif /* UA_SUBSCRIPTION_H_ */
|
Reference in New Issue
Block a user