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 1625 : FullQName() : names(nullptr), nameCount(0) {} 49 : FullQName(const FullQName &) = default; 50 : FullQName & operator=(const FullQName &) = default; 51 : 52 : template <size_t N> 53 501 : FullQName(const QNamePart (&data)[N]) : names(data), nameCount(N) 54 501 : {} 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 6322 : SerializedQNameIterator() : mLookBehindMax(0), mCurrentPosition(nullptr), mIsValid(false) {} 71 : SerializedQNameIterator(const SerializedQNameIterator &) = default; 72 : SerializedQNameIterator & operator=(const SerializedQNameIterator &) = default; 73 : 74 8084 : SerializedQNameIterator(const BytesRange validData, const uint8_t * position) : 75 8084 : mValidData(validData), mLookBehindMax(static_cast<size_t>(position - validData.Start())), mCurrentPosition(position) 76 8084 : {} 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 45140 : bool IsValid() const { return mIsValid; } 86 : 87 : /// Valid IFF Next() returned true. 88 : /// Next has to be called after construction 89 14755 : 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 96 : bool operator!=(const SerializedQNameIterator & other) const { return !(*this == other); } 102 : 103 1535 : 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