diff options
Diffstat (limited to 'osp/impl/dns_sd_publisher_client.cc')
-rw-r--r-- | osp/impl/dns_sd_publisher_client.cc | 131 |
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 |