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