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