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