diff --git a/doc/Changelog.md b/doc/Changelog.md index 621b7f1..7fcd0f2 100644 --- a/doc/Changelog.md +++ b/doc/Changelog.md @@ -3,6 +3,8 @@ # git master +* [82](https://github.com/HBPVis/Servus/pull/20): + Expose servus_host and servus_port keys. * [80](https://github.com/HBPVis/Servus/pull/80): Failsafe when Servus implementation can't be created and fallback to dummy. * [77](https://github.com/HBPVis/Servus/pull/77): diff --git a/servus/avahi/servus.h b/servus/avahi/servus.h index c4cc301..962d464 100644 --- a/servus/avahi/servus.h +++ b/servus/avahi/servus.h @@ -313,16 +313,17 @@ class Servus : public servus::Servus::Impl static void _resolveCBS(AvahiServiceResolver* resolver, AvahiIfIndex, AvahiProtocol, AvahiResolverEvent event, const char* name, const char*, const char*, - const char* host, const AvahiAddress*, uint16_t, - AvahiStringList* txt, AvahiLookupResultFlags flags, - void* servus) + const char* host, const AvahiAddress*, + const uint16_t port, AvahiStringList* txt, + AvahiLookupResultFlags flags, void* servus) { - ((Servus*)servus)->_resolveCB(resolver, event, name, host, txt, flags); + ((Servus*)servus) + ->_resolveCB(resolver, event, name, host, port, txt, flags); } void _resolveCB(AvahiServiceResolver* resolver, const AvahiResolverEvent event, const char* name, - const char* host, AvahiStringList* txt, + const char* host, const uint16_t port, AvahiStringList* txt, const AvahiLookupResultFlags flags) { // If browsing through the local interface, consider only the local @@ -342,6 +343,7 @@ class Servus : public servus::Servus::Impl { ValueMap& values = _instanceMap[name]; values["servus_host"] = host; + values["servus_port"] = std::to_string(unsigned(port)); for (; txt; txt = txt->next) { const std::string entry(reinterpret_cast( diff --git a/servus/dnssd/servus.h b/servus/dnssd/servus.h index 1f3e5b2..27de81e 100644 --- a/servus/dnssd/servus.h +++ b/servus/dnssd/servus.h @@ -294,19 +294,21 @@ class Servus : public servus::Servus::Impl static void resolveCBS_(DNSServiceRef, DNSServiceFlags, uint32_t /*interfaceIdx*/, DNSServiceErrorType error, const char* /*name*/, - const char* host, uint16_t /*port*/, + const char* host, const uint16_t port, uint16_t txtLen, const unsigned char* txt, Servus* servus) { if (error == kDNSServiceErr_NoError) - servus->resolveCB_(host, txtLen, txt); + servus->resolveCB_(host, port, txtLen, txt); servus->_result = error; } - void resolveCB_(const char* host, uint16_t txtLen, const unsigned char* txt) + void resolveCB_(const char* host, const uint16_t port, uint16_t txtLen, + const unsigned char* txt) { ValueMap& values = _instanceMap[_browsedName]; values["servus_host"] = host; + values["servus_port"] = std::to_string(unsigned(ntohs(port))); char key[256] = {0}; const char* value = 0; diff --git a/servus/servus.h b/servus/servus.h index e694fbe..4038e5f 100644 --- a/servus/servus.h +++ b/servus/servus.h @@ -42,6 +42,9 @@ static const std::string TEST_DRIVER{"_servus._test"}; * to browse a ZeroConf service. If the Servus library is compiled without * zeroconf support (@sa isAvailable()), this class does not do anything useful. * + * The keys 'servus_host' and 'servus_port' are set for discovered instances to + * the values of the implementation-specific dnssd hostname and port. + * * Example: @include tests/servus.cpp */ class Servus diff --git a/servus/test/servus.h b/servus/test/servus.h index 48c38c5..638632f 100644 --- a/servus/test/servus.h +++ b/servus/test/servus.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, Stefan.Eilemann@epfl.ch +/* Copyright (c) 2017-2018, Stefan.Eilemann@epfl.ch * * This file is part of Servus * @@ -18,7 +18,7 @@ #include #include -#include +#include namespace servus { @@ -31,7 +31,7 @@ namespace struct { std::mutex mutex; - std::set instances; + std::unordered_map instances; } _directory; } @@ -60,7 +60,7 @@ class Servus : public servus::Servus::Impl _instance = getHostname(); else _instance = instance; - _directory.instances.insert(this); + _directory.instances[this] = _instance; _announced = true; return servus::Servus::Result(servus::Result::SUCCESS); } @@ -91,7 +91,7 @@ class Servus : public servus::Servus::Impl { std::lock_guard lock(_directory.mutex); - std::vector diff; + std::vector> diff; std::set_symmetric_difference(_directory.instances.begin(), _directory.instances.end(), _instances.begin(), _instances.end(), @@ -100,27 +100,28 @@ class Servus : public servus::Servus::Impl _instanceMap.clear(); for (auto i : _directory.instances) { - ValueMap& values = _instanceMap[i->_instance]; + ValueMap& values = _instanceMap[i.second]; values.clear(); values["servus_host"] = "localhost"; + values["servus_port"] = std::to_string(unsigned(_port)); - for (const auto& j : i->_data) + for (const auto& j : i.first->_data) values[j.first] = j.second; } for (auto i : diff) { - if (_instances.count(i) == 0) + if (_instances.count(i.first) == 0) { - _instances.insert(i); + _instances[i.first] = i.second; for (Listener* listener : _listeners) - listener->instanceAdded(i->_instance); + listener->instanceAdded(i.second); } else { for (Listener* listener : _listeners) - listener->instanceRemoved(i->_instance); - _instances.erase(i); + listener->instanceRemoved(i.second); + _instances.erase(i.first); } } return servus::Servus::Result(servus::Servus::Result::SUCCESS); @@ -139,7 +140,7 @@ class Servus : public servus::Servus::Impl bool _announced{false}; bool _browsing{false}; - std::set _instances; + std::unordered_map _instances; void _updateRecord() final { /*nop*/} }; diff --git a/tests/itemModel.cpp b/tests/itemModel.cpp index 4334ff9..dea7234 100644 --- a/tests/itemModel.cpp +++ b/tests/itemModel.cpp @@ -102,7 +102,11 @@ class WatchRemove : public Watchdog, public servus::Listener { } - void instanceAdded(const std::string&) final {} + void instanceAdded(const std::string& instance) final + { + BOOST_CHECK_EQUAL(instance, TEST_INSTANCE); + } + void instanceRemoved(const std::string& instance) final { BOOST_CHECK_EQUAL(instance, TEST_INSTANCE); @@ -114,10 +118,7 @@ BOOST_GLOBAL_FIXTURE(GlobalQtApp); BOOST_AUTO_TEST_CASE(invalidAccess) { - const std::string serviceName = - "_servustest_" + servus::make_UUID().getString() + "._tcp"; - - servus::Servus service(serviceName); + servus::Servus service(servus::TEST_DRIVER); const servus::qt::ItemModel model(service); const QVariant invalidHeader = @@ -131,10 +132,7 @@ BOOST_AUTO_TEST_CASE(invalidAccess) BOOST_AUTO_TEST_CASE(servusItemModel) { - const std::string serviceName = - "_servustest_" + servus::make_UUID().getString() + "._tcp"; - - servus::Servus service(serviceName); + servus::Servus service(servus::TEST_DRIVER); const servus::qt::ItemModel model(service); WatchAdd watchAdd; @@ -146,10 +144,10 @@ BOOST_AUTO_TEST_CASE(servusItemModel) model.headerData(0, Qt::Horizontal, Qt::DisplayRole) .toString() .toStdString(); - BOOST_CHECK_EQUAL(header, "Instances for " + serviceName); + BOOST_CHECK_EQUAL(header, "Instances for " + servus::TEST_DRIVER); BOOST_CHECK(model.data(QModelIndex()) == QVariant()); - servus::Servus service2(serviceName); + servus::Servus service2(servus::TEST_DRIVER); const servus::Servus::Result& result = service2.announce(0, TEST_INSTANCE); if (result != servus::Result::SUCCESS) // happens on CI VMs { @@ -178,15 +176,17 @@ BOOST_AUTO_TEST_CASE(servusItemModel) model.data(instanceIndex, Qt::UserRole).toString().toStdString(), service.get(TEST_INSTANCE, "servus_host")); BOOST_CHECK(model.data(instanceIndex, Qt::EditRole) == QVariant()); - BOOST_REQUIRE_EQUAL(model.rowCount(instanceIndex), 2); + BOOST_REQUIRE_EQUAL(model.rowCount(instanceIndex), 3); const QModelIndex kv1Index = model.index(0, 0, instanceIndex); BOOST_CHECK(model.parent(kv1Index) == instanceIndex); BOOST_CHECK(model.data(kv1Index, Qt::UserRole) == QVariant()); const QVariant kv1 = model.data(kv1Index); const QVariant kv2 = model.data(model.index(1, 0, instanceIndex)); + const QVariant kv3 = model.data(model.index(2, 0, instanceIndex)); BOOST_REQUIRE_EQUAL(model.rowCount(kv1Index), 0); BOOST_CHECK_EQUAL(kv1.toString().toStdString(), "foo = bar"); BOOST_CHECK(kv2.toString().startsWith("servus_host = ")); + BOOST_CHECK(kv3.toString().startsWith("servus_port = ")); WatchRemove watchRemove; service.addListener(&watchRemove); diff --git a/tests/servus.cpp b/tests/servus.cpp index a30e529..cf48967 100644 --- a/tests/servus.cpp +++ b/tests/servus.cpp @@ -120,6 +120,9 @@ void test(const std::string& serviceName) BOOST_REQUIRE_EQUAL(hosts.size(), 1); BOOST_CHECK_EQUAL(hosts.front(), std::to_string(port)); BOOST_CHECK(service.containsKey(hosts.front(), "foo")); + BOOST_CHECK(service.containsKey(hosts.front(), "servus_host")); + BOOST_CHECK_EQUAL(service.get(hosts.front(), "servus_port"), + std::to_string(unsigned(port))); BOOST_CHECK_EQUAL(service.get(hosts.front(), "foo"), "bar"); BOOST_CHECK_EQUAL(service.get("bar", "foo"), std::string()); BOOST_CHECK_EQUAL(service.get(hosts.front(), "foobar"), std::string());