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 : #include "Resolver.h"
19 :
20 : #include <limits>
21 :
22 : #include <lib/core/CHIPConfig.h>
23 : #include <lib/dnssd/ActiveResolveAttempts.h>
24 : #include <lib/dnssd/IncrementalResolve.h>
25 : #include <lib/dnssd/MinimalMdnsServer.h>
26 : #include <lib/dnssd/ServiceNaming.h>
27 : #include <lib/dnssd/minimal_mdns/Logging.h>
28 : #include <lib/dnssd/minimal_mdns/Parser.h>
29 : #include <lib/dnssd/minimal_mdns/QueryBuilder.h>
30 : #include <lib/dnssd/minimal_mdns/RecordData.h>
31 : #include <lib/dnssd/minimal_mdns/core/FlatAllocatedQName.h>
32 : #include <lib/support/CHIPMemString.h>
33 : #include <lib/support/logging/CHIPLogging.h>
34 : #include <tracing/macros.h>
35 :
36 : // MDNS servers will receive all broadcast packets over the network.
37 : // Disable 'invalid packet' messages because the are expected and common
38 : // These logs are useful for debug only
39 : #undef MINMDNS_RESOLVER_OVERLY_VERBOSE
40 :
41 : namespace chip {
42 : namespace Dnssd {
43 : namespace {
44 :
45 : constexpr size_t kMdnsMaxPacketSize = 1024;
46 : constexpr uint16_t kMdnsPort = 5353;
47 :
48 : using namespace mdns::Minimal;
49 :
50 : /// Handles processing of minmdns packet data.
51 : ///
52 : /// Can process multiple incremental resolves based on SRV data and allows
53 : /// retrieval of pending (e.g. to ask for AAAA) and complete data items.
54 : ///
55 : class PacketParser : private ParserDelegate
56 : {
57 : public:
58 87 : PacketParser(ActiveResolveAttempts & activeResolves) : mActiveResolves(activeResolves) {}
59 :
60 : /// Goes through the given SRV records within a response packet
61 : /// and sets up data resolution
62 : void ParseSrvRecords(const BytesRange & packet);
63 :
64 : /// Goes through non-SRV records and feeds them through the initialized
65 : /// SRV record parsing.
66 : ///
67 : /// Must be called AFTER ParseSrvRecords has been called.
68 : void ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet);
69 :
70 32 : IncrementalResolver * ResolverBegin() { return mResolvers; }
71 96 : IncrementalResolver * ResolverEnd() { return mResolvers + kMinMdnsNumParallelResolvers; }
72 :
73 : private:
74 : // ParserDelegate implementation
75 : void OnHeader(ConstHeaderRef & header) override;
76 : void OnQuery(const QueryData & data) override;
77 : void OnResource(ResourceType type, const ResourceData & data) override;
78 :
79 : /// Called IFF data is of SRV type and we are in SRV initialization state
80 : ///
81 : /// Initializes a resolver with the given SRV content as long as
82 : /// inactive resolvers exist.
83 : void ParseSRVResource(const ResourceData & data);
84 :
85 : /// Called IFF parsing state is in RecordParsing
86 : ///
87 : /// Forwards the resource to all active resolvers.
88 : void ParseResource(const ResourceData & data);
89 :
90 : enum class RecordParsingState
91 : {
92 : kIdle,
93 : kSrvInitialization,
94 : kRecordParsing,
95 : };
96 :
97 : static constexpr size_t kMinMdnsNumParallelResolvers = CHIP_CONFIG_MINMDNS_MAX_PARALLEL_RESOLVES;
98 :
99 : // Individual parse set
100 : bool mIsResponse = false;
101 : Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
102 : BytesRange mPacketRange;
103 : RecordParsingState mParsingState = RecordParsingState::kIdle;
104 :
105 : // resolvers kept between parse steps
106 : ActiveResolveAttempts & mActiveResolves;
107 : IncrementalResolver mResolvers[kMinMdnsNumParallelResolvers];
108 : };
109 :
110 64 : void PacketParser::OnHeader(ConstHeaderRef & header)
111 : {
112 64 : mIsResponse = header.GetFlags().IsResponse();
113 :
114 : #ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
115 : if (header.GetFlags().IsTruncated())
116 : {
117 : // MinMdns does not cache data, so receiving piecewise data does not work
118 : ChipLogError(Discovery, "Truncated responses not supported for address resolution");
119 : }
120 : #endif
121 64 : }
122 :
123 0 : void PacketParser::OnQuery(const QueryData & data)
124 : {
125 : // Ignore queries:
126 : // - unicast answers will include the corresponding query in the answer
127 : // packet, however that is not interesting for the resolver.
128 0 : }
129 :
130 576 : void PacketParser::OnResource(ResourceType type, const ResourceData & data)
131 : {
132 576 : if (!mIsResponse)
133 : {
134 0 : return;
135 : }
136 :
137 576 : switch (mParsingState)
138 : {
139 288 : case RecordParsingState::kSrvInitialization: {
140 288 : if (data.GetType() != QType::SRV)
141 : {
142 256 : return;
143 : }
144 32 : mdns::Minimal::Logging::LogReceivedResource(data);
145 32 : ParseSRVResource(data);
146 32 : break;
147 : }
148 288 : case RecordParsingState::kRecordParsing:
149 288 : if (data.GetType() != QType::SRV)
150 : {
151 : // SRV packets logged during 'SrvInitialization' phase
152 256 : mdns::Minimal::Logging::LogReceivedResource(data);
153 : }
154 288 : ParseResource(data);
155 288 : break;
156 0 : case RecordParsingState::kIdle:
157 0 : ChipLogError(Discovery, "Illegal state: received DNSSD resource while IDLE");
158 0 : break;
159 : }
160 : }
161 :
162 288 : void PacketParser::ParseResource(const ResourceData & data)
163 : {
164 864 : for (auto & resolver : mResolvers)
165 : {
166 576 : if (resolver.IsActive())
167 : {
168 288 : CHIP_ERROR err = resolver.OnRecord(mInterfaceId, data, mPacketRange);
169 :
170 : //
171 : // CHIP_ERROR_NO_MEMORY usually gets returned when we have no more memory available to hold the
172 : // resolved data. This gets emitted fairly frequently in dense environments or when receiving records
173 : // from devices with lots of interfaces. Consequently, don't log that unless we have DNS verbosity
174 : // logging enabled.
175 : //
176 288 : if (err != CHIP_NO_ERROR)
177 : {
178 : #if !CHIP_MINMDNS_HIGH_VERBOSITY
179 0 : if (err != CHIP_ERROR_NO_MEMORY)
180 : #endif
181 0 : ChipLogError(Discovery, "DNSSD parse error: %" CHIP_ERROR_FORMAT, err.Format());
182 : }
183 : }
184 : }
185 :
186 : // Once an IP address is received, stop requesting it.
187 288 : if (data.GetType() == QType::AAAA)
188 : {
189 32 : mActiveResolves.CompleteIpResolution(data.GetName());
190 : }
191 288 : }
192 :
193 32 : void PacketParser::ParseSRVResource(const ResourceData & data)
194 : {
195 32 : SrvRecord srv;
196 32 : if (!srv.Parse(data.GetData(), mPacketRange))
197 : {
198 0 : ChipLogError(Discovery, "Packet data reporter failed to parse SRV record");
199 32 : return;
200 : }
201 :
202 96 : for (auto & resolver : mResolvers)
203 : {
204 64 : if (resolver.IsActive() && (resolver.GetRecordName() == data.GetName()))
205 : {
206 0 : ChipLogDetail(Discovery, "SRV record already actively processed.");
207 0 : return;
208 : }
209 : }
210 :
211 32 : for (auto & resolver : mResolvers)
212 : {
213 32 : if (resolver.IsActive())
214 : {
215 0 : continue;
216 : }
217 :
218 32 : CHIP_ERROR err = resolver.InitializeParsing(data.GetName(), srv);
219 32 : if (err != CHIP_NO_ERROR)
220 : {
221 : // Receiving records that we do not need to parse is normal:
222 : // MinMDNS may receive all DNSSD packets on the network, only
223 : // interested in a subset that is matter-specific
224 : #ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
225 : ChipLogError(Discovery, "Could not start SRV record processing: %" CHIP_ERROR_FORMAT, err.Format());
226 : #endif
227 : }
228 :
229 : // Done finding an inactive resolver and attempting to use it.
230 32 : return;
231 : }
232 :
233 : #if CHIP_MINMDNS_HIGH_VERBOSITY
234 : ChipLogError(Discovery, "Insufficient parsers to process all SRV entries.");
235 : #endif
236 : }
237 :
238 32 : void PacketParser::ParseSrvRecords(const BytesRange & packet)
239 : {
240 : MATTER_TRACE_SCOPE("Searching SRV Records", "PacketParser");
241 :
242 32 : mParsingState = RecordParsingState::kSrvInitialization;
243 32 : mPacketRange = packet;
244 :
245 32 : if (!ParsePacket(packet, this))
246 : {
247 0 : ChipLogError(Discovery, "DNSSD packet parsing failed (for SRV records)");
248 : }
249 :
250 32 : mParsingState = RecordParsingState::kIdle;
251 32 : }
252 :
253 32 : void PacketParser::ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet)
254 : {
255 : MATTER_TRACE_SCOPE("Searching NON-SRV Records", "PacketParser");
256 :
257 32 : mParsingState = RecordParsingState::kRecordParsing;
258 32 : mPacketRange = packet;
259 32 : mInterfaceId = interface;
260 :
261 32 : if (!ParsePacket(packet, this))
262 : {
263 0 : ChipLogError(Discovery, "DNSSD packet parsing failed (for non-srv records)");
264 : }
265 :
266 32 : mParsingState = RecordParsingState::kIdle;
267 32 : }
268 :
269 : class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
270 : {
271 : public:
272 29 : MinMdnsResolver() : mActiveResolves(&chip::System::SystemClock()), mPacketParser(mActiveResolves)
273 : {
274 29 : GlobalMinimalMdnsServer::Instance().SetResponseDelegate(this);
275 29 : }
276 29 : ~MinMdnsResolver() { SetDiscoveryContext(nullptr); }
277 :
278 : //// MdnsPacketDelegate implementation
279 : void OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override;
280 :
281 : ///// Resolver implementation
282 : CHIP_ERROR Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager) override;
283 : bool IsInitialized() override;
284 : void Shutdown() override;
285 1 : void SetOperationalDelegate(OperationalResolveDelegate * delegate) override { mOperationalDelegate = delegate; }
286 : CHIP_ERROR ResolveNodeId(const PeerId & peerId) override;
287 : void NodeIdResolutionNoLongerNeeded(const PeerId & peerId) override;
288 : CHIP_ERROR DiscoverCommissionableNodes(DiscoveryFilter filter, DiscoveryContext & context) override;
289 : CHIP_ERROR DiscoverCommissioners(DiscoveryFilter filter, DiscoveryContext & context) override;
290 : CHIP_ERROR StopDiscovery(DiscoveryContext & context) override;
291 : CHIP_ERROR ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId) override;
292 :
293 : private:
294 : OperationalResolveDelegate * mOperationalDelegate = nullptr;
295 : DiscoveryContext * mDiscoveryContext = nullptr;
296 : System::Layer * mSystemLayer = nullptr;
297 : ActiveResolveAttempts mActiveResolves;
298 : PacketParser mPacketParser;
299 :
300 : void SetDiscoveryContext(DiscoveryContext * context);
301 : void ScheduleIpAddressResolve(SerializedQNameIterator hostName);
302 :
303 : CHIP_ERROR SendAllPendingQueries();
304 : CHIP_ERROR ScheduleRetries();
305 :
306 : /// Prepare a query for the given schedule attempt
307 : CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt);
308 :
309 : /// Prepare a query for specific resolve types
310 : CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data, bool firstSend);
311 : CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data, bool firstSend);
312 : CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data, bool firstSend);
313 :
314 : /// Clear any incremental resolver that is not waiting for a AAAA address.
315 : void ExpireIncrementalResolvers();
316 : void AdvancePendingResolverStates();
317 :
318 : static void RetryCallback(System::Layer *, void * self);
319 :
320 : CHIP_ERROR BrowseNodes(DiscoveryType type, DiscoveryFilter subtype);
321 : template <typename... Args>
322 0 : mdns::Minimal::FullQName CheckAndAllocateQName(Args &&... parts)
323 : {
324 0 : size_t requiredSize = mdns::Minimal::FlatAllocatedQName::RequiredStorageSize(parts...);
325 0 : if (requiredSize > kMaxQnameSize)
326 : {
327 0 : return mdns::Minimal::FullQName();
328 : }
329 0 : return mdns::Minimal::FlatAllocatedQName::Build(qnameStorage, parts...);
330 : }
331 : static constexpr int kMaxQnameSize = 100;
332 : char qnameStorage[kMaxQnameSize];
333 : };
334 :
335 29 : void MinMdnsResolver::SetDiscoveryContext(DiscoveryContext * context)
336 : {
337 29 : if (mDiscoveryContext != nullptr)
338 : {
339 0 : mDiscoveryContext->Release();
340 : }
341 :
342 29 : if (context != nullptr)
343 : {
344 0 : context->Retain();
345 : }
346 :
347 29 : mDiscoveryContext = context;
348 29 : }
349 :
350 0 : void MinMdnsResolver::ScheduleIpAddressResolve(SerializedQNameIterator hostName)
351 : {
352 0 : HeapQName target(hostName);
353 0 : if (!target.IsOk())
354 : {
355 0 : ChipLogError(Discovery, "Memory allocation error for IP address resolution");
356 0 : return;
357 : }
358 0 : mActiveResolves.MarkPending(ActiveResolveAttempts::ScheduledAttempt::IpResolve(std::move(target)));
359 0 : }
360 :
361 32 : void MinMdnsResolver::AdvancePendingResolverStates()
362 : {
363 : MATTER_TRACE_SCOPE("Advance pending resolve states", "MinMdnsResolver");
364 :
365 96 : for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
366 : {
367 64 : if (!resolver->IsActive())
368 : {
369 32 : continue;
370 : }
371 :
372 32 : IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();
373 :
374 32 : if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
375 : {
376 0 : ScheduleIpAddressResolve(resolver->GetTargetHostName());
377 0 : continue;
378 : }
379 :
380 32 : if (missing.HasAny())
381 : {
382 : // Expect either IP missing (ask for it) or done. Anything else is not handled
383 0 : ChipLogError(Discovery, "Unexpected state: cannot advance resolver with missing information");
384 0 : resolver->ResetToInactive();
385 0 : continue;
386 : }
387 :
388 : // SUCCESS. Call the delegates
389 32 : if (resolver->IsActiveCommissionParse())
390 : {
391 : MATTER_TRACE_SCOPE("Active commissioning delegate call", "MinMdnsResolver");
392 32 : DiscoveredNodeData nodeData;
393 :
394 32 : CHIP_ERROR err = resolver->Take(nodeData);
395 32 : if (err != CHIP_NO_ERROR)
396 : {
397 0 : ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format());
398 0 : continue;
399 : }
400 :
401 : // TODO: Ideally commissioning delegates should be aware of the
402 : // node types they receive, however they are currently not
403 : // so try to help out by only calling the delegate when an
404 : // active browse exists.
405 : //
406 : // This is NOT ok and probably we should have separate comissioner
407 : // or commissionable delegates or pass in a node type argument.
408 32 : bool discoveredNodeIsRelevant = false;
409 :
410 32 : switch (resolver->GetCurrentType())
411 : {
412 0 : case IncrementalResolver::ServiceNameType::kCommissioner:
413 0 : discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionerNode);
414 0 : mActiveResolves.CompleteCommissioner(nodeData);
415 0 : break;
416 32 : case IncrementalResolver::ServiceNameType::kCommissionable:
417 32 : discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionableNode);
418 32 : mActiveResolves.CompleteCommissionable(nodeData);
419 32 : break;
420 0 : default:
421 0 : ChipLogError(Discovery, "Unexpected type for commission data parsing");
422 0 : continue;
423 : }
424 :
425 32 : if (discoveredNodeIsRelevant)
426 : {
427 0 : if (mDiscoveryContext != nullptr)
428 : {
429 0 : mDiscoveryContext->OnNodeDiscovered(nodeData);
430 : }
431 : else
432 : {
433 : #if CHIP_MINMDNS_HIGH_VERBOSITY
434 : ChipLogError(Discovery, "No delegate to report commissioning node discovery");
435 : #endif
436 : }
437 : }
438 32 : }
439 0 : else if (resolver->IsActiveOperationalParse())
440 : {
441 : MATTER_TRACE_SCOPE("Active operational delegate call", "MinMdnsResolver");
442 0 : ResolvedNodeData nodeData;
443 :
444 0 : CHIP_ERROR err = resolver->Take(nodeData);
445 0 : if (err != CHIP_NO_ERROR)
446 : {
447 0 : ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format());
448 : }
449 :
450 0 : mActiveResolves.Complete(nodeData.operationalData.peerId);
451 0 : if (mOperationalDelegate != nullptr)
452 : {
453 0 : mOperationalDelegate->OnOperationalNodeResolved(nodeData);
454 : }
455 : else
456 : {
457 : #if CHIP_MINMDNS_HIGH_VERBOSITY
458 : ChipLogError(Discovery, "No delegate to report operational node discovery");
459 : #endif
460 : }
461 0 : }
462 : else
463 : {
464 0 : ChipLogError(Discovery, "Unexpected state: record type unknown");
465 0 : resolver->ResetToInactive();
466 : }
467 : }
468 32 : }
469 :
470 32 : void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
471 : {
472 : MATTER_TRACE_SCOPE("Received MDNS Packet", "MinMdnsResolver");
473 :
474 : // Fill up any relevant data
475 32 : mPacketParser.ParseSrvRecords(data);
476 32 : mPacketParser.ParseNonSrvRecords(info->Interface, data);
477 :
478 32 : AdvancePendingResolverStates();
479 :
480 32 : ScheduleRetries();
481 32 : }
482 :
483 1 : CHIP_ERROR MinMdnsResolver::Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager)
484 : {
485 : /// Note: we do not double-check the port as we assume the APP will always use
486 : /// the same udpEndPointManager and port for mDNS.
487 1 : mSystemLayer = &udpEndPointManager->SystemLayer();
488 :
489 1 : if (GlobalMinimalMdnsServer::Server().IsListening())
490 : {
491 0 : return CHIP_NO_ERROR;
492 : }
493 :
494 1 : return GlobalMinimalMdnsServer::Instance().StartServer(udpEndPointManager, kMdnsPort);
495 : }
496 :
497 1 : bool MinMdnsResolver::IsInitialized()
498 : {
499 1 : return GlobalMinimalMdnsServer::Server().IsListening();
500 : }
501 :
502 1 : void MinMdnsResolver::Shutdown()
503 : {
504 1 : GlobalMinimalMdnsServer::Instance().ShutdownServer();
505 1 : }
506 :
507 0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data,
508 : bool firstSend)
509 : {
510 0 : mdns::Minimal::FullQName qname;
511 :
512 0 : switch (data.type)
513 : {
514 0 : case DiscoveryType::kOperational:
515 0 : qname = CheckAndAllocateQName(kOperationalServiceName, kOperationalProtocol, kLocalDomain);
516 0 : break;
517 0 : case DiscoveryType::kCommissionableNode:
518 0 : if (data.filter.type == DiscoveryFilterType::kNone)
519 : {
520 0 : qname = CheckAndAllocateQName(kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
521 : }
522 0 : else if (data.filter.type == DiscoveryFilterType::kInstanceName)
523 : {
524 0 : qname = CheckAndAllocateQName(data.filter.instanceName, kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
525 : }
526 : else
527 : {
528 : char subtypeStr[Common::kSubTypeMaxLength + 1];
529 0 : ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
530 0 : qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionableServiceName, kCommissionProtocol,
531 : kLocalDomain);
532 : }
533 0 : break;
534 0 : case DiscoveryType::kCommissionerNode:
535 0 : if (data.filter.type == DiscoveryFilterType::kNone)
536 : {
537 0 : qname = CheckAndAllocateQName(kCommissionerServiceName, kCommissionProtocol, kLocalDomain);
538 : }
539 : else
540 : {
541 : char subtypeStr[Common::kSubTypeMaxLength + 1];
542 0 : ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
543 0 : qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionerServiceName, kCommissionProtocol,
544 : kLocalDomain);
545 : }
546 0 : break;
547 0 : case DiscoveryType::kUnknown:
548 0 : break;
549 : }
550 :
551 0 : ReturnErrorCodeIf(!qname.nameCount, CHIP_ERROR_NO_MEMORY);
552 :
553 0 : mdns::Minimal::Query query(qname);
554 : query
555 0 : .SetClass(QClass::IN) //
556 0 : .SetType(QType::ANY) //
557 0 : .SetAnswerViaUnicast(firstSend) //
558 : ;
559 :
560 0 : mdns::Minimal::Logging::LogSendingQuery(query);
561 0 : builder.AddQuery(query);
562 :
563 0 : return CHIP_NO_ERROR;
564 : }
565 :
566 0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data,
567 : bool firstSend)
568 : {
569 0 : char nameBuffer[kMaxOperationalServiceNameSize] = "";
570 :
571 : // Node and fabricid are encoded in server names.
572 0 : ReturnErrorOnFailure(MakeInstanceName(nameBuffer, sizeof(nameBuffer), data.peerId));
573 :
574 0 : const char * instanceQName[] = { nameBuffer, kOperationalServiceName, kOperationalProtocol, kLocalDomain };
575 0 : Query query(instanceQName);
576 :
577 : query
578 0 : .SetClass(QClass::IN) //
579 0 : .SetType(QType::ANY) //
580 0 : .SetAnswerViaUnicast(firstSend) //
581 : ;
582 :
583 0 : mdns::Minimal::Logging::LogSendingQuery(query);
584 0 : builder.AddQuery(query);
585 :
586 0 : return CHIP_NO_ERROR;
587 : }
588 :
589 0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data,
590 : bool firstSend)
591 : {
592 :
593 0 : Query query(data.hostName.Content());
594 :
595 : query
596 0 : .SetClass(QClass::IN) //
597 0 : .SetType(QType::AAAA) //
598 0 : .SetAnswerViaUnicast(firstSend) //
599 : ;
600 :
601 0 : mdns::Minimal::Logging::LogSendingQuery(query);
602 0 : builder.AddQuery(query);
603 :
604 0 : return CHIP_NO_ERROR;
605 : }
606 :
607 0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt)
608 : {
609 0 : if (attempt.IsResolve())
610 : {
611 0 : ReturnErrorOnFailure(BuildQuery(builder, attempt.ResolveData(), attempt.firstSend));
612 : }
613 0 : else if (attempt.IsBrowse())
614 : {
615 0 : ReturnErrorOnFailure(BuildQuery(builder, attempt.BrowseData(), attempt.firstSend));
616 : }
617 0 : else if (attempt.IsIpResolve())
618 : {
619 0 : ReturnErrorOnFailure(BuildQuery(builder, attempt.IpResolveData(), attempt.firstSend));
620 : }
621 : else
622 : {
623 0 : return CHIP_ERROR_INVALID_ARGUMENT;
624 : }
625 :
626 0 : ReturnErrorCodeIf(!builder.Ok(), CHIP_ERROR_INTERNAL);
627 0 : return CHIP_NO_ERROR;
628 : }
629 :
630 0 : CHIP_ERROR MinMdnsResolver::SendAllPendingQueries()
631 : {
632 : while (true)
633 : {
634 0 : Optional<ActiveResolveAttempts::ScheduledAttempt> resolve = mActiveResolves.NextScheduled();
635 :
636 0 : if (!resolve.HasValue())
637 : {
638 0 : break;
639 : }
640 :
641 0 : System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
642 0 : ReturnErrorCodeIf(buffer.IsNull(), CHIP_ERROR_NO_MEMORY);
643 :
644 0 : QueryBuilder builder(std::move(buffer));
645 0 : builder.Header().SetMessageId(0);
646 :
647 0 : ReturnErrorOnFailure(BuildQuery(builder, resolve.Value()));
648 :
649 0 : if (resolve.Value().firstSend)
650 : {
651 0 : ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastUnicastQuery(builder.ReleasePacket(), kMdnsPort));
652 : }
653 : else
654 : {
655 0 : ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastSend(builder.ReleasePacket(), kMdnsPort));
656 : }
657 0 : }
658 :
659 0 : ExpireIncrementalResolvers();
660 :
661 0 : return ScheduleRetries();
662 : }
663 :
664 0 : void MinMdnsResolver::ExpireIncrementalResolvers()
665 : {
666 : // once all queries are sent, if any SRV cannot receive AAAA addresses, expire it
667 0 : for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
668 : {
669 0 : if (!resolver->IsActive())
670 : {
671 0 : continue;
672 : }
673 :
674 0 : IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();
675 0 : if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
676 : {
677 0 : if (mActiveResolves.IsWaitingForIpResolutionFor(resolver->GetTargetHostName()))
678 : {
679 0 : continue;
680 : }
681 : }
682 :
683 : // mark as expired: not waiting for anything
684 0 : resolver->ResetToInactive();
685 : }
686 0 : }
687 :
688 0 : CHIP_ERROR MinMdnsResolver::DiscoverCommissionableNodes(DiscoveryFilter filter, DiscoveryContext & context)
689 : {
690 : // minmdns currently supports only one discovery context at a time so override the previous context
691 0 : SetDiscoveryContext(&context);
692 :
693 0 : return BrowseNodes(DiscoveryType::kCommissionableNode, filter);
694 : }
695 :
696 0 : CHIP_ERROR MinMdnsResolver::DiscoverCommissioners(DiscoveryFilter filter, DiscoveryContext & context)
697 : {
698 : // minmdns currently supports only one discovery context at a time so override the previous context
699 0 : SetDiscoveryContext(&context);
700 :
701 0 : return BrowseNodes(DiscoveryType::kCommissionerNode, filter);
702 : }
703 :
704 0 : CHIP_ERROR MinMdnsResolver::StopDiscovery(DiscoveryContext & context)
705 : {
706 0 : SetDiscoveryContext(nullptr);
707 :
708 0 : return mActiveResolves.CompleteAllBrowses();
709 : }
710 :
711 0 : CHIP_ERROR MinMdnsResolver::ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId)
712 : {
713 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
714 : }
715 :
716 0 : CHIP_ERROR MinMdnsResolver::BrowseNodes(DiscoveryType type, DiscoveryFilter filter)
717 : {
718 0 : mActiveResolves.MarkPending(filter, type);
719 :
720 0 : return SendAllPendingQueries();
721 : }
722 :
723 0 : CHIP_ERROR MinMdnsResolver::ResolveNodeId(const PeerId & peerId)
724 : {
725 0 : mActiveResolves.MarkPending(peerId);
726 :
727 0 : return SendAllPendingQueries();
728 : }
729 :
730 0 : void MinMdnsResolver::NodeIdResolutionNoLongerNeeded(const PeerId & peerId)
731 : {
732 0 : mActiveResolves.NodeIdResolutionNoLongerNeeded(peerId);
733 0 : }
734 :
735 32 : CHIP_ERROR MinMdnsResolver::ScheduleRetries()
736 : {
737 : MATTER_TRACE_SCOPE("Schedule retries", "MinMdnsResolver");
738 :
739 32 : ReturnErrorCodeIf(mSystemLayer == nullptr, CHIP_ERROR_INCORRECT_STATE);
740 32 : mSystemLayer->CancelTimer(&RetryCallback, this);
741 :
742 32 : Optional<System::Clock::Timeout> delay = mActiveResolves.GetTimeUntilNextExpectedResponse();
743 :
744 32 : if (!delay.HasValue())
745 : {
746 32 : return CHIP_NO_ERROR;
747 : }
748 :
749 0 : return mSystemLayer->StartTimer(delay.Value(), &RetryCallback, this);
750 32 : }
751 :
752 0 : void MinMdnsResolver::RetryCallback(System::Layer *, void * self)
753 : {
754 0 : reinterpret_cast<MinMdnsResolver *>(self)->SendAllPendingQueries();
755 0 : }
756 :
757 : MinMdnsResolver gResolver;
758 :
759 : } // namespace
760 :
761 6 : Resolver & chip::Dnssd::Resolver::Instance()
762 : {
763 6 : return gResolver;
764 : }
765 :
766 : } // namespace Dnssd
767 : } // namespace chip
|