diff --git a/etc/visual-studio/libopenthread.vcxproj b/etc/visual-studio/libopenthread.vcxproj index eb0f75ee2..725d0d277 100644 --- a/etc/visual-studio/libopenthread.vcxproj +++ b/etc/visual-studio/libopenthread.vcxproj @@ -81,6 +81,7 @@ + @@ -160,6 +161,7 @@ + diff --git a/etc/visual-studio/libopenthread.vcxproj.filters b/etc/visual-studio/libopenthread.vcxproj.filters index 1b6526cd5..0d2db8dbd 100644 --- a/etc/visual-studio/libopenthread.vcxproj.filters +++ b/etc/visual-studio/libopenthread.vcxproj.filters @@ -141,6 +141,9 @@ Source Files\common + + Source Files\common + Source Files\common @@ -368,6 +371,9 @@ Header Files\common + + Header Files\common + Header Files\common diff --git a/etc/visual-studio/libopenthread_k.vcxproj b/etc/visual-studio/libopenthread_k.vcxproj index f687a92cf..d8cb5e0cd 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj +++ b/etc/visual-studio/libopenthread_k.vcxproj @@ -90,6 +90,7 @@ + @@ -192,6 +193,7 @@ + diff --git a/etc/visual-studio/libopenthread_k.vcxproj.filters b/etc/visual-studio/libopenthread_k.vcxproj.filters index 816a4bfbe..fa03ea8d8 100644 --- a/etc/visual-studio/libopenthread_k.vcxproj.filters +++ b/etc/visual-studio/libopenthread_k.vcxproj.filters @@ -141,6 +141,9 @@ Source Files\common + + Source Files\common + Source Files\common @@ -368,6 +371,9 @@ Header Files\common + + Header Files\common + Header Files\common diff --git a/include/openthread/instance.h b/include/openthread/instance.h index ac9de8feb..c93a9463b 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -234,22 +234,21 @@ typedef void (OTCALL *otStateChangedCallback)(uint32_t aFlags, void *aContext); * @param[in] aContext A pointer to application-specific context. * * @retval OT_ERROR_NONE Added the callback to the list of callbacks. + * @retval OT_ERROR_ALREADY The callback was already registered. * @retval OT_ERROR_NO_BUFS Could not add the callback due to resource constraints. * */ -OTAPI otError OTCALL otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, - void *aContext); +OTAPI otError OTCALL otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aContext); /** * This function removes a callback to indicate when certain configuration or state changes within OpenThread. * - * @param[in] aInstance A pointer to an OpenThread instance. - * @param[in] aCallback A pointer to a function that is called with certain configuration or state changes. - * @param[in] aCallbackContext A pointer to application-specific context. + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aCallback A pointer to a function that is called with certain configuration or state changes. + * @param[in] aContext A pointer to application-specific context. * */ -OTAPI void OTCALL otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, - void *aCallbackContext); +OTAPI void OTCALL otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aContext); /** * This method triggers a platform reset. diff --git a/include/openthread/types.h b/include/openthread/types.h index 4878c2b9c..1551e7611 100644 --- a/include/openthread/types.h +++ b/include/openthread/types.h @@ -696,6 +696,13 @@ enum OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED = 1 << 13, ///< Unsubscribed from a IPv6 multicast address OT_CHANGED_COMMISSIONER_STATE = 1 << 14, ///< Commissioner state changed OT_CHANGED_JOINER_STATE = 1 << 15, ///< Joiner state changed + OT_CHANGED_THREAD_CHANNEL = 1 << 16, ///< Thread network channel changed + OT_CHANGED_THREAD_PANID = 1 << 17, ///< Thread network PAN Id changed + OT_CHANGED_THREAD_NETWORK_NAME = 1 << 18, ///< Thread network name changed + OT_CHANGED_THREAD_EXT_PANID = 1 << 19, ///< Thread network extended PAN ID changed + OT_CHANGED_MASTER_KEY = 1 << 20, ///< Master key changed + OT_CHANGED_PSKC = 1 << 21, ///< PSKc changed + OT_CHANGED_SECURITY_POLICY = 1 << 22, ///< Security Policy changed }; /** diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 2c35149c3..0d71dbd58 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -119,6 +119,7 @@ SOURCES_COMMON = \ common/instance.cpp \ common/logging.cpp \ common/locator.cpp \ + common/notifier.cpp \ common/message.cpp \ common/tasklet.cpp \ common/timer.cpp \ @@ -213,6 +214,7 @@ HEADERS_COMMON = \ common/locator.hpp \ common/logging.hpp \ common/message.hpp \ + common/notifier.hpp \ common/owner-locator.hpp \ common/settings.hpp \ common/new.hpp \ diff --git a/src/core/api/instance_api.cpp b/src/core/api/instance_api.cpp index b2f3bf31b..ac4b3ed6a 100644 --- a/src/core/api/instance_api.cpp +++ b/src/core/api/instance_api.cpp @@ -81,18 +81,18 @@ void otInstanceFinalize(otInstance *aInstance) otLogFuncExit(); } -otError otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aCallbackContext) +otError otSetStateChangedCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aContext) { Instance &instance = *static_cast(aInstance); - return instance.RegisterStateChangedCallback(aCallback, aCallbackContext); + return instance.GetNotifier().RegisterCallback(aCallback, aContext); } -void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aCallbackContext) +void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback aCallback, void *aContext) { Instance &instance = *static_cast(aInstance); - instance.RemoveStateChangedCallback(aCallback, aCallbackContext); + instance.GetNotifier().RemoveCallback(aCallback, aContext); } void otInstanceReset(otInstance *aInstance) diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index edf9c1004..a8685d37d 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -55,6 +55,7 @@ Instance::Instance(void) : mActiveScanCallbackContext(NULL), mEnergyScanCallback(NULL), mEnergyScanCallbackContext(NULL), + mNotifier(*this), mTimerMilliScheduler(*this), #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER mTimerMicroScheduler(*this), @@ -161,36 +162,6 @@ exit: return; } -otError Instance::RegisterStateChangedCallback(otStateChangedCallback aCallback, void *aContext) -{ - otError error = OT_ERROR_NO_BUFS; - - for (size_t i = 0; i < kMaxNetifCallbacks; i++) - { - if (mNetifCallback[i].IsFree()) - { - mNetifCallback[i].Set(aCallback, aContext); - error = mThreadNetif.RegisterCallback(mNetifCallback[i]); - break; - } - } - - return error; -} - -void Instance::RemoveStateChangedCallback(otStateChangedCallback aCallback, void *aContext) -{ - for (size_t i = 0; i < kMaxNetifCallbacks; i++) - { - if (mNetifCallback[i].IsServing(aCallback, aContext)) - { - mThreadNetif.RemoveCallback(mNetifCallback[i]); - mNetifCallback[i].Free(); - break; - } - } -} - void Instance::Reset(void) { otPlatReset(this); @@ -243,6 +214,11 @@ void Instance::InvokeEnergyScanCallback(otEnergyScanResult *aResult) const // Specializations of the `Get()` method. +template<> Notifier &Instance::Get(void) +{ + return GetNotifier(); +} + template<> TaskletScheduler &Instance::Get(void) { return GetTaskletScheduler(); diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index 6b18fd7d9..fd2e8c301 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -51,10 +51,10 @@ #include "crypto/heap.hpp" #include "crypto/mbedtls.hpp" #endif +#include "common/notifier.hpp" #include "net/ip6.hpp" #include "thread/thread_netif.hpp" - /** * @addtogroup core-instance * @@ -138,27 +138,6 @@ public: */ void Finalize(void); - /** - * This method registers a callback to indicate when certain configuration or state changes within OpenThread. - * - * @param[in] aCallback A pointer to a function that is called with certain configuration or state changes. - * @param[in] aContext A pointer to application-specific context. - * - * @retval OT_ERROR_NONE Added the callback to the list of callbacks and registered it with OpenThread. - * @retval OT_ERROR_NO_BUFS Could not add the callback due to resource constraints. - * - */ - otError RegisterStateChangedCallback(otStateChangedCallback aCallback, void *aContext); - - /** - * This method removes/unregisters a previously registered "state changed" callback. - * - * @param[in] aCallback A pointer to the callback function pointer. - * @param[in] aCallbackContext A pointer to application-specific context. - * - */ - void RemoveStateChangedCallback(otStateChangedCallback aCallback, void *aCallbackContext); - /** * This method triggers a platform reset. * @@ -241,6 +220,14 @@ public: */ void InvokeEnergyScanCallback(otEnergyScanResult *aResult) const; + /** + * This method returns a reference to the `Notifier` object. + * + * @returns A reference to the `Notifier` object. + * + */ + Notifier &GetNotifier(void) { return mNotifier; } + /** * This method returns a reference to the tasklet scheduler object. * @@ -343,17 +330,13 @@ private: Instance(void); void AfterInit(void); - enum - { - kMaxNetifCallbacks = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS, - }; - - Ip6::NetifCallback mNetifCallback[kMaxNetifCallbacks]; otHandleActiveScanResult mActiveScanCallback; void *mActiveScanCallbackContext; otHandleEnergyScanResult mEnergyScanCallback; void *mEnergyScanCallbackContext; + Notifier mNotifier; + TaskletScheduler mTaskletScheduler; TimerMilliScheduler mTimerMilliScheduler; diff --git a/src/core/common/locator.cpp b/src/core/common/locator.cpp index 27cb19796..0748c3dcd 100644 --- a/src/core/common/locator.cpp +++ b/src/core/common/locator.cpp @@ -57,4 +57,9 @@ ThreadNetif &InstanceLocator::GetNetif(void) const return GetInstance().GetThreadNetif(); } +Notifier &InstanceLocator::GetNotifier(void) const +{ + return GetInstance().GetNotifier(); +} + } // namespace ot diff --git a/src/core/common/locator.hpp b/src/core/common/locator.hpp index c60892951..32a626520 100644 --- a/src/core/common/locator.hpp +++ b/src/core/common/locator.hpp @@ -42,6 +42,7 @@ namespace ot { class Instance; class ThreadNetif; +class Notifier; namespace Ip6 { class Ip6; } @@ -97,6 +98,14 @@ public: */ ThreadNetif &GetNetif(void) const; + /** + * This method returns a reference to the Notifier. + * + * @returns A reference to the Notifier. + * + */ + Notifier &GetNotifier(void) const; + protected: /** * This constructor initializes the object. diff --git a/src/core/common/notifier.cpp b/src/core/common/notifier.cpp new file mode 100644 index 000000000..31f709d0d --- /dev/null +++ b/src/core/common/notifier.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2016-2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the Notifier class. + */ + +#define WPP_NAME "notifier.tmh" + +#include "notifier.hpp" + +#include "common/code_utils.hpp" +#include "common/logging.hpp" +#include "common/owner-locator.hpp" + +namespace ot { + +Notifier::Callback::Callback(Handler aHandler, void *aOwner): + OwnerLocator(aOwner), + mHandler(aHandler), + mNext(this) +{ +} + +Notifier::Notifier(Instance &aInstance): + InstanceLocator(aInstance), + mFlags(0), + mTask(aInstance, &Notifier::HandleStateChanged, this), + mCallbacks(NULL) +{ + for (unsigned int i = 0; i < kMaxExternalHandlers; i++) + { + mExternalCallbacks[i].mHandler = NULL; + mExternalCallbacks[i].mContext = NULL; + } +} + +otError Notifier::RegisterCallback(Callback &aCallback) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(aCallback.mNext == &aCallback, error = OT_ERROR_ALREADY); + + aCallback.mNext = mCallbacks; + mCallbacks = &aCallback; + +exit: + return error; +} + +void Notifier::RemoveCallback(Callback &aCallback) +{ + VerifyOrExit(mCallbacks != NULL); + + if (mCallbacks == &aCallback) + { + mCallbacks = mCallbacks->mNext; + ExitNow(); + } + + for (Callback *callback = mCallbacks; callback->mNext != NULL; callback = callback->mNext) + { + if (callback->mNext == &aCallback) + { + callback->mNext = aCallback.mNext; + ExitNow(); + } + } + +exit: + aCallback.mNext = &aCallback; +} + +otError Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext) +{ + otError error = OT_ERROR_NONE; + ExternalCallback *unusedCallback = NULL; + + VerifyOrExit(aCallback != NULL); + + for (unsigned int i = 0; i < kMaxExternalHandlers; i++) + { + ExternalCallback &callback = mExternalCallbacks[i]; + + if (callback.mHandler == NULL) + { + if (unusedCallback == NULL) + { + unusedCallback = &callback; + } + + continue; + } + + VerifyOrExit((callback.mHandler != aCallback) || (callback.mContext != aContext), error = OT_ERROR_ALREADY); + } + + VerifyOrExit(unusedCallback != NULL, error = OT_ERROR_NO_BUFS); + + unusedCallback->mHandler = aCallback; + unusedCallback->mContext = aContext; + +exit: + return error; +} + +void Notifier::RemoveCallback(otStateChangedCallback aCallback, void *aContext) +{ + VerifyOrExit(aCallback != NULL); + + for (unsigned int i = 0; i < kMaxExternalHandlers; i++) + { + ExternalCallback &callback = mExternalCallbacks[i]; + + if ((callback.mHandler == aCallback) && (callback.mContext == aContext)) + { + callback.mHandler = NULL; + callback.mContext = NULL; + } + } + +exit: + return; +} + +void Notifier::SetFlags(uint32_t aFlags) +{ + mFlags |= aFlags; + mTask.Post(); +} + +void Notifier::HandleStateChanged(Tasklet &aTasklet) +{ + aTasklet.GetOwner().HandleStateChanged(); +} + +void Notifier::HandleStateChanged(void) +{ + uint32_t flags = mFlags; + + VerifyOrExit(flags != 0); + + mFlags = 0; + + LogChangedFlags(flags); + + for (Callback *callback = mCallbacks; callback != NULL; callback = callback->mNext) + { + if (callback->mHandler != NULL) + { + callback->mHandler(*callback, flags); + } + } + + for (unsigned int i = 0; i < kMaxExternalHandlers; i++) + { + ExternalCallback &callback = mExternalCallbacks[i]; + + if (callback.mHandler != NULL) + { + callback.mHandler(flags, callback.mContext); + } + } + +exit: + return; +} + +#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1) + +void Notifier::LogChangedFlags(uint32_t aFlags) const +{ + uint32_t flags = aFlags; + char stringBuffer[kFlagsStringBufferSize]; + char *buf = stringBuffer; + int len = sizeof(stringBuffer) - 1; + int charsWritten; + + for (uint8_t bit = 0; bit < 32; bit++) + { + VerifyOrExit(flags != 0); + + if (flags & (1 << bit)) + { + charsWritten = snprintf(buf, static_cast(len), "%s ", FlagToString(1 << bit)); + VerifyOrExit(charsWritten >= 0 && charsWritten < len); + buf += charsWritten; + len -= charsWritten; + + flags ^= (1 << bit); + } + } + +exit: + stringBuffer[sizeof(stringBuffer) - 1] = 0; + otLogInfoMle(GetInstance(), "Notifier: StateChanged (0x%04x) [ %s] ", aFlags, stringBuffer); +} + +const char *Notifier::FlagToString(uint32_t aFlag) const +{ + const char *retval = "(unknown)"; + + switch (aFlag) + { + case OT_CHANGED_IP6_ADDRESS_ADDED: + retval = "Ip6+"; + break; + + case OT_CHANGED_IP6_ADDRESS_REMOVED: + retval = "Ip6-"; + break; + + case OT_CHANGED_THREAD_ROLE: + retval = "Role"; + break; + + case OT_CHANGED_THREAD_LL_ADDR: + retval = "LLAddr"; + break; + + case OT_CHANGED_THREAD_ML_ADDR: + retval = "MLAddr"; + break; + + case OT_CHANGED_THREAD_RLOC_ADDED: + retval = "Rloc+"; + break; + + case OT_CHANGED_THREAD_RLOC_REMOVED: + retval = "Rloc-"; + break; + + case OT_CHANGED_THREAD_PARTITION_ID: + retval = "PartitionId"; + break; + + case OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER: + retval = "KeySeqCntr"; + break; + + case OT_CHANGED_THREAD_NETDATA: + retval = "NetData"; + break; + + case OT_CHANGED_THREAD_CHILD_ADDED: + retval = "Child+"; + break; + + case OT_CHANGED_THREAD_CHILD_REMOVED: + retval = "Child-"; + break; + + case OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED: + retval = "Ip6Mult+"; + break; + + case OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED: + retval = "Ip6Mult-"; + break; + + case OT_CHANGED_COMMISSIONER_STATE: + retval = "CommissionerState"; + break; + + case OT_CHANGED_JOINER_STATE: + retval = "JoinerState"; + break; + + case OT_CHANGED_THREAD_CHANNEL: + retval = "Channel"; + break; + + case OT_CHANGED_THREAD_PANID: + retval = "PanId"; + break; + + case OT_CHANGED_THREAD_NETWORK_NAME: + retval = "NetName"; + break; + + case OT_CHANGED_THREAD_EXT_PANID: + retval = "ExtPanId"; + break; + + case OT_CHANGED_MASTER_KEY: + retval = "MstrKey"; + break; + + case OT_CHANGED_PSKC: + retval = "PSKc"; + break; + + case OT_CHANGED_SECURITY_POLICY: + retval = "SecPolicy"; + break; + + default: + break; + } + + return retval; +} + +#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1) + +void Notifier::LogChangedFlags(uint32_t aFlags) const +{ + OT_UNUSED_VARIABLE(aFlags); +} + +const char *Notifier::FlagToString(uint32_t aFlag) const +{ + OT_UNUSED_VARIABLE(aFlag); + return NULL; +} + +#endif // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1) + +} // namespace ot diff --git a/src/core/common/notifier.hpp b/src/core/common/notifier.hpp new file mode 100644 index 000000000..7c2869b61 --- /dev/null +++ b/src/core/common/notifier.hpp @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016-2017, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file defines OpenThread Notifier class. + */ + +#ifndef NOTIFIER_HPP_ +#define NOTIFIER_HPP_ + +#include "openthread-core-config.h" + +#include "utils/wrap_stdint.h" +#include "utils/wrap_stdbool.h" + +#include +#include + +#include "common/locator.hpp" +#include "common/tasklet.hpp" + +namespace ot { + +/** + * @addtogroup core-notifier + * + * @brief + * This module includes definitions for OpenThread Notifier class. + * + * @{ + * + */ + +/** + * This class implements the OpenThread Notifier. + * + * It can be used to register callbacks to be notified of state or configuration changes within OpenThread. + * + */ +class Notifier: public InstanceLocator +{ +public: + + /** + * This class defines a callback instance that can be registered with the `Notifier`. + * + */ + class Callback: public OwnerLocator + { + friend class Notifier; + + public: + /** + * This type defines the function pointer which is called to notify of state or configuration changes. + * + * @param[in] aCallback A reference to callback instance. + * @param[in] aFlags A bit-field indicating specific state that has changed. See `OT_CHANGED_` + * definitions in `types.h`. + * + */ + typedef void (*Handler)(Callback &aCallback, uint32_t aFlags); + + /** + * This constructor initializes a `Callback` instance + * + * @param[in] aHandler A function pointer to the callback handler. + * @param[in] aOwner A pointer to the owner of the `Callback` instance. + * + */ + Callback(Handler aHandler, void *aOwner); + + private: + Handler mHandler; + Callback *mNext; + }; + + /** + * This constructor initializes a `Notifier` instance. + * + * @param[in] aInstance A reference to OpenThread instance. + * + */ + Notifier(Instance &aInstance); + + /** + * This method registers a callback. + * + * @param[in] aCallback A reference to the callback instance. + * + * @retval OT_ERROR_NONE Successfully registered the callback. + * @retval OT_ERROR_ALREADY The callback was already registered. + * + */ + otError RegisterCallback(Callback &aCallback); + + /** + * This method removes a previously registered callback. + * + * @param[in] aCallback A reference to the callback instance. + * + */ + void RemoveCallback(Callback &aCallback); + + /** + * This method registers an `otStateChangedCallback` handler. + * + * @param[in] aCallback A pointer to the handler function that is called to notify of the changes. + * @param[in] aContext A pointer to arbitrary context information. + * + * @retval OT_ERROR_NONE Successfully registered the callback. + * @retval OT_ERROR_ALREADY The callback was already registered. + * @retval OT_ERROR_NO_BUFS Could not add the callback due to resource constraints. + * + */ + otError RegisterCallback(otStateChangedCallback aCallback, void *aContext); + + /** + * This method removes/unregisters a previously registered `otStateChangedCallback` handler. + * + * @param[in] aCallback A pointer to the callback function pointer. + * @param[in] aContex A pointer to arbitrary context information. + * + */ + void RemoveCallback(otStateChangedCallback aCallback, void *aContext); + + /** + * This method schedules notification of changed flags. + * + * The @p aFlags are combined (bitwise-or) with other flags that have not been provided in a callback yet. + * + * @param[in] aFlags A bit-field indicating what configuration or state has changed. + * + */ + void SetFlags(uint32_t aFlags); + + /** + * This method indicates whether or not a state changed callback is pending. + * + * @retval TRUE if a state changed callback is pending, FALSE otherwise. + * + */ + bool IsPending(void) const { return (mFlags != 0); } + +private: + enum + { + kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS, + kFlagsStringBufferSize = 128, + }; + + struct ExternalCallback + { + otStateChangedCallback mHandler; + void *mContext; + }; + + static void HandleStateChanged(Tasklet &aTasklet); + void HandleStateChanged(void); + + void LogChangedFlags(uint32_t aFlags) const; + const char *FlagToString(uint32_t aFlag) const; + + uint32_t mFlags; + Tasklet mTask; + Callback *mCallbacks; + ExternalCallback mExternalCallbacks[kMaxExternalHandlers]; +}; + +/** + * @} + * + */ + +} // namespace ot + +#endif // NOTIFIER_HPP_ diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 25b59590c..8e8e97b4d 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -127,7 +127,7 @@ otError Commissioner::Stop(void) GetNetif().GetCoapSecure().Stop(); mState = OT_COMMISSIONER_STATE_DISABLED; - GetNetif().SetStateChangedFlags(OT_CHANGED_COMMISSIONER_STATE); + GetNotifier().SetFlags(OT_CHANGED_COMMISSIONER_STATE); RemoveCoapResources(); mTransmitAttempts = 0; @@ -677,7 +677,7 @@ exit: } } - GetNetif().SetStateChangedFlags(OT_CHANGED_COMMISSIONER_STATE); + GetNotifier().SetFlags(OT_CHANGED_COMMISSIONER_STATE); otLogFuncExit(); } diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index d444a19b4..12bffe348 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -103,6 +103,7 @@ const Tlv *DatasetManager::GetTlv(Tlv::Type aType) const otError DatasetManager::ApplyConfiguration(void) { ThreadNetif &netif = GetNetif(); + Mac::Mac &mac = netif.GetMac(); otError error = OT_ERROR_NONE; Dataset datasetLocal(mLocal.GetType()); Dataset *dataset; @@ -128,22 +129,49 @@ otError DatasetManager::ApplyConfiguration(void) { case Tlv::kChannel: { - const ChannelTlv *channel = static_cast(cur); - netif.GetMac().SetChannel(static_cast(channel->GetChannel())); + uint8_t channel = static_cast(static_cast(cur)->GetChannel()); + + if (mac.GetChannel() != channel) + { + error = mac.SetChannel(channel); + + if (error != OT_ERROR_NONE) + { + otLogWarnMeshCoP(GetInstance(), + "DatasetManager::ApplyConfiguration() Failed to set channel to %d (%s)", + channel, otThreadErrorToString(error)); + ExitNow(); + } + + GetNotifier().SetFlags(OT_CHANGED_THREAD_CHANNEL); + } + break; } case Tlv::kPanId: { - const PanIdTlv *panid = static_cast(cur); - netif.GetMac().SetPanId(panid->GetPanId()); + uint16_t panid = static_cast(cur)->GetPanId(); + + if (mac.GetPanId() != panid) + { + mac.SetPanId(panid); + GetNotifier().SetFlags(OT_CHANGED_THREAD_PANID); + } + break; } case Tlv::kExtendedPanId: { const ExtendedPanIdTlv *extpanid = static_cast(cur); - netif.GetMac().SetExtendedPanId(extpanid->GetExtendedPanId()); + + if (memcmp(mac.GetExtendedPanId(), extpanid->GetExtendedPanId(), OT_EXT_PAN_ID_SIZE) != 0) + { + mac.SetExtendedPanId(extpanid->GetExtendedPanId()); + GetNotifier().SetFlags(OT_CHANGED_THREAD_EXT_PANID); + } + break; } @@ -153,7 +181,13 @@ otError DatasetManager::ApplyConfiguration(void) otNetworkName networkName; memcpy(networkName.m8, name->GetNetworkName(), name->GetLength()); networkName.m8[name->GetLength()] = '\0'; - netif.GetMac().SetNetworkName(networkName.m8); + + if (strcmp(networkName.m8, mac.GetNetworkName()) != 0) + { + mac.SetNetworkName(networkName.m8); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETWORK_NAME); + } + break; } @@ -199,6 +233,7 @@ otError DatasetManager::ApplyConfiguration(void) cur = cur->GetNext(); } +exit: return error; } diff --git a/src/core/meshcop/joiner.cpp b/src/core/meshcop/joiner.cpp index e3bbf2b7a..baec25cec 100644 --- a/src/core/meshcop/joiner.cpp +++ b/src/core/meshcop/joiner.cpp @@ -98,7 +98,7 @@ otError Joiner::Start(const char *aPSKd, const char *aProvisioningUrl, VerifyOrExit(mState == OT_JOINER_STATE_IDLE, error = OT_ERROR_BUSY); - GetNetif().SetStateChangedFlags(OT_CHANGED_JOINER_STATE); + GetNotifier().SetFlags(OT_CHANGED_JOINER_STATE); // use extended address based on factory-assigned IEEE EUI-64 GetJoinerId(joinerId); @@ -173,7 +173,7 @@ void Joiner::Complete(otError aError) ThreadNetif &netif = GetNetif(); mState = OT_JOINER_STATE_IDLE; otError error = OT_ERROR_NOT_FOUND; - GetNetif().SetStateChangedFlags(OT_CHANGED_JOINER_STATE); + GetNotifier().SetFlags(OT_CHANGED_JOINER_STATE); netif.GetCoapSecure().Disconnect(); diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 45dbbe290..8cf8a7c27 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -61,22 +61,22 @@ JoinerRouter::JoinerRouter(Instance &aInstance): mSocket(aInstance.GetThreadNetif().GetIp6().GetUdp()), mRelayTransmit(OT_URI_PATH_RELAY_TX, &JoinerRouter::HandleRelayTransmit, this), mTimer(aInstance, &JoinerRouter::HandleTimer, this), + mNotifierCallback(&JoinerRouter::HandleStateChanged, this), mJoinerUdpPort(0), mIsJoinerPortConfigured(false), mExpectJoinEntRsp(false) { mSocket.GetSockName().mPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT; GetNetif().GetCoap().AddResource(mRelayTransmit); - mNetifCallback.Set(HandleNetifStateChanged, this); - GetNetif().RegisterCallback(mNetifCallback); + aInstance.GetNotifier().RegisterCallback(mNotifierCallback); } -void JoinerRouter::HandleNetifStateChanged(uint32_t aFlags, void *aContext) +void JoinerRouter::HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags) { - static_cast(aContext)->HandleNetifStateChanged(aFlags); + aCallback.GetOwner().HandleStateChanged(aFlags); } -void JoinerRouter::HandleNetifStateChanged(uint32_t aFlags) +void JoinerRouter::HandleStateChanged(uint32_t aFlags) { ThreadNetif &netif = GetNetif(); @@ -142,7 +142,7 @@ otError JoinerRouter::SetJoinerUdpPort(uint16_t aJoinerUdpPort) otLogFuncEntry(); mJoinerUdpPort = aJoinerUdpPort; mIsJoinerPortConfigured = true; - HandleNetifStateChanged(OT_CHANGED_THREAD_NETDATA); + HandleStateChanged(OT_CHANGED_THREAD_NETDATA); otLogFuncExit(); return OT_ERROR_NONE; } diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp index fcbc5c196..a301d4af8 100644 --- a/src/core/meshcop/joiner_router.hpp +++ b/src/core/meshcop/joiner_router.hpp @@ -42,6 +42,7 @@ #include "coap/coap_header.hpp" #include "common/locator.hpp" #include "common/message.hpp" +#include "common/notifier.hpp" #include "common/timer.hpp" #include "mac/mac_frame.hpp" #include "meshcop/meshcop_tlvs.hpp" @@ -89,8 +90,8 @@ private: kDelayJoinEnt = 50, ///< milliseconds }; - static void HandleNetifStateChanged(uint32_t aFlags, void *aContext); - void HandleNetifStateChanged(uint32_t aFlags); + static void HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags); + void HandleStateChanged(uint32_t aFlags); static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); @@ -113,14 +114,14 @@ private: otError GetBorderAgentRloc(uint16_t &aRloc); - Ip6::NetifCallback mNetifCallback; - Ip6::UdpSocket mSocket; Coap::Resource mRelayTransmit; TimerMilli mTimer; MessageQueue mDelayedJoinEnts; + Notifier::Callback mNotifierCallback; + uint16_t mJoinerUdpPort; bool mIsJoinerPortConfigured : 1; diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index 70ec9173f..a51706248 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -93,14 +93,11 @@ const otNetifMulticastAddress Netif::kLinkLocalAllRoutersMulticastAddress = Netif::Netif(Instance &aInstance, int8_t aInterfaceId): InstanceLocator(aInstance), - mCallbacks(NULL), mUnicastAddresses(NULL), mMulticastAddresses(NULL), mInterfaceId(aInterfaceId), mMulticastPromiscuous(false), - mStateChangedTask(aInstance, &Netif::HandleStateChangedTask, this), - mNext(NULL), - mStateChangedFlags(0) + mNext(NULL) { for (size_t i = 0; i < sizeof(mExtUnicastAddresses) / sizeof(mExtUnicastAddresses[0]); i++) { @@ -118,54 +115,6 @@ Netif::Netif(Instance &aInstance, int8_t aInterfaceId): const_cast(&kLinkLocalAllNodesMulticastAddress)); } -otError Netif::RegisterCallback(NetifCallback &aCallback) -{ - otError error = OT_ERROR_NONE; - - for (NetifCallback *cur = mCallbacks; cur; cur = cur->mNext) - { - if (cur == &aCallback) - { - ExitNow(error = OT_ERROR_ALREADY); - } - } - - aCallback.mNext = mCallbacks; - mCallbacks = &aCallback; - -exit: - return error; -} - -otError Netif::RemoveCallback(NetifCallback &aCallback) -{ - otError error = OT_ERROR_ALREADY; - NetifCallback *prev = NULL; - - for (NetifCallback *cur = mCallbacks; cur; cur = cur->mNext) - { - if (cur == &aCallback) - { - if (prev) - { - prev->mNext = cur->mNext; - } - else - { - mCallbacks = mCallbacks->mNext; - } - - cur->mNext = NULL; - error = OT_ERROR_NONE; - break; - } - - prev = cur; - } - - return error; -} - bool Netif::IsMulticastSubscribed(const Address &aAddress) const { bool rval = false; @@ -208,7 +157,7 @@ otError Netif::SubscribeAllRoutersMulticast(void) } } - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; @@ -240,7 +189,7 @@ exit: if (error != OT_ERROR_NOT_FOUND) { - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } return error; @@ -261,7 +210,7 @@ otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress) aAddress.mNext = mMulticastAddresses; mMulticastAddresses = &aAddress; - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; @@ -294,7 +243,7 @@ exit: if (error != OT_ERROR_NOT_FOUND) { - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } return error; @@ -327,7 +276,7 @@ otError Netif::SubscribeExternalMulticast(const Address &aAddress) entry->mAddress = aAddress; entry->mNext = mMulticastAddresses; mMulticastAddresses = entry; - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: return error; @@ -367,7 +316,7 @@ otError Netif::UnsubscribeExternalMulticast(const Address &aAddress) // To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself. entry->mNext = entry; - SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); + GetNotifier().SetFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); exit: return error; @@ -402,7 +351,7 @@ otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress) aAddress.mNext = mUnicastAddresses; mUnicastAddresses = &aAddress; - SetStateChangedFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_ADDED : OT_CHANGED_IP6_ADDRESS_ADDED); + GetNotifier().SetFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_ADDED : OT_CHANGED_IP6_ADDRESS_ADDED); exit: return error; @@ -435,7 +384,8 @@ exit: if (error != OT_ERROR_NOT_FOUND) { - SetStateChangedFlags(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED); + GetNotifier().SetFlags(aAddress.mRloc ? + OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED); } return error; @@ -478,7 +428,7 @@ otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress) entry->mNext = mUnicastAddresses; mUnicastAddresses = entry; - SetStateChangedFlags(OT_CHANGED_IP6_ADDRESS_ADDED); + GetNotifier().SetFlags(OT_CHANGED_IP6_ADDRESS_ADDED); exit: return error; @@ -518,7 +468,7 @@ otError Netif::RemoveExternalUnicastAddress(const Address &aAddress) // To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself. entry->mNext = entry; - SetStateChangedFlags(OT_CHANGED_IP6_ADDRESS_REMOVED); + GetNotifier().SetFlags(OT_CHANGED_IP6_ADDRESS_REMOVED); exit: return error; @@ -554,28 +504,5 @@ exit: return rval; } -void Netif::SetStateChangedFlags(uint32_t aFlags) -{ - mStateChangedFlags |= aFlags; - mStateChangedTask.Post(); -} - -void Netif::HandleStateChangedTask(Tasklet &aTasklet) -{ - aTasklet.GetOwner().HandleStateChangedTask(); -} - -void Netif::HandleStateChangedTask(void) -{ - uint32_t flags = mStateChangedFlags; - - mStateChangedFlags = 0; - - for (NetifCallback *callback = mCallbacks; callback; callback = callback->mNext) - { - callback->Callback(flags); - } -} - } // namespace Ip6 } // namespace ot diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index 6cfd326d2..b350dc51a 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -174,80 +174,6 @@ public: } }; -/** - * This class implements network interface handlers. - * - */ -class NetifCallback -{ - friend class Netif; - -public: - /** - * This constructor initializes the object. - * - */ - NetifCallback(void): - mCallback(NULL), - mContext(NULL), - mNext(NULL) { - } - - /** - * This method sets the callback information. - * - * @param[in] aCallback A pointer to a function that is called when configuration or state changes. - * @param[in] aContext A pointer to arbitrary context information. - * - */ - void Set(otStateChangedCallback aCallback, void *aContext) { - mCallback = aCallback; - mContext = aContext; - } - - /** - * This method tests whether the object is free or in use. - * - * @returns True if the object is free, false otherwise. - * - */ - bool IsFree(void) { return (mCallback == NULL); } - - /** - * This method frees the object. - * - */ - void Free(void) { - mCallback = NULL; - mContext = NULL; - mNext = NULL; - } - - /** - * This method tests whether the object is set to the provided elements. - * - * @param[in] aCallback A pointer to a function that is called when configuration or state changes. - * @param[in] aContext A pointer to arbitrary context information. - * - * @returns True if the object elements equal the input params, false otherwise. - * - */ - bool IsServing(otStateChangedCallback aCallback, void *aContext) { - return (aCallback == mCallback && aContext == mContext); - } - -private: - void Callback(uint32_t aFlags) { - if (mCallback != NULL) { - mCallback(aFlags, mContext); - } - } - - otStateChangedCallback mCallback; - void *mContext; - NetifCallback *mNext; -}; - /** * This class implements an IPv6 network interface. * @@ -458,44 +384,6 @@ public: */ void SetMulticastPromiscuous(bool aEnabled) { mMulticastPromiscuous = aEnabled; } - /** - * This method registers a network interface callback. - * - * @param[in] aCallback A reference to the callback. - * - * @retval OT_ERROR_NONE Successfully registered the callback. - * @retval OT_ERROR_ALREADY The callback was already registered. - */ - otError RegisterCallback(NetifCallback &aCallback); - - /** - * This method removes a network interface callback. - * - * @param[in] aCallback A reference to the callback. - * - * @retval OT_ERROR_NONE Successfully removed the callback. - * @retval OT_ERROR_ALREADY The callback was not in the list. - */ - otError RemoveCallback(NetifCallback &aCallback); - - /** - * This method indicates whether or not a state changed callback is pending. - * - * @retval TRUE if a state changed callback is pending, FALSE otherwise. - * - */ - bool IsStateChangedCallbackPending(void) { return mStateChangedFlags != 0; } - - /** - * This method schedules notification of @p aFlags. - * - * The @p aFlags are combined (bitwise-or) with other flags that have not been provided in a callback yet. - * - * @param[in] aFlags A bit-field indicating what configuration or state has changed. - * - */ - void SetStateChangedFlags(uint32_t aFlags); - /** * This virtual method enqueues an IPv6 messages on this network interface. * @@ -531,19 +419,12 @@ public: uint8_t *aPrefixMatch) = 0; private: - static void HandleStateChangedTask(Tasklet &aTasklet); - void HandleStateChangedTask(void); - - NetifCallback *mCallbacks; NetifUnicastAddress *mUnicastAddresses; NetifMulticastAddress *mMulticastAddresses; int8_t mInterfaceId; bool mMulticastPromiscuous; - Tasklet mStateChangedTask; Netif *mNext; - uint32_t mStateChangedFlags; - NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS]; NetifMulticastAddress mExtMulticastAddresses[OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS]; diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp index 7088f62a9..0f5c0e71c 100644 --- a/src/core/thread/energy_scan_server.cpp +++ b/src/core/thread/energy_scan_server.cpp @@ -60,11 +60,10 @@ EnergyScanServer::EnergyScanServer(Instance &aInstance) : mActive(false), mScanResultsLength(0), mTimer(aInstance, &EnergyScanServer::HandleTimer, this), + mNotifierCallback(&EnergyScanServer::HandleStateChanged, this), mEnergyScan(OT_URI_PATH_ENERGY_SCAN, &EnergyScanServer::HandleRequest, this) { - mNetifCallback.Set(&EnergyScanServer::HandleNetifStateChanged, this); - GetNetif().RegisterCallback(mNetifCallback); - + aInstance.GetNotifier().RegisterCallback(mNotifierCallback); GetNetif().GetCoap().AddResource(mEnergyScan); } @@ -226,12 +225,12 @@ exit: return error; } -void EnergyScanServer::HandleNetifStateChanged(uint32_t aFlags, void *aContext) +void EnergyScanServer::HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags) { - static_cast(aContext)->HandleNetifStateChanged(aFlags); + aCallback.GetOwner().HandleStateChanged(aFlags); } -void EnergyScanServer::HandleNetifStateChanged(uint32_t aFlags) +void EnergyScanServer::HandleStateChanged(uint32_t aFlags) { if ((aFlags & OT_CHANGED_THREAD_NETDATA) != 0 && !mActive && diff --git a/src/core/thread/energy_scan_server.hpp b/src/core/thread/energy_scan_server.hpp index a87ed5dd1..71e67dc94 100644 --- a/src/core/thread/energy_scan_server.hpp +++ b/src/core/thread/energy_scan_server.hpp @@ -40,6 +40,7 @@ #include "coap/coap.hpp" #include "common/locator.hpp" +#include "common/notifier.hpp" #include "common/timer.hpp" #include "net/ip6_address.hpp" #include "net/udp6.hpp" @@ -82,8 +83,8 @@ private: static void HandleTimer(Timer &aTimer); void HandleTimer(void); - static void HandleNetifStateChanged(uint32_t aFlags, void *aContext); - void HandleNetifStateChanged(uint32_t aFlags); + static void HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags); + void HandleStateChanged(uint32_t aFlags); otError SendReport(void); @@ -100,7 +101,7 @@ private: TimerMilli mTimer; - Ip6::NetifCallback mNetifCallback; + Notifier::Callback mNotifierCallback; Coap::Resource mEnergyScan; }; diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index e923b033b..3233e8ea1 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -84,7 +84,11 @@ const uint8_t *KeyManager::GetPSKc(void) const void KeyManager::SetPSKc(const uint8_t *aPSKc) { - memcpy(mPSKc, aPSKc, sizeof(mPSKc)); + if (memcmp(mPSKc, aPSKc, sizeof(mPSKc)) != 0) + { + memcpy(mPSKc, aPSKc, sizeof(mPSKc)); + GetNotifier().SetFlags(OT_CHANGED_PSKC); + } } #endif @@ -132,7 +136,7 @@ otError KeyManager::SetMasterKey(const otMasterKey &aKey) children[i].SetMleFrameCounter(0); } - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER); + GetNotifier().SetFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER | OT_CHANGED_MASTER_KEY); exit: return error; @@ -185,7 +189,7 @@ void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence) StartKeyRotationTimer(); } - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER); + GetNotifier().SetFlags(OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER); exit: return; @@ -241,6 +245,15 @@ exit: return result; } +void KeyManager::SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags) +{ + if (mSecurityPolicyFlags != aSecurityPolicyFlags) + { + mSecurityPolicyFlags = aSecurityPolicyFlags; + GetNotifier().SetFlags(OT_CHANGED_SECURITY_POLICY); + } +} + void KeyManager::StartKeyRotationTimer(void) { mHoursSinceKeyRotation = 0; diff --git a/src/core/thread/key_manager.hpp b/src/core/thread/key_manager.hpp index f3e592789..66cd2209c 100644 --- a/src/core/thread/key_manager.hpp +++ b/src/core/thread/key_manager.hpp @@ -323,7 +323,7 @@ public: * @param[in] aSecurityPolicyFlags The Security Policy Flags. * */ - void SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags) { mSecurityPolicyFlags = aSecurityPolicyFlags; } + void SetSecurityPolicyFlags(uint8_t aSecurityPolicyFlags); private: enum diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index df4448365..bcf517b20 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -103,7 +103,8 @@ Mle::Mle(Instance &aInstance) : #endif mAnnounceChannel(OT_RADIO_CHANNEL_MIN), mPreviousChannel(0), - mPreviousPanId(Mac::kPanIdBroadcast) + mPreviousPanId(Mac::kPanIdBroadcast), + mNotifierCallback(&Mle::HandleStateChanged, this) { uint8_t meshLocalPrefix[8]; size_t i = 0; @@ -199,8 +200,7 @@ Mle::Mle(Instance &aInstance) : // `SetMeshLocalPrefix()` also adds the Mesh-Local EID and subscribes // to the Link- and Realm-Local All Thread Nodes multicast addresses. - mNetifCallback.Set(&Mle::HandleNetifStateChanged, this); - GetNetif().RegisterCallback(mNetifCallback); + aInstance.GetNotifier().RegisterCallback(mNotifierCallback); #if OPENTHREAD_CONFIG_ENABLE_PERIODIC_PARENT_SEARCH StartParentSearchTimer(); @@ -244,7 +244,7 @@ otError Mle::Start(bool aEnableReattach, bool aAnnounceAttach) VerifyOrExit(netif.IsUp(), error = OT_ERROR_INVALID_STATE); mRole = OT_DEVICE_ROLE_DETACHED; - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ROLE); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ROLE); SetStateDetached(); netif.GetKeyManager().Start(); @@ -582,7 +582,7 @@ otError Mle::SetStateDetached(void) if (mRole != OT_DEVICE_ROLE_DETACHED) { - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ROLE); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ROLE); } if (mRole == OT_DEVICE_ROLE_LEADER) @@ -610,7 +610,7 @@ otError Mle::SetStateChild(uint16_t aRloc16) if (mRole != OT_DEVICE_ROLE_CHILD) { - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ROLE); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ROLE); } if (mRole == OT_DEVICE_ROLE_LEADER) @@ -735,7 +735,7 @@ otError Mle::UpdateLinkLocalAddress(void) mLinkLocal64.GetAddress().SetIid(netif.GetMac().GetExtAddress()); netif.AddUnicastAddress(mLinkLocal64); - netif.SetStateChangedFlags(OT_CHANGED_THREAD_LL_ADDR); + GetNotifier().SetFlags(OT_CHANGED_THREAD_LL_ADDR); return OT_ERROR_NONE; } @@ -802,7 +802,7 @@ otError Mle::SetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix) } // Changing the prefix also causes the mesh local address to be different. - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ML_ADDR); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ML_ADDR); exit: return OT_ERROR_NONE; @@ -854,7 +854,7 @@ void Mle::SetLeaderData(uint32_t aPartitionId, uint8_t aWeighting, uint8_t aLead mLastPartitionId = mLeaderData.GetPartitionId(); mLastPartitionRouterIdSequence = GetNetif().GetMle().GetRouterIdSequence(); mLastPartitionIdTimeout = GetNetif().GetMle().GetNetworkIdTimeout(); - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_PARTITION_ID); + GetNotifier().SetFlags(OT_CHANGED_THREAD_PARTITION_ID); } mLeaderData.SetPartitionId(aPartitionId); @@ -1276,12 +1276,12 @@ exit: return error; } -void Mle::HandleNetifStateChanged(uint32_t aFlags, void *aContext) +void Mle::HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags) { - static_cast(aContext)->HandleNetifStateChanged(aFlags); + aCallback.GetOwner().HandleStateChanged(aFlags); } -void Mle::HandleNetifStateChanged(uint32_t aFlags) +void Mle::HandleStateChanged(uint32_t aFlags) { ThreadNetif &netif = GetNetif(); VerifyOrExit(mRole != OT_DEVICE_ROLE_DISABLED); @@ -1297,7 +1297,7 @@ void Mle::HandleNetifStateChanged(uint32_t aFlags) } netif.AddUnicastAddress(mMeshLocal64); - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ML_ADDR); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ML_ADDR); } if (mRole == OT_DEVICE_ROLE_CHILD && (mDeviceMode & ModeTlv::kModeFFD) == 0) @@ -1752,7 +1752,7 @@ void Mle::HandleSendChildUpdateRequest(void) { // a Network Data update can cause a change to the IPv6 address configuration // only send a Child Update Request after we know there are no more pending changes - if (GetNetif().IsStateChangedCallbackPending()) + if (GetNotifier().IsPending()) { mSendChildUpdateRequest.Post(); } diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 31e5af9ad..f4f384982 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1419,8 +1419,8 @@ private: void GenerateNonce(const Mac::ExtAddress &aMacAddr, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce); - static void HandleNetifStateChanged(uint32_t aFlags, void *aContext); - void HandleNetifStateChanged(uint32_t aFlags); + static void HandleStateChanged(Notifier::Callback &aCallback, uint32_t aFlags); + void HandleStateChanged(uint32_t aFlags); static void HandleParentRequestTimer(Timer &aTimer); void HandleParentRequestTimer(void); static void HandleDelayedResponseTimer(Timer &aTimer); @@ -1534,7 +1534,7 @@ private: Ip6::NetifMulticastAddress mLinkLocalAllThreadNodes; Ip6::NetifMulticastAddress mRealmLocalAllThreadNodes; - Ip6::NetifCallback mNetifCallback; + Notifier::Callback mNotifierCallback; }; } // namespace Mle diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 0e3681722..e0d9b4e13 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -427,7 +427,7 @@ otError MleRouter::SetStateRouter(uint16_t aRloc16) if (mRole != OT_DEVICE_ROLE_ROUTER) { - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ROLE); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ROLE); } SetRloc16(aRloc16); @@ -466,7 +466,7 @@ otError MleRouter::SetStateLeader(uint16_t aRloc16) if (mRole != OT_DEVICE_ROLE_LEADER) { - netif.SetStateChangedFlags(OT_CHANGED_THREAD_ROLE); + GetNotifier().SetFlags(OT_CHANGED_THREAD_ROLE); } SetRloc16(aRloc16); @@ -4939,11 +4939,11 @@ void MleRouter::SignalChildUpdated(otThreadChildTableEvent aEvent, Child &aChild switch (aEvent) { case OT_THREAD_CHILD_TABLE_EVENT_CHILD_ADDED: - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_CHILD_ADDED); + GetNotifier().SetFlags(OT_CHANGED_THREAD_CHILD_ADDED); break; case OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED: - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_CHILD_REMOVED); + GetNotifier().SetFlags(OT_CHANGED_THREAD_CHILD_REMOVED); break; } } diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index ed229f772..1954d2573 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -68,7 +68,7 @@ void LeaderBase::Reset(void) mVersion = static_cast(otPlatRandomGet()); mStableVersion = static_cast(otPlatRandomGet()); mLength = 0; - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); } otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext) @@ -423,7 +423,7 @@ void LeaderBase::SetNetworkData(uint8_t aVersion, uint8_t aStableVersion, bool a otDumpDebgNetData(GetInstance(), "set network data", mTlvs, mLength); - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); } otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength) @@ -446,7 +446,7 @@ otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLe } mVersion++; - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); exit: return error; diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index a220b7ae7..5ba4297e7 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -101,12 +101,10 @@ void Leader::Stop(void) void Leader::IncrementVersion(void) { - ThreadNetif &netif = GetNetif(); - - if (netif.GetMle().GetRole() == OT_DEVICE_ROLE_LEADER) + if (GetNetif().GetMle().GetRole() == OT_DEVICE_ROLE_LEADER) { mVersion++; - netif.SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); } } @@ -145,7 +143,7 @@ void Leader::RemoveBorderRouter(uint16_t aRloc16) mStableVersion++; } - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); exit: return; @@ -771,7 +769,7 @@ otError Leader::RegisterNetworkData(uint16_t aRloc16, uint8_t *aTlvs, uint8_t aT } } - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); exit: return error; @@ -1177,7 +1175,7 @@ otError Leader::FreeContext(uint8_t aContextId) mContextUsed &= ~(1 << aContextId); mVersion++; mStableVersion++; - GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA); + GetNotifier().SetFlags(OT_CHANGED_THREAD_NETDATA); return OT_ERROR_NONE; } diff --git a/src/ncp/changed_props_set.cpp b/src/ncp/changed_props_set.cpp index 41ad8013d..2b59c0d05 100644 --- a/src/ncp/changed_props_set.cpp +++ b/src/ncp/changed_props_set.cpp @@ -73,6 +73,12 @@ const ChangedPropsSet::Entry ChangedPropsSet::mSupportedProps[] = { SPINEL_PROP_LAST_STATUS, SPINEL_STATUS_JOIN_FAILURE, false }, // 19 { SPINEL_PROP_MAC_SCAN_STATE, SPINEL_STATUS_OK, false }, // 20 { SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE, SPINEL_STATUS_OK, true }, // 21 + { SPINEL_PROP_PHY_CHAN, SPINEL_STATUS_OK, true }, // 22 + { SPINEL_PROP_MAC_15_4_PANID, SPINEL_STATUS_OK, true }, // 23 + { SPINEL_PROP_NET_NETWORK_NAME, SPINEL_STATUS_OK, true }, // 24 + { SPINEL_PROP_NET_XPANID, SPINEL_STATUS_OK, true }, // 25 + { SPINEL_PROP_NET_MASTER_KEY, SPINEL_STATUS_OK, true }, // 26 + { SPINEL_PROP_NET_PSKC, SPINEL_STATUS_OK, true }, // 27 }; uint8_t ChangedPropsSet::GetNumEntries(void) const diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 8e566dcb9..83bb23532 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -577,7 +577,7 @@ NcpBase::NcpBase(Instance *aInstance): #if OPENTHREAD_MTD || OPENTHREAD_FTD otMessageQueueInit(&mMessageQueue); - otSetStateChangedCallback(mInstance, &NcpBase::HandleNetifStateChanged, this); + otSetStateChangedCallback(mInstance, &NcpBase::HandleStateChanged, this); otIp6SetReceiveCallback(mInstance, &NcpBase::HandleDatagramFromStack, this); otIp6SetReceiveFilterEnabled(mInstance, true); otLinkSetPcapCallback(mInstance, &NcpBase::HandleRawFrame, static_cast(this)); diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 92990ad13..cd1bf49c0 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -250,7 +250,7 @@ protected: #endif // OPENTHREAD_ENABLE_RAW_LINK_API #if OPENTHREAD_MTD || OPENTHREAD_FTD - static void HandleNetifStateChanged(uint32_t aFlags, void *aContext); + static void HandleStateChanged(uint32_t aFlags, void *aContext); void ProcessThreadChangedFlags(void); #if OPENTHREAD_FTD diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 265db998a..95a7862af 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2763,7 +2763,7 @@ exit: // MARK: Property/Status Changed // ---------------------------------------------------------------------------- -void NcpBase::HandleNetifStateChanged(uint32_t aFlags, void *aContext) +void NcpBase::HandleStateChanged(uint32_t aFlags, void *aContext) { NcpBase *ncp = static_cast(aContext); @@ -2791,6 +2791,12 @@ void NcpBase::ProcessThreadChangedFlags(void) { OT_CHANGED_THREAD_CHILD_REMOVED, SPINEL_PROP_THREAD_CHILD_TABLE }, { OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE }, { OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED, SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE }, + { OT_CHANGED_THREAD_CHANNEL, SPINEL_PROP_PHY_CHAN }, + { OT_CHANGED_THREAD_PANID, SPINEL_PROP_MAC_15_4_PANID }, + { OT_CHANGED_THREAD_NETWORK_NAME, SPINEL_PROP_NET_NETWORK_NAME }, + { OT_CHANGED_THREAD_EXT_PANID, SPINEL_PROP_NET_XPANID }, + { OT_CHANGED_MASTER_KEY, SPINEL_PROP_NET_MASTER_KEY }, + { OT_CHANGED_PSKC, SPINEL_PROP_NET_PSKC }, }; VerifyOrExit(mThreadChangedFlags != 0);