mirror of
https://github.com/espressif/openthread.git
synced 2026-08-11 13:17:48 +00:00
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:
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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(), ;);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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_
|
||||
|
||||
Reference in New Issue
Block a user