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/type_traits.hpp" 41 #include "mac/mac_types.hpp" 42 43 namespace ot { 44 class Message; 45 46 /** 47 * The `FrameBuilder` can be used to construct frame content in a given data buffer. 48 */ 49 class FrameBuilder 50 { 51 public: 52 /** 53 * 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 max data length (number of bytes in @p aBuffer). 59 */ 60 void Init(void *aBuffer, uint16_t aMaxLength); 61 62 /** 63 * Returns a pointer to the start of `FrameBuilder` buffer. 64 * 65 * @returns A pointer to the frame buffer. 66 */ GetBytes(void) const67 const uint8_t *GetBytes(void) const { return mBuffer; } 68 69 /** 70 * Returns the current length of frame (number of bytes appended so far). 71 * 72 * @returns The current frame length. 73 */ GetLength(void) const74 uint16_t GetLength(void) const { return mLength; } 75 76 /** 77 * Returns the maximum length of the frame. 78 * 79 * @returns The maximum frame length (max number of bytes in the frame buffer). 80 */ GetMaxLength(void) const81 uint16_t GetMaxLength(void) const { return mMaxLength; } 82 83 /** 84 * Sets the maximum length of the frame. 85 * 86 * Does not perform any checks on the new given length. The caller MUST ensure that the specified max 87 * length is valid for the frame buffer. 88 * 89 * @param[in] aLength The maximum frame length. 90 */ SetMaxLength(uint16_t aLength)91 void SetMaxLength(uint16_t aLength) { mMaxLength = aLength; } 92 93 /** 94 * Returns the remaining length (number of bytes that can be appended) in the frame. 95 * 96 * @returns The remaining length. 97 */ GetRemainingLength(void) const98 uint16_t GetRemainingLength(void) const { return mMaxLength - mLength; } 99 100 /** 101 * Indicates whether or not there are enough bytes remaining in the `FrameBuilder` buffer to append a 102 * given number of bytes. 103 * 104 * @param[in] aLength The append length. 105 * 106 * @retval TRUE There are enough remaining bytes to append @p aLength bytes. 107 * @retval FALSE There are not enough remaining bytes to append @p aLength bytes. 108 */ CanAppend(uint16_t aLength) const109 bool CanAppend(uint16_t aLength) const { return (static_cast<uint32_t>(mLength) + aLength) <= mMaxLength; } 110 111 /** 112 * Appends an `uint8_t` value to the `FrameBuilder`. 113 * 114 * @param[in] aUint8 The `uint8_t` value to append. 115 * 116 * @retval kErrorNone Successfully appended the value. 117 * @retval kErrorNoBufs Insufficient available buffers. 118 */ 119 Error AppendUint8(uint8_t aUint8); 120 121 /** 122 * Appends an `uint16_t` value assuming big endian encoding to the `FrameBuilder`. 123 * 124 * @param[in] aUint16 The `uint16_t` value to append. 125 * 126 * @retval kErrorNone Successfully appended the value. 127 * @retval kErrorNoBufs Insufficient available buffers. 128 */ 129 Error AppendBigEndianUint16(uint16_t aUint16); 130 131 /** 132 * Appends an `uint32_t` value assuming big endian encoding to the `FrameBuilder`. 133 * 134 * @param[in] aUint32 The `uint32_t` value to append. 135 * 136 * @retval kErrorNone Successfully appended the value. 137 * @retval kErrorNoBufs Insufficient available buffers. 138 */ 139 Error AppendBigEndianUint32(uint32_t aUint32); 140 141 /** 142 * Appends an `uint16_t` value assuming little endian encoding to the `FrameBuilder`. 143 * 144 * @param[in] aUint16 The `uint16_t` value to append. 145 * 146 * @retval kErrorNone Successfully appended the value. 147 * @retval kErrorNoBufs Insufficient available buffers. 148 */ 149 Error AppendLittleEndianUint16(uint16_t aUint16); 150 151 /** 152 * Appends an `uint32_t` value assuming little endian encoding to the `FrameBuilder`. 153 * 154 * @param[in] aUint32 The `uint32_t` value to append. 155 * 156 * @retval kErrorNone Successfully appended the value. 157 * @retval kErrorNoBufs Insufficient available buffers. 158 */ 159 Error AppendLittleEndianUint32(uint32_t aUint32); 160 161 /** 162 * Appends bytes from a given buffer to the `FrameBuilder`. 163 * 164 * @param[in] aBuffer A pointer to a data bytes to append. 165 * @param[in] aLength Number of bytes in @p aBuffer. 166 * 167 * @retval kErrorNone Successfully appended the bytes. 168 * @retval kErrorNoBufs Insufficient available buffers. 169 */ 170 Error AppendBytes(const void *aBuffer, uint16_t aLength); 171 172 /** 173 * Appends a given `Mac::Address` to the `FrameBuilder`. 174 * 175 * @param[in] aMacAddress A `Mac::Address` to append. 176 * 177 * @retval kErrorNone Successfully appended the address. 178 * @retval kErrorNoBufs Insufficient available buffers. 179 */ 180 Error AppendMacAddress(const Mac::Address &aMacAddress); 181 182 #if OPENTHREAD_FTD || OPENTHREAD_MTD 183 /** 184 * Appends bytes read from a given message to the `FrameBuilder`. 185 * 186 * @param[in] aMessage The message to read the bytes from. 187 * @param[in] aOffset The offset in @p aMessage to start reading the bytes from. 188 * @param[in] aLength Number of bytes to read from @p aMessage and append. 189 * 190 * @retval kErrorNone Successfully appended the bytes. 191 * @retval kErrorNoBufs Insufficient available buffers to append the requested @p aLength bytes. 192 * @retval kErrorParse Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset. 193 */ 194 Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); 195 #endif 196 197 /** 198 * Appends an object to the `FrameBuilder`. 199 * 200 * @tparam ObjectType The object type to append. 201 * 202 * @param[in] aObject A reference to the object to append. 203 * 204 * @retval kErrorNone Successfully appended the object. 205 * @retval kErrorNoBufs Insufficient available buffers to append @p aObject. 206 */ Append(const ObjectType & aObject)207 template <typename ObjectType> Error Append(const ObjectType &aObject) 208 { 209 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 210 211 return AppendBytes(&aObject, sizeof(ObjectType)); 212 } 213 214 /** 215 * Appends the given number of bytes to the `FrameBuilder`. 216 * 217 * This method reserves @p aLength bytes at the current position of the `FrameBuilder` and returns a pointer to the 218 * start of this reserved buffer if successful. The reserved bytes are left uninitialized. The caller is 219 * responsible for initializing them. 220 * 221 * @param[in] aLength The number of bytes to append. 222 * 223 * @returns A pointer to the start of the appended bytes if successful, or `nullptr` if there are not enough 224 * remaining bytes to append @p aLength bytes. 225 */ 226 void *AppendLength(uint16_t aLength); 227 228 /** 229 * Appends an object to the `FrameBuilder`. 230 * 231 * @tparam ObjectType The object type to append. 232 * 233 * This method reserves bytes in `FrameBuilder` to accommodate an `ObjectType` and returns a pointer to the 234 * appended `ObjectType`. The `ObjectType` bytes are left uninitialized. Caller is responsible to initialize them. 235 * 236 * @returns A pointer the appended `ObjectType` if successful, or `nullptr` if there are not enough remaining 237 * bytes to append an `ObjectType`. 238 */ Append(void)239 template <typename ObjectType> ObjectType *Append(void) 240 { 241 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 242 243 return static_cast<ObjectType *>(AppendLength(sizeof(ObjectType))); 244 } 245 246 /** 247 * Writes bytes in `FrameBuilder` at a given offset overwriting the previously appended content. 248 * 249 * Does not perform any bound checks. The caller MUST ensure that the given data length fits within the 250 * previously appended content. Otherwise the behavior of this method is undefined. 251 * 252 * @param[in] aOffset The offset to begin writing. 253 * @param[in] aBuffer A pointer to a data buffer to write. 254 * @param[in] aLength Number of bytes in @p aBuffer. 255 */ 256 void WriteBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength); 257 258 /** 259 * Writes an object to the `FrameBuilder` at a given offset overwriting previously appended content. 260 * 261 * Does not perform any bound checks. The caller MUST ensure the given data length fits within the 262 * previously appended content. Otherwise the behavior of this method is undefined. 263 * 264 * @tparam ObjectType The object type to write. 265 * 266 * @param[in] aOffset The offset to begin writing. 267 * @param[in] aObject A reference to the object to write. 268 */ Write(uint16_t aOffset,const ObjectType & aObject)269 template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject) 270 { 271 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 272 273 WriteBytes(aOffset, &aObject, sizeof(ObjectType)); 274 } 275 276 /** 277 * Inserts bytes in `FrameBuilder` at a given offset, moving previous content forward. 278 * 279 * The caller MUST ensure that @p aOffset is within the current frame length (from 0 up to and including 280 * `GetLength()`). Otherwise the behavior of this method is undefined. 281 * 282 * @param[in] aOffset The offset to insert bytes. 283 * @param[in] aBuffer A pointer to a data buffer to insert. 284 * @param[in] aLength Number of bytes in @p aBuffer. 285 * 286 * @retval kErrorNone Successfully inserted the bytes. 287 * @retval kErrorNoBufs Insufficient available buffers to insert the bytes. 288 */ 289 Error InsertBytes(uint16_t aOffset, const void *aBuffer, uint16_t aLength); 290 291 /** 292 * Inserts an object in `FrameBuilder` at a given offset, moving previous content forward. 293 * 294 * The caller MUST ensure that @p aOffset is within the current frame length (from 0 up to and including 295 * `GetLength()`). Otherwise the behavior of this method is undefined. 296 * 297 * @tparam ObjectType The object type to insert. 298 * 299 * @param[in] aOffset The offset to insert bytes. 300 * @param[in] aObject A reference to the object to insert. 301 * 302 * @retval kErrorNone Successfully inserted the bytes. 303 * @retval kErrorNoBufs Insufficient available buffers to insert the bytes. 304 */ Insert(uint16_t aOffset,const ObjectType & aObject)305 template <typename ObjectType> Error Insert(uint16_t aOffset, const ObjectType &aObject) 306 { 307 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); 308 309 return InsertBytes(aOffset, &aObject, sizeof(ObjectType)); 310 } 311 312 /** 313 * Removes a given number of bytes in `FrameBuilder` at a given offset, moving existing content 314 * after removed bytes backward. 315 * 316 * Does not perform any bound checks. The caller MUST ensure that the given length and offset fits 317 * within the previously appended content. Otherwise the behavior of this method is undefined. 318 * 319 * @param[in] aOffset The offset to remove bytes from. 320 * @param[in] aLength The number of bytes to remove. 321 */ 322 void RemoveBytes(uint16_t aOffset, uint16_t aLength); 323 324 private: 325 uint8_t *mBuffer; 326 uint16_t mLength; 327 uint16_t mMaxLength; 328 }; 329 330 } // namespace ot 331 332 #endif // FRAME_BUILDER_HPP_ 333