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