ua_server.c 72 KB

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