• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016-2017, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *  This file defines OpenThread Notifier class.
32  */
33 
34 #ifndef NOTIFIER_HPP_
35 #define NOTIFIER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdbool.h>
40 #include <stdint.h>
41 
42 #include <openthread/instance.h>
43 #include <openthread/platform/toolchain.h>
44 
45 #include "common/array.hpp"
46 #include "common/callback.hpp"
47 #include "common/error.hpp"
48 #include "common/locator.hpp"
49 #include "common/non_copyable.hpp"
50 #include "common/tasklet.hpp"
51 
52 namespace ot {
53 
54 /**
55  * @addtogroup core-notifier
56  *
57  * @brief
58  *   This module includes definitions for OpenThread Notifier class.
59  *
60  * @{
61  */
62 
63 /**
64  * Type represents events emitted from OpenThread Notifier.
65  */
66 enum Event : uint32_t
67 {
68     kEventIp6AddressAdded                  = OT_CHANGED_IP6_ADDRESS_ADDED,            ///< IPv6 address was added
69     kEventIp6AddressRemoved                = OT_CHANGED_IP6_ADDRESS_REMOVED,          ///< IPv6 address was removed
70     kEventThreadRoleChanged                = OT_CHANGED_THREAD_ROLE,                  ///< Role changed
71     kEventThreadLinkLocalAddrChanged       = OT_CHANGED_THREAD_LL_ADDR,               ///< Link-local address changed
72     kEventThreadMeshLocalAddrChanged       = OT_CHANGED_THREAD_ML_ADDR,               ///< Mesh-local address changed
73     kEventThreadRlocAdded                  = OT_CHANGED_THREAD_RLOC_ADDED,            ///< RLOC was added
74     kEventThreadRlocRemoved                = OT_CHANGED_THREAD_RLOC_REMOVED,          ///< RLOC was removed
75     kEventThreadPartitionIdChanged         = OT_CHANGED_THREAD_PARTITION_ID,          ///< Partition ID changed
76     kEventThreadKeySeqCounterChanged       = OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER,  ///< Key Sequence changed
77     kEventThreadNetdataChanged             = OT_CHANGED_THREAD_NETDATA,               ///< Network Data changed
78     kEventThreadChildAdded                 = OT_CHANGED_THREAD_CHILD_ADDED,           ///< Child was added
79     kEventThreadChildRemoved               = OT_CHANGED_THREAD_CHILD_REMOVED,         ///< Child was removed
80     kEventIp6MulticastSubscribed           = OT_CHANGED_IP6_MULTICAST_SUBSCRIBED,     ///< Multicast address added
81     kEventIp6MulticastUnsubscribed         = OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED,   ///< Multicast address removed
82     kEventThreadChannelChanged             = OT_CHANGED_THREAD_CHANNEL,               ///< Network channel changed
83     kEventThreadPanIdChanged               = OT_CHANGED_THREAD_PANID,                 ///< Network PAN ID changed
84     kEventThreadNetworkNameChanged         = OT_CHANGED_THREAD_NETWORK_NAME,          ///< Network name changed
85     kEventThreadExtPanIdChanged            = OT_CHANGED_THREAD_EXT_PANID,             ///< Extended PAN ID changed
86     kEventNetworkKeyChanged                = OT_CHANGED_NETWORK_KEY,                  ///< Network Key changed
87     kEventPskcChanged                      = OT_CHANGED_PSKC,                         ///< PSKc changed
88     kEventSecurityPolicyChanged            = OT_CHANGED_SECURITY_POLICY,              ///< Security Policy changed
89     kEventChannelManagerNewChannelChanged  = OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL,  ///< New Channel (channel-manager)
90     kEventSupportedChannelMaskChanged      = OT_CHANGED_SUPPORTED_CHANNEL_MASK,       ///< Channel mask changed
91     kEventCommissionerStateChanged         = OT_CHANGED_COMMISSIONER_STATE,           ///< Commissioner state changed
92     kEventThreadNetifStateChanged          = OT_CHANGED_THREAD_NETIF_STATE,           ///< Netif state changed
93     kEventThreadBackboneRouterStateChanged = OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE, ///< Backbone Router state changed
94     kEventThreadBackboneRouterLocalChanged = OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL, ///< Local Backbone Router changed
95     kEventJoinerStateChanged               = OT_CHANGED_JOINER_STATE,                 ///< Joiner state changed
96     kEventActiveDatasetChanged             = OT_CHANGED_ACTIVE_DATASET,               ///< Active Dataset changed
97     kEventPendingDatasetChanged            = OT_CHANGED_PENDING_DATASET,              ///< Pending Dataset changed
98     kEventNat64TranslatorStateChanged      = OT_CHANGED_NAT64_TRANSLATOR_STATE,       ///< Nat64Translator state changed
99     kEventParentLinkQualityChanged         = OT_CHANGED_PARENT_LINK_QUALITY,          ///< Parent link quality changed
100 };
101 
102 /**
103  * Represents a list of events.
104  */
105 class Events
106 {
107 public:
108     /**
109      * Represents a bit-field indicating a list of events (with values from `Event`)
110      */
111     typedef otChangedFlags Flags;
112 
113     /**
114      * Initializes the `Events` list (as empty).
115      */
Events(void)116     Events(void)
117         : mEventFlags(0)
118     {
119     }
120 
121     /**
122      * Clears the `Events` list.
123      */
Clear(void)124     void Clear(void) { mEventFlags = 0; }
125 
126     /**
127      * Indicates whether the `Events` list contains a given event.
128      *
129      * @param[in] aEvent  The event to check.
130      *
131      * @returns TRUE if the list contains the @p aEvent, FALSE otherwise.
132      */
Contains(Event aEvent) const133     bool Contains(Event aEvent) const { return (mEventFlags & aEvent) != 0; }
134 
135     /**
136      * Indicates whether the `Events` list contains any of a given set of events.
137      *
138      * @param[in] aEvents  The events set to check (must be a collection of `Event` constants combined using `|`).
139      *
140      * @returns TRUE if the list contains any of the @p aEvents set, FALSE otherwise.
141      */
ContainsAny(Flags aEvents) const142     bool ContainsAny(Flags aEvents) const { return (mEventFlags & aEvents) != 0; }
143 
144     /**
145      * Indicates whether the `Events` list contains all of a given set of events.
146      *
147      * @param[in] aEvents  The events set to check (must be collection of `Event` constants combined using `|`).
148      *
149      * @returns TRUE if the list contains all of the @p aEvents set, FALSE otherwise.
150      */
ContainsAll(Flags aEvents) const151     bool ContainsAll(Flags aEvents) const { return (mEventFlags & aEvents) == aEvents; }
152 
153     /**
154      * Adds a given event to the `Events` list.
155      *
156      * @param[in] aEvent  The event to add.
157      */
Add(Event aEvent)158     void Add(Event aEvent) { mEventFlags |= aEvent; }
159 
160     /**
161      * Indicates whether the `Events` list is empty.
162      *
163      * @returns TRUE if the list is empty, FALSE otherwise.
164      */
IsEmpty(void) const165     bool IsEmpty(void) const { return (mEventFlags == 0); }
166 
167     /**
168      * Gets the `Events` list as bit-field `Flags` value.
169      *
170      * @returns The list as bit-field `Flags` value.
171      */
GetAsFlags(void) const172     Flags GetAsFlags(void) const { return mEventFlags; }
173 
174 private:
175     Flags mEventFlags;
176 };
177 
178 /**
179  * Implements the OpenThread Notifier.
180  *
181  * For core internal modules, `Notifier` class emits events directly to them by invoking method `HandleNotifierEvents()`
182  * on the module instance.
183  */
184 class Notifier : public InstanceLocator, private NonCopyable
185 {
186 public:
187     /**
188      * Maximum number of external callback handlers that can be registered.
189      */
190     static constexpr uint16_t kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS;
191 
192     typedef otStateChangedCallback StateChangedCallback; ///< State changed callback
193 
194     /**
195      * Initializes a `Notifier` instance.
196      *
197      *  @param[in] aInstance     A reference to OpenThread instance.
198      */
199     explicit Notifier(Instance &aInstance);
200 
201     /**
202      * Registers an external `StateChangedCallback`.
203      *
204      * This is intended for use by external users (i.e., provided as an OpenThread public API). `kMaxExternalHandlers`
205      * specifies the maximum number of callbacks.
206      *
207      * @param[in]  aCallback     A pointer to the handler function that is called to notify of the changes.
208      * @param[in]  aContext      A pointer to arbitrary context information.
209      *
210      * @retval kErrorNone     Successfully registered the callback.
211      * @retval kErrorAlready  The callback was already registered.
212      * @retval kErrorNoBufs   Could not add the callback due to resource constraints.
213      */
214     Error RegisterCallback(StateChangedCallback aCallback, void *aContext);
215 
216     /**
217      * Removes/unregisters a previously registered `StateChangedCallback` handler.
218      *
219      * @param[in]  aCallback     A pointer to the callback function pointer.
220      * @param[in]  aContext      A pointer to arbitrary context information.
221      */
222     void RemoveCallback(StateChangedCallback aCallback, void *aContext);
223 
224     /**
225      * Schedules signaling of an event.
226      *
227      * @param[in]  aEvent     The event to signal.
228      */
229     void Signal(Event aEvent);
230 
231     /**
232      * Schedules signaling of am event only if the event has not been signaled before (first time signal).
233      *
234      * @param[in]  aEvent     The event to signal.
235      */
236     void SignalIfFirst(Event aEvent);
237 
238     /**
239      * Indicates whether or not an event signal callback is pending/scheduled.
240      *
241      * @returns TRUE if a callback is pending, FALSE otherwise.
242      */
IsPending(void) const243     bool IsPending(void) const { return !mEventsToSignal.IsEmpty(); }
244 
245     /**
246      * Indicates whether or not an event has been signaled before.
247      *
248      * @param[in]  aEvent    The event to check.
249      *
250      * @retval TRUE    The event @p aEvent have been signaled before.
251      * @retval FALSE   The event @p aEvent has not been signaled before.
252      */
HasSignaled(Event aEvent) const253     bool HasSignaled(Event aEvent) const { return mSignaledEvents.Contains(aEvent); }
254 
255     /**
256      * Updates a variable of a type `Type` with a new value and signals the given event.
257      *
258      * If the variable is already set to the same value, this method returns `kErrorAlready` and the event is
259      * signaled using `SignalIfFirst()` (i.e., signal is scheduled only if event has not been signaled before).
260      *
261      * The template `Type` should support comparison operator `==` and assignment operator `=`.
262      *
263      * @param[in,out] aVariable    A reference to the variable to update.
264      * @param[in]     aNewValue    The new value.
265      * @param[in]     aEvent       The event to signal.
266      *
267      * @retval kErrorNone      The variable was update successfully and @p aEvent was signaled.
268      * @retval kErrorAlready   The variable was already set to the same value.
269      */
Update(Type & aVariable,const Type & aNewValue,Event aEvent)270     template <typename Type> Error Update(Type &aVariable, const Type &aNewValue, Event aEvent)
271     {
272         Error error = kErrorNone;
273 
274         if (aVariable == aNewValue)
275         {
276             SignalIfFirst(aEvent);
277             error = kErrorAlready;
278         }
279         else
280         {
281             aVariable = aNewValue;
282             Signal(aEvent);
283         }
284 
285         return error;
286     }
287 
288 private:
289     // Character limit to divide the log into multiple lines in `LogChangedFlags()`.
290     static constexpr uint16_t kFlagsStringLineLimit = 70;
291 
292     // Max length for string representation of a flag by `FlagToString()`.
293     static constexpr uint8_t kMaxFlagNameLength = 25;
294 
295     static constexpr uint16_t kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength;
296 
297     typedef Callback<StateChangedCallback> ExternalCallback;
298 
299     void EmitEvents(void);
300 
301     void        LogEvents(Events aEvents) const;
302     const char *EventToString(Event aEvent) const;
303 
304     using EmitEventsTask        = TaskletIn<Notifier, &Notifier::EmitEvents>;
305     using ExternalCallbackArray = Array<ExternalCallback, kMaxExternalHandlers>;
306 
307     Events                mEventsToSignal;
308     Events                mSignaledEvents;
309     EmitEventsTask        mTask;
310     ExternalCallbackArray mExternalCallbacks;
311 };
312 
313 /**
314  * @}
315  */
316 
317 } // namespace ot
318 
319 #endif // NOTIFIER_HPP_
320