Add wdm update server support
-- add wdm update request processing and update response generation
mechanism
-- add TraitUpdatableDataSource
diff --git a/src/lib/core/WeaveDMConfig.h b/src/lib/core/WeaveDMConfig.h
index 742d7f4..66b1814 100644
--- a/src/lib/core/WeaveDMConfig.h
+++ b/src/lib/core/WeaveDMConfig.h
@@ -294,6 +294,18 @@
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
/**
+ * @def WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ *
+ * @brief
+ * Enable (1) or disable (0) sending/handling update response
+ * in Weave Data Management Next profile.
+ *
+ */
+#ifndef WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+#define WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT 1
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
+/**
* @def WDM_PUBLISHER_ENABLE_VIEW
*
* @brief
@@ -573,6 +585,29 @@
#endif /* WDM_MIN_UPDATE_SIZE */
/**
+ * @def WDM_MAX_UPDATE_RESPONSE_SIZE
+ *
+ * @brief
+ * Specify the maximum size (in bytes) of a WDM update response
+ * payload. Note that the WDM update payload is also limited
+ * by the size of `nl::Weave::System::PacketBuffer`
+ */
+#ifndef WDM_MAX_UPDATE_RESPONSE_SIZE
+#define WDM_MAX_UPDATE_RESPONSE_SIZE 2048
+#endif /* WDM_MAX_UPDATE_SIZE */
+
+/**
+ * @def WDM_MIN_UPDATE_RESPONSE_SIZE
+ *
+ * @brief
+ * Specify the minimum size (in bytes) of a WDM update response
+ * payload.
+ */
+#ifndef WDM_MIN_UPDATE_RESPONSE_SIZE
+#define WDM_MIN_UPDATE_RESPONSE_SIZE 1024
+#endif /* WDM_MIN_UPDATE_SIZE */
+
+/**
* @def TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
*
* @brief
diff --git a/src/lib/profiles/common/WeaveMessage.cpp b/src/lib/profiles/common/WeaveMessage.cpp
index 00ddb8a..117669a 100644
--- a/src/lib/profiles/common/WeaveMessage.cpp
+++ b/src/lib/profiles/common/WeaveMessage.cpp
@@ -851,6 +851,7 @@
* @brief Pack a ReferencedTLVData object using a TLVWriter.
*
* @param [in] i An iterator over the message being packed.
+ * @param [in] maxLen The maximum number of bytes that should be written to the output buffer.
*
* @return a WEAVE_ERROR - WEAVE_NO_ERROR if all goes well, otherwise
* an error reflecting an inability of the writer to write the
@@ -858,7 +859,7 @@
* return an error and so fails silently.
*/
-WEAVE_ERROR ReferencedTLVData::pack(MessageIterator &i)
+WEAVE_ERROR ReferencedTLVData::pack(MessageIterator &i, uint32_t maxLen)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
System::PacketBuffer *theBuffer = i.GetBuffer();
@@ -868,7 +869,7 @@
if (theWriteCallback != NULL)
{
theData = i.thePoint;
- writer.Init(theBuffer);
+ writer.Init(theBuffer, maxLen);
theWriteCallback(writer, theAppState);
theLength = theBuffer->DataLength() - oldDataLength;
i.thePoint += theLength;
diff --git a/src/lib/profiles/common/WeaveMessage.h b/src/lib/profiles/common/WeaveMessage.h
index ca7d493..7589970 100644
--- a/src/lib/profiles/common/WeaveMessage.h
+++ b/src/lib/profiles/common/WeaveMessage.h
@@ -289,7 +289,7 @@
return pack(i);
};
- WEAVE_ERROR pack(MessageIterator&i);
+ WEAVE_ERROR pack(MessageIterator&i, uint32_t maxLen = 0xFFFFFFFFUL);
/**
* Return the data length assuming that the object has been packed
diff --git a/src/lib/profiles/data-management/Current/SubscriptionEngine.cpp b/src/lib/profiles/data-management/Current/SubscriptionEngine.cpp
index b57d9a2..c0468a4 100644
--- a/src/lib/profiles/data-management/Current/SubscriptionEngine.cpp
+++ b/src/lib/profiles/data-management/Current/SubscriptionEngine.cpp
@@ -32,11 +32,17 @@
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Profiles/data-management/DataManagement.h>
#include <Weave/Profiles/data-management/NotificationEngine.h>
+#include <Weave/Profiles/status-report/StatusReportProfile.h>
#include <Weave/Profiles/time/WeaveTime.h>
#include <Weave/Support/crypto/WeaveCrypto.h>
#include <Weave/Support/WeaveFaultInjection.h>
#include <SystemLayer/SystemStats.h>
+#ifndef WEAVE_WDM_ALIGNED_TYPE
+#define WEAVE_WDM_ALIGNED_TYPE(address, type) \
+ reinterpret_cast<type *> WEAVE_SYSTEM_ALIGN_SIZE((size_t)(address), 4)
+#endif
+
namespace nl {
namespace Weave {
namespace Profiles {
@@ -229,13 +235,12 @@
WEAVE_ERROR SubscriptionEngine::NewClient(SubscriptionClient ** const appClient, Binding * const apBinding, void * const apAppState,
SubscriptionClient::EventCallback const aEventCallback,
const TraitCatalogBase<TraitDataSink> * const apCatalog,
- const uint32_t aInactivityTimeoutDuringSubscribingMsec,
- IWeaveWDMMutex * aUpdateMutex)
+ const uint32_t aInactivityTimeoutDuringSubscribingMsec, IWeaveWDMMutex * aUpdateMutex)
{
WEAVE_ERROR err = WEAVE_ERROR_NO_MEMORY;
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
- uint32_t maxSize = WDM_MAX_UPDATE_SIZE;
+ uint32_t maxSize = WDM_MAX_UPDATE_SIZE;
#else
VerifyOrExit(aUpdateMutex == NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
@@ -249,9 +254,9 @@
if (SubscriptionClient::kState_Free == mClients[i].mCurrentState)
{
*appClient = &mClients[i];
- err = (*appClient)->Init(apBinding, apAppState, aEventCallback, apCatalog,
- aInactivityTimeoutDuringSubscribingMsec,
- aUpdateMutex);
+ err =
+ (*appClient)
+ ->Init(apBinding, apAppState, aEventCallback, apCatalog, aInactivityTimeoutDuringSubscribingMsec, aUpdateMutex);
if (WEAVE_NO_ERROR != err)
{
@@ -360,6 +365,17 @@
func = OnSubscriptionlessNotification;
break;
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ case kMsgType_UpdateRequest:
+ func = OnUpdateRequest;
+ break;
+
+ case kMsgType_PartialUpdateRequest:
+ WeaveLogDetail(DataManagement, "PartialUpdateRequest not supported yet for update server");
+ break;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
default:
break;
}
@@ -463,8 +479,7 @@
}
WEAVE_ERROR SubscriptionEngine::ProcessDataList(nl::Weave::TLV::TLVReader & aReader,
- const TraitCatalogBase<TraitDataSink> * aCatalog,
- bool & aOutIsPartialChange,
+ const TraitCatalogBase<TraitDataSink> * aCatalog, bool & aOutIsPartialChange,
TraitDataHandle & aOutTraitDataHandle,
IDataElementAccessControlDelegate & acDelegate)
{
@@ -536,7 +551,7 @@
#endif
SuccessOrExit(err);
- traitPath.mTraitDataHandle = handle;
+ traitPath.mTraitDataHandle = handle;
traitPath.mPropertyPathHandle = pathHandle;
err = acDelegate.DataElementAccessCheck(traitPath, *aCatalog);
@@ -592,22 +607,20 @@
exit:
return err;
-
}
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
-WEAVE_ERROR SubscriptionEngine::RegisterForSubscriptionlessNotifications(
- const TraitCatalogBase<TraitDataSink> * const apCatalog)
+WEAVE_ERROR SubscriptionEngine::RegisterForSubscriptionlessNotifications(const TraitCatalogBase<TraitDataSink> * const apCatalog)
{
- WEAVE_ERROR err = WEAVE_NO_ERROR;
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
mSubscriptionlessNotifySinkCatalog = apCatalog;
return err;
}
void SubscriptionEngine::OnSubscriptionlessNotification(nl::Weave::ExchangeContext * aEC, const nl::Inet::IPPacketInfo * aPktInfo,
- const nl::Weave::WeaveMessageInfo * aMsgInfo, uint32_t aProfileId, uint8_t aMsgType,
- PacketBuffer * aPayload)
+ const nl::Weave::WeaveMessageInfo * aMsgInfo, uint32_t aProfileId,
+ uint8_t aMsgType, PacketBuffer * aPayload)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
NotificationRequest::Parser notify;
@@ -624,8 +637,8 @@
inParam.Clear();
outParam.Clear();
- inParam.mIncomingSubscriptionlessNotification.processingError = err;
- inParam.mIncomingSubscriptionlessNotification.mMsgInfo = aMsgInfo;
+ inParam.mIncomingSubscriptionlessNotification.processingError = err;
+ inParam.mIncomingSubscriptionlessNotification.mMsgInfo = aMsgInfo;
outParam.mIncomingSubscriptionlessNotification.mShouldContinueProcessing = true;
if (pEngine->mEventCallback)
@@ -679,8 +692,7 @@
SubscriptionlessNotifyDataElementAccessControlDelegate acDelegate(aMsgInfo);
IDataElementAccessControlDelegate & acDelegateRef = acDelegate;
- err = ProcessDataList(reader, pEngine->mSubscriptionlessNotifySinkCatalog,
- isPartialChange, traitDataHandle, acDelegateRef);
+ err = ProcessDataList(reader, pEngine->mSubscriptionlessNotifySinkCatalog, isPartialChange, traitDataHandle, acDelegateRef);
SuccessOrExit(err);
if (isPartialChange)
@@ -711,16 +723,17 @@
outParam.Clear();
inParam.mIncomingSubscriptionlessNotification.processingError = err;
- inParam.mIncomingSubscriptionlessNotification.mMsgInfo = aMsgInfo;
+ inParam.mIncomingSubscriptionlessNotification.mMsgInfo = aMsgInfo;
// Subscriptionless Notification completion event indication.
pEngine->mEventCallback(pEngine->mAppState, kEvent_SubscriptionlessNotificationProcessingComplete, inParam, outParam);
}
}
-WEAVE_ERROR SubscriptionEngine::SubscriptionlessNotifyDataElementAccessControlDelegate::DataElementAccessCheck(const TraitPath & aTraitPath, const TraitCatalogBase<TraitDataSink> & aCatalog)
+WEAVE_ERROR SubscriptionEngine::SubscriptionlessNotifyDataElementAccessControlDelegate::DataElementAccessCheck(
+ const TraitPath & aTraitPath, const TraitCatalogBase<TraitDataSink> & aCatalog)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
- TraitDataSink *dataSink;
+ TraitDataSink * dataSink;
InEventParam inParam;
OutEventParam outParam;
SubscriptionEngine * pEngine = SubscriptionEngine::GetInstance();
@@ -734,22 +747,21 @@
if (dataSink->AcceptsSubscriptionlessNotifications())
{
outParam.mDataElementAccessControlForNotification.mRejectNotification = false;
- outParam.mDataElementAccessControlForNotification.mReason = WEAVE_NO_ERROR;
+ outParam.mDataElementAccessControlForNotification.mReason = WEAVE_NO_ERROR;
}
else
{
outParam.mDataElementAccessControlForNotification.mRejectNotification = true;
- outParam.mDataElementAccessControlForNotification.mReason = WEAVE_ERROR_ACCESS_DENIED;
+ outParam.mDataElementAccessControlForNotification.mReason = WEAVE_ERROR_ACCESS_DENIED;
}
- inParam.mDataElementAccessControlForNotification.mPath = &aTraitPath;
+ inParam.mDataElementAccessControlForNotification.mPath = &aTraitPath;
inParam.mDataElementAccessControlForNotification.mCatalog = &aCatalog;
inParam.mDataElementAccessControlForNotification.mMsgInfo = mMsgInfo;
if (NULL != pEngine->mEventCallback)
{
- pEngine->mEventCallback(pEngine->mAppState, kEvent_DataElementAccessControlCheck,
- inParam, outParam);
+ pEngine->mEventCallback(pEngine->mAppState, kEvent_DataElementAccessControlCheck, inParam, outParam);
}
// If application rejects it then deny access, else set reason to whatever
@@ -765,7 +777,7 @@
exit:
- return err;
+ return err;
}
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
@@ -1454,7 +1466,7 @@
statusReportCode = nl::Weave::Profiles::DataManagement::kStatus_NotTimeSyncedYet;
ExitNow();
}
- else if (now_usec >= (uint64_t)command->expiryTimeMicroSecond)
+ else if (now_usec >= (uint64_t) command->expiryTimeMicroSecond)
{
statusReportCode = nl::Weave::Profiles::DataManagement::kStatus_RequestExpiredInTime;
ExitNow();
@@ -1476,15 +1488,13 @@
ExitNow();
}
}
-
// Note we cannot just use pathReader at here because the TDM related functions
// generally assume they can move the reader at their will.
// Note that callee is supposed to cache whatever is useful in the TLV stream into its own memory
// when this callback returns, we'd destroy the TLV object
- dataSource->OnCustomCommand(command, aMsgInfo, aPayload, command->commandType,
- command->IsExpiryTimeValid(), command->expiryTimeMicroSecond,
- command->IsMustBeVersionValid(), command->mustBeVersion,
+ dataSource->OnCustomCommand(command, aMsgInfo, aPayload, command->commandType, command->IsExpiryTimeValid(),
+ command->expiryTimeMicroSecond, command->IsMustBeVersionValid(), command->mustBeVersion,
reader);
command = NULL;
@@ -1515,7 +1525,671 @@
}
#endif // WDM_PUBLISHER_ENABLE_CUSTOM_COMMANDS
-#endif // #if WDM_ENABLE_SUBSCRIPTION_PUBLISHER
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+WEAVE_ERROR SubscriptionEngine::AllocateRightSizedBuffer(PacketBuffer *& buf, const uint32_t desiredSize, const uint32_t minSize,
+ uint32_t & outMaxPayloadSize)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint32_t bufferAllocSize = 0;
+ uint32_t maxWeavePayloadSize;
+ uint32_t weaveTrailerSize = WEAVE_TRAILER_RESERVE_SIZE;
+ uint32_t weaveHeaderSize = WEAVE_SYSTEM_CONFIG_HEADER_RESERVE_SIZE;
+
+ bufferAllocSize = nl::Weave::min(
+ desiredSize, static_cast<uint32_t>(WEAVE_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX - weaveHeaderSize - weaveTrailerSize));
+
+ // Add the Weave Trailer size as NewWithAvailableSize() includes that in
+ // availableSize.
+ bufferAllocSize += weaveTrailerSize;
+
+ buf = PacketBuffer::NewWithAvailableSize(weaveHeaderSize, bufferAllocSize);
+ VerifyOrExit(buf != NULL, err = WEAVE_ERROR_NO_MEMORY);
+
+ maxWeavePayloadSize = WeaveMessageLayer::GetMaxWeavePayloadSize(buf, true, WEAVE_CONFIG_DEFAULT_UDP_MTU_SIZE);
+
+ outMaxPayloadSize = nl::Weave::min(maxWeavePayloadSize, bufferAllocSize);
+
+ if (outMaxPayloadSize < minSize)
+ {
+ err = WEAVE_ERROR_BUFFER_TOO_SMALL;
+
+ PacketBuffer::Free(buf);
+ buf = NULL;
+ }
+
+exit:
+ return err;
+}
+
+void SubscriptionEngine::ConstructStatusListVersionList(nl::Weave::TLV::TLVWriter & aWriter, void * apContext)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ nl::Weave::TLV::TLVWriter checkpoint = aWriter;
+ TraitDataSource * dataSource = NULL;
+ struct StatusDataHandleElement * elementTracker = NULL;
+ UpdateResponseWriterContext * context = NULL;
+ UpdateResponse::Builder updateResponseBuilder;
+
+ VerifyOrExit(NULL != apContext, err = WEAVE_ERROR_INCORRECT_STATE);
+ context = static_cast<UpdateResponseWriterContext *>(apContext);
+
+ err = updateResponseBuilder.Init(&aWriter);
+ SuccessOrExit(err);
+
+ elementTracker = static_cast<struct StatusDataHandleElement *>(context->mpFirstStatusDataHandleElement);
+ {
+ VersionList::Builder & lVLBuilder = updateResponseBuilder.CreateVersionListBuilder();
+ for (uint32_t i = 0; i < context->mNumDataElements; i++)
+ {
+ if ((elementTracker->mProfileId == Weave::Profiles::kWeaveProfile_Common) &&
+ (elementTracker->mStatusCode == Weave::Profiles::Common::kStatus_AccessDenied))
+ {
+ lVLBuilder.AddNull();
+ }
+ else if ((elementTracker->mProfileId == Weave::Profiles::kWeaveProfile_WDM) &&
+ (elementTracker->mStatusCode == kStatus_InvalidPath))
+ {
+ lVLBuilder.AddNull();
+ }
+ else if (context->mpCatalog->Locate(elementTracker->mTraitDataHandle, &dataSource) == WEAVE_NO_ERROR)
+ {
+ lVLBuilder.AddVersion(dataSource->GetVersion());
+ }
+ else
+ {
+ lVLBuilder.AddNull();
+ }
+ elementTracker++;
+ }
+ lVLBuilder.EndOfVersionList();
+ SuccessOrExit(lVLBuilder.GetError());
+ }
+
+ elementTracker = static_cast<struct StatusDataHandleElement *>(context->mpFirstStatusDataHandleElement);
+ {
+ StatusList::Builder & lSLBuilder = updateResponseBuilder.CreateStatusListBuilder();
+ for (uint32_t j = 0; j < context->mNumDataElements; j++)
+ {
+ lSLBuilder.AddStatus(elementTracker->mProfileId, elementTracker->mStatusCode);
+ elementTracker++;
+ }
+ lSLBuilder.EndOfStatusList();
+ SuccessOrExit(lSLBuilder.GetError());
+ }
+
+ updateResponseBuilder.EndOfResponse();
+ SuccessOrExit(updateResponseBuilder.GetError());
+
+ aWriter.Finalize();
+
+ WeaveLogDetail(DataManagement, "ConstructStatusListVersionList success with number of elements %d", context->mNumDataElements);
+
+exit:
+ if (err != WEAVE_NO_ERROR)
+ {
+ aWriter = checkpoint;
+ }
+}
+
+void SubscriptionEngine::BuildStatusDataHandleElement(PacketBuffer * pBuf, TraitDataHandle aTraitDataHandle, WEAVE_ERROR & err,
+ uint32_t aCurrentIndex)
+{
+ uint32_t profileId = 0;
+ uint16_t statusCode = 0;
+
+ if (WEAVE_ERROR_ACCESS_DENIED == err)
+ {
+ profileId = Weave::Profiles::kWeaveProfile_Common;
+ statusCode = Weave::Profiles::Common::kStatus_AccessDenied;
+ err = WEAVE_NO_ERROR;
+ }
+ else if (WEAVE_ERROR_INVALID_PROFILE_ID == err)
+ {
+ profileId = Weave::Profiles::kWeaveProfile_WDM;
+ statusCode = kStatus_InvalidPath;
+ err = WEAVE_NO_ERROR;
+ }
+ else if (WEAVE_ERROR_WDM_VERSION_MISMATCH == err)
+ {
+ profileId = Weave::Profiles::kWeaveProfile_WDM;
+ statusCode = kStatus_VersionMismatch;
+ err = WEAVE_NO_ERROR;
+ }
+ else if (WEAVE_NO_ERROR == err)
+ {
+ profileId = Weave::Profiles::kWeaveProfile_Common;
+ statusCode = Weave::Profiles::Common::kStatus_Success;
+ }
+ else
+ {
+ profileId = Weave::Profiles::kWeaveProfile_Common;
+ statusCode = Weave::Profiles::Common::kStatus_InternalError;
+ WeaveLogError(DataManagement, "fail to process UpdateRequest with error %s at %s:%d", nl::ErrorStr(err), __FILE__, __LINE__);
+ }
+
+ StatusDataHandleElement * statusDataHandleList = WEAVE_WDM_ALIGNED_TYPE(pBuf->Start(), StatusDataHandleElement);
+ statusDataHandleList[aCurrentIndex].mProfileId = profileId;
+ statusDataHandleList[aCurrentIndex].mStatusCode = statusCode;
+ statusDataHandleList[aCurrentIndex].mTraitDataHandle = aTraitDataHandle;
+}
+
+/**
+ * Check if this triat path is the starting one
+ */
+bool SubscriptionEngine::IsStartingPath(StatusDataHandleElement * apStatusDataHandleList, TraitDataHandle aTraitDataHandle,
+ uint32_t aCurrentIndex)
+{
+ bool isStarting = true;
+ // TODO: Optimize to reduce lookup loop
+ for (uint32_t index = 0; index < aCurrentIndex; index++)
+ {
+ if ((nl::Weave::Profiles::kWeaveProfile_Common == apStatusDataHandleList[index].mProfileId) &&
+ (nl::Weave::Profiles::Common::kStatus_Success == apStatusDataHandleList[index].mStatusCode) &&
+ (aTraitDataHandle == apStatusDataHandleList[index].mTraitDataHandle))
+ {
+ isStarting = false;
+ }
+ }
+ return isStarting;
+}
+
+/**
+ * Update version for all traits according to temporary statusDataHandleList, and bump version once at starting path
+ * for each trait
+ */
+WEAVE_ERROR SubscriptionEngine::UpdateTraitVersions(PacketBuffer * apBuf, const TraitCatalogBase<TraitDataSource> * apCatalog,
+ uint32_t aNumDataElements)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ TraitDataSource * dataSource = NULL;
+ TraitUpdatableDataSource * updatableSource = NULL;
+ StatusDataHandleElement * statusDataHandleList = WEAVE_WDM_ALIGNED_TYPE(apBuf->Start(), StatusDataHandleElement);
+
+ for (uint32_t index = 0; index < aNumDataElements; index++)
+ {
+ if ((nl::Weave::Profiles::kWeaveProfile_Common == statusDataHandleList[index].mProfileId) &&
+ (nl::Weave::Profiles::Common::kStatus_Success == statusDataHandleList[index].mStatusCode))
+ {
+
+ err = apCatalog->Locate(statusDataHandleList[index].mTraitDataHandle, &dataSource);
+ SuccessOrExit(err);
+
+ updatableSource = static_cast<TraitUpdatableDataSource *>(dataSource);
+
+ if (IsStartingPath(statusDataHandleList, statusDataHandleList[index].mTraitDataHandle, index))
+ {
+ updatableSource->IncrementVersion();
+ WeaveLogDetail(DataManagement, "<UpdateTraitVersions> [Trait %08x] bumped version: 0x%" PRIx64 " ",
+ updatableSource->GetSchemaEngine()->GetProfileId(), updatableSource->GetVersion());
+ }
+ else
+ {
+ WeaveLogDetail(DataManagement, "<UpdateTraitVersions> [Trait %08x] version: 0x%" PRIx64 " (no-change)",
+ updatableSource->GetSchemaEngine()->GetProfileId(), updatableSource->GetVersion());
+ }
+ }
+ }
+
+exit:
+ return err;
+}
+
+/**
+ * If update request is malformed, it would send status report along with error status.
+ */
+WEAVE_ERROR SubscriptionEngine::SendFaultyUpdateResponse(Weave::ExchangeContext * apEC)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ uint8_t * p;
+ uint8_t statusReportLen = 6;
+ PacketBuffer * msgBuf = PacketBuffer::NewWithAvailableSize(statusReportLen);
+ VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY);
+
+ p = msgBuf->Start();
+ nl::Weave::Encoding::LittleEndian::Write32(p, Weave::Profiles::kWeaveProfile_Common);
+ nl::Weave::Encoding::LittleEndian::Write16(p, Weave::Profiles::Common::kStatus_InternalError);
+ msgBuf->SetDataLength(statusReportLen);
+
+ err = apEC->SendMessage(Profiles::kWeaveProfile_Common, Profiles::Common::kMsgType_StatusReport, msgBuf);
+ msgBuf = NULL;
+ SuccessOrExit(err);
+
+exit:
+ if (msgBuf != NULL)
+ {
+ PacketBuffer::Free(msgBuf);
+ msgBuf = NULL;
+ }
+ return err;
+}
+
+/**
+ * Relocating statusDataHandleList to the end of Update Response buffer, based upon existFailure and
+ * statusDataHandleList, it constructs and sends status report.
+ */
+WEAVE_ERROR SubscriptionEngine::SendUpdateResponse(Weave::ExchangeContext * apEC, uint32_t aNumDataElements,
+ const TraitCatalogBase<TraitDataSource> * apCatalog, PacketBuffer * apBuf,
+ bool existFailure, uint32_t aMaxPayloadSize)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ UpdateResponseWriterContext context;
+ StatusReport statusReport;
+ ReferencedTLVData referenceTLVData;
+ uint32_t totalStatusDataHandleListBytes = 0;
+ uint32_t overalStatusProfile = Weave::Profiles::kWeaveProfile_Common;
+ uint16_t overalStatusCode = Weave::Profiles::Common::kStatus_Success;
+ uint8_t * movedStartAddr = NULL;
+ uint8_t * pBufStartAddr = WEAVE_WDM_ALIGNED_TYPE(apBuf->Start(), uint8_t);
+
+ totalStatusDataHandleListBytes = aNumDataElements * sizeof(StatusDataHandleElement);
+
+ WeaveLogDetail(DataManagement, "relocating the %d bytes statusDataHandleList to the end, NumDataElements is %d",
+ totalStatusDataHandleListBytes, aNumDataElements);
+
+ movedStartAddr = WEAVE_WDM_ALIGNED_TYPE(pBufStartAddr + aMaxPayloadSize - totalStatusDataHandleListBytes - 3, uint8_t);
+
+ memmove(movedStartAddr, pBufStartAddr, totalStatusDataHandleListBytes);
+
+ context.mpFirstStatusDataHandleElement = movedStartAddr;
+ context.mpCatalog = apCatalog;
+ context.mNumDataElements = aNumDataElements;
+
+ // TODO: Refactor StatusReport and remove referenceTLVData
+ err = referenceTLVData.init(ConstructStatusListVersionList, &context);
+ SuccessOrExit(err);
+
+ if (existFailure)
+ {
+ overalStatusProfile = Weave::Profiles::kWeaveProfile_WDM;
+ overalStatusCode = kStatus_MultipleFailures;
+ }
+ else
+ {
+ overalStatusProfile = Weave::Profiles::kWeaveProfile_Common;
+ overalStatusCode = Weave::Profiles::Common::kStatus_Success;
+ }
+
+ err = statusReport.init(overalStatusProfile, overalStatusCode, &referenceTLVData);
+ SuccessOrExit(err);
+
+ err = statusReport.pack(apBuf, aMaxPayloadSize - totalStatusDataHandleListBytes);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "Send Update Response with profileId 0x%" PRIX32 " statusCode 0x%" PRIX16 " ",
+ overalStatusProfile, overalStatusCode);
+ err = apEC->SendMessage(Weave::Profiles::kWeaveProfile_Common, Weave::Profiles::Common::kMsgType_StatusReport, apBuf);
+ apBuf = NULL;
+
+exit:
+ if (apBuf != NULL)
+ {
+ PacketBuffer::Free(apBuf);
+ apBuf = NULL;
+ }
+ return err;
+}
+
+/**
+ * Run access check to check if DE is allowed, then during conditional DE loop, if DE does not have required version,
+ * skip this one, otherwises its required version for current DE should be same as current trait.
+ * During unconditional loop, if its required version is not 0, skip this one.
+ * Finally it starts to store data element
+ */
+WEAVE_ERROR SubscriptionEngine::ProcessUpdateRequestDataElement(Weave::TLV::TLVReader & aReader, TraitDataHandle & aHandle,
+ PropertyPathHandle & aPathHandle,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate,
+ bool aConditionalLoop, uint32_t aCurrentIndex, bool & aExistFailure,
+ PacketBuffer * apBuf)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ Weave::TLV::TLVReader pathReader;
+ Weave::TLV::TLVReader dataReader;
+ TraitPath traitPath;
+ DataElement::Parser element;
+ uint64_t requiredVersion = 0;
+ uint64_t versionInTrait = 0;
+ bool isPartialChange = false;
+ bool isLocked = false;
+ bool needSkip = false;
+ bool isConditionalDE = true;
+ SchemaVersionRange versionRange;
+ TraitDataSource * dataSource = NULL;
+ TraitUpdatableDataSource * updatableSource = NULL;
+
+ dataReader.Init(aReader);
+
+ err = element.Init(aReader);
+ SuccessOrExit(err);
+ err = element.GetReaderOnPath(&pathReader);
+ SuccessOrExit(err);
+
+ // Not support partial change handling
+ isPartialChange = false;
+ element.GetPartialChangeFlag(&isPartialChange);
+ VerifyOrExit(isPartialChange == false, err = WEAVE_ERROR_INCORRECT_STATE);
+
+ err = apCatalog->AddressToHandle(pathReader, aHandle, versionRange);
+ SuccessOrExit(err);
+
+ err = apCatalog->Locate(aHandle, &dataSource);
+ SuccessOrExit(err);
+ err = dataSource->GetSchemaEngine()->MapPathToHandle(pathReader, aPathHandle);
+#if TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
+ if (err == WEAVE_ERROR_TLV_TAG_NOT_FOUND)
+ {
+ WeaveLogDetail(DataManagement, "Ignoring un-mappable path!");
+ err = WEAVE_NO_ERROR;
+ }
+#endif
+
+ traitPath.mTraitDataHandle = aHandle;
+ traitPath.mPropertyPathHandle = aPathHandle;
+
+ err = acDelegate.DataElementAccessCheck(traitPath, *apCatalog);
+ SuccessOrExit(err);
+
+ updatableSource = static_cast<TraitUpdatableDataSource *>(dataSource);
+ updatableSource->Lock();
+ isLocked = true;
+
+ versionInTrait = updatableSource->GetVersion();
+
+ err = element.GetVersion(&requiredVersion);
+ if (WEAVE_END_OF_TLV == err)
+ {
+ err = WEAVE_NO_ERROR;
+ isConditionalDE = false;
+ }
+ SuccessOrExit(err);
+
+ if (aConditionalLoop)
+ {
+ VerifyOrExit(isConditionalDE, needSkip = true);
+ VerifyOrExit(versionInTrait == requiredVersion, err = WEAVE_ERROR_WDM_VERSION_MISMATCH);
+ }
+ else
+ {
+ VerifyOrExit(!isConditionalDE, needSkip = true);
+ }
+ WeaveLogDetail(DataManagement, "processing %s DE, index %d", aConditionalLoop ? "conditional" : "unconditional", aCurrentIndex);
+
+ err = updatableSource->StoreDataElement(aPathHandle, dataReader, 0, NULL, NULL);
+ SuccessOrExit(err);
+
+ updatableSource->SetDirty(aPathHandle);
+
+ updatableSource->Unlock(true);
+ isLocked = false;
+
+exit:
+ if (isLocked && updatableSource != NULL)
+ {
+ updatableSource->Unlock(true);
+ }
+
+ if (WEAVE_NO_ERROR != err)
+ {
+ WeaveLogDetail(DataManagement, "There exists %d DE with err %d", aCurrentIndex, err);
+ aExistFailure = true;
+ }
+
+ if (!needSkip)
+ {
+ BuildStatusDataHandleElement(apBuf, aHandle, err, aCurrentIndex);
+ }
+
+ return err;
+}
+
+/**
+ * Loop through all data elements in list and process either conditional data elements or unconditional data elements in
+ * one loop, and build temporary statusDataHandleList. Later it would use this list to construct update response.
+ */
+WEAVE_ERROR SubscriptionEngine::ProcessUpdateRequestDataList(Weave::TLV::TLVReader & aReader, PacketBuffer * apBuf,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate,
+ bool & aExistFailure, uint32_t & aNumDataElements,
+ bool aConditionalLoop)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ Weave::TLV::TLVReader dataReader;
+ dataReader.Init(aReader);
+
+ for (aNumDataElements = 0; WEAVE_NO_ERROR == (err = dataReader.Next()); aNumDataElements++)
+ {
+ TraitDataHandle handle;
+ PropertyPathHandle pathHandle;
+
+ // if it is running conditional loop, needs to skip unconditional elements, vice versa.
+ err = ProcessUpdateRequestDataElement(dataReader, handle, pathHandle, apCatalog, acDelegate, aConditionalLoop,
+ aNumDataElements, aExistFailure, apBuf);
+ SuccessOrExit(err);
+ }
+
+ // if we have exhausted this container
+ if (WEAVE_END_OF_TLV == err)
+ {
+ err = WEAVE_NO_ERROR;
+ }
+
+exit:
+ return err;
+}
+
+/**
+ * Apply all conditional DEs first, then apply all unconditional DEs second, during loop, add status and dataHandle to
+ * temporary result list. Then update starting version for traits and generate update response.
+ */
+WEAVE_ERROR SubscriptionEngine::ProcessUpdateRequest(Weave::ExchangeContext * apEC, Weave::TLV::TLVReader & aReader,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ PacketBuffer * pBuf = NULL;
+ bool existFailure = false;
+ uint32_t numDataElements = 0;
+ uint32_t maxPayloadSize = 0;
+
+ VerifyOrExit(apCatalog != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
+
+ err = AllocateRightSizedBuffer(pBuf, WDM_MAX_UPDATE_RESPONSE_SIZE, WDM_MIN_UPDATE_RESPONSE_SIZE, maxPayloadSize);
+ SuccessOrExit(err);
+
+ // process conditional DEs
+ err = ProcessUpdateRequestDataList(aReader, pBuf, apCatalog, acDelegate, existFailure, numDataElements, true);
+ SuccessOrExit(err);
+
+ // process unconditional DEs
+ err = ProcessUpdateRequestDataList(aReader, pBuf, apCatalog, acDelegate, existFailure, numDataElements, false);
+ SuccessOrExit(err);
+
+ // update trait versions
+ err = UpdateTraitVersions(pBuf, apCatalog, numDataElements);
+ SuccessOrExit(err);
+
+ err = SendUpdateResponse(apEC, numDataElements, apCatalog, pBuf, existFailure, maxPayloadSize);
+ pBuf = NULL;
+
+exit:
+
+ if (pBuf != NULL)
+ {
+ PacketBuffer::Free(pBuf);
+ }
+
+ if (WEAVE_NO_ERROR != err)
+ {
+ SendFaultyUpdateResponse(apEC);
+ }
+ return err;
+}
+
+/**
+ * Process UpdateRequest if Data list is present and send notification if subscription exists
+ */
+void SubscriptionEngine::OnUpdateRequest(Weave::ExchangeContext * apEC, const Inet::IPPacketInfo * aPktInfo,
+ const Weave::WeaveMessageInfo * aMsgInfo, uint32_t aProfileId, uint8_t aMsgType,
+ PacketBuffer * aPayload)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ UpdateRequest::Parser update;
+ Weave::TLV::TLVReader reader;
+ bool isDataListPresent = false;
+ bool hasUpdateRequestBegin = false;
+ InEventParam inParam;
+ OutEventParam outParam;
+
+ SubscriptionEngine * const pEngine = reinterpret_cast<SubscriptionEngine *>(apEC->AppState);
+
+ inParam.Clear();
+ outParam.Clear();
+
+ inParam.mIncomingUpdateRequest.processingError = err;
+ inParam.mIncomingUpdateRequest.mMsgInfo = aMsgInfo;
+ outParam.mIncomingUpdateRequest.mShouldContinueProcessing = true;
+
+ if (pEngine->mEventCallback)
+ {
+ pEngine->mEventCallback(pEngine->mAppState, kEvent_OnIncomingUpdateRequest, inParam, outParam);
+ }
+
+ if (!outParam.mIncomingUpdateRequest.mShouldContinueProcessing)
+ {
+ WeaveLogDetail(DataManagement, "Update not allowed");
+ ExitNow();
+ }
+
+ pEngine->mPublisherCatalog->DispatchEvent(TraitUpdatableDataSource::kEventUpdateRequestBegin, NULL);
+ hasUpdateRequestBegin = true;
+
+ reader.Init(aPayload);
+
+ err = reader.Next();
+ SuccessOrExit(err);
+
+ err = update.Init(reader);
+ SuccessOrExit(err);
+
+#if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
+ err = update.CheckSchemaValidity();
+ SuccessOrExit(err);
+#endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK
+
+ {
+ DataList::Parser dataList;
+
+ err = update.GetDataList(&dataList);
+ if (WEAVE_NO_ERROR == err)
+ {
+ isDataListPresent = true;
+ }
+ else if (WEAVE_END_OF_TLV == err)
+ {
+ isDataListPresent = false;
+ err = WEAVE_NO_ERROR;
+ }
+ SuccessOrExit(err);
+
+ // re-initialize the reader to point to individual date element (reuse to save stack depth).
+ dataList.GetReader(&reader);
+ }
+
+ if (isDataListPresent)
+ {
+ UpdateRequestDataElementAccessControlDelegate acDelegate(aMsgInfo);
+ IUpdateRequestDataElementAccessControlDelegate & acDelegateRef = acDelegate;
+
+ err = ProcessUpdateRequest(apEC, reader, pEngine->mPublisherCatalog, acDelegateRef);
+ SuccessOrExit(err);
+
+ pEngine->GetNotificationEngine()->ScheduleRun();
+ }
+
+exit:
+ if (hasUpdateRequestBegin)
+ {
+ pEngine->mPublisherCatalog->DispatchEvent(TraitUpdatableDataSource::kEventUpdateRequestEnd, NULL);
+ }
+
+ if (NULL != aPayload)
+ {
+ PacketBuffer::Free(aPayload);
+ aPayload = NULL;
+ }
+
+ if (NULL != apEC)
+ {
+ apEC->Abort();
+ apEC = NULL;
+ }
+
+ if (NULL != pEngine->mEventCallback)
+ {
+ inParam.Clear();
+ outParam.Clear();
+
+ inParam.mIncomingUpdateRequest.processingError = err;
+ inParam.mIncomingUpdateRequest.mMsgInfo = aMsgInfo;
+ // Update completion event indication.
+ pEngine->mEventCallback(pEngine->mAppState, kEvent_UpdateRequestProcessingComplete, inParam, outParam);
+ }
+}
+
+WEAVE_ERROR SubscriptionEngine::UpdateRequestDataElementAccessControlDelegate::DataElementAccessCheck(
+ const TraitPath & aTraitPath, const TraitCatalogBase<TraitDataSource> & aCatalog)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ TraitDataSource * dataSource;
+ InEventParam inParam;
+ OutEventParam outParam;
+ SubscriptionEngine * pEngine = SubscriptionEngine::GetInstance();
+
+ err = aCatalog.Locate(aTraitPath.mTraitDataHandle, &dataSource);
+ SuccessOrExit(err);
+
+ inParam.Clear();
+ outParam.Clear();
+
+ if (dataSource->IsUpdatableDataSource())
+ {
+ outParam.mDataElementAccessControlForUpdateRequest.mRejectUpdateRequest = false;
+ outParam.mDataElementAccessControlForUpdateRequest.mReason = WEAVE_NO_ERROR;
+ }
+ else
+ {
+ outParam.mDataElementAccessControlForUpdateRequest.mRejectUpdateRequest = true;
+ outParam.mDataElementAccessControlForUpdateRequest.mReason = WEAVE_ERROR_ACCESS_DENIED;
+ }
+
+ inParam.mDataElementAccessControlForUpdateRequest.mPath = &aTraitPath;
+ inParam.mDataElementAccessControlForUpdateRequest.mCatalog = &aCatalog;
+ inParam.mDataElementAccessControlForUpdateRequest.mMsgInfo = mMsgInfo;
+
+ if (NULL != pEngine->mEventCallback)
+ {
+ pEngine->mEventCallback(pEngine->mAppState, kEvent_UpdateRequestDataElementAccessControlCheck, inParam, outParam);
+ }
+
+ // If application rejects it then deny access, else set reason to whatever
+ // reason is set by application.
+ if (outParam.mDataElementAccessControlForUpdateRequest.mRejectUpdateRequest == true)
+ {
+ err = WEAVE_ERROR_ACCESS_DENIED;
+ }
+ else
+ {
+ err = outParam.mDataElementAccessControlForUpdateRequest.mReason;
+ }
+
+exit:
+
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
+#endif // WDM_ENABLE_SUBSCRIPTION_PUBLISHER
}; // namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
}; // namespace Profiles
diff --git a/src/lib/profiles/data-management/Current/SubscriptionEngine.h b/src/lib/profiles/data-management/Current/SubscriptionEngine.h
index 51bd71e..941c7a8 100644
--- a/src/lib/profiles/data-management/Current/SubscriptionEngine.h
+++ b/src/lib/profiles/data-management/Current/SubscriptionEngine.h
@@ -53,6 +53,15 @@
virtual WEAVE_ERROR Unlock(void) = 0;
};
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+class IUpdateRequestDataElementAccessControlDelegate
+{
+public:
+ virtual WEAVE_ERROR DataElementAccessCheck(const TraitPath & aTraitPath,
+ const TraitCatalogBase<TraitDataSource> & aCatalog) = 0;
+};
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
/**
* @class SubscriptionEngine
*
@@ -84,11 +93,17 @@
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
kEvent_OnIncomingSubscriptionlessNotification =
1, ///< Called when an incoming subscriptionless notification has arrived before updating the data element.
- kEvent_DataElementAccessControlCheck =
- 2, ///< Called when an incoming subscriptionless notification is being processed for access control of each data element.
+ kEvent_DataElementAccessControlCheck = 2, ///< Called when an incoming subscriptionless notification is being processed for
+ ///< access control of each data element.
kEvent_SubscriptionlessNotificationProcessingComplete =
3, ///< Called upon completion of processing of all trait data in the subscriptionless notify.
#endif // #if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ kEvent_OnIncomingUpdateRequest = 4, ///< Called when an incoming update has arrived before updating the data element.
+ kEvent_UpdateRequestDataElementAccessControlCheck =
+ 5, ///< Called when an incoming update is being processed for access control of each data element.
+ kEvent_UpdateRequestProcessingComplete = 6, ///< Called upon completion of processing of all trait data in the update.
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
};
/**
@@ -124,11 +139,28 @@
struct
{
const TraitCatalogBase<TraitDataSink> * mCatalog; ///< A pointer to the TraitCatalog for the data sinks.
- const TraitPath *mPath; ///< A pointer to the TraitPath being accessed by the
- ///< subscriptionless notification.
- const nl::Weave::WeaveMessageInfo * mMsgInfo; ///< A pointer to the message information for the request
+ const TraitPath * mPath; ///< A pointer to the TraitPath being accessed by the
+ ///< subscriptionless notification.
+ const nl::Weave::WeaveMessageInfo * mMsgInfo; ///< A pointer to the message information for the request
} mDataElementAccessControlForNotification;
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ struct
+ {
+ WEAVE_ERROR processingError; ///< The WEAVE_ERROR encountered in processing the
+ ///< Update Request.
+ const nl::Weave::WeaveMessageInfo * mMsgInfo; ///< A pointer to the message information for the request
+ } mIncomingUpdateRequest;
+
+ struct
+ {
+ const TraitCatalogBase<TraitDataSource> * mCatalog; ///< A pointer to the TraitCatalog for the data sources.
+ const TraitPath * mPath; ///< A pointer to the TraitPath being accessed by the
+ ///< update request.
+ const nl::Weave::WeaveMessageInfo * mMsgInfo; ///< A pointer to the message information for the request
+ } mDataElementAccessControlForUpdateRequest;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
};
/**
@@ -158,15 +190,28 @@
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
struct
{
- bool mShouldContinueProcessing; ///< Set to true if subscriptionless notification is allowed.
+ bool mShouldContinueProcessing; ///< Set to true if subscriptionless notification is allowed.
} mIncomingSubscriptionlessNotification;
struct
{
- bool mRejectNotification; ///< Set to true if subscriptionless notification is rejected.
- WEAVE_ERROR mReason; ///< The reason for the rejection, if any.
+ bool mRejectNotification; ///< Set to true if subscriptionless notification is rejected.
+ WEAVE_ERROR mReason; ///< The reason for the rejection, if any.
} mDataElementAccessControlForNotification;
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ struct
+ {
+ bool mShouldContinueProcessing; ///< Set to true if update is allowed.
+ } mIncomingUpdateRequest;
+
+ struct
+ {
+ bool mRejectUpdateRequest; ///< Set to true if update is rejected.
+ WEAVE_ERROR mReason; ///< The reason for the rejection, if any.
+ } mDataElementAccessControlForUpdateRequest;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
};
/**
@@ -253,8 +298,7 @@
WEAVE_ERROR NewClient(SubscriptionClient ** const appClient, Binding * const apBinding, void * const apAppState,
SubscriptionClient::EventCallback const aEventCallback,
const TraitCatalogBase<TraitDataSink> * const apCatalog,
- const uint32_t aInactivityTimeoutDuringSubscribingMsec,
- IWeaveWDMMutex * aUpdateMutex);
+ const uint32_t aInactivityTimeoutDuringSubscribingMsec, IWeaveWDMMutex * aUpdateMutex);
WEAVE_ERROR NewSubscriptionHandler(SubscriptionHandler ** const subHandler);
@@ -301,8 +345,7 @@
const EventCallback aEventCallback = NULL);
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
- WEAVE_ERROR RegisterForSubscriptionlessNotifications(
- const TraitCatalogBase<TraitDataSink> * const apCatalog);
+ WEAVE_ERROR RegisterForSubscriptionlessNotifications(const TraitCatalogBase<TraitDataSink> * const apCatalog);
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
nl::Weave::WeaveExchangeManager * GetExchangeManager(void) const { return mExchangeMgr; };
@@ -342,16 +385,12 @@
class SubscriptionlessNotifyDataElementAccessControlDelegate : public IDataElementAccessControlDelegate
{
public:
- SubscriptionlessNotifyDataElementAccessControlDelegate(const WeaveMessageInfo * aMsgInfo)
- {
- mMsgInfo = aMsgInfo;
- }
+ SubscriptionlessNotifyDataElementAccessControlDelegate(const WeaveMessageInfo * aMsgInfo) { mMsgInfo = aMsgInfo; }
- WEAVE_ERROR DataElementAccessCheck(const TraitPath & aTraitPath,
- const TraitCatalogBase<TraitDataSink> & aCatalog);
+ WEAVE_ERROR DataElementAccessCheck(const TraitPath & aTraitPath, const TraitCatalogBase<TraitDataSink> & aCatalog);
private:
- const WeaveMessageInfo * mMsgInfo;
+ const WeaveMessageInfo * mMsgInfo;
};
static void OnSubscriptionlessNotification(nl::Weave::ExchangeContext * aEC, const nl::Inet::IPPacketInfo * aPktInfo,
@@ -359,6 +398,23 @@
PacketBuffer * aPayload);
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ class UpdateRequestDataElementAccessControlDelegate : public IUpdateRequestDataElementAccessControlDelegate
+ {
+ public:
+ UpdateRequestDataElementAccessControlDelegate(const WeaveMessageInfo * aMsgInfo) { mMsgInfo = aMsgInfo; }
+
+ WEAVE_ERROR DataElementAccessCheck(const TraitPath & aTraitPath, const TraitCatalogBase<TraitDataSource> & aCatalog);
+
+ private:
+ const WeaveMessageInfo * mMsgInfo;
+ };
+
+ static void OnUpdateRequest(nl::Weave::ExchangeContext * apEC, const nl::Inet::IPPacketInfo * aPktInfo,
+ const nl::Weave::WeaveMessageInfo * aMsgInfo, uint32_t aProfileId, uint8_t aMsgType,
+ PacketBuffer * aPayload);
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
#if WDM_ENABLE_SUBSCRIPTION_CLIENT
// Client-specific features
@@ -370,11 +426,54 @@
#endif // WDM_ENABLE_SUBSCRIPTION_CLIENT
- static WEAVE_ERROR ProcessDataList(nl::Weave::TLV::TLVReader & aReader,
- const TraitCatalogBase<TraitDataSink> * aCatalog,
- bool & aOutIsPartialChange,
- TraitDataHandle & aOutTraitDataHandle,
+ static WEAVE_ERROR ProcessDataList(nl::Weave::TLV::TLVReader & aReader, const TraitCatalogBase<TraitDataSink> * aCatalog,
+ bool & aOutIsPartialChange, TraitDataHandle & aOutTraitDataHandle,
IDataElementAccessControlDelegate & acDelegate);
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ struct StatusDataHandleElement
+ {
+ uint32_t mProfileId;
+ uint16_t mStatusCode;
+ TraitDataHandle mTraitDataHandle;
+ };
+
+ struct UpdateResponseWriterContext
+ {
+ void * mpFirstStatusDataHandleElement;
+ const TraitCatalogBase<TraitDataSource> * mpCatalog;
+ uint32_t mNumDataElements;
+ };
+
+ static WEAVE_ERROR AllocateRightSizedBuffer(PacketBuffer *& buf, const uint32_t desiredSize, const uint32_t minSize,
+ uint32_t & outMaxPayloadSize);
+ static void ConstructStatusListVersionList(Weave::TLV::TLVWriter & aWriter, void * apContext);
+ static void BuildStatusDataHandleElement(PacketBuffer * pBuf, TraitDataHandle aTraitDataHandle, WEAVE_ERROR & err,
+ uint32_t aCurrentIndex);
+ static bool IsStartingPath(StatusDataHandleElement * apStatusDataHandleList, TraitDataHandle aTraitDataHandle,
+ uint32_t aCurrentIndex);
+ static WEAVE_ERROR UpdateTraitVersions(PacketBuffer * apBuf, const TraitCatalogBase<TraitDataSource> * apCatalog,
+ uint32_t aNumDataElements);
+ static WEAVE_ERROR SendFaultyUpdateResponse(Weave::ExchangeContext * apEC);
+ static WEAVE_ERROR SendUpdateResponse(Weave::ExchangeContext * apEC, uint32_t aNumDataElements,
+ const TraitCatalogBase<TraitDataSource> * apCatalog, PacketBuffer * apBuf,
+ bool existFailure, uint32_t aMaxPayloadSize);
+ static WEAVE_ERROR ProcessUpdateRequestDataElement(Weave::TLV::TLVReader & aReader, TraitDataHandle & aHandle,
+ PropertyPathHandle & aPathHandle,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate,
+ bool aConditionalLoop, uint32_t aCurrentIndex, bool & aExistFailure,
+ PacketBuffer * apBuf);
+ static WEAVE_ERROR ProcessUpdateRequestDataList(Weave::TLV::TLVReader & aReader, PacketBuffer * apBuf,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate,
+ bool & aExistFailure, uint32_t & aNumDataElements, bool aConditionalLoop);
+
+ static WEAVE_ERROR ProcessUpdateRequest(Weave::ExchangeContext * apEC, Weave::TLV::TLVReader & aReader,
+ const TraitCatalogBase<TraitDataSource> * apCatalog,
+ IUpdateRequestDataElementAccessControlDelegate & acDelegate);
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
#if WEAVE_DETAIL_LOGGING
void LogSubscriptionFreed(void) const;
#endif // #if WEAVE_DETAIL_LOGGING
diff --git a/src/lib/profiles/data-management/Current/TraitData.cpp b/src/lib/profiles/data-management/Current/TraitData.cpp
index 6c1ebd9..7b73cd5 100644
--- a/src/lib/profiles/data-management/Current/TraitData.cpp
+++ b/src/lib/profiles/data-management/Current/TraitData.cpp
@@ -1,6 +1,7 @@
/*
*
- * Copyright (c) 2016-2017 Nest Labs, Inc.
+ * Copyright (c) 2016-2018 Nest Labs, Inc.
+ * Copyright (c) 2019-2020 Google, LLC.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -44,16 +45,15 @@
using namespace ::nl::Weave::Profiles::DataManagement;
using namespace ::nl::Weave::Profiles::DataManagement_Current;
-UpdateDirtyPathFilter::UpdateDirtyPathFilter(SubscriptionClient *apSubClient,
- TraitDataHandle traitDataHandle,
+UpdateDirtyPathFilter::UpdateDirtyPathFilter(SubscriptionClient * apSubClient, TraitDataHandle traitDataHandle,
const TraitSchemaEngine * aEngine)
{
- mpSubClient = apSubClient;
+ mpSubClient = apSubClient;
mTraitDataHandle = traitDataHandle;
- mSchemaEngine = aEngine;
+ mSchemaEngine = aEngine;
}
-bool UpdateDirtyPathFilter::FilterPath (PropertyPathHandle pathhandle)
+bool UpdateDirtyPathFilter::FilterPath(PropertyPathHandle pathhandle)
{
bool retval = false;
@@ -71,11 +71,11 @@
UpdateDictionaryDirtyPathCut::UpdateDictionaryDirtyPathCut(TraitDataHandle aTraitDataHandle, UpdateEncoder * apEncoder)
{
- mpUpdateEncoder = apEncoder;
+ mpUpdateEncoder = apEncoder;
mTraitDataHandle = aTraitDataHandle;
}
-WEAVE_ERROR UpdateDictionaryDirtyPathCut::CutPath (PropertyPathHandle aPathhandle, const TraitSchemaEngine * apEngine)
+WEAVE_ERROR UpdateDictionaryDirtyPathCut::CutPath(PropertyPathHandle aPathhandle, const TraitSchemaEngine * apEngine)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
// TODO: rename this struct, and pass apEngine to the constructor.
@@ -88,14 +88,14 @@
return err;
}
-WEAVE_ERROR TraitSchemaEngine::ParseTagString(const char *apTagString, char **apEndptr, uint8_t& aParseRes) const
+WEAVE_ERROR TraitSchemaEngine::ParseTagString(const char * apTagString, char ** apEndptr, uint8_t & aParseRes) const
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
VerifyOrExit(apTagString != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
VerifyOrExit(*apTagString == '/', err = WEAVE_ERROR_INVALID_ARGUMENT);
- apTagString ++;
+ apTagString++;
aParseRes = strtoul(apTagString, apEndptr, 0);
VerifyOrExit(!(*apEndptr == apTagString || (**apEndptr != '\0' && **apEndptr != '/')), err = WEAVE_ERROR_INVALID_ARGUMENT);
@@ -109,9 +109,9 @@
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
PropertyPathHandle childProperty, curProperty;
- char *parseEnd;
+ char * parseEnd;
uint8_t parseRes = 0;
- uint64_t tag = 0;
+ uint64_t tag = 0;
VerifyOrExit(aPathString != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
@@ -362,10 +362,8 @@
}
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
-WEAVE_ERROR TraitSchemaEngine::RetrieveUpdatableDictionaryData(PropertyPathHandle aHandle,
- uint64_t aTagToWrite,
- TLVWriter & aWriter,
- IGetDataDelegate * aDelegate,
+WEAVE_ERROR TraitSchemaEngine::RetrieveUpdatableDictionaryData(PropertyPathHandle aHandle, uint64_t aTagToWrite,
+ TLVWriter & aWriter, IGetDataDelegate * aDelegate,
PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom) const
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -373,8 +371,8 @@
#if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT
nl::Weave::TLV::TLVType dataContainerType;
PropertyDictionaryKey dictionaryItemKey;
- uintptr_t context = 0;
- uint32_t numKeysEncoded = 0;
+ uintptr_t context = 0;
+ uint32_t numKeysEncoded = 0;
PropertySchemaHandle dictionaryItemSchemaHandle = GetPropertySchemaHandle(GetFirstChild(aHandle));
PropertyPathHandle dictionaryItemPathHandle;
PropertyPathHandle itemToSkipTo = aPropertyPathHandleOfDictItemToStartFrom;
@@ -385,8 +383,7 @@
// items.
aPropertyPathHandleOfDictItemToStartFrom = kNullPropertyPathHandle;
- err = aWriter.StartContainer(aTagToWrite,
- nl::Weave::TLV::kTLVType_Structure, dataContainerType);
+ err = aWriter.StartContainer(aTagToWrite, nl::Weave::TLV::kTLVType_Structure, dataContainerType);
SuccessOrExit(err);
while ((err = aDelegate->GetNextDictionaryItemKey(aHandle, context, dictionaryItemKey)) == WEAVE_NO_ERROR)
@@ -407,18 +404,18 @@
err = RetrieveData(dictionaryItemPathHandle, tag, aWriter, aDelegate);
if (err != WEAVE_NO_ERROR)
{
- WeaveLogDetail(DataManagement, "Dictionary item whith path 0x%" PRIx32 ", tag 0x% " PRIx64 " failed with error % " PRIu32 "",
- dictionaryItemPathHandle, tag, err);
+ WeaveLogDetail(DataManagement,
+ "Dictionary item whith path 0x%" PRIx32 ", tag 0x% " PRIx64 " failed with error % " PRIu32 "",
+ dictionaryItemPathHandle, tag, err);
}
- if (numKeysEncoded > 0 &&
- ((err == WEAVE_ERROR_BUFFER_TOO_SMALL) || (err == WEAVE_ERROR_NO_MEMORY)))
+ if (numKeysEncoded > 0 && ((err == WEAVE_ERROR_BUFFER_TOO_SMALL) || (err == WEAVE_ERROR_NO_MEMORY)))
{
// BUFFER_TOO_SMALL means there is no more space in the current buffer.
// NO_MEMORY means the application is trying to build a chain of pBufs, but
// there are no more buffers.
- aWriter = backupWriter;
+ aWriter = backupWriter;
aPropertyPathHandleOfDictItemToStartFrom = dictionaryItemPathHandle;
- err = WEAVE_NO_ERROR;
+ err = WEAVE_NO_ERROR;
break;
}
SuccessOrExit(err);
@@ -440,13 +437,11 @@
return err;
}
-WEAVE_ERROR TraitSchemaEngine::GetRelativePathTags(const PropertyPathHandle aCandidateHandle,
- uint64_t *aTags,
- const uint32_t aTagsSize,
- uint32_t &aNumTags) const
+WEAVE_ERROR TraitSchemaEngine::GetRelativePathTags(const PropertyPathHandle aCandidateHandle, uint64_t * aTags,
+ const uint32_t aTagsSize, uint32_t & aNumTags) const
{
PropertyPathHandle pathWalkStore[mSchema.mTreeDepth];
- uint32_t pathWalkDepth = 0;
+ uint32_t pathWalkDepth = 0;
PropertyPathHandle curProperty;
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -468,7 +463,7 @@
while (pathWalkDepth)
{
PropertyPathHandle curHandle = pathWalkStore[pathWalkDepth - 1];
- aTags[aNumTags] = GetTag(curHandle);
+ aTags[aNumTags] = GetTag(curHandle);
pathWalkDepth--;
aNumTags++;
}
@@ -479,7 +474,8 @@
}
#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
-WEAVE_ERROR TraitSchemaEngine::StoreData(PropertyPathHandle aHandle, TLVReader & aReader, ISetDataDelegate * aDelegate, IPathFilter * apPathFilter) const
+WEAVE_ERROR TraitSchemaEngine::StoreData(PropertyPathHandle aHandle, TLVReader & aReader, ISetDataDelegate * aDelegate,
+ IPathFilter * apPathFilter) const
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
TLVType type = kTLVType_NotSpecified;
@@ -498,7 +494,7 @@
// The logic further below deals with the cases where this function was called on a path handle at the dictionary or higher.
if (IsInDictionary(curHandle, dictionaryItemHandle))
{
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryItemModifyBegin, dictionaryItemHandle);
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryItemModifyBegin, dictionaryItemHandle);
dictionaryEventSignalled = true;
}
@@ -516,29 +512,40 @@
// ascension is returning back to a higher point in the tree.
do
{
- if (!(apPathFilter != NULL && apPathFilter->FilterPath(curHandle))) {
+ if (!(apPathFilter != NULL && apPathFilter->FilterPath(curHandle)))
+ {
#if TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
if (!IsNullPropertyPathHandle(curHandle))
#endif
{
- if (!IsLeaf(curHandle)) {
- if (descending) {
+ if (!IsLeaf(curHandle))
+ {
+ if (descending)
+ {
bool enterContainer = (aReader.GetType() != kTLVType_Null);
- if (enterContainer) {
+ if (enterContainer)
+ {
err = aReader.EnterContainer(type);
SuccessOrExit(err);
parentHandle = curHandle;
- } else {
- if (IsNullable(curHandle)) {
+ }
+ else
+ {
+ if (IsNullable(curHandle))
+ {
err = aDelegate->SetData(curHandle, aReader, !enterContainer);
- } else {
+ }
+ else
+ {
err = WEAVE_ERROR_WDM_SCHEMA_MISMATCH;
}
SuccessOrExit(err);
}
}
- } else {
+ }
+ else
+ {
err = aDelegate->SetData(curHandle, aReader, aReader.GetType() == kTLVType_Null);
SuccessOrExit(err);
@@ -548,18 +555,22 @@
}
}
- if (!descending) {
- if (IsDictionary(curHandle)) {
+ if (!descending)
+ {
+ if (IsDictionary(curHandle))
+ {
// We can surmise this is a replace if we're ascending to a node that is a dictionary, and that node
// is lower than the target node this function was directed at (we can't get to this point in code if the
// two handles (target and current) are equivalent to each other).
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryReplaceEnd, curHandle);
- } else if (IsDictionary(parentHandle)) {
- // We can surmise this is a modify/add if we're ascending to a node whose parent is a dictionary, and that node
- // is lower than the target node this function was directed at (we can't get to this point in code if the
- // two handles (target and current) are equivalent to each other). Those cases are handled by the two 'if'
- // statements at the top and bottom of this function.
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryItemModifyEnd, curHandle);
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryReplaceEnd, curHandle);
+ }
+ else if (IsDictionary(parentHandle))
+ {
+ // We can surmise this is a modify/add if we're ascending to a node whose parent is a dictionary, and that
+ // node is lower than the target node this function was directed at (we can't get to this point in code if
+ // the two handles (target and current) are equivalent to each other). Those cases are handled by the two
+ // 'if' statements at the top and bottom of this function.
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryItemModifyEnd, curHandle);
}
}
}
@@ -568,45 +579,54 @@
err = aReader.Next();
VerifyOrExit((err == WEAVE_NO_ERROR) || (err == WEAVE_END_OF_TLV), );
- if (err == WEAVE_END_OF_TLV) {
+ if (err == WEAVE_END_OF_TLV)
+ {
// We've hit the end of the container - exit out and point our current handle to its parent.
// In the process, restore the parentHandle as well.
err = aReader.ExitContainer(type);
SuccessOrExit(err);
- curHandle = parentHandle;
+ curHandle = parentHandle;
parentHandle = GetParent(curHandle);
descending = false;
- } else {
+ }
+ else
+ {
const uint64_t tag = aReader.GetTag();
descending = true;
- if (IsProfileTag(tag)) {
- VerifyOrExit(ProfileIdFromTag(tag) == kWeaveProfile_DictionaryKey,
- err = WEAVE_ERROR_INVALID_TLV_TAG);
+ if (IsProfileTag(tag))
+ {
+ VerifyOrExit(ProfileIdFromTag(tag) == kWeaveProfile_DictionaryKey, err = WEAVE_ERROR_INVALID_TLV_TAG);
curHandle = GetDictionaryItemHandle(parentHandle, TagNumFromTag(tag));
- } else {
+ }
+ else
+ {
curHandle = GetChildHandle(parentHandle, TagNumFromTag(tag));
}
- if (!(apPathFilter != NULL && apPathFilter->FilterPath(curHandle))) {
- if (IsDictionary(curHandle)) {
+ if (!(apPathFilter != NULL && apPathFilter->FilterPath(curHandle)))
+ {
+ if (IsDictionary(curHandle))
+ {
// If we're descending onto a node that is a dictionary, we know for certain that it is a replace operation
// since the target path handle for this function was higher in the tree than the node representing the
// dictionary itself.
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryReplaceBegin, curHandle);
- } else if (IsDictionary(parentHandle)) {
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryReplaceBegin, curHandle);
+ }
+ else if (IsDictionary(parentHandle))
+ {
// Alternatively, if we're descending onto a node whose parent is a dictionary, we know that this node
- // represents an element in the dictionary and as such, is an appropriate point in the traversal to notify the
- // application of an upcoming dictionary item modification/insertion.
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryItemModifyBegin,
- curHandle);
+ // represents an element in the dictionary and as such, is an appropriate point in the traversal to notify
+ // the application of an upcoming dictionary item modification/insertion.
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryItemModifyBegin, curHandle);
}
}
#if !TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
- if (IsNullPropertyPathHandle(curHandle)) {
+ if (IsNullPropertyPathHandle(curHandle))
+ {
err = WEAVE_ERROR_TLV_TAG_NOT_FOUND;
break;
}
@@ -617,7 +637,7 @@
if (dictionaryEventSignalled)
{
- aDelegate->OnDataSinkEvent(ISetDataDelegate::kDataSinkEvent_DictionaryItemModifyEnd, dictionaryItemHandle);
+ aDelegate->OnSetDataEvent(ISetDataDelegate::kSetDataEvent_DictionaryItemModifyEnd, dictionaryItemHandle);
}
exit:
@@ -633,8 +653,7 @@
{
bool retval = false;
- VerifyOrExit(aChildHandle != kNullPropertyPathHandle &&
- aParentHandle != kNullPropertyPathHandle, );
+ VerifyOrExit(aChildHandle != kNullPropertyPathHandle && aParentHandle != kNullPropertyPathHandle, );
do
{
@@ -996,15 +1015,15 @@
{
if (aVersion != mVersion)
{
- WeaveLogDetail(DataManagement, "Trait %08x version: 0x%" PRIx64 " -> 0x%" PRIx64 "", mSchemaEngine->GetProfileId(), mVersion,
- aVersion);
+ WeaveLogDetail(DataManagement, "Trait %08x version: 0x%" PRIx64 " -> 0x%" PRIx64 "", mSchemaEngine->GetProfileId(),
+ mVersion, aVersion);
}
}
else
{
WeaveLogDetail(DataManagement, "Trait %08x version: n/a -> 0x%" PRIx64 "", mSchemaEngine->GetProfileId(), aVersion);
}
- mVersion = aVersion;
+ mVersion = aVersion;
mHasValidVersion = true;
}
@@ -1016,8 +1035,8 @@
void TraitDataSink::SetLastNotifyVersion(uint64_t aVersion)
{
- WeaveLogDetail(DataManagement, "Trait %08x last notify version: 0x%" PRIx64 " -> 0x%" PRIx64 "", mSchemaEngine->GetProfileId(), mLastNotifyVersion,
- aVersion);
+ WeaveLogDetail(DataManagement, "Trait %08x last notify version: 0x%" PRIx64 " -> 0x%" PRIx64 "", mSchemaEngine->GetProfileId(),
+ mLastNotifyVersion, aVersion);
mLastNotifyVersion = aVersion;
}
@@ -1027,10 +1046,10 @@
TraitDataSink::TraitDataSink(const TraitSchemaEngine * aEngine)
{
- mSchemaEngine = aEngine;
- mVersion = 0;
+ mSchemaEngine = aEngine;
+ mVersion = 0;
mLastNotifyVersion = 0;
- mHasValidVersion = 0;
+ mHasValidVersion = 0;
}
WEAVE_ERROR TraitDataSink::StoreDataElement(PropertyPathHandle aHandle, TLVReader & aReader, uint8_t aFlags,
@@ -1130,8 +1149,8 @@
}
else
{
- WeaveLogDetail(DataManagement, "<StoreData> [Trait %08x] version: 0x%" PRIx64 " (no-change)",
- mSchemaEngine->GetProfileId(), mVersion);
+ WeaveLogDetail(DataManagement, "<StoreData> [Trait %08x] version: 0x%" PRIx64 " (no-change)", mSchemaEngine->GetProfileId(),
+ mVersion);
}
if (aFlags & kLastElementInChange)
@@ -1143,25 +1162,25 @@
return err;
}
-void TraitDataSink::OnDataSinkEvent(DataSinkEventType aEventType, PropertyPathHandle aHandle)
+void TraitDataSink::OnSetDataEvent(SetDataEventType aEventType, PropertyPathHandle aHandle)
{
EventType event;
switch (aEventType)
{
- case kDataSinkEvent_DictionaryReplaceBegin:
+ case kSetDataEvent_DictionaryReplaceBegin:
event = kEventDictionaryReplaceBegin;
break;
- case kDataSinkEvent_DictionaryReplaceEnd:
+ case kSetDataEvent_DictionaryReplaceEnd:
event = kEventDictionaryReplaceEnd;
break;
- case kDataSinkEvent_DictionaryItemModifyBegin:
+ case kSetDataEvent_DictionaryItemModifyBegin:
event = kEventDictionaryItemModifyBegin;
break;
- case kDataSinkEvent_DictionaryItemModifyEnd:
+ case kSetDataEvent_DictionaryItemModifyEnd:
event = kEventDictionaryItemModifyEnd;
break;
@@ -1215,8 +1234,9 @@
uint64_t TraitDataSource::GetVersion(void)
{
- // At the time of version retrieval, check to see if the version is still at the sentinel value of 0 (indicating 'no version') set at construction. If it is,
- // it means that the data source has not over-ridden the version to something other than 0, indicating that it desires to use randomized data versions.
+ // At the time of version retrieval, check to see if the version is still at the sentinel value of 0 (indicating 'no version')
+ // set at construction. If it is, it means that the data source has not over-ridden the version to something other than 0,
+ // indicating that it desires to use randomized data versions.
while (mVersion == 0)
{
mVersion = GetRandU64();
@@ -1263,8 +1283,7 @@
* object.
*/
void TraitDataSource::OnCustomCommand(Command * aCommand, const nl::Weave::WeaveMessageInfo * aMsgInfo,
- nl::Weave::PacketBuffer * aPayload,
- nl::Weave::TLV::TLVReader & aArgumentReader)
+ nl::Weave::PacketBuffer * aPayload, nl::Weave::TLV::TLVReader & aArgumentReader)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -1344,27 +1363,33 @@
return SubscriptionEngine::GetInstance()->Unlock();
}
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+WEAVE_ERROR TraitDataSource::Unlock(bool aSkipVersionIncrement)
+{
+ if (mManagedVersion && mSetDirtyCalled && !aSkipVersionIncrement)
+ {
+ IncrementVersion();
+ }
+
+ VerifyOrDie(SubscriptionEngine::GetInstance());
+ return SubscriptionEngine::GetInstance()->Unlock();
+}
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
TraitUpdatableDataSink::TraitUpdatableDataSink(const TraitSchemaEngine * aEngine) :
- TraitDataSink(aEngine),
- mUpdateRequiredVersion(0),
- mUpdateStartVersion(0),
- mConditionalUpdate(false),
- mPotentialDataLoss(false),
- mpSubClient(NULL),
- mpUpdateEncoder(NULL)
-{
-};
+ TraitDataSink(aEngine), mUpdateRequiredVersion(0), mUpdateStartVersion(0), mConditionalUpdate(false), mPotentialDataLoss(false),
+ mpSubClient(NULL), mpUpdateEncoder(NULL) { };
void TraitUpdatableDataSink::Lock(SubscriptionClient * apSubClient)
{
- VerifyOrDie(apSubClient!=NULL);
+ VerifyOrDie(apSubClient != NULL);
apSubClient->LockUpdateMutex();
}
void TraitUpdatableDataSink::Unlock(SubscriptionClient * apSubClient)
{
- VerifyOrDie(apSubClient!=NULL);
+ VerifyOrDie(apSubClient != NULL);
apSubClient->UnlockUpdateMutex();
}
@@ -1383,12 +1408,12 @@
return err;
}
-void TraitUpdatableDataSink::SetUpdateRequiredVersion(const uint64_t &aUpdateRequiredVersion)
+void TraitUpdatableDataSink::SetUpdateRequiredVersion(const uint64_t & aUpdateRequiredVersion)
{
if (aUpdateRequiredVersion != mUpdateRequiredVersion)
{
WeaveLogDetail(DataManagement, "[Trait %08x] UpdateRequiredVersion: 0x%" PRIx64 " -> 0x%" PRIx64 "",
- mSchemaEngine->GetProfileId(), mUpdateRequiredVersion, aUpdateRequiredVersion);
+ mSchemaEngine->GetProfileId(), mUpdateRequiredVersion, aUpdateRequiredVersion);
mUpdateRequiredVersion = aUpdateRequiredVersion;
// TODO: Ideally, this fault would be injected when the payload is encoded; but, all DataElements for the
@@ -1406,16 +1431,13 @@
if (GetVersion() != mUpdateStartVersion)
{
WeaveLogDetail(DataManagement, "[Trait %08x] UpdateStartVersion: 0x%" PRIx64 " -> 0x%" PRIx64 "",
- mSchemaEngine->GetProfileId(), mUpdateStartVersion, GetVersion());
+ mSchemaEngine->GetProfileId(), mUpdateStartVersion, GetVersion());
mUpdateStartVersion = GetVersion();
}
}
-WEAVE_ERROR TraitUpdatableDataSink::ReadData(TraitDataHandle aTraitDataHandle,
- PropertyPathHandle aHandle,
- uint64_t aTagToWrite,
- TLVWriter & aWriter,
- PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom)
+WEAVE_ERROR TraitUpdatableDataSink::ReadData(TraitDataHandle aTraitDataHandle, PropertyPathHandle aHandle, uint64_t aTagToWrite,
+ TLVWriter & aWriter, PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -1423,14 +1445,13 @@
{
WeaveLogDetail(DataManagement, "process dictionary in update");
err = mSchemaEngine->RetrieveUpdatableDictionaryData(aHandle, aTagToWrite, aWriter,
- static_cast<TraitSchemaEngine::IGetDataDelegate*>(this),
+ static_cast<TraitSchemaEngine::IGetDataDelegate *>(this),
aPropertyPathHandleOfDictItemToStartFrom);
}
else
{
UpdateDictionaryDirtyPathCut updateDirtyPathCut(aTraitDataHandle, GetUpdateEncoder());
- err = mSchemaEngine->RetrieveData(aHandle, aTagToWrite, aWriter,
- static_cast<TraitSchemaEngine::IGetDataDelegate *>(this),
+ err = mSchemaEngine->RetrieveData(aHandle, aTagToWrite, aWriter, static_cast<TraitSchemaEngine::IGetDataDelegate *>(this),
&updateDirtyPathCut);
}
SuccessOrExit(err);
@@ -1467,7 +1488,8 @@
* @retval WEAVE_ERROR_WDM_PATH_STORE_FULL if there is no memory to store the path.
* @retval Other WEAVE_ERROR codes depending on the failure.
*/
-WEAVE_ERROR TraitUpdatableDataSink::SetUpdated(SubscriptionClient * apSubClient, PropertyPathHandle aPropertyHandle, bool aIsConditional)
+WEAVE_ERROR TraitUpdatableDataSink::SetUpdated(SubscriptionClient * apSubClient, PropertyPathHandle aPropertyHandle,
+ bool aIsConditional)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
@@ -1479,5 +1501,120 @@
exit:
return err;
}
-
#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+TraitUpdatableDataSource::OnChangeRejection TraitUpdatableDataSource::sChangeRejectionCb = NULL;
+void * TraitUpdatableDataSource::sChangeRejectionContext = NULL;
+
+TraitUpdatableDataSource::TraitUpdatableDataSource(const TraitSchemaEngine * aEngine) : TraitDataSource(aEngine) { }
+
+WEAVE_ERROR TraitUpdatableDataSource::StoreDataElement(PropertyPathHandle aHandle, TLVReader & aReader, uint8_t aFlags,
+ OnChangeRejection aFunc, void * aContext)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ DataElement::Parser parser;
+ bool dataPresent = false, deletePresent = false;
+
+ err = parser.Init(aReader);
+ SuccessOrExit(err);
+
+ err = parser.CheckPresence(&dataPresent, &deletePresent);
+ SuccessOrExit(err);
+
+ if (deletePresent)
+ {
+ err = parser.GetDeletedDictionaryKeys(&aReader);
+ SuccessOrExit(err);
+
+ while ((err = aReader.Next()) == WEAVE_NO_ERROR)
+ {
+ PropertyDictionaryKey key;
+ PropertyPathHandle handle;
+
+ err = aReader.Get(key);
+ SuccessOrExit(err);
+
+ // In the case of a delete, the path is usually directed to the dictionary itself. We
+ // need to get the handle to the child dictionary element handle first before we can
+ // pass it up to the application.
+ handle = mSchemaEngine->GetFirstChild(aHandle);
+ VerifyOrExit(handle != kNullPropertyPathHandle, err = WEAVE_ERROR_INVALID_ARGUMENT);
+
+ handle = CreatePropertyPathHandle(GetPropertySchemaHandle(handle), key);
+ OnEvent(kEventDictionaryItemDelete, &handle);
+ }
+
+ VerifyOrExit(err == WEAVE_NO_ERROR || err == WEAVE_END_OF_TLV, );
+ err = WEAVE_NO_ERROR;
+ }
+
+ if (aHandle != kNullPropertyPathHandle && dataPresent)
+ {
+ err = parser.GetData(&aReader);
+ SuccessOrExit(err);
+ err = mSchemaEngine->StoreData(aHandle, aReader, this, NULL);
+ SuccessOrExit(err);
+ }
+
+exit:
+ return err;
+}
+
+void TraitUpdatableDataSource::OnSetDataEvent(SetDataEventType aEventType, PropertyPathHandle aHandle)
+{
+ EventType event;
+
+ switch (aEventType)
+ {
+ case kSetDataEvent_DictionaryReplaceBegin:
+ event = kEventDictionaryReplaceBegin;
+ break;
+
+ case kSetDataEvent_DictionaryReplaceEnd:
+ event = kEventDictionaryReplaceEnd;
+ break;
+
+ case kSetDataEvent_DictionaryItemModifyBegin:
+ event = kEventDictionaryItemModifyBegin;
+ break;
+
+ case kSetDataEvent_DictionaryItemModifyEnd:
+ event = kEventDictionaryItemModifyEnd;
+ break;
+
+ default:
+ return;
+ };
+
+ OnEvent(event, &aHandle);
+}
+
+void TraitUpdatableDataSource::RejectChange(uint16_t aRejectionStatusCode)
+{
+ if (sChangeRejectionCb)
+ {
+ sChangeRejectionCb(aRejectionStatusCode, GetVersion(), sChangeRejectionContext);
+ }
+}
+
+WEAVE_ERROR TraitUpdatableDataSource::SetData(PropertyPathHandle aHandle, TLVReader & aReader, bool aIsNull)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ // if a trait has no nullable handles, aIsNull will always be false
+ // and serves no purpose. this is true for the default implementation.
+ IgnoreUnusedVariable(aIsNull);
+
+ if (mSchemaEngine->IsLeaf(aHandle))
+ {
+ err = SetLeafData(aHandle, aReader);
+ if (err != WEAVE_NO_ERROR)
+ {
+ WeaveLogDetail(DataManagement, "ahandle %u err: %d", aHandle, err);
+ }
+ }
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
diff --git a/src/lib/profiles/data-management/Current/TraitData.h b/src/lib/profiles/data-management/Current/TraitData.h
index 2ffde51..2b1b0dd 100644
--- a/src/lib/profiles/data-management/Current/TraitData.h
+++ b/src/lib/profiles/data-management/Current/TraitData.h
@@ -72,7 +72,6 @@
typedef uint16_t PropertyDictionaryKey;
typedef uint16_t TraitDataHandle;
-
/* Reserved property path handles that have special meaning */
enum
{
@@ -120,15 +119,14 @@
class UpdateDirtyPathFilter : public IPathFilter
{
public:
- UpdateDirtyPathFilter(SubscriptionClient *apSubClient,
- TraitDataHandle traitDataHandle,
+ UpdateDirtyPathFilter(SubscriptionClient * apSubClient, TraitDataHandle traitDataHandle,
const TraitSchemaEngine * aSchemaEngine);
- virtual bool FilterPath (PropertyPathHandle aPathhandle);
+ virtual bool FilterPath(PropertyPathHandle aPathhandle);
private:
- SubscriptionClient *mpSubClient;
+ SubscriptionClient * mpSubClient;
TraitDataHandle mTraitDataHandle;
- const TraitSchemaEngine *mSchemaEngine;
+ const TraitSchemaEngine * mSchemaEngine;
};
class IDirtyPathCut
@@ -145,11 +143,11 @@
class UpdateDictionaryDirtyPathCut : public IDirtyPathCut
{
public:
- UpdateDictionaryDirtyPathCut(TraitDataHandle aTraitDataHandle, UpdateEncoder *pEncoder);
- virtual WEAVE_ERROR CutPath (PropertyPathHandle aPathhandle, const TraitSchemaEngine * apEngine);
+ UpdateDictionaryDirtyPathCut(TraitDataHandle aTraitDataHandle, UpdateEncoder * pEncoder);
+ virtual WEAVE_ERROR CutPath(PropertyPathHandle aPathhandle, const TraitSchemaEngine * apEngine);
private:
- UpdateEncoder *mpUpdateEncoder;
+ UpdateEncoder * mpUpdateEncoder;
TraitDataHandle mTraitDataHandle;
};
@@ -183,23 +181,23 @@
struct Schema
{
uint32_t mProfileId; ///< The ID of the trait profile.
- const PropertyInfo * mSchemaHandleTbl; ///< A pointer to the schema handle table, which provides parent info and context tags
- ///< for each schema handle.
+ const PropertyInfo * mSchemaHandleTbl; ///< A pointer to the schema handle table, which provides parent info and context
+ ///< tags for each schema handle.
uint32_t mNumSchemaHandleEntries; ///< The number of schema handles in this trait.
uint32_t mTreeDepth; ///< The max depth of this schema.
#if (TDM_EXTENSION_SUPPORT) || (TDM_VERSIONING_SUPPORT)
- PropertyPathHandle mMaxParentPathHandle;///< Max handle supported by the parent schema
+ PropertyPathHandle mMaxParentPathHandle; ///< Max handle supported by the parent schema
#endif
- uint8_t * mIsDictionaryBitfield; ///< A bitfield indicating whether each schema handle is a dictionary or not.
- uint8_t * mIsOptionalBitfield; ///< A bitfield indicating whether each schema handle is optional or not.
- uint8_t * mIsImplementedBitfield; ///< A bitfield indicating whether each optional schema handle is implemented or not.
- uint8_t * mIsNullableBitfield; ///< A bitfield indicating whether each schema handle is nullable or not.
- uint8_t * mIsEphemeralBitfield; ///< A bitfield indicating whether each schema handle is ephemeral or not.
+ uint8_t * mIsDictionaryBitfield; ///< A bitfield indicating whether each schema handle is a dictionary or not.
+ uint8_t * mIsOptionalBitfield; ///< A bitfield indicating whether each schema handle is optional or not.
+ uint8_t * mIsImplementedBitfield; ///< A bitfield indicating whether each optional schema handle is implemented or not.
+ uint8_t * mIsNullableBitfield; ///< A bitfield indicating whether each schema handle is nullable or not.
+ uint8_t * mIsEphemeralBitfield; ///< A bitfield indicating whether each schema handle is ephemeral or not.
#if (TDM_EXTENSION_SUPPORT)
- Schema *mParentSchema; ///< A pointer to the parent schema
+ Schema * mParentSchema; ///< A pointer to the parent schema
#endif
#if (TDM_VERSIONING_SUPPORT)
- const ConstSchemaVersionRange *mVersionRange; ///< Range of versions supported by this trait
+ const ConstSchemaVersionRange * mVersionRange; ///< Range of versions supported by this trait
#endif
};
@@ -211,19 +209,19 @@
class ISetDataDelegate
{
public:
- enum DataSinkEventType
+ enum SetDataEventType
{
/* Start of replacement of an entire dictionary */
- kDataSinkEvent_DictionaryReplaceBegin,
+ kSetDataEvent_DictionaryReplaceBegin,
/* End of replacement of an entire dictionary */
- kDataSinkEvent_DictionaryReplaceEnd,
+ kSetDataEvent_DictionaryReplaceEnd,
/* Start of modification or addition of a dictionary item */
- kDataSinkEvent_DictionaryItemModifyBegin,
+ kSetDataEvent_DictionaryItemModifyBegin,
/* End of modification or addition of a dictionary item */
- kDataSinkEvent_DictionaryItemModifyEnd,
+ kSetDataEvent_DictionaryItemModifyEnd,
};
/**
@@ -260,7 +258,7 @@
* For dictionary item added/modififed events, these handles are property path handles as they contain the dictionary key as
* well.
*/
- virtual void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) = 0;
+ virtual void OnSetDataEvent(SetDataEventType aType, PropertyPathHandle aHandle) = 0;
};
class IGetDataDelegate
@@ -366,7 +364,8 @@
* @retval #WEAVE_NO_ERROR On success.
* @retval other Encountered errors parsing/processing the data.
*/
- WEAVE_ERROR StoreData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader & aReader, ISetDataDelegate * aDelegate, IPathFilter * aPathFilter) const;
+ WEAVE_ERROR StoreData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader & aReader, ISetDataDelegate * aDelegate,
+ IPathFilter * aPathFilter) const;
/**
* Given a path handle and a writer position on the corresponding data element, retrieve leaf data from the source and write it
@@ -376,10 +375,11 @@
* @retval other Encountered errors writing out the data.
*/
WEAVE_ERROR RetrieveData(PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter & aWriter,
- IGetDataDelegate * aDelegate, IDirtyPathCut * apDirtyPathCut=NULL) const;
+ IGetDataDelegate * aDelegate, IDirtyPathCut * apDirtyPathCut = NULL) const;
- WEAVE_ERROR RetrieveUpdatableDictionaryData(PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter & aWriter,
- IGetDataDelegate * aDelegate, PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom) const;
+ WEAVE_ERROR RetrieveUpdatableDictionaryData(PropertyPathHandle aHandle, uint64_t aTagToWrite,
+ nl::Weave::TLV::TLVWriter & aWriter, IGetDataDelegate * aDelegate,
+ PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom) const;
/**********
*
* Schema Query Functions
@@ -473,7 +473,8 @@
* @return WEAVE_NO_ERROR in case of success; WEAVE_ERROR_NO_MEMORY if aTags is too small
* to store the full path.
*/
- WEAVE_ERROR GetRelativePathTags(const PropertyPathHandle aCandidateHandle, uint64_t *aTags, const uint32_t aTagsSize, uint32_t &aNumTags) const;
+ WEAVE_ERROR GetRelativePathTags(const PropertyPathHandle aCandidateHandle, uint64_t * aTags, const uint32_t aTagsSize,
+ uint32_t & aNumTags) const;
/**
* Returns true if the passed in profileId matches that stored in the schema.
*
@@ -544,7 +545,8 @@
* aParseRes must be less than kContextTagMaxNum. If apEndptr is not NULL,
* it stores the address of the first "/" in *apEndptr.
*/
- WEAVE_ERROR ParseTagString(const char *apTagString, char **apEndptr, uint8_t& aParseRes) const;
+ WEAVE_ERROR ParseTagString(const char * apTagString, char ** apEndptr, uint8_t & aParseRes) const;
+
public:
const Schema mSchema;
};
@@ -558,10 +560,9 @@
* It takes in a pointer to a schema that it then uses to help decipher incoming TLV data from a publisher and invoke the
* relevant data setter calls to pass the data up to subclasses.
*/
-class TraitDataSink : private TraitSchemaEngine::ISetDataDelegate
+class TraitDataSink : protected TraitSchemaEngine::ISetDataDelegate
{
public:
-
TraitDataSink(const TraitSchemaEngine * aEngine);
virtual ~TraitDataSink() { }
const TraitSchemaEngine * GetSchemaEngine(void) const { return mSchemaEngine; }
@@ -585,7 +586,7 @@
* @retval other Encountered errors writing out the data.
*/
WEAVE_ERROR StoreDataElement(PropertyPathHandle aHandle, TLV::TLVReader & aReader, uint8_t aFlags, OnChangeRejection aFunc,
- void * aContext, TraitDataHandle aDatahandle=0);
+ void * aContext, TraitDataHandle aDatahandle = 0);
/**
* Retrieves the current version of the data that resides in this sink.
@@ -596,7 +597,7 @@
*/
bool IsVersionValid(void) const { return mHasValidVersion; }
- virtual bool IsVersionNewer(DataVersion &aVersion) { return aVersion != mVersion || false == mHasValidVersion; }
+ virtual bool IsVersionNewer(DataVersion & aVersion) { return aVersion != mVersion || false == mHasValidVersion; }
#if WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
/**
@@ -708,7 +709,7 @@
virtual WEAVE_ERROR OnEvent(uint16_t aType, void * aInEventParam) { return WEAVE_NO_ERROR; }
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
- virtual bool IsUpdatableDataSink(void) { return false; }
+ virtual bool IsUpdatableDataSink(void) { return false; }
virtual WEAVE_ERROR SetSubscriptionClient(SubscriptionClient * apSubClient) { return WEAVE_NO_ERROR; };
virtual WEAVE_ERROR SetUpdateEncoder(UpdateEncoder * apEncoder) { return WEAVE_NO_ERROR; };
@@ -743,7 +744,9 @@
* subscriptionless notifications.
*/
void SetAcceptsSubscriptionlessNotifications(const bool aAcceptsSublessNotifies)
- { mAcceptsSubscriptionlessNotifications = aAcceptsSublessNotifies; }
+ {
+ mAcceptsSubscriptionlessNotifications = aAcceptsSublessNotifies;
+ }
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
// Set current version of the data in this sink.
@@ -751,14 +754,13 @@
void SetLastNotifyVersion(uint64_t version);
uint64_t GetLastNotifyVersion(void) const { return mLastNotifyVersion; }
-
const TraitSchemaEngine * mSchemaEngine;
private:
// Current version of the data in this sink.
uint64_t mVersion;
uint64_t mLastNotifyVersion;
- void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) __OVERRIDE;
+ void OnSetDataEvent(SetDataEventType aType, PropertyPathHandle aHandle) __OVERRIDE;
static OnChangeRejection sChangeRejectionCb;
static void * sChangeRejectionContext;
bool mHasValidVersion;
@@ -768,7 +770,7 @@
#endif // WDM_ENABLE_SUBSCRIPTIONLESS_NOTIFICATION
};
-#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
+#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
/*
* @class TraitUpdatableDataSink
*
@@ -782,23 +784,33 @@
public:
TraitUpdatableDataSink(const TraitSchemaEngine * aEngine);
- WEAVE_ERROR ReadData(TraitDataHandle aTraitDataHandle, PropertyPathHandle aHandle, uint64_t aTagToWrite, TLV::TLVWriter & aWriter, PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom);
+ WEAVE_ERROR ReadData(TraitDataHandle aTraitDataHandle, PropertyPathHandle aHandle, uint64_t aTagToWrite,
+ TLV::TLVWriter & aWriter, PropertyPathHandle & aPropertyPathHandleOfDictItemToStartFrom);
virtual WEAVE_ERROR GetData(PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter & aWriter,
bool & aIsNull, bool & aIsPresent) __OVERRIDE;
- WEAVE_ERROR SetUpdated(SubscriptionClient * apSubClient, PropertyPathHandle aPropertyHandle, bool aIsConditional=false);
+ WEAVE_ERROR SetUpdated(SubscriptionClient * apSubClient, PropertyPathHandle aPropertyHandle, bool aIsConditional = false);
void Lock(SubscriptionClient * apSubClient);
void Unlock(SubscriptionClient * apSubClient);
virtual bool IsUpdatableDataSink(void) __OVERRIDE { return true; }
- virtual WEAVE_ERROR SetSubscriptionClient(SubscriptionClient * apSubClient) __OVERRIDE { mpSubClient = apSubClient; return WEAVE_NO_ERROR; }
- virtual WEAVE_ERROR SetUpdateEncoder(UpdateEncoder * apEncoder) __OVERRIDE { mpUpdateEncoder = apEncoder; return WEAVE_NO_ERROR; }
+ virtual WEAVE_ERROR SetSubscriptionClient(SubscriptionClient * apSubClient) __OVERRIDE
+ {
+ mpSubClient = apSubClient;
+ return WEAVE_NO_ERROR;
+ }
+ virtual WEAVE_ERROR SetUpdateEncoder(UpdateEncoder * apEncoder) __OVERRIDE
+ {
+ mpUpdateEncoder = apEncoder;
+ return WEAVE_NO_ERROR;
+ }
virtual SubscriptionClient * GetSubscriptionClient() __OVERRIDE { return mpSubClient; }
virtual UpdateEncoder * GetUpdateEncoder() __OVERRIDE { return mpUpdateEncoder; }
+
private:
friend class SubscriptionClient;
friend class UpdateEncoder;
@@ -810,13 +822,16 @@
* a version number that is lower than the current one. Please refer to the WDM
* specification for more details.
*/
- bool IsVersionNewer(DataVersion &aVersion) __OVERRIDE { return false == IsVersionValid() || aVersion > GetVersion() || aVersion < GetLastNotifyVersion(); }
+ bool IsVersionNewer(DataVersion & aVersion) __OVERRIDE
+ {
+ return false == IsVersionValid() || aVersion > GetVersion() || aVersion < GetLastNotifyVersion();
+ }
uint64_t GetUpdateRequiredVersion(void) const { return mUpdateRequiredVersion; }
void ClearUpdateRequiredVersion(void) { SetUpdateRequiredVersion(0); }
- void SetUpdateRequiredVersion(const uint64_t &aUpdateRequiredVersion);
+ void SetUpdateRequiredVersion(const uint64_t & aUpdateRequiredVersion);
uint64_t GetUpdateStartVersion(void) const { return mUpdateStartVersion; }
- void SetUpdateStartVersion (void);
+ void SetUpdateStartVersion(void);
void ClearUpdateStartVersion(void) { mUpdateStartVersion = 0; }
bool IsConditionalUpdate(void) { return mConditionalUpdate; }
@@ -832,7 +847,7 @@
SubscriptionClient * mpSubClient;
UpdateEncoder * mpUpdateEncoder;
};
-#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
+#endif // WEAVE_CONFIG_ENABLE_WDM_UPDATE
class Command;
@@ -856,6 +871,15 @@
void SetDirty(PropertyPathHandle aPropertyHandle);
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ WEAVE_ERROR Unlock(bool aSkipVersionIncrement);
+
+ virtual bool IsUpdatableDataSource(void) { return false; }
+
+ // Check if version is equal to the internal trait version
+ bool IsVersionEqual(DataVersion & aVersion) { return aVersion == GetVersion(); }
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
#if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT
void DeleteKey(PropertyPathHandle aPropertyHandle);
#endif
@@ -869,9 +893,12 @@
// API with all meta information housed within the Command
// object.
virtual void OnCustomCommand(Command * aCommand, const nl::Weave::WeaveMessageInfo * aMsgInfo,
- nl::Weave::PacketBuffer * aPayload,
- nl::Weave::TLV::TLVReader & aArgumentReader);
+ nl::Weave::PacketBuffer * aPayload, nl::Weave::TLV::TLVReader & aArgumentReader);
+ enum EventType
+ {
+ kEvent_DataSourceMax
+ };
/*
* Invoked either by the base class or by an external agent (like the subscription engine) to signal the occurrence of an event
* (of type EventType). Sub-classes are expected to over-ride this if they desire to be made known of these events.
@@ -915,7 +942,6 @@
// Increment current version of the data in this source.
void IncrementVersion(void);
-
// Controls whether mVersion is incremented automatically or not.
bool mManagedVersion;
@@ -928,6 +954,151 @@
bool mSetDirtyCalled;
};
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+/*
+ * @class TraitUpdatableDataSource
+ *
+ * @brief Base abstract class that represents a particular instance of a trait on a specific resource (publisher).
+ * Application developers are expected to subclass this to make a concrete source that apply data received from client
+ *
+ */
+class TraitUpdatableDataSource : public TraitDataSource, protected TraitSchemaEngine::ISetDataDelegate
+{
+public:
+ TraitUpdatableDataSource(const TraitSchemaEngine * aEngine);
+
+ typedef WEAVE_ERROR (*OnChangeRejection)(uint16_t aRejectionStatusCode, uint64_t aVersion, void * aContext);
+
+ /**
+ * Convenience function for data sinks to handle unknown leaf handles with
+ * a system level tolerance for mismatched schema as defined by
+ * TDM_DISABLE_STRICT_SCHEMA_COMPILANCE.
+ */
+ WEAVE_ERROR HandleUnknownLeafHandle(void)
+ {
+#if TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
+ return WEAVE_NO_ERROR;
+#else
+ return WEAVE_ERROR_TLV_TAG_NOT_FOUND;
+#endif
+ }
+
+ enum EventType
+ {
+ kEventChangeFirst = kEvent_DataSourceMax,
+
+ /* Signals the beginning of a change record which in certain scenarios can span multiple data elements over multiple
+ * update requests (the latter only a possibility if the data being transmitted is unable to fit within a single packet)
+ */
+ kEventChangeBegin,
+
+ /* Start of a data element */
+ kEventDataElementBegin,
+
+ /* End of a data element */
+ kEventDataElementEnd,
+
+ /* End of a change record */
+ kEventChangeEnd,
+
+ /* Start of replacement of an entire dictionary */
+ kEventDictionaryReplaceBegin,
+
+ /* End of replacement of an entire dictionary */
+ kEventDictionaryReplaceEnd,
+
+ /* Start of modification or addition of a dictionary item */
+ kEventDictionaryItemModifyBegin,
+
+ /* End of modification or addition of a dictionary item */
+ kEventDictionaryItemModifyEnd,
+
+ /* Deletion of a dictionary item */
+ kEventDictionaryItemDelete,
+
+ /* Signals the start of the processing of a update request packet
+ */
+ kEventUpdateRequestBegin,
+
+ /* Signals the end of the processing of a update request packet
+ */
+ kEventUpdateRequestEnd,
+
+ /* Signals the termination of a subscription either due to an error, or the subscription was cancelled */
+ kEventSubscriptionTerminated,
+
+ kEvent_UpdatableDataSourceMax
+ };
+
+ union InEventParam
+ {
+ struct
+ {
+ PropertyPathHandle mTargetHandle;
+ } mDictionaryReplaceBegin;
+
+ struct
+ {
+ PropertyPathHandle mTargetHandle;
+ } mDictionaryReplaceEnd;
+
+ struct
+ {
+ PropertyPathHandle mTargetHandle;
+ } mDictionaryItemModifyBegin;
+
+ struct
+ {
+ PropertyPathHandle mTargetHandle;
+ } mDictionaryItemModifyEnd;
+
+ struct
+ {
+ PropertyPathHandle mTargetHandle;
+ } mDictionaryItemDelete;
+ };
+
+ /**
+ * Given a reader that points to a data element conformant to a schema bound to this object, this method processes that data and
+ * invokes the relevant SetLeafData call below for all leaf items in the buffer.
+ *
+ * A change rejection function can be passed in as well that will be invoked if the updatable source chooses to reject this data
+ * for any reason.
+ *
+ * @retval #WEAVE_NO_ERROR On success.
+ * @retval other Encountered errors writing out the data.
+ */
+ WEAVE_ERROR StoreDataElement(PropertyPathHandle aHandle, TLV::TLVReader & aReader, uint8_t aFlags, OnChangeRejection aFunc,
+ void * aContext);
+ virtual bool IsUpdatableDataSource(void) __OVERRIDE { return true; }
+
+protected: // ISetDataDelegate
+ virtual WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader & aReader) __OVERRIDE = 0;
+
+ /*
+ * Defaults to calling SetLeafData if aHandle is a leaf. DataSinks
+ * can optionally implement this if they need to support nullable,
+ * ephemeral, or optional properties.
+ *
+ * TODO: make this the defacto API, moving all the logic from
+ * SetLeafData into this function.
+ */
+ virtual WEAVE_ERROR SetData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader & aReader, bool aIsNull) __OVERRIDE;
+
+ /* Subclass can invoke this if they desire to reject a particular data change */
+ void RejectChange(uint16_t aRejectionStatusCode);
+
+private:
+ friend class SubscriptionEngine;
+
+ void OnSetDataEvent(SetDataEventType aType, PropertyPathHandle aHandle) __OVERRIDE;
+
+private:
+ static OnChangeRejection sChangeRejectionCb;
+ static void * sChangeRejectionContext;
+};
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
}; // namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
}; // namespace Profiles
}; // namespace Weave
diff --git a/src/lib/profiles/status-report/StatusReportProfile.cpp b/src/lib/profiles/status-report/StatusReportProfile.cpp
index 085de6c..bcf805c 100644
--- a/src/lib/profiles/status-report/StatusReportProfile.cpp
+++ b/src/lib/profiles/status-report/StatusReportProfile.cpp
@@ -81,7 +81,7 @@
return WEAVE_NO_ERROR;
}
-WEAVE_ERROR StatusReport::pack(PacketBuffer *aBuffer)
+WEAVE_ERROR StatusReport::pack(PacketBuffer *aBuffer, uint32_t maxLen)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
MessageIterator i(aBuffer);
@@ -129,7 +129,7 @@
else
{
- err = mAdditionalInfo.pack(i);
+ err = mAdditionalInfo.pack(i, maxLen - 6);
}
exit:
diff --git a/src/lib/profiles/status-report/StatusReportProfile.h b/src/lib/profiles/status-report/StatusReportProfile.h
index e3cc58f..4f5affb 100644
--- a/src/lib/profiles/status-report/StatusReportProfile.h
+++ b/src/lib/profiles/status-report/StatusReportProfile.h
@@ -73,7 +73,7 @@
WEAVE_ERROR init(WEAVE_ERROR aError);
- WEAVE_ERROR pack(PacketBuffer *aBuffer);
+ WEAVE_ERROR pack(PacketBuffer *aBuffer, uint32_t maxLen = 0xFFFFFFFFUL);
uint16_t packedLength(void);
static WEAVE_ERROR parse(PacketBuffer *aBuffer, StatusReport &aDestination);
diff --git a/src/test-apps/Makefile.am b/src/test-apps/Makefile.am
index 9d35c48..801e077 100644
--- a/src/test-apps/Makefile.am
+++ b/src/test-apps/Makefile.am
@@ -1035,6 +1035,8 @@
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_01.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_02.py \
happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py \
+ happy/tests/standalone/wdmNext/test_weave_wdm_next_update_04.py \
+ happy/tests/standalone/wdmNext/test_weave_wdm_next_update_05.py \
$(NULL)
endif # WEAVE_RUN_HAPPY_WDM
@@ -1411,6 +1413,7 @@
TestWdmSubscriptionlessNotificationReceiver.cpp \
schema/nest/test/trait/TestATrait.cpp \
schema/nest/test/trait/TestBTrait.cpp \
+ schema/nest/test/trait/TestCTrait.cpp \
schema/nest/test/trait/TestETrait.cpp \
schema/nest/test/trait/TestCommon.cpp \
schema/weave/trait/locale/LocaleSettingsTrait.cpp \
@@ -1441,6 +1444,7 @@
MockEvents.cpp \
schema/nest/test/trait/TestATrait.cpp \
schema/nest/test/trait/TestBTrait.cpp \
+ schema/nest/test/trait/TestCTrait.cpp \
schema/nest/test/trait/TestETrait.cpp \
schema/nest/test/trait/TestCommon.cpp \
schema/weave/trait/locale/LocaleSettingsTrait.cpp \
@@ -1474,6 +1478,7 @@
MockSourceTraits.cpp \
schema/nest/test/trait/TestATrait.cpp \
schema/nest/test/trait/TestBTrait.cpp \
+ schema/nest/test/trait/TestCTrait.cpp \
schema/nest/test/trait/TestETrait.cpp \
schema/nest/test/trait/TestCommon.cpp \
schema/weave/trait/locale/LocaleSettingsTrait.cpp \
diff --git a/src/test-apps/MockSourceTraits.cpp b/src/test-apps/MockSourceTraits.cpp
index 3a59d9b..9c88e35 100644
--- a/src/test-apps/MockSourceTraits.cpp
+++ b/src/test-apps/MockSourceTraits.cpp
@@ -72,11 +72,16 @@
return strlen(src);
}
-LocaleSettingsTraitDataSource::LocaleSettingsTraitDataSource()
- : TraitDataSource(&LocaleSettingsTrait::TraitSchema)
+LocaleSettingsTraitDataSource::LocaleSettingsTraitDataSource():
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ TraitUpdatableDataSource(&LocaleSettingsTrait::TraitSchema)
+#else
+ TraitDataSource(&LocaleSettingsTrait::TraitSchema)
+#endif
{
SetVersion(300);
memset(mLocale, 0, sizeof(mLocale));
+ MOCK_strlcpy(mLocale, "en-US", sizeof(mLocale));
}
void LocaleSettingsTraitDataSource::Mutate()
@@ -94,6 +99,37 @@
Unlock();
}
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+WEAVE_ERROR
+LocaleSettingsTraitDataSource::SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ switch (aLeafHandle) {
+ case LocaleSettingsTrait::kPropertyHandle_active_locale:
+ char next_locale[24];
+ err = aReader.GetString(next_locale, MAX_LOCALE_SIZE);
+ SuccessOrExit(err);
+ if (strncmp(next_locale, mLocale, MAX_LOCALE_SIZE) != 0)
+ {
+ WeaveLogDetail(DataManagement, "<< active_locale is changed from \"%s\" to \"%s\"", mLocale, next_locale);
+ memcpy(mLocale, next_locale, MAX_LOCALE_SIZE);
+ }
+
+ WeaveLogDetail(DataManagement, "<< active_locale = \"%s\"", mLocale);
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, "<< UNKNOWN!");
+ err = WEAVE_ERROR_TLV_TAG_NOT_FOUND;
+ }
+
+exit:
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
WEAVE_ERROR
LocaleSettingsTraitDataSource::GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter)
{
@@ -119,14 +155,17 @@
}
LocaleCapabilitiesTraitDataSource::LocaleCapabilitiesTraitDataSource()
- : TraitDataSource(&LocaleCapabilitiesTrait::TraitSchema)
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ :TraitUpdatableDataSource(&LocaleCapabilitiesTrait::TraitSchema)
+#else
+ :TraitDataSource(&LocaleCapabilitiesTrait::TraitSchema)
+#endif
{
SetVersion(400);
- mNumLocales = 3;
- mLocales[0] = "pl-PL";
- mLocales[1] = "ja-JP";
- mLocales[2] = "fr-FR";
+ memcpy(mLocales[0], "pl-PL", MAX_LOCALE_SIZE);
+ memcpy(mLocales[1], "ja-JP", MAX_LOCALE_SIZE);
+ memcpy(mLocales[2], "fr-FR", MAX_LOCALE_SIZE);
}
void LocaleCapabilitiesTraitDataSource::Mutate()
@@ -136,20 +175,20 @@
switch (GetVersion() % 3) {
case 0:
mNumLocales = 2;
- mLocales[0] = "en-US";
- mLocales[1] = "zh-TW";
+ memcpy(mLocales[0], "en-US", MAX_LOCALE_SIZE);
+ memcpy(mLocales[1], "zh-TW", MAX_LOCALE_SIZE);
break;
case 1:
mNumLocales = 1;
- mLocales[0] = "zh-CN";
+ memcpy(mLocales[0], "zh-CN", MAX_LOCALE_SIZE);
break;
case 2:
mNumLocales = 3;
- mLocales[0] = "ja-JP";
- mLocales[1] = "pl-PL";
- mLocales[2] = "zh-CN";
+ memcpy(mLocales[0], "ja-JP", MAX_LOCALE_SIZE);
+ memcpy(mLocales[1], "pl-PL", MAX_LOCALE_SIZE);
+ memcpy(mLocales[2], "zh-CN", MAX_LOCALE_SIZE);
break;
}
@@ -158,6 +197,65 @@
Unlock();
}
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+WEAVE_ERROR
+LocaleCapabilitiesTraitDataSource::SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ char next_locale[kMaxNumOfCharsPerLocale];
+
+ if (LocaleCapabilitiesTrait::kPropertyHandle_available_locales == aLeafHandle)
+ {
+ nl::Weave::TLV::TLVType OuterContainerType;
+
+ // clear all locales
+ mNumLocales = 0;
+
+ VerifyOrExit(aReader.GetType() == nl::Weave::TLV::kTLVType_Array, err = WEAVE_ERROR_WRONG_TLV_TYPE);
+
+ err = aReader.EnterContainer(OuterContainerType);
+ SuccessOrExit(err);
+
+ while (WEAVE_NO_ERROR == (err = aReader.Next()))
+ {
+ VerifyOrExit(nl::Weave::TLV::kTLVType_UTF8String == aReader.GetType(), err = WEAVE_ERROR_WRONG_TLV_TYPE);
+ VerifyOrExit(nl::Weave::TLV::AnonymousTag == aReader.GetTag(), err = WEAVE_ERROR_INVALID_TLV_TAG);
+
+ err = aReader.GetString(next_locale, kMaxNumOfCharsPerLocale);
+ SuccessOrExit(err);
+ if (strncmp(next_locale, mLocales[mNumLocales], MAX_LOCALE_SIZE) != 0)
+ {
+ WeaveLogDetail(DataManagement, "<< locale[%u] is changed from [%s] to [%s]", mNumLocales, mLocales[mNumLocales], next_locale);
+ memcpy(mLocales[mNumLocales], next_locale, MAX_LOCALE_SIZE);
+ }
+
+ WeaveLogDetail(DataManagement, "<< locale[%u] = [%s]", mNumLocales, mLocales[mNumLocales]);
+
+ ++mNumLocales;
+
+ if (kMaxNumOfLocals == mNumLocales)
+ {
+ WeaveLogDetail(DataManagement, "Cannot handle more than %d locales, skip", kMaxNumOfLocals);
+ break;
+ }
+ }
+
+ // Note that ExitContainer internally skip all unread elements till the end of current container
+ err = aReader.ExitContainer(OuterContainerType);
+ SuccessOrExit(err);
+ }
+ else
+ {
+ WeaveLogDetail(DataManagement, "<< UNKNOWN!");
+ ExitNow(err = WEAVE_ERROR_INVALID_TLV_TAG);
+ }
+
+exit:
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
WEAVE_ERROR
LocaleCapabilitiesTraitDataSource::GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter)
{
@@ -245,9 +343,13 @@
return err;
}
-TestATraitDataSource::TestATraitDataSource()
- : TraitDataSource(&TestATrait::TraitSchema),
- mActiveCommand(NULL)
+TestATraitDataSource::TestATraitDataSource():
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ TraitUpdatableDataSource(&TestATrait::TraitSchema),
+#else
+ TraitDataSource(&TestATrait::TraitSchema),
+#endif
+ mActiveCommand(NULL)
{
uint8_t *tmp;
SetVersion(100);
@@ -748,6 +850,251 @@
}
}
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+WEAVE_ERROR
+TestATraitDataSource::SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ switch (GetPropertySchemaHandle(aLeafHandle)) {
+ case TestATrait::kPropertyHandle_TaA:
+ err = aReader.Get(taa);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_a = %u", taa);
+ break;
+
+ case TestATrait::kPropertyHandle_TaB:
+ err = aReader.Get(tab);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_b = %u", tab);
+ break;
+
+ case TestATrait::kPropertyHandle_TaC:
+ uint32_t next_tac;
+ err = aReader.Get(next_tac);
+ SuccessOrExit(err);
+ if (next_tac != tac)
+ {
+ WeaveLogDetail(DataManagement, "<< ta_c is changed from %u to %u", tac, next_tac);
+ tac = next_tac;
+ }
+
+ WeaveLogDetail(DataManagement, "<< ta_c = %u", tac);
+ break;
+
+ case TestATrait::kPropertyHandle_TaD_SaA:
+ uint32_t next_tad_saa;
+ err = aReader.Get(next_tad_saa);
+ SuccessOrExit(err);
+ if (next_tad_saa != tad.saA)
+ {
+ WeaveLogDetail(DataManagement, "<< ta_d.sa_a is changed from %u to %u", tad.saA, next_tad_saa);
+ tad.saA = next_tad_saa;
+ }
+
+ WeaveLogDetail(DataManagement, "<< ta_d.sa_a = %u", tad.saA);
+ break;
+
+ case TestATrait::kPropertyHandle_TaD_SaB:
+ bool next_tad_sab;
+ err = aReader.Get(next_tad_sab);
+ SuccessOrExit(err);
+ if (next_tad_sab != tad.saB)
+ {
+ WeaveLogDetail(DataManagement, "<< ta_d.sa_b is changed from %u to %u", tad.saB, next_tad_sab);
+ tad.saB = next_tad_sab;
+ }
+
+ WeaveLogDetail(DataManagement, "<< ta_d.sa_b = %u", tad.saB);
+ break;
+
+ case TestATrait::kPropertyHandle_TaE:
+ {
+ TLVType outerType;
+ uint32_t i = 0;
+
+ err = aReader.EnterContainer(outerType);
+ SuccessOrExit(err);
+
+ while (((err = aReader.Next()) == WEAVE_NO_ERROR) && (i < (sizeof(tae) / sizeof(tae[0])))) {
+ uint32_t next_tae;
+ err = aReader.Get(next_tae);
+ SuccessOrExit(err);
+ if (tae[i] != next_tae)
+ {
+ WeaveLogDetail(DataManagement, "<< ta_e[%u] is changed from %u to %u", i, tae[i], next_tae);
+ tae[i] = next_tae;
+ }
+
+ WeaveLogDetail(DataManagement, "<< ta_e[%u] = %u", i, tae[i]);
+ i++;
+ }
+
+ err = aReader.ExitContainer(outerType);
+ break;
+ }
+
+ case TestATrait::kPropertyHandle_TaG:
+ {
+ if (aReader.GetType() == kTLVType_UTF8String)
+ {
+ err = aReader.GetString(tag_string, sizeof(tag_string));
+ SuccessOrExit(err);
+
+ tag_use_ref = false;
+
+ WeaveLogDetail(DataManagement, "<< ta_g string = %s", tag_string);
+ }
+ else
+ {
+ err = aReader.Get(tag_ref);
+ SuccessOrExit(err);
+
+ tag_use_ref = true;
+
+ WeaveLogDetail(DataManagement, "<< ta_g ref = %u", tag_ref);
+ }
+ }
+ break;
+
+ case TestATrait::kPropertyHandle_TaK:
+ err = aReader.GetBytes(&tak[0], sizeof(tak));
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_k %d bytes", sizeof(tak));
+ break;
+
+ case TestATrait::kPropertyHandle_TaL:
+ err = aReader.Get(tal);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_l = %x", tal);
+ break;
+
+ case TestATrait::kPropertyHandle_TaM:
+ err = aReader.Get(tam_resourceid);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_m = %" PRIx64 , tam_resourceid);
+ break;
+
+ case TestATrait::kPropertyHandle_TaN:
+ err = aReader.GetBytes(&tan[0], sizeof(tan));
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_n %d bytes", sizeof(tan));
+ DumpMemory(&tan[0], sizeof(tan), "WEAVE:DMG: << ta_n ", 16);
+ break;
+
+ case TestATrait::kPropertyHandle_TaO:
+ err = aReader.Get(tao);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_o = %d", tao);
+ break;
+
+ case TestATrait::kPropertyHandle_TaP:
+ int64_t next_tap;
+ err = aReader.Get(next_tap);
+ SuccessOrExit(err);
+
+ if (next_tap != tap)
+ {
+ WeaveLogDetail(DataManagement, "<< ta_p is changed from %d to %d", tap, next_tap);
+ tap = next_tap;
+ }
+ WeaveLogDetail(DataManagement, "<< ta_p = %d", tap);
+ break;
+
+ case TestATrait::kPropertyHandle_TaQ:
+ err = aReader.Get(taq);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_q %" PRId64 , taq);
+ break;
+
+ case TestATrait::kPropertyHandle_TaR:
+ err = aReader.Get(tar);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_r %u", tar);
+ break;
+
+ case TestATrait::kPropertyHandle_TaS:
+ err = aReader.Get(tas);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_s %u", tas);
+ break;
+
+ case TestATrait::kPropertyHandle_TaT:
+ err = aReader.Get(tat);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_t %u", tat);
+ break;
+
+ case TestATrait::kPropertyHandle_TaU:
+ err = aReader.Get(tau);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_u %d", tau);
+ break;
+
+ case TestATrait::kPropertyHandle_TaV:
+ err = aReader.Get(tav);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_v %u", tav);
+ break;
+
+ case TestATrait::kPropertyHandle_TaW:
+ err = aReader.GetString(&taw[0], sizeof(taw));
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_w %s", taw);
+ break;
+
+ case TestATrait::kPropertyHandle_TaX:
+ err = aReader.Get(tax);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< ta_x %d", tax);
+ break;
+
+ case TestATrait::kPropertyHandle_TaI_Value:
+ err = aReader.Get(tai_stageditem);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< tai[%u] = %u", GetPropertyDictionaryKey(aLeafHandle), tai_stageditem);
+ break;
+
+ case TestATrait::kPropertyHandle_TaJ_Value_SaA:
+ err = aReader.Get(taj_stageditem.saA);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< taj[%u].sa_a = %u", GetPropertyDictionaryKey(aLeafHandle), taj_stageditem.saA);
+ break;
+
+ case TestATrait::kPropertyHandle_TaJ_Value_SaB:
+ err = aReader.Get(taj_stageditem.saB);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< taj[%u].sa_b = %u", GetPropertyDictionaryKey(aLeafHandle), taj_stageditem.saB);
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, "<< UNKNOWN!");
+ }
+
+ exit:
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
WEAVE_ERROR TestATraitDataSource::GetData(PropertyPathHandle aHandle,
uint64_t aTagToWrite,
TLVWriter &aWriter,
@@ -1992,3 +2339,147 @@
return err;
}
+
+TestCTraitDataSource::TestCTraitDataSource():
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ TraitUpdatableDataSource(&TestCTrait::TraitSchema)
+#else
+ TraitDataSource(&TestCTrait::TraitSchema)
+#endif
+{
+ SetVersion(300);
+ taa = true;
+ tab = TestCTrait::ENUM_C_VALUE_1;
+ tac.scA= 3;
+ tac.scB = true;
+ tad = 4;
+}
+
+void TestCTraitDataSource::Mutate()
+{
+ Lock();
+
+ if ((GetVersion() % 2) == 0) {
+ SetDirty(TestCTrait::kPropertyHandle_TcA);
+ taa = !taa;
+ }
+ else
+ {
+ SetDirty(TestCTrait::kPropertyHandle_TcC_ScA);
+ SetDirty(TestCTrait::kPropertyHandle_TcC_ScB);
+ tac.scA ++;
+ tac.scB = !tac.scB;
+ }
+
+ Unlock();
+}
+
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+void TestCTraitDataSource::TLVPrettyPrinter(const char *aFormat, ...)
+{
+ va_list args;
+
+ va_start(args, aFormat);
+
+ vprintf(aFormat, args);
+
+ va_end(args);
+}
+
+WEAVE_ERROR
+TestCTraitDataSource::SetLeafData(PropertyPathHandle aLeafHandle, TLVReader &aReader)
+{
+
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+ switch (aLeafHandle) {
+ case TestCTrait::kPropertyHandle_TcA:
+ err = aReader.Get(taa);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< taa = %s", taa ? "true" : "false");
+ break;
+ case TestCTrait::kPropertyHandle_TcB:
+ err = aReader.Get(tab);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< tab %d", tab);
+ break;
+ case TestCTrait::kPropertyHandle_TcC_ScA:
+ err = aReader.Get(tac.scA);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< tac.scA %u", tac.scA);
+ break;
+ case TestCTrait::kPropertyHandle_TcC_ScB:
+ err = aReader.Get(tac.scB);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< tac.scB = %s", tac.scB ? "true" : "false");
+ break;
+ case TestCTrait::kPropertyHandle_TcD:
+ err = aReader.Get(tad);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, "<< tad %u", tad);
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, "<< UNKNOWN!");
+ err = WEAVE_ERROR_TLV_TAG_NOT_FOUND;
+ }
+
+exit:
+ return err;
+}
+
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
+WEAVE_ERROR
+TestCTraitDataSource::GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, TLVWriter &aWriter)
+{
+ WEAVE_ERROR err = WEAVE_NO_ERROR;
+
+ switch (aLeafHandle) {
+ case TestCTrait::kPropertyHandle_TcA:
+ err = aWriter.PutBoolean(aTagToWrite, taa);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, ">> taa = %s", taa ? "true" : "false");
+ break;
+ case TestCTrait::kPropertyHandle_TcB:
+ err = aWriter.Put(aTagToWrite, tab);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, ">> tab = %d", tab);
+ break;
+
+ case TestCTrait::kPropertyHandle_TcC_ScA:
+ err = aWriter.Put(aTagToWrite, tac.scA);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, ">> tac.scA = %u", tac.scA);
+ break;
+
+ case TestCTrait::kPropertyHandle_TcC_ScB:
+ err = aWriter.PutBoolean(aTagToWrite, taa);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, ">> tac.scB = %s", tac.scB ? "true" : "false");
+ break;
+ case TestCTrait::kPropertyHandle_TcD:
+ err = aWriter.Put(aTagToWrite, tad);
+ SuccessOrExit(err);
+
+ WeaveLogDetail(DataManagement, ">> tad = %u", tad);
+ break;
+
+ default:
+ WeaveLogDetail(DataManagement, ">> UNKNOWN!");
+ ExitNow(err = WEAVE_ERROR_TLV_TAG_NOT_FOUND);
+ }
+
+exit:
+ WeaveLogFunctError(err);
+
+ return err;
+}
diff --git a/src/test-apps/MockSourceTraits.h b/src/test-apps/MockSourceTraits.h
index d1c7af4..9e802a1 100644
--- a/src/test-apps/MockSourceTraits.h
+++ b/src/test-apps/MockSourceTraits.h
@@ -34,37 +34,58 @@
#include <weave/trait/locale/LocaleCapabilitiesTrait.h>
#include <nest/test/trait/TestATrait.h>
#include <nest/test/trait/TestBTrait.h>
+#include <nest/test/trait/TestCTrait.h>
+#include <nest/test/trait/TestDTrait.h>
#include <nest/test/trait/TestCommon.h>
#include "TestGroupKeyStore.h"
#include <map>
-class LocaleSettingsTraitDataSource : public nl::Weave::Profiles::DataManagement::TraitDataSource
+#define MAX_LOCALE_SIZE sizeof(char) * 24
+
+class LocaleSettingsTraitDataSource :
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ public nl::Weave::Profiles::DataManagement::TraitUpdatableDataSource
+#else
+ public nl::Weave::Profiles::DataManagement::TraitDataSource
+#endif
{
public:
LocaleSettingsTraitDataSource();
void Mutate();
private:
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ WEAVE_ERROR SetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
WEAVE_ERROR GetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE;
char mLocale[24];
};
-class LocaleCapabilitiesTraitDataSource : public nl::Weave::Profiles::DataManagement::TraitDataSource
+class LocaleCapabilitiesTraitDataSource :
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ public nl::Weave::Profiles::DataManagement::TraitUpdatableDataSource
+#else
+ public nl::Weave::Profiles::DataManagement::TraitDataSource
+#endif
{
public:
LocaleCapabilitiesTraitDataSource();
void Mutate();
private:
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ WEAVE_ERROR SetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
WEAVE_ERROR GetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE;
enum {
+ kMaxNumOfCharsPerLocale = 24,
kMaxNumOfLocals = 10,
};
uint8_t mNumLocales;
- const char * mLocales[kMaxNumOfLocals];
+ char mLocales[kMaxNumOfLocals][kMaxNumOfCharsPerLocale];
};
class BoltLockSettingTraitDataSource : public nl::Weave::Profiles::DataManagement::TraitDataSource
@@ -80,7 +101,12 @@
uint32_t mAutoRelockDuration;
};
-class TestATraitDataSource : public nl::Weave::Profiles::DataManagement::TraitDataSource
+class TestATraitDataSource :
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ public nl::Weave::Profiles::DataManagement::TraitUpdatableDataSource
+#else
+ public nl::Weave::Profiles::DataManagement::TraitDataSource
+#endif
{
public:
TestATraitDataSource();
@@ -89,6 +115,10 @@
uint32_t mTraitTestSet;
private:
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ WEAVE_ERROR SetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
void SetNullifiedPath(nl::Weave::Profiles::DataManagement::PropertyPathHandle aHandle, bool isNull);
WEAVE_ERROR GetData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter, bool &aIsNull, bool &aIsPresent) __OVERRIDE;
@@ -126,11 +156,12 @@
uint32_t tae[10];
// weave.common.StringRef is implemented as a union
- const char *tag_string = "stringreftest";
+ char *tag_string = "stringreftest";
uint16_t tag_ref;
bool tag_use_ref;
-
+ uint32_t tai_stageditem;
std::map<uint16_t, uint32_t> tai_map;
+ Schema::Nest::Test::Trait::TestATrait::StructA taj_stageditem;
std::map<uint16_t, Schema::Nest::Test::Trait::TestATrait::StructA> taj_map;
// byte array
@@ -155,7 +186,7 @@
uint32_t tat;
int32_t tau;
bool tav;
- const char *taw = "boxedstring";
+ char *taw = "boxedstring";
// boxed float
int16_t tax;
@@ -241,4 +272,27 @@
nl::Weave::Profiles::Security::AppKeys::WeaveGroupKey GroupMasterKeys[WEAVE_CONFIG_MAX_APPLICATION_GROUPS];
};
+class TestCTraitDataSource :
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ public nl::Weave::Profiles::DataManagement::TraitUpdatableDataSource
+#else
+ public nl::Weave::Profiles::DataManagement::TraitDataSource
+#endif
+{
+public:
+ TestCTraitDataSource();
+ void Mutate();
+ static void TLVPrettyPrinter(const char *aFormat, ...);
+private:
+#if WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+ WEAVE_ERROR SetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE;
+#endif // WDM_ENABLE_PUBLISHER_UPDATE_SERVER_SUPPORT
+
+ WEAVE_ERROR GetLeafData(nl::Weave::Profiles::DataManagement::PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE;
+ bool taa;
+ int32_t tab;
+ Schema::Nest::Test::Trait::TestCTrait::StructC tac;
+ uint32_t tad;
+};
+
#endif // MOCK_TRAIT_SOURCES_H_
diff --git a/src/test-apps/MockWdmSubscriptionInitiator.cpp b/src/test-apps/MockWdmSubscriptionInitiator.cpp
index 51b99d6..77d311c 100644
--- a/src/test-apps/MockWdmSubscriptionInitiator.cpp
+++ b/src/test-apps/MockWdmSubscriptionInitiator.cpp
@@ -1142,7 +1142,7 @@
break;
#if WEAVE_CONFIG_ENABLE_WDM_UPDATE
case SubscriptionClient::kEvent_OnUpdateComplete:
- if ((aInParam.mUpdateComplete.mReason == WEAVE_NO_ERROR) && (nl::Weave::Profiles::Common::kStatus_Success == aInParam.mUpdateComplete.mStatusCode))
+ if ((aInParam.mUpdateComplete.mReason == WEAVE_NO_ERROR) && (nl::Weave::Profiles::kWeaveProfile_Common == aInParam.mUpdateComplete.mStatusProfileId) && (nl::Weave::Profiles::Common::kStatus_Success == aInParam.mUpdateComplete.mStatusCode))
{
WeaveLogDetail(DataManagement, "Update: path result: success");
}
@@ -1156,8 +1156,6 @@
if (initiator->mUpdateDiscardOnError)
{
- TraitDataSink *sink = NULL;
- initiator->mSinkCatalog.Locate(aInParam.mUpdateComplete.mTraitDataHandle, &sink);
initiator->mSubscriptionClient->DiscardUpdates();
}
}
diff --git a/src/test-apps/MockWdmSubscriptionResponder.cpp b/src/test-apps/MockWdmSubscriptionResponder.cpp
index 469681c..e6be727 100644
--- a/src/test-apps/MockWdmSubscriptionResponder.cpp
+++ b/src/test-apps/MockWdmSubscriptionResponder.cpp
@@ -152,16 +152,18 @@
// publisher side
uint32_t mTimeBetweenLivenessCheckSec;
SingleResourceSourceTraitCatalog mSourceCatalog;
- SingleResourceSourceTraitCatalog::CatalogItem mSourceCatalogStore[6];
+ SingleResourceSourceTraitCatalog::CatalogItem mSourceCatalogStore[10];
// source traits
LocaleSettingsTraitDataSource mLocaleSettingsDataSource;
+ LocaleCapabilitiesTraitDataSource mLocaleCapabilitiesDataSource;
TestATraitDataSource mTestADataSource0;
TestATraitDataSource mTestADataSource1;
TestBTraitDataSource mTestBDataSource;
TestBLargeTraitDataSource mTestBLargeDataSource;
BoltLockSettingTraitDataSource mBoltLockSettingDataSource;
ApplicationKeysTraitDataSource mApplicationKeysTraitDataSource;
+ TestCTraitDataSource mTestCDataSource;
static void EngineEventCallback (void * const aAppState, SubscriptionEngine::EventID aEvent,
const SubscriptionEngine::InEventParam & aInParam, SubscriptionEngine::OutEventParam & aOutParam);
@@ -193,6 +195,8 @@
kLocaleSettingsTraitSourceIndex,
kBoltLockSettingTraitSourceIndex,
kApplicationKeysTraitSourceIndex,
+ kTestCTraitSourceIndex,
+ kLocaleCapabilitiesTraitSourceIndex,
kNumTraitHandles,
};
@@ -293,15 +297,6 @@
const nl::Weave::WeaveMessageInfo *aMsgInfo, uint32_t aProfileId,
uint8_t aMsgType, PacketBuffer *aPayload);
static void HandleCustomCommandTimeout(nl::Weave::System::Layer* aSystemLayer, void *aAppState, ::nl::Weave::System::Error aErr);
- static void IncomingUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload);
- static void IncomingPartialUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload);
- static void IncomingUpdateRequestHandler(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload);
};
static MockWdmSubscriptionResponderImpl gWdmSubscriptionResponder;
@@ -404,6 +399,8 @@
mSourceCatalog.Add(0, &mLocaleSettingsDataSource, mTraitHandleSet[kLocaleSettingsTraitSourceIndex]);
mSourceCatalog.Add(0, &mBoltLockSettingDataSource, mTraitHandleSet[kBoltLockSettingTraitSourceIndex]);
mSourceCatalog.Add(0, &mApplicationKeysTraitDataSource, mTraitHandleSet[kApplicationKeysTraitSourceIndex]);
+ mSourceCatalog.Add(0, &mTestCDataSource, mTraitHandleSet[kTestCTraitSourceIndex]);
+ mSourceCatalog.Add(0, &mLocaleCapabilitiesDataSource, mTraitHandleSet[kLocaleCapabilitiesTraitSourceIndex]);
switch (mTestCaseId)
{
@@ -478,16 +475,6 @@
mSinkAddressList[kTestBDataSinkIndex] = &mTestBDataSink;
mSinkAddressList[kLocaleCapabilitiesTraitSinkIndex] = &mLocaleCapabilitiesDataSink;
- err = mExchangeMgr->RegisterUnsolicitedMessageHandler(nl::Weave::Profiles::kWeaveProfile_WDM,
- kMsgType_UpdateRequest,
- IncomingUpdateRequest,
- this);
- SuccessOrExit(err);
- err = mExchangeMgr->RegisterUnsolicitedMessageHandler(nl::Weave::Profiles::kWeaveProfile_WDM,
- kMsgType_PartialUpdateRequest,
- IncomingPartialUpdateRequest,
- this);
- SuccessOrExit(err);
Command_End();
exit:
@@ -1080,160 +1067,6 @@
pResponder->Command_End(true);
}
-void MockWdmSubscriptionResponderImpl::IncomingUpdateRequestHandler(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload)
-{
- switch (msgType)
- {
- case kMsgType_UpdateRequest:
- IncomingUpdateRequest(ec, pktInfo, msgInfo, profileId, msgType, payload);
- break;
-
- case kMsgType_PartialUpdateRequest:
- IncomingPartialUpdateRequest(ec, pktInfo, msgInfo, profileId, msgType, payload);
- break;
-
- default:
- WeaveLogError(DataManagement, "Unexpected message with type 0x" PRIu8 "");
- PacketBuffer::Free(payload);
- ec->Close();
- break;
- }
-}
-
-void MockWdmSubscriptionResponderImpl::IncomingUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload)
-{
- WEAVE_ERROR err = WEAVE_NO_ERROR;
- nl::Weave::TLV::TLVReader reader;
- nl::Weave::TLV::TLVWriter writer;
- UpdateRequest::Parser parser;
- UpdateResponse::Builder updateResponseBuilder;
- StatusReport statusReport;
- uint8_t updateResponseBuf[512];
- ReferencedTLVData referenceTLVData;
- PacketBuffer * mBuf = PacketBuffer::NewWithAvailableSize(1024);
- MockWdmSubscriptionResponderImpl * pResponder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(ec->AppState);
-
- VerifyOrExit(NULL != pResponder, err = WEAVE_ERROR_INCORRECT_STATE);
-
- WeaveLogDetail(DataManagement, "Incoming Update Request, dumping it");
-
- reader.Init(payload);
- reader.Next();
- DebugPrettyPrint(reader);
-
- WeaveLogDetail(DataManagement, "constructing notification if subscription exists and status report");
-
- if (pResponder->mUpdateTiming != MockWdmNodeOptions::kTiming_NoSub)
- {
- pResponder->mLocaleSettingsDataSource.Mutate();
- SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run();
- }
-
- writer.Init(updateResponseBuf, sizeof(updateResponseBuf));
- err = updateResponseBuilder.Init(&writer);
- SuccessOrExit(err);
-
- {
- VersionList::Builder &lVLBuilder = updateResponseBuilder.CreateVersionListBuilder();
- lVLBuilder.AddVersion(pResponder->mLocaleSettingsDataSource.GetVersion());
- lVLBuilder.EndOfVersionList();
- SuccessOrExit(lVLBuilder.GetError());
- }
-
- {
- StatusList::Builder &lSLBuilder = updateResponseBuilder.CreateStatusListBuilder();
- lSLBuilder.AddStatus(nl::Weave::Profiles::kWeaveProfile_Common, nl::Weave::Profiles::Common::kStatus_Success);
- lSLBuilder.EndOfStatusList();
- SuccessOrExit(lSLBuilder.GetError());
- }
-
- updateResponseBuilder.EndOfResponse();
- SuccessOrExit(updateResponseBuilder.GetError());
-
- referenceTLVData.init(sizeof(updateResponseBuf), sizeof(updateResponseBuf), updateResponseBuf);
-
- statusReport.init(nl::Weave::Profiles::kWeaveProfile_Common, nl::Weave::Profiles::Common::kStatus_Success, &referenceTLVData);
- err = statusReport.pack(mBuf);
- SuccessOrExit(err);
-
- err = ec->SendMessage(nl::Weave::Profiles::kWeaveProfile_Common, nl::Weave::Profiles::Common::kMsgType_StatusReport, mBuf, nl::Weave::ExchangeContext::kSendFlag_RequestAck);
- mBuf = NULL;
- SuccessOrExit(err);
-
-exit:
- WeaveLogFunctError(err);
-
- if (NULL != payload)
- {
- PacketBuffer::Free(payload);
- payload = NULL;
- }
-
- if (NULL != mBuf)
- {
- PacketBuffer::Free(mBuf);
- mBuf = NULL;
- }
-
- if (NULL != ec)
- {
- ec->Close();
- }
-}
-
-void MockWdmSubscriptionResponderImpl::IncomingPartialUpdateRequest(nl::Weave::ExchangeContext *ec, const nl::Weave::IPPacketInfo *pktInfo,
- const nl::Weave::WeaveMessageInfo *msgInfo, uint32_t profileId,
- uint8_t msgType, PacketBuffer *payload)
-{
- WEAVE_ERROR err = WEAVE_NO_ERROR;
- nl::Weave::TLV::TLVReader reader;
- UpdateRequest::Parser parser;
- WeaveLogDetail(DataManagement, "Incoming PartialUpdate Request");
-
- // Set the handler on the EC, as we'll get more requests on this exchange.
- ec->OnMessageReceived = IncomingUpdateRequestHandler;
-
- reader.Init(payload);
- reader.Next();
- parser.Init(reader);
- parser.CheckSchemaValidity();
-
- reader.Init(payload);
- DebugPrettyPrint(reader);
-
- PacketBuffer * msgBuf = PacketBuffer::NewWithAvailableSize(0);
- VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY);
-
- err = ec->SendMessage(nl::Weave::Profiles::kWeaveProfile_WDM,
- nl::Weave::Profiles::DataManagement::kMsgType_UpdateContinue,
- msgBuf,
- nl::Weave::ExchangeContext::kSendFlag_RequestAck);
- msgBuf = NULL;
- SuccessOrExit(err);
-
-exit:
- WeaveLogFunctError(err);
-
- if (NULL != payload)
- {
- PacketBuffer::Free(payload);
- payload = NULL;
- }
-
- if (NULL != msgBuf)
- {
- PacketBuffer::Free(msgBuf);
- msgBuf = NULL;
- }
-
- // Don't close the EC; more requests fill follow.
- // TODO: we should close the EC on a timeout.
-}
-
void MockWdmSubscriptionResponderImpl::OnMessageReceivedForCustomCommand (nl::Weave::ExchangeContext *aEC, const nl::Inet::IPPacketInfo *aPktInfo,
const nl::Weave::WeaveMessageInfo *aMsgInfo, uint32_t aProfileId,
uint8_t aMsgType, PacketBuffer *aPayload)
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_01.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_01.py
index f6d6d05..b4839a3 100755
--- a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_01.py
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_01.py
@@ -57,13 +57,14 @@
wdm_next_args['client_clear_state_between_iterations'] = False
wdm_next_args['server_clear_state_between_iterations'] = False
- wdm_next_args['client_update_mutation'] = "OneLeaf"
+ wdm_next_args['client_update_mutation'] = "SameLevelLeaves"
wdm_next_args['client_update_conditionality'] = "Conditional"
- wdm_next_args['client_update_num_mutations'] = 1
+ wdm_next_args['client_update_num_mutations'] = 2
+ wdm_next_args['client_update_num_traits'] = 2
wdm_next_args['client_update_timing'] = "AfterSub"
- wdm_next_args['client_log_check'] = [('Update: path result: success', wdm_next_args['test_client_iterations'] * wdm_next_args['total_client_count'])]
- wdm_next_args['server_log_check'] = []
+ wdm_next_args['client_log_check'] = [('UpdateComplete event: 1', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['server_log_check'] = [('Send Update Response with profileId 0x0 statusCode 0x0', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
wdm_next_args['test_case_name'] = ['Update 01: Client creates mutual subscription, sends conditional update request to publisher, and receives notification and status report']
print 'test file: ' + self.__class__.__name__
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_02.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_02.py
index 7c231cd..815d529 100755
--- a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_02.py
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_02.py
@@ -57,13 +57,14 @@
wdm_next_args['client_clear_state_between_iterations'] = False
wdm_next_args['server_clear_state_between_iterations'] = False
- wdm_next_args['client_update_mutation'] = "OneLeaf"
+ wdm_next_args['client_update_mutation'] = "SameLevelLeaves"
wdm_next_args['client_update_conditionality'] = "Unconditional"
- wdm_next_args['client_update_num_mutations'] = 1
+ wdm_next_args['client_update_num_mutations'] = 2
+ wdm_next_args['client_update_num_traits'] = 2
wdm_next_args['client_update_timing'] = "AfterSub"
- wdm_next_args['client_log_check'] = [('Update: path result: success', wdm_next_args['test_client_iterations'] * wdm_next_args['total_client_count'])]
- wdm_next_args['server_log_check'] = []
+ wdm_next_args['client_log_check'] = [('UpdateComplete event: 1', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['server_log_check'] = [('Send Update Response with profileId 0x0 statusCode 0x0', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
wdm_next_args['test_case_name'] = ['Update 02: Client creates mutual subscription, sends unconditional update request to publisher, and receives notification and status report']
print 'test file: ' + self.__class__.__name__
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py
index 3ae7e53..f198f17 100755
--- a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_03.py
@@ -56,13 +56,14 @@
wdm_next_args['client_clear_state_between_iterations'] = False
wdm_next_args['server_clear_state_between_iterations'] = False
- wdm_next_args['client_update_mutation'] = "OneLeaf"
+ wdm_next_args['client_update_mutation'] = "SameLevelLeaves"
wdm_next_args['client_update_conditionality'] = "Unconditional"
- wdm_next_args['client_update_num_mutations'] = 1
+ wdm_next_args['client_update_num_mutations'] = 2
+ wdm_next_args['client_update_num_traits'] = 2
wdm_next_args['client_update_timing'] = "NoSub"
- wdm_next_args['client_log_check'] = [('Update: path result: success', wdm_next_args['test_client_iterations'] * wdm_next_args['total_client_count'])]
- wdm_next_args['server_log_check'] = []
+ wdm_next_args['client_log_check'] = [('UpdateComplete event: 1', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['server_log_check'] = [('Send Update Response with profileId 0x0 statusCode 0x0', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
wdm_next_args['test_case_name'] = ['Update 03: Client sends standalone unconditional update request to publisher, and receives status report']
print 'test file: ' + self.__class__.__name__
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_04.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_04.py
new file mode 100755
index 0000000..71629b8
--- /dev/null
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_04.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+
+
+#
+# Copyright (c) 2019 Google, LLC.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# @file
+# Calls Weave WDM Update between nodes.
+# Update 04: Client sends standalone unconditional update request to publisher during subscription, and receives
+# status report and notification.
+
+import unittest
+import set_test_path
+from weave_wdm_next_test_base import weave_wdm_next_test_base
+import WeaveUtilities
+
+
+class test_weave_wdm_next_update_04(weave_wdm_next_test_base):
+
+ def test_weave_wdm_next_mutual_subscribe_04(self):
+ wdm_next_args = {}
+ wdm_next_args['wdm_option'] = "mutual_subscribe"
+
+ wdm_next_args['total_client_count'] = 1
+ wdm_next_args['final_client_status'] = 0
+ wdm_next_args['timer_client_period'] = 10000
+ wdm_next_args['test_client_iterations'] = 1
+ wdm_next_args['test_client_delay'] = 2000
+ wdm_next_args['enable_client_flip'] = 1
+ wdm_next_args['test_client_case'] = 10 # kTestCase_TestUpdatableTrait
+
+ wdm_next_args['enable_retry'] = True
+
+ wdm_next_args['total_server_count'] = 0
+ wdm_next_args['final_server_status'] = 4
+ wdm_next_args['timer_server_period'] = 0
+ wdm_next_args['enable_server_flip'] = 0
+ wdm_next_args['test_server_case'] = 10
+
+ wdm_next_args['client_clear_state_between_iterations'] = False
+ wdm_next_args['server_clear_state_between_iterations'] = False
+
+ wdm_next_args['client_update_mutation'] = "SameLevelLeaves"
+ wdm_next_args['client_update_conditionality'] = "Unconditional"
+ wdm_next_args['client_update_num_mutations'] = 2
+ wdm_next_args['client_update_num_traits'] = 2
+ wdm_next_args['client_update_timing'] = "DuringSub"
+
+ wdm_next_args['client_log_check'] = [('UpdateComplete event: 1', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['server_log_check'] = [('Send Update Response with profileId 0x0 statusCode 0x0', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
+ wdm_next_args['test_case_name'] = ['Update 04: Client sends standalone unconditional update request to publisher during subscription, and receives status report and notification']
+ print 'test file: ' + self.__class__.__name__
+ print "weave-wdm-next update test 04"
+ super(test_weave_wdm_next_update_04, self).weave_wdm_next_test_base(wdm_next_args)
+
+
+if __name__ == "__main__":
+ WeaveUtilities.run_unittest()
diff --git a/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_05.py b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_05.py
new file mode 100755
index 0000000..4068cbb
--- /dev/null
+++ b/src/test-apps/happy/tests/standalone/wdmNext/test_weave_wdm_next_update_05.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+
+
+#
+# Copyright (c) 2019 Google, LLC.
+# Copyright (c) 2016-2018 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# @file
+# Calls Weave WDM Update between nodes.
+# Update 05: Client sends standalone unconditional update request to publisher, and receives status report
+#
+
+import unittest
+import set_test_path
+from weave_wdm_next_test_base import weave_wdm_next_test_base
+import WeaveUtilities
+
+
+class test_weave_wdm_next_update_05(weave_wdm_next_test_base):
+
+ def test_weave_wdm_next_mutual_subscribe_05(self):
+ wdm_next_args = {}
+ wdm_next_args['wdm_option'] = "mutual_subscribe"
+
+ wdm_next_args['total_client_count'] = 1
+ wdm_next_args['final_client_status'] = 0
+ wdm_next_args['timer_client_period'] = 10000
+ wdm_next_args['test_client_iterations'] = 1
+ wdm_next_args['test_client_delay'] = 2000
+ wdm_next_args['enable_client_flip'] = 1
+ wdm_next_args['test_client_case'] = 10 # kTestCase_TestUpdatableTrait
+
+ wdm_next_args['enable_retry'] = True
+
+ wdm_next_args['total_server_count'] = 0
+ wdm_next_args['final_server_status'] = 4
+ wdm_next_args['timer_server_period'] = 0
+ wdm_next_args['enable_server_flip'] = 0
+ wdm_next_args['test_server_case'] = 10
+
+ wdm_next_args['client_clear_state_between_iterations'] = False
+ wdm_next_args['server_clear_state_between_iterations'] = False
+
+ wdm_next_args['client_update_mutation'] = "SameLevelLeaves"
+ wdm_next_args['client_update_conditionality'] = "Mixed"
+ wdm_next_args['client_update_num_mutations'] = 2
+ wdm_next_args['client_update_num_traits'] = 2
+ wdm_next_args['client_update_timing'] = "AfterSub"
+
+ wdm_next_args['client_log_check'] = [('UpdateComplete event: 1', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['server_log_check'] = [('Send Update Response with profileId 0x0 statusCode 0x0', wdm_next_args['test_client_iterations'] * wdm_next_args['client_update_num_mutations'])]
+ wdm_next_args['test_tag'] = self.__class__.__name__[19:].upper()
+ wdm_next_args['test_case_name'] = ['Update 05: Client sends standalone unconditional update request to publisher, and receives status report']
+ print 'test file: ' + self.__class__.__name__
+ print "weave-wdm-next update test 05"
+ super(test_weave_wdm_next_update_05, self).weave_wdm_next_test_base(wdm_next_args)
+
+
+if __name__ == "__main__":
+ WeaveUtilities.run_unittest()
diff --git a/src/test-apps/mock-device.cpp b/src/test-apps/mock-device.cpp
index 7c8b981..5c9ec1c 100644
--- a/src/test-apps/mock-device.cpp
+++ b/src/test-apps/mock-device.cpp
@@ -104,6 +104,7 @@
static void InitiateConnection(System::Layer* aSystemLayer, void* aAppState, System::Error aError);
static void HandleConnectionComplete(WeaveConnection *con, WEAVE_ERROR conErr);
static void HandleWdmCompleteTest();
+static void HandleError();
#if CONFIG_BLE_PLATFORM_BLUEZ
bool EnableWeaveBluezPeripheral = false;
@@ -766,6 +767,111 @@
#endif // CONFIG_BLE_PLATFORM_BLUEZ
+ InitializeEventLogging(&ExchangeMgr);
+
+ switch (gMockWdmNodeOptions.mWdmRoleInTest)
+ {
+ case 0:
+ break;
+ case kToolOpt_WdmInitMutualSubscription:
+ case kToolOpt_WdmSubscriptionClient:
+
+ if (gMockWdmNodeOptions.mWdmPublisherNodeId != kAnyNodeId)
+ {
+ err = MockWdmSubscriptionInitiator::GetInstance()->Init(&ExchangeMgr,
+ gGroupKeyEncOptions.GetEncKeyId(),
+ gWeaveSecurityMode.SecurityMode,
+ gMockWdmNodeOptions);
+ FAIL_ERROR(err, "MockWdmSubscriptionInitiator.Init failed");
+ MockWdmSubscriptionInitiator::GetInstance()->onCompleteTest = HandleWdmCompleteTest;
+ MockWdmSubscriptionInitiator::GetInstance()->onError = HandleError;
+
+ }
+ else
+ {
+ err = WEAVE_ERROR_INVALID_ARGUMENT;
+ FAIL_ERROR(err, "MockWdmSubscriptionInitiator requires node ID to some publisher");
+ }
+
+ break;
+ case kToolOpt_WdmRespMutualSubscription:
+ case kToolOpt_WdmSubscriptionPublisher:
+ if (gMockWdmNodeOptions.mEnableRetry)
+ {
+ err = WEAVE_ERROR_INVALID_ARGUMENT;
+ FAIL_ERROR(err, "MockWdmSubcriptionResponder is incompatible with --enable-retry");
+ }
+
+ err = MockWdmSubscriptionResponder::GetInstance()->Init(&ExchangeMgr,
+ gMockWdmNodeOptions
+ );
+ FAIL_ERROR(err, "MockWdmSubscriptionResponder.Init failed");
+ MockWdmSubscriptionResponder::GetInstance()->onCompleteTest = HandleWdmCompleteTest;
+ MockWdmSubscriptionResponder::GetInstance()->onError = HandleError;
+ if (gTestWdmNextOptions.mClearDataSinkState)
+ {
+ MockWdmSubscriptionResponder::GetInstance()->ClearDataSinkState();
+ }
+ break;
+ default:
+ err = WEAVE_ERROR_INVALID_ARGUMENT;
+ FAIL_ERROR(err, "WdmRoleInTest is invalid");
+ };
+
+ for (uint32_t iteration = 1; iteration <= gTestWdmNextOptions.mTestIterations; iteration++) {
+
+ switch (gMockWdmNodeOptions.mWdmRoleInTest) {
+ case 0:
+ break;
+ case kToolOpt_WdmInitMutualSubscription:
+ case kToolOpt_WdmSubscriptionClient:
+ if (gTestWdmNextOptions.mClearDataSinkState) {
+ MockWdmSubscriptionInitiator::GetInstance()->ClearDataSinkState();
+ }
+ err = MockWdmSubscriptionInitiator::GetInstance()->StartTesting(gMockWdmNodeOptions.mWdmPublisherNodeId,
+ gMockWdmNodeOptions.mWdmUseSubnetId);
+ if (err != WEAVE_NO_ERROR) {
+ printf("\nMockWdmSubscriptionInitiator.StartTesting failed: %s\n", ErrorStr(err));
+ Done = true;
+ }
+ //FAIL_ERROR(err, "MockWdmSubscriptionInitiator.StartTesting failed");
+ break;
+ default:
+ printf("TestWdmNext server is ready\n");
+ };
+
+ switch (gMockWdmNodeOptions.mEventGeneratorType) {
+ case MockWdmNodeOptions::kGenerator_None:
+ gEventGenerator = NULL;
+ break;
+ case MockWdmNodeOptions::kGenerator_TestDebug:
+ gEventGenerator = GetTestDebugGenerator();
+ break;
+ case MockWdmNodeOptions::kGenerator_TestLiveness:
+ gEventGenerator = GetTestLivenessGenerator();
+ break;
+ case MockWdmNodeOptions::kGenerator_TestSecurity:
+ gEventGenerator = GetTestSecurityGenerator();
+ break;
+ case MockWdmNodeOptions::kGenerator_TestTelemetry:
+ gEventGenerator = GetTestTelemetryGenerator();
+ break;
+ case MockWdmNodeOptions::kGenerator_TestTrait:
+ gEventGenerator = GetTestTraitGenerator();
+ break;
+ case MockWdmNodeOptions::kGenerator_NumItems:
+ default:
+ gEventGenerator = NULL;
+ break;
+ }
+
+ if (gEventGenerator != NULL) {
+ printf("Starting Event Generator\n");
+ MockEventGenerator::GetInstance()->Init(&ExchangeMgr, gEventGenerator,
+ gMockWdmNodeOptions.mTimeBetweenEvents, true);
+ }
+
+ }
while (!Done)
{
struct timeval sleepTime;
@@ -1069,3 +1175,8 @@
Done = true;
}
}
+
+static void HandleError()
+{
+ Done = true;
+}