1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 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
|