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"
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 includes definitions for generating and processing CoAP messages.
32  */
33 
34 #ifndef COAP_HEADER_HPP_
35 #define COAP_HEADER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/coap.h>
40 
41 #include "common/clearable.hpp"
42 #include "common/code_utils.hpp"
43 #include "common/encoding.hpp"
44 #include "common/message.hpp"
45 #include "net/ip6.hpp"
46 #include "net/ip6_address.hpp"
47 #include "net/udp6.hpp"
48 
49 namespace ot {
50 
51 /**
52  * @namespace ot::Coap
53  * @brief
54  *   This namespace includes definitions for CoAP.
55  *
56  */
57 namespace Coap {
58 
59 using ot::Encoding::BigEndian::HostSwap16;
60 
61 /**
62  * @addtogroup core-coap
63  *
64  * @brief
65  *   This module includes definitions for CoAP.
66  *
67  * @{
68  *
69  */
70 
71 class Option;
72 
73 /**
74  * CoAP Type values.
75  *
76  */
77 enum Type : uint8_t
78 {
79     kTypeConfirmable    = OT_COAP_TYPE_CONFIRMABLE,     ///< Confirmable type.
80     kTypeNonConfirmable = OT_COAP_TYPE_NON_CONFIRMABLE, ///< Non-confirmable type.
81     kTypeAck            = OT_COAP_TYPE_ACKNOWLEDGMENT,  ///< Acknowledgment type.
82     kTypeReset          = OT_COAP_TYPE_RESET,           ///< Reset type.
83 };
84 
85 /**
86  * CoAP Code values.
87  *
88  */
89 enum Code : uint8_t
90 {
91     // Request Codes:
92 
93     kCodeEmpty  = OT_COAP_CODE_EMPTY,  ///< Empty message code
94     kCodeGet    = OT_COAP_CODE_GET,    ///< Get
95     kCodePost   = OT_COAP_CODE_POST,   ///< Post
96     kCodePut    = OT_COAP_CODE_PUT,    ///< Put
97     kCodeDelete = OT_COAP_CODE_DELETE, ///< Delete
98 
99     // Response Codes:
100 
101     kCodeResponseMin = OT_COAP_CODE_RESPONSE_MIN, ///< 2.00
102     kCodeCreated     = OT_COAP_CODE_CREATED,      ///< Created
103     kCodeDeleted     = OT_COAP_CODE_DELETED,      ///< Deleted
104     kCodeValid       = OT_COAP_CODE_VALID,        ///< Valid
105     kCodeChanged     = OT_COAP_CODE_CHANGED,      ///< Changed
106     kCodeContent     = OT_COAP_CODE_CONTENT,      ///< Content
107     kCodeContinue    = OT_COAP_CODE_CONTINUE,     ///< RFC7959 Continue
108 
109     // Client Error Codes:
110 
111     kCodeBadRequest         = OT_COAP_CODE_BAD_REQUEST,         ///< Bad Request
112     kCodeUnauthorized       = OT_COAP_CODE_UNAUTHORIZED,        ///< Unauthorized
113     kCodeBadOption          = OT_COAP_CODE_BAD_OPTION,          ///< Bad Option
114     kCodeForbidden          = OT_COAP_CODE_FORBIDDEN,           ///< Forbidden
115     kCodeNotFound           = OT_COAP_CODE_NOT_FOUND,           ///< Not Found
116     kCodeMethodNotAllowed   = OT_COAP_CODE_METHOD_NOT_ALLOWED,  ///< Method Not Allowed
117     kCodeNotAcceptable      = OT_COAP_CODE_NOT_ACCEPTABLE,      ///< Not Acceptable
118     kCodeRequestIncomplete  = OT_COAP_CODE_REQUEST_INCOMPLETE,  ///< RFC7959 Request Entity Incomplete
119     kCodePreconditionFailed = OT_COAP_CODE_PRECONDITION_FAILED, ///< Precondition Failed
120     kCodeRequestTooLarge    = OT_COAP_CODE_REQUEST_TOO_LARGE,   ///< Request Entity Too Large
121     kCodeUnsupportedFormat  = OT_COAP_CODE_UNSUPPORTED_FORMAT,  ///< Unsupported Content-Format
122 
123     // Server Error Codes:
124 
125     kCodeInternalError      = OT_COAP_CODE_INTERNAL_ERROR,      ///< Internal Server Error
126     kCodeNotImplemented     = OT_COAP_CODE_NOT_IMPLEMENTED,     ///< Not Implemented
127     kCodeBadGateway         = OT_COAP_CODE_BAD_GATEWAY,         ///< Bad Gateway
128     kCodeServiceUnavailable = OT_COAP_CODE_SERVICE_UNAVAILABLE, ///< Service Unavailable
129     kCodeGatewayTimeout     = OT_COAP_CODE_GATEWAY_TIMEOUT,     ///< Gateway Timeout
130     kCodeProxyNotSupported  = OT_COAP_CODE_PROXY_NOT_SUPPORTED, ///< Proxying Not Supported
131 };
132 
133 /**
134  * CoAP Option Numbers.
135  *
136  */
137 enum OptionNumber : uint16_t
138 {
139     kOptionIfMatch       = OT_COAP_OPTION_IF_MATCH,       ///< If-Match
140     kOptionUriHost       = OT_COAP_OPTION_URI_HOST,       ///< Uri-Host
141     kOptionETag          = OT_COAP_OPTION_E_TAG,          ///< ETag
142     kOptionIfNoneMatch   = OT_COAP_OPTION_IF_NONE_MATCH,  ///< If-None-Match
143     kOptionObserve       = OT_COAP_OPTION_OBSERVE,        ///< Observe [RFC7641]
144     kOptionUriPort       = OT_COAP_OPTION_URI_PORT,       ///< Uri-Port
145     kOptionLocationPath  = OT_COAP_OPTION_LOCATION_PATH,  ///< Location-Path
146     kOptionUriPath       = OT_COAP_OPTION_URI_PATH,       ///< Uri-Path
147     kOptionContentFormat = OT_COAP_OPTION_CONTENT_FORMAT, ///< Content-Format
148     kOptionMaxAge        = OT_COAP_OPTION_MAX_AGE,        ///< Max-Age
149     kOptionUriQuery      = OT_COAP_OPTION_URI_QUERY,      ///< Uri-Query
150     kOptionAccept        = OT_COAP_OPTION_ACCEPT,         ///< Accept
151     kOptionLocationQuery = OT_COAP_OPTION_LOCATION_QUERY, ///< Location-Query
152     kOptionBlock2        = OT_COAP_OPTION_BLOCK2,         ///< Block2 (RFC7959)
153     kOptionBlock1        = OT_COAP_OPTION_BLOCK1,         ///< Block1 (RFC7959)
154     kOptionSize2         = OT_COAP_OPTION_SIZE2,          ///< Size2 (RFC7959)
155     kOptionProxyUri      = OT_COAP_OPTION_PROXY_URI,      ///< Proxy-Uri
156     kOptionProxyScheme   = OT_COAP_OPTION_PROXY_SCHEME,   ///< Proxy-Scheme
157     kOptionSize1         = OT_COAP_OPTION_SIZE1,          ///< Size1
158 };
159 
160 /**
161  * This class implements CoAP message generation and parsing.
162  *
163  */
164 class Message : public ot::Message
165 {
166     friend class Option;
167 
168 public:
169     static constexpr uint8_t kDefaultTokenLength = OT_COAP_DEFAULT_TOKEN_LENGTH; ///< Default token length.
170     static constexpr uint8_t kMaxReceivedUriPath = 32;                           ///< Max URI path length on rx msgs.
171     static constexpr uint8_t kMaxTokenLength     = OT_COAP_MAX_TOKEN_LENGTH;     ///< Maximum token length.
172 
173     typedef ot::Coap::Type Type; ///< CoAP Type.
174     typedef ot::Coap::Code Code; ///< CoAP Code.
175 
176     /**
177      * CoAP Block1/Block2 Types
178      *
179      */
180     enum BlockType : uint8_t
181     {
182         kBlockType1 = 1,
183         kBlockType2 = 2,
184     };
185 
186     static constexpr uint8_t kBlockSzxBase = 4;
187 
188     /**
189      * This method initializes the CoAP header.
190      *
191      */
192     void Init(void);
193 
194     /**
195      * This method initializes the CoAP header with specific Type and Code.
196      *
197      * @param[in]  aType  The Type value.
198      * @param[in]  aCode  The Code value.
199      *
200      */
201     void Init(Type aType, Code aCode);
202 
203     /**
204      * This method initializes the CoAP header as `kTypeConfirmable` and `kCodePost`.
205      *
206      */
207     void InitAsConfirmablePost(void);
208 
209     /**
210      * This method initializes the CoAP header as `kTypeNonConfirmable` and `kCodePost`.
211      *
212      */
213     void InitAsNonConfirmablePost(void);
214 
215     /**
216      * This method initializes the CoAP header with specific Type and Code.
217      *
218      * @param[in]  aType              The Type value.
219      * @param[in]  aCode              The Code value.
220      * @param[in]  aUriPath           A pointer to a null-terminated string.
221      *
222      * @retval kErrorNone         Successfully appended the option.
223      * @retval kErrorNoBufs       The option length exceeds the buffer size.
224      *
225      */
226     Error Init(Type aType, Code aCode, const char *aUriPath);
227 
228     /**
229      * This method initializes the CoAP header as `kTypeConfirmable` and `kCodePost` with a given URI Path.
230      *
231      * @param[in]  aUriPath           A pointer to a null-terminated string.
232      *
233      * @retval kErrorNone         Successfully appended the option.
234      * @retval kErrorNoBufs       The option length exceeds the buffer size.
235      *
236      */
237     Error InitAsConfirmablePost(const char *aUriPath);
238 
239     /**
240      * This method initializes the CoAP header as `kTypeNonConfirmable` and `kCodePost` with a given URI Path.
241      *
242      * @param[in]  aUriPath           A pointer to a null-terminated string.
243      *
244      * @retval kErrorNone         Successfully appended the option.
245      * @retval kErrorNoBufs       The option length exceeds the buffer size.
246      *
247      */
248     Error InitAsNonConfirmablePost(const char *aUriPath);
249 
250     /**
251      * This method initializes the CoAP header as `kCodePost` with a given URI Path with its type determined from a
252      * given destination IPv6 address.
253      *
254      * @param[in]  aDestination       The message destination IPv6 address used to determine the CoAP type,
255      *                                `kTypeNonConfirmable` if multicast address, `kTypeConfirmable` otherwise.
256      * @param[in]  aUriPath           A pointer to a null-terminated string.
257      *
258      * @retval kErrorNone         Successfully appended the option.
259      * @retval kErrorNoBufs       The option length exceeds the buffer size.
260      *
261      */
262     Error InitAsPost(const Ip6::Address &aDestination, const char *aUriPath);
263 
264     /**
265      * This method writes header to the message. This must be called before sending the message.
266      *
267      * This method also checks whether the payload marker is set (`SetPayloadMarker()`) but the message contains no
268      * payload, and if so it removes the payload marker from the message.
269      *
270      */
271     void Finish(void);
272 
273     /**
274      * This method returns the Version value.
275      *
276      * @returns The Version value.
277      *
278      */
GetVersion(void) const279     uint8_t GetVersion(void) const
280     {
281         return (GetHelpData().mHeader.mVersionTypeToken & kVersionMask) >> kVersionOffset;
282     }
283 
284     /**
285      * This method sets the Version value.
286      *
287      * @param[in]  aVersion  The Version value.
288      *
289      */
SetVersion(uint8_t aVersion)290     void SetVersion(uint8_t aVersion)
291     {
292         GetHelpData().mHeader.mVersionTypeToken &= ~kVersionMask;
293         GetHelpData().mHeader.mVersionTypeToken |= aVersion << kVersionOffset;
294     }
295 
296     /**
297      * This method returns the Type value.
298      *
299      * @returns The Type value.
300      *
301      */
GetType(void) const302     uint8_t GetType(void) const { return (GetHelpData().mHeader.mVersionTypeToken & kTypeMask) >> kTypeOffset; }
303 
304     /**
305      * This method sets the Type value.
306      *
307      * @param[in]  aType  The Type value.
308      *
309      */
SetType(Type aType)310     void SetType(Type aType)
311     {
312         GetHelpData().mHeader.mVersionTypeToken &= ~kTypeMask;
313         GetHelpData().mHeader.mVersionTypeToken |= (static_cast<uint8_t>(aType) << kTypeOffset);
314     }
315 
316     /**
317      * This method returns the Code value.
318      *
319      * @returns The Code value.
320      *
321      */
GetCode(void) const322     uint8_t GetCode(void) const { return static_cast<Code>(GetHelpData().mHeader.mCode); }
323 
324     /**
325      * This method sets the Code value.
326      *
327      * @param[in]  aCode  The Code value.
328      *
329      */
SetCode(Code aCode)330     void SetCode(Code aCode) { GetHelpData().mHeader.mCode = static_cast<uint8_t>(aCode); }
331 
332 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
333     /**
334      * This method returns the CoAP Code as human readable string.
335      *
336      * @ returns The CoAP Code as string.
337      *
338      */
339     const char *CodeToString(void) const;
340 #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE
341 
342     /**
343      * This method returns the Message ID value.
344      *
345      * @returns The Message ID value.
346      *
347      */
GetMessageId(void) const348     uint16_t GetMessageId(void) const { return HostSwap16(GetHelpData().mHeader.mMessageId); }
349 
350     /**
351      * This method sets the Message ID value.
352      *
353      * @param[in]  aMessageId  The Message ID value.
354      *
355      */
SetMessageId(uint16_t aMessageId)356     void SetMessageId(uint16_t aMessageId) { GetHelpData().mHeader.mMessageId = HostSwap16(aMessageId); }
357 
358     /**
359      * This method returns the Token length.
360      *
361      * @returns The Token length.
362      *
363      */
GetTokenLength(void) const364     uint8_t GetTokenLength(void) const
365     {
366         return (GetHelpData().mHeader.mVersionTypeToken & kTokenLengthMask) >> kTokenLengthOffset;
367     }
368 
369     /**
370      * This method returns a pointer to the Token value.
371      *
372      * @returns A pointer to the Token value.
373      *
374      */
GetToken(void) const375     const uint8_t *GetToken(void) const { return GetHelpData().mHeader.mToken; }
376 
377     /**
378      * This method sets the Token value and length.
379      *
380      * @param[in]  aToken        A pointer to the Token value.
381      * @param[in]  aTokenLength  The Length of @p aToken.
382      *
383      * @retval kErrorNone    Successfully set the token value.
384      * @retval kErrorNoBufs  Insufficient message buffers available to set the token value.
385      *
386      */
387     Error SetToken(const uint8_t *aToken, uint8_t aTokenLength);
388 
389     /**
390      * This method sets the Token value and length by copying it from another given message.
391      *
392      * @param[in] aMessage       The message to copy the Token from.
393      *
394      * @retval kErrorNone    Successfully set the token value.
395      * @retval kErrorNoBufs  Insufficient message buffers available to set the token value.
396      *
397      */
398     Error SetTokenFromMessage(const Message &aMessage);
399 
400     /**
401      * This method sets the Token length and randomizes its value.
402      *
403      * @param[in]  aTokenLength  The Length of a Token to set.
404      *
405      * @retval kErrorNone    Successfully set the token value.
406      * @retval kErrorNoBufs  Insufficient message buffers available to set the token value.
407      *
408      */
409     Error GenerateRandomToken(uint8_t aTokenLength);
410 
411     /**
412      * This method checks if Tokens in two CoAP headers are equal.
413      *
414      * @param[in]  aMessage  A header to compare.
415      *
416      * @retval TRUE   If two Tokens are equal.
417      * @retval FALSE  If Tokens differ in length or value.
418      *
419      */
420     bool IsTokenEqual(const Message &aMessage) const;
421 
422     /**
423      * This method appends a CoAP option.
424      *
425      * @param[in] aNumber   The CoAP Option number.
426      * @param[in] aLength   The CoAP Option length.
427      * @param[in] aValue    A pointer to the CoAP Option value (@p aLength bytes are used as Option value).
428      *
429      * @retval kErrorNone         Successfully appended the option.
430      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
431      * @retval kErrorNoBufs       The option length exceeds the buffer size.
432      *
433      */
434     Error AppendOption(uint16_t aNumber, uint16_t aLength, const void *aValue);
435 
436     /**
437      * This method appends an unsigned integer CoAP option as specified in RFC-7252 section-3.2
438      *
439      * @param[in]  aNumber  The CoAP Option number.
440      * @param[in]  aValue   The CoAP Option unsigned integer value.
441      *
442      * @retval kErrorNone         Successfully appended the option.
443      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
444      * @retval kErrorNoBufs       The option length exceeds the buffer size.
445      *
446      */
447     Error AppendUintOption(uint16_t aNumber, uint32_t aValue);
448 
449     /**
450      * This method appends a string CoAP option.
451      *
452      * @param[in]  aNumber  The CoAP Option number.
453      * @param[in]  aValue   The CoAP Option string value.
454      *
455      * @retval kErrorNone         Successfully appended the option.
456      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
457      * @retval kErrorNoBufs       The option length exceeds the buffer size.
458      *
459      */
460     Error AppendStringOption(uint16_t aNumber, const char *aValue);
461 
462     /**
463      * This method appends an Observe option.
464      *
465      * @param[in]  aObserve  Observe field value.
466      *
467      * @retval kErrorNone         Successfully appended the option.
468      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
469      * @retval kErrorNoBufs       The option length exceeds the buffer size.
470      */
AppendObserveOption(uint32_t aObserve)471     Error AppendObserveOption(uint32_t aObserve) { return AppendUintOption(kOptionObserve, aObserve & kObserveMask); }
472 
473     /**
474      * This method appends a Uri-Path option.
475      *
476      * @param[in]  aUriPath           A pointer to a null-terminated string.
477      *
478      * @retval kErrorNone         Successfully appended the option.
479      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
480      * @retval kErrorNoBufs       The option length exceeds the buffer size.
481      *
482      */
483     Error AppendUriPathOptions(const char *aUriPath);
484 
485     /**
486      * This method reads the Uri-Path options and constructs the URI path in the buffer referenced by @p `aUriPath`.
487      *
488      * @param[in] aUriPath  A reference to the buffer for storing URI path.
489      *                      NOTE: The buffer size must be `kMaxReceivedUriPath + 1`.
490      *
491      * @retval  kErrorNone   Successfully read the Uri-Path options.
492      * @retval  kErrorParse  CoAP Option header not well-formed.
493      *
494      */
495     Error ReadUriPathOptions(char (&aUriPath)[kMaxReceivedUriPath + 1]) const;
496 
497     /**
498      * This method appends a Block option
499      *
500      * @param[in]  aType              Type of block option, 1 or 2.
501      * @param[in]  aNum               Current block number.
502      * @param[in]  aMore              Boolean to indicate more blocks are to be sent.
503      * @param[in]  aSize              Maximum block size.
504      *
505      * @retval kErrorNone         Successfully appended the option.
506      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
507      * @retval kErrorNoBufs       The option length exceeds the buffer size.
508      *
509      */
510     Error AppendBlockOption(BlockType aType, uint32_t aNum, bool aMore, otCoapBlockSzx aSize);
511 
512     /**
513      * This method appends a Proxy-Uri option.
514      *
515      * @param[in]  aProxyUri          A pointer to a null-terminated string.
516      *
517      * @retval kErrorNone         Successfully appended the option.
518      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
519      * @retval kErrorNoBufs       The option length exceeds the buffer size.
520      *
521      */
AppendProxyUriOption(const char * aProxyUri)522     Error AppendProxyUriOption(const char *aProxyUri) { return AppendStringOption(kOptionProxyUri, aProxyUri); }
523 
524     /**
525      * This method appends a Content-Format option.
526      *
527      * @param[in]  aContentFormat  The Content Format value.
528      *
529      * @retval kErrorNone         Successfully appended the option.
530      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
531      * @retval kErrorNoBufs       The option length exceeds the buffer size.
532      *
533      */
AppendContentFormatOption(otCoapOptionContentFormat aContentFormat)534     Error AppendContentFormatOption(otCoapOptionContentFormat aContentFormat)
535     {
536         return AppendUintOption(kOptionContentFormat, static_cast<uint32_t>(aContentFormat));
537     }
538 
539     /**
540      * This method appends a Max-Age option.
541      *
542      * @param[in]  aMaxAge  The Max-Age value.
543      *
544      * @retval kErrorNone         Successfully appended the option.
545      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
546      * @retval kErrorNoBufs       The option length exceeds the buffer size.
547      */
AppendMaxAgeOption(uint32_t aMaxAge)548     Error AppendMaxAgeOption(uint32_t aMaxAge) { return AppendUintOption(kOptionMaxAge, aMaxAge); }
549 
550     /**
551      * This method appends a single Uri-Query option.
552      *
553      * @param[in]  aUriQuery  A pointer to null-terminated string, which should contain a single key=value pair.
554      *
555      * @retval kErrorNone         Successfully appended the option.
556      * @retval kErrorInvalidArgs  The option type is not equal or greater than the last option type.
557      * @retval kErrorNoBufs       The option length exceeds the buffer size.
558      */
AppendUriQueryOption(const char * aUriQuery)559     Error AppendUriQueryOption(const char *aUriQuery) { return AppendStringOption(kOptionUriQuery, aUriQuery); }
560 
561 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
562     /**
563      * This function reads the information contained in a Block1 or Block2 option and set it in
564      * the HelpData of the message.
565      *
566      * @param[in]   aBlockType  Block1 or Block2 option value.
567      *
568      * @retval  kErrorNone          The option has been found and is valid.
569      * @retval  kErrorNotFound      The option has not been found.
570      * @retval  kErrorInvalidArgs   The option is invalid.
571      */
572     Error ReadBlockOptionValues(uint16_t aBlockType);
573 
574     /**
575      * This method returns the current header length of a message.
576      *
577      * @returns The length of the message header.
578      *
579      */
GetHeaderLength(void) const580     uint16_t GetHeaderLength(void) const { return GetHelpData().mHeaderLength; }
581 
582     /**
583      * This method returns the block number of a CoAP block-wise transfer message.
584      *
585      * @returns The block number.
586      *
587      */
GetBlockWiseBlockNumber(void) const588     uint32_t GetBlockWiseBlockNumber(void) const { return GetHelpData().mBlockWiseData.mBlockNumber; }
589 
590     /**
591      * This method checks if the More Blocks flag is set.
592      *
593      * @retval TRUE   More Blocks flag is set.
594      * @retval FALSE  More Blocks flag is not set.
595      *
596      */
IsMoreBlocksFlagSet(void) const597     bool IsMoreBlocksFlagSet(void) const { return GetHelpData().mBlockWiseData.mMoreBlocks; }
598 
599     /**
600      * This method returns the block size of a CoAP block-wise transfer message.
601      *
602      * @returns The block size.
603      *
604      */
GetBlockWiseBlockSize(void) const605     otCoapBlockSzx GetBlockWiseBlockSize(void) const { return GetHelpData().mBlockWiseData.mBlockSize; }
606 #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
607 
608     /**
609      * This function reads and reassembles the URI path string and fills it into @p aUriPath.
610      *
611      * @retval  kErrorNone      URI path string has been reassembled.
612      * @retval  kErrorNoBufs    URI path string is too long.
613      *
614      */
615     Error GetUriPath(char *aUriPath) const;
616 
617     /**
618      * This method adds Payload Marker indicating beginning of the payload to the CoAP header.
619      *
620      * It also set offset to the start of payload.
621      *
622      * @retval kErrorNone    Payload Marker successfully added.
623      * @retval kErrorNoBufs  Message Payload Marker exceeds the buffer size.
624      *
625      */
626     Error SetPayloadMarker(void);
627 
628     /**
629      * This method returns the offset of the first CoAP option.
630      *
631      * @returns The offset of the first CoAP option.
632      *
633      */
GetOptionStart(void) const634     uint16_t GetOptionStart(void) const { return kMinHeaderLength + GetTokenLength(); }
635 
636     /**
637      * This method parses CoAP header and moves offset end of CoAP header.
638      *
639      * @retval  kErrorNone   Successfully parsed CoAP header from the message.
640      * @retval  kErrorParse  Failed to parse the CoAP header.
641      *
642      */
643     Error ParseHeader(void);
644 
645     /**
646      * This method sets a default response header based on request header.
647      *
648      * @param[in]  aRequest  The request message.
649      *
650      * @retval kErrorNone    Successfully set the default response header.
651      * @retval kErrorNoBufs  Insufficient message buffers available to set the default response header.
652      *
653      */
654     Error SetDefaultResponseHeader(const Message &aRequest);
655 
656 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
657 
658     /**
659      * This method sets the block number value in the message HelpData.
660      *
661      * @param[in]   aBlockNumber    Block number value to set.
662      *
663      */
SetBlockWiseBlockNumber(uint32_t aBlockNumber)664     void SetBlockWiseBlockNumber(uint32_t aBlockNumber) { GetHelpData().mBlockWiseData.mBlockNumber = aBlockNumber; }
665 
666     /**
667      * This method sets the More Blocks falg in the message HelpData.
668      *
669      * @param[in]   aMoreBlocks    TRUE or FALSE.
670      *
671      */
SetMoreBlocksFlag(bool aMoreBlocks)672     void SetMoreBlocksFlag(bool aMoreBlocks) { GetHelpData().mBlockWiseData.mMoreBlocks = aMoreBlocks; }
673 
674     /**
675      * This method sets the block size value in the message HelpData.
676      *
677      * @param[in]   aBlockSize    Block size value to set.
678      *
679      */
SetBlockWiseBlockSize(otCoapBlockSzx aBlockSize)680     void SetBlockWiseBlockSize(otCoapBlockSzx aBlockSize) { GetHelpData().mBlockWiseData.mBlockSize = aBlockSize; }
681 #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
682 
683     /**
684      * This method checks if a header is an empty message header.
685      *
686      * @retval TRUE   Message is an empty message header.
687      * @retval FALSE  Message is not an empty message header.
688      *
689      */
IsEmpty(void) const690     bool IsEmpty(void) const { return (GetCode() == kCodeEmpty); }
691 
692     /**
693      * This method checks if a header is a request header.
694      *
695      * @retval TRUE   Message is a request header.
696      * @retval FALSE  Message is not a request header.
697      *
698      */
IsRequest(void) const699     bool IsRequest(void) const { return (GetCode() >= kCodeGet) && (GetCode() <= kCodeDelete); }
700 
701     /**
702      * This method indicates whether or not the CoAP code in header is "Get" request.
703      *
704      * @retval TRUE   Message is a Get request.
705      * @retval FALSE  Message is not a Get request.
706      *
707      */
IsGetRequest(void) const708     bool IsGetRequest(void) const { return GetCode() == kCodeGet; }
709 
710     /**
711      * This method indicates whether or not the CoAP code in header is "Post" request.
712      *
713      * @retval TRUE   Message is a Post request.
714      * @retval FALSE  Message is not a Post request.
715      *
716      */
IsPostRequest(void) const717     bool IsPostRequest(void) const { return GetCode() == kCodePost; }
718 
719     /**
720      * This method indicates whether or not the CoAP code in header is "Put" request.
721      *
722      * @retval TRUE   Message is a Put request.
723      * @retval FALSE  Message is not a Put request.
724      *
725      */
IsPutRequest(void) const726     bool IsPutRequest(void) const { return GetCode() == kCodePut; }
727 
728     /**
729      * This method indicates whether or not the CoAP code in header is "Delete" request.
730      *
731      * @retval TRUE   Message is a Delete request.
732      * @retval FALSE  Message is not a Delete request.
733      *
734      */
IsDeleteRequest(void) const735     bool IsDeleteRequest(void) const { return GetCode() == kCodeDelete; }
736 
737     /**
738      * This method checks if a header is a response header.
739      *
740      * @retval TRUE   Message is a response header.
741      * @retval FALSE  Message is not a response header.
742      *
743      */
IsResponse(void) const744     bool IsResponse(void) const { return GetCode() >= OT_COAP_CODE_RESPONSE_MIN; }
745 
746     /**
747      * This method checks if a header is a CON message header.
748      *
749      * @retval TRUE   Message is a CON message header.
750      * @retval FALSE  Message is not is a CON message header.
751      *
752      */
IsConfirmable(void) const753     bool IsConfirmable(void) const { return (GetType() == kTypeConfirmable); }
754 
755     /**
756      * This method checks if a header is a NON message header.
757      *
758      * @retval TRUE   Message is a NON message header.
759      * @retval FALSE  Message is not is a NON message header.
760      *
761      */
IsNonConfirmable(void) const762     bool IsNonConfirmable(void) const { return (GetType() == kTypeNonConfirmable); }
763 
764     /**
765      * This method checks if a header is a ACK message header.
766      *
767      * @retval TRUE   Message is a ACK message header.
768      * @retval FALSE  Message is not is a ACK message header.
769      *
770      */
IsAck(void) const771     bool IsAck(void) const { return (GetType() == kTypeAck); }
772 
773     /**
774      * This method checks if a header is a RST message header.
775      *
776      * @retval TRUE   Message is a RST message header.
777      * @retval FALSE  Message is not is a RST message header.
778      *
779      */
IsReset(void) const780     bool IsReset(void) const { return (GetType() == kTypeReset); }
781 
782     /**
783      * This method indicates whether or not the header is a confirmable Put request (i.e, `kTypeConfirmable` with
784      *  `kCodePost`).
785      *
786      * @retval TRUE   Message is a confirmable Post request.
787      * @retval FALSE  Message is not a confirmable Post request.
788      *
789      */
790     bool IsConfirmablePostRequest(void) const;
791 
792     /**
793      * This method indicates whether or not the header is a non-confirmable Put request (i.e, `kTypeNonConfirmable` with
794      *  `kCodePost`).
795      *
796      * @retval TRUE   Message is a non-confirmable Post request.
797      * @retval FALSE  Message is not a non-confirmable Post request.
798      *
799      */
800     bool IsNonConfirmablePostRequest(void) const;
801 
802     /**
803      * This method creates a copy of this CoAP message.
804      *
805      * It allocates the new message from the same message pool as the original one and copies @p aLength octets
806      * of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
807      * cloned message are also copied from the original one.
808      *
809      * @param[in] aLength  Number of payload bytes to copy.
810      *
811      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
812      *
813      */
814     Message *Clone(uint16_t aLength) const;
815 
816     /**
817      * This method creates a copy of the message.
818      *
819      * It allocates the new message from the same message pool as the original one and copies the entire payload. The
820      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
821      * copied from the original one.
822      *
823      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
824      *
825      */
Clone(void) const826     Message *Clone(void) const { return Clone(GetLength()); }
827 
828     /**
829      * This method returns the minimal reserved bytes required for CoAP message.
830      *
831      */
GetHelpDataReserved(void)832     static uint16_t GetHelpDataReserved(void) { return sizeof(HelpData) + kHelpDataAlignment; }
833 
834     /**
835      * This method returns a pointer to the next message after this as a `Coap::Message`.
836      *
837      * This method should be used when the message is in a `Coap::MessageQueue` (i.e., a queue containing only CoAP
838      * messages).
839      *
840      * @returns A pointer to the next message in the queue or nullptr if at the end of the queue.
841      *
842      */
GetNextCoapMessage(void)843     Message *GetNextCoapMessage(void) { return static_cast<Message *>(GetNext()); }
844 
845     /**
846      * This method returns a pointer to the next message after this as a `Coap::Message`.
847      *
848      * This method should be used when the message is in a `Coap::MessageQueue` (i.e., a queue containing only CoAP
849      * messages).
850      *
851      * @returns A pointer to the next message in the queue or nullptr if at the end of the queue.
852      *
853      */
GetNextCoapMessage(void) const854     const Message *GetNextCoapMessage(void) const { return static_cast<const Message *>(GetNext()); }
855 
856 private:
857     /*
858      * Header field first byte (RFC 7252).
859      *
860      *    7 6 5 4 3 2 1 0
861      *   +-+-+-+-+-+-+-+-+
862      *   |Ver| T |  TKL  |  (Version, Type and Token Length).
863      *   +-+-+-+-+-+-+-+-+
864      */
865     static constexpr uint8_t kVersionOffset     = 6;
866     static constexpr uint8_t kVersionMask       = 0x3 << kVersionOffset;
867     static constexpr uint8_t kVersion1          = 1;
868     static constexpr uint8_t kTypeOffset        = 4;
869     static constexpr uint8_t kTypeMask          = 0x3 << kTypeOffset;
870     static constexpr uint8_t kTokenLengthOffset = 0;
871     static constexpr uint8_t kTokenLengthMask   = 0xf << kTokenLengthOffset;
872 
873     /*
874      *
875      * Option Format (RFC 7252).
876      *
877      *      7   6   5   4   3   2   1   0
878      *    +---------------+---------------+
879      *    |  Option Delta | Option Length |   1 byte
880      *    +---------------+---------------+
881      *    /         Option Delta          /   0-2 bytes
882      *    \          (extended)           \
883      *    +-------------------------------+
884      *    /         Option Length         /   0-2 bytes
885      *    \          (extended)           \
886      *    +-------------------------------+
887      *    /         Option Value          /   0 or more bytes
888      *    +-------------------------------+
889      *
890      */
891 
892     static constexpr uint8_t kOptionDeltaOffset  = 4;
893     static constexpr uint8_t kOptionDeltaMask    = 0xf << kOptionDeltaOffset;
894     static constexpr uint8_t kOptionLengthOffset = 0;
895     static constexpr uint8_t kOptionLengthMask   = 0xf << kOptionLengthOffset;
896 
897     static constexpr uint8_t kMaxOptionHeaderSize = 5;
898 
899     static constexpr uint8_t kOption1ByteExtension = 13; // Indicates a one-byte extension.
900     static constexpr uint8_t kOption2ByteExtension = 14; // Indicates a two-byte extension.
901 
902     static constexpr uint8_t kPayloadMarker = 0xff;
903 
904     static constexpr uint8_t kHelpDataAlignment = sizeof(uint16_t); // Alignment of help data.
905 
906     static constexpr uint16_t kMinHeaderLength = 4;
907     static constexpr uint16_t kMaxHeaderLength = 512;
908 
909     static constexpr uint16_t kOption1ByteExtensionOffset = 13;  // Delta/Length offset as specified (RFC 7252).
910     static constexpr uint16_t kOption2ByteExtensionOffset = 269; // Delta/Length offset as specified (RFC 7252).
911 
912     static constexpr uint8_t kBlockSzxOffset = 0;
913     static constexpr uint8_t kBlockMOffset   = 3;
914     static constexpr uint8_t kBlockNumOffset = 4;
915 
916     static constexpr uint32_t kObserveMask = 0xffffff;
917     static constexpr uint32_t kBlockNumMax = 0xffff;
918 
919 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
920     struct BlockWiseData
921     {
922         uint32_t       mBlockNumber;
923         bool           mMoreBlocks;
924         otCoapBlockSzx mBlockSize;
925     };
926 #endif
927 
928     /**
929      * This structure represents a CoAP header excluding CoAP options.
930      *
931      */
932     OT_TOOL_PACKED_BEGIN
933     struct Header
934     {
935         uint8_t  mVersionTypeToken;       ///< The CoAP Version, Type, and Token Length
936         uint8_t  mCode;                   ///< The CoAP Code
937         uint16_t mMessageId;              ///< The CoAP Message ID
938         uint8_t  mToken[kMaxTokenLength]; ///< The CoAP Token
939     } OT_TOOL_PACKED_END;
940 
941     /**
942      * This structure represents a HelpData used by this CoAP message.
943      *
944      */
945     struct HelpData : public Clearable<HelpData>
946     {
947         Header   mHeader;
948         uint16_t mOptionLast;
949         uint16_t mHeaderOffset; ///< The byte offset for the CoAP Header
950         uint16_t mHeaderLength;
951         bool     mPayloadMarkerSet;
952 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
953         BlockWiseData mBlockWiseData;
954 #endif
955     };
956 
957     static_assert(sizeof(HelpData) <= sizeof(Ip6::Header) + sizeof(Ip6::HopByHopHeader) + sizeof(Ip6::OptionMpl) +
958                                           sizeof(Ip6::Udp::Header),
959                   "HelpData size exceeds the size of the reserved region in the message");
960 
GetHelpData(void) const961     const HelpData &GetHelpData(void) const
962     {
963         static_assert(sizeof(mBuffer.mHead.mMetadata) + sizeof(HelpData) + kHelpDataAlignment <= sizeof(mBuffer),
964                       "Insufficient buffer size for CoAP processing!");
965 
966         return *static_cast<const HelpData *>(OT_ALIGN(mBuffer.mHead.mData, kHelpDataAlignment));
967     }
968 
GetHelpData(void)969     HelpData &GetHelpData(void) { return const_cast<HelpData &>(static_cast<const Message *>(this)->GetHelpData()); }
970 
GetToken(void)971     uint8_t *GetToken(void) { return GetHelpData().mHeader.mToken; }
972 
SetTokenLength(uint8_t aTokenLength)973     void SetTokenLength(uint8_t aTokenLength)
974     {
975         GetHelpData().mHeader.mVersionTypeToken &= ~kTokenLengthMask;
976         GetHelpData().mHeader.mVersionTypeToken |= ((aTokenLength << kTokenLengthOffset) & kTokenLengthMask);
977     }
978 
979     uint8_t WriteExtendedOptionField(uint16_t aValue, uint8_t *&aBuffer);
980 };
981 
982 /**
983  * This class implements a CoAP message queue.
984  *
985  */
986 class MessageQueue : public ot::MessageQueue
987 {
988 public:
989     /**
990      * This constructor initializes the message queue.
991      *
992      */
993     MessageQueue(void) = default;
994 
995     /**
996      * This method returns a pointer to the first message.
997      *
998      * @returns A pointer to the first message.
999      *
1000      */
GetHead(void) const1001     Message *GetHead(void) const { return static_cast<Message *>(ot::MessageQueue::GetHead()); }
1002 
1003     /**
1004      * This method adds a message to the end of the queue.
1005      *
1006      * @param[in]  aMessage  The message to add.
1007      *
1008      */
Enqueue(Message & aMessage)1009     void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
1010 
1011     /**
1012      * This method adds a message at a given position (head/tail) of the queue.
1013      *
1014      * @param[in]  aMessage  The message to add.
1015      * @param[in]  aPosition The position (head or tail) where to add the message.
1016      *
1017      */
Enqueue(Message & aMessage,QueuePosition aPosition)1018     void Enqueue(Message &aMessage, QueuePosition aPosition) { ot::MessageQueue::Enqueue(aMessage, aPosition); }
1019 
1020     /**
1021      * This method removes a message from the queue.
1022      *
1023      * @param[in]  aMessage  The message to remove.
1024      *
1025      */
Dequeue(Message & aMessage)1026     void Dequeue(Message &aMessage) { ot::MessageQueue::Dequeue(aMessage); }
1027 
1028     /**
1029      * This method removes a message from the queue and frees it.
1030      *
1031      * @param[in]  aMessage  The message to remove and free.
1032      *
1033      */
DequeueAndFree(Message & aMessage)1034     void DequeueAndFree(Message &aMessage) { ot::MessageQueue::DequeueAndFree(aMessage); }
1035 };
1036 
1037 /**
1038  * This class represents a CoAP option.
1039  *
1040  */
1041 class Option : public otCoapOption
1042 {
1043 public:
1044     /**
1045      * This class represents an iterator for CoAP options.
1046      *
1047      */
1048     class Iterator : public otCoapOptionIterator
1049     {
1050     public:
1051         /**
1052          * This method initializes the iterator to iterate over CoAP Options in a CoAP message.
1053          *
1054          * The iterator MUST be initialized before any other methods are used, otherwise its behavior is undefined.
1055          *
1056          * After initialization, the iterator is either updated to point to the first option, or it is marked as done
1057          * (i.e., `IsDone()` returns `true`) when there is no option or if there is a parse error.
1058          *
1059          * @param[in] aMessage  The CoAP message.
1060          *
1061          * @retval kErrorNone   Successfully initialized. Iterator is either at the first option or done.
1062          * @retval kErrorParse  CoAP Option header in @p aMessage is not well-formed.
1063          *
1064          */
1065         Error Init(const Message &aMessage);
1066 
1067         /**
1068          * This method initializes the iterator to iterate over CoAP Options in a CoAP message matching a given Option
1069          * Number value.
1070          *
1071          * The iterator MUST be initialized before any other methods are used, otherwise its behavior is undefined.
1072          *
1073          * After initialization, the iterator is either updated to point to the first option matching the given Option
1074          * Number value, or it is marked as done (i.e., `IsDone()` returns `true`) when there is no matching option or
1075          * if there is a parse error.
1076          *
1077          * @param[in] aMessage  The CoAP message.
1078          * @param[in] aNumber   The CoAP Option Number.
1079          *
1080          * @retval  kErrorNone   Successfully initialized. Iterator is either at the first matching option or done.
1081          * @retval  kErrorParse  CoAP Option header in @p aMessage is not well-formed.
1082          *
1083          */
Init(const Message & aMessage,uint16_t aNumber)1084         Error Init(const Message &aMessage, uint16_t aNumber) { return InitOrAdvance(&aMessage, aNumber); }
1085 
1086         /**
1087          * This method indicates whether or not the iterator is done (i.e., has reached the end of CoAP Option Header).
1088          *
1089          * @retval TRUE   Iterator is done (reached end of Option header).
1090          * @retval FALSE  Iterator is not done and currently pointing to a CoAP Option.
1091          *
1092          */
IsDone(void) const1093         bool IsDone(void) const { return mOption.mLength == kIteratorDoneLength; }
1094 
1095         /**
1096          * This method indicates whether or not there was a earlier parse error (i.e., whether the iterator is valid).
1097          *
1098          * After a parse errors, iterator would also be marked as done.
1099          *
1100          * @retval TRUE   There was an earlier parse error and the iterator is not valid.
1101          * @retval FALSE  There was no earlier parse error and the iterator is valid.
1102          *
1103          */
HasParseErrored(void) const1104         bool HasParseErrored(void) const { return mNextOptionOffset == kNextOptionOffsetParseError; }
1105 
1106         /**
1107          * This method advances the iterator to the next CoAP Option in the header.
1108          *
1109          * The iterator is updated to point to the next option or marked as done when there are no more options.
1110          *
1111          * @retval  kErrorNone   Successfully advanced the iterator.
1112          * @retval  kErrorParse  CoAP Option header is not well-formed.
1113          *
1114          */
1115         Error Advance(void);
1116 
1117         /**
1118          * This method advances the iterator to the next CoAP Option in the header matching a given Option Number value.
1119          *
1120          * The iterator is updated to point to the next matching option or marked as done when there are no more
1121          * matching options.
1122          *
1123          * @param[in] aNumber   The CoAP Option Number.
1124          *
1125          * @retval  kErrorNone   Successfully advanced the iterator.
1126          * @retval  kErrorParse  CoAP Option header is not well-formed.
1127          *
1128          */
Advance(uint16_t aNumber)1129         Error Advance(uint16_t aNumber) { return InitOrAdvance(nullptr, aNumber); }
1130 
1131         /**
1132          * This method gets the CoAP message associated with the iterator.
1133          *
1134          * @returns A reference to the CoAP message.
1135          *
1136          */
GetMessage(void) const1137         const Message &GetMessage(void) const { return *static_cast<const Message *>(mMessage); }
1138 
1139         /**
1140          * This methods gets a pointer to the current CoAP Option to which the iterator is currently pointing.
1141          *
1142          * @returns A pointer to the current CoAP Option, or nullptr if iterator is done (or there was an earlier
1143          *          parse error).
1144          *
1145          */
GetOption(void) const1146         const Option *GetOption(void) const { return IsDone() ? nullptr : static_cast<const Option *>(&mOption); }
1147 
1148         /**
1149          * This method reads the current Option Value into a given buffer.
1150          *
1151          * @param[out]  aValue   The pointer to a buffer to copy the Option Value. The buffer is assumed to be
1152          *                       sufficiently large (i.e. at least `GetOption()->GetLength()` bytes).
1153          *
1154          * @retval kErrorNone       Successfully read and copied the Option Value into given buffer.
1155          * @retval kErrorNotFound   Iterator is done (not pointing to any option).
1156          *
1157          */
1158         Error ReadOptionValue(void *aValue) const;
1159 
1160         /**
1161          * This method read the current Option Value which is assumed to be an unsigned integer.
1162          *
1163          * @param[out]  aUintValue      A reference to `uint64_t` to output the read Option Value.
1164          *
1165          * @retval kErrorNone       Successfully read the Option value.
1166          * @retval kErrorNoBufs     Value is too long to fit in an `uint64_t`.
1167          * @retval kErrorNotFound   Iterator is done (not pointing to any option).
1168          *
1169          */
1170         Error ReadOptionValue(uint64_t &aUintValue) const;
1171 
1172         /**
1173          * This method gets the offset of beginning of the CoAP message payload (after the CoAP header).
1174          *
1175          * This method MUST be used after the iterator is done (i.e. iterated through all options).
1176          *
1177          * @returns The offset of beginning of the CoAP message payload
1178          *
1179          */
GetPayloadMessageOffset(void) const1180         uint16_t GetPayloadMessageOffset(void) const { return mNextOptionOffset; }
1181 
1182     private:
1183         // `mOption.mLength` value to indicate iterator is done.
1184         static constexpr uint16_t kIteratorDoneLength = 0xffff;
1185 
1186         // Special `mNextOptionOffset` value to indicate a parse error.
1187         static constexpr uint16_t kNextOptionOffsetParseError = 0;
1188 
MarkAsDone(void)1189         void MarkAsDone(void) { mOption.mLength = kIteratorDoneLength; }
MarkAsParseErrored(void)1190         void MarkAsParseErrored(void) { MarkAsDone(), mNextOptionOffset = kNextOptionOffsetParseError; }
1191 
1192         Error Read(uint16_t aLength, void *aBuffer);
1193         Error ReadExtendedOptionField(uint16_t &aValue);
1194         Error InitOrAdvance(const Message *aMessage, uint16_t aNumber);
1195     };
1196 
1197     /**
1198      * This method gets the CoAP Option Number.
1199      *
1200      * @returns The CoAP Option Number.
1201      *
1202      */
GetNumber(void) const1203     uint16_t GetNumber(void) const { return mNumber; }
1204 
1205     /**
1206      * This method gets the CoAP Option Length (length of Option Value in bytes).
1207      *
1208      * @returns The CoAP Option Length (in bytes).
1209      *
1210      */
GetLength(void) const1211     uint16_t GetLength(void) const { return mLength; }
1212 };
1213 
1214 /**
1215  * @}
1216  *
1217  */
1218 
1219 } // namespace Coap
1220 } // namespace ot
1221 
1222 #endif // COAP_HEADER_HPP_
1223