Merge pull request #512 from didishe90/persistSerDir
Persistent service directory
diff --git a/src/lib/core/WeaveConfig.h b/src/lib/core/WeaveConfig.h
index 3ae8835..52540bc 100644
--- a/src/lib/core/WeaveConfig.h
+++ b/src/lib/core/WeaveConfig.h
@@ -1905,6 +1905,23 @@
#endif // WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
/**
+ * @def WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ *
+ * @brief
+ * If set to (1), persistent service directory is enabled.
+ * Default value is (0) or disabled.
+ *
+ * @note
+ * Enabling this feature flag persists the service directory
+ * cache retrieved from the directory server and use it to
+ * populate the in-memory cache at initialization time.
+ *
+ */
+#ifndef WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+#define WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY 0
+#endif // WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
+/**
* @def WEAVE_CONFIG_SERVICE_DIR_CONNECT_TIMEOUT_MSECS
*
* @brief
diff --git a/src/lib/profiles/service-directory/ServiceDirectory.cpp b/src/lib/profiles/service-directory/ServiceDirectory.cpp
index 86e6eb6..ecfba9c 100644
--- a/src/lib/profiles/service-directory/ServiceDirectory.cpp
+++ b/src/lib/profiles/service-directory/ServiceDirectory.cpp
@@ -358,6 +358,30 @@
clearCacheState();
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
+ if (Platform::IsPersistentServiceDirPresent(kPersistedServiceDirVersion))
+ {
+ WeaveLogProgress(ServiceDirectory, "Persistent service directory exists");
+
+ err = loadPersistentServiceDirIntoCache();
+
+ if (err != WEAVE_NO_ERROR)
+ {
+ Platform::ClearPersistentServiceDir();
+ WeaveLogProgress(ServiceDirectory, "Restore error, persistent service directory cleared");
+
+ }
+ else
+ {
+ mCacheState = kServiceMgrState_Resolved;
+ WeaveLogProgress(ServiceDirectory, "Persistent service directory successfully restored");
+ }
+
+ }
+
+#endif // WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
finalizeConnectRequests();
exit:
@@ -428,6 +452,10 @@
* service config and install it.
*/
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif // WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
err = mAccessor(mCache.base, mCache.length);
SuccessOrExit(err);
@@ -903,6 +931,11 @@
if (mCacheState > kServiceMgrState_Resolving)
{
+
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif //WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
cleanupExchangeContext();
mCacheState = kServiceMgrState_Resolving;
@@ -949,6 +982,10 @@
clearWorkingState();
clearCacheState();
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif //WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
finalizeConnectRequests();
}
@@ -1114,6 +1151,10 @@
clearWorkingState();
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif
+
mCacheState = kServiceMgrState_Initial;
transactionsReportStatus(report);
@@ -1133,79 +1174,19 @@
VerifyOrExit(aMsgType == kMsgType_ServiceEndpointResponse, err = WEAVE_ERROR_INVALID_MESSAGE_TYPE);
VerifyOrExit(mCacheState == kServiceMgrState_Waiting, err = WEAVE_ERROR_INCORRECT_STATE);
- /*
- * this block unpacks the service directory message.
- */
+ err = unpackPacketBuffer(aMsg, true, &redir);
+ SuccessOrExit(err);
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ if (!redir)
{
- MessageIterator i(aMsg);
-
- uint16_t msgLen = aMsg->DataLength();
- uint8_t dirCtrl;
- uint8_t *writePtr;
- uint8_t dirLen;
- bool suffixesPresent;
- uint8_t aLength;
- bool timePresent = false;
-
- err = i.readByte(&dirCtrl);
+ WeaveLogProgress(ServiceDirectory, "Persisting service directory response");
+ err = Platform::StorePersistentServiceDir(aMsg->Start(),
+ aMsg->DataLength(),
+ kPersistedServiceDirVersion);
SuccessOrExit(err);
-
- dirLen = dirCtrl & kMask_DirectoryLen;
- redir = (dirCtrl & kMask_Redirect) != 0;
- suffixesPresent = (dirCtrl & kMask_SuffixTablePresent) != 0;
- timePresent = (dirCtrl & kMask_TimeFieldsPresent) != 0;
-
- if (((msgLen > mCache.length) && !timePresent) || (msgLen > (mCache.length + (sizeof(uint64_t) + sizeof(uint32_t)))))
- {
- WeaveLogProgress(ServiceDirectory, "message length error: %d m.len:%d", msgLen, mCache.length);
-
- err = WEAVE_ERROR_MESSAGE_TOO_LONG;
- }
- SuccessOrExit(err);
-
- /*
- * here we have directory information beyond the root directory but
- * we're not done yet.
- */
-
- mDirectory.length = dirLen;
- writePtr = mDirectory.base = mCache.base;
-
- err = cacheDirectory(i, mDirectory.length, writePtr);
- SuccessOrExit(err);
-
- if (suffixesPresent)
- {
- WeaveLogProgress(ServiceDirectory, "suffixesPresent");
-
- err = i.readByte(&aLength);
- SuccessOrExit(err);
-
- mSuffixTable.length = aLength;
- writePtr += 1;
- mSuffixTable.base = writePtr;
-
- mDirAndSuffTableSize++;
-
- err = cacheSuffixes(i, mSuffixTable.length, writePtr);
- SuccessOrExit(err);
- }
-
- else
- {
- mSuffixTable.length = 0;
- mSuffixTable.base = NULL;
- }
-
- if (timePresent)
- {
- WeaveLogProgress(ServiceDirectory, "timePresent");
-
- err = handleTimeInfo(i);
- SuccessOrExit(err);
- }
}
+#endif // WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
/*
* Release the received message buffer so that any code we
@@ -1576,6 +1557,128 @@
return err;
}
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+/**
+ * @brief
+ * This method loads the persistent service directory to cache.
+ */
+WEAVE_ERROR WeaveServiceManager::loadPersistentServiceDirIntoCache()
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ PacketBuffer* msgBuf = NULL;
+ uint16_t len;
+
+ msgBuf = PacketBuffer::New();
+ err = Platform::LoadPersistentServiceDir(msgBuf->Start(),
+ msgBuf->AvailableDataLength(),
+ len,
+ kPersistedServiceDirVersion);
+ SuccessOrExit(err);
+
+ msgBuf->SetDataLength(len);
+
+ err = unpackPacketBuffer(msgBuf, false);
+ SuccessOrExit(err);
+
+exit:
+
+ if (msgBuf != NULL)
+ PacketBuffer::Free(msgBuf);
+
+ return err;
+}
+#endif //WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
+
+/**
+ * @brief
+ * This method unpacks the packetbuffer to cache.
+ *
+ * @param [in] aMsg The content of this message.
+ * @param [in] useTimeInfo If need to handle time info
+ * @param [in] redir Return whether need to redirect
+ */
+WEAVE_ERROR WeaveServiceManager::unpackPacketBuffer(PacketBuffer *aMsg, bool useTimeInfo, bool *redir)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ WeaveLogProgress(ServiceDirectory, "Unpacks the packetBuffer to cache");
+
+ {
+ MessageIterator i(aMsg);
+
+ uint16_t msgLen = aMsg->DataLength();
+ uint8_t dirCtrl;
+ uint8_t *writePtr;
+ uint8_t dirLen;
+ bool suffixesPresent;
+ uint8_t aLength;
+ bool timePresent = false;
+
+ err = i.readByte(&dirCtrl);
+ SuccessOrExit(err);
+ dirLen = dirCtrl & kMask_DirectoryLen;
+ if (redir != NULL)
+ {
+ *redir = (dirCtrl & kMask_Redirect) != 0;
+ }
+ suffixesPresent = (dirCtrl & kMask_SuffixTablePresent) != 0;
+ timePresent = (dirCtrl & kMask_TimeFieldsPresent) != 0;
+
+ if (((msgLen > mCache.length) && !timePresent) || (msgLen > (mCache.length + (sizeof(uint64_t) + sizeof(uint32_t)))))
+ {
+ WeaveLogProgress(ServiceDirectory, "message length error: %d m.len:%d", msgLen, mCache.length);
+
+ err = WEAVE_ERROR_MESSAGE_TOO_LONG;
+ }
+ SuccessOrExit(err);
+
+ /*
+ * here we have directory information beyond the root directory but
+ * we're not done yet.
+ */
+
+ mDirectory.length = dirLen;
+ writePtr = mDirectory.base = mCache.base;
+
+ err = cacheDirectory(i, mDirectory.length, writePtr);
+ SuccessOrExit(err);
+
+ if (suffixesPresent)
+ {
+ WeaveLogProgress(ServiceDirectory, "suffixesPresent");
+
+ err = i.readByte(&aLength);
+ SuccessOrExit(err);
+
+ mSuffixTable.length = aLength;
+ writePtr += 1;
+ mSuffixTable.base = writePtr;
+
+ mDirAndSuffTableSize++;
+
+ err = cacheSuffixes(i, mSuffixTable.length, writePtr);
+ SuccessOrExit(err);
+ }
+
+ else
+ {
+ mSuffixTable.length = 0;
+ mSuffixTable.base = NULL;
+ }
+
+ if (timePresent && useTimeInfo)
+ {
+ WeaveLogProgress(ServiceDirectory, "timePresent");
+
+ err = handleTimeInfo(i);
+ SuccessOrExit(err);
+ }
+ }
+
+exit:
+
+ return err;
+}
/**
* @brief
@@ -1763,6 +1866,10 @@
clearWorkingState();
clearCacheState();
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif
+
transactionsErrorOut(aError);
}
@@ -1922,6 +2029,10 @@
{
clearWorkingState();
clearCacheState();
+
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ Platform::ClearPersistentServiceDir();
+#endif
}
}
#endif //WEAVE_CONFIG_ENABLE_SERVICE_DIRECTORY
diff --git a/src/lib/profiles/service-directory/ServiceDirectory.h b/src/lib/profiles/service-directory/ServiceDirectory.h
index 479101b..582c9c1 100644
--- a/src/lib/profiles/service-directory/ServiceDirectory.h
+++ b/src/lib/profiles/service-directory/ServiceDirectory.h
@@ -133,6 +133,27 @@
kServiceMgrState_Resolved = 3
};
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+enum
+{
+ /** Version number associated with persisted service directory data
+ *
+ * By convention, the version number of persisted service directory
+ * data is the same as the message type number of the SD response
+ * message. This reflects the fact that the persisted data is an
+ * exact copy of the payload of that message.
+ */
+ kPersistedServiceDirVersion = kMsgType_ServiceEndpointResponse
+};
+
+namespace Platform {
+ extern WEAVE_ERROR LoadPersistentServiceDir(uint8_t *buf, uint16_t bufsize, uint16_t &len, uint8_t version);
+ extern WEAVE_ERROR StorePersistentServiceDir(uint8_t *buf, uint16_t len, uint8_t version);
+ extern WEAVE_ERROR ClearPersistentServiceDir();
+ extern bool IsPersistentServiceDirPresent(uint8_t version);
+}
+#endif // WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+
#define kServiceEndpoint_Directory (0x18B4300200000001ull) ///< Directory profile endpoint
#define kServiceEndpoint_SoftwareUpdate (0x18B4300200000002ull) ///< Software update profile endpoint
#define kServiceEndpoint_Data_Management (0x18B4300200000003ull) ///< Core Weave data management protocol endpoint
@@ -411,6 +432,10 @@
const uint32_t aConnectTimeoutMsecs = 0,
const InterfaceId aConnectIntf = INET_NULL_INTERFACEID);
+#if WEAVE_CONFIG_PERSIST_SERVICE_DIRECTORY
+ WEAVE_ERROR loadPersistentServiceDirIntoCache();
+#endif
+ WEAVE_ERROR unpackPacketBuffer(PacketBuffer *aMsg, bool useTimePresent, bool *redir = NULL);
WEAVE_ERROR cacheDirectory(MessageIterator &, uint8_t, uint8_t *&);
WEAVE_ERROR cacheSuffixes(MessageIterator &, uint8_t, uint8_t *&);
WEAVE_ERROR calculateEntryLength(uint8_t *entryStart, uint8_t entryCtrlByte, uint16_t *entryLen);