• 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 implements the Notifier class.
32  */
33 
34 #include "notifier.hpp"
35 
36 #include "instance/instance.hpp"
37 
38 namespace ot {
39 
40 RegisterLogModule("Notifier");
41 
Notifier(Instance & aInstance)42 Notifier::Notifier(Instance &aInstance)
43     : InstanceLocator(aInstance)
44     , mTask(aInstance)
45 {
46 }
47 
RegisterCallback(StateChangedCallback aCallback,void * aContext)48 Error Notifier::RegisterCallback(StateChangedCallback aCallback, void *aContext)
49 {
50     Error            error = kErrorNone;
51     ExternalCallback newCallback;
52 
53     newCallback.Set(aCallback, aContext);
54     VerifyOrExit(!mExternalCallbacks.Contains(newCallback), error = kErrorAlready);
55     error = mExternalCallbacks.PushBack(newCallback);
56 
57 exit:
58     return error;
59 }
60 
RemoveCallback(StateChangedCallback aCallback,void * aContext)61 void Notifier::RemoveCallback(StateChangedCallback aCallback, void *aContext)
62 {
63     ExternalCallback callbackToRemove;
64 
65     callbackToRemove.Set(aCallback, aContext);
66     mExternalCallbacks.Remove(callbackToRemove);
67 }
68 
Signal(Event aEvent)69 void Notifier::Signal(Event aEvent)
70 {
71     mEventsToSignal.Add(aEvent);
72     mSignaledEvents.Add(aEvent);
73     mTask.Post();
74 }
75 
SignalIfFirst(Event aEvent)76 void Notifier::SignalIfFirst(Event aEvent)
77 {
78     if (!HasSignaled(aEvent))
79     {
80         Signal(aEvent);
81     }
82 }
83 
EmitEvents(void)84 void Notifier::EmitEvents(void)
85 {
86     Events events;
87 
88     VerifyOrExit(!mEventsToSignal.IsEmpty());
89 
90     // Note that the callbacks may signal new events, so we create a
91     // copy of `mEventsToSignal` and then clear it.
92 
93     events = mEventsToSignal;
94     mEventsToSignal.Clear();
95 
96     LogEvents(events);
97 
98     // Emit events to core internal modules
99 
100     Get<Mle::Mle>().HandleNotifierEvents(events);
101     Get<EnergyScanServer>().HandleNotifierEvents(events);
102 #if OPENTHREAD_FTD
103     Get<MeshCoP::JoinerRouter>().HandleNotifierEvents(events);
104 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
105     Get<BackboneRouter::Manager>().HandleNotifierEvents(events);
106 #endif
107     Get<ChildSupervisor>().HandleNotifierEvents(events);
108 #if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
109     Get<MeshCoP::DatasetUpdater>().HandleNotifierEvents(events);
110 #endif
111 #endif // OPENTHREAD_FTD
112 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
113     Get<NetworkData::Notifier>().HandleNotifierEvents(events);
114 #endif
115 #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
116     Get<AnnounceSender>().HandleNotifierEvents(events);
117 #endif
118 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
119     Get<MeshCoP::BorderAgent>().HandleNotifierEvents(events);
120 #endif
121 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
122     Get<MlrManager>().HandleNotifierEvents(events);
123 #endif
124 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
125     Get<DuaManager>().HandleNotifierEvents(events);
126 #endif
127 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
128     Get<Trel::Link>().HandleNotifierEvents(events);
129 #endif
130 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
131     Get<TimeSync>().HandleNotifierEvents(events);
132 #endif
133 #if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
134     Get<Utils::Slaac>().HandleNotifierEvents(events);
135 #endif
136 #if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
137     Get<Utils::JamDetector>().HandleNotifierEvents(events);
138 #endif
139 #if OPENTHREAD_CONFIG_OTNS_ENABLE
140     Get<Utils::Otns>().HandleNotifierEvents(events);
141 #endif
142 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
143     Get<Utils::HistoryTracker>().HandleNotifierEvents(events);
144 #endif
145 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
146     Get<Extension::ExtensionBase>().HandleNotifierEvents(events);
147 #endif
148 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
149     Get<BorderRouter::RoutingManager>().HandleNotifierEvents(events);
150 #endif
151 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
152     Get<Srp::Client>().HandleNotifierEvents(events);
153 #endif
154 #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE && OPENTHREAD_CONFIG_SRP_SERVER_FAST_START_MODE_ENABLE
155     Get<Srp::Server>().HandleNotifierEvents(events);
156 #endif
157 
158 #if OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE
159     // The `NetworkData::Publisher` is notified last (e.g., after SRP
160     // client) to allow other modules to request changes to what is
161     // being published (if needed).
162     Get<NetworkData::Publisher>().HandleNotifierEvents(events);
163 #endif
164 #if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
165     Get<Utils::LinkMetricsManager>().HandleNotifierEvents(events);
166 #endif
167 
168     for (ExternalCallback &callback : mExternalCallbacks)
169     {
170         callback.InvokeIfSet(events.GetAsFlags());
171     }
172 
173 exit:
174     return;
175 }
176 
177 // LCOV_EXCL_START
178 
179 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
180 
LogEvents(Events aEvents) const181 void Notifier::LogEvents(Events aEvents) const
182 {
183     Events::Flags                  flags    = aEvents.GetAsFlags();
184     bool                           addSpace = false;
185     bool                           didLog   = false;
186     String<kFlagsStringBufferSize> string;
187 
188     for (uint8_t bit = 0; bit < BitSizeOf(Events::Flags); bit++)
189     {
190         VerifyOrExit(flags != 0);
191 
192         if (flags & (1 << bit))
193         {
194             if (string.GetLength() >= kFlagsStringLineLimit)
195             {
196                 LogInfo("StateChanged (0x%08lx) %s%s ...", ToUlong(aEvents.GetAsFlags()), didLog ? "... " : "[",
197                         string.AsCString());
198                 string.Clear();
199                 didLog   = true;
200                 addSpace = false;
201             }
202 
203             string.Append("%s%s", addSpace ? " " : "", EventToString(static_cast<Event>(1 << bit)));
204             addSpace = true;
205 
206             flags ^= (1 << bit);
207         }
208     }
209 
210 exit:
211     LogInfo("StateChanged (0x%08lx) %s%s]", ToUlong(aEvents.GetAsFlags()), didLog ? "... " : "[", string.AsCString());
212 }
213 
EventToString(Event aEvent) const214 const char *Notifier::EventToString(Event aEvent) const
215 {
216     const char *retval = "(unknown)";
217 
218     // To ensure no clipping of flag names in the logs, the returned
219     // strings from this method should have shorter length than
220     // `kMaxFlagNameLength` value.
221     static const char *const kEventStrings[] = {
222         "Ip6+",              // kEventIp6AddressAdded                  (1 << 0)
223         "Ip6-",              // kEventIp6AddressRemoved                (1 << 1)
224         "Role",              // kEventThreadRoleChanged                (1 << 2)
225         "LLAddr",            // kEventThreadLinkLocalAddrChanged       (1 << 3)
226         "MLAddr",            // kEventThreadMeshLocalAddrChanged       (1 << 4)
227         "Rloc+",             // kEventThreadRlocAdded                  (1 << 5)
228         "Rloc-",             // kEventThreadRlocRemoved                (1 << 6)
229         "PartitionId",       // kEventThreadPartitionIdChanged         (1 << 7)
230         "KeySeqCntr",        // kEventThreadKeySeqCounterChanged       (1 << 8)
231         "NetData",           // kEventThreadNetdataChanged             (1 << 9)
232         "Child+",            // kEventThreadChildAdded                 (1 << 10)
233         "Child-",            // kEventThreadChildRemoved               (1 << 11)
234         "Ip6Mult+",          // kEventIp6MulticastSubscribed           (1 << 12)
235         "Ip6Mult-",          // kEventIp6MulticastUnsubscribed         (1 << 13)
236         "Channel",           // kEventThreadChannelChanged             (1 << 14)
237         "PanId",             // kEventThreadPanIdChanged               (1 << 15)
238         "NetName",           // kEventThreadNetworkNameChanged         (1 << 16)
239         "ExtPanId",          // kEventThreadExtPanIdChanged            (1 << 17)
240         "NetworkKey",        // kEventNetworkKeyChanged                (1 << 18)
241         "PSKc",              // kEventPskcChanged                      (1 << 19)
242         "SecPolicy",         // kEventSecurityPolicyChanged            (1 << 20)
243         "CMNewChan",         // kEventChannelManagerNewChannelChanged  (1 << 21)
244         "ChanMask",          // kEventSupportedChannelMaskChanged      (1 << 22)
245         "CommissionerState", // kEventCommissionerStateChanged         (1 << 23)
246         "NetifState",        // kEventThreadNetifStateChanged          (1 << 24)
247         "BbrState",          // kEventThreadBackboneRouterStateChanged (1 << 25)
248         "BbrLocal",          // kEventThreadBackboneRouterLocalChanged (1 << 26)
249         "JoinerState",       // kEventJoinerStateChanged               (1 << 27)
250         "ActDset",           // kEventActiveDatasetChanged             (1 << 28)
251         "PndDset",           // kEventPendingDatasetChanged            (1 << 29)
252         "Nat64",             // kEventNat64TranslatorStateChanged      (1 << 30)
253         "ParentLq",          // kEventParentLinkQualityChanged         (1 << 31)
254     };
255 
256     for (uint8_t index = 0; index < GetArrayLength(kEventStrings); index++)
257     {
258         if (static_cast<uint32_t>(aEvent) == (1U << index))
259         {
260             retval = kEventStrings[index];
261             break;
262         }
263     }
264 
265     return retval;
266 }
267 
268 #else // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO)
269 
LogEvents(Events) const270 void Notifier::LogEvents(Events) const {}
271 
EventToString(Event) const272 const char *Notifier::EventToString(Event) const { return ""; }
273 
274 #endif // #if OT_SHOULD_LOG_AT( OT_LOG_LEVEL_INFO)
275 
276 // LCOV_EXCL_STOP
277 
278 } // namespace ot
279