diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 57da1d45c..04c6a617d 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -48,9 +48,8 @@ namespace ot { namespace Coap { -Coap::Coap(Instance &aInstance) +CoapBase::CoapBase(Instance &aInstance, Sender aSender) : InstanceLocator(aInstance) - , mSocket(aInstance.GetThreadNetif().GetIp6().GetUdp()) , mRetransmissionTimer(aInstance, &Coap::HandleRetransmissionTimer, this) , mResources(NULL) , mContext(NULL) @@ -58,24 +57,12 @@ Coap::Coap(Instance &aInstance) , mResponsesQueue(aInstance) , mDefaultHandler(NULL) , mDefaultHandlerContext(NULL) + , mSender(aSender) { mMessageId = Random::GetUint16(); } -otError Coap::Start(uint16_t aPort) -{ - otError error; - Ip6::SockAddr sockaddr; - sockaddr.mPort = aPort; - - SuccessOrExit(error = mSocket.Open(&Coap::HandleUdpReceive, this)); - SuccessOrExit(error = mSocket.Bind(sockaddr)); - -exit: - return error; -} - -otError Coap::Stop(void) +void CoapBase::ClearRequestsAndResponses(void) { Message * message = static_cast(mPendingRequests.GetHead()); Message * messageToRemove; @@ -92,11 +79,9 @@ otError Coap::Stop(void) } mResponsesQueue.DequeueAllResponses(); - - return mSocket.Close(); } -otError Coap::AddResource(Resource &aResource) +otError CoapBase::AddResource(Resource &aResource) { otError error = OT_ERROR_NONE; @@ -112,7 +97,7 @@ exit: return error; } -void Coap::RemoveResource(Resource &aResource) +void CoapBase::RemoveResource(Resource &aResource) { if (mResources == &aResource) { @@ -134,27 +119,27 @@ exit: aResource.mNext = NULL; } -void Coap::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext) +void CoapBase::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext) { mDefaultHandler = aHandler; mDefaultHandlerContext = aContext; } -Message *Coap::NewMessage(const otMessageSettings *aSettings) +Message *CoapBase::NewMessage(const otMessageSettings *aSettings) { Message *message = NULL; - VerifyOrExit((message = static_cast(mSocket.NewMessage(0, aSettings))) != NULL); + VerifyOrExit((message = static_cast(GetInstance().GetIp6().GetUdp().NewMessage(0, aSettings))) != NULL); message->SetOffset(0); exit: return message; } -otError Coap::SendMessage(Message & aMessage, - const Ip6::MessageInfo &aMessageInfo, - otCoapResponseHandler aHandler, - void * aContext) +otError CoapBase::SendMessage(Message & aMessage, + const Ip6::MessageInfo &aMessageInfo, + otCoapResponseHandler aHandler, + void * aContext) { otError error; CoapMetadata coapMetadata; @@ -206,13 +191,13 @@ exit: return error; } -otError Coap::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +otError CoapBase::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { static_cast(aMessage).Finish(); - return mSocket.SendTo(aMessage, aMessageInfo); + return mSender(*this, aMessage, aMessageInfo); } -otError Coap::SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) +otError CoapBase::SendEmptyMessage(Message::Type aType, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { otError error = OT_ERROR_NONE; Message *message = NULL; @@ -236,7 +221,7 @@ exit: return error; } -otError Coap::SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) +otError CoapBase::SendHeaderResponse(Message::Code aCode, const Message &aRequest, const Ip6::MessageInfo &aMessageInfo) { otError error = OT_ERROR_NONE; Message *message = NULL; @@ -275,12 +260,12 @@ exit: return error; } -void Coap::HandleRetransmissionTimer(Timer &aTimer) +void CoapBase::HandleRetransmissionTimer(Timer &aTimer) { static_cast(static_cast(aTimer).GetContext())->HandleRetransmissionTimer(); } -void Coap::HandleRetransmissionTimer(void) +void CoapBase::HandleRetransmissionTimer(void) { uint32_t now = TimerMilli::GetNow(); uint32_t nextDelta = 0xffffffff; @@ -342,11 +327,11 @@ void Coap::HandleRetransmissionTimer(void) } } -void Coap::FinalizeCoapTransaction(Message & aRequest, - const CoapMetadata & aCoapMetadata, - Message * aResponse, - const Ip6::MessageInfo *aMessageInfo, - otError aResult) +void CoapBase::FinalizeCoapTransaction(Message & aRequest, + const CoapMetadata & aCoapMetadata, + Message * aResponse, + const Ip6::MessageInfo *aMessageInfo, + otError aResult) { DequeueMessage(aRequest); @@ -356,7 +341,7 @@ void Coap::FinalizeCoapTransaction(Message & aRequest, } } -otError Coap::AbortTransaction(otCoapResponseHandler aHandler, void *aContext) +otError CoapBase::AbortTransaction(otCoapResponseHandler aHandler, void *aContext) { otError error = OT_ERROR_NOT_FOUND; Message * message; @@ -378,7 +363,9 @@ otError Coap::AbortTransaction(otCoapResponseHandler aHandler, void *aContext) return error; } -Message *Coap::CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const CoapMetadata &aCoapMetadata) +Message *CoapBase::CopyAndEnqueueMessage(const Message & aMessage, + uint16_t aCopyLength, + const CoapMetadata &aCoapMetadata) { otError error = OT_ERROR_NONE; Message *messageCopy = NULL; @@ -420,7 +407,7 @@ exit: return messageCopy; } -void Coap::DequeueMessage(Message &aMessage) +void CoapBase::DequeueMessage(Message &aMessage) { mPendingRequests.Dequeue(aMessage); @@ -437,7 +424,7 @@ void Coap::DequeueMessage(Message &aMessage) // the timer would just shoot earlier and then it'd be setup again. } -otError Coap::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +otError CoapBase::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { otError error; Message *messageCopy = NULL; @@ -459,9 +446,9 @@ exit: return error; } -Message *Coap::FindRelatedRequest(const Message & aResponse, - const Ip6::MessageInfo &aMessageInfo, - CoapMetadata & aCoapMetadata) +Message *CoapBase::FindRelatedRequest(const Message & aResponse, + const Ip6::MessageInfo &aMessageInfo, + CoapMetadata & aCoapMetadata) { Message *message = static_cast(mPendingRequests.GetHead()); @@ -503,13 +490,7 @@ exit: return message; } -void Coap::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) -{ - static_cast(aContext)->Receive(*static_cast(aMessage), - *static_cast(aMessageInfo)); -} - -void Coap::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void CoapBase::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Message &message = static_cast(aMessage); @@ -527,7 +508,7 @@ void Coap::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) } } -void Coap::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void CoapBase::ProcessReceivedResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { CoapMetadata coapMetadata; Message * request = NULL; @@ -602,7 +583,7 @@ exit: } } -void Coap::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void CoapBase::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { char uriPath[Resource::kMaxReceivedUriPath]; char * curUriPath = uriPath; @@ -866,5 +847,46 @@ uint32_t EnqueuedResponseHeader::GetRemainingTime(void) const return remainingTime >= 0 ? static_cast(remainingTime) : 0; } +Coap::Coap(Instance &aInstance) + : CoapBase(aInstance, &Coap::Send) + , mSocket(aInstance.GetIp6().GetUdp()) +{ +} + +otError Coap::Start(uint16_t aPort) +{ + otError error; + Ip6::SockAddr sockaddr; + + sockaddr.mPort = aPort; + SuccessOrExit(error = mSocket.Open(&Coap::HandleUdpReceive, this)); + VerifyOrExit((error = mSocket.Bind(sockaddr)) == OT_ERROR_NONE, mSocket.Close()); + +exit: + return error; +} + +otError Coap::Stop(void) +{ + otError error; + + SuccessOrExit(error = mSocket.Close()); + ClearRequestsAndResponses(); + +exit: + return error; +} + +void Coap::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) +{ + static_cast(aContext)->Receive(*static_cast(aMessage), + *static_cast(aMessageInfo)); +} + +otError Coap::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +{ + return mSocket.SendTo(aMessage, aMessageInfo); +} + } // namespace Coap } // namespace ot diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 79b3073d4..8c84cde1f 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -91,7 +91,7 @@ enum OT_TOOL_PACKED_BEGIN class CoapMetadata { - friend class Coap; + friend class CoapBase; public: /** @@ -198,7 +198,7 @@ private: */ class Resource : public otCoapResource { - friend class Coap; + friend class CoapBase; public: enum @@ -426,11 +426,24 @@ private: * This class implements the CoAP client and server. * */ -class Coap : public InstanceLocator +class CoapBase : public InstanceLocator { friend class ResponsesQueue; public: + /** + * 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 OT_ERROR_NONE Successfully sent CoAP message. + * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data. + * + */ + typedef otError (*Sender)(CoapBase &aCoapBase, Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + /** * This function pointer is called before CoAP server processing a CoAP packets. * @@ -447,30 +460,10 @@ public: typedef otError (*Interceptor)(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, void *aContext); /** - * This constructor initializes the object. - * - * @param[in] aInstance A reference to the OpenThread instance. + * This method clears requests and responses used by this CoAP agent. * */ - explicit Coap(Instance &aInstance); - - /** - * This method starts the CoAP service. - * - * @param[in] aPort The local UDP port to bind to. - * - * @retval OT_ERROR_NONE Successfully started the CoAP service. - * - */ - otError Start(uint16_t aPort); - - /** - * This method stops the CoAP service. - * - * @retval OT_ERROR_NONE Successfully stopped the CoAP service. - * - */ - otError Stop(void); + void ClearRequestsAndResponses(void); /** * This method adds a resource to the CoAP server. @@ -656,31 +649,40 @@ public: protected: /** - * This method sends a message. + * 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 descendent of this class. + * + */ + explicit CoapBase(Instance &aInstance, Sender aSender); + + /** + * This method sends a CoAP message. * * @param[in] aMessage A reference to the message to send. * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. * + * @retval OT_ERROR_NONE Successfully sent CoAP message. + * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data. + * */ - virtual otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); /** - * This method receives a message. + * 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. * */ - virtual void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); - - Ip6::UdpSocket mSocket; + void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); private: static void HandleRetransmissionTimer(Timer &aTimer); void HandleRetransmissionTimer(void); - static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); - Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength, const CoapMetadata &aCoapMetadata); void DequeueMessage(Message &aMessage); Message *FindRelatedRequest(const Message & aResponse, @@ -710,6 +712,55 @@ private: otCoapRequestHandler mDefaultHandler; void * mDefaultHandlerContext; + + Sender mSender; +}; + +/** + * 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. + * + * @retval OT_ERROR_NONE Successfully started the CoAP service. + * @retval OT_ERROR_ALREADY Already started. + * + */ + otError Start(uint16_t aPort); + + /** + * This method stops the CoAP service. + * + * @retval OT_ERROR_NONE Successfully stopped the CoAP service. + * @retval OT_ERROR_FAILED Failed to stop CoAP agent. + * + */ + otError Stop(void); + +private: + static otError Send(CoapBase &aCoapBase, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) + { + return static_cast(aCoapBase).Send(aMessage, aMessageInfo); + } + otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + + static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); + + Ip6::UdpSocket mSocket; }; } // namespace Coap diff --git a/src/core/coap/coap_secure.cpp b/src/core/coap/coap_secure.cpp index 342333509..d1dc408b4 100644 --- a/src/core/coap/coap_secure.cpp +++ b/src/core/coap/coap_secure.cpp @@ -48,13 +48,14 @@ namespace ot { namespace Coap { CoapSecure::CoapSecure(Instance &aInstance, bool aLayerTwoSecurity) - : Coap(aInstance) + : CoapBase(aInstance, &CoapSecure::Send) , mConnectedCallback(NULL) , mConnectedContext(NULL) , mTransportCallback(NULL) , mTransportContext(NULL) , mTransmitQueue() , mTransmitTask(aInstance, &CoapSecure::HandleTransmit, this) + , mSocket(aInstance.GetThreadNetif().GetIp6().GetUdp()) , mLayerTwoSecurity(aLayerTwoSecurity) { } @@ -71,9 +72,14 @@ otError CoapSecure::Start(uint16_t aPort, TransportCallback aCallback, void *aCo // to transmit/receive messages, so do not open it in that case. if (mTransportCallback == NULL) { - error = Coap::Start(aPort); + Ip6::SockAddr sockaddr; + + sockaddr.mPort = aPort; + SuccessOrExit(error = mSocket.Open(&CoapSecure::HandleUdpReceive, this)); + VerifyOrExit((error = mSocket.Bind(sockaddr)) == OT_ERROR_NONE, mSocket.Close()); } +exit: return error; } @@ -85,6 +91,10 @@ void CoapSecure::SetConnectedCallback(ConnectedCallback aCallback, void *aContex otError CoapSecure::Stop(void) { + otError error; + + SuccessOrExit(error = mSocket.Close()); + if (IsConnectionActive()) { Disconnect(); @@ -99,7 +109,10 @@ otError CoapSecure::Stop(void) mTransportCallback = NULL; mTransportContext = NULL; - return Coap::Stop(); + ClearRequestsAndResponses(); + +exit: + return error; } otError CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aCallback, void *aContext) @@ -209,7 +222,7 @@ otError CoapSecure::SendMessage(Message &aMessage, otCoapResponseHandler aHandle VerifyOrExit(IsConnected(), error = OT_ERROR_INVALID_STATE); - error = Coap::SendMessage(aMessage, mPeerAddress, aHandler, aContext); + error = CoapBase::SendMessage(aMessage, mPeerAddress, aHandler, aContext); exit: return error; @@ -220,7 +233,7 @@ otError CoapSecure::SendMessage(Message & aMessage, otCoapResponseHandler aHandler, void * aContext) { - return Coap::SendMessage(aMessage, aMessageInfo, aHandler, aContext); + return CoapBase::SendMessage(aMessage, aMessageInfo, aHandler, aContext); } otError CoapSecure::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) @@ -233,7 +246,13 @@ otError CoapSecure::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo return OT_ERROR_NONE; } -void CoapSecure::Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) +void CoapSecure::HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) +{ + static_cast(aContext)->HandleUdpReceive(*static_cast(aMessage), + *static_cast(aMessageInfo)); +} + +void CoapSecure::HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif &netif = GetNetif(); @@ -301,7 +320,7 @@ void CoapSecure::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength) NULL); SuccessOrExit(message->Append(aBuf, aLength)); - Coap::Receive(*message, mPeerAddress); + CoapBase::Receive(*message, mPeerAddress); exit: diff --git a/src/core/coap/coap_secure.hpp b/src/core/coap/coap_secure.hpp index 937ccff12..005dd43e9 100644 --- a/src/core/coap/coap_secure.hpp +++ b/src/core/coap/coap_secure.hpp @@ -45,7 +45,7 @@ namespace ot { namespace Coap { -class CoapSecure : public Coap +class CoapSecure : public CoapBase { public: /** @@ -84,7 +84,8 @@ public: * If NULL, the message is sent directly to the socket. * @param[in] aContext A pointer to arbitrary context information. * - * @retval OT_ERROR_NONE Successfully started the CoAP agent. + * @retval OT_ERROR_NONE Successfully started the CoAP agent. + * @retval OT_ERROR_ALREADY Already started. * */ otError Start(uint16_t aPort, TransportCallback aCallback = NULL, void *aContext = NULL); @@ -300,14 +301,14 @@ public: void * aContext = NULL); /** - * This method is used to pass messages to the secure CoAP server. + * This method is used to pass UDP messages to the secure CoAP server. * It can be used when messages are received other way that via server's socket. * * @param[in] aMessage A reference to the received message. * @param[in] aMessageInfo A reference to the message info associated with @p aMessage. * */ - virtual void Receive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + void HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo); /** * This method returns the DTLS session's peer address. @@ -318,7 +319,11 @@ public: const Ip6::MessageInfo &GetPeerMessageInfo(void) const { return mPeerAddress; } private: - virtual otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); + static otError Send(CoapBase &aCoapBase, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) + { + return static_cast(aCoapBase).Send(aMessage, aMessageInfo); + } + otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); static void HandleDtlsConnected(void *aContext, bool aConnected); void HandleDtlsConnected(bool aConnected); @@ -332,6 +337,8 @@ private: static void HandleTransmit(Tasklet &aTasklet); void HandleTransmit(void); + static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); + Ip6::MessageInfo mPeerAddress; ConnectedCallback mConnectedCallback; void * mConnectedContext; @@ -339,6 +346,7 @@ private: void * mTransportContext; MessageQueue mTransmitQueue; TaskletContext mTransmitTask; + Ip6::UdpSocket mSocket; bool mLayerTwoSecurity : 1; }; diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 05e3bd6ed..86accc107 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -855,7 +855,7 @@ void Commissioner::HandleRelayReceive(Coap::Message &aMessage, const Ip6::Messag joinerMessageInfo.GetPeerAddr().SetIid(mJoinerIid); joinerMessageInfo.SetPeerPort(mJoinerPort); - netif.GetCoapSecure().Receive(aMessage, joinerMessageInfo); + netif.GetCoapSecure().HandleUdpReceive(aMessage, joinerMessageInfo); exit: return; diff --git a/src/core/meshcop/meshcop.hpp b/src/core/meshcop/meshcop.hpp index d47def6ac..08e53ff53 100644 --- a/src/core/meshcop/meshcop.hpp +++ b/src/core/meshcop/meshcop.hpp @@ -55,7 +55,7 @@ enum * This function create Message for MeshCoP * */ -inline Coap::Message *NewMeshCoPMessage(Coap::Coap &aCoap) +inline Coap::Message *NewMeshCoPMessage(Coap::CoapBase &aCoap) { otMessageSettings settings = {true, static_cast(kMeshCoPMessagePriority)}; return aCoap.NewMessage(&settings); diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp index 470d038e7..0c51a743b 100644 --- a/src/core/net/udp6.hpp +++ b/src/core/net/udp6.hpp @@ -104,7 +104,7 @@ public: * @param[in] aUdp A reference to the UDP transport object. * */ - UdpSocket(Udp &aUdp); + explicit UdpSocket(Udp &aUdp); /** * This method returns a new UDP message with sufficient header space reserved. @@ -137,7 +137,8 @@ public: * * @param[in] aSockAddr A reference to the socket address. * - * @retval OT_ERROR_NONE Successfully bound the socket. + * @retval OT_ERROR_NONE Successfully bound the socket. + * @retval OT_ERROR_FAILED Failed to bind UDP Socket. * */ otError Bind(const SockAddr &aSockAddr); @@ -147,14 +148,17 @@ public: * * @param[in] aSockAddr A reference to the socket address. * - * @retval OT_ERROR_NONE Successfully connected the socket. + * @retval OT_ERROR_NONE Successfully connected the socket. + * @retval OT_ERROR_FAILED Failed to connect UDP Socket. + * */ otError Connect(const SockAddr &aSockAddr); /** * This method closes the UDP socket. * - * @retval OT_ERROR_NONE Successfully closed the UDP socket. + * @retval OT_ERROR_NONE Successfully closed the UDP socket. + * @retval OT_ERROR_FAILED Failed to close UDP Socket. * */ otError Close(void);