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/callback.hpp"
46 #include "common/error.hpp"
47 #include "common/locator.hpp"
48 #include "common/non_copyable.hpp"
49 #include "common/tasklet.hpp"
50 
51 namespace ot {
52 
53 /**
54  * @addtogroup core-notifier
55  *
56  * @brief
57  *   This module includes definitions for OpenThread Notifier class.
58  *
59  * @{
60  *
61  */
62 
63 /**
64  * This enumeration type represents events emitted from OpenThread Notifier.
65  *
66  */
67 enum Event : uint32_t
68 {
69     kEventIp6AddressAdded                  = OT_CHANGED_IP6_ADDRESS_ADDED,            ///< IPv6 address was added
70     kEventIp6AddressRemoved                = OT_CHANGED_IP6_ADDRESS_REMOVED,          ///< IPv6 address was removed
71     kEventThreadRoleChanged                = OT_CHANGED_THREAD_ROLE,                  ///< Role changed
72     kEventThreadLinkLocalAddrChanged       = OT_CHANGED_THREAD_LL_ADDR,               ///< Link-local address changed
73     kEventThreadMeshLocalAddrChanged       = OT_CHANGED_THREAD_ML_ADDR,               ///< Mesh-local address changed
74     kEventThreadRlocAdded                  = OT_CHANGED_THREAD_RLOC_ADDED,            ///< RLOC was added
75     kEventThreadRlocRemoved                = OT_CHANGED_THREAD_RLOC_REMOVED,          ///< RLOC was removed
76     kEventThreadPartitionIdChanged         = OT_CHANGED_THREAD_PARTITION_ID,          ///< Partition ID changed
77     kEventThreadKeySeqCounterChanged       = OT_CHANGED_THREAD_KEY_SEQUENCE_COUNTER,  ///< Key Sequence changed
78     kEventThreadNetdataChanged             = OT_CHANGED_THREAD_NETDATA,               ///< Network Data changed
79     kEventThreadChildAdded                 = OT_CHANGED_THREAD_CHILD_ADDED,           ///< Child was added
80     kEventThreadChildRemoved               = OT_CHANGED_THREAD_CHILD_REMOVED,         ///< Child was removed
81     kEventIp6MulticastSubscribed           = OT_CHANGED_IP6_MULTICAST_SUBSCRIBED,     ///< Multicast address added
82     kEventIp6MulticastUnsubscribed         = OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED,   ///< Multicast address removed
83     kEventThreadChannelChanged             = OT_CHANGED_THREAD_CHANNEL,               ///< Network channel changed
84     kEventThreadPanIdChanged               = OT_CHANGED_THREAD_PANID,                 ///< Network PAN ID changed
85     kEventThreadNetworkNameChanged         = OT_CHANGED_THREAD_NETWORK_NAME,          ///< Network name changed
86     kEventThreadExtPanIdChanged            = OT_CHANGED_THREAD_EXT_PANID,             ///< Extended PAN ID changed
87     kEventNetworkKeyChanged                = OT_CHANGED_NETWORK_KEY,                  ///< Network Key changed
88     kEventPskcChanged                      = OT_CHANGED_PSKC,                         ///< PSKc changed
89     kEventSecurityPolicyChanged            = OT_CHANGED_SECURITY_POLICY,              ///< Security Policy changed
90     kEventChannelManagerNewChannelChanged  = OT_CHANGED_CHANNEL_MANAGER_NEW_CHANNEL,  ///< New Channel (channel-manager)
91     kEventSupportedChannelMaskChanged      = OT_CHANGED_SUPPORTED_CHANNEL_MASK,       ///< Channel mask changed
92     kEventCommissionerStateChanged         = OT_CHANGED_COMMISSIONER_STATE,           ///< Commissioner state changed
93     kEventThreadNetifStateChanged          = OT_CHANGED_THREAD_NETIF_STATE,           ///< Netif state changed
94     kEventThreadBackboneRouterStateChanged = OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE, ///< Backbone Router state changed
95     kEventThreadBackboneRouterLocalChanged = OT_CHANGED_THREAD_BACKBONE_ROUTER_LOCAL, ///< Local Backbone Router changed
96     kEventJoinerStateChanged               = OT_CHANGED_JOINER_STATE,                 ///< Joiner state changed
97     kEventActiveDatasetChanged             = OT_CHANGED_ACTIVE_DATASET,               ///< Active Dataset changed
98     kEventPendingDatasetChanged            = OT_CHANGED_PENDING_DATASET,              ///< Pending Dataset changed
99     kEventNat64TranslatorStateChanged      = OT_CHANGED_NAT64_TRANSLATOR_STATE,       ///< Nat64Translator state changed
100 };
101 
102 /**
103  * This type represents a list of events.
104  *
105  */
106 class Events
107 {
108 public:
109     /**
110      * This type represents a bit-field indicating a list of events (with values from `Event`)
111      *
112      */
113     typedef otChangedFlags Flags;
114 
115     /**
116      * This constructor initializes the `Events` list (as empty).
117      *
118      */
Events(void)119     Events(void)
120         : mEventFlags(0)
121     {
122     }
123 
124     /**
125      * This method clears the `Events` list.
126      *
127      */
Clear(void)128     void Clear(void) { mEventFlags = 0; }
129 
130     /**
131      * This method indicates whether the `Events` list contains a given event.
132      *
133      * @param[in] aEvent  The event to check.
134      *
135      * @returns TRUE if the list contains the @p aEvent, FALSE otherwise.
136      *
137      */
Contains(Event aEvent) const138     bool Contains(Event aEvent) const { return (mEventFlags & aEvent) != 0; }
139 
140     /**
141      * This method indicates whether the `Events` list contains any of a given set of events.
142      *
143      * @param[in] aEvents  The events set to check (must be a collection of `Event` constants combined using `|`).
144      *
145      * @returns TRUE if the list contains any of the @p aEvents set, FALSE otherwise.
146      *
147      */
ContainsAny(Flags aEvents) const148     bool ContainsAny(Flags aEvents) const { return (mEventFlags & aEvents) != 0; }
149 
150     /**
151      * This method indicates whether the `Events` list contains all of a given set of events.
152      *
153      * @param[in] aEvents  The events set to check (must be collection of `Event` constants combined using `|`).
154      *
155      * @returns TRUE if the list contains all of the @p aEvents set, FALSE otherwise.
156      *
157      */
ContainsAll(Flags aEvents) const158     bool ContainsAll(Flags aEvents) const { return (mEventFlags & aEvents) == aEvents; }
159 
160     /**
161      * This method adds a given event to the `Events` list.
162      *
163      * @param[in] aEvent  The event to add.
164      *
165      */
Add(Event aEvent)166     void Add(Event aEvent) { mEventFlags |= aEvent; }
167 
168     /**
169      * This method indicates whether the `Events` list is empty.
170      *
171      * @returns TRUE if the list is empty, FALSE otherwise.
172      *
173      */
IsEmpty(void) const174     bool IsEmpty(void) const { return (mEventFlags == 0); }
175 
176     /**
177      * This method gets the `Events` list as bit-field `Flags` value.
178      *
179      * @returns The list as bit-field `Flags` value.
180      *
181      */
GetAsFlags(void) const182     Flags GetAsFlags(void) const { return mEventFlags; }
183 
184 private:
185     Flags mEventFlags;
186 };
187 
188 /**
189  * This class implements the OpenThread Notifier.
190  *
191  * For core internal modules, `Notifier` class emits events directly to them by invoking method `HandleNotifierEvents()`
192  * on the module instance.
193  *
194  * A `otStateChangedCallback` callback can be explicitly registered with the `Notifier`. This is mainly intended for use
195  * by external users (i.e.provided as an OpenThread public API). Max number of such callbacks that can be registered at
196  * the same time is specified by `OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS` configuration parameter.
197  *
198  */
199 class Notifier : public InstanceLocator, private NonCopyable
200 {
201 public:
202     /**
203      * This constructor initializes a `Notifier` instance.
204      *
205      *  @param[in] aInstance     A reference to OpenThread instance.
206      *
207      */
208     explicit Notifier(Instance &aInstance);
209 
210     /**
211      * This method registers an `otStateChangedCallback` handler.
212      *
213      * @param[in]  aCallback     A pointer to the handler function that is called to notify of the changes.
214      * @param[in]  aContext      A pointer to arbitrary context information.
215      *
216      * @retval kErrorNone     Successfully registered the callback.
217      * @retval kErrorAlready  The callback was already registered.
218      * @retval kErrorNoBufs   Could not add the callback due to resource constraints.
219      *
220      */
221     Error RegisterCallback(otStateChangedCallback aCallback, void *aContext);
222 
223     /**
224      * This method removes/unregisters a previously registered `otStateChangedCallback` handler.
225      *
226      * @param[in]  aCallback     A pointer to the callback function pointer.
227      * @param[in]  aContext      A pointer to arbitrary context information.
228      *
229      */
230     void RemoveCallback(otStateChangedCallback aCallback, void *aContext);
231 
232     /**
233      * This method schedules signaling of an event.
234      *
235      * @param[in]  aEvent     The event to signal.
236      *
237      */
238     void Signal(Event aEvent);
239 
240     /**
241      * This method schedules signaling of am event only if the event has not been signaled before (first time signal).
242      *
243      * @param[in]  aEvent     The event to signal.
244      *
245      */
246     void SignalIfFirst(Event aEvent);
247 
248     /**
249      * This method indicates whether or not an event signal callback is pending/scheduled.
250      *
251      * @returns TRUE if a callback is pending, FALSE otherwise.
252      *
253      */
IsPending(void) const254     bool IsPending(void) const { return !mEventsToSignal.IsEmpty(); }
255 
256     /**
257      * This method indicates whether or not an event has been signaled before.
258      *
259      * @param[in]  aEvent    The event to check.
260      *
261      * @retval TRUE    The event @p aEvent have been signaled before.
262      * @retval FALSE   The event @p aEvent has not been signaled before.
263      *
264      */
HasSignaled(Event aEvent) const265     bool HasSignaled(Event aEvent) const { return mSignaledEvents.Contains(aEvent); }
266 
267     /**
268      * This template method updates a variable of a type `Type` with a new value and signals the given event.
269      *
270      * If the variable is already set to the same value, this method returns `kErrorAlready` and the event is
271      * signaled using `SignalIfFirst()` (i.e., signal is scheduled only if event has not been signaled before).
272      *
273      * The template `Type` should support comparison operator `==` and assignment operator `=`.
274      *
275      * @param[in,out] aVariable    A reference to the variable to update.
276      * @param[in]     aNewValue    The new value.
277      * @param[in]     aEvent       The event to signal.
278      *
279      * @retval kErrorNone      The variable was update successfully and @p aEvent was signaled.
280      * @retval kErrorAlready   The variable was already set to the same value.
281      *
282      */
Update(Type & aVariable,const Type & aNewValue,Event aEvent)283     template <typename Type> Error Update(Type &aVariable, const Type &aNewValue, Event aEvent)
284     {
285         Error error = kErrorNone;
286 
287         if (aVariable == aNewValue)
288         {
289             SignalIfFirst(aEvent);
290             error = kErrorAlready;
291         }
292         else
293         {
294             aVariable = aNewValue;
295             Signal(aEvent);
296         }
297 
298         return error;
299     }
300 
301 private:
302     static constexpr uint16_t kMaxExternalHandlers = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS;
303 
304     // Character limit to divide the log into multiple lines in `LogChangedFlags()`.
305     static constexpr uint16_t kFlagsStringLineLimit = 70;
306 
307     // Max length for string representation of a flag by `FlagToString()`.
308     static constexpr uint8_t kMaxFlagNameLength = 25;
309 
310     static constexpr uint16_t kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength;
311 
312     typedef Callback<otStateChangedCallback> ExternalCallback;
313 
314     void EmitEvents(void);
315 
316     void        LogEvents(Events aEvents) const;
317     const char *EventToString(Event aEvent) const;
318 
319     using EmitEventsTask = TaskletIn<Notifier, &Notifier::EmitEvents>;
320 
321     Events           mEventsToSignal;
322     Events           mSignaledEvents;
323     EmitEventsTask   mTask;
324     ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
325 };
326 
327 /**
328  * @}
329  *
330  */
331 
332 } // namespace ot
333 
334 #endif // NOTIFIER_HPP_
335