Coverage Report

Created: 2025-05-12 06:47

/src/openthread/src/core/common/notifier.cpp
Line
Count
Source (jump to first uncovered line)
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
42
Notifier::Notifier(Instance &aInstance)
43
35.4k
    : InstanceLocator(aInstance)
44
35.4k
    , mTask(aInstance)
45
35.4k
{
46
35.4k
}
47
48
Error Notifier::RegisterCallback(StateChangedCallback aCallback, void *aContext)
49
21.3k
{
50
21.3k
    Error            error = kErrorNone;
51
21.3k
    ExternalCallback newCallback;
52
53
21.3k
    newCallback.Set(aCallback, aContext);
54
21.3k
    VerifyOrExit(!mExternalCallbacks.Contains(newCallback), error = kErrorAlready);
55
21.3k
    error = mExternalCallbacks.PushBack(newCallback);
56
57
21.3k
exit:
58
21.3k
    return error;
59
21.3k
}
60
61
void Notifier::RemoveCallback(StateChangedCallback aCallback, void *aContext)
62
0
{
63
0
    ExternalCallback callbackToRemove;
64
65
0
    callbackToRemove.Set(aCallback, aContext);
66
0
    mExternalCallbacks.Remove(callbackToRemove);
67
0
}
68
69
void Notifier::Signal(Event aEvent)
70
2.43M
{
71
2.43M
    mEventsToSignal.Add(aEvent);
72
2.43M
    mSignaledEvents.Add(aEvent);
73
2.43M
    mTask.Post();
74
2.43M
}
75
76
void Notifier::SignalIfFirst(Event aEvent)
77
190k
{
78
190k
    if (!HasSignaled(aEvent))
79
35.5k
    {
80
35.5k
        Signal(aEvent);
81
35.5k
    }
82
190k
}
83
84
void Notifier::EmitEvents(void)
85
35.7k
{
86
35.7k
    Events events;
87
88
35.7k
    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
35.7k
    events = mEventsToSignal;
94
35.7k
    mEventsToSignal.Clear();
95
96
35.7k
    LogEvents(events);
97
98
    // Emit events to core internal modules
99
100
35.7k
    Get<Mle::Mle>().HandleNotifierEvents(events);
101
35.7k
    Get<EnergyScanServer>().HandleNotifierEvents(events);
102
35.7k
#if OPENTHREAD_FTD
103
35.7k
    Get<MeshCoP::JoinerRouter>().HandleNotifierEvents(events);
104
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
105
    Get<BackboneRouter::Manager>().HandleNotifierEvents(events);
106
#endif
107
35.7k
    Get<ChildSupervisor>().HandleNotifierEvents(events);
108
35.7k
#if OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
109
35.7k
    Get<MeshCoP::DatasetUpdater>().HandleNotifierEvents(events);
110
35.7k
#endif
111
35.7k
#endif // OPENTHREAD_FTD
112
35.7k
#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
113
35.7k
    Get<NetworkData::Notifier>().HandleNotifierEvents(events);
114
35.7k
#endif
115
35.7k
#if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
116
35.7k
    Get<AnnounceSender>().HandleNotifierEvents(events);
117
35.7k
#endif
118
35.7k
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
119
35.7k
    Get<MeshCoP::BorderAgent>().HandleNotifierEvents(events);
120
35.7k
#endif
121
35.7k
#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
122
35.7k
    Get<MlrManager>().HandleNotifierEvents(events);
123
35.7k
#endif
124
35.7k
#if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
125
35.7k
    Get<DuaManager>().HandleNotifierEvents(events);
126
35.7k
#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
35.7k
#if OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE
134
35.7k
    Get<Utils::Slaac>().HandleNotifierEvents(events);
135
35.7k
#endif
136
35.7k
#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
137
35.7k
    Get<Utils::JamDetector>().HandleNotifierEvents(events);
138
35.7k
#endif
139
#if OPENTHREAD_CONFIG_OTNS_ENABLE
140
    Get<Utils::Otns>().HandleNotifierEvents(events);
141
#endif
142
35.7k
#if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
143
35.7k
    Get<Utils::HistoryTracker>().HandleNotifierEvents(events);
144
35.7k
#endif
145
#if OPENTHREAD_ENABLE_VENDOR_EXTENSION
146
    Get<Extension::ExtensionBase>().HandleNotifierEvents(events);
147
#endif
148
35.7k
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
149
35.7k
    Get<BorderRouter::RoutingManager>().HandleNotifierEvents(events);
150
35.7k
#endif
151
35.7k
#if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
152
35.7k
    Get<Srp::Client>().HandleNotifierEvents(events);
153
35.7k
#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
35.7k
#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
35.7k
    Get<NetworkData::Publisher>().HandleNotifierEvents(events);
163
35.7k
#endif
164
#if OPENTHREAD_CONFIG_LINK_METRICS_MANAGER_ENABLE
165
    Get<Utils::LinkMetricsManager>().HandleNotifierEvents(events);
166
#endif
167
168
35.7k
    for (ExternalCallback &callback : mExternalCallbacks)
169
21.3k
    {
170
21.3k
        callback.InvokeIfSet(events.GetAsFlags());
171
21.3k
    }
172
173
35.7k
exit:
174
35.7k
    return;
175
35.7k
}
176
177
// LCOV_EXCL_START
178
179
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
180
181
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
214
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
270
35.7k
void Notifier::LogEvents(Events) const {}
271
272
0
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