diff --git a/Makefile.am b/Makefile.am index 46fdfdc41..c39282beb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,6 +79,10 @@ PRETTY_SUBDIRS = \ tools \ $(NULL) +# Ignore the pseudo flash files on Posix platform during diskcheck +distcleancheck_listfiles = \ + $(AM_V_at)find . -type f -name "*flash" + # # Package version files: # diff --git a/etc/visual-studio/libopenthread-windows.vcxproj b/etc/visual-studio/libopenthread-windows.vcxproj index f53a7bbce..15c9487db 100644 --- a/etc/visual-studio/libopenthread-windows.vcxproj +++ b/etc/visual-studio/libopenthread-windows.vcxproj @@ -20,6 +20,7 @@ + @@ -171,4 +172,4 @@ - \ No newline at end of file + diff --git a/etc/visual-studio/libopenthread-windows.vcxproj.filters b/etc/visual-studio/libopenthread-windows.vcxproj.filters index bc34f58f9..68f59f463 100644 --- a/etc/visual-studio/libopenthread-windows.vcxproj.filters +++ b/etc/visual-studio/libopenthread-windows.vcxproj.filters @@ -13,6 +13,9 @@ Source Files + + Source Files + Source Files @@ -40,4 +43,4 @@ Header Files - \ No newline at end of file + diff --git a/examples/platforms/cc2538/platform.c b/examples/platforms/cc2538/platform.c index 72bcea2b2..15a9ca23d 100644 --- a/examples/platforms/cc2538/platform.c +++ b/examples/platforms/cc2538/platform.c @@ -33,6 +33,7 @@ */ #include +#include #include "platform-cc2538.h" otInstance *sInstance; @@ -43,6 +44,7 @@ void PlatformInit(int argc, char *argv[]) cc2538RandomInit(); cc2538RadioInit(); otPlatUartEnable(); + otPlatFlashInit(); (void)argc; (void)argv; diff --git a/examples/platforms/posix/flash-windows-stubs.c b/examples/platforms/posix/flash-windows-stubs.c new file mode 100644 index 000000000..b174fefe9 --- /dev/null +++ b/examples/platforms/posix/flash-windows-stubs.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "platform-posix.h" + +ThreadError otPlatFlashInit(void) +{ + return kThreadError_NotImplemented; +} + +uint32_t otPlatFlashGetSize(void) +{ + return 0; +} + +ThreadError otPlatFlashErasePage(uint32_t aAddress) +{ + return kThreadError_NotImplemented; +} + +ThreadError otPlatFlashStatusWait(uint32_t aTimeout) +{ + return kThreadError_None; +} + +uint32_t otPlatFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + return 0; +} + +uint32_t otPlatFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize) +{ + return 0; +} diff --git a/examples/platforms/posix/flash.c b/examples/platforms/posix/flash.c index 52aefeddb..9aa853007 100644 --- a/examples/platforms/posix/flash.c +++ b/examples/platforms/posix/flash.c @@ -53,9 +53,12 @@ enum ThreadError otPlatFlashInit(void) { ThreadError error = kThreadError_None; - char fileName[16]; + char fileName[20]; struct stat st; bool create = false; + struct timeval tv; + + gettimeofday(&tv, NULL); memset(&st, 0, sizeof(st)); @@ -64,7 +67,7 @@ ThreadError otPlatFlashInit(void) mkdir("tmp", 0777); } - snprintf(fileName, sizeof(fileName), "tmp/%d.flash", NODE_ID); + snprintf(fileName, sizeof(fileName), "tmp/%d_%d.flash", NODE_ID, (uint32_t)tv.tv_usec); if (access(fileName, 0)) { diff --git a/examples/platforms/posix/platform.c b/examples/platforms/posix/platform.c index e83ee60bc..ee2f7d018 100644 --- a/examples/platforms/posix/platform.c +++ b/examples/platforms/posix/platform.c @@ -43,6 +43,7 @@ #include #include +#include #include uint32_t NODE_ID = 1; @@ -68,6 +69,7 @@ void PlatformInit(int argc, char *argv[]) platformAlarmInit(); platformRadioInit(); platformRandomInit(); + otPlatFlashInit(); } bool UartInitialized = false; diff --git a/include/platform/settings.h b/include/platform/settings.h index 1da0a0a51..c399534cd 100644 --- a/include/platform/settings.h +++ b/include/platform/settings.h @@ -36,6 +36,7 @@ #define OT_PLATFORM_SETTINGS_H 1 #include +#include #ifdef __cplusplus extern "C" { diff --git a/src/core/Makefile.am b/src/core/Makefile.am index e35cd1d59..6f0492692 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -126,6 +126,7 @@ noinst_HEADERS = \ common/logging.hpp \ common/message.hpp \ common/new.hpp \ + common/settings.hpp \ common/tasklet.hpp \ common/timer.hpp \ common/trickle_timer.hpp \ diff --git a/src/core/common/settings.hpp b/src/core/common/settings.hpp new file mode 100644 index 000000000..5636580cf --- /dev/null +++ b/src/core/common/settings.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes functions for debugging. + */ + +#ifndef SETTINGS_HPP_ +#define SETTINGS_HPP_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This enumeration defines the keys of settings + * + */ +enum +{ + kKeyActiveDataset = 0x0001, + kKeyPendingDataset = 0x0002, +}; + +#ifdef __cplusplus +}; +#endif + +#endif // SETTINGS_HPP_ diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 5a9092b2c..dfde5fbf2 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -1019,6 +1020,13 @@ otInstance *otInstanceInit(void *aInstanceBuffer, size_t *aInstanceBufferSize) // Construct the context aInstance = new(aInstanceBuffer)otInstance(); + // restore datasets + otPlatSettingsInit(aInstance); + + aInstance->mThreadNetif.GetActiveDataset().Restore(); + + aInstance->mThreadNetif.GetPendingDataset().Restore(); + exit: otLogFuncExit(); @@ -1038,6 +1046,13 @@ otInstance *otInstanceInit() // Construct the context sInstance = new(&sInstanceRaw)otInstance(); + // restore datasets + otPlatSettingsInit(sInstance); + + sInstance->mThreadNetif.GetActiveDataset().Restore(); + + sInstance->mThreadNetif.GetPendingDataset().Restore(); + exit: otLogFuncExit(); diff --git a/src/core/thread/meshcop_dataset.cpp b/src/core/thread/meshcop_dataset.cpp index 9591501b2..d629c70f9 100644 --- a/src/core/thread/meshcop_dataset.cpp +++ b/src/core/thread/meshcop_dataset.cpp @@ -35,21 +35,29 @@ #include #include +#include +#include #include #include namespace Thread { namespace MeshCoP { -Dataset::Dataset(const Tlv::Type aType) : +Dataset::Dataset(otInstance *aInstance, const Tlv::Type aType) : mType(aType), - mLength(0) + mLength(0), + mInstance(aInstance) { } -void Dataset::Clear(void) +void Dataset::Clear(bool isLocal) { mLength = 0; + + if (isLocal) + { + otPlatSettingsDelete(mInstance, mType == Tlv::kActiveTimestamp ? kKeyActiveDataset : kKeyPendingDataset, -1); + } } Tlv *Dataset::Get(Tlv::Type aType) @@ -109,8 +117,6 @@ void Dataset::Get(otOperationalDataset &aDataset) const const ActiveTimestampTlv *tlv = static_cast(cur); aDataset.mActiveTimestamp = tlv->GetSeconds(); aDataset.mIsActiveTimestampSet = true; - - GetTimestamp(); break; } @@ -432,6 +438,18 @@ int Dataset::Compare(const Dataset &aCompare) const return rval; } +ThreadError Dataset::Restore(void) +{ + return otPlatSettingsGet(mInstance, mType == Tlv::kActiveTimestamp ? kKeyActiveDataset : kKeyPendingDataset, 0, mTlvs, + reinterpret_cast(&mLength)); +} + +ThreadError Dataset::Store(void) +{ + return otPlatSettingsSet(mInstance, mType == Tlv::kActiveTimestamp ? kKeyActiveDataset : kKeyPendingDataset, mTlvs, + mLength); +} + ThreadError Dataset::Set(const Tlv &aTlv) { ThreadError error = kThreadError_None; diff --git a/src/core/thread/meshcop_dataset.hpp b/src/core/thread/meshcop_dataset.hpp index 07872257e..8108f026a 100644 --- a/src/core/thread/meshcop_dataset.hpp +++ b/src/core/thread/meshcop_dataset.hpp @@ -56,13 +56,15 @@ public: * @param[in] aType The type of the dataset, active or pending. * */ - Dataset(const Tlv::Type aType); + Dataset(otInstance *aInstance, const Tlv::Type aType); /** * This method clears the Dataset. * + * @param[in] isLocal TRUE to delete the local dataset from non-volatile memory, FALSE not. + * */ - void Clear(void); + void Clear(bool isLocal); /** * This method returns a pointer to the TLV. @@ -128,6 +130,24 @@ public: */ int Compare(const Dataset &aCompare) const; + /** + * This method restores dataset from non-volatile memory. + * + * @retval kThreadError_None Successfully restore the dataset. + * @retval kThreadError_NotFound There is no corresponding dataset stored in non-volatile memory. + * + */ + ThreadError Restore(void); + + /** + * This method stores dataset into non-volatile memory. + * + * @retval kThreadError_None Successfully store the dataset. + * @retval kThreadError_NoBufs Could not store the dataset due to insufficient memory space. + * + */ + ThreadError Store(void); + /** * This method sets a TLV in the Dataset. * @@ -153,6 +173,7 @@ private: Tlv::Type mType; ///< Active or Pending uint8_t mTlvs[kMaxSize]; ///< The Dataset buffer uint8_t mLength; ///< The number of valid bytes in @var mTlvs + otInstance *mInstance; ///< The pointer to an OpenThread instance }; } // namespace MeshCoP diff --git a/src/core/thread/meshcop_dataset_manager.cpp b/src/core/thread/meshcop_dataset_manager.cpp index 27efcd9dc..c7f772812 100644 --- a/src/core/thread/meshcop_dataset_manager.cpp +++ b/src/core/thread/meshcop_dataset_manager.cpp @@ -57,8 +57,8 @@ namespace MeshCoP { DatasetManager::DatasetManager(ThreadNetif &aThreadNetif, const Tlv::Type aType, const char *aUriSet, const char *aUriGet): - mLocal(aType), - mNetwork(aType), + mLocal(aThreadNetif.GetInstance(), aType), + mNetwork(aThreadNetif.GetInstance(), aType), mCoapServer(aThreadNetif.GetCoapServer()), mMle(aThreadNetif.GetMle()), mNetif(aThreadNetif), @@ -75,6 +75,7 @@ ThreadError DatasetManager::Set(const otOperationalDataset &aDataset, uint8_t &a ThreadError error = kThreadError_None; SuccessOrExit(error = mLocal.Set(aDataset)); + mLocal.Store(); aFlags = kFlagLocalUpdated; switch (mMle.GetDeviceState()) @@ -101,7 +102,12 @@ exit: ThreadError DatasetManager::Clear(uint8_t &aFlags) { - mNetwork.Clear(); + if (mLocal.Compare(mNetwork) == 0) + { + mLocal.Clear(true); + } + + mNetwork.Clear(false); HandleNetworkUpdate(aFlags); return kThreadError_None; } @@ -135,6 +141,7 @@ void DatasetManager::HandleNetworkUpdate(uint8_t &aFlags) if (compare > 0) { mLocal = mNetwork; + mLocal.Store(); aFlags |= kFlagLocalUpdated; } else if (compare < 0) @@ -352,6 +359,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const offset += sizeof(Tlv) + data.tlv.GetLength(); } + mLocal.Store(); mNetwork = mLocal; mNetworkDataLeader.IncrementVersion(); mNetworkDataLeader.IncrementStableVersion(); @@ -644,8 +652,59 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif): { } +void ActiveDataset::Restore(void) +{ + mLocal.Restore(); + ApplyConfiguration(); +} + void ActiveDataset::StartLeader(void) { + if (mLocal.GetTimestamp() == NULL) + { + otOperationalDataset dataset; + + memset(&dataset, 0, sizeof(dataset)); + + // Active Timestamp + dataset.mActiveTimestamp = 0; + dataset.mIsActiveTimestampSet = true; + + // Channel + dataset.mChannel = mNetif.GetMac().GetChannel(); + dataset.mIsChannelSet = true; + + // Extended PAN ID + memcpy(dataset.mExtendedPanId.m8, mNetif.GetMac().GetExtendedPanId(), sizeof(dataset.mExtendedPanId)); + dataset.mIsExtendedPanIdSet = true; + + // Mesh-Local Prefix + memcpy(dataset.mMeshLocalPrefix.m8, mNetif.GetMle().GetMeshLocalPrefix(), sizeof(dataset.mMeshLocalPrefix)); + dataset.mIsMeshLocalPrefixSet = true; + + // Master Key + const uint8_t *key; + uint8_t keyLength; + + key = mNetif.GetKeyManager().GetMasterKey(&keyLength); + memcpy(dataset.mMasterKey.m8, key, keyLength); + dataset.mIsMasterKeySet = true; + + // Network Name + const char *name; + + name = mNetif.GetMac().GetNetworkName(); + memcpy(dataset.mNetworkName.m8, name, strlen(name)); + dataset.mIsNetworkNameSet = true; + + // Pan ID + dataset.mPanId = mNetif.GetMac().GetPanId(); + dataset.mIsPanIdSet = true; + + mLocal.Set(dataset); + } + + mLocal.Store(); mNetwork = mLocal; mCoapServer.AddResource(mResourceGet); mCoapServer.AddResource(mResourceSet); @@ -812,9 +871,16 @@ PendingDataset::PendingDataset(ThreadNetif &aThreadNetif): { } +void PendingDataset::Restore(void) +{ + mLocal.Restore(); + ResetDelayTimer(kFlagLocalUpdated); +} + void PendingDataset::StartLeader(void) { UpdateDelayTimer(mLocal, mLocalTime); + mLocal.Store(); mNetwork = mLocal; ResetDelayTimer(kFlagNetworkUpdated); @@ -972,6 +1038,8 @@ void PendingDataset::HandleTimer(void) assert(delayTimer != NULL && delayTimer->GetDelayTimer() == 0); mNetif.GetActiveDataset().Set(mNetwork); + + Clear(); } } // namespace MeshCoP diff --git a/src/core/thread/meshcop_dataset_manager.hpp b/src/core/thread/meshcop_dataset_manager.hpp index 9362a5bf1..9284b6298 100644 --- a/src/core/thread/meshcop_dataset_manager.hpp +++ b/src/core/thread/meshcop_dataset_manager.hpp @@ -115,6 +115,8 @@ class ActiveDataset: public DatasetManager public: ActiveDataset(ThreadNetif &aThreadNetif); + void Restore(void); + void StartLeader(void); void StopLeader(void); @@ -147,6 +149,8 @@ class PendingDataset: public DatasetManager public: PendingDataset(ThreadNetif &aThreadNetif); + void Restore(void); + void StartLeader(void); void StopLeader(void);