mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 13:47:47 +00:00
Implement Provisioning URL TLV. (#646)
This commit is contained in:
@@ -49,14 +49,15 @@ extern "C" {
|
||||
/**
|
||||
* This function enables the Thread Commissioner role.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the Commissioner role.
|
||||
* @retval kThreadError_InvalidArgs @p aPSKd is invalid.
|
||||
* @retval kThreadError_InvalidArgs @p aPSKd or @p aProvisioningUrl is invalid.
|
||||
*
|
||||
*/
|
||||
ThreadError otCommissionerStart(otInstance *aInstance, const char *aPSKd);
|
||||
ThreadError otCommissionerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl);
|
||||
|
||||
/**
|
||||
* This function disables the Thread Commissioner role.
|
||||
|
||||
@@ -49,14 +49,15 @@ extern "C" {
|
||||
/**
|
||||
* This function enables the Thread Joiner role.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the Commissioner role.
|
||||
* @retval kThreadError_InvalidArgs @p aPSKd is invalid.
|
||||
* @retval kThreadError_InvalidArgs @p aPSKd or @p aProvisioningUrl is invalid.
|
||||
*
|
||||
*/
|
||||
ThreadError otJoinerStart(otInstance *aInstance, const char *aPSKd);
|
||||
ThreadError otJoinerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl);
|
||||
|
||||
/**
|
||||
* This function disables the Thread Joiner role.
|
||||
|
||||
@@ -402,6 +402,7 @@ typedef enum otMeshcopTlvType
|
||||
OT_MESHCOP_TLV_JOINER_IID = 19, ///< meshcop Joiner IID TLV
|
||||
OT_MESHCOP_TLV_JOINER_RLOC = 20, ///< meshcop Joiner Router Locator TLV
|
||||
OT_MESHCOP_TLV_JOINER_ROUTER_KEK = 21, ///< meshcop Joiner Router KEK TLV
|
||||
OT_MESHCOP_TLV_PROVISIONING_URL = 32, ///< meshcop Provisioning URL 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
|
||||
|
||||
+6
-2
@@ -1912,8 +1912,10 @@ void Interpreter::ProcessCommissioner(int argc, char *argv[])
|
||||
|
||||
if (strcmp(argv[0], "start") == 0)
|
||||
{
|
||||
const char *provisioningUrl;
|
||||
VerifyOrExit(argc > 1, error = kThreadError_Parse);
|
||||
otCommissionerStart(mInstance, argv[1]);
|
||||
provisioningUrl = argc > 2 ? argv[2] : NULL;
|
||||
otCommissionerStart(mInstance, argv[1], provisioningUrl);
|
||||
}
|
||||
else if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
@@ -2022,8 +2024,10 @@ void Interpreter::ProcessJoiner(int argc, char *argv[])
|
||||
|
||||
if (strcmp(argv[0], "start") == 0)
|
||||
{
|
||||
const char *provisioningUrl;
|
||||
VerifyOrExit(argc > 1, error = kThreadError_Parse);
|
||||
otJoinerStart(mInstance, argv[1]);
|
||||
provisioningUrl = (argc > 2) ? argv[2] : NULL;
|
||||
otJoinerStart(mInstance, argv[1], provisioningUrl);
|
||||
}
|
||||
else if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
|
||||
@@ -65,7 +65,7 @@ Commissioner::Commissioner(ThreadNetif &aThreadNetif):
|
||||
aThreadNetif.GetCoapServer().AddResource(mRelayReceive);
|
||||
}
|
||||
|
||||
ThreadError Commissioner::Start(const char *aPSKd)
|
||||
ThreadError Commissioner::Start(const char *aPSKd, const char *aProvisioningUrl)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
@@ -73,6 +73,7 @@ ThreadError Commissioner::Start(const char *aPSKd)
|
||||
|
||||
SuccessOrExit(error = mNetif.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd),
|
||||
static_cast<uint8_t>(strlen(aPSKd))));
|
||||
SuccessOrExit(error = mNetif.GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl));
|
||||
SuccessOrExit(error = mSocket.Open(HandleUdpReceive, this));
|
||||
mState = kStatePetition;
|
||||
SendPetition();
|
||||
@@ -429,18 +430,21 @@ exit:
|
||||
|
||||
void Commissioner::ReceiveJoinerFinalize(uint8_t *buf, uint16_t length)
|
||||
{
|
||||
Message *message;
|
||||
Message *message = NULL;
|
||||
Coap::Header header;
|
||||
char uriPath[16];
|
||||
char *curUriPath = uriPath;
|
||||
const Coap::Header::Option *coapOption;
|
||||
|
||||
StateTlv::State state = StateTlv::kAccept;
|
||||
ProvisioningUrlTlv provisioningUrl;
|
||||
|
||||
otLogInfoMeshCoP("receive joiner finalize 1\r\n");
|
||||
|
||||
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
|
||||
SuccessOrExit(message->Append(buf, length));
|
||||
SuccessOrExit(header.FromMessage(*message));
|
||||
message->SetOffset(header.GetLength());
|
||||
SuccessOrExit(message->SetOffset(header.GetLength()));
|
||||
|
||||
coapOption = header.GetCurrentOption();
|
||||
|
||||
@@ -465,15 +469,34 @@ void Commissioner::ReceiveJoinerFinalize(uint8_t *buf, uint16_t length)
|
||||
coapOption = header.GetNextOption();
|
||||
}
|
||||
|
||||
curUriPath[-1] = '\0';
|
||||
if (curUriPath > uriPath)
|
||||
{
|
||||
curUriPath[-1] = '\0';
|
||||
}
|
||||
|
||||
SendJoinFinalizeResponse(header);
|
||||
VerifyOrExit(strcmp(uriPath, OPENTHREAD_URI_JOINER_FINALIZE) == 0,);
|
||||
|
||||
if (Tlv::GetTlv(*message, Tlv::kProvisioningUrl, sizeof(provisioningUrl), provisioningUrl) == kThreadError_None)
|
||||
{
|
||||
if (provisioningUrl.GetLength() != mNetif.GetDtls().mProvisioningUrl.GetLength() ||
|
||||
memcmp(provisioningUrl.GetProvisioningUrl(), mNetif.GetDtls().mProvisioningUrl.GetProvisioningUrl(),
|
||||
provisioningUrl.GetLength()) != 0)
|
||||
{
|
||||
state = StateTlv::kReject;
|
||||
}
|
||||
}
|
||||
|
||||
SendJoinFinalizeResponse(header, state);
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader)
|
||||
void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState)
|
||||
{
|
||||
Coap::Header responseHeader;
|
||||
MeshCoP::StateTlv *stateTlv;
|
||||
@@ -491,7 +514,7 @@ void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader)
|
||||
|
||||
stateTlv = reinterpret_cast<MeshCoP::StateTlv *>(cur);
|
||||
stateTlv->Init();
|
||||
stateTlv->SetState(MeshCoP::StateTlv::kAccept);
|
||||
stateTlv->SetState(aState);
|
||||
cur += sizeof(*stateTlv);
|
||||
|
||||
mSendKek = true;
|
||||
|
||||
@@ -61,12 +61,13 @@ public:
|
||||
/**
|
||||
* This method starts the Commissioner service.
|
||||
*
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the Commissioner service.
|
||||
*
|
||||
*/
|
||||
ThreadError Start(const char *aPSKd);
|
||||
ThreadError Start(const char *aPSKd, const char *aProvisioningUrl);
|
||||
|
||||
/**
|
||||
* This method stops the Commissioner service.
|
||||
@@ -108,7 +109,7 @@ private:
|
||||
void HandleUdpTransmit(void);
|
||||
|
||||
void ReceiveJoinerFinalize(uint8_t *buf, uint16_t length);
|
||||
void SendJoinFinalizeResponse(const Coap::Header &aRequestHeader);
|
||||
void SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState);
|
||||
|
||||
ThreadError SendPetition(void);
|
||||
ThreadError SendKeepAlive(void);
|
||||
|
||||
@@ -54,6 +54,7 @@ Dtls::Dtls(ThreadNetif &aNetif):
|
||||
mTimerSet(false),
|
||||
mNetif(aNetif)
|
||||
{
|
||||
mProvisioningUrl.Init();
|
||||
}
|
||||
|
||||
ThreadError Dtls::Start(bool aClient, ReceiveHandler aReceiveHandler, SendHandler aSendHandler, void *aContext)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <common/message.hpp>
|
||||
#include <common/timer.hpp>
|
||||
#include <crypto/sha256.hpp>
|
||||
#include <thread/meshcop_tlvs.hpp>
|
||||
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
@@ -158,6 +159,12 @@ public:
|
||||
*/
|
||||
ThreadError Receive(Message &aMessage, uint16_t aOffset, uint16_t aLength);
|
||||
|
||||
/**
|
||||
* The provisioning URL is placed here so that both the Commissioner and Joiner can share the same object.
|
||||
*
|
||||
*/
|
||||
ProvisioningUrlTlv mProvisioningUrl;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ Joiner::Joiner(ThreadNetif &aNetif):
|
||||
mNetif.GetCoapServer().AddResource(mJoinerEntrust);
|
||||
}
|
||||
|
||||
ThreadError Joiner::Start(const char *aPSKd)
|
||||
ThreadError Joiner::Start(const char *aPSKd, const char *aProvisioningUrl)
|
||||
{
|
||||
ThreadError error;
|
||||
Mac::ExtAddress extAddress;
|
||||
@@ -76,6 +76,7 @@ ThreadError Joiner::Start(const char *aPSKd)
|
||||
|
||||
SuccessOrExit(error = mNetif.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd),
|
||||
static_cast<uint8_t>(strlen(aPSKd))));
|
||||
SuccessOrExit(error = mNetif.GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl));
|
||||
SuccessOrExit(error = mNetif.GetMle().Discover(0, 0, mNetif.GetMac().GetPanId(), HandleDiscoverResult, this));
|
||||
|
||||
exit:
|
||||
@@ -215,7 +216,8 @@ exit:
|
||||
void Joiner::SendJoinerFinalize(void)
|
||||
{
|
||||
Coap::Header header;
|
||||
MeshCoP::StateTlv *stateTlv;
|
||||
StateTlv *stateTlv;
|
||||
uint8_t length;
|
||||
uint8_t buf[128];
|
||||
uint8_t *cur = buf;
|
||||
|
||||
@@ -234,6 +236,15 @@ void Joiner::SendJoinerFinalize(void)
|
||||
stateTlv->SetState(MeshCoP::StateTlv::kAccept);
|
||||
cur += sizeof(*stateTlv);
|
||||
|
||||
length = mNetif.GetDtls().mProvisioningUrl.GetLength();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
length += sizeof(Tlv);
|
||||
memcpy(cur, &mNetif.GetDtls().mProvisioningUrl, length);
|
||||
cur += length;
|
||||
}
|
||||
|
||||
mNetif.GetDtls().Send(buf, static_cast<uint16_t>(cur - buf));
|
||||
|
||||
otLogInfoMeshCoP("Sent joiner finalize\r\n");
|
||||
@@ -241,24 +252,33 @@ void Joiner::SendJoinerFinalize(void)
|
||||
|
||||
void Joiner::ReceiveJoinerFinalizeResponse(uint8_t *buf, uint16_t length)
|
||||
{
|
||||
Message *message;
|
||||
Message *message = NULL;
|
||||
Coap::Header header;
|
||||
StateTlv state;
|
||||
|
||||
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
|
||||
SuccessOrExit(message->Append(buf, length));
|
||||
SuccessOrExit(header.FromMessage(*message));
|
||||
SuccessOrExit(message->SetOffset(header.GetLength()));
|
||||
|
||||
VerifyOrExit(header.GetType() == Coap::Header::kTypeAcknowledgment &&
|
||||
header.GetCode() == Coap::Header::kCodeChanged &&
|
||||
header.GetMessageId() == 0 &&
|
||||
header.GetTokenLength() == 0, ;);
|
||||
|
||||
otLogInfoMeshCoP("received joiner finalize response\r\n");
|
||||
SuccessOrExit(Tlv::GetTlv(*message, Tlv::kState, sizeof(state), state));
|
||||
VerifyOrExit(state.IsValid(), ;);
|
||||
|
||||
otLogInfoMeshCoP("received joiner finalize response %d\r\n", static_cast<uint8_t>(state.GetState()));
|
||||
|
||||
Close();
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
void Joiner::HandleJoinerEntrust(void *aContext, Coap::Header &aHeader,
|
||||
|
||||
@@ -63,12 +63,13 @@ public:
|
||||
/**
|
||||
* This method starts the Joiner service.
|
||||
*
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
|
||||
*
|
||||
* @retval kThreadError_None Successfully started the Joiner service.
|
||||
*
|
||||
*/
|
||||
ThreadError Start(const char *aPSKd);
|
||||
ThreadError Start(const char *aPSKd, const char *aProvisioningUrl);
|
||||
|
||||
/**
|
||||
* This method stops the Joiner service.
|
||||
|
||||
@@ -1339,9 +1339,9 @@ ThreadError otSendPendingSet(otInstance *, const otOperationalDataset *aDataset,
|
||||
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
#include <commissioning/commissioner.h>
|
||||
ThreadError otCommissionerStart(otInstance *, const char *aPSKd)
|
||||
ThreadError otCommissionerStart(otInstance *, const char *aPSKd, const char *aProvisioningUrl)
|
||||
{
|
||||
return sThreadNetif->GetCommissioner().Start(aPSKd);
|
||||
return sThreadNetif->GetCommissioner().Start(aPSKd, aProvisioningUrl);
|
||||
}
|
||||
|
||||
ThreadError otCommissionerStop(otInstance *)
|
||||
@@ -1369,9 +1369,9 @@ ThreadError otCommissionerPanIdQuery(otInstance *, uint16_t aPanId, uint32_t aCh
|
||||
#endif // OPENTHREAD_ENABLE_COMMISSIONER
|
||||
|
||||
#if OPENTHREAD_ENABLE_JOINER
|
||||
ThreadError otJoinerStart(otInstance *, const char *aPSKd)
|
||||
ThreadError otJoinerStart(otInstance *, const char *aPSKd, const char *aProvisioningUrl)
|
||||
{
|
||||
return sThreadNetif->GetJoiner().Start(aPSKd);
|
||||
return sThreadNetif->GetJoiner().Start(aPSKd, aProvisioningUrl);
|
||||
}
|
||||
|
||||
ThreadError otJoinerStop(otInstance *)
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
kJoinerIid = OT_MESHCOP_TLV_JOINER_IID, ///< Joiner IID TLV
|
||||
kJoinerRouterLocator = OT_MESHCOP_TLV_JOINER_RLOC, ///< Joiner Router Locator TLV
|
||||
kJoinerRouterKek = OT_MESHCOP_TLV_JOINER_ROUTER_KEK, ///< Joiner Router KEK TLV
|
||||
kProvisioningUrl = OT_MESHCOP_TLV_PROVISIONING_URL, ///< Provisioning URL 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
|
||||
@@ -1491,6 +1492,62 @@ public:
|
||||
bool IsValid(void) const { return true; }
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Provisioning URL TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ProvisioningUrlTlv: public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void) { SetType(kProvisioningUrl); SetLength(0); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() <= sizeof(*this) - sizeof(Tlv); }
|
||||
|
||||
/**
|
||||
* This method returns the Provisioning URL value.
|
||||
*
|
||||
* @returns The Provisioning URL value.
|
||||
*
|
||||
*/
|
||||
const char *GetProvisioningUrl(void) const { return mProvisioningUrl; }
|
||||
|
||||
/**
|
||||
* This method sets the Provisioning URL value.
|
||||
*
|
||||
* @param[in] aProvisioningUrl A pointer to the Provisioning URL value.
|
||||
*
|
||||
*/
|
||||
ThreadError SetProvisioningUrl(const char *aProvisioningUrl) {
|
||||
ThreadError error = kThreadError_None;
|
||||
size_t len = aProvisioningUrl ? strnlen(aProvisioningUrl, kMaxLength + 1) : 0;
|
||||
SetLength(static_cast<uint8_t>(len));
|
||||
VerifyOrExit(len <= kMaxLength, error = kThreadError_InvalidArgs);
|
||||
memcpy(mProvisioningUrl, aProvisioningUrl, len);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxLength = 64,
|
||||
};
|
||||
|
||||
char mProvisioningUrl[kMaxLength];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Discovery Request TLV generation and parsing.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user