ua_server_discovery.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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_server_internal.h"
  5. #include "ua_client.h"
  6. #include "ua_config_default.h"
  7. #ifdef UA_ENABLE_DISCOVERY
  8. static UA_StatusCode
  9. register_server_with_discovery_server(UA_Server *server,
  10. const char* discoveryServerUrl,
  11. const UA_Boolean isUnregister,
  12. const char* semaphoreFilePath) {
  13. if(!discoveryServerUrl) {
  14. UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_SERVER,
  15. "No discovery server url provided");
  16. return UA_STATUSCODE_BADINTERNALERROR;
  17. }
  18. /* Create the client */
  19. UA_Client *client = UA_Client_new(UA_ClientConfig_default);
  20. if(!client)
  21. return UA_STATUSCODE_BADOUTOFMEMORY;
  22. /* Connect the client */
  23. UA_StatusCode retval = UA_Client_connect(client, discoveryServerUrl);
  24. if(retval != UA_STATUSCODE_GOOD) {
  25. UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT,
  26. "Connecting to the discovery server failed with statuscode %s",
  27. UA_StatusCode_name(retval));
  28. UA_Client_disconnect(client);
  29. UA_Client_delete(client);
  30. return retval;
  31. }
  32. /* Prepare the request. Do not cleanup the request after the service call,
  33. * as the members are stack-allocated or point into the server config. */
  34. UA_RegisterServer2Request request;
  35. UA_RegisterServer2Request_init(&request);
  36. request.requestHeader.timestamp = UA_DateTime_now();
  37. request.requestHeader.timeoutHint = 10000;
  38. request.server.isOnline = !isUnregister;
  39. request.server.serverUri = server->config.applicationDescription.applicationUri;
  40. request.server.productUri = server->config.applicationDescription.productUri;
  41. request.server.serverType = server->config.applicationDescription.applicationType;
  42. request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri;
  43. if(semaphoreFilePath) {
  44. #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
  45. request.server.semaphoreFilePath =
  46. UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */
  47. #else
  48. UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_CLIENT,
  49. "Ignoring semaphore file path. open62541 not compiled "
  50. "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
  51. #endif
  52. }
  53. request.server.serverNames = &server->config.applicationDescription.applicationName;
  54. request.server.serverNamesSize = 1;
  55. /* Copy the discovery urls from the server config and the network layers*/
  56. size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize;
  57. size_t nl_discurls = server->config.networkLayersSize;
  58. size_t total_discurls = config_discurls + nl_discurls;
  59. request.server.discoveryUrls = (UA_String*)UA_alloca(sizeof(UA_String) * total_discurls);
  60. if (!request.server.discoveryUrls) {
  61. UA_Client_disconnect(client);
  62. UA_Client_delete(client);
  63. return UA_STATUSCODE_BADOUTOFMEMORY;
  64. }
  65. request.server.discoveryUrlsSize = total_discurls;
  66. for(size_t i = 0; i < config_discurls; ++i)
  67. request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i];
  68. /* TODO: Add nl only if discoveryUrl not already present */
  69. for(size_t i = 0; i < nl_discurls; ++i) {
  70. UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
  71. request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl;
  72. }
  73. UA_MdnsDiscoveryConfiguration mdnsConfig;
  74. UA_MdnsDiscoveryConfiguration_init(&mdnsConfig);
  75. request.discoveryConfigurationSize = 1;
  76. request.discoveryConfiguration = UA_ExtensionObject_new();
  77. UA_ExtensionObject_init(&request.discoveryConfiguration[0]);
  78. request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
  79. request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION];
  80. request.discoveryConfiguration[0].content.decoded.data = &mdnsConfig;
  81. mdnsConfig.mdnsServerName = server->config.mdnsServerName;
  82. mdnsConfig.serverCapabilities = server->config.serverCapabilities;
  83. mdnsConfig.serverCapabilitiesSize = server->config.serverCapabilitiesSize;
  84. // First try with RegisterServer2, if that isn't implemented, use RegisterServer
  85. UA_RegisterServer2Response response;
  86. UA_RegisterServer2Response_init(&response);
  87. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST],
  88. &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]);
  89. UA_StatusCode serviceResult = response.responseHeader.serviceResult;
  90. UA_RegisterServer2Response_deleteMembers(&response);
  91. UA_ExtensionObject_delete(request.discoveryConfiguration);
  92. if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
  93. serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
  94. /* Try RegisterServer */
  95. UA_RegisterServerRequest request_fallback;
  96. UA_RegisterServerRequest_init(&request_fallback);
  97. /* Copy from RegisterServer2 request */
  98. request_fallback.requestHeader = request.requestHeader;
  99. request_fallback.server = request.server;
  100. UA_RegisterServerResponse response_fallback;
  101. UA_RegisterServerResponse_init(&response_fallback);
  102. __UA_Client_Service(client, &request_fallback,
  103. &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST],
  104. &response_fallback,
  105. &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]);
  106. serviceResult = response_fallback.responseHeader.serviceResult;
  107. UA_RegisterServerResponse_deleteMembers(&response_fallback);
  108. }
  109. if(serviceResult != UA_STATUSCODE_GOOD) {
  110. UA_LOG_ERROR(server->config.logger, UA_LOGCATEGORY_CLIENT,
  111. "RegisterServer/RegisterServer2 failed with statuscode %s",
  112. UA_StatusCode_name(serviceResult));
  113. }
  114. UA_Client_disconnect(client);
  115. UA_Client_delete(client);
  116. return serviceResult;
  117. }
  118. UA_StatusCode
  119. UA_Server_register_discovery(UA_Server *server, const char* discoveryServerUrl,
  120. const char* semaphoreFilePath) {
  121. return register_server_with_discovery_server(server, discoveryServerUrl,
  122. UA_FALSE, semaphoreFilePath);
  123. }
  124. UA_StatusCode
  125. UA_Server_unregister_discovery(UA_Server *server, const char* discoveryServerUrl) {
  126. return register_server_with_discovery_server(server, discoveryServerUrl,
  127. UA_TRUE, NULL);
  128. }
  129. #endif /* UA_ENABLE_DISCOVERY */