Implement Server Data Notify. (#457)

This commit is contained in:
Jonathan Hui
2016-08-25 23:14:50 -07:00
committed by GitHub
parent 83348b5afd
commit 4d37d0098e
9 changed files with 190 additions and 100 deletions
+1 -3
View File
@@ -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)
+1
View File
@@ -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;
+93 -1
View File
@@ -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
+25 -1
View File
@@ -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
+30 -11
View File
@@ -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);
+11 -1
View File
@@ -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;
};
/**
+9 -67
View File
@@ -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
+5 -16
View File
@@ -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
+15
View File
@@ -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