1 /* 2 * Copyright (c) 2022, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * This file defines OpenThread `FrameBuilder` class. 32 */ 33 34 #ifndef FRAME_BUILDER_HPP_ 35 #define FRAME_BUILDER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include "common/error.hpp" 40 #include "common/message.hpp" 41 #include "common/type_traits.hpp" 42 43 namespace ot { 44 45 /** 46 * The `FrameBuilder` can be used to construct frame content in a given data buffer. 47 * 48 */ 49 class FrameBuilder 50 { 51 public: 52 /** 53 * This method initializes the `FrameBuilder` to use a given buffer. 54 * 55 * `FrameBuilder` MUST be initialized before its other methods are used. 56 * 57 * @param[in] aBuffer A pointer to a buffer. 58 * @param[in] aLength The data length (number of bytes in @p aBuffer). 59 * 60 */ 61 void Init(void *aBuffer, uint16_t aLength); 62 63 /** 64 * This method returns a pointer to the start of `FrameBuilder` buffer. 65 * 66 * @returns A pointer to the frame buffer. 67 * 68 */ GetBytes(void) const69 const uint8_t *GetBytes(void) const { return mBuffer; } 70 71 /** 72 * This method returns the current length of frame (number of bytes appended so far). 73 * 74 * @returns The current frame length. 75 * 76 */ GetLength(void) const77 uint16_t GetLength(void) const { return mLength; } 78 79 /** 80 * This method returns the maximum length of frame. 81 * 82 * @returns The maximum frame length (max number of bytes in the frame buffer). 83 * 84 */ GetMaxLength(void) const85 uint16_t GetMaxLength(void) const { return mMaxLength; } 86 87 /** 88 * This method indicates whether or not there are enough bytes remaining in the `FrameBuilder` buffer to append a 89 * given number of bytes. 90 * 91 * @param[in] aLength The append length. 92 * 93 * @retval TRUE There are enough remaining bytes to append @p aLength bytes. 94 * @retval FALSE There are not enough remaining bytes to append @p aLength bytes. 95 * 96 */ CanAppend(uint16_t aLength) const97 bool CanAppend(uint16_t aLength) const { return (static_cast<uint32_t>(mLength) + aLength) <= mMaxLength; } 98 99 /** 100 * This method appends an `uint8_t` value to the `FrameBuilder`. 101 * 102 * @param[in] aUint8 The `uint8_t` value to append. 103 * 104 * @retval kErrorNone Successfully appended the value. 105 * @retval kErrorNoBufs Insufficient available buffers. 106 * 107 */ 108 Error AppendUint8(uint8_t aUint8); 109 110 /** 111 * This method appends an `uint16_t` value assuming big endian encoding to the `FrameBuilder`. 112 * 113 * @param[in] aUint16 The `uint16_t` value to append. 114 * 115 * @retval kErrorNone Successfully appended the value. 116 * @retval kErrorNoBufs Insufficient available buffers. 117 * 118 */ 119 Error AppendBigEndianUint16(uint16_t aUint16); 120 121 /** 122 * This method appends an `uint32_t` value assuming big endian encoding to the `FrameBuilder`. 123 * 124 * @param[in] aUint32 The `uint32_t` value to append. 125 * 126 * @retval kErrorNone Successfully appended the value. 127 * @retval kErrorNoBufs Insufficient available buffers. 128 * 129 */ 130 Error AppendBigEndianUint32(uint32_t aUint32); 131 132 /** 133 * This method appends an `uint16_t` value assuming little endian encoding to the `FrameBuilder`. 134 * 135 * @param[in] aUint16 The `uint16_t` value to append. 136 * 137 * @retval kErrorNone Successfully appended the value. 138 * @retval kErrorNoBufs Insufficient available buffers. 139 * 140 */ 141 Error AppendLittleEndianUint16(uint16_t aUint16); 142 143 /** 144 * This method appends an `uint32_t` value assuming little endian encoding to the `FrameBuilder`. 145 * 146 * @param[in] aUint32 The `uint32_t` value to append. 147 * 148 * @retval kErrorNone Successfully appended the value. 149 * @retval kErrorNoBufs Insufficient available buffers. 150 * 151 */ 152 Error AppendLittleEndianUint32(uint32_t aUint32); 153 154 /** 155 * This method appends bytes from a given buffer to the `FrameBuilder`. 156 * 157 * @param[in] aBuffer A pointer to a data bytes to append. 158 * @param[in] aLength Number of bytes in @p aBuffer. 159 * 160 * @retval kErrorNone Successfully appended the bytes. 161 * @retval kErrorNoBufs Insufficient available buffers. 162 * 163 */ 164 Error AppendBytes(const void *aBuffer, uint16_t aLength); 165 166 /** 167 * This method appends bytes read from a given message to the `FrameBuilder`. 168 * 169 * @param[in] aMessage The message to read the bytes from. 170 * @param[in] aOffset The offset in @p aMessage to start reading the bytes from. 171 * @param[in] aLength Number of bytes to read from @p aMessage and append. 172 * 173 * @retval kErrorNone Successfully appended the bytes. 174 * @retval kErrorNoBufs Insufficient available buffers to append the requested @p aLength bytes. 175 * @retval kErrorParse Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset. 176 * 177 */ 178 Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); 179 180 /** 181 * This method appends an object to the `FrameBuilder`. 182 * 183 * @tparam ObjectType The object type to append. 184 * 185 * @param[in] aObject A reference to the object to append. 186 * 187 * @retval kErrorNone Successfully appended the object. 188 * @retval kErrorNoBufs Insufficient available buffers to append @p aObject. 189 * 190 */ Append(const ObjectType & aObject)191 template <typename ObjectType> Error Append(const ObjectType &aObject) 192 { 193 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 194 195 return AppendBytes(&aObject, sizeof(ObjectType)); 196 } 197 198 /** 199 * This method writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content. 200 * 201 * This method does not perform any bound checks. The caller MUST ensure that the given data length fits within the 202 * previously appended content. Otherwise the behavior of this method is undefined. 203 * 204 * @param[in] aOffset The offset to begin writing. 205 * @param[in] aBuffer A pointer to a data buffer to write. 206 * @param[in] aLength Number of bytes in @p aBuffer. 207 * 208 */ 209 void WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength); 210 211 /** 212 * This methods writes an object to the `FrameBuilder` at a given offset overwriting previously appended content. 213 * 214 * This method does not perform any bound checks. The caller MUST ensure the given data length fits within the 215 * previously appended content. Otherwise the behavior of this method is undefined. 216 * 217 * @tparam ObjectType The object type to write. 218 * 219 * @param[in] aOffset The offset to begin writing. 220 * @param[in] aObject A reference to the object to write. 221 * 222 */ Write(uint16_t aOffset,const ObjectType & aObject)223 template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject) 224 { 225 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 226 227 WriteBytes(aOffset, &aObject, sizeof(ObjectType)); 228 } 229 230 private: 231 uint8_t *mBuffer; 232 uint16_t mLength; 233 uint16_t mMaxLength; 234 }; 235 236 } // namespace ot 237 238 #endif // FRAME_BUILDER_HPP_ 239