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 common methods for manipulating MeshCoP Datasets.
32 *
33 */
34
35 #include "dataset_local.hpp"
36
37 #include <stdio.h>
38
39 #include "common/code_utils.hpp"
40 #include "common/instance.hpp"
41 #include "common/locator_getters.hpp"
42 #include "common/logging.hpp"
43 #include "common/settings.hpp"
44 #include "meshcop/dataset.hpp"
45 #include "meshcop/meshcop_tlvs.hpp"
46 #include "thread/mle_tlvs.hpp"
47
48 namespace ot {
49 namespace MeshCoP {
50
DatasetLocal(Instance & aInstance,Dataset::Type aType)51 DatasetLocal::DatasetLocal(Instance &aInstance, Dataset::Type aType)
52 : InstanceLocator(aInstance)
53 , mUpdateTime(0)
54 , mType(aType)
55 , mTimestampPresent(false)
56 , mSaved(false)
57 {
58 mTimestamp.Init();
59 }
60
Clear(void)61 void DatasetLocal::Clear(void)
62 {
63 IgnoreError(Get<Settings>().DeleteOperationalDataset(IsActive()));
64 mTimestamp.Init();
65 mTimestampPresent = false;
66 mSaved = false;
67 }
68
Restore(Dataset & aDataset)69 Error DatasetLocal::Restore(Dataset &aDataset)
70 {
71 const Timestamp *timestamp;
72 Error error;
73
74 mTimestampPresent = false;
75
76 error = Read(aDataset);
77 SuccessOrExit(error);
78
79 mSaved = true;
80 timestamp = aDataset.GetTimestamp(mType);
81
82 if (timestamp != nullptr)
83 {
84 mTimestamp = *timestamp;
85 mTimestampPresent = true;
86 }
87
88 exit:
89 return error;
90 }
91
Read(Dataset & aDataset) const92 Error DatasetLocal::Read(Dataset &aDataset) const
93 {
94 DelayTimerTlv *delayTimer;
95 uint32_t elapsed;
96 Error error;
97
98 error = Get<Settings>().ReadOperationalDataset(IsActive(), aDataset);
99 VerifyOrExit(error == kErrorNone, aDataset.mLength = 0);
100
101 if (mType == Dataset::kActive)
102 {
103 aDataset.RemoveTlv(Tlv::kPendingTimestamp);
104 aDataset.RemoveTlv(Tlv::kDelayTimer);
105 }
106 else
107 {
108 delayTimer = aDataset.GetTlv<DelayTimerTlv>();
109 VerifyOrExit(delayTimer);
110
111 elapsed = TimerMilli::GetNow() - mUpdateTime;
112
113 if (delayTimer->GetDelayTimer() > elapsed)
114 {
115 delayTimer->SetDelayTimer(delayTimer->GetDelayTimer() - elapsed);
116 }
117 else
118 {
119 delayTimer->SetDelayTimer(0);
120 }
121 }
122
123 aDataset.mUpdateTime = TimerMilli::GetNow();
124
125 exit:
126 return error;
127 }
128
Read(Dataset::Info & aDatasetInfo) const129 Error DatasetLocal::Read(Dataset::Info &aDatasetInfo) const
130 {
131 Dataset dataset;
132 Error error;
133
134 aDatasetInfo.Clear();
135
136 SuccessOrExit(error = Read(dataset));
137 dataset.ConvertTo(aDatasetInfo);
138
139 exit:
140 return error;
141 }
142
Read(otOperationalDatasetTlvs & aDataset) const143 Error DatasetLocal::Read(otOperationalDatasetTlvs &aDataset) const
144 {
145 Dataset dataset;
146 Error error;
147
148 memset(&aDataset, 0, sizeof(aDataset));
149
150 SuccessOrExit(error = Read(dataset));
151 dataset.ConvertTo(aDataset);
152
153 exit:
154 return error;
155 }
156
Save(const Dataset::Info & aDatasetInfo)157 Error DatasetLocal::Save(const Dataset::Info &aDatasetInfo)
158 {
159 Error error;
160 Dataset dataset;
161
162 SuccessOrExit(error = dataset.SetFrom(aDatasetInfo));
163 SuccessOrExit(error = Save(dataset));
164
165 exit:
166 return error;
167 }
168
Save(const otOperationalDatasetTlvs & aDataset)169 Error DatasetLocal::Save(const otOperationalDatasetTlvs &aDataset)
170 {
171 Dataset dataset;
172
173 dataset.SetFrom(aDataset);
174
175 return Save(dataset);
176 }
177
Save(const Dataset & aDataset)178 Error DatasetLocal::Save(const Dataset &aDataset)
179 {
180 const Timestamp *timestamp;
181 Error error = kErrorNone;
182
183 if (aDataset.GetSize() == 0)
184 {
185 // do not propagate error back
186 IgnoreError(Get<Settings>().DeleteOperationalDataset(IsActive()));
187 mSaved = false;
188 otLogInfoMeshCoP("%s dataset deleted", Dataset::TypeToString(mType));
189 }
190 else
191 {
192 SuccessOrExit(error = Get<Settings>().SaveOperationalDataset(IsActive(), aDataset));
193 mSaved = true;
194 otLogInfoMeshCoP("%s dataset set", Dataset::TypeToString(mType));
195 }
196
197 timestamp = aDataset.GetTimestamp(mType);
198
199 if (timestamp != nullptr)
200 {
201 mTimestamp = *timestamp;
202 mTimestampPresent = true;
203 }
204 else
205 {
206 mTimestampPresent = false;
207 }
208
209 mUpdateTime = TimerMilli::GetNow();
210
211 exit:
212 return error;
213 }
214
Compare(const Timestamp * aCompare)215 int DatasetLocal::Compare(const Timestamp *aCompare)
216 {
217 return (aCompare == nullptr) ? (!mTimestampPresent ? 0 : -1)
218 : (!mTimestampPresent ? 1 : mTimestamp.Compare(*aCompare));
219 }
220
221 } // namespace MeshCoP
222 } // namespace ot
223