aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormark a. foltz <mfoltz@chromium.org>2021-07-15 12:25:07 -0700
committerOpenscreen LUCI CQ <openscreen-scoped@luci-project-accounts.iam.gserviceaccount.com>2021-07-16 19:21:35 +0000
commitd29ea545e02197c5166c0e0c76b3c181b3e3b370 (patch)
tree746c47238a40687f7d46d4280af6499b52688c2e
parent3eca605e12cb57e49eea49dc0a2ca80a79f93836 (diff)
downloadopenscreen-d29ea545e02197c5166c0e0c76b3c181b3e3b370.tar.gz
[Open Screen] Replace mDNSResponder.
This replaces the mDNSResponder-based publisher implementation in OSP with the the Open Screen Library's dnssd module. third_party/mDNSResponder is removed as well as all of the glue/support code. Caveats: - The OSP listener is not ported to dnssd, that will be done in a future change. - Resuming the publisher after Suspend() does not seem to be working yet. - The publisher configuration hostname is not used by dnssd. Bug: b/174207562 Change-Id: I9c7a6339a0f405550effc33ad0d5b5a79fa8e919 Reviewed-on: https://chromium-review.googlesource.com/c/openscreen/+/2535076 Commit-Queue: mark a. foltz <mfoltz@chromium.org> Reviewed-by: Ryan Keane <rwkeane@google.com>
-rw-r--r--BUILD.gn15
-rw-r--r--DEPS8
-rw-r--r--osp/BUILD.gn9
-rw-r--r--osp/build/config/services.gni2
-rw-r--r--osp/demo/osp_demo.cc30
-rw-r--r--osp/impl/BUILD.gn20
-rw-r--r--osp/impl/DEPS10
-rw-r--r--osp/impl/discovery/mdns/BUILD.gn62
-rw-r--r--osp/impl/discovery/mdns/DEPS7
-rw-r--r--osp/impl/discovery/mdns/domain_name.cc132
-rw-r--r--osp/impl/discovery/mdns/domain_name.h91
-rw-r--r--osp/impl/discovery/mdns/domain_name_unittest.cc194
-rw-r--r--osp/impl/discovery/mdns/mdns_demo.cc374
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_adapter.cc77
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_adapter.h258
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_adapter_impl.cc1044
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_adapter_impl.h159
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_adapter_impl_unittest.cc94
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_platform.cc290
-rw-r--r--osp/impl/discovery/mdns/mdns_responder_platform.h16
-rw-r--r--osp/impl/dns_sd_publisher_client.cc131
-rw-r--r--osp/impl/dns_sd_publisher_client.h62
-rw-r--r--osp/impl/dns_sd_service_publisher_factory.cc34
-rw-r--r--osp/impl/internal_services.cc229
-rw-r--r--osp/impl/internal_services.h90
-rw-r--r--osp/impl/mdns_platform_service.cc46
-rw-r--r--osp/impl/mdns_platform_service.h43
-rw-r--r--osp/impl/mdns_responder_service.cc664
-rw-r--r--osp/impl/mdns_responder_service.h209
-rw-r--r--osp/impl/mdns_responder_service_unittest.cc884
-rw-r--r--osp/impl/mdns_service_listener_factory.cc24
-rw-r--r--osp/impl/mdns_service_publisher_factory.cc24
-rw-r--r--osp/impl/network_service_manager.cc12
-rw-r--r--osp/impl/service_publisher_impl.cc12
-rw-r--r--osp/impl/service_publisher_impl.h16
-rw-r--r--osp/impl/service_publisher_impl_unittest.cc81
-rw-r--r--osp/impl/testing/BUILD.gn38
-rw-r--r--osp/impl/testing/fake_mdns_platform_service.cc50
-rw-r--r--osp/impl/testing/fake_mdns_platform_service.h39
-rw-r--r--osp/impl/testing/fake_mdns_platform_service_unittest.cc112
-rw-r--r--osp/impl/testing/fake_mdns_responder_adapter.cc600
-rw-r--r--osp/impl/testing/fake_mdns_responder_adapter.h202
-rw-r--r--osp/impl/testing/fake_mdns_responder_adapter_unittest.cc319
-rw-r--r--osp/public/BUILD.gn2
-rw-r--r--osp/public/mdns_service_listener_factory.h5
-rw-r--r--osp/public/network_service_manager.h8
-rw-r--r--osp/public/service_info.h2
-rw-r--r--osp/public/service_publisher.cc23
-rw-r--r--osp/public/service_publisher.h38
-rw-r--r--osp/public/service_publisher_factory.h (renamed from osp/public/mdns_service_publisher_factory.h)8
-rw-r--r--third_party/mDNSResponder/BUILD.gn38
-rw-r--r--third_party/mDNSResponder/README.chromium10
52 files changed, 365 insertions, 6582 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 2744cfa8..95ab0c96 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -37,10 +37,6 @@ group("gn_all") {
"osp/msgs",
]
- if (use_mdns_responder) {
- deps += [ "osp/impl/discovery/mdns:mdns_demo" ]
- }
-
if (use_chromium_quic) {
deps += [
"third_party/chromium_quic",
@@ -49,7 +45,7 @@ group("gn_all") {
]
}
- if (use_chromium_quic && use_mdns_responder) {
+ if (use_chromium_quic) {
deps += [ "osp:osp_demo" ]
}
}
@@ -95,15 +91,6 @@ source_set("openscreen_unittests_all") {
"osp:unittests",
"osp/msgs:unittests",
]
-
- if (use_mdns_responder) {
- public_deps += [
- "osp/impl/discovery/mdns:unittests",
-
- # Currently this target only includes mDNS tests.
- "osp/impl/testing:unittests",
- ]
- }
}
}
diff --git a/DEPS b/DEPS
index b38d9c6a..2fb5f1ba 100644
--- a/DEPS
+++ b/DEPS
@@ -108,14 +108,6 @@ deps = {
'condition': 'not build_with_chromium',
},
- 'third_party/mDNSResponder/src': {
- # NOTE: this fork of mDNSResponder is ancient (9 years old), but since
- # we are moving away from mDNSResponder we will not be updating this.
- 'url': Var('github') + '/jevinskie/mDNSResponder.git' +
- '@' + '2942dde61f920fbbf96ff9a3840567ebbe7cb1b6',
- 'condition': 'not build_with_chromium',
- },
-
# Note about updating BoringSSL: after changing this hash, run the update
# script in BoringSSL's util folder for generating build files from the
# <openscreen src-dir>/third_party/boringssl directory:
diff --git a/osp/BUILD.gn b/osp/BUILD.gn
index 14bb1ae1..5a2feb44 100644
--- a/osp/BUILD.gn
+++ b/osp/BUILD.gn
@@ -48,20 +48,13 @@ source_set("unittests") {
"public",
"public:test_support",
]
-
- if (use_mdns_responder) {
- sources += [ "impl/mdns_responder_service_unittest.cc" ]
-
- deps += [ "impl/testing" ]
- }
}
-if (use_chromium_quic && use_mdns_responder) {
+if (use_chromium_quic) {
executable("osp_demo") {
sources = [ "demo/osp_demo.cc" ]
deps = [
":osp_with_chromium_quic",
- "//osp/impl/discovery/mdns",
"//platform",
"//util",
]
diff --git a/osp/build/config/services.gni b/osp/build/config/services.gni
index 1d3d3466..808c123b 100644
--- a/osp/build/config/services.gni
+++ b/osp/build/config/services.gni
@@ -5,9 +5,7 @@
import("//build_overrides/build.gni")
use_chromium_quic = true
-use_mdns_responder = true
if (build_with_chromium) {
use_chromium_quic = false
- use_mdns_responder = false
}
diff --git a/osp/demo/osp_demo.cc b/osp/demo/osp_demo.cc
index 952a925f..93f593fa 100644
--- a/osp/demo/osp_demo.cc
+++ b/osp/demo/osp_demo.cc
@@ -16,7 +16,6 @@
#include "absl/strings/string_view.h"
#include "osp/msgs/osp_messages.h"
#include "osp/public/mdns_service_listener_factory.h"
-#include "osp/public/mdns_service_publisher_factory.h"
#include "osp/public/message_demuxer.h"
#include "osp/public/network_service_manager.h"
#include "osp/public/presentation/presentation_controller.h"
@@ -27,6 +26,7 @@
#include "osp/public/protocol_connection_server_factory.h"
#include "osp/public/service_listener.h"
#include "osp/public/service_publisher.h"
+#include "osp/public/service_publisher_factory.h"
#include "platform/api/network_interface.h"
#include "platform/api/time.h"
#include "platform/impl/logging.h"
@@ -152,7 +152,9 @@ class DemoPublisherObserver final : public ServicePublisher::Observer {
void OnStopped() override { OSP_LOG_INFO << "publisher stopped!"; }
void OnSuspended() override { OSP_LOG_INFO << "publisher suspended!"; }
- void OnError(ServicePublisherError) override {}
+ void OnError(Error error) override {
+ OSP_LOG_ERROR << "publisher error: " << error;
+ }
void OnMetrics(ServicePublisher::Metrics) override {}
};
@@ -457,7 +459,10 @@ void HandleReceiverCommand(absl::string_view command,
DemoReceiverDelegate& delegate,
NetworkServiceManager* manager) {
if (command == "avail") {
- ServicePublisher* publisher = manager->GetMdnsServicePublisher();
+ ServicePublisher* publisher = manager->GetServicePublisher();
+
+ OSP_LOG_INFO << "publisher->state() == "
+ << static_cast<int>(publisher->state());
if (publisher->state() == ServicePublisher::State::kSuspended) {
publisher->Resume();
@@ -497,7 +502,7 @@ void RunReceiverPollLoop(pollfd& file_descriptor,
void CleanupPublisherDemo(NetworkServiceManager* manager) {
Receiver::Get()->SetReceiverDelegate(nullptr);
Receiver::Get()->Deinit();
- manager->GetMdnsServicePublisher()->Stop();
+ manager->GetServicePublisher()->Stop();
manager->GetProtocolConnectionServer()->Stop();
NetworkServiceManager::Dispose();
@@ -508,7 +513,6 @@ void PublisherDemo(absl::string_view friendly_name) {
constexpr uint16_t server_port = 6667;
- DemoPublisherObserver publisher_observer;
// TODO(btolsch): aggregate initialization probably better?
ServicePublisher::Config publisher_config;
publisher_config.friendly_name = std::string(friendly_name);
@@ -516,21 +520,23 @@ void PublisherDemo(absl::string_view friendly_name) {
publisher_config.service_instance_name = "deadbeef";
publisher_config.connection_server_port = server_port;
- auto mdns_publisher = MdnsServicePublisherFactory::Create(
- publisher_config, &publisher_observer,
- PlatformClientPosix::GetInstance()->GetTaskRunner());
-
ServerConfig server_config;
for (const InterfaceInfo& interface : GetNetworkInterfaces()) {
OSP_VLOG << "Found interface: " << interface;
if (!interface.addresses.empty()) {
server_config.connection_endpoints.push_back(
IPEndpoint{interface.addresses[0].address, server_port});
+ publisher_config.network_interfaces.push_back(interface);
}
}
OSP_LOG_IF(WARN, server_config.connection_endpoints.empty())
<< "No network interfaces had usable addresses for mDNS publishing.";
+ DemoPublisherObserver publisher_observer;
+ auto service_publisher = ServicePublisherFactory::Create(
+ publisher_config, &publisher_observer,
+ PlatformClientPosix::GetInstance()->GetTaskRunner());
+
MessageDemuxer demuxer(Clock::now, MessageDemuxer::kDefaultBufferLimit);
DemoConnectionServerObserver server_observer;
auto connection_server = ProtocolConnectionServerFactory::Create(
@@ -538,13 +544,13 @@ void PublisherDemo(absl::string_view friendly_name) {
PlatformClientPosix::GetInstance()->GetTaskRunner());
auto* network_service =
- NetworkServiceManager::Create(nullptr, std::move(mdns_publisher), nullptr,
- std::move(connection_server));
+ NetworkServiceManager::Create(nullptr, std::move(service_publisher),
+ nullptr, std::move(connection_server));
DemoReceiverDelegate receiver_delegate;
Receiver::Get()->Init();
Receiver::Get()->SetReceiverDelegate(&receiver_delegate);
- network_service->GetMdnsServicePublisher()->Start();
+ network_service->GetServicePublisher()->Start();
network_service->GetProtocolConnectionServer()->Start();
pollfd stdin_pollfd{STDIN_FILENO, POLLIN};
diff --git a/osp/impl/BUILD.gn b/osp/impl/BUILD.gn
index dcccfc19..8b50164f 100644
--- a/osp/impl/BUILD.gn
+++ b/osp/impl/BUILD.gn
@@ -6,8 +6,9 @@ import("../../osp/build/config/services.gni")
source_set("impl") {
sources = [
- "mdns_platform_service.cc",
- "mdns_platform_service.h",
+ "dns_sd_publisher_client.cc",
+ "dns_sd_publisher_client.h",
+ "dns_sd_service_publisher_factory.cc",
"message_demuxer.cc",
"network_service_manager.cc",
"presentation/presentation_common.cc",
@@ -31,23 +32,14 @@ source_set("impl") {
"../public",
]
deps = [
+ "../../discovery:common",
+ "../../discovery:dnssd",
+ "../../discovery:public",
"../../platform",
"../../third_party/abseil",
"../../util",
"quic",
]
-
- if (use_mdns_responder) {
- sources += [
- "internal_services.cc",
- "internal_services.h",
- "mdns_responder_service.cc",
- "mdns_responder_service.h",
- "mdns_service_listener_factory.cc",
- "mdns_service_publisher_factory.cc",
- ]
- deps += [ "discovery/mdns:mdns" ]
- }
}
if (use_chromium_quic) {
diff --git a/osp/impl/DEPS b/osp/impl/DEPS
index 63752366..cd004f79 100644
--- a/osp/impl/DEPS
+++ b/osp/impl/DEPS
@@ -1,7 +1,9 @@
-# Copyright (c) 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
+# -*- Mode: Python; -*-
include_rules = [
- '+osp/impl/discovery/mdns',
+ # Allowed to use discovery module.
+ '+discovery/public',
+ '+discovery/dnssd/public',
+ # Also necessary to implement discovery APIs.
+ '+discovery/common',
]
diff --git a/osp/impl/discovery/mdns/BUILD.gn b/osp/impl/discovery/mdns/BUILD.gn
deleted file mode 100644
index 3ef05106..00000000
--- a/osp/impl/discovery/mdns/BUILD.gn
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("../../../build/config/services.gni")
-assert(use_mdns_responder)
-
-source_set("mdns_interface") {
- sources = [
- "domain_name.cc",
- "domain_name.h",
- "mdns_responder_adapter.cc",
- "mdns_responder_adapter.h",
- ]
-
- public_deps = [
- "../../../../platform",
- "../../../../third_party/abseil",
- "../../../../util",
- ]
-}
-
-source_set("unittests") {
- testonly = true
-
- sources = [ "domain_name_unittest.cc" ]
-
- deps = [
- ":mdns_interface",
- "../../../../third_party/googletest:gmock",
- "../../../../third_party/googletest:gtest",
- ]
-
- sources += [ "mdns_responder_adapter_impl_unittest.cc" ]
- deps += [ ":mdns" ]
-}
-
-executable("mdns_demo") {
- sources = [ "mdns_demo.cc" ]
-
- deps = [
- ":mdns",
- "../../../../platform:standalone_impl",
- ]
-}
-
-source_set("mdns") {
- sources = [
- "mdns_responder_adapter_impl.cc",
- "mdns_responder_adapter_impl.h",
- "mdns_responder_platform.cc",
- "mdns_responder_platform.h",
- ]
-
- public_deps = [
- ":mdns_interface",
- "../../../../platform",
- "../../../../util",
- ]
-
- deps = [ "../../../../third_party/mDNSResponder:core" ]
-}
diff --git a/osp/impl/discovery/mdns/DEPS b/osp/impl/discovery/mdns/DEPS
deleted file mode 100644
index 96a7209c..00000000
--- a/osp/impl/discovery/mdns/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-include_rules = [
- '+platform/impl', # Needed by embedder_demo.cc
-]
diff --git a/osp/impl/discovery/mdns/domain_name.cc b/osp/impl/discovery/mdns/domain_name.cc
deleted file mode 100644
index c574793a..00000000
--- a/osp/impl/discovery/mdns/domain_name.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/domain_name.h"
-
-#include <algorithm>
-#include <iterator>
-
-#include "util/stringprintf.h"
-
-namespace openscreen {
-namespace osp {
-
-// static
-DomainName DomainName::GetLocalDomain() {
- return DomainName{{5, 'l', 'o', 'c', 'a', 'l', 0}};
-}
-
-// static
-ErrorOr<DomainName> DomainName::Append(const DomainName& first,
- const DomainName& second) {
- OSP_CHECK(first.domain_name_.size());
- OSP_CHECK(second.domain_name_.size());
-
- // Both vectors should represent null terminated domain names.
- OSP_DCHECK_EQ(first.domain_name_.back(), '\0');
- OSP_DCHECK_EQ(second.domain_name_.back(), '\0');
- if ((first.domain_name_.size() + second.domain_name_.size() - 1) >
- kDomainNameMaxLength) {
- return Error::Code::kDomainNameTooLong;
- }
-
- DomainName result;
- result.domain_name_.clear();
- result.domain_name_.insert(result.domain_name_.begin(),
- first.domain_name_.begin(),
- first.domain_name_.end());
- result.domain_name_.insert(result.domain_name_.end() - 1,
- second.domain_name_.begin(),
- second.domain_name_.end() - 1);
- return result;
-}
-
-DomainName::DomainName() : domain_name_{0u} {}
-DomainName::DomainName(std::vector<uint8_t>&& domain_name)
- : domain_name_(std::move(domain_name)) {
- OSP_CHECK_LE(domain_name_.size(), kDomainNameMaxLength);
-}
-DomainName::DomainName(const DomainName&) = default;
-DomainName::DomainName(DomainName&&) noexcept = default;
-DomainName::~DomainName() = default;
-DomainName& DomainName::operator=(const DomainName&) = default;
-DomainName& DomainName::operator=(DomainName&&) noexcept = default;
-
-bool DomainName::operator==(const DomainName& other) const {
- if (domain_name_.size() != other.domain_name_.size()) {
- return false;
- }
- for (size_t i = 0; i < domain_name_.size(); ++i) {
- if (tolower(domain_name_[i]) != tolower(other.domain_name_[i])) {
- return false;
- }
- }
- return true;
-}
-
-bool DomainName::operator!=(const DomainName& other) const {
- return !(*this == other);
-}
-
-bool DomainName::EndsWithLocalDomain() const {
- const DomainName local_domain = GetLocalDomain();
- if (domain_name_.size() < local_domain.domain_name_.size())
- return false;
-
- return std::equal(local_domain.domain_name_.begin(),
- local_domain.domain_name_.end(),
- domain_name_.end() - local_domain.domain_name_.size());
-}
-
-Error DomainName::Append(const DomainName& after) {
- OSP_CHECK(after.domain_name_.size());
- OSP_DCHECK_EQ(after.domain_name_.back(), 0u);
-
- if ((domain_name_.size() + after.domain_name_.size() - 1) >
- kDomainNameMaxLength) {
- return Error::Code::kDomainNameTooLong;
- }
-
- domain_name_.insert(domain_name_.end() - 1, after.domain_name_.begin(),
- after.domain_name_.end() - 1);
- return Error::None();
-}
-
-std::vector<absl::string_view> DomainName::GetLabels() const {
- OSP_DCHECK_GT(domain_name_.size(), 0u);
- OSP_DCHECK_LT(domain_name_.size(), kDomainNameMaxLength);
-
- std::vector<absl::string_view> result;
- const uint8_t* data = domain_name_.data();
- while (*data != 0) {
- const size_t label_length = *data;
- OSP_DCHECK_LT(label_length, kDomainNameMaxLabelLength);
-
- ++data;
- result.emplace_back(reinterpret_cast<const char*>(data), label_length);
- data += label_length;
- }
- return result;
-}
-
-bool DomainNameComparator::operator()(const DomainName& a,
- const DomainName& b) const {
- return a.domain_name() < b.domain_name();
-}
-
-std::ostream& operator<<(std::ostream& os, const DomainName& domain_name) {
- const auto& data = domain_name.domain_name();
- OSP_DCHECK_GT(data.size(), 0u);
- auto it = data.begin();
- while (*it != 0) {
- size_t length = *it++;
- PrettyPrintAsciiHex(os, it, it + length);
- it += length;
- os << ".";
- }
- return os;
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/discovery/mdns/domain_name.h b/osp/impl/discovery/mdns/domain_name.h
deleted file mode 100644
index c29ef9db..00000000
--- a/osp/impl/discovery/mdns/domain_name.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
-#define OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
-
-#include <cstdint>
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "absl/strings/string_view.h"
-#include "platform/base/error.h"
-#include "util/osp_logging.h"
-
-namespace openscreen {
-namespace osp {
-
-struct DomainName {
- static ErrorOr<DomainName> Append(const DomainName& first,
- const DomainName& second);
-
- template <typename It>
- static ErrorOr<DomainName> FromLabels(It first, It last) {
- size_t total_length = 1;
- for (auto label = first; label != last; ++label) {
- if (label->size() > kDomainNameMaxLabelLength)
- return Error::Code::kDomainNameLabelTooLong;
-
- total_length += label->size() + 1;
- }
- if (total_length > kDomainNameMaxLength)
- return Error::Code::kDomainNameTooLong;
-
- DomainName result;
- result.domain_name_.resize(total_length);
- auto result_it = result.domain_name_.begin();
- for (auto label = first; label != last; ++label) {
- *result_it++ = static_cast<uint8_t>(label->size());
- result_it = std::copy(label->begin(), label->end(), result_it);
- }
- *result_it = 0;
- return std::move(result);
- }
-
- static DomainName GetLocalDomain();
-
- static constexpr uint8_t kDomainNameMaxLabelLength = 63u;
- static constexpr uint16_t kDomainNameMaxLength = 256u;
-
- DomainName();
- explicit DomainName(std::vector<uint8_t>&& domain_name);
- DomainName(const DomainName&);
- DomainName(DomainName&&) noexcept;
- ~DomainName();
- DomainName& operator=(const DomainName&);
- DomainName& operator=(DomainName&&) noexcept;
-
- bool operator==(const DomainName& other) const;
- bool operator!=(const DomainName& other) const;
-
- bool EndsWithLocalDomain() const;
- bool IsEmpty() const { return domain_name_.size() == 1 && !domain_name_[0]; }
-
- Error Append(const DomainName& after);
- std::vector<absl::string_view> GetLabels() const;
-
- const std::vector<uint8_t>& domain_name() const { return domain_name_; }
-
- private:
- // RFC 1035 domain name format: sequence of 1 octet label length followed by
- // label data, ending with a 0 octet. May not exceed 256 bytes (including
- // terminating 0).
- // For example, openscreen.org would be encoded as:
- // {10, 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n',
- // 3, 'o', 'r', 'g', 0}
- std::vector<uint8_t> domain_name_;
-};
-
-class DomainNameComparator {
- public:
- bool operator()(const DomainName& a, const DomainName& b) const;
-};
-
-std::ostream& operator<<(std::ostream& os, const DomainName& domain_name);
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_DISCOVERY_MDNS_DOMAIN_NAME_H_
diff --git a/osp/impl/discovery/mdns/domain_name_unittest.cc b/osp/impl/discovery/mdns/domain_name_unittest.cc
deleted file mode 100644
index 76f31003..00000000
--- a/osp/impl/discovery/mdns/domain_name_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/domain_name.h"
-
-#include <sstream>
-
-#include "gtest/gtest.h"
-#include "platform/base/error.h"
-
-namespace openscreen {
-namespace osp {
-
-namespace {
-
-ErrorOr<DomainName> FromLabels(const std::vector<std::string>& labels) {
- return DomainName::FromLabels(labels.begin(), labels.end());
-}
-
-template <typename T>
-T UnpackErrorOr(ErrorOr<T> error_or) {
- EXPECT_TRUE(error_or);
- return std::move(error_or.value());
-}
-
-} // namespace
-
-TEST(DomainNameTest, Constructors) {
- DomainName empty;
-
- ASSERT_EQ(1u, empty.domain_name().size());
- EXPECT_EQ(0, empty.domain_name()[0]);
-
- DomainName original({10, 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n', 3,
- 'o', 'r', 'g', 0});
- ASSERT_EQ(16u, original.domain_name().size());
-
- auto data_copy = original.domain_name();
- DomainName direct_ctor(std::move(data_copy));
- EXPECT_EQ(direct_ctor.domain_name(), original.domain_name());
-
- DomainName copy_ctor(original);
- EXPECT_EQ(copy_ctor.domain_name(), original.domain_name());
-
- DomainName move_ctor(std::move(copy_ctor));
- EXPECT_EQ(move_ctor.domain_name(), original.domain_name());
-
- DomainName copy_assign;
- copy_assign = move_ctor;
- EXPECT_EQ(copy_assign.domain_name(), original.domain_name());
-
- DomainName move_assign;
- move_assign = std::move(move_ctor);
- EXPECT_EQ(move_assign.domain_name(), original.domain_name());
-}
-
-TEST(DomainNameTest, FromLabels) {
- const auto typical =
- std::vector<uint8_t>{10, 'o', 'p', 'e', 'n', 's', 'c', 'r',
- 'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
- DomainName result = UnpackErrorOr(FromLabels({"openscreen", "org"}));
- EXPECT_EQ(result.domain_name(), typical);
-
- const auto includes_dot =
- std::vector<uint8_t>{11, 'o', 'p', 'e', 'n', '.', 's', 'c', 'r',
- 'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
- result = UnpackErrorOr(FromLabels({"open.screen", "org"}));
- EXPECT_EQ(result.domain_name(), includes_dot);
-
- const auto includes_non_ascii =
- std::vector<uint8_t>{11, 'o', 'p', 'e', 'n', 7, 's', 'c', 'r',
- 'e', 'e', 'n', 3, 'o', 'r', 'g', 0};
- result = UnpackErrorOr(FromLabels({"open\7screen", "org"}));
- EXPECT_EQ(result.domain_name(), includes_non_ascii);
-
- ASSERT_FALSE(
- FromLabels({"extremely-long-label-that-is-actually-too-long-"
- "for-rfc-1034-and-will-not-generate"}));
-
- ASSERT_FALSE(FromLabels({
- "extremely-long-domain-name-that-is-made-of",
- "valid-labels",
- "however-overall-it-is-too-long-for-rfc-1034",
- "so-it-should-fail-to-generate",
- "filler-filler-filler-filler-filler",
- "filler-filler-filler-filler-filler",
- "filler-filler-filler-filler-filler",
- "filler-filler-filler-filler-filler",
- }));
-}
-
-TEST(DomainNameTest, Equality) {
- DomainName alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
- DomainName beta = UnpackErrorOr(FromLabels({"beta", "openscreen", "org"}));
-
- const DomainName alpha_copy = alpha;
-
- EXPECT_TRUE(alpha == alpha);
- EXPECT_FALSE(alpha != alpha);
- EXPECT_TRUE(alpha == alpha_copy);
- EXPECT_FALSE(alpha != alpha_copy);
- EXPECT_FALSE(alpha == beta);
- EXPECT_TRUE(alpha != beta);
-}
-
-TEST(DomainNameTest, EndsWithLocalDomain) {
- DomainName alpha;
- EXPECT_FALSE(alpha.EndsWithLocalDomain());
-
- alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
- DomainName beta = UnpackErrorOr(FromLabels({"beta", "local"}));
-
- EXPECT_FALSE(alpha.EndsWithLocalDomain());
- EXPECT_TRUE(beta.EndsWithLocalDomain());
-}
-
-TEST(DomainNameTest, IsEmpty) {
- DomainName alpha;
- DomainName beta(std::vector<uint8_t>{0});
-
- EXPECT_TRUE(alpha.IsEmpty());
- EXPECT_TRUE(beta.IsEmpty());
-
- alpha = UnpackErrorOr(FromLabels({"alpha", "openscreen", "org"}));
- EXPECT_FALSE(alpha.IsEmpty());
-}
-
-TEST(DomainNameTest, Append) {
- const auto expected_service_name =
- std::vector<uint8_t>{5, 'a', 'l', 'p', 'h', 'a', '\0'};
- const auto expected_service_type_initial = std::vector<uint8_t>{
- 11, '_', 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e', 'e', 'n', '\0'};
- const auto expected_protocol =
- std::vector<uint8_t>{5, '_', 'q', 'u', 'i', 'c', '\0'};
- const auto expected_service_type =
- std::vector<uint8_t>{11, '_', 'o', 'p', 'e', 'n', 's', 'c', 'r', 'e',
- 'e', 'n', 5, '_', 'q', 'u', 'i', 'c', '\0'};
- const auto total_expected = std::vector<uint8_t>{
- 5, 'a', 'l', 'p', 'h', 'a', 11, '_', 'o', 'p', 'e', 'n', 's',
- 'c', 'r', 'e', 'e', 'n', 5, '_', 'q', 'u', 'i', 'c', '\0'};
-
- DomainName service_name = UnpackErrorOr(FromLabels({"alpha"}));
- EXPECT_EQ(service_name.domain_name(), expected_service_name);
-
- DomainName service_type = UnpackErrorOr(FromLabels({"_openscreen"}));
- EXPECT_EQ(service_type.domain_name(), expected_service_type_initial);
-
- DomainName protocol = UnpackErrorOr(FromLabels({"_quic"}));
- EXPECT_EQ(protocol.domain_name(), expected_protocol);
-
- EXPECT_TRUE(service_type.Append(protocol).ok());
- EXPECT_EQ(service_type.domain_name(), expected_service_type);
-
- DomainName result =
- UnpackErrorOr(DomainName::Append(service_name, service_type));
- EXPECT_EQ(result.domain_name(), total_expected);
-}
-
-TEST(DomainNameTest, GetLabels) {
- const auto labels = std::vector<std::string>{"alpha", "beta", "gamma", "org"};
- DomainName domain_name = UnpackErrorOr(FromLabels(labels));
-
- const auto actual_labels = domain_name.GetLabels();
- for (size_t i = 0; i < labels.size(); ++i) {
- EXPECT_EQ(labels[i], actual_labels[i]);
- }
-}
-
-TEST(DomainNameTest, StreamEscaping) {
- {
- std::stringstream ss;
- ss << DomainName(std::vector<uint8_t>{1, 0, 0});
- EXPECT_EQ(ss.str(), "\\x00.");
- }
- {
- std::stringstream ss;
- ss << DomainName(std::vector<uint8_t>{1, 1, 0});
- EXPECT_EQ(ss.str(), "\\x01.");
- }
- {
- std::stringstream ss;
- ss << DomainName(std::vector<uint8_t>{1, 18, 0});
- EXPECT_EQ(ss.str(), "\\x12.");
- }
- {
- std::stringstream ss;
- ss << DomainName(std::vector<uint8_t>{1, 255, 0});
- EXPECT_EQ(ss.str(), "\\xff.");
- }
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/discovery/mdns/mdns_demo.cc b/osp/impl/discovery/mdns/mdns_demo.cc
deleted file mode 100644
index 1fc1513e..00000000
--- a/osp/impl/discovery/mdns/mdns_demo.cc
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <signal.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <map>
-#include <memory>
-#include <vector>
-
-// TODO(rwkeane): Remove references to platform/impl
-#include "osp/impl/discovery/mdns/mdns_responder_adapter_impl.h"
-#include "platform/api/network_interface.h"
-#include "platform/api/time.h"
-#include "platform/base/error.h"
-#include "platform/impl/logging.h"
-#include "platform/impl/platform_client_posix.h"
-#include "platform/impl/task_runner.h"
-#include "platform/impl/udp_socket_reader_posix.h"
-
-// This file contains a demo of our mDNSResponder wrapper code. It can both
-// listen for mDNS services and advertise an mDNS service. The command-line
-// usage is:
-// mdns_demo [service_type] [service_instance_name]
-// service_type defaults to '_openscreen._udp' and service_instance_name
-// defaults to ''. service_type determines services the program listens for and
-// when service_instance_name is not empty, a service of
-// 'service_instance_name.service_type' is also advertised.
-//
-// The program will print a list of discovered services when it receives a USR1
-// or INT signal. The pid is printed at the beginning of the program to
-// facilitate this.
-//
-// There are a few known bugs around the handling of record events, so this
-// shouldn't be expected to be a source of truth, nor should it be expected to
-// be correct after running for a long time.
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-bool g_done = false;
-bool g_dump_services = false;
-
-struct Service {
- explicit Service(DomainName service_instance)
- : service_instance(std::move(service_instance)) {}
- ~Service() = default;
-
- DomainName service_instance;
- DomainName domain_name;
- IPAddress address;
- uint16_t port;
- std::vector<std::string> txt;
-};
-
-class DemoSocketClient : public UdpSocket::Client {
- public:
- explicit DemoSocketClient(MdnsResponderAdapterImpl* mdns) : mdns_(mdns) {}
-
- void OnError(UdpSocket* socket, Error error) override {
- // TODO(crbug.com/openscreen/66): Change to OSP_LOG_FATAL.
- OSP_LOG_ERROR << "configuration failed for interface " << error.message();
- OSP_CHECK(false);
- }
-
- void OnSendError(UdpSocket* socket, Error error) override {
- OSP_UNIMPLEMENTED();
- }
-
- void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override {
- mdns_->OnRead(socket, std::move(packet));
- }
-
- private:
- MdnsResponderAdapterImpl* mdns_;
-};
-
-using ServiceMap = std::map<DomainName, Service, DomainNameComparator>;
-ServiceMap* g_services = nullptr;
-
-void sigusr1_dump_services(int) {
- g_dump_services = true;
-}
-
-void sigint_stop(int) {
- OSP_LOG_INFO << "caught SIGINT, exiting...";
- g_done = true;
-}
-
-std::vector<std::string> SplitByDot(const std::string& domain_part) {
- std::vector<std::string> result;
- auto copy_it = domain_part.begin();
- for (auto it = domain_part.begin(); it != domain_part.end(); ++it) {
- if (*it == '.') {
- result.emplace_back(copy_it, it);
- copy_it = it + 1;
- }
- }
- if (copy_it != domain_part.end())
- result.emplace_back(copy_it, domain_part.end());
-
- return result;
-}
-
-void SignalThings() {
- struct sigaction usr1_sa;
- struct sigaction int_sa;
- struct sigaction unused;
-
- usr1_sa.sa_handler = &sigusr1_dump_services;
- sigemptyset(&usr1_sa.sa_mask);
- usr1_sa.sa_flags = 0;
-
- int_sa.sa_handler = &sigint_stop;
- sigemptyset(&int_sa.sa_mask);
- int_sa.sa_flags = 0;
-
- sigaction(SIGUSR1, &usr1_sa, &unused);
- sigaction(SIGINT, &int_sa, &unused);
-
- OSP_LOG_INFO << "signal handlers setup" << std::endl << "pid: " << getpid();
-}
-
-std::vector<std::unique_ptr<UdpSocket>> SetUpMulticastSockets(
- TaskRunner* task_runner,
- const std::vector<NetworkInterfaceIndex>& index_list,
- UdpSocket::Client* client) {
- std::vector<std::unique_ptr<UdpSocket>> sockets;
- for (const auto ifindex : index_list) {
- auto create_result =
- UdpSocket::Create(task_runner, client, IPEndpoint{{}, 5353});
- if (!create_result) {
- OSP_LOG_ERROR << "failed to create IPv4 socket for interface " << ifindex
- << ": " << create_result.error().message();
- continue;
- }
- std::unique_ptr<UdpSocket> socket = std::move(create_result.value());
-
- socket->JoinMulticastGroup(IPAddress{224, 0, 0, 251}, ifindex);
- socket->SetMulticastOutboundInterface(ifindex);
- socket->Bind();
-
- OSP_LOG_INFO << "listening on interface " << ifindex;
- sockets.emplace_back(std::move(socket));
- }
- return sockets;
-}
-
-void LogService(const Service& s) {
- OSP_LOG_INFO << "PTR: (" << s.service_instance << ")" << std::endl
- << "SRV: " << s.domain_name << ":" << s.port << std::endl
- << "TXT:";
-
- for (const auto& l : s.txt) {
- OSP_LOG_INFO << " | " << l;
- }
- OSP_LOG_INFO << "A: " << s.address;
-}
-
-void HandleEvents(MdnsResponderAdapterImpl* mdns_adapter) {
- for (auto& ptr_event : mdns_adapter->TakePtrResponses()) {
- auto it = g_services->find(ptr_event.service_instance);
- switch (ptr_event.header.response_type) {
- case QueryEventHeader::Type::kAdded:
- case QueryEventHeader::Type::kAddedNoCache:
- mdns_adapter->StartSrvQuery(ptr_event.header.socket,
- ptr_event.service_instance);
- mdns_adapter->StartTxtQuery(ptr_event.header.socket,
- ptr_event.service_instance);
- if (it == g_services->end()) {
- g_services->emplace(ptr_event.service_instance,
- Service(ptr_event.service_instance));
- }
- break;
- case QueryEventHeader::Type::kRemoved:
- // PTR may be removed and added without updating related entries (SRV
- // and friends) so this simple logic is actually broken, but I don't
- // want to do a better design or pointer hell for just a demo.
- OSP_LOG_WARN << "ptr-remove: " << ptr_event.service_instance;
- if (it != g_services->end())
- g_services->erase(it);
-
- break;
- }
- }
- for (auto& srv_event : mdns_adapter->TakeSrvResponses()) {
- auto it = g_services->find(srv_event.service_instance);
- if (it == g_services->end())
- continue;
-
- switch (srv_event.header.response_type) {
- case QueryEventHeader::Type::kAdded:
- case QueryEventHeader::Type::kAddedNoCache:
- mdns_adapter->StartAQuery(srv_event.header.socket,
- srv_event.domain_name);
- it->second.domain_name = std::move(srv_event.domain_name);
- it->second.port = srv_event.port;
- break;
- case QueryEventHeader::Type::kRemoved:
- OSP_LOG_WARN << "srv-remove: " << srv_event.service_instance;
- it->second.domain_name = DomainName();
- it->second.port = 0;
- break;
- }
- }
- for (auto& txt_event : mdns_adapter->TakeTxtResponses()) {
- auto it = g_services->find(txt_event.service_instance);
- if (it == g_services->end())
- continue;
-
- switch (txt_event.header.response_type) {
- case QueryEventHeader::Type::kAdded:
- case QueryEventHeader::Type::kAddedNoCache:
- it->second.txt = std::move(txt_event.txt_info);
- break;
- case QueryEventHeader::Type::kRemoved:
- OSP_LOG_WARN << "txt-remove: " << txt_event.service_instance;
- it->second.txt.clear();
- break;
- }
- }
- for (const auto& a_event : mdns_adapter->TakeAResponses()) {
- // TODO(btolsch): If multiple SRV records specify the same domain, the A
- // will only update the first. I didn't think this would happen but I
- // noticed this happens for cast groups.
- auto it = std::find_if(g_services->begin(), g_services->end(),
- [&a_event](const std::pair<DomainName, Service>& s) {
- return s.second.domain_name == a_event.domain_name;
- });
- if (it == g_services->end())
- continue;
-
- switch (a_event.header.response_type) {
- case QueryEventHeader::Type::kAdded:
- case QueryEventHeader::Type::kAddedNoCache:
- it->second.address = a_event.address;
- break;
- case QueryEventHeader::Type::kRemoved:
- OSP_LOG_WARN << "a-remove: " << a_event.domain_name;
- it->second.address = IPAddress(0, 0, 0, 0);
- break;
- }
- }
-}
-
-void BrowseDemo(TaskRunner* task_runner,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::string& service_instance) {
- SignalThings();
-
- std::vector<std::string> labels{service_name, service_protocol};
- ErrorOr<DomainName> service_type =
- DomainName::FromLabels(labels.begin(), labels.end());
-
- if (!service_type) {
- OSP_LOG_ERROR << "bad domain labels: " << service_name << ", "
- << service_protocol;
- return;
- }
-
- auto mdns_adapter = std::make_unique<MdnsResponderAdapterImpl>();
- mdns_adapter->Init();
- mdns_adapter->SetHostLabel("gigliorononomicon");
- const std::vector<InterfaceInfo> interfaces = GetNetworkInterfaces();
- std::vector<NetworkInterfaceIndex> index_list;
- for (const auto& interface : interfaces) {
- OSP_LOG_INFO << "Found interface: " << interface;
- if (!interface.addresses.empty()) {
- index_list.push_back(interface.index);
- }
- }
- OSP_LOG_IF(WARN, index_list.empty())
- << "No network interfaces had usable addresses for mDNS.";
-
- DemoSocketClient client(mdns_adapter.get());
- auto sockets = SetUpMulticastSockets(task_runner, index_list, &client);
- // The code below assumes the elements in |sockets| is in exact 1:1
- // correspondence with the elements in |index_list|. Crash the demo if any
- // sockets are missing (i.e., failed to be set up).
- OSP_CHECK_EQ(sockets.size(), index_list.size());
-
- // Listen on all interfaces.
- auto socket_it = sockets.begin();
- for (NetworkInterfaceIndex index : index_list) {
- const auto& interface =
- *std::find_if(interfaces.begin(), interfaces.end(),
- [index](const openscreen::InterfaceInfo& info) {
- return info.index == index;
- });
- // Pick any address for the given interface.
- mdns_adapter->RegisterInterface(interface, interface.addresses.front(),
- socket_it->get());
- ++socket_it;
- }
-
- if (!service_instance.empty()) {
- mdns_adapter->RegisterService(service_instance, service_name,
- service_protocol, DomainName(), 12345,
- {{"k1", "yurtle"}, {"k2", "turtle"}});
- }
-
- for (const std::unique_ptr<UdpSocket>& socket : sockets) {
- mdns_adapter->StartPtrQuery(socket.get(), service_type.value());
- }
-
- while (!g_done) {
- HandleEvents(mdns_adapter.get());
- if (g_dump_services) {
- OSP_LOG_INFO << "num services: " << g_services->size();
- for (const auto& s : *g_services) {
- LogService(s.second);
- }
- if (!service_instance.empty()) {
- mdns_adapter->UpdateTxtData(
- service_instance, service_name, service_protocol,
- {{"k1", "oogley"}, {"k2", "moogley"}, {"k3", "googley"}});
- }
- g_dump_services = false;
- }
- mdns_adapter->RunTasks();
- }
- OSP_LOG_INFO << "num services: " << g_services->size();
- for (const auto& s : *g_services) {
- LogService(s.second);
- }
- for (const std::unique_ptr<UdpSocket>& socket : sockets) {
- mdns_adapter->DeregisterInterface(socket.get());
- }
- mdns_adapter->Close();
-}
-
-} // namespace
-} // namespace osp
-} // namespace openscreen
-
-int main(int argc, char** argv) {
- using openscreen::Clock;
- using openscreen::PlatformClientPosix;
-
- openscreen::SetLogLevel(openscreen::LogLevel::kVerbose);
-
- std::string service_instance;
- std::string service_type("_openscreen._udp");
- if (argc >= 2)
- service_type = argv[1];
-
- if (argc >= 3)
- service_instance = argv[2];
-
- if (service_type.size() && service_type[0] == '.')
- return 1;
-
- auto labels = openscreen::osp::SplitByDot(service_type);
- if (labels.size() != 2)
- return 1;
-
- openscreen::osp::ServiceMap services;
- openscreen::osp::g_services = &services;
-
- PlatformClientPosix::Create(std::chrono::milliseconds(50));
-
- openscreen::osp::BrowseDemo(
- PlatformClientPosix::GetInstance()->GetTaskRunner(), labels[0], labels[1],
- service_instance);
-
- PlatformClientPosix::ShutDown();
-
- openscreen::osp::g_services = nullptr;
- return 0;
-}
diff --git a/osp/impl/discovery/mdns/mdns_responder_adapter.cc b/osp/impl/discovery/mdns/mdns_responder_adapter.cc
deleted file mode 100644
index edf25503..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_adapter.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
-
-namespace openscreen {
-namespace osp {
-
-QueryEventHeader::QueryEventHeader() = default;
-QueryEventHeader::QueryEventHeader(QueryEventHeader::Type response_type,
- UdpSocket* socket)
- : response_type(response_type), socket(socket) {}
-QueryEventHeader::QueryEventHeader(QueryEventHeader&&) noexcept = default;
-QueryEventHeader::~QueryEventHeader() = default;
-QueryEventHeader& QueryEventHeader::operator=(QueryEventHeader&&) noexcept =
- default;
-
-AEvent::AEvent() = default;
-AEvent::AEvent(QueryEventHeader header,
- DomainName domain_name,
- IPAddress address)
- : header(std::move(header)),
- domain_name(std::move(domain_name)),
- address(std::move(address)) {}
-AEvent::AEvent(AEvent&&) noexcept = default;
-AEvent::~AEvent() = default;
-AEvent& AEvent::operator=(AEvent&&) noexcept = default;
-
-AaaaEvent::AaaaEvent() = default;
-AaaaEvent::AaaaEvent(QueryEventHeader header,
- DomainName domain_name,
- IPAddress address)
- : header(std::move(header)),
- domain_name(std::move(domain_name)),
- address(std::move(address)) {}
-AaaaEvent::AaaaEvent(AaaaEvent&&) noexcept = default;
-AaaaEvent::~AaaaEvent() = default;
-AaaaEvent& AaaaEvent::operator=(AaaaEvent&&) noexcept = default;
-
-PtrEvent::PtrEvent() = default;
-PtrEvent::PtrEvent(QueryEventHeader header, DomainName service_instance)
- : header(std::move(header)),
- service_instance(std::move(service_instance)) {}
-PtrEvent::PtrEvent(PtrEvent&&) noexcept = default;
-PtrEvent::~PtrEvent() = default;
-PtrEvent& PtrEvent::operator=(PtrEvent&&) noexcept = default;
-
-SrvEvent::SrvEvent() = default;
-SrvEvent::SrvEvent(QueryEventHeader header,
- DomainName service_instance,
- DomainName domain_name,
- uint16_t port)
- : header(std::move(header)),
- service_instance(std::move(service_instance)),
- domain_name(std::move(domain_name)),
- port(port) {}
-SrvEvent::SrvEvent(SrvEvent&&) noexcept = default;
-SrvEvent::~SrvEvent() = default;
-SrvEvent& SrvEvent::operator=(SrvEvent&&) noexcept = default;
-
-TxtEvent::TxtEvent() = default;
-TxtEvent::TxtEvent(QueryEventHeader header,
- DomainName service_instance,
- std::vector<std::string> txt_info)
- : header(std::move(header)),
- service_instance(std::move(service_instance)),
- txt_info(std::move(txt_info)) {}
-TxtEvent::TxtEvent(TxtEvent&&) noexcept = default;
-TxtEvent::~TxtEvent() = default;
-TxtEvent& TxtEvent::operator=(TxtEvent&&) noexcept = default;
-
-MdnsResponderAdapter::MdnsResponderAdapter() = default;
-MdnsResponderAdapter::~MdnsResponderAdapter() = default;
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/discovery/mdns/mdns_responder_adapter.h b/osp/impl/discovery/mdns/mdns_responder_adapter.h
deleted file mode 100644
index 66083d57..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_adapter.h
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_H_
-#define OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_H_
-
-#include <cstdint>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "osp/impl/discovery/mdns/domain_name.h"
-#include "osp/impl/discovery/mdns/mdns_responder_platform.h"
-#include "platform/api/network_interface.h"
-#include "platform/api/time.h"
-#include "platform/api/udp_socket.h"
-#include "platform/base/error.h"
-#include "platform/base/ip_address.h"
-
-namespace openscreen {
-namespace osp {
-
-struct QueryEventHeader {
- enum class Type {
- kAdded = 0,
- kAddedNoCache,
- kRemoved,
- };
-
- QueryEventHeader();
- QueryEventHeader(Type response_type, UdpSocket* socket);
- QueryEventHeader(QueryEventHeader&&) noexcept;
- ~QueryEventHeader();
- QueryEventHeader& operator=(QueryEventHeader&&) noexcept;
-
- Type response_type;
- UdpSocket* socket;
-};
-
-struct PtrEvent {
- PtrEvent();
- PtrEvent(QueryEventHeader header, DomainName service_instance);
- PtrEvent(PtrEvent&&) noexcept;
- ~PtrEvent();
- PtrEvent& operator=(PtrEvent&&) noexcept;
-
- QueryEventHeader header;
- DomainName service_instance;
-};
-
-struct SrvEvent {
- SrvEvent();
- SrvEvent(QueryEventHeader header,
- DomainName service_instance,
- DomainName domain_name,
- uint16_t port);
- SrvEvent(SrvEvent&&) noexcept;
- ~SrvEvent();
- SrvEvent& operator=(SrvEvent&&) noexcept;
-
- QueryEventHeader header;
- DomainName service_instance;
- DomainName domain_name;
- uint16_t port;
-};
-
-struct TxtEvent {
- TxtEvent();
- TxtEvent(QueryEventHeader header,
- DomainName service_instance,
- std::vector<std::string> txt_info);
- TxtEvent(TxtEvent&&) noexcept;
- ~TxtEvent();
- TxtEvent& operator=(TxtEvent&&) noexcept;
-
- QueryEventHeader header;
- DomainName service_instance;
-
- // NOTE: mDNS does not specify a character encoding for the data in TXT
- // records.
- std::vector<std::string> txt_info;
-};
-
-struct AEvent {
- AEvent();
- AEvent(QueryEventHeader header, DomainName domain_name, IPAddress address);
- AEvent(AEvent&&) noexcept;
- ~AEvent();
- AEvent& operator=(AEvent&&) noexcept;
-
- QueryEventHeader header;
- DomainName domain_name;
- IPAddress address;
-};
-
-struct AaaaEvent {
- AaaaEvent();
- AaaaEvent(QueryEventHeader header, DomainName domain_name, IPAddress address);
- AaaaEvent(AaaaEvent&&) noexcept;
- ~AaaaEvent();
- AaaaEvent& operator=(AaaaEvent&&) noexcept;
-
- QueryEventHeader header;
- DomainName domain_name;
- IPAddress address;
-};
-
-enum class MdnsResponderErrorCode {
- kNoError = 0,
- kUnsupportedError,
- kDomainOverflowError,
- kInvalidParameters,
- kUnknownError,
-};
-
-// This interface wraps all the functionality of mDNSResponder, which includes
-// both listening and publishing. As a result, some methods are only used by
-// listeners, some are only used by publishers, and some are used by both.
-//
-// Listening for records might look like this:
-// adapter->Init();
-//
-// // Once for each interface, the meaning of false is described below.
-// adapter->RegisterInterface(..., false);
-//
-// adapter->StartPtrQuery("_openscreen._udp");
-// adapter->RunTasks();
-//
-// // When receiving multicast UDP traffic from port 5353.
-// adapter->OnDataReceived(...);
-// adapter->RunTasks();
-//
-// // Check |ptrs| for responses after pulling.
-// auto ptrs = adapter->TakePtrResponses();
-//
-// // Eventually...
-// adapter->StopPtrQuery("_openscreen._udp");
-//
-// Publishing a service might look like this:
-// adapter->Init();
-//
-// // Once for each interface, the meaning of true is described below.
-// adapter->RegisterInterface(..., true);
-//
-// adapter->SetHostLabel("deadbeef");
-// adapter->RegisterService("living-room", "_openscreen._udp", ...);
-// adapter->RunTasks();
-//
-// // When receiving multicast UDP traffic from port 5353.
-// adapter->OnDataReceived(...);
-// adapter->RunTasks();
-//
-// // Eventually...
-// adapter->DeregisterService("living-room", "_openscreen", "_udp");
-//
-// Additionally, it's important to understand that mDNSResponder may defer some
-// tasks (e.g. parsing responses, sending queries, etc.) and those deferred
-// tasks are only run when RunTasks is called. Therefore, RunTasks should be
-// called after any sequence of calls to mDNSResponder. It also returns a
-// timeout value, after which it must be called again (e.g. for maintaining its
-// cache).
-class MdnsResponderAdapter : public UdpSocket::Client {
- public:
- MdnsResponderAdapter();
- virtual ~MdnsResponderAdapter() = 0;
-
- // Initializes mDNSResponder. This should be called before any queries or
- // service registrations are made.
- virtual Error Init() = 0;
-
- // Stops all open queries and service registrations. If this is not called
- // before destruction, any registered services will not send their goodbye
- // messages.
- virtual void Close() = 0;
-
- // Called to change the name published by the A and AAAA records for the host
- // when any service is active (via RegisterService). Returns true if the
- // label was set successfully, false otherwise (e.g. the label did not meet
- // DNS name requirements).
- virtual Error SetHostLabel(const std::string& host_label) = 0;
-
- // The following methods register and deregister a network interface with
- // mDNSResponder. |socket| will be used to identify which interface received
- // the data in OnDataReceived and will be used to send data via the platform
- // layer.
- virtual Error RegisterInterface(const InterfaceInfo& interface_info,
- const IPSubnet& interface_address,
- UdpSocket* socket) = 0;
- virtual Error DeregisterInterface(UdpSocket* socket) = 0;
-
- // Returns the time period after which this method must be called again, if
- // any.
- virtual Clock::duration RunTasks() = 0;
-
- virtual std::vector<PtrEvent> TakePtrResponses() = 0;
- virtual std::vector<SrvEvent> TakeSrvResponses() = 0;
- virtual std::vector<TxtEvent> TakeTxtResponses() = 0;
- virtual std::vector<AEvent> TakeAResponses() = 0;
- virtual std::vector<AaaaEvent> TakeAaaaResponses() = 0;
-
- virtual MdnsResponderErrorCode StartPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) = 0;
- virtual MdnsResponderErrorCode StartSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) = 0;
- virtual MdnsResponderErrorCode StartTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) = 0;
- virtual MdnsResponderErrorCode StartAQuery(UdpSocket* socket,
- const DomainName& domain_name) = 0;
- virtual MdnsResponderErrorCode StartAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) = 0;
-
- virtual MdnsResponderErrorCode StopPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) = 0;
- virtual MdnsResponderErrorCode StopSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) = 0;
- virtual MdnsResponderErrorCode StopTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) = 0;
- virtual MdnsResponderErrorCode StopAQuery(UdpSocket* socket,
- const DomainName& domain_name) = 0;
- virtual MdnsResponderErrorCode StopAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) = 0;
-
- // The following methods concern advertising a service via mDNS. The
- // arguments correspond to values needed in the PTR, SRV, and TXT records that
- // will be published for the service. An A or AAAA record will also be
- // published with the service for each active interface known to mDNSResponder
- // via RegisterInterface.
- virtual MdnsResponderErrorCode RegisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const DomainName& target_host,
- uint16_t target_port,
- const std::map<std::string, std::string>& txt_data) = 0;
- virtual MdnsResponderErrorCode DeregisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol) = 0;
- virtual MdnsResponderErrorCode UpdateTxtData(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::map<std::string, std::string>& txt_data) = 0;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_H_
diff --git a/osp/impl/discovery/mdns/mdns_responder_adapter_impl.cc b/osp/impl/discovery/mdns/mdns_responder_adapter_impl.cc
deleted file mode 100644
index 205e125b..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_adapter_impl.cc
+++ /dev/null
@@ -1,1044 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter_impl.h"
-
-#include <algorithm>
-#include <cctype>
-#include <cstring>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "util/osp_logging.h"
-#include "util/trace_logging.h"
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-// RFC 1035 specifies a max string length of 256, including the leading length
-// octet.
-constexpr size_t kMaxDnsStringLength = 255;
-
-// RFC 6763 recommends a maximum key length of 9 characters.
-constexpr size_t kMaxTxtKeyLength = 9;
-
-constexpr size_t kMaxStaticTxtDataSize = 256;
-
-static_assert(sizeof(std::declval<RData>().u.txt) == kMaxStaticTxtDataSize,
- "mDNSResponder static TXT data size expected to be 256 bytes");
-
-static_assert(sizeof(mDNSAddr::ip.v4.b) == 4u,
- "mDNSResponder IPv4 address must be 4 bytes");
-static_assert(sizeof(mDNSAddr::ip.v6.b) == 16u,
- "mDNSResponder IPv6 address must be 16 bytes");
-
-void AssignMdnsPort(mDNSIPPort* mdns_port, uint16_t port) {
- mdns_port->b[0] = (port >> 8) & 0xff;
- mdns_port->b[1] = port & 0xff;
-}
-
-uint16_t GetNetworkOrderPort(const mDNSOpaque16& port) {
- return port.b[0] << 8 | port.b[1];
-}
-
-bool IsValidServiceName(const std::string& service_name) {
- // Service name requirements come from RFC 6335:
- // - No more than 16 characters.
- // - Begin with '_'.
- // - Next is a letter or digit and end with a letter or digit.
- // - May contain hyphens, but no consecutive hyphens.
- // - Must contain at least one letter.
- if (service_name.size() <= 1 || service_name.size() > 16)
- return false;
-
- if (service_name[0] != '_' || !std::isalnum(service_name[1]) ||
- !std::isalnum(service_name.back())) {
- return false;
- }
- bool has_alpha = false;
- bool previous_hyphen = false;
- for (auto it = service_name.begin() + 1; it != service_name.end(); ++it) {
- if (*it == '-' && previous_hyphen)
- return false;
-
- previous_hyphen = *it == '-';
- has_alpha = has_alpha || std::isalpha(*it);
- }
- return has_alpha && !previous_hyphen;
-}
-
-bool IsValidServiceProtocol(const std::string& protocol) {
- // RFC 6763 requires _tcp be used for TCP services and _udp for all others.
- return protocol == "_tcp" || protocol == "_udp";
-}
-
-void MakeLocalServiceNameParts(const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- domainlabel* instance,
- domainlabel* name,
- domainlabel* protocol,
- domainname* type,
- domainname* domain) {
- MakeDomainLabelFromLiteralString(instance, service_instance.c_str());
- MakeDomainLabelFromLiteralString(name, service_name.c_str());
- MakeDomainLabelFromLiteralString(protocol, service_protocol.c_str());
- type->c[0] = 0;
- AppendDomainLabel(type, name);
- AppendDomainLabel(type, protocol);
- const DomainName local_domain = DomainName::GetLocalDomain();
- std::copy(local_domain.domain_name().begin(),
- local_domain.domain_name().end(), domain->c);
-}
-
-void MakeSubnetMaskFromPrefixLengthV4(uint8_t mask[4], uint8_t prefix_length) {
- for (int i = 0; i < 4; prefix_length -= 8, ++i) {
- if (prefix_length >= 8) {
- mask[i] = 0xff;
- } else if (prefix_length > 0) {
- mask[i] = 0xff << (8 - prefix_length);
- } else {
- mask[i] = 0;
- }
- }
-}
-
-void MakeSubnetMaskFromPrefixLengthV6(uint8_t mask[16], uint8_t prefix_length) {
- for (int i = 0; i < 16; prefix_length -= 8, ++i) {
- if (prefix_length >= 8) {
- mask[i] = 0xff;
- } else if (prefix_length > 0) {
- mask[i] = 0xff << (8 - prefix_length);
- } else {
- mask[i] = 0;
- }
- }
-}
-
-bool IsValidTxtDataKey(const std::string& s) {
- if (s.size() > kMaxTxtKeyLength)
- return false;
- for (unsigned char c : s)
- if (c < 0x20 || c > 0x7e || c == '=')
- return false;
- return true;
-}
-
-std::string MakeTxtData(const std::map<std::string, std::string>& txt_data) {
- std::string txt;
- txt.reserve(kMaxStaticTxtDataSize);
- for (const auto& line : txt_data) {
- const auto key_size = line.first.size();
- const auto value_size = line.second.size();
- const auto line_size = value_size ? (key_size + 1 + value_size) : key_size;
- if (!IsValidTxtDataKey(line.first) || line_size > kMaxDnsStringLength ||
- (txt.size() + 1 + line_size) > kMaxStaticTxtDataSize) {
- return {};
- }
- txt.push_back(line_size);
- txt += line.first;
- if (value_size) {
- txt.push_back('=');
- txt += line.second;
- }
- }
- return txt;
-}
-
-MdnsResponderErrorCode MapMdnsError(int err) {
- switch (err) {
- case mStatus_NoError:
- return MdnsResponderErrorCode::kNoError;
- case mStatus_UnsupportedErr:
- return MdnsResponderErrorCode::kUnsupportedError;
- case mStatus_UnknownErr:
- return MdnsResponderErrorCode::kUnknownError;
- default:
- break;
- }
- OSP_DLOG_WARN << "unmapped mDNSResponder error: " << err;
- return MdnsResponderErrorCode::kUnknownError;
-}
-
-std::vector<std::string> ParseTxtResponse(
- const uint8_t data[kMaxStaticTxtDataSize],
- uint16_t length) {
- OSP_DCHECK(length <= kMaxStaticTxtDataSize);
- if (length == 0)
- return {};
-
- std::vector<std::string> lines;
- int total_pos = 0;
- while (total_pos < length) {
- uint8_t line_length = data[total_pos];
- if ((line_length > kMaxDnsStringLength) ||
- (total_pos + line_length >= length)) {
- return {};
- }
- lines.emplace_back(&data[total_pos + 1],
- &data[total_pos + line_length + 1]);
- total_pos += line_length + 1;
- }
- return lines;
-}
-
-void MdnsStatusCallback(mDNS* mdns, mStatus result) {
- OSP_LOG_INFO << "status good? " << (result == mStatus_NoError);
-}
-
-} // namespace
-
-MdnsResponderAdapterImpl::MdnsResponderAdapterImpl() = default;
-MdnsResponderAdapterImpl::~MdnsResponderAdapterImpl() = default;
-
-Error MdnsResponderAdapterImpl::Init() {
- const auto err =
- mDNS_Init(&mdns_, &platform_storage_, rr_cache_, kRrCacheSize,
- mDNS_Init_DontAdvertiseLocalAddresses, &MdnsStatusCallback,
- mDNS_Init_NoInitCallbackContext);
-
- return (err == mStatus_NoError) ? Error::None()
- : Error::Code::kInitializationFailure;
-}
-
-void MdnsResponderAdapterImpl::Close() {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::Close");
- mDNS_StartExit(&mdns_);
- // Let all services send goodbyes.
- while (!service_records_.empty()) {
- RunTasks();
- }
- mDNS_FinalExit(&mdns_);
-
- socket_to_questions_.clear();
-
- responder_interface_info_.clear();
-
- a_responses_.clear();
- aaaa_responses_.clear();
- ptr_responses_.clear();
- srv_responses_.clear();
- txt_responses_.clear();
-
- service_records_.clear();
-}
-
-Error MdnsResponderAdapterImpl::SetHostLabel(const std::string& host_label) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::SetHostLabel");
- if (host_label.size() > DomainName::kDomainNameMaxLabelLength)
- return Error::Code::kDomainNameTooLong;
-
- MakeDomainLabelFromLiteralString(&mdns_.hostlabel, host_label.c_str());
- mDNS_SetFQDN(&mdns_);
- if (!service_records_.empty()) {
- DeadvertiseInterfaces();
- AdvertiseInterfaces();
- }
- return Error::None();
-}
-
-Error MdnsResponderAdapterImpl::RegisterInterface(
- const InterfaceInfo& interface_info,
- const IPSubnet& interface_address,
- UdpSocket* socket) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::RegisterInterface");
- OSP_DCHECK(socket);
-
- const auto info_it = responder_interface_info_.find(socket);
- if (info_it != responder_interface_info_.end())
- return Error::None();
-
- NetworkInterfaceInfo& info = responder_interface_info_[socket];
- std::memset(&info, 0, sizeof(NetworkInterfaceInfo));
- info.InterfaceID = reinterpret_cast<decltype(info.InterfaceID)>(socket);
- info.Advertise = mDNSfalse;
- if (interface_address.address.IsV4()) {
- info.ip.type = mDNSAddrType_IPv4;
- interface_address.address.CopyToV4(info.ip.ip.v4.b);
- info.mask.type = mDNSAddrType_IPv4;
- MakeSubnetMaskFromPrefixLengthV4(info.mask.ip.v4.b,
- interface_address.prefix_length);
- } else {
- info.ip.type = mDNSAddrType_IPv6;
- interface_address.address.CopyToV6(info.ip.ip.v6.b);
- info.mask.type = mDNSAddrType_IPv6;
- MakeSubnetMaskFromPrefixLengthV6(info.mask.ip.v6.b,
- interface_address.prefix_length);
- }
-
- static_assert(sizeof(info.MAC.b) == sizeof(interface_info.hardware_address),
- "MAC address size mismatch.");
- memcpy(info.MAC.b, interface_info.hardware_address.data(),
- sizeof(info.MAC.b));
- info.McastTxRx = 1;
- platform_storage_.sockets.push_back(socket);
- auto result = mDNS_RegisterInterface(&mdns_, &info, mDNSfalse);
- OSP_LOG_IF(WARN, result != mStatus_NoError)
- << "mDNS_RegisterInterface failed: " << result;
-
- return (result == mStatus_NoError) ? Error::None()
- : Error::Code::kMdnsRegisterFailure;
-}
-
-Error MdnsResponderAdapterImpl::DeregisterInterface(UdpSocket* socket) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::DeregisterInterface");
- const auto info_it = responder_interface_info_.find(socket);
- if (info_it == responder_interface_info_.end())
- return Error::Code::kItemNotFound;
-
- const auto it = std::find(platform_storage_.sockets.begin(),
- platform_storage_.sockets.end(), socket);
- OSP_DCHECK(it != platform_storage_.sockets.end());
- platform_storage_.sockets.erase(it);
- if (info_it->second.RR_A.namestorage.c[0]) {
- mDNS_Deregister(&mdns_, &info_it->second.RR_A);
- info_it->second.RR_A.namestorage.c[0] = 0;
- }
- mDNS_DeregisterInterface(&mdns_, &info_it->second, mDNSfalse);
- responder_interface_info_.erase(info_it);
- return Error::None();
-}
-void MdnsResponderAdapterImpl::OnRead(UdpSocket* socket,
- ErrorOr<UdpPacket> packet_or_error) {
- if (packet_or_error.is_error()) {
- return;
- }
-
- UdpPacket packet = std::move(packet_or_error.value());
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::OnRead");
- mDNSAddr src;
- if (packet.source().address.IsV4()) {
- src.type = mDNSAddrType_IPv4;
- packet.source().address.CopyToV4(src.ip.v4.b);
- } else {
- src.type = mDNSAddrType_IPv6;
- packet.source().address.CopyToV6(src.ip.v6.b);
- }
- mDNSIPPort srcport;
- AssignMdnsPort(&srcport, packet.source().port);
-
- mDNSAddr dst;
- if (packet.source().address.IsV4()) {
- dst.type = mDNSAddrType_IPv4;
- packet.destination().address.CopyToV4(dst.ip.v4.b);
- } else {
- dst.type = mDNSAddrType_IPv6;
- packet.destination().address.CopyToV6(dst.ip.v6.b);
- }
- mDNSIPPort dstport;
- AssignMdnsPort(&dstport, packet.destination().port);
-
- auto* packet_data = packet.data();
- mDNSCoreReceive(&mdns_, const_cast<uint8_t*>(packet_data),
- packet_data + packet.size(), &src, srcport, &dst, dstport,
- reinterpret_cast<mDNSInterfaceID>(packet.socket()));
-}
-
-void MdnsResponderAdapterImpl::OnSendError(UdpSocket* socket, Error error) {
- // TODO(crbug.com/openscreen/67): Implement this method.
- OSP_UNIMPLEMENTED();
-}
-
-void MdnsResponderAdapterImpl::OnError(UdpSocket* socket, Error error) {
- // TODO(crbug.com/openscreen/67): Implement this method.
- OSP_UNIMPLEMENTED();
-}
-
-void MdnsResponderAdapterImpl::OnBound(UdpSocket* socket) {
- // TODO(crbug.com/openscreen/67): Implement this method.
- OSP_UNIMPLEMENTED();
-}
-
-Clock::duration MdnsResponderAdapterImpl::RunTasks() {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::RunTasks");
-
- mDNS_Execute(&mdns_);
-
- // Using mDNS_Execute's response to determine the correct timespan before
- // re-running this method doesn't work as expected. In the demo, under some
- // cases (about 25% of demo runs), the response is set to an unreasonably
- // large number (in the order of multiple days).
- //
- // From the mDNS documentation: "it is the responsibility [...] to set the
- // timer according to the m->NextScheduledEvent value, and then when the timer
- // fires, the timer callback function should call mDNS_Execute()" - for more
- // details see third_party/mDNSResponder/src/mDNSCore/mDNS.c : 3390
- //
- // Together, I understand these to mean that the mdns library code doesn't
- // expect we need mDNS_Execute called again by the task runner, only in the
- // other special cases it calls out in documentation (which we currently do
- // correctly). In our code, when we call mDNS_Execute again outside of the
- // task runner, the result is currently discarded. What we would need to do is
- // reach into the Task Runner's task and update how long before the task runs
- // again. That would require some large refactoring and changes.
- //
- // Additionally, beyond this, the mDNS code documents that there are cases
- // where the return value for mDNS_Execute should be ignored because it may be
- // stale.
- //
- // TODO(rwkeane): More accurately determine when the next run of this method
- // should be.
- constexpr auto seconds_before_next_run = 1;
-
- // Return as a duration.
- return std::chrono::seconds(seconds_before_next_run);
-}
-
-std::vector<PtrEvent> MdnsResponderAdapterImpl::TakePtrResponses() {
- return std::move(ptr_responses_);
-}
-
-std::vector<SrvEvent> MdnsResponderAdapterImpl::TakeSrvResponses() {
- return std::move(srv_responses_);
-}
-
-std::vector<TxtEvent> MdnsResponderAdapterImpl::TakeTxtResponses() {
- return std::move(txt_responses_);
-}
-
-std::vector<AEvent> MdnsResponderAdapterImpl::TakeAResponses() {
- return std::move(a_responses_);
-}
-
-std::vector<AaaaEvent> MdnsResponderAdapterImpl::TakeAaaaResponses() {
- return std::move(aaaa_responses_);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StartPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StartPtrQuery");
- auto& ptr_questions = socket_to_questions_[socket].ptr;
- if (ptr_questions.find(service_type) != ptr_questions.end())
- return MdnsResponderErrorCode::kNoError;
-
- auto& question = ptr_questions[service_type];
-
- question.InterfaceID = reinterpret_cast<mDNSInterfaceID>(socket);
- question.Target = {0};
- if (service_type.EndsWithLocalDomain()) {
- std::copy(service_type.domain_name().begin(),
- service_type.domain_name().end(), question.qname.c);
- } else {
- const DomainName local_domain = DomainName::GetLocalDomain();
- ErrorOr<DomainName> service_type_with_local =
- DomainName::Append(service_type, local_domain);
- if (!service_type_with_local) {
- return MdnsResponderErrorCode::kDomainOverflowError;
- }
- std::copy(service_type_with_local.value().domain_name().begin(),
- service_type_with_local.value().domain_name().end(),
- question.qname.c);
- }
- question.qtype = kDNSType_PTR;
- question.qclass = kDNSClass_IN;
- question.LongLived = mDNStrue;
- question.ExpectUnique = mDNSfalse;
- question.ForceMCast = mDNStrue;
- question.ReturnIntermed = mDNSfalse;
- question.SuppressUnusable = mDNSfalse;
- question.RetryWithSearchDomains = mDNSfalse;
- question.TimeoutQuestion = 0;
- question.WakeOnResolve = 0;
- question.SearchListIndex = 0;
- question.AppendSearchDomains = 0;
- question.AppendLocalSearchDomains = 0;
- question.qnameOrig = nullptr;
- question.QuestionCallback = &MdnsResponderAdapterImpl::PtrQueryCallback;
- question.QuestionContext = this;
- const auto err = mDNS_StartQuery(&mdns_, &question);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StartQuery failed: " << err;
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StartSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StartSrvQuery");
- if (!service_instance.EndsWithLocalDomain())
- return MdnsResponderErrorCode::kInvalidParameters;
-
- auto& srv_questions = socket_to_questions_[socket].srv;
- if (srv_questions.find(service_instance) != srv_questions.end())
- return MdnsResponderErrorCode::kNoError;
-
- auto& question = srv_questions[service_instance];
-
- question.InterfaceID = reinterpret_cast<mDNSInterfaceID>(socket);
- question.Target = {0};
- std::copy(service_instance.domain_name().begin(),
- service_instance.domain_name().end(), question.qname.c);
- question.qtype = kDNSType_SRV;
- question.qclass = kDNSClass_IN;
- question.LongLived = mDNStrue;
- question.ExpectUnique = mDNSfalse;
- question.ForceMCast = mDNStrue;
- question.ReturnIntermed = mDNSfalse;
- question.SuppressUnusable = mDNSfalse;
- question.RetryWithSearchDomains = mDNSfalse;
- question.TimeoutQuestion = 0;
- question.WakeOnResolve = 0;
- question.SearchListIndex = 0;
- question.AppendSearchDomains = 0;
- question.AppendLocalSearchDomains = 0;
- question.qnameOrig = nullptr;
- question.QuestionCallback = &MdnsResponderAdapterImpl::SrvQueryCallback;
- question.QuestionContext = this;
- const auto err = mDNS_StartQuery(&mdns_, &question);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StartQuery failed: " << err;
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StartTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StartTxtQuery");
- if (!service_instance.EndsWithLocalDomain())
- return MdnsResponderErrorCode::kInvalidParameters;
-
- auto& txt_questions = socket_to_questions_[socket].txt;
- if (txt_questions.find(service_instance) != txt_questions.end())
- return MdnsResponderErrorCode::kNoError;
-
- auto& question = txt_questions[service_instance];
-
- question.InterfaceID = reinterpret_cast<mDNSInterfaceID>(socket);
- question.Target = {0};
- std::copy(service_instance.domain_name().begin(),
- service_instance.domain_name().end(), question.qname.c);
- question.qtype = kDNSType_TXT;
- question.qclass = kDNSClass_IN;
- question.LongLived = mDNStrue;
- question.ExpectUnique = mDNSfalse;
- question.ForceMCast = mDNStrue;
- question.ReturnIntermed = mDNSfalse;
- question.SuppressUnusable = mDNSfalse;
- question.RetryWithSearchDomains = mDNSfalse;
- question.TimeoutQuestion = 0;
- question.WakeOnResolve = 0;
- question.SearchListIndex = 0;
- question.AppendSearchDomains = 0;
- question.AppendLocalSearchDomains = 0;
- question.qnameOrig = nullptr;
- question.QuestionCallback = &MdnsResponderAdapterImpl::TxtQueryCallback;
- question.QuestionContext = this;
- const auto err = mDNS_StartQuery(&mdns_, &question);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StartQuery failed: " << err;
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StartAQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StartAQuery");
- if (!domain_name.EndsWithLocalDomain())
- return MdnsResponderErrorCode::kInvalidParameters;
-
- auto& a_questions = socket_to_questions_[socket].a;
- if (a_questions.find(domain_name) != a_questions.end())
- return MdnsResponderErrorCode::kNoError;
-
- auto& question = a_questions[domain_name];
- std::copy(domain_name.domain_name().begin(), domain_name.domain_name().end(),
- question.qname.c);
-
- question.InterfaceID = reinterpret_cast<mDNSInterfaceID>(socket);
- question.Target = {0};
- question.qtype = kDNSType_A;
- question.qclass = kDNSClass_IN;
- question.LongLived = mDNStrue;
- question.ExpectUnique = mDNSfalse;
- question.ForceMCast = mDNStrue;
- question.ReturnIntermed = mDNSfalse;
- question.SuppressUnusable = mDNSfalse;
- question.RetryWithSearchDomains = mDNSfalse;
- question.TimeoutQuestion = 0;
- question.WakeOnResolve = 0;
- question.SearchListIndex = 0;
- question.AppendSearchDomains = 0;
- question.AppendLocalSearchDomains = 0;
- question.qnameOrig = nullptr;
- question.QuestionCallback = &MdnsResponderAdapterImpl::AQueryCallback;
- question.QuestionContext = this;
- const auto err = mDNS_StartQuery(&mdns_, &question);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StartQuery failed: " << err;
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StartAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::StartAaaaQuery");
- if (!domain_name.EndsWithLocalDomain())
- return MdnsResponderErrorCode::kInvalidParameters;
-
- auto& aaaa_questions = socket_to_questions_[socket].aaaa;
- if (aaaa_questions.find(domain_name) != aaaa_questions.end())
- return MdnsResponderErrorCode::kNoError;
-
- auto& question = aaaa_questions[domain_name];
- std::copy(domain_name.domain_name().begin(), domain_name.domain_name().end(),
- question.qname.c);
-
- question.InterfaceID = reinterpret_cast<mDNSInterfaceID>(socket);
- question.Target = {0};
- question.qtype = kDNSType_AAAA;
- question.qclass = kDNSClass_IN;
- question.LongLived = mDNStrue;
- question.ExpectUnique = mDNSfalse;
- question.ForceMCast = mDNStrue;
- question.ReturnIntermed = mDNSfalse;
- question.SuppressUnusable = mDNSfalse;
- question.RetryWithSearchDomains = mDNSfalse;
- question.TimeoutQuestion = 0;
- question.WakeOnResolve = 0;
- question.SearchListIndex = 0;
- question.AppendSearchDomains = 0;
- question.AppendLocalSearchDomains = 0;
- question.qnameOrig = nullptr;
- question.QuestionCallback = &MdnsResponderAdapterImpl::AaaaQueryCallback;
- question.QuestionContext = this;
- const auto err = mDNS_StartQuery(&mdns_, &question);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StartQuery failed: " << err;
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StopPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StopPtrQuery");
- auto interface_entry = socket_to_questions_.find(socket);
- if (interface_entry == socket_to_questions_.end())
- return MdnsResponderErrorCode::kNoError;
- auto entry = interface_entry->second.ptr.find(service_type);
- if (entry == interface_entry->second.ptr.end())
- return MdnsResponderErrorCode::kNoError;
-
- const auto err = mDNS_StopQuery(&mdns_, &entry->second);
- interface_entry->second.ptr.erase(entry);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StopQuery failed: " << err;
- RemoveQuestionsIfEmpty(socket);
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StopSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StopSrvQuery");
- auto interface_entry = socket_to_questions_.find(socket);
- if (interface_entry == socket_to_questions_.end())
- return MdnsResponderErrorCode::kNoError;
- auto entry = interface_entry->second.srv.find(service_instance);
- if (entry == interface_entry->second.srv.end())
- return MdnsResponderErrorCode::kNoError;
-
- const auto err = mDNS_StopQuery(&mdns_, &entry->second);
- interface_entry->second.srv.erase(entry);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StopQuery failed: " << err;
- RemoveQuestionsIfEmpty(socket);
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StopTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StopTxtQuery");
- auto interface_entry = socket_to_questions_.find(socket);
- if (interface_entry == socket_to_questions_.end())
- return MdnsResponderErrorCode::kNoError;
- auto entry = interface_entry->second.txt.find(service_instance);
- if (entry == interface_entry->second.txt.end())
- return MdnsResponderErrorCode::kNoError;
-
- const auto err = mDNS_StopQuery(&mdns_, &entry->second);
- interface_entry->second.txt.erase(entry);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StopQuery failed: " << err;
- RemoveQuestionsIfEmpty(socket);
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StopAQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StopAQuery");
- auto interface_entry = socket_to_questions_.find(socket);
- if (interface_entry == socket_to_questions_.end())
- return MdnsResponderErrorCode::kNoError;
- auto entry = interface_entry->second.a.find(domain_name);
- if (entry == interface_entry->second.a.end())
- return MdnsResponderErrorCode::kNoError;
-
- const auto err = mDNS_StopQuery(&mdns_, &entry->second);
- interface_entry->second.a.erase(entry);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StopQuery failed: " << err;
- RemoveQuestionsIfEmpty(socket);
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::StopAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::StopAaaaQuery");
- auto interface_entry = socket_to_questions_.find(socket);
- if (interface_entry == socket_to_questions_.end())
- return MdnsResponderErrorCode::kNoError;
- auto entry = interface_entry->second.aaaa.find(domain_name);
- if (entry == interface_entry->second.aaaa.end())
- return MdnsResponderErrorCode::kNoError;
-
- const auto err = mDNS_StopQuery(&mdns_, &entry->second);
- interface_entry->second.aaaa.erase(entry);
- OSP_LOG_IF(WARN, err != mStatus_NoError) << "mDNS_StopQuery failed: " << err;
- RemoveQuestionsIfEmpty(socket);
- return MapMdnsError(err);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::RegisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const DomainName& target_host,
- uint16_t target_port,
- const std::map<std::string, std::string>& txt_data) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::RegisterService");
- OSP_DCHECK(IsValidServiceName(service_name));
- OSP_DCHECK(IsValidServiceProtocol(service_protocol));
- service_records_.push_back(std::make_unique<ServiceRecordSet>());
- auto* service_record = service_records_.back().get();
- domainlabel instance;
- domainlabel name;
- domainlabel protocol;
- domainname type;
- domainname domain;
- domainname host;
- mDNSIPPort port;
-
- MakeLocalServiceNameParts(service_instance, service_name, service_protocol,
- &instance, &name, &protocol, &type, &domain);
- std::copy(target_host.domain_name().begin(), target_host.domain_name().end(),
- host.c);
- AssignMdnsPort(&port, target_port);
- auto txt = MakeTxtData(txt_data);
- if (txt.size() > kMaxStaticTxtDataSize) {
- // Not handling oversized TXT records.
- return MdnsResponderErrorCode::kUnsupportedError;
- }
-
- if (service_records_.size() == 1)
- AdvertiseInterfaces();
-
- auto result = mDNS_RegisterService(
- &mdns_, service_record, &instance, &type, &domain, &host, port,
- reinterpret_cast<const uint8_t*>(txt.data()), txt.size(), nullptr, 0,
- mDNSInterface_Any, &MdnsResponderAdapterImpl::ServiceCallback, this, 0);
-
- if (result != mStatus_NoError) {
- service_records_.pop_back();
- if (service_records_.empty())
- DeadvertiseInterfaces();
- }
- return MapMdnsError(result);
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::DeregisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::DeregisterService");
- domainlabel instance;
- domainlabel name;
- domainlabel protocol;
- domainname type;
- domainname domain;
- domainname full_instance_name;
-
- MakeLocalServiceNameParts(service_instance, service_name, service_protocol,
- &instance, &name, &protocol, &type, &domain);
- if (!ConstructServiceName(&full_instance_name, &instance, &type, &domain))
- return MdnsResponderErrorCode::kInvalidParameters;
-
- for (auto it = service_records_.begin(); it != service_records_.end(); ++it) {
- if (SameDomainName(&full_instance_name, &(*it)->RR_SRV.namestorage)) {
- // |it| will be removed from |service_records_| in ServiceCallback, when
- // mDNSResponder is done with the memory.
- mDNS_DeregisterService(&mdns_, it->get());
- return MdnsResponderErrorCode::kNoError;
- }
- }
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode MdnsResponderAdapterImpl::UpdateTxtData(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::map<std::string, std::string>& txt_data) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderAdapterImpl::UpdateTxtData");
- domainlabel instance;
- domainlabel name;
- domainlabel protocol;
- domainname type;
- domainname domain;
- domainname full_instance_name;
-
- MakeLocalServiceNameParts(service_instance, service_name, service_protocol,
- &instance, &name, &protocol, &type, &domain);
- if (!ConstructServiceName(&full_instance_name, &instance, &type, &domain))
- return MdnsResponderErrorCode::kInvalidParameters;
- std::string txt = MakeTxtData(txt_data);
- if (txt.size() > kMaxStaticTxtDataSize) {
- // Not handling oversized TXT records.
- return MdnsResponderErrorCode::kUnsupportedError;
- }
-
- for (std::unique_ptr<ServiceRecordSet>& record : service_records_) {
- if (SameDomainName(&full_instance_name, &record->RR_SRV.namestorage)) {
- std::copy(txt.begin(), txt.end(), record->RR_TXT.rdatastorage.u.txt.c);
- mDNS_Update(&mdns_, &record->RR_TXT, 0, txt.size(),
- &record->RR_TXT.rdatastorage, nullptr);
- return MdnsResponderErrorCode::kNoError;
- }
- }
- return MdnsResponderErrorCode::kNoError;
-}
-
-// static
-void MdnsResponderAdapterImpl::AQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::AQueryCallback");
- OSP_DCHECK(question);
- OSP_DCHECK(answer);
- OSP_DCHECK_EQ(answer->rrtype, kDNSType_A);
- DomainName domain(std::vector<uint8_t>(
- question->qname.c,
- question->qname.c + DomainNameLength(&question->qname)));
- IPAddress address(answer->rdata->u.ipv4.b);
-
- auto* adapter =
- reinterpret_cast<MdnsResponderAdapterImpl*>(question->QuestionContext);
- OSP_DCHECK(adapter);
- auto event_type = QueryEventHeader::Type::kAddedNoCache;
- if (added == QC_add) {
- event_type = QueryEventHeader::Type::kAdded;
- } else if (added == QC_rmv) {
- event_type = QueryEventHeader::Type::kRemoved;
- } else {
- OSP_DCHECK_EQ(added, QC_addnocache);
- }
- adapter->a_responses_.emplace_back(
- QueryEventHeader{event_type,
- reinterpret_cast<UdpSocket*>(answer->InterfaceID)},
- std::move(domain), address);
-}
-
-// static
-void MdnsResponderAdapterImpl::AaaaQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::AaaaQueryCallback");
- OSP_DCHECK(question);
- OSP_DCHECK(answer);
- OSP_DCHECK_EQ(answer->rrtype, kDNSType_A);
- DomainName domain(std::vector<uint8_t>(
- question->qname.c,
- question->qname.c + DomainNameLength(&question->qname)));
- IPAddress address(IPAddress::Version::kV6, answer->rdata->u.ipv6.b);
-
- auto* adapter =
- reinterpret_cast<MdnsResponderAdapterImpl*>(question->QuestionContext);
- OSP_DCHECK(adapter);
- auto event_type = QueryEventHeader::Type::kAddedNoCache;
- if (added == QC_add) {
- event_type = QueryEventHeader::Type::kAdded;
- } else if (added == QC_rmv) {
- event_type = QueryEventHeader::Type::kRemoved;
- } else {
- OSP_DCHECK_EQ(added, QC_addnocache);
- }
- adapter->aaaa_responses_.emplace_back(
- QueryEventHeader{event_type,
- reinterpret_cast<UdpSocket*>(answer->InterfaceID)},
- std::move(domain), address);
-}
-
-// static
-void MdnsResponderAdapterImpl::PtrQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::PtrQueryCallback");
- OSP_DCHECK(question);
- OSP_DCHECK(answer);
- OSP_DCHECK_EQ(answer->rrtype, kDNSType_PTR);
- DomainName result(std::vector<uint8_t>(
- answer->rdata->u.name.c,
- answer->rdata->u.name.c + DomainNameLength(&answer->rdata->u.name)));
-
- auto* adapter =
- reinterpret_cast<MdnsResponderAdapterImpl*>(question->QuestionContext);
- OSP_DCHECK(adapter);
- auto event_type = QueryEventHeader::Type::kAddedNoCache;
- if (added == QC_add) {
- event_type = QueryEventHeader::Type::kAdded;
- } else if (added == QC_rmv) {
- event_type = QueryEventHeader::Type::kRemoved;
- } else {
- OSP_DCHECK_EQ(added, QC_addnocache);
- }
- adapter->ptr_responses_.emplace_back(
- QueryEventHeader{event_type,
- reinterpret_cast<UdpSocket*>(answer->InterfaceID)},
- std::move(result));
-}
-
-// static
-void MdnsResponderAdapterImpl::SrvQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added) {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::SrvQueryCallback");
- OSP_DCHECK(question);
- OSP_DCHECK(answer);
- OSP_DCHECK_EQ(answer->rrtype, kDNSType_SRV);
- DomainName service(std::vector<uint8_t>(
- question->qname.c,
- question->qname.c + DomainNameLength(&question->qname)));
- DomainName result(
- std::vector<uint8_t>(answer->rdata->u.srv.target.c,
- answer->rdata->u.srv.target.c +
- DomainNameLength(&answer->rdata->u.srv.target)));
-
- auto* adapter =
- reinterpret_cast<MdnsResponderAdapterImpl*>(question->QuestionContext);
- OSP_DCHECK(adapter);
- auto event_type = QueryEventHeader::Type::kAddedNoCache;
- if (added == QC_add) {
- event_type = QueryEventHeader::Type::kAdded;
- } else if (added == QC_rmv) {
- event_type = QueryEventHeader::Type::kRemoved;
- } else {
- OSP_DCHECK_EQ(added, QC_addnocache);
- }
- adapter->srv_responses_.emplace_back(
- QueryEventHeader{event_type,
- reinterpret_cast<UdpSocket*>(answer->InterfaceID)},
- std::move(service), std::move(result),
- GetNetworkOrderPort(answer->rdata->u.srv.port));
-}
-
-// static
-void MdnsResponderAdapterImpl::TxtQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added) {
- OSP_DCHECK(question);
- OSP_DCHECK(answer);
- OSP_DCHECK_EQ(answer->rrtype, kDNSType_TXT);
- DomainName service(std::vector<uint8_t>(
- question->qname.c,
- question->qname.c + DomainNameLength(&question->qname)));
- auto lines = ParseTxtResponse(answer->rdata->u.txt.c, answer->rdlength);
-
- auto* adapter =
- reinterpret_cast<MdnsResponderAdapterImpl*>(question->QuestionContext);
- OSP_DCHECK(adapter);
- auto event_type = QueryEventHeader::Type::kAddedNoCache;
- if (added == QC_add) {
- event_type = QueryEventHeader::Type::kAdded;
- } else if (added == QC_rmv) {
- event_type = QueryEventHeader::Type::kRemoved;
- } else {
- OSP_DCHECK_EQ(added, QC_addnocache);
- }
- adapter->txt_responses_.emplace_back(
- QueryEventHeader{event_type,
- reinterpret_cast<UdpSocket*>(answer->InterfaceID)},
- std::move(service), std::move(lines));
-}
-
-// static
-void MdnsResponderAdapterImpl::ServiceCallback(mDNS* m,
- ServiceRecordSet* service_record,
- mStatus result) {
- // TODO(btolsch): Handle mStatus_NameConflict.
- if (result == mStatus_MemFree) {
- OSP_DLOG_INFO << "free service record";
- auto* adapter = reinterpret_cast<MdnsResponderAdapterImpl*>(
- service_record->ServiceContext);
- auto& service_records = adapter->service_records_;
- service_records.erase(
- std::remove_if(
- service_records.begin(), service_records.end(),
- [service_record](const std::unique_ptr<ServiceRecordSet>& sr) {
- return sr.get() == service_record;
- }),
- service_records.end());
-
- if (service_records.empty())
- adapter->DeadvertiseInterfaces();
- }
-}
-
-void MdnsResponderAdapterImpl::AdvertiseInterfaces() {
- TRACE_SCOPED(TraceCategory::kMdns,
- "MdnsResponderAdapterImpl::AdvertiseInterfaces");
- for (auto& info : responder_interface_info_) {
- UdpSocket* socket = info.first;
- NetworkInterfaceInfo& interface_info = info.second;
- mDNS_SetupResourceRecord(&interface_info.RR_A, /** RDataStorage */ nullptr,
- reinterpret_cast<mDNSInterfaceID>(socket),
- kDNSType_A, kHostNameTTL, kDNSRecordTypeUnique,
- AuthRecordAny,
- /** Callback */ nullptr, /** Context */ nullptr);
- AssignDomainName(&interface_info.RR_A.namestorage,
- &mdns_.MulticastHostname);
- if (interface_info.ip.type == mDNSAddrType_IPv4) {
- interface_info.RR_A.resrec.rdata->u.ipv4 = interface_info.ip.ip.v4;
- } else {
- interface_info.RR_A.resrec.rdata->u.ipv6 = interface_info.ip.ip.v6;
- }
- mDNS_Register(&mdns_, &interface_info.RR_A);
- }
-}
-
-void MdnsResponderAdapterImpl::DeadvertiseInterfaces() {
- // Both loops below use the A resource record's domain name to determine
- // whether the record was advertised. AdvertiseInterfaces sets the domain
- // name before registering the A record, and this clears it after
- // deregistering.
- for (auto& info : responder_interface_info_) {
- NetworkInterfaceInfo& interface_info = info.second;
- if (interface_info.RR_A.namestorage.c[0]) {
- mDNS_Deregister(&mdns_, &interface_info.RR_A);
- interface_info.RR_A.namestorage.c[0] = 0;
- }
- }
-}
-
-void MdnsResponderAdapterImpl::RemoveQuestionsIfEmpty(UdpSocket* socket) {
- auto entry = socket_to_questions_.find(socket);
- bool empty = entry->second.a.empty() || entry->second.aaaa.empty() ||
- entry->second.ptr.empty() || entry->second.srv.empty() ||
- entry->second.txt.empty();
- if (empty)
- socket_to_questions_.erase(entry);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/discovery/mdns/mdns_responder_adapter_impl.h b/osp/impl/discovery/mdns/mdns_responder_adapter_impl.h
deleted file mode 100644
index d0dd55a1..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_adapter_impl.h
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_
-#define OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_
-
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
-#include "platform/api/udp_socket.h"
-#include "platform/base/error.h"
-#include "third_party/mDNSResponder/src/mDNSCore/mDNSEmbeddedAPI.h"
-
-namespace openscreen {
-namespace osp {
-
-class MdnsResponderAdapterImpl final : public MdnsResponderAdapter {
- public:
- static constexpr int kRrCacheSize = 500;
-
- MdnsResponderAdapterImpl();
- ~MdnsResponderAdapterImpl() override;
-
- Error Init() override;
- void Close() override;
-
- Error SetHostLabel(const std::string& host_label) override;
-
- Error RegisterInterface(const InterfaceInfo& interface_info,
- const IPSubnet& interface_address,
- UdpSocket* socket) override;
- Error DeregisterInterface(UdpSocket* socket) override;
-
- void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
- void OnSendError(UdpSocket* socket, Error error) override;
- void OnError(UdpSocket* socket, Error error) override;
- void OnBound(UdpSocket* socket) override;
-
- Clock::duration RunTasks() override;
-
- std::vector<PtrEvent> TakePtrResponses() override;
- std::vector<SrvEvent> TakeSrvResponses() override;
- std::vector<TxtEvent> TakeTxtResponses() override;
- std::vector<AEvent> TakeAResponses() override;
- std::vector<AaaaEvent> TakeAaaaResponses() override;
-
- MdnsResponderErrorCode StartPtrQuery(UdpSocket* socket,
- const DomainName& service_type) override;
- MdnsResponderErrorCode StartSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StartTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StartAQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
- MdnsResponderErrorCode StartAaaaQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
- MdnsResponderErrorCode StopPtrQuery(UdpSocket* socket,
- const DomainName& service_type) override;
- MdnsResponderErrorCode StopSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StopTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StopAQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
- MdnsResponderErrorCode StopAaaaQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
-
- MdnsResponderErrorCode RegisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const DomainName& target_host,
- uint16_t target_port,
- const std::map<std::string, std::string>& txt_data) override;
- MdnsResponderErrorCode DeregisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol) override;
- MdnsResponderErrorCode UpdateTxtData(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::map<std::string, std::string>& txt_data) override;
-
- private:
- struct Questions {
- std::map<DomainName, DNSQuestion, DomainNameComparator> a;
- std::map<DomainName, DNSQuestion, DomainNameComparator> aaaa;
- std::map<DomainName, DNSQuestion, DomainNameComparator> ptr;
- std::map<DomainName, DNSQuestion, DomainNameComparator> srv;
- std::map<DomainName, DNSQuestion, DomainNameComparator> txt;
- };
-
- static void AQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added);
- static void AaaaQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added);
- static void PtrQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added);
- static void SrvQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added);
- static void TxtQueryCallback(mDNS* m,
- DNSQuestion* question,
- const ResourceRecord* answer,
- QC_result added);
- static void ServiceCallback(mDNS* m,
- ServiceRecordSet* service_record,
- mStatus result);
-
- void AdvertiseInterfaces();
- void DeadvertiseInterfaces();
- void RemoveQuestionsIfEmpty(UdpSocket* socket);
-
- CacheEntity rr_cache_[kRrCacheSize];
-
- // The main context structure for mDNSResponder.
- mDNS mdns_;
-
- // Our own storage that is placed inside |mdns_|. The intent in C is to allow
- // us access to our own state during callbacks. Here we just use it to group
- // platform sockets.
- mDNS_PlatformSupport platform_storage_;
-
- std::map<UdpSocket*, Questions> socket_to_questions_;
-
- std::map<UdpSocket*, NetworkInterfaceInfo> responder_interface_info_;
-
- std::vector<AEvent> a_responses_;
- std::vector<AaaaEvent> aaaa_responses_;
- std::vector<PtrEvent> ptr_responses_;
- std::vector<SrvEvent> srv_responses_;
- std::vector<TxtEvent> txt_responses_;
-
- // A list of services we are advertising. ServiceRecordSet is an
- // mDNSResponder structure which holds all the resource record data
- // (PTR/SRV/TXT/A and misc.) that is necessary to advertise a service.
- std::vector<std::unique_ptr<ServiceRecordSet>> service_records_;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_ADAPTER_IMPL_H_
diff --git a/osp/impl/discovery/mdns/mdns_responder_adapter_impl_unittest.cc b/osp/impl/discovery/mdns/mdns_responder_adapter_impl_unittest.cc
deleted file mode 100644
index 29b76679..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_adapter_impl_unittest.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter_impl.h"
-
-#include <memory>
-#include <string>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::ElementsAreArray;
-
-// Example response for _openscreen._udp. Contains PTR, SRV, TXT, A records.
-uint8_t data[] = {
- 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03,
- 0x06, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, 0x0b, 0x5f, 0x6f, 0x70, 0x65,
- 0x6e, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x04, 0x5f, 0x75, 0x64, 0x70,
- 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x10, 0x80, 0x01, 0x00,
- 0x00, 0x11, 0x94, 0x00, 0x0e, 0x06, 0x79, 0x75, 0x72, 0x74, 0x6c, 0x65,
- 0x06, 0x74, 0x75, 0x72, 0x74, 0x6c, 0x65, 0x09, 0x5f, 0x73, 0x65, 0x72,
- 0x76, 0x69, 0x63, 0x65, 0x73, 0x07, 0x5f, 0x64, 0x6e, 0x73, 0x2d, 0x73,
- 0x64, 0xc0, 0x1f, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00,
- 0x02, 0xc0, 0x13, 0xc0, 0x13, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x11,
- 0x94, 0x00, 0x02, 0xc0, 0x0c, 0x11, 0x67, 0x69, 0x67, 0x6c, 0x69, 0x6f,
- 0x72, 0x6f, 0x6e, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63, 0x6f, 0x6e, 0xc0,
- 0x24, 0x00, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04, 0xac,
- 0x11, 0x20, 0x96, 0xc0, 0x0c, 0x00, 0x21, 0x80, 0x01, 0x00, 0x00, 0x00,
- 0x78, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x30, 0x39, 0xc0, 0x71, 0xc0,
- 0x0c, 0x00, 0x2f, 0x80, 0x01, 0x00, 0x00, 0x11, 0x94, 0x00, 0x09, 0xc0,
- 0x0c, 0x00, 0x05, 0x00, 0x00, 0x80, 0x00, 0x40, 0xc0, 0x71, 0x00, 0x2f,
- 0x80, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05, 0xc0, 0x71, 0x00, 0x01,
- 0x40, 0x00, 0x00, 0x29, 0x05, 0xa0, 0x00, 0x00, 0x11, 0x94, 0x00, 0x12,
- 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x50, 0x65, 0xf3, 0x41, 0x27, 0x01,
-};
-
-} // namespace
-
-TEST(MdnsResponderAdapterImplTest, ExampleData) {
- const DomainName openscreen_service{{11, '_', 'o', 'p', 'e', 'n', 's', 'c',
- 'r', 'e', 'e', 'n', 4, '_', 'u', 'd',
- 'p', 5, 'l', 'o', 'c', 'a', 'l', 0}};
- const IPEndpoint mdns_endpoint{{224, 0, 0, 251}, 5353};
-
- UdpPacket packet(std::begin(data), std::end(data));
- packet.set_source({{192, 168, 0, 2}, 6556});
- packet.set_destination(mdns_endpoint);
- packet.set_socket(nullptr);
-
- auto mdns_adapter =
- std::unique_ptr<MdnsResponderAdapter>(new MdnsResponderAdapterImpl);
- mdns_adapter->Init();
- mdns_adapter->StartPtrQuery(0, openscreen_service);
- mdns_adapter->OnRead(nullptr, std::move(packet));
- mdns_adapter->RunTasks();
-
- auto ptr = mdns_adapter->TakePtrResponses();
- ASSERT_EQ(1u, ptr.size());
- ASSERT_THAT(ptr[0].service_instance.GetLabels(),
- ElementsAre("turtle", "_openscreen", "_udp", "local"));
- mdns_adapter->StartSrvQuery(0, ptr[0].service_instance);
- mdns_adapter->StartTxtQuery(0, ptr[0].service_instance);
- mdns_adapter->RunTasks();
-
- auto srv = mdns_adapter->TakeSrvResponses();
- ASSERT_EQ(1u, srv.size());
- ASSERT_THAT(srv[0].domain_name.GetLabels(),
- ElementsAre("gigliorononomicon", "local"));
- EXPECT_EQ(12345, srv[0].port);
-
- auto txt = mdns_adapter->TakeTxtResponses();
- ASSERT_EQ(1u, txt.size());
- const std::string expected_txt[] = {"yurtle", "turtle"};
- EXPECT_THAT(txt[0].txt_info, ElementsAreArray(expected_txt));
-
- mdns_adapter->StartAQuery(0, srv[0].domain_name);
- mdns_adapter->RunTasks();
-
- auto a = mdns_adapter->TakeAResponses();
- ASSERT_EQ(1u, a.size());
- EXPECT_EQ((IPAddress{172, 17, 32, 150}), a[0].address);
-
- mdns_adapter->Close();
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/discovery/mdns/mdns_responder_platform.cc b/osp/impl/discovery/mdns/mdns_responder_platform.cc
deleted file mode 100644
index 14204ff5..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_platform.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/discovery/mdns/mdns_responder_platform.h"
-
-#include <algorithm>
-#include <chrono>
-#include <cstring>
-#include <limits>
-#include <vector>
-
-#include "platform/api/network_interface.h"
-#include "platform/api/time.h"
-#include "platform/api/udp_socket.h"
-#include "platform/base/error.h"
-#include "platform/base/ip_address.h"
-#include "third_party/mDNSResponder/src/mDNSCore/mDNSEmbeddedAPI.h"
-#include "util/osp_logging.h"
-
-namespace {
-
-using std::chrono::duration_cast;
-using std::chrono::hours;
-using std::chrono::milliseconds;
-using std::chrono::seconds;
-
-} // namespace
-
-extern "C" {
-
-const char ProgramName[] = "openscreen";
-
-mDNSs32 mDNSPlatformOneSecond = 1000;
-
-mStatus mDNSPlatformInit(mDNS* m) {
- mDNSCoreInitComplete(m, mStatus_NoError);
- return mStatus_NoError;
-}
-
-void mDNSPlatformClose(mDNS* m) {}
-
-mStatus mDNSPlatformSendUDP(const mDNS* m,
- const void* msg,
- const mDNSu8* last,
- mDNSInterfaceID InterfaceID,
- UDPSocket* src,
- const mDNSAddr* dst,
- mDNSIPPort dstport) {
- auto* const socket = reinterpret_cast<openscreen::UdpSocket*>(InterfaceID);
- const auto socket_it =
- std::find(m->p->sockets.begin(), m->p->sockets.end(), socket);
- if (socket_it == m->p->sockets.end())
- return mStatus_BadInterfaceErr;
-
- openscreen::IPEndpoint dest{
- openscreen::IPAddress{dst->type == mDNSAddrType_IPv4
- ? openscreen::IPAddress::Version::kV4
- : openscreen::IPAddress::Version::kV6,
- dst->ip.v4.b},
- static_cast<uint16_t>((dstport.b[0] << 8) | dstport.b[1])};
- const int64_t length = last - static_cast<const uint8_t*>(msg);
- if (length < 0 || length > std::numeric_limits<ssize_t>::max()) {
- return mStatus_BadParamErr;
- }
-
- // UDP is inherently lossy, so don't worry about async failures and let the
- // underlying protocol handle it.
- (*socket_it)->SendMessage(msg, length, dest);
- return mStatus_NoError;
-}
-
-void mDNSPlatformLock(const mDNS* m) {
- // We're single threaded.
-}
-
-void mDNSPlatformUnlock(const mDNS* m) {}
-
-void mDNSPlatformStrCopy(void* dst, const void* src) {
- // Unfortunately, the caller is responsible for making sure that dst
- // if of sufficient length to store the src string. Otherwise we may
- // cause an access violation.
- std::strcpy(static_cast<char*>(dst), // NOLINT
- static_cast<const char*>(src));
-}
-
-mDNSu32 mDNSPlatformStrLen(const void* src) {
- return std::strlen(static_cast<const char*>(src));
-}
-
-void mDNSPlatformMemCopy(void* dst, const void* src, mDNSu32 len) {
- std::memcpy(dst, src, len);
-}
-
-mDNSBool mDNSPlatformMemSame(const void* dst, const void* src, mDNSu32 len) {
- return std::memcmp(dst, src, len) == 0 ? mDNStrue : mDNSfalse;
-}
-
-void mDNSPlatformMemZero(void* dst, mDNSu32 len) {
- std::memset(dst, 0, len);
-}
-
-void* mDNSPlatformMemAllocate(mDNSu32 len) {
- return malloc(len);
-}
-
-void mDNSPlatformMemFree(void* mem) {
- free(mem);
-}
-
-mDNSu32 mDNSPlatformRandomSeed() {
- return std::chrono::steady_clock::now().time_since_epoch().count();
-}
-
-mStatus mDNSPlatformTimeInit() {
- return mStatus_NoError;
-}
-
-mDNSs32 mDNSPlatformRawTime() {
- using openscreen::Clock;
-
- const Clock::time_point now = Clock::now();
-
- // A signed 32-bit integer counting milliseconds only gives ~24.8 days of
- // range. Thus, the first time this function is called, record a new origin
- // timestamp to subtract from the raw monotonic clock values. The "one hour
- // before now" value is used to keep the results well-ahead of zero because
- // the mDNS library assumes this is the time since kernel boot and has hacks
- // to disable certain things in the first few minutes. :-/
- static const Clock::time_point origin = now - hours(1);
-
- const int64_t millis_since_origin =
- duration_cast<milliseconds>(now - origin).count();
- OSP_CHECK_LE(millis_since_origin, std::numeric_limits<mDNSs32>::max());
- return static_cast<mDNSs32>(millis_since_origin);
-}
-
-mDNSs32 mDNSPlatformUTC() {
- const auto seconds_since_epoch =
- duration_cast<seconds>(openscreen::GetWallTimeSinceUnixEpoch()).count();
-
- // The return type will cause overflow in early 2038. Warn future developers
- // a year ahead of time.
- constexpr mDNSs32 a_year_before_overflow =
- std::numeric_limits<mDNSs32>::max() -
- duration_cast<seconds>(365 * hours(24)).count();
- OSP_DCHECK_LE(seconds_since_epoch, a_year_before_overflow);
-
- return static_cast<mDNSs32>(seconds_since_epoch);
-}
-
-void mDNSPlatformWriteDebugMsg(const char* msg) {
- OSP_DVLOG << __func__ << ": " << msg;
-}
-
-void mDNSPlatformWriteLogMsg(const char* ident,
- const char* msg,
- mDNSLogLevel_t loglevel) {
- OSP_VLOG << __func__ << ": " << msg;
-}
-
-TCPSocket* mDNSPlatformTCPSocket(mDNS* const m,
- TCPSocketFlags flags,
- mDNSIPPort* port) {
- OSP_UNIMPLEMENTED();
- return nullptr;
-}
-
-TCPSocket* mDNSPlatformTCPAccept(TCPSocketFlags flags, int sd) {
- OSP_UNIMPLEMENTED();
- return nullptr;
-}
-
-int mDNSPlatformTCPGetFD(TCPSocket* sock) {
- OSP_UNIMPLEMENTED();
- return 0;
-}
-
-mStatus mDNSPlatformTCPConnect(TCPSocket* sock,
- const mDNSAddr* dst,
- mDNSOpaque16 dstport,
- domainname* hostname,
- mDNSInterfaceID InterfaceID,
- TCPConnectionCallback callback,
- void* context) {
- OSP_UNIMPLEMENTED();
- return mStatus_NoError;
-}
-
-void mDNSPlatformTCPCloseConnection(TCPSocket* sock) {
- OSP_UNIMPLEMENTED();
-}
-
-long mDNSPlatformReadTCP(TCPSocket* sock, // NOLINT
- void* buf,
- unsigned long buflen, // NOLINT
- mDNSBool* closed) {
- OSP_UNIMPLEMENTED();
- return 0;
-}
-
-long mDNSPlatformWriteTCP(TCPSocket* sock, // NOLINT
- const char* msg,
- unsigned long len) { // NOLINT
- OSP_UNIMPLEMENTED();
- return 0;
-}
-
-UDPSocket* mDNSPlatformUDPSocket(mDNS* const m,
- const mDNSIPPort requestedport) {
- OSP_UNIMPLEMENTED();
- return nullptr;
-}
-
-void mDNSPlatformUDPClose(UDPSocket* sock) {
- OSP_UNIMPLEMENTED();
-}
-
-void mDNSPlatformReceiveBPF_fd(mDNS* const m, int fd) {
- OSP_UNIMPLEMENTED();
-}
-
-void mDNSPlatformUpdateProxyList(mDNS* const m,
- const mDNSInterfaceID InterfaceID) {
- OSP_UNIMPLEMENTED();
-}
-
-void mDNSPlatformSendRawPacket(const void* const msg,
- const mDNSu8* const end,
- mDNSInterfaceID InterfaceID) {
- OSP_UNIMPLEMENTED();
-}
-
-void mDNSPlatformSetLocalAddressCacheEntry(mDNS* const m,
- const mDNSAddr* const tpa,
- const mDNSEthAddr* const tha,
- mDNSInterfaceID InterfaceID) {}
-
-void mDNSPlatformSourceAddrForDest(mDNSAddr* const src,
- const mDNSAddr* const dst) {}
-
-mStatus mDNSPlatformTLSSetupCerts(void) {
- OSP_UNIMPLEMENTED();
- return mStatus_NoError;
-}
-
-void mDNSPlatformTLSTearDownCerts(void) {
- OSP_UNIMPLEMENTED();
-}
-
-void mDNSPlatformSetDNSConfig(mDNS* const m,
- mDNSBool setservers,
- mDNSBool setsearch,
- domainname* const fqdn,
- DNameListElem** RegDomains,
- DNameListElem** BrowseDomains) {
- if (fqdn) {
- std::memset(fqdn, 0, sizeof(*fqdn));
- }
-}
-
-mStatus mDNSPlatformGetPrimaryInterface(mDNS* const m,
- mDNSAddr* v4,
- mDNSAddr* v6,
- mDNSAddr* router) {
- return mStatus_NoError;
-}
-
-void mDNSPlatformDynDNSHostNameStatusChanged(const domainname* const dname,
- const mStatus status) {}
-
-void mDNSPlatformSetAllowSleep(mDNS* const m,
- mDNSBool allowSleep,
- const char* reason) {}
-
-void mDNSPlatformSendWakeupPacket(mDNS* const m,
- mDNSInterfaceID InterfaceID,
- char* EthAddr,
- char* IPAddr,
- int iteration) {
- OSP_UNIMPLEMENTED();
-}
-
-mDNSBool mDNSPlatformValidRecordForInterface(AuthRecord* rr,
- const NetworkInterfaceInfo* intf) {
- OSP_UNIMPLEMENTED();
- return mDNStrue;
-}
-
-} // extern "C"
diff --git a/osp/impl/discovery/mdns/mdns_responder_platform.h b/osp/impl/discovery/mdns/mdns_responder_platform.h
deleted file mode 100644
index 342913fe..00000000
--- a/osp/impl/discovery/mdns/mdns_responder_platform.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_PLATFORM_H_
-#define OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_PLATFORM_H_
-
-#include <vector>
-
-#include "platform/api/udp_socket.h"
-
-struct mDNS_PlatformSupport_struct {
- std::vector<openscreen::UdpSocket*> sockets;
-};
-
-#endif // OSP_IMPL_DISCOVERY_MDNS_MDNS_RESPONDER_PLATFORM_H_
diff --git a/osp/impl/dns_sd_publisher_client.cc b/osp/impl/dns_sd_publisher_client.cc
new file mode 100644
index 00000000..322bd4e0
--- /dev/null
+++ b/osp/impl/dns_sd_publisher_client.cc
@@ -0,0 +1,131 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "osp/impl/dns_sd_publisher_client.h"
+
+#include <utility>
+
+#include "discovery/common/config.h"
+#include "discovery/dnssd/public/dns_sd_instance.h"
+#include "discovery/dnssd/public/dns_sd_txt_record.h"
+#include "discovery/public/dns_sd_service_factory.h"
+#include "osp/public/service_info.h"
+#include "platform/base/macros.h"
+#include "util/osp_logging.h"
+
+namespace openscreen {
+namespace osp {
+
+using State = ServicePublisher::State;
+
+namespace {
+
+constexpr char kFriendlyNameTxtKey[] = "fn";
+constexpr char kDnsSdDomainId[] = "local";
+
+discovery::DnsSdInstance ServiceConfigToDnsSdInstance(
+ const ServicePublisher::Config& config) {
+ discovery::DnsSdTxtRecord txt;
+ const bool did_set_everything =
+ txt.SetValue(kFriendlyNameTxtKey, config.friendly_name).ok();
+ OSP_DCHECK(did_set_everything);
+
+ // NOTE: Not totally clear how we should be using config.hostname, which in
+ // principle is already part of config.service_instance_name.
+ return discovery::DnsSdInstance(
+ config.service_instance_name, kOpenScreenServiceName, kDnsSdDomainId,
+ std::move(txt), config.connection_server_port);
+}
+
+} // namespace
+
+DnsSdPublisherClient::DnsSdPublisherClient(ServicePublisher::Observer* observer,
+ openscreen::TaskRunner* task_runner)
+ : observer_(observer), task_runner_(task_runner) {
+ OSP_DCHECK(observer_);
+ OSP_DCHECK(task_runner_);
+}
+
+DnsSdPublisherClient::~DnsSdPublisherClient() = default;
+
+void DnsSdPublisherClient::StartPublisher(
+ const ServicePublisher::Config& config) {
+ OSP_LOG_INFO << "StartPublisher with " << config.network_interfaces.size()
+ << " interfaces";
+ StartPublisherInternal(config);
+ Error result = dns_sd_publisher_->Register(config);
+ if (result.ok()) {
+ SetState(State::kRunning);
+ } else {
+ OnFatalError(result);
+ SetState(State::kStopped);
+ }
+}
+
+void DnsSdPublisherClient::StartAndSuspendPublisher(
+ const ServicePublisher::Config& config) {
+ StartPublisherInternal(config);
+ SetState(State::kSuspended);
+}
+
+void DnsSdPublisherClient::StopPublisher() {
+ dns_sd_publisher_.reset();
+ SetState(State::kStopped);
+}
+
+void DnsSdPublisherClient::SuspendPublisher() {
+ OSP_DCHECK(dns_sd_publisher_);
+ dns_sd_publisher_->DeregisterAll();
+ SetState(State::kSuspended);
+}
+
+void DnsSdPublisherClient::ResumePublisher(
+ const ServicePublisher::Config& config) {
+ OSP_DCHECK(dns_sd_publisher_);
+ dns_sd_publisher_->Register(config);
+ SetState(State::kRunning);
+}
+
+void DnsSdPublisherClient::OnFatalError(Error error) {
+ observer_->OnError(error);
+}
+
+void DnsSdPublisherClient::OnRecoverableError(Error error) {
+ observer_->OnError(error);
+}
+
+void DnsSdPublisherClient::StartPublisherInternal(
+ const ServicePublisher::Config& config) {
+ OSP_DCHECK(!dns_sd_publisher_);
+ if (!dns_sd_service_) {
+ dns_sd_service_ = CreateDnsSdServiceInternal(config);
+ }
+ dns_sd_publisher_ = std::make_unique<OspDnsSdPublisher>(
+ dns_sd_service_.get(), kOpenScreenServiceName,
+ ServiceConfigToDnsSdInstance);
+}
+
+SerialDeletePtr<discovery::DnsSdService>
+DnsSdPublisherClient::CreateDnsSdServiceInternal(
+ const ServicePublisher::Config& config) {
+ // NOTE: With the current API, the client cannot customize the behavior of
+ // DNS-SD beyond the interface list.
+ openscreen::discovery::Config dns_sd_config;
+ dns_sd_config.enable_querying = false;
+ dns_sd_config.network_info = config.network_interfaces;
+
+ // NOTE:
+ // It's desirable for the DNS-SD publisher and the DNS-SD listener for OSP to
+ // share the underlying mDNS socket and state, to avoid the agent from
+ // binding 2 sockets per network interface.
+ //
+ // This can be accomplished by having the agent use a shared instance of the
+ // discovery::DnsSdService, e.g. through a ref-counting handle, so that the
+ // OSP publisher and the OSP listener don't have to coordinate through an
+ // additional object.
+ return CreateDnsSdService(task_runner_, this, dns_sd_config);
+}
+
+} // namespace osp
+} // namespace openscreen
diff --git a/osp/impl/dns_sd_publisher_client.h b/osp/impl/dns_sd_publisher_client.h
new file mode 100644
index 00000000..9b055ed5
--- /dev/null
+++ b/osp/impl/dns_sd_publisher_client.h
@@ -0,0 +1,62 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef OSP_IMPL_DNS_SD_PUBLISHER_CLIENT_H_
+#define OSP_IMPL_DNS_SD_PUBLISHER_CLIENT_H_
+
+#include <memory>
+
+#include "discovery/common/reporting_client.h"
+#include "discovery/dnssd/public/dns_sd_service.h"
+#include "discovery/public/dns_sd_service_publisher.h"
+#include "osp/impl/service_publisher_impl.h"
+#include "platform/api/serial_delete_ptr.h"
+
+namespace openscreen {
+
+class TaskRunner;
+
+namespace osp {
+
+class DnsSdPublisherClient final : public ServicePublisherImpl::Delegate,
+ openscreen::discovery::ReportingClient {
+ public:
+ DnsSdPublisherClient(ServicePublisher::Observer* observer,
+ openscreen::TaskRunner* task_runner);
+ ~DnsSdPublisherClient() override;
+
+ // ServicePublisherImpl::Delegate overrides.
+ void StartPublisher(const ServicePublisher::Config& config) override;
+ void StartAndSuspendPublisher(
+ const ServicePublisher::Config& config) override;
+ void StopPublisher() override;
+ void SuspendPublisher() override;
+ void ResumePublisher(const ServicePublisher::Config& config) override;
+
+ private:
+ DnsSdPublisherClient(const DnsSdPublisherClient&) = delete;
+ DnsSdPublisherClient(DnsSdPublisherClient&&) noexcept = delete;
+
+ // openscreen::discovery::ReportingClient overrides.
+ void OnFatalError(Error) override;
+ void OnRecoverableError(Error) override;
+
+ void StartPublisherInternal(const ServicePublisher::Config& config);
+ SerialDeletePtr<discovery::DnsSdService> CreateDnsSdServiceInternal(
+ const ServicePublisher::Config& config);
+
+ ServicePublisher::Observer* const observer_;
+ TaskRunner* const task_runner_;
+ SerialDeletePtr<discovery::DnsSdService> dns_sd_service_;
+
+ using OspDnsSdPublisher =
+ discovery::DnsSdServicePublisher<ServicePublisher::Config>;
+
+ std::unique_ptr<OspDnsSdPublisher> dns_sd_publisher_;
+};
+
+} // namespace osp
+} // namespace openscreen
+
+#endif // OSP_IMPL_DNS_SD_PUBLISHER_CLIENT_H_
diff --git a/osp/impl/dns_sd_service_publisher_factory.cc b/osp/impl/dns_sd_service_publisher_factory.cc
new file mode 100644
index 00000000..5c63dc83
--- /dev/null
+++ b/osp/impl/dns_sd_service_publisher_factory.cc
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+#include <memory>
+
+#include "discovery/dnssd/public/dns_sd_publisher.h"
+#include "osp/impl/dns_sd_publisher_client.h"
+#include "osp/impl/service_publisher_impl.h"
+#include "osp/public/service_publisher.h"
+#include "osp/public/service_publisher_factory.h"
+
+namespace openscreen {
+
+class TaskRunner;
+
+namespace osp {
+
+// static
+std::unique_ptr<ServicePublisher> ServicePublisherFactory::Create(
+ const ServicePublisher::Config& config,
+ ServicePublisher::Observer* observer,
+ TaskRunner* task_runner) {
+ auto dns_sd_client =
+ std::make_unique<DnsSdPublisherClient>(observer, task_runner);
+ auto publisher_impl = std::make_unique<ServicePublisherImpl>(
+ observer, std::move(dns_sd_client));
+ publisher_impl->SetConfig(config);
+ return publisher_impl;
+}
+
+} // namespace osp
+} // namespace openscreen
diff --git a/osp/impl/internal_services.cc b/osp/impl/internal_services.cc
deleted file mode 100644
index 19b55927..00000000
--- a/osp/impl/internal_services.cc
+++ /dev/null
@@ -1,229 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/internal_services.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter_impl.h"
-#include "osp/impl/mdns_responder_service.h"
-#include "platform/api/udp_socket.h"
-#include "platform/base/error.h"
-#include "util/osp_logging.h"
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-constexpr char kServiceName[] = "_openscreen";
-constexpr char kServiceProtocol[] = "_udp";
-const IPAddress kMulticastAddress{224, 0, 0, 251};
-const IPAddress kMulticastIPv6Address{
- // ff02::fb
- 0xff02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00fb,
-};
-const uint16_t kMulticastListeningPort = 5353;
-
-class MdnsResponderAdapterImplFactory final
- : public MdnsResponderAdapterFactory {
- public:
- MdnsResponderAdapterImplFactory() = default;
- ~MdnsResponderAdapterImplFactory() override = default;
-
- std::unique_ptr<MdnsResponderAdapter> Create() override {
- return std::make_unique<MdnsResponderAdapterImpl>();
- }
-};
-
-Error SetUpMulticastSocket(UdpSocket* socket, NetworkInterfaceIndex ifindex) {
- const IPAddress broadcast_address =
- socket->IsIPv6() ? kMulticastIPv6Address : kMulticastAddress;
-
- socket->JoinMulticastGroup(broadcast_address, ifindex);
- socket->SetMulticastOutboundInterface(ifindex);
- socket->Bind();
-
- return Error::None();
-}
-
-// Ref-counted singleton instance of InternalServices. This lives only as long
-// as there is at least one ServiceListener and/or ServicePublisher alive.
-InternalServices* g_instance = nullptr;
-int g_instance_ref_count = 0;
-
-} // namespace
-
-// static
-std::unique_ptr<ServiceListener> InternalServices::CreateListener(
- const MdnsServiceListenerConfig& config,
- ServiceListener::Observer* observer,
- TaskRunner* task_runner) {
- auto* services = ReferenceSingleton(task_runner);
- auto listener =
- std::make_unique<ServiceListenerImpl>(&services->mdns_service_);
- listener->AddObserver(observer);
- listener->SetDestructionCallback(&InternalServices::DereferenceSingleton,
- services);
- return listener;
-}
-
-// static
-std::unique_ptr<ServicePublisher> InternalServices::CreatePublisher(
- const ServicePublisher::Config& config,
- ServicePublisher::Observer* observer,
- TaskRunner* task_runner) {
- auto* services = ReferenceSingleton(task_runner);
- services->mdns_service_.SetServiceConfig(
- config.hostname, config.service_instance_name,
- config.connection_server_port, config.network_interface_indices,
- {{"fn", config.friendly_name}});
- auto publisher = std::make_unique<ServicePublisherImpl>(
- observer, &services->mdns_service_);
- publisher->SetDestructionCallback(&InternalServices::DereferenceSingleton,
- services);
- return publisher;
-}
-
-InternalServices::InternalPlatformLinkage::InternalPlatformLinkage(
- InternalServices* parent)
- : parent_(parent) {}
-
-InternalServices::InternalPlatformLinkage::~InternalPlatformLinkage() {
- // If there are open sockets, then there will be dangling references to
- // destroyed objects after destruction.
- OSP_CHECK(open_sockets_.empty());
-}
-
-std::vector<MdnsPlatformService::BoundInterface>
-InternalServices::InternalPlatformLinkage::RegisterInterfaces(
- const std::vector<NetworkInterfaceIndex>& allowlist) {
- const std::vector<InterfaceInfo> interfaces = GetNetworkInterfaces();
- const bool do_filter_using_allowlist = !allowlist.empty();
- std::vector<NetworkInterfaceIndex> index_list;
- for (const auto& interface : interfaces) {
- OSP_VLOG << "Found interface: " << interface;
- if (do_filter_using_allowlist &&
- std::find(allowlist.begin(), allowlist.end(), interface.index) ==
- allowlist.end()) {
- OSP_VLOG << "Ignoring interface not in allowed list: " << interface;
- continue;
- }
- if (!interface.addresses.empty())
- index_list.push_back(interface.index);
- }
- OSP_LOG_IF(WARN, index_list.empty())
- << "No network interfaces had usable addresses for mDNS.";
-
- // Set up sockets to send and listen to mDNS multicast traffic on all
- // interfaces.
- std::vector<BoundInterface> result;
- for (NetworkInterfaceIndex index : index_list) {
- const auto& interface = *std::find_if(
- interfaces.begin(), interfaces.end(),
- [index](const InterfaceInfo& info) { return info.index == index; });
- if (interface.addresses.empty()) {
- continue;
- }
-
- // Pick any address for the given interface.
- const IPSubnet& primary_subnet = interface.addresses.front();
-
- auto create_result =
- UdpSocket::Create(parent_->task_runner_, parent_,
- IPEndpoint{{}, kMulticastListeningPort});
- if (!create_result) {
- OSP_LOG_ERROR << "failed to create socket for interface " << index << ": "
- << create_result.error().message();
- continue;
- }
- std::unique_ptr<UdpSocket> socket = std::move(create_result.value());
- if (!SetUpMulticastSocket(socket.get(), index).ok()) {
- continue;
- }
- result.emplace_back(interface, primary_subnet, socket.get());
- parent_->RegisterMdnsSocket(socket.get());
-
- open_sockets_.emplace_back(std::move(socket));
- }
-
- return result;
-}
-
-void InternalServices::InternalPlatformLinkage::DeregisterInterfaces(
- const std::vector<BoundInterface>& registered_interfaces) {
- for (const auto& interface : registered_interfaces) {
- UdpSocket* const socket = interface.socket;
- parent_->DeregisterMdnsSocket(socket);
-
- const auto it = std::find_if(open_sockets_.begin(), open_sockets_.end(),
- [socket](const std::unique_ptr<UdpSocket>& s) {
- return s.get() == socket;
- });
- OSP_DCHECK(it != open_sockets_.end());
- open_sockets_.erase(it);
- }
-}
-
-InternalServices::InternalServices(ClockNowFunctionPtr now_function,
- TaskRunner* task_runner)
- : mdns_service_(now_function,
- task_runner,
- kServiceName,
- kServiceProtocol,
- std::make_unique<MdnsResponderAdapterImplFactory>(),
- std::make_unique<InternalPlatformLinkage>(this)),
- task_runner_(task_runner) {}
-
-InternalServices::~InternalServices() = default;
-
-void InternalServices::RegisterMdnsSocket(UdpSocket* socket) {
- OSP_CHECK(g_instance) << "No listener or publisher is alive.";
- // TODO(rwkeane): Hook this up to the new mDNS library once we swap out the
- // mDNSResponder.
-}
-
-void InternalServices::DeregisterMdnsSocket(UdpSocket* socket) {
- // TODO(rwkeane): Hook this up to the new mDNS library once we swap out the
- // mDNSResponder.
-}
-
-// static
-InternalServices* InternalServices::ReferenceSingleton(
- TaskRunner* task_runner) {
- if (!g_instance) {
- OSP_CHECK_EQ(g_instance_ref_count, 0);
- g_instance = new InternalServices(&Clock::now, task_runner);
- }
- ++g_instance_ref_count;
- return g_instance;
-}
-
-// static
-void InternalServices::DereferenceSingleton(void* instance) {
- OSP_CHECK_EQ(static_cast<InternalServices*>(instance), g_instance);
- OSP_CHECK_GT(g_instance_ref_count, 0);
- --g_instance_ref_count;
- if (g_instance_ref_count == 0) {
- delete g_instance;
- g_instance = nullptr;
- }
-}
-
-void InternalServices::OnError(UdpSocket* socket, Error error) {
- OSP_LOG_ERROR << "failed to configure socket " << error.message();
- this->DeregisterMdnsSocket(socket);
-}
-
-void InternalServices::OnSendError(UdpSocket* socket, Error error) {
- // TODO(crbug.com/openscreen/67): Implement this method.
- OSP_UNIMPLEMENTED();
-}
-
-void InternalServices::OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) {
- g_instance->mdns_service_.OnRead(socket, std::move(packet));
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/internal_services.h b/osp/impl/internal_services.h
deleted file mode 100644
index 042be4c1..00000000
--- a/osp/impl/internal_services.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_INTERNAL_SERVICES_H_
-#define OSP_IMPL_INTERNAL_SERVICES_H_
-
-#include <memory>
-#include <vector>
-
-#include "osp/impl/mdns_platform_service.h"
-#include "osp/impl/mdns_responder_service.h"
-#include "osp/impl/quic/quic_connection_factory.h"
-#include "osp/impl/service_listener_impl.h"
-#include "osp/impl/service_publisher_impl.h"
-#include "osp/public/mdns_service_listener_factory.h"
-#include "osp/public/mdns_service_publisher_factory.h"
-#include "osp/public/protocol_connection_client.h"
-#include "osp/public/protocol_connection_server.h"
-#include "platform/api/network_interface.h"
-#include "platform/api/time.h"
-#include "platform/api/udp_socket.h"
-#include "platform/base/ip_address.h"
-#include "platform/base/macros.h"
-
-namespace openscreen {
-
-class TaskRunner;
-
-namespace osp {
-
-// Factory for ServiceListener and ServicePublisher instances; owns internal
-// objects needed to instantiate them such as MdnsResponderService and runs an
-// event loop.
-// TODO(btolsch): This may be renamed and/or split up once QUIC code lands and
-// this use case is more concrete.
-class InternalServices : UdpSocket::Client {
- public:
- static std::unique_ptr<ServiceListener> CreateListener(
- const MdnsServiceListenerConfig& config,
- ServiceListener::Observer* observer,
- TaskRunner* task_runner);
- static std::unique_ptr<ServicePublisher> CreatePublisher(
- const ServicePublisher::Config& config,
- ServicePublisher::Observer* observer,
- TaskRunner* task_runner);
-
- // UdpSocket::Client overrides.
- void OnError(UdpSocket* socket, Error error) override;
- void OnSendError(UdpSocket* socket, Error error) override;
- void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
-
- private:
- class InternalPlatformLinkage final : public MdnsPlatformService {
- public:
- explicit InternalPlatformLinkage(InternalServices* parent);
- ~InternalPlatformLinkage() override;
-
- std::vector<BoundInterface> RegisterInterfaces(
- const std::vector<NetworkInterfaceIndex>& allowlist) override;
- void DeregisterInterfaces(
- const std::vector<BoundInterface>& registered_interfaces) override;
-
- private:
- InternalServices* const parent_;
- std::vector<std::unique_ptr<UdpSocket>> open_sockets_;
- };
-
- // The TaskRunner provided here should live for the duration of this
- // InternalService object's lifetime.
- InternalServices(ClockNowFunctionPtr now_function, TaskRunner* task_runner);
- ~InternalServices() override;
-
- void RegisterMdnsSocket(UdpSocket* socket);
- void DeregisterMdnsSocket(UdpSocket* socket);
-
- static InternalServices* ReferenceSingleton(TaskRunner* task_runner);
- static void DereferenceSingleton(void* instance);
-
- MdnsResponderService mdns_service_;
-
- TaskRunner* const task_runner_;
-
- OSP_DISALLOW_COPY_AND_ASSIGN(InternalServices);
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_INTERNAL_SERVICES_H_
diff --git a/osp/impl/mdns_platform_service.cc b/osp/impl/mdns_platform_service.cc
deleted file mode 100644
index 4968c259..00000000
--- a/osp/impl/mdns_platform_service.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/mdns_platform_service.h"
-
-#include <cstring>
-
-#include "util/osp_logging.h"
-
-namespace openscreen {
-namespace osp {
-
-MdnsPlatformService::BoundInterface::BoundInterface(
- const InterfaceInfo& interface_info,
- const IPSubnet& subnet,
- UdpSocket* socket)
- : interface_info(interface_info), subnet(subnet), socket(socket) {
- OSP_DCHECK(socket);
-}
-
-MdnsPlatformService::BoundInterface::~BoundInterface() = default;
-
-bool MdnsPlatformService::BoundInterface::operator==(
- const MdnsPlatformService::BoundInterface& other) const {
- if (interface_info.index != other.interface_info.index)
- return false;
-
- if (subnet.address != other.subnet.address ||
- subnet.prefix_length != other.subnet.prefix_length) {
- return false;
- }
-
- if (socket != other.socket)
- return false;
-
- return true;
-}
-
-bool MdnsPlatformService::BoundInterface::operator!=(
- const MdnsPlatformService::BoundInterface& other) const {
- return !(*this == other);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/mdns_platform_service.h b/osp/impl/mdns_platform_service.h
deleted file mode 100644
index aca4ffd7..00000000
--- a/osp/impl/mdns_platform_service.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_MDNS_PLATFORM_SERVICE_H_
-#define OSP_IMPL_MDNS_PLATFORM_SERVICE_H_
-
-#include <vector>
-
-#include "platform/api/network_interface.h"
-#include "platform/api/udp_socket.h"
-
-namespace openscreen {
-namespace osp {
-
-class MdnsPlatformService {
- public:
- struct BoundInterface {
- BoundInterface(const InterfaceInfo& interface_info,
- const IPSubnet& subnet,
- UdpSocket* socket);
- ~BoundInterface();
-
- bool operator==(const BoundInterface& other) const;
- bool operator!=(const BoundInterface& other) const;
-
- InterfaceInfo interface_info;
- IPSubnet subnet;
- UdpSocket* socket;
- };
-
- virtual ~MdnsPlatformService() = default;
-
- virtual std::vector<BoundInterface> RegisterInterfaces(
- const std::vector<NetworkInterfaceIndex>& allowlist) = 0;
- virtual void DeregisterInterfaces(
- const std::vector<BoundInterface>& registered_interfaces) = 0;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_MDNS_PLATFORM_SERVICE_H_
diff --git a/osp/impl/mdns_responder_service.cc b/osp/impl/mdns_responder_service.cc
deleted file mode 100644
index f9a80fae..00000000
--- a/osp/impl/mdns_responder_service.cc
+++ /dev/null
@@ -1,664 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/mdns_responder_service.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "osp/impl/internal_services.h"
-#include "platform/base/error.h"
-#include "util/osp_logging.h"
-#include "util/trace_logging.h"
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-// TODO(btolsch): This should probably at least also contain network identity
-// information.
-std::string ServiceIdFromServiceInstanceName(
- const DomainName& service_instance) {
- std::string service_id;
- service_id.assign(
- reinterpret_cast<const char*>(service_instance.domain_name().data()),
- service_instance.domain_name().size());
- return service_id;
-}
-
-} // namespace
-
-MdnsResponderService::MdnsResponderService(
- ClockNowFunctionPtr now_function,
- TaskRunner* task_runner,
- const std::string& service_name,
- const std::string& service_protocol,
- std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory,
- std::unique_ptr<MdnsPlatformService> platform)
- : service_type_{{service_name, service_protocol}},
- mdns_responder_factory_(std::move(mdns_responder_factory)),
- platform_(std::move(platform)),
- task_runner_(task_runner),
- background_tasks_alarm_(now_function, task_runner) {}
-
-MdnsResponderService::~MdnsResponderService() = default;
-
-void MdnsResponderService::SetServiceConfig(
- const std::string& hostname,
- const std::string& instance,
- uint16_t port,
- const std::vector<NetworkInterfaceIndex> allowlist,
- const std::map<std::string, std::string>& txt_data) {
- OSP_DCHECK(!hostname.empty());
- OSP_DCHECK(!instance.empty());
- OSP_DCHECK_NE(0, port);
- service_hostname_ = hostname;
- service_instance_name_ = instance;
- service_port_ = port;
- interface_index_allowlist_ = allowlist;
- service_txt_data_ = txt_data;
-}
-
-void MdnsResponderService::OnRead(UdpSocket* socket,
- ErrorOr<UdpPacket> packet) {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderService::OnRead");
- if (!mdns_responder_) {
- return;
- }
-
- mdns_responder_->OnRead(socket, std::move(packet));
- HandleMdnsEvents();
-}
-
-void MdnsResponderService::OnSendError(UdpSocket* socket, Error error) {
- mdns_responder_->OnSendError(socket, std::move(error));
-}
-
-void MdnsResponderService::OnError(UdpSocket* socket, Error error) {
- mdns_responder_->OnError(socket, std::move(error));
-}
-
-void MdnsResponderService::StartListener() {
- task_runner_->PostTask([this]() { this->StartListenerInternal(); });
-}
-
-void MdnsResponderService::StartAndSuspendListener() {
- task_runner_->PostTask([this]() { this->StartAndSuspendListenerInternal(); });
-}
-
-void MdnsResponderService::StopListener() {
- task_runner_->PostTask([this]() { this->StopListenerInternal(); });
-}
-
-void MdnsResponderService::SuspendListener() {
- task_runner_->PostTask([this]() { this->SuspendListenerInternal(); });
-}
-
-void MdnsResponderService::ResumeListener() {
- task_runner_->PostTask([this]() { this->ResumeListenerInternal(); });
-}
-
-void MdnsResponderService::SearchNow(ServiceListener::State from) {
- task_runner_->PostTask([this, from]() { this->SearchNowInternal(from); });
-}
-
-void MdnsResponderService::StartPublisher() {
- task_runner_->PostTask([this]() { this->StartPublisherInternal(); });
-}
-
-void MdnsResponderService::StartAndSuspendPublisher() {
- task_runner_->PostTask(
- [this]() { this->StartAndSuspendPublisherInternal(); });
-}
-
-void MdnsResponderService::StopPublisher() {
- task_runner_->PostTask([this]() { this->StopPublisherInternal(); });
-}
-
-void MdnsResponderService::SuspendPublisher() {
- task_runner_->PostTask([this]() { this->SuspendPublisherInternal(); });
-}
-
-void MdnsResponderService::ResumePublisher() {
- task_runner_->PostTask([this]() { this->ResumePublisherInternal(); });
-}
-
-void MdnsResponderService::StartListenerInternal() {
- if (!mdns_responder_) {
- mdns_responder_ = mdns_responder_factory_->Create();
- }
-
- StartListening();
- ServiceListenerImpl::Delegate::SetState(ServiceListener::State::kRunning);
- RunBackgroundTasks();
-}
-
-void MdnsResponderService::StartAndSuspendListenerInternal() {
- mdns_responder_ = mdns_responder_factory_->Create();
- ServiceListenerImpl::Delegate::SetState(ServiceListener::State::kSuspended);
-}
-
-void MdnsResponderService::StopListenerInternal() {
- StopListening();
- if (!publisher_ || publisher_->state() == ServicePublisher::State::kStopped ||
- publisher_->state() == ServicePublisher::State::kSuspended) {
- StopMdnsResponder();
- if (!publisher_ || publisher_->state() == ServicePublisher::State::kStopped)
- mdns_responder_.reset();
- }
- ServiceListenerImpl::Delegate::SetState(ServiceListener::State::kStopped);
-}
-
-void MdnsResponderService::SuspendListenerInternal() {
- StopMdnsResponder();
- ServiceListenerImpl::Delegate::SetState(ServiceListener::State::kSuspended);
-}
-
-void MdnsResponderService::ResumeListenerInternal() {
- StartListening();
- ServiceListenerImpl::Delegate::SetState(ServiceListener::State::kRunning);
-}
-
-void MdnsResponderService::SearchNowInternal(ServiceListener::State from) {
- ServiceListenerImpl::Delegate::SetState(from);
-}
-
-void MdnsResponderService::StartPublisherInternal() {
- if (!mdns_responder_) {
- mdns_responder_ = mdns_responder_factory_->Create();
- }
-
- StartService();
- ServicePublisherImpl::Delegate::SetState(ServicePublisher::State::kRunning);
- RunBackgroundTasks();
-}
-
-void MdnsResponderService::StartAndSuspendPublisherInternal() {
- mdns_responder_ = mdns_responder_factory_->Create();
- ServicePublisherImpl::Delegate::SetState(ServicePublisher::State::kSuspended);
-}
-
-void MdnsResponderService::StopPublisherInternal() {
- StopService();
- if (!listener_ || listener_->state() == ServiceListener::State::kStopped ||
- listener_->state() == ServiceListener::State::kSuspended) {
- StopMdnsResponder();
- if (!listener_ || listener_->state() == ServiceListener::State::kStopped)
- mdns_responder_.reset();
- }
- ServicePublisherImpl::Delegate::SetState(ServicePublisher::State::kStopped);
-}
-
-void MdnsResponderService::SuspendPublisherInternal() {
- StopService();
- ServicePublisherImpl::Delegate::SetState(ServicePublisher::State::kSuspended);
-}
-
-void MdnsResponderService::ResumePublisherInternal() {
- StartService();
- ServicePublisherImpl::Delegate::SetState(ServicePublisher::State::kRunning);
-}
-
-bool MdnsResponderService::NetworkScopedDomainNameComparator::operator()(
- const NetworkScopedDomainName& a,
- const NetworkScopedDomainName& b) const {
- if (a.socket != b.socket) {
- return (a.socket - b.socket) < 0;
- }
- return DomainNameComparator()(a.domain_name, b.domain_name);
-}
-
-void MdnsResponderService::HandleMdnsEvents() {
- TRACE_SCOPED(TraceCategory::kMdns, "MdnsResponderService::HandleMdnsEvents");
- // NOTE: In the common case, we will get a single combined packet for
- // PTR/SRV/TXT/A and then no other packets. If we don't loop here, we would
- // start SRV/TXT queries based on the PTR response, but never check for events
- // again. This should no longer be a problem when we have correct scheduling
- // of RunTasks.
- bool events_possible = false;
- // NOTE: This set will track which service instances were changed by all the
- // events throughout all the loop iterations. At the end, we can dispatch our
- // ServiceInfo updates to |listener_| just once (e.g. instead of
- // OnReceiverChanged, OnReceiverChanged, ..., just a single
- // OnReceiverChanged).
- InstanceNameSet modified_instance_names;
- do {
- events_possible = false;
- for (auto& ptr_event : mdns_responder_->TakePtrResponses()) {
- events_possible = HandlePtrEvent(ptr_event, &modified_instance_names) ||
- events_possible;
- }
- for (auto& srv_event : mdns_responder_->TakeSrvResponses()) {
- events_possible = HandleSrvEvent(srv_event, &modified_instance_names) ||
- events_possible;
- }
- for (auto& txt_event : mdns_responder_->TakeTxtResponses()) {
- events_possible = HandleTxtEvent(txt_event, &modified_instance_names) ||
- events_possible;
- }
- for (const auto& a_event : mdns_responder_->TakeAResponses()) {
- events_possible =
- HandleAEvent(a_event, &modified_instance_names) || events_possible;
- }
- for (const auto& aaaa_event : mdns_responder_->TakeAaaaResponses()) {
- events_possible = HandleAaaaEvent(aaaa_event, &modified_instance_names) ||
- events_possible;
- }
- if (events_possible) {
- // NOTE: This still needs to be called here, even though it runs in the
- // background regularly, because we just finished processing MDNS events.
- RunBackgroundTasks();
- }
- } while (events_possible);
-
- for (const auto& instance_name : modified_instance_names) {
- auto service_entry = service_by_name_.find(instance_name);
- std::unique_ptr<ServiceInstance>& service = service_entry->second;
-
- std::string service_id = ServiceIdFromServiceInstanceName(instance_name);
- auto receiver_info_entry = receiver_info_.find(service_id);
- HostInfo* host = GetHostInfo(service->ptr_socket, service->domain_name);
- if (!IsServiceReady(*service, host)) {
- if (receiver_info_entry != receiver_info_.end()) {
- const ServiceInfo& receiver_info = receiver_info_entry->second;
- listener_->OnReceiverRemoved(receiver_info);
- receiver_info_.erase(receiver_info_entry);
- }
- if (!service->has_ptr_record && !service->has_srv())
- service_by_name_.erase(service_entry);
- continue;
- }
-
- // TODO(btolsch): Verify UTF-8 here.
- std::string friendly_name(instance_name.GetLabels()[0]);
-
- if (receiver_info_entry == receiver_info_.end()) {
- ServiceInfo receiver_info{
- std::move(service_id),
- std::move(friendly_name),
- GetNetworkInterfaceIndexFromSocket(service->ptr_socket),
- {host->v4_address, service->port},
- {host->v6_address, service->port}};
- listener_->OnReceiverAdded(receiver_info);
- receiver_info_.emplace(receiver_info.service_id,
- std::move(receiver_info));
- } else {
- ServiceInfo& receiver_info = receiver_info_entry->second;
- if (receiver_info.Update(
- std::move(friendly_name),
- GetNetworkInterfaceIndexFromSocket(service->ptr_socket),
- {host->v4_address, service->port},
- {host->v6_address, service->port})) {
- listener_->OnReceiverChanged(receiver_info);
- }
- }
- }
-}
-
-void MdnsResponderService::StartListening() {
- // TODO(btolsch): This needs the same |interface_index_allowlist_| logic as
- // StartService, but this can also wait until the network-change TODO is
- // addressed.
- if (bound_interfaces_.empty()) {
- mdns_responder_->Init();
- bound_interfaces_ = platform_->RegisterInterfaces({});
- for (auto& interface : bound_interfaces_) {
- mdns_responder_->RegisterInterface(interface.interface_info,
- interface.subnet, interface.socket);
- }
- }
- ErrorOr<DomainName> service_type =
- DomainName::FromLabels(service_type_.begin(), service_type_.end());
- OSP_CHECK(service_type);
- for (const auto& interface : bound_interfaces_) {
- mdns_responder_->StartPtrQuery(interface.socket, service_type.value());
- }
-}
-
-void MdnsResponderService::StopListening() {
- ErrorOr<DomainName> service_type =
- DomainName::FromLabels(service_type_.begin(), service_type_.end());
- OSP_CHECK(service_type);
- for (const auto& kv : network_scoped_domain_to_host_) {
- const NetworkScopedDomainName& scoped_domain = kv.first;
-
- mdns_responder_->StopAQuery(scoped_domain.socket,
- scoped_domain.domain_name);
- mdns_responder_->StopAaaaQuery(scoped_domain.socket,
- scoped_domain.domain_name);
- }
- network_scoped_domain_to_host_.clear();
- for (const auto& service : service_by_name_) {
- UdpSocket* const socket = service.second->ptr_socket;
- mdns_responder_->StopSrvQuery(socket, service.first);
- mdns_responder_->StopTxtQuery(socket, service.first);
- }
- service_by_name_.clear();
- for (const auto& interface : bound_interfaces_) {
- mdns_responder_->StopPtrQuery(interface.socket, service_type.value());
- }
- RemoveAllReceivers();
-}
-
-void MdnsResponderService::StartService() {
- // TODO(crbug.com/openscreen/45): This should really be a library-wide
- // allowed list.
- if (!bound_interfaces_.empty() && !interface_index_allowlist_.empty()) {
- // TODO(btolsch): New interfaces won't be picked up on this path, but this
- // also highlights a larger issue of the interface list being frozen while
- // no state transitions are being made. There should be another interface
- // on MdnsPlatformService for getting network interface updates.
- std::vector<MdnsPlatformService::BoundInterface> deregistered_interfaces;
- for (auto it = bound_interfaces_.begin(); it != bound_interfaces_.end();) {
- if (std::find(interface_index_allowlist_.begin(),
- interface_index_allowlist_.end(),
- it->interface_info.index) ==
- interface_index_allowlist_.end()) {
- mdns_responder_->DeregisterInterface(it->socket);
- deregistered_interfaces.push_back(*it);
- it = bound_interfaces_.erase(it);
- } else {
- ++it;
- }
- }
- platform_->DeregisterInterfaces(deregistered_interfaces);
- } else if (bound_interfaces_.empty()) {
- mdns_responder_->Init();
- mdns_responder_->SetHostLabel(service_hostname_);
- bound_interfaces_ =
- platform_->RegisterInterfaces(interface_index_allowlist_);
- for (auto& interface : bound_interfaces_) {
- mdns_responder_->RegisterInterface(interface.interface_info,
- interface.subnet, interface.socket);
- }
- }
-
- ErrorOr<DomainName> domain_name =
- DomainName::FromLabels(&service_hostname_, &service_hostname_ + 1);
- OSP_CHECK(domain_name) << "bad hostname configured: " << service_hostname_;
- DomainName name = std::move(domain_name.value());
-
- Error error = name.Append(DomainName::GetLocalDomain());
- OSP_CHECK(error.ok());
-
- mdns_responder_->RegisterService(service_instance_name_, service_type_[0],
- service_type_[1], name, service_port_,
- service_txt_data_);
-}
-
-void MdnsResponderService::StopService() {
- mdns_responder_->DeregisterService(service_instance_name_, service_type_[0],
- service_type_[1]);
-}
-
-void MdnsResponderService::StopMdnsResponder() {
- mdns_responder_->Close();
- platform_->DeregisterInterfaces(bound_interfaces_);
- bound_interfaces_.clear();
- network_scoped_domain_to_host_.clear();
- service_by_name_.clear();
- RemoveAllReceivers();
-}
-
-void MdnsResponderService::UpdatePendingServiceInfoSet(
- InstanceNameSet* modified_instance_names,
- const DomainName& domain_name) {
- for (auto& entry : service_by_name_) {
- const auto& instance_name = entry.first;
- const auto& instance = entry.second;
- if (instance->domain_name == domain_name) {
- modified_instance_names->emplace(instance_name);
- }
- }
-}
-
-void MdnsResponderService::RemoveAllReceivers() {
- bool had_receivers = !receiver_info_.empty();
- receiver_info_.clear();
- if (had_receivers)
- listener_->OnAllReceiversRemoved();
-}
-
-bool MdnsResponderService::HandlePtrEvent(
- const PtrEvent& ptr_event,
- InstanceNameSet* modified_instance_names) {
- bool events_possible = false;
- const auto& instance_name = ptr_event.service_instance;
- UdpSocket* const socket = ptr_event.header.socket;
- auto entry = service_by_name_.find(ptr_event.service_instance);
- switch (ptr_event.header.response_type) {
- case QueryEventHeader::Type::kAddedNoCache:
- break;
- case QueryEventHeader::Type::kAdded: {
- if (entry != service_by_name_.end()) {
- entry->second->has_ptr_record = true;
- modified_instance_names->emplace(instance_name);
- break;
- }
- mdns_responder_->StartSrvQuery(socket, instance_name);
- mdns_responder_->StartTxtQuery(socket, instance_name);
- events_possible = true;
-
- auto new_instance = std::make_unique<ServiceInstance>();
- new_instance->ptr_socket = socket;
- new_instance->has_ptr_record = true;
- modified_instance_names->emplace(instance_name);
- service_by_name_.emplace(std::move(instance_name),
- std::move(new_instance));
- } break;
- case QueryEventHeader::Type::kRemoved:
- if (entry == service_by_name_.end())
- break;
- if (entry->second->ptr_socket != socket)
- break;
- entry->second->has_ptr_record = false;
- // NOTE: Occasionally, we can observe this situation in the wild where the
- // PTR for a service is removed and then immediately re-added (like an odd
- // refresh). Additionally, the recommended TTL of PTR records is much
- // shorter than the other records. This means that short network drops or
- // latency spikes could cause the PTR refresh queries and/or responses to
- // be lost so the record isn't quite refreshed in time. The solution here
- // and in HandleSrvEvent is to only remove the service records completely
- // when both the PTR and SRV have been removed.
- if (!entry->second->has_srv()) {
- mdns_responder_->StopSrvQuery(socket, instance_name);
- mdns_responder_->StopTxtQuery(socket, instance_name);
- }
- modified_instance_names->emplace(std::move(instance_name));
- break;
- }
- return events_possible;
-}
-
-bool MdnsResponderService::HandleSrvEvent(
- const SrvEvent& srv_event,
- InstanceNameSet* modified_instance_names) {
- bool events_possible = false;
- auto& domain_name = srv_event.domain_name;
- const auto& instance_name = srv_event.service_instance;
- UdpSocket* const socket = srv_event.header.socket;
- auto entry = service_by_name_.find(srv_event.service_instance);
- if (entry == service_by_name_.end())
- return events_possible;
- switch (srv_event.header.response_type) {
- case QueryEventHeader::Type::kAddedNoCache:
- break;
- case QueryEventHeader::Type::kAdded: {
- NetworkScopedDomainName scoped_domain_name{socket, domain_name};
- auto host_entry = network_scoped_domain_to_host_.find(scoped_domain_name);
- if (host_entry == network_scoped_domain_to_host_.end()) {
- mdns_responder_->StartAQuery(socket, domain_name);
- mdns_responder_->StartAaaaQuery(socket, domain_name);
- events_possible = true;
- auto result = network_scoped_domain_to_host_.emplace(
- std::move(scoped_domain_name), HostInfo{});
- host_entry = result.first;
- }
- auto& dependent_services = host_entry->second.services;
- if (std::find_if(dependent_services.begin(), dependent_services.end(),
- [entry](ServiceInstance* instance) {
- return instance == entry->second.get();
- }) == dependent_services.end()) {
- dependent_services.push_back(entry->second.get());
- }
- entry->second->domain_name = std::move(domain_name);
- entry->second->port = srv_event.port;
- modified_instance_names->emplace(std::move(instance_name));
- } break;
- case QueryEventHeader::Type::kRemoved: {
- NetworkScopedDomainName scoped_domain_name{socket, domain_name};
- auto host_entry = network_scoped_domain_to_host_.find(scoped_domain_name);
- if (host_entry != network_scoped_domain_to_host_.end()) {
- auto& dependent_services = host_entry->second.services;
- dependent_services.erase(
- std::remove_if(dependent_services.begin(), dependent_services.end(),
- [entry](ServiceInstance* instance) {
- return instance == entry->second.get();
- }),
- dependent_services.end());
- if (dependent_services.empty()) {
- mdns_responder_->StopAQuery(socket, domain_name);
- mdns_responder_->StopAaaaQuery(socket, domain_name);
- network_scoped_domain_to_host_.erase(host_entry);
- }
- }
- entry->second->domain_name = DomainName();
- entry->second->port = 0;
- if (!entry->second->has_ptr_record) {
- mdns_responder_->StopSrvQuery(socket, instance_name);
- mdns_responder_->StopTxtQuery(socket, instance_name);
- }
- modified_instance_names->emplace(std::move(instance_name));
- } break;
- }
- return events_possible;
-}
-
-bool MdnsResponderService::HandleTxtEvent(
- const TxtEvent& txt_event,
- InstanceNameSet* modified_instance_names) {
- bool events_possible = false;
- const auto& instance_name = txt_event.service_instance;
- auto entry = service_by_name_.find(instance_name);
- if (entry == service_by_name_.end())
- return events_possible;
- switch (txt_event.header.response_type) {
- case QueryEventHeader::Type::kAddedNoCache:
- break;
- case QueryEventHeader::Type::kAdded:
- modified_instance_names->emplace(instance_name);
- if (entry == service_by_name_.end()) {
- auto result = service_by_name_.emplace(
- std::move(instance_name), std::make_unique<ServiceInstance>());
- entry = result.first;
- }
- entry->second->txt_info = std::move(txt_event.txt_info);
- break;
- case QueryEventHeader::Type::kRemoved:
- entry->second->txt_info.clear();
- modified_instance_names->emplace(std::move(instance_name));
- break;
- }
- return events_possible;
-}
-
-bool MdnsResponderService::HandleAddressEvent(
- UdpSocket* socket,
- QueryEventHeader::Type response_type,
- const DomainName& domain_name,
- bool a_event,
- const IPAddress& address,
- InstanceNameSet* modified_instance_names) {
- bool events_possible = false;
- switch (response_type) {
- case QueryEventHeader::Type::kAddedNoCache:
- break;
- case QueryEventHeader::Type::kAdded: {
- HostInfo* host = AddOrGetHostInfo(socket, domain_name);
- if (a_event)
- host->v4_address = address;
- else
- host->v6_address = address;
- UpdatePendingServiceInfoSet(modified_instance_names, domain_name);
- } break;
- case QueryEventHeader::Type::kRemoved: {
- HostInfo* host = GetHostInfo(socket, domain_name);
-
- if (a_event)
- host->v4_address = IPAddress();
- else
- host->v6_address = IPAddress();
-
- if (host->v4_address || host->v6_address)
- UpdatePendingServiceInfoSet(modified_instance_names, domain_name);
- } break;
- }
- return events_possible;
-}
-
-bool MdnsResponderService::HandleAEvent(
- const AEvent& a_event,
- InstanceNameSet* modified_instance_names) {
- return HandleAddressEvent(a_event.header.socket, a_event.header.response_type,
- a_event.domain_name, true, a_event.address,
- modified_instance_names);
-}
-
-bool MdnsResponderService::HandleAaaaEvent(
- const AaaaEvent& aaaa_event,
- InstanceNameSet* modified_instance_names) {
- return HandleAddressEvent(aaaa_event.header.socket,
- aaaa_event.header.response_type,
- aaaa_event.domain_name, false, aaaa_event.address,
- modified_instance_names);
-}
-
-MdnsResponderService::HostInfo* MdnsResponderService::AddOrGetHostInfo(
- UdpSocket* socket,
- const DomainName& domain_name) {
- return &network_scoped_domain_to_host_[NetworkScopedDomainName{socket,
- domain_name}];
-}
-
-MdnsResponderService::HostInfo* MdnsResponderService::GetHostInfo(
- UdpSocket* socket,
- const DomainName& domain_name) {
- auto kv = network_scoped_domain_to_host_.find(
- NetworkScopedDomainName{socket, domain_name});
- if (kv == network_scoped_domain_to_host_.end())
- return nullptr;
-
- return &kv->second;
-}
-
-bool MdnsResponderService::IsServiceReady(const ServiceInstance& instance,
- HostInfo* host) const {
- return (host && instance.has_ptr_record && instance.has_srv() &&
- !instance.txt_info.empty() && (host->v4_address || host->v6_address));
-}
-
-NetworkInterfaceIndex MdnsResponderService::GetNetworkInterfaceIndexFromSocket(
- const UdpSocket* socket) const {
- auto it = std::find_if(
- bound_interfaces_.begin(), bound_interfaces_.end(),
- [socket](const MdnsPlatformService::BoundInterface& interface) {
- return interface.socket == socket;
- });
- if (it == bound_interfaces_.end())
- return kInvalidNetworkInterfaceIndex;
- return it->interface_info.index;
-}
-
-void MdnsResponderService::RunBackgroundTasks() {
- if (!mdns_responder_) {
- return;
- }
- const auto delay_until_next_run = mdns_responder_->RunTasks();
- background_tasks_alarm_.ScheduleFromNow([this] { RunBackgroundTasks(); },
- delay_until_next_run);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/mdns_responder_service.h b/osp/impl/mdns_responder_service.h
deleted file mode 100644
index ddcd0dbd..00000000
--- a/osp/impl/mdns_responder_service.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
-#define OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
-
-#include <array>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
-#include "osp/impl/mdns_platform_service.h"
-#include "osp/impl/service_listener_impl.h"
-#include "osp/impl/service_publisher_impl.h"
-#include "platform/api/network_interface.h"
-#include "platform/api/task_runner.h"
-#include "platform/api/time.h"
-#include "platform/base/ip_address.h"
-#include "util/alarm.h"
-
-namespace openscreen {
-namespace osp {
-
-class MdnsResponderAdapterFactory {
- public:
- virtual ~MdnsResponderAdapterFactory() = default;
-
- virtual std::unique_ptr<MdnsResponderAdapter> Create() = 0;
-};
-
-class MdnsResponderService : public ServiceListenerImpl::Delegate,
- public ServicePublisherImpl::Delegate,
- public UdpSocket::Client {
- public:
- MdnsResponderService(
- ClockNowFunctionPtr now_function,
- TaskRunner* task_runner,
- const std::string& service_name,
- const std::string& service_protocol,
- std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory,
- std::unique_ptr<MdnsPlatformService> platform);
- ~MdnsResponderService() override;
-
- void SetServiceConfig(const std::string& hostname,
- const std::string& instance,
- uint16_t port,
- const std::vector<NetworkInterfaceIndex> allowlist,
- const std::map<std::string, std::string>& txt_data);
-
- // UdpSocket::Client overrides.
- void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
- void OnSendError(UdpSocket* socket, Error error) override;
- void OnError(UdpSocket* socket, Error error) override;
-
- // ServiceListenerImpl::Delegate overrides.
- void StartListener() override;
- void StartAndSuspendListener() override;
- void StopListener() override;
- void SuspendListener() override;
- void ResumeListener() override;
- void SearchNow(ServiceListener::State from) override;
-
- // ServicePublisherImpl::Delegate overrides.
- void StartPublisher() override;
- void StartAndSuspendPublisher() override;
- void StopPublisher() override;
- void SuspendPublisher() override;
- void ResumePublisher() override;
-
- protected:
- void HandleMdnsEvents();
-
- std::unique_ptr<MdnsResponderAdapter> mdns_responder_;
-
- private:
- // Create internal versions of all public methods. These are used to push all
- // calls to these methods to the task runner.
- // TODO(rwkeane): Clean up these methods. Some result in multiple pushes to
- // the task runner when just one would suffice.
- // ServiceListenerImpl::Delegate overrides.
- void StartListenerInternal();
- void StartAndSuspendListenerInternal();
- void StopListenerInternal();
- void SuspendListenerInternal();
- void ResumeListenerInternal();
- void SearchNowInternal(ServiceListener::State from);
- void StartPublisherInternal();
- void StartAndSuspendPublisherInternal();
- void StopPublisherInternal();
- void SuspendPublisherInternal();
- void ResumePublisherInternal();
-
- // NOTE: service_instance implicit in map key.
- struct ServiceInstance {
- UdpSocket* ptr_socket = nullptr;
- DomainName domain_name;
- uint16_t port = 0;
- bool has_ptr_record = false;
- std::vector<std::string> txt_info;
-
- // |port| == 0 signals that we have no SRV record.
- bool has_srv() const { return port != 0; }
- };
-
- // NOTE: hostname implicit in map key.
- struct HostInfo {
- std::vector<ServiceInstance*> services;
- IPAddress v4_address;
- IPAddress v6_address;
- };
-
- struct NetworkScopedDomainName {
- UdpSocket* socket;
- DomainName domain_name;
- };
-
- struct NetworkScopedDomainNameComparator {
- bool operator()(const NetworkScopedDomainName& a,
- const NetworkScopedDomainName& b) const;
- };
-
- using InstanceNameSet = std::set<DomainName, DomainNameComparator>;
-
- void StartListening();
- void StopListening();
- void StartService();
- void StopService();
- void StopMdnsResponder();
- void UpdatePendingServiceInfoSet(InstanceNameSet* modified_instance_names,
- const DomainName& domain_name);
- void RemoveAllReceivers();
-
- // NOTE: |modified_instance_names| is used to track which service instances
- // are modified by the record events. See HandleMdnsEvents for more details.
- bool HandlePtrEvent(const PtrEvent& ptr_event,
- InstanceNameSet* modified_instance_names);
- bool HandleSrvEvent(const SrvEvent& srv_event,
- InstanceNameSet* modified_instance_names);
- bool HandleTxtEvent(const TxtEvent& txt_event,
- InstanceNameSet* modified_instance_names);
- bool HandleAddressEvent(UdpSocket* socket,
- QueryEventHeader::Type response_type,
- const DomainName& domain_name,
- bool a_event,
- const IPAddress& address,
- InstanceNameSet* modified_instance_names);
- bool HandleAEvent(const AEvent& a_event,
- InstanceNameSet* modified_instance_names);
- bool HandleAaaaEvent(const AaaaEvent& aaaa_event,
- InstanceNameSet* modified_instance_names);
-
- HostInfo* AddOrGetHostInfo(UdpSocket* socket, const DomainName& domain_name);
- HostInfo* GetHostInfo(UdpSocket* socket, const DomainName& domain_name);
- bool IsServiceReady(const ServiceInstance& instance, HostInfo* host) const;
- NetworkInterfaceIndex GetNetworkInterfaceIndexFromSocket(
- const UdpSocket* socket) const;
-
- // Runs background tasks to manage the internal mDNS state.
- void RunBackgroundTasks();
-
- // Service type separated as service name and service protocol for both
- // listening and publishing (e.g. {"_openscreen", "_udp"}).
- std::array<std::string, 2> service_type_;
-
- // The following variables all relate to what MdnsResponderService publishes,
- // if anything.
- std::string service_hostname_;
- std::string service_instance_name_;
- uint16_t service_port_;
- std::vector<NetworkInterfaceIndex> interface_index_allowlist_;
- std::map<std::string, std::string> service_txt_data_;
-
- std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory_;
- std::unique_ptr<MdnsPlatformService> platform_;
- std::vector<MdnsPlatformService::BoundInterface> bound_interfaces_;
-
- // A map of service information collected from PTR, SRV, and TXT records. It
- // is keyed by service instance names.
- std::map<DomainName, std::unique_ptr<ServiceInstance>, DomainNameComparator>
- service_by_name_;
-
- // The map key is a combination of the interface to which the address records
- // belong and the hostname of the address records. The values are IPAddresses
- // for the given hostname on the given network and pointers to dependent
- // service instances. The service instance pointers act as a reference count
- // to keep the A/AAAA queries alive, when more than one service refers to the
- // same hostname. This is not currently used by openscreen, but is used by
- // Cast, so may be supported in openscreen in the future.
- std::map<NetworkScopedDomainName, HostInfo, NetworkScopedDomainNameComparator>
- network_scoped_domain_to_host_;
-
- std::map<std::string, ServiceInfo> receiver_info_;
-
- TaskRunner* const task_runner_;
-
- // Scheduled to run periodic background tasks.
- Alarm background_tasks_alarm_;
-
- friend class TestingMdnsResponderService;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_MDNS_RESPONDER_SERVICE_H_
diff --git a/osp/impl/mdns_responder_service_unittest.cc b/osp/impl/mdns_responder_service_unittest.cc
deleted file mode 100644
index 1d542a3e..00000000
--- a/osp/impl/mdns_responder_service_unittest.cc
+++ /dev/null
@@ -1,884 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/mdns_responder_service.h"
-
-#include <cstdint>
-#include <iostream>
-#include <memory>
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "osp/impl/service_listener_impl.h"
-#include "osp/impl/testing/fake_mdns_platform_service.h"
-#include "osp/impl/testing/fake_mdns_responder_adapter.h"
-#include "platform/test/fake_task_runner.h"
-
-namespace openscreen {
-namespace osp {
-
-// Child of the MdnsResponderService for testing purposes. Only difference
-// betweeen this and the base class is that methods on this class are executed
-// synchronously, rather than pushed to the task runner for later execution.
-class TestingMdnsResponderService final : public MdnsResponderService {
- public:
- TestingMdnsResponderService(
- FakeTaskRunner* task_runner,
- const std::string& service_name,
- const std::string& service_protocol,
- std::unique_ptr<MdnsResponderAdapterFactory> mdns_responder_factory,
- std::unique_ptr<MdnsPlatformService> platform_service)
- : MdnsResponderService(&FakeClock::now,
- task_runner,
- service_name,
- service_protocol,
- std::move(mdns_responder_factory),
- std::move(platform_service)) {}
- ~TestingMdnsResponderService() = default;
-
- // Override the default ServiceListenerImpl and ServicePublisherImpl
- // implementations. These call the internal implementations of each of the
- // methods provided, meaning that the end result of the call is the same, but
- // without pushing to the task runner and waiting for it to be pulled off
- // again.
- // ServiceListenerImpl::Delegate overrides.
- void StartListener() override { StartListenerInternal(); }
- void StartAndSuspendListener() override { StartAndSuspendListenerInternal(); }
- void StopListener() override { StopListenerInternal(); }
- void SuspendListener() override { SuspendListenerInternal(); }
- void ResumeListener() override { ResumeListenerInternal(); }
- void SearchNow(ServiceListener::State from) override {
- SearchNowInternal(from);
- }
-
- // ServicePublisherImpl::Delegate overrides.
- void StartPublisher() override { StartPublisherInternal(); }
- void StartAndSuspendPublisher() override {
- StartAndSuspendPublisherInternal();
- }
- void StopPublisher() override { StopPublisherInternal(); }
- void SuspendPublisher() override { SuspendPublisherInternal(); }
- void ResumePublisher() override { ResumePublisherInternal(); }
-
- // Handles new events as OnRead does, but without the need of a TaskRunner.
- void HandleNewEvents() {
- if (!mdns_responder_) {
- return;
- }
-
- mdns_responder_->RunTasks();
- HandleMdnsEvents();
- }
-};
-
-class FakeMdnsResponderAdapterFactory final
- : public MdnsResponderAdapterFactory,
- public FakeMdnsResponderAdapter::LifetimeObserver {
- public:
- ~FakeMdnsResponderAdapterFactory() override = default;
-
- std::unique_ptr<MdnsResponderAdapter> Create() override {
- auto mdns = std::make_unique<FakeMdnsResponderAdapter>();
- mdns->SetLifetimeObserver(this);
- last_mdns_responder_ = mdns.get();
- ++instances_;
- return mdns;
- }
-
- void OnDestroyed() override {
- last_running_ = last_mdns_responder_->running();
- last_registered_services_size_ =
- last_mdns_responder_->registered_services().size();
- last_mdns_responder_ = nullptr;
- }
-
- FakeMdnsResponderAdapter* last_mdns_responder() {
- return last_mdns_responder_;
- }
-
- int32_t instances() const { return instances_; }
- bool last_running() const { return last_running_; }
- size_t last_registered_services_size() const {
- return last_registered_services_size_;
- }
-
- private:
- FakeMdnsResponderAdapter* last_mdns_responder_ = nullptr;
- int32_t instances_ = 0;
- bool last_running_ = false;
- size_t last_registered_services_size_ = 0;
-};
-
-namespace {
-
-using ::testing::_;
-
-constexpr char kTestServiceInstance[] = "turtle";
-constexpr char kTestServiceName[] = "_foo";
-constexpr char kTestServiceProtocol[] = "_udp";
-constexpr char kTestHostname[] = "hostname";
-constexpr uint16_t kTestPort = 12345;
-
-// Wrapper around the above class. In MdnsResponderServiceTest, we need to both
-// pass a unique_ptr to the created MdnsResponderService and to maintain a
-// local pointer as well. Doing this with the same object causes a race
-// condition, where ~FakeMdnsResponderAdapter() calls observer_->OnDestroyed()
-// after the object is already deleted, resulting in a seg fault. This is to
-// prevent that race condition.
-class WrapperMdnsResponderAdapterFactory final
- : public MdnsResponderAdapterFactory,
- public FakeMdnsResponderAdapter::LifetimeObserver {
- public:
- explicit WrapperMdnsResponderAdapterFactory(
- FakeMdnsResponderAdapterFactory* ptr)
- : other_(ptr) {}
-
- std::unique_ptr<MdnsResponderAdapter> Create() override {
- return other_->Create();
- }
-
- void OnDestroyed() override { other_->OnDestroyed(); }
-
- private:
- FakeMdnsResponderAdapterFactory* other_;
-};
-
-class MockServiceListenerObserver final : public ServiceListener::Observer {
- public:
- ~MockServiceListenerObserver() override = default;
-
- MOCK_METHOD0(OnStarted, void());
- MOCK_METHOD0(OnStopped, void());
- MOCK_METHOD0(OnSuspended, void());
- MOCK_METHOD0(OnSearching, void());
-
- MOCK_METHOD1(OnReceiverAdded, void(const ServiceInfo&));
- MOCK_METHOD1(OnReceiverChanged, void(const ServiceInfo&));
- MOCK_METHOD1(OnReceiverRemoved, void(const ServiceInfo&));
- MOCK_METHOD0(OnAllReceiversRemoved, void());
-
- MOCK_METHOD1(OnError, void(ServiceListenerError));
- MOCK_METHOD1(OnMetrics, void(ServiceListener::Metrics));
-};
-
-class MockServicePublisherObserver final : public ServicePublisher::Observer {
- public:
- ~MockServicePublisherObserver() override = default;
-
- MOCK_METHOD0(OnStarted, void());
- MOCK_METHOD0(OnStopped, void());
- MOCK_METHOD0(OnSuspended, void());
- MOCK_METHOD1(OnError, void(ServicePublisherError));
- MOCK_METHOD1(OnMetrics, void(ServicePublisher::Metrics));
-};
-
-UdpSocket* const kDefaultSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(16));
-UdpSocket* const kSecondSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(24));
-
-class MdnsResponderServiceTest : public ::testing::Test {
- protected:
- void SetUp() override {
- mdns_responder_factory_ =
- std::make_unique<FakeMdnsResponderAdapterFactory>();
- auto wrapper_factory = std::make_unique<WrapperMdnsResponderAdapterFactory>(
- mdns_responder_factory_.get());
- clock_ = std::make_unique<FakeClock>(Clock::now());
- task_runner_ = std::make_unique<FakeTaskRunner>(clock_.get());
- auto platform_service = std::make_unique<FakeMdnsPlatformService>();
- fake_platform_service_ = platform_service.get();
- fake_platform_service_->set_interfaces(bound_interfaces_);
- mdns_service_ = std::make_unique<TestingMdnsResponderService>(
- task_runner_.get(), kTestServiceName, kTestServiceProtocol,
- std::move(wrapper_factory), std::move(platform_service));
- service_listener_ =
- std::make_unique<ServiceListenerImpl>(mdns_service_.get());
- service_listener_->AddObserver(&observer_);
-
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {}, {{"model", "shifty"}});
- service_publisher_ = std::make_unique<ServicePublisherImpl>(
- &publisher_observer_, mdns_service_.get());
- }
-
- std::unique_ptr<FakeClock> clock_;
- std::unique_ptr<FakeTaskRunner> task_runner_;
- MockServiceListenerObserver observer_;
- FakeMdnsPlatformService* fake_platform_service_;
- std::unique_ptr<FakeMdnsResponderAdapterFactory> mdns_responder_factory_;
- std::unique_ptr<TestingMdnsResponderService> mdns_service_;
- std::unique_ptr<ServiceListenerImpl> service_listener_;
- MockServicePublisherObserver publisher_observer_;
- std::unique_ptr<ServicePublisherImpl> service_publisher_;
- const uint8_t default_mac_[6] = {0, 11, 22, 33, 44, 55};
- const uint8_t second_mac_[6] = {55, 33, 22, 33, 44, 77};
- const IPSubnet default_subnet_{IPAddress{192, 168, 3, 2}, 24};
- const IPSubnet second_subnet_{IPAddress{10, 0, 0, 3}, 24};
- std::vector<MdnsPlatformService::BoundInterface> bound_interfaces_{
- MdnsPlatformService::BoundInterface{
- InterfaceInfo{1,
- default_mac_,
- "eth0",
- InterfaceInfo::Type::kEthernet,
- {default_subnet_}},
- default_subnet_, kDefaultSocket},
- MdnsPlatformService::BoundInterface{
- InterfaceInfo{2,
- second_mac_,
- "eth1",
- InterfaceInfo::Type::kEthernet,
- {second_subnet_}},
- second_subnet_, kSecondSocket},
- };
-};
-
-} // namespace
-
-TEST_F(MdnsResponderServiceTest, BasicServiceStates) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- std::string service_id;
- EXPECT_CALL(observer_, OnReceiverAdded(_))
- .WillOnce(::testing::Invoke([&service_id](const ServiceInfo& info) {
- service_id = info.service_id;
- EXPECT_EQ(kTestServiceInstance, info.friendly_name);
- EXPECT_EQ((IPEndpoint{{192, 168, 3, 7}, kTestPort}), info.v4_endpoint);
- EXPECT_FALSE(info.v6_endpoint.address);
- }));
- mdns_service_->HandleNewEvents();
-
- mdns_responder->AddAEvent(MakeAEvent(
- "gigliorononomicon", IPAddress{192, 168, 3, 8}, kDefaultSocket));
-
- EXPECT_CALL(observer_, OnReceiverChanged(_))
- .WillOnce(::testing::Invoke([&service_id](const ServiceInfo& info) {
- EXPECT_EQ(service_id, info.service_id);
- EXPECT_EQ(kTestServiceInstance, info.friendly_name);
- EXPECT_EQ((IPEndpoint{{192, 168, 3, 8}, kTestPort}), info.v4_endpoint);
- EXPECT_FALSE(info.v6_endpoint.address);
- }));
- mdns_service_->HandleNewEvents();
-
- auto ptr_remove = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- ptr_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddPtrEvent(std::move(ptr_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_))
- .WillOnce(::testing::Invoke([&service_id](const ServiceInfo& info) {
- EXPECT_EQ(service_id, info.service_id);
- }));
- mdns_service_->HandleNewEvents();
-}
-
-TEST_F(MdnsResponderServiceTest, NetworkNetworkInterfaceIndex) {
- constexpr uint8_t mac[6] = {12, 34, 56, 78, 90};
- const IPSubnet subnet{IPAddress{10, 0, 0, 2}, 24};
- bound_interfaces_.emplace_back(
- InterfaceInfo{2, mac, "wlan0", InterfaceInfo::Type::kWifi, {subnet}},
- subnet, kSecondSocket);
- fake_platform_service_->set_interfaces(bound_interfaces_);
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kSecondSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_))
- .WillOnce(::testing::Invoke([](const ServiceInfo& info) {
- EXPECT_EQ(2, info.network_interface_index);
- }));
- mdns_service_->HandleNewEvents();
-}
-
-TEST_F(MdnsResponderServiceTest, SimultaneousFieldChanges) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- mdns_responder->AddSrvEvent(
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", 54321, kDefaultSocket));
- auto a_remove = MakeAEvent("gigliorononomicon", IPAddress{192, 168, 3, 7},
- kDefaultSocket);
- a_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddAEvent(std::move(a_remove));
- mdns_responder->AddAEvent(MakeAEvent(
- "gigliorononomicon", IPAddress{192, 168, 3, 8}, kDefaultSocket));
-
- EXPECT_CALL(observer_, OnReceiverChanged(_))
- .WillOnce(::testing::Invoke([](const ServiceInfo& info) {
- EXPECT_EQ((IPAddress{192, 168, 3, 8}), info.v4_endpoint.address);
- EXPECT_EQ(54321, info.v4_endpoint.port);
- EXPECT_FALSE(info.v6_endpoint.address);
- }));
- mdns_service_->HandleNewEvents();
-}
-
-TEST_F(MdnsResponderServiceTest, SimultaneousHostAndAddressChange) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto srv_remove =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
- mdns_responder->AddSrvEvent(
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "alpha", kTestPort, kDefaultSocket));
- mdns_responder->AddAEvent(MakeAEvent(
- "gigliorononomicon", IPAddress{192, 168, 3, 8}, kDefaultSocket));
- mdns_responder->AddAEvent(
- MakeAEvent("alpha", IPAddress{192, 168, 3, 10}, kDefaultSocket));
-
- EXPECT_CALL(observer_, OnReceiverChanged(_))
- .WillOnce(::testing::Invoke([](const ServiceInfo& info) {
- EXPECT_EQ((IPAddress{192, 168, 3, 10}), info.v4_endpoint.address);
- EXPECT_FALSE(info.v6_endpoint.address);
- }));
- mdns_service_->HandleNewEvents();
-}
-
-TEST_F(MdnsResponderServiceTest, ListenerStateTransitions) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- EXPECT_CALL(observer_, OnSuspended());
- service_listener_->Suspend();
- ASSERT_EQ(mdns_responder, mdns_responder_factory_->last_mdns_responder());
- EXPECT_FALSE(mdns_responder->running());
-
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Resume();
- ASSERT_EQ(mdns_responder, mdns_responder_factory_->last_mdns_responder());
- EXPECT_TRUE(mdns_responder->running());
-
- EXPECT_CALL(observer_, OnStopped());
- service_listener_->Stop();
- ASSERT_FALSE(mdns_responder_factory_->last_mdns_responder());
-
- EXPECT_CALL(observer_, OnSuspended());
- auto instances = mdns_responder_factory_->instances();
- service_listener_->StartAndSuspend();
- EXPECT_EQ(instances + 1, mdns_responder_factory_->instances());
- mdns_responder = mdns_responder_factory_->last_mdns_responder();
- EXPECT_FALSE(mdns_responder->running());
-
- EXPECT_CALL(observer_, OnStopped());
- service_listener_->Stop();
- ASSERT_FALSE(mdns_responder_factory_->last_mdns_responder());
-}
-
-TEST_F(MdnsResponderServiceTest, BasicServicePublish) {
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- const auto& services = mdns_responder->registered_services();
- ASSERT_EQ(1u, services.size());
- EXPECT_EQ(kTestServiceInstance, services[0].service_instance);
- EXPECT_EQ(kTestServiceName, services[0].service_name);
- EXPECT_EQ(kTestServiceProtocol, services[0].service_protocol);
- auto host_labels = services[0].target_host.GetLabels();
- ASSERT_EQ(2u, host_labels.size());
- EXPECT_EQ(kTestHostname, host_labels[0]);
- EXPECT_EQ("local", host_labels[1]);
- EXPECT_EQ(kTestPort, services[0].target_port);
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
-
- EXPECT_FALSE(mdns_responder_factory_->last_mdns_responder());
- EXPECT_EQ(0u, mdns_responder_factory_->last_registered_services_size());
-}
-
-TEST_F(MdnsResponderServiceTest, PublisherStateTransitions) {
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- EXPECT_EQ(1u, mdns_responder->registered_services().size());
-
- EXPECT_CALL(publisher_observer_, OnSuspended());
- service_publisher_->Suspend();
- EXPECT_EQ(0u, mdns_responder->registered_services().size());
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Resume();
- EXPECT_EQ(1u, mdns_responder->registered_services().size());
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- EXPECT_EQ(0u, mdns_responder_factory_->last_registered_services_size());
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
- mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- EXPECT_EQ(1u, mdns_responder->registered_services().size());
- EXPECT_CALL(publisher_observer_, OnSuspended());
- service_publisher_->Suspend();
- EXPECT_EQ(0u, mdns_responder->registered_services().size());
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- EXPECT_FALSE(mdns_responder_factory_->last_mdns_responder());
- EXPECT_EQ(0u, mdns_responder_factory_->last_registered_services_size());
-}
-
-TEST_F(MdnsResponderServiceTest, PublisherObeysInterfaceAllowlist) {
- {
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {}, {{"model", "shifty"}});
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(2u, interfaces.size());
- EXPECT_EQ(kDefaultSocket, interfaces[0].socket);
- EXPECT_EQ(kSecondSocket, interfaces[1].socket);
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- }
- {
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {1, 2}, {{"model", "shifty"}});
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(2u, interfaces.size());
- EXPECT_EQ(kDefaultSocket, interfaces[0].socket);
- EXPECT_EQ(kSecondSocket, interfaces[1].socket);
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- }
- {
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {2}, {{"model", "shifty"}});
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(1u, interfaces.size());
- EXPECT_EQ(kSecondSocket, interfaces[0].socket);
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- }
-}
-
-TEST_F(MdnsResponderServiceTest, ListenAndPublish) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- {
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(2u, interfaces.size());
- EXPECT_EQ(kDefaultSocket, interfaces[0].socket);
- EXPECT_EQ(kSecondSocket, interfaces[1].socket);
- }
-
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {2}, {{"model", "shifty"}});
-
- auto instances = mdns_responder_factory_->instances();
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- EXPECT_EQ(instances, mdns_responder_factory_->instances());
- ASSERT_TRUE(mdns_responder->running());
- {
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(1u, interfaces.size());
- EXPECT_EQ(kSecondSocket, interfaces[0].socket);
- }
-
- EXPECT_CALL(observer_, OnStopped());
- service_listener_->Stop();
- ASSERT_TRUE(mdns_responder->running());
- EXPECT_EQ(1u, mdns_responder->registered_interfaces().size());
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- EXPECT_FALSE(mdns_responder_factory_->last_mdns_responder());
- EXPECT_EQ(0u, mdns_responder_factory_->last_registered_services_size());
-}
-
-TEST_F(MdnsResponderServiceTest, PublishAndListen) {
- mdns_service_->SetServiceConfig(kTestHostname, kTestServiceInstance,
- kTestPort, {2}, {{"model", "shifty"}});
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
- {
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(1u, interfaces.size());
- EXPECT_EQ(kSecondSocket, interfaces[0].socket);
- }
-
- auto instances = mdns_responder_factory_->instances();
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- EXPECT_EQ(instances, mdns_responder_factory_->instances());
- ASSERT_TRUE(mdns_responder->running());
- {
- auto interfaces = mdns_responder->registered_interfaces();
- ASSERT_EQ(1u, interfaces.size());
- EXPECT_EQ(kSecondSocket, interfaces[0].socket);
- }
-
- EXPECT_CALL(publisher_observer_, OnStopped());
- service_publisher_->Stop();
- ASSERT_TRUE(mdns_responder->running());
- EXPECT_EQ(1u, mdns_responder->registered_interfaces().size());
-
- EXPECT_CALL(observer_, OnStopped());
- service_listener_->Stop();
- EXPECT_FALSE(mdns_responder_factory_->last_mdns_responder());
- EXPECT_EQ(0u, mdns_responder_factory_->last_registered_services_size());
-}
-
-TEST_F(MdnsResponderServiceTest, AddressQueryStopped) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto srv_remove =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_FALSE(mdns_responder->srv_queries_empty());
- EXPECT_FALSE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-}
-
-TEST_F(MdnsResponderServiceTest, AddressQueryRefCount) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
- AddEventsForNewService(mdns_responder, "instance-2", kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", 4321,
- {"model=shwofty", "id=asdf"},
- IPAddress{192, 168, 3, 7}, kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_)).Times(2);
- mdns_service_->HandleNewEvents();
-
- auto srv_remove =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_FALSE(mdns_responder->srv_queries_empty());
- EXPECT_FALSE(mdns_responder->txt_queries_empty());
- EXPECT_FALSE(mdns_responder->a_queries_empty());
- EXPECT_FALSE(mdns_responder->aaaa_queries_empty());
-
- srv_remove =
- MakeSrvEvent("instance-2", kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", 4321, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_FALSE(mdns_responder->srv_queries_empty());
- EXPECT_FALSE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-}
-
-TEST_F(MdnsResponderServiceTest, ServiceQueriesStoppedSrvFirst) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto srv_remove =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_FALSE(mdns_responder->srv_queries_empty());
- EXPECT_FALSE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-
- auto ptr_remove = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- ptr_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddPtrEvent(std::move(ptr_remove));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_TRUE(mdns_responder->srv_queries_empty());
- EXPECT_TRUE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-}
-
-TEST_F(MdnsResponderServiceTest, ServiceQueriesStoppedPtrFirst) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto ptr_remove = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- ptr_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddPtrEvent(std::move(ptr_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_FALSE(mdns_responder->srv_queries_empty());
- EXPECT_FALSE(mdns_responder->txt_queries_empty());
- EXPECT_FALSE(mdns_responder->a_queries_empty());
- EXPECT_FALSE(mdns_responder->aaaa_queries_empty());
-
- auto srv_remove =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_TRUE(mdns_responder->srv_queries_empty());
- EXPECT_TRUE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-}
-
-TEST_F(MdnsResponderServiceTest, MultipleInterfaceRemove) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kSecondSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto srv_remove1 =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kSecondSocket);
- srv_remove1.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove1));
- EXPECT_CALL(observer_, OnReceiverChanged(_)).Times(0);
- EXPECT_CALL(observer_, OnReceiverRemoved(_)).Times(0);
- mdns_service_->HandleNewEvents();
-
- auto srv_remove2 =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "gigliorononomicon", kTestPort, kDefaultSocket);
- srv_remove2.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddSrvEvent(std::move(srv_remove2));
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
- EXPECT_TRUE(mdns_responder->a_queries_empty());
-
- auto ptr_remove = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- ptr_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddPtrEvent(std::move(ptr_remove));
- mdns_service_->HandleNewEvents();
-
- EXPECT_FALSE(mdns_responder->ptr_queries_empty());
- EXPECT_TRUE(mdns_responder->srv_queries_empty());
- EXPECT_TRUE(mdns_responder->txt_queries_empty());
- EXPECT_TRUE(mdns_responder->a_queries_empty());
- EXPECT_TRUE(mdns_responder->aaaa_queries_empty());
-}
-
-TEST_F(MdnsResponderServiceTest, ResumeService) {
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
- ASSERT_TRUE(mdns_responder);
- ASSERT_TRUE(mdns_responder->running());
-
- EXPECT_EQ(2u, mdns_responder->registered_interfaces().size());
- ASSERT_EQ(1u, mdns_responder->registered_services().size());
-
- EXPECT_CALL(publisher_observer_, OnSuspended());
- service_publisher_->Suspend();
-
- EXPECT_TRUE(mdns_responder_factory_->last_mdns_responder());
- EXPECT_EQ(0u, mdns_responder->registered_services().size());
-
- EXPECT_CALL(publisher_observer_, OnStarted());
- service_publisher_->Resume();
-
- EXPECT_EQ(2u, mdns_responder->registered_interfaces().size());
- ASSERT_EQ(1u, mdns_responder->registered_services().size());
-}
-
-TEST_F(MdnsResponderServiceTest, RestorePtrNotifiesObserver) {
- EXPECT_CALL(observer_, OnStarted());
- service_listener_->Start();
-
- auto* mdns_responder = mdns_responder_factory_->last_mdns_responder();
-
- AddEventsForNewService(mdns_responder, kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, "gigliorononomicon", kTestPort,
- {"model=shifty", "id=asdf"}, IPAddress{192, 168, 3, 7},
- kDefaultSocket);
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-
- auto ptr_remove = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- ptr_remove.header.response_type = QueryEventHeader::Type::kRemoved;
- mdns_responder->AddPtrEvent(std::move(ptr_remove));
-
- EXPECT_CALL(observer_, OnReceiverRemoved(_));
- mdns_service_->HandleNewEvents();
-
- auto ptr_add = MakePtrEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, kDefaultSocket);
- mdns_responder->AddPtrEvent(std::move(ptr_add));
-
- EXPECT_CALL(observer_, OnReceiverAdded(_));
- mdns_service_->HandleNewEvents();
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/mdns_service_listener_factory.cc b/osp/impl/mdns_service_listener_factory.cc
deleted file mode 100644
index cae4a341..00000000
--- a/osp/impl/mdns_service_listener_factory.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/public/mdns_service_listener_factory.h"
-
-#include "osp/impl/internal_services.h"
-
-namespace openscreen {
-
-class TaskRunner;
-
-namespace osp {
-
-// static
-std::unique_ptr<ServiceListener> MdnsServiceListenerFactory::Create(
- const MdnsServiceListenerConfig& config,
- ServiceListener::Observer* observer,
- TaskRunner* task_runner) {
- return InternalServices::CreateListener(config, observer, task_runner);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/mdns_service_publisher_factory.cc b/osp/impl/mdns_service_publisher_factory.cc
deleted file mode 100644
index f055e772..00000000
--- a/osp/impl/mdns_service_publisher_factory.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/public/mdns_service_publisher_factory.h"
-
-#include "osp/impl/internal_services.h"
-
-namespace openscreen {
-
-class TaskRunner;
-
-namespace osp {
-
-// static
-std::unique_ptr<ServicePublisher> MdnsServicePublisherFactory::Create(
- const ServicePublisher::Config& config,
- ServicePublisher::Observer* observer,
- TaskRunner* task_runner) {
- return InternalServices::CreatePublisher(config, observer, task_runner);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/network_service_manager.cc b/osp/impl/network_service_manager.cc
index d05192c0..10890ca8 100644
--- a/osp/impl/network_service_manager.cc
+++ b/osp/impl/network_service_manager.cc
@@ -17,14 +17,14 @@ namespace osp {
// static
NetworkServiceManager* NetworkServiceManager::Create(
std::unique_ptr<ServiceListener> mdns_listener,
- std::unique_ptr<ServicePublisher> mdns_publisher,
+ std::unique_ptr<ServicePublisher> service_publisher,
std::unique_ptr<ProtocolConnectionClient> connection_client,
std::unique_ptr<ProtocolConnectionServer> connection_server) {
// TODO(mfoltz): Convert to assertion failure
if (g_network_service_manager_instance)
return nullptr;
g_network_service_manager_instance = new NetworkServiceManager(
- std::move(mdns_listener), std::move(mdns_publisher),
+ std::move(mdns_listener), std::move(service_publisher),
std::move(connection_client), std::move(connection_server));
return g_network_service_manager_instance;
}
@@ -50,8 +50,8 @@ ServiceListener* NetworkServiceManager::GetMdnsServiceListener() {
return mdns_listener_.get();
}
-ServicePublisher* NetworkServiceManager::GetMdnsServicePublisher() {
- return mdns_publisher_.get();
+ServicePublisher* NetworkServiceManager::GetServicePublisher() {
+ return service_publisher_.get();
}
ProtocolConnectionClient* NetworkServiceManager::GetProtocolConnectionClient() {
@@ -64,11 +64,11 @@ ProtocolConnectionServer* NetworkServiceManager::GetProtocolConnectionServer() {
NetworkServiceManager::NetworkServiceManager(
std::unique_ptr<ServiceListener> mdns_listener,
- std::unique_ptr<ServicePublisher> mdns_publisher,
+ std::unique_ptr<ServicePublisher> service_publisher,
std::unique_ptr<ProtocolConnectionClient> connection_client,
std::unique_ptr<ProtocolConnectionServer> connection_server)
: mdns_listener_(std::move(mdns_listener)),
- mdns_publisher_(std::move(mdns_publisher)),
+ service_publisher_(std::move(service_publisher)),
connection_client_(std::move(connection_client)),
connection_server_(std::move(connection_server)) {}
diff --git a/osp/impl/service_publisher_impl.cc b/osp/impl/service_publisher_impl.cc
index bde3e528..8a984969 100644
--- a/osp/impl/service_publisher_impl.cc
+++ b/osp/impl/service_publisher_impl.cc
@@ -4,6 +4,8 @@
#include "osp/impl/service_publisher_impl.h"
+#include <utility>
+
#include "util/osp_logging.h"
namespace openscreen {
@@ -44,8 +46,8 @@ void ServicePublisherImpl::Delegate::SetPublisherImpl(
}
ServicePublisherImpl::ServicePublisherImpl(Observer* observer,
- Delegate* delegate)
- : ServicePublisher(observer), delegate_(delegate) {
+ std::unique_ptr<Delegate> delegate)
+ : ServicePublisher(observer), delegate_(std::move(delegate)) {
delegate_->SetPublisherImpl(this);
}
@@ -55,14 +57,14 @@ bool ServicePublisherImpl::Start() {
if (state_ != State::kStopped)
return false;
state_ = State::kStarting;
- delegate_->StartPublisher();
+ delegate_->StartPublisher(config_);
return true;
}
bool ServicePublisherImpl::StartAndSuspend() {
if (state_ != State::kStopped)
return false;
state_ = State::kStarting;
- delegate_->StartAndSuspendPublisher();
+ delegate_->StartAndSuspendPublisher(config_);
return true;
}
bool ServicePublisherImpl::Stop() {
@@ -84,7 +86,7 @@ bool ServicePublisherImpl::Resume() {
if (state_ != State::kSuspended)
return false;
- delegate_->ResumePublisher();
+ delegate_->ResumePublisher(config_);
return true;
}
diff --git a/osp/impl/service_publisher_impl.h b/osp/impl/service_publisher_impl.h
index d15e4dc9..fa2c3890 100644
--- a/osp/impl/service_publisher_impl.h
+++ b/osp/impl/service_publisher_impl.h
@@ -5,6 +5,8 @@
#ifndef OSP_IMPL_SERVICE_PUBLISHER_IMPL_H_
#define OSP_IMPL_SERVICE_PUBLISHER_IMPL_H_
+#include <memory>
+
#include "osp/impl/with_destruction_callback.h"
#include "osp/public/service_publisher.h"
#include "platform/base/macros.h"
@@ -18,18 +20,18 @@ class ServicePublisherImpl final : public ServicePublisher,
class Delegate {
public:
Delegate();
+ virtual ~Delegate();
void SetPublisherImpl(ServicePublisherImpl* publisher);
- virtual void StartPublisher() = 0;
- virtual void StartAndSuspendPublisher() = 0;
+ virtual void StartPublisher(const ServicePublisher::Config& config) = 0;
+ virtual void StartAndSuspendPublisher(
+ const ServicePublisher::Config& config) = 0;
virtual void StopPublisher() = 0;
virtual void SuspendPublisher() = 0;
- virtual void ResumePublisher() = 0;
+ virtual void ResumePublisher(const ServicePublisher::Config& config) = 0;
protected:
- virtual ~Delegate();
-
void SetState(State state) { publisher_->SetState(state); }
ServicePublisherImpl* publisher_ = nullptr;
@@ -38,7 +40,7 @@ class ServicePublisherImpl final : public ServicePublisher,
// |observer| is optional. If it is provided, it will receive appropriate
// notifications about this ServicePublisher. |delegate| is required and
// is used to implement state transitions.
- ServicePublisherImpl(Observer* observer, Delegate* delegate);
+ ServicePublisherImpl(Observer* observer, std::unique_ptr<Delegate> delegate);
~ServicePublisherImpl() override;
// ServicePublisher overrides.
@@ -57,7 +59,7 @@ class ServicePublisherImpl final : public ServicePublisher,
// by the observer interface.
void MaybeNotifyObserver();
- Delegate* const delegate_;
+ std::unique_ptr<Delegate> delegate_;
OSP_DISALLOW_COPY_AND_ASSIGN(ServicePublisherImpl);
};
diff --git a/osp/impl/service_publisher_impl_unittest.cc b/osp/impl/service_publisher_impl_unittest.cc
index 8c8bc9ec..b77a8aa5 100644
--- a/osp/impl/service_publisher_impl_unittest.cc
+++ b/osp/impl/service_publisher_impl_unittest.cc
@@ -5,6 +5,7 @@
#include "osp/impl/service_publisher_impl.h"
#include <memory>
+#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -13,6 +14,7 @@ namespace openscreen {
namespace osp {
namespace {
+using ::testing::_;
using ::testing::Expectation;
using ::testing::NiceMock;
@@ -26,7 +28,7 @@ class MockObserver final : public ServicePublisher::Observer {
MOCK_METHOD0(OnStopped, void());
MOCK_METHOD0(OnSuspended, void());
- MOCK_METHOD1(OnError, void(ServicePublisherError));
+ MOCK_METHOD1(OnError, void(Error));
MOCK_METHOD1(OnMetrics, void(ServicePublisher::Metrics));
};
@@ -38,23 +40,27 @@ class MockMdnsDelegate : public ServicePublisherImpl::Delegate {
using ServicePublisherImpl::Delegate::SetState;
- MOCK_METHOD0(StartPublisher, void());
- MOCK_METHOD0(StartAndSuspendPublisher, void());
+ MOCK_METHOD1(StartPublisher, void(const ServicePublisher::Config&));
+ MOCK_METHOD1(StartAndSuspendPublisher, void(const ServicePublisher::Config&));
MOCK_METHOD0(StopPublisher, void());
MOCK_METHOD0(SuspendPublisher, void());
- MOCK_METHOD0(ResumePublisher, void());
+ MOCK_METHOD1(ResumePublisher, void(const ServicePublisher::Config&));
MOCK_METHOD0(RunTasksPublisher, void());
};
class ServicePublisherImplTest : public ::testing::Test {
protected:
void SetUp() override {
- service_publisher_ =
- std::make_unique<ServicePublisherImpl>(nullptr, &mock_delegate_);
+ auto mock_delegate = std::make_unique<NiceMock<MockMdnsDelegate>>();
+ mock_delegate_ = mock_delegate.get();
+ service_publisher_ = std::make_unique<ServicePublisherImpl>(
+ nullptr, std::move(mock_delegate));
+ service_publisher_->SetConfig(config);
}
- NiceMock<MockMdnsDelegate> mock_delegate_;
+ NiceMock<MockMdnsDelegate>* mock_delegate_ = nullptr;
std::unique_ptr<ServicePublisherImpl> service_publisher_;
+ ServicePublisher::Config config;
};
} // namespace
@@ -62,99 +68,100 @@ class ServicePublisherImplTest : public ::testing::Test {
TEST_F(ServicePublisherImplTest, NormalStartStop) {
ASSERT_EQ(State::kStopped, service_publisher_->state());
- EXPECT_CALL(mock_delegate_, StartPublisher());
+ EXPECT_CALL(*mock_delegate_, StartPublisher(_));
EXPECT_TRUE(service_publisher_->Start());
EXPECT_FALSE(service_publisher_->Start());
EXPECT_EQ(State::kStarting, service_publisher_->state());
- mock_delegate_.SetState(State::kRunning);
+ mock_delegate_->SetState(State::kRunning);
EXPECT_EQ(State::kRunning, service_publisher_->state());
- EXPECT_CALL(mock_delegate_, StopPublisher());
+ EXPECT_CALL(*mock_delegate_, StopPublisher());
EXPECT_TRUE(service_publisher_->Stop());
EXPECT_FALSE(service_publisher_->Stop());
EXPECT_EQ(State::kStopping, service_publisher_->state());
- mock_delegate_.SetState(State::kStopped);
+ mock_delegate_->SetState(State::kStopped);
EXPECT_EQ(State::kStopped, service_publisher_->state());
}
TEST_F(ServicePublisherImplTest, StopBeforeRunning) {
- EXPECT_CALL(mock_delegate_, StartPublisher());
+ EXPECT_CALL(*mock_delegate_, StartPublisher(_));
EXPECT_TRUE(service_publisher_->Start());
EXPECT_EQ(State::kStarting, service_publisher_->state());
- EXPECT_CALL(mock_delegate_, StopPublisher());
+ EXPECT_CALL(*mock_delegate_, StopPublisher());
EXPECT_TRUE(service_publisher_->Stop());
EXPECT_FALSE(service_publisher_->Stop());
EXPECT_EQ(State::kStopping, service_publisher_->state());
- mock_delegate_.SetState(State::kStopped);
+ mock_delegate_->SetState(State::kStopped);
EXPECT_EQ(State::kStopped, service_publisher_->state());
}
TEST_F(ServicePublisherImplTest, StartSuspended) {
- EXPECT_CALL(mock_delegate_, StartAndSuspendPublisher());
- EXPECT_CALL(mock_delegate_, StartPublisher()).Times(0);
+ EXPECT_CALL(*mock_delegate_, StartAndSuspendPublisher(_));
+ EXPECT_CALL(*mock_delegate_, StartPublisher(_)).Times(0);
EXPECT_TRUE(service_publisher_->StartAndSuspend());
EXPECT_FALSE(service_publisher_->Start());
EXPECT_EQ(State::kStarting, service_publisher_->state());
- mock_delegate_.SetState(State::kSuspended);
+ mock_delegate_->SetState(State::kSuspended);
EXPECT_EQ(State::kSuspended, service_publisher_->state());
}
TEST_F(ServicePublisherImplTest, SuspendAndResume) {
EXPECT_TRUE(service_publisher_->Start());
- mock_delegate_.SetState(State::kRunning);
+ mock_delegate_->SetState(State::kRunning);
- EXPECT_CALL(mock_delegate_, ResumePublisher()).Times(0);
- EXPECT_CALL(mock_delegate_, SuspendPublisher()).Times(2);
+ EXPECT_CALL(*mock_delegate_, ResumePublisher(_)).Times(0);
+ EXPECT_CALL(*mock_delegate_, SuspendPublisher()).Times(2);
EXPECT_FALSE(service_publisher_->Resume());
EXPECT_TRUE(service_publisher_->Suspend());
EXPECT_TRUE(service_publisher_->Suspend());
- mock_delegate_.SetState(State::kSuspended);
+ mock_delegate_->SetState(State::kSuspended);
EXPECT_EQ(State::kSuspended, service_publisher_->state());
- EXPECT_CALL(mock_delegate_, StartPublisher()).Times(0);
- EXPECT_CALL(mock_delegate_, SuspendPublisher()).Times(0);
- EXPECT_CALL(mock_delegate_, ResumePublisher()).Times(2);
+ EXPECT_CALL(*mock_delegate_, StartPublisher(_)).Times(0);
+ EXPECT_CALL(*mock_delegate_, SuspendPublisher()).Times(0);
+ EXPECT_CALL(*mock_delegate_, ResumePublisher(_)).Times(2);
EXPECT_FALSE(service_publisher_->Start());
EXPECT_FALSE(service_publisher_->Suspend());
EXPECT_TRUE(service_publisher_->Resume());
EXPECT_TRUE(service_publisher_->Resume());
- mock_delegate_.SetState(State::kRunning);
+ mock_delegate_->SetState(State::kRunning);
EXPECT_EQ(State::kRunning, service_publisher_->state());
- EXPECT_CALL(mock_delegate_, ResumePublisher()).Times(0);
+ EXPECT_CALL(*mock_delegate_, ResumePublisher(_)).Times(0);
EXPECT_FALSE(service_publisher_->Resume());
}
TEST_F(ServicePublisherImplTest, ObserverTransitions) {
MockObserver observer;
- NiceMock<MockMdnsDelegate> mock_delegate;
- service_publisher_ =
- std::make_unique<ServicePublisherImpl>(&observer, &mock_delegate);
+ auto mock_delegate = std::make_unique<NiceMock<MockMdnsDelegate>>();
+ NiceMock<MockMdnsDelegate>* const mock_delegate_ptr = mock_delegate.get();
+ auto service_publisher = std::make_unique<ServicePublisherImpl>(
+ &observer, std::move(mock_delegate));
- service_publisher_->Start();
+ service_publisher->Start();
Expectation start_from_stopped = EXPECT_CALL(observer, OnStarted());
- mock_delegate.SetState(State::kRunning);
+ mock_delegate_ptr->SetState(State::kRunning);
- service_publisher_->Suspend();
+ service_publisher->Suspend();
Expectation suspend_from_running =
EXPECT_CALL(observer, OnSuspended()).After(start_from_stopped);
- mock_delegate.SetState(State::kSuspended);
+ mock_delegate_ptr->SetState(State::kSuspended);
- service_publisher_->Resume();
+ service_publisher->Resume();
Expectation resume_from_suspended =
EXPECT_CALL(observer, OnStarted()).After(suspend_from_running);
- mock_delegate.SetState(State::kRunning);
+ mock_delegate_ptr->SetState(State::kRunning);
- service_publisher_->Stop();
+ service_publisher->Stop();
EXPECT_CALL(observer, OnStopped()).After(resume_from_suspended);
- mock_delegate.SetState(State::kStopped);
+ mock_delegate_ptr->SetState(State::kStopped);
}
} // namespace osp
diff --git a/osp/impl/testing/BUILD.gn b/osp/impl/testing/BUILD.gn
deleted file mode 100644
index 94bcc504..00000000
--- a/osp/impl/testing/BUILD.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("../../build/config/services.gni")
-assert(use_mdns_responder)
-
-source_set("testing") {
- testonly = true
- sources = [
- "fake_mdns_platform_service.cc",
- "fake_mdns_platform_service.h",
- "fake_mdns_responder_adapter.cc",
- "fake_mdns_responder_adapter.h",
- ]
-
- deps = [
- "../discovery/mdns:mdns_interface",
- ]
-
- public_deps = [
- "../../../platform",
- ]
-}
-
-source_set("unittests") {
- testonly = true
- sources = [
- "fake_mdns_platform_service_unittest.cc",
- "fake_mdns_responder_adapter_unittest.cc",
- ]
-
- deps = [
- ":testing",
- "../../../third_party/abseil",
- "../../../third_party/googletest:gtest",
- ]
-}
diff --git a/osp/impl/testing/fake_mdns_platform_service.cc b/osp/impl/testing/fake_mdns_platform_service.cc
deleted file mode 100644
index 8ce6faf7..00000000
--- a/osp/impl/testing/fake_mdns_platform_service.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/testing/fake_mdns_platform_service.h"
-
-#include <algorithm>
-
-#include "util/osp_logging.h"
-
-namespace openscreen {
-namespace osp {
-
-FakeMdnsPlatformService::FakeMdnsPlatformService() = default;
-FakeMdnsPlatformService::~FakeMdnsPlatformService() = default;
-
-std::vector<MdnsPlatformService::BoundInterface>
-FakeMdnsPlatformService::RegisterInterfaces(
- const std::vector<NetworkInterfaceIndex>& allowlist) {
- OSP_CHECK(registered_interfaces_.empty());
- if (allowlist.empty()) {
- registered_interfaces_ = interfaces_;
- } else {
- for (const auto& interface : interfaces_) {
- if (std::find(allowlist.begin(), allowlist.end(),
- interface.interface_info.index) != allowlist.end()) {
- registered_interfaces_.push_back(interface);
- }
- }
- }
- return registered_interfaces_;
-}
-
-void FakeMdnsPlatformService::DeregisterInterfaces(
- const std::vector<BoundInterface>& interfaces) {
- for (const auto& interface : interfaces) {
- auto index = interface.interface_info.index;
- auto it = std::find_if(registered_interfaces_.begin(),
- registered_interfaces_.end(),
- [index](const BoundInterface& interface) {
- return interface.interface_info.index == index;
- });
- OSP_CHECK(it != registered_interfaces_.end())
- << "Must deregister a previously returned interface: " << index;
- registered_interfaces_.erase(it);
- }
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/testing/fake_mdns_platform_service.h b/osp/impl/testing/fake_mdns_platform_service.h
deleted file mode 100644
index a21c48cd..00000000
--- a/osp/impl/testing/fake_mdns_platform_service.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_TESTING_FAKE_MDNS_PLATFORM_SERVICE_H_
-#define OSP_IMPL_TESTING_FAKE_MDNS_PLATFORM_SERVICE_H_
-
-#include <vector>
-
-#include "osp/impl/mdns_platform_service.h"
-
-namespace openscreen {
-namespace osp {
-
-class FakeMdnsPlatformService final : public MdnsPlatformService {
- public:
- FakeMdnsPlatformService();
- ~FakeMdnsPlatformService() override;
-
- void set_interfaces(const std::vector<BoundInterface>& interfaces) {
- interfaces_ = interfaces;
- }
-
- // PlatformService overrides.
- std::vector<BoundInterface> RegisterInterfaces(
- const std::vector<NetworkInterfaceIndex>& interface_index_allowlist)
- override;
- void DeregisterInterfaces(
- const std::vector<BoundInterface>& registered_interfaces) override;
-
- private:
- std::vector<BoundInterface> registered_interfaces_;
- std::vector<BoundInterface> interfaces_;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_TESTING_FAKE_MDNS_PLATFORM_SERVICE_H_
diff --git a/osp/impl/testing/fake_mdns_platform_service_unittest.cc b/osp/impl/testing/fake_mdns_platform_service_unittest.cc
deleted file mode 100644
index 5a1d5f4c..00000000
--- a/osp/impl/testing/fake_mdns_platform_service_unittest.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/testing/fake_mdns_platform_service.h"
-
-#include <cstdint>
-
-#include "gtest/gtest.h"
-
-namespace openscreen {
-namespace osp {
-namespace {
-
-UdpSocket* const kDefaultSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(16));
-UdpSocket* const kSecondSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(24));
-
-class FakeMdnsPlatformServiceTest : public ::testing::Test {
- protected:
- const uint8_t mac1_[6] = {11, 22, 33, 44, 55, 66};
- const uint8_t mac2_[6] = {12, 23, 34, 45, 56, 67};
- const IPSubnet subnet1_{IPAddress{192, 168, 3, 2}, 24};
- const IPSubnet subnet2_{
- IPAddress{0x0102, 0x0304, 0x0504, 0x0302, 0x0102, 0x0304, 0x0506, 0x0708},
- 24};
- std::vector<MdnsPlatformService::BoundInterface> bound_interfaces_{
- MdnsPlatformService::BoundInterface{
- InterfaceInfo{1,
- mac1_,
- "eth0",
- InterfaceInfo::Type::kEthernet,
- {subnet1_}},
- subnet1_, kDefaultSocket},
- MdnsPlatformService::BoundInterface{
- InterfaceInfo{2,
- mac2_,
- "eth1",
- InterfaceInfo::Type::kEthernet,
- {subnet2_}},
- subnet2_, kSecondSocket}};
-};
-
-} // namespace
-
-TEST_F(FakeMdnsPlatformServiceTest, SimpleRegistration) {
- FakeMdnsPlatformService platform_service;
- std::vector<MdnsPlatformService::BoundInterface> bound_interfaces{
- bound_interfaces_[0]};
-
- platform_service.set_interfaces(bound_interfaces);
-
- auto registered_interfaces = platform_service.RegisterInterfaces({});
- EXPECT_EQ(bound_interfaces, registered_interfaces);
- platform_service.DeregisterInterfaces(registered_interfaces);
-
- registered_interfaces = platform_service.RegisterInterfaces({});
- EXPECT_EQ(bound_interfaces, registered_interfaces);
- platform_service.DeregisterInterfaces(registered_interfaces);
- platform_service.set_interfaces({});
-
- registered_interfaces = platform_service.RegisterInterfaces({});
- EXPECT_TRUE(registered_interfaces.empty());
- platform_service.DeregisterInterfaces(registered_interfaces);
-
- std::vector<MdnsPlatformService::BoundInterface> new_interfaces{
- bound_interfaces_[1]};
-
- platform_service.set_interfaces(new_interfaces);
-
- registered_interfaces = platform_service.RegisterInterfaces({});
- EXPECT_EQ(new_interfaces, registered_interfaces);
- platform_service.DeregisterInterfaces(registered_interfaces);
-}
-
-TEST_F(FakeMdnsPlatformServiceTest, ObeyIndexAllowlist) {
- FakeMdnsPlatformService platform_service;
- platform_service.set_interfaces(bound_interfaces_);
-
- auto eth0_only = platform_service.RegisterInterfaces({1});
- EXPECT_EQ(
- (std::vector<MdnsPlatformService::BoundInterface>{bound_interfaces_[0]}),
- eth0_only);
- platform_service.DeregisterInterfaces(eth0_only);
-
- auto eth1_only = platform_service.RegisterInterfaces({2});
- EXPECT_EQ(
- (std::vector<MdnsPlatformService::BoundInterface>{bound_interfaces_[1]}),
- eth1_only);
- platform_service.DeregisterInterfaces(eth1_only);
-
- auto both = platform_service.RegisterInterfaces({1, 2});
- EXPECT_EQ(bound_interfaces_, both);
- platform_service.DeregisterInterfaces(both);
-}
-
-TEST_F(FakeMdnsPlatformServiceTest, PartialDeregister) {
- FakeMdnsPlatformService platform_service;
- platform_service.set_interfaces(bound_interfaces_);
-
- auto both = platform_service.RegisterInterfaces({});
- std::vector<MdnsPlatformService::BoundInterface> eth0_only{
- bound_interfaces_[0]};
- std::vector<MdnsPlatformService::BoundInterface> eth1_only{
- bound_interfaces_[1]};
- platform_service.DeregisterInterfaces(eth0_only);
- platform_service.DeregisterInterfaces(eth1_only);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/testing/fake_mdns_responder_adapter.cc b/osp/impl/testing/fake_mdns_responder_adapter.cc
deleted file mode 100644
index 7b5a3b5e..00000000
--- a/osp/impl/testing/fake_mdns_responder_adapter.cc
+++ /dev/null
@@ -1,600 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/testing/fake_mdns_responder_adapter.h"
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "platform/base/error.h"
-#include "util/osp_logging.h"
-
-namespace openscreen {
-namespace osp {
-
-constexpr char kLocalDomain[] = "local";
-
-PtrEvent MakePtrEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- UdpSocket* socket) {
- const auto labels = std::vector<std::string>{service_instance, service_type,
- service_protocol, kLocalDomain};
- ErrorOr<DomainName> full_instance_name =
- DomainName::FromLabels(labels.begin(), labels.end());
- OSP_CHECK(full_instance_name);
- PtrEvent result{QueryEventHeader{QueryEventHeader::Type::kAdded, socket},
- full_instance_name.value()};
- return result;
-}
-
-SrvEvent MakeSrvEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- const std::string& hostname,
- uint16_t port,
- UdpSocket* socket) {
- const auto instance_labels = std::vector<std::string>{
- service_instance, service_type, service_protocol, kLocalDomain};
- ErrorOr<DomainName> full_instance_name =
- DomainName::FromLabels(instance_labels.begin(), instance_labels.end());
- OSP_CHECK(full_instance_name);
-
- const auto host_labels = std::vector<std::string>{hostname, kLocalDomain};
- ErrorOr<DomainName> domain_name =
- DomainName::FromLabels(host_labels.begin(), host_labels.end());
- OSP_CHECK(domain_name);
-
- SrvEvent result{QueryEventHeader{QueryEventHeader::Type::kAdded, socket},
- full_instance_name.value(), domain_name.value(), port};
- return result;
-}
-
-TxtEvent MakeTxtEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- const std::vector<std::string>& txt_lines,
- UdpSocket* socket) {
- const auto labels = std::vector<std::string>{service_instance, service_type,
- service_protocol, kLocalDomain};
- ErrorOr<DomainName> domain_name =
- DomainName::FromLabels(labels.begin(), labels.end());
- OSP_CHECK(domain_name);
- TxtEvent result{QueryEventHeader{QueryEventHeader::Type::kAdded, socket},
- domain_name.value(), txt_lines};
- return result;
-}
-
-AEvent MakeAEvent(const std::string& hostname,
- IPAddress address,
- UdpSocket* socket) {
- const auto labels = std::vector<std::string>{hostname, kLocalDomain};
- ErrorOr<DomainName> domain_name =
- DomainName::FromLabels(labels.begin(), labels.end());
- OSP_CHECK(domain_name);
- AEvent result{QueryEventHeader{QueryEventHeader::Type::kAdded, socket},
- domain_name.value(), address};
- return result;
-}
-
-AaaaEvent MakeAaaaEvent(const std::string& hostname,
- IPAddress address,
- UdpSocket* socket) {
- const auto labels = std::vector<std::string>{hostname, kLocalDomain};
- ErrorOr<DomainName> domain_name =
- DomainName::FromLabels(labels.begin(), labels.end());
- OSP_CHECK(domain_name);
- AaaaEvent result{QueryEventHeader{QueryEventHeader::Type::kAdded, socket},
- domain_name.value(), address};
- return result;
-}
-
-void AddEventsForNewService(FakeMdnsResponderAdapter* mdns_responder,
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::string& hostname,
- uint16_t port,
- const std::vector<std::string>& txt_lines,
- const IPAddress& address,
- UdpSocket* socket) {
- mdns_responder->AddPtrEvent(
- MakePtrEvent(service_instance, service_name, service_protocol, socket));
- mdns_responder->AddSrvEvent(MakeSrvEvent(service_instance, service_name,
- service_protocol, hostname, port,
- socket));
- mdns_responder->AddTxtEvent(MakeTxtEvent(
- service_instance, service_name, service_protocol, txt_lines, socket));
- mdns_responder->AddAEvent(MakeAEvent(hostname, address, socket));
-}
-
-FakeMdnsResponderAdapter::~FakeMdnsResponderAdapter() {
- if (observer_) {
- observer_->OnDestroyed();
- }
-}
-
-void FakeMdnsResponderAdapter::AddPtrEvent(PtrEvent&& ptr_event) {
- if (running_)
- ptr_events_.push_back(std::move(ptr_event));
-}
-
-void FakeMdnsResponderAdapter::AddSrvEvent(SrvEvent&& srv_event) {
- if (running_)
- srv_events_.push_back(std::move(srv_event));
-}
-
-void FakeMdnsResponderAdapter::AddTxtEvent(TxtEvent&& txt_event) {
- if (running_)
- txt_events_.push_back(std::move(txt_event));
-}
-
-void FakeMdnsResponderAdapter::AddAEvent(AEvent&& a_event) {
- if (running_)
- a_events_.push_back(std::move(a_event));
-}
-
-void FakeMdnsResponderAdapter::AddAaaaEvent(AaaaEvent&& aaaa_event) {
- if (running_)
- aaaa_events_.push_back(std::move(aaaa_event));
-}
-
-bool FakeMdnsResponderAdapter::ptr_queries_empty() const {
- for (const auto& queries : queries_) {
- if (!queries.second.ptr_queries.empty())
- return false;
- }
- return true;
-}
-
-bool FakeMdnsResponderAdapter::srv_queries_empty() const {
- for (const auto& queries : queries_) {
- if (!queries.second.srv_queries.empty())
- return false;
- }
- return true;
-}
-
-bool FakeMdnsResponderAdapter::txt_queries_empty() const {
- for (const auto& queries : queries_) {
- if (!queries.second.txt_queries.empty())
- return false;
- }
- return true;
-}
-
-bool FakeMdnsResponderAdapter::a_queries_empty() const {
- for (const auto& queries : queries_) {
- if (!queries.second.a_queries.empty())
- return false;
- }
- return true;
-}
-
-bool FakeMdnsResponderAdapter::aaaa_queries_empty() const {
- for (const auto& queries : queries_) {
- if (!queries.second.aaaa_queries.empty())
- return false;
- }
- return true;
-}
-
-Error FakeMdnsResponderAdapter::Init() {
- OSP_CHECK(!running_);
- running_ = true;
- return Error::None();
-}
-
-void FakeMdnsResponderAdapter::Close() {
- queries_.clear();
- ptr_events_.clear();
- srv_events_.clear();
- txt_events_.clear();
- a_events_.clear();
- aaaa_events_.clear();
- registered_interfaces_.clear();
- registered_services_.clear();
- running_ = false;
-}
-
-Error FakeMdnsResponderAdapter::SetHostLabel(const std::string& host_label) {
- return Error::Code::kNotImplemented;
-}
-
-Error FakeMdnsResponderAdapter::RegisterInterface(
- const InterfaceInfo& interface_info,
- const IPSubnet& interface_address,
- UdpSocket* socket) {
- if (!running_)
- return Error::Code::kOperationInvalid;
-
- if (std::find_if(registered_interfaces_.begin(), registered_interfaces_.end(),
- [&socket](const RegisteredInterface& interface) {
- return interface.socket == socket;
- }) != registered_interfaces_.end()) {
- return Error::Code::kItemNotFound;
- }
- registered_interfaces_.push_back({interface_info, interface_address, socket});
- return Error::None();
-}
-
-Error FakeMdnsResponderAdapter::DeregisterInterface(UdpSocket* socket) {
- auto it =
- std::find_if(registered_interfaces_.begin(), registered_interfaces_.end(),
- [&socket](const RegisteredInterface& interface) {
- return interface.socket == socket;
- });
- if (it == registered_interfaces_.end())
- return Error::Code::kItemNotFound;
-
- registered_interfaces_.erase(it);
- return Error::None();
-}
-
-void FakeMdnsResponderAdapter::OnRead(UdpSocket* socket,
- ErrorOr<UdpPacket> packet) {
- OSP_NOTREACHED();
-}
-
-void FakeMdnsResponderAdapter::OnSendError(UdpSocket* socket, Error error) {
- OSP_NOTREACHED();
-}
-
-void FakeMdnsResponderAdapter::OnError(UdpSocket* socket, Error error) {
- OSP_NOTREACHED();
-}
-
-void FakeMdnsResponderAdapter::OnBound(UdpSocket* socket) {
- OSP_NOTREACHED();
-}
-
-Clock::duration FakeMdnsResponderAdapter::RunTasks() {
- return std::chrono::seconds(1);
-}
-
-std::vector<PtrEvent> FakeMdnsResponderAdapter::TakePtrResponses() {
- std::vector<PtrEvent> result;
- for (auto& queries : queries_) {
- const auto query_it = std::stable_partition(
- ptr_events_.begin(), ptr_events_.end(),
- [&queries](const PtrEvent& ptr_event) {
- const auto instance_labels = ptr_event.service_instance.GetLabels();
- for (const auto& query : queries.second.ptr_queries) {
- const auto query_labels = query.GetLabels();
- // TODO(btolsch): Just use qname if it's added to PtrEvent.
- if (ptr_event.header.socket == queries.first &&
- std::equal(instance_labels.begin() + 1, instance_labels.end(),
- query_labels.begin())) {
- return false;
- }
- }
- return true;
- });
- for (auto it = query_it; it != ptr_events_.end(); ++it) {
- result.push_back(std::move(*it));
- }
- ptr_events_.erase(query_it, ptr_events_.end());
- }
- OSP_LOG_INFO << "taking " << result.size() << " ptr response(s)";
- return result;
-}
-
-std::vector<SrvEvent> FakeMdnsResponderAdapter::TakeSrvResponses() {
- std::vector<SrvEvent> result;
- for (auto& queries : queries_) {
- const auto query_it = std::stable_partition(
- srv_events_.begin(), srv_events_.end(),
- [&queries](const SrvEvent& srv_event) {
- for (const auto& query : queries.second.srv_queries) {
- if (srv_event.header.socket == queries.first &&
- srv_event.service_instance == query)
- return false;
- }
- return true;
- });
- for (auto it = query_it; it != srv_events_.end(); ++it) {
- result.push_back(std::move(*it));
- }
- srv_events_.erase(query_it, srv_events_.end());
- }
- OSP_LOG_INFO << "taking " << result.size() << " srv response(s)";
- return result;
-}
-
-std::vector<TxtEvent> FakeMdnsResponderAdapter::TakeTxtResponses() {
- std::vector<TxtEvent> result;
- for (auto& queries : queries_) {
- const auto query_it = std::stable_partition(
- txt_events_.begin(), txt_events_.end(),
- [&queries](const TxtEvent& txt_event) {
- for (const auto& query : queries.second.txt_queries) {
- if (txt_event.header.socket == queries.first &&
- txt_event.service_instance == query) {
- return false;
- }
- }
- return true;
- });
- for (auto it = query_it; it != txt_events_.end(); ++it) {
- result.push_back(std::move(*it));
- }
- txt_events_.erase(query_it, txt_events_.end());
- }
- OSP_LOG_INFO << "taking " << result.size() << " txt response(s)";
- return result;
-}
-
-std::vector<AEvent> FakeMdnsResponderAdapter::TakeAResponses() {
- std::vector<AEvent> result;
- for (auto& queries : queries_) {
- const auto query_it = std::stable_partition(
- a_events_.begin(), a_events_.end(), [&queries](const AEvent& a_event) {
- for (const auto& query : queries.second.a_queries) {
- if (a_event.header.socket == queries.first &&
- a_event.domain_name == query) {
- return false;
- }
- }
- return true;
- });
- for (auto it = query_it; it != a_events_.end(); ++it) {
- result.push_back(std::move(*it));
- }
- a_events_.erase(query_it, a_events_.end());
- }
- OSP_LOG_INFO << "taking " << result.size() << " a response(s)";
- return result;
-}
-
-std::vector<AaaaEvent> FakeMdnsResponderAdapter::TakeAaaaResponses() {
- std::vector<AaaaEvent> result;
- for (auto& queries : queries_) {
- const auto query_it = std::stable_partition(
- aaaa_events_.begin(), aaaa_events_.end(),
- [&queries](const AaaaEvent& aaaa_event) {
- for (const auto& query : queries.second.aaaa_queries) {
- if (aaaa_event.header.socket == queries.first &&
- aaaa_event.domain_name == query) {
- return false;
- }
- }
- return true;
- });
- for (auto it = query_it; it != aaaa_events_.end(); ++it) {
- result.push_back(std::move(*it));
- }
- aaaa_events_.erase(query_it, aaaa_events_.end());
- }
- OSP_LOG_INFO << "taking " << result.size() << " a response(s)";
- return result;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StartPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto canonical_service_type = service_type;
- if (!canonical_service_type.EndsWithLocalDomain())
- OSP_CHECK(canonical_service_type.Append(DomainName::GetLocalDomain()).ok());
-
- auto maybe_inserted =
- queries_[socket].ptr_queries.insert(canonical_service_type);
- if (maybe_inserted.second) {
- return MdnsResponderErrorCode::kNoError;
- } else {
- return MdnsResponderErrorCode::kUnknownError;
- }
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StartSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto maybe_inserted = queries_[socket].srv_queries.insert(service_instance);
- if (maybe_inserted.second) {
- return MdnsResponderErrorCode::kNoError;
- } else {
- return MdnsResponderErrorCode::kUnknownError;
- }
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StartTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto maybe_inserted = queries_[socket].txt_queries.insert(service_instance);
- if (maybe_inserted.second) {
- return MdnsResponderErrorCode::kNoError;
- } else {
- return MdnsResponderErrorCode::kUnknownError;
- }
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StartAQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto maybe_inserted = queries_[socket].a_queries.insert(domain_name);
- if (maybe_inserted.second) {
- return MdnsResponderErrorCode::kNoError;
- } else {
- return MdnsResponderErrorCode::kUnknownError;
- }
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StartAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto maybe_inserted = queries_[socket].aaaa_queries.insert(domain_name);
- if (maybe_inserted.second) {
- return MdnsResponderErrorCode::kNoError;
- } else {
- return MdnsResponderErrorCode::kUnknownError;
- }
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StopPtrQuery(
- UdpSocket* socket,
- const DomainName& service_type) {
- auto interface_entry = queries_.find(socket);
- if (interface_entry == queries_.end())
- return MdnsResponderErrorCode::kUnknownError;
- auto& ptr_queries = interface_entry->second.ptr_queries;
- auto canonical_service_type = service_type;
- if (!canonical_service_type.EndsWithLocalDomain())
- OSP_CHECK(canonical_service_type.Append(DomainName::GetLocalDomain()).ok());
-
- auto it = ptr_queries.find(canonical_service_type);
- if (it == ptr_queries.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- ptr_queries.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StopSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- auto interface_entry = queries_.find(socket);
- if (interface_entry == queries_.end())
- return MdnsResponderErrorCode::kUnknownError;
- auto& srv_queries = interface_entry->second.srv_queries;
- auto it = srv_queries.find(service_instance);
- if (it == srv_queries.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- srv_queries.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StopTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) {
- auto interface_entry = queries_.find(socket);
- if (interface_entry == queries_.end())
- return MdnsResponderErrorCode::kUnknownError;
- auto& txt_queries = interface_entry->second.txt_queries;
- auto it = txt_queries.find(service_instance);
- if (it == txt_queries.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- txt_queries.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StopAQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- auto interface_entry = queries_.find(socket);
- if (interface_entry == queries_.end())
- return MdnsResponderErrorCode::kUnknownError;
- auto& a_queries = interface_entry->second.a_queries;
- auto it = a_queries.find(domain_name);
- if (it == a_queries.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- a_queries.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::StopAaaaQuery(
- UdpSocket* socket,
- const DomainName& domain_name) {
- auto interface_entry = queries_.find(socket);
- if (interface_entry == queries_.end())
- return MdnsResponderErrorCode::kUnknownError;
- auto& aaaa_queries = interface_entry->second.aaaa_queries;
- auto it = aaaa_queries.find(domain_name);
- if (it == aaaa_queries.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- aaaa_queries.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::RegisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const DomainName& target_host,
- uint16_t target_port,
- const std::map<std::string, std::string>& txt_data) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- if (std::find_if(registered_services_.begin(), registered_services_.end(),
- [&service_instance, &service_name,
- &service_protocol](const RegisteredService& service) {
- return service.service_instance == service_instance &&
- service.service_name == service_name &&
- service.service_protocol == service_protocol;
- }) != registered_services_.end()) {
- return MdnsResponderErrorCode::kUnknownError;
- }
- registered_services_.push_back({service_instance, service_name,
- service_protocol, target_host, target_port,
- txt_data});
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::DeregisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto it =
- std::find_if(registered_services_.begin(), registered_services_.end(),
- [&service_instance, &service_name,
- &service_protocol](const RegisteredService& service) {
- return service.service_instance == service_instance &&
- service.service_name == service_name &&
- service.service_protocol == service_protocol;
- });
- if (it == registered_services_.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- registered_services_.erase(it);
- return MdnsResponderErrorCode::kNoError;
-}
-
-MdnsResponderErrorCode FakeMdnsResponderAdapter::UpdateTxtData(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::map<std::string, std::string>& txt_data) {
- if (!running_)
- return MdnsResponderErrorCode::kUnknownError;
-
- auto it =
- std::find_if(registered_services_.begin(), registered_services_.end(),
- [&service_instance, &service_name,
- &service_protocol](const RegisteredService& service) {
- return service.service_instance == service_instance &&
- service.service_name == service_name &&
- service.service_protocol == service_protocol;
- });
- if (it == registered_services_.end())
- return MdnsResponderErrorCode::kUnknownError;
-
- it->txt_data = txt_data;
- return MdnsResponderErrorCode::kNoError;
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/impl/testing/fake_mdns_responder_adapter.h b/osp/impl/testing/fake_mdns_responder_adapter.h
deleted file mode 100644
index ecdb21cc..00000000
--- a/osp/impl/testing/fake_mdns_responder_adapter.h
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef OSP_IMPL_TESTING_FAKE_MDNS_RESPONDER_ADAPTER_H_
-#define OSP_IMPL_TESTING_FAKE_MDNS_RESPONDER_ADAPTER_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "osp/impl/discovery/mdns/mdns_responder_adapter.h"
-
-namespace openscreen {
-namespace osp {
-
-class FakeMdnsResponderAdapter;
-
-PtrEvent MakePtrEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- UdpSocket* socket);
-
-SrvEvent MakeSrvEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- const std::string& hostname,
- uint16_t port,
- UdpSocket* socket);
-
-TxtEvent MakeTxtEvent(const std::string& service_instance,
- const std::string& service_type,
- const std::string& service_protocol,
- const std::vector<std::string>& txt_lines,
- UdpSocket* socket);
-
-AEvent MakeAEvent(const std::string& hostname,
- IPAddress address,
- UdpSocket* socket);
-
-AaaaEvent MakeAaaaEvent(const std::string& hostname,
- IPAddress address,
- UdpSocket* socket);
-
-void AddEventsForNewService(FakeMdnsResponderAdapter* mdns_responder,
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::string& hostname,
- uint16_t port,
- const std::vector<std::string>& txt_lines,
- const IPAddress& address,
- UdpSocket* socket);
-
-class FakeMdnsResponderAdapter final : public MdnsResponderAdapter {
- public:
- struct RegisteredInterface {
- InterfaceInfo interface_info;
- IPSubnet interface_address;
- UdpSocket* socket;
- };
-
- struct RegisteredService {
- std::string service_instance;
- std::string service_name;
- std::string service_protocol;
- DomainName target_host;
- uint16_t target_port;
- std::map<std::string, std::string> txt_data;
- };
-
- class LifetimeObserver {
- public:
- virtual ~LifetimeObserver() = default;
-
- virtual void OnDestroyed() = 0;
- };
-
- ~FakeMdnsResponderAdapter() override;
-
- void SetLifetimeObserver(LifetimeObserver* observer) { observer_ = observer; }
-
- void AddPtrEvent(PtrEvent&& ptr_event);
- void AddSrvEvent(SrvEvent&& srv_event);
- void AddTxtEvent(TxtEvent&& txt_event);
- void AddAEvent(AEvent&& a_event);
- void AddAaaaEvent(AaaaEvent&& aaaa_event);
-
- const std::vector<RegisteredInterface>& registered_interfaces() {
- return registered_interfaces_;
- }
- const std::vector<RegisteredService>& registered_services() {
- return registered_services_;
- }
- bool ptr_queries_empty() const;
- bool srv_queries_empty() const;
- bool txt_queries_empty() const;
- bool a_queries_empty() const;
- bool aaaa_queries_empty() const;
- bool running() const { return running_; }
-
- // UdpSocket::Client overrides.
- void OnRead(UdpSocket* socket, ErrorOr<UdpPacket> packet) override;
- void OnSendError(UdpSocket* socket, Error error) override;
- void OnError(UdpSocket* socket, Error error) override;
- void OnBound(UdpSocket* socket) override;
-
- // MdnsResponderAdapter overrides.
- Error Init() override;
- void Close() override;
-
- Error SetHostLabel(const std::string& host_label) override;
-
- // TODO(btolsch): Reject/OSP_CHECK events that don't match any registered
- // interface?
- Error RegisterInterface(const InterfaceInfo& interface_info,
- const IPSubnet& interface_address,
- UdpSocket* socket) override;
- Error DeregisterInterface(UdpSocket* socket) override;
-
- Clock::duration RunTasks() override;
-
- std::vector<PtrEvent> TakePtrResponses() override;
- std::vector<SrvEvent> TakeSrvResponses() override;
- std::vector<TxtEvent> TakeTxtResponses() override;
- std::vector<AEvent> TakeAResponses() override;
- std::vector<AaaaEvent> TakeAaaaResponses() override;
-
- MdnsResponderErrorCode StartPtrQuery(UdpSocket* socket,
- const DomainName& service_type) override;
- MdnsResponderErrorCode StartSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StartTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StartAQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
- MdnsResponderErrorCode StartAaaaQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
-
- MdnsResponderErrorCode StopPtrQuery(UdpSocket* socket,
- const DomainName& service_type) override;
- MdnsResponderErrorCode StopSrvQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StopTxtQuery(
- UdpSocket* socket,
- const DomainName& service_instance) override;
- MdnsResponderErrorCode StopAQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
- MdnsResponderErrorCode StopAaaaQuery(UdpSocket* socket,
- const DomainName& domain_name) override;
-
- MdnsResponderErrorCode RegisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const DomainName& target_host,
- uint16_t target_port,
- const std::map<std::string, std::string>& txt_data) override;
- MdnsResponderErrorCode DeregisterService(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol) override;
- MdnsResponderErrorCode UpdateTxtData(
- const std::string& service_instance,
- const std::string& service_name,
- const std::string& service_protocol,
- const std::map<std::string, std::string>& txt_data) override;
-
- private:
- struct InterfaceQueries {
- std::set<DomainName, DomainNameComparator> a_queries;
- std::set<DomainName, DomainNameComparator> aaaa_queries;
- std::set<DomainName, DomainNameComparator> ptr_queries;
- std::set<DomainName, DomainNameComparator> srv_queries;
- std::set<DomainName, DomainNameComparator> txt_queries;
- };
-
- bool running_ = false;
- LifetimeObserver* observer_ = nullptr;
-
- std::map<UdpSocket*, InterfaceQueries> queries_;
- // NOTE: One of many simplifications here is that there is no cache. This
- // means that calling StartQuery, StopQuery, StartQuery will only return an
- // event the first time, unless the test also adds the event a second time.
- std::vector<PtrEvent> ptr_events_;
- std::vector<SrvEvent> srv_events_;
- std::vector<TxtEvent> txt_events_;
- std::vector<AEvent> a_events_;
- std::vector<AaaaEvent> aaaa_events_;
-
- std::vector<RegisteredInterface> registered_interfaces_;
- std::vector<RegisteredService> registered_services_;
-};
-
-} // namespace osp
-} // namespace openscreen
-
-#endif // OSP_IMPL_TESTING_FAKE_MDNS_RESPONDER_ADAPTER_H_
diff --git a/osp/impl/testing/fake_mdns_responder_adapter_unittest.cc b/osp/impl/testing/fake_mdns_responder_adapter_unittest.cc
deleted file mode 100644
index 06cec89a..00000000
--- a/osp/impl/testing/fake_mdns_responder_adapter_unittest.cc
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "osp/impl/testing/fake_mdns_responder_adapter.h"
-
-#include "gtest/gtest.h"
-
-namespace openscreen {
-namespace osp {
-
-namespace {
-
-constexpr char kTestServiceInstance[] = "turtle";
-constexpr char kTestServiceName[] = "_foo";
-constexpr char kTestServiceProtocol[] = "_udp";
-
-UdpSocket* const kDefaultSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(8));
-UdpSocket* const kSecondSocket =
- reinterpret_cast<UdpSocket*>(static_cast<uintptr_t>(32));
-
-} // namespace
-
-TEST(FakeMdnsResponderAdapterTest, AQueries) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
- auto event = MakeAEvent("alpha", IPAddress{1, 2, 3, 4}, kDefaultSocket);
- auto domain_name = event.domain_name;
- mdns_responder.AddAEvent(std::move(event));
-
- auto a_events = mdns_responder.TakeAResponses();
- EXPECT_TRUE(a_events.empty());
-
- auto result = mdns_responder.StartAQuery(kDefaultSocket, domain_name);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- a_events = mdns_responder.TakeAResponses();
- ASSERT_EQ(1u, a_events.size());
- EXPECT_EQ(domain_name, a_events[0].domain_name);
- EXPECT_EQ((IPAddress{1, 2, 3, 4}), a_events[0].address);
-
- result = mdns_responder.StopAQuery(kDefaultSocket, domain_name);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
-
- mdns_responder.AddAEvent(
- MakeAEvent("alpha", IPAddress{1, 2, 3, 4}, kDefaultSocket));
- result = mdns_responder.StartAQuery(kDefaultSocket, domain_name);
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- a_events = mdns_responder.TakeAResponses();
- EXPECT_TRUE(a_events.empty());
-}
-
-TEST(FakeMdnsResponderAdapterTest, AaaaQueries) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
- auto event = MakeAaaaEvent("alpha", IPAddress{1, 2, 3, 4}, kDefaultSocket);
- auto domain_name = event.domain_name;
- mdns_responder.AddAaaaEvent(std::move(event));
-
- auto aaaa_events = mdns_responder.TakeAaaaResponses();
- EXPECT_TRUE(aaaa_events.empty());
-
- auto result = mdns_responder.StartAaaaQuery(kDefaultSocket, domain_name);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- aaaa_events = mdns_responder.TakeAaaaResponses();
- ASSERT_EQ(1u, aaaa_events.size());
- EXPECT_EQ(domain_name, aaaa_events[0].domain_name);
- EXPECT_EQ((IPAddress{1, 2, 3, 4}), aaaa_events[0].address);
-
- result = mdns_responder.StopAaaaQuery(kDefaultSocket, domain_name);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
-
- mdns_responder.AddAaaaEvent(
- MakeAaaaEvent("alpha", IPAddress{1, 2, 3, 4}, kDefaultSocket));
- result = mdns_responder.StartAaaaQuery(kDefaultSocket, domain_name);
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- aaaa_events = mdns_responder.TakeAaaaResponses();
- EXPECT_TRUE(aaaa_events.empty());
-}
-
-TEST(FakeMdnsResponderAdapterTest, PtrQueries) {
- const DomainName kTestServiceType{
- {4, '_', 'f', 'o', 'o', 4, '_', 'u', 'd', 'p', 0}};
- const DomainName kTestServiceTypeCanon{{4, '_', 'f', 'o', 'o', 4, '_', 'u',
- 'd', 'p', 5, 'l', 'o', 'c', 'a', 'l',
- 0}};
-
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
- mdns_responder.AddPtrEvent(
- MakePtrEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- kDefaultSocket));
-
- auto ptr_events = mdns_responder.TakePtrResponses();
- EXPECT_TRUE(ptr_events.empty());
-
- auto result = mdns_responder.StartPtrQuery(kDefaultSocket, kTestServiceType);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- ptr_events = mdns_responder.TakePtrResponses();
- ASSERT_EQ(1u, ptr_events.size());
- auto labels = ptr_events[0].service_instance.GetLabels();
- EXPECT_EQ(kTestServiceInstance, labels[0]);
-
- // TODO(btolsch): qname if PtrEvent gets it.
- ErrorOr<DomainName> st =
- DomainName::FromLabels(labels.begin() + 1, labels.end());
- ASSERT_TRUE(st);
- EXPECT_EQ(kTestServiceTypeCanon, st.value());
-
- result = mdns_responder.StopPtrQuery(kDefaultSocket, kTestServiceType);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
-
- mdns_responder.AddPtrEvent(
- MakePtrEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- kDefaultSocket));
- result = mdns_responder.StartPtrQuery(kDefaultSocket, kTestServiceType);
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- ptr_events = mdns_responder.TakePtrResponses();
- EXPECT_TRUE(ptr_events.empty());
-}
-
-TEST(FakeMdnsResponderAdapterTest, SrvQueries) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
-
- auto event =
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "alpha", 12345, kDefaultSocket);
- auto service_instance = event.service_instance;
- auto domain_name = event.domain_name;
- mdns_responder.AddSrvEvent(std::move(event));
-
- auto srv_events = mdns_responder.TakeSrvResponses();
- EXPECT_TRUE(srv_events.empty());
-
- auto result = mdns_responder.StartSrvQuery(kDefaultSocket, service_instance);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- srv_events = mdns_responder.TakeSrvResponses();
- ASSERT_EQ(1u, srv_events.size());
- EXPECT_EQ(service_instance, srv_events[0].service_instance);
- EXPECT_EQ(domain_name, srv_events[0].domain_name);
- EXPECT_EQ(12345, srv_events[0].port);
-
- result = mdns_responder.StopSrvQuery(kDefaultSocket, service_instance);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
-
- mdns_responder.AddSrvEvent(
- MakeSrvEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- "alpha", 12345, kDefaultSocket));
- result = mdns_responder.StartSrvQuery(kDefaultSocket, service_instance);
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- srv_events = mdns_responder.TakeSrvResponses();
- EXPECT_TRUE(srv_events.empty());
-}
-
-TEST(FakeMdnsResponderAdapterTest, TxtQueries) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
-
- const auto txt_lines = std::vector<std::string>{"asdf", "jkl;", "j"};
- auto event = MakeTxtEvent(kTestServiceInstance, kTestServiceName,
- kTestServiceProtocol, txt_lines, kDefaultSocket);
- auto service_instance = event.service_instance;
- mdns_responder.AddTxtEvent(std::move(event));
-
- auto txt_events = mdns_responder.TakeTxtResponses();
- EXPECT_TRUE(txt_events.empty());
-
- auto result = mdns_responder.StartTxtQuery(kDefaultSocket, service_instance);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- txt_events = mdns_responder.TakeTxtResponses();
- ASSERT_EQ(1u, txt_events.size());
- EXPECT_EQ(service_instance, txt_events[0].service_instance);
- EXPECT_EQ(txt_lines, txt_events[0].txt_info);
-
- result = mdns_responder.StopTxtQuery(kDefaultSocket, service_instance);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
-
- mdns_responder.AddTxtEvent(
- MakeTxtEvent(kTestServiceInstance, kTestServiceName, kTestServiceProtocol,
- txt_lines, kDefaultSocket));
- result = mdns_responder.StartTxtQuery(kDefaultSocket, service_instance);
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- txt_events = mdns_responder.TakeTxtResponses();
- EXPECT_TRUE(txt_events.empty());
-}
-
-TEST(FakeMdnsResponderAdapterTest, RegisterServices) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
-
- auto result = mdns_responder.RegisterService(
- "instance", "name", "proto",
- DomainName{{1, 'a', 5, 'l', 'o', 'c', 'a', 'l', 0}}, 12345,
- {{"k1", "asdf"}, {"k2", "jkl"}});
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
- EXPECT_EQ(1u, mdns_responder.registered_services().size());
-
- result = mdns_responder.RegisterService(
- "instance2", "name", "proto",
- DomainName{{1, 'b', 5, 'l', 'o', 'c', 'a', 'l', 0}}, 12346,
- {{"k1", "asdf"}, {"k2", "jkl"}});
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
- EXPECT_EQ(2u, mdns_responder.registered_services().size());
-
- result = mdns_responder.DeregisterService("instance", "name", "proto");
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
- result = mdns_responder.DeregisterService("instance", "name", "proto");
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- EXPECT_EQ(1u, mdns_responder.registered_services().size());
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
- EXPECT_EQ(0u, mdns_responder.registered_services().size());
-
- result = mdns_responder.RegisterService(
- "instance2", "name", "proto",
- DomainName{{1, 'b', 5, 'l', 'o', 'c', 'a', 'l', 0}}, 12346,
- {{"k1", "asdf"}, {"k2", "jkl"}});
- EXPECT_NE(MdnsResponderErrorCode::kNoError, result);
- EXPECT_EQ(0u, mdns_responder.registered_services().size());
-}
-
-TEST(FakeMdnsResponderAdapterTest, RegisterInterfaces) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
- EXPECT_EQ(0u, mdns_responder.registered_interfaces().size());
-
- Error result = mdns_responder.RegisterInterface(InterfaceInfo{}, IPSubnet{},
- kDefaultSocket);
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(1u, mdns_responder.registered_interfaces().size());
-
- result = mdns_responder.RegisterInterface(InterfaceInfo{}, IPSubnet{},
- kDefaultSocket);
- EXPECT_FALSE(result.ok());
- EXPECT_EQ(1u, mdns_responder.registered_interfaces().size());
-
- result = mdns_responder.RegisterInterface(InterfaceInfo{}, IPSubnet{},
- kSecondSocket);
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(2u, mdns_responder.registered_interfaces().size());
-
- result = mdns_responder.DeregisterInterface(kSecondSocket);
- EXPECT_TRUE(result.ok());
- EXPECT_EQ(1u, mdns_responder.registered_interfaces().size());
- result = mdns_responder.DeregisterInterface(kSecondSocket);
- EXPECT_FALSE(result.ok());
- EXPECT_EQ(1u, mdns_responder.registered_interfaces().size());
-
- mdns_responder.Close();
- ASSERT_FALSE(mdns_responder.running());
- EXPECT_EQ(0u, mdns_responder.registered_interfaces().size());
-
- result = mdns_responder.RegisterInterface(InterfaceInfo{}, IPSubnet{},
- kDefaultSocket);
- EXPECT_FALSE(result.ok());
- EXPECT_EQ(0u, mdns_responder.registered_interfaces().size());
-}
-
-TEST(FakeMdnsResponderAdapterTest, UpdateTxtData) {
- FakeMdnsResponderAdapter mdns_responder;
-
- mdns_responder.Init();
- ASSERT_TRUE(mdns_responder.running());
-
- const std::map<std::string, std::string> txt_data1{{"k1", "asdf"},
- {"k2", "jkl"}};
- auto result = mdns_responder.RegisterService(
- "instance", "name", "proto",
- DomainName{{1, 'a', 5, 'l', 'o', 'c', 'a', 'l', 0}}, 12345, txt_data1);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
- ASSERT_EQ(1u, mdns_responder.registered_services().size());
- EXPECT_EQ(txt_data1, mdns_responder.registered_services()[0].txt_data);
-
- const std::map<std::string, std::string> txt_data2{
- {"k1", "monkey"}, {"k2", "panda"}, {"k3", "turtle"}, {"k4", "rhino"}};
- result = mdns_responder.UpdateTxtData("instance", "name", "proto", txt_data2);
- EXPECT_EQ(MdnsResponderErrorCode::kNoError, result);
- ASSERT_EQ(1u, mdns_responder.registered_services().size());
- EXPECT_EQ(txt_data2, mdns_responder.registered_services()[0].txt_data);
-}
-
-} // namespace osp
-} // namespace openscreen
diff --git a/osp/public/BUILD.gn b/osp/public/BUILD.gn
index cc915c60..3606dcd5 100644
--- a/osp/public/BUILD.gn
+++ b/osp/public/BUILD.gn
@@ -11,7 +11,6 @@ source_set("public") {
"endpoint_request_ids.cc",
"endpoint_request_ids.h",
"mdns_service_listener_factory.h",
- "mdns_service_publisher_factory.h",
"message_demuxer.h",
"network_metrics.h",
"network_service_manager.h",
@@ -35,6 +34,7 @@ source_set("public") {
"service_listener.h",
"service_publisher.cc",
"service_publisher.h",
+ "service_publisher_factory.h",
"timestamp.h",
]
diff --git a/osp/public/mdns_service_listener_factory.h b/osp/public/mdns_service_listener_factory.h
index 663d060f..fa33f54f 100644
--- a/osp/public/mdns_service_listener_factory.h
+++ b/osp/public/mdns_service_listener_factory.h
@@ -8,6 +8,7 @@
#include <memory>
#include "osp/public/service_listener.h"
+#include "util/osp_logging.h"
namespace openscreen {
@@ -25,7 +26,9 @@ class MdnsServiceListenerFactory {
static std::unique_ptr<ServiceListener> Create(
const MdnsServiceListenerConfig& config,
ServiceListener::Observer* observer,
- TaskRunner* task_runner);
+ TaskRunner* task_runner) {
+ OSP_NOTREACHED();
+ }
};
} // namespace osp
diff --git a/osp/public/network_service_manager.h b/osp/public/network_service_manager.h
index 8289e178..b1a225c4 100644
--- a/osp/public/network_service_manager.h
+++ b/osp/public/network_service_manager.h
@@ -28,7 +28,7 @@ class NetworkServiceManager final {
// be passed for services not provided by the embedder.
static NetworkServiceManager* Create(
std::unique_ptr<ServiceListener> mdns_listener,
- std::unique_ptr<ServicePublisher> mdns_publisher,
+ std::unique_ptr<ServicePublisher> service_publisher,
std::unique_ptr<ProtocolConnectionClient> connection_client,
std::unique_ptr<ProtocolConnectionServer> connection_server);
@@ -47,7 +47,7 @@ class NetworkServiceManager final {
// Returns an instance of the mDNS receiver publisher, or nullptr if not
// provided.
- ServicePublisher* GetMdnsServicePublisher();
+ ServicePublisher* GetServicePublisher();
// Returns an instance of the protocol connection client, or nullptr if not
// provided.
@@ -60,14 +60,14 @@ class NetworkServiceManager final {
private:
NetworkServiceManager(
std::unique_ptr<ServiceListener> mdns_listener,
- std::unique_ptr<ServicePublisher> mdns_publisher,
+ std::unique_ptr<ServicePublisher> service_publisher,
std::unique_ptr<ProtocolConnectionClient> connection_client,
std::unique_ptr<ProtocolConnectionServer> connection_server);
~NetworkServiceManager();
std::unique_ptr<ServiceListener> mdns_listener_;
- std::unique_ptr<ServicePublisher> mdns_publisher_;
+ std::unique_ptr<ServicePublisher> service_publisher_;
std::unique_ptr<ProtocolConnectionClient> connection_client_;
std::unique_ptr<ProtocolConnectionServer> connection_server_;
};
diff --git a/osp/public/service_info.h b/osp/public/service_info.h
index e486052c..7c95ff2e 100644
--- a/osp/public/service_info.h
+++ b/osp/public/service_info.h
@@ -14,6 +14,8 @@
namespace openscreen {
namespace osp {
+constexpr char kOpenScreenServiceName[] = "_openscreen._udp";
+
// This contains canonical information about a specific Open Screen service
// found on the network via our discovery mechanism (mDNS).
struct ServiceInfo {
diff --git a/osp/public/service_publisher.cc b/osp/public/service_publisher.cc
index 3a8e70b7..2268f2d1 100644
--- a/osp/public/service_publisher.cc
+++ b/osp/public/service_publisher.cc
@@ -7,26 +7,25 @@
namespace openscreen {
namespace osp {
-ServicePublisherError::ServicePublisherError() = default;
-ServicePublisherError::ServicePublisherError(Code error,
- const std::string& message)
- : error(error), message(message) {}
-ServicePublisherError::ServicePublisherError(
- const ServicePublisherError& other) = default;
-ServicePublisherError::~ServicePublisherError() = default;
-
-ServicePublisherError& ServicePublisherError::operator=(
- const ServicePublisherError& other) = default;
-
ServicePublisher::Metrics::Metrics() = default;
ServicePublisher::Metrics::~Metrics() = default;
ServicePublisher::Config::Config() = default;
ServicePublisher::Config::~Config() = default;
+bool ServicePublisher::Config::IsValid() const {
+ return !friendly_name.empty() && !service_instance_name.empty() &&
+ connection_server_port > 0 && !network_interfaces.empty();
+}
+
+ServicePublisher::~ServicePublisher() = default;
+
+void ServicePublisher::SetConfig(const Config& config) {
+ config_ = config;
+}
+
ServicePublisher::ServicePublisher(Observer* observer)
: state_(State::kStopped), observer_(observer) {}
-ServicePublisher::~ServicePublisher() = default;
} // namespace osp
} // namespace openscreen
diff --git a/osp/public/service_publisher.h b/osp/public/service_publisher.h
index b31f59fc..190d22df 100644
--- a/osp/public/service_publisher.h
+++ b/osp/public/service_publisher.h
@@ -10,30 +10,13 @@
#include <vector>
#include "osp/public/timestamp.h"
-#include "platform/api/network_interface.h"
+#include "platform/base/error.h"
+#include "platform/base/interface_info.h"
#include "platform/base/macros.h"
namespace openscreen {
namespace osp {
-// Used to report an error from a ServiceListener implementation.
-struct ServicePublisherError {
- // TODO(mfoltz): Add additional error types, as implementations progress.
- enum class Code {
- kNone = 0,
- };
-
- ServicePublisherError();
- ServicePublisherError(Code error, const std::string& message);
- ServicePublisherError(const ServicePublisherError& other);
- ~ServicePublisherError();
-
- ServicePublisherError& operator=(const ServicePublisherError& other);
-
- Code error;
- std::string message;
-};
-
class ServicePublisher {
public:
enum class State {
@@ -74,7 +57,7 @@ class ServicePublisher {
virtual void OnSuspended() = 0;
// Reports an error.
- virtual void OnError(ServicePublisherError) = 0;
+ virtual void OnError(Error) = 0;
// Reports metrics.
virtual void OnMetrics(Metrics) = 0;
@@ -103,15 +86,21 @@ class ServicePublisher {
// configured in the ProtocolConnectionServer.
uint16_t connection_server_port = 0;
- // A list of network interface names that the publisher should use.
+ // A list of network interfaces that the publisher should use.
// By default, all enabled Ethernet and WiFi interfaces are used.
// This configuration must be identical to the interfaces configured
// in the ScreenConnectionServer.
- std::vector<NetworkInterfaceIndex> network_interface_indices;
+ std::vector<InterfaceInfo> network_interfaces;
+
+ // Returns true if the config object is valid.
+ bool IsValid() const;
};
virtual ~ServicePublisher();
+ // Sets the service configuration for this publisher.
+ virtual void SetConfig(const Config& config);
+
// Starts publishing this service using the config object.
// Returns true if state() == kStopped and the service will be started, false
// otherwise.
@@ -139,14 +128,15 @@ class ServicePublisher {
State state() const { return state_; }
// Returns the last error reported by this publisher.
- ServicePublisherError last_error() const { return last_error_; }
+ Error last_error() const { return last_error_; }
protected:
explicit ServicePublisher(Observer* observer);
State state_;
- ServicePublisherError last_error_;
+ Error last_error_;
Observer* observer_;
+ Config config_;
OSP_DISALLOW_COPY_AND_ASSIGN(ServicePublisher);
};
diff --git a/osp/public/mdns_service_publisher_factory.h b/osp/public/service_publisher_factory.h
index 075137a7..93193d03 100644
--- a/osp/public/mdns_service_publisher_factory.h
+++ b/osp/public/service_publisher_factory.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef OSP_PUBLIC_MDNS_SERVICE_PUBLISHER_FACTORY_H_
-#define OSP_PUBLIC_MDNS_SERVICE_PUBLISHER_FACTORY_H_
+#ifndef OSP_PUBLIC_SERVICE_PUBLISHER_FACTORY_H_
+#define OSP_PUBLIC_SERVICE_PUBLISHER_FACTORY_H_
#include <memory>
@@ -15,7 +15,7 @@ class TaskRunner;
namespace osp {
-class MdnsServicePublisherFactory {
+class ServicePublisherFactory {
public:
static std::unique_ptr<ServicePublisher> Create(
const ServicePublisher::Config& config,
@@ -26,4 +26,4 @@ class MdnsServicePublisherFactory {
} // namespace osp
} // namespace openscreen
-#endif // OSP_PUBLIC_MDNS_SERVICE_PUBLISHER_FACTORY_H_
+#endif // OSP_PUBLIC_SERVICE_PUBLISHER_FACTORY_H_
diff --git a/third_party/mDNSResponder/BUILD.gn b/third_party/mDNSResponder/BUILD.gn
deleted file mode 100644
index bb0047ee..00000000
--- a/third_party/mDNSResponder/BUILD.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-config("mdnsresponder_config") {
- cflags = [ "-w" ] # Disable all warnings.
-
- cflags_c = [
- # We need to rename some linked symbols in order to avoid multiple
- # definitions.
- "-DMD5_Update=MD5_Update_mDNS",
- "-DMD5_Init=MD5_Init_mDNS",
- "-DMD5_Final=MD5_Final_mDNS",
- "-DMD5_Transform=MD5_Transform_mDNS",
- ]
-}
-
-source_set("core") {
- sources = [
- "src/mDNSCore/DNSCommon.c",
- "src/mDNSCore/DNSCommon.h",
- "src/mDNSCore/DNSDigest.c",
- "src/mDNSCore/mDNS.c",
- "src/mDNSCore/mDNSDebug.h",
- "src/mDNSCore/mDNSEmbeddedAPI.h",
- "src/mDNSCore/uDNS.c",
- "src/mDNSCore/uDNS.h",
- "src/mDNSShared/mDNSDebug.c",
- ]
-
- configs += [ ":mdnsresponder_config" ]
-
- if (is_debug) {
- defines = [ "MDNS_DEBUGMSGS=2" ]
- }
-
- include_dirs = [ "src/mDNSCore" ]
-}
diff --git a/third_party/mDNSResponder/README.chromium b/third_party/mDNSResponder/README.chromium
deleted file mode 100644
index 77469188..00000000
--- a/third_party/mDNSResponder/README.chromium
+++ /dev/null
@@ -1,10 +0,0 @@
-Name: mDNSResponder
-URL: https://github.com/jevinskie/mDNSResponder
-License: Apache License, Version 2.0
-License File: src/LICENSE
-Security Critical: no
-
-Description:
-
-Pull from Apple Bonjour's MDNS/DNS-SD implementation. Will eventually be
-replaced with our custom implementation, currently only used in osp.