1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DISCOVERY_PUBLIC_DNS_SD_SERVICE_PUBLISHER_H_
6 #define DISCOVERY_PUBLIC_DNS_SD_SERVICE_PUBLISHER_H_
7 
8 #include <string>
9 #include <utility>
10 
11 #include "discovery/dnssd/public/dns_sd_instance.h"
12 #include "discovery/dnssd/public/dns_sd_instance_endpoint.h"
13 #include "discovery/dnssd/public/dns_sd_publisher.h"
14 #include "discovery/dnssd/public/dns_sd_service.h"
15 #include "platform/base/error.h"
16 #include "util/osp_logging.h"
17 
18 namespace openscreen {
19 namespace discovery {
20 
21 // This class represents a top-level discovery API which sits on top of DNS-SD.
22 // The main purpose of this class is to hide DNS-SD internals from embedders who
23 // do not care about the specific functionality and do not need to understand
24 // DNS-SD Internals.
25 // T is the service-specific type which stores information regarding a specific
26 // service instance.
27 // NOTE: This class is not thread-safe and calls will be made to DnsSdService in
28 // the same sequence and on the same threads from which these methods are
29 // called. This is to avoid forcing design decisions on embedders who write
30 // their own implementations of the DNS-SD layer.
31 template <typename T>
32 class DnsSdServicePublisher : public DnsSdPublisher::Client {
33  public:
34   // This function type is responsible for converting from a T type to a
35   // DNS service instance (to publish to the network).
36   using ServiceInstanceConverter = std::function<DnsSdInstance(const T&)>;
37 
DnsSdServicePublisher(DnsSdService * service,std::string service_name,ServiceInstanceConverter conversion)38   DnsSdServicePublisher(DnsSdService* service,
39                         std::string service_name,
40                         ServiceInstanceConverter conversion)
41       : conversion_(conversion),
42         service_name_(std::move(service_name)),
43         publisher_(service ? service->GetPublisher() : nullptr) {
44     OSP_DCHECK(publisher_);
45   }
46 
47   ~DnsSdServicePublisher() = default;
48 
Register(const T & service)49   Error Register(const T& service) {
50     if (!service.IsValid()) {
51       return Error::Code::kParameterInvalid;
52     }
53 
54     DnsSdInstance instance = conversion_(service);
55     return publisher_->Register(instance, this);
56   }
57 
UpdateRegistration(const T & service)58   Error UpdateRegistration(const T& service) {
59     if (!service.IsValid()) {
60       return Error::Code::kParameterInvalid;
61     }
62 
63     DnsSdInstance instance = conversion_(service);
64     return publisher_->UpdateRegistration(instance);
65   }
66 
DeregisterAll()67   ErrorOr<int> DeregisterAll() {
68     return publisher_->DeregisterAll(service_name_);
69   }
70 
71  protected:
72   // DnsSdPublisher::Client overrides.
73   //
74   // Embedders who care about the instance id with which the service was
75   // published may override this method.
OnEndpointClaimed(const DnsSdInstance & requested_instance,const DnsSdInstanceEndpoint & claimed_endpoint)76   void OnEndpointClaimed(
77       const DnsSdInstance& requested_instance,
78       const DnsSdInstanceEndpoint& claimed_endpoint) override {
79     OSP_DVLOG << "Instance ID '" << claimed_endpoint.instance_id()
80               << "' claimed for requested ID '"
81               << requested_instance.instance_id() << "'";
82     OnInstanceClaimed(requested_instance.instance_id());
83   }
84 
OnInstanceClaimed(const std::string & requested_instance_id)85   virtual void OnInstanceClaimed(const std::string& requested_instance_id) {}
86 
87  private:
88   ServiceInstanceConverter conversion_;
89   std::string service_name_;
90   DnsSdPublisher* const publisher_;
91 };
92 
93 }  // namespace discovery
94 }  // namespace openscreen
95 
96 #endif  // DISCOVERY_PUBLIC_DNS_SD_SERVICE_PUBLISHER_H_
97