blob: d2bd0a8f7b1cf5b35cd042c15305f361c5f72866 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COAP_HPP_
#define COAP_HPP_
#include "openthread-core-config.h"
#include <openthread/coap.h>
#include "coap/coap_message.hpp"
#include "common/as_core_type.hpp"
#include "common/debug.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
#include "common/timer.hpp"
#include "net/ip6.hpp"
#include "net/netif.hpp"
#include "net/udp6.hpp"
/**
* @file
* This file includes definitions for CoAP client and server functionality.
*/
namespace ot {
namespace Coap {
/**
* @addtogroup core-coap
*
* @{
*
*/
/**
* This type represents a function pointer which is called when a CoAP response is received or on the request timeout.
*
* Please see otCoapResponseHandler for details.
*
*/
typedef otCoapResponseHandler ResponseHandler;
/**
* This type represents a function pointer which is called when a CoAP request associated with a given URI path is
* received.
*
* Please see otCoapRequestHandler for details.
*
*/
typedef otCoapRequestHandler RequestHandler;
/**
* This structure represents the CoAP transmission parameters.
*
*/
class TxParameters : public otCoapTxParameters
{
friend class CoapBase;
friend class ResponsesQueue;
public:
/**
* This static method coverts a pointer to `otCoapTxParameters` to `Coap::TxParamters`
*
* If the pointer is `nullptr`, the default parameters are used instead.
*
* @param[in] aTxParameters A pointer to tx parameter.
*
* @returns A reference to corresponding `TxParamters` if @p aTxParameters is not `nullptr`, otherwise the default
* tx parameters.
*
*/
static const TxParameters &From(const otCoapTxParameters *aTxParameters)
{
return aTxParameters ? *static_cast<const TxParameters *>(aTxParameters) : GetDefault();
}
/**
* This method validates whether the CoAP transmission parameters are valid.
*
* @returns Whether the parameters are valid.
*
*/
bool IsValid(void) const;
/**
* This static method returns default CoAP tx parameters.
*
* @returns The default tx parameters.
*
*/
static const TxParameters &GetDefault(void) { return static_cast<const TxParameters &>(kDefaultTxParameters); }
private:
static constexpr uint32_t kDefaultAckTimeout = 2000; // in msec
static constexpr uint8_t kDefaultAckRandomFactorNumerator = 3;
static constexpr uint8_t kDefaultAckRandomFactorDenominator = 2;
static constexpr uint8_t kDefaultMaxRetransmit = 4;
static constexpr uint32_t kDefaultMaxLatency = 100000; // in msec
uint32_t CalculateInitialRetransmissionTimeout(void) const;
uint32_t CalculateExchangeLifetime(void) const;
uint32_t CalculateMaxTransmitWait(void) const;
uint32_t CalculateSpan(uint8_t aMaxRetx) const;
static const otCoapTxParameters kDefaultTxParameters;
};
/**
* This class implements CoAP resource handling.
*
*/
class Resource : public otCoapResource, public LinkedListEntry<Resource>
{
friend class CoapBase;
public:
/**
* This constructor initializes the resource.
*
* @param[in] aUriPath A pointer to a null-terminated string for the URI path.
* @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath.
* @param[in] aContext A pointer to arbitrary context information.
*/
Resource(const char *aUriPath, RequestHandler aHandler, void *aContext)
{
mUriPath = aUriPath;
mHandler = aHandler;
mContext = aContext;
mNext = nullptr;
}
/**
* This method returns a pointer to the URI path.
*
* @returns A pointer to the URI path.
*
*/
const char *GetUriPath(void) const { return mUriPath; }
protected:
void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This class implements CoAP block-wise resource handling.
*
*/
class ResourceBlockWise : public otCoapBlockwiseResource
{
friend class CoapBase;
public:
/**
* This constructor initializes the resource.
*
* @param[in] aUriPath A pointer to a NULL-terminated string for the Uri-Path.
* @param[in] aHandler A function pointer that is called when receiving a CoAP message for @p aUriPath.
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aReceiveHook A function pointer that is called when receiving a CoAP block message for @p
* aUriPath.
* @param[in] aTransmitHook A function pointer that is called when transmitting a CoAP block message from @p
* aUriPath.
*/
ResourceBlockWise(const char * aUriPath,
otCoapRequestHandler aHandler,
void * aContext,
otCoapBlockwiseReceiveHook aReceiveHook,
otCoapBlockwiseTransmitHook aTransmitHook)
{
mUriPath = aUriPath;
mHandler = aHandler;
mContext = aContext;
mReceiveHook = aReceiveHook;
mTransmitHook = aTransmitHook;
mNext = nullptr;
}
Error HandleBlockReceive(const uint8_t *aBlock,
uint32_t aPosition,
uint16_t aBlockLength,
bool aMore,
uint32_t aTotalLength) const
{
return mReceiveHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore, aTotalLength);
}
Error HandleBlockTransmit(uint8_t *aBlock, uint32_t aPosition, uint16_t *aBlockLength, bool *aMore) const
{
return mTransmitHook(otCoapBlockwiseResource::mContext, aBlock, aPosition, aBlockLength, aMore);
}
/**
* This method gets the next entry in the linked list.
*
* @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
*
*/
const ResourceBlockWise *GetNext(void) const
{
return static_cast<const ResourceBlockWise *>(static_cast<const ResourceBlockWise *>(this)->mNext);
}
/**
* This method gets the next entry in the linked list.
*
* @returns A pointer to the next entry in the linked list or `nullptr` if at the end of the list.
*
*/
ResourceBlockWise *GetNext(void)
{
return static_cast<ResourceBlockWise *>(static_cast<ResourceBlockWise *>(this)->mNext);
}
/**
* This method sets the next pointer on the entry.
*
* @param[in] aNext A pointer to the next entry.
*
*/
void SetNext(ResourceBlockWise *aNext) { static_cast<ResourceBlockWise *>(this)->mNext = aNext; }
/**
* This method returns a pointer to the URI path.
*
* @returns A pointer to the URI path.
*
*/
const char *GetUriPath(void) const { return mUriPath; }
protected:
void HandleRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
mHandler(mContext, &aMessage, &aMessageInfo);
}
};
#endif
/**
* This class caches CoAP responses to implement message deduplication.
*
*/
class ResponsesQueue
{
public:
/**
* Default class constructor.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit ResponsesQueue(Instance &aInstance);
/**
* This method adds a given response to the cache.
*
* If matching response (the same Message ID, source endpoint address and port) exists in the cache given
* response is not added.
*
* The CoAP response is copied before it is added to the cache.
*
* @param[in] aMessage The CoAP response to add to the cache.
* @param[in] aMessageInfo The message info corresponding to @p aMessage.
* @param[in] aTxParameters Transmission parameters.
*
*/
void EnqueueResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo, const TxParameters &aTxParameters);
/**
* This method removes all responses from the cache.
*
*/
void DequeueAllResponses(void);
/**
* This method gets a copy of CoAP response from the cache that matches a given Message ID and source endpoint.
*
* @param[in] aRequest The CoAP message containing Message ID.
* @param[in] aMessageInfo The message info containing source endpoint address and port.
* @param[out] aResponse A pointer to return a copy of a cached CoAP response matching given arguments.
*
* @retval kErrorNone Matching response found and successfully created a copy.
* @retval kErrorNoBufs Matching response found but there is not sufficient buffer to create a copy.
* @retval kErrorNotFound Matching response not found.
*
*/
Error GetMatchedResponseCopy(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Message **aResponse);
/**
* This method gets a reference to the cached CoAP responses queue.
*
* @returns A reference to the cached CoAP responses queue.
*
*/
const MessageQueue &GetResponses(void) const { return mQueue; }
private:
static constexpr uint16_t kMaxCachedResponses = OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES;
struct ResponseMetadata
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
TimeMilli mDequeueTime;
Ip6::MessageInfo mMessageInfo;
};
const Message *FindMatchedResponse(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) const;
void DequeueResponse(Message &aMessage);
void UpdateQueue(void);
static void HandleTimer(Timer &aTimer);
void HandleTimer(void);
MessageQueue mQueue;
TimerMilliContext mTimer;
};
/**
* This class implements the CoAP client and server.
*
*/
class CoapBase : public InstanceLocator, private NonCopyable
{
friend class ResponsesQueue;
public:
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
static constexpr uint16_t kMaxBlockLength = OPENTHREAD_CONFIG_COAP_MAX_BLOCK_LENGTH;
#endif
/**
* This function pointer is called before CoAP server processing a CoAP message.
*
* @param[in] aMessage A reference to the message.
@ @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Server should continue processing this message, other return values indicates the
* server should stop processing this message.
* @retval kErrorNotTmf The message is not a TMF message.
*
*/
typedef Error (*Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext);
/**
* This method clears requests and responses used by this CoAP agent.
*
*/
void ClearRequestsAndResponses(void);
/**
* This method clears requests with specified source address used by this CoAP agent.
*
* @param[in] aAddress A reference to the specified address.
*
*/
void ClearRequests(const Ip6::Address &aAddress);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method adds a block-wise resource to the CoAP server.
*
* @param[in] aResource A reference to the resource.
*
*/
void AddBlockWiseResource(ResourceBlockWise &aResource);
/**
* This method removes a block-wise resource from the CoAP server.
*
* @param[in] aResource A reference to the resource.
*
*/
void RemoveBlockWiseResource(ResourceBlockWise &aResource);
#endif
/**
* This method adds a resource to the CoAP server.
*
* @param[in] aResource A reference to the resource.
*
*/
void AddResource(Resource &aResource);
/**
* This method removes a resource from the CoAP server.
*
* @param[in] aResource A reference to the resource.
*
*/
void RemoveResource(Resource &aResource);
/* This method sets the default handler for unhandled CoAP requests.
*
* @param[in] aHandler A function pointer that shall be called when an unhandled request arrives.
* @param[in] aContext A pointer to arbitrary context information. May be `nullptr` if not used.
*
*/
void SetDefaultHandler(RequestHandler aHandler, void *aContext);
/**
* This method creates a new message with a CoAP header.
*
* @param[in] aSettings The message settings.
*
* @returns A pointer to the message or `nullptr` if failed to allocate message.
*
*/
Message *NewMessage(const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method creates a new message with a CoAP header that has Network Control priority level.
*
* @returns A pointer to the message or `nullptr` if failed to allocate message.
*
*/
Message *NewPriorityMessage(void)
{
return NewMessage(Message::Settings(Message::kWithLinkSecurity, Message::kPriorityNet));
}
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a CoAP message block-wise with custom transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be NULL pointers.
* If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
*
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aTxParameters A reference to transmission parameters for this message.
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aTransmitHook A pointer to a hook function for outgoing block-wise transfer.
* @param[in] aReceiveHook A pointer to a hook function for incoming block-wise transfer.
*
* @retval kErrorNone Successfully sent CoAP message.
* @retval kErrorNoBufs Failed to allocate retransmission data.
*
*/
Error SendMessage(Message & aMessage,
const Ip6::MessageInfo & aMessageInfo,
const TxParameters & aTxParameters,
otCoapResponseHandler aHandler = nullptr,
void * aContext = nullptr,
otCoapBlockwiseTransmitHook aTransmitHook = nullptr,
otCoapBlockwiseReceiveHook aReceiveHook = nullptr);
#else // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a CoAP message with custom transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be `nullptr` pointers.
* If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
*
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aTxParameters A reference to transmission parameters for this message.
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Successfully sent CoAP message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP message.
*
*/
Error SendMessage(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const TxParameters & aTxParameters,
ResponseHandler aHandler = nullptr,
void * aContext = nullptr);
#endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a CoAP message with default transmission parameters.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be `nullptr` pointers.
* If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
*
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Successfully sent CoAP message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*
*/
Error SendMessage(Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
ResponseHandler aHandler = nullptr,
void * aContext = nullptr);
/**
* This method sends a CoAP reset message.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRequest is not of confirmable type.
*
*/
Error SendReset(Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends header-only CoAP response message.
*
* @param[in] aCode The CoAP code of this response.
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
Error SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends a CoAP ACK empty message which is used in Separate Response for confirmable requests.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
Error SendAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sends a CoAP ACK message on which a dummy CoAP response is piggybacked.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
* @param[in] aCode The CoAP code of the dummy CoAP response.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
* @retval kErrorInvalidArgs The @p aRequest header is not of confirmable type.
*
*/
Error SendEmptyAck(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo, Code aCode = kCodeChanged);
/**
* This method sends a header-only CoAP message to indicate no resource matched for the request.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*
*/
Error SendNotFound(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
/**
* This method sends a header-only CoAP message to indicate not all blocks have been sent or
* were sent out of order.
*
* @param[in] aRequest A reference to the CoAP Message that was used in CoAP request.
* @param[in] aMessageInfo The message info corresponding to the CoAP request.
*
* @retval kErrorNone Successfully enqueued the CoAP response message.
* @retval kErrorNoBufs Insufficient buffers available to send the CoAP response.
*
*/
Error SendRequestEntityIncomplete(const Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
{
return SendHeaderResponse(kCodeRequestIncomplete, aRequest, aMessageInfo);
}
#endif
/**
* This method aborts CoAP transactions associated with given handler and context.
*
* The associated response handler will be called with kErrorAbort.
*
* @param[in] aHandler A function pointer that should be called when the transaction ends.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kErrorNone Successfully aborted CoAP transactions.
* @retval kErrorNotFound CoAP transaction associated with given handler was not found.
*
*/
Error AbortTransaction(ResponseHandler aHandler, void *aContext);
/**
* This method sets interceptor to be called before processing a CoAP packet.
*
* @param[in] aInterceptor A pointer to the interceptor.
* @param[in] aContext A pointer to arbitrary context information.
*
*/
void SetInterceptor(Interceptor aInterceptor, void *aContext);
/**
* This method returns a reference to the request message list.
*
* @returns A reference to the request message list.
*
*/
const MessageQueue &GetRequestMessages(void) const { return mPendingRequests; }
/**
* This method returns a reference to the cached response list.
*
* @returns A reference to the cached response list.
*
*/
const MessageQueue &GetCachedResponses(void) const { return mResponsesQueue.GetResponses(); }
protected:
/**
* This function pointer is called to send a CoAP message.
*
* @param[in] aCoapBase A reference to the CoAP agent.
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
* @retval kErrorNone Successfully sent CoAP message.
* @retval kErrorNoBufs Failed to allocate retransmission data.
*
*/
typedef Error (*Sender)(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aSender A function pointer to send CoAP message, which SHOULD be a static
* member method of a descendant of this class.
*
*/
CoapBase(Instance &aInstance, Sender aSender);
/**
* This method receives a CoAP message.
*
* @param[in] aMessage A reference to the received message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
struct Metadata
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
void UpdateIn(Message &aMessage) const;
Ip6::Address mSourceAddress; // IPv6 address of the message source.
Ip6::Address mDestinationAddress; // IPv6 address of the message destination.
uint16_t mDestinationPort; // UDP port of the message destination.
ResponseHandler mResponseHandler; // A function pointer that is called on response reception.
void * mResponseContext; // A pointer to arbitrary context information.
TimeMilli mNextTimerShot; // Time when the timer should shoot for this message.
uint32_t mRetransmissionTimeout; // Delay that is applied to next retransmission.
uint8_t mRetransmissionsRemaining; // Number of retransmissions remaining.
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
uint8_t mHopLimit; // The hop limit.
#endif
bool mAcknowledged : 1; // Information that request was acknowledged.
bool mConfirmable : 1; // Information that message is confirmable.
bool mMulticastLoop : 1; // Information that multicast loop is enabled.
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
bool mIsHostInterface : 1; // TRUE if packets sent/received via host interface, FALSE otherwise.
#endif
#if OPENTHREAD_CONFIG_COAP_OBSERVE_API_ENABLE
bool mObserve : 1; // Information that this request involves Observations.
#endif
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
otCoapBlockwiseReceiveHook mBlockwiseReceiveHook; // Function pointer called on Block2 response reception.
otCoapBlockwiseTransmitHook mBlockwiseTransmitHook; // Function pointer called on Block1 response reception.
#endif
};
static void HandleRetransmissionTimer(Timer &aTimer);
void HandleRetransmissionTimer(void);
void ClearRequests(const Ip6::Address *aAddress);
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const Metadata &aMetadata);
void DequeueMessage(Message &aMessage);
Message *FindRelatedRequest(const Message &aResponse, const Ip6::MessageInfo &aMessageInfo, Metadata &aMetadata);
void FinalizeCoapTransaction(Message & aRequest,
const Metadata & aMetadata,
Message * aResponse,
const Ip6::MessageInfo *aMessageInfo,
Error aResult);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
void FreeLastBlockResponse(void);
Error CacheLastBlockResponse(Message *aResponse);
Error PrepareNextBlockRequest(Message::BlockType aType,
bool aMoreBlocks,
Message & aRequestOld,
Message & aRequest,
Message & aMessage);
Error ProcessBlock1Request(Message & aMessage,
const Ip6::MessageInfo & aMessageInfo,
const ResourceBlockWise &aResource,
uint32_t aTotalLength);
Error ProcessBlock2Request(Message & aMessage,
const Ip6::MessageInfo & aMessageInfo,
const ResourceBlockWise &aResource);
#endif
void ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
Error SendNextBlock1Request(Message & aRequest,
Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata & aCoapMetadata);
Error SendNextBlock2Request(Message & aRequest,
Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Metadata & aCoapMetadata,
uint32_t aTotalLength,
bool aBeginBlock1Transfer);
#endif
void SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
Error SendEmptyMessage(Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo);
Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
MessageQueue mPendingRequests;
uint16_t mMessageId;
TimerMilliContext mRetransmissionTimer;
LinkedList<Resource> mResources;
void * mContext;
Interceptor mInterceptor;
ResponsesQueue mResponsesQueue;
RequestHandler mDefaultHandler;
void * mDefaultHandlerContext;
const Sender mSender;
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
LinkedList<ResourceBlockWise> mBlockWiseResources;
Message * mLastResponse;
#endif
};
/**
* This class implements the CoAP client and server.
*
*/
class Coap : public CoapBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Coap(Instance &aInstance);
/**
* This method starts the CoAP service.
*
* @param[in] aPort The local UDP port to bind to.
* @param[in] aNetifIdentifier The network interface identifier to bind.
*
* @retval kErrorNone Successfully started the CoAP service.
* @retval kErrorFailed Failed to start CoAP agent.
*
*/
Error Start(uint16_t aPort, otNetifIdentifier aNetifIdentifier = OT_NETIF_UNSPECIFIED);
/**
* This method stops the CoAP service.
*
* @retval kErrorNone Successfully stopped the CoAP service.
* @retval kErrorFailed Failed to stop CoAP agent.
*
*/
Error Stop(void);
protected:
Ip6::Udp::Socket mSocket;
private:
static Error Send(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
Error Send(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
};
} // namespace Coap
DefineCoreType(otCoapTxParameters, Coap::TxParameters);
DefineCoreType(otCoapResource, Coap::Resource);
#if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
DefineCoreType(otCoapBlockwiseResource, Coap::ResourceBlockWise);
#endif
} // namespace ot
#endif // COAP_HPP_