1 /* 2 * Copyright (c) 2016, 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" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /** 29 * @file 30 * This file includes definitions for an HDLC-lite encoder and decoder. 31 */ 32 33 #ifndef HDLC_HPP_ 34 #define HDLC_HPP_ 35 36 #include <stdint.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include <openthread/error.h> 41 42 #include "common/code_utils.hpp" 43 #include "common/debug.hpp" 44 #include "common/encoding.hpp" 45 46 namespace ot { 47 48 /** 49 * @namespace ot::Hdlc 50 * 51 * @brief 52 * This namespace includes definitions for the HDLC-lite encoder and decoder. 53 * 54 */ 55 namespace Hdlc { 56 57 /** 58 * This class defines a frame write pointer used by `Hdlc::Encoder` or `Hdlc::Decoder`. 59 * 60 * This class defines the minimum set of APIs used by `Encoder/Decoder` for writing an encoded/decoded frame. It is 61 * simply a wrapper over a pointer into a buffer indicating where next byte should be written. Along with a write 62 * pointer, this class stores a remaining length variable indicating number of remaining bytes that can be written into 63 * the buffer. 64 * 65 * @note This class does NOT define the underlying buffer space or how it is being managed. 66 * 67 * `Encoder` or `Decoder` users are expected to use sub-classes of this class adding the buffer space and implementing 68 * the frame buffer management scheme. 69 * 70 * Two template sub-class `FrameBuffer` and `MultiFrameBuffer` are defined which respectively allow storing a single 71 * frame or multiple frames (FIFO queue of frame) in a buffer of a given size. 72 * 73 */ 74 class FrameWritePointer 75 { 76 public: 77 /** 78 * This method indicates whether there is buffer space available to write @p aWriteLength bytes. 79 * 80 * param[in] aWriteLength Number of bytes to write. 81 * 82 * @retval TRUE Enough buffer space is available to write the requested number of bytes. 83 * @retval FALSE Insufficient buffer space to write the requested number of bytes. 84 * 85 */ CanWrite(uint16_t aWriteLength) const86 bool CanWrite(uint16_t aWriteLength) const { return (mRemainingLength >= aWriteLength); } 87 88 /** 89 * This method writes a byte into the buffer and updates the write pointer (if space is available). 90 * 91 * @retval OT_ERROR_NONE Successfully wrote the byte and updated the pointer. 92 * @retval OT_ERROR_NO_BUFS Insufficient buffer space to write the byte. 93 * 94 */ WriteByte(uint8_t aByte)95 otError WriteByte(uint8_t aByte) 96 { 97 return CanWrite(sizeof(uint8_t)) ? (*mWritePointer++ = aByte, mRemainingLength--, OT_ERROR_NONE) 98 : OT_ERROR_NO_BUFS; 99 } 100 101 /** 102 * This method undoes the last @p aUndoLength writes, removing them from frame. 103 * 104 * @note Caller should ensure that @p aUndoLength is less than or equal to the number of previously written bytes 105 * into the frame. This method does not perform any checks and its behavior is undefined if @p aUndoLength is 106 * larger than the number of bytes previously written into the frame. 107 * 108 * @param[in] aUndoLength Number of bytes to remove (number of last `WriteByte()` calls to undo). 109 * 110 */ UndoLastWrites(uint16_t aUndoLength)111 void UndoLastWrites(uint16_t aUndoLength) 112 { 113 mWritePointer -= aUndoLength; 114 mRemainingLength += aUndoLength; 115 } 116 117 protected: FrameWritePointer(void)118 FrameWritePointer(void) 119 : mWritePointer(nullptr) 120 , mRemainingLength(0) 121 { 122 } 123 124 uint8_t *mWritePointer; ///< A pointer to current write position in the buffer. 125 uint16_t mRemainingLength; ///< Number of remaining bytes available to write. 126 }; 127 128 /** 129 * This class defines a template frame buffer of a given size for storing a single frame. 130 * 131 * The template parameter `kSize` specifies the size of the buffer. 132 * 133 */ 134 template <uint16_t kSize> class FrameBuffer : public FrameWritePointer 135 { 136 public: 137 /** 138 * This constructor initializes the `FrameBuffer` object. 139 * 140 */ FrameBuffer(void)141 FrameBuffer(void) 142 : FrameWritePointer() 143 { 144 Clear(); 145 } 146 147 /** 148 * This method clears the buffer, moving the write pointer to the beginning of the buffer. 149 * 150 */ Clear(void)151 void Clear(void) 152 { 153 mWritePointer = mBuffer; 154 mRemainingLength = sizeof(mBuffer); 155 } 156 157 /** 158 * This method indicates whether the buffer is empty or contains a frame. 159 * 160 * @retval TRUE Buffer is empty 161 * @retval FALSE Buffer contains a frame 162 * 163 */ IsEmpty(void) const164 bool IsEmpty(void) const { return (mWritePointer == mBuffer); } 165 166 /** 167 * This method gets the length (number of bytes) in the frame. 168 * 169 * @returns The length (number of bytes) in the frame. 170 * 171 */ GetLength(void) const172 uint16_t GetLength(void) const { return static_cast<uint16_t>(mWritePointer - mBuffer); } 173 174 /** 175 * This method gets a pointer to start of the frame. 176 * 177 * @returns A pointer to start of the frame. 178 * 179 */ GetFrame(void)180 uint8_t *GetFrame(void) { return mBuffer; } 181 182 private: 183 uint8_t mBuffer[kSize]; 184 }; 185 186 /** 187 * This class defines a template frame buffer of a given size for storing multiple frames. 188 * 189 * The template parameter `kSize` specifies the total size of the buffer. 190 * 191 * Unlike `FrameBuffer` class where a single frame can be stored, this class is capable of saving multiple frames 192 * in a FIFO queue format. 193 * 194 */ 195 template <uint16_t kSize> class MultiFrameBuffer : public FrameWritePointer 196 { 197 public: 198 /** 199 * This constructor initializes the `MultiFrameBuffer` object. 200 * 201 */ MultiFrameBuffer(void)202 MultiFrameBuffer(void) 203 : FrameWritePointer() 204 { 205 Clear(); 206 } 207 208 /** 209 * This method clears the buffer, removing current frame and all previously saved frames. 210 * 211 * It moves the write pointer to the beginning of the buffer. 212 * 213 */ Clear(void)214 void Clear(void) 215 { 216 mWriteFrameStart = mBuffer; 217 mWritePointer = mBuffer + kHeaderSize; 218 mRemainingLength = kSize - kHeaderSize; 219 220 IgnoreError(SetSkipLength(0)); 221 } 222 223 /** 224 * This method indicates whether the current frame (being written) is empty or not. 225 * 226 * @retval TRUE Current frame is empty. 227 * @retval FALSE Current frame is not empty. 228 * 229 */ HasFrame(void) const230 bool HasFrame(void) const { return (mWritePointer != GetFrame()); } 231 232 /** 233 * This method sets the length (number of bytes) of the current frame being written. 234 * 235 * param[in] aLength The length of current frame. 236 * 237 * @retval OT_ERROR_NONE Successfully set the length of the current frame. 238 * @retval OT_ERROR_NO_BUFS Insufficient buffer space to hold a frame of length @p aLength. 239 * 240 */ SetLength(uint16_t aLength)241 otError SetLength(uint16_t aLength) 242 { 243 otError error = OT_ERROR_NO_BUFS; 244 245 if (GetFrame() + aLength <= OT_ARRAY_END(mBuffer)) 246 { 247 mWritePointer = GetFrame() + aLength; 248 mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer); 249 error = OT_ERROR_NONE; 250 } 251 252 return error; 253 } 254 255 /** 256 * This method gets the length (number of bytes) in the current frame being written into the buffer. 257 * 258 * @returns The length (number of bytes) in the frame. 259 * 260 */ GetLength(void) const261 uint16_t GetLength(void) const { return static_cast<uint16_t>(mWritePointer - GetFrame()); } 262 263 /** 264 * This method sets the length (number of bytes) of reserved buffer in front of the current frame being written. 265 * 266 * param[in] aSkipLength The length of reserved buffer. 267 * 268 * @retval OT_ERROR_NONE Successfully set the length of reserved buffer. 269 * @retval OT_ERROR_NO_BUFS Insufficient buffer space to hold a reserved buffer of length @p aLength. 270 * 271 */ SetSkipLength(uint16_t aSkipLength)272 otError SetSkipLength(uint16_t aSkipLength) 273 { 274 otError error = OT_ERROR_NO_BUFS; 275 276 if (mWriteFrameStart + kHeaderSize + aSkipLength <= OT_ARRAY_END(mBuffer)) 277 { 278 Encoding::LittleEndian::WriteUint16(aSkipLength, mWriteFrameStart + kHeaderSkipLengthOffset); 279 mWritePointer = GetFrame(); 280 mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer); 281 error = OT_ERROR_NONE; 282 } 283 284 return error; 285 } 286 287 /** 288 * This method gets the length (number of bytes) of reserved buffer in front of the current frame being written. 289 * 290 * @returns The length (number of bytes) of the reserved buffer. 291 * 292 */ GetSkipLength(void) const293 uint16_t GetSkipLength(void) const 294 { 295 return Encoding::LittleEndian::ReadUint16(mWriteFrameStart + kHeaderSkipLengthOffset); 296 } 297 298 /** 299 * This method gets a pointer to the start of the current frame. 300 * 301 * @returns A pointer to the start of the frame. 302 * 303 */ GetFrame(void) const304 uint8_t *GetFrame(void) const { return mWriteFrameStart + kHeaderSize + GetSkipLength(); } 305 306 /** 307 * This method gets the maximum length of the current frame. 308 * 309 * @returns The maximum length of the current frame. 310 * 311 */ GetFrameMaxLength(void) const312 uint16_t GetFrameMaxLength(void) const { return static_cast<uint16_t>(mBuffer + kSize - GetFrame()); } 313 314 /** 315 * This method saves the current frame and prepares the write pointer for a next frame to be written into the 316 * buffer. 317 * 318 * Saved frame can be retrieved later using `GetNextSavedFrame()`. 319 * 320 */ SaveFrame(void)321 void SaveFrame(void) 322 { 323 Encoding::LittleEndian::WriteUint16(GetSkipLength() + GetLength(), mWriteFrameStart + kHeaderTotalLengthOffset); 324 mWriteFrameStart = mWritePointer; 325 IgnoreError(SetSkipLength(0)); 326 mWritePointer = GetFrame(); 327 mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer); 328 } 329 330 /** 331 * This method discards the current frame and prepares the write pointer for a next frame to be written into the 332 * buffer. 333 * 334 */ DiscardFrame(void)335 void DiscardFrame(void) 336 { 337 IgnoreError(SetSkipLength(0)); 338 339 mWritePointer = GetFrame(); 340 mRemainingLength = static_cast<uint16_t>(mBuffer + kSize - mWritePointer); 341 } 342 343 /** 344 * This method indicates whether there are any saved frames in the buffer. 345 * 346 * @retval TRUE There is at least one saved frame in the buffer. 347 * @retval FALSE There is no saved frame in the buffer. 348 * 349 */ HasSavedFrame(void) const350 bool HasSavedFrame(void) const { return (mWriteFrameStart != mBuffer); } 351 352 /** 353 * This method iterates through previously saved frames in the buffer, getting a next frame in the queue. 354 * 355 * @param[inout] aFrame On entry, should point to a previous saved frame or nullptr to get the first frame. 356 * On exit, the pointer variable is updated to next frame or set to nullptr if there are 357 * none. 358 * @param[inout] aLength On entry, should be a reference to the frame length of the previous saved frame. 359 * On exit, the reference is updated to the frame length (number of bytes) of next frame. 360 * 361 * @retval OT_ERROR_NONE Updated @aFrame and @aLength successfully with the next saved frame. 362 * @retval OT_ERROR_NOT_FOUND No more saved frame in the buffer. 363 * 364 */ GetNextSavedFrame(uint8_t * & aFrame,uint16_t & aLength)365 otError GetNextSavedFrame(uint8_t *&aFrame, uint16_t &aLength) 366 { 367 otError error = OT_ERROR_NONE; 368 369 OT_ASSERT(aFrame == nullptr || (mBuffer <= aFrame && aFrame < OT_ARRAY_END(mBuffer))); 370 371 aFrame = (aFrame == nullptr) ? mBuffer : aFrame + aLength; 372 373 if (aFrame != mWriteFrameStart) 374 { 375 uint16_t totalLength = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderTotalLengthOffset); 376 uint16_t skipLength = Encoding::LittleEndian::ReadUint16(aFrame + kHeaderSkipLengthOffset); 377 378 aLength = totalLength - skipLength; 379 aFrame += kHeaderSize + skipLength; 380 } 381 else 382 { 383 aLength = 0; 384 aFrame = nullptr; 385 error = OT_ERROR_NOT_FOUND; 386 } 387 388 return error; 389 } 390 391 /** 392 * This method clears all saved frames from the buffer and adjusts all the pointers. 393 * 394 * @note This method moves the pointers into the buffer and also copies the content. Any previously retrieved 395 * pointer to buffer (from `GetFrame()` or `GetNextSavedFrame()`) should be considered invalid after calling this 396 * method. 397 * 398 */ ClearSavedFrames(void)399 void ClearSavedFrames(void) 400 { 401 uint16_t len = static_cast<uint16_t>(mWriteFrameStart - mBuffer); 402 403 if (len > 0) 404 { 405 memmove(mBuffer, mWriteFrameStart, static_cast<uint16_t>(mWritePointer - mWriteFrameStart)); 406 mWritePointer -= len; 407 mWriteFrameStart -= len; 408 mRemainingLength += len; 409 } 410 } 411 412 private: 413 /* 414 * The diagram below illustrates the format of a saved frame. 415 * 416 * +---------+-------------+------------+----------------+----------------------------+ 417 * | Octets: | 2 | 2 | SkipLength | TotalLength - SkipLength | 418 * +---------+-------------+------------+----------------+----------------------------+ 419 * | Fields: | TotalLength | SkipLength | ReservedBuffer | FrameBuffer | 420 * +---------+-------------+------------+----------------+----------------------------+ 421 * 422 * - "TotalLength" : The total length of the `ReservedBuffer` and `FrameBuffer`. It is stored in header bytes 423 * as a `uint16_t` value using little-endian encoding. 424 * - "SkipLength" : The length of the `ReservedBuffer`. It is stored in header bytes as a `uint16_t` value 425 * using little-endian encoding. 426 * - "ReservedBuffer": A reserved buffer in front of `FrameBuffer`. User can use it to store extra header, etc. 427 * - "FrameBuffer" : Frame buffer. 428 * 429 * The diagram below illustrates how the frames are saved in the buffer. 430 * 431 * The diagram shows `mBuffer` and different pointers into the buffer. It represents buffer state when there are 432 * two saved frames in the buffer. 433 * 434 * Saved frame #1 Saved frame #2 Current frame being written 435 * / \ / \ / \ 436 * +-----------+-------------+-----------+------------+---------+--------------------------------------------+ 437 * | header #1 | ... | header #2 | ... | header | ... | ... | 438 * +-----------+-------------+-----------+------------+---------+--------------------------------------------+ 439 * ^ ^ ^\ /^ 440 * | | | mRemainingLength | 441 * mBuffer[0] mWriteFrameStart | | 442 * | mBuffer[kSize] 443 * mWritePointer 444 */ 445 446 enum 447 { 448 kHeaderTotalLengthOffset = 0, 449 kHeaderSkipLengthOffset = sizeof(uint16_t), 450 kHeaderSize = sizeof(uint16_t) + sizeof(uint16_t), 451 }; 452 453 uint8_t mBuffer[kSize]; 454 uint8_t *mWriteFrameStart; // Pointer to start of current frame being written. 455 }; 456 457 /** 458 * This class implements the HDLC-lite encoder. 459 * 460 */ 461 class Encoder 462 { 463 public: 464 /** 465 * This constructor initializes the object. 466 * 467 * @param[in] aWritePointer The `FrameWritePointer` used by `Encoder` to write the encoded frames. 468 * 469 */ 470 explicit Encoder(FrameWritePointer &aWritePointer); 471 472 /** 473 * This method begins an HDLC frame. 474 * 475 * @retval OT_ERROR_NONE Successfully started the HDLC frame. 476 * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start the HDLC frame. 477 * 478 */ 479 otError BeginFrame(void); 480 481 /** 482 * This method encodes a single byte into current frame. 483 * 484 * If there is no space to add the byte, the write pointer in frame buffer remains the same. 485 * 486 * @param[in] aByte A byte value to encode and add to frame. 487 * 488 * @retval OT_ERROR_NONE Successfully encoded and added the byte to frame buffer. 489 * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to encode and add the byte. 490 * 491 */ 492 otError Encode(uint8_t aByte); 493 494 /** 495 * This method encodes a given block of data into current frame. 496 * 497 * This method returns success only if there is space in buffer to encode the entire block of data. If there is no 498 * space to encode the entire block of data, the write pointer in frame buffer remains the same. 499 * 500 * @param[in] aData A pointer to a buffer containing the data to encode. 501 * @param[in] aLength The number of bytes in @p aData. 502 * 503 * @retval OT_ERROR_NONE Successfully encoded and added the data to frame. 504 * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the frame. 505 * 506 */ 507 otError Encode(const uint8_t *aData, uint16_t aLength); 508 509 /** 510 * This method ends/finalizes the HDLC frame. 511 * 512 * @retval OT_ERROR_NONE Successfully ended the HDLC frame. 513 * @retval OT_ERROR_NO_BUFS Insufficient buffer space available to end the HDLC frame. 514 * 515 */ 516 otError EndFrame(void); 517 518 private: 519 FrameWritePointer &mWritePointer; 520 uint16_t mFcs; 521 }; 522 523 /** 524 * This class implements the HDLC-lite decoder. 525 * 526 */ 527 class Decoder 528 { 529 public: 530 /** 531 * This function pointer is called when either a complete frame has been decoded or an error occurs during 532 * decoding. 533 * 534 * The decoded frame (or the partially decoded frame in case of an error) is available in `aFrameWritePointer` 535 * buffer given in `Decoder` constructor. 536 * 537 * @param[in] aContext A pointer to arbitrary context information. 538 * @param[in] aError OT_ERROR_NONE if the frame was decoded successfully, 539 * OT_ERROR_PARSE if the Frame Check Sequence (FCS) was incorrect in decoded frame, 540 * OT_ERROR_NO_BUFS insufficient buffer space available to save the decoded frame. 541 * 542 */ 543 typedef void (*FrameHandler)(void *aContext, otError aError); 544 545 /** 546 * This constructor initializes the decoder. 547 * 548 * @param[in] aFrameWritePointer The `FrameWritePointer` used by `Decoder` to write the decoded frames. 549 * @param[in] aFrameHandler The frame handler callback function pointer. 550 * @param[in] aContext A pointer to arbitrary context information. 551 * 552 */ 553 Decoder(FrameWritePointer &aFrameWritePointer, FrameHandler aFrameHandler, void *aContext); 554 555 /** 556 * This method feeds a block of data into the decoder. 557 * 558 * If during decoding, a full HDLC frame is successfully decoded or an error occurs, the `FrameHandler` callback 559 * is called. The decoded frame (or the partially decoded frame in case of an error) is available in 560 * `aFrameWritePointer` buffer from the constructor. The `Decoder` user (if required) must update/reset the write 561 * pointer from this callback for the next frame to be decoded. 562 * 563 * @param[in] aData A pointer to a buffer containing data to be fed to decoder. 564 * @param[in] aLength The number of bytes in @p aData. 565 * 566 */ 567 void Decode(const uint8_t *aData, uint16_t aLength); 568 569 /** 570 * This method resets internal states of the decoder. 571 * 572 */ 573 void Reset(void); 574 575 private: 576 enum State 577 { 578 kStateNoSync, 579 kStateSync, 580 kStateEscaped, 581 }; 582 583 State mState; 584 FrameWritePointer &mWritePointer; 585 FrameHandler mFrameHandler; 586 void * mContext; 587 uint16_t mFcs; 588 uint16_t mDecodedLength; 589 }; 590 591 } // namespace Hdlc 592 } // namespace ot 593 594 #endif // HDLC_HPP_ 595