Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / mdns / minimal / core / QName.h
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 <core/CHIPEncoding.h>
28 #include <support/BufferWriter.h>
29
30 #include <mdns/minimal/core/BytesRange.h>
31 #include <mdns/minimal/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     FullQName() : names(nullptr), nameCount(0) {}
49     FullQName(const FullQName &) = default;
50     FullQName & operator=(const FullQName &) = default;
51
52     template <size_t N>
53     FullQName(const QNamePart (&data)[N]) : names(data), nameCount(N)
54     {}
55
56     void Output(chip::Encoding::BigEndian::BufferWriter & out) const
57     {
58         for (uint16_t i = 0; i < nameCount; i++)
59         {
60
61             out.Put8(static_cast<uint8_t>(strlen(names[i])));
62             out.Put(names[i]);
63         }
64         out.Put8(0); // end of qnames
65     }
66
67     bool operator==(const FullQName & other) const;
68     bool operator!=(const FullQName & other) const { return !(*this == other); }
69 };
70
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)
75 ///
76 /// This class allows iterating over such parts while validating
77 /// that the parts are within a valid range
78 class SerializedQNameIterator
79 {
80 public:
81     SerializedQNameIterator() : mLookBehindMax(0), mCurrentPosition(nullptr), mIsValid(false) {}
82     SerializedQNameIterator(const SerializedQNameIterator &) = default;
83     SerializedQNameIterator & operator=(const SerializedQNameIterator &) = default;
84
85     SerializedQNameIterator(const BytesRange validData, const uint8_t * position) :
86         mValidData(validData), mLookBehindMax(static_cast<size_t>(position - validData.Start())), mCurrentPosition(position)
87     {}
88
89     /// Advances to the next element in the sequence
90     /// Returns true if new data was available
91     bool Next();
92
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; }
97
98     /// Valid IFF Next() returned true.
99     /// Next has to be called after construction
100     QNamePart Value() const { return mValue; }
101
102     /// Get the end of the sequence *without* following any
103     /// backwards pointers. Changes iterator state.
104     ///
105     /// returs nullptr on error (invalid data)
106     const uint8_t * FindDataEnd();
107
108     bool operator==(const FullQName & other) const;
109     bool operator!=(const FullQName & other) const { return !(*this == other); }
110
111     void Put(chip::Encoding::BigEndian::BufferWriter & out) const
112     {
113         SerializedQNameIterator copy = *this;
114         while (copy.Next())
115         {
116
117             out.Put8(static_cast<uint8_t>(strlen(copy.Value())));
118             out.Put(copy.Value());
119         }
120         out.Put8(0); // end of qnames
121     }
122
123 private:
124     static constexpr size_t kMaxValueSize = 63;
125     static constexpr uint8_t kPtrMask     = 0xC0;
126
127     BytesRange mValidData;
128     size_t mLookBehindMax; // avoid loops by limiting lookbehind
129     const uint8_t * mCurrentPosition;
130     bool mIsValid = true;
131
132     char mValue[kMaxValueSize + 1] = { 0 };
133
134     // Advances to the next element in the sequence
135     bool Next(bool followIndirectPointers);
136 };
137
138 } // namespace Minimal
139 } // namespace mdns