aboutsummaryrefslogtreecommitdiff
path: root/osp/impl/dns_sd_publisher_client.cc
diff options
context:
space:
mode:
Diffstat (limited to 'osp/impl/dns_sd_publisher_client.cc')
-rw-r--r--osp/impl/dns_sd_publisher_client.cc131
1 files changed, 131 insertions, 0 deletions
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