Commissioner joiner list. (#729)

This commit is contained in:
Jonathan Hui
2016-10-03 08:54:54 -07:00
committed by GitHub
parent 95d2e8cdec
commit cb04fe8391
12 changed files with 343 additions and 40 deletions
+43 -6
View File
@@ -50,23 +50,60 @@ 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] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
*
* @retval kThreadError_None Successfully started the Commissioner role.
* @retval kThreadError_InvalidArgs @p aPSKd or @p aProvisioningUrl is invalid.
* @retval kThreadError_None Successfully started the Commissioner role.
*
*/
ThreadError otCommissionerStart(otInstance *aInstance, const char *aPSKd, const char *aProvisioningUrl);
ThreadError otCommissionerStart(otInstance *aInstance);
/**
* This function disables the Thread Commissioner role.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @retval kThreadError_None Successfully started the Commissioner role.
*
*/
ThreadError otCommissionerStop(otInstance *aInstance);
/**
* This function adds a Joiner entry.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aExtAddress A pointer to the Joiner's extended address or NULL for any Joiner.
* @param[in] aPSKd A pointer to the PSKd.
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_NoBufs No buffers available to add the Joiner.
* @retval kThreadError_InvalidArgs @p aExtAddress or @p aPSKd is invalid.
*
*/
ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress, const char *aPSKd);
/**
* This function removes a Joiner entry.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aExtAddress A pointer to the Joiner's extended address or NULL for any Joiner.
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_NotFound The Joiner specified by @p aExtAddress was not found.
* @retval kThreadError_InvalidArgs @p aExtAddress is invalid.
*
*/
ThreadError otCommissionerRemoveJoiner(otInstance *aIntsance, const otExtAddress *aExtAddress);
/**
* This function sets the Provisioning URL.
*
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_InvalidArgs @p aProvisioningUrl is invalid.
*
*/
ThreadError otCommissionerSetProvisioningUrl(otInstance *aInstance, const char *aProvisioningUrl);
/**
* This function pointer is called when the Commissioner receives an Energy Report.
*
+34 -3
View File
@@ -213,17 +213,16 @@ Set the Thread Child Timeout value.
Done
```
### commissioner start \<psdk\> \<provisioningUrl\>
### commissioner start \<provisioningUrl\>
Start the Commissioner role.
* pskd: Pre-Shared Key for the Joiner.
* provisioningUrl: Provisioning URL for the Joiner (optional).
This command will cause the device to send LEAD_PET and LEAD_KA messages.
```bash
> commissioner start PSK
> commissioner start
Done
```
@@ -238,6 +237,38 @@ This command will cause the device to send LEAD_KA[Reject] messages.
Done
```
### commissioner joiner add \<hashmacaddr\> \<psdk\>
Add a Joiner entry.
* hashmacaddr: The Extended Address of the Joiner or '*' to match any Joiner.
* pskd: Pre-Shared Key for the Joiner.
```bash
> commissioner joiner add d45e64fa83f81cf7 PSK
Done
```
### commissioner joiner remove \<hashmacaddr\>
Remove a Joiner entry.
* hashmacaddr: The Extended Address of the Joiner or '*' to match any Joiner.
```bash
> commissioner joiner remove d45e64fa83f81cf7
Done
```
### commissioner provisioningurl \<provisioningUrl\>
Set the Provisioning URL.
```bash
> commissioner provisioningurl http://github.com/openthread/openthread
Done
```
### commissioner energy \<mask\> \<count\> \<period\> \<scanDuration\> \<destination\>
Send a MGMT_ED_SCAN message.
+33 -5
View File
@@ -1992,14 +1992,42 @@ void Interpreter::ProcessCommissioner(int argc, char *argv[])
if (strcmp(argv[0], "start") == 0)
{
const char *provisioningUrl;
VerifyOrExit(argc > 1, error = kThreadError_Parse);
provisioningUrl = argc > 2 ? argv[2] : NULL;
otCommissionerStart(mInstance, argv[1], provisioningUrl);
SuccessOrExit(error = otCommissionerStart(mInstance));
}
else if (strcmp(argv[0], "stop") == 0)
{
otCommissionerStop(mInstance);
SuccessOrExit(error = otCommissionerStop(mInstance));
}
else if (strcmp(argv[0], "joiner") == 0)
{
otExtAddress addr;
const otExtAddress *addrPtr;
VerifyOrExit(argc > 2, error = kThreadError_Parse);
if (strcmp(argv[2], "*") == 0)
{
addrPtr = NULL;
}
else
{
VerifyOrExit(Hex2Bin(argv[2], addr.m8, sizeof(addr)) == sizeof(addr), error = kThreadError_Parse);
addrPtr = &addr;
}
if (strcmp(argv[1], "add") == 0)
{
VerifyOrExit(argc > 3, error = kThreadError_Parse);
SuccessOrExit(error = otCommissionerAddJoiner(mInstance, addrPtr, argv[3]));
}
else if (strcmp(argv[1], "remove") == 0)
{
SuccessOrExit(error = otCommissionerRemoveJoiner(mInstance, addrPtr));
}
}
else if (strcmp(argv[0], "provisioningurl") == 0)
{
SuccessOrExit(error = otCommissionerSetProvisioningUrl(mInstance, (argc > 1) ? argv[1] : NULL));
}
else if (strcmp(argv[0], "energy") == 0)
{
+99 -7
View File
@@ -38,6 +38,7 @@
#endif
#include <stdio.h>
#include <string.h>
#include <coap/coap_header.hpp>
#include <common/logging.hpp>
@@ -63,18 +64,16 @@ Commissioner::Commissioner(ThreadNetif &aThreadNetif):
mNetif(aThreadNetif),
mIsSendMgmtCommRequest(false)
{
memset(mJoiners, 0, sizeof(mJoiners));
aThreadNetif.GetCoapServer().AddResource(mRelayReceive);
}
ThreadError Commissioner::Start(const char *aPSKd, const char *aProvisioningUrl)
ThreadError Commissioner::Start(void)
{
ThreadError error = kThreadError_None;
VerifyOrExit(mState == kStateDisabled, error = kThreadError_InvalidState);
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();
@@ -91,6 +90,75 @@ ThreadError Commissioner::Stop(void)
return kThreadError_None;
}
ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd)
{
ThreadError error = kThreadError_NoBufs;
VerifyOrExit(strlen(aPSKd) <= Dtls::kPskMaxLength, error = kThreadError_InvalidArgs);
RemoveJoiner(aExtAddress);
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
{
if (mJoiners[i].mValid)
{
continue;
}
if (aExtAddress != NULL)
{
mJoiners[i].mExtAddress = *aExtAddress;
mJoiners[i].mAny = false;
}
else
{
mJoiners[i].mAny = true;
}
strncpy(mJoiners[i].mPsk, aPSKd, sizeof(mJoiners[i].mPsk));
mJoiners[i].mValid = true;
ExitNow(error = kThreadError_None);
}
exit:
return error;
}
ThreadError Commissioner::RemoveJoiner(const Mac::ExtAddress *aExtAddress)
{
ThreadError error = kThreadError_NotFound;
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
{
if (!mJoiners[i].mValid)
{
continue;
}
if (aExtAddress != NULL)
{
if (memcmp(&mJoiners[i].mExtAddress, &aExtAddress, sizeof(mJoiners[i].mExtAddress)))
{
continue;
}
}
else if (!mJoiners[i].mAny)
{
continue;
}
mJoiners[i].mValid = false;
ExitNow(error = kThreadError_None);
}
exit:
return error;
}
ThreadError Commissioner::SetProvisioningUrl(const char *aProvisioningUrl)
{
return mNetif.GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl);
}
uint16_t Commissioner::GetSessionId(void) const
{
return mSessionId;
@@ -383,10 +451,36 @@ void Commissioner::HandleRelayReceive(Coap::Header &aHeader, Message &aMessage,
SuccessOrExit(error = Tlv::GetValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
memcpy(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid));
mNetif.GetDtls().SetClientId(mJoinerIid, sizeof(mJoinerIid));
mJoinerPort = joinerPort.GetUdpPort();
mJoinerRloc = joinerRloc.GetJoinerRouterLocator();
if (!mNetif.GetDtls().IsStarted())
{
mJoinerIid[0] ^= 0x2;
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
{
if (!mJoiners[i].mValid)
{
continue;
}
if (mJoiners[i].mAny || !memcmp(&mJoiners[i].mExtAddress, mJoinerIid, sizeof(mJoiners[i].mExtAddress)))
{
SuccessOrExit(error = mNetif.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(mJoiners[i].mPsk),
static_cast<uint8_t>(strlen(mJoiners[i].mPsk))));
SuccessOrExit(error = mNetif.GetDtls().Start(false, HandleDtlsReceive, HandleDtlsSend, this));
otLogInfoMeshCoP("found joiner, starting new session\r\n");
break;
}
}
mJoinerIid[0] ^= 0x2;
}
VerifyOrExit(mNetif.GetDtls().IsStarted() && memcmp(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid)) == 0,);
SuccessOrExit(error = mNetif.GetDtls().SetClientId(mJoinerIid, sizeof(mJoinerIid)));
mNetif.GetDtls().Receive(aMessage, offset, length);
exit:
@@ -441,8 +535,6 @@ void Commissioner::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
mState = kStateActive;
mTimer.Start(5000);
mNetif.GetDtls().Start(false, HandleDtlsReceive, HandleDtlsSend, this);
otLogInfoMeshCoP("received petition response\r\n");
break;
+48 -6
View File
@@ -34,8 +34,12 @@
#ifndef COMMISSIONER_HPP_
#define COMMISSIONER_HPP_
#include <openthread-core-config.h>
#include <coap/coap_server.hpp>
#include <common/timer.hpp>
#include <mac/mac_frame.hpp>
#include <meshcop/dtls.hpp>
#include <meshcop/energy_scan_client.hpp>
#include <meshcop/panid_query_client.hpp>
#include <net/udp6.hpp>
@@ -61,13 +65,10 @@ public:
/**
* This method starts the Commissioner service.
*
* @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, const char *aProvisioningUrl);
ThreadError Start(void);
/**
* This method stops the Commissioner service.
@@ -77,6 +78,40 @@ public:
*/
ThreadError Stop(void);
/**
* This method adds a Joiner entry.
*
* @param[in] aExtAddress A pointer to the Joiner's extended address or NULL for any Joiner.
* @param[in] aPSKd A pointer to the PSKd
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_NoBufs No buffers available to add the Joiner.
*
*/
ThreadError AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd);
/**
* This method removes a Joiner entry.
*
* @param[in] aExtAddress A pointer to the Joiner's extended address or NULL for any Joiner.
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_NotFound The Joiner specified by @p aExtAddress was not found.
*
*/
ThreadError RemoveJoiner(const Mac::ExtAddress *aExtAddress);
/**
* This function sets the Provisioning URL.
*
* @param[in] aProvisioningUrl A pointer to the Provisioning URL (may be NULL).
*
* @retval kThreadError_None Successfully added the Joiner.
* @retval kThreadError_InvalidArgs @p aProvisioningUrl is invalid.
*
*/
ThreadError SetProvisioningUrl(const char *aProvisioningUrl);
/**
* This method returns the Commissioner Session ID.
*
@@ -88,7 +123,6 @@ public:
EnergyScanClient mEnergyScan;
PanIdQueryClient mPanIdQuery;
/**
* This method sends MGMT_COMMISSIONER_GET.
*
@@ -147,9 +181,17 @@ private:
kStatePetition = 1,
kStateActive = 2,
};
uint8_t mState;
struct Joiner
{
Mac::ExtAddress mExtAddress;
char mPsk[Dtls::kPskMaxLength + 1];
bool mValid : 1;
bool mAny : 1;
};
Joiner mJoiners[OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES];
uint8_t mJoinerIid[8];
uint16_t mJoinerPort;
uint16_t mJoinerRloc;
+26 -2
View File
@@ -121,14 +121,24 @@ exit:
ThreadError Dtls::Stop(void)
{
mStarted = false;
mbedtls_ssl_close_notify(&mSsl);
Close();
return kThreadError_None;
}
void Dtls::Close(void)
{
mStarted = false;
mbedtls_ssl_free(&mSsl);
mbedtls_ssl_config_free(&mConf);
mbedtls_ctr_drbg_free(&mCtrDrbg);
mbedtls_entropy_free(&mEntropy);
mbedtls_ssl_cookie_free(&mCookieCtx);
return kThreadError_None;
}
bool Dtls::IsStarted(void)
{
return mStarted;
}
ThreadError Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
@@ -321,6 +331,7 @@ void Dtls::HandleTimer(void)
void Dtls::Process(void)
{
uint8_t buf[MBEDTLS_SSL_MAX_CONTENT_LEN];
bool shouldClose = false;
int rval;
while (mStarted)
@@ -348,10 +359,14 @@ void Dtls::Process(void)
{
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
mbedtls_ssl_close_notify(&mSsl);
ExitNow(shouldClose = true);
break;
case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
break;
case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
ExitNow(shouldClose = true);
break;
case MBEDTLS_ERR_SSL_INVALID_MAC:
@@ -359,6 +374,7 @@ void Dtls::Process(void)
{
mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC);
ExitNow(shouldClose = true);
}
break;
@@ -368,6 +384,7 @@ void Dtls::Process(void)
{
mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
ExitNow(shouldClose = true);
}
break;
@@ -378,6 +395,13 @@ void Dtls::Process(void)
break;
}
}
exit:
if (shouldClose)
{
Close();
}
}
ThreadError Dtls::MapError(int rval)
+14 -5
View File
@@ -56,6 +56,11 @@ namespace MeshCoP {
class Dtls
{
public:
enum
{
kPskMaxLength = 32,
};
/**
* This constructor initializes the DTLS object.
*
@@ -105,6 +110,14 @@ public:
*/
ThreadError Stop(void);
/**
* This method indicates whether or not the DTLS service is active.
*
* @returns TRUE if the DTLS service is active, FALSE otherwise.
*
*/
bool IsStarted(void);
/**
* This method sets the PSK.
*
@@ -166,11 +179,6 @@ public:
ProvisioningUrlTlv mProvisioningUrl;
private:
enum
{
kPskMaxLength = 32,
};
static ThreadError MapError(int rval);
static void HandleMbedtlsDebug(void *ctx, int level, const char *file, int line, const char *str);
@@ -196,6 +204,7 @@ private:
static void HandleTimer(void *aContext);
void HandleTimer(void);
void Close(void);
void Process(void);
uint8_t mPsk[kPskMaxLength];
+10
View File
@@ -175,6 +175,16 @@
#define OPENTHREAD_CONFIG_MAX_ENERGY_RESULTS 64
#endif // OPENTHREAD_CONFIG_MAX_ENERGY_RESULTS
/**
* @def OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES
*
* The maximum number of Joiner entries maintained by the Commissioner.
*
*/
#ifndef OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES
#define OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES 2
#endif // OPENTHREAD_CONFIG_MAX_JOINER_ENTRIES
/**
* @def OPENTHREAD_CONFIG_LOG_LEVEL
*
+17 -2
View File
@@ -1418,9 +1418,9 @@ ThreadError otSendPendingSet(otInstance *, const otOperationalDataset *aDataset,
#if OPENTHREAD_ENABLE_COMMISSIONER
#include <commissioning/commissioner.h>
ThreadError otCommissionerStart(otInstance *, const char *aPSKd, const char *aProvisioningUrl)
ThreadError otCommissionerStart(otInstance *)
{
return sThreadNetif->GetCommissioner().Start(aPSKd, aProvisioningUrl);
return sThreadNetif->GetCommissioner().Start();
}
ThreadError otCommissionerStop(otInstance *)
@@ -1428,6 +1428,21 @@ ThreadError otCommissionerStop(otInstance *)
return sThreadNetif->GetCommissioner().Stop();
}
ThreadError otCommissionerAddJoiner(otInstance *, const otExtAddress *aExtAddress, const char *aPSKd)
{
return sThreadNetif->GetCommissioner().AddJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress), aPSKd);
}
ThreadError otCommissionerRemoveJoiner(otInstance *, const otExtAddress *aExtAddress)
{
return sThreadNetif->GetCommissioner().RemoveJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress));
}
ThreadError otCommissionerSetProvisioningUrl(otInstance *, const char *aProvisioningUrl)
{
return sThreadNetif->GetCommissioner().SetProvisioningUrl(aProvisioningUrl);
}
ThreadError otCommissionerEnergyScan(otInstance *, uint32_t aChannelMask, uint8_t aCount, uint16_t aPeriod,
uint16_t aScanDuration, const otIp6Address *aAddress,
otCommissionerEnergyReportCallback aCallback, void *aContext)
@@ -59,7 +59,8 @@ class Cert_8_1_01_Commissioning(unittest.TestCase):
self.nodes[COMMISSIONER].thread_start()
time.sleep(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
self.nodes[COMMISSIONER].commissioner_start('openthread')
self.nodes[COMMISSIONER].commissioner_start()
self.nodes[COMMISSIONER].commissioner_add_joiner('*', 'openthread')
self.nodes[JOINER].interface_up()
self.nodes[JOINER].joiner_start('openthread')
@@ -59,7 +59,8 @@ class Cert_8_1_02_Commissioning(unittest.TestCase):
self.nodes[COMMISSIONER].thread_start()
time.sleep(5)
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'leader')
self.nodes[COMMISSIONER].commissioner_start('openthread')
self.nodes[COMMISSIONER].commissioner_start()
self.nodes[COMMISSIONER].commissioner_add_joiner(self.nodes[JOINER].get_hashmacaddr(), 'openthread')
self.nodes[JOINER].interface_up()
self.nodes[JOINER].joiner_start('daerhtnepo')
+15 -2
View File
@@ -144,8 +144,13 @@ class Node:
self.send_command('thread stop')
self.pexpect.expect('Done')
def commissioner_start(self, pskd='', provisioning_url=''):
cmd = 'commissioner start ' + pskd + ' ' + provisioning_url
def commissioner_start(self):
cmd = 'commissioner start'
self.send_command(cmd)
self.pexpect.expect('Done')
def commissioner_add_joiner(self, addr, psk):
cmd = 'commissioner joiner add ' + addr + ' ' + psk
self.send_command(cmd)
self.pexpect.expect('Done')
@@ -202,6 +207,14 @@ class Node:
self.pexpect.expect('Done')
return addr64
def get_hashmacaddr(self):
self.send_command('hashmacaddr')
i = self.pexpect.expect('([0-9a-fA-F]{16})')
if i == 0:
addr = self.pexpect.match.groups()[0].decode("utf-8")
self.pexpect.expect('Done')
return addr
def set_channel(self, channel):
cmd = 'channel %d' % channel
self.send_command(cmd)