/src/open62541_15/src/server/ua_server_ns0.c
Line | Count | Source |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
4 | | * |
5 | | * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
6 | | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
7 | | * Copyright 2017 (c) Thomas Bender |
8 | | * Copyright 2017 (c) Julian Grothoff |
9 | | * Copyright 2017 (c) Henrik Norrman |
10 | | * Copyright 2018 (c) Fabian Arndt, Root-Core |
11 | | * Copyright 2019 (c) Kalycito Infotech Private Limited |
12 | | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
13 | | * Copyright 2023-2025 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
14 | | */ |
15 | | |
16 | | #include "ua_server_internal.h" |
17 | | |
18 | | #ifdef UA_GENERATED_NAMESPACE_ZERO |
19 | | #include "open62541/namespace0_generated.h" |
20 | | #endif |
21 | | |
22 | | #include "ua_session.h" |
23 | | #include "ua_subscription.h" |
24 | | |
25 | | static UA_StatusCode |
26 | | ns0_addNode_raw(UA_Server *server, UA_NodeClass nodeClass, |
27 | | UA_UInt32 nodeId, char *name, void *attributes, |
28 | 118k | const UA_DataType *attributesType) { |
29 | 118k | UA_AddNodesItem item; |
30 | 118k | UA_AddNodesItem_init(&item); |
31 | 118k | item.nodeClass = nodeClass; |
32 | 118k | item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(0, nodeId); |
33 | 118k | item.browseName = UA_QUALIFIEDNAME(0, name); |
34 | 118k | UA_ExtensionObject_setValueNoDelete(&item.nodeAttributes, |
35 | 118k | attributes, attributesType); |
36 | 118k | return addNode_raw(server, &server->adminSession, NULL, &item, NULL); |
37 | 118k | } |
38 | | |
39 | | static UA_StatusCode |
40 | | ns0_addNode_finish(UA_Server *server, UA_UInt32 nodeId, |
41 | 39.1k | UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) { |
42 | 39.1k | const UA_NodeId sourceId = UA_NODEID_NUMERIC(0, nodeId); |
43 | 39.1k | const UA_NodeId refTypeId = UA_NODEID_NUMERIC(0, referenceTypeId); |
44 | 39.1k | const UA_NodeId targetId = UA_NODEID_NUMERIC(0, parentNodeId); |
45 | 39.1k | UA_StatusCode retval = addRef(server, sourceId, refTypeId, targetId, false); |
46 | 39.1k | if(retval != UA_STATUSCODE_GOOD) |
47 | 0 | return retval; |
48 | 39.1k | return addNode_finish(server, &server->adminSession, &sourceId); |
49 | 39.1k | } |
50 | | |
51 | | static UA_StatusCode |
52 | | addObjectNode(UA_Server *server, char* name, UA_UInt32 objectid, |
53 | 177k | UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) { |
54 | 177k | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
55 | 177k | object_attr.displayName = UA_LOCALIZEDTEXT("", name); |
56 | 177k | return addNode(server, UA_NODECLASS_OBJECT, UA_NODEID_NUMERIC(0, objectid), |
57 | 177k | UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid), |
58 | 177k | UA_QUALIFIEDNAME(0, name), UA_NODEID_NUMERIC(0, type_id), |
59 | 177k | &object_attr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
60 | 177k | NULL, NULL); |
61 | 177k | } |
62 | | |
63 | | static UA_StatusCode |
64 | | addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid, |
65 | 296k | UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) { |
66 | 296k | UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default; |
67 | 296k | reference_attr.displayName = UA_LOCALIZEDTEXT("", name); |
68 | 296k | reference_attr.isAbstract = isabstract; |
69 | 296k | reference_attr.symmetric = symmetric; |
70 | 296k | if(inverseName) |
71 | 236k | reference_attr.inverseName = UA_LOCALIZEDTEXT("", inverseName); |
72 | 296k | return addNode(server, UA_NODECLASS_REFERENCETYPE, UA_NODEID_NUMERIC(0, referencetypeid), |
73 | 296k | UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NULL, UA_QUALIFIEDNAME(0, name), |
74 | 296k | UA_NODEID_NULL, &reference_attr, |
75 | 296k | &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], NULL, NULL); |
76 | 296k | } |
77 | | |
78 | | /***************************/ |
79 | | /* Bootstrap NS0 hierarchy */ |
80 | | /***************************/ |
81 | | |
82 | | /* Creates the basic nodes which are expected by the nodeset compiler to be |
83 | | * already created. This is necessary to reduce the dependencies for the nodeset |
84 | | * compiler. */ |
85 | | static UA_StatusCode |
86 | 19.7k | createNS0_base(UA_Server *server) { |
87 | | /* Bootstrap ReferenceTypes. The order of these is important for the |
88 | | * ReferenceTypeIndex. The ReferenceTypeIndex is created with the raw node. |
89 | | * The ReferenceTypeSet of subtypes for every ReferenceType is created |
90 | | * during the call to AddNode_finish. */ |
91 | 19.7k | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
92 | 19.7k | UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default; |
93 | 19.7k | references_attr.displayName = UA_LOCALIZEDTEXT("", "References"); |
94 | 19.7k | references_attr.isAbstract = true; |
95 | 19.7k | references_attr.symmetric = true; |
96 | 19.7k | references_attr.inverseName = UA_LOCALIZEDTEXT("", "References"); |
97 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, "References", |
98 | 19.7k | &references_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
99 | | |
100 | 19.7k | UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default; |
101 | 19.7k | hassubtype_attr.displayName = UA_LOCALIZEDTEXT("", "HasSubtype"); |
102 | 19.7k | hassubtype_attr.isAbstract = false; |
103 | 19.7k | hassubtype_attr.symmetric = false; |
104 | 19.7k | hassubtype_attr.inverseName = UA_LOCALIZEDTEXT("", "SubtypeOf"); |
105 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, "HasSubtype", |
106 | 19.7k | &hassubtype_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
107 | | |
108 | 19.7k | UA_ReferenceTypeAttributes aggregates_attr = UA_ReferenceTypeAttributes_default; |
109 | 19.7k | aggregates_attr.displayName = UA_LOCALIZEDTEXT("", "Aggregates"); |
110 | 19.7k | aggregates_attr.isAbstract = true; |
111 | 19.7k | aggregates_attr.symmetric = false; |
112 | 19.7k | aggregates_attr.inverseName = UA_LOCALIZEDTEXT("", "AggregatedBy"); |
113 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_REFERENCETYPE, UA_NS0ID_AGGREGATES, "Aggregates", |
114 | 19.7k | &aggregates_attr, &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
115 | | |
116 | 19.7k | ret |= addReferenceTypeNode(server, "HierarchicalReferences", NULL, |
117 | 19.7k | UA_NS0ID_HIERARCHICALREFERENCES, true, false, UA_NS0ID_REFERENCES); |
118 | | |
119 | 19.7k | ret |= addReferenceTypeNode(server, "NonHierarchicalReferences", NULL, |
120 | 19.7k | UA_NS0ID_NONHIERARCHICALREFERENCES, true, true, UA_NS0ID_REFERENCES); |
121 | | |
122 | 19.7k | ret |= addReferenceTypeNode(server, "HasChild", NULL, UA_NS0ID_HASCHILD, |
123 | 19.7k | true, false, UA_NS0ID_HIERARCHICALREFERENCES); |
124 | | |
125 | 19.7k | ret |= addReferenceTypeNode(server, "Organizes", "OrganizedBy", UA_NS0ID_ORGANIZES, |
126 | 19.7k | false, false, UA_NS0ID_HIERARCHICALREFERENCES); |
127 | | |
128 | 19.7k | ret |= addReferenceTypeNode(server, "HasEventSource", "EventSourceOf", UA_NS0ID_HASEVENTSOURCE, |
129 | 19.7k | false, false, UA_NS0ID_HIERARCHICALREFERENCES); |
130 | | |
131 | 19.7k | ret |= addReferenceTypeNode(server, "HasModellingRule", "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE, |
132 | 19.7k | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
133 | | |
134 | 19.7k | ret |= addReferenceTypeNode(server, "HasEncoding", "EncodingOf", UA_NS0ID_HASENCODING, |
135 | 19.7k | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
136 | | |
137 | 19.7k | ret |= addReferenceTypeNode(server, "HasDescription", "DescriptionOf", UA_NS0ID_HASDESCRIPTION, |
138 | 19.7k | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
139 | | |
140 | 19.7k | ret |= addReferenceTypeNode(server, "HasTypeDefinition", "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION, |
141 | 19.7k | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
142 | | |
143 | 19.7k | ret |= addReferenceTypeNode(server, "GeneratesEvent", "GeneratedBy", UA_NS0ID_GENERATESEVENT, |
144 | 19.7k | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
145 | | |
146 | | /* Complete bootstrap of Aggregates */ |
147 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_AGGREGATES, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE); |
148 | | |
149 | | /* Complete bootstrap of HasSubtype */ |
150 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE); |
151 | | |
152 | 19.7k | ret |= addReferenceTypeNode(server, "HasProperty", "PropertyOf", UA_NS0ID_HASPROPERTY, |
153 | 19.7k | false, false, UA_NS0ID_AGGREGATES); |
154 | | |
155 | 19.7k | ret |= addReferenceTypeNode(server, "HasComponent", "ComponentOf", UA_NS0ID_HASCOMPONENT, |
156 | 19.7k | false, false, UA_NS0ID_AGGREGATES); |
157 | | |
158 | 19.7k | ret |= addReferenceTypeNode(server, "HasNotifier", "NotifierOf", UA_NS0ID_HASNOTIFIER, |
159 | 19.7k | false, false, UA_NS0ID_HASEVENTSOURCE); |
160 | | |
161 | 19.7k | ret |= addReferenceTypeNode(server, "HasOrderedComponent", "OrderedComponentOf", |
162 | 19.7k | UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT); |
163 | | |
164 | 19.7k | ret |= addReferenceTypeNode(server, "HasInterface", "InterfaceOf", |
165 | 19.7k | UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
166 | | |
167 | | /**************/ |
168 | | /* Data Types */ |
169 | | /**************/ |
170 | | |
171 | | /* Bootstrap BaseDataType */ |
172 | 19.7k | UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default; |
173 | 19.7k | basedatatype_attr.displayName = UA_LOCALIZEDTEXT("", "BaseDataType"); |
174 | 19.7k | basedatatype_attr.isAbstract = true; |
175 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, "BaseDataType", |
176 | 19.7k | &basedatatype_attr, &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]); |
177 | | |
178 | | /*****************/ |
179 | | /* VariableTypes */ |
180 | | /*****************/ |
181 | | |
182 | 19.7k | UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default; |
183 | 19.7k | basevar_attr.displayName = UA_LOCALIZEDTEXT("", "BaseVariableType"); |
184 | 19.7k | basevar_attr.isAbstract = true; |
185 | 19.7k | basevar_attr.valueRank = UA_VALUERANK_ANY; |
186 | 19.7k | basevar_attr.dataType = UA_NS0ID(BASEDATATYPE); |
187 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_VARIABLETYPE, |
188 | 19.7k | UA_NS0ID_BASEVARIABLETYPE, "BaseVariableType", |
189 | 19.7k | &basevar_attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]); |
190 | | |
191 | 19.7k | UA_VariableTypeAttributes bdv_attr = UA_VariableTypeAttributes_default; |
192 | 19.7k | bdv_attr.displayName = UA_LOCALIZEDTEXT("", "BaseDataVariableType"); |
193 | 19.7k | bdv_attr.dataType = UA_NS0ID(BASEDATATYPE); |
194 | 19.7k | bdv_attr.valueRank = UA_VALUERANK_ANY; |
195 | 19.7k | ret |= addNode(server, UA_NODECLASS_VARIABLETYPE, |
196 | 19.7k | UA_NS0ID(BASEDATAVARIABLETYPE), UA_NS0ID(BASEVARIABLETYPE), |
197 | 19.7k | UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "BaseDataVariableType"), |
198 | 19.7k | UA_NODEID_NULL, &bdv_attr, &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], |
199 | 19.7k | NULL, NULL); |
200 | | |
201 | 19.7k | UA_VariableTypeAttributes prop_attr = UA_VariableTypeAttributes_default; |
202 | 19.7k | prop_attr.displayName = UA_LOCALIZEDTEXT("", "PropertyType"); |
203 | 19.7k | prop_attr.dataType = UA_NS0ID(BASEDATATYPE); |
204 | 19.7k | prop_attr.valueRank = UA_VALUERANK_ANY; |
205 | 19.7k | ret |= addNode(server, UA_NODECLASS_VARIABLETYPE, |
206 | 19.7k | UA_NS0ID(PROPERTYTYPE), UA_NS0ID(BASEVARIABLETYPE), |
207 | 19.7k | UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "PropertyType"), |
208 | 19.7k | UA_NODEID_NULL, &prop_attr, |
209 | 19.7k | &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], NULL, NULL); |
210 | | |
211 | | /***************/ |
212 | | /* ObjectTypes */ |
213 | | /***************/ |
214 | | |
215 | 19.7k | UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default; |
216 | 19.7k | baseobj_attr.displayName = UA_LOCALIZEDTEXT("", "BaseObjectType"); |
217 | 19.7k | ret |= ns0_addNode_raw(server, UA_NODECLASS_OBJECTTYPE, |
218 | 19.7k | UA_NS0ID_BASEOBJECTTYPE, "BaseObjectType", |
219 | 19.7k | &baseobj_attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]); |
220 | | |
221 | 19.7k | UA_ObjectTypeAttributes folder_attr = UA_ObjectTypeAttributes_default; |
222 | 19.7k | folder_attr.displayName = UA_LOCALIZEDTEXT("", "FolderType"); |
223 | 19.7k | ret |= addNode(server, UA_NODECLASS_OBJECTTYPE, |
224 | 19.7k | UA_NS0ID(FOLDERTYPE), UA_NS0ID(BASEOBJECTTYPE), |
225 | 19.7k | UA_NODEID_NULL, UA_QUALIFIEDNAME(0, "FolderType"), |
226 | 19.7k | UA_NODEID_NULL, |
227 | 19.7k | &folder_attr, &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL); |
228 | | |
229 | | /******************/ |
230 | | /* Root and below */ |
231 | | /******************/ |
232 | | |
233 | 19.7k | ret |= addObjectNode(server, "Root", UA_NS0ID_ROOTFOLDER, 0, 0, UA_NS0ID_FOLDERTYPE); |
234 | | |
235 | 19.7k | ret |= addObjectNode(server, "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER, |
236 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
237 | | |
238 | 19.7k | ret |= addObjectNode(server, "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER, |
239 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
240 | | |
241 | 19.7k | ret |= addObjectNode(server, "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
242 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
243 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_REFERENCES, |
244 | 19.7k | UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_ORGANIZES); |
245 | | |
246 | 19.7k | ret |= addObjectNode(server, "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
247 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
248 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEDATATYPE, |
249 | 19.7k | UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_ORGANIZES); |
250 | | |
251 | 19.7k | ret |= addObjectNode(server, "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
252 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
253 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE, |
254 | 19.7k | UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_ORGANIZES); |
255 | | |
256 | 19.7k | ret |= addObjectNode(server, "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
257 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
258 | 19.7k | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE, |
259 | 19.7k | UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_ORGANIZES); |
260 | | |
261 | 19.7k | ret |= addObjectNode(server, "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
262 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
263 | | |
264 | 19.7k | ret |= addObjectNode(server, "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER, |
265 | 19.7k | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
266 | | |
267 | | /* Add BaseEventType */ |
268 | 19.7k | UA_ObjectTypeAttributes eventtype_attr = UA_ObjectTypeAttributes_default; |
269 | 19.7k | eventtype_attr.displayName = UA_LOCALIZEDTEXT("", "BaseEventType"); |
270 | 19.7k | ret |= addNode(server, UA_NODECLASS_OBJECTTYPE, UA_NS0ID(BASEEVENTTYPE), |
271 | 19.7k | UA_NS0ID(BASEOBJECTTYPE), UA_NODEID_NULL, |
272 | 19.7k | UA_QUALIFIEDNAME(0, "BaseEventType"), UA_NODEID_NULL, &eventtype_attr, |
273 | 19.7k | &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL); |
274 | 19.7k | ret |= addRef(server, UA_NS0ID(EVENTTYPESFOLDER), UA_NS0ID(ORGANIZES), |
275 | 19.7k | UA_NS0ID(BASEEVENTTYPE), true); |
276 | | |
277 | 19.7k | if(ret != UA_STATUSCODE_GOOD) |
278 | 0 | ret = UA_STATUSCODE_BADINTERNALERROR; |
279 | | |
280 | 19.7k | return ret; |
281 | 19.7k | } |
282 | | |
283 | | /****************/ |
284 | | /* Data Sources */ |
285 | | /****************/ |
286 | | |
287 | | static UA_StatusCode |
288 | | writeStatus(UA_Server *server, const UA_NodeId *sessionId, |
289 | | void *sessionContext, const UA_NodeId *nodeId, |
290 | | void *nodeContext, const UA_NumericRange *range, |
291 | 0 | const UA_DataValue *value) { |
292 | 0 | if(range) |
293 | 0 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
294 | | |
295 | 0 | if(nodeId->identifier.numeric != UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN) |
296 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
297 | | |
298 | | /* Only the local user can write into this variable */ |
299 | 0 | if(sessionId != &server->adminSession.sessionId) |
300 | 0 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
301 | | |
302 | 0 | if(!UA_Variant_hasScalarType(&value->value, &UA_TYPES[UA_TYPES_UINT32])) |
303 | 0 | return UA_STATUSCODE_BADTYPEMISMATCH; |
304 | | |
305 | 0 | UA_EventLoop *el = server->config.eventLoop; |
306 | 0 | UA_UInt32 *endTime = (UA_UInt32*)value->value.data; |
307 | 0 | server->endTime = el->dateTime_now(el) + (UA_DateTime)(*endTime * UA_DATETIME_SEC); |
308 | 0 | return UA_STATUSCODE_GOOD; |
309 | 0 | } |
310 | | |
311 | | static UA_StatusCode |
312 | | readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
313 | | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, |
314 | 0 | const UA_NumericRange *range, UA_DataValue *value) { |
315 | 0 | UA_EventLoop *el = server->config.eventLoop; |
316 | |
|
317 | 0 | if(range) { |
318 | 0 | value->hasStatus = true; |
319 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
320 | 0 | return UA_STATUSCODE_GOOD; |
321 | 0 | } |
322 | | |
323 | 0 | if(sourceTimestamp) { |
324 | 0 | value->hasSourceTimestamp = true; |
325 | 0 | value->sourceTimestamp = el->dateTime_now(el); |
326 | 0 | } |
327 | |
|
328 | 0 | void *data = NULL; |
329 | |
|
330 | 0 | UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC); |
331 | | |
332 | 0 | switch(nodeId->identifier.numeric) { |
333 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN: { |
334 | 0 | UA_UInt32 *shutdown = UA_UInt32_new(); |
335 | 0 | if(!shutdown) |
336 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
337 | 0 | if(server->endTime != 0) |
338 | 0 | *shutdown = (UA_UInt32)((server->endTime - el->dateTime_now(el)) / UA_DATETIME_SEC); |
339 | 0 | value->value.data = shutdown; |
340 | 0 | value->value.type = &UA_TYPES[UA_TYPES_UINT32]; |
341 | 0 | value->hasValue = true; |
342 | 0 | return UA_STATUSCODE_GOOD; |
343 | 0 | } |
344 | | |
345 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_STATE: { |
346 | 0 | UA_ServerState *state = UA_ServerState_new(); |
347 | 0 | if(!state) |
348 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
349 | 0 | if(server->endTime != 0) |
350 | 0 | *state = UA_SERVERSTATE_SHUTDOWN; |
351 | 0 | value->value.data = state; |
352 | 0 | value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE]; |
353 | 0 | value->hasValue = true; |
354 | 0 | return UA_STATUSCODE_GOOD; |
355 | 0 | } |
356 | | |
357 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS: { |
358 | 0 | UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new(); |
359 | 0 | if(!statustype) |
360 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
361 | 0 | statustype->startTime = server->startTime; |
362 | 0 | statustype->currentTime = el->dateTime_now(el); |
363 | |
|
364 | 0 | statustype->state = UA_SERVERSTATE_RUNNING; |
365 | 0 | statustype->secondsTillShutdown = 0; |
366 | 0 | if(server->endTime != 0) { |
367 | 0 | statustype->state = UA_SERVERSTATE_SHUTDOWN; |
368 | 0 | statustype->secondsTillShutdown = (UA_UInt32) |
369 | 0 | ((server->endTime - el->dateTime_now(el)) / UA_DATETIME_SEC); |
370 | 0 | } |
371 | |
|
372 | 0 | value->value.data = statustype; |
373 | 0 | value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]; |
374 | 0 | value->hasValue = true; |
375 | 0 | return UA_BuildInfo_copy(&server->config.buildInfo, &statustype->buildInfo); |
376 | 0 | } |
377 | | |
378 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO: |
379 | 0 | value->value.type = &UA_TYPES[UA_TYPES_BUILDINFO]; |
380 | 0 | data = &server->config.buildInfo; |
381 | 0 | break; |
382 | | |
383 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI: |
384 | 0 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
385 | 0 | data = &server->config.buildInfo.productUri; |
386 | 0 | break; |
387 | | |
388 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME: |
389 | 0 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
390 | 0 | data = &server->config.buildInfo.manufacturerName; |
391 | 0 | break; |
392 | | |
393 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME: |
394 | 0 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
395 | 0 | data = &server->config.buildInfo.productName; |
396 | 0 | break; |
397 | | |
398 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION: |
399 | 0 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
400 | 0 | data = &server->config.buildInfo.softwareVersion; |
401 | 0 | break; |
402 | | |
403 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER: |
404 | 0 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
405 | 0 | data = &server->config.buildInfo.buildNumber; |
406 | 0 | break; |
407 | | |
408 | 0 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE: |
409 | 0 | value->value.type = &UA_TYPES[UA_TYPES_DATETIME]; |
410 | 0 | data = &server->config.buildInfo.buildDate; |
411 | 0 | break; |
412 | | |
413 | 0 | default: |
414 | 0 | value->hasStatus = true; |
415 | 0 | value->status = UA_STATUSCODE_BADINTERNALERROR; |
416 | 0 | return UA_STATUSCODE_GOOD; |
417 | 0 | } |
418 | | |
419 | 0 | value->value.data = UA_new(value->value.type); |
420 | 0 | if(!value->value.data) { |
421 | 0 | value->value.type = NULL; |
422 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
423 | 0 | } |
424 | | |
425 | 0 | value->hasValue = true; |
426 | 0 | return UA_copy(data, value->value.data, value->value.type); |
427 | 0 | } |
428 | | |
429 | | #ifdef UA_GENERATED_NAMESPACE_ZERO |
430 | | static UA_StatusCode |
431 | | readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
432 | | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
433 | 0 | const UA_NumericRange *range, UA_DataValue *value) { |
434 | 0 | UA_EventLoop *el = server->config.eventLoop; |
435 | |
|
436 | 0 | if(range) { |
437 | 0 | value->hasStatus = true; |
438 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
439 | 0 | return UA_STATUSCODE_GOOD; |
440 | 0 | } |
441 | | |
442 | 0 | value->value.type = &UA_TYPES[UA_TYPES_BYTE]; |
443 | 0 | value->value.arrayLength = 0; |
444 | 0 | UA_Byte *byte = UA_Byte_new(); |
445 | 0 | if(!byte) |
446 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
447 | 0 | *byte = 255; |
448 | 0 | value->value.data = byte; |
449 | 0 | value->value.arrayDimensionsSize = 0; |
450 | 0 | value->value.arrayDimensions = NULL; |
451 | 0 | value->hasValue = true; |
452 | 0 | if(includeSourceTimeStamp) { |
453 | 0 | value->hasSourceTimestamp = true; |
454 | 0 | value->sourceTimestamp = el->dateTime_now(el); |
455 | 0 | } |
456 | 0 | return UA_STATUSCODE_GOOD; |
457 | 0 | } |
458 | | |
459 | | static UA_StatusCode |
460 | | readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
461 | | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
462 | 0 | const UA_NumericRange *range, UA_DataValue *value) { |
463 | 0 | UA_EventLoop *el = server->config.eventLoop; |
464 | |
|
465 | 0 | if(range) { |
466 | 0 | value->hasStatus = true; |
467 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
468 | 0 | return UA_STATUSCODE_GOOD; |
469 | 0 | } |
470 | | |
471 | 0 | value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN]; |
472 | 0 | value->value.arrayLength = 0; |
473 | 0 | UA_Boolean *boolean = UA_Boolean_new(); |
474 | 0 | if(!boolean) |
475 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
476 | 0 | *boolean = false; |
477 | 0 | value->value.data = boolean; |
478 | 0 | value->value.arrayDimensionsSize = 0; |
479 | 0 | value->value.arrayDimensions = NULL; |
480 | 0 | value->hasValue = true; |
481 | 0 | if(includeSourceTimeStamp) { |
482 | 0 | value->hasSourceTimestamp = true; |
483 | 0 | value->sourceTimestamp = el->dateTime_now(el); |
484 | 0 | } |
485 | 0 | return UA_STATUSCODE_GOOD; |
486 | 0 | } |
487 | | #endif |
488 | | |
489 | | static UA_StatusCode |
490 | | readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
491 | | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
492 | | const UA_NumericRange *range, |
493 | 0 | UA_DataValue *value) { |
494 | 0 | UA_EventLoop *el = server->config.eventLoop; |
495 | | |
496 | | /* ensure that the uri for ns1 is set up from the app description */ |
497 | 0 | setupNs1Uri(server); |
498 | |
|
499 | 0 | if(range) { |
500 | 0 | value->hasStatus = true; |
501 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
502 | 0 | return UA_STATUSCODE_GOOD; |
503 | 0 | } |
504 | 0 | UA_StatusCode retval; |
505 | 0 | retval = UA_Variant_setArrayCopy(&value->value, server->namespaces, |
506 | 0 | server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]); |
507 | 0 | if(retval != UA_STATUSCODE_GOOD) |
508 | 0 | return retval; |
509 | 0 | value->hasValue = true; |
510 | 0 | if(includeSourceTimeStamp) { |
511 | 0 | value->hasSourceTimestamp = true; |
512 | 0 | value->sourceTimestamp = el->dateTime_now(el); |
513 | 0 | } |
514 | 0 | return UA_STATUSCODE_GOOD; |
515 | 0 | } |
516 | | |
517 | | static UA_StatusCode |
518 | | writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
519 | | const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range, |
520 | 0 | const UA_DataValue *value) { |
521 | | /* Check the data type */ |
522 | 0 | if(!value->hasValue || |
523 | 0 | value->value.type != &UA_TYPES[UA_TYPES_STRING]) |
524 | 0 | return UA_STATUSCODE_BADTYPEMISMATCH; |
525 | | |
526 | | /* Check that the variant is not empty */ |
527 | 0 | if(!value->value.data) |
528 | 0 | return UA_STATUSCODE_BADTYPEMISMATCH; |
529 | | |
530 | | /* TODO: Writing with a range is not implemented */ |
531 | 0 | if(range) |
532 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
533 | | |
534 | 0 | UA_String *newNamespaces = (UA_String*)value->value.data; |
535 | 0 | size_t newNamespacesSize = value->value.arrayLength; |
536 | | |
537 | | /* Test if we append to the existing namespaces */ |
538 | 0 | if(newNamespacesSize <= server->namespacesSize) |
539 | 0 | return UA_STATUSCODE_BADTYPEMISMATCH; |
540 | | |
541 | | /* ensure that the uri for ns1 is set up from the app description */ |
542 | 0 | setupNs1Uri(server); |
543 | | |
544 | | /* Test if the existing namespaces are unchanged */ |
545 | 0 | for(size_t i = 0; i < server->namespacesSize; ++i) { |
546 | 0 | if(!UA_String_equal(&server->namespaces[i], &newNamespaces[i])) |
547 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
548 | 0 | } |
549 | | |
550 | | /* Add namespaces */ |
551 | 0 | for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i) |
552 | 0 | addNamespace(server, newNamespaces[i]); |
553 | 0 | return UA_STATUSCODE_GOOD; |
554 | 0 | } |
555 | | |
556 | | static UA_StatusCode |
557 | | readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
558 | | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean sourceTimeStamp, |
559 | 0 | const UA_NumericRange *range, UA_DataValue *value) { |
560 | 0 | UA_EventLoop *el = server->config.eventLoop; |
561 | |
|
562 | 0 | if(range) { |
563 | 0 | value->hasStatus = true; |
564 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
565 | 0 | return UA_STATUSCODE_GOOD; |
566 | 0 | } |
567 | | |
568 | 0 | UA_DateTime currentTime = el->dateTime_now(el); |
569 | 0 | UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, ¤tTime, |
570 | 0 | &UA_TYPES[UA_TYPES_DATETIME]); |
571 | 0 | if(retval != UA_STATUSCODE_GOOD) |
572 | 0 | return retval; |
573 | 0 | value->hasValue = true; |
574 | 0 | if(sourceTimeStamp) { |
575 | 0 | value->hasSourceTimestamp = true; |
576 | 0 | value->sourceTimestamp = currentTime; |
577 | 0 | } |
578 | 0 | return UA_STATUSCODE_GOOD; |
579 | 0 | } |
580 | | |
581 | | #ifdef UA_GENERATED_NAMESPACE_ZERO |
582 | | static UA_StatusCode |
583 | | readOperationLimits(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
584 | | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
585 | | const UA_NumericRange *range, |
586 | 0 | UA_DataValue *value) { |
587 | 0 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
588 | 0 | if(nodeid->identifierType != UA_NODEIDTYPE_NUMERIC) |
589 | 0 | return UA_STATUSCODE_BADNOTSUPPORTED; |
590 | 0 | switch(nodeid->identifier.numeric) { |
591 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD: |
592 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerRead, &UA_TYPES[UA_TYPES_UINT32]); |
593 | 0 | break; |
594 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE: |
595 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerWrite, &UA_TYPES[UA_TYPES_UINT32]); |
596 | 0 | break; |
597 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL: |
598 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerMethodCall, &UA_TYPES[UA_TYPES_UINT32]); |
599 | 0 | break; |
600 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE: |
601 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerBrowse, &UA_TYPES[UA_TYPES_UINT32]); |
602 | 0 | break; |
603 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES: |
604 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerRegisterNodes, &UA_TYPES[UA_TYPES_UINT32]); |
605 | 0 | break; |
606 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS: |
607 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, &UA_TYPES[UA_TYPES_UINT32]); |
608 | 0 | break; |
609 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT: |
610 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxNodesPerNodeManagement, &UA_TYPES[UA_TYPES_UINT32]); |
611 | 0 | break; |
612 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL: |
613 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.maxMonitoredItemsPerCall, &UA_TYPES[UA_TYPES_UINT32]); |
614 | 0 | break; |
615 | 0 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSQUEUESIZE: |
616 | 0 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
617 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &server->config.queueSizeLimits.max, |
618 | 0 | &UA_TYPES[UA_TYPES_UINT32]); |
619 | | #else |
620 | | { |
621 | | UA_UInt32 maxQueueSize = 0; |
622 | | retval = UA_Variant_setScalarCopy(&value->value, &maxQueueSize, |
623 | | &UA_TYPES[UA_TYPES_UINT32]); |
624 | | } |
625 | | #endif |
626 | 0 | break; |
627 | 0 | default: |
628 | 0 | retval = UA_STATUSCODE_BADNOTSUPPORTED; |
629 | 0 | } |
630 | 0 | return retval; |
631 | 0 | } |
632 | | |
633 | | static UA_StatusCode |
634 | | readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
635 | | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
636 | 0 | const UA_NumericRange *range, UA_DataValue *value) { |
637 | 0 | UA_EventLoop *el = server->config.eventLoop; |
638 | |
|
639 | 0 | if(range) { |
640 | 0 | value->hasStatus = true; |
641 | 0 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
642 | 0 | return UA_STATUSCODE_GOOD; |
643 | 0 | } |
644 | | |
645 | 0 | UA_StatusCode retval; |
646 | 0 | UA_Duration minInterval; |
647 | 0 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
648 | 0 | minInterval = server->config.samplingIntervalLimits.min; |
649 | | #else |
650 | | minInterval = 0.0; |
651 | | #endif |
652 | 0 | retval = UA_Variant_setScalarCopy(&value->value, &minInterval, &UA_TYPES[UA_TYPES_DURATION]); |
653 | 0 | if(retval != UA_STATUSCODE_GOOD) |
654 | 0 | return retval; |
655 | 0 | value->hasValue = true; |
656 | 0 | if(includeSourceTimeStamp) { |
657 | 0 | value->hasSourceTimestamp = true; |
658 | 0 | value->sourceTimestamp = el->dateTime_now(el); |
659 | 0 | } |
660 | 0 | return UA_STATUSCODE_GOOD; |
661 | 0 | } |
662 | | #endif |
663 | | |
664 | | #if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) |
665 | | static UA_StatusCode |
666 | | resendData(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
667 | | const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, |
668 | | void *objectContext, size_t inputSize, const UA_Variant *input, |
669 | 0 | size_t outputSize, UA_Variant *output) { |
670 | | /* Get the input argument */ |
671 | 0 | if(inputSize != 1 || |
672 | 0 | !UA_Variant_hasScalarType(input, &UA_TYPES[UA_TYPES_UINT32])) |
673 | 0 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
674 | 0 | UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data)); |
675 | | |
676 | | /* Get the Session */ |
677 | 0 | lockServer(server); |
678 | 0 | UA_Session *session = getSessionById(server, sessionId); |
679 | 0 | if(!session) { |
680 | 0 | unlockServer(server); |
681 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
682 | 0 | } |
683 | | |
684 | | /* Get the Subscription */ |
685 | 0 | UA_Subscription *subscription = getSubscriptionById(server, subscriptionId); |
686 | 0 | if(!subscription) { |
687 | 0 | unlockServer(server); |
688 | 0 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
689 | 0 | } |
690 | | |
691 | | /* The Subscription is not attached to this Session */ |
692 | 0 | if(subscription->session != session) { |
693 | 0 | unlockServer(server); |
694 | 0 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
695 | 0 | } |
696 | | |
697 | 0 | UA_Subscription_resendData(server, subscription); |
698 | |
|
699 | 0 | unlockServer(server); |
700 | 0 | return UA_STATUSCODE_GOOD; |
701 | 0 | } |
702 | | |
703 | | struct FillHandlesContext { |
704 | | UA_UInt32 *clientHandles; |
705 | | UA_UInt32 *serverHandles; |
706 | | UA_UInt32 i; |
707 | | }; |
708 | | |
709 | | static void * |
710 | 0 | fillHandlesVisitor(void *context, UA_MonitoredItem *monitoredItem) { |
711 | 0 | struct FillHandlesContext *ctx = (struct FillHandlesContext*)context; |
712 | 0 | ctx->clientHandles[ctx->i] = monitoredItem->parameters.clientHandle; |
713 | 0 | ctx->serverHandles[ctx->i] = monitoredItem->monitoredItemId; |
714 | 0 | ctx->i++; |
715 | 0 | return NULL; |
716 | 0 | } |
717 | | |
718 | | static UA_StatusCode |
719 | | readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
720 | | const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, |
721 | | void *objectContext, size_t inputSize, const UA_Variant *input, |
722 | 0 | size_t outputSize, UA_Variant *output) { |
723 | | /* The argument metadata is mutable through the information model. Validate |
724 | | * the actual callback arguments before accessing them. */ |
725 | 0 | if(inputSize != 1 || |
726 | 0 | !UA_Variant_hasScalarType(input, &UA_TYPES[UA_TYPES_UINT32])) |
727 | 0 | return UA_STATUSCODE_BADTYPEMISMATCH; |
728 | 0 | if(outputSize != 2) |
729 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
730 | | |
731 | | /* Return two empty arrays by default */ |
732 | 0 | UA_Variant_setArray(&output[0], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]), |
733 | 0 | 0, &UA_TYPES[UA_TYPES_UINT32]); |
734 | 0 | UA_Variant_setArray(&output[1], UA_Array_new(0, &UA_TYPES[UA_TYPES_UINT32]), |
735 | 0 | 0, &UA_TYPES[UA_TYPES_UINT32]); |
736 | |
|
737 | 0 | lockServer(server); |
738 | | |
739 | | /* Get the Session */ |
740 | 0 | UA_Session *session = getSessionById(server, sessionId); |
741 | 0 | if(!session) { |
742 | 0 | unlockServer(server); |
743 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
744 | 0 | } |
745 | | /* Get the Subscription */ |
746 | 0 | UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data)); |
747 | 0 | UA_Subscription *subscription = getSubscriptionById(server, subscriptionId); |
748 | 0 | if(!subscription) { |
749 | 0 | unlockServer(server); |
750 | 0 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
751 | 0 | } |
752 | | |
753 | | /* The Subscription is not attached to this Session */ |
754 | 0 | if(subscription->session != session) { |
755 | 0 | unlockServer(server); |
756 | 0 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
757 | 0 | } |
758 | | |
759 | | /* Count the MonitoredItems */ |
760 | 0 | UA_UInt32 sizeOfOutput = subscription->monitoredItemsSize; |
761 | 0 | if(sizeOfOutput == 0) { |
762 | 0 | unlockServer(server); |
763 | 0 | return UA_STATUSCODE_GOOD; |
764 | 0 | } |
765 | | |
766 | | /* Allocate the output arrays */ |
767 | 0 | UA_UInt32 *clientHandles = (UA_UInt32*) |
768 | 0 | UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]); |
769 | 0 | if(!clientHandles) { |
770 | 0 | unlockServer(server); |
771 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
772 | 0 | } |
773 | 0 | UA_UInt32 *serverHandles = (UA_UInt32*) |
774 | 0 | UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]); |
775 | 0 | if(!serverHandles) { |
776 | 0 | unlockServer(server); |
777 | 0 | UA_free(clientHandles); |
778 | 0 | return UA_STATUSCODE_BADOUTOFMEMORY; |
779 | 0 | } |
780 | | |
781 | | /* Fill the array */ |
782 | 0 | struct FillHandlesContext ctx = {clientHandles, serverHandles, 0}; |
783 | 0 | ZIP_ITER(UA_MonitoredItemIdTree, &subscription->monitoredItemsById, |
784 | 0 | fillHandlesVisitor, &ctx); |
785 | 0 | UA_assert(ctx.i == sizeOfOutput); |
786 | 0 | UA_Variant_setArray(&output[0], serverHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]); |
787 | 0 | UA_Variant_setArray(&output[1], clientHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]); |
788 | |
|
789 | 0 | unlockServer(server); |
790 | 0 | return UA_STATUSCODE_GOOD; |
791 | 0 | } |
792 | | #endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */ |
793 | | |
794 | | static UA_StatusCode |
795 | | writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v, |
796 | 59.2k | size_t length, const UA_DataType *type) { |
797 | 59.2k | UA_Variant var; |
798 | 59.2k | UA_Variant_init(&var); |
799 | 59.2k | UA_Variant_setArray(&var, v, length, type); |
800 | 59.2k | return writeValueAttribute(server, UA_NODEID_NUMERIC(0, id), &var); |
801 | 59.2k | } |
802 | | |
803 | | #ifdef UA_GENERATED_NAMESPACE_ZERO |
804 | | static UA_StatusCode |
805 | 394k | writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) { |
806 | 394k | UA_Variant var; |
807 | 394k | UA_Variant_init(&var); |
808 | 394k | UA_Variant_setScalar(&var, v, type); |
809 | 394k | return writeValueAttribute(server, UA_NODEID_NUMERIC(0, id), &var); |
810 | 394k | } |
811 | | #endif |
812 | | |
813 | | #ifndef UA_GENERATED_NAMESPACE_ZERO |
814 | | static UA_StatusCode |
815 | | addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid, |
816 | | UA_UInt32 parentid, UA_UInt32 referenceid, |
817 | | UA_Int32 valueRank, UA_UInt32 dataType) { |
818 | | UA_VariableAttributes attr = UA_VariableAttributes_default; |
819 | | attr.displayName = UA_LOCALIZEDTEXT("", name); |
820 | | attr.dataType = UA_NODEID_NUMERIC(0, dataType); |
821 | | attr.valueRank = valueRank; |
822 | | attr.accessLevel = UA_ACCESSLEVELMASK_READ; |
823 | | return addNode(server, UA_NODECLASS_VARIABLE, UA_NODEID_NUMERIC(0, variableid), |
824 | | UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid), |
825 | | UA_QUALIFIEDNAME(0, name), UA_NS0ID(BASEDATAVARIABLETYPE), |
826 | | &attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, NULL); |
827 | | } |
828 | | |
829 | | /* A minimal server object that is not complete and does not use the mandated |
830 | | * references to a server type. To be used on very constrained devices. */ |
831 | | static UA_StatusCode |
832 | | minimalServerObject(UA_Server *server) { |
833 | | /* Server */ |
834 | | UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER, |
835 | | UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE); |
836 | | |
837 | | /* Use a valuerank of -2 for now. The array is added later on and the valuerank set to 1. */ |
838 | | retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY, |
839 | | UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, |
840 | | UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE); |
841 | | |
842 | | retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY, |
843 | | UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, |
844 | | UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE); |
845 | | |
846 | | retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS, |
847 | | UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT, |
848 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
849 | | |
850 | | retval |= addVariableNode(server, "StartTime", UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME, |
851 | | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
852 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
853 | | |
854 | | retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME, |
855 | | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
856 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
857 | | |
858 | | retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE, |
859 | | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
860 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
861 | | |
862 | | retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, |
863 | | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
864 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
865 | | |
866 | | retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI, |
867 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
868 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
869 | | |
870 | | retval |= addVariableNode(server, "ManufacturerName", |
871 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME, |
872 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
873 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
874 | | |
875 | | retval |= addVariableNode(server, "ProductName", |
876 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME, |
877 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
878 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
879 | | |
880 | | retval |= addVariableNode(server, "SoftwareVersion", |
881 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION, |
882 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
883 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
884 | | |
885 | | retval |= addVariableNode(server, "BuildNumber", |
886 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER, |
887 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
888 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
889 | | |
890 | | retval |= addVariableNode(server, "BuildDate", |
891 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE, |
892 | | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
893 | | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
894 | | |
895 | | return retval; |
896 | | } |
897 | | |
898 | | #else |
899 | | |
900 | | static void |
901 | 19.7k | addModellingRules(UA_Server *server) { |
902 | | /* Test if the ModellingRules folder was added. (Only for the full ns0.) */ |
903 | 19.7k | UA_NodeId mrNodeId = UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES); |
904 | 19.7k | const UA_Node *mrnode = UA_NODESTORE_GET(server, &mrNodeId); |
905 | 19.7k | if(!mrnode) |
906 | 0 | return; |
907 | 19.7k | UA_NODESTORE_RELEASE(server, mrnode); |
908 | | |
909 | | /* Add ExposesItsArray */ |
910 | 19.7k | addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
911 | 19.7k | UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_EXPOSESITSARRAY), true); |
912 | | |
913 | | /* Add Mandatory */ |
914 | 19.7k | addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
915 | 19.7k | UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_MANDATORY), true); |
916 | | |
917 | | |
918 | | /* Add MandatoryPlaceholder */ |
919 | 19.7k | addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
920 | 19.7k | UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_MANDATORYPLACEHOLDER), true); |
921 | | |
922 | | /* Add Optional */ |
923 | 19.7k | addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
924 | 19.7k | UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_OPTIONAL), true); |
925 | | |
926 | | /* Add OptionalPlaceholder */ |
927 | 19.7k | addRef(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
928 | 19.7k | UA_NS0ID(HASCOMPONENT), UA_NS0ID(MODELLINGRULE_OPTIONALPLACEHOLDER), true); |
929 | 19.7k | } |
930 | | |
931 | | #endif |
932 | | |
933 | | static UA_StatusCode connectNS0_dataSources(UA_Server *server); |
934 | | static UA_StatusCode configureNS0(UA_Server *server); |
935 | | |
936 | | /* Initialize the nodeset 0 by using the generated code of the nodeset compiler. |
937 | | * This also initialized the data sources for various variables, such as for |
938 | | * example server time. */ |
939 | | UA_StatusCode |
940 | 19.7k | initNS0(UA_Server *server) { |
941 | 19.7k | UA_LOCK_ASSERT(&server->serviceMutex); |
942 | | |
943 | | /* Initialize base nodes which are always required an cannot be created |
944 | | * through the NS compiler */ |
945 | 19.7k | server->bootstrapNS0 = true; |
946 | 19.7k | UA_StatusCode retVal = createNS0_base(server); |
947 | | |
948 | 19.7k | #ifdef UA_GENERATED_NAMESPACE_ZERO |
949 | | /* Load nodes and references generated from the XML ns0 definition */ |
950 | 19.7k | retVal |= namespace0_generated(server); |
951 | | #else |
952 | | /* Create a minimal server object */ |
953 | | retVal |= minimalServerObject(server); |
954 | | #endif |
955 | | |
956 | 19.7k | server->bootstrapNS0 = false; |
957 | | |
958 | 19.7k | if(retVal != UA_STATUSCODE_GOOD) { |
959 | 0 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
960 | 0 | "Initialization of Namespace 0 failed with %s. " |
961 | 0 | "See previous outputs for any error messages.", |
962 | 0 | UA_StatusCode_name(retVal)); |
963 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
964 | 0 | } |
965 | | |
966 | | /* Connect data sources and configure NS0 (shared with ROM nodestore) */ |
967 | 19.7k | retVal |= connectNS0_dataSources(server); |
968 | 19.7k | retVal |= configureNS0(server); |
969 | | |
970 | 19.7k | if(retVal != UA_STATUSCODE_GOOD) { |
971 | 0 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
972 | 0 | "Initialization of Namespace 0 (after bootstrapping) " |
973 | 0 | "failed with %s. See previous outputs for any error messages.", |
974 | 0 | UA_StatusCode_name(retVal)); |
975 | 0 | return UA_STATUSCODE_BADINTERNALERROR; |
976 | 0 | } |
977 | 19.7k | return UA_STATUSCODE_GOOD; |
978 | 19.7k | } |
979 | | |
980 | | /* Configure NS0 nodes: write values, delete unused nodes, add references. |
981 | | * This is called after nodes are created (initNS0) or loaded from ROM. |
982 | | * Shared between initNS0() and initNS0_dataSources() to avoid duplication. */ |
983 | | static UA_StatusCode |
984 | 19.7k | configureNS0(UA_Server *server) { |
985 | 19.7k | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
986 | | |
987 | | /* Additional attribute setup for NamespaceArray */ |
988 | 19.7k | retVal |= writeValueRankAttribute(server, UA_NS0ID(SERVER_NAMESPACEARRAY), 1); |
989 | | |
990 | | /* ServerArray */ |
991 | 19.7k | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY, |
992 | 19.7k | &server->config.applicationDescription.applicationUri, |
993 | 19.7k | 1, &UA_TYPES[UA_TYPES_STRING]); |
994 | 19.7k | retVal |= writeValueRankAttribute(server, UA_NS0ID(SERVER_SERVERARRAY), 1); |
995 | | |
996 | | /* StartTime will be sampled in UA_Server_run_startup()*/ |
997 | | |
998 | | /* CurrentTime - additional attribute setup */ |
999 | 19.7k | UA_NodeId currTime = UA_NS0ID(SERVER_SERVERSTATUS_CURRENTTIME); |
1000 | 19.7k | retVal |= writeMinimumSamplingIntervalAttribute(server, currTime, 100.0); |
1001 | | |
1002 | 19.7k | #ifdef UA_GENERATED_NAMESPACE_ZERO |
1003 | | |
1004 | | /* ShutDownReason */ |
1005 | 19.7k | UA_LocalizedText shutdownReason; |
1006 | 19.7k | UA_LocalizedText_init(&shutdownReason); |
1007 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON, |
1008 | 19.7k | &shutdownReason, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
1009 | | |
1010 | | /* ServerDiagnostics - EnabledFlag */ |
1011 | 19.7k | #ifdef UA_ENABLE_DIAGNOSTICS |
1012 | 19.7k | UA_Boolean enabledFlag = true; |
1013 | | #else |
1014 | | UA_Boolean enabledFlag = false; |
1015 | | #endif |
1016 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG, |
1017 | 19.7k | &enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1018 | | |
1019 | | /* According to Specification part-5 - pg.no-11(PDF pg.no-29), when the |
1020 | | * ServerDiagnostics is disabled the client may modify the value of |
1021 | | * enabledFlag=true in the server. By default, this node have |
1022 | | * CurrentRead/Write access. In CTT, Subscription_Minimum_1/002.js test will |
1023 | | * modify the above flag. This will not be a problem when build |
1024 | | * configuration is set at UA_NAMESPACE_ZERO="REDUCED" as NodeIds will not |
1025 | | * be present. When UA_NAMESPACE_ZERO="FULL", the test will fail. Hence made |
1026 | | * the NodeId as read only */ |
1027 | 19.7k | retVal |= writeAccessLevelAttribute(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG), |
1028 | 19.7k | UA_ACCESSLEVELMASK_READ); |
1029 | | |
1030 | | /* Redundancy Support */ |
1031 | 19.7k | UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE; |
1032 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT, |
1033 | 19.7k | &redundancySupport, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]); |
1034 | | /* Remove unused subtypes of ServerRedundancy */ |
1035 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_CURRENTSERVERID), true); |
1036 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_REDUNDANTSERVERARRAY), true); |
1037 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_SERVERURIARRAY), true); |
1038 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERREDUNDANCY_SERVERNETWORKGROUPS), true); |
1039 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true); |
1040 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_URISVERSION), true); |
1041 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true); |
1042 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMS), true); |
1043 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSPERSUBSCRIPTION), true); |
1044 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSELECTCLAUSEPARAMETERS), true); |
1045 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSESSIONS), true); |
1046 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONS), true); |
1047 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONSPERSESSION), true); |
1048 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXWHERECLAUSEPARAMETERS), true); |
1049 | | |
1050 | | /* ServerCapabilities - LocaleIdArray */ |
1051 | 19.7k | UA_LocaleId locale_en = UA_STRING("en"); |
1052 | 19.7k | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY, |
1053 | 19.7k | &locale_en, 1, &UA_TYPES[UA_TYPES_LOCALEID]); |
1054 | | |
1055 | | /* ServerCapabilities - MaxBrowseContinuationPoints */ |
1056 | 19.7k | UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS; |
1057 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS, |
1058 | 19.7k | &maxBrowseContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]); |
1059 | | |
1060 | | /* ServerProfileArray */ |
1061 | 19.7k | UA_String profileArray[3]; |
1062 | 19.7k | UA_UInt16 profileArraySize = 0; |
1063 | 59.2k | #define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x) |
1064 | 19.7k | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/StandardUA2017"); |
1065 | 19.7k | #ifdef UA_ENABLE_NODEMANAGEMENT |
1066 | 19.7k | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement"); |
1067 | 19.7k | #endif |
1068 | 19.7k | #ifdef UA_ENABLE_METHODCALLS |
1069 | 19.7k | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods"); |
1070 | 19.7k | #endif |
1071 | 19.7k | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY, |
1072 | 19.7k | profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]); |
1073 | | |
1074 | | /* ServerCapabilities - MaxQueryContinuationPoints */ |
1075 | 19.7k | UA_UInt16 maxQueryContinuationPoints = 0; |
1076 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS, |
1077 | 19.7k | &maxQueryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]); |
1078 | | |
1079 | | /* ServerCapabilities - MaxHistoryContinuationPoints */ |
1080 | 19.7k | UA_UInt16 maxHistoryContinuationPoints = 0; |
1081 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS, |
1082 | 19.7k | &maxHistoryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]); |
1083 | | |
1084 | | /* Remove unused operation limit components */ |
1085 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true); |
1086 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true); |
1087 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEDATA), true); |
1088 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEEVENTS), true); |
1089 | 19.7k | #ifndef UA_NODESET_INJECTOR_NEEDS_ROLESET |
1090 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_ROLESET), true); |
1091 | 19.7k | #endif |
1092 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXSTRINGLENGTH), true); |
1093 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true); |
1094 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true); |
1095 | | |
1096 | | /* Remove not supported server configurations */ |
1097 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_ESTIMATEDRETURNTIME), true); |
1098 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_LOCALTIME), true); |
1099 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_REQUESTSERVERSTATECHANGE), true); |
1100 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SETSUBSCRIPTIONDURABLE), true); |
1101 | 19.7k | deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTHTTPSGROUP), true); |
1102 | | #ifdef UA_NS0ID_SERVERLOG |
1103 | | deleteNode(server, UA_NS0ID(SERVERLOG), true); |
1104 | | #endif |
1105 | | #ifdef UA_NS0ID_LLDP |
1106 | | deleteNode(server, UA_NS0ID(LLDP), true); |
1107 | | #endif |
1108 | 19.7k | deleteNode(server, UA_NS0ID(PROVISIONABLEDEVICE), true); |
1109 | 19.7k | deleteNode(server, UA_NS0ID(USERMANAGEMENT), true); |
1110 | 19.7k | deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_TRANSACTIONDIAGNOSTICS), true); |
1111 | | #ifdef UA_NS0ID_SERVERCONFIGURATION_CONFIGURATIONFILE |
1112 | | deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CONFIGURATIONFILE), true); |
1113 | | #endif |
1114 | 19.7k | #ifndef UA_ENABLE_GDS_PUSHMANAGEMENT |
1115 | 19.7k | deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP), true); |
1116 | 19.7k | deleteNode(server, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP), true); |
1117 | 19.7k | #endif |
1118 | | |
1119 | | #ifndef UA_ENABLE_DIAGNOSTICS |
1120 | | /* Removing these NodeIds make Server Object to be non-complaint with UA |
1121 | | * 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js) In the |
1122 | | * 1.04 specification this has been resolved by allowing to remove these |
1123 | | * static nodes as well */ |
1124 | | deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true); |
1125 | | deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true); |
1126 | | deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true); |
1127 | | #endif |
1128 | | |
1129 | | /* The sampling diagnostics array is optional |
1130 | | * TODO: Add support for this diagnostics */ |
1131 | 19.7k | deleteNode(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true); |
1132 | | |
1133 | | #ifndef UA_ENABLE_PUBSUB |
1134 | | deleteNode(server, UA_NS0ID(PUBLISHSUBSCRIBE), true); |
1135 | | #endif |
1136 | | |
1137 | | /* ServerConfiguration - MulticastDnsEnabled */ |
1138 | | #ifdef UA_GENERATED_NAMESPACE_ZERO_FULL |
1139 | | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
1140 | | retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED, |
1141 | | &server->config.mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1142 | | #else |
1143 | | { |
1144 | | UA_Boolean mdnsEnabled = false; |
1145 | | retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED, |
1146 | | &mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1147 | | } |
1148 | | #endif |
1149 | | #endif |
1150 | | |
1151 | | #ifdef UA_GENERATED_NAMESPACE_ZERO_FULL |
1152 | | /* ServerConfiguration - HasSecureElement */ |
1153 | | { |
1154 | | UA_Boolean hasSecureElement = false; |
1155 | | retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_HASSECUREELEMENT, |
1156 | | &hasSecureElement, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1157 | | } |
1158 | | /* ServerConfiguration - ApplicationType */ |
1159 | | retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_APPLICATIONTYPE, |
1160 | | &server->config.applicationDescription.applicationType, |
1161 | | &UA_TYPES[UA_TYPES_APPLICATIONTYPE]); |
1162 | | /* OPCUANamespaceMetadata - DefaultAccessRestrictions */ |
1163 | | { |
1164 | | UA_AccessRestrictionType defaultAccessRestrictions = UA_ACCESSRESTRICTIONTYPE_NONE; |
1165 | | retVal |= writeNs0Variable(server, UA_NS0ID_OPCUANAMESPACEMETADATA_DEFAULTACCESSRESTRICTIONS, |
1166 | | &defaultAccessRestrictions, |
1167 | | &UA_TYPES[UA_TYPES_ACCESSRESTRICTIONTYPE]); |
1168 | | } |
1169 | | #endif |
1170 | | #ifndef UA_ENABLE_HISTORIZING |
1171 | | deleteNode(server, UA_NS0ID(HISTORYSERVERCAPABILITIES), true); |
1172 | | #ifdef UA_NS0ID_DEFAULTHACONFIGURATION |
1173 | | deleteNode(server, UA_NS0ID(DEFAULTHACONFIGURATION), true); |
1174 | | #endif |
1175 | | #else |
1176 | | /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryDataCapability */ |
1177 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYDATACAPABILITY, |
1178 | 19.7k | &server->config.accessHistoryDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1179 | | |
1180 | | /* ServerCapabilities - HistoryServerCapabilities - MaxReturnDataValues */ |
1181 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNDATAVALUES, |
1182 | 19.7k | &server->config.maxReturnDataValues, &UA_TYPES[UA_TYPES_UINT32]); |
1183 | | |
1184 | | /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryEventsCapability */ |
1185 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYEVENTSCAPABILITY, |
1186 | 19.7k | &server->config.accessHistoryEventsCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1187 | | |
1188 | | /* ServerCapabilities - HistoryServerCapabilities - MaxReturnEventValues */ |
1189 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNEVENTVALUES, |
1190 | 19.7k | &server->config.maxReturnEventValues, &UA_TYPES[UA_TYPES_UINT32]); |
1191 | | |
1192 | | /* ServerCapabilities - HistoryServerCapabilities - InsertDataCapability */ |
1193 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTDATACAPABILITY, |
1194 | 19.7k | &server->config.insertDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1195 | | |
1196 | | /* ServerCapabilities - HistoryServerCapabilities - InsertEventCapability */ |
1197 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTEVENTCAPABILITY, |
1198 | 19.7k | &server->config.insertEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1199 | | |
1200 | | /* ServerCapabilities - HistoryServerCapabilities - InsertAnnotationsCapability */ |
1201 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTANNOTATIONCAPABILITY, |
1202 | 19.7k | &server->config.insertAnnotationsCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1203 | | |
1204 | | /* ServerCapabilities - HistoryServerCapabilities - ReplaceDataCapability */ |
1205 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEDATACAPABILITY, |
1206 | 19.7k | &server->config.replaceDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1207 | | |
1208 | | /* ServerCapabilities - HistoryServerCapabilities - ReplaceEventCapability */ |
1209 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEEVENTCAPABILITY, |
1210 | 19.7k | &server->config.replaceEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1211 | | |
1212 | | /* ServerCapabilities - HistoryServerCapabilities - UpdateDataCapability */ |
1213 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEDATACAPABILITY, |
1214 | 19.7k | &server->config.updateDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1215 | | |
1216 | | /* ServerCapabilities - HistoryServerCapabilities - UpdateEventCapability */ |
1217 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEEVENTCAPABILITY, |
1218 | 19.7k | &server->config.updateEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1219 | | |
1220 | | /* ServerCapabilities - HistoryServerCapabilities - DeleteRawCapability */ |
1221 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETERAWCAPABILITY, |
1222 | 19.7k | &server->config.deleteRawCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1223 | | |
1224 | | /* ServerCapabilities - HistoryServerCapabilities - DeleteEventCapability */ |
1225 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEEVENTCAPABILITY, |
1226 | 19.7k | &server->config.deleteEventCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1227 | | |
1228 | | /* ServerCapabilities - HistoryServerCapabilities - DeleteAtTimeDataCapability */ |
1229 | 19.7k | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEATTIMECAPABILITY, |
1230 | 19.7k | &server->config.deleteAtTimeDataCapability, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1231 | | |
1232 | | #ifdef UA_GENERATED_NAMESPACE_ZERO_FULL |
1233 | | /* HistoryServerCapabilities - ServerTimestampSupported */ |
1234 | | { |
1235 | | UA_Boolean serverTimestampSupported = true; |
1236 | | retVal |= writeNs0Variable(server, |
1237 | | UA_NS0ID_HISTORYSERVERCAPABILITIES_SERVERTIMESTAMPSUPPORTED, |
1238 | | &serverTimestampSupported, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1239 | | } |
1240 | | #endif |
1241 | | |
1242 | | /* DefaultHAConfiguration */ |
1243 | | #ifdef UA_NS0ID_DEFAULTHACONFIGURATION_STEPPED |
1244 | | { |
1245 | | UA_Boolean bTrue = true, bFalse = false; |
1246 | | UA_Byte percentDataBad = 100, percentDataGood = 100; |
1247 | | UA_Duration zeroDuration = 0.0; |
1248 | | UA_Double zeroDouble = 0.0; |
1249 | | UA_UInt32 zeroUInt32 = 0; |
1250 | | UA_ExceptionDeviationFormat absValue = UA_EXCEPTIONDEVIATIONFORMAT_ABSOLUTEVALUE; |
1251 | | |
1252 | | retVal |= writeNs0Variable(server, |
1253 | | UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_TREATUNCERTAINASBAD, |
1254 | | &bTrue, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1255 | | retVal |= writeNs0Variable(server, |
1256 | | UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_PERCENTDATABAD, |
1257 | | &percentDataBad, &UA_TYPES[UA_TYPES_BYTE]); |
1258 | | retVal |= writeNs0Variable(server, |
1259 | | UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_PERCENTDATAGOOD, |
1260 | | &percentDataGood, &UA_TYPES[UA_TYPES_BYTE]); |
1261 | | retVal |= writeNs0Variable(server, |
1262 | | UA_NS0ID_DEFAULTHACONFIGURATION_AGGREGATECONFIGURATION_USESLOPEDEXTRAPOLATION, |
1263 | | &bFalse, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1264 | | retVal |= writeNs0Variable(server, |
1265 | | UA_NS0ID_DEFAULTHACONFIGURATION_STEPPED, |
1266 | | &bFalse, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1267 | | retVal |= writeNs0Variable(server, |
1268 | | UA_NS0ID_DEFAULTHACONFIGURATION_MAXTIMEINTERVAL, |
1269 | | &zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]); |
1270 | | retVal |= writeNs0Variable(server, |
1271 | | UA_NS0ID_DEFAULTHACONFIGURATION_MINTIMEINTERVAL, |
1272 | | &zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]); |
1273 | | retVal |= writeNs0Variable(server, |
1274 | | UA_NS0ID_DEFAULTHACONFIGURATION_EXCEPTIONDEVIATION, |
1275 | | &zeroDouble, &UA_TYPES[UA_TYPES_DOUBLE]); |
1276 | | retVal |= writeNs0Variable(server, |
1277 | | UA_NS0ID_DEFAULTHACONFIGURATION_EXCEPTIONDEVIATIONFORMAT, |
1278 | | &absValue, &UA_TYPES[UA_TYPES_EXCEPTIONDEVIATIONFORMAT]); |
1279 | | retVal |= writeNs0Variable(server, |
1280 | | UA_NS0ID_DEFAULTHACONFIGURATION_SERVERTIMESTAMPSUPPORTED, |
1281 | | &bTrue, &UA_TYPES[UA_TYPES_BOOLEAN]); |
1282 | | retVal |= writeNs0Variable(server, |
1283 | | UA_NS0ID_DEFAULTHACONFIGURATION_MAXTIMESTOREDVALUES, |
1284 | | &zeroDuration, &UA_TYPES[UA_TYPES_DOUBLE]); |
1285 | | retVal |= writeNs0Variable(server, |
1286 | | UA_NS0ID_DEFAULTHACONFIGURATION_MAXCOUNTSTOREDVALUES, |
1287 | | &zeroUInt32, &UA_TYPES[UA_TYPES_UINT32]); |
1288 | | } |
1289 | | #endif |
1290 | 19.7k | #endif |
1291 | | |
1292 | | /* The HasComponent references to the ModellingRules are not part of the |
1293 | | * Nodeset2.xml. So we add the references manually. */ |
1294 | 19.7k | addModellingRules(server); |
1295 | | |
1296 | 19.7k | #endif /* UA_GENERATED_NAMESPACE_ZERO */ |
1297 | | |
1298 | 19.7k | return retVal; |
1299 | 19.7k | } |
1300 | | |
1301 | | /* Connect data sources and callbacks to existing NS0 nodes. |
1302 | | * This is used when NS0 is loaded from an external source (e.g., ROM nodestore) |
1303 | | * and we only need to attach the dynamic data sources without creating nodes. |
1304 | | * Also called by initNS0() after node creation to avoid code duplication. */ |
1305 | | static UA_StatusCode |
1306 | 19.7k | connectNS0_dataSources(UA_Server *server) { |
1307 | 19.7k | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
1308 | | |
1309 | | /* NamespaceArray - dynamic callback */ |
1310 | 19.7k | UA_CallbackValueSource namespaceDataSource = {readNamespaces, writeNamespaces}; |
1311 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_NAMESPACEARRAY), |
1312 | 19.7k | namespaceDataSource); |
1313 | | |
1314 | | /* ServerStatus - dynamic callback */ |
1315 | 19.7k | UA_CallbackValueSource serverStatus = {readStatus, writeStatus}; |
1316 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS), serverStatus); |
1317 | | |
1318 | | /* CurrentTime */ |
1319 | 19.7k | UA_CallbackValueSource currentTime = {readCurrentTime, NULL}; |
1320 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_CURRENTTIME), currentTime); |
1321 | | |
1322 | | /* State */ |
1323 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_STATE), serverStatus); |
1324 | | |
1325 | | /* BuildInfo and sub-components */ |
1326 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO), serverStatus); |
1327 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI), serverStatus); |
1328 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME), serverStatus); |
1329 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME), serverStatus); |
1330 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION), serverStatus); |
1331 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER), serverStatus); |
1332 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE), serverStatus); |
1333 | | |
1334 | 19.7k | #ifdef UA_GENERATED_NAMESPACE_ZERO |
1335 | | /* SecondsTillShutdown */ |
1336 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN), serverStatus); |
1337 | | |
1338 | | /* ServiceLevel */ |
1339 | 19.7k | UA_CallbackValueSource serviceLevel = {readServiceLevel, NULL}; |
1340 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVICELEVEL), serviceLevel); |
1341 | | |
1342 | | /* Auditing */ |
1343 | 19.7k | UA_CallbackValueSource auditing = {readAuditing, NULL}; |
1344 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_AUDITING), auditing); |
1345 | | |
1346 | | /* MinSupportedSampleRate */ |
1347 | 19.7k | UA_CallbackValueSource samplingInterval = {readMinSamplingInterval, NULL}; |
1348 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE), samplingInterval); |
1349 | | |
1350 | | /* OperationLimits */ |
1351 | 19.7k | UA_CallbackValueSource operationLimitRead = {readOperationLimits, NULL}; |
1352 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD), operationLimitRead); |
1353 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE), operationLimitRead); |
1354 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL), operationLimitRead); |
1355 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE), operationLimitRead); |
1356 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES), operationLimitRead); |
1357 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS), operationLimitRead); |
1358 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT), operationLimitRead); |
1359 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL), operationLimitRead); |
1360 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSQUEUESIZE), operationLimitRead); |
1361 | | |
1362 | 19.7k | #ifdef UA_ENABLE_DIAGNOSTICS |
1363 | | /* ServerDiagnostics */ |
1364 | 19.7k | UA_CallbackValueSource serverDiagSummary = {readDiagnostics, NULL}; |
1365 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), serverDiagSummary); |
1366 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), serverDiagSummary); |
1367 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), serverDiagSummary); |
1368 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), serverDiagSummary); |
1369 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), serverDiagSummary); |
1370 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), serverDiagSummary); |
1371 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), serverDiagSummary); |
1372 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), serverDiagSummary); |
1373 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), serverDiagSummary); |
1374 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), serverDiagSummary); |
1375 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), serverDiagSummary); |
1376 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), serverDiagSummary); |
1377 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), serverDiagSummary); |
1378 | | |
1379 | 19.7k | #ifdef UA_ENABLE_SUBSCRIPTIONS |
1380 | 19.7k | UA_CallbackValueSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL}; |
1381 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), serverSubDiagSummary); |
1382 | 19.7k | #endif |
1383 | | |
1384 | 19.7k | UA_CallbackValueSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL}; |
1385 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), sessionDiagSummary); |
1386 | | |
1387 | 19.7k | UA_CallbackValueSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL}; |
1388 | 19.7k | retVal |= setVariableNode_callbackValueSource(server, UA_NS0ID(SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), sessionSecDiagSummary); |
1389 | 19.7k | #endif /* UA_ENABLE_DIAGNOSTICS */ |
1390 | | |
1391 | 19.7k | #if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) |
1392 | 19.7k | retVal |= setMethodNode_callback(server, UA_NS0ID(SERVER_GETMONITOREDITEMS), readMonitoredItems); |
1393 | 19.7k | retVal |= setMethodNode_callback(server, UA_NS0ID(SERVER_RESENDDATA), resendData); |
1394 | 19.7k | #endif |
1395 | | |
1396 | 19.7k | #endif /* UA_GENERATED_NAMESPACE_ZERO */ |
1397 | | |
1398 | 19.7k | return retVal; |
1399 | 19.7k | } |
1400 | | |
1401 | | /* Public function for external nodestores (e.g., ROM nodestore) that have |
1402 | | * NS0 pre-loaded and only need to connect the dynamic data sources and |
1403 | | * configure values/deletions. */ |
1404 | | UA_StatusCode |
1405 | 0 | initNS0_dataSources(UA_Server *server) { |
1406 | 0 | UA_LOCK_ASSERT(&server->serviceMutex); |
1407 | |
|
1408 | 0 | UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER, |
1409 | 0 | "Configuring pre-loaded NS0 nodes (data sources, values, deletions)"); |
1410 | | |
1411 | | /* Connect all data source callbacks (shared with initNS0) */ |
1412 | 0 | UA_StatusCode retVal = connectNS0_dataSources(server); |
1413 | | |
1414 | | /* Configure NS0: write values, delete unused nodes, add references */ |
1415 | 0 | retVal |= configureNS0(server); |
1416 | |
|
1417 | 0 | if(retVal != UA_STATUSCODE_GOOD) { |
1418 | 0 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
1419 | 0 | "Some NS0 configuration operations failed: %s " |
1420 | 0 | "(this may be normal if some nodes don't exist in ROM)", |
1421 | 0 | UA_StatusCode_name(retVal)); |
1422 | | /* Don't fail - some nodes may simply not exist in the ROM */ |
1423 | 0 | } |
1424 | |
|
1425 | 0 | return UA_STATUSCODE_GOOD; |
1426 | 0 | } |