Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #pragma once
19 :
20 : #include <cstdint>
21 : #include <limits>
22 : #include <optional>
23 : #include <utility>
24 :
25 : #include <inet/IPAddress.h>
26 : #include <inet/InetInterface.h>
27 : #include <inet/UDPEndPoint.h>
28 : #include <lib/core/CHIPError.h>
29 : #include <lib/core/PeerId.h>
30 : #include <lib/core/ReferenceCounted.h>
31 : #include <lib/dnssd/Constants.h>
32 : #include <lib/dnssd/Types.h>
33 : #include <lib/support/logging/CHIPLogging.h>
34 :
35 : namespace chip {
36 : namespace Dnssd {
37 :
38 : /// Node resolution data common to both operational and commissionable discovery
39 :
40 : /// Callbacks for resolving operational node resolution
41 : class OperationalResolveDelegate
42 : {
43 : public:
44 1 : virtual ~OperationalResolveDelegate() = default;
45 :
46 : /// Called within the CHIP event loop after a successful node resolution.
47 : ///
48 : /// May be called multiple times: implementations may call this once per
49 : /// received packet and MDNS packets may arrive over different interfaces
50 : /// which will make nodeData have different content.
51 : virtual void OnOperationalNodeResolved(const ResolvedNodeData & nodeData) = 0;
52 :
53 : /// Notify a final failure for a node operational resolution.
54 : ///
55 : /// Called within the chip event loop if node resolution could not be performed.
56 : /// This may be due to internal errors or timeouts.
57 : ///
58 : /// This will be called only if 'OnOperationalNodeResolved' is never called.
59 : virtual void OnOperationalNodeResolutionFailed(const PeerId & peerId, CHIP_ERROR error) = 0;
60 : };
61 :
62 : /**
63 : * Node discovery context class.
64 : *
65 : * This class enables multiple clients of the global DNS-SD resolver to start simultaneous
66 : * discovery operations.
67 : *
68 : * An object of this class is shared between a resolver client and the concrete resolver
69 : * implementation. The client is responsible for allocating the context and passing it to
70 : * the resolver when initiating a discovery operation. The resolver, in turn, is supposed to retain
71 : * the context until the operation is finished. This allows the client to release the ownership of
72 : * the context at any time without putting the resolver at risk of using a deleted object.
73 : */
74 : class DiscoveryContext : public ReferenceCounted<DiscoveryContext>
75 : {
76 : public:
77 : void SetBrowseIdentifier(intptr_t identifier) { mBrowseIdentifier.emplace(identifier); }
78 : void ClearBrowseIdentifier() { mBrowseIdentifier.reset(); }
79 : const std::optional<intptr_t> & GetBrowseIdentifier() const { return mBrowseIdentifier; }
80 :
81 9 : void SetDiscoveryDelegate(DiscoverNodeDelegate * delegate) { mDelegate = delegate; }
82 0 : void OnNodeDiscovered(const DiscoveredNodeData & nodeData)
83 : {
84 0 : if (mDelegate != nullptr)
85 : {
86 0 : mDelegate->OnNodeDiscovered(nodeData);
87 : }
88 : else
89 : {
90 0 : ChipLogError(Discovery, "Missing commissioning delegate. Data discarded");
91 : }
92 0 : }
93 :
94 : private:
95 : DiscoverNodeDelegate * mDelegate = nullptr;
96 : std::optional<intptr_t> mBrowseIdentifier;
97 : };
98 :
99 : /**
100 : * Interface for resolving CHIP DNS-SD services
101 : */
102 : class Resolver
103 : {
104 : public:
105 62 : virtual ~Resolver() {}
106 :
107 : /**
108 : * Initializes the resolver.
109 : *
110 : * The method must be called before other methods of this class.
111 : * If the resolver has already been initialized, the method exits immediately with no error.
112 : */
113 : virtual CHIP_ERROR Init(Inet::EndPointManager<Inet::UDPEndPoint> * endPointManager) = 0;
114 :
115 : /**
116 : * Returns whether the resolver has completed the initialization.
117 : *
118 : * Returns true if the resolver is ready to take node resolution and discovery requests.
119 : */
120 : virtual bool IsInitialized() = 0;
121 :
122 : /**
123 : * Shuts down the resolver if it has been initialized before.
124 : */
125 : virtual void Shutdown() = 0;
126 :
127 : /**
128 : * If nullptr is passed, the previously registered delegate is unregistered.
129 : */
130 : virtual void SetOperationalDelegate(OperationalResolveDelegate * delegate) = 0;
131 :
132 : /**
133 : * Requests resolution of the given operational node service.
134 : *
135 : * This will trigger a DNSSD query.
136 : *
137 : * When the operation succeeds or fails, and a resolver delegate has been registered,
138 : * the result of the operation is passed to the delegate's `OnOperationalNodeResolved` or
139 : * `OnOperationalNodeResolutionFailed` method, respectively.
140 : *
141 : * Multiple calls to ResolveNodeId may be coalesced by the implementation
142 : * and lead to just one call to
143 : * OnOperationalNodeResolved/OnOperationalNodeResolutionFailed, as long as
144 : * the later calls cause the underlying querying mechanism to re-query as if
145 : * there were no coalescing.
146 : *
147 : * A single call to ResolveNodeId may lead to multiple calls to
148 : * OnOperationalNodeResolved with different IP addresses.
149 : *
150 : * @see NodeIdResolutionNoLongerNeeded.
151 : */
152 : virtual CHIP_ERROR ResolveNodeId(const PeerId & peerId) = 0;
153 :
154 : /*
155 : * Notify the resolver that one of the consumers that called ResolveNodeId
156 : * successfully no longer needs the resolution result (e.g. because it got
157 : * the result via OnOperationalNodeResolved, or got an via
158 : * OnOperationalNodeResolutionFailed, or no longer cares about future
159 : * updates).
160 : *
161 : * There must be a NodeIdResolutionNoLongerNeeded call that matches every
162 : * successful ResolveNodeId call. In particular, implementations of
163 : * OnOperationalNodeResolved and OnOperationalNodeResolutionFailed must call
164 : * NodeIdResolutionNoLongerNeeded once for each prior successful call to
165 : * ResolveNodeId for the relevant PeerId that has not yet had a matching
166 : * NodeIdResolutionNoLongerNeeded call made.
167 : */
168 : virtual void NodeIdResolutionNoLongerNeeded(const PeerId & peerId) = 0;
169 :
170 : /**
171 : * Finds all nodes of given type matching the given filter.
172 : *
173 : * Whenever a new matching node is found, the node information is passed to
174 : * the `OnNodeDiscovered` method of the discovery delegate configured
175 : * in the context object.
176 : *
177 : * This method is expected to increase the reference count of the context
178 : * object for as long as it takes to complete the discovery request.
179 : */
180 : virtual CHIP_ERROR StartDiscovery(DiscoveryType type, DiscoveryFilter filter, DiscoveryContext & context) = 0;
181 :
182 : /**
183 : * Stop discovery (of all node types).
184 : *
185 : * Some back ends may not support stopping discovery, so consumers should
186 : * not assume they will stop getting callbacks after calling this.
187 : */
188 : virtual CHIP_ERROR StopDiscovery(DiscoveryContext & context) = 0;
189 :
190 : /**
191 : * Verify the validity of an address that appears to be out of date (for example
192 : * because establishing a connection to it has failed).
193 : */
194 : virtual CHIP_ERROR ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId) = 0;
195 :
196 : /**
197 : * Returns the system-wide implementation of the service resolver.
198 : *
199 : * The method returns a reference to the resolver object configured by
200 : * a user using the \c Resolver::SetInstance() method, or the default
201 : * resolver returned by the \c GetDefaultResolver() function.
202 : */
203 : static Resolver & Instance();
204 :
205 : /**
206 : * Overrides the default implementation of the service resolver
207 : */
208 : static void SetInstance(Resolver & resolver);
209 :
210 : private:
211 : static Resolver * sInstance;
212 : };
213 :
214 : /**
215 : * Returns the default implementation of the service resolver.
216 : */
217 : extern Resolver & GetDefaultResolver();
218 :
219 : } // namespace Dnssd
220 : } // namespace chip
|