Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020 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 "QueryResponder.h"
19 :
20 : #include <lib/dnssd/minimal_mdns/core/QNameString.h>
21 : #include <lib/dnssd/minimal_mdns/records/Ptr.h>
22 :
23 : #include <lib/support/logging/CHIPLogging.h>
24 :
25 : namespace mdns {
26 : namespace Minimal {
27 :
28 : const QNamePart kDnsSdQueryPath[] = { "_services", "_dns-sd", "_udp", "local" };
29 :
30 40 : QueryResponderBase::QueryResponderBase(Internal::QueryResponderInfo * infos, size_t infoSizes) :
31 40 : Responder(QType::PTR, FullQName(kDnsSdQueryPath)), mResponderInfos(infos), mResponderInfoSize(infoSizes)
32 40 : {}
33 :
34 131 : void QueryResponderBase::Init()
35 : {
36 1435 : for (size_t i = 0; i < mResponderInfoSize; i++)
37 : {
38 1304 : mResponderInfos[i].Clear();
39 : }
40 :
41 131 : if (mResponderInfoSize > 0)
42 : {
43 : // reply to queries about services available
44 131 : mResponderInfos[0].responder = this;
45 : }
46 :
47 131 : if (mResponderInfoSize < 2)
48 : {
49 : // Nothing useful really
50 7 : ChipLogError(Discovery, "Query responder storage size too small");
51 : }
52 131 : }
53 :
54 306 : QueryResponderSettings QueryResponderBase::AddResponder(RecordResponder * responder)
55 : {
56 306 : if (responder == nullptr)
57 : {
58 0 : return QueryResponderSettings();
59 : }
60 306 : ChipLogDetail(Discovery, "Responding with %s", QNameString(responder->GetQName()).c_str());
61 :
62 1441 : for (size_t i = 0; i < mResponderInfoSize; i++)
63 : {
64 1341 : if (mResponderInfos[i].responder == nullptr)
65 : {
66 206 : mResponderInfos[i].Clear();
67 206 : mResponderInfos[i].responder = responder;
68 :
69 206 : return QueryResponderSettings(&mResponderInfos[i]);
70 : }
71 : }
72 100 : return QueryResponderSettings();
73 : }
74 :
75 339 : void QueryResponderBase::ResetAdditionals()
76 : {
77 :
78 3982 : for (size_t i = 0; i < mResponderInfoSize; i++)
79 : {
80 3643 : mResponderInfos[i].reportNowAsAdditional = false;
81 : }
82 339 : }
83 :
84 777 : size_t QueryResponderBase::MarkAdditional(const FullQName & qname)
85 : {
86 777 : size_t count = 0;
87 8529 : for (size_t i = 0; i < mResponderInfoSize; i++)
88 : {
89 7752 : if (mResponderInfos[i].responder == nullptr)
90 : {
91 858 : continue; // not a valid entry
92 : }
93 :
94 6894 : if (mResponderInfos[i].reportNowAsAdditional)
95 : {
96 2330 : continue; // already marked
97 : }
98 :
99 4564 : if (mResponderInfos[i].responder->GetQName() == qname)
100 : {
101 500 : mResponderInfos[i].reportNowAsAdditional = true;
102 500 : count++;
103 : }
104 : }
105 :
106 777 : return count;
107 : }
108 :
109 704 : void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it)
110 : {
111 704 : Internal::QueryResponderInfo * info = it.GetInternal();
112 :
113 704 : if (!info->alsoReportAdditionalQName)
114 : {
115 287 : return; // nothing additional to report
116 : }
117 :
118 417 : if (MarkAdditional(info->additionalQName) == 0)
119 : {
120 287 : return; // nothing additional added
121 : }
122 :
123 : // something additionally added. Iterate and re-add until no more additional items were added
124 130 : bool keepAdding = true;
125 380 : while (keepAdding)
126 : {
127 250 : keepAdding = false;
128 :
129 250 : QueryResponderRecordFilter filter;
130 250 : filter.SetIncludeAdditionalRepliesOnly(true);
131 :
132 1230 : for (auto ait = begin(&filter); ait != end(); ait++)
133 : {
134 980 : if (ait.GetInternal()->alsoReportAdditionalQName)
135 : {
136 480 : keepAdding = keepAdding || (MarkAdditional(ait.GetInternal()->additionalQName) != 0);
137 : }
138 : }
139 : }
140 : }
141 :
142 281 : void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate,
143 : const ResponseConfiguration & configuration)
144 : {
145 281 : if (!delegate->ShouldSend(*this))
146 : {
147 256 : return;
148 : }
149 :
150 : // reply to dns-sd service list request
151 278 : for (size_t i = 0; i < mResponderInfoSize; i++)
152 : {
153 253 : if (!mResponderInfos[i].reportService)
154 : {
155 214 : continue;
156 : }
157 :
158 39 : if (mResponderInfos[i].responder == nullptr)
159 : {
160 0 : continue;
161 : }
162 :
163 39 : PtrResourceRecord record(GetQName(), mResponderInfos[i].responder->GetQName());
164 39 : configuration.Adjust(record);
165 39 : delegate->AddResponse(record);
166 39 : }
167 :
168 25 : delegate->ResponsesAdded(*this);
169 : }
170 :
171 384 : void QueryResponderBase::ClearBroadcastThrottle()
172 : {
173 4572 : for (size_t i = 0; i < mResponderInfoSize; i++)
174 : {
175 4188 : mResponderInfos[i].lastMulticastTime = chip::System::Clock::kZero;
176 : }
177 384 : }
178 :
179 : } // namespace Minimal
180 : } // namespace mdns
|