Add support for MGMT_COMMISSIONER_GET and MGMT_COMMISSIONER_SET (#634)

* - Add support for MGMT_COMMISSIONER_GET and MGMT_COMMISSIONER_SET
- Add CLI for sending this two commands

* - Move MGMT_COMMISSIONER_GET and MGMT_COMMISSIONER_SET to MeshCoP::commissioner
This commit is contained in:
Lu Wang
2016-09-23 09:38:21 -07:00
committed by Jonathan Hui
parent 34b23702ae
commit 9b97c1c7d0
10 changed files with 592 additions and 5 deletions
+28
View File
@@ -127,6 +127,34 @@ ThreadError otCommissionerPanIdQuery(otInstance *aInstance, uint16_t aPanId, uin
const otIp6Address *aAddress,
otCommissionerPanIdConflictCallback aCallback, void *aContext);
/**
* This function sends MGMT_COMMISSIONER_GET.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aTlvs A pointer to TLVs.
* @param[in] aLength The length of TLVs.
*
* @retval kThreadError_None Successfully send the meshcop dataset command.
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
ThreadError otSendMgmtCommissionerGet(otInstance *, const uint8_t *aTlvs, uint8_t aLength);
/**
* This function sends MGMT_COMMISSIONER_SET.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aDataset A pointer to commissioning dataset.
* @param[in] aTlvs A pointer to TLVs.
* @param[in] aLength The length of TLVs.
*
* @retval kThreadError_None Successfully send the meshcop dataset command.
* @retval kThreadError_NoBufs Insufficient buffer space to send.
*
*/
ThreadError otSendMgmtCommissionerSet(otInstance *, const otCommissioningDataset *aDataset,
const uint8_t *aTlvs, uint8_t aLength);
/**
* @}
*
+29
View File
@@ -376,6 +376,35 @@ typedef struct otOperationalDataset
bool mIsChannelMaskPage0Set : 1; ///< TRUE if Channel Mask Page 0 is set, FALSE otherwise.
} otOperationalDataset;
#define OT_STEERING_DATA_MAX_LENGTH 16 ///< Max steering data length (bytes)
/**
* This structure represents the steering data.
*
*/
typedef struct otSteeringData
{
uint8_t mLength;
uint8_t m8[OT_STEERING_DATA_MAX_LENGTH];
} otSteeringData;
/**
* This structure represents a Commissioning Dataset.
*
*/
typedef struct otCommissioningDataset
{
uint16_t mLocator; ///< Border Router RLOC16
uint16_t mSessionId; ///< Commissioner Session Id
otSteeringData mSteeringData; ///< Steering Data
uint16_t mJoinerUdpPort; ///< Joiner UDP Port
bool mIsLocatorSet : 1; ///< TRUE if Border Router RLOC16 is set, FALSE otherwise.
bool mIsSessionIdSet: 1; ///< TRUE if Commissioner Session Id is set, FALSE otherwise.
bool mIsSteeringDataSet : 1; ///< TRUE if Steering Data is set, FALSE otherwise.
bool mIsJoinerUdpPortSet : 1; ///< TRUE if Joiner UDP Port is set, FALSE otherwise.
} otCommissioningDataset;
/**
* This enumeration represents meshcop TLV types.
*
+106
View File
@@ -2038,6 +2038,112 @@ void Interpreter::ProcessCommissioner(int argc, char *argv[])
Interpreter::s_HandlePanIdConflict,
this));
}
else if (strcmp(argv[0], "mgmtget") == 0)
{
uint8_t tlvs[32];
long value;
int length = 0;
for (uint8_t index = 1; index < argc; index++)
{
VerifyOrExit(static_cast<size_t>(length) < sizeof(tlvs), error = kThreadError_NoBufs);
if (strcmp(argv[index], "locator") == 0)
{
tlvs[length++] = OT_MESHCOP_TLV_BORDER_AGENT_RLOC;
}
else if (strcmp(argv[index], "sessionid") == 0)
{
tlvs[length++] = OT_MESHCOP_TLV_COMM_SESSION_ID;
}
else if (strcmp(argv[index], "steeringdata") == 0)
{
tlvs[length++] = OT_MESHCOP_TLV_STEERING_DATA;
}
else if (strcmp(argv[index], "joinerudpport") == 0)
{
tlvs[length++] = OT_MESHCOP_TLV_JOINER_UDP_PORT;
}
else if (strcmp(argv[index], "binary") == 0)
{
VerifyOrExit((index + 1) < argc, error = kThreadError_Parse);
value = static_cast<long>(strlen(argv[++index]) + 1) / 2;
VerifyOrExit(static_cast<size_t>(value) <= (sizeof(tlvs) - static_cast<size_t>(length)), error = kThreadError_NoBufs);
VerifyOrExit(Interpreter::Hex2Bin(argv[index], tlvs + length, static_cast<uint16_t>(value)) >= 0,
error = kThreadError_Parse);
length += value;
}
else
{
ExitNow(error = kThreadError_Parse);
}
}
SuccessOrExit(error = otSendMgmtCommissionerGet(mInstance, tlvs, static_cast<uint8_t>(length)));
}
else if (strcmp(argv[0], "mgmtset") == 0)
{
otCommissioningDataset dataset;
uint8_t tlvs[32];
long value;
int length = 0;
VerifyOrExit(argc > 0, error = kThreadError_Parse);
memset(&dataset, 0, sizeof(dataset));
for (uint8_t index = 1; index < argc; index++)
{
VerifyOrExit(static_cast<size_t>(length) < sizeof(tlvs), error = kThreadError_NoBufs);
if (strcmp(argv[index], "locator") == 0)
{
VerifyOrExit(index < argc, error = kThreadError_Parse);
dataset.mIsLocatorSet = true;
SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value));
dataset.mLocator = static_cast<uint16_t>(value);
}
else if (strcmp(argv[index], "sessionid") == 0)
{
VerifyOrExit(index < argc, error = kThreadError_Parse);
dataset.mIsSessionIdSet = true;
SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value));
dataset.mSessionId = static_cast<uint16_t>(value);
}
else if (strcmp(argv[index], "steeringdata") == 0)
{
VerifyOrExit((index + 1) < argc, error = kThreadError_Parse);
dataset.mIsSteeringDataSet = true;
length = static_cast<int>((strlen(argv[++index]) + 1) / 2);
VerifyOrExit(static_cast<size_t>(length) <= OT_STEERING_DATA_MAX_LENGTH, error = kThreadError_NoBufs);
VerifyOrExit(Interpreter::Hex2Bin(argv[index], dataset.mSteeringData.m8, static_cast<uint16_t>(length)) >= 0,
error = kThreadError_Parse);
dataset.mSteeringData.mLength = length;
length = 0;
}
else if (strcmp(argv[index], "joinerudpport") == 0)
{
VerifyOrExit(index < argc, error = kThreadError_Parse);
dataset.mIsJoinerUdpPortSet = true;
SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value));
dataset.mJoinerUdpPort = static_cast<uint16_t>(value);
}
else if (strcmp(argv[index], "binary") == 0)
{
VerifyOrExit((index + 1) < argc, error = kThreadError_Parse);
length = static_cast<int>((strlen(argv[++index]) + 1) / 2);
VerifyOrExit(static_cast<size_t>(length) <= sizeof(tlvs), error = kThreadError_NoBufs);
VerifyOrExit(Interpreter::Hex2Bin(argv[index], tlvs, static_cast<uint16_t>(length)) >= 0,
error = kThreadError_Parse);
}
else
{
ExitNow(error = kThreadError_Parse);
}
}
SuccessOrExit(error = otSendMgmtCommissionerSet(mInstance, &dataset, tlvs, static_cast<uint8_t>(length)));
}
exit:
AppendResult(error);
+148
View File
@@ -119,6 +119,145 @@ void Commissioner::HandleTimer(void)
}
}
ThreadError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs,
uint8_t aLength)
{
ThreadError error = kThreadError_None;
Coap::Header header;
Message *message;
Ip6::MessageInfo messageInfo;
MeshCoP::Tlv tlv;
mIsSendMgmtCommRequest = true;
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_COMMISSIONER_GET);
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
header.Finalize();
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
if (aLength > 0)
{
tlv.SetType(MeshCoP::Tlv::kGet);
tlv.SetLength(aLength);
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
SuccessOrExit(error = message->Append(aTlvs, aLength));
}
memset(&messageInfo, 0, sizeof(messageInfo));
mNetif.GetMle().GetLeaderAddress(messageInfo.GetPeerAddr());
messageInfo.mPeerPort = kCoapUdpPort;
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
otLogInfoMeshCoP("sent MGMT_COMMISSIONER_GET.req to leader\n");
exit:
if (error != kThreadError_None && message != NULL)
{
mIsSendMgmtCommRequest = false;
message->Free();
}
return error;
}
ThreadError Commissioner::SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
const uint8_t *aTlvs, uint8_t aLength)
{
ThreadError error = kThreadError_None;
Coap::Header header;
Message *message;
Ip6::MessageInfo messageInfo;
mIsSendMgmtCommRequest = true;
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_COMMISSIONER_SET);
header.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
header.Finalize();
VerifyOrExit((message = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = message->Append(header.GetBytes(), header.GetLength()));
if (aDataset.mIsLocatorSet)
{
MeshCoP::BorderAgentLocatorTlv locator;
locator.Init();
locator.SetBorderAgentLocator(aDataset.mLocator);
SuccessOrExit(error = message->Append(&locator, sizeof(locator)));
}
if (aDataset.mIsSessionIdSet)
{
MeshCoP::CommissionerSessionIdTlv sessionId;
sessionId.Init();
sessionId.SetCommissionerSessionId(aDataset.mSessionId);
SuccessOrExit(error = message->Append(&sessionId, sizeof(sessionId)));
}
if (aDataset.mIsSteeringDataSet)
{
MeshCoP::SteeringDataTlv steeringData;
steeringData.Init();
steeringData.SetLength(aDataset.mSteeringData.mLength);
SuccessOrExit(error = message->Append(&steeringData, sizeof(MeshCoP::Tlv)));
SuccessOrExit(error = message->Append(&aDataset.mSteeringData.m8, aDataset.mSteeringData.mLength));
}
if (aDataset.mIsJoinerUdpPortSet)
{
MeshCoP::JoinerUdpPortTlv joinerUdpPort;
joinerUdpPort.Init();
joinerUdpPort.SetUdpPort(aDataset.mJoinerUdpPort);
SuccessOrExit(error = message->Append(&joinerUdpPort, sizeof(joinerUdpPort)));
}
if (aLength > 0)
{
SuccessOrExit(error = message->Append(aTlvs, aLength));
}
memset(&messageInfo, 0, sizeof(messageInfo));
mNetif.GetMle().GetLeaderAddress(messageInfo.GetPeerAddr());
messageInfo.mPeerPort = kCoapUdpPort;
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
otLogInfoMeshCoP("sent MGMT_COMMISSIONER_SET.req to leader\n");
exit:
if (error != kThreadError_None && message != NULL)
{
mIsSendMgmtCommRequest = false;
message->Free();
}
return error;
}
ThreadError Commissioner::SendPetition(void)
{
ThreadError error = kThreadError_None;
@@ -278,6 +417,15 @@ void Commissioner::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
memcmp(mCoapToken, header.GetToken(), sizeof(mCoapToken)) == 0, ;);
aMessage.MoveOffset(header.GetLength());
if (mIsSendMgmtCommRequest)
{
mIsSendMgmtCommRequest = false;
otLogInfoMeshCoP("received MGMT_COMMISSIONER_SET and MGMT_COMMISSIONER_GET response\r\n");
ExitNow();
}
SuccessOrExit(Tlv::GetTlv(aMessage, Tlv::kState, sizeof(state), state));
VerifyOrExit(state.IsValid(), ;);
+29
View File
@@ -88,6 +88,33 @@ public:
EnergyScanClient mEnergyScan;
PanIdQueryClient mPanIdQuery;
/**
* This method sends MGMT_COMMISSIONER_GET.
*
* @param[in] aTlvs A pointer to Commissioning Data TLVs.
* @param[in] aLength The length of requested TLVs in bytes.
*
* @retval kThreadError_None Send MGMT_COMMISSIONER_GET successfully.
* @retval kThreadError_Failed Send MGMT_COMMISSIONER_GET fail.
*
*/
ThreadError SendMgmtCommissionerGetRequest(const uint8_t *aTlvs, uint8_t aLength);
/**
* This method sends MGMT_COMMISSIONER_SET.
*
* @param[in] aDataset A reference to Commissioning Data.
* @param[in] aTlvs A pointer to user specific Commissioning Data TLVs.
* @param[in] aLength The length of user specific TLVs in bytes.
*
* @retval kThreadError_None Send MGMT_COMMISSIONER_SET successfully.
* @retval kThreadError_Failed Send MGMT_COMMISSIONER_SET fail.
*
*/
ThreadError SendMgmtCommissionerSetRequest(const otCommissioningDataset &aDataset,
const uint8_t *aTlvs, uint8_t aLength);
private:
static void HandleTimer(void *aContext);
void HandleTimer(void);
@@ -139,6 +166,8 @@ private:
Coap::Resource mRelayReceive;
ThreadNetif &mNetif;
bool mIsSendMgmtCommRequest = false;
};
} // namespace MeshCoP
+11
View File
@@ -1366,6 +1366,17 @@ ThreadError otCommissionerPanIdQuery(otInstance *, uint16_t aPanId, uint32_t aCh
*static_cast<const Ip6::Address *>(aAddress),
aCallback, aContext);
}
ThreadError otSendMgmtCommissionerGet(otInstance *, const uint8_t *aTlvs, uint8_t aLength)
{
return sThreadNetif->GetCommissioner().SendMgmtCommissionerGetRequest(aTlvs, aLength);
}
ThreadError otSendMgmtCommissionerSet(otInstance *, const otCommissioningDataset *aDataset,
const uint8_t *aTlvs, uint8_t aLength)
{
return sThreadNetif->GetCommissioner().SendMgmtCommissionerSetRequest(*aDataset, aTlvs, aLength);
}
#endif // OPENTHREAD_ENABLE_COMMISSIONER
#if OPENTHREAD_ENABLE_JOINER
+1 -5
View File
@@ -604,11 +604,7 @@ public:
void SetBit(uint8_t aBit) { mSteeringData[aBit / 8] |= 1 << (aBit % 8); }
private:
enum
{
kMaxLength = 16,
};
uint8_t mSteeringData[kMaxLength];
uint8_t mSteeringData[OT_STEERING_DATA_MAX_LENGTH];
} OT_TOOL_PACKED_END;
/**
+209
View File
@@ -55,6 +55,8 @@ Leader::Leader(ThreadNetif &aThreadNetif):
NetworkData(aThreadNetif, false),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, &Leader::HandleTimer, this),
mServerData(OPENTHREAD_URI_SERVER_DATA, &Leader::HandleServerData, this),
mCommissioningDataGet(OPENTHREAD_URI_COMMISSIONER_GET, &Leader::HandleCommissioningGet, this),
mCommissioningDataSet(OPENTHREAD_URI_COMMISSIONER_SET, &Leader::HandleCommissioningSet, this),
mCoapServer(aThreadNetif.GetCoapServer()),
mNetif(aThreadNetif)
{
@@ -75,11 +77,15 @@ void Leader::Reset(void)
void Leader::Start(void)
{
mCoapServer.AddResource(mServerData);
mCoapServer.AddResource(mCommissioningDataGet);
mCoapServer.AddResource(mCommissioningDataSet);
}
void Leader::Stop(void)
{
mCoapServer.RemoveResource(mServerData);
mCoapServer.RemoveResource(mCommissioningDataGet);
mCoapServer.RemoveResource(mCommissioningDataSet);
}
uint8_t Leader::GetVersion(void) const
@@ -551,6 +557,106 @@ void Leader::HandleServerData(Coap::Header &aHeader, Message &aMessage,
SendServerDataResponse(aHeader, aMessageInfo, NULL, 0);
}
void Leader::HandleCommissioningSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
Leader *obj = static_cast<Leader *>(aContext);
obj->HandleCommissioningSet(aHeader, aMessage, aMessageInfo);
}
void Leader::HandleCommissioningSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
uint16_t offset = aMessage.GetOffset();
uint8_t length = static_cast<uint8_t>(aMessage.GetLength() - aMessage.GetOffset());
uint8_t tlvs[NetworkData::kMaxSize];
MeshCoP::StateTlv::State state = MeshCoP::StateTlv::kAccept;
bool hasSessionId = false;
uint16_t sessionId = 0;
VerifyOrExit(mMle.GetDeviceState() == Mle::kDeviceStateLeader, state = MeshCoP::StateTlv::kReject);
aMessage.Read(offset, length, tlvs);
// Session Id and Border Router Locator MUST NOT be set, and only includes commissioning data tlvs
for (MeshCoP::Tlv *cur = reinterpret_cast<MeshCoP::Tlv *>(tlvs);
cur < reinterpret_cast<MeshCoP::Tlv *>(tlvs + length);
cur = cur->GetNext())
{
MeshCoP::Tlv::Type type = cur->GetType();
VerifyOrExit(type == MeshCoP::Tlv::kCommissionerSessionId ||
type == MeshCoP::Tlv::kJoinerUdpPort || type == MeshCoP::Tlv::kSteeringData,
state = MeshCoP::StateTlv::kReject);
if (type == MeshCoP::Tlv::kCommissionerSessionId)
{
hasSessionId = true;
sessionId = static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId();
}
}
VerifyOrExit(hasSessionId, state = MeshCoP::StateTlv::kReject);
for (MeshCoP::Tlv *cur = reinterpret_cast<MeshCoP::Tlv *>(mTlvs + sizeof(CommissioningDataTlv));
cur < reinterpret_cast<MeshCoP::Tlv *>(mTlvs + mLength);
cur = cur->GetNext())
{
if (cur->GetType() == MeshCoP::Tlv::kCommissionerSessionId)
{
VerifyOrExit(sessionId ==
static_cast<MeshCoP::CommissionerSessionIdTlv *>(cur)->GetCommissionerSessionId(),
state = MeshCoP::StateTlv::kReject);
}
else if (cur->GetType() == MeshCoP::Tlv::kBorderAgentLocator)
{
memcpy(tlvs + length, reinterpret_cast<uint8_t *>(cur), cur->GetLength() + sizeof(MeshCoP::Tlv));
length += (cur->GetLength() + sizeof(MeshCoP::Tlv));
}
}
SetCommissioningData(tlvs, length);
exit:
if (mMle.GetDeviceState() == Mle::kDeviceStateLeader)
{
SendCommissioningSetResponse(aHeader, aMessageInfo, state);
}
return;
}
void Leader::HandleCommissioningGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo)
{
Leader *obj = static_cast<Leader *>(aContext);
obj->HandleCommissioningGet(aHeader, aMessage, aMessageInfo);
}
void Leader::HandleCommissioningGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
MeshCoP::Tlv tlv;
uint16_t offset = aMessage.GetOffset();
uint8_t tlvs[NetworkData::kMaxSize];
uint8_t length = 0;
while (offset < aMessage.GetLength())
{
aMessage.Read(offset, sizeof(tlv), &tlv);
if (tlv.GetType() == MeshCoP::Tlv::kGet)
{
length = tlv.GetLength();
aMessage.Read(offset + sizeof(MeshCoP::Tlv), length, tlvs);
break;
}
offset += sizeof(tlv) + tlv.GetLength();
}
SendCommissioningGetResponse(aHeader, aMessageInfo, tlvs, length);
}
void Leader::SendServerDataResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
const uint8_t *aTlvs, uint8_t aTlvsLength)
{
@@ -581,6 +687,109 @@ exit:
}
}
void Leader::SendCommissioningGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
uint8_t *aTlvs, uint8_t aLength)
{
ThreadError error = kThreadError_None;
Coap::Header responseHeader;
Message *message;
uint8_t index;
uint8_t *data = NULL;
uint8_t length = 0;
VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
responseHeader.Init();
responseHeader.SetVersion(1);
responseHeader.SetType(Coap::Header::kTypeAcknowledgment);
responseHeader.SetCode(Coap::Header::kCodeChanged);
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
responseHeader.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
responseHeader.Finalize();
SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength()));
for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
cur = cur->GetNext())
{
if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
{
data = cur->GetValue();
length = cur->GetLength();
break;
}
}
VerifyOrExit(data && length, error = kThreadError_Drop);
if (aLength == 0)
{
SuccessOrExit(error = message->Append(data, length));
}
else
{
for (index = 0; index < aLength; index++)
{
for (MeshCoP::Tlv *cur = reinterpret_cast<MeshCoP::Tlv *>(data);
cur < reinterpret_cast<MeshCoP::Tlv *>(data + length);
cur = cur->GetNext())
{
if (cur->GetType() == aTlvs[index])
{
SuccessOrExit(error = message->Append(cur, sizeof(NetworkDataTlv) + cur->GetLength()));
break;
}
}
}
}
SuccessOrExit(error = mCoapServer.SendMessage(*message, aMessageInfo));
otLogInfoMeshCoP("sent commissioning dataset get response\n");
exit:
if (error != kThreadError_None && message != NULL)
{
message->Free();
}
}
void Leader::SendCommissioningSetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
MeshCoP::StateTlv::State aState)
{
ThreadError error = kThreadError_None;
Coap::Header responseHeader;
Message *message;
MeshCoP::StateTlv state;
VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
responseHeader.Init();
responseHeader.SetVersion(1);
responseHeader.SetType(Coap::Header::kTypeAcknowledgment);
responseHeader.SetCode(Coap::Header::kCodeChanged);
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
responseHeader.AppendContentFormatOption(Coap::Header::kApplicationOctetStream);
responseHeader.Finalize();
SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength()));
state.Init();
state.SetState(aState);
SuccessOrExit(error = message->Append(&state, sizeof(state)));
SuccessOrExit(error = mCoapServer.SendMessage(*message, aMessageInfo));
otLogInfoMeshCoP("sent commissioning dataset set response\n");
exit:
if (error != kThreadError_None && message != NULL)
{
message->Free();
}
}
void Leader::RlocLookup(uint16_t aRloc16, bool &aIn, bool &aStable, uint8_t *aTlvs, uint8_t aTlvsLength)
{
NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(aTlvs);
+15
View File
@@ -281,6 +281,18 @@ private:
bool IsStableUpdated(uint16_t aRloc16, uint8_t *aTlvs, uint8_t aTlvsLength, uint8_t *aTlvsBase,
uint8_t aTlvsBaseLength);
static void HandleCommissioningSet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleCommissioningSet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleCommissioningGet(void *aContext, Coap::Header &aHeader, Message &aMessage,
const Ip6::MessageInfo &aMessageInfo);
void HandleCommissioningGet(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendCommissioningGetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
uint8_t *aTlvs, uint8_t aLength);
void SendCommissioningSetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo,
MeshCoP::StateTlv::State aState);
/**
* Thread Specification Constants
@@ -302,6 +314,9 @@ private:
uint8_t mStableVersion;
uint8_t mVersion;
Coap::Resource mCommissioningDataGet;
Coap::Resource mCommissioningDataSet;
Coap::Server &mCoapServer;
ThreadNetif &mNetif;
};
+16
View File
@@ -194,6 +194,22 @@ namespace Thread {
*/
#define OPENTHREAD_URI_PANID_QUERY "c/pq"
/**
* @def OPENTHREAD_URI_COMMISSIONER_GET
*
* The URI Path for MGMT_COMMISSIONER_GET
*
*/
#define OPENTHREAD_URI_COMMISSIONER_GET "c/cg"
/**
* @def OPENTHREAD_URI_COMMISSIONER_SET
*
* The URI Path for MGMT_COMMISSIONER_SET
*
*/
#define OPENTHREAD_URI_COMMISSIONER_SET "c/cs"
} // namespace Thread
#endif // THREAD_URIS_HPP_