blob: f3dd79ec3f37b8a22580c20d291d042199e8b1bd [file] [log] [blame]
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
*/
#include <open62541/client.h>
#include "ua_server_internal.h"
#ifdef UA_ENABLE_DISCOVERY
static UA_StatusCode
register_server_with_discovery_server(UA_Server *server,
UA_Client *client,
const UA_Boolean isUnregister,
const char* semaphoreFilePath) {
/* Prepare the request. Do not cleanup the request after the service call,
* as the members are stack-allocated or point into the server config. */
UA_RegisterServer2Request request;
UA_RegisterServer2Request_init(&request);
request.requestHeader.timestamp = UA_DateTime_now();
request.requestHeader.timeoutHint = 10000;
request.server.isOnline = !isUnregister;
request.server.serverUri = server->config.applicationDescription.applicationUri;
request.server.productUri = server->config.applicationDescription.productUri;
request.server.serverType = server->config.applicationDescription.applicationType;
request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri;
if(semaphoreFilePath) {
#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
request.server.semaphoreFilePath =
UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */
#else
UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT,
"Ignoring semaphore file path. open62541 not compiled "
"with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
#endif
}
request.server.serverNames = &server->config.applicationDescription.applicationName;
request.server.serverNamesSize = 1;
/* Copy the discovery urls from the server config and the network layers*/
size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize;
size_t nl_discurls = server->config.networkLayersSize;
size_t total_discurls = config_discurls + nl_discurls;
UA_STACKARRAY(UA_String, urlsBuf, total_discurls);
request.server.discoveryUrls = urlsBuf;
request.server.discoveryUrlsSize = total_discurls;
for(size_t i = 0; i < config_discurls; ++i)
request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i];
/* TODO: Add nl only if discoveryUrl not already present */
for(size_t i = 0; i < nl_discurls; ++i) {
UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl;
}
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
request.discoveryConfigurationSize = 1;
request.discoveryConfiguration = UA_ExtensionObject_new();
UA_ExtensionObject_init(&request.discoveryConfiguration[0]);
// Set to NODELETE so that we can just use a pointer to the mdns config
request.discoveryConfiguration[0].encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
request.discoveryConfiguration[0].content.decoded.type = &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION];
request.discoveryConfiguration[0].content.decoded.data = &server->config.discovery.mdns;
#endif
// First try with RegisterServer2, if that isn't implemented, use RegisterServer
UA_RegisterServer2Response response;
__UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST],
&response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]);
UA_StatusCode serviceResult = response.responseHeader.serviceResult;
UA_RegisterServer2Response_deleteMembers(&response);
UA_Array_delete(request.discoveryConfiguration,
request.discoveryConfigurationSize,
&UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
request.discoveryConfiguration = NULL;
request.discoveryConfigurationSize = 0;
if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
/* Try RegisterServer */
UA_RegisterServerRequest request_fallback;
UA_RegisterServerRequest_init(&request_fallback);
/* Copy from RegisterServer2 request */
request_fallback.requestHeader = request.requestHeader;
request_fallback.server = request.server;
UA_RegisterServerResponse response_fallback;
__UA_Client_Service(client, &request_fallback,
&UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST],
&response_fallback,
&UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]);
serviceResult = response_fallback.responseHeader.serviceResult;
UA_RegisterServerResponse_deleteMembers(&response_fallback);
}
if(serviceResult != UA_STATUSCODE_GOOD) {
UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_CLIENT,
"RegisterServer/RegisterServer2 failed with statuscode %s",
UA_StatusCode_name(serviceResult));
}
return serviceResult;
}
UA_StatusCode
UA_Server_register_discovery(UA_Server *server, UA_Client *client,
const char* semaphoreFilePath) {
return register_server_with_discovery_server(server, client,
false, semaphoreFilePath);
}
UA_StatusCode
UA_Server_unregister_discovery(UA_Server *server, UA_Client *client) {
return register_server_with_discovery_server(server, client,
true, NULL);
}
#endif /* UA_ENABLE_DISCOVERY */