void Interpreter::HandleEchoResponse(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Ip6::IcmpHeader icmp6Header; uint32_t timestamp = 0; aMessage.Read(aMessage.GetOffset(), sizeof(icmp6Header), &icmp6Header); sServer->OutputFormat("%d bytes from ", aMessage.GetLength() - aMessage.GetOffset()); sServer->OutputFormat("%x:%x:%x:%x:%x:%x:%x:%x", HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[0]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[1]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[2]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[3]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[4]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[5]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[6]), HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7])); sServer->OutputFormat(": icmp_seq=%d hlim=%d", icmp6Header.GetSequence(), aMessageInfo.mHopLimit); if (aMessage.Read(aMessage.GetOffset() + sizeof(icmp6Header), sizeof(uint32_t), ×tamp) >= static_cast<int>(sizeof(uint32_t))) { sServer->OutputFormat(" time=%dms", Timer::GetNow() - HostSwap32(timestamp)); } sServer->OutputFormat("\r\n"); (void)aContext; }
void Joiner::HandleUdpTransmit(void) { ThreadError error = kThreadError_None; Ip6::MessageInfo messageInfo; otLogFuncEntry(); VerifyOrExit(mTransmitMessage != NULL, error = kThreadError_NoBufs); otLogInfoMeshCoP("transmit %d (to %llX)", mTransmitMessage->GetLength(), HostSwap64(*reinterpret_cast<uint64_t *>(&mJoinerRouter))); messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80); messageInfo.GetPeerAddr().SetIid(mJoinerRouter); messageInfo.SetPeerPort(mJoinerUdpPort); messageInfo.SetInterfaceId(OT_NETIF_INTERFACE_ID_THREAD); SuccessOrExit(error = mSocket.SendTo(*mTransmitMessage, messageInfo)); exit: if (error != kThreadError_None && mTransmitMessage != NULL) { mTransmitMessage->Free(); } mTransmitMessage = NULL; otLogFuncExit(); }
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 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; }
otError Dhcp6Server::SendReply(otIp6Address &aDst, uint8_t *aTransactionId, ClientIdentifier &aClient, IaNa &aIaNa) { otError error = OT_ERROR_NONE; Ip6::MessageInfo messageInfo; Message *message; VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS); SuccessOrExit(error = AppendHeader(*message, aTransactionId)); SuccessOrExit(error = AppendServerIdentifier(*message)); SuccessOrExit(error = AppendClientIdentifier(*message, aClient)); SuccessOrExit(error = AppendIaNa(*message, aIaNa)); SuccessOrExit(error = AppendStatusCode(*message, kStatusSuccess)); SuccessOrExit(error = AppendIaAddress(*message, aClient)); SuccessOrExit(error = AppendRapidCommit(*message)); memset(&messageInfo, 0, sizeof(messageInfo)); memcpy(&messageInfo.GetPeerAddr().mFields.m8, &aDst, sizeof(otIp6Address)); messageInfo.mPeerPort = kDhcpClientPort; SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); exit: if (message != NULL && error != OT_ERROR_NONE) { message->Free(); } return error; }
RequestMetadata::RequestMetadata(bool aConfirmable, const Ip6::MessageInfo &aMessageInfo, otCoapResponseHandler aHandler, void *aContext) { mDestinationPort = aMessageInfo.mPeerPort; 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; }
bool ThreadNetif::IsTmfMessage(const Ip6::MessageInfo &aMessageInfo) { bool rval = true; // A TMF message must comply with following rules: // 1. The destination is a Mesh Local Address or a Link-Local Multicast Address or a Realm-Local Multicast Address, // and the source is a Mesh Local Address. Or // 2. Both the destination and the source are Link-Local Addresses. VerifyOrExit( ((mMleRouter.IsMeshLocalAddress(aMessageInfo.GetSockAddr()) || aMessageInfo.GetSockAddr().IsLinkLocalMulticast() || aMessageInfo.GetSockAddr().IsRealmLocalMulticast()) && mMleRouter.IsMeshLocalAddress(aMessageInfo.GetPeerAddr())) || ((aMessageInfo.GetSockAddr().IsLinkLocal() || aMessageInfo.GetSockAddr().IsLinkLocalMulticast()) && aMessageInfo.GetPeerAddr().IsLinkLocal()), rval = false); exit: return rval; }
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 EnergyScanServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; MeshCoP::ScanDurationTlv scanDuration; MeshCoP::ChannelMask0Tlv channelMask; Ip6::MessageInfo responseInfo(aMessageInfo); VerifyOrExit(aHeader.GetCode() == OT_COAP_CODE_POST); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kCount, sizeof(count), count)); VerifyOrExit(count.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kPeriod, sizeof(period), period)); VerifyOrExit(period.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kScanDuration, sizeof(scanDuration), scanDuration)); VerifyOrExit(scanDuration.IsValid()); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid()); mChannelMask = channelMask.GetMask(); mChannelMaskCurrent = mChannelMask; mCount = count.GetCount(); mPeriod = period.GetPeriod(); mScanDuration = scanDuration.GetScanDuration(); mScanResultsLength = 0; mActive = true; mTimer.Start(kScanDelay); mCommissioner = aMessageInfo.GetPeerAddr(); if (aHeader.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast()) { SuccessOrExit(GetNetif().GetCoap().SendEmptyAck(aHeader, responseInfo)); otLogInfoMeshCoP(GetInstance(), "sent energy scan query response"); } exit: return; }
void Leader::HandlePetition(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { CommissioningData data; CommissionerIdTlv commissionerId; StateTlv::State state = StateTlv::kReject; otLogInfoMeshCoP(GetInstance(), "received petition"); SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kCommissionerId, sizeof(commissionerId), commissionerId)); VerifyOrExit(commissionerId.IsValid()); if (mTimer.IsRunning()) { VerifyOrExit(!strncmp(commissionerId.GetCommissionerId(), mCommissionerId.GetCommissionerId(), sizeof(mCommissionerId))); ResignCommissioner(); } data.mBorderAgentLocator.Init(); data.mBorderAgentLocator.SetBorderAgentLocator(HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7])); data.mCommissionerSessionId.Init(); data.mCommissionerSessionId.SetCommissionerSessionId(++mSessionId); data.mSteeringData.Init(); data.mSteeringData.SetLength(1); data.mSteeringData.Clear(); SuccessOrExit(GetNetif().GetNetworkDataLeader().SetCommissioningData(reinterpret_cast<uint8_t *>(&data), data.GetLength())); mCommissionerId = commissionerId; state = StateTlv::kAccept; mTimer.Start(TimerMilli::SecToMsec(kTimeoutLeaderPetition)); exit: OT_UNUSED_VARIABLE(aMessageInfo); SendPetitionResponse(aHeader, aMessageInfo, state); }
void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Header responseHeader; Header requestHeader; RequestMetadata requestMetadata; Message *message = NULL; ThreadError error; SuccessOrExit(error = responseHeader.FromMessage(aMessage)); 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, 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, 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.mPeerPort, responseHeader.GetMessageId()); } FinalizeCoapTransaction(*message, requestMetadata, &responseHeader, &aMessage, 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.mPeerPort, responseHeader.GetMessageId()); } } }
void Client::HandleRetransmissionTimer(void) { uint32_t now = otPlatAlarmGetNow(); uint32_t nextDelta = 0xffffffff; RequestMetadata requestMetadata; Message *message = mPendingRequests.GetHead(); Message *nextMessage = NULL; Ip6::MessageInfo messageInfo; while (message != NULL) { nextMessage = message->GetNext(); requestMetadata.ReadFrom(*message); if (requestMetadata.IsLater(now)) { // Calculate the next delay and choose the lowest. if (requestMetadata.mNextTimerShot - now < nextDelta) { nextDelta = requestMetadata.mNextTimerShot - now; } } else if ((requestMetadata.mConfirmable) && (requestMetadata.mRetransmissionCount < kMaxRetransmit)) { // Increment retransmission counter and timer. requestMetadata.mRetransmissionCount++; requestMetadata.mRetransmissionTimeout *= 2; requestMetadata.mNextTimerShot = now + requestMetadata.mRetransmissionTimeout; requestMetadata.UpdateIn(*message); // Check if retransmission time is lower than current lowest. if (requestMetadata.mRetransmissionTimeout < nextDelta) { nextDelta = requestMetadata.mRetransmissionTimeout; } // Retransmit if (!requestMetadata.mAcknowledged) { memset(&messageInfo, 0, sizeof(messageInfo)); messageInfo.GetPeerAddr() = requestMetadata.mDestinationAddress; messageInfo.mPeerPort = requestMetadata.mDestinationPort; SendCopy(*message, messageInfo); } } else { // No expected response or acknowledgment. FinalizeCoapTransaction(*message, requestMetadata, NULL, NULL, kThreadError_ResponseTimeout); } message = nextMessage; } if (nextDelta != 0xffffffff) { mRetransmissionTimer.Start(nextDelta); } }