void Dtls::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { switch (mState) { case MeshCoP::Dtls::kStateClosed: ExitNow(); case MeshCoP::Dtls::kStateOpen: { Ip6::SockAddr sockAddr; sockAddr.mAddress = aMessageInfo.GetPeerAddr(); sockAddr.mPort = aMessageInfo.GetPeerPort(); mSocket.Connect(sockAddr); mPeerAddress.SetPeerAddr(aMessageInfo.GetPeerAddr()); mPeerAddress.SetPeerPort(aMessageInfo.GetPeerPort()); mPeerAddress.SetInterfaceId(aMessageInfo.GetInterfaceId()); if (Get<ThreadNetif>().IsUnicastAddress(aMessageInfo.GetSockAddr())) { mPeerAddress.SetSockAddr(aMessageInfo.GetSockAddr()); } mPeerAddress.SetSockPort(aMessageInfo.GetSockPort()); SuccessOrExit(Setup(false)); break; } default: // Once DTLS session is started, communicate only with a peer. VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) && (mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort())); break; } #if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER if (mState == MeshCoP::Dtls::kStateConnecting) { SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields)); } #endif Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset()); exit: return; }
RequestMetadata::RequestMetadata(bool aConfirmable, const Ip6::MessageInfo &aMessageInfo, otCoapResponseHandler aHandler, void *aContext) { mSourceAddress = aMessageInfo.GetSockAddr(); mDestinationPort = aMessageInfo.GetPeerPort(); mDestinationAddress = aMessageInfo.GetPeerAddr(); mResponseHandler = aHandler; mResponseContext = aContext; mRetransmissionCount = 0; mRetransmissionTimeout = Timer::SecToMsec(kAckTimeout); mRetransmissionTimeout += otPlatRandomGet() % (Timer::SecToMsec(kAckTimeout) * kAckRandomFactorNumerator / kAckRandomFactorDenominator - Timer::SecToMsec(kAckTimeout) + 1); if (aConfirmable) { // Set next retransmission timeout. mNextTimerShot = Timer::GetNow() + mRetransmissionTimeout; } else { // Set overall response timeout. mNextTimerShot = Timer::GetNow() + kMaxTransmitWait; } mAcknowledged = false; mConfirmable = aConfirmable; }
void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif & netif = GetNetif(); otError error; Coap::Message * message = NULL; Ip6::MessageInfo messageInfo; JoinerUdpPortTlv udpPort; JoinerIidTlv iid; JoinerRouterLocatorTlv rloc; ExtendedTlv tlv; uint16_t borderAgentRloc; uint16_t offset; otLogInfoMeshCoP("JoinerRouter::HandleUdpReceive"); SuccessOrExit(error = GetBorderAgentRloc(GetNetif(), borderAgentRloc)); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST); message->SetToken(Coap::Message::kDefaultTokenLength); message->AppendUriPathOptions(OT_URI_PATH_RELAY_RX); message->SetPayloadMarker(); udpPort.Init(); udpPort.SetUdpPort(aMessageInfo.GetPeerPort()); SuccessOrExit(error = message->Append(&udpPort, sizeof(udpPort))); iid.Init(); iid.SetIid(aMessageInfo.GetPeerAddr().mFields.m8 + 8); SuccessOrExit(error = message->Append(&iid, sizeof(iid))); rloc.Init(); rloc.SetJoinerRouterLocator(netif.GetMle().GetRloc16()); SuccessOrExit(error = message->Append(&rloc, sizeof(rloc))); tlv.SetType(Tlv::kJoinerDtlsEncapsulation); tlv.SetLength(aMessage.GetLength() - aMessage.GetOffset()); SuccessOrExit(error = message->Append(&tlv, sizeof(tlv))); offset = message->GetLength(); SuccessOrExit(error = message->SetLength(offset + tlv.GetLength())); aMessage.CopyTo(aMessage.GetOffset(), offset, tlv.GetLength(), *message); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(netif.GetMle().GetMeshLocal16()); messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(borderAgentRloc); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("Sent relay rx"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
void CoapSecure::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { ThreadNetif &netif = GetNetif(); if (!netif.GetDtls().IsStarted()) { Ip6::SockAddr sockAddr; sockAddr.mAddress = aMessageInfo.GetPeerAddr(); sockAddr.mPort = aMessageInfo.GetPeerPort(); mSocket.Connect(sockAddr); mPeerAddress.SetPeerAddr(aMessageInfo.GetPeerAddr()); mPeerAddress.SetPeerPort(aMessageInfo.GetPeerPort()); mPeerAddress.SetInterfaceId(aMessageInfo.GetInterfaceId()); if (netif.IsUnicastAddress(aMessageInfo.GetSockAddr())) { mPeerAddress.SetSockAddr(aMessageInfo.GetSockAddr()); } mPeerAddress.SetSockPort(aMessageInfo.GetSockPort()); netif.GetDtls().Start(false, &CoapSecure::HandleDtlsConnected, &CoapSecure::HandleDtlsReceive, CoapSecure::HandleDtlsSend, this); } else { // Once DTLS session is started, communicate only with a peer. VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) && (mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort())); } netif.GetDtls().SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields)); netif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset()); exit: return; }
void Client::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Header responseHeader; Header requestHeader; RequestMetadata requestMetadata; Message *message = NULL; ThreadError error; SuccessOrExit(error = responseHeader.FromMessage(aMessage, false)); aMessage.MoveOffset(responseHeader.GetLength()); message = FindRelatedRequest(responseHeader, aMessageInfo, requestHeader, requestMetadata); if (message == NULL) { ExitNow(); } switch (responseHeader.GetType()) { case kCoapTypeReset: if (responseHeader.IsEmpty()) { FinalizeCoapTransaction(*message, requestMetadata, NULL, NULL, NULL, kThreadError_Abort); } // Silently ignore non-empty reset messages (RFC 7252, p. 4.2). break; case kCoapTypeAcknowledgment: if (responseHeader.IsEmpty()) { // Empty acknowledgment. if (requestMetadata.mConfirmable) { requestMetadata.mAcknowledged = true; requestMetadata.UpdateIn(*message); } // Remove the message if response is not expected, otherwise await response. if (requestMetadata.mResponseHandler == NULL) { DequeueMessage(*message); } } else if (responseHeader.IsResponse() && responseHeader.IsTokenEqual(requestHeader)) { // Piggybacked response. FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, &aMessageInfo, kThreadError_None); } // Silently ignore acknowledgments carrying requests (RFC 7252, p. 4.2) // or with no token match (RFC 7252, p. 5.3.2) break; case kCoapTypeConfirmable: case kCoapTypeNonConfirmable: if (responseHeader.IsConfirmable()) { // Send empty ACK if it is a CON message. SendEmptyAck(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort(), responseHeader.GetMessageId()); } FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, &aMessageInfo, kThreadError_None); break; } exit: if (error == kThreadError_None && message == NULL) { if (responseHeader.IsConfirmable() || responseHeader.IsNonConfirmable()) { // Successfully parsed a header but no matching request was found - reject the message by sending reset. SendReset(aMessageInfo.GetPeerAddr(), aMessageInfo.GetPeerPort(), responseHeader.GetMessageId()); } } }