/src/connectedhomeip/src/lib/dnssd/Resolver.h
Line | Count | Source |
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 | 0 | 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 | 0 | void SetBrowseIdentifier(intptr_t identifier) { mBrowseIdentifier.emplace(identifier); } |
78 | 0 | void ClearBrowseIdentifier() { mBrowseIdentifier.reset(); } |
79 | 0 | const std::optional<intptr_t> & GetBrowseIdentifier() const { return mBrowseIdentifier; } |
80 | | |
81 | 0 | void SetDiscoveryDelegate(DiscoverNodeDelegate * delegate) { mDelegate = delegate; } |
82 | | void OnNodeDiscovered(const DiscoveredNodeData & nodeData) |
83 | 0 | { |
84 | 0 | if (mDelegate != nullptr) |
85 | 0 | { |
86 | 0 | mDelegate->OnNodeDiscovered(nodeData); |
87 | 0 | } |
88 | 0 | else |
89 | 0 | { |
90 | 0 | ChipLogError(Discovery, "Missing commissioning delegate. Data discarded"); |
91 | 0 | } |
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 | 0 | 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 |