3 * Copyright (c) 2020 Project CHIP Authors
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 bool QueryData::Parse(const BytesRange & validData, const uint8_t ** start)
32 // CLASS (plus a flag for unicast)
34 if (!validData.Contains(*start))
39 const uint8_t * nameEnd = nullptr;
41 SerializedQNameIterator it(validData, *start);
42 nameEnd = it.FindDataEnd();
44 if (nameEnd == nullptr)
49 if (!validData.Contains(nameEnd + 3))
54 // TODO: should there be checks for valid mType/class?
56 mType = static_cast<QType>(chip::Encoding::BigEndian::Read16(nameEnd));
58 uint16_t klass = chip::Encoding::BigEndian::Read16(nameEnd);
60 mAnswerViaUnicast = (klass & kQClassUnicastAnswerFlag) != 0;
61 mClass = static_cast<QClass>(klass & ~kQClassUnicastAnswerFlag);
62 mNameIterator = SerializedQNameIterator(validData, *start);
69 bool QueryData::Append(HeaderRef & hdr, chip::Encoding::BigEndian::BufferWriter & out) const
71 if ((hdr.GetAdditionalCount() != 0) || (hdr.GetAnswerCount() != 0) || (hdr.GetAuthorityCount() != 0))
77 out.Put16(static_cast<uint16_t>(mType));
78 out.Put16(static_cast<uint16_t>(mClass) | (mAnswerViaUnicast ? kQClassUnicastAnswerFlag : 0));
82 hdr.SetQueryCount(static_cast<uint16_t>(hdr.GetQueryCount() + 1));
88 bool ResourceData::Parse(const BytesRange & validData, const uint8_t ** start)
96 // <DATA> (RDLENGTH bytes)
97 if (!validData.Contains(*start))
102 const uint8_t * nameEnd = nullptr;
105 SerializedQNameIterator it(validData, *start);
106 nameEnd = it.FindDataEnd();
108 if (nameEnd == nullptr)
114 if (!validData.Contains(nameEnd + 9))
119 mType = static_cast<QType>(chip::Encoding::BigEndian::Read16(nameEnd));
120 mClass = static_cast<QClass>(chip::Encoding::BigEndian::Read16(nameEnd));
121 mTtl = chip::Encoding::BigEndian::Read32(nameEnd);
123 uint16_t dataLen = chip::Encoding::BigEndian::Read16(nameEnd); // resource data
125 if (!validData.Contains(nameEnd + dataLen - 1))
127 return false; // no space for RDATA
129 mData = BytesRange(nameEnd, nameEnd + dataLen);
131 mNameIterator = SerializedQNameIterator(validData, *start);
133 *start = nameEnd + dataLen;
138 bool ParsePacket(const BytesRange & packetData, ParserDelegate * delegate)
140 if (packetData.Size() < static_cast<ptrdiff_t>(HeaderRef::kSizeBytes))
145 // header is used as const, so cast is safe
146 ConstHeaderRef header(packetData.Start());
148 if (!header.GetFlags().IsValidMdns())
153 delegate->OnHeader(header);
155 const uint8_t * data = packetData.Start() + HeaderRef::kSizeBytes;
159 for (uint16_t i = 0; i < header.GetQueryCount(); i++)
161 if (!queryData.Parse(packetData, &data))
166 delegate->OnQuery(queryData);
171 ResourceData resourceData;
172 for (uint16_t i = 0; i < header.GetAnswerCount(); i++)
174 if (!resourceData.Parse(packetData, &data))
179 delegate->OnResource(ResourceType::kAnswer, resourceData);
182 for (uint16_t i = 0; i < header.GetAuthorityCount(); i++)
184 if (!resourceData.Parse(packetData, &data))
189 delegate->OnResource(ResourceType::kAuthority, resourceData);
192 for (uint16_t i = 0; i < header.GetAdditionalCount(); i++)
194 if (!resourceData.Parse(packetData, &data))
199 delegate->OnResource(ResourceType::kAdditional, resourceData);
206 } // namespace Minimal