xref: /aosp_15_r20/external/openscreen/discovery/mdns/mdns_responder.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef DISCOVERY_MDNS_MDNS_RESPONDER_H_
6*3f982cf4SFabien Sanglard #define DISCOVERY_MDNS_MDNS_RESPONDER_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <map>
9*3f982cf4SFabien Sanglard #include <memory>
10*3f982cf4SFabien Sanglard #include <vector>
11*3f982cf4SFabien Sanglard 
12*3f982cf4SFabien Sanglard #include "discovery/mdns/mdns_records.h"
13*3f982cf4SFabien Sanglard #include "platform/api/time.h"
14*3f982cf4SFabien Sanglard #include "platform/base/macros.h"
15*3f982cf4SFabien Sanglard #include "util/alarm.h"
16*3f982cf4SFabien Sanglard 
17*3f982cf4SFabien Sanglard namespace openscreen {
18*3f982cf4SFabien Sanglard 
19*3f982cf4SFabien Sanglard struct IPEndpoint;
20*3f982cf4SFabien Sanglard class TaskRunner;
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard namespace discovery {
23*3f982cf4SFabien Sanglard 
24*3f982cf4SFabien Sanglard struct Config;
25*3f982cf4SFabien Sanglard class MdnsMessage;
26*3f982cf4SFabien Sanglard class MdnsProbeManager;
27*3f982cf4SFabien Sanglard class MdnsRandom;
28*3f982cf4SFabien Sanglard class MdnsReceiver;
29*3f982cf4SFabien Sanglard class MdnsRecordChangedCallback;
30*3f982cf4SFabien Sanglard class MdnsSender;
31*3f982cf4SFabien Sanglard class MdnsQuerier;
32*3f982cf4SFabien Sanglard 
33*3f982cf4SFabien Sanglard // This class is responsible for responding to any incoming mDNS Queries
34*3f982cf4SFabien Sanglard // received via the OnMessageReceived() method. When responding, the generated
35*3f982cf4SFabien Sanglard // MdnsMessage will contain the requested record(s) in the answers section, or
36*3f982cf4SFabien Sanglard // an NSEC record to specify that the requested record was not found in the case
37*3f982cf4SFabien Sanglard // of a query with DnsType aside from ANY. In the case where records are found,
38*3f982cf4SFabien Sanglard // the additional records field may be populated with additional records, as
39*3f982cf4SFabien Sanglard // specified in RFCs 6762 and 6763.
40*3f982cf4SFabien Sanglard class MdnsResponder {
41*3f982cf4SFabien Sanglard  public:
42*3f982cf4SFabien Sanglard   // Class to handle querying for existing records.
43*3f982cf4SFabien Sanglard   class RecordHandler {
44*3f982cf4SFabien Sanglard    public:
45*3f982cf4SFabien Sanglard     virtual ~RecordHandler();
46*3f982cf4SFabien Sanglard 
47*3f982cf4SFabien Sanglard     // Returns whether this service has one or more records matching the
48*3f982cf4SFabien Sanglard     // provided name, type, and class.
49*3f982cf4SFabien Sanglard     virtual bool HasRecords(const DomainName& name,
50*3f982cf4SFabien Sanglard                             DnsType type,
51*3f982cf4SFabien Sanglard                             DnsClass clazz) = 0;
52*3f982cf4SFabien Sanglard 
53*3f982cf4SFabien Sanglard     // Returns all records owned by this service with name, type, and class
54*3f982cf4SFabien Sanglard     // matching the provided values.
55*3f982cf4SFabien Sanglard     virtual std::vector<MdnsRecord::ConstRef> GetRecords(const DomainName& name,
56*3f982cf4SFabien Sanglard                                                          DnsType type,
57*3f982cf4SFabien Sanglard                                                          DnsClass clazz) = 0;
58*3f982cf4SFabien Sanglard 
59*3f982cf4SFabien Sanglard     // Enumerates all PTR records owned by this service.
60*3f982cf4SFabien Sanglard     virtual std::vector<MdnsRecord::ConstRef> GetPtrRecords(DnsClass clazz) = 0;
61*3f982cf4SFabien Sanglard   };
62*3f982cf4SFabien Sanglard 
63*3f982cf4SFabien Sanglard   // |record_handler|, |sender|, |receiver|, |task_runner|, |random_delay|, and
64*3f982cf4SFabien Sanglard   // |config| are expected to persist for the duration of this instance's
65*3f982cf4SFabien Sanglard   // lifetime.
66*3f982cf4SFabien Sanglard   MdnsResponder(RecordHandler* record_handler,
67*3f982cf4SFabien Sanglard                 MdnsProbeManager* ownership_handler,
68*3f982cf4SFabien Sanglard                 MdnsSender* sender,
69*3f982cf4SFabien Sanglard                 MdnsReceiver* receiver,
70*3f982cf4SFabien Sanglard                 TaskRunner* task_runner,
71*3f982cf4SFabien Sanglard                 ClockNowFunctionPtr now_function,
72*3f982cf4SFabien Sanglard                 MdnsRandom* random_delay,
73*3f982cf4SFabien Sanglard                 const Config& config);
74*3f982cf4SFabien Sanglard   ~MdnsResponder();
75*3f982cf4SFabien Sanglard 
76*3f982cf4SFabien Sanglard   OSP_DISALLOW_COPY_AND_ASSIGN(MdnsResponder);
77*3f982cf4SFabien Sanglard 
78*3f982cf4SFabien Sanglard  private:
79*3f982cf4SFabien Sanglard   // Class which handles processing and responding to queries segmented into
80*3f982cf4SFabien Sanglard   // multiple messages.
81*3f982cf4SFabien Sanglard   class TruncatedQuery {
82*3f982cf4SFabien Sanglard    public:
83*3f982cf4SFabien Sanglard     // |responder| and |task_runner| are expected to persist for the duration of
84*3f982cf4SFabien Sanglard     // this instance's lifetime.
85*3f982cf4SFabien Sanglard     TruncatedQuery(MdnsResponder* responder,
86*3f982cf4SFabien Sanglard                    TaskRunner* task_runner,
87*3f982cf4SFabien Sanglard                    ClockNowFunctionPtr now_function,
88*3f982cf4SFabien Sanglard                    IPEndpoint src,
89*3f982cf4SFabien Sanglard                    const MdnsMessage& message,
90*3f982cf4SFabien Sanglard                    const Config& config);
91*3f982cf4SFabien Sanglard     TruncatedQuery(const TruncatedQuery& other) = delete;
92*3f982cf4SFabien Sanglard     TruncatedQuery(TruncatedQuery&& other) = delete;
93*3f982cf4SFabien Sanglard 
94*3f982cf4SFabien Sanglard     TruncatedQuery& operator=(const TruncatedQuery& other) = delete;
95*3f982cf4SFabien Sanglard     TruncatedQuery& operator=(TruncatedQuery&& other) = delete;
96*3f982cf4SFabien Sanglard 
97*3f982cf4SFabien Sanglard     // Sets the query associated with this instance. Must only be called if no
98*3f982cf4SFabien Sanglard     // query has already been set, here or through the ctor.
99*3f982cf4SFabien Sanglard     void SetQuery(const MdnsMessage& message);
100*3f982cf4SFabien Sanglard 
101*3f982cf4SFabien Sanglard     // Adds additional known answers.
102*3f982cf4SFabien Sanglard     void AddKnownAnswers(const std::vector<MdnsRecord>& records);
103*3f982cf4SFabien Sanglard 
104*3f982cf4SFabien Sanglard     // Responds to the stored queries.
105*3f982cf4SFabien Sanglard     void SendResponse();
106*3f982cf4SFabien Sanglard 
src()107*3f982cf4SFabien Sanglard     const IPEndpoint& src() const { return src_; }
questions()108*3f982cf4SFabien Sanglard     const std::vector<MdnsQuestion>& questions() const { return questions_; }
known_answers()109*3f982cf4SFabien Sanglard     const std::vector<MdnsRecord>& known_answers() const {
110*3f982cf4SFabien Sanglard       return known_answers_;
111*3f982cf4SFabien Sanglard     }
112*3f982cf4SFabien Sanglard 
113*3f982cf4SFabien Sanglard    private:
114*3f982cf4SFabien Sanglard     void RescheduleSend();
115*3f982cf4SFabien Sanglard 
116*3f982cf4SFabien Sanglard     // The number of messages received so far associated with this known answer
117*3f982cf4SFabien Sanglard     // query.
118*3f982cf4SFabien Sanglard     int messages_received_so_far = 0;
119*3f982cf4SFabien Sanglard 
120*3f982cf4SFabien Sanglard     const int max_allowed_messages_;
121*3f982cf4SFabien Sanglard     const int max_allowed_records_;
122*3f982cf4SFabien Sanglard     const IPEndpoint src_;
123*3f982cf4SFabien Sanglard     MdnsResponder* const responder_;
124*3f982cf4SFabien Sanglard 
125*3f982cf4SFabien Sanglard     std::vector<MdnsQuestion> questions_;
126*3f982cf4SFabien Sanglard     std::vector<MdnsRecord> known_answers_;
127*3f982cf4SFabien Sanglard     Alarm alarm_;
128*3f982cf4SFabien Sanglard   };
129*3f982cf4SFabien Sanglard 
130*3f982cf4SFabien Sanglard   // Called when a new MdnsMessage is received.
131*3f982cf4SFabien Sanglard   void OnMessageReceived(const MdnsMessage& message, const IPEndpoint& src);
132*3f982cf4SFabien Sanglard 
133*3f982cf4SFabien Sanglard   // Responds a truncated query for which all known answers have been received.
134*3f982cf4SFabien Sanglard   void RespondToTruncatedQuery(TruncatedQuery* query);
135*3f982cf4SFabien Sanglard 
136*3f982cf4SFabien Sanglard   // Processes a message associated with a multi-packet truncated query.
137*3f982cf4SFabien Sanglard   void ProcessMultiPacketTruncatedMessage(const MdnsMessage& message,
138*3f982cf4SFabien Sanglard                                           const IPEndpoint& src);
139*3f982cf4SFabien Sanglard 
140*3f982cf4SFabien Sanglard   // Processes queries provided.
141*3f982cf4SFabien Sanglard   void ProcessQueries(const IPEndpoint& src,
142*3f982cf4SFabien Sanglard                       const std::vector<MdnsQuestion>& questions,
143*3f982cf4SFabien Sanglard                       const std::vector<MdnsRecord>& known_answers);
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard   // Sends the response to the provided query.
146*3f982cf4SFabien Sanglard   void SendResponse(const MdnsQuestion& question,
147*3f982cf4SFabien Sanglard                     const std::vector<MdnsRecord>& known_answers,
148*3f982cf4SFabien Sanglard                     std::function<void(const MdnsMessage&)> send_response,
149*3f982cf4SFabien Sanglard                     bool is_exclusive_owner);
150*3f982cf4SFabien Sanglard 
151*3f982cf4SFabien Sanglard   // Set of all truncated queries received so far. Per RFC 6762 section 7.1,
152*3f982cf4SFabien Sanglard   // matching of a query with additional known answers should be done based on
153*3f982cf4SFabien Sanglard   // the source address.
154*3f982cf4SFabien Sanglard   // NOTE: unique_ptrs used because TruncatedQuery is not movable.
155*3f982cf4SFabien Sanglard   std::map<IPEndpoint, std::unique_ptr<TruncatedQuery>> truncated_queries_;
156*3f982cf4SFabien Sanglard 
157*3f982cf4SFabien Sanglard   RecordHandler* const record_handler_;
158*3f982cf4SFabien Sanglard   MdnsProbeManager* const ownership_handler_;
159*3f982cf4SFabien Sanglard   MdnsSender* const sender_;
160*3f982cf4SFabien Sanglard   MdnsReceiver* const receiver_;
161*3f982cf4SFabien Sanglard   TaskRunner* const task_runner_;
162*3f982cf4SFabien Sanglard   const ClockNowFunctionPtr now_function_;
163*3f982cf4SFabien Sanglard   MdnsRandom* const random_delay_;
164*3f982cf4SFabien Sanglard   const Config& config_;
165*3f982cf4SFabien Sanglard 
166*3f982cf4SFabien Sanglard   friend class MdnsResponderTest;
167*3f982cf4SFabien Sanglard };
168*3f982cf4SFabien Sanglard 
169*3f982cf4SFabien Sanglard }  // namespace discovery
170*3f982cf4SFabien Sanglard }  // namespace openscreen
171*3f982cf4SFabien Sanglard 
172*3f982cf4SFabien Sanglard #endif  // DISCOVERY_MDNS_MDNS_RESPONDER_H_
173