otError Leader::SendDatasetChanged(const Ip6::Address &aAddress) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header header; Ip6::MessageInfo messageInfo; Message *message; header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_DATASET_CHANGED); VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent dataset changed"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
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; }
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; }
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 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(); }
otError AnnounceBeginClient::SendRequest(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, const Ip6::Address &aAddress) { otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; Ip6::MessageInfo messageInfo; Message *message = NULL; VerifyOrExit(GetNetif().GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); header.Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_ANNOUNCE_BEGIN); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(GetNetif().GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); sessionId.Init(); sessionId.SetCommissionerSessionId(GetNetif().GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); count.Init(); count.SetCount(aCount); SuccessOrExit(error = message->Append(&count, sizeof(count))); period.Init(); period.SetPeriod(aPeriod); SuccessOrExit(error = message->Append(&period, sizeof(period))); messageInfo.SetSockAddr(GetNetif().GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(GetNetif().GetInterfaceId()); SuccessOrExit(error = GetNetif().GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent announce begin query"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
otError PanIdQueryClient::SendQuery(uint16_t aPanId, uint32_t aChannelMask, const Ip6::Address &aAddress, otCommissionerPanIdConflictCallback aCallback, void *aContext) { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::PanIdTlv panId; Ip6::MessageInfo messageInfo; Message *message = NULL; VerifyOrExit(netif.GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); header.Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_PANID_QUERY); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); sessionId.Init(); sessionId.SetCommissionerSessionId(netif.GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); panId.Init(); panId.SetPanId(aPanId); SuccessOrExit(error = message->Append(&panId, sizeof(panId))); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(netif.GetInterfaceId()); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent panid query"); mCallback = aCallback; mContext = aContext; exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
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; }
void AnnounceBeginServer::HandleRequest(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; Ip6::MessageInfo responseInfo(aMessageInfo); VerifyOrExit(aHeader.GetCode() == OT_COAP_CODE_POST); SuccessOrExit(MeshCoP::Tlv::GetTlv(aMessage, MeshCoP::Tlv::kChannelMask, sizeof(channelMask), channelMask)); VerifyOrExit(channelMask.IsValid()); 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()); SendAnnounce(channelMask.GetMask(), count.GetCount(), period.GetPeriod()); if (aHeader.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast()) { SuccessOrExit(GetNetif().GetCoap().SendEmptyAck(aHeader, responseInfo)); otLogInfoMeshCoP(GetInstance(), "sent announce begin response"); } exit: return; }
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(); } }
otError EnergyScanServer::SendReport(void) { otError error = OT_ERROR_NONE; Coap::Header header; MeshCoP::ChannelMask0Tlv channelMask; MeshCoP::EnergyListTlv energyList; Ip6::MessageInfo messageInfo; Message * message; header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OT_URI_PATH_ENERGY_REPORT); header.SetPayloadMarker(); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(GetNetif().GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS); channelMask.Init(); channelMask.SetMask(mChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); energyList.Init(); energyList.SetLength(mScanResultsLength); SuccessOrExit(error = message->Append(&energyList, sizeof(energyList))); SuccessOrExit(error = message->Append(mScanResults, mScanResultsLength)); messageInfo.SetSockAddr(GetNetif().GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(mCommissioner); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = GetNetif().GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP(GetInstance(), "sent scan results"); exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } mActive = false; return error; }
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; }
ThreadError DatasetManager::Register(void) { ThreadError error = kThreadError_None; Coap::Header header; Message *message; Ip6::Address leader; Ip6::MessageInfo messageInfo; header.Init(kCoapTypeConfirmable, kCoapRequestPost); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(mUriSet); header.SetPayloadMarker(); if (strcmp(mUriSet, OPENTHREAD_URI_PENDING_SET) == 0) { PendingDatasetBase *pending = static_cast<PendingDatasetBase *>(this); pending->UpdateDelayTimer(); } VerifyOrExit((message = mNetif.GetCoapClient().NewMeshCoPMessage(header)) != NULL, error = kThreadError_NoBufs); SuccessOrExit(error = message->Append(mLocal.GetBytes(), mLocal.GetSize())); mNetif.GetMle().GetLeaderAloc(leader); messageInfo.SetPeerAddr(leader); messageInfo.SetPeerPort(kCoapUdpPort); SuccessOrExit(error = mNetif.GetCoapClient().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("sent dataset to leader"); exit: if (error != kThreadError_None && message != NULL) { message->Free(); } return error; }
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; }
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 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 otUdpProxyReceive(otInstance * aInstance, otMessage * aMessage, uint16_t aPeerPort, const otIp6Address *aPeerAddr, uint16_t aSockPort) { Ip6::MessageInfo messageInfo; Instance & instance = *static_cast<Instance *>(aInstance); Ip6::Ip6 & ip6 = instance.Get<Ip6::Ip6>(); assert(aMessage != NULL && aPeerAddr != NULL); messageInfo.SetSockAddr(instance.GetThreadNetif().GetMle().GetMeshLocal16()); messageInfo.SetSockPort(aSockPort); messageInfo.SetPeerAddr(*static_cast<const ot::Ip6::Address *>(aPeerAddr)); messageInfo.SetPeerPort(aPeerPort); messageInfo.SetInterfaceId(OT_NETIF_INTERFACE_ID_HOST); ip6.GetUdp().HandlePayload(*static_cast<ot::Message *>(aMessage), messageInfo); static_cast<ot::Message *>(aMessage)->Free(); }
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); } }
otError JoinerRouter::DelaySendingJoinerEntrust(const Ip6::MessageInfo &aMessageInfo, const JoinerRouterKekTlv &aKek) { ThreadNetif & netif = GetNetif(); otError error; Coap::Message * message = NULL; Ip6::MessageInfo messageInfo; Dataset dataset(MeshCoP::Tlv::kActiveTimestamp); NetworkMasterKeyTlv masterKey; MeshLocalPrefixTlv meshLocalPrefix; ExtendedPanIdTlv extendedPanId; NetworkNameTlv networkName; NetworkKeySequenceTlv networkKeySequence; const Tlv * tlv; DelayedJoinEntHeader delayedMessage; VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); message->AppendUriPathOptions(OT_URI_PATH_JOINER_ENTRUST); message->SetPayloadMarker(); message->SetSubType(Message::kSubTypeJoinerEntrust); masterKey.Init(); masterKey.SetNetworkMasterKey(netif.GetKeyManager().GetMasterKey()); SuccessOrExit(error = message->Append(&masterKey, sizeof(masterKey))); meshLocalPrefix.Init(); meshLocalPrefix.SetMeshLocalPrefix(netif.GetMle().GetMeshLocalPrefix()); SuccessOrExit(error = message->Append(&meshLocalPrefix, sizeof(meshLocalPrefix))); extendedPanId.Init(); extendedPanId.SetExtendedPanId(netif.GetMac().GetExtendedPanId()); SuccessOrExit(error = message->Append(&extendedPanId, sizeof(extendedPanId))); networkName.Init(); networkName.SetNetworkName(netif.GetMac().GetNetworkName()); SuccessOrExit(error = message->Append(&networkName, sizeof(Tlv) + networkName.GetLength())); netif.GetActiveDataset().Get(dataset); if ((tlv = dataset.Get(Tlv::kActiveTimestamp)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { ActiveTimestampTlv activeTimestamp; activeTimestamp.Init(); SuccessOrExit(error = message->Append(&activeTimestamp, sizeof(activeTimestamp))); } if ((tlv = dataset.Get(Tlv::kChannelMask)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { ChannelMaskBaseTlv channelMask; channelMask.Init(); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); } if ((tlv = dataset.Get(Tlv::kPSKc)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { PSKcTlv pskc; pskc.Init(); SuccessOrExit(error = message->Append(&pskc, sizeof(pskc))); } if ((tlv = dataset.Get(Tlv::kSecurityPolicy)) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } else { SecurityPolicyTlv securityPolicy; securityPolicy.Init(); SuccessOrExit(error = message->Append(&securityPolicy, sizeof(securityPolicy))); } networkKeySequence.Init(); networkKeySequence.SetNetworkKeySequence(netif.GetKeyManager().GetCurrentKeySequence()); SuccessOrExit(error = message->Append(&networkKeySequence, networkKeySequence.GetSize())); messageInfo = aMessageInfo; messageInfo.SetPeerPort(kCoapUdpPort); delayedMessage = DelayedJoinEntHeader(TimerMilli::GetNow() + kDelayJoinEnt, messageInfo, aKek.GetKek()); SuccessOrExit(delayedMessage.AppendTo(*message)); mDelayedJoinEnts.Enqueue(*message); if (!mTimer.IsRunning()) { mTimer.Start(kDelayJoinEnt); } exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }
void JoinerRouter::HandleRelayTransmit(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { OT_UNUSED_VARIABLE(aMessageInfo); otError error; JoinerUdpPortTlv joinerPort; JoinerIidTlv joinerIid; JoinerRouterKekTlv kek; uint16_t offset; uint16_t length; Message * message = NULL; otMessageSettings settings = {false, static_cast<otMessagePriority>(kMeshCoPMessagePriority)}; Ip6::MessageInfo messageInfo; VerifyOrExit(aMessage.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST, error = OT_ERROR_DROP); otLogInfoMeshCoP("Received relay transmit"); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kJoinerUdpPort, sizeof(joinerPort), joinerPort)); VerifyOrExit(joinerPort.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kJoinerIid, sizeof(joinerIid), joinerIid)); VerifyOrExit(joinerIid.IsValid(), error = OT_ERROR_PARSE); SuccessOrExit(error = Tlv::GetValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length)); VerifyOrExit((message = mSocket.NewMessage(0, &settings)) != NULL, error = OT_ERROR_NO_BUFS); while (length) { uint16_t copyLength = length; uint8_t tmp[16]; if (copyLength >= sizeof(tmp)) { copyLength = sizeof(tmp); } aMessage.Read(offset, copyLength, tmp); SuccessOrExit(error = message->Append(tmp, copyLength)); offset += copyLength; length -= copyLength; } aMessage.CopyTo(offset, 0, length, *message); messageInfo.mPeerAddr.mFields.m16[0] = HostSwap16(0xfe80); memcpy(messageInfo.mPeerAddr.mFields.m8 + 8, joinerIid.GetIid(), 8); messageInfo.SetPeerPort(joinerPort.GetUdpPort()); messageInfo.SetInterfaceId(GetNetif().GetInterfaceId()); SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); if (Tlv::GetTlv(aMessage, Tlv::kJoinerRouterKek, sizeof(kek), kek) == OT_ERROR_NONE) { otLogInfoMeshCoP("Received kek"); DelaySendingJoinerEntrust(messageInfo, kek); } exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } }
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()); } } }
otError EnergyScanClient::SendQuery(uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod, uint16_t aScanDuration, const Ip6::Address & aAddress, otCommissionerEnergyReportCallback aCallback, void * aContext) { ThreadNetif & netif = GetNetif(); otError error = OT_ERROR_NONE; MeshCoP::CommissionerSessionIdTlv sessionId; MeshCoP::ChannelMaskTlv channelMask; MeshCoP::CountTlv count; MeshCoP::PeriodTlv period; MeshCoP::ScanDurationTlv scanDuration; Ip6::MessageInfo messageInfo; Coap::Message * message = NULL; VerifyOrExit(netif.GetCommissioner().IsActive(), error = OT_ERROR_INVALID_STATE); VerifyOrExit((message = MeshCoP::NewMeshCoPMessage(netif.GetCoap())) != NULL, error = OT_ERROR_NO_BUFS); message->Init(aAddress.IsMulticast() ? OT_COAP_TYPE_NON_CONFIRMABLE : OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST); message->SetToken(Coap::Message::kDefaultTokenLength); message->AppendUriPathOptions(OT_URI_PATH_ENERGY_SCAN); message->SetPayloadMarker(); sessionId.Init(); sessionId.SetCommissionerSessionId(netif.GetCommissioner().GetSessionId()); SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId))); channelMask.Init(); channelMask.SetChannelPage(OT_RADIO_CHANNEL_PAGE); channelMask.SetMask(aChannelMask); SuccessOrExit(error = message->Append(&channelMask, sizeof(channelMask))); count.Init(); count.SetCount(aCount); SuccessOrExit(error = message->Append(&count, sizeof(count))); period.Init(); period.SetPeriod(aPeriod); SuccessOrExit(error = message->Append(&period, sizeof(period))); scanDuration.Init(); scanDuration.SetScanDuration(aScanDuration); SuccessOrExit(error = message->Append(&scanDuration, sizeof(scanDuration))); messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16()); messageInfo.SetPeerAddr(aAddress); messageInfo.SetPeerPort(kCoapUdpPort); messageInfo.SetInterfaceId(netif.GetInterfaceId()); SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo)); otLogInfoMeshCoP("sent energy scan query"); mCallback = aCallback; mContext = aContext; exit: if (error != OT_ERROR_NONE && message != NULL) { message->Free(); } return error; }