mirror of
https://github.com/open62541/open62541.git
synced 2026-10-29 13:20:10 +08:00
refactor(server): Manage the RegisteredServers and ServersOnNetwork for Discovery via the public API
This commit is contained in:
committed by
Julius Pfrommer
parent
da864962ae
commit
575e5d97da
@@ -109,25 +109,9 @@
|
||||
maxAsyncOperationQueueSize: 1000000,
|
||||
|
||||
// Only available when discovery support is enabled.
|
||||
discoveryCleanupTimeout: 60,
|
||||
|
||||
// mDNS / LDS-ME support (UA_ENABLE_DISCOVERY_MULTICAST).
|
||||
// mdnsEnabled: false,
|
||||
// mdns: {
|
||||
// mdnsServerName: "open62541-json5-server",
|
||||
// // Common capability tags: "LDS", "DA", "HD", "GDS".
|
||||
// // Use ["NA"] if no capability should be advertised.
|
||||
// serverCapabilities: [
|
||||
// "DA",
|
||||
// "HD"
|
||||
// ],
|
||||
// // Bind to one interface or leave empty for the default.
|
||||
// mdnsInterfaceIP: "127.0.0.1",
|
||||
// // Raw IPv4 addresses as unsigned integers. Leave empty to auto-detect.
|
||||
// mdnsIpAddressList: [
|
||||
// 2130706433
|
||||
// ]
|
||||
// },
|
||||
registeredServersEnabled: true,
|
||||
registeredServerCleanupTimeout: 600,
|
||||
serversOnNetworkEnabled: false,
|
||||
|
||||
// Subscription and MonitoredItem limits (UA_ENABLE_SUBSCRIPTIONS).
|
||||
subscriptionsEnabled: true,
|
||||
|
||||
+82
-67
@@ -1624,16 +1624,14 @@ UA_Server_createEventEx(UA_Server *server,
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
|
||||
/**
|
||||
* Discovery
|
||||
* ---------
|
||||
*
|
||||
* Registering at a Discovery Server
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
* Remote Discovery Server Registration
|
||||
* ------------------------------------
|
||||
* The current server can register itself at a discovery. For that it requires
|
||||
* to open a client connection. */
|
||||
|
||||
/* Register the given server instance at the discovery server. This should be
|
||||
/* Register the given server instance at a discovery server. This should be
|
||||
* called periodically, for example every 10 minutes, depending on the
|
||||
* configuration of the discovery server. You should also call
|
||||
* _unregisterDiscovery when the server shuts down.
|
||||
* configuration of the discovery server.
|
||||
*
|
||||
* The supplied client configuration is used to create a new client to connect
|
||||
* to the discovery server. The client configuration is moved over to the server
|
||||
@@ -1654,58 +1652,70 @@ UA_Server_deregisterDiscovery(UA_Server *server, UA_ClientConfig *cc,
|
||||
const UA_String discoveryServerUrl);
|
||||
|
||||
/**
|
||||
* Operating a Discovery Server
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/* Callback for RegisterServer. Data is passed from the register call */
|
||||
typedef void
|
||||
(*UA_Server_registerServerCallback)(const UA_RegisteredServer *registeredServer,
|
||||
void* data);
|
||||
|
||||
/* Set the callback which is called if another server registeres or unregisters
|
||||
* with this instance. This callback is called every time the server gets a
|
||||
* register call. This especially means that for every periodic server register
|
||||
* the callback will be called.
|
||||
* Local Discovery Server Records
|
||||
* ------------------------------
|
||||
* The Discovery Service-Set allows the registering of local (for FindServers)
|
||||
* and also remote servers (for FindServersOnNetwork).
|
||||
*
|
||||
* @param server
|
||||
* @param cb the callback
|
||||
* @param data data passed to the callback
|
||||
* @return ``UA_STATUSCODE_SUCCESS`` on success */
|
||||
void UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_setRegisterServerCallback(UA_Server *server,
|
||||
UA_Server_registerServerCallback cb, void* data);
|
||||
* We uniquely identify records by their combination of ServerUri + one matching
|
||||
* DiscoveryUrl. */
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_findServers(UA_Server *server, UA_String endpointUrl,
|
||||
size_t localeIdsSize, UA_LocaleId *localeIds,
|
||||
size_t serverUrisSize, UA_String *serverUris,
|
||||
size_t *outServersSize,
|
||||
UA_ApplicationDescription **outServers);
|
||||
|
||||
/* Callback for server detected through mDNS. Data is passed from the register
|
||||
* call
|
||||
/* Local API for the RegisterServer2 service. If configurationResults is
|
||||
* non-Null, then it must point to an array of discoveryConfigurationSize
|
||||
* length. */
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_registerServer(UA_Server *server,
|
||||
const UA_RegisteredServer *registeredServer,
|
||||
const size_t discoveryConfigurationSize,
|
||||
const UA_ExtensionObject *discoveryConfiguration,
|
||||
UA_StatusCode *configurationResults);
|
||||
|
||||
/* Remove the servers matching the ServerUri and at least one of the
|
||||
* provided DiscoveryUrls */
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_deregisterServer(UA_Server *server, const UA_String serverUri,
|
||||
size_t discoveryUrlsSize,
|
||||
const UA_String *discoveryUrls);
|
||||
|
||||
/**
|
||||
* The server internally manages the ServersOnNetwork list. Multicast discovery
|
||||
* is implemented on top in a driver outside of the core library. */
|
||||
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_findServersOnNetwork(UA_Server *server, UA_String endpointUrl,
|
||||
UA_UInt32 startingRecordId,
|
||||
UA_UInt32 maxRecordsToReturn,
|
||||
size_t serverCapabilityFilterSize,
|
||||
const UA_String *serverCapabilityFilter,
|
||||
UA_DateTime *outLastCounterResetTime,
|
||||
size_t *outServersSize,
|
||||
UA_ServerOnNetwork **outServers);
|
||||
|
||||
/* Register a remote server. If the server name was previously known, the
|
||||
* existing entry gets updated. The parameter kv-map can be extended with
|
||||
* additional parameters in the future. Currently supported are:
|
||||
*
|
||||
* @param isServerAnnounce indicates if the server has just been detected. If
|
||||
* set to false, this means the server is shutting down.
|
||||
* @param isTxtReceived indicates if we already received the corresponding TXT
|
||||
* record with the path and caps data */
|
||||
typedef void
|
||||
(*UA_Server_serverOnNetworkCallback)(const UA_ServerOnNetwork *serverOnNetwork,
|
||||
UA_Boolean isServerAnnounce,
|
||||
UA_Boolean isTxtReceived, void* data);
|
||||
* 0:remote-address [String]
|
||||
* IP-address or other host identifier from which the information
|
||||
* was received.
|
||||
* 0:ttl [UInt32]
|
||||
* Time-to-live of DNS information. Zero means infinite. */
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_registerServerOnNetwork(UA_Server *server,
|
||||
const UA_ServerOnNetwork *son,
|
||||
const UA_KeyValueMap params);
|
||||
|
||||
/* Set the callback which is called if another server is found through mDNS or
|
||||
* deleted. It will be called for any mDNS message from the remote server, thus
|
||||
* it may be called multiple times for the same instance. Also the SRV and TXT
|
||||
* records may arrive later, therefore for the first call the server
|
||||
* capabilities may not be set yet. If called multiple times, previous data will
|
||||
* be overwritten.
|
||||
*
|
||||
* @param server
|
||||
* @param cb the callback
|
||||
* @param data data passed to the callback
|
||||
* @return ``UA_STATUSCODE_SUCCESS`` on success */
|
||||
void UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_setServerOnNetworkCallback(UA_Server *server,
|
||||
UA_Server_serverOnNetworkCallback cb,
|
||||
void* data);
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
/* Remove the entry of the remote server with the matching ServerName */
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_deregisterServerOnNetwork(UA_Server *server,
|
||||
UA_String serverName);
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
|
||||
@@ -2222,6 +2232,7 @@ struct UA_ServerConfig {
|
||||
UA_ServerNotificationCallback sessionNotificationCallback;
|
||||
UA_ServerNotificationCallback serviceNotificationCallback;
|
||||
UA_ServerNotificationCallback subscriptionNotificationCallback;
|
||||
UA_ServerNotificationCallback discoveryNotificationCallback;
|
||||
#ifdef UA_ENABLE_AUDITING
|
||||
UA_ServerNotificationCallback auditNotificationCallback;
|
||||
#endif
|
||||
@@ -2351,25 +2362,29 @@ struct UA_ServerConfig {
|
||||
/* Discovery
|
||||
* ~~~~~~~~~ */
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
/* Enable the internal management of RegisteredServers (besides the local
|
||||
* server itself) via the RegisterServer and FindServer services. */
|
||||
UA_Boolean registeredServersEnabled;
|
||||
|
||||
/* Timeout in seconds when to automatically remove a registered server from
|
||||
* the list, if it doesn't re-register within the given time frame. A value
|
||||
* of 0 disables automatic removal. Default is 60 Minutes (60*60). Must be
|
||||
* bigger than 10 seconds, because cleanup is only triggered approximately
|
||||
* every 10 seconds. The server will still be removed depending on the
|
||||
* state of the semaphore file. */
|
||||
UA_UInt32 discoveryCleanupTimeout;
|
||||
UA_UInt32 registeredServerCleanupTimeout;
|
||||
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_Boolean mdnsEnabled;
|
||||
UA_MdnsDiscoveryConfiguration mdnsConfig;
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
UA_String mdnsInterfaceIP;
|
||||
# if !defined(UA_HAS_GETIFADDR)
|
||||
size_t mdnsIpAddressListSize;
|
||||
UA_UInt32 *mdnsIpAddressList;
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
/* mDNS based Announcement and Discovery is implemented in drivers that
|
||||
* attach to a server outside the main configuration (cf. server_driver.h).
|
||||
* The FindServersOnNetwork Server is however implemented by the server
|
||||
* itself. The drivers interact with the server via the Discovery API. For
|
||||
* example to add/update/remove a ServerOnNetwork structure. */
|
||||
|
||||
/* Enable the internal management of ServerOnNetwork entries and the
|
||||
* FindServersOnNetwork Service. This is used in conjunction with mDNS to
|
||||
* implement a Discovery Server that detects other servers on the
|
||||
* network. */
|
||||
UA_Boolean serversOnNetworkEnabled;
|
||||
#endif
|
||||
|
||||
/* Subscriptions
|
||||
|
||||
@@ -393,17 +393,6 @@ setDefaultConfig(UA_ServerConfig *conf, UA_UInt16 portNumber) {
|
||||
/* conf->applicationDescription.discoveryUrlsSize = 0; */
|
||||
/* conf->applicationDescription.discoveryUrls = NULL; */
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_MdnsDiscoveryConfiguration_clear(&conf->mdnsConfig);
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
conf->mdnsInterfaceIP = UA_STRING_NULL;
|
||||
# if !defined(UA_HAS_GETIFADDR)
|
||||
conf->mdnsIpAddressList = NULL;
|
||||
conf->mdnsIpAddressListSize = 0;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Custom DataTypes */
|
||||
/* conf->customDataTypesSize = 0; */
|
||||
/* conf->customDataTypes = NULL; */
|
||||
@@ -498,7 +487,7 @@ setDefaultConfig(UA_ServerConfig *conf, UA_UInt16 portNumber) {
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
conf->discoveryCleanupTimeout = 60 * 60;
|
||||
conf->registeredServerCleanupTimeout = 60 * 60;
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_HISTORIZING
|
||||
|
||||
@@ -526,84 +526,6 @@ PARSE_JSON(MessageSecurityMode) {
|
||||
"Unknown MessageSecurityMode '%S'", rawToken);
|
||||
return UA_STATUSCODE_BAD;
|
||||
}
|
||||
#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && defined(UA_ENABLE_DISCOVERY_MULTICAST_MDNSD) && !defined(UA_HAS_GETIFADDR)
|
||||
PARSE_JSON(UInt32ArrayField) {
|
||||
if(configFieldSize == NULL) {
|
||||
UA_LOG_ERROR(ctx->logging, UA_LOGCATEGORY_APPLICATION, "Pointer to the array size is not set.");
|
||||
return UA_STATUSCODE_BADARGUMENTSMISSING;
|
||||
}
|
||||
cj5_token tok = ctx->result.tokens[++ctx->index];
|
||||
UA_UInt32 *numberArray = (UA_UInt32*)UA_malloc(sizeof(UA_UInt32) * tok.size);
|
||||
size_t numberArraySize = 0;
|
||||
for(size_t j = tok.size; j > 0; j--) {
|
||||
UA_UInt32 value;
|
||||
UA_StatusCode retval = UInt32Field_parseJson(ctx, &value, NULL);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
UA_Array_delete(numberArray, numberArraySize, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
return retval;
|
||||
}
|
||||
numberArray[numberArraySize++] = value;
|
||||
}
|
||||
/* Add to the config */
|
||||
UA_UInt32 **field = (UA_UInt32**)configField;
|
||||
if(*configFieldSize > 0) {
|
||||
UA_Array_delete(*field, *configFieldSize,
|
||||
&UA_TYPES[UA_TYPES_UINT32]);
|
||||
*field = NULL;
|
||||
*configFieldSize = 0;
|
||||
}
|
||||
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
||||
if(numberArraySize > 0) {
|
||||
retval = UA_Array_copy(numberArray, numberArraySize,
|
||||
(void **)field, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
*configFieldSize = numberArraySize;
|
||||
}
|
||||
/* Clean up */
|
||||
UA_Array_delete(numberArray, numberArraySize, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
PARSE_JSON(MdnsConfigurationField) {
|
||||
UA_ServerConfig *config = (UA_ServerConfig*)configField;
|
||||
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
||||
cj5_token tok = ctx->result.tokens[++ctx->index];
|
||||
for(size_t j = tok.size/2; j > 0; j--) {
|
||||
tok = ctx->result.tokens[++ctx->index];
|
||||
switch (tok.type) {
|
||||
case CJ5_TOKEN_STRING: {
|
||||
char *field_str = (char*)UA_malloc(tok.size + 1);
|
||||
unsigned int str_len = 0;
|
||||
cj5_get_str(&ctx->result, (unsigned int)ctx->index, field_str, &str_len);
|
||||
if(strcmp(field_str, "mdnsServerName") == 0)
|
||||
retval = StringField_parseJson(ctx, &config->mdnsConfig.mdnsServerName, NULL);
|
||||
else if(strcmp(field_str, "serverCapabilities") == 0)
|
||||
retval = StringArrayField_parseJson(ctx, &config->mdnsConfig.serverCapabilities, &config->mdnsConfig.serverCapabilitiesSize);
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
else if(strcmp(field_str, "mdnsInterfaceIP") == 0)
|
||||
retval = StringField_parseJson(ctx, &config->mdnsInterfaceIP, NULL);
|
||||
/* mdnsIpAddressList and mdnsIpAddressListSize are only available if UA_HAS_GETIFADDR is not defined: */
|
||||
# if !defined(UA_HAS_GETIFADDR)
|
||||
else if(strcmp(field_str, "mdnsIpAddressList") == 0)
|
||||
retval = UInt32ArrayField_parseJson(ctx, &config->mdnsIpAddressList, &config->mdnsIpAddressListSize);
|
||||
# endif
|
||||
#endif
|
||||
else {
|
||||
LOG_UNKNOWN_FIELD(ctx, field_str);
|
||||
}
|
||||
UA_free(field_str);
|
||||
if(retval != UA_STATUSCODE_GOOD) {
|
||||
return retval;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
PARSE_JSON(SubscriptionConfigurationField) {
|
||||
@@ -1127,14 +1049,12 @@ parseJSONServerConfig(UA_ServerConfig *config, UA_ByteString json_config) {
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
else if(strcmp(field, "discoveryCleanupTimeout") == 0)
|
||||
retval = UInt32Field_parseJson(&ctx, &config->discoveryCleanupTimeout, NULL);
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
else if(strcmp(field, "mdnsEnabled") == 0)
|
||||
retval = BooleanField_parseJson(&ctx, &config->mdnsEnabled, NULL);
|
||||
else if(strcmp(field, "mdns") == 0)
|
||||
retval = MdnsConfigurationField_parseJson(&ctx, config, NULL);
|
||||
#endif
|
||||
else if(strcmp(field, "registeredServersEnabled") == 0)
|
||||
retval = BooleanField_parseJson(&ctx, &config->registeredServersEnabled, NULL);
|
||||
else if(strcmp(field, "registeredServerCleanupTimeout") == 0)
|
||||
retval = UInt32Field_parseJson(&ctx, &config->registeredServerCleanupTimeout, NULL);
|
||||
else if(strcmp(field, "serversOnNetworkEnabled") == 0)
|
||||
retval = BooleanField_parseJson(&ctx, &config->serversOnNetworkEnabled, NULL);
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
|
||||
+80
-196
@@ -11,27 +11,23 @@
|
||||
* Copyright 2017 (c) Julian Grothoff
|
||||
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
|
||||
* Copyright 2017 (c) HMS Industrial Networks AB (Author: Jonas Green)
|
||||
* Copyright 2026 (c) o6 Automation GmbH (Author: Julius Pfrommer)
|
||||
*/
|
||||
|
||||
#include <open62541/client.h>
|
||||
#include <open62541/client_highlevel_async.h>
|
||||
|
||||
#include "ua_discovery.h"
|
||||
#include "ua_server_internal.h"
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
|
||||
void
|
||||
static void
|
||||
UA_DiscoveryManager_setState(UA_DiscoveryManager *dm,
|
||||
UA_LifecycleState state) {
|
||||
/* Check if open connections remain */
|
||||
if(state == UA_LIFECYCLESTATE_STOPPING ||
|
||||
state == UA_LIFECYCLESTATE_STOPPED) {
|
||||
state = UA_LIFECYCLESTATE_STOPPED;
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
if(UA_DiscoveryManager_getMdnsConnectionCount() > 0)
|
||||
state = UA_LIFECYCLESTATE_STOPPING;
|
||||
#endif
|
||||
|
||||
for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) {
|
||||
if(dm->registerRequests[i].client != NULL)
|
||||
state = UA_LIFECYCLESTATE_STOPPING;
|
||||
@@ -46,179 +42,6 @@ UA_DiscoveryManager_setState(UA_DiscoveryManager *dm,
|
||||
dm->drv.state = state;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_DiscoveryManager_free(struct UA_Driver *drv) {
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)drv;
|
||||
|
||||
if(drv->state != UA_LIFECYCLESTATE_STOPPED) {
|
||||
UA_LOG_ERROR(drv->server->config.logging, UA_LOGCATEGORY_SERVER,
|
||||
"Cannot delete the DiscoveryManager because "
|
||||
"it is not stopped");
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
registeredServer *rs, *rs_tmp;
|
||||
LIST_FOREACH_SAFE(rs, &dm->registeredServers, pointers, rs_tmp) {
|
||||
LIST_REMOVE(rs, pointers);
|
||||
UA_RegisteredServer_clear(&rs->registeredServer);
|
||||
UA_free(rs);
|
||||
}
|
||||
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_DiscoveryManager_clearMdns(dm);
|
||||
# endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
|
||||
UA_free(drv);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
/* Cleanup server registration: If the semaphore file path is set, then it just
|
||||
* checks the existence of the file. When it is deleted, the registration is
|
||||
* removed. If there is no semaphore file, then the registration will be removed
|
||||
* if it is older than 60 minutes. */
|
||||
static void
|
||||
UA_DiscoveryManager_cleanupTimedOut(UA_Server *server, void *data) {
|
||||
UA_EventLoop *el = server->config.eventLoop;
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)data;
|
||||
|
||||
/* TimedOut gives the last DateTime at which we must have seen the
|
||||
* registered server. Otherwise it is timed out. */
|
||||
UA_DateTime timedOut = el->dateTime_nowMonotonic(el);
|
||||
if(server->config.discoveryCleanupTimeout)
|
||||
timedOut -= server->config.discoveryCleanupTimeout * UA_DATETIME_SEC;
|
||||
|
||||
registeredServer *current, *temp;
|
||||
LIST_FOREACH_SAFE(current, &dm->registeredServers, pointers, temp) {
|
||||
UA_Boolean semaphoreDeleted = false;
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
|
||||
if(current->registeredServer.semaphoreFilePath.length) {
|
||||
size_t fpSize = current->registeredServer.semaphoreFilePath.length+1;
|
||||
char* filePath = (char *)UA_malloc(fpSize);
|
||||
if(filePath) {
|
||||
memcpy(filePath, current->registeredServer.semaphoreFilePath.data,
|
||||
current->registeredServer.semaphoreFilePath.length );
|
||||
filePath[current->registeredServer.semaphoreFilePath.length] = '\0';
|
||||
semaphoreDeleted = UA_fileExists(filePath) == false;
|
||||
UA_free(filePath);
|
||||
} else {
|
||||
UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
|
||||
"Cannot check registration semaphore. Out of memory");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(semaphoreDeleted ||
|
||||
(server->config.discoveryCleanupTimeout &&
|
||||
current->lastSeen < timedOut)) {
|
||||
if(semaphoreDeleted) {
|
||||
UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER,
|
||||
"Registration of server with URI %S is removed because "
|
||||
"the semaphore file '%S' was deleted",
|
||||
current->registeredServer.serverUri,
|
||||
current->registeredServer.semaphoreFilePath);
|
||||
} else {
|
||||
// cppcheck-suppress unreadVariable
|
||||
UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER,
|
||||
"Registration of server with URI %S has timed out "
|
||||
"and is removed", current->registeredServer.serverUri);
|
||||
}
|
||||
LIST_REMOVE(current, pointers);
|
||||
UA_RegisteredServer_clear(¤t->registeredServer);
|
||||
UA_free(current);
|
||||
dm->registeredServersSize--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UA_DiscoveryManager_cyclicTimer(UA_Server *server, void *data) {
|
||||
UA_DiscoveryManager_cleanupTimedOut(server, data);
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_DiscoveryManager_mdnsCyclicTimer(server, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_DiscoveryManager_start(struct UA_Driver *drv) {
|
||||
/* Check that the server backpointer is set */
|
||||
UA_Server *server = drv->server;
|
||||
if(!server)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
/* Cannot start an already started DiscoveryManager */
|
||||
if(drv->state != UA_LIFECYCLESTATE_STOPPED)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)drv;
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_DiscoveryManager_resetServerOnNetworkRecordCounter(dm);
|
||||
#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
|
||||
UA_StatusCode res =
|
||||
addRepeatedCallback(server, UA_DiscoveryManager_cyclicTimer,
|
||||
dm, 1000.0, &dm->discoveryCallbackId);
|
||||
if(res != UA_STATUSCODE_GOOD)
|
||||
return res;
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
if(server->config.mdnsEnabled)
|
||||
UA_DiscoveryManager_startMulticast(dm);
|
||||
#endif
|
||||
|
||||
UA_DiscoveryManager_setState(dm, UA_LIFECYCLESTATE_STARTED);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
UA_DiscoveryManager_stop(struct UA_Driver *drv) {
|
||||
if(drv->state != UA_LIFECYCLESTATE_STARTED)
|
||||
return;
|
||||
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)drv;
|
||||
|
||||
/* Set STOPPING early so that CLOSING callbacks (fired by stopMulticast
|
||||
* below) do not trigger UA_DiscoveryManager_startMulticast and re-open
|
||||
* connections that would prevent the DM from reaching STOPPED. */
|
||||
drv->state = UA_LIFECYCLESTATE_STOPPING;
|
||||
|
||||
removeCallback(drv->server, dm->discoveryCallbackId);
|
||||
|
||||
/* Cancel all outstanding register requests */
|
||||
for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) {
|
||||
if(dm->registerRequests[i].client == NULL)
|
||||
continue;
|
||||
UA_Client_disconnectSecureChannelAsync(dm->registerRequests[i].client);
|
||||
}
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
if(drv->server->config.mdnsEnabled)
|
||||
UA_DiscoveryManager_stopMulticast(dm);
|
||||
#endif
|
||||
|
||||
UA_DiscoveryManager_setState(dm, UA_LIFECYCLESTATE_STOPPED);
|
||||
}
|
||||
|
||||
UA_Driver *
|
||||
UA_DiscoveryManager_new(void) {
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)
|
||||
UA_calloc(1, sizeof(UA_DiscoveryManager));
|
||||
if(!dm)
|
||||
return NULL;
|
||||
|
||||
dm->drv.name = UA_STRING("discovery");
|
||||
dm->drv.start = UA_DiscoveryManager_start;
|
||||
dm->drv.stop = UA_DiscoveryManager_stop;
|
||||
dm->drv.free = UA_DiscoveryManager_free;
|
||||
return &dm->drv;
|
||||
}
|
||||
|
||||
/********************************/
|
||||
/* Register at Discovery Server */
|
||||
/********************************/
|
||||
|
||||
static void
|
||||
asyncRegisterRequest_clear(void *_, void *context) {
|
||||
asyncRegisterRequest *ar = (asyncRegisterRequest*)context;
|
||||
@@ -376,9 +199,6 @@ discoveryClientStateCallback(UA_Client *client,
|
||||
const UA_DataType *respType;
|
||||
UA_RegisterServerRequest reg1;
|
||||
UA_RegisterServer2Request reg2;
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_ExtensionObject mdnsConfig;
|
||||
#endif
|
||||
void *request;
|
||||
|
||||
/* Prepare the request. This does not allocate memory */
|
||||
@@ -389,14 +209,12 @@ discoveryClientStateCallback(UA_Client *client,
|
||||
respType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE];
|
||||
request = ®2;
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
/* Set the configuration that is only available for
|
||||
* UA_RegisterServer2Request */
|
||||
UA_ExtensionObject_setValueNoDelete(&mdnsConfig, &sc->mdnsConfig,
|
||||
&UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]);
|
||||
reg2.discoveryConfigurationSize = 1;
|
||||
reg2.discoveryConfiguration = &mdnsConfig;
|
||||
#endif
|
||||
/* /\* Set the configuration that is only available for */
|
||||
/* * UA_RegisterServer2Request *\/ */
|
||||
/* UA_ExtensionObject_setValueNoDelete(&mdnsConfig, &sc->mdnsSelfConfig, */
|
||||
/* &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]); */
|
||||
/* reg2.discoveryConfigurationSize = 1; */
|
||||
/* reg2.discoveryConfiguration = &mdnsConfig; */
|
||||
} else {
|
||||
UA_RegisterServerRequest_init(®1);
|
||||
setupRegisterRequest(ar, ®1.requestHeader, ®1.server);
|
||||
@@ -420,9 +238,9 @@ discoveryClientStateCallback(UA_Client *client,
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_Server_register(UA_Server *server, UA_ClientConfig *cc, UA_Boolean unregister,
|
||||
const UA_String discoveryServerUrl,
|
||||
const UA_String semaphoreFilePath) {
|
||||
registerDiscovery(UA_Server *server, UA_ClientConfig *cc, UA_Boolean unregister,
|
||||
const UA_String discoveryServerUrl,
|
||||
const UA_String semaphoreFilePath) {
|
||||
/* Get the discovery manager */
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)server->discoveryDriver;
|
||||
if(!dm) {
|
||||
@@ -511,7 +329,7 @@ UA_Server_registerDiscovery(UA_Server *server, UA_ClientConfig *cc,
|
||||
"Registering at the DiscoveryServer: %S", discoveryServerUrl);
|
||||
lockServer(server);
|
||||
UA_StatusCode res =
|
||||
UA_Server_register(server, cc, false, discoveryServerUrl, semaphoreFilePath);
|
||||
registerDiscovery(server, cc, false, discoveryServerUrl, semaphoreFilePath);
|
||||
unlockServer(server);
|
||||
return res;
|
||||
}
|
||||
@@ -523,9 +341,75 @@ UA_Server_deregisterDiscovery(UA_Server *server, UA_ClientConfig *cc,
|
||||
"Deregistering at the DiscoveryServer: %S", discoveryServerUrl);
|
||||
lockServer(server);
|
||||
UA_StatusCode res =
|
||||
UA_Server_register(server, cc, true, discoveryServerUrl, UA_STRING_NULL);
|
||||
registerDiscovery(server, cc, true, discoveryServerUrl, UA_STRING_NULL);
|
||||
unlockServer(server);
|
||||
return res;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_DiscoveryManager_free(struct UA_Driver *drv) {
|
||||
if(drv->state != UA_LIFECYCLESTATE_STOPPED) {
|
||||
UA_LOG_ERROR(drv->server->config.logging, UA_LOGCATEGORY_SERVER,
|
||||
"Cannot delete the DiscoveryManager because "
|
||||
"it is not stopped");
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
}
|
||||
|
||||
UA_free(drv);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
UA_DiscoveryManager_start(struct UA_Driver *drv) {
|
||||
/* Check that the server backpointer is set */
|
||||
UA_Server *server = drv->server;
|
||||
if(!server)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
/* Cannot start an already started DiscoveryManager */
|
||||
if(drv->state != UA_LIFECYCLESTATE_STOPPED)
|
||||
return UA_STATUSCODE_BADINTERNALERROR;
|
||||
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)drv;
|
||||
UA_DiscoveryManager_setState(dm, UA_LIFECYCLESTATE_STARTED);
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
static void
|
||||
UA_DiscoveryManager_stop(struct UA_Driver *drv) {
|
||||
if(drv->state != UA_LIFECYCLESTATE_STARTED)
|
||||
return;
|
||||
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)drv;
|
||||
|
||||
/* Set STOPPING early so that CLOSING callbacks (fired by stopMulticast
|
||||
* below) do not trigger UA_DiscoveryManager_startMulticast and re-open
|
||||
* connections that would prevent the DM from reaching STOPPED. */
|
||||
drv->state = UA_LIFECYCLESTATE_STOPPING;
|
||||
|
||||
/* Cancel all outstanding register requests */
|
||||
for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) {
|
||||
if(dm->registerRequests[i].client == NULL)
|
||||
continue;
|
||||
UA_Client_disconnectSecureChannelAsync(dm->registerRequests[i].client);
|
||||
}
|
||||
|
||||
UA_DiscoveryManager_setState(dm, UA_LIFECYCLESTATE_STOPPED);
|
||||
}
|
||||
|
||||
UA_Driver *
|
||||
UA_DiscoveryManager_new(void) {
|
||||
UA_DiscoveryManager *dm = (UA_DiscoveryManager*)
|
||||
UA_calloc(1, sizeof(UA_DiscoveryManager));
|
||||
if(!dm)
|
||||
return NULL;
|
||||
|
||||
dm->drv.name = UA_STRING("discovery");
|
||||
dm->drv.start = UA_DiscoveryManager_start;
|
||||
dm->drv.stop = UA_DiscoveryManager_stop;
|
||||
dm->drv.free = UA_DiscoveryManager_free;
|
||||
return &dm->drv;
|
||||
}
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
|
||||
@@ -20,18 +20,13 @@ _UA_BEGIN_DECLS
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
struct UA_DiscoveryManager;
|
||||
typedef struct UA_DiscoveryManager UA_DiscoveryManager;
|
||||
#endif
|
||||
|
||||
typedef struct registeredServer {
|
||||
LIST_ENTRY(registeredServer) pointers;
|
||||
UA_RegisteredServer registeredServer;
|
||||
UA_DateTime lastSeen;
|
||||
} registeredServer;
|
||||
|
||||
/* Store async register service calls. So we can cancel outstanding requests
|
||||
/* The DiscoveryManager holds the state of clients that register at a
|
||||
* DiscoveryServer.
|
||||
*
|
||||
* Store async register service calls. So we can cancel outstanding requests
|
||||
* during shutdown. */
|
||||
typedef struct {
|
||||
UA_DelayedCallback cleanupCallback; /* delayed cleanup */
|
||||
@@ -45,84 +40,16 @@ typedef struct {
|
||||
UA_Boolean shutdown;
|
||||
UA_Boolean connectSuccess;
|
||||
} asyncRegisterRequest;
|
||||
|
||||
#define UA_MAXREGISTERREQUESTS 4
|
||||
|
||||
struct UA_DiscoveryManager {
|
||||
UA_Driver drv;
|
||||
|
||||
UA_UInt64 discoveryCallbackId;
|
||||
|
||||
/* Outstanding requests. So they can be cancelled during shutdown. */
|
||||
asyncRegisterRequest registerRequests[UA_MAXREGISTERREQUESTS];
|
||||
|
||||
LIST_HEAD(, registeredServer) registeredServers;
|
||||
size_t registeredServersSize;
|
||||
UA_Server_registerServerCallback registerServerCallback;
|
||||
void* registerServerCallbackData;
|
||||
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_Boolean mdnsMainSrvAdded;
|
||||
UA_Server_serverOnNetworkCallback serverOnNetworkCallback;
|
||||
void *serverOnNetworkCallbackData;
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
UA_ConnectionManager *cm;
|
||||
# endif
|
||||
# endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
};
|
||||
|
||||
void
|
||||
UA_DiscoveryManager_setState(UA_DiscoveryManager *dm,
|
||||
UA_LifecycleState state);
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
|
||||
/* Sends out a new mDNS package for the given server data. This Method is
|
||||
* normally called when another server calls the RegisterServer Service on this
|
||||
* server. Then this server is responsible to send out a new mDNS package to
|
||||
* announce it.
|
||||
*
|
||||
* Additionally this method also adds the given server to the internal
|
||||
* serversOnNetwork list so that a client finds it when calling
|
||||
* FindServersOnNetwork. */
|
||||
void
|
||||
UA_Discovery_updateMdnsForDiscoveryUrl(UA_DiscoveryManager *dm, const UA_String serverName,
|
||||
const UA_MdnsDiscoveryConfiguration *mdnsConfig,
|
||||
const UA_String discoveryUrl, UA_Boolean isOnline,
|
||||
UA_Boolean updateTxt);
|
||||
|
||||
void UA_DiscoveryManager_startMulticast(UA_DiscoveryManager *dm);
|
||||
void UA_DiscoveryManager_stopMulticast(UA_DiscoveryManager *dm);
|
||||
|
||||
void
|
||||
UA_DiscoveryManager_clearMdns(UA_DiscoveryManager *dm);
|
||||
|
||||
UA_UInt32
|
||||
UA_DiscoveryManager_getMdnsConnectionCount(void);
|
||||
|
||||
UA_UInt32
|
||||
UA_DiscoveryManager_getServerOnNetworkRecordIdCounter(UA_DiscoveryManager *dm);
|
||||
|
||||
UA_StatusCode
|
||||
UA_DiscoveryManager_resetServerOnNetworkRecordCounter(UA_DiscoveryManager *dm);
|
||||
|
||||
UA_DateTime
|
||||
UA_DiscoveryManager_getServerOnNetworkCounterResetTime(UA_DiscoveryManager *dm);
|
||||
|
||||
UA_ServerOnNetwork*
|
||||
UA_DiscoveryManager_getServerOnNetworkList(UA_DiscoveryManager *dm);
|
||||
|
||||
UA_ServerOnNetwork*
|
||||
UA_DiscoveryManager_getNextServerOnNetworkRecord(UA_DiscoveryManager *dm,
|
||||
UA_ServerOnNetwork *current);
|
||||
|
||||
UA_StatusCode
|
||||
UA_DiscoveryManager_clearServerOnNetwork(UA_DiscoveryManager *dm);
|
||||
|
||||
void
|
||||
UA_DiscoveryManager_mdnsCyclicTimer(UA_Server *server, void *data);
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
|
||||
_UA_END_DECLS
|
||||
|
||||
+33
-1
@@ -22,6 +22,10 @@
|
||||
|
||||
#include "ua_server_internal.h"
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
#include "ua_discovery.h"
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
#include "ua_subscription.h"
|
||||
#endif
|
||||
@@ -495,11 +499,30 @@ UA_Server_delete(UA_Server *server) {
|
||||
|
||||
unlockServer(server); /* The timer has its own mutex */
|
||||
|
||||
#ifdef UA_ENABLE_RBAC
|
||||
/* Clean up internal RBAC state (before config clear) */
|
||||
#ifdef UA_ENABLE_RBAC
|
||||
UA_Server_cleanupRBAC(server);
|
||||
#endif
|
||||
|
||||
/* Clean up Discovery entries */
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
/* Remove registered servers. Don't notify the application here */
|
||||
RegisteredServerRecord *rs, *rs_tmp;
|
||||
LIST_FOREACH_SAFE(rs, &server->registeredServers, pointers, rs_tmp) {
|
||||
LIST_REMOVE(rs, pointers);
|
||||
UA_RegisteredServer_clear(&rs->registeredServer);
|
||||
UA_free(rs);
|
||||
}
|
||||
server->registeredServersSize = 0;
|
||||
|
||||
/* Remove ServersOnNetwork */
|
||||
UA_Array_delete(server->serversOnNetwork,
|
||||
server->serversOnNetworkSize,
|
||||
&UA_TYPES[UA_TYPES_SERVERONNETWORK]);
|
||||
server->serversOnNetwork = NULL;
|
||||
server->serversOnNetworkSize = 0;
|
||||
#endif
|
||||
|
||||
/* Clean up the config */
|
||||
UA_ServerConfig_clear(&server->config);
|
||||
|
||||
@@ -532,6 +555,9 @@ serverHouseKeeping(UA_Server *server, void *_) {
|
||||
lockServer(server);
|
||||
UA_EventLoop *el = server->config.eventLoop;
|
||||
cleanupSessions(server, el->dateTime_nowMonotonic(el));
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
cleanupRegisteredServers(server);
|
||||
#endif
|
||||
unlockServer(server);
|
||||
}
|
||||
|
||||
@@ -646,6 +672,12 @@ UA_Server_init(UA_Server *server) {
|
||||
server->discoveryDriver = UA_DiscoveryManager_new();
|
||||
res = addDriver(server, server->discoveryDriver);
|
||||
UA_CHECK_STATUS(res, goto cleanup);
|
||||
|
||||
UA_EventLoop *el = server->config.eventLoop;
|
||||
server->lastCounterResetTime = el->dateTime_now(el);
|
||||
server->serversOnNetworkRecordCounter = 1;
|
||||
server->serversOnNetworkSize = 0;
|
||||
server->serversOnNetwork = NULL;
|
||||
#endif
|
||||
|
||||
/* Initialize PubSub */
|
||||
|
||||
@@ -18,17 +18,6 @@ UA_ServerConfig_clear(UA_ServerConfig *config) {
|
||||
/* Server Description */
|
||||
UA_BuildInfo_clear(&config->buildInfo);
|
||||
UA_ApplicationDescription_clear(&config->applicationDescription);
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_MdnsDiscoveryConfiguration_clear(&config->mdnsConfig);
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST_MDNSD
|
||||
UA_String_clear(&config->mdnsInterfaceIP);
|
||||
# if !defined(UA_HAS_GETIFADDR)
|
||||
if (config->mdnsIpAddressListSize) {
|
||||
UA_free(config->mdnsIpAddressList);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Stop and delete the EventLoop */
|
||||
UA_EventLoop *el = config->eventLoop;
|
||||
|
||||
@@ -132,6 +132,7 @@ UA_GDSManager_clear(UA_GDSManager *gdsManager);
|
||||
/********************/
|
||||
|
||||
#ifdef UA_ENABLE_RBAC
|
||||
|
||||
/* Internal role-permission entry with reference counting.
|
||||
* Multiple nodes can share the same entry via the permissionIndex stored
|
||||
* in the node head. Entries originating from the server configuration
|
||||
@@ -157,8 +158,19 @@ void UA_Server_cleanupRBAC(UA_Server *server);
|
||||
|
||||
/* Initialize RBAC information model (NS0 role representations and methods) */
|
||||
UA_StatusCode initNS0RBAC(UA_Server *server);
|
||||
|
||||
#endif /* UA_ENABLE_RBAC */
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
|
||||
typedef struct RegisteredServerRecord {
|
||||
LIST_ENTRY(RegisteredServerRecord) pointers;
|
||||
UA_RegisteredServer registeredServer;
|
||||
UA_DateTime lastSeen;
|
||||
} RegisteredServerRecord;
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
|
||||
typedef struct session_list_entry {
|
||||
UA_DelayedCallback cleanupCallback;
|
||||
LIST_ENTRY(session_list_entry) pointers;
|
||||
@@ -269,6 +281,19 @@ struct UA_Server {
|
||||
size_t namespaceMetadataSize;
|
||||
UA_NamespaceMetadata *namespaceMetadata;
|
||||
#endif
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
/* Registered Servers */
|
||||
LIST_HEAD(, RegisteredServerRecord) registeredServers;
|
||||
size_t registeredServersSize;
|
||||
|
||||
/* Servers On Network
|
||||
* TODO: Use a TAILQ for easier updates */
|
||||
UA_UInt32 serversOnNetworkRecordCounter;
|
||||
UA_DateTime lastCounterResetTime;
|
||||
size_t serversOnNetworkSize;
|
||||
UA_ServerOnNetwork *serversOnNetwork;
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
};
|
||||
|
||||
/* In case the configuration was updated. Make the ->next pointer in the
|
||||
@@ -721,6 +746,7 @@ addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
UA_Driver * UA_DiscoveryManager_new(void);
|
||||
void cleanupRegisteredServers(UA_Server *server);
|
||||
#endif
|
||||
|
||||
UA_Driver * UA_BinaryProtocolManager_new(void);
|
||||
|
||||
@@ -1123,16 +1123,9 @@ configureNS0(UA_Server *server) {
|
||||
|
||||
/* ServerConfiguration - MulticastDnsEnabled */
|
||||
#ifdef UA_GENERATED_NAMESPACE_ZERO_FULL
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED,
|
||||
&server->config.mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
#else
|
||||
{
|
||||
UA_Boolean mdnsEnabled = false;
|
||||
retVal |= writeNs0Variable(server, UA_NS0ID_SERVERCONFIGURATION_MULTICASTDNSENABLED,
|
||||
&mdnsEnabled, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
}
|
||||
#endif
|
||||
&server->config.serversOnNetworkEnabled,
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
#endif
|
||||
|
||||
#ifdef UA_GENERATED_NAMESPACE_ZERO_FULL
|
||||
|
||||
@@ -53,11 +53,9 @@ static UA_ServiceDescription serviceDescriptions[] = {
|
||||
{UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY,
|
||||
UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_RegisterServer2,
|
||||
&UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST], &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]},
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
{UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY,
|
||||
UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)Service_FindServersOnNetwork,
|
||||
&UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]},
|
||||
# endif
|
||||
#endif
|
||||
{UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY,
|
||||
UA_SERVICECOUNTER_OFFSET_NONE(false), (UA_Service)(uintptr_t)Service_CreateSession,
|
||||
@@ -223,7 +221,7 @@ processServiceInternal(UA_Server *server, UA_SecureChannel *channel, UA_Session
|
||||
channel->securityPolicy->policyType == UA_SECURITYPOLICYTYPE_NONE &&
|
||||
sd->requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] &&
|
||||
sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]
|
||||
#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
|
||||
#if defined(UA_ENABLE_DISCOVERY)
|
||||
&& sd->requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
|
||||
#endif
|
||||
) {
|
||||
|
||||
@@ -65,15 +65,11 @@ Service_RegisterServer2(UA_Server *server, UA_Session *session,
|
||||
const UA_RegisterServer2Request *request,
|
||||
UA_RegisterServer2Response *response);
|
||||
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
|
||||
UA_Boolean
|
||||
Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
|
||||
const UA_FindServersOnNetworkRequest *request,
|
||||
UA_FindServersOnNetworkResponse *response);
|
||||
|
||||
# endif /* UA_ENABLE_DISCOVERY_MULTICAST */
|
||||
|
||||
#endif /* UA_ENABLE_DISCOVERY */
|
||||
|
||||
/** SecureChannel Service Set **/
|
||||
|
||||
+652
-256
File diff suppressed because it is too large
Load Diff
@@ -298,9 +298,7 @@ typedef union {
|
||||
UA_FindServersRequest findServersRequest;
|
||||
UA_GetEndpointsRequest getEndpointsRequest;
|
||||
#ifdef UA_ENABLE_DISCOVERY
|
||||
# ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
UA_FindServersOnNetworkRequest findServersOnNetworkRequest;
|
||||
# endif
|
||||
UA_RegisterServerRequest registerServerRequest;
|
||||
UA_RegisterServer2Request registerServer2Request;
|
||||
#endif
|
||||
|
||||
@@ -86,16 +86,7 @@ configure_lds_server(UA_Server *pServer) {
|
||||
UA_LocalizedText_clear(&config_lds->applicationDescription.applicationName);
|
||||
config_lds->applicationDescription.applicationName =
|
||||
UA_LOCALIZEDTEXT_ALLOC("en", "LDS Server");
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
config_lds->mdnsEnabled = true;
|
||||
config_lds->mdnsConfig.mdnsServerName = UA_String_fromChars("LDS_test");
|
||||
config_lds->mdnsConfig.serverCapabilitiesSize = 2;
|
||||
UA_String *caps = (UA_String *)UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
|
||||
caps[0] = UA_String_fromChars("LDS");
|
||||
caps[1] = UA_String_fromChars("MyFancyCap");
|
||||
config_lds->mdnsConfig.serverCapabilities = caps;
|
||||
#endif
|
||||
config_lds->discoveryCleanupTimeout = registerTimeout;
|
||||
config_lds->registeredServerCleanupTimeout = registerTimeout;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -169,10 +160,6 @@ setup_register(void) {
|
||||
UA_LocalizedText_clear(&config_register->applicationDescription.applicationName);
|
||||
config_register->applicationDescription.applicationName =
|
||||
UA_LOCALIZEDTEXT_ALLOC("de", "Anmeldungsserver");
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
config_register->mdnsConfig.mdnsServerName = UA_String_fromChars("Register_test");
|
||||
#endif
|
||||
|
||||
UA_Server_run_startup(server_register);
|
||||
THREAD_CREATE(server_thread_register, serverloop_register);
|
||||
}
|
||||
@@ -413,67 +400,6 @@ FindAndCheckDiscoveryUrls(const char *requestedEndpointUrl,
|
||||
return ok;
|
||||
}
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
|
||||
static void
|
||||
FindOnNetworkAndCheck(UA_String expectedServerNames[], size_t expectedServerNamesSize,
|
||||
const char *filterUri, const char *filterLocale,
|
||||
const char** filterCapabilities, size_t filterCapabilitiesSize) {
|
||||
UA_Client *client = UA_Client_newForUnitTest();
|
||||
|
||||
UA_ServerOnNetwork* serverOnNetwork = NULL;
|
||||
size_t serverOnNetworkSize = 0;
|
||||
|
||||
size_t serverCapabilityFilterSize = 0;
|
||||
UA_String *serverCapabilityFilter = NULL;
|
||||
|
||||
if(filterCapabilitiesSize) {
|
||||
serverCapabilityFilterSize = filterCapabilitiesSize;
|
||||
serverCapabilityFilter =
|
||||
(UA_String*)UA_malloc(sizeof(UA_String) * filterCapabilitiesSize);
|
||||
for(size_t i = 0; i < filterCapabilitiesSize; i++)
|
||||
serverCapabilityFilter[i] = UA_String_fromChars(filterCapabilities[i]);
|
||||
}
|
||||
|
||||
UA_StatusCode retval =
|
||||
UA_Client_findServersOnNetwork(client, "opc.tcp://localhost:4840", 0, 0,
|
||||
serverCapabilityFilterSize, serverCapabilityFilter,
|
||||
&serverOnNetworkSize, &serverOnNetwork);
|
||||
|
||||
if(serverCapabilityFilterSize)
|
||||
UA_Array_delete(serverCapabilityFilter, serverCapabilityFilterSize,
|
||||
&UA_TYPES[UA_TYPES_STRING]);
|
||||
|
||||
ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD);
|
||||
|
||||
// only the discovery server is expected
|
||||
ck_assert_uint_eq(serverOnNetworkSize , expectedServerNamesSize);
|
||||
|
||||
if(expectedServerNamesSize > 0)
|
||||
ck_assert_ptr_ne(serverOnNetwork, NULL);
|
||||
|
||||
if(serverOnNetwork != NULL) {
|
||||
for(size_t i = 0; i < expectedServerNamesSize; i++) {
|
||||
UA_Boolean expectedServerNameInServerOnNetwork = false;
|
||||
for(size_t j = 0;
|
||||
j < expectedServerNamesSize && !expectedServerNameInServerOnNetwork; j++) {
|
||||
expectedServerNameInServerOnNetwork =
|
||||
UA_String_equal(&serverOnNetwork[j].serverName,
|
||||
&expectedServerNames[i]);
|
||||
}
|
||||
ck_assert_msg(expectedServerNameInServerOnNetwork,
|
||||
"Expected %.*s in serverOnNetwork list, but not found",
|
||||
(int)expectedServerNames[i].length, expectedServerNames[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
UA_Array_delete(serverOnNetwork, serverOnNetworkSize,
|
||||
&UA_TYPES[UA_TYPES_SERVERONNETWORK]);
|
||||
|
||||
UA_Client_disconnect(client);
|
||||
UA_Client_delete(client);
|
||||
}
|
||||
|
||||
static UA_StatusCode
|
||||
GetEndpoints(UA_Client *client, const UA_String* endpointUrl,
|
||||
size_t* endpointDescriptionsSize,
|
||||
@@ -565,44 +491,6 @@ Client_filter_locale(void) {
|
||||
return FindAndCheck(expectedUris, 2, expectedLocales, expectedNames, NULL, "en");
|
||||
}
|
||||
|
||||
// Test if registered server is returned from LDS using FindServersOnNetwork
|
||||
static void
|
||||
Client_find_on_network_registered(void) {
|
||||
char urls[2][384];
|
||||
UA_String expectedUris[2];
|
||||
char hostname[256];
|
||||
|
||||
ck_assert_int_eq(gethostname(hostname, 255), 0);
|
||||
|
||||
// DNS limits name to max 63 chars (+ \0). We need this ugly casting,
|
||||
// otherwise gcc >7.2 will complain about format-truncation, but we want it
|
||||
// here
|
||||
void *hostnameVoid = (void*)hostname;
|
||||
snprintf(urls[0], 384, "LDS_test-%s", (char*)hostnameVoid);
|
||||
snprintf(urls[1], 384, "Register_test-%s", (char*)hostnameVoid);
|
||||
expectedUris[0] = UA_STRING(urls[0]);
|
||||
expectedUris[1] = UA_STRING(urls[1]);
|
||||
FindOnNetworkAndCheck(expectedUris, 2, NULL, NULL, NULL, 0);
|
||||
|
||||
// filter by Capabilities
|
||||
const char* capsLDS[] = {"LDS"};
|
||||
const char* capsNA[] = {"NA"};
|
||||
const char* capsMultipleNone[] = {"LDS", "NA"};
|
||||
const char* capsMultipleCustom[] = {"LDS", "MyFancyCap"};
|
||||
const char* capsMultipleCustomIgnoreCase[] = {"LDS", "myfancycap"};
|
||||
|
||||
// only LDS expected
|
||||
FindOnNetworkAndCheck(expectedUris, 1, NULL, NULL, capsLDS, 1);
|
||||
// only register server expected
|
||||
FindOnNetworkAndCheck(&expectedUris[1], 1, NULL, NULL, capsNA, 1);
|
||||
// no server expected
|
||||
FindOnNetworkAndCheck(NULL, 0, NULL, NULL, capsMultipleNone, 2);
|
||||
// only LDS expected
|
||||
FindOnNetworkAndCheck(expectedUris, 1, NULL, NULL, capsMultipleCustom, 2);
|
||||
// only LDS expected
|
||||
FindOnNetworkAndCheck(expectedUris, 1, NULL, NULL, capsMultipleCustomIgnoreCase, 2);
|
||||
}
|
||||
|
||||
// Test if filtering with uris works
|
||||
static UA_Boolean
|
||||
Client_find_filter(void) {
|
||||
@@ -630,8 +518,6 @@ Client_get_endpoints(void) {
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Test if discovery server lists himself as registered server, before any other registration.
|
||||
static UA_Boolean
|
||||
Client_find_discovery(void) {
|
||||
@@ -720,7 +606,6 @@ START_TEST(Server_findServers_mirrors_endpointUrl) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
START_TEST(Server_registerFindServers) {
|
||||
while(!Client_find_discovery()) {}
|
||||
|
||||
@@ -728,10 +613,6 @@ START_TEST(Server_registerFindServers) {
|
||||
|
||||
while(!Client_find_registered()) {}
|
||||
|
||||
UA_fakeSleep(4000);
|
||||
|
||||
Client_find_on_network_registered();
|
||||
|
||||
while(!Client_find_filter()) {}
|
||||
|
||||
Client_get_endpoints();
|
||||
@@ -745,7 +626,6 @@ START_TEST(Server_registerFindServers) {
|
||||
while(!Client_filter_discovery()) {}
|
||||
}
|
||||
END_TEST
|
||||
#endif
|
||||
|
||||
static Suite* testSuite_Client(void) {
|
||||
Suite *s = suite_create("Register Server and Client");
|
||||
@@ -762,13 +642,11 @@ static Suite* testSuite_Client(void) {
|
||||
tcase_add_test(tc_register, Server_findServers_mirrors_endpointUrl);
|
||||
suite_add_tcase(s,tc_register);
|
||||
|
||||
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
||||
TCase *tc_register_find = tcase_create("RegisterServer and FindServers");
|
||||
tcase_add_unchecked_fixture(tc_register_find, setup_lds, teardown_lds);
|
||||
tcase_add_unchecked_fixture(tc_register_find, setup_register, teardown_register);
|
||||
tcase_add_test(tc_register_find, Server_registerFindServers);
|
||||
suite_add_tcase(s,tc_register_find);
|
||||
#endif
|
||||
|
||||
// register server again, then wait for timeout and auto unregister
|
||||
TCase *tc_register_timeout = tcase_create("RegisterServer timeout");
|
||||
|
||||
Reference in New Issue
Block a user