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