ua_server.c 64 KB

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