| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "QueryResponder.h" |
| |
| #include <lib/dnssd/minimal_mdns/core/QNameString.h> |
| #include <lib/dnssd/minimal_mdns/records/Ptr.h> |
| |
| #include <lib/support/logging/CHIPLogging.h> |
| |
| namespace mdns { |
| namespace Minimal { |
| |
| const QNamePart kDnsSdQueryPath[] = { "_services", "_dns-sd", "_udp", "local" }; |
| |
| QueryResponderBase::QueryResponderBase(Internal::QueryResponderInfo * infos, size_t infoSizes) : |
| Responder(QType::PTR, FullQName(kDnsSdQueryPath)), mResponderInfos(infos), mResponderInfoSize(infoSizes) |
| {} |
| |
| void QueryResponderBase::Init() |
| { |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| mResponderInfos[i].Clear(); |
| } |
| |
| if (mResponderInfoSize > 0) |
| { |
| // reply to queries about services available |
| mResponderInfos[0].responder = this; |
| } |
| |
| if (mResponderInfoSize < 2) |
| { |
| // Nothing useful really |
| ChipLogError(Discovery, "Query responder storage size too small"); |
| } |
| } |
| |
| QueryResponderSettings QueryResponderBase::AddResponder(RecordResponder * responder) |
| { |
| if (responder == nullptr) |
| { |
| return QueryResponderSettings(); |
| } |
| ChipLogDetail(Discovery, "Responding with %s", QNameString(responder->GetQName()).c_str()); |
| |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| if (mResponderInfos[i].responder == nullptr) |
| { |
| mResponderInfos[i].Clear(); |
| mResponderInfos[i].responder = responder; |
| |
| return QueryResponderSettings(&mResponderInfos[i]); |
| } |
| } |
| return QueryResponderSettings(); |
| } |
| |
| void QueryResponderBase::ResetAdditionals() |
| { |
| |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| mResponderInfos[i].reportNowAsAdditional = false; |
| } |
| } |
| |
| size_t QueryResponderBase::MarkAdditional(const FullQName & qname) |
| { |
| size_t count = 0; |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| if (mResponderInfos[i].responder == nullptr) |
| { |
| continue; // not a valid entry |
| } |
| |
| if (mResponderInfos[i].reportNowAsAdditional) |
| { |
| continue; // already marked |
| } |
| |
| if (mResponderInfos[i].responder->GetQName() == qname) |
| { |
| mResponderInfos[i].reportNowAsAdditional = true; |
| count++; |
| } |
| } |
| |
| return count; |
| } |
| |
| void QueryResponderBase::MarkAdditionalRepliesFor(QueryResponderIterator it) |
| { |
| Internal::QueryResponderInfo * info = it.GetInternal(); |
| |
| if (!info->alsoReportAdditionalQName) |
| { |
| return; // nothing additional to report |
| } |
| |
| if (MarkAdditional(info->additionalQName) == 0) |
| { |
| return; // nothing additional added |
| } |
| |
| // something additionally added. Iterate and re-add until no more additional items were added |
| bool keepAdding = true; |
| while (keepAdding) |
| { |
| keepAdding = false; |
| |
| QueryResponderRecordFilter filter; |
| filter.SetIncludeAdditionalRepliesOnly(true); |
| |
| for (auto ait = begin(&filter); ait != end(); ait++) |
| { |
| if (ait.GetInternal()->alsoReportAdditionalQName) |
| { |
| keepAdding = keepAdding || (MarkAdditional(ait.GetInternal()->additionalQName) != 0); |
| } |
| } |
| } |
| } |
| |
| void QueryResponderBase::AddAllResponses(const chip::Inet::IPPacketInfo * source, ResponderDelegate * delegate, |
| const ResponseConfiguration & configuration) |
| { |
| // reply to dns-sd service list request |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| if (!mResponderInfos[i].reportService) |
| { |
| continue; |
| } |
| |
| if (mResponderInfos[i].responder == nullptr) |
| { |
| continue; |
| } |
| |
| PtrResourceRecord record(GetQName(), mResponderInfos[i].responder->GetQName()); |
| configuration.Adjust(record); |
| delegate->AddResponse(record); |
| } |
| } |
| |
| void QueryResponderBase::ClearBroadcastThrottle() |
| { |
| for (size_t i = 0; i < mResponderInfoSize; i++) |
| { |
| mResponderInfos[i].lastMulticastTime = chip::System::Clock::kZero; |
| } |
| } |
| |
| } // namespace Minimal |
| } // namespace mdns |