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/error.hpp"
46 #include "common/locator.hpp"
47 #include "common/non_copyable.hpp"
48 #include "common/tasklet.hpp"
49 
50 namespace ot {
51 
52 /**
53  * @addtogroup core-notifier
54  *
55  * @brief
56  *   This module includes definitions for OpenThread Notifier class.
57  *
58  * @{
59  *
60  */
61 
62 /**
63  * This enumeration type represents events emitted from OpenThread Notifier.
64  *
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 };
99 
100 /**
101  * This type represents a list of events.
102  *
103  */
104 class Events
105 {
106 public:
107     /**
108      * This type represents a bit-field indicating a list of events (with values from `Event`)
109      *
110      */
111     typedef otChangedFlags Flags;
112 
113     /**
114      * This constructor initializes the `Events` list (as empty).
115      *
116      */
Events(void)117     Events(void)
118         : mEventFlags(0)
119     {
120     }
121 
122     /**
123      * This method clears the `Events` list.
124      *
125      */
Clear(void)126     void Clear(void) { mEventFlags = 0; }
127 
128     /**
129      * This method indicates whether the `Events` list contains a given event.
130      *
131      * @param[in] aEvent  The event to check.
132      *
133      * @returns TRUE if the list contains the @p aEvent, FALSE otherwise.
134      *
135      */
Contains(Event aEvent) const136     bool Contains(Event aEvent) const { return (mEventFlags & aEvent) != 0; }
137 
138     /**
139      * This method indicates whether the `Events` list contains any of a given set of events.
140      *
141      * @param[in] aEvents  The events set to check (must be a collection of `Event` constants combined using `|`).
142      *
143      * @returns TRUE if the list contains any of the @p aEvents set, FALSE otherwise.
144      *
145      */
ContainsAny(Flags aEvents) const146     bool ContainsAny(Flags aEvents) const { return (mEventFlags & aEvents) != 0; }
147 
148     /**
149      * This method indicates whether the `Events` list contains all of a given set of events.
150      *
151      * @param[in] aEvents  The events set to check (must be collection of `Event` constants combined using `|`).
152      *
153      * @returns TRUE if the list contains all of the @p aEvents set, FALSE otherwise.
154      *
155      */
ContainsAll(Flags aEvents) const156     bool ContainsAll(Flags aEvents) const { return (mEventFlags & aEvents) == aEvents; }
157 
158     /**
159      * This method adds a given event to the `Events` list.
160      *
161      * @param[in] aEvent  The event to add.
162      *
163      */
Add(Event aEvent)164     void Add(Event aEvent) { mEventFlags |= aEvent; }
165 
166     /**
167      * This method indicates whether the `Events` list is empty.
168      *
169      * @returns TRUE if the list is empty, FALSE otherwise.
170      *
171      */
IsEmpty(void) const172     bool IsEmpty(void) const { return (mEventFlags == 0); }
173 
174     /**
175      * This method gets the `Events` list as bit-field `Flags` value.
176      *
177      * @returns The list as bit-field `Flags` value.
178      *
179      */
GetAsFlags(void) const180     Flags GetAsFlags(void) const { return mEventFlags; }
181 
182 private:
183     Flags mEventFlags;
184 };
185 
186 /**
187  * This class implements the OpenThread Notifier.
188  *
189  * For core internal modules, `Notifier` class emits events directly to them by invoking method `HandleNotifierEvents()`
190  * on the module instance.
191  *
192  * A `otStateChangedCallback` callback can be explicitly registered with the `Notifier`. This is mainly intended for use
193  * by external users (i.e.provided as an OpenThread public API). Max number of such callbacks that can be registered at
194  * the same time is specified by `OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS` configuration parameter.
195  *
196  */
197 class Notifier : public InstanceLocator, private NonCopyable
198 {
199 public:
200     /**
201      * This constructor initializes a `Notifier` instance.
202      *
203      *  @param[in] aInstance     A reference to OpenThread instance.
204      *
205      */
206     explicit Notifier(Instance &aInstance);
207 
208     /**
209      * This method registers an `otStateChangedCallback` handler.
210      *
211      * @param[in]  aCallback     A pointer to the handler function that is called to notify of the changes.
212      * @param[in]  aContext      A pointer to arbitrary context information.
213      *
214      * @retval kErrorNone     Successfully registered the callback.
215      * @retval kErrorAlready  The callback was already registered.
216      * @retval kErrorNoBufs   Could not add the callback due to resource constraints.
217      *
218      */
219     Error RegisterCallback(otStateChangedCallback aCallback, void *aContext);
220 
221     /**
222      * This method removes/unregisters a previously registered `otStateChangedCallback` handler.
223      *
224      * @param[in]  aCallback     A pointer to the callback function pointer.
225      * @param[in]  aContex       A pointer to arbitrary context information.
226      *
227      */
228     void RemoveCallback(otStateChangedCallback aCallback, void *aContext);
229 
230     /**
231      * This method schedules signaling of an event.
232      *
233      * @param[in]  aEvent     The event to signal.
234      *
235      */
236     void Signal(Event aEvent);
237 
238     /**
239      * This method schedules signaling of am event only if the event has not been signaled before (first time signal).
240      *
241      * @param[in]  aEvent     The event to signal.
242      *
243      */
244     void SignalIfFirst(Event aEvent);
245 
246     /**
247      * This method indicates whether or not an event signal callback is pending/scheduled.
248      *
249      * @returns TRUE if a callback is pending, FALSE otherwise.
250      *
251      */
IsPending(void) const252     bool IsPending(void) const { return !mEventsToSignal.IsEmpty(); }
253 
254     /**
255      * This method indicates whether or not an event has been signaled before.
256      *
257      * @param[in]  aEvent    The event to check.
258      *
259      * @retval TRUE    The event @p aEvent have been signaled before.
260      * @retval FALSE   The event @p aEvent has not been signaled before.
261      *
262      */
HasSignaled(Event aEvent) const263     bool HasSignaled(Event aEvent) const { return mSignaledEvents.Contains(aEvent); }
264 
265     /**
266      * This template method updates a variable of a type `Type` with a new value and signals the given event.
267      *
268      * If the variable is already set to the same value, this method returns `kErrorAlready` and the event is
269      * signaled using `SignalIfFirst()` (i.e., signal is scheduled only if event has not been signaled before).
270      *
271      * The template `Type` should support comparison operator `==` and assignment operator `=`.
272      *
273      * @param[inout] aVariable    A reference to the variable to update.
274      * @param[in]    aNewValue    The new value.
275      * @param[in]    aEvent       The event to signal.
276      *
277      * @retval kErrorNone      The variable was update successfully and @p aEvent was signaled.
278      * @retval kErrorAlready   The variable was already set to the same value.
279      *
280      */
Update(Type & aVariable,const Type & aNewValue,Event aEvent)281     template <typename Type> Error Update(Type &aVariable, const Type &aNewValue, Event aEvent)
282     {
283         Error error = kErrorNone;
284 
285         if (aVariable == aNewValue)
286         {
287             SignalIfFirst(aEvent);
288             error = kErrorAlready;
289         }
290         else
291         {
292             aVariable = aNewValue;
293             Signal(aEvent);
294         }
295 
296         return error;
297     }
298 
299 private:
300     static constexpr uint16_t kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS;
301 
302     // Character limit to divide the log into multiple lines in `LogChangedFlags()`.
303     static constexpr uint16_t kFlagsStringLineLimit = 70;
304 
305     // Max length for string representation of a flag by `FlagToString()`.
306     static constexpr uint8_t kMaxFlagNameLength = 25;
307 
308     static constexpr uint16_t kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength;
309 
310     struct ExternalCallback
311     {
312         otStateChangedCallback mHandler;
313         void *                 mContext;
314     };
315 
316     static void EmitEvents(Tasklet &aTasklet);
317     void        EmitEvents(void);
318 
319     void        LogEvents(Events aEvents) const;
320     const char *EventToString(Event aEvent) const;
321 
322     Events           mEventsToSignal;
323     Events           mSignaledEvents;
324     Tasklet          mTask;
325     ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
326 };
327 
328 /**
329  * @}
330  *
331  */
332 
333 } // namespace ot
334 
335 #endif // NOTIFIER_HPP_
336