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 #include <core/CHIPEncoding.h>
28 #include <support/BufferWriter.h>
30 #include <mdns/minimal/core/BytesRange.h>
31 #include <mdns/minimal/core/DnsHeader.h>
36 /// A QName part is a null-terminated string
37 using QNamePart = const char *;
39 /// A list of QNames that is simple to pass around
41 /// As the struct may be copied, the lifetime of 'names' has to extend beyond
42 /// the objects that use this struct.
45 const QNamePart * names;
48 FullQName() : names(nullptr), nameCount(0) {}
49 FullQName(const FullQName &) = default;
50 FullQName & operator=(const FullQName &) = default;
53 FullQName(const QNamePart (&data)[N]) : names(data), nameCount(N)
56 void Output(chip::Encoding::BigEndian::BufferWriter & out) const
58 for (uint16_t i = 0; i < nameCount; i++)
61 out.Put8(static_cast<uint8_t>(strlen(names[i])));
64 out.Put8(0); // end of qnames
67 bool operator==(const FullQName & other) const;
68 bool operator!=(const FullQName & other) const { return !(*this == other); }
71 /// A serialized QNAME is comprised of
72 /// - length-prefixed parts
73 /// - Ends in a 0-length item
74 /// - May contain pointers to previous data (for efficient transmission)
76 /// This class allows iterating over such parts while validating
77 /// that the parts are within a valid range
78 class SerializedQNameIterator
81 SerializedQNameIterator() : mLookBehindMax(0), mCurrentPosition(nullptr), mIsValid(false) {}
82 SerializedQNameIterator(const SerializedQNameIterator &) = default;
83 SerializedQNameIterator & operator=(const SerializedQNameIterator &) = default;
85 SerializedQNameIterator(const BytesRange validData, const uint8_t * position) :
86 mValidData(validData), mLookBehindMax(static_cast<size_t>(position - validData.Start())), mCurrentPosition(position)
89 /// Advances to the next element in the sequence
90 /// Returns true if new data was available
93 /// Find out if the data parsing is ok.
94 /// If invalid data is encountered during a [Next] call, this will
95 /// return false. Check this after Next returns false.
96 bool IsValid() const { return mIsValid; }
98 /// Valid IFF Next() returned true.
99 /// Next has to be called after construction
100 QNamePart Value() const { return mValue; }
102 /// Get the end of the sequence *without* following any
103 /// backwards pointers. Changes iterator state.
105 /// returs nullptr on error (invalid data)
106 const uint8_t * FindDataEnd();
108 bool operator==(const FullQName & other) const;
109 bool operator!=(const FullQName & other) const { return !(*this == other); }
111 void Put(chip::Encoding::BigEndian::BufferWriter & out) const
113 SerializedQNameIterator copy = *this;
117 out.Put8(static_cast<uint8_t>(strlen(copy.Value())));
118 out.Put(copy.Value());
120 out.Put8(0); // end of qnames
124 static constexpr size_t kMaxValueSize = 63;
125 static constexpr uint8_t kPtrMask = 0xC0;
127 BytesRange mValidData;
128 size_t mLookBehindMax; // avoid loops by limiting lookbehind
129 const uint8_t * mCurrentPosition;
130 bool mIsValid = true;
132 char mValue[kMaxValueSize + 1] = { 0 };
134 // Advances to the next element in the sequence
135 bool Next(bool followIndirectPointers);
138 } // namespace Minimal