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 OpenThread Instance class.
32 */
33
34 #include "instance.hpp"
35
36 #include <openthread/platform/misc.h>
37
38 #include "common/logging.hpp"
39 #include "common/new.hpp"
40 #include "radio/trel_link.hpp"
41 #include "utils/heap.hpp"
42
43 namespace ot {
44
45 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
46
47 // Define the raw storage used for OpenThread instance (in single-instance case).
48 OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t);
49
50 #endif
51
52 #if OPENTHREAD_MTD || OPENTHREAD_FTD
53 #if !OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
54 Utils::Heap Instance::sHeap;
55 #endif
56 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
57 bool Instance::sDnsNameCompressionEnabled = true;
58 #endif
59 #endif
60
Instance(void)61 Instance::Instance(void)
62 : mTimerMilliScheduler(*this)
63 #if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
64 , mTimerMicroScheduler(*this)
65 #endif
66 , mRadio(*this)
67 #if OPENTHREAD_MTD || OPENTHREAD_FTD
68 , mNotifier(*this)
69 , mTimeTicker(*this)
70 , mSettings(*this)
71 , mSettingsDriver(*this)
72 , mMessagePool(*this)
73 , mIp6(*this)
74 , mThreadNetif(*this)
75 #if OPENTHREAD_CONFIG_COAP_API_ENABLE
76 , mApplicationCoap(*this)
77 #endif
78 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
79 , mApplicationCoapSecure(*this, /* aLayerTwoSecurity */ true)
80 #endif
81 #if OPENTHREAD_CONFIG_PING_SENDER_ENABLE
82 , mPingSender(*this)
83 #endif
84 #if OPENTHREAD_CONFIG_CHANNEL_MONITOR_ENABLE
85 , mChannelMonitor(*this)
86 #endif
87 #if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE && OPENTHREAD_FTD
88 , mChannelManager(*this)
89 #endif
90 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
91 , mHistoryTracker(*this)
92 #endif
93 #if (OPENTHREAD_CONFIG_DATASET_UPDATER_ENABLE || OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE) && OPENTHREAD_FTD
94 , mDatasetUpdater(*this)
95 #endif
96 #if OPENTHREAD_CONFIG_ANNOUNCE_SENDER_ENABLE
97 , mAnnounceSender(*this)
98 #endif
99 #if OPENTHREAD_CONFIG_OTNS_ENABLE
100 , mOtns(*this)
101 #endif
102 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
103 , mRoutingManager(*this)
104 #endif
105 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
106 #if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
107 , mLinkRaw(*this)
108 #endif
109 #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE
110 , mLogLevel(static_cast<otLogLevel>(OPENTHREAD_CONFIG_LOG_LEVEL_INIT))
111 #endif
112 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
113 , mExtension(Extension::ExtensionBase::Init(*this))
114 #endif
115 #if OPENTHREAD_CONFIG_DIAG_ENABLE
116 , mDiags(*this)
117 #endif
118 , mIsInitialized(false)
119 {
120 }
121
122 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
123
InitSingle(void)124 Instance &Instance::InitSingle(void)
125 {
126 Instance *instance = &Get();
127
128 VerifyOrExit(!instance->mIsInitialized);
129
130 instance = new (&gInstanceRaw) Instance();
131
132 instance->AfterInit();
133
134 exit:
135 return *instance;
136 }
137
Get(void)138 Instance &Instance::Get(void)
139 {
140 void *instance = &gInstanceRaw;
141
142 return *static_cast<Instance *>(instance);
143 }
144
145 #else // #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
146
Init(void * aBuffer,size_t * aBufferSize)147 Instance *Instance::Init(void *aBuffer, size_t *aBufferSize)
148 {
149 Instance *instance = nullptr;
150
151 VerifyOrExit(aBufferSize != nullptr);
152
153 // Make sure the input buffer is big enough
154 VerifyOrExit(sizeof(Instance) <= *aBufferSize, *aBufferSize = sizeof(Instance));
155
156 VerifyOrExit(aBuffer != nullptr);
157
158 instance = new (aBuffer) Instance();
159
160 instance->AfterInit();
161
162 exit:
163 return instance;
164 }
165
166 #endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
167
Reset(void)168 void Instance::Reset(void)
169 {
170 otPlatReset(this);
171 }
172
AfterInit(void)173 void Instance::AfterInit(void)
174 {
175 mIsInitialized = true;
176 #if OPENTHREAD_MTD || OPENTHREAD_FTD
177
178 // Restore datasets and network information
179
180 Get<Settings>().Init();
181 IgnoreError(Get<Mle::MleRouter>().Restore());
182
183 #if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
184 Get<Trel::Link>().AfterInit();
185 #endif
186
187 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
188
189 #if OPENTHREAD_ENABLE_VENDOR_EXTENSION
190 Get<Extension::ExtensionBase>().SignalInstanceInit();
191 #endif
192 }
193
Finalize(void)194 void Instance::Finalize(void)
195 {
196 VerifyOrExit(mIsInitialized);
197
198 mIsInitialized = false;
199
200 #if OPENTHREAD_MTD || OPENTHREAD_FTD
201 IgnoreError(otThreadSetEnabled(this, false));
202 IgnoreError(otIp6SetEnabled(this, false));
203 IgnoreError(otLinkSetEnabled(this, false));
204
205 Get<Settings>().Deinit();
206 #endif
207
208 IgnoreError(Get<Mac::SubMac>().Disable());
209
210 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
211
212 /**
213 * Object was created on buffer, so instead of deleting
214 * the object we call destructor explicitly.
215 */
216 this->~Instance();
217
218 #endif // !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
219
220 exit:
221 return;
222 }
223
224 #if OPENTHREAD_MTD || OPENTHREAD_FTD
FactoryReset(void)225 void Instance::FactoryReset(void)
226 {
227 Get<Settings>().Wipe();
228 otPlatReset(this);
229 }
230
ErasePersistentInfo(void)231 Error Instance::ErasePersistentInfo(void)
232 {
233 Error error = kErrorNone;
234
235 VerifyOrExit(Get<Mle::MleRouter>().IsDisabled(), error = kErrorInvalidState);
236 Get<Settings>().Wipe();
237
238 exit:
239 return error;
240 }
241
242 #endif // OPENTHREAD_MTD || OPENTHREAD_FTD
243
244 } // namespace ot
245