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 <string.h>
21 :
22 : #include <array>
23 : #include <cstddef>
24 : #include <cstdint>
25 : #include <utility>
26 :
27 : #include <lib/core/CHIPEncoding.h>
28 : #include <lib/support/BufferWriter.h>
29 :
30 : #include <lib/dnssd/minimal_mdns/core/BytesRange.h>
31 : #include <lib/dnssd/minimal_mdns/core/DnsHeader.h>
32 :
33 : namespace mdns {
34 : namespace Minimal {
35 :
36 : /// A QName part is a null-terminated string
37 : using QNamePart = const char *;
38 :
39 : /// A list of QNames that is simple to pass around
40 : ///
41 : /// As the struct may be copied, the lifetime of 'names' has to extend beyond
42 : /// the objects that use this struct.
43 : struct FullQName
44 : {
45 : const QNamePart * names;
46 : size_t nameCount;
47 :
48 1497 : FullQName() : names(nullptr), nameCount(0) {}
49 : FullQName(const FullQName &) = default;
50 : FullQName & operator=(const FullQName &) = default;
51 :
52 : template <size_t N>
53 405 : FullQName(const QNamePart (&data)[N]) : names(data), nameCount(N)
54 405 : {}
55 :
56 : bool operator==(const FullQName & other) const;
57 : bool operator!=(const FullQName & other) const { return !(*this == other); }
58 : };
59 :
60 : /// A serialized QNAME is comprised of
61 : /// - length-prefixed parts
62 : /// - Ends in a 0-length item
63 : /// - May contain pointers to previous data (for efficient transmission)
64 : ///
65 : /// This class allows iterating over such parts while validating
66 : /// that the parts are within a valid range
67 : class SerializedQNameIterator
68 : {
69 : public:
70 4586 : SerializedQNameIterator() : mLookBehindMax(0), mCurrentPosition(nullptr), mIsValid(false) {}
71 : SerializedQNameIterator(const SerializedQNameIterator &) = default;
72 : SerializedQNameIterator & operator=(const SerializedQNameIterator &) = default;
73 :
74 6832 : SerializedQNameIterator(const BytesRange validData, const uint8_t * position) :
75 6832 : mValidData(validData), mLookBehindMax(static_cast<size_t>(position - validData.Start())), mCurrentPosition(position)
76 6832 : {}
77 :
78 : /// Advances to the next element in the sequence
79 : /// Returns true if new data was available
80 : bool Next();
81 :
82 : /// Find out if the data parsing is ok.
83 : /// If invalid data is encountered during a [Next] call, this will
84 : /// return false. Check this after Next returns false.
85 40772 : bool IsValid() const { return mIsValid; }
86 :
87 : /// Valid IFF Next() returned true.
88 : /// Next has to be called after construction
89 12635 : QNamePart Value() const { return mValue; }
90 :
91 : /// Get the end of the sequence *without* following any
92 : /// backwards pointers. Changes iterator state.
93 : ///
94 : /// returs nullptr on error (invalid data)
95 : const uint8_t * FindDataEnd();
96 :
97 : bool operator==(const FullQName & other) const;
98 : bool operator!=(const FullQName & other) const { return !(*this == other); }
99 :
100 : bool operator==(const SerializedQNameIterator & other) const;
101 36 : bool operator!=(const SerializedQNameIterator & other) const { return !(*this == other); }
102 :
103 1447 : size_t OffsetInCurrentValidData() const { return static_cast<size_t>(mCurrentPosition - mValidData.Start()); }
104 :
105 : private:
106 : static constexpr size_t kMaxValueSize = 63;
107 : static constexpr uint8_t kPtrMask = 0xC0;
108 :
109 : BytesRange mValidData;
110 : size_t mLookBehindMax; // avoid loops by limiting lookbehind
111 : const uint8_t * mCurrentPosition;
112 : bool mIsValid = true;
113 :
114 : char mValue[kMaxValueSize + 1] = { 0 };
115 :
116 : // Advances to the next element in the sequence
117 : bool Next(bool followIndirectPointers);
118 : };
119 :
120 : } // namespace Minimal
121 : } // namespace mdns
|