mirror of
https://github.com/espressif/openthread.git
synced 2026-08-07 03:07:47 +00:00
Automatic Joiners removal in Commissioner (#1421)
* Implement automatic Joiner removal feature. * Save some RAM in JoinerRouter class. * Specify timeout for each Joiner separately. * Update Windows API files.
This commit is contained in:
committed by
Jonathan Hui
parent
6eaacdd4a4
commit
746a40a340
@@ -602,6 +602,7 @@ typedef struct otCommissionConfig
|
||||
// uint8_t - aExtAddressValid
|
||||
// otExtAddress - aExtAddress (optional)
|
||||
// char[OPENTHREAD_PSK_MAX_LENGTH + 1] - aPSKd
|
||||
// uint32_t - aTimeout
|
||||
|
||||
#define IOCTL_OTLWF_OT_COMMISIONER_REMOVE_JOINER \
|
||||
OTLWF_CTL_CODE(181, METHOD_BUFFERED, FILE_WRITE_DATA)
|
||||
|
||||
@@ -3513,7 +3513,8 @@ OTCALL
|
||||
otCommissionerAddJoiner(
|
||||
_In_ otInstance *aInstance,
|
||||
const otExtAddress *aExtAddress,
|
||||
const char *aPSKd
|
||||
const char *aPSKd,
|
||||
uint32_t aTimeout
|
||||
)
|
||||
{
|
||||
if (aInstance == nullptr || aPSKd == nullptr) return kThreadError_InvalidArgs;
|
||||
@@ -3526,13 +3527,14 @@ otCommissionerAddJoiner(
|
||||
|
||||
uint8_t aExtAddressValid = aExtAddress ? 1 : 0;
|
||||
|
||||
const ULONG BufferLength = sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + (ULONG)aPSKdLength + 1;
|
||||
BYTE Buffer[sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + OPENTHREAD_PSK_MAX_LENGTH + 1] = {0};
|
||||
const ULONG BufferLength = sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + (ULONG)aPSKdLength + 1 + sizeof(aTimeout);
|
||||
BYTE Buffer[sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + OPENTHREAD_PSK_MAX_LENGTH + 1 + sizeof(aTimeout)] = {0};
|
||||
memcpy_s(Buffer, sizeof(Buffer), &aInstance->InterfaceGuid, sizeof(GUID));
|
||||
memcpy_s(Buffer + sizeof(GUID), sizeof(Buffer) - sizeof(GUID), &aExtAddressValid, sizeof(aExtAddressValid));
|
||||
if (aExtAddressValid)
|
||||
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t), sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t), aExtAddress, sizeof(otExtAddress));
|
||||
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress), sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t) - sizeof(otExtAddress), aPSKd, aPSKdLength);
|
||||
memcpy_s(Buffer + sizeof(GUID) + sizeof(uint8_t) + sizeof(otExtAddress) + aPSKdLength + 1, sizeof(Buffer) - sizeof(GUID) - sizeof(uint8_t) - sizeof(otExtAddress) - aPSKdLength - 1, &aTimeout, sizeof(aTimeout));
|
||||
|
||||
return DwordToThreadError(SendIOCTL(aInstance->ApiHandle, IOCTL_OTLWF_OT_COMMISIONER_ADD_JOINER, Buffer, BufferLength, nullptr, 0));
|
||||
}
|
||||
|
||||
@@ -5596,19 +5596,20 @@ otLwfIoCtl_otCommissionerAddJoiner(
|
||||
|
||||
if (InBufferLength >= sizeof(uint8_t) + sizeof(otExtAddress))
|
||||
{
|
||||
const ULONG aPSKdBufferLength = InBufferLength - sizeof(uint8_t) - sizeof(otExtAddress);
|
||||
const ULONG aPSKdBufferLength = InBufferLength - sizeof(uint8_t) - sizeof(otExtAddress) - sizeof(uint32_t);
|
||||
|
||||
if (aPSKdBufferLength <= OPENTHREAD_PSK_MAX_LENGTH + 1)
|
||||
{
|
||||
uint8_t aExtAddressValid = *(uint8_t*)InBuffer;
|
||||
const otExtAddress *aExtAddress = aExtAddressValid == 0 ? NULL : (otExtAddress*)(InBuffer + sizeof(uint8_t));
|
||||
char *aPSKd = (char*)(InBuffer + sizeof(uint8_t) + sizeof(otExtAddress));
|
||||
uint32_t aTimeout = *(uint32_t*)(InBuffer + sizeof(uint8_t) + sizeof(otExtAddress) + aPSKdBufferLength);
|
||||
|
||||
// Ensure aPSKd is NULL terminated in the buffer
|
||||
if (strnlen(aPSKd, aPSKdBufferLength) < aPSKdBufferLength)
|
||||
{
|
||||
status = ThreadErrorToNtstatus(otCommissionerAddJoiner(
|
||||
pFilter->otCtx, aExtAddress, aPSKd));
|
||||
pFilter->otCtx, aExtAddress, aPSKd, aTimeout));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1010,11 +1010,13 @@ OTNODEAPI int32_t OTCALL otNodeCommissionerJoinerAdd(otNode* aNode, const char *
|
||||
otLogFuncEntryMsg("[%d] %s %s", aNode->mId, aExtAddr, aPSKd);
|
||||
printf("%d: commissioner joiner add %s %s\r\n", aNode->mId, aExtAddr, aPSKd);
|
||||
|
||||
const uint32_t kDefaultJoinerTimeout = 120;
|
||||
|
||||
ThreadError error;
|
||||
|
||||
if (strcmp(aExtAddr, "*") == 0)
|
||||
{
|
||||
error = otCommissionerAddJoiner(aNode->mInstance, nullptr, aPSKd);
|
||||
error = otCommissionerAddJoiner(aNode->mInstance, nullptr, aPSKd, kDefaultJoinerTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1022,7 +1024,7 @@ OTNODEAPI int32_t OTCALL otNodeCommissionerJoinerAdd(otNode* aNode, const char *
|
||||
if (Hex2Bin(aExtAddr, extAddr.m8, sizeof(extAddr)) != sizeof(extAddr))
|
||||
return kThreadError_Parse;
|
||||
|
||||
error = otCommissionerAddJoiner(aNode->mInstance, &extAddr, aPSKd);
|
||||
error = otCommissionerAddJoiner(aNode->mInstance, &extAddr, aPSKd, kDefaultJoinerTimeout);
|
||||
}
|
||||
|
||||
otLogFuncExit();
|
||||
|
||||
@@ -75,6 +75,7 @@ OTAPI ThreadError OTCALL otCommissionerStop(otInstance *aInstance);
|
||||
* @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.
|
||||
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
|
||||
*
|
||||
* @retval kThreadError_None Successfully added the Joiner.
|
||||
* @retval kThreadError_NoBufs No buffers available to add the Joiner.
|
||||
@@ -82,7 +83,7 @@ OTAPI ThreadError OTCALL otCommissionerStop(otInstance *aInstance);
|
||||
*
|
||||
*/
|
||||
OTAPI ThreadError OTCALL otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress,
|
||||
const char *aPSKd);
|
||||
const char *aPSKd, uint32_t aTimeout);
|
||||
|
||||
/**
|
||||
* This function removes a Joiner entry.
|
||||
|
||||
+9
-1
@@ -2327,7 +2327,15 @@ void Interpreter::ProcessCommissioner(int argc, char *argv[])
|
||||
if (strcmp(argv[1], "add") == 0)
|
||||
{
|
||||
VerifyOrExit(argc > 3, error = kThreadError_Parse);
|
||||
SuccessOrExit(error = otCommissionerAddJoiner(mInstance, addrPtr, argv[3]));
|
||||
// Timeout parameter is optional - if not specified, use default value.
|
||||
unsigned long timeout = kDefaultJoinerTimeout;
|
||||
|
||||
if (argc > 4)
|
||||
{
|
||||
SuccessOrExit(error = ParseUnsignedLong(argv[4], timeout));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCommissionerAddJoiner(mInstance, addrPtr, argv[3], static_cast<uint32_t>(timeout)));
|
||||
}
|
||||
else if (strcmp(argv[1], "remove") == 0)
|
||||
{
|
||||
|
||||
@@ -147,6 +147,7 @@ private:
|
||||
{
|
||||
kMaxArgs = 32,
|
||||
kMaxAutoAddresses = 8,
|
||||
kDefaultJoinerTimeout = 120, ///< Default timeout for Joiners, in seconds.
|
||||
};
|
||||
|
||||
void AppendResult(ThreadError error);
|
||||
|
||||
@@ -53,9 +53,11 @@ ThreadError otCommissionerStop(otInstance *aInstance)
|
||||
return aInstance->mThreadNetif.GetCommissioner().Stop();
|
||||
}
|
||||
|
||||
ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress, const char *aPSKd)
|
||||
ThreadError otCommissionerAddJoiner(otInstance *aInstance, const otExtAddress *aExtAddress, const char *aPSKd,
|
||||
uint32_t aTimeout)
|
||||
{
|
||||
return aInstance->mThreadNetif.GetCommissioner().AddJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress), aPSKd);
|
||||
return aInstance->mThreadNetif.GetCommissioner().AddJoiner(static_cast<const Mac::ExtAddress *>(aExtAddress), aPSKd,
|
||||
aTimeout);
|
||||
}
|
||||
|
||||
ThreadError otCommissionerRemoveJoiner(otInstance *aInstance, const otExtAddress *aExtAddress)
|
||||
|
||||
@@ -68,6 +68,7 @@ Commissioner::Commissioner(ThreadNetif &aThreadNetif):
|
||||
mState(kStateDisabled),
|
||||
mJoinerPort(0),
|
||||
mJoinerRloc(0),
|
||||
mJoinerExpirationTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleJoinerExpirationTimer, this),
|
||||
mTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleTimer, this),
|
||||
mSessionId(0),
|
||||
mTransmitAttempts(0),
|
||||
@@ -199,7 +200,7 @@ void Commissioner::ClearJoiners(void)
|
||||
otLogFuncExit();
|
||||
}
|
||||
|
||||
ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd)
|
||||
ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd, uint32_t aTimeout)
|
||||
{
|
||||
ThreadError error = kThreadError_NoBufs;
|
||||
|
||||
@@ -226,6 +227,9 @@ ThreadError Commissioner::AddJoiner(const Mac::ExtAddress *aExtAddress, const ch
|
||||
|
||||
strncpy(mJoiners[i].mPsk, aPSKd, sizeof(mJoiners[i].mPsk) - 1);
|
||||
mJoiners[i].mValid = true;
|
||||
mJoiners[i].mExpirationTime = Timer::GetNow() + Timer::SecToMsec(aTimeout);
|
||||
|
||||
UpdateJoinerExpirationTimer();
|
||||
|
||||
SendCommissionerSet();
|
||||
|
||||
@@ -264,6 +268,8 @@ ThreadError Commissioner::RemoveJoiner(const Mac::ExtAddress *aExtAddress)
|
||||
|
||||
mJoiners[i].mValid = false;
|
||||
|
||||
UpdateJoinerExpirationTimer();
|
||||
|
||||
SendCommissionerSet();
|
||||
|
||||
ExitNow(error = kThreadError_None);
|
||||
@@ -311,6 +317,66 @@ void Commissioner::HandleTimer(void)
|
||||
}
|
||||
}
|
||||
|
||||
void Commissioner::HandleJoinerExpirationTimer(void *aContext)
|
||||
{
|
||||
static_cast<Commissioner *>(aContext)->HandleJoinerExpirationTimer();
|
||||
}
|
||||
|
||||
void Commissioner::HandleJoinerExpirationTimer(void)
|
||||
{
|
||||
uint32_t now = Timer::GetNow();
|
||||
|
||||
// Remove expired Joiners.
|
||||
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
|
||||
{
|
||||
if (!mJoiners[i].mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (static_cast<int32_t>(now - mJoiners[i].mExpirationTime) >= 0)
|
||||
{
|
||||
otLogDebgMeshCoP("removing joiner due to timeout");
|
||||
RemoveJoiner(&mJoiners[i].mExtAddress);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateJoinerExpirationTimer();
|
||||
}
|
||||
|
||||
void Commissioner::UpdateJoinerExpirationTimer(void)
|
||||
{
|
||||
uint32_t now = Timer::GetNow();
|
||||
uint32_t nextTimeout = 0xffffffff;
|
||||
|
||||
// Check if timer should be set for next Joiner.
|
||||
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
|
||||
{
|
||||
{
|
||||
if (!mJoiners[i].mValid)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mJoiners[i].mExpirationTime - now < nextTimeout)
|
||||
{
|
||||
nextTimeout = mJoiners[i].mExpirationTime - now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nextTimeout != 0xffffffff)
|
||||
{
|
||||
// Update the timer to the timeout of the next Joiner.
|
||||
mJoinerExpirationTimer.Start(nextTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No Joiners, stop the timer.
|
||||
mJoinerExpirationTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError Commissioner::SendMgmtCommissionerGetRequest(const uint8_t *aTlvs,
|
||||
uint8_t aLength)
|
||||
{
|
||||
@@ -822,6 +888,7 @@ void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader,
|
||||
Ip6::MessageInfo joinerMessageInfo;
|
||||
MeshCoP::StateTlv stateTlv;
|
||||
Message *message;
|
||||
Mac::ExtAddress extAddr;
|
||||
|
||||
otLogFuncEntry();
|
||||
|
||||
@@ -842,6 +909,10 @@ void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader,
|
||||
mSendKek = true;
|
||||
SuccessOrExit(error = mNetif.GetSecureCoapServer().SendMessage(*message, joinerMessageInfo));
|
||||
|
||||
memcpy(extAddr.m8, mJoinerIid, sizeof(extAddr.m8));
|
||||
extAddr.SetLocal(!extAddr.IsLocal());
|
||||
RemoveJoiner(&extAddr);
|
||||
|
||||
otLogInfoMeshCoP("sent joiner finalize response");
|
||||
otLogCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.rsp");
|
||||
exit:
|
||||
|
||||
@@ -92,13 +92,14 @@ public:
|
||||
* 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
|
||||
* @param[in] aPSKd A pointer to the PSKd.
|
||||
* @param[in] aTimeout A time after which a Joiner is automatically removed, in seconds.
|
||||
*
|
||||
* @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);
|
||||
ThreadError AddJoiner(const Mac::ExtAddress *aExtAddress, const char *aPSKd, uint32_t aTimeout);
|
||||
|
||||
/**
|
||||
* This method removes a Joiner entry.
|
||||
@@ -199,15 +200,20 @@ public:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kPetitionAttemptDelay = 5, ///< COMM_PET_ATTEMPT_DELAY (seconds)
|
||||
kPetitionRetryCount = 2, ///< COMM_PET_RETRY_COUNT
|
||||
kPetitionRetryDelay = 1, ///< COMM_PET_RETRY_DELAY (seconds)
|
||||
kKeepAliveTimeout = 50, ///< TIMEOUT_COMM_PET (seconds)
|
||||
kPetitionAttemptDelay = 5, ///< COMM_PET_ATTEMPT_DELAY (seconds)
|
||||
kPetitionRetryCount = 2, ///< COMM_PET_RETRY_COUNT
|
||||
kPetitionRetryDelay = 1, ///< COMM_PET_RETRY_DELAY (seconds)
|
||||
kKeepAliveTimeout = 50, ///< TIMEOUT_COMM_PET (seconds)
|
||||
};
|
||||
|
||||
static void HandleTimer(void *aContext);
|
||||
void HandleTimer(void);
|
||||
|
||||
static void HandleJoinerExpirationTimer(void *aContext);
|
||||
void HandleJoinerExpirationTimer(void);
|
||||
|
||||
void UpdateJoinerExpirationTimer(void);
|
||||
|
||||
static void HandleMgmtCommissionerSetResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
|
||||
const otMessageInfo *aMessageInfo, ThreadError aResult);
|
||||
void HandleMgmtCommissisonerSetResponse(Coap::Header *aHeader, Message *aMessage,
|
||||
@@ -251,6 +257,7 @@ private:
|
||||
struct Joiner
|
||||
{
|
||||
Mac::ExtAddress mExtAddress;
|
||||
uint32_t mExpirationTime;
|
||||
char mPsk[Dtls::kPskMaxLength + 1];
|
||||
bool mValid : 1;
|
||||
bool mAny : 1;
|
||||
@@ -264,6 +271,7 @@ private:
|
||||
};
|
||||
uint16_t mJoinerPort;
|
||||
uint16_t mJoinerRloc;
|
||||
Timer mJoinerExpirationTimer;
|
||||
|
||||
Timer mTimer;
|
||||
uint16_t mSessionId;
|
||||
|
||||
@@ -60,9 +60,9 @@ JoinerRouter::JoinerRouter(ThreadNetif &aNetif):
|
||||
mSocket(aNetif.GetIp6().mUdp),
|
||||
mRelayTransmit(OPENTHREAD_URI_RELAY_TX, &JoinerRouter::HandleRelayTransmit, this),
|
||||
mNetif(aNetif),
|
||||
mTimer(aNetif.GetIp6().mTimerScheduler, &JoinerRouter::HandleTimer, this),
|
||||
mJoinerUdpPort(0),
|
||||
mIsJoinerPortConfigured(false),
|
||||
mTimer(aNetif.GetIp6().mTimerScheduler, &JoinerRouter::HandleTimer, this),
|
||||
mExpectJoinEntRsp(false)
|
||||
{
|
||||
mSocket.GetSockName().mPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
|
||||
@@ -118,12 +118,13 @@ private:
|
||||
Coap::Resource mRelayTransmit;
|
||||
ThreadNetif &mNetif;
|
||||
|
||||
uint16_t mJoinerUdpPort;
|
||||
bool mIsJoinerPortConfigured;
|
||||
|
||||
Timer mTimer;
|
||||
MessageQueue mDelayedJoinEnts;
|
||||
bool mExpectJoinEntRsp;
|
||||
|
||||
uint16_t mJoinerUdpPort;
|
||||
|
||||
bool mIsJoinerPortConfigured : 1;
|
||||
bool mExpectJoinEntRsp : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user