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 38 : QueryResponderBase::QueryResponderBase(Internal::QueryResponderInfo * infos, size_t infoSizes) : 31 38 : Responder(QType::PTR, FullQName(kDnsSdQueryPath)), mResponderInfos(infos), mResponderInfoSize(infoSizes) 32 38 : {} 33 : 34 132 : void QueryResponderBase::Init() 35 : { 36 1448 : for (size_t i = 0; i < mResponderInfoSize; i++) 37 : { 38 1316 : mResponderInfos[i].Clear(); 39 : } 40 : 41 132 : if (mResponderInfoSize > 0) 42 : { 43 : // reply to queries about services available 44 132 : mResponderInfos[0].responder = this; 45 : } 46 : 47 132 : if (mResponderInfoSize < 2) 48 : { 49 : // Nothing useful really 50 7 : ChipLogError(Discovery, "Query responder storage size too small"); 51 : } 52 132 : } 53 : 54 315 : QueryResponderSettings QueryResponderBase::AddResponder(RecordResponder * responder) 55 : { 56 315 : if (responder == nullptr) 57 : { 58 0 : return QueryResponderSettings(); 59 : } 60 315 : ChipLogDetail(Discovery, "Responding with %s", QNameString(responder->GetQName()).c_str()); 61 : 62 1495 : for (size_t i = 0; i < mResponderInfoSize; i++) 63 : { 64 1395 : if (mResponderInfos[i].responder == nullptr) 65 : { 66 215 : mResponderInfos[i].Clear(); 67 215 : mResponderInfos[i].responder = responder; 68 : 69 215 : return QueryResponderSettings(&mResponderInfos[i]); 70 : } 71 : } 72 100 : return QueryResponderSettings(); 73 : } 74 : 75 367 : void QueryResponderBase::ResetAdditionals() 76 : { 77 : 78 4346 : for (size_t i = 0; i < mResponderInfoSize; i++) 79 : { 80 3979 : mResponderInfos[i].reportNowAsAdditional = false; 81 : } 82 367 : } 83 : 84 825 : size_t QueryResponderBase::MarkAdditional(const FullQName & qname) 85 : { 86 825 : size_t count = 0; 87 9153 : for (size_t i = 0; i < mResponderInfoSize; i++) 88 : { 89 8328 : if (mResponderInfos[i].responder == nullptr) 90 : { 91 954 : continue; // not a valid entry 92 : } 93 : 94 7374 : if (mResponderInfos[i].reportNowAsAdditional) 95 : { 96 2486 : continue; // already marked 97 : } 98 : 99 4888 : if (mResponderInfos[i].responder->GetQName() == qname) 100 : { 101 524 : mResponderInfos[i].reportNowAsAdditional = true; 102 524 : count++; 103 : } 104 : } 105 : 106 825 : return count; 107 : } 108 : 109 762 : void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it) 110 : { 111 762 : Internal::QueryResponderInfo * info = it.GetInternal(); 112 : 113 762 : if (!info->alsoReportAdditionalQName) 114 : { 115 315 : return; // nothing additional to report 116 : } 117 : 118 447 : if (MarkAdditional(info->additionalQName) == 0) 119 : { 120 311 : return; // nothing additional added 121 : } 122 : 123 : // something additionally added. Iterate and re-add until no more additional items were added 124 136 : bool keepAdding = true; 125 398 : while (keepAdding) 126 : { 127 262 : keepAdding = false; 128 : 129 262 : QueryResponderRecordFilter filter; 130 262 : filter.SetIncludeAdditionalRepliesOnly(true); 131 : 132 1290 : for (auto ait = begin(&filter); ait != end(); ait++) 133 : { 134 1028 : if (ait.GetInternal()->alsoReportAdditionalQName) 135 : { 136 504 : keepAdding = keepAdding || (MarkAdditional(ait.GetInternal()->additionalQName) != 0); 137 : } 138 : } 139 : } 140 : } 141 : 142 309 : void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, 143 : const ResponseConfiguration & configuration) 144 : { 145 309 : if (!delegate->ShouldSend(*this)) 146 : { 147 284 : 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 426 : void QueryResponderBase::ClearBroadcastThrottle() 172 : { 173 5118 : for (size_t i = 0; i < mResponderInfoSize; i++) 174 : { 175 4692 : mResponderInfos[i].lastMulticastTime = chip::System::Clock::kZero; 176 : } 177 426 : } 178 : 179 : } // namespace Minimal 180 : } // namespace mdns