mirror of
https://github.com/open62541/open62541.git
synced 2026-10-29 13:20:10 +08:00
feat(discovery): mark ServerOnNetwork entries for announcement
The mDNS drivers announce every ServerOnNetwork entry that differs from their cache of received records. Whether an entry is announced therefore depends on its content instead of its origin. An entry that was received first and then added locally with the same content is never announced. And every registered server is announced, without a way to turn that off. This commit adds the 0:announce parameter to UA_Server_registerServerOnNetwork and the announceRegisteredServers config option for the entries of registered servers. The ServerOnNetwork notifications carry the flag as 0:announce. Entries without the parameter, such as the received ones, are not marked. The drivers do not use the flag yet.
This commit is contained in:
committed by
Julius Pfrommer
parent
d359379935
commit
d0994d2adb
@@ -614,6 +614,9 @@ typedef uint64_t UA_ApplicationNotificationType;
|
||||
* 0:ttl [UInt32]
|
||||
* Time-to-live of DNS information. Zero means infinite
|
||||
* (if the server is not currently getting removed).
|
||||
* 0:announce [Boolean]
|
||||
* Announce the entry on the network (for example over mDNS). False for
|
||||
* removed entries.
|
||||
* 0:server-added [Boolean]
|
||||
* They entry was added.
|
||||
* 0:server-updated [Boolean]
|
||||
|
||||
@@ -1932,15 +1932,18 @@ UA_Server_findServersOnNetwork(UA_Server *server, UA_String endpointUrl,
|
||||
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:
|
||||
/* Register a received or local 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:
|
||||
*
|
||||
* 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. */
|
||||
* Time-to-live of DNS information. Zero means infinite.
|
||||
* 0:announce [Boolean]
|
||||
* Announce the entry on the network, for example by an attached mDNS
|
||||
* driver. Default is false. */
|
||||
UA_StatusCode UA_EXPORT UA_THREADSAFE
|
||||
UA_Server_registerServerOnNetwork(UA_Server *server,
|
||||
const UA_ServerOnNetwork *son,
|
||||
@@ -2592,10 +2595,16 @@ struct UA_ServerConfig {
|
||||
* implement a Discovery Server that detects other servers on the
|
||||
* network. If registeredServersEnabled is also set, every registered
|
||||
* server gets a ServerOnNetwork entry under its mDNS name (the
|
||||
* mdnsServerName from RegisterServer2 or else the first ServerName). An
|
||||
* attached mDNS driver announces these entries on the network. */
|
||||
* mdnsServerName from RegisterServer2 or else the first ServerName). See
|
||||
* announceRegisteredServers for the announcement of these entries. */
|
||||
UA_Boolean serversOnNetworkEnabled;
|
||||
|
||||
/* Announce the ServerOnNetwork entries of locally registered servers on the
|
||||
* network. The entries are created and returned by FindServersOnNetwork
|
||||
* also without this. An attached mDNS driver with the 0:announce parameter
|
||||
* announces them. */
|
||||
UA_Boolean announceRegisteredServers;
|
||||
|
||||
/* Subscriptions
|
||||
* ~~~~~~~~~~~~~ */
|
||||
UA_Boolean subscriptionsEnabled;
|
||||
|
||||
@@ -1175,6 +1175,8 @@ parseJSONServerConfig(UA_ServerConfig *config, UA_ByteString json_config) {
|
||||
retval = UInt32Field_parseJson(&ctx, &config->registeredServerCleanupTimeout, NULL);
|
||||
else if(strcmp(field, "serversOnNetworkEnabled") == 0)
|
||||
retval = BooleanField_parseJson(&ctx, &config->serversOnNetworkEnabled, NULL);
|
||||
else if(strcmp(field, "announceRegisteredServers") == 0)
|
||||
retval = BooleanField_parseJson(&ctx, &config->announceRegisteredServers, NULL);
|
||||
|
||||
#ifdef UA_ENABLE_SUBSCRIPTIONS
|
||||
else if(strcmp(field, "subscriptionsEnabled") == 0)
|
||||
|
||||
@@ -226,13 +226,14 @@ UA_Server_findServers(UA_Server *server, UA_String endpointUrl,
|
||||
static void
|
||||
notifyServerOnNetwork(UA_Server *server,
|
||||
const UA_ServerOnNetwork *son,
|
||||
const UA_KeyValueMap params,
|
||||
const UA_KeyValueMap params, UA_Boolean announce,
|
||||
UA_Boolean added, UA_Boolean updated,
|
||||
UA_Boolean removed) {
|
||||
UA_STATIC_THREAD_LOCAL UA_KeyValuePair kvp[6] = {
|
||||
UA_STATIC_THREAD_LOCAL UA_KeyValuePair kvp[7] = {
|
||||
{{0, UA_STRING_STATIC("server-on-network")}, {0}},
|
||||
{{0, UA_STRING_STATIC("remote-address")}, {0}},
|
||||
{{0, UA_STRING_STATIC("ttl")}, {0}},
|
||||
{{0, UA_STRING_STATIC("announce")}, {0}},
|
||||
{{0, UA_STRING_STATIC("server-added")}, {0}},
|
||||
{{0, UA_STRING_STATIC("server-updated")}, {0}},
|
||||
{{0, UA_STRING_STATIC("server-removed")}, {0}},
|
||||
@@ -258,10 +259,11 @@ notifyServerOnNetwork(UA_Server *server,
|
||||
&UA_TYPES[UA_TYPES_SERVERONNETWORK]);
|
||||
UA_Variant_setScalar(&kvp[1].value, &remote, &UA_TYPES[UA_TYPES_STRING]);
|
||||
UA_Variant_setScalar(&kvp[2].value, &ttl, &UA_TYPES[UA_TYPES_UINT32]);
|
||||
UA_Variant_setScalar(&kvp[3].value, &added, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_Variant_setScalar(&kvp[4].value, &updated, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_Variant_setScalar(&kvp[5].value, &removed, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_KeyValueMap kvm = {6, kvp};
|
||||
UA_Variant_setScalar(&kvp[3].value, &announce, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_Variant_setScalar(&kvp[4].value, &added, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_Variant_setScalar(&kvp[5].value, &updated, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_Variant_setScalar(&kvp[6].value, &removed, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_KeyValueMap kvm = {7, kvp};
|
||||
|
||||
notifyApplication(server,
|
||||
UA_APPLICATIONNOTIFICATIONTYPE_DISCOVERY_SERVERONNETWORK,
|
||||
@@ -449,7 +451,7 @@ findServerOnNetworkIndex(UA_Server *server,
|
||||
|
||||
static UA_StatusCode
|
||||
addServerOnNetwork(UA_Server *server, const UA_ServerOnNetwork *newSon,
|
||||
const UA_KeyValueMap params) {
|
||||
const UA_KeyValueMap params, UA_Boolean announce) {
|
||||
UA_LOCK_ASSERT(&server->serviceMutex);
|
||||
|
||||
if(!newSon)
|
||||
@@ -476,7 +478,7 @@ addServerOnNetwork(UA_Server *server, const UA_ServerOnNetwork *newSon,
|
||||
*son = tmp;
|
||||
|
||||
/* Notify the application about an updated entry */
|
||||
notifyServerOnNetwork(server, son, params, false, true, false);
|
||||
notifyServerOnNetwork(server, son, params, announce, false, true, false);
|
||||
|
||||
/* All new RecordIds in increasing order */
|
||||
resetDiscoveryResetIds(server);
|
||||
@@ -496,7 +498,7 @@ addServerOnNetwork(UA_Server *server, const UA_ServerOnNetwork *newSon,
|
||||
son->recordId = ++server->serversOnNetworkRecordCounter;
|
||||
|
||||
/* Notify the application about an added entry */
|
||||
notifyServerOnNetwork(server, son, params, true, false, false);
|
||||
notifyServerOnNetwork(server, son, params, announce, true, false, false);
|
||||
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
@@ -516,7 +518,7 @@ removeServerOnNetwork(UA_Server *server, const UA_String serverName) {
|
||||
|
||||
/* Notify the application about removed entry */
|
||||
notifyServerOnNetwork(server, son, UA_KEYVALUEMAP_NULL,
|
||||
false, false, true);
|
||||
false, false, false, true);
|
||||
|
||||
/* Move the last entry in the current position */
|
||||
UA_ServerOnNetwork_clear(son);
|
||||
@@ -544,8 +546,12 @@ UA_StatusCode
|
||||
UA_Server_registerServerOnNetwork(UA_Server *server,
|
||||
const UA_ServerOnNetwork *newSon,
|
||||
const UA_KeyValueMap params) {
|
||||
const UA_Boolean *announce = (const UA_Boolean*)
|
||||
UA_KeyValueMap_getScalar(¶ms, UA_QUALIFIEDNAME(0, "announce"),
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
lockServer(server);
|
||||
UA_StatusCode res = addServerOnNetwork(server, newSon, params);
|
||||
UA_StatusCode res = addServerOnNetwork(server, newSon, params,
|
||||
announce ? *announce : false);
|
||||
unlockServer(server);
|
||||
return res;
|
||||
}
|
||||
@@ -1287,7 +1293,8 @@ process_RegisterServer(UA_Server *server, UA_Session *session,
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
res = addServerOnNetwork(server, &son, UA_KEYVALUEMAP_NULL);
|
||||
res = addServerOnNetwork(server, &son, UA_KEYVALUEMAP_NULL,
|
||||
sc->announceRegisteredServers);
|
||||
if(res != UA_STATUSCODE_GOOD) {
|
||||
UA_LOG_WARNING_SESSION(sc->logging, session,
|
||||
"Could not add the ServerOnNetwork entry "
|
||||
|
||||
@@ -520,6 +520,77 @@ START_TEST(register_server_empty_mdns_name_uses_server_name) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Notifications about ServerOnNetwork entries and the last 0:announce flag */
|
||||
static size_t sonNotifications;
|
||||
static UA_Boolean lastAnnounce;
|
||||
|
||||
static void
|
||||
announceNotificationCallback(UA_Server *server,
|
||||
UA_ApplicationNotificationType type,
|
||||
const UA_KeyValueMap payload) {
|
||||
(void)server;
|
||||
if(type != UA_APPLICATIONNOTIFICATIONTYPE_DISCOVERY_SERVERONNETWORK)
|
||||
return;
|
||||
const UA_Boolean *announce = (const UA_Boolean*)
|
||||
UA_KeyValueMap_getScalar(&payload, UA_QUALIFIEDNAME(0, "announce"),
|
||||
&UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
ck_assert_ptr_ne(announce, NULL);
|
||||
lastAnnounce = *announce;
|
||||
sonNotifications++;
|
||||
}
|
||||
|
||||
/* The entry of a registered server is created in either case. It is announced
|
||||
* only with announceRegisteredServers. */
|
||||
START_TEST(register_server_announce_follows_config) {
|
||||
UA_Boolean announceRegistered = (_i == 1);
|
||||
UA_Server *server = newRegistrationServer();
|
||||
server->config.announceRegisteredServers = announceRegistered;
|
||||
server->config.discoveryNotificationCallback = announceNotificationCallback;
|
||||
sonNotifications = 0;
|
||||
|
||||
registerWithMdnsName(server, NULL);
|
||||
ck_assert_uint_eq(sonNotifications, 1);
|
||||
ck_assert(lastAnnounce == announceRegistered);
|
||||
|
||||
UA_Server_delete(server);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Entries from the public API are announced only on request. Received entries
|
||||
* are added without the parameter. */
|
||||
START_TEST(register_server_on_network_announce_param) {
|
||||
UA_Server *server = newRegistrationServer();
|
||||
server->config.discoveryNotificationCallback = announceNotificationCallback;
|
||||
sonNotifications = 0;
|
||||
|
||||
UA_String caps = UA_STRING("NA");
|
||||
UA_ServerOnNetwork son;
|
||||
UA_ServerOnNetwork_init(&son);
|
||||
son.serverName = UA_STRING("local-entry");
|
||||
son.discoveryUrl = UA_STRING(REGISTERED_DISCOVERY_URL);
|
||||
son.serverCapabilitiesSize = 1;
|
||||
son.serverCapabilities = ∩︀
|
||||
|
||||
ck_assert_uint_eq(UA_Server_registerServerOnNetwork(server, &son,
|
||||
UA_KEYVALUEMAP_NULL),
|
||||
UA_STATUSCODE_GOOD);
|
||||
ck_assert_uint_eq(sonNotifications, 1);
|
||||
ck_assert(!lastAnnounce);
|
||||
|
||||
UA_Boolean announce = true;
|
||||
UA_KeyValuePair param;
|
||||
param.key = UA_QUALIFIEDNAME(0, "announce");
|
||||
UA_Variant_setScalar(¶m.value, &announce, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
||||
UA_KeyValueMap params = {1, ¶m};
|
||||
ck_assert_uint_eq(UA_Server_registerServerOnNetwork(server, &son, params),
|
||||
UA_STATUSCODE_GOOD);
|
||||
ck_assert_uint_eq(sonNotifications, 2);
|
||||
ck_assert(lastAnnounce);
|
||||
|
||||
UA_Server_delete(server);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static Suite *
|
||||
testSuite(void) {
|
||||
Suite *suite = suite_create("FindServersOnNetwork");
|
||||
@@ -539,6 +610,8 @@ testSuite(void) {
|
||||
tcase_add_loop_test(tc_registered, register_server_uses_tcp_discovery_url, 0, 2);
|
||||
tcase_add_test(tc_registered, reregister_server_without_tcp_url_removes_server_on_network);
|
||||
tcase_add_test(tc_registered, deregister_server_without_tcp_url_keeps_other_entry);
|
||||
tcase_add_loop_test(tc_registered, register_server_announce_follows_config, 0, 2);
|
||||
tcase_add_test(tc_registered, register_server_on_network_announce_param);
|
||||
suite_add_tcase(suite, tc_registered);
|
||||
TCase *tc_names = tcase_create("server names");
|
||||
tcase_add_test(tc_names, register_server_without_server_names_rejected);
|
||||
|
||||
Reference in New Issue
Block a user