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