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