ua_server.c 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355
  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. #include "ua_types.h"
  5. #include "ua_server_internal.h"
  6. #include "ua_securechannel_manager.h"
  7. #include "ua_session_manager.h"
  8. #include "ua_util.h"
  9. #include "ua_services.h"
  10. #include "ua_nodeids.h"
  11. #ifdef UA_ENABLE_GENERATE_NAMESPACE0
  12. #include "ua_namespaceinit_generated.h"
  13. #endif
  14. #ifdef UA_ENABLE_SUBSCRIPTIONS
  15. #include "ua_subscription.h"
  16. #endif
  17. #if defined(UA_ENABLE_MULTITHREADING) && !defined(NDEBUG)
  18. UA_THREAD_LOCAL bool rcu_locked = false;
  19. #endif
  20. #if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
  21. UA_THREAD_LOCAL UA_Session* methodCallSession = NULL;
  22. #endif
  23. static const UA_NodeId nodeIdHasSubType = {
  24. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  25. .identifier.numeric = UA_NS0ID_HASSUBTYPE};
  26. static const UA_NodeId nodeIdHasComponent = {
  27. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  28. .identifier.numeric = UA_NS0ID_HASCOMPONENT};
  29. static const UA_NodeId nodeIdHasProperty = {
  30. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  31. .identifier.numeric = UA_NS0ID_HASPROPERTY};
  32. static const UA_NodeId nodeIdOrganizes = {
  33. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  34. .identifier.numeric = UA_NS0ID_ORGANIZES};
  35. #ifndef UA_ENABLE_GENERATE_NAMESPACE0
  36. static const UA_NodeId nodeIdNonHierarchicalReferences = {
  37. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  38. .identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES};
  39. #endif
  40. /**********************/
  41. /* Namespace Handling */
  42. /**********************/
  43. UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
  44. /* Check if the namespace already exists in the server's namespace array */
  45. for(UA_UInt16 i=0;i<server->namespacesSize;++i) {
  46. if(UA_String_equal(&name, &server->namespaces[i]))
  47. return i;
  48. }
  49. /* Add a new namespace to the namsepace array */
  50. UA_String *newNS = UA_realloc(server->namespaces,
  51. sizeof(UA_String) * (server->namespacesSize + 1));
  52. if(!newNS)
  53. return 0;
  54. server->namespaces = newNS;
  55. UA_StatusCode retval = UA_String_copy(&name, &server->namespaces[server->namespacesSize]);
  56. if(retval != UA_STATUSCODE_GOOD)
  57. return 0;
  58. ++server->namespacesSize;
  59. return (UA_UInt16)(server->namespacesSize - 1);
  60. }
  61. UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
  62. /* Override const attribute to get string (dirty hack) */
  63. const UA_String nameString = {.length = strlen(name),
  64. .data = (UA_Byte*)(uintptr_t)name};
  65. return addNamespace(server, nameString);
  66. }
  67. #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
  68. static void UA_ExternalNamespace_init(UA_ExternalNamespace *ens) {
  69. ens->index = 0;
  70. UA_String_init(&ens->url);
  71. }
  72. static void UA_ExternalNamespace_deleteMembers(UA_ExternalNamespace *ens) {
  73. UA_String_deleteMembers(&ens->url);
  74. ens->externalNodeStore.destroy(ens->externalNodeStore.ensHandle);
  75. }
  76. static void UA_Server_deleteExternalNamespaces(UA_Server *server) {
  77. for(UA_UInt32 i = 0; i < server->externalNamespacesSize; ++i)
  78. UA_ExternalNamespace_deleteMembers(&server->externalNamespaces[i]);
  79. if(server->externalNamespacesSize > 0) {
  80. UA_free(server->externalNamespaces);
  81. server->externalNamespaces = NULL;
  82. server->externalNamespacesSize = 0;
  83. }
  84. }
  85. UA_StatusCode UA_EXPORT
  86. UA_Server_addExternalNamespace(UA_Server *server, const UA_String *url,
  87. UA_ExternalNodeStore *nodeStore,
  88. UA_UInt16 *assignedNamespaceIndex) {
  89. if(!nodeStore)
  90. return UA_STATUSCODE_BADARGUMENTSMISSING;
  91. size_t size = server->externalNamespacesSize;
  92. server->externalNamespaces =
  93. UA_realloc(server->externalNamespaces, sizeof(UA_ExternalNamespace) * (size + 1));
  94. server->externalNamespaces[size].externalNodeStore = *nodeStore;
  95. server->externalNamespaces[size].index = (UA_UInt16)server->namespacesSize;
  96. *assignedNamespaceIndex = (UA_UInt16)server->namespacesSize;
  97. UA_String_copy(url, &server->externalNamespaces[size].url);
  98. ++server->externalNamespacesSize;
  99. return UA_STATUSCODE_GOOD;
  100. }
  101. #endif /* UA_ENABLE_EXTERNAL_NAMESPACES*/
  102. UA_StatusCode
  103. UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
  104. UA_NodeIteratorCallback callback, void *handle) {
  105. UA_RCU_LOCK();
  106. const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId);
  107. if(!parent) {
  108. UA_RCU_UNLOCK();
  109. return UA_STATUSCODE_BADNODEIDINVALID;
  110. }
  111. /* TODO: We need to do an ugly copy of the references array since users may
  112. * delete references from within the callback. In single-threaded mode this
  113. * changes the same node we point at here. In multi-threaded mode, this
  114. * creates a new copy as nodes are truly immutable. */
  115. UA_ReferenceNode *refs = NULL;
  116. size_t refssize = parent->referencesSize;
  117. UA_StatusCode retval = UA_Array_copy(parent->references, parent->referencesSize,
  118. (void**)&refs, &UA_TYPES[UA_TYPES_REFERENCENODE]);
  119. if(retval != UA_STATUSCODE_GOOD) {
  120. UA_RCU_UNLOCK();
  121. return retval;
  122. }
  123. for(size_t i = parent->referencesSize; i > 0; --i) {
  124. UA_ReferenceNode *ref = &refs[i-1];
  125. retval |= callback(ref->targetId.nodeId, ref->isInverse,
  126. ref->referenceTypeId, handle);
  127. }
  128. UA_RCU_UNLOCK();
  129. UA_Array_delete(refs, refssize, &UA_TYPES[UA_TYPES_REFERENCENODE]);
  130. return retval;
  131. }
  132. static UA_AddNodesResult
  133. addNodeInternal(UA_Server *server, UA_Node *node, const UA_NodeId parentNodeId,
  134. const UA_NodeId referenceTypeId) {
  135. UA_AddNodesResult res;
  136. UA_AddNodesResult_init(&res);
  137. UA_RCU_LOCK();
  138. res.statusCode = Service_AddNodes_existing(server, &adminSession, node, &parentNodeId,
  139. &referenceTypeId, &UA_NODEID_NULL,
  140. NULL, &res.addedNodeId);
  141. UA_RCU_UNLOCK();
  142. return res;
  143. }
  144. static UA_AddNodesResult
  145. addNodeInternalWithType(UA_Server *server, UA_Node *node, const UA_NodeId parentNodeId,
  146. const UA_NodeId referenceTypeId, const UA_NodeId typeIdentifier) {
  147. UA_AddNodesResult res;
  148. UA_AddNodesResult_init(&res);
  149. UA_RCU_LOCK();
  150. res.statusCode = Service_AddNodes_existing(server, &adminSession, node, &parentNodeId,
  151. &referenceTypeId, &typeIdentifier,
  152. NULL, &res.addedNodeId);
  153. UA_RCU_UNLOCK();
  154. return res;
  155. }
  156. // delete any children of an instance without touching the object itself
  157. static void
  158. deleteInstanceChildren(UA_Server *server, UA_NodeId *objectNodeId) {
  159. /* Browse for children */
  160. UA_BrowseDescription bDes;
  161. UA_BrowseDescription_init(&bDes);
  162. bDes.nodeId = *objectNodeId;
  163. bDes.browseDirection = UA_BROWSEDIRECTION_FORWARD;
  164. bDes.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
  165. bDes.resultMask = UA_BROWSERESULTMASK_ISFORWARD | UA_BROWSERESULTMASK_NODECLASS | UA_BROWSERESULTMASK_REFERENCETYPEINFO;
  166. UA_BrowseResult bRes = UA_Server_browse(server, 0, &bDes);
  167. /* Delete Children */
  168. for(size_t i=0; i<bRes.referencesSize; ++i) {
  169. UA_ReferenceDescription *rd = &bRes.references[i];
  170. if((rd->nodeClass == UA_NODECLASS_OBJECT || rd->nodeClass == UA_NODECLASS_VARIABLE)) {
  171. UA_Server_deleteNode(server, rd->nodeId.nodeId, true);
  172. } else if (rd->nodeClass == UA_NODECLASS_METHOD) {
  173. UA_Server_deleteReference(server, *objectNodeId, rd->referenceTypeId,
  174. true, rd->nodeId, true);
  175. }
  176. }
  177. UA_BrowseResult_deleteMembers(&bRes);
  178. }
  179. /**********/
  180. /* Server */
  181. /**********/
  182. /* The server needs to be stopped before it can be deleted */
  183. void UA_Server_delete(UA_Server *server) {
  184. // Delete the timed work
  185. UA_Server_deleteAllRepeatedJobs(server);
  186. // Delete all internal data
  187. UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
  188. UA_SessionManager_deleteMembers(&server->sessionManager);
  189. UA_RCU_LOCK();
  190. UA_NodeStore_delete(server->nodestore);
  191. UA_RCU_UNLOCK();
  192. #ifdef UA_ENABLE_EXTERNAL_NAMESPACES
  193. UA_Server_deleteExternalNamespaces(server);
  194. #endif
  195. UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
  196. UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize,
  197. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  198. #ifdef UA_ENABLE_MULTITHREADING
  199. pthread_cond_destroy(&server->dispatchQueue_condition);
  200. pthread_mutex_destroy(&server->dispatchQueue_mutex);
  201. #endif
  202. UA_free(server);
  203. }
  204. /* Recurring cleanup. Removing unused and timed-out channels and sessions */
  205. static void UA_Server_cleanup(UA_Server *server, void *_) {
  206. UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
  207. UA_SessionManager_cleanupTimedOut(&server->sessionManager, nowMonotonic);
  208. UA_SecureChannelManager_cleanupTimedOut(&server->secureChannelManager, nowMonotonic);
  209. }
  210. static UA_StatusCode
  211. readStatus(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp,
  212. const UA_NumericRange *range, UA_DataValue *value) {
  213. if(range) {
  214. value->hasStatus = true;
  215. value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
  216. return UA_STATUSCODE_GOOD;
  217. }
  218. UA_Server *server = (UA_Server*)handle;
  219. UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
  220. status->startTime = server->startTime;
  221. status->currentTime = UA_DateTime_now();
  222. status->state = UA_SERVERSTATE_RUNNING;
  223. status->secondsTillShutdown = 0;
  224. UA_BuildInfo_copy(&server->config.buildInfo, &status->buildInfo);
  225. value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
  226. value->value.arrayLength = 0;
  227. value->value.data = status;
  228. value->value.arrayDimensionsSize = 0;
  229. value->value.arrayDimensions = NULL;
  230. value->hasValue = true;
  231. if(sourceTimeStamp) {
  232. value->hasSourceTimestamp = true;
  233. value->sourceTimestamp = UA_DateTime_now();
  234. }
  235. return UA_STATUSCODE_GOOD;
  236. }
  237. /** TODO: rework the code duplication in the getter methods **/
  238. static UA_StatusCode
  239. readServiceLevel(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp,
  240. const UA_NumericRange *range, UA_DataValue *value) {
  241. if(range) {
  242. value->hasStatus = true;
  243. value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
  244. return UA_STATUSCODE_GOOD;
  245. }
  246. value->value.type = &UA_TYPES[UA_TYPES_BYTE];
  247. value->value.arrayLength = 0;
  248. UA_Byte *byte = UA_Byte_new();
  249. *byte = 255;
  250. value->value.data = byte;
  251. value->value.arrayDimensionsSize = 0;
  252. value->value.arrayDimensions = NULL;
  253. value->hasValue = true;
  254. if(sourceTimeStamp) {
  255. value->hasSourceTimestamp = true;
  256. value->sourceTimestamp = UA_DateTime_now();
  257. }
  258. return UA_STATUSCODE_GOOD;
  259. }
  260. /** TODO: rework the code duplication in the getter methods **/
  261. static UA_StatusCode
  262. readAuditing(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp,
  263. const UA_NumericRange *range, UA_DataValue *value) {
  264. if(range) {
  265. value->hasStatus = true;
  266. value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
  267. return UA_STATUSCODE_GOOD;
  268. }
  269. value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
  270. value->value.arrayLength = 0;
  271. UA_Boolean *boolean = UA_Boolean_new();
  272. *boolean = false;
  273. value->value.data = boolean;
  274. value->value.arrayDimensionsSize = 0;
  275. value->value.arrayDimensions = NULL;
  276. value->hasValue = true;
  277. if(sourceTimeStamp) {
  278. value->hasSourceTimestamp = true;
  279. value->sourceTimestamp = UA_DateTime_now();
  280. }
  281. return UA_STATUSCODE_GOOD;
  282. }
  283. static UA_StatusCode
  284. readNamespaces(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimestamp,
  285. const UA_NumericRange *range, UA_DataValue *value) {
  286. if(range) {
  287. value->hasStatus = true;
  288. value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
  289. return UA_STATUSCODE_GOOD;
  290. }
  291. UA_Server *server = (UA_Server*)handle;
  292. UA_StatusCode retval;
  293. retval = UA_Variant_setArrayCopy(&value->value, server->namespaces,
  294. server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
  295. if(retval != UA_STATUSCODE_GOOD)
  296. return retval;
  297. value->hasValue = true;
  298. if(sourceTimestamp) {
  299. value->hasSourceTimestamp = true;
  300. value->sourceTimestamp = UA_DateTime_now();
  301. }
  302. return UA_STATUSCODE_GOOD;
  303. }
  304. static UA_StatusCode
  305. writeNamespaces(void *handle, const UA_NodeId nodeid, const UA_Variant *data,
  306. const UA_NumericRange *range) {
  307. UA_Server *server = (UA_Server*)handle;
  308. /* Check the data type */
  309. if(data->type != &UA_TYPES[UA_TYPES_STRING])
  310. return UA_STATUSCODE_BADTYPEMISMATCH;
  311. /* Check that the variant is not empty */
  312. if(!data->data)
  313. return UA_STATUSCODE_BADTYPEMISMATCH;
  314. /* TODO: Writing with a range is not implemented */
  315. if(range)
  316. return UA_STATUSCODE_BADINTERNALERROR;
  317. UA_String *newNamespaces = data->data;
  318. size_t newNamespacesSize = data->arrayLength;
  319. /* Test if we append to the existing namespaces */
  320. if(newNamespacesSize <= server->namespacesSize)
  321. return UA_STATUSCODE_BADTYPEMISMATCH;
  322. /* Test if the existing namespaces are unchanged */
  323. for(size_t i = 0; i < server->namespacesSize; ++i) {
  324. if(!UA_String_equal(&server->namespaces[i], &newNamespaces[i]))
  325. return UA_STATUSCODE_BADINTERNALERROR;
  326. }
  327. /* Add namespaces */
  328. for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i)
  329. addNamespace(server, newNamespaces[i]);
  330. return UA_STATUSCODE_GOOD;
  331. }
  332. static UA_StatusCode
  333. readCurrentTime(void *handle, const UA_NodeId nodeid, UA_Boolean sourceTimeStamp,
  334. const UA_NumericRange *range, UA_DataValue *value) {
  335. if(range) {
  336. value->hasStatus = true;
  337. value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
  338. return UA_STATUSCODE_GOOD;
  339. }
  340. UA_DateTime currentTime = UA_DateTime_now();
  341. UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &currentTime,
  342. &UA_TYPES[UA_TYPES_DATETIME]);
  343. if(retval != UA_STATUSCODE_GOOD)
  344. return retval;
  345. value->hasValue = true;
  346. if(sourceTimeStamp) {
  347. value->hasSourceTimestamp = true;
  348. value->sourceTimestamp = currentTime;
  349. }
  350. return UA_STATUSCODE_GOOD;
  351. }
  352. static void copyNames(UA_Node *node, char *name) {
  353. node->browseName = UA_QUALIFIEDNAME_ALLOC(0, name);
  354. node->displayName = UA_LOCALIZEDTEXT_ALLOC("en_US", name);
  355. node->description = UA_LOCALIZEDTEXT_ALLOC("en_US", name);
  356. }
  357. static void
  358. addDataTypeNode(UA_Server *server, char* name, UA_UInt32 datatypeid,
  359. UA_Boolean isAbstract, UA_UInt32 parent) {
  360. UA_DataTypeNode *datatype = UA_NodeStore_newDataTypeNode();
  361. copyNames((UA_Node*)datatype, name);
  362. datatype->nodeId.identifier.numeric = datatypeid;
  363. datatype->isAbstract = isAbstract;
  364. addNodeInternal(server, (UA_Node*)datatype,
  365. UA_NODEID_NUMERIC(0, parent), nodeIdHasSubType);
  366. }
  367. static void
  368. addObjectTypeNode(UA_Server *server, char* name, UA_UInt32 objecttypeid,
  369. UA_UInt32 parent, UA_UInt32 parentreference) {
  370. UA_ObjectTypeNode *objecttype = UA_NodeStore_newObjectTypeNode();
  371. copyNames((UA_Node*)objecttype, name);
  372. objecttype->nodeId.identifier.numeric = objecttypeid;
  373. addNodeInternal(server, (UA_Node*)objecttype, UA_NODEID_NUMERIC(0, parent),
  374. UA_NODEID_NUMERIC(0, parentreference));
  375. }
  376. static UA_VariableTypeNode*
  377. createVariableTypeNode(UA_Server *server, char* name, UA_UInt32 variabletypeid,
  378. UA_Boolean abstract) {
  379. UA_VariableTypeNode *variabletype = UA_NodeStore_newVariableTypeNode();
  380. copyNames((UA_Node*)variabletype, name);
  381. variabletype->nodeId.identifier.numeric = variabletypeid;
  382. variabletype->isAbstract = abstract;
  383. return variabletype;
  384. }
  385. #if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
  386. static UA_StatusCode
  387. GetMonitoredItems(void *handle, const UA_NodeId objectId, size_t inputSize,
  388. const UA_Variant *input, size_t outputSize, UA_Variant *output) {
  389. UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
  390. UA_Session* session = methodCallSession;
  391. UA_Subscription* subscription = UA_Session_getSubscriptionByID(session, subscriptionId);
  392. if(!subscription)
  393. return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
  394. UA_UInt32 sizeOfOutput = 0;
  395. UA_MonitoredItem* monitoredItem;
  396. LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
  397. ++sizeOfOutput;
  398. }
  399. if(sizeOfOutput==0)
  400. return UA_STATUSCODE_GOOD;
  401. UA_UInt32* clientHandles = UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
  402. UA_UInt32* serverHandles = UA_Array_new(sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
  403. UA_UInt32 i = 0;
  404. LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
  405. clientHandles[i] = monitoredItem->clientHandle;
  406. serverHandles[i] = monitoredItem->itemId;
  407. ++i;
  408. }
  409. UA_Variant_setArray(&output[0], clientHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
  410. UA_Variant_setArray(&output[1], serverHandles, sizeOfOutput, &UA_TYPES[UA_TYPES_UINT32]);
  411. return UA_STATUSCODE_GOOD;
  412. }
  413. #endif
  414. UA_Server * UA_Server_new(const UA_ServerConfig config) {
  415. UA_Server *server = UA_calloc(1, sizeof(UA_Server));
  416. if(!server)
  417. return NULL;
  418. server->config = config;
  419. server->nodestore = UA_NodeStore_new();
  420. LIST_INIT(&server->repeatedJobs);
  421. #ifdef UA_ENABLE_MULTITHREADING
  422. rcu_init();
  423. cds_wfcq_init(&server->dispatchQueue_head, &server->dispatchQueue_tail);
  424. cds_lfs_init(&server->mainLoopJobs);
  425. #else
  426. SLIST_INIT(&server->delayedCallbacks);
  427. #endif
  428. #ifndef UA_ENABLE_DETERMINISTIC_RNG
  429. UA_random_seed((UA_UInt64)UA_DateTime_now());
  430. #endif
  431. /* ns0 and ns1 */
  432. server->namespaces = UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
  433. server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
  434. UA_String_copy(&server->config.applicationDescription.applicationUri, &server->namespaces[1]);
  435. server->namespacesSize = 2;
  436. /* Create endpoints w/o endpointurl. It is added from the networklayers at startup */
  437. server->endpointDescriptions = UA_Array_new(server->config.networkLayersSize,
  438. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  439. server->endpointDescriptionsSize = server->config.networkLayersSize;
  440. for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
  441. UA_EndpointDescription *endpoint = &server->endpointDescriptions[i];
  442. endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
  443. endpoint->securityPolicyUri =
  444. UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  445. endpoint->transportProfileUri =
  446. UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
  447. size_t policies = 0;
  448. if(server->config.enableAnonymousLogin)
  449. ++policies;
  450. if(server->config.enableUsernamePasswordLogin)
  451. ++policies;
  452. endpoint->userIdentityTokensSize = policies;
  453. endpoint->userIdentityTokens = UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  454. size_t currentIndex = 0;
  455. if(server->config.enableAnonymousLogin) {
  456. UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
  457. endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
  458. endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
  459. ++currentIndex;
  460. }
  461. if(server->config.enableUsernamePasswordLogin) {
  462. UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
  463. endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_USERNAME;
  464. endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
  465. }
  466. /* The standard says "the HostName specified in the Server Certificate is the
  467. same as the HostName contained in the endpointUrl provided in the
  468. EndpointDescription */
  469. UA_String_copy(&server->config.serverCertificate, &endpoint->serverCertificate);
  470. UA_ApplicationDescription_copy(&server->config.applicationDescription, &endpoint->server);
  471. /* copy the discovery url only once the networlayer has been started */
  472. // UA_String_copy(&server->config.networkLayers[i].discoveryUrl, &endpoint->endpointUrl);
  473. }
  474. UA_SecureChannelManager_init(&server->secureChannelManager, server);
  475. UA_SessionManager_init(&server->sessionManager, server);
  476. UA_Job cleanup = {.type = UA_JOBTYPE_METHODCALL,
  477. .job.methodCall = {.method = UA_Server_cleanup, .data = NULL} };
  478. UA_Server_addRepeatedJob(server, cleanup, 10000, NULL);
  479. server->startTime = UA_DateTime_now();
  480. #ifndef UA_ENABLE_GENERATE_NAMESPACE0
  481. /*********************************/
  482. /* Bootstrap reference hierarchy */
  483. /*********************************/
  484. UA_ReferenceTypeNode *references = UA_NodeStore_newReferenceTypeNode();
  485. copyNames((UA_Node*)references, "References");
  486. references->nodeId.identifier.numeric = UA_NS0ID_REFERENCES;
  487. references->isAbstract = true;
  488. references->symmetric = true;
  489. references->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "References");
  490. UA_ReferenceTypeNode *hassubtype = UA_NodeStore_newReferenceTypeNode();
  491. copyNames((UA_Node*)hassubtype, "HasSubtype");
  492. hassubtype->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "HasSupertype");
  493. hassubtype->nodeId.identifier.numeric = UA_NS0ID_HASSUBTYPE;
  494. hassubtype->isAbstract = false;
  495. hassubtype->symmetric = false;
  496. UA_RCU_LOCK();
  497. UA_NodeStore_insert(server->nodestore, (UA_Node*)references);
  498. UA_NodeStore_insert(server->nodestore, (UA_Node*)hassubtype);
  499. UA_RCU_UNLOCK();
  500. UA_ReferenceTypeNode *hierarchicalreferences = UA_NodeStore_newReferenceTypeNode();
  501. copyNames((UA_Node*)hierarchicalreferences, "HierarchicalReferences");
  502. hierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_HIERARCHICALREFERENCES;
  503. hierarchicalreferences->isAbstract = true;
  504. hierarchicalreferences->symmetric = false;
  505. addNodeInternal(server, (UA_Node*)hierarchicalreferences,
  506. UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
  507. UA_ReferenceTypeNode *nonhierarchicalreferences = UA_NodeStore_newReferenceTypeNode();
  508. copyNames((UA_Node*)nonhierarchicalreferences, "NonHierarchicalReferences");
  509. nonhierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES;
  510. nonhierarchicalreferences->isAbstract = true;
  511. nonhierarchicalreferences->symmetric = false;
  512. addNodeInternal(server, (UA_Node*)nonhierarchicalreferences,
  513. UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCES), nodeIdHasSubType);
  514. UA_ReferenceTypeNode *haschild = UA_NodeStore_newReferenceTypeNode();
  515. copyNames((UA_Node*)haschild, "HasChild");
  516. haschild->nodeId.identifier.numeric = UA_NS0ID_HASCHILD;
  517. haschild->isAbstract = false;
  518. haschild->symmetric = false;
  519. addNodeInternal(server, (UA_Node*)haschild,
  520. UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
  521. UA_ReferenceTypeNode *organizes = UA_NodeStore_newReferenceTypeNode();
  522. copyNames((UA_Node*)organizes, "Organizes");
  523. organizes->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OrganizedBy");
  524. organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
  525. organizes->isAbstract = false;
  526. organizes->symmetric = false;
  527. addNodeInternal(server, (UA_Node*)organizes,
  528. UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
  529. UA_ReferenceTypeNode *haseventsource = UA_NodeStore_newReferenceTypeNode();
  530. copyNames((UA_Node*)haseventsource, "HasEventSource");
  531. haseventsource->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "EventSourceOf");
  532. haseventsource->nodeId.identifier.numeric = UA_NS0ID_HASEVENTSOURCE;
  533. haseventsource->isAbstract = false;
  534. haseventsource->symmetric = false;
  535. addNodeInternal(server, (UA_Node*)haseventsource,
  536. UA_NODEID_NUMERIC(0, UA_NS0ID_HIERARCHICALREFERENCES), nodeIdHasSubType);
  537. UA_ReferenceTypeNode *hasmodellingrule = UA_NodeStore_newReferenceTypeNode();
  538. copyNames((UA_Node*)hasmodellingrule, "HasModellingRule");
  539. hasmodellingrule->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ModellingRuleOf");
  540. hasmodellingrule->nodeId.identifier.numeric = UA_NS0ID_HASMODELLINGRULE;
  541. hasmodellingrule->isAbstract = false;
  542. hasmodellingrule->symmetric = false;
  543. addNodeInternal(server, (UA_Node*)hasmodellingrule, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  544. UA_ReferenceTypeNode *hasencoding = UA_NodeStore_newReferenceTypeNode();
  545. copyNames((UA_Node*)hasencoding, "HasEncoding");
  546. hasencoding->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "EncodingOf");
  547. hasencoding->nodeId.identifier.numeric = UA_NS0ID_HASENCODING;
  548. hasencoding->isAbstract = false;
  549. hasencoding->symmetric = false;
  550. addNodeInternal(server, (UA_Node*)hasencoding, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  551. UA_ReferenceTypeNode *hasdescription = UA_NodeStore_newReferenceTypeNode();
  552. copyNames((UA_Node*)hasdescription, "HasDescription");
  553. hasdescription->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "DescriptionOf");
  554. hasdescription->nodeId.identifier.numeric = UA_NS0ID_HASDESCRIPTION;
  555. hasdescription->isAbstract = false;
  556. hasdescription->symmetric = false;
  557. addNodeInternal(server, (UA_Node*)hasdescription, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  558. UA_ReferenceTypeNode *hastypedefinition = UA_NodeStore_newReferenceTypeNode();
  559. copyNames((UA_Node*)hastypedefinition, "HasTypeDefinition");
  560. hastypedefinition->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "TypeDefinitionOf");
  561. hastypedefinition->nodeId.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION;
  562. hastypedefinition->isAbstract = false;
  563. hastypedefinition->symmetric = false;
  564. addNodeInternal(server, (UA_Node*)hastypedefinition, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  565. UA_ReferenceTypeNode *generatesevent = UA_NodeStore_newReferenceTypeNode();
  566. copyNames((UA_Node*)generatesevent, "GeneratesEvent");
  567. generatesevent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "GeneratedBy");
  568. generatesevent->nodeId.identifier.numeric = UA_NS0ID_GENERATESEVENT;
  569. generatesevent->isAbstract = false;
  570. generatesevent->symmetric = false;
  571. addNodeInternal(server, (UA_Node*)generatesevent, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  572. UA_ReferenceTypeNode *aggregates = UA_NodeStore_newReferenceTypeNode();
  573. copyNames((UA_Node*)aggregates, "Aggregates");
  574. aggregates->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "AggregatedBy");
  575. aggregates->nodeId.identifier.numeric = UA_NS0ID_AGGREGATES;
  576. aggregates->isAbstract = false;
  577. aggregates->symmetric = false;
  578. addNodeInternal(server, (UA_Node*)aggregates, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType);
  579. /* complete bootstrap of hassubtype */
  580. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCHILD), nodeIdHasSubType,
  581. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE), true);
  582. UA_ReferenceTypeNode *hasproperty = UA_NodeStore_newReferenceTypeNode();
  583. copyNames((UA_Node*)hasproperty, "HasProperty");
  584. hasproperty->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "PropertyOf");
  585. hasproperty->nodeId.identifier.numeric = UA_NS0ID_HASPROPERTY;
  586. hasproperty->isAbstract = false;
  587. hasproperty->symmetric = false;
  588. addNodeInternal(server, (UA_Node*)hasproperty,
  589. UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
  590. UA_ReferenceTypeNode *hascomponent = UA_NodeStore_newReferenceTypeNode();
  591. copyNames((UA_Node*)hascomponent, "HasComponent");
  592. hascomponent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ComponentOf");
  593. hascomponent->nodeId.identifier.numeric = UA_NS0ID_HASCOMPONENT;
  594. hascomponent->isAbstract = false;
  595. hascomponent->symmetric = false;
  596. addNodeInternal(server, (UA_Node*)hascomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
  597. UA_ReferenceTypeNode *hasnotifier = UA_NodeStore_newReferenceTypeNode();
  598. copyNames((UA_Node*)hasnotifier, "HasNotifier");
  599. hasnotifier->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "NotifierOf");
  600. hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
  601. hasnotifier->isAbstract = false;
  602. hasnotifier->symmetric = false;
  603. addNodeInternal(server, (UA_Node*)hasnotifier, UA_NODEID_NUMERIC(0, UA_NS0ID_HASEVENTSOURCE), nodeIdHasSubType);
  604. UA_ReferenceTypeNode *hasorderedcomponent = UA_NodeStore_newReferenceTypeNode();
  605. copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
  606. hasorderedcomponent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "OrderedComponentOf");
  607. hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
  608. hasorderedcomponent->isAbstract = false;
  609. hasorderedcomponent->symmetric = false;
  610. addNodeInternal(server, (UA_Node*)hasorderedcomponent, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), nodeIdHasSubType);
  611. UA_ReferenceTypeNode *hasmodelparent = UA_NodeStore_newReferenceTypeNode();
  612. copyNames((UA_Node*)hasmodelparent, "HasModelParent");
  613. hasmodelparent->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ModelParentOf");
  614. hasmodelparent->nodeId.identifier.numeric = UA_NS0ID_HASMODELPARENT;
  615. hasmodelparent->isAbstract = false;
  616. hasmodelparent->symmetric = false;
  617. addNodeInternal(server, (UA_Node*)hasmodelparent, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  618. UA_ReferenceTypeNode *fromstate = UA_NodeStore_newReferenceTypeNode();
  619. copyNames((UA_Node*)fromstate, "FromState");
  620. fromstate->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "ToTransition");
  621. fromstate->nodeId.identifier.numeric = UA_NS0ID_FROMSTATE;
  622. fromstate->isAbstract = false;
  623. fromstate->symmetric = false;
  624. addNodeInternal(server, (UA_Node*)fromstate, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  625. UA_ReferenceTypeNode *tostate = UA_NodeStore_newReferenceTypeNode();
  626. copyNames((UA_Node*)tostate, "ToState");
  627. tostate->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "FromTransition");
  628. tostate->nodeId.identifier.numeric = UA_NS0ID_TOSTATE;
  629. tostate->isAbstract = false;
  630. tostate->symmetric = false;
  631. addNodeInternal(server, (UA_Node*)tostate, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  632. UA_ReferenceTypeNode *hascause = UA_NodeStore_newReferenceTypeNode();
  633. copyNames((UA_Node*)hascause, "HasCause");
  634. hascause->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeCausedBy");
  635. hascause->nodeId.identifier.numeric = UA_NS0ID_HASCAUSE;
  636. hascause->isAbstract = false;
  637. hascause->symmetric = false;
  638. addNodeInternal(server, (UA_Node*)hascause, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  639. UA_ReferenceTypeNode *haseffect = UA_NodeStore_newReferenceTypeNode();
  640. copyNames((UA_Node*)haseffect, "HasEffect");
  641. haseffect->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "MayBeEffectedBy");
  642. haseffect->nodeId.identifier.numeric = UA_NS0ID_HASEFFECT;
  643. haseffect->isAbstract = false;
  644. haseffect->symmetric = false;
  645. addNodeInternal(server, (UA_Node*)haseffect, nodeIdNonHierarchicalReferences, nodeIdHasSubType);
  646. UA_ReferenceTypeNode *hashistoricalconfiguration = UA_NodeStore_newReferenceTypeNode();
  647. copyNames((UA_Node*)hashistoricalconfiguration, "HasHistoricalConfiguration");
  648. hashistoricalconfiguration->inverseName = UA_LOCALIZEDTEXT_ALLOC("en_US", "HistoricalConfigurationOf");
  649. hashistoricalconfiguration->nodeId.identifier.numeric = UA_NS0ID_HASHISTORICALCONFIGURATION;
  650. hashistoricalconfiguration->isAbstract = false;
  651. hashistoricalconfiguration->symmetric = false;
  652. addNodeInternal(server, (UA_Node*)hashistoricalconfiguration, UA_NODEID_NUMERIC(0, UA_NS0ID_AGGREGATES), nodeIdHasSubType);
  653. /**************/
  654. /* Data Types */
  655. /**************/
  656. UA_DataTypeNode *basedatatype = UA_NodeStore_newDataTypeNode();
  657. copyNames((UA_Node*)basedatatype, "BaseDataType");
  658. basedatatype->nodeId.identifier.numeric = UA_NS0ID_BASEDATATYPE;
  659. basedatatype->isAbstract = true;
  660. UA_RCU_LOCK();
  661. UA_NodeStore_insert(server->nodestore, (UA_Node*)basedatatype);
  662. UA_RCU_UNLOCK();
  663. addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, false, UA_NS0ID_BASEDATATYPE);
  664. addDataTypeNode(server, "Number", UA_NS0ID_NUMBER, true, UA_NS0ID_BASEDATATYPE);
  665. addDataTypeNode(server, "Float", UA_NS0ID_FLOAT, false, UA_NS0ID_NUMBER);
  666. addDataTypeNode(server, "Double", UA_NS0ID_DOUBLE, false, UA_NS0ID_NUMBER);
  667. addDataTypeNode(server, "Integer", UA_NS0ID_INTEGER, true, UA_NS0ID_NUMBER);
  668. addDataTypeNode(server, "SByte", UA_NS0ID_SBYTE, false, UA_NS0ID_INTEGER);
  669. addDataTypeNode(server, "Int16", UA_NS0ID_INT16, false, UA_NS0ID_INTEGER);
  670. addDataTypeNode(server, "Int32", UA_NS0ID_INT32, false, UA_NS0ID_INTEGER);
  671. addDataTypeNode(server, "Int64", UA_NS0ID_INT64, false, UA_NS0ID_INTEGER);
  672. addDataTypeNode(server, "UInteger", UA_NS0ID_UINTEGER, true, UA_NS0ID_INTEGER);
  673. addDataTypeNode(server, "Byte", UA_NS0ID_BYTE, false, UA_NS0ID_UINTEGER);
  674. addDataTypeNode(server, "UInt16", UA_NS0ID_UINT16, false, UA_NS0ID_UINTEGER);
  675. addDataTypeNode(server, "UInt32", UA_NS0ID_UINT32, false, UA_NS0ID_UINTEGER);
  676. addDataTypeNode(server, "UInt64", UA_NS0ID_UINT64, false, UA_NS0ID_UINTEGER);
  677. addDataTypeNode(server, "String", UA_NS0ID_STRING, false, UA_NS0ID_BASEDATATYPE);
  678. addDataTypeNode(server, "DateTime", UA_NS0ID_DATETIME, false, UA_NS0ID_BASEDATATYPE);
  679. addDataTypeNode(server, "Guid", UA_NS0ID_GUID, false, UA_NS0ID_BASEDATATYPE);
  680. addDataTypeNode(server, "ByteString", UA_NS0ID_BYTESTRING, false, UA_NS0ID_BASEDATATYPE);
  681. addDataTypeNode(server, "XmlElement", UA_NS0ID_XMLELEMENT, false, UA_NS0ID_BASEDATATYPE);
  682. addDataTypeNode(server, "NodeId", UA_NS0ID_NODEID, false, UA_NS0ID_BASEDATATYPE);
  683. addDataTypeNode(server, "ExpandedNodeId", UA_NS0ID_EXPANDEDNODEID, false, UA_NS0ID_BASEDATATYPE);
  684. addDataTypeNode(server, "StatusCode", UA_NS0ID_STATUSCODE, false, UA_NS0ID_BASEDATATYPE);
  685. addDataTypeNode(server, "QualifiedName", UA_NS0ID_QUALIFIEDNAME, false, UA_NS0ID_BASEDATATYPE);
  686. addDataTypeNode(server, "LocalizedText", UA_NS0ID_LOCALIZEDTEXT, false, UA_NS0ID_BASEDATATYPE);
  687. addDataTypeNode(server, "Structure", UA_NS0ID_STRUCTURE, true, UA_NS0ID_BASEDATATYPE);
  688. addDataTypeNode(server, "ServerStatusDataType", UA_NS0ID_SERVERSTATUSDATATYPE, false, UA_NS0ID_STRUCTURE);
  689. addDataTypeNode(server, "BuildInfo", UA_NS0ID_BUILDINFO, false, UA_NS0ID_STRUCTURE);
  690. addDataTypeNode(server, "DataValue", UA_NS0ID_DATAVALUE, false, UA_NS0ID_BASEDATATYPE);
  691. addDataTypeNode(server, "DiagnosticInfo", UA_NS0ID_DIAGNOSTICINFO, false, UA_NS0ID_BASEDATATYPE);
  692. addDataTypeNode(server, "Enumeration", UA_NS0ID_ENUMERATION, true, UA_NS0ID_BASEDATATYPE);
  693. addDataTypeNode(server, "ServerState", UA_NS0ID_SERVERSTATE, false, UA_NS0ID_ENUMERATION);
  694. /*****************/
  695. /* VariableTypes */
  696. /*****************/
  697. UA_VariableTypeNode *basevartype =
  698. createVariableTypeNode(server, "BaseVariableType", UA_NS0ID_BASEVARIABLETYPE, true);
  699. basevartype->valueRank = -2;
  700. basevartype->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
  701. UA_RCU_LOCK();
  702. UA_NodeStore_insert(server->nodestore, (UA_Node*)basevartype);
  703. UA_RCU_UNLOCK();
  704. UA_VariableTypeNode *basedatavartype =
  705. createVariableTypeNode(server, "BaseDataVariableType", UA_NS0ID_BASEDATAVARIABLETYPE, false);
  706. basedatavartype->valueRank = -2;
  707. basedatavartype->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
  708. addNodeInternalWithType(server, (UA_Node*)basedatavartype,
  709. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE),
  710. nodeIdHasSubType, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE));
  711. UA_VariableTypeNode *propertytype =
  712. createVariableTypeNode(server, "PropertyType", UA_NS0ID_PROPERTYTYPE, false);
  713. propertytype->valueRank = -2;
  714. propertytype->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE);
  715. addNodeInternalWithType(server, (UA_Node*)propertytype,
  716. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE),
  717. nodeIdHasSubType, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE));
  718. UA_VariableTypeNode *buildinfotype =
  719. createVariableTypeNode(server, "BuildInfoType", UA_NS0ID_BUILDINFOTYPE, false);
  720. buildinfotype->valueRank = -1;
  721. buildinfotype->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_BUILDINFO);
  722. addNodeInternalWithType(server, (UA_Node*)buildinfotype,
  723. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
  724. nodeIdHasSubType, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  725. UA_VariableTypeNode *serverstatustype =
  726. createVariableTypeNode(server, "ServerStatusType", UA_NS0ID_SERVERSTATUSTYPE, false);
  727. serverstatustype->valueRank = -1;
  728. serverstatustype->dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERSTATUSDATATYPE);
  729. addNodeInternalWithType(server, (UA_Node*)serverstatustype,
  730. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
  731. nodeIdHasSubType, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  732. /**********************/
  733. /* Basic Object Types */
  734. /**********************/
  735. UA_ObjectTypeNode *baseobjtype = UA_NodeStore_newObjectTypeNode();
  736. copyNames((UA_Node*)baseobjtype, "BaseObjectType");
  737. baseobjtype->nodeId.identifier.numeric = UA_NS0ID_BASEOBJECTTYPE;
  738. UA_RCU_LOCK();
  739. UA_NodeStore_insert(server->nodestore, (UA_Node*)baseobjtype);
  740. UA_RCU_UNLOCK();
  741. addObjectTypeNode(server, "ModellingRuleType", UA_NS0ID_MODELLINGRULETYPE,
  742. UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
  743. addObjectTypeNode(server, "FolderType", UA_NS0ID_FOLDERTYPE,
  744. UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
  745. addObjectTypeNode(server, "ServerType", UA_NS0ID_SERVERTYPE,
  746. UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
  747. addObjectTypeNode(server, "ServerDiagnosticsType", UA_NS0ID_SERVERDIAGNOSTICSTYPE,
  748. UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
  749. addObjectTypeNode(server, "ServerCapatilitiesType", UA_NS0ID_SERVERCAPABILITIESTYPE,
  750. UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_HASSUBTYPE);
  751. /******************/
  752. /* Root and below */
  753. /******************/
  754. static const UA_NodeId nodeIdFolderType = {
  755. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  756. .identifier.numeric = UA_NS0ID_FOLDERTYPE};
  757. static const UA_NodeId nodeIdHasTypeDefinition = {
  758. .namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
  759. .identifier.numeric = UA_NS0ID_HASTYPEDEFINITION};
  760. UA_ObjectNode *root = UA_NodeStore_newObjectNode();
  761. copyNames((UA_Node*)root, "Root");
  762. root->nodeId.identifier.numeric = UA_NS0ID_ROOTFOLDER;
  763. UA_RCU_LOCK();
  764. UA_NodeStore_insert(server->nodestore, (UA_Node*)root);
  765. UA_RCU_UNLOCK();
  766. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER), nodeIdHasTypeDefinition,
  767. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE), true);
  768. UA_ObjectNode *objects = UA_NodeStore_newObjectNode();
  769. copyNames((UA_Node*)objects, "Objects");
  770. objects->nodeId.identifier.numeric = UA_NS0ID_OBJECTSFOLDER;
  771. addNodeInternalWithType(server, (UA_Node*)objects, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
  772. nodeIdOrganizes, nodeIdFolderType);
  773. UA_ObjectNode *types = UA_NodeStore_newObjectNode();
  774. copyNames((UA_Node*)types, "Types");
  775. types->nodeId.identifier.numeric = UA_NS0ID_TYPESFOLDER;
  776. addNodeInternalWithType(server, (UA_Node*)types, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
  777. nodeIdOrganizes, nodeIdFolderType);
  778. UA_ObjectNode *referencetypes = UA_NodeStore_newObjectNode();
  779. copyNames((UA_Node*)referencetypes, "ReferenceTypes");
  780. referencetypes->nodeId.identifier.numeric = UA_NS0ID_REFERENCETYPESFOLDER;
  781. addNodeInternalWithType(server, (UA_Node*)referencetypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
  782. nodeIdOrganizes, nodeIdFolderType);
  783. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_REFERENCETYPESFOLDER), nodeIdOrganizes,
  784. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_REFERENCES), true);
  785. UA_ObjectNode *datatypes = UA_NodeStore_newObjectNode();
  786. copyNames((UA_Node*)datatypes, "DataTypes");
  787. datatypes->nodeId.identifier.numeric = UA_NS0ID_DATATYPESFOLDER;
  788. addNodeInternalWithType(server, (UA_Node*)datatypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
  789. nodeIdOrganizes, nodeIdFolderType);
  790. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATATYPESFOLDER), nodeIdOrganizes,
  791. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEDATATYPE), true);
  792. UA_ObjectNode *variabletypes = UA_NodeStore_newObjectNode();
  793. copyNames((UA_Node*)variabletypes, "VariableTypes");
  794. variabletypes->nodeId.identifier.numeric = UA_NS0ID_VARIABLETYPESFOLDER;
  795. addNodeInternalWithType(server, (UA_Node*)variabletypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
  796. nodeIdOrganizes, nodeIdFolderType);
  797. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_VARIABLETYPESFOLDER), nodeIdOrganizes,
  798. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEVARIABLETYPE), true);
  799. UA_ObjectNode *objecttypes = UA_NodeStore_newObjectNode();
  800. copyNames((UA_Node*)objecttypes, "ObjectTypes");
  801. objecttypes->nodeId.identifier.numeric = UA_NS0ID_OBJECTTYPESFOLDER;
  802. addNodeInternalWithType(server, (UA_Node*)objecttypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
  803. nodeIdOrganizes, nodeIdFolderType);
  804. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTTYPESFOLDER), nodeIdOrganizes,
  805. UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), true);
  806. UA_ObjectNode *eventtypes = UA_NodeStore_newObjectNode();
  807. copyNames((UA_Node*)eventtypes, "EventTypes");
  808. eventtypes->nodeId.identifier.numeric = UA_NS0ID_EVENTTYPESFOLDER;
  809. addNodeInternalWithType(server, (UA_Node*)eventtypes, UA_NODEID_NUMERIC(0, UA_NS0ID_TYPESFOLDER),
  810. nodeIdOrganizes, nodeIdFolderType);
  811. UA_ObjectNode *views = UA_NodeStore_newObjectNode();
  812. copyNames((UA_Node*)views, "Views");
  813. views->nodeId.identifier.numeric = UA_NS0ID_VIEWSFOLDER;
  814. addNodeInternalWithType(server, (UA_Node*)views, UA_NODEID_NUMERIC(0, UA_NS0ID_ROOTFOLDER),
  815. nodeIdOrganizes, nodeIdFolderType);
  816. /*******************/
  817. /* Modelling Rules */
  818. /*******************/
  819. UA_ObjectNode *mandatory = UA_NodeStore_newObjectNode();
  820. copyNames((UA_Node*)mandatory, "Mandatory");
  821. mandatory->nodeId.identifier.numeric = UA_NS0ID_MODELLINGRULE_MANDATORY;
  822. addNodeInternalWithType(server, (UA_Node*)mandatory, UA_NODEID_NULL,
  823. UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULETYPE));
  824. UA_ObjectNode *optional = UA_NodeStore_newObjectNode();
  825. copyNames((UA_Node*)optional, "Optional");
  826. optional->nodeId.identifier.numeric = UA_NS0ID_MODELLINGRULE_OPTIONAL;
  827. addNodeInternalWithType(server, (UA_Node*)optional, UA_NODEID_NULL,
  828. UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULETYPE));
  829. #else
  830. /* load the generated namespace externally */
  831. ua_namespaceinit_generated(server);
  832. #endif
  833. /*********************/
  834. /* The Server Object */
  835. /*********************/
  836. /* Create our own server object */
  837. UA_ObjectNode *servernode = UA_NodeStore_newObjectNode();
  838. copyNames((UA_Node*)servernode, "Server");
  839. servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
  840. addNodeInternalWithType(server, (UA_Node*)servernode, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
  841. nodeIdOrganizes, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERTYPE));
  842. // If we are in an UA conformant namespace, the above function just created a full ServerType object.
  843. // Before readding every variable, delete whatever got instantiated.
  844. // here we can't reuse servernode->nodeId because it may be deleted in addNodeInternalWithType if the node could not be added
  845. UA_NodeId serverNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER);
  846. deleteInstanceChildren(server, &serverNodeId);
  847. UA_VariableNode *namespaceArray = UA_NodeStore_newVariableNode();
  848. copyNames((UA_Node*)namespaceArray, "NamespaceArray");
  849. namespaceArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_NAMESPACEARRAY;
  850. namespaceArray->valueSource = UA_VALUESOURCE_DATASOURCE;
  851. namespaceArray->value.dataSource = (UA_DataSource) {.handle = server, .read = readNamespaces,
  852. .write = writeNamespaces};
  853. namespaceArray->dataType = UA_TYPES[UA_TYPES_STRING].typeId;
  854. namespaceArray->valueRank = 1;
  855. namespaceArray->minimumSamplingInterval = 1.0;
  856. addNodeInternalWithType(server, (UA_Node*)namespaceArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  857. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  858. UA_VariableNode *serverArray = UA_NodeStore_newVariableNode();
  859. copyNames((UA_Node*)serverArray, "ServerArray");
  860. serverArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERARRAY;
  861. UA_Variant_setArrayCopy(&serverArray->value.data.value.value,
  862. &server->config.applicationDescription.applicationUri, 1,
  863. &UA_TYPES[UA_TYPES_STRING]);
  864. serverArray->value.data.value.hasValue = true;
  865. serverArray->valueRank = 1;
  866. serverArray->minimumSamplingInterval = 1.0;
  867. addNodeInternalWithType(server, (UA_Node*)serverArray, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  868. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  869. UA_ObjectNode *servercapablities = UA_NodeStore_newObjectNode();
  870. copyNames((UA_Node*)servercapablities, "ServerCapabilities");
  871. servercapablities->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES;
  872. addNodeInternalWithType(server, (UA_Node*)servercapablities, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  873. nodeIdHasComponent,
  874. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCAPABILITIESTYPE));
  875. UA_NodeId ServerCapabilitiesNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES);
  876. deleteInstanceChildren(server, &ServerCapabilitiesNodeId);
  877. UA_VariableNode *localeIdArray = UA_NodeStore_newVariableNode();
  878. copyNames((UA_Node*)localeIdArray, "LocaleIdArray");
  879. localeIdArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY;
  880. UA_String enLocale = UA_STRING("en");
  881. UA_Variant_setArrayCopy(&localeIdArray->value.data.value.value,
  882. &enLocale, 1, &UA_TYPES[UA_TYPES_STRING]);
  883. localeIdArray->value.data.value.hasValue = true;
  884. localeIdArray->valueRank = 1;
  885. localeIdArray->minimumSamplingInterval = 1.0;
  886. addNodeInternalWithType(server, (UA_Node*)localeIdArray,
  887. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  888. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  889. UA_VariableNode *maxBrowseContinuationPoints = UA_NodeStore_newVariableNode();
  890. copyNames((UA_Node*)maxBrowseContinuationPoints, "MaxBrowseContinuationPoints");
  891. maxBrowseContinuationPoints->nodeId.identifier.numeric =
  892. UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS;
  893. UA_Variant_setScalar(&maxBrowseContinuationPoints->value.data.value.value,
  894. UA_UInt16_new(), &UA_TYPES[UA_TYPES_UINT16]);
  895. maxBrowseContinuationPoints->value.data.value.hasValue = true;
  896. addNodeInternalWithType(server, (UA_Node*)maxBrowseContinuationPoints,
  897. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  898. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  899. /** ServerProfileArray **/
  900. #define MAX_PROFILEARRAY 16 //a *magic* limit to the number of supported profiles
  901. #define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING_ALLOC(x)
  902. UA_String profileArray[MAX_PROFILEARRAY];
  903. UA_UInt16 profileArraySize = 0;
  904. ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NanoEmbeddedDevice");
  905. #ifdef UA_ENABLE_SERVICESET_NODEMANAGEMENT
  906. ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
  907. #endif
  908. #ifdef UA_ENABLE_SERVICESET_METHOD
  909. ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
  910. #endif
  911. #ifdef UA_ENABLE_SUBSCRIPTIONS
  912. ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/EmbeddedDataChangeSubscription");
  913. #endif
  914. UA_VariableNode *serverProfileArray = UA_NodeStore_newVariableNode();
  915. copyNames((UA_Node*)serverProfileArray, "ServerProfileArray");
  916. serverProfileArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY;
  917. UA_Variant_setArray(&serverProfileArray->value.data.value.value,
  918. UA_Array_new(profileArraySize, &UA_TYPES[UA_TYPES_STRING]),
  919. profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
  920. for(UA_UInt16 i=0;i<profileArraySize;++i)
  921. ((UA_String *)serverProfileArray->value.data.value.value.data)[i] = profileArray[i];
  922. serverProfileArray->value.data.value.hasValue = true;
  923. serverProfileArray->valueRank = 1;
  924. serverProfileArray->minimumSamplingInterval = 1.0;
  925. addNodeInternalWithType(server, (UA_Node*)serverProfileArray,
  926. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  927. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  928. UA_VariableNode *softwareCertificates = UA_NodeStore_newVariableNode();
  929. copyNames((UA_Node*)softwareCertificates, "SoftwareCertificates");
  930. softwareCertificates->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_SOFTWARECERTIFICATES;
  931. softwareCertificates->dataType = UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE].typeId;
  932. addNodeInternalWithType(server, (UA_Node*)softwareCertificates,
  933. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  934. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  935. UA_VariableNode *maxQueryContinuationPoints = UA_NodeStore_newVariableNode();
  936. copyNames((UA_Node*)maxQueryContinuationPoints, "MaxQueryContinuationPoints");
  937. maxQueryContinuationPoints->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS;
  938. UA_Variant_setScalar(&maxQueryContinuationPoints->value.data.value.value,
  939. UA_UInt16_new(), &UA_TYPES[UA_TYPES_UINT16]);
  940. maxQueryContinuationPoints->value.data.value.hasValue = true;
  941. addNodeInternalWithType(server, (UA_Node*)maxQueryContinuationPoints,
  942. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  943. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  944. UA_VariableNode *maxHistoryContinuationPoints = UA_NodeStore_newVariableNode();
  945. copyNames((UA_Node*)maxHistoryContinuationPoints, "MaxHistoryContinuationPoints");
  946. maxHistoryContinuationPoints->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS;
  947. UA_Variant_setScalar(&maxHistoryContinuationPoints->value.data.value.value,
  948. UA_UInt16_new(), &UA_TYPES[UA_TYPES_UINT16]);
  949. maxHistoryContinuationPoints->value.data.value.hasValue = true;
  950. addNodeInternalWithType(server, (UA_Node*)maxHistoryContinuationPoints,
  951. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  952. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  953. UA_VariableNode *minSupportedSampleRate = UA_NodeStore_newVariableNode();
  954. copyNames((UA_Node*)minSupportedSampleRate, "MinSupportedSampleRate");
  955. minSupportedSampleRate->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE;
  956. UA_Variant_setScalar(&minSupportedSampleRate->value.data.value.value,
  957. UA_Double_new(), &UA_TYPES[UA_TYPES_DOUBLE]);
  958. minSupportedSampleRate->value.data.value.hasValue = true;
  959. addNodeInternalWithType(server, (UA_Node*)minSupportedSampleRate,
  960. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  961. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  962. UA_ObjectNode *modellingRules = UA_NodeStore_newObjectNode();
  963. copyNames((UA_Node*)modellingRules, "ModellingRules");
  964. modellingRules->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES;
  965. addNodeInternalWithType(server, (UA_Node*)modellingRules,
  966. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES), nodeIdHasProperty,
  967. UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
  968. UA_ObjectNode *aggregateFunctions = UA_NodeStore_newObjectNode();
  969. copyNames((UA_Node*)aggregateFunctions, "AggregateFunctions");
  970. aggregateFunctions->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERCAPABILITIES_AGGREGATEFUNCTIONS;
  971. addNodeInternalWithType(server, (UA_Node*)aggregateFunctions,
  972. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES),
  973. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
  974. UA_ObjectNode *serverdiagnostics = UA_NodeStore_newObjectNode();
  975. copyNames((UA_Node*)serverdiagnostics, "ServerDiagnostics");
  976. serverdiagnostics->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS;
  977. addNodeInternalWithType(server, (UA_Node*)serverdiagnostics,
  978. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  979. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERDIAGNOSTICSTYPE));
  980. UA_NodeId ServerDiagnosticsNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS);
  981. deleteInstanceChildren(server, &ServerDiagnosticsNodeId);
  982. UA_VariableNode *enabledFlag = UA_NodeStore_newVariableNode();
  983. copyNames((UA_Node*)enabledFlag, "EnabledFlag");
  984. enabledFlag->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG;
  985. UA_Variant_setScalar(&enabledFlag->value.data.value.value, UA_Boolean_new(),
  986. &UA_TYPES[UA_TYPES_BOOLEAN]);
  987. enabledFlag->value.data.value.hasValue = true;
  988. enabledFlag->valueRank = 1;
  989. enabledFlag->minimumSamplingInterval = 1.0;
  990. addNodeInternalWithType(server, (UA_Node*)enabledFlag,
  991. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS),
  992. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  993. UA_VariableNode *serverstatus = UA_NodeStore_newVariableNode();
  994. copyNames((UA_Node*)serverstatus, "ServerStatus");
  995. serverstatus->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS);
  996. serverstatus->valueSource = UA_VALUESOURCE_DATASOURCE;
  997. serverstatus->value.dataSource = (UA_DataSource) {.handle = server, .read = readStatus,
  998. .write = NULL};
  999. addNodeInternalWithType(server, (UA_Node*)serverstatus, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  1000. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1001. UA_VariableNode *starttime = UA_NodeStore_newVariableNode();
  1002. copyNames((UA_Node*)starttime, "StartTime");
  1003. starttime->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME);
  1004. UA_Variant_setScalarCopy(&starttime->value.data.value.value,
  1005. &server->startTime, &UA_TYPES[UA_TYPES_DATETIME]);
  1006. starttime->value.data.value.hasValue = true;
  1007. addNodeInternalWithType(server, (UA_Node*)starttime,
  1008. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1009. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1010. UA_VariableNode *currenttime = UA_NodeStore_newVariableNode();
  1011. copyNames((UA_Node*)currenttime, "CurrentTime");
  1012. currenttime->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
  1013. currenttime->valueSource = UA_VALUESOURCE_DATASOURCE;
  1014. currenttime->value.dataSource = (UA_DataSource) {.handle = NULL, .read = readCurrentTime,
  1015. .write = NULL};
  1016. addNodeInternalWithType(server, (UA_Node*)currenttime,
  1017. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1018. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1019. UA_VariableNode *state = UA_NodeStore_newVariableNode();
  1020. copyNames((UA_Node*)state, "State");
  1021. state->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERSTATUS_STATE;
  1022. UA_Variant_setScalar(&state->value.data.value.value, UA_ServerState_new(),
  1023. &UA_TYPES[UA_TYPES_SERVERSTATE]);
  1024. state->value.data.value.hasValue = true;
  1025. state->minimumSamplingInterval = 500.0f;
  1026. addNodeInternalWithType(server, (UA_Node*)state, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1027. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1028. UA_VariableNode *buildinfo = UA_NodeStore_newVariableNode();
  1029. copyNames((UA_Node*)buildinfo, "BuildInfo");
  1030. buildinfo->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO);
  1031. UA_Variant_setScalarCopy(&buildinfo->value.data.value.value,
  1032. &server->config.buildInfo, &UA_TYPES[UA_TYPES_BUILDINFO]);
  1033. buildinfo->value.data.value.hasValue = true;
  1034. addNodeInternalWithType(server, (UA_Node*)buildinfo,
  1035. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1036. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BUILDINFOTYPE));
  1037. UA_VariableNode *producturi = UA_NodeStore_newVariableNode();
  1038. copyNames((UA_Node*)producturi, "ProductUri");
  1039. producturi->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI);
  1040. UA_Variant_setScalarCopy(&producturi->value.data.value.value, &server->config.buildInfo.productUri,
  1041. &UA_TYPES[UA_TYPES_STRING]);
  1042. producturi->value.data.value.hasValue = true;
  1043. addNodeInternalWithType(server, (UA_Node*)producturi,
  1044. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1045. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1046. UA_VariableNode *manufacturername = UA_NodeStore_newVariableNode();
  1047. copyNames((UA_Node*)manufacturername, "ManufacturerName");
  1048. manufacturername->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME);
  1049. UA_Variant_setScalarCopy(&manufacturername->value.data.value.value,
  1050. &server->config.buildInfo.manufacturerName,
  1051. &UA_TYPES[UA_TYPES_STRING]);
  1052. manufacturername->value.data.value.hasValue = true;
  1053. addNodeInternalWithType(server, (UA_Node*)manufacturername,
  1054. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1055. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1056. UA_VariableNode *productname = UA_NodeStore_newVariableNode();
  1057. copyNames((UA_Node*)productname, "ProductName");
  1058. productname->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME);
  1059. UA_Variant_setScalarCopy(&productname->value.data.value.value, &server->config.buildInfo.productName,
  1060. &UA_TYPES[UA_TYPES_STRING]);
  1061. productname->value.data.value.hasValue = true;
  1062. addNodeInternalWithType(server, (UA_Node*)productname,
  1063. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1064. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1065. UA_VariableNode *softwareversion = UA_NodeStore_newVariableNode();
  1066. copyNames((UA_Node*)softwareversion, "SoftwareVersion");
  1067. softwareversion->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION);
  1068. UA_Variant_setScalarCopy(&softwareversion->value.data.value.value,
  1069. &server->config.buildInfo.softwareVersion, &UA_TYPES[UA_TYPES_STRING]);
  1070. softwareversion->value.data.value.hasValue = true;
  1071. addNodeInternalWithType(server, (UA_Node*)softwareversion,
  1072. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1073. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1074. UA_VariableNode *buildnumber = UA_NodeStore_newVariableNode();
  1075. copyNames((UA_Node*)buildnumber, "BuildNumber");
  1076. buildnumber->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER);
  1077. UA_Variant_setScalarCopy(&buildnumber->value.data.value.value, &server->config.buildInfo.buildNumber,
  1078. &UA_TYPES[UA_TYPES_STRING]);
  1079. buildnumber->value.data.value.hasValue = true;
  1080. addNodeInternalWithType(server, (UA_Node*)buildnumber,
  1081. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1082. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1083. UA_VariableNode *builddate = UA_NodeStore_newVariableNode();
  1084. copyNames((UA_Node*)builddate, "BuildDate");
  1085. builddate->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE);
  1086. UA_Variant_setScalarCopy(&builddate->value.data.value.value, &server->config.buildInfo.buildDate,
  1087. &UA_TYPES[UA_TYPES_DATETIME]);
  1088. builddate->value.data.value.hasValue = true;
  1089. addNodeInternalWithType(server, (UA_Node*)builddate,
  1090. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO),
  1091. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1092. UA_VariableNode *secondstillshutdown = UA_NodeStore_newVariableNode();
  1093. copyNames((UA_Node*)secondstillshutdown, "SecondsTillShutdown");
  1094. secondstillshutdown->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN);
  1095. UA_Variant_setScalar(&secondstillshutdown->value.data.value.value, UA_UInt32_new(),
  1096. &UA_TYPES[UA_TYPES_UINT32]);
  1097. secondstillshutdown->value.data.value.hasValue = true;
  1098. addNodeInternalWithType(server, (UA_Node*)secondstillshutdown,
  1099. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1100. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1101. UA_VariableNode *shutdownreason = UA_NodeStore_newVariableNode();
  1102. copyNames((UA_Node*)shutdownreason, "ShutdownReason");
  1103. shutdownreason->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON);
  1104. UA_Variant_setScalar(&shutdownreason->value.data.value.value, UA_LocalizedText_new(),
  1105. &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
  1106. shutdownreason->value.data.value.hasValue = true;
  1107. addNodeInternalWithType(server, (UA_Node*)shutdownreason,
  1108. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS),
  1109. nodeIdHasComponent, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE));
  1110. UA_VariableNode *servicelevel = UA_NodeStore_newVariableNode();
  1111. copyNames((UA_Node*)servicelevel, "ServiceLevel");
  1112. servicelevel->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVICELEVEL);
  1113. servicelevel->valueSource = UA_VALUESOURCE_DATASOURCE;
  1114. servicelevel->value.dataSource = (UA_DataSource) {.handle = server, .read = readServiceLevel,
  1115. .write = NULL};
  1116. addNodeInternalWithType(server, (UA_Node*)servicelevel,
  1117. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent,
  1118. UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  1119. UA_VariableNode *auditing = UA_NodeStore_newVariableNode();
  1120. copyNames((UA_Node*)auditing, "Auditing");
  1121. auditing->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_AUDITING);
  1122. auditing->valueSource = UA_VALUESOURCE_DATASOURCE;
  1123. auditing->value.dataSource = (UA_DataSource) {.handle = server, .read = readAuditing, .write = NULL};
  1124. addNodeInternalWithType(server, (UA_Node*)auditing,
  1125. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasComponent,
  1126. UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  1127. UA_ObjectNode *vendorServerInfo = UA_NodeStore_newObjectNode();
  1128. copyNames((UA_Node*)vendorServerInfo, "VendorServerInfo");
  1129. vendorServerInfo->nodeId.identifier.numeric = UA_NS0ID_SERVER_VENDORSERVERINFO;
  1130. addNodeInternalWithType(server, (UA_Node*)vendorServerInfo,
  1131. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty,
  1132. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE));
  1133. /*
  1134. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_VENDORSERVERINFO),
  1135. nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_VENDORSERVERINFOTYPE), true);
  1136. */
  1137. UA_ObjectNode *serverRedundancy = UA_NodeStore_newObjectNode();
  1138. copyNames((UA_Node*)serverRedundancy, "ServerRedundancy");
  1139. serverRedundancy->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERREDUNDANCY;
  1140. addNodeInternalWithType(server, (UA_Node*)serverRedundancy,
  1141. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER), nodeIdHasProperty,
  1142. UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE));
  1143. /*
  1144. UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERREDUNDANCY),
  1145. nodeIdHasTypeDefinition, UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_SERVERREDUNDANCYTYPE), true);
  1146. */
  1147. UA_VariableNode *redundancySupport = UA_NodeStore_newVariableNode();
  1148. copyNames((UA_Node*)redundancySupport, "RedundancySupport");
  1149. redundancySupport->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT);
  1150. redundancySupport->valueRank = -1;
  1151. redundancySupport->dataType = UA_TYPES[UA_TYPES_INT32].typeId;
  1152. //FIXME: enum is needed for type letting it uninitialized for now
  1153. UA_Variant_setScalar(&redundancySupport->value.data.value.value, UA_Int32_new(),
  1154. &UA_TYPES[UA_TYPES_INT32]);
  1155. redundancySupport->value.data.value.hasValue = true;
  1156. addNodeInternalWithType(server, (UA_Node*)redundancySupport,
  1157. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERREDUNDANCY),
  1158. nodeIdHasProperty, UA_NODEID_NUMERIC(0, UA_NS0ID_PROPERTYTYPE));
  1159. #if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
  1160. UA_Argument inputArguments;
  1161. UA_Argument_init(&inputArguments);
  1162. inputArguments.dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
  1163. inputArguments.name = UA_STRING("SubscriptionId");
  1164. inputArguments.valueRank = -1; /* scalar argument */
  1165. UA_Argument outputArguments[2];
  1166. UA_Argument_init(&outputArguments[0]);
  1167. outputArguments[0].dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
  1168. outputArguments[0].name = UA_STRING("ServerHandles");
  1169. outputArguments[0].valueRank = 1;
  1170. UA_Argument_init(&outputArguments[1]);
  1171. outputArguments[1].dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
  1172. outputArguments[1].name = UA_STRING("ClientHandles");
  1173. outputArguments[1].valueRank = 1;
  1174. UA_MethodAttributes addmethodattributes;
  1175. UA_MethodAttributes_init(&addmethodattributes);
  1176. addmethodattributes.displayName = UA_LOCALIZEDTEXT("", "GetMonitoredItems");
  1177. addmethodattributes.executable = true;
  1178. addmethodattributes.userExecutable = true;
  1179. UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS),
  1180. UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER),
  1181. UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
  1182. UA_QUALIFIEDNAME(0, "GetMonitoredItems"), addmethodattributes,
  1183. GetMonitoredItems, /* callback of the method node */
  1184. NULL, /* handle passed with the callback */
  1185. 1, &inputArguments, 2, outputArguments, NULL);
  1186. #endif
  1187. return server;
  1188. }