Coverage Report

Created: 2026-05-16 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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