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 #ifndef COAP_HPP_ 30 #define COAP_HPP_ 31 32 #include "openthread-core-config.h" 33 34 #include <openthread/coap.h> 35 36 #include "coap/coap_message.hpp" 37 #include "common/as_core_type.hpp" 38 #include "common/callback.hpp" 39 #include "common/debug.hpp" 40 #include "common/linked_list.hpp" 41 #include "common/locator.hpp" 42 #include "common/message.hpp" 43 #include "common/non_copyable.hpp" 44 #include "common/timer.hpp" 45 #include "net/ip6.hpp" 46 #include "net/netif.hpp" 47 #include "net/udp6.hpp" 48 #include "thread/uri_paths.hpp" 49 50 /** 51 * @file 52 * This file includes definitions for CoAP client and server functionality. 53 */ 54 55 namespace ot { 56 57 namespace Coap { 58 59 /** 60 * @addtogroup core-coap 61 * 62 * @{ 63 * 64 */ 65 66 /** 67 * Represents a function pointer which is called when a CoAP response is received or on the request timeout. 68 * 69 * Please see otCoapResponseHandler for details. 70 * 71 */ 72 typedef otCoapResponseHandler ResponseHandler; 73 74 /** 75 * Represents a function pointer which is called when a CoAP request associated with a given URI path is 76 * received. 77 * 78 * Please see otCoapRequestHandler for details. 79 * 80 */ 81 typedef otCoapRequestHandler RequestHandler; 82 83 /** 84 * Represents the CoAP transmission parameters. 85 * 86 */ 87 class TxParameters : public otCoapTxParameters 88 { 89 friend class CoapBase; 90 friend class ResponsesQueue; 91 92 public: 93 /** 94 * Coverts a pointer to `otCoapTxParameters` to `Coap::TxParamters` 95 * 96 * If the pointer is `nullptr`, the default parameters are used instead. 97 * 98 * @param[in] aTxParameters A pointer to tx parameter. 99 * 100 * @returns A reference to corresponding `TxParamters` if @p aTxParameters is not `nullptr`, otherwise the default 101 * tx parameters. 102 * 103 */ From(const otCoapTxParameters * aTxParameters)104 static const TxParameters &From(const otCoapTxParameters *aTxParameters) 105 { 106 return aTxParameters ? *static_cast<const TxParameters *>(aTxParameters) : GetDefault(); 107 } 108 109 /** 110 * Validates whether the CoAP transmission parameters are valid. 111 * 112 * @returns Whether the parameters are valid. 113 * 114 */ 115 bool IsValid(void) const; 116 117 /** 118 * Returns default CoAP tx parameters. 119 * 120 * @returns The default tx parameters. 121 * 122 */ GetDefault(void)123 static const TxParameters &GetDefault(void) { return static_cast<const TxParameters &>(kDefaultTxParameters); } 124 125 private: 126 static constexpr uint32_t kDefaultAckTimeout = 2000; // in msec 127 static constexpr uint8_t kDefaultAckRandomFactorNumerator = 3; 128 static constexpr uint8_t kDefaultAckRandomFactorDenominator = 2; 129 static constexpr uint8_t kDefaultMaxRetransmit = 4; 130 static constexpr uint32_t kDefaultMaxLatency = 100000; // in msec 131 132 uint32_t CalculateInitialRetransmissionTimeout(void) const; 133 uint32_t CalculateExchangeLifetime(void) const; 134 uint32_t CalculateMaxTransmitWait(void) const; 135 uint32_t CalculateSpan(uint8_t aMaxRetx) const; 136 137 static const otCoapTxParameters kDefaultTxParameters; 138 }; 139 140 /** 141 * Implements CoAP resource handling. 142 * 143 */ 144 class Resource : public otCoapResource, public LinkedListEntry<Resource> 145 { 146 friend class CoapBase; 147 148 public: 149 /** 150 * Initializes the resource. 151 * 152 * @param[in] aUriPath A pointer to a null-terminated string for the URI path. 153 * @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath. 154 * @param[in] aContext A pointer to arbitrary context information. 155 * 156 */ 157 Resource(const char *aUriPath, RequestHandler aHandler, void *aContext); 158 159 /** 160 * Initializes the resource. 161 * 162 * @param[in] aUri A Thread URI. 163 * @param[in] aHandler A function pointer that is called when receiving a CoAP message for the URI. 164 * @param[in] aContext A pointer to arbitrary context information. 165 * 166 */ 167 Resource(Uri aUri, RequestHandler aHandler, void *aContext); 168 169 /** 170 * Returns a pointer to the URI path. 171 * 172 * @returns A pointer to the URI path. 173 * 174 */ GetUriPath(void) const175 const char *GetUriPath(void) const { return mUriPath; } 176 177 protected: HandleRequest(Message & aMessage,const Ip6::MessageInfo & aMessageInfo) const178 void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const 179 { 180 mHandler(mContext, &aMessage, &aMessageInfo); 181 } 182 }; 183 184 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 185 /** 186 * Implements CoAP block-wise resource handling. 187 * 188 */ 189 class ResourceBlockWise : public otCoapBlockwiseResource 190 { 191 friend class CoapBase; 192 193 public: 194 /** 195 * Initializes the resource. 196 * 197 * @param[in] aUriPath A pointer to a NULL-terminated string for the Uri-Path. 198 * @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath. 199 * @param[in] aContext A pointer to arbitrary context information. 200 * @param[in] aReceiveHook A function pointer that is called when receiving a CoAP block message for @p 201 * aUriPath. 202 * @param[in] aTransmitHook A function pointer that is called when transmitting a CoAP block message from @p 203 * aUriPath. 204 */ ResourceBlockWise(const char * aUriPath,otCoapRequestHandler aHandler,void * aContext,otCoapBlockwiseReceiveHook aReceiveHook,otCoapBlockwiseTransmitHook aTransmitHook)205 ResourceBlockWise(const char *aUriPath, 206 otCoapRequestHandler aHandler, 207 void *aContext, 208 otCoapBlockwiseReceiveHook aReceiveHook, 209 otCoapBlockwiseTransmitHook aTransmitHook) 210 { 211 mUriPath = aUriPath; 212 mHandler = aHandler; 213 mContext = aContext; 214 mReceiveHook = aReceiveHook; 215 mTransmitHook = aTransmitHook; 216 mNext = nullptr; 217 } 218 HandleBlockReceive(const uint8_t * aBlock,uint32_t aPosition,uint16_t aBlockLength,bool aMore,uint32_t aTotalLength) const219 Error HandleBlockReceive(const uint8_t *aBlock, 220 uint32_t aPosition, 221 uint16_t aBlockLength, 222 bool aMore, 223 uint32_t aTotalLength) const 224 { 225 return mReceiveHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore, aTotalLength); 226 } 227 HandleBlockTransmit(uint8_t * aBlock,uint32_t aPosition,uint16_t * aBlockLength,bool * aMore) const228 Error HandleBlockTransmit(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore) const 229 { 230 return mTransmitHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore); 231 } 232 233 /** 234 * Gets the next entry in the linked list. 235 * 236 * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list. 237 * 238 */ GetNext(void) const239 const ResourceBlockWise *GetNext(void) const 240 { 241 return static_cast<const ResourceBlockWise *>(static_cast<const ResourceBlockWise *>(this)->mNext); 242 } 243 244 /** 245 * Gets the next entry in the linked list. 246 * 247 * @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list. 248 * 249 */ GetNext(void)250 ResourceBlockWise *GetNext(void) 251 { 252 return static_cast<ResourceBlockWise *>(static_cast<ResourceBlockWise *>(this)->mNext); 253 } 254 255 /** 256 * Sets the next pointer on the entry. 257 * 258 * @param[in] aNext A pointer to the next entry. 259 * 260 */ SetNext(ResourceBlockWise * aNext)261 void SetNext(ResourceBlockWise *aNext) { static_cast<ResourceBlockWise *>(this)->mNext = aNext; } 262 263 /** 264 * Returns a pointer to the URI path. 265 * 266 * @returns A pointer to the URI path. 267 * 268 */ GetUriPath(void) const269 const char *GetUriPath(void) const { return mUriPath; } 270 271 protected: HandleRequest(Message & aMessage,const Ip6::MessageInfo & aMessageInfo) const272 void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const 273 { 274 mHandler(mContext, &aMessage, &aMessageInfo); 275 } 276 }; 277 #endif 278 279 /** 280 * Caches CoAP responses to implement message deduplication. 281 * 282 */ 283 class ResponsesQueue 284 { 285 public: 286 /** 287 * Default class constructor. 288 * 289 * @param[in] aInstance A reference to the OpenThread instance. 290 * 291 */ 292 explicit ResponsesQueue(Instance &aInstance); 293 294 /** 295 * Adds a given response to the cache. 296 * 297 * If matching response (the same Message ID, source endpoint address and port) exists in the cache given 298 * response is not added. 299 * 300 * The CoAP response is copied before it is added to the cache. 301 * 302 * @param[in] aMessage The CoAP response to add to the cache. 303 * @param[in] aMessageInfo The message info corresponding to @p aMessage. 304 * @param[in] aTxParameters Transmission parameters. 305 * 306 */ 307 void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const TxParameters &aTxParameters); 308 309 /** 310 * Removes all responses from the cache. 311 * 312 */ 313 void DequeueAllResponses(void); 314 315 /** 316 * Gets a copy of CoAP response from the cache that matches a given Message ID and source endpoint. 317 * 318 * @param[in] aRequest The CoAP message containing Message ID. 319 * @param[in] aMessageInfo The message info containing source endpoint address and port. 320 * @param[out] aResponse A pointer to return a copy of a cached CoAP response matching given arguments. 321 * 322 * @retval kErrorNone Matching response found and successfully created a copy. 323 * @retval kErrorNoBufs Matching response found but there is not sufficient buffer to create a copy. 324 * @retval kErrorNotFound Matching response not found. 325 * 326 */ 327 Error GetMatchedResponseCopy(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Message **aResponse); 328 329 /** 330 * Gets a reference to the cached CoAP responses queue. 331 * 332 * @returns A reference to the cached CoAP responses queue. 333 * 334 */ GetResponses(void) const335 const MessageQueue &GetResponses(void) const { return mQueue; } 336 337 private: 338 static constexpr uint16_t kMaxCachedResponses = OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES; 339 340 struct ResponseMetadata 341 { AppendToot::Coap::ResponsesQueue::ResponseMetadata342 Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } 343 void ReadFrom(const Message &aMessage); 344 345 TimeMilli mDequeueTime; 346 Ip6::MessageInfo mMessageInfo; 347 }; 348 349 const Message *FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const; 350 void DequeueResponse(Message &aMessage); 351 void UpdateQueue(void); 352 353 static void HandleTimer(Timer &aTimer); 354 void HandleTimer(void); 355 356 MessageQueue mQueue; 357 TimerMilliContext mTimer; 358 }; 359 360 /** 361 * Implements the CoAP client and server. 362 * 363 */ 364 class CoapBase : public InstanceLocator, private NonCopyable 365 { 366 friend class ResponsesQueue; 367 368 public: 369 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 370 static constexpr uint16_t kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH; 371 #endif 372 373 /** 374 * Pointer is called before CoAP server processing a CoAP message. 375 * 376 * @param[in] aMessage A reference to the message. 377 @ @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 378 * @param[in] aContext A pointer to arbitrary context information. 379 * 380 * @retval kErrorNone Server should continue processing this message, other return values indicates the 381 * server should stop processing this message. 382 * @retval kErrorNotTmf The message is not a TMF message. 383 * 384 */ 385 typedef Error (*Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext); 386 387 /** 388 * Clears requests and responses used by this CoAP agent. 389 * 390 */ 391 void ClearRequestsAndResponses(void); 392 393 /** 394 * Clears requests with specified source address used by this CoAP agent. 395 * 396 * @param[in] aAddress A reference to the specified address. 397 * 398 */ 399 void ClearRequests(const Ip6::Address &aAddress); 400 401 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 402 403 /** 404 * Adds a block-wise resource to the CoAP server. 405 * 406 * @param[in] aResource A reference to the resource. 407 * 408 */ 409 void AddBlockWiseResource(ResourceBlockWise &aResource); 410 411 /** 412 * Removes a block-wise resource from the CoAP server. 413 * 414 * @param[in] aResource A reference to the resource. 415 * 416 */ 417 void RemoveBlockWiseResource(ResourceBlockWise &aResource); 418 #endif 419 420 /** 421 * Adds a resource to the CoAP server. 422 * 423 * @param[in] aResource A reference to the resource. 424 * 425 */ 426 void AddResource(Resource &aResource); 427 428 /** 429 * Removes a resource from the CoAP server. 430 * 431 * @param[in] aResource A reference to the resource. 432 * 433 */ 434 void RemoveResource(Resource &aResource); 435 436 /* Sets the default handler for unhandled CoAP requests. 437 * 438 * @param[in] aHandler A function pointer that shall be called when an unhandled request arrives. 439 * @param[in] aContext A pointer to arbitrary context information. May be `nullptr` if not used. 440 * 441 */ SetDefaultHandler(RequestHandler aHandler,void * aContext)442 void SetDefaultHandler(RequestHandler aHandler, void *aContext) { mDefaultHandler.Set(aHandler, aContext); } 443 444 /** 445 * Allocates a new message with a CoAP header. 446 * 447 * @param[in] aSettings The message settings. 448 * 449 * @returns A pointer to the message or `nullptr` if failed to allocate message. 450 * 451 */ 452 Message *NewMessage(const Message::Settings &aSettings); 453 454 /** 455 * Allocates a new message with a CoAP header with default settings. 456 * 457 * @returns A pointer to the message or `nullptr` if failed to allocate message. 458 * 459 */ 460 Message *NewMessage(void); 461 462 /** 463 * Allocates a new message with a CoAP header that has Network Control priority level. 464 * 465 * @returns A pointer to the message or `nullptr` if failed to allocate message. 466 * 467 */ 468 Message *NewPriorityMessage(void); 469 470 /** 471 * Allocates and initializes a new CoAP Confirmable Post message with Network Control priority level. 472 * 473 * The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI path and a randomly 474 * generated token (of default length). This method also sets the payload marker (`SetPayloadMarker()` on message. 475 * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and 476 * remove the payload marker when there is no payload. 477 * 478 * @param[in] aUri The URI. 479 * 480 * @returns A pointer to the message or `nullptr` if failed to allocate message. 481 * 482 */ 483 Message *NewPriorityConfirmablePostMessage(Uri aUri); 484 485 /** 486 * Allocates and initializes a new CoAP Confirmable Post message with normal priority level. 487 * 488 * The CoAP header is initialized as `kTypeConfirmable` and `kCodePost` with a given URI and a randomly 489 * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`). 490 * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and 491 * remove the payload marker when there is no payload. 492 * 493 * @param[in] aUri The URI. 494 * 495 * @returns A pointer to the message or `nullptr` if failed to allocate message. 496 * 497 */ 498 Message *NewConfirmablePostMessage(Uri aUri); 499 500 /** 501 * Allocates and initializes a new CoAP Non-confirmable Post message with Network Control priority 502 * level. 503 * 504 * The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI and a randomly 505 * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`). 506 * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and 507 * remove the payload marker when there is no payload. 508 * 509 * @param[in] aUri The URI. 510 * 511 * @returns A pointer to the message or `nullptr` if failed to allocate message. 512 * 513 */ 514 Message *NewPriorityNonConfirmablePostMessage(Uri aUri); 515 516 /** 517 * Allocates and initializes a new CoAP Non-confirmable Post message with normal priority level. 518 * 519 * The CoAP header is initialized as `kTypeNonConfirmable` and `kCodePost` with a given URI and a randomly 520 * generated token (of default length). This method also sets the payload marker (calling `SetPayloadMarker()`). 521 * Even if message has no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and 522 * remove the payload marker when there is no payload. 523 * 524 * @param[in] aUri The URI. 525 * 526 * @returns A pointer to the message or `nullptr` if failed to allocate message. 527 * 528 */ 529 Message *NewNonConfirmablePostMessage(Uri aUri); 530 531 /** 532 * Allocates and initializes a new CoAP response message with Network Control priority level for a 533 * given request message. 534 * 535 * The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from 536 * @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has 537 * no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload 538 * marker when there is no payload. 539 * 540 * @returns A pointer to the message or `nullptr` if failed to allocate message. 541 * 542 */ 543 Message *NewPriorityResponseMessage(const Message &aRequest); 544 545 /** 546 * Allocates and initializes a new CoAP response message with regular priority level for a given 547 * request message. 548 * 549 * The CoAP header is initialized as `kTypeAck` with `kCodeChanged`. The token and message ID is copied from 550 * @p aRequest. This method also sets the payload marker (calling `SetPayloadMarker()`). Even if message has 551 * no payload, calling `SetPayloadMarker()` is harmless, since `SendMessage()` will check and remove the payload 552 * marker when there is no payload. 553 * 554 * @returns A pointer to the message or `nullptr` if failed to allocate message. 555 * 556 */ 557 Message *NewResponseMessage(const Message &aRequest); 558 559 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 560 /** 561 * Sends a CoAP message block-wise with custom transmission parameters. 562 * 563 * If a response for a request is expected, respective function and context information should be provided. 564 * If no response is expected, these arguments should be NULL pointers. 565 * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. 566 * 567 * @param[in] aMessage A reference to the message to send. 568 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 569 * @param[in] aTxParameters A reference to transmission parameters for this message. 570 * @param[in] aHandler A function pointer that shall be called on response reception or time-out. 571 * @param[in] aContext A pointer to arbitrary context information. 572 * @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer. 573 * @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer. 574 * 575 * @retval kErrorNone Successfully sent CoAP message. 576 * @retval kErrorNoBufs Failed to allocate retransmission data. 577 * 578 */ 579 Error SendMessage(Message &aMessage, 580 const Ip6::MessageInfo &aMessageInfo, 581 const TxParameters &aTxParameters, 582 otCoapResponseHandler aHandler = nullptr, 583 void *aContext = nullptr, 584 otCoapBlockwiseTransmitHook aTransmitHook = nullptr, 585 otCoapBlockwiseReceiveHook aReceiveHook = nullptr); 586 #else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 587 588 /** 589 * Sends a CoAP message with custom transmission parameters. 590 * 591 * If a response for a request is expected, respective function and context information should be provided. 592 * If no response is expected, these arguments should be `nullptr` pointers. 593 * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. 594 * 595 * @param[in] aMessage A reference to the message to send. 596 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 597 * @param[in] aTxParameters A reference to transmission parameters for this message. 598 * @param[in] aHandler A function pointer that shall be called on response reception or time-out. 599 * @param[in] aContext A pointer to arbitrary context information. 600 * 601 * @retval kErrorNone Successfully sent CoAP message. 602 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP message. 603 * 604 */ 605 Error SendMessage(Message &aMessage, 606 const Ip6::MessageInfo &aMessageInfo, 607 const TxParameters &aTxParameters, 608 ResponseHandler aHandler, 609 void *aContext); 610 #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 611 612 /** 613 * Sends a CoAP message with custom transmission parameters. 614 * 615 * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. 616 * 617 * @param[in] aMessage A reference to the message to send. 618 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 619 * @param[in] aTxParameters A reference to transmission parameters for this message. 620 * 621 * @retval kErrorNone Successfully sent CoAP message. 622 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP message. 623 * 624 */ 625 Error SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const TxParameters &aTxParameters); 626 /** 627 * Sends a CoAP message with default transmission parameters. 628 * 629 * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. 630 * 631 * @param[in] aMessage A reference to the message to send. 632 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 633 * @param[in] aHandler A function pointer that shall be called on response reception or time-out. 634 * @param[in] aContext A pointer to arbitrary context information. 635 * 636 * @retval kErrorNone Successfully sent CoAP message. 637 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 638 * 639 */ 640 Error SendMessage(Message &aMessage, 641 const Ip6::MessageInfo &aMessageInfo, 642 ResponseHandler aHandler, 643 void *aContext); 644 645 /** 646 * Sends a CoAP message with default transmission parameters. 647 * 648 * If Message ID was not set in the header (equal to 0), this method will assign unique Message ID to the message. 649 * 650 * @param[in] aMessage A reference to the message to send. 651 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 652 * 653 * @retval kErrorNone Successfully sent CoAP message. 654 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 655 * 656 */ 657 Error SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 658 659 /** 660 * Sends a CoAP reset message. 661 * 662 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 663 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 664 * 665 * @retval kErrorNone Successfully enqueued the CoAP response message. 666 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 667 * @retval kErrorInvalidArgs The @p aRequest is not of confirmable type. 668 * 669 */ 670 Error SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 671 672 /** 673 * Sends header-only CoAP response message. 674 * 675 * @param[in] aCode The CoAP code of this response. 676 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 677 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 678 * 679 * @retval kErrorNone Successfully enqueued the CoAP response message. 680 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 681 * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type. 682 * 683 */ 684 Error SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 685 686 /** 687 * Sends a CoAP ACK empty message which is used in Separate Response for confirmable requests. 688 * 689 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 690 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 691 * 692 * @retval kErrorNone Successfully enqueued the CoAP response message. 693 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 694 * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type. 695 * 696 */ 697 Error SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 698 699 /** 700 * Sends a CoAP ACK message on which a dummy CoAP response is piggybacked. 701 * 702 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 703 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 704 * @param[in] aCode The CoAP code of the dummy CoAP response. 705 * 706 * @retval kErrorNone Successfully enqueued the CoAP response message. 707 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 708 * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type. 709 * 710 */ 711 Error SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode); 712 713 /** 714 * Sends a CoAP ACK message on which a dummy CoAP response is piggybacked. 715 * 716 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 717 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 718 * 719 * @retval kErrorNone Successfully enqueued the CoAP response message. 720 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 721 * @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type. 722 * 723 */ 724 Error SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 725 726 /** 727 * Sends a header-only CoAP message to indicate no resource matched for the request. 728 * 729 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 730 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 731 * 732 * @retval kErrorNone Successfully enqueued the CoAP response message. 733 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 734 * 735 */ 736 Error SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 737 738 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 739 /** 740 * Sends a header-only CoAP message to indicate not all blocks have been sent or 741 * were sent out of order. 742 * 743 * @param[in] aRequest A reference to the CoAP Message that was used in CoAP request. 744 * @param[in] aMessageInfo The message info corresponding to the CoAP request. 745 * 746 * @retval kErrorNone Successfully enqueued the CoAP response message. 747 * @retval kErrorNoBufs Insufficient buffers available to send the CoAP response. 748 * 749 */ SendRequestEntityIncomplete(const Message & aRequest,const Ip6::MessageInfo & aMessageInfo)750 Error SendRequestEntityIncomplete(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) 751 { 752 return SendHeaderResponse(kCodeRequestIncomplete, aRequest, aMessageInfo); 753 } 754 #endif 755 756 /** 757 * Aborts CoAP transactions associated with given handler and context. 758 * 759 * The associated response handler will be called with kErrorAbort. 760 * 761 * @param[in] aHandler A function pointer that should be called when the transaction ends. 762 * @param[in] aContext A pointer to arbitrary context information. 763 * 764 * @retval kErrorNone Successfully aborted CoAP transactions. 765 * @retval kErrorNotFound CoAP transaction associated with given handler was not found. 766 * 767 */ 768 Error AbortTransaction(ResponseHandler aHandler, void *aContext); 769 770 /** 771 * Sets interceptor to be called before processing a CoAP packet. 772 * 773 * @param[in] aInterceptor A pointer to the interceptor. 774 * @param[in] aContext A pointer to arbitrary context information. 775 * 776 */ SetInterceptor(Interceptor aInterceptor,void * aContext)777 void SetInterceptor(Interceptor aInterceptor, void *aContext) { mInterceptor.Set(aInterceptor, aContext); } 778 779 /** 780 * Returns a reference to the request message list. 781 * 782 * @returns A reference to the request message list. 783 * 784 */ GetRequestMessages(void) const785 const MessageQueue &GetRequestMessages(void) const { return mPendingRequests; } 786 787 /** 788 * Returns a reference to the cached response list. 789 * 790 * @returns A reference to the cached response list. 791 * 792 */ GetCachedResponses(void) const793 const MessageQueue &GetCachedResponses(void) const { return mResponsesQueue.GetResponses(); } 794 795 protected: 796 /** 797 * Defines function pointer to handle a CoAP resource. 798 * 799 * When processing a received request, this handler is called first with the URI path before checking the list of 800 * added `Resource` entries to match against the URI path. 801 * 802 * @param[in] aCoapBase A reference the CoAP agent. 803 * @param[in] aUriPath The URI Path string. 804 * @param[in] aMessage The received message. 805 * @param[in] aMessageInfo The message info associated with @p aMessage. 806 * 807 * @retval TRUE Indicates that the URI path was known and the message was processed by the handler. 808 * @retval FALSE Indicates that URI path was not known and the message was not processed by the handler. 809 * 810 */ 811 typedef bool (*ResourceHandler)(CoapBase &aCoapBase, 812 const char *aUriPath, 813 Message &aMessage, 814 const Ip6::MessageInfo &aMessageInfo); 815 816 /** 817 * Pointer is called to send a CoAP message. 818 * 819 * @param[in] aCoapBase A reference to the CoAP agent. 820 * @param[in] aMessage A reference to the message to send. 821 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 822 * 823 * @retval kErrorNone Successfully sent CoAP message. 824 * @retval kErrorNoBufs Failed to allocate retransmission data. 825 * 826 */ 827 typedef Error (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 828 829 /** 830 * Initializes the object. 831 * 832 * @param[in] aInstance A reference to the OpenThread instance. 833 * @param[in] aSender A function pointer to send CoAP message, which SHOULD be a static 834 * member method of a descendant of this class. 835 * 836 */ 837 CoapBase(Instance &aInstance, Sender aSender); 838 839 /** 840 * Receives a CoAP message. 841 * 842 * @param[in] aMessage A reference to the received message. 843 * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. 844 * 845 */ 846 void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 847 848 /** 849 * Sets the resource handler function. 850 * 851 * @param[in] aHandler The resource handler function pointer. 852 * 853 */ SetResourceHandler(ResourceHandler aHandler)854 void SetResourceHandler(ResourceHandler aHandler) { mResourceHandler = aHandler; } 855 856 private: 857 struct Metadata 858 { AppendToot::Coap::CoapBase::Metadata859 Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } 860 void ReadFrom(const Message &aMessage); 861 void UpdateIn(Message &aMessage) const; 862 863 Ip6::Address mSourceAddress; // IPv6 address of the message source. 864 Ip6::Address mDestinationAddress; // IPv6 address of the message destination. 865 uint16_t mDestinationPort; // UDP port of the message destination. 866 ResponseHandler mResponseHandler; // A function pointer that is called on response reception. 867 void *mResponseContext; // A pointer to arbitrary context information. 868 TimeMilli mNextTimerShot; // Time when the timer should shoot for this message. 869 uint32_t mRetransmissionTimeout; // Delay that is applied to next retransmission. 870 uint8_t mRetransmissionsRemaining; // Number of retransmissions remaining. 871 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 872 uint8_t mHopLimit; // The hop limit. 873 #endif 874 bool mAcknowledged : 1; // Information that request was acknowledged. 875 bool mConfirmable : 1; // Information that message is confirmable. 876 bool mMulticastLoop : 1; // Information that multicast loop is enabled. 877 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE 878 bool mIsHostInterface : 1; // TRUE if packets sent/received via host interface, FALSE otherwise. 879 #endif 880 #if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE 881 bool mObserve : 1; // Information that this request involves Observations. 882 #endif 883 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 884 otCoapBlockwiseReceiveHook mBlockwiseReceiveHook; // Function pointer called on Block2 response reception. 885 otCoapBlockwiseTransmitHook mBlockwiseTransmitHook; // Function pointer called on Block1 response reception. 886 #endif 887 }; 888 889 Message *InitMessage(Message *aMessage, Type aType, Uri aUri); 890 Message *InitResponse(Message *aMessage, const Message &aResponse); 891 892 static void HandleRetransmissionTimer(Timer &aTimer); 893 void HandleRetransmissionTimer(void); 894 895 void ClearRequests(const Ip6::Address *aAddress); 896 Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata); 897 void DequeueMessage(Message &aMessage); 898 Message *FindRelatedRequest(const Message &aResponse, const Ip6::MessageInfo &aMessageInfo, Metadata &aMetadata); 899 void FinalizeCoapTransaction(Message &aRequest, 900 const Metadata &aMetadata, 901 Message *aResponse, 902 const Ip6::MessageInfo *aMessageInfo, 903 Error aResult); 904 905 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 906 void FreeLastBlockResponse(void); 907 Error CacheLastBlockResponse(Message *aResponse); 908 909 Error PrepareNextBlockRequest(Message::BlockType aType, 910 bool aMoreBlocks, 911 Message &aRequestOld, 912 Message &aRequest, 913 Message &aMessage); 914 Error ProcessBlock1Request(Message &aMessage, 915 const Ip6::MessageInfo &aMessageInfo, 916 const ResourceBlockWise &aResource, 917 uint32_t aTotalLength); 918 Error ProcessBlock2Request(Message &aMessage, 919 const Ip6::MessageInfo &aMessageInfo, 920 const ResourceBlockWise &aResource); 921 #endif 922 void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 923 void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 924 925 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 926 Error SendNextBlock1Request(Message &aRequest, 927 Message &aMessage, 928 const Ip6::MessageInfo &aMessageInfo, 929 const Metadata &aCoapMetadata); 930 Error SendNextBlock2Request(Message &aRequest, 931 Message &aMessage, 932 const Ip6::MessageInfo &aMessageInfo, 933 const Metadata &aCoapMetadata, 934 uint32_t aTotalLength, 935 bool aBeginBlock1Transfer); 936 #endif 937 void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 938 Error SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo); 939 940 Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 941 942 MessageQueue mPendingRequests; 943 uint16_t mMessageId; 944 TimerMilliContext mRetransmissionTimer; 945 946 LinkedList<Resource> mResources; 947 948 Callback<Interceptor> mInterceptor; 949 ResponsesQueue mResponsesQueue; 950 951 Callback<RequestHandler> mDefaultHandler; 952 953 ResourceHandler mResourceHandler; 954 955 const Sender mSender; 956 957 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 958 LinkedList<ResourceBlockWise> mBlockWiseResources; 959 Message *mLastResponse; 960 #endif 961 }; 962 963 /** 964 * Implements the CoAP client and server. 965 * 966 */ 967 class Coap : public CoapBase 968 { 969 public: 970 /** 971 * Initializes the object. 972 * 973 * @param[in] aInstance A reference to the OpenThread instance. 974 * 975 */ 976 explicit Coap(Instance &aInstance); 977 978 /** 979 * Starts the CoAP service. 980 * 981 * @param[in] aPort The local UDP port to bind to. 982 * @param[in] aNetifIdentifier The network interface identifier to bind. 983 * 984 * @retval kErrorNone Successfully started the CoAP service. 985 * @retval kErrorFailed Failed to start CoAP agent. 986 * 987 */ 988 Error Start(uint16_t aPort, Ip6::NetifIdentifier aNetifIdentifier = Ip6::kNetifUnspecified); 989 990 /** 991 * Stops the CoAP service. 992 * 993 * @retval kErrorNone Successfully stopped the CoAP service. 994 * @retval kErrorFailed Failed to stop CoAP agent. 995 * 996 */ 997 Error Stop(void); 998 999 protected: 1000 Ip6::Udp::Socket mSocket; 1001 1002 private: 1003 static Error Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 1004 static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); 1005 Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); 1006 }; 1007 1008 } // namespace Coap 1009 1010 DefineCoreType(otCoapTxParameters, Coap::TxParameters); 1011 DefineCoreType(otCoapResource, Coap::Resource); 1012 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE 1013 DefineCoreType(otCoapBlockwiseResource, Coap::ResourceBlockWise); 1014 #endif 1015 1016 } // namespace ot 1017 1018 #endif // COAP_HPP_ 1019