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