| // Copyright 2017 The Fuchsia 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 GARNET_BIN_MDNS_SERVICE_PROBER_H_ |
| #define GARNET_BIN_MDNS_SERVICE_PROBER_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include <lib/fit/function.h> |
| |
| #include "garnet/bin/mdns/service/mdns_agent.h" |
| #include "lib/fxl/time/time_delta.h" |
| |
| namespace mdns { |
| |
| // Base class for |AddressProber| and |InstanceProber|. |
| // |
| // Probing involves repeatedly sending a probe message. The first probe message |
| // is sent after a random delta of 0 to 250ms. This prevents synchronized |
| // probing in case multiple devices are powered on simultaneously. Two more |
| // probe messages are sent at intervals of 250ms, and we'll wait up to 250ms |
| // for a response. |
| // |
| // A probe message consists of a question record asking for any type of |
| // resource matching the resource name in question. We're looking for specific |
| // records types, but the wildcard ANY type is used. The question is marked for |
| // unicast response. The message also includes our proposed record(s) in the |
| // authority section. |
| // |
| // If we see a matching response before we're done with the probe sequence, |
| // there's a conflict. If not, the probe has completed successfully. |
| class Prober : public MdnsAgent { |
| public: |
| using CompletionCallback = fit::function<void(bool)>; |
| |
| // Creates a |Prober|. |type| is the resource type for which we're probing. |
| // Use |kA| for address types (A and AAAA). |
| Prober(MdnsAgent::Host* host, DnsType type, CompletionCallback callback); |
| |
| ~Prober() override; |
| |
| // MdnsAgent overrides. |
| void Start(const std::string& host_full_name) final; |
| |
| void ReceiveResource(const DnsResource& resource, |
| MdnsResourceSection section) final; |
| |
| protected: |
| const std::string& host_full_name() { return host_full_name_; } |
| |
| // Returns the name of the resource for which we're probing. |
| virtual const std::string& ResourceName() = 0; |
| |
| // Sends the proposed resources. |
| virtual void SendProposedResources(MdnsResourceSection section) = 0; |
| |
| private: |
| static const fxl::TimeDelta kMaxProbeInterval; |
| static constexpr uint32_t kMaxProbeAttemptCount = 3; |
| |
| // Returns a time delta between 0 and |kMaxProbeInterval|. |
| fxl::TimeDelta InitialDelay(); |
| |
| // Waits for |delay| and either sends a probe message or signals success and |
| // calls |RemoveSelf|. |
| void Probe(fxl::TimeDelta delay); |
| |
| DnsType type_; |
| CompletionCallback callback_; |
| std::string host_full_name_; |
| std::shared_ptr<DnsQuestion> question_; |
| uint32_t probe_attempt_count_ = 0; |
| }; |
| |
| } // namespace mdns |
| |
| #endif // GARNET_BIN_MDNS_SERVICE_PROBER_H_ |