1 /*
2 * Copyright (c) 2020, 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 transmissions of SVR_DATA.ntf messages to the Leader.
32 */
33
34 #include "network_data_notifier.hpp"
35
36 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
37
38 #include "common/code_utils.hpp"
39 #include "common/instance.hpp"
40 #include "common/locator_getters.hpp"
41 #include "thread/network_data_leader.hpp"
42 #include "thread/network_data_local.hpp"
43
44 namespace ot {
45 namespace NetworkData {
46
Notifier(Instance & aInstance)47 Notifier::Notifier(Instance &aInstance)
48 : InstanceLocator(aInstance)
49 , mTimer(aInstance, Notifier::HandleTimer)
50 , mNextDelay(0)
51 , mWaitingForResponse(false)
52 {
53 }
54
HandleServerDataUpdated(void)55 void Notifier::HandleServerDataUpdated(void)
56 {
57 mNextDelay = 0;
58 SynchronizeServerData();
59 }
60
SynchronizeServerData(void)61 void Notifier::SynchronizeServerData(void)
62 {
63 Error error = kErrorNotFound;
64
65 VerifyOrExit(Get<Mle::MleRouter>().IsAttached() && !mWaitingForResponse);
66
67 VerifyOrExit((mNextDelay == 0) || !mTimer.IsRunning());
68
69 #if OPENTHREAD_FTD
70 mNextDelay = kDelayRemoveStaleChildren;
71 error = Get<Leader>().RemoveStaleChildEntries(&Notifier::HandleCoapResponse, this);
72 VerifyOrExit(error == kErrorNotFound);
73 #endif
74
75 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
76 mNextDelay = kDelaySynchronizeServerData;
77 error = Get<Local>().UpdateInconsistentServerData(&Notifier::HandleCoapResponse, this);
78 VerifyOrExit(error == kErrorNotFound);
79 #endif
80
81 exit:
82 switch (error)
83 {
84 case kErrorNone:
85 mWaitingForResponse = true;
86 break;
87 case kErrorNoBufs:
88 mTimer.Start(kDelayNoBufs);
89 break;
90 #if OPENTHREAD_FTD
91 case kErrorInvalidState:
92 mTimer.Start(Time::SecToMsec(Get<Mle::MleRouter>().GetRouterSelectionJitterTimeout() + 1));
93 break;
94 #endif
95 case kErrorNotFound:
96 break;
97 default:
98 OT_ASSERT(false);
99 OT_UNREACHABLE_CODE(break);
100 }
101 }
102
HandleNotifierEvents(Events aEvents)103 void Notifier::HandleNotifierEvents(Events aEvents)
104 {
105 if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadChildRemoved))
106 {
107 mNextDelay = 0;
108 }
109
110 if (aEvents.ContainsAny(kEventThreadNetdataChanged | kEventThreadRoleChanged | kEventThreadChildRemoved))
111 {
112 SynchronizeServerData();
113 }
114 }
115
HandleTimer(Timer & aTimer)116 void Notifier::HandleTimer(Timer &aTimer)
117 {
118 aTimer.Get<Notifier>().HandleTimer();
119 }
120
HandleTimer(void)121 void Notifier::HandleTimer(void)
122 {
123 SynchronizeServerData();
124 }
125
HandleCoapResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,Error aResult)126 void Notifier::HandleCoapResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult)
127 {
128 OT_UNUSED_VARIABLE(aMessage);
129 OT_UNUSED_VARIABLE(aMessageInfo);
130
131 static_cast<Notifier *>(aContext)->HandleCoapResponse(aResult);
132 }
133
HandleCoapResponse(Error aResult)134 void Notifier::HandleCoapResponse(Error aResult)
135 {
136 mWaitingForResponse = false;
137
138 switch (aResult)
139 {
140 case kErrorNone:
141 mTimer.Start(mNextDelay + 1);
142 break;
143
144 case kErrorResponseTimeout:
145 case kErrorAbort:
146 SynchronizeServerData();
147 break;
148
149 default:
150 OT_ASSERT(false);
151 OT_UNREACHABLE_CODE(break);
152 }
153 }
154
155 } // namespace NetworkData
156 } // namespace ot
157
158 #endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
159