ua_server.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #ifdef UA_MULTITHREADING
  2. #define _LGPL_SOURCE
  3. #include <urcu.h>
  4. #endif
  5. #include "ua_types.h"
  6. #include "ua_server_internal.h"
  7. #include "ua_securechannel_manager.h"
  8. #include "ua_session_manager.h"
  9. #include "ua_util.h"
  10. #include "ua_services.h"
  11. #include "ua_nodeids.h"
  12. const char *UA_LoggerCategoryNames[3] = {"communication", "server", "userland"};
  13. /**********************/
  14. /* Namespace Handling */
  15. /**********************/
  16. static void UA_ExternalNamespace_init(UA_ExternalNamespace *ens) {
  17. ens->index = 0;
  18. UA_String_init(&ens->url);
  19. }
  20. static void UA_ExternalNamespace_deleteMembers(UA_ExternalNamespace *ens) {
  21. UA_String_deleteMembers(&ens->url);
  22. ens->externalNodeStore.destroy(ens->externalNodeStore.ensHandle);
  23. }
  24. /*****************/
  25. /* Configuration */
  26. /*****************/
  27. void UA_Server_addNetworkLayer(UA_Server *server, UA_ServerNetworkLayer networkLayer) {
  28. UA_ServerNetworkLayer *newlayers = UA_realloc(server->nls, sizeof(UA_ServerNetworkLayer)*(server->nlsSize+1));
  29. if(!newlayers) {
  30. UA_LOG_ERROR(server->logger, UA_LOGGERCATEGORY_SERVER, "Networklayer added");
  31. return;
  32. }
  33. server->nls = newlayers;
  34. server->nls[server->nlsSize] = networkLayer;
  35. server->nlsSize++;
  36. UA_LOG_INFO(server->logger, UA_LOGGERCATEGORY_SERVER, "Networklayer added");
  37. }
  38. void UA_Server_setServerCertificate(UA_Server *server, UA_ByteString certificate) {
  39. UA_ByteString_copy(&certificate, &server->serverCertificate);
  40. }
  41. void UA_Server_setLogger(UA_Server *server, UA_Logger logger) {
  42. server->logger = logger;
  43. }
  44. /**********/
  45. /* Server */
  46. /**********/
  47. void UA_Server_delete(UA_Server *server) {
  48. // The server needs to be stopped before it can be deleted
  49. // Delete the network layers
  50. for(UA_Int32 i=0;i<server->nlsSize;i++) {
  51. server->nls[i].free(server->nls[i].nlHandle);
  52. }
  53. UA_free(server->nls);
  54. // Delete the timed work
  55. UA_Server_deleteTimedWork(server);
  56. // Delete all internal data
  57. UA_ApplicationDescription_deleteMembers(&server->description);
  58. UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
  59. UA_SessionManager_deleteMembers(&server->sessionManager);
  60. UA_NodeStore_delete(server->nodestore);
  61. UA_ByteString_deleteMembers(&server->serverCertificate);
  62. UA_Array_delete(server->endpointDescriptions, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], server->endpointDescriptionsSize);
  63. #ifdef UA_MULTITHREADING
  64. pthread_cond_destroy(&server->dispatchQueue_condition); // so the workers don't spin if the queue is empty
  65. rcu_barrier(); // wait for all scheduled call_rcu work to complete
  66. #endif
  67. UA_free(server);
  68. }
  69. static UA_StatusCode readStatus(const void *handle, UA_DataValue *value) {
  70. UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
  71. status->startTime = ((const UA_Server*)handle)->startTime;
  72. status->currentTime = UA_DateTime_now();
  73. status->state = UA_SERVERSTATE_RUNNING;
  74. UA_String_copycstring("http://www.open62541.org", &status->buildInfo.productUri);
  75. UA_String_copycstring("open62541", &status->buildInfo.manufacturerName);
  76. UA_String_copycstring("open62541 OPC UA Server", &status->buildInfo.productName);
  77. #define STRINGIFY(x) #x //some magic
  78. #define TOSTRING(x) STRINGIFY(x) //some magic
  79. UA_String_copycstring(TOSTRING(OPEN62541_VERSION_MAJOR) "." TOSTRING(OPEN62541_VERSION_MINOR) "." TOSTRING(OPEN62541_VERSION_PATCH), &status->buildInfo.softwareVersion);
  80. UA_String_copycstring("0", &status->buildInfo.buildNumber);
  81. status->buildInfo.buildDate = ((const UA_Server*)handle)->buildDate;
  82. status->secondsTillShutdown = 0;
  83. value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
  84. value->value.arrayLength = 1;
  85. value->value.dataPtr = status;
  86. value->value.arrayDimensionsSize = -1;
  87. value->value.arrayDimensions = UA_NULL;
  88. value->hasVariant = UA_TRUE;
  89. return UA_STATUSCODE_GOOD;
  90. }
  91. static void releaseStatus(const void *handle, UA_DataValue *value) {
  92. UA_DataValue_deleteMembers(value);
  93. }
  94. static void copyNames(UA_Node *node, char *name) {
  95. UA_QualifiedName_copycstring(name, &node->browseName);
  96. UA_LocalizedText_copycstring(name, &node->displayName);
  97. UA_LocalizedText_copycstring(name, &node->description);
  98. }
  99. static void addDataTypeNode(UA_Server *server, char* name, UA_UInt32 datatypeid, UA_Int32 parent) {
  100. UA_DataTypeNode *datatype = UA_DataTypeNode_new();
  101. copyNames((UA_Node*)datatype, name);
  102. datatype->nodeId.identifier.numeric = datatypeid;
  103. UA_Server_addNode(server, (UA_Node*)datatype,
  104. &UA_EXPANDEDNODEID_STATIC(0, parent),
  105. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  106. }
  107. UA_Server * UA_Server_new(void) {
  108. UA_Server *server = UA_malloc(sizeof(UA_Server));
  109. if(!server)
  110. return UA_NULL;
  111. LIST_INIT(&server->timedWork);
  112. #ifdef UA_MULTITHREADING
  113. rcu_init();
  114. cds_wfcq_init(&server->dispatchQueue_head, &server->dispatchQueue_tail);
  115. server->delayedWork = UA_NULL;
  116. #endif
  117. // logger
  118. server->logger = (UA_Logger){ UA_NULL, UA_NULL, UA_NULL, UA_NULL, UA_NULL, UA_NULL };
  119. // random seed
  120. server->random_seed = (UA_UInt32)UA_DateTime_now();
  121. // networklayers
  122. server->nls = UA_NULL;
  123. server->nlsSize = 0;
  124. UA_ByteString_init(&server->serverCertificate);
  125. // mockup application description
  126. UA_ApplicationDescription_init(&server->description);
  127. UA_String_copycstring("urn:unconfigured:open62541:application", &server->description.productUri);
  128. UA_String_copycstring("http://unconfigured.open62541/applications/", &server->description.applicationUri);
  129. UA_LocalizedText_copycstring("Unconfigured open62541 application", &server->description.applicationName);
  130. server->description.applicationType = UA_APPLICATIONTYPE_SERVER;
  131. server->externalNamespacesSize = 0;
  132. server->externalNamespaces = UA_NULL;
  133. // mockup endpoint description
  134. server->endpointDescriptionsSize = 1;
  135. UA_EndpointDescription *endpoint = UA_EndpointDescription_new(); // todo: check return code
  136. endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
  137. UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None", &endpoint->securityPolicyUri);
  138. UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary", &endpoint->transportProfileUri);
  139. endpoint->userIdentityTokens = UA_malloc(sizeof(UA_UserTokenPolicy));
  140. endpoint->userIdentityTokensSize = 1;
  141. UA_UserTokenPolicy_init(endpoint->userIdentityTokens);
  142. UA_String_copycstring("my-anonymous-policy", &endpoint->userIdentityTokens->policyId); // defined per server
  143. endpoint->userIdentityTokens->tokenType = UA_USERTOKENTYPE_ANONYMOUS;
  144. /* UA_String_copy(endpointUrl, &endpoint->endpointUrl); */
  145. /* /\* The standard says "the HostName specified in the Server Certificate is the */
  146. /* same as the HostName contained in the endpointUrl provided in the */
  147. /* EndpointDescription *\/ */
  148. /* UA_String_copy(&server->serverCertificate, &endpoint->serverCertificate); */
  149. UA_ApplicationDescription_copy(&server->description, &endpoint->server);
  150. server->endpointDescriptions = endpoint;
  151. #define MAXCHANNELCOUNT 100
  152. #define STARTCHANNELID 1
  153. #define TOKENLIFETIME 600000
  154. #define STARTTOKENID 1
  155. UA_SecureChannelManager_init(&server->secureChannelManager, MAXCHANNELCOUNT,
  156. TOKENLIFETIME, STARTCHANNELID, STARTTOKENID);
  157. #define MAXSESSIONCOUNT 1000
  158. #define SESSIONLIFETIME 10000
  159. #define STARTSESSIONID 1
  160. UA_SessionManager_init(&server->sessionManager, MAXSESSIONCOUNT, SESSIONLIFETIME, STARTSESSIONID);
  161. server->nodestore = UA_NodeStore_new();
  162. /**************/
  163. /* References */
  164. /**************/
  165. /* bootstrap by manually inserting "references" and "hassubtype" */
  166. UA_ReferenceTypeNode *references = UA_ReferenceTypeNode_new();
  167. copyNames((UA_Node*)references, "References");
  168. references->nodeId.identifier.numeric = UA_NS0ID_REFERENCES;
  169. references->isAbstract = UA_TRUE;
  170. references->symmetric = UA_TRUE;
  171. // this node has no parent??
  172. UA_NodeStore_insert(server->nodestore, (UA_Node*)references, UA_NULL);
  173. UA_ReferenceTypeNode *hassubtype = UA_ReferenceTypeNode_new();
  174. copyNames((UA_Node*)hassubtype, "HasSubtype");
  175. UA_LocalizedText_copycstring("HasSupertype", &hassubtype->inverseName);
  176. hassubtype->nodeId.identifier.numeric = UA_NS0ID_HASSUBTYPE;
  177. hassubtype->isAbstract = UA_FALSE;
  178. hassubtype->symmetric = UA_FALSE;
  179. UA_NodeStore_insert(server->nodestore, (UA_Node*)hassubtype, UA_NULL);
  180. /* continue adding reference types with normal "addnode" */
  181. UA_ReferenceTypeNode *hierarchicalreferences = UA_ReferenceTypeNode_new();
  182. copyNames((UA_Node*)hierarchicalreferences, "Hierarchicalreferences");
  183. hierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_HIERARCHICALREFERENCES;
  184. hierarchicalreferences->isAbstract = UA_TRUE;
  185. hierarchicalreferences->symmetric = UA_FALSE;
  186. UA_Server_addNode(server, (UA_Node*)hierarchicalreferences,
  187. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_REFERENCES),
  188. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  189. UA_ReferenceTypeNode *nonhierarchicalreferences = UA_ReferenceTypeNode_new();
  190. copyNames((UA_Node*)nonhierarchicalreferences, "NonHierarchicalReferences");
  191. nonhierarchicalreferences->nodeId.identifier.numeric = UA_NS0ID_NONHIERARCHICALREFERENCES;
  192. nonhierarchicalreferences->isAbstract = UA_TRUE;
  193. nonhierarchicalreferences->symmetric = UA_FALSE;
  194. UA_Server_addNode(server, (UA_Node*)nonhierarchicalreferences,
  195. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_REFERENCES),
  196. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  197. UA_ReferenceTypeNode *haschild = UA_ReferenceTypeNode_new();
  198. copyNames((UA_Node*)haschild, "HasChild");
  199. haschild->nodeId.identifier.numeric = UA_NS0ID_HASCHILD;
  200. haschild->isAbstract = UA_TRUE;
  201. haschild->symmetric = UA_FALSE;
  202. UA_Server_addNode(server, (UA_Node*)haschild,
  203. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
  204. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  205. UA_ReferenceTypeNode *organizes = UA_ReferenceTypeNode_new();
  206. copyNames((UA_Node*)organizes, "Organizes");
  207. UA_LocalizedText_copycstring("OrganizedBy", &organizes->inverseName);
  208. organizes->nodeId.identifier.numeric = UA_NS0ID_ORGANIZES;
  209. organizes->isAbstract = UA_FALSE;
  210. organizes->symmetric = UA_FALSE;
  211. UA_Server_addNode(server, (UA_Node*)organizes,
  212. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
  213. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  214. UA_ReferenceTypeNode *haseventsource = UA_ReferenceTypeNode_new();
  215. copyNames((UA_Node*)haseventsource, "HasEventSource");
  216. UA_LocalizedText_copycstring("EventSourceOf", &haseventsource->inverseName);
  217. haseventsource->nodeId.identifier.numeric = UA_NS0ID_HASEVENTSOURCE;
  218. haseventsource->isAbstract = UA_FALSE;
  219. haseventsource->symmetric = UA_FALSE;
  220. UA_Server_addNode(server, (UA_Node*)haseventsource,
  221. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HIERARCHICALREFERENCES),
  222. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  223. UA_ReferenceTypeNode *hasmodellingrule = UA_ReferenceTypeNode_new();
  224. copyNames((UA_Node*)hasmodellingrule, "HasModellingRule");
  225. UA_LocalizedText_copycstring("ModellingRuleOf", &hasmodellingrule->inverseName);
  226. hasmodellingrule->nodeId.identifier.numeric = UA_NS0ID_HASMODELLINGRULE;
  227. hasmodellingrule->isAbstract = UA_FALSE;
  228. hasmodellingrule->symmetric = UA_FALSE;
  229. UA_Server_addNode(server, (UA_Node*)hasmodellingrule,
  230. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  231. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  232. UA_ReferenceTypeNode *hasencoding = UA_ReferenceTypeNode_new();
  233. copyNames((UA_Node*)hasencoding, "HasEncoding");
  234. UA_LocalizedText_copycstring("EncodingOf", &hasencoding->inverseName);
  235. hasencoding->nodeId.identifier.numeric = UA_NS0ID_HASENCODING;
  236. hasencoding->isAbstract = UA_FALSE;
  237. hasencoding->symmetric = UA_FALSE;
  238. UA_Server_addNode(server, (UA_Node*)hasencoding,
  239. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  240. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  241. UA_ReferenceTypeNode *hasdescription = UA_ReferenceTypeNode_new();
  242. copyNames((UA_Node*)hasdescription, "HasDescription");
  243. UA_LocalizedText_copycstring("DescriptionOf", &hasdescription->inverseName);
  244. hasdescription->nodeId.identifier.numeric = UA_NS0ID_HASDESCRIPTION;
  245. hasdescription->isAbstract = UA_FALSE;
  246. hasdescription->symmetric = UA_FALSE;
  247. UA_Server_addNode(server, (UA_Node*)hasdescription,
  248. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  249. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  250. UA_ReferenceTypeNode *hastypedefinition = UA_ReferenceTypeNode_new();
  251. copyNames((UA_Node*)hastypedefinition, "HasTypeDefinition");
  252. UA_LocalizedText_copycstring("TypeDefinitionOf", &hastypedefinition->inverseName);
  253. hastypedefinition->nodeId.identifier.numeric = UA_NS0ID_HASTYPEDEFINITION;
  254. hastypedefinition->isAbstract = UA_FALSE;
  255. hastypedefinition->symmetric = UA_FALSE;
  256. UA_Server_addNode(server, (UA_Node*)hastypedefinition,
  257. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  258. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  259. UA_ReferenceTypeNode *generatesevent = UA_ReferenceTypeNode_new();
  260. copyNames((UA_Node*)generatesevent, "GeneratesEvent");
  261. UA_LocalizedText_copycstring("GeneratedBy", &generatesevent->inverseName);
  262. generatesevent->nodeId.identifier.numeric = UA_NS0ID_GENERATESEVENT;
  263. generatesevent->isAbstract = UA_FALSE;
  264. generatesevent->symmetric = UA_FALSE;
  265. UA_Server_addNode(server, (UA_Node*)generatesevent,
  266. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  267. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  268. UA_ReferenceTypeNode *aggregates = UA_ReferenceTypeNode_new();
  269. copyNames((UA_Node*)aggregates, "Aggregates");
  270. // Todo: Is there an inverse name?
  271. aggregates->nodeId.identifier.numeric = UA_NS0ID_AGGREGATES;
  272. aggregates->isAbstract = UA_TRUE;
  273. aggregates->symmetric = UA_FALSE;
  274. UA_Server_addNode(server, (UA_Node*)aggregates,
  275. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HASCHILD),
  276. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  277. // complete bootstrap of hassubtype
  278. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_HASCHILD), UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE),
  279. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  280. UA_ReferenceTypeNode *hasproperty = UA_ReferenceTypeNode_new();
  281. copyNames((UA_Node*)hasproperty, "HasProperty");
  282. UA_LocalizedText_copycstring("PropertyOf", &hasproperty->inverseName);
  283. hasproperty->nodeId.identifier.numeric = UA_NS0ID_HASPROPERTY;
  284. hasproperty->isAbstract = UA_FALSE;
  285. hasproperty->symmetric = UA_FALSE;
  286. UA_Server_addNode(server, (UA_Node*)hasproperty,
  287. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_AGGREGATES),
  288. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  289. UA_ReferenceTypeNode *hascomponent = UA_ReferenceTypeNode_new();
  290. copyNames((UA_Node*)hascomponent, "HasComponent");
  291. UA_LocalizedText_copycstring("ComponentOf", &hascomponent->inverseName);
  292. hascomponent->nodeId.identifier.numeric = UA_NS0ID_HASCOMPONENT;
  293. hascomponent->isAbstract = UA_FALSE;
  294. hascomponent->symmetric = UA_FALSE;
  295. UA_Server_addNode(server, (UA_Node*)hascomponent,
  296. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_AGGREGATES),
  297. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  298. UA_ReferenceTypeNode *hasnotifier = UA_ReferenceTypeNode_new();
  299. copyNames((UA_Node*)hasnotifier, "HasNotifier");
  300. UA_LocalizedText_copycstring("NotifierOf", &hasnotifier->inverseName);
  301. hasnotifier->nodeId.identifier.numeric = UA_NS0ID_HASNOTIFIER;
  302. hasnotifier->isAbstract = UA_FALSE;
  303. hasnotifier->symmetric = UA_FALSE;
  304. UA_Server_addNode(server, (UA_Node*)hasnotifier,
  305. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HASEVENTSOURCE),
  306. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  307. UA_ReferenceTypeNode *hasorderedcomponent = UA_ReferenceTypeNode_new();
  308. copyNames((UA_Node*)hasorderedcomponent, "HasOrderedComponent");
  309. UA_LocalizedText_copycstring("OrderedComponentOf", &hasorderedcomponent->inverseName);
  310. hasorderedcomponent->nodeId.identifier.numeric = UA_NS0ID_HASORDEREDCOMPONENT;
  311. hasorderedcomponent->isAbstract = UA_FALSE;
  312. hasorderedcomponent->symmetric = UA_FALSE;
  313. UA_Server_addNode(server, (UA_Node*)hasorderedcomponent,
  314. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_HASCOMPONENT),
  315. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  316. UA_ReferenceTypeNode *hasmodelparent = UA_ReferenceTypeNode_new();
  317. copyNames((UA_Node*)hasmodelparent, "HasModelParent");
  318. UA_LocalizedText_copycstring("ModelParentOf", &hasmodelparent->inverseName);
  319. hasmodelparent->nodeId.identifier.numeric = UA_NS0ID_HASMODELPARENT;
  320. hasmodelparent->isAbstract = UA_FALSE;
  321. hasmodelparent->symmetric = UA_FALSE;
  322. UA_Server_addNode(server, (UA_Node*)hasmodelparent,
  323. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  324. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  325. UA_ReferenceTypeNode *fromstate = UA_ReferenceTypeNode_new();
  326. copyNames((UA_Node*)fromstate, "FromState");
  327. UA_LocalizedText_copycstring("ToTransition", &fromstate->inverseName);
  328. fromstate->nodeId.identifier.numeric = UA_NS0ID_FROMSTATE;
  329. fromstate->isAbstract = UA_FALSE;
  330. fromstate->symmetric = UA_FALSE;
  331. UA_Server_addNode(server, (UA_Node*)fromstate,
  332. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  333. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  334. UA_ReferenceTypeNode *tostate = UA_ReferenceTypeNode_new();
  335. copyNames((UA_Node*)tostate, "ToState");
  336. UA_LocalizedText_copycstring("FromTransition", &tostate->inverseName);
  337. tostate->nodeId.identifier.numeric = UA_NS0ID_TOSTATE;
  338. tostate->isAbstract = UA_FALSE;
  339. tostate->symmetric = UA_FALSE;
  340. UA_Server_addNode(server, (UA_Node*)tostate,
  341. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  342. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  343. UA_ReferenceTypeNode *hascause = UA_ReferenceTypeNode_new();
  344. copyNames((UA_Node*)hascause, "HasCause");
  345. UA_LocalizedText_copycstring("MayBeCausedBy", &hascause->inverseName);
  346. hascause->nodeId.identifier.numeric = UA_NS0ID_HASCAUSE;
  347. hascause->isAbstract = UA_FALSE;
  348. hascause->symmetric = UA_FALSE;
  349. UA_Server_addNode(server, (UA_Node*)hascause,
  350. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  351. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  352. UA_ReferenceTypeNode *haseffect = UA_ReferenceTypeNode_new();
  353. copyNames((UA_Node*)haseffect, "HasEffect");
  354. UA_LocalizedText_copycstring("MayBeEffectedBy", &haseffect->inverseName);
  355. haseffect->nodeId.identifier.numeric = UA_NS0ID_HASEFFECT;
  356. haseffect->isAbstract = UA_FALSE;
  357. haseffect->symmetric = UA_FALSE;
  358. UA_Server_addNode(server, (UA_Node*)haseffect,
  359. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_NONHIERARCHICALREFERENCES),
  360. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  361. UA_ReferenceTypeNode *hashistoricalconfiguration = UA_ReferenceTypeNode_new();
  362. copyNames((UA_Node*)hashistoricalconfiguration, "HasHistoricalConfiguration");
  363. UA_LocalizedText_copycstring("HistoricalConfigurationOf", &hashistoricalconfiguration->inverseName);
  364. hashistoricalconfiguration->nodeId.identifier.numeric = UA_NS0ID_HASHISTORICALCONFIGURATION;
  365. hashistoricalconfiguration->isAbstract = UA_FALSE;
  366. hashistoricalconfiguration->symmetric = UA_FALSE;
  367. UA_Server_addNode(server, (UA_Node*)hashistoricalconfiguration,
  368. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_AGGREGATES),
  369. &UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE));
  370. /***********/
  371. /* Objects */
  372. /***********/
  373. UA_ObjectTypeNode *baseObjectType = UA_ObjectTypeNode_new();
  374. baseObjectType->nodeId.identifier.numeric = UA_NS0ID_BASEOBJECTTYPE;
  375. copyNames((UA_Node*)baseObjectType, "BaseObjectType");
  376. UA_NodeStore_insert(server->nodestore, (UA_Node*)baseObjectType, UA_NULL);
  377. UA_ObjectTypeNode *baseDataVarialbeType = UA_ObjectTypeNode_new();
  378. baseDataVarialbeType->nodeId.identifier.numeric = UA_NS0ID_BASEDATAVARIABLETYPE;
  379. copyNames((UA_Node*)baseDataVarialbeType, "BaseDataVariableType");
  380. UA_NodeStore_insert(server->nodestore, (UA_Node*)baseDataVarialbeType, UA_NULL);
  381. UA_ObjectTypeNode *folderType = UA_ObjectTypeNode_new();
  382. folderType->nodeId.identifier.numeric = UA_NS0ID_FOLDERTYPE;
  383. copyNames((UA_Node*)folderType, "FolderType");
  384. UA_NodeStore_insert(server->nodestore, (UA_Node*)folderType, UA_NULL);
  385. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_BASEOBJECTTYPE), UA_NODEID_STATIC(0, UA_NS0ID_HASSUBTYPE),
  386. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  387. UA_ObjectNode *root = UA_ObjectNode_new();
  388. copyNames((UA_Node*)root, "Root");
  389. root->nodeId.identifier.numeric = UA_NS0ID_ROOTFOLDER;
  390. UA_NodeStore_insert(server->nodestore, (UA_Node*)root, UA_NULL);
  391. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_ROOTFOLDER), UA_NODEID_STATIC(0, UA_NS0ID_HASTYPEDEFINITION),
  392. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  393. UA_ObjectNode *objects = UA_ObjectNode_new();
  394. copyNames((UA_Node*)objects, "Objects");
  395. objects->nodeId.identifier.numeric = UA_NS0ID_OBJECTSFOLDER;
  396. UA_Server_addNode(server, (UA_Node*)objects,
  397. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_ROOTFOLDER),
  398. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  399. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_STATIC(0, UA_NS0ID_HASTYPEDEFINITION),
  400. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  401. UA_ObjectNode *types = UA_ObjectNode_new();
  402. copyNames((UA_Node*)types, "Types");
  403. types->nodeId.identifier.numeric = UA_NS0ID_TYPESFOLDER;
  404. UA_Server_addNode(server, (UA_Node*)types,
  405. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_ROOTFOLDER),
  406. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  407. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_TYPESFOLDER), UA_NODEID_STATIC(0, UA_NS0ID_HASTYPEDEFINITION),
  408. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  409. UA_ObjectNode *views = UA_ObjectNode_new();
  410. copyNames((UA_Node*)views, "Views");
  411. views->nodeId.identifier.numeric = UA_NS0ID_VIEWSFOLDER;
  412. UA_Server_addNode(server, (UA_Node*)views,
  413. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_ROOTFOLDER),
  414. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  415. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_VIEWSFOLDER), UA_NODEID_STATIC(0, UA_NS0ID_HASTYPEDEFINITION),
  416. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  417. UA_ObjectNode *servernode = UA_ObjectNode_new();
  418. copyNames((UA_Node*)servernode, "Server");
  419. servernode->nodeId.identifier.numeric = UA_NS0ID_SERVER;
  420. UA_Server_addNode(server, (UA_Node*)servernode,
  421. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_OBJECTSFOLDER),
  422. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  423. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_SERVER), UA_NODEID_STATIC(0, UA_NS0ID_HASCOMPONENT),
  424. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_SERVER_SERVERCAPABILITIES));
  425. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_SERVER), UA_NODEID_STATIC(0, UA_NS0ID_HASPROPERTY),
  426. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_SERVER_SERVERARRAY));
  427. UA_VariableNode *namespaceArray = UA_VariableNode_new();
  428. copyNames((UA_Node*)namespaceArray, "NamespaceArray");
  429. namespaceArray->nodeId.identifier.numeric = UA_NS0ID_SERVER_NAMESPACEARRAY;
  430. namespaceArray->variableType = UA_VARIABLENODETYPE_VARIANT;
  431. namespaceArray->variable.variant.dataPtr = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], 2);
  432. namespaceArray->variable.variant.arrayLength = 2;
  433. namespaceArray->variable.variant.type = &UA_TYPES[UA_TYPES_STRING];
  434. // Fixme: Insert the external namespaces
  435. UA_String_copycstring("http://opcfoundation.org/UA/",
  436. &((UA_String *)(namespaceArray->variable.variant.dataPtr))[0]);
  437. UA_String_copycstring("urn:myServer:myApplication",
  438. &((UA_String *)(namespaceArray->variable.variant.dataPtr))[1]);
  439. namespaceArray->valueRank = 1;
  440. namespaceArray->minimumSamplingInterval = 1.0;
  441. namespaceArray->historizing = UA_FALSE;
  442. UA_Server_addNode(server, (UA_Node*)namespaceArray,
  443. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_SERVER),
  444. &UA_NODEID_STATIC(0, UA_NS0ID_HASPROPERTY));
  445. UA_VariableNode *serverstatus = UA_VariableNode_new();
  446. copyNames((UA_Node*)serverstatus, "ServerStatus");
  447. serverstatus->nodeId = UA_NODEID_STATIC(0, UA_NS0ID_SERVER_SERVERSTATUS);
  448. serverstatus->variableType = UA_VARIABLENODETYPE_DATASOURCE;
  449. serverstatus->variable.dataSource = (UA_DataSource) {.handle = server, .read = readStatus,
  450. .release = releaseStatus, .write = UA_NULL};
  451. UA_Server_addNode(server, (UA_Node*)serverstatus, &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_SERVER),
  452. &UA_NODEID_STATIC(0, UA_NS0ID_HASCOMPONENT));
  453. UA_VariableNode *state = UA_VariableNode_new();
  454. UA_ServerState *stateEnum = UA_ServerState_new();
  455. *stateEnum = UA_SERVERSTATE_RUNNING;
  456. copyNames((UA_Node*)state, "State");
  457. state->nodeId.identifier.numeric = UA_NS0ID_SERVER_SERVERSTATUS_STATE;
  458. state->variableType = UA_VARIABLENODETYPE_VARIANT;
  459. state->variable.variant.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
  460. state->variable.variant.arrayLength = 1;
  461. state->variable.variant.dataPtr = stateEnum; // points into the other object.
  462. UA_NodeStore_insert(server->nodestore, (UA_Node*)state, UA_NULL);
  463. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_SERVER_SERVERSTATUS), UA_NODEID_STATIC(0, UA_NS0ID_HASCOMPONENT),
  464. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STATE));
  465. /**************/
  466. /* Data Types */
  467. /**************/
  468. UA_ObjectNode *datatypes = UA_ObjectNode_new();
  469. copyNames((UA_Node*)datatypes, "DataTypes");
  470. datatypes->nodeId.identifier.numeric = UA_NS0ID_DATATYPESFOLDER;
  471. UA_Server_addNode(server, (UA_Node*)datatypes,
  472. &UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_TYPESFOLDER),
  473. &UA_NODEID_STATIC(0, UA_NS0ID_ORGANIZES));
  474. ADDREFERENCE(UA_NODEID_STATIC(0, UA_NS0ID_DATATYPESFOLDER), UA_NODEID_STATIC(0, UA_NS0ID_HASTYPEDEFINITION),
  475. UA_EXPANDEDNODEID_STATIC(0, UA_NS0ID_FOLDERTYPE));
  476. addDataTypeNode(server, "BaseDataType", UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER);
  477. addDataTypeNode(server, "Boolean", UA_NS0ID_BOOLEAN, UA_NS0ID_BASEDATATYPE);
  478. addDataTypeNode(server, "Number", UA_NS0ID_NUMBER, UA_NS0ID_BASEDATATYPE);
  479. addDataTypeNode(server, "Float", UA_NS0ID_FLOAT, UA_NS0ID_NUMBER);
  480. addDataTypeNode(server, "Double", UA_NS0ID_DOUBLE, UA_NS0ID_NUMBER);
  481. addDataTypeNode(server, "Integer", UA_NS0ID_INTEGER, UA_NS0ID_NUMBER);
  482. addDataTypeNode(server, "SByte", UA_NS0ID_SBYTE, UA_NS0ID_INTEGER);
  483. addDataTypeNode(server, "Int16", UA_NS0ID_INT16, UA_NS0ID_INTEGER);
  484. addDataTypeNode(server, "Int32", UA_NS0ID_INT32, UA_NS0ID_INTEGER);
  485. addDataTypeNode(server, "Int64", UA_NS0ID_INT64, UA_NS0ID_INTEGER);
  486. addDataTypeNode(server, "UInteger", UA_NS0ID_UINTEGER, UA_NS0ID_INTEGER);
  487. addDataTypeNode(server, "Byte", UA_NS0ID_BYTE, UA_NS0ID_UINTEGER);
  488. addDataTypeNode(server, "UInt16", UA_NS0ID_UINT16, UA_NS0ID_UINTEGER);
  489. addDataTypeNode(server, "UInt32", UA_NS0ID_UINT32, UA_NS0ID_UINTEGER);
  490. addDataTypeNode(server, "UInt64", UA_NS0ID_UINT64, UA_NS0ID_UINTEGER);
  491. addDataTypeNode(server, "String", UA_NS0ID_STRING, UA_NS0ID_BASEDATATYPE);
  492. addDataTypeNode(server, "DateTime", UA_NS0ID_DATETIME, UA_NS0ID_BASEDATATYPE);
  493. addDataTypeNode(server, "Guid", UA_NS0ID_GUID, UA_NS0ID_BASEDATATYPE);
  494. addDataTypeNode(server, "ByteString", UA_NS0ID_BYTESTRING, UA_NS0ID_BASEDATATYPE);
  495. addDataTypeNode(server, "XmlElement", UA_NS0ID_XMLELEMENT, UA_NS0ID_BASEDATATYPE);
  496. addDataTypeNode(server, "NodeId", UA_NS0ID_NODEID, UA_NS0ID_BASEDATATYPE);
  497. addDataTypeNode(server, "ExpandedNodeId", UA_NS0ID_EXPANDEDNODEID, UA_NS0ID_BASEDATATYPE);
  498. addDataTypeNode(server, "StatusCode", UA_NS0ID_STATUSCODE, UA_NS0ID_BASEDATATYPE);
  499. addDataTypeNode(server, "QualifiedName", UA_NS0ID_QUALIFIEDNAME, UA_NS0ID_BASEDATATYPE);
  500. addDataTypeNode(server, "LocalizedText", UA_NS0ID_LOCALIZEDTEXT, UA_NS0ID_BASEDATATYPE);
  501. addDataTypeNode(server, "Structure", UA_NS0ID_STRUCTURE, UA_NS0ID_BASEDATATYPE);
  502. addDataTypeNode(server, "DataValue", UA_NS0ID_DATAVALUE, UA_NS0ID_BASEDATATYPE);
  503. addDataTypeNode(server, "DiagnosticInfo", UA_NS0ID_DIAGNOSTICINFO, UA_NS0ID_BASEDATATYPE);
  504. addDataTypeNode(server, "Enumeration", UA_NS0ID_ENUMERATION, UA_NS0ID_BASEDATATYPE);
  505. return server;
  506. }