mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 13:47:47 +00:00
Implement Server Data Notify. (#457)
This commit is contained in:
@@ -410,9 +410,7 @@ ThreadError otRemoveExternalRoute(const otIp6Prefix *aPrefix)
|
||||
|
||||
ThreadError otSendServerData(void)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
sThreadNetif->GetMle().GetLeaderAddress(destination);
|
||||
return sThreadNetif->GetNetworkDataLocal().Register(destination);
|
||||
return sThreadNetif->GetNetworkDataLocal().SendServerDataNotification();
|
||||
}
|
||||
|
||||
ThreadError otAddUnsecurePort(uint16_t aPort)
|
||||
|
||||
@@ -2314,6 +2314,7 @@ ThreadError MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
|
||||
if (aNeighbor.mState == Neighbor::kStateValid && !IsActiveRouter(aNeighbor.mValid.mRloc16))
|
||||
{
|
||||
mNetif.SetStateChangedFlags(OT_THREAD_CHILD_REMOVED);
|
||||
mNetworkData.SendServerDataNotification(aNeighbor.mValid.mRloc16);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -31,17 +31,25 @@
|
||||
* This file implements common methods for manipulating Thread Network Data.
|
||||
*/
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <thread/network_data.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_tlvs.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace NetworkData {
|
||||
|
||||
NetworkData::NetworkData(void)
|
||||
NetworkData::NetworkData(ThreadNetif &aThreadNetif):
|
||||
mMle(aThreadNetif.GetMle())
|
||||
{
|
||||
mLength = 0;
|
||||
mCoapMessageId = 0;
|
||||
}
|
||||
|
||||
void NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength)
|
||||
@@ -438,5 +446,89 @@ ThreadError NetworkData::Remove(uint8_t *aStart, uint8_t aLength)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError NetworkData::SendServerDataNotification(bool aLocal, uint16_t aRloc16)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Coap::Header header;
|
||||
Message *message;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
{
|
||||
mCoapToken[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
header.Init();
|
||||
header.SetVersion(1);
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(mCoapToken, sizeof(mCoapToken));
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_SERVER_DATA);
|
||||
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
|
||||
header.Finalize();
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
|
||||
if (aLocal)
|
||||
{
|
||||
ThreadTlv tlv;
|
||||
tlv.SetType(ThreadTlv::kThreadNetworkData);
|
||||
tlv.SetLength(mLength);
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
SuccessOrExit(error = message->Append(mTlvs, mLength));
|
||||
}
|
||||
|
||||
if (aRloc16 != Mac::kShortAddrInvalid)
|
||||
{
|
||||
ThreadRloc16Tlv rloc16Tlv;
|
||||
rloc16Tlv.Init();
|
||||
rloc16Tlv.SetRloc16(aRloc16);
|
||||
SuccessOrExit(error = message->Append(&rloc16Tlv, sizeof(rloc16Tlv)));
|
||||
}
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
mMle.GetLeaderAddress(messageInfo.GetPeerAddr());
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoNetData("Sent server data notification\n");
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void NetworkData::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Local *obj = static_cast<Local *>(aContext);
|
||||
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void NetworkData::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Coap::Header header;
|
||||
|
||||
SuccessOrExit(header.FromMessage(aMessage));
|
||||
VerifyOrExit(header.GetType() == Coap::Header::kTypeAcknowledgment &&
|
||||
header.GetCode() == Coap::Header::kCodeChanged &&
|
||||
header.GetMessageId() == mCoapMessageId &&
|
||||
header.GetTokenLength() == sizeof(mCoapToken) &&
|
||||
memcmp(mCoapToken, header.GetToken(), sizeof(mCoapToken)) == 0, ;);
|
||||
|
||||
otLogInfoNetData("Server data notification acknowledged\n");
|
||||
|
||||
exit:
|
||||
(void)aMessageInfo;
|
||||
}
|
||||
|
||||
} // namespace NetworkData
|
||||
} // namespace Thread
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
#define NETWORK_DATA_HPP_
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <net/udp6.hpp>
|
||||
#include <thread/lowpan.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/network_data_tlvs.hpp>
|
||||
|
||||
namespace Thread {
|
||||
@@ -91,7 +93,7 @@ public:
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
*/
|
||||
NetworkData(void);
|
||||
NetworkData(ThreadNetif &aThreadNetif);
|
||||
|
||||
/**
|
||||
* This method provides a full or stable copy of the Thread Network Data.
|
||||
@@ -248,8 +250,30 @@ protected:
|
||||
*/
|
||||
int8_t PrefixMatch(const uint8_t *a, const uint8_t *b, uint8_t aLength);
|
||||
|
||||
/**
|
||||
* This method sends a Server Data Notification message to the Leader.
|
||||
*
|
||||
* @param[in] aLocal TRUE if notifying Leader of local network data, FALSE otherwise.
|
||||
* @param[in] aRloc16 The old RLOC16 value that was previously registered.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the notification message.
|
||||
* @retval kThreadError_NoBufs Insufficient message buffers to generate the notification message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendServerDataNotification(bool aLocal, uint16_t aRloc16);
|
||||
|
||||
uint8_t mTlvs[kMaxSize]; ///< The Network Data buffer.
|
||||
uint8_t mLength; ///< The number of valid bytes in @var mTlvs.
|
||||
|
||||
Mle::MleRouter &mMle;
|
||||
|
||||
private:
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint8_t mCoapToken[2];
|
||||
uint16_t mCoapMessageId;
|
||||
};
|
||||
|
||||
} // namespace NetworkData
|
||||
|
||||
@@ -52,11 +52,11 @@ namespace Thread {
|
||||
namespace NetworkData {
|
||||
|
||||
Leader::Leader(ThreadNetif &aThreadNetif):
|
||||
NetworkData(aThreadNetif),
|
||||
mTimer(&HandleTimer, this),
|
||||
mServerData(OPENTHREAD_URI_SERVER_DATA, &HandleServerData, this),
|
||||
mCoapServer(aThreadNetif.GetCoapServer()),
|
||||
mNetif(aThreadNetif),
|
||||
mMle(aThreadNetif.GetMle())
|
||||
mNetif(aThreadNetif)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
@@ -470,21 +470,24 @@ void Leader::HandleServerData(void *aContext, Coap::Header &aHeader, Message &aM
|
||||
void Leader::HandleServerData(Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
ThreadNetworkDataTlv threadNetworkDataTlv;
|
||||
uint8_t tlvsLength;
|
||||
uint8_t tlvs[kMaxSize];
|
||||
uint16_t rloc16;
|
||||
ThreadNetworkDataTlv networkData;
|
||||
ThreadRloc16Tlv rloc16;
|
||||
|
||||
otLogInfoNetData("Received network data registration\n");
|
||||
|
||||
aMessage.Read(aMessage.GetOffset(), sizeof(threadNetworkDataTlv), &threadNetworkDataTlv);
|
||||
tlvsLength = threadNetworkDataTlv.GetLength();
|
||||
if (ThreadTlv::GetTlv(aMessage, ThreadTlv::kRloc16, sizeof(rloc16), rloc16) == kThreadError_None)
|
||||
{
|
||||
RemoveBorderRouter(rloc16.GetRloc16());
|
||||
}
|
||||
|
||||
aMessage.Read(aMessage.GetOffset() + sizeof(threadNetworkDataTlv), tlvsLength, tlvs);
|
||||
rloc16 = HostSwap16(aMessageInfo.mPeerAddr.mFields.m16[7]);
|
||||
if (ThreadTlv::GetTlv(aMessage, ThreadTlv::kThreadNetworkData, sizeof(networkData), networkData) ==
|
||||
kThreadError_None)
|
||||
{
|
||||
RegisterNetworkData(HostSwap16(aMessageInfo.mPeerAddr.mFields.m16[7]),
|
||||
networkData.GetTlvs(), networkData.GetLength());
|
||||
}
|
||||
|
||||
SendServerDataResponse(aHeader, aMessageInfo, NULL, 0);
|
||||
RegisterNetworkData(rloc16, tlvs, tlvsLength);
|
||||
}
|
||||
|
||||
void Leader::SendServerDataResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
|
||||
@@ -882,6 +885,22 @@ ThreadError Leader::FreeContext(uint8_t aContextId)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Leader::SendServerDataNotification(uint16_t aRloc16)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
bool rlocIn = false;
|
||||
bool rlocStable = false;
|
||||
|
||||
RlocLookup(aRloc16, rlocIn, rlocStable, mTlvs, mLength);
|
||||
|
||||
VerifyOrExit(rlocIn, error = kThreadError_NotFound);
|
||||
|
||||
SuccessOrExit(error = NetworkData::SendServerDataNotification(false, aRloc16));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Leader::RemoveRloc(uint16_t aRloc16)
|
||||
{
|
||||
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
|
||||
|
||||
@@ -208,6 +208,17 @@ public:
|
||||
*/
|
||||
void RemoveBorderRouter(uint16_t aRloc16);
|
||||
|
||||
/**
|
||||
* This method sends a Server Data Notification message to the Leader indicating an invalid RLOC16.
|
||||
*
|
||||
* @param[in] aRloc16 The invalid RLOC16 to notify.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the notification message.
|
||||
* @retval kThreadError_NoBufs Insufficient message buffers to generate the notification message.
|
||||
*
|
||||
*/
|
||||
ThreadError SendServerDataNotification(uint16_t aRloc16);
|
||||
|
||||
private:
|
||||
static void HandleServerData(void *aContext, Coap::Header &aHeader, Message &aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
@@ -269,7 +280,6 @@ private:
|
||||
|
||||
Coap::Server &mCoapServer;
|
||||
ThreadNetif &mNetif;
|
||||
Mle::MleRouter &mMle;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,24 +31,20 @@
|
||||
* This file implements the local Thread Network Data.
|
||||
*/
|
||||
|
||||
#include <coap/coap_header.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/logging.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <mac/mac_frame.hpp>
|
||||
#include <thread/network_data_local.hpp>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_tlvs.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace NetworkData {
|
||||
|
||||
Local::Local(ThreadNetif &aThreadNetif):
|
||||
NetworkData(),
|
||||
mMle(aThreadNetif.GetMle())
|
||||
NetworkData(aThreadNetif),
|
||||
mOldRloc(Mac::kShortAddrInvalid)
|
||||
{
|
||||
mCoapMessageId = 0;
|
||||
}
|
||||
|
||||
ThreadError Local::AddOnMeshPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, int8_t aPrf,
|
||||
@@ -199,79 +195,25 @@ ThreadError Local::UpdateRloc(BorderRouterTlv &aBorderRouter)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError Local::Register(const Ip6::Address &aDestination)
|
||||
ThreadError Local::SendServerDataNotification(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Coap::Header header;
|
||||
Message *message;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
ThreadNetworkDataTlv threadNetworkDataTlv;
|
||||
uint16_t rloc = mMle.GetRloc16();
|
||||
|
||||
UpdateRloc();
|
||||
mSocket.Open(&HandleUdpReceive, this);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mCoapToken); i++)
|
||||
if (mOldRloc == rloc)
|
||||
{
|
||||
mCoapToken[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
mOldRloc = Mac::kShortAddrInvalid;
|
||||
}
|
||||
|
||||
header.Init();
|
||||
header.SetVersion(1);
|
||||
header.SetType(Coap::Header::kTypeConfirmable);
|
||||
header.SetCode(Coap::Header::kCodePost);
|
||||
header.SetMessageId(++mCoapMessageId);
|
||||
header.SetToken(mCoapToken, sizeof(mCoapToken));
|
||||
header.AppendUriPathOptions(OPENTHREAD_URI_SERVER_DATA);
|
||||
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
|
||||
header.Finalize();
|
||||
|
||||
VerifyOrExit((message = Ip6::Udp::NewMessage(0)) != NULL, error = kThreadError_NoBufs);
|
||||
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
|
||||
threadNetworkDataTlv.Init();
|
||||
threadNetworkDataTlv.SetLength(mLength);
|
||||
SuccessOrExit(error = message->Append(&threadNetworkDataTlv, sizeof(threadNetworkDataTlv)));
|
||||
SuccessOrExit(error = message->Append(mTlvs, mLength));
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
memcpy(&messageInfo.mPeerAddr, &aDestination, sizeof(messageInfo.mPeerAddr));
|
||||
messageInfo.mPeerPort = kCoapUdpPort;
|
||||
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
|
||||
|
||||
otLogInfoNetData("Sent network data registration\n");
|
||||
SuccessOrExit(error = NetworkData::SendServerDataNotification(true, mOldRloc));
|
||||
mOldRloc = rloc;
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && message != NULL)
|
||||
{
|
||||
Message::Free(*message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void Local::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Local *obj = reinterpret_cast<Local *>(aContext);
|
||||
obj->HandleUdpReceive(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void Local::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Coap::Header header;
|
||||
|
||||
SuccessOrExit(header.FromMessage(aMessage));
|
||||
VerifyOrExit(header.GetType() == Coap::Header::kTypeAcknowledgment &&
|
||||
header.GetCode() == Coap::Header::kCodeChanged &&
|
||||
header.GetMessageId() == mCoapMessageId &&
|
||||
header.GetTokenLength() == sizeof(mCoapToken) &&
|
||||
memcmp(mCoapToken, header.GetToken(), sizeof(mCoapToken)) == 0, ;);
|
||||
|
||||
otLogInfoNetData("Network data registration acknowledged\n");
|
||||
|
||||
exit:
|
||||
(void)aMessageInfo;
|
||||
}
|
||||
|
||||
} // namespace NetworkData
|
||||
} // namespace Thread
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
#ifndef NETWORK_DATA_LOCAL_HPP_
|
||||
#define NETWORK_DATA_LOCAL_HPP_
|
||||
|
||||
#include <net/udp6.hpp>
|
||||
#include <thread/mle_router.hpp>
|
||||
#include <thread/network_data.hpp>
|
||||
|
||||
namespace Thread {
|
||||
@@ -123,30 +121,21 @@ public:
|
||||
ThreadError RemoveHasRoutePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength);
|
||||
|
||||
/**
|
||||
* This method sends a Server Data Registration message to the Leader.
|
||||
* This method sends a Server Data Notification message to the Leader.
|
||||
*
|
||||
* @param[in] aDestination The IPv6 destination.
|
||||
*
|
||||
* @retval kThreadError_None Successfully enqueued the registration message.
|
||||
* @retval kThreadError_NoBufs Insufficient message buffers to generate the registration message.
|
||||
* @retval kThreadError_None Successfully enqueued the notification message.
|
||||
* @retval kThreadError_NoBufs Insufficient message buffers to generate the notification message.
|
||||
*
|
||||
*/
|
||||
ThreadError Register(const Ip6::Address &aDestination);
|
||||
ThreadError SendServerDataNotification(void);
|
||||
|
||||
private:
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
ThreadError UpdateRloc(void);
|
||||
ThreadError UpdateRloc(PrefixTlv &aPrefix);
|
||||
ThreadError UpdateRloc(HasRouteTlv &aHasRoute);
|
||||
ThreadError UpdateRloc(BorderRouterTlv &aBorderRouter);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
uint8_t mCoapToken[2];
|
||||
uint16_t mCoapMessageId;
|
||||
|
||||
Mle::MleRouter &mMle;
|
||||
uint16_t mOldRloc;
|
||||
};
|
||||
|
||||
} // namespace NetworkData
|
||||
|
||||
@@ -487,6 +487,21 @@ public:
|
||||
*/
|
||||
bool IsValid() const { return true; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Network Data TLVs.
|
||||
*
|
||||
* @returns A pointer to the Network Data TLVs.
|
||||
*
|
||||
*/
|
||||
uint8_t *GetTlvs(void) { return mTlvs; }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxSize = 255,
|
||||
};
|
||||
|
||||
uint8_t mTlvs[kMaxSize];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
} // namespace Thread
|
||||
|
||||
Reference in New Issue
Block a user