3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "QueryResponder.h"
20 #include <mdns/minimal/records/Ptr.h>
22 #include <support/logging/CHIPLogging.h>
27 const QNamePart kDnsSdQueryPath[] = { "_services", "_dns-sd", "_udp", "local" };
29 QueryResponderBase::QueryResponderBase(Internal::QueryResponderInfo * infos, size_t infoSizes) :
30 Responder(QType::PTR, FullQName(kDnsSdQueryPath)), mResponderInfos(infos), mResponderInfoSize(infoSizes)
33 void QueryResponderBase::Init()
35 for (size_t i = 0; i < mResponderInfoSize; i++)
37 mResponderInfos[i].Clear();
40 if (mResponderInfoSize > 0)
42 // reply to queries about services available
43 mResponderInfos[0].responder = this;
46 if (mResponderInfoSize < 2)
48 // Nothing usefull really
49 ChipLogError(Discovery, "Query responder storage size too small");
53 QueryResponderSettings QueryResponderBase::AddResponder(Responder * responder)
55 if (responder == nullptr)
57 return QueryResponderSettings();
60 for (size_t i = 0; i < mResponderInfoSize; i++)
62 if (mResponderInfos[i].responder == nullptr)
64 mResponderInfos[i].Clear();
65 mResponderInfos[i].responder = responder;
67 return QueryResponderSettings(&mResponderInfos[i]);
70 return QueryResponderSettings();
73 void QueryResponderBase::ResetAdditionals()
76 for (size_t i = 0; i < mResponderInfoSize; i++)
78 mResponderInfos[i].reportNowAsAdditional = false;
82 size_t QueryResponderBase::MarkAdditional(const FullQName & qname)
85 for (size_t i = 0; i < mResponderInfoSize; i++)
87 if (mResponderInfos[i].responder == nullptr)
89 continue; // not a valid entry
92 if (mResponderInfos[i].reportNowAsAdditional)
94 continue; // already marked
97 if (mResponderInfos[i].responder->GetQName() == qname)
99 mResponderInfos[i].reportNowAsAdditional = true;
107 void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it)
109 Internal::QueryResponderInfo * info = it.GetInternal();
111 if (!info->alsoReportAdditionalQName)
113 return; // nothing additional to report
116 if (MarkAdditional(info->additionalQName) == 0)
118 return; // nothing additional added
121 // something additionally added. Iterate and re-add until no more additional items were added
122 bool keepAdding = true;
127 QueryResponderRecordFilter filter;
128 filter.SetIncludeAdditionalRepliesOnly(true);
130 for (auto ait = begin(&filter); ait != end(); ait++)
132 if (ait.GetInternal()->alsoReportAdditionalQName)
134 keepAdding = keepAdding || (MarkAdditional(ait.GetInternal()->additionalQName) != 0);
140 void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate)
142 ChipLogProgress(Discovery, "Replying to DNS-SD service listing request");
144 // reply to dns-sd service list request
145 for (size_t i = 0; i < mResponderInfoSize; i++)
147 if (!mResponderInfos[i].reportService)
152 if (mResponderInfos[i].responder == nullptr)
157 delegate->AddResponse(PtrResourceRecord(GetQName(), mResponderInfos[i].responder->GetQName()));
161 void QueryResponderBase::ClearBroadcastThrottle()
163 for (size_t i = 0; i < mResponderInfoSize; i++)
165 mResponderInfos[i].lastMulticastTime = 0;
169 } // namespace Minimal