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