From f4ea00c5f3075490a75fc037b131bea300a959af Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Wed, 31 Aug 2016 01:48:52 +0800 Subject: [PATCH] Add CLI for sending MGMT_ACTIVE_GET/SET, MGMT_PENDING_GET/SET (Reopen #402) (#474) * Add CLI for sending MGMT_ACTIVE_GET, MGMT_ACTIVE_SET, MGMT_PENDING_GET and MGMT_PENDING_SET --- include/openthread-types.h | 24 ++ include/openthread.h | 50 ++++ src/cli/README.md | 271 ++++++++++++++++++++ src/cli/cli.hpp | 2 +- src/cli/cli_dataset.cpp | 200 ++++++++++++++- src/cli/cli_dataset.hpp | 2 + src/core/openthread.cpp | 21 ++ src/core/thread/meshcop_dataset_manager.cpp | 183 ++++++++++++- src/core/thread/meshcop_dataset_manager.hpp | 4 + src/core/thread/meshcop_tlvs.hpp | 32 +-- 10 files changed, 769 insertions(+), 20 deletions(-) diff --git a/include/openthread-types.h b/include/openthread-types.h index a23e1871e..99ae3b15e 100644 --- a/include/openthread-types.h +++ b/include/openthread-types.h @@ -321,6 +321,30 @@ typedef struct otOperationalDataset bool mIsChannelSet : 1; ///< TRUE if Channel is set, FALSE otherwise. } otOperationalDataset; +/** + * This enumeration represents meshcop TLV types. + * + */ +typedef enum otMeshcopTlvType +{ + OT_MESHCOP_TLV_CHANNEL = 0, ///< meshcop Channel TLV + OT_MESHCOP_TLV_PANID = 1, ///< meshcop Pan Id TLV + OT_MESHCOP_TLV_EXTPANID = 2, ///< meshcop Extended Pan Id TLV + OT_MESHCOP_TLV_NETWORKNAME = 3, ///< meshcop Network Name TLV + OT_MESHCOP_TLV_PSKC = 4, ///< meshcop PSKc TLV + OT_MESHCOP_TLV_MASTERKEY = 5, ///< meshcop Network Master Key TLV + OT_MESHCOP_TLV_LOCALPREFIX = 7, ///< meshcop Mesh Local Prefix TLV + OT_MESHCOP_TLV_SECURITYPOLICY = 12, ///< meshcop Security Policy TLV + OT_MESHCOP_TLV_GET = 13, ///< meshcop Get TLV + OT_MESHCOP_TLV_ACTIVETIMESTAMP = 14, ///< meshcop Active Timestamp TLV + OT_MESHCOP_TLV_STATE = 16, ///< meshcop State TLV + OT_MESHCOP_TLV_PENDINGTIMESTAMP = 51, ///< meshcop Pending Timestamp TLV + OT_MESHCOP_TLV_DELAYTIMER = 52, ///< meshcop Delay Timer TLV + OT_MESHCOP_TLV_CHANNELMASK = 53, ///< meshcop Channel Mask TLV + OT_MESHCOP_TLV_DISCOVERYREQUEST = 128, ///< meshcop Discovery Request TLV + OT_MESHCOP_TLV_DISCOVERYRESPONSE = 129, ///< meshcop Discovery Response TLV +} otMeshcopTlvType; + /** * This structure represents an MLE Link Mode configuration. */ diff --git a/include/openthread.h b/include/openthread.h index de121246f..510db6236 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -735,6 +735,56 @@ ThreadError otGetPendingDataset(otOperationalDataset *aDataset); */ ThreadError otSetPendingDataset(otOperationalDataset *aDataset); +/** + * This function sends MGMT_ACTIVE_GET. + * + * @param[in] aTlvTypes A pointer to the TLV Types. + * @param[in] aLength The length of TLV Types. + * + * @retval kThreadError_None Successfully send the meshcop dataset command. + * @retval kThreadError_NoBufs Insufficient buffer space to send. + * + */ +ThreadError otSendActiveGet(const uint8_t *aTlvTypes, uint8_t aLength); + +/** + * This function sends MGMT_ACTIVE_SET. + * + * @param[in] aDataset A pointer to operational 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 otSendActiveSet(const otOperationalDataset *aDataset, const uint8_t *aTlvs, uint8_t aLength); + +/** + * This function sends MGMT_PENDING_GET. + * + * @param[in] aTlvTypes A pointer to the TLV Types. + * @param[in] aLength The length of TLV Types. + * + * @retval kThreadError_None Successfully send the meshcop dataset command. + * @retval kThreadError_NoBufs Insufficient buffer space to send. + * + */ +ThreadError otSendPendingGet(const uint8_t *aTlvTypes, uint8_t aLength); + +/** + * This function sends MGMT_PENDING_SET. + * + * @param[in] aDataset A pointer to operational 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 otSendPendingSet(const otOperationalDataset *aDataset, const uint8_t *aTlvs, uint8_t aLength); + /** * Get the data poll period of sleepy end deivce. * diff --git a/src/cli/README.md b/src/cli/README.md index 5758511d5..40244afab 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -14,6 +14,7 @@ OpenThread test scripts use the CLI to execute test cases. * [childtimeout](#childtimeout) * [contextreusedelay](#contextreusedelay) * [counter](#counter) +* [dataset](#dataset) * [discover](#discover) * [eidcache](#eidcache) * [extaddr](#extaddr) @@ -255,6 +256,276 @@ RxTotal: 11 RxErrOther: 0 ``` +### dataset help + +Print meshcop dataset help menu. + +```bash +> dataset help +help +active +activetimestamp +channel +clear +commit +delay +extpanid +masterkey +meshlocalprefix +mgmtgetcommand +mgmtsetcommand +networkname +panid +pending +pendingtimestamp +userdata +Done +``` + +### dataset active + +Print meshcop active operational dataset. + +```bash +> dataset active +Active Timestamp: 0 +Done +``` + +### dataset activetimestamp + +Set getting active timestamp flag. + +```bash +> dataset activestamp +Done +``` + +### dataset activetimestamp \[activetimestamp\] + +Set active timestamp. + +```bash +> dataset activestamp 123456789 +Done +``` + +### dataset channel + +Set getting channel flag. + +```bash +> dataset channel +Done +``` + +### dataset channel \[channel\] + +Set channel. + +```bash +> dataset channel 12 +Done +``` + +### dataset clear + +Reset operational dataset buffer. + +```bash +> dataset clear +Done +``` + +### dataset commit \[commit\] + +Commit operational dataset buffer to active/pending operational dataset. + +```bash +> dataset commit active +Done +``` + +### dataset delay + +Set getting delay timer value flag. + +```bash +> dataset delay +Done +``` + +### dataset delay \[delay\] + +Set delay timer value. + +```bash +> dataset delay 1000 +Done +``` + +### dataset extpanid + +Set getting extended panid flag. + +```bash +> dataset extpanid +Done +``` + +### dataset extpanid \[extpanid\] + +Set extended panid. + +```bash +> dataset extpanid 000db80123456789 +Done +``` + +### dataset masterkey + +Set getting master key flag. + +```bash +> dataset masterkey +Done +``` + +### dataset masterkey \[masterkey\] + +Set master key. + +```bash +> dataset master 1234567890123456 +Done +``` + +### dataset meshlocalprefix + +Set getting mesh local prefix flag. + +```bash +> dataset meshlocalprefix +Done +``` + +### dataset meshlocalprefix fd00:db8:: + +Set mesh local prefix. + +```bash +> dataset meshlocalprefix fd00:db8:: +Done +``` + +### dataset mgmtgetcommand active \[TLVs list\] \[binary\] + +Send MGMT_ACTIVE_GET. + +```bash +> dataset mgmtgetcommand active activetimestamp 123 binary 0001 +Done +``` + +### dataset mgmtsetcommand active \[TLV Types list\] \[binary\] + +Send MGMT_ACTIVE_SET. + +```bash +> dataset mgmtsetcommand active activetimestamp binary 820155 +Done +``` + +### dataset mgmtgetcommand pending \[TLVs list\] \[binary\] + +Send MGMT_PENDING_GET. + +```bash +> dataset mgmtgetcommand pending activetimestamp binary 0001 +Done +``` + +### dataset mgmtsetcommand pending \[TLV Types list\] \[binary\] + +Send MGMT_PENDING_SET. + +```bash +> dataset mgmtsetcommand pending activetimestamp binary 820155 +Done +``` + +### dataset networkname + +Set getting network name flag. + +```bash +> dataset networkname +Done +``` + +### dataset networkname \[networkname\] + +Set network name. + +```bash +> dataset networkname openthread +Done +``` + +### dataset panid + +Set getting panid flag. + +```bash +> dataset panid +Done +``` + +### dataset panid \[panid\] + +Set panid. + +```bash +> dataset panid 0x1234 +Done +``` + +### dataset pending + +Print meshcop pending operational dataset. + +```bash +> dataset pending +Done +``` + +### dataset pendingtimestamp + +Set getting pending timestamp flag. + +```bash +> dataset pendingtimestamp +Done +``` + +### dataset pendingtimestamp \[pendingtimestamp\] + +Set pending timestamp. + +```bash +> dataset pendingtimestamp 123456789 +Done +``` + +### dataset userdata \[size\] \[data\] + +Set user specific data for the command. + +```bash +> dataset userdata 3 820155 +Done +``` + ### discover \[channel\] Perform an MLE Discovery operation. diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 087fac63f..0a96cfb4e 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -123,7 +123,7 @@ public: private: enum { - kMaxArgs = 8, + kMaxArgs = 32, }; static void AppendResult(ThreadError error); diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 3092b65c3..6f7edbeac 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -56,6 +56,8 @@ const DatasetCommand Dataset::sCommands[] = { "extpanid", &ProcessExtPanId }, { "masterkey", &ProcessMasterKey }, { "meshlocalprefix", &ProcessMeshLocalPrefix }, + { "mgmtgetcommand", &ProcessMgmtGetCommand }, + { "mgmtsetcommand", &ProcessMgmtSetCommand }, { "networkname", &ProcessNetworkName }, { "panid", &ProcessPanId }, { "pending", &ProcessPending }, @@ -346,7 +348,6 @@ ThreadError Dataset::ProcessPendingTimestamp(int argc, char *argv[]) long value; VerifyOrExit(argc > 0, error = kThreadError_Parse); - SuccessOrExit(error = Interpreter::ParseLong(argv[0], value)); sDataset.mPendingTimestamp = static_cast(value); sDataset.mIsPendingTimestampSet = true; @@ -355,5 +356,202 @@ exit: return error; } +ThreadError Dataset::ProcessMgmtSetCommand(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + otOperationalDataset dataset; + uint8_t tlvs[32]; + long value; + int length = 0; + otIp6Address prefix; + + VerifyOrExit(argc > 0, error = kThreadError_Parse); + + memset(&dataset, 0, sizeof(dataset)); + + for (uint8_t index = 1; index < argc; index++) + { + if (strcmp(argv[index], "activetimestamp") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsActiveTimestampSet = true; + SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value)); + dataset.mActiveTimestamp = static_cast(value); + } + else if (strcmp(argv[index], "pendingtimestamp") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsPendingTimestampSet = true; + SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value)); + dataset.mPendingTimestamp = static_cast(value); + } + else if (strcmp(argv[index], "masterkey") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsMasterKeySet = true; + VerifyOrExit((length = Interpreter::Hex2Bin(argv[++index], dataset.mMasterKey.m8, + sizeof(dataset.mMasterKey.m8))) == OT_MASTER_KEY_SIZE, error = kThreadError_Parse); + length = 0; + } + else if (strcmp(argv[index], "networkname") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsNetworkNameSet = true; + VerifyOrExit((length = static_cast(strlen(argv[++index]))) <= OT_NETWORK_NAME_MAX_SIZE, + error = kThreadError_Parse); + memset(&dataset.mNetworkName, 0, sizeof(sDataset.mNetworkName)); + memcpy(dataset.mNetworkName.m8, argv[0], static_cast(length)); + length = 0; + } + else if (strcmp(argv[index], "extpanid") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsExtendedPanIdSet = true; + VerifyOrExit(Interpreter::Hex2Bin(argv[++index], dataset.mExtendedPanId.m8, + sizeof(dataset.mExtendedPanId.m8)) >= 0, error = kThreadError_Parse); + } + else if (strcmp(argv[index], "localprefix") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsMeshLocalPrefixSet = true; + SuccessOrExit(error = otIp6AddressFromString(argv[++index], &prefix)); + memcpy(dataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(dataset.mMeshLocalPrefix.m8)); + } + else if (strcmp(argv[index], "delaytimer") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsDelaySet = true; + SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value)); + dataset.mDelay = static_cast(value); + } + else if (strcmp(argv[index], "panid") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsPanIdSet = true; + SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value)); + dataset.mPanId = static_cast(value); + } + else if (strcmp(argv[index], "channel") == 0) + { + VerifyOrExit(index < argc, error = kThreadError_Parse); + dataset.mIsChannelSet = true; + SuccessOrExit(error = Interpreter::ParseLong(argv[++index], value)); + dataset.mChannel = static_cast(value); + } + else if (strcmp(argv[index], "binary") == 0) + { + VerifyOrExit((index + 1) < argc, error = kThreadError_Parse); + length = static_cast((strlen(argv[++index]) + 1) / 2); + VerifyOrExit(static_cast(length) <= sizeof(tlvs), error = kThreadError_NoBufs); + VerifyOrExit(Interpreter::Hex2Bin(argv[index], tlvs, static_cast(length)) >= 0, + error = kThreadError_Parse); + } + else + { + ExitNow(error = kThreadError_Parse); + } + } + + if (strcmp(argv[0], "active") == 0) + { + SuccessOrExit(error = otSendActiveSet(&dataset, tlvs, static_cast(length))); + } + else if (strcmp(argv[0], "pending") == 0) + { + SuccessOrExit(error = otSendPendingSet(&dataset, tlvs, static_cast(length))); + } + else + { + ExitNow(error = kThreadError_Parse); + } + +exit: + return error; +} + +ThreadError Dataset::ProcessMgmtGetCommand(int argc, char *argv[]) +{ + ThreadError error = kThreadError_None; + otOperationalDataset 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(length) < sizeof(tlvs), error = kThreadError_NoBufs); + + if (strcmp(argv[index], "activetimestamp") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_ACTIVETIMESTAMP; + } + else if (strcmp(argv[index], "pendingtimestamp") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_PENDINGTIMESTAMP; + } + else if (strcmp(argv[index], "masterkey") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_MASTERKEY; + } + else if (strcmp(argv[index], "networkname") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_NETWORKNAME; + } + else if (strcmp(argv[index], "extpanid") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_EXTPANID; + } + else if (strcmp(argv[index], "localprefix") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_LOCALPREFIX; + } + else if (strcmp(argv[index], "delaytimer") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_DELAYTIMER; + } + else if (strcmp(argv[index], "panid") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_PANID; + } + else if (strcmp(argv[index], "channel") == 0) + { + tlvs[length++] = OT_MESHCOP_TLV_CHANNEL; + } + else if (strcmp(argv[index], "binary") == 0) + { + VerifyOrExit((index + 1) < argc, error = kThreadError_Parse); + value = (strlen(argv[++index]) + 1) / 2; + VerifyOrExit(static_cast(value) <= (sizeof(tlvs) - static_cast(length)), error = kThreadError_NoBufs); + VerifyOrExit(Interpreter::Hex2Bin(argv[index], tlvs + length, static_cast(value)) >= 0, + error = kThreadError_Parse); + length += value; + } + else + { + ExitNow(error = kThreadError_Parse); + } + } + + if (strcmp(argv[0], "active") == 0) + { + SuccessOrExit(error = otSendActiveGet(tlvs, static_cast(length))); + } + else if (strcmp(argv[0], "pending") == 0) + { + SuccessOrExit(error = otSendPendingGet(tlvs, static_cast(length))); + } + else + { + ExitNow(error = kThreadError_Parse); + } + +exit: + return error; +} + } // namespace Cli } // namespace Thread diff --git a/src/cli/cli_dataset.hpp b/src/cli/cli_dataset.hpp index daeb5d994..1c3518876 100644 --- a/src/cli/cli_dataset.hpp +++ b/src/cli/cli_dataset.hpp @@ -86,6 +86,8 @@ private: static ThreadError ProcessPanId(int argc, char *argv[]); static ThreadError ProcessPending(int argc, char *argv[]); static ThreadError ProcessPendingTimestamp(int argc, char *argv[]); + static ThreadError ProcessMgmtSetCommand(int argc, char *argv[]); + static ThreadError ProcessMgmtGetCommand(int argc, char *argv[]); static const DatasetCommand sCommands[]; static otOperationalDataset sDataset; diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 97c4547e2..0d7302304 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -45,6 +45,7 @@ #include #include #include +#include namespace Thread { @@ -1212,6 +1213,26 @@ exit: return error; } +ThreadError otSendActiveGet(const uint8_t *aTlvTypes, uint8_t aLength) +{ + return sThreadNetif->GetActiveDataset().SendGetRequest(aTlvTypes, aLength); +} + +ThreadError otSendActiveSet(const otOperationalDataset *aDataset, const uint8_t *aTlvs, uint8_t aLength) +{ + return sThreadNetif->GetActiveDataset().SendSetRequest(*aDataset, aTlvs, aLength); +} + +ThreadError otSendPendingGet(const uint8_t *aTlvTypes, uint8_t aLength) +{ + return sThreadNetif->GetPendingDataset().SendGetRequest(aTlvTypes, aLength); +} + +ThreadError otSendPendingSet(const otOperationalDataset *aDataset, const uint8_t *aTlvs, uint8_t aLength) +{ + return sThreadNetif->GetPendingDataset().SendSetRequest(*aDataset, aTlvs, aLength); +} + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index ca81de5a3..df176e036 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -34,6 +34,7 @@ #include +#include #include #include #include @@ -56,6 +57,7 @@ DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const char *aUriSet, c mResourceGet(aUriGet, &HandleGet, this), mTimer(&HandleTimer, this), mUriSet(aUriSet), + mUriGet(aUriGet), mCoapServer(aThreadNetif.GetCoapServer()) { mCoapServer.AddResource(mResourceSet); @@ -306,6 +308,182 @@ void DatasetManager::HandleGet(Coap::Header &aHeader, Message &aMessage, const I SendGetResponse(aHeader, aMessageInfo, tlvs, length); } +ThreadError DatasetManager::SendSetRequest(const otOperationalDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength) +{ + 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(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(mUriSet); + 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 (aDataset.mIsActiveTimestampSet) + { + ActiveTimestampTlv timestamp; + timestamp.Init(); + static_cast(×tamp)->SetSeconds((aDataset.mActiveTimestamp) >> 16); + static_cast(×tamp)->SetTicks((aDataset.mActiveTimestamp) & 0xffff); + SuccessOrExit(error = message->Append(×tamp, sizeof(timestamp))); + } + + if (aDataset.mIsPendingTimestampSet) + { + PendingTimestampTlv timestamp; + timestamp.Init(); + static_cast(×tamp)->SetSeconds((aDataset.mPendingTimestamp) >> 16); + static_cast(×tamp)->SetTicks((aDataset.mPendingTimestamp) & 0xffff); + SuccessOrExit(error = message->Append(×tamp, sizeof(timestamp))); + } + + if (aDataset.mIsMasterKeySet) + { + NetworkMasterKeyTlv masterkey; + masterkey.Init(); + masterkey.SetNetworkMasterKey(aDataset.mMasterKey.m8); + SuccessOrExit(error = message->Append(&masterkey, sizeof(masterkey))); + } + + if (aDataset.mIsNetworkNameSet) + { + NetworkNameTlv networkname; + networkname.Init(); + networkname.SetNetworkName(aDataset.mNetworkName.m8); + SuccessOrExit(error = message->Append(&networkname, sizeof(Tlv) + networkname.GetLength())); + } + + if (aDataset.mIsExtendedPanIdSet) + { + ExtendedPanIdTlv extpanid; + extpanid.Init(); + extpanid.SetExtendedPanId(aDataset.mExtendedPanId.m8); + SuccessOrExit(error = message->Append(&extpanid, sizeof(extpanid))); + } + + if (aDataset.mIsMeshLocalPrefixSet) + { + MeshLocalPrefixTlv localprefix; + localprefix.Init(); + localprefix.SetMeshLocalPrefix(aDataset.mMeshLocalPrefix.m8); + SuccessOrExit(error = message->Append(&localprefix, sizeof(localprefix))); + } + + if (aDataset.mIsDelaySet) + { + DelayTimerTlv delaytimer; + delaytimer.Init(); + delaytimer.SetDelayTimer(aDataset.mDelay); + SuccessOrExit(error = message->Append(&delaytimer, sizeof(delaytimer))); + } + + if (aDataset.mIsPanIdSet) + { + PanIdTlv panid; + panid.Init(); + panid.SetPanId(aDataset.mPanId); + SuccessOrExit(error = message->Append(&panid, sizeof(panid))); + } + + if (aDataset.mIsChannelSet) + { + ChannelTlv channel; + channel.Init(); + channel.SetChannel(aDataset.mChannel); + SuccessOrExit(error = message->Append(&channel, sizeof(channel))); + } + + if (aLength > 0) + { + SuccessOrExit(error = message->Append(aTlvs, aLength)); + } + + memset(&messageInfo, 0, sizeof(messageInfo)); + mMle.GetLeaderAddress(messageInfo.GetPeerAddr()); + messageInfo.mPeerPort = kCoapUdpPort; + SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + + otLogInfoMeshCoP("sent dataset set request to leader\n"); + +exit: + + if (error != kThreadError_None && message != NULL) + { + Message::Free(*message); + } + + return error; +} + +ThreadError DatasetManager::SendGetRequest(const uint8_t *aTlvTypes, const uint8_t aLength) +{ + ThreadError error = kThreadError_None; + Coap::Header header; + Message *message; + Ip6::MessageInfo messageInfo; + Tlv tlv; + + mSocket.Open(&HandleUdpReceive, this); + + for (size_t i = 0; i < sizeof(mCoapToken); i++) + { + mCoapToken[i] = static_cast(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(mUriGet); + 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 (aLength > 0) + { + tlv.SetType(Tlv::kGet); + tlv.SetLength(aLength); + SuccessOrExit(error = message->Append(&tlv, sizeof(tlv))); + SuccessOrExit(error = message->Append(aTlvTypes, aLength)); + } + + memset(&messageInfo, 0, sizeof(messageInfo)); + mMle.GetLeaderAddress(messageInfo.GetPeerAddr()); + messageInfo.mPeerPort = kCoapUdpPort; + SuccessOrExit(error = mSocket.SendTo(*message, messageInfo)); + + otLogInfoMeshCoP("sent dataset get request to leader\n"); + +exit: + + if (error != kThreadError_None && message != NULL) + { + Message::Free(*message); + } + + return error; +} + void DatasetManager::SendSetResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo, StateTlv::State aState) { @@ -368,7 +546,7 @@ void DatasetManager::SendGetResponse(const Coap::Header &aRequestHeader, const I { for (index = 0; index < aLength; index++) { - if ((tlv = mNetwork.Get((Tlv::Type)aTlvs[index])) != NULL) + if ((tlv = mNetwork.Get(static_cast(aTlvs[index]))) != NULL) { SuccessOrExit(error = message->Append(tlv, sizeof(Tlv) + tlv->GetLength())); } @@ -652,7 +830,8 @@ void PendingDataset::HandleTimer(void) mLocal.Remove(Tlv::kDelayTimer); - VerifyOrExit((activeTimestamp = static_cast(mLocal.Get(Tlv::kActiveTimestamp))) != NULL, ;); + VerifyOrExit((activeTimestamp = static_cast(mLocal.Get(Tlv::kActiveTimestamp))) != NULL, + ;); mNetif.GetActiveDataset().GetLocal() = mLocal; mNetif.GetActiveDataset().GetLocal().SetTimestamp(*activeTimestamp); diff --git a/src/core/thread/meshcop_dataset_manager.hpp b/src/core/thread/meshcop_dataset_manager.hpp index 4f62f11f0..ffd956c0d 100644 --- a/src/core/thread/meshcop_dataset_manager.hpp +++ b/src/core/thread/meshcop_dataset_manager.hpp @@ -59,6 +59,9 @@ public: Dataset &GetNetwork(void) { return mNetwork; } + ThreadError SendSetRequest(const otOperationalDataset &aDataset, const uint8_t *aTlvs, uint8_t aLength); + ThreadError SendGetRequest(const uint8_t *aTlvTypes, uint8_t aLength); + protected: enum { @@ -109,6 +112,7 @@ private: uint16_t mCoapMessageId; const char *mUriSet; + const char *mUriGet; Coap::Server &mCoapServer; }; diff --git a/src/core/thread/meshcop_tlvs.hpp b/src/core/thread/meshcop_tlvs.hpp index 6ecb4ee67..476d22e7e 100644 --- a/src/core/thread/meshcop_tlvs.hpp +++ b/src/core/thread/meshcop_tlvs.hpp @@ -60,22 +60,22 @@ public: */ enum Type { - kChannel = 0, ///< Channel TLV - kPanId = 1, ///< PAN ID TLV - kExtendedPanId = 2, ///< Extended PAN ID TLV - kNetworkName = 3, ///< Newtork Name TLV - kPSKc = 4, ///< PSKc TLV - kNetworkMasterKey = 5, ///< Network Master Key TLV - kMeshLocalPrefix = 7, ///< Mesh Local Prefix TLV - kSecurityPolicy = 12, ///< Security Policy TLV - kGet = 13, ///< Get TLV - kActiveTimestamp = 14, ///< Active Timestamp TLV - kState = 16, ///< State TLV - kPendingTimestamp = 51, ///< Pending Timestamp TLV - kDelayTimer = 52, ///< Delay Timer TLV - kChannelMask = 53, ///< Channel Mask TLV - kDiscoveryRequest = 128, ///< Discovery Request TLV - kDiscoveryResponse = 129, ///< Discovery Response TLV + kChannel = OT_MESHCOP_TLV_CHANNEL, ///< Channel TLV + kPanId = OT_MESHCOP_TLV_PANID, ///< PAN ID TLV + kExtendedPanId = OT_MESHCOP_TLV_EXTPANID, ///< Extended PAN ID TLV + kNetworkName = OT_MESHCOP_TLV_NETWORKNAME, ///< Newtork Name TLV + kPSKc = OT_MESHCOP_TLV_PSKC, ///< PSKc TLV + kNetworkMasterKey = OT_MESHCOP_TLV_MASTERKEY, ///< Network Master Key TLV + kMeshLocalPrefix = OT_MESHCOP_TLV_LOCALPREFIX, ///< Mesh Local Prefix TLV + kSecurityPolicy = OT_MESHCOP_TLV_SECURITYPOLICY, ///< Security Policy TLV + kGet = OT_MESHCOP_TLV_GET, ///< Get TLV + kActiveTimestamp = OT_MESHCOP_TLV_ACTIVETIMESTAMP, ///< Active Timestamp TLV + kState = OT_MESHCOP_TLV_STATE, ///< State TLV + kPendingTimestamp = OT_MESHCOP_TLV_PENDINGTIMESTAMP, ///< Pending Timestamp TLV + kDelayTimer = OT_MESHCOP_TLV_DELAYTIMER, ///< Delay Timer TLV + kChannelMask = OT_MESHCOP_TLV_CHANNELMASK, ///< Channel Mask TLV + kDiscoveryRequest = OT_MESHCOP_TLV_DISCOVERYREQUEST, ///< Discovery Request TLV + kDiscoveryResponse = OT_MESHCOP_TLV_DISCOVERYRESPONSE, ///< Discovery Response TLV }; /**