ua_server.c 73 KB

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