Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / mdns / minimal / responders / QueryResponder.cpp
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 <mdns/minimal/records/Ptr.h>
21
22 #include <support/logging/CHIPLogging.h>
23
24 namespace mdns {
25 namespace Minimal {
26
27 const QNamePart kDnsSdQueryPath[] = { "_services", "_dns-sd", "_udp", "local" };
28
29 QueryResponderBase::QueryResponderBase(Internal::QueryResponderInfo * infos, size_t infoSizes) :
30     Responder(QType::PTR, FullQName(kDnsSdQueryPath)), mResponderInfos(infos), mResponderInfoSize(infoSizes)
31 {}
32
33 void QueryResponderBase::Init()
34 {
35     for (size_t i = 0; i < mResponderInfoSize; i++)
36     {
37         mResponderInfos[i].Clear();
38     }
39
40     if (mResponderInfoSize > 0)
41     {
42         // reply to queries about services available
43         mResponderInfos[0].responder = this;
44     }
45
46     if (mResponderInfoSize < 2)
47     {
48         // Nothing usefull really
49         ChipLogError(Discovery, "Query responder storage size too small");
50     }
51 }
52
53 QueryResponderSettings QueryResponderBase::AddResponder(Responder * responder)
54 {
55     if (responder == nullptr)
56     {
57         return QueryResponderSettings();
58     }
59
60     for (size_t i = 0; i < mResponderInfoSize; i++)
61     {
62         if (mResponderInfos[i].responder == nullptr)
63         {
64             mResponderInfos[i].Clear();
65             mResponderInfos[i].responder = responder;
66
67             return QueryResponderSettings(&mResponderInfos[i]);
68         }
69     }
70     return QueryResponderSettings();
71 }
72
73 void QueryResponderBase::ResetAdditionals()
74 {
75
76     for (size_t i = 0; i < mResponderInfoSize; i++)
77     {
78         mResponderInfos[i].reportNowAsAdditional = false;
79     }
80 }
81
82 size_t QueryResponderBase::MarkAdditional(const FullQName & qname)
83 {
84     size_t count = 0;
85     for (size_t i = 0; i < mResponderInfoSize; i++)
86     {
87         if (mResponderInfos[i].responder == nullptr)
88         {
89             continue; // not a valid entry
90         }
91
92         if (mResponderInfos[i].reportNowAsAdditional)
93         {
94             continue; // already marked
95         }
96
97         if (mResponderInfos[i].responder->GetQName() == qname)
98         {
99             mResponderInfos[i].reportNowAsAdditional = true;
100             count++;
101         }
102     }
103
104     return count;
105 }
106
107 void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it)
108 {
109     Internal::QueryResponderInfo * info = it.GetInternal();
110
111     if (!info->alsoReportAdditionalQName)
112     {
113         return; // nothing additional to report
114     }
115
116     if (MarkAdditional(info->additionalQName) == 0)
117     {
118         return; // nothing additional added
119     }
120
121     // something additionally added. Iterate and re-add until no more additional items were added
122     bool keepAdding = true;
123     while (keepAdding)
124     {
125         keepAdding = false;
126
127         QueryResponderRecordFilter filter;
128         filter.SetIncludeAdditionalRepliesOnly(true);
129
130         for (auto ait = begin(&filter); ait != end(); ait++)
131         {
132             if (ait.GetInternal()->alsoReportAdditionalQName)
133             {
134                 keepAdding = keepAdding || (MarkAdditional(ait.GetInternal()->additionalQName) != 0);
135             }
136         }
137     }
138 }
139
140 void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate)
141 {
142     ChipLogProgress(Discovery, "Replying to DNS-SD service listing request");
143
144     // reply to dns-sd service list request
145     for (size_t i = 0; i < mResponderInfoSize; i++)
146     {
147         if (!mResponderInfos[i].reportService)
148         {
149             continue;
150         }
151
152         if (mResponderInfos[i].responder == nullptr)
153         {
154             continue;
155         }
156
157         delegate->AddResponse(PtrResourceRecord(GetQName(), mResponderInfos[i].responder->GetQName()));
158     }
159 }
160
161 void QueryResponderBase::ClearBroadcastThrottle()
162 {
163     for (size_t i = 0; i < mResponderInfoSize; i++)
164     {
165         mResponderInfos[i].lastMulticastTime = 0;
166     }
167 }
168
169 } // namespace Minimal
170 } // namespace mdns