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 : #pragma once 19 : 20 : #include "Parser.h" 21 : #include "ResponseBuilder.h" 22 : #include "Server.h" 23 : 24 : #include <lib/dnssd/minimal_mdns/responders/QueryResponder.h> 25 : 26 : #include <system/SystemPacketBuffer.h> 27 : 28 : #if CHIP_CONFIG_MINMDNS_DYNAMIC_OPERATIONAL_RESPONDER_LIST 29 : 30 : #include <list> 31 : using QueryResponderPtrPool = std::list<mdns::Minimal::QueryResponderBase *>; 32 : #else 33 : 34 : #include <array> 35 : 36 : // Note: ptr storage is 2 + number of operational networks required, based on 37 : // the current implementation of Advertiser_ImplMinimalMdns.cpp: 38 : // - 1 for commissionable advertising 39 : // - 1 for commissioner responder 40 : // - extra for every operational advertisement 41 : using QueryResponderPtrPool = std::array<mdns::Minimal::QueryResponderBase *, CHIP_CONFIG_MAX_FABRICS + 2>; 42 : 43 : #endif 44 : 45 : namespace mdns { 46 : namespace Minimal { 47 : 48 : namespace Internal { 49 : 50 : // Flags for keeping track of items having been sent as DNSSD responses 51 : // 52 : // We rely on knowing Matter DNSSD only sends the same set of data 53 : // for some instances like A/AAAA always being the same. 54 : // 55 : enum class ResponseItemsSent : uint8_t 56 : { 57 : // DNSSD may have different servers referenced by IP addresses, 58 : // however we know the matter dnssd server name is fixed and 59 : // the same even across SRV records. 60 : kIPv4Addresses = 0x01, 61 : kIPv6Addresses = 0x02, 62 : 63 : // Boot time advertisement filters. We allow multiple of these 64 : // however we also allow filtering them out at response start 65 : kServiceListingData = 0x04, 66 : }; 67 : 68 : /// Represents the internal state for sending a currently active request 69 : class ResponseSendingState 70 : { 71 : public: 72 2 : ResponseSendingState() {} 73 : 74 149 : void Reset(uint16_t messageId, const QueryData & query, const chip::Inet::IPPacketInfo * packet) 75 : { 76 149 : mMessageId = messageId; 77 149 : mQuery = &query; 78 149 : mSource = packet; 79 149 : mSendError = CHIP_NO_ERROR; 80 149 : mResourceType = ResourceType::kAnswer; 81 149 : mSentItems.ClearAll(); 82 149 : } 83 : 84 35 : void SetResourceType(ResourceType resourceType) { mResourceType = resourceType; } 85 831 : ResourceType GetResourceType() const { return mResourceType; } 86 : 87 120 : CHIP_ERROR SetError(CHIP_ERROR chipError) 88 : { 89 120 : mSendError = chipError; 90 120 : return mSendError; 91 : } 92 2097 : CHIP_ERROR GetError() const { return mSendError; } 93 : 94 110 : uint16_t GetMessageId() const { return mMessageId; } 95 : 96 32 : const QueryData * GetQuery() const { return mQuery; } 97 : 98 : /// Check if the reply should be sent as a unicast reply 99 : bool SendUnicast() const; 100 : 101 : /// Check if the original query should be included in the reply 102 : bool IncludeQuery() const; 103 : 104 : const chip::Inet::IPPacketInfo * GetSource() const { return mSource; } 105 : 106 32 : uint16_t GetSourcePort() const { return mSource->SrcPort; } 107 220 : const chip::Inet::IPAddress & GetSourceAddress() const { return mSource->SrcAddress; } 108 110 : chip::Inet::InterfaceId GetSourceInterfaceId() const { return mSource->Interface; } 109 : 110 509 : bool GetWasSent(ResponseItemsSent item) const { return mSentItems.Has(item); } 111 296 : void MarkWasSent(ResponseItemsSent item) { mSentItems.Set(item); } 112 : 113 : private: 114 : const QueryData * mQuery = nullptr; // query being replied to 115 : const chip::Inet::IPPacketInfo * mSource = nullptr; // Where to send the reply (if unicast) 116 : uint16_t mMessageId = 0; // message id for the reply 117 : ResourceType mResourceType = ResourceType::kAnswer; // what is being sent right now 118 : CHIP_ERROR mSendError = CHIP_NO_ERROR; 119 : chip::BitFlags<ResponseItemsSent> mSentItems; 120 : }; 121 : 122 : } // namespace Internal 123 : 124 : /// Sends responses to mDNS queries. 125 : /// 126 : /// Handles processing the query via a QueryResponderBase and then sending back the reply 127 : /// using appropriate paths (unicast or multicast) via the given Server. 128 : class ResponseSender : public ResponderDelegate 129 : { 130 : public: 131 2 : ResponseSender(ServerBase * server) : mServer(server) {} 132 : 133 : CHIP_ERROR AddQueryResponder(QueryResponderBase * queryResponder); 134 : CHIP_ERROR RemoveQueryResponder(QueryResponderBase * queryResponder); 135 : bool HasQueryResponders() const; 136 : 137 : /// Send back the response to a particular query 138 : CHIP_ERROR Respond(uint16_t messageId, const QueryData & query, const chip::Inet::IPPacketInfo * querySource, 139 : const ResponseConfiguration & configuration); 140 : 141 : // Implementation of ResponderDelegate 142 : void AddResponse(const ResourceRecord & record) override; 143 : bool ShouldSend(const Responder &) const override; 144 : void ResponsesAdded(const Responder &) override; 145 : 146 16 : void SetServer(ServerBase * server) { mServer = server; } 147 : 148 : private: 149 : CHIP_ERROR FlushReply(); 150 : CHIP_ERROR PrepareNewReplyPacket(); 151 : 152 : ServerBase * mServer; 153 : QueryResponderPtrPool mResponders = {}; 154 : 155 : /// Current send state 156 : ResponseBuilder mResponseBuilder; // packet being built 157 : Internal::ResponseSendingState mSendState; // sending state 158 : }; 159 : 160 : } // namespace Minimal 161 : } // namespace mdns