ua_server.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "ua_types.h"
  5. #include "ua_server_internal.h"
  6. #include "ua_securechannel_manager.h"
  7. #include "ua_session_manager.h"
  8. #include "ua_util.h"
  9. #include "ua_services.h"
  10. #ifdef UA_ENABLE_GENERATE_NAMESPACE0
  11. #include "ua_namespaceinit_generated.h"
  12. #endif
  13. #if defined(UA_ENABLE_MULTITHREADING) && !defined(NDEBUG)
  14. UA_THREAD_LOCAL bool rcu_locked = false;
  15. #endif
  16. /**********************/
  17. /* Namespace Handling */
  18. /**********************/
  19. UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
  20. /* Check if the namespace already exists in the server's namespace array */
  21. for(UA_UInt16 i = 0; i < server->namespacesSize; ++i) {
  22. if(UA_String_equal(&name, &server->namespaces[i]))
  23. return i;
  24. }
  25. /* Make the array bigger */
  26. UA_String *newNS = (UA_String*)UA_realloc(server->namespaces,
  27. sizeof(UA_String) * (server->namespacesSize + 1));
  28. if(!newNS)
  29. return 0;
  30. server->namespaces = newNS;
  31. /* Copy the namespace string */
  32. UA_StatusCode retval = UA_String_copy(&name, &server->namespaces[server->namespacesSize]);
  33. if(retval != UA_STATUSCODE_GOOD)
  34. return 0;
  35. /* Announce the change (otherwise, the array appears unchanged) */
  36. ++server->namespacesSize;
  37. return (UA_UInt16)(server->namespacesSize - 1);
  38. }
  39. UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
  40. /* Override const attribute to get string (dirty hack) */
  41. UA_String nameString;
  42. nameString.length = strlen(name);
  43. nameString.data = (UA_Byte*)(uintptr_t)name;
  44. return addNamespace(server, nameString);
  45. }
  46. UA_StatusCode
  47. UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
  48. UA_NodeIteratorCallback callback, void *handle) {
  49. UA_RCU_LOCK();
  50. const UA_Node *parent = UA_NodeStore_get(server->nodestore, &parentNodeId);
  51. if(!parent) {
  52. UA_RCU_UNLOCK();
  53. return UA_STATUSCODE_BADNODEIDINVALID;
  54. }
  55. /* TODO: We need to do an ugly copy of the references array since users may
  56. * delete references from within the callback. In single-threaded mode this
  57. * changes the same node we point at here. In multi-threaded mode, this
  58. * creates a new copy as nodes are truly immutable. */
  59. UA_ReferenceNode *refs = NULL;
  60. size_t refssize = parent->referencesSize;
  61. UA_StatusCode retval = UA_Array_copy(parent->references, parent->referencesSize,
  62. (void**)&refs, &UA_TYPES[UA_TYPES_REFERENCENODE]);
  63. if(retval != UA_STATUSCODE_GOOD) {
  64. UA_RCU_UNLOCK();
  65. return retval;
  66. }
  67. for(size_t i = parent->referencesSize; i > 0; --i) {
  68. UA_ReferenceNode *ref = &refs[i-1];
  69. retval |= callback(ref->targetId.nodeId, ref->isInverse,
  70. ref->referenceTypeId, handle);
  71. }
  72. UA_RCU_UNLOCK();
  73. UA_Array_delete(refs, refssize, &UA_TYPES[UA_TYPES_REFERENCENODE]);
  74. return retval;
  75. }
  76. /********************/
  77. /* Server Lifecycle */
  78. /********************/
  79. /* The server needs to be stopped before it can be deleted */
  80. void UA_Server_delete(UA_Server *server) {
  81. /* Delete all internal data */
  82. UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
  83. UA_SessionManager_deleteMembers(&server->sessionManager);
  84. UA_RCU_LOCK();
  85. UA_NodeStore_delete(server->nodestore);
  86. UA_RCU_UNLOCK();
  87. UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
  88. UA_Array_delete(server->endpointDescriptions, server->endpointDescriptionsSize,
  89. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  90. #ifdef UA_ENABLE_DISCOVERY
  91. registeredServer_list_entry *rs, *rs_tmp;
  92. LIST_FOREACH_SAFE(rs, &server->registeredServers, pointers, rs_tmp) {
  93. LIST_REMOVE(rs, pointers);
  94. UA_RegisteredServer_deleteMembers(&rs->registeredServer);
  95. UA_free(rs);
  96. }
  97. if(server->periodicServerRegisterCallback)
  98. UA_free(server->periodicServerRegisterCallback);
  99. # ifdef UA_ENABLE_DISCOVERY_MULTICAST
  100. if(server->config.applicationDescription.applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER)
  101. destroyMulticastDiscoveryServer(server);
  102. serverOnNetwork_list_entry *son, *son_tmp;
  103. LIST_FOREACH_SAFE(son, &server->serverOnNetwork, pointers, son_tmp) {
  104. LIST_REMOVE(son, pointers);
  105. UA_ServerOnNetwork_deleteMembers(&son->serverOnNetwork);
  106. if(son->pathTmp)
  107. UA_free(son->pathTmp);
  108. UA_free(son);
  109. }
  110. for(size_t i = 0; i < SERVER_ON_NETWORK_HASH_PRIME; i++) {
  111. serverOnNetwork_hash_entry* currHash = server->serverOnNetworkHash[i];
  112. while(currHash) {
  113. serverOnNetwork_hash_entry* nextHash = currHash->next;
  114. UA_free(currHash);
  115. currHash = nextHash;
  116. }
  117. }
  118. # endif
  119. #endif
  120. #ifdef UA_ENABLE_MULTITHREADING
  121. pthread_cond_destroy(&server->dispatchQueue_condition);
  122. pthread_mutex_destroy(&server->dispatchQueue_mutex);
  123. #endif
  124. /* Delete the timed work */
  125. UA_Timer_deleteMembers(&server->timer);
  126. /* Delete the server itself */
  127. UA_free(server);
  128. }
  129. /* Recurring cleanup. Removing unused and timed-out channels and sessions */
  130. static void
  131. UA_Server_cleanup(UA_Server *server, void *_) {
  132. UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
  133. UA_SessionManager_cleanupTimedOut(&server->sessionManager, nowMonotonic);
  134. UA_SecureChannelManager_cleanupTimedOut(&server->secureChannelManager, nowMonotonic);
  135. #ifdef UA_ENABLE_DISCOVERY
  136. UA_Discovery_cleanupTimedOut(server, nowMonotonic);
  137. #endif
  138. }
  139. /* Create endpoints w/o endpointurl. It is added from the networklayers at startup */
  140. static void
  141. addEndpointDefinitions(UA_Server *server) {
  142. server->endpointDescriptions =
  143. (UA_EndpointDescription*)UA_Array_new(server->config.networkLayersSize,
  144. &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
  145. server->endpointDescriptionsSize = server->config.networkLayersSize;
  146. for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
  147. UA_EndpointDescription *endpoint = &server->endpointDescriptions[i];
  148. endpoint->securityMode = UA_MESSAGESECURITYMODE_NONE;
  149. endpoint->securityPolicyUri =
  150. UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  151. endpoint->transportProfileUri =
  152. UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
  153. size_t policies = 0;
  154. if(server->config.accessControl.enableAnonymousLogin)
  155. ++policies;
  156. if(server->config.accessControl.enableUsernamePasswordLogin)
  157. ++policies;
  158. endpoint->userIdentityTokensSize = policies;
  159. endpoint->userIdentityTokens =
  160. (UA_UserTokenPolicy*)UA_Array_new(policies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
  161. size_t currentIndex = 0;
  162. if(server->config.accessControl.enableAnonymousLogin) {
  163. UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
  164. endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
  165. endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
  166. ++currentIndex;
  167. }
  168. if(server->config.accessControl.enableUsernamePasswordLogin) {
  169. UA_UserTokenPolicy_init(&endpoint->userIdentityTokens[currentIndex]);
  170. endpoint->userIdentityTokens[currentIndex].tokenType = UA_USERTOKENTYPE_USERNAME;
  171. endpoint->userIdentityTokens[currentIndex].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
  172. }
  173. /* The standard says "the HostName specified in the Server Certificate is the
  174. same as the HostName contained in the endpointUrl provided in the
  175. EndpointDescription */
  176. UA_String_copy(&server->config.serverCertificate, &endpoint->serverCertificate);
  177. UA_ApplicationDescription_copy(&server->config.applicationDescription, &endpoint->server);
  178. /* copy the discovery url only once the networlayer has been started */
  179. // UA_String_copy(&server->config.networkLayers[i].discoveryUrl, &endpoint->endpointUrl);
  180. }
  181. }
  182. UA_Server *
  183. UA_Server_new(const UA_ServerConfig config) {
  184. UA_Server *server = (UA_Server *)UA_calloc(1, sizeof(UA_Server));
  185. if(!server)
  186. return NULL;
  187. server->config = config;
  188. server->startTime = UA_DateTime_now();
  189. server->nodestore = UA_NodeStore_new();
  190. /* Set a seed for non-cyptographic randomness */
  191. #ifndef UA_ENABLE_DETERMINISTIC_RNG
  192. UA_random_seed((UA_UInt64)UA_DateTime_now());
  193. #endif
  194. /* Initialize the handling of repeated callbacks */
  195. UA_Timer_init(&server->timer);
  196. /* Initialized the linked list for delayed callbacks */
  197. #ifndef UA_ENABLE_MULTITHREADING
  198. SLIST_INIT(&server->delayedCallbacks);
  199. #endif
  200. /* Initialized the dispatch queue for worker threads */
  201. #ifdef UA_ENABLE_MULTITHREADING
  202. rcu_init();
  203. cds_wfcq_init(&server->dispatchQueue_head, &server->dispatchQueue_tail);
  204. #endif
  205. /* Create Namespaces 0 and 1 */
  206. server->namespaces = (UA_String *)UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
  207. server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
  208. UA_String_copy(&server->config.applicationDescription.applicationUri, &server->namespaces[1]);
  209. server->namespacesSize = 2;
  210. /* Create Endpoint Definitions */
  211. addEndpointDefinitions(server);
  212. /* Initialized SecureChannel and Session managers */
  213. UA_SecureChannelManager_init(&server->secureChannelManager, server);
  214. UA_SessionManager_init(&server->sessionManager, server);
  215. /* Add a regular callback for cleanup and maintenance */
  216. UA_Server_addRepeatedCallback(server, (UA_ServerCallback)UA_Server_cleanup, NULL,
  217. 10000, NULL);
  218. /* Initialized discovery database */
  219. #ifdef UA_ENABLE_DISCOVERY
  220. LIST_INIT(&server->registeredServers);
  221. server->registeredServersSize = 0;
  222. server->periodicServerRegisterCallback = NULL;
  223. server->registerServerCallback = NULL;
  224. server->registerServerCallbackData = NULL;
  225. #endif
  226. /* Initialize multicast discovery */
  227. #if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
  228. server->mdnsDaemon = NULL;
  229. server->mdnsSocket = 0;
  230. server->mdnsMainSrvAdded = UA_FALSE;
  231. if(server->config.applicationDescription.applicationType == UA_APPLICATIONTYPE_DISCOVERYSERVER)
  232. initMulticastDiscoveryServer(server);
  233. LIST_INIT(&server->serverOnNetwork);
  234. server->serverOnNetworkSize = 0;
  235. server->serverOnNetworkRecordIdCounter = 0;
  236. server->serverOnNetworkRecordIdLastReset = UA_DateTime_now();
  237. memset(server->serverOnNetworkHash, 0,
  238. sizeof(struct serverOnNetwork_hash_entry*) * SERVER_ON_NETWORK_HASH_PRIME);
  239. server->serverOnNetworkCallback = NULL;
  240. server->serverOnNetworkCallbackData = NULL;
  241. #endif
  242. /* Initialize Namespace 0 */
  243. #ifndef UA_ENABLE_GENERATE_NAMESPACE0
  244. UA_Server_createNS0(server);
  245. #else
  246. ua_namespaceinit_generated(server);
  247. #endif
  248. return server;
  249. }
  250. /*****************/
  251. /* Repeated Jobs */
  252. /*****************/
  253. UA_StatusCode
  254. UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
  255. void *data, UA_UInt32 interval,
  256. UA_UInt64 *callbackId) {
  257. return UA_Timer_addRepeatedCallback(&server->timer, (UA_TimerCallback)callback,
  258. data, interval, callbackId);
  259. }
  260. UA_StatusCode
  261. UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
  262. UA_UInt32 interval) {
  263. return UA_Timer_changeRepeatedCallbackInterval(&server->timer, callbackId, interval);
  264. }
  265. UA_StatusCode
  266. UA_Server_removeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId) {
  267. return UA_Timer_removeRepeatedCallback(&server->timer, callbackId);
  268. }