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