ua_server.c 73 KB

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