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 3 : ResponseSendingState() {}
73 :
74 135 : void Reset(uint16_t messageId, const QueryData & query, const chip::Inet::IPPacketInfo * packet)
75 : {
76 135 : mMessageId = messageId;
77 135 : mQuery = &query;
78 135 : mSource = packet;
79 135 : mSendError = CHIP_NO_ERROR;
80 135 : mResourceType = ResourceType::kAnswer;
81 135 : mSentItems.ClearAll();
82 135 : }
83 :
84 35 : void SetResourceType(ResourceType resourceType) { mResourceType = resourceType; }
85 775 : ResourceType GetResourceType() const { return mResourceType; }
86 :
87 114 : CHIP_ERROR SetError(CHIP_ERROR chipError)
88 : {
89 114 : mSendError = chipError;
90 114 : return mSendError;
91 : }
92 1951 : CHIP_ERROR GetError() const { return mSendError; }
93 :
94 104 : 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 208 : const chip::Inet::IPAddress & GetSourceAddress() const { return mSource->SrcAddress; }
108 104 : chip::Inet::InterfaceId GetSourceInterfaceId() const { return mSource->Interface; }
109 :
110 469 : bool GetWasSent(ResponseItemsSent item) const { return mSentItems.Has(item); }
111 270 : 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 3 : 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 13 : 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
|