| /* |
| * |
| * Copyright (c) 2016-2017 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 |
| * This file implements the Weave Data Management mock subscription responder. |
| * |
| */ |
| |
| #define WEAVE_CONFIG_ENABLE_FUNCT_ERROR_LOGGING 1 |
| |
| #ifndef __STDC_FORMAT_MACROS |
| #define __STDC_FORMAT_MACROS |
| #endif // __STDC_FORMAT_MACROS |
| #include <inttypes.h> |
| |
| // Note that the choice of namespace alias must be made up front for each and every compile unit |
| // This is because many include paths could set the default alias to unintended target. |
| #include <Weave/Profiles/bulk-data-transfer/Development/BDXManagedNamespace.hpp> |
| #include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h> |
| |
| #include <Weave/Core/WeaveCore.h> |
| #include <Weave/Core/WeaveTLVDebug.hpp> |
| #include <Weave/Profiles/WeaveProfiles.h> |
| #include <Weave/Profiles/common/CommonProfile.h> |
| #include <Weave/Profiles/data-management/DataManagement.h> |
| #include <Weave/Profiles/status-report/StatusReportProfile.h> |
| #include <Weave/Profiles/security/ApplicationKeysTraitDataSink.h> |
| #include <Weave/Support/CodeUtils.h> |
| #include <Weave/Support/TimeUtils.h> |
| #include <Weave/Support/ASN1.h> |
| #include "MockWdmTestVerifier.h" |
| #include "MockWdmSubscriptionResponder.h" |
| #include "MockSinkTraits.h" |
| #include "MockSourceTraits.h" |
| #include "MockWdmTestVerifier.h" |
| |
| #include "MockPlatformClocks.h" |
| |
| using nl::Weave::System::PacketBuffer; |
| |
| #if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING |
| |
| using namespace nl::Weave::TLV; |
| using namespace nl::Weave::Profiles; |
| using namespace nl::Weave::Profiles::DataManagement; |
| using namespace Schema::Weave::Trait::Auth::ApplicationKeysTrait; |
| |
| const nl::Weave::ExchangeContext::Timeout kResponseTimeoutMsec = 15000; |
| const nl::Weave::ExchangeContext::Timeout kWRMPActiveRetransTimeoutMsec = 3000; |
| const nl::Weave::ExchangeContext::Timeout kWRMPInitialRetransTimeoutMsec = 3000; |
| const uint16_t kWRMPMaxRetrans = 3; |
| const uint16_t kWRMPAckTimeoutMsec = 200; |
| const nl::Weave::Profiles::Time::timesync_t kCommandTimeoutMicroSecs = 30*nl::kMicrosecondsPerSecond; |
| |
| static int gNumDataChangeBeforeCancellation; |
| static int gFinalStatus; |
| static SubscriptionHandler *gSubscriptionHandler = NULL; |
| static int gTimeBetweenDataChangeMsec = 0; |
| static bool gEnableDataFlip = true; |
| static nl::Weave::Binding * gBinding = NULL; |
| static bool gClearDataSink = false; |
| static bool gCleanStatus = true; |
| static nl::Weave::WRMPConfig gWRMPConfig = { kWRMPInitialRetransTimeoutMsec, kWRMPActiveRetransTimeoutMsec, kWRMPAckTimeoutMsec, kWRMPMaxRetrans }; |
| |
| |
| static void TLVPrettyPrinter(const char *aFormat, ...) |
| { |
| va_list args; |
| |
| va_start(args, aFormat); |
| |
| // There is no proper Weave logging routine for us to use here |
| vprintf(aFormat, args); |
| |
| va_end(args); |
| } |
| |
| static WEAVE_ERROR DebugPrettyPrint(nl::Weave::TLV::TLVReader & aReader) |
| { |
| return nl::Weave::TLV::Debug::Dump(aReader, TLVPrettyPrinter); |
| } |
| |
| nl::Weave::Profiles::DataManagement::SubscriptionEngine * nl::Weave::Profiles::DataManagement::SubscriptionEngine::GetInstance() |
| { |
| static nl::Weave::Profiles::DataManagement::SubscriptionEngine gWdmSubscriptionEngine; |
| |
| return &gWdmSubscriptionEngine; |
| } |
| |
| struct VersionNode |
| { |
| uint64_t versionInfo; |
| VersionNode * next; |
| }; |
| |
| |
| class WdmResponderState |
| { |
| public: |
| int mDataflipCount; |
| int mClientStateCount; |
| int mPublisherStateCount; |
| void init(void) |
| { |
| mDataflipCount = 1; |
| mClientStateCount = 1; |
| mPublisherStateCount = 1; |
| } |
| }; |
| |
| static WdmResponderState gResponderState; |
| |
| |
| class MockWdmSubscriptionResponderImpl: public MockWdmSubscriptionResponder |
| { |
| public: |
| |
| MockWdmSubscriptionResponderImpl (); |
| |
| virtual WEAVE_ERROR Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, |
| const MockWdmNodeOptions &aConfig); |
| void PrintVersionsLog(); |
| virtual void ClearDataSinkState(void); |
| |
| private: |
| nl::Weave::WeaveExchangeManager *mExchangeMgr; |
| static void ClearDataSinkIterator(void *aTraitInstance, TraitDataHandle aHandle, void *aContext); |
| |
| bool mIsMutualSubscription; |
| int mTestCaseId; |
| // publisher side |
| uint32_t mTimeBetweenLivenessCheckSec; |
| SingleResourceSourceTraitCatalog mSourceCatalog; |
| SingleResourceSourceTraitCatalog::CatalogItem mSourceCatalogStore[6]; |
| |
| // source traits |
| LocaleSettingsTraitDataSource mLocaleSettingsDataSource; |
| TestATraitDataSource mTestADataSource0; |
| TestATraitDataSource mTestADataSource1; |
| TestBTraitDataSource mTestBDataSource; |
| TestBLargeTraitDataSource mTestBLargeDataSource; |
| BoltLockSettingTraitDataSource mBoltLockSettingDataSource; |
| ApplicationKeysTraitDataSource mApplicationKeysTraitDataSource; |
| |
| static void EngineEventCallback (void * const aAppState, SubscriptionEngine::EventID aEvent, |
| const SubscriptionEngine::InEventParam & aInParam, SubscriptionEngine::OutEventParam & aOutParam); |
| |
| static void PublisherEventCallback (void * const aAppState, |
| SubscriptionHandler::EventID aEvent, const SubscriptionHandler::InEventParam & aInParam, SubscriptionHandler::OutEventParam & aOutParam); |
| |
| // client side |
| TestATraitDataSink mTestADataSink0; |
| TestATraitDataSink mTestADataSink1; |
| TestBTraitDataSink mTestBDataSink; |
| LocaleCapabilitiesTraitDataSink mLocaleCapabilitiesDataSink; |
| SingleResourceSinkTraitCatalog mSinkCatalog; |
| SingleResourceSinkTraitCatalog::CatalogItem mSinkCatalogStore[5]; |
| nl::Weave::Profiles::DataManagement_Current::TraitSchemaEngine::IGetDataDelegate* mSinkAddressList[4]; |
| |
| enum |
| { |
| kTestADataSink0Index = 0, |
| kTestADataSink1Index, |
| kTestBDataSinkIndex, |
| kLocaleCapabilitiesTraitSinkIndex, |
| kLocaleSettingsTraitSinkIndex, |
| |
| kTestATraitSource0Index, |
| kTestATraitSource1Index, |
| kTestBTraitSourceIndex, |
| kTestBLargeTraitSourceIndex, |
| kLocaleSettingsTraitSourceIndex, |
| kBoltLockSettingTraitSourceIndex, |
| kApplicationKeysTraitSourceIndex, |
| |
| kNumTraitHandles, |
| }; |
| |
| enum |
| { |
| kClientCancel = 0, |
| kPublisherCancel, |
| kClientAbort, |
| kPublisherAbort, |
| kIdle, |
| }; |
| |
| TraitDataHandle mTraitHandleSet[kNumTraitHandles]; |
| |
| enum |
| { |
| // subscribe LocaleSettings, TestA(two instances) and TestB traits in initiator |
| // publish TestA(two instances) and TestB traits in initiator |
| kTestCase_TestTrait = 1, |
| |
| // subscribe Locale Setting, ApplicationKeys traits in initiator |
| // publish Locale Capabilities traits in responder |
| kTestCase_IntegrationTrait = 2, |
| |
| //Reject Incoming subscribe request |
| kTestCase_RejectIncomingSubscribeRequest = 3, |
| |
| // subscribe oversize TestB, TestA(two instances) traits and LocaleSettings in initiator |
| // publish TestA(two instances) and oversize TestB traits in initiator |
| kTestCase_TestOversizeTrait1 = 4, |
| |
| // subscribe oversize LocaleSettings, TestB, and TestA(two instances) traits in initiator |
| // publish TestA(two instances) and oversize TestB traits in initiator |
| kTestCase_TestOversizeTrait2 = 5, |
| |
| kTestCase_CompatibleVersionedRequest = 6, |
| |
| kTestCase_ForwardCompatibleVersionedRequest = 7, |
| |
| kTestCase_IncompatibleVersionedRequest = 8, |
| |
| kTestCase_IncompatibleVersionedCommandRequest = 9, |
| |
| kTestCase_TestUpdatableTrait1 = 10, |
| |
| kTestCase_TestUpdatableTrait2 = 11, |
| |
| kTestCase_TestUpdatableTrait3 = 12, |
| }; |
| |
| enum |
| { |
| kMonitorCurrentStateCnt = 160, |
| kMonitorCurrentStateInterval = 120 //msec |
| }; |
| |
| TraitPath mTraitPaths[4]; |
| VersionedTraitPath mVersionedTraitPaths[4]; |
| uint32_t mNumPaths; |
| |
| VersionNode mTraitVersionSet[kNumTraitHandles]; |
| |
| SubscriptionClient * mSubscriptionClient; |
| |
| void AddNewVersion (int aTraitDataSinkIndex); |
| |
| void DumpClientTraitChecksum(int TraitDataSinkIndex); |
| void DumpClientTraits(void); |
| |
| void DumpPublisherTraitChecksum(int TraitDataSounceIndex); |
| void DumpPublisherTraits(void); |
| |
| static void ClientEventCallback (void * const aAppState, SubscriptionClient::EventID aEvent, |
| const SubscriptionClient::InEventParam & aInParam, SubscriptionClient::OutEventParam & aOutParam); |
| |
| static void HandleDataFlipTimeout(nl::Weave::System::Layer* aSystemLayer, void *aAppState, ::nl::Weave::System::Error aErr); |
| |
| static void HandleClientComplete(void *aAppState); |
| |
| static void HandleClientRelease(void *aAppState); |
| |
| static void HandlePublisherComplete(); |
| |
| static void HandlePublisherRelease(); |
| |
| static void MonitorPublisherCurrentState (nl::Weave::System::Layer* aSystemLayer, void *aAppState, INET_ERROR aErr); |
| |
| static void MonitorClientCurrentState (nl::Weave::System::Layer* aSystemLayer, void *aAppState, INET_ERROR aErr); |
| |
| enum CustomCommandState |
| { |
| kCmdState_Idle = 0, ///< No active command |
| kCmdState_Requesting = 1, ///< Command has been sent but we haven't heard anything back |
| kCmdState_Operating = 2, ///< We have received In-Progress message but are still waiting for response |
| }; |
| CustomCommandState mCmdState; |
| nl::Weave::ExchangeContext * mEcCommand; |
| void Command_Send (void); |
| void Command_End (const bool aAbort = false); |
| static void OnMessageReceivedForCustomCommand (nl::Weave::ExchangeContext *aEC, const nl::Inet::IPPacketInfo *aPktInfo, |
| 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; |
| |
| MockWdmSubscriptionResponder * MockWdmSubscriptionResponder::GetInstance () |
| { |
| return &gWdmSubscriptionResponder; |
| } |
| |
| MockWdmSubscriptionResponderImpl::MockWdmSubscriptionResponderImpl() : |
| mTimeBetweenLivenessCheckSec(30), |
| mSourceCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID), mSourceCatalogStore, sizeof(mSourceCatalogStore) / sizeof(mSourceCatalogStore[0])), |
| mSinkCatalog(ResourceIdentifier(ResourceIdentifier::SELF_NODE_ID), mSinkCatalogStore, sizeof(mSinkCatalogStore) / sizeof(mSinkCatalogStore[0])), |
| mCmdState(kCmdState_Idle), |
| mEcCommand(NULL) |
| { |
| } |
| |
| WEAVE_ERROR MockWdmSubscriptionResponderImpl::Init (nl::Weave::WeaveExchangeManager *aExchangeMgr, |
| const MockWdmNodeOptions &aConfig) |
| { |
| gResponderState.init(); |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| WeaveLogDetail(DataManagement, "Test Case ID: %s", (aConfig.mTestCaseId == NULL) ? "NULL" : aConfig.mTestCaseId); |
| |
| if (NULL != aConfig.mNumDataChangeBeforeCancellation) |
| { |
| gNumDataChangeBeforeCancellation = atoi(aConfig.mNumDataChangeBeforeCancellation); |
| if (gNumDataChangeBeforeCancellation < -1) |
| { |
| gNumDataChangeBeforeCancellation = -1; |
| } |
| } |
| else |
| { |
| gNumDataChangeBeforeCancellation = -1; |
| } |
| |
| if (NULL != aConfig.mFinalStatus) |
| { |
| gFinalStatus = atoi(aConfig.mFinalStatus); |
| } |
| else |
| { |
| gFinalStatus = 1; |
| } |
| |
| if (NULL != aConfig.mTestCaseId) |
| { |
| mTestCaseId = atoi(aConfig.mTestCaseId); |
| } |
| else |
| { |
| mTestCaseId = kTestCase_TestTrait; |
| } |
| |
| if (NULL != aConfig.mTimeBetweenDataChangeMsec) |
| { |
| gTimeBetweenDataChangeMsec = atoi(aConfig.mTimeBetweenDataChangeMsec); |
| } |
| else |
| { |
| gTimeBetweenDataChangeMsec = 15000; |
| } |
| |
| gEnableDataFlip = aConfig.mEnableDataFlip; |
| |
| if (NULL != aConfig.mTimeBetweenLivenessCheckSec) |
| { |
| mTimeBetweenLivenessCheckSec = atoi(aConfig.mTimeBetweenLivenessCheckSec); |
| } |
| else |
| { |
| mTimeBetweenLivenessCheckSec = 30; |
| } |
| |
| mTestADataSource0.mTraitTestSet = 0; |
| mTestADataSource1.mTraitTestSet = 1; |
| |
| mSinkCatalog.Add(1, &mTestADataSink0, mTraitHandleSet[kTestADataSink0Index]); |
| mSinkCatalog.Add(2, &mTestADataSink1, mTraitHandleSet[kTestADataSink1Index]); |
| mSinkCatalog.Add(1, &mTestBDataSink, mTraitHandleSet[kTestBDataSinkIndex]); |
| mSinkCatalog.Add(0, &mLocaleCapabilitiesDataSink, mTraitHandleSet[kLocaleCapabilitiesTraitSinkIndex]); |
| |
| mSourceCatalog.Add(0, &mTestADataSource0, mTraitHandleSet[kTestATraitSource0Index]); |
| mSourceCatalog.Add(1, &mTestADataSource1, mTraitHandleSet[kTestATraitSource1Index]); |
| |
| switch (mTestCaseId) |
| { |
| case kTestCase_TestOversizeTrait1: |
| case kTestCase_TestOversizeTrait2: |
| mSourceCatalog.Add(0, &mTestBLargeDataSource, mTraitHandleSet[kTestBLargeTraitSourceIndex]); |
| break; |
| default: |
| mSourceCatalog.Add(0, &mTestBDataSource, mTraitHandleSet[kTestBTraitSourceIndex]); |
| break; |
| } |
| |
| mSourceCatalog.Add(0, &mLocaleSettingsDataSource, mTraitHandleSet[kLocaleSettingsTraitSourceIndex]); |
| mSourceCatalog.Add(0, &mBoltLockSettingDataSource, mTraitHandleSet[kBoltLockSettingTraitSourceIndex]); |
| mSourceCatalog.Add(0, &mApplicationKeysTraitDataSource, mTraitHandleSet[kApplicationKeysTraitSourceIndex]); |
| |
| switch (mTestCaseId) |
| { |
| case kTestCase_IntegrationTrait: |
| WeaveLogDetail(DataManagement, "kTestCase_IntegrationTrait"); |
| break; |
| |
| case kTestCase_RejectIncomingSubscribeRequest: |
| WeaveLogDetail(DataManagement, "kTestCase_RejectIncomingSubscribeRequest"); |
| break; |
| |
| case kTestCase_TestTrait: |
| WeaveLogDetail(DataManagement, "kTestCase_TestTrait"); |
| break; |
| |
| case kTestCase_TestOversizeTrait1: |
| case kTestCase_TestOversizeTrait2: |
| WeaveLogDetail(DataManagement, "kTestCase_TestOversizeTrait %d", mTestCaseId); |
| break; |
| |
| case kTestCase_CompatibleVersionedRequest: |
| WeaveLogDetail(DataManagement, "kTestCase_CompatibleVersionedRequest"); |
| break; |
| |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| WeaveLogDetail(DataManagement, "kTestCase_ForwardCompatibleVersionedRequest"); |
| break; |
| |
| case kTestCase_IncompatibleVersionedRequest: |
| WeaveLogDetail(DataManagement, "kTestCase_IncompatibleVersionedRequest"); |
| break; |
| |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| WeaveLogDetail(DataManagement, "kTestCase_IncompatibleVersionedCommandRequest"); |
| break; |
| |
| case kTestCase_TestUpdatableTrait1: |
| WeaveLogDetail(DataManagement, "kTestCase_TestUpdatableTrait1"); |
| mTestADataSource0.mTraitTestSet = 2; |
| break; |
| |
| case kTestCase_TestUpdatableTrait2: |
| WeaveLogDetail(DataManagement, "kTestCase_TestUpdatableTrait2"); |
| mTestADataSource0.mTraitTestSet = 2; |
| break; |
| |
| case kTestCase_TestUpdatableTrait3: |
| WeaveLogDetail(DataManagement, "kTestCase_TestUpdatableTrait3"); |
| mTestADataSource0.mTraitTestSet = 3; |
| break; |
| |
| default: |
| WeaveLogDetail(DataManagement, "kTestCase_TestTrait"); |
| break; |
| } |
| |
| mIsMutualSubscription = aConfig.mEnableMutualSubscription; |
| |
| mSubscriptionClient = NULL; |
| mExchangeMgr = aExchangeMgr; |
| |
| err = SubscriptionEngine::GetInstance()->Init(mExchangeMgr, this, EngineEventCallback); |
| SuccessOrExit(err); |
| |
| err = SubscriptionEngine::GetInstance()->EnablePublisher(NULL, &mSourceCatalog); |
| SuccessOrExit(err); |
| |
| mTraitVersionSet[kTestADataSink0Index].versionInfo = mTestADataSink0.GetVersion(); |
| mTraitVersionSet[kTestADataSink0Index].next = NULL; |
| mTraitVersionSet[kTestADataSink1Index].versionInfo = mTestADataSink1.GetVersion(); |
| mTraitVersionSet[kTestADataSink1Index].next = NULL; |
| mTraitVersionSet[kTestBDataSinkIndex].versionInfo = mTestBDataSink.GetVersion(); |
| mTraitVersionSet[kTestBDataSinkIndex].next = NULL; |
| mTraitVersionSet[kLocaleCapabilitiesTraitSinkIndex].versionInfo = mLocaleCapabilitiesDataSink.GetVersion(); |
| mTraitVersionSet[kLocaleCapabilitiesTraitSinkIndex].next = NULL; |
| |
| mSinkAddressList[kTestADataSink0Index] = &mTestADataSink0; |
| mSinkAddressList[kTestADataSink1Index] = &mTestADataSink1; |
| 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: |
| return err; |
| } |
| |
| void MockWdmSubscriptionResponderImpl::DumpPublisherTraitChecksum(int inTraitDataSourceIndex) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TraitDataSource *dataSource; |
| err = mSourceCatalog.Locate(mTraitHandleSet[inTraitDataSourceIndex], &dataSource); |
| SuccessOrExit(err); |
| |
| ::DumpPublisherTraitChecksum(dataSource); |
| exit: |
| WeaveLogFunctError(err); |
| } |
| |
| void MockWdmSubscriptionResponderImpl::DumpClientTraitChecksum(int inTraitDataSinkIndex) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| TraitDataSink *dataSink; |
| TraitSchemaEngine::IGetDataDelegate *dataSource; |
| |
| dataSource = mSinkAddressList[inTraitDataSinkIndex]; |
| err = mSinkCatalog.Locate(mTraitHandleSet[inTraitDataSinkIndex], &dataSink); |
| SuccessOrExit(err); |
| |
| ::DumpClientTraitChecksum(dataSink->GetSchemaEngine(), dataSource); |
| exit: |
| WeaveLogFunctError(err); |
| } |
| |
| void MockWdmSubscriptionResponderImpl::DumpClientTraits(void) |
| { |
| switch (mTestCaseId) |
| { |
| case kTestCase_IntegrationTrait: |
| DumpClientTraitChecksum(kLocaleCapabilitiesTraitSinkIndex); |
| break; |
| case kTestCase_TestTrait: |
| case kTestCase_CompatibleVersionedRequest: |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| DumpClientTraitChecksum(kTestADataSink0Index); |
| DumpClientTraitChecksum(kTestADataSink1Index); |
| DumpClientTraitChecksum(kTestBDataSinkIndex); |
| break; |
| case kTestCase_TestOversizeTrait1: |
| case kTestCase_TestOversizeTrait2: |
| DumpClientTraitChecksum(kTestADataSink0Index); |
| DumpClientTraitChecksum(kTestADataSink1Index); |
| break; |
| case kTestCase_TestUpdatableTrait1: |
| case kTestCase_TestUpdatableTrait2: |
| case kTestCase_TestUpdatableTrait3: |
| break; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::DumpPublisherTraits(void) |
| { |
| switch (mTestCaseId) |
| { |
| case kTestCase_IntegrationTrait: |
| DumpPublisherTraitChecksum(kLocaleSettingsTraitSourceIndex); |
| DumpPublisherTraitChecksum(kApplicationKeysTraitSourceIndex); |
| break; |
| case kTestCase_TestTrait: |
| case kTestCase_CompatibleVersionedRequest: |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| DumpPublisherTraitChecksum(kTestATraitSource0Index); |
| DumpPublisherTraitChecksum(kTestATraitSource1Index); |
| DumpPublisherTraitChecksum(kTestBTraitSourceIndex); |
| DumpPublisherTraitChecksum(kLocaleSettingsTraitSourceIndex); |
| break; |
| case kTestCase_TestOversizeTrait1: |
| DumpPublisherTraitChecksum(kTestATraitSource0Index); |
| DumpPublisherTraitChecksum(kTestATraitSource1Index); |
| DumpPublisherTraitChecksum(kLocaleSettingsTraitSourceIndex); |
| break; |
| case kTestCase_TestOversizeTrait2: |
| DumpPublisherTraitChecksum(kLocaleSettingsTraitSourceIndex); |
| DumpPublisherTraitChecksum(kTestATraitSource0Index); |
| DumpPublisherTraitChecksum(kTestATraitSource1Index); |
| break; |
| case kTestCase_TestUpdatableTrait1: |
| case kTestCase_TestUpdatableTrait2: |
| case kTestCase_TestUpdatableTrait3: |
| break; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::EngineEventCallback (void * const aAppState, |
| SubscriptionEngine::EventID aEvent, |
| const SubscriptionEngine::InEventParam & aInParam, SubscriptionEngine::OutEventParam & aOutParam) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| switch (aEvent) |
| { |
| case SubscriptionEngine::kEvent_OnIncomingSubscribeRequest: |
| WeaveLogDetail(DataManagement, "Engine->kEvent_OnIncomingSubscribeRequest peer = 0x%" PRIX64, aInParam.mIncomingSubscribeRequest.mEC->PeerNodeId); |
| aOutParam.mIncomingSubscribeRequest.mHandlerAppState = responder; |
| aOutParam.mIncomingSubscribeRequest.mHandlerEventCallback = MockWdmSubscriptionResponderImpl::PublisherEventCallback; |
| aOutParam.mIncomingSubscribeRequest.mRejectRequest = false; |
| |
| aInParam.mIncomingSubscribeRequest.mBinding->SetDefaultResponseTimeout(kResponseTimeoutMsec); |
| aInParam.mIncomingSubscribeRequest.mBinding->SetDefaultWRMPConfig(gWRMPConfig); |
| |
| break; |
| default: |
| SubscriptionEngine::DefaultEventHandler(aEvent, aInParam, aOutParam); |
| break; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::AddNewVersion(int aTraitDataSinkIndex) |
| { |
| VersionNode * curr = &mTraitVersionSet[aTraitDataSinkIndex]; |
| while (curr->next != NULL) |
| { |
| curr = curr->next; |
| } |
| |
| if (curr->versionInfo != mSinkCatalogStore[aTraitDataSinkIndex].mItem->GetVersion()) |
| { |
| VersionNode * updatingVersion = (VersionNode *)malloc(sizeof(VersionNode)); |
| WeaveLogDetail(DataManagement, "Trait %u version is changed %" PRIu64 " ---> %" PRIu64, aTraitDataSinkIndex, curr->versionInfo, mSinkCatalogStore[aTraitDataSinkIndex].mItem->GetVersion()); |
| updatingVersion->versionInfo = mSinkCatalogStore[aTraitDataSinkIndex].mItem->GetVersion(); |
| updatingVersion->next = NULL; |
| curr->next = updatingVersion; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::PublisherEventCallback (void * const aAppState, |
| SubscriptionHandler::EventID aEvent, const SubscriptionHandler::InEventParam & aInParam, SubscriptionHandler::OutEventParam & aOutParam) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| switch (aEvent) |
| { |
| case SubscriptionHandler::kEvent_OnSubscribeRequestParsed: |
| WeaveLogDetail(DataManagement, "Publisher->kEvent_OnSubscribeRequestParsed"); |
| |
| // ideally this number should be set to something for cloud service, and something else for everyone else |
| // we can potentially copy this from the client side, but it would take considerable amount of code to be generic enough |
| // setting to some constant here seems to be easier |
| |
| aInParam.mSubscribeRequestParsed.mHandler->GetBinding()->SetDefaultResponseTimeout(kResponseTimeoutMsec); |
| aInParam.mSubscribeRequestParsed.mHandler->GetBinding()->SetDefaultWRMPConfig(gWRMPConfig); |
| |
| switch (responder->mTestCaseId) |
| { |
| case kTestCase_RejectIncomingSubscribeRequest: |
| // reject right here and release the resources associated with this incoming request |
| aInParam.mSubscribeRequestParsed.mHandler->EndSubscription(nl::Weave::Profiles::kWeaveProfile_Common, |
| nl::Weave::Profiles::Common::kStatus_Canceled); |
| break; |
| default: |
| WeaveLogDetail(DataManagement, "Liveness check range provided by client %u - %u sec. Set to %u sec", |
| aInParam.mSubscribeRequestParsed.mTimeoutSecMin, |
| aInParam.mSubscribeRequestParsed.mTimeoutSecMax, |
| responder->mTimeBetweenLivenessCheckSec); |
| aInParam.mSubscribeRequestParsed.mHandler->AcceptSubscribeRequest(responder->mTimeBetweenLivenessCheckSec); |
| } |
| break; |
| |
| case SubscriptionHandler::kEvent_OnExchangeStart: |
| WeaveLogDetail(DataManagement, "Publisher->kEvent_OnExchangeStart"); |
| break; |
| |
| case SubscriptionHandler::kEvent_OnSubscriptionEstablished: |
| if (true == gClearDataSink || true == gCleanStatus) |
| { |
| responder->DumpPublisherTraits(); |
| gCleanStatus = false; |
| } |
| |
| WeaveLogDetail(DataManagement, "Publisher->kEvent_OnSubscriptionEstablished"); |
| gSubscriptionHandler = aInParam.mSubscriptionEstablished.mHandler; |
| gBinding = gSubscriptionHandler->GetBinding(); |
| gBinding->AddRef(); |
| |
| if (responder->mIsMutualSubscription) |
| { |
| if (NULL != responder->mSubscriptionClient) |
| { |
| WeaveLogDetail(DataManagement, "Skip mutual subscription setup, for we only have one client"); |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "Creating mutual subscription"); |
| |
| switch (responder->mTestCaseId) |
| { |
| case kTestCase_TestTrait: |
| case kTestCase_TestUpdatableTrait1: |
| case kTestCase_TestUpdatableTrait2: |
| case kTestCase_TestUpdatableTrait3: |
| responder->mNumPaths = 3; |
| responder->mTraitPaths[0].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink0Index]; |
| responder->mTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mTraitPaths[1].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink1Index]; |
| responder->mTraitPaths[1].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mTraitPaths[2].mTraitDataHandle = responder->mTraitHandleSet[kTestBDataSinkIndex]; |
| responder->mTraitPaths[2].mPropertyPathHandle = kRootPropertyPathHandle; |
| break; |
| case kTestCase_IntegrationTrait: |
| responder->mNumPaths = 1; |
| responder->mTraitPaths[0].mTraitDataHandle = responder->mTraitHandleSet[kLocaleCapabilitiesTraitSinkIndex]; |
| responder->mTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle; |
| break; |
| case kTestCase_TestOversizeTrait1: |
| case kTestCase_TestOversizeTrait2: |
| responder->mNumPaths = 3; |
| responder->mTraitPaths[0].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink0Index]; |
| responder->mTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mTraitPaths[1].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink1Index]; |
| responder->mTraitPaths[1].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mTraitPaths[2].mTraitDataHandle = responder->mTraitHandleSet[kTestBDataSinkIndex]; |
| responder->mTraitPaths[2].mPropertyPathHandle = kRootPropertyPathHandle; |
| break; |
| |
| case kTestCase_CompatibleVersionedRequest: |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| case kTestCase_IncompatibleVersionedRequest: |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| |
| responder->mNumPaths = 3; |
| |
| for (int i = 0; i < 3; i++) { |
| if (responder->mTestCaseId == kTestCase_CompatibleVersionedRequest) { |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMinVersion = 1; |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMaxVersion = 1; |
| } |
| else if (responder->mTestCaseId == kTestCase_ForwardCompatibleVersionedRequest) { |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMinVersion = 1; |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMaxVersion = 4; |
| } |
| else if (responder->mTestCaseId == kTestCase_IncompatibleVersionedRequest) { |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMinVersion = 2; |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMaxVersion = 4; |
| } |
| else if (responder->mTestCaseId == kTestCase_IncompatibleVersionedCommandRequest) { |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMinVersion = 1; |
| responder->mVersionedTraitPaths[i].mRequestedVersionRange.mMaxVersion = 4; |
| } |
| } |
| |
| responder->mVersionedTraitPaths[0].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink0Index]; |
| responder->mVersionedTraitPaths[0].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mVersionedTraitPaths[1].mTraitDataHandle = responder->mTraitHandleSet[kTestADataSink1Index]; |
| responder->mVersionedTraitPaths[1].mPropertyPathHandle = kRootPropertyPathHandle; |
| |
| responder->mVersionedTraitPaths[2].mTraitDataHandle = responder->mTraitHandleSet[kTestBDataSinkIndex]; |
| responder->mVersionedTraitPaths[2].mPropertyPathHandle = kRootPropertyPathHandle; |
| break; |
| } |
| |
| err = SubscriptionEngine::GetInstance()->NewClient(&(responder->mSubscriptionClient), |
| aInParam.mSubscriptionEstablished.mHandler->GetBinding(), |
| responder, ClientEventCallback, |
| &(responder->mSinkCatalog), kResponseTimeoutMsec * 2); |
| VerifyOrExit(err == WEAVE_NO_ERROR, gBinding->Release()); |
| |
| // TODO: EVENT-DEMO |
| responder->mSubscriptionClient->InitiateCounterSubscription( |
| responder->mTimeBetweenLivenessCheckSec); |
| } |
| } |
| else |
| { |
| if (gNumDataChangeBeforeCancellation != 0) |
| { |
| // alter data every gTimeBetweenDataChangeMsec milliseconds |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(gTimeBetweenDataChangeMsec, HandleDataFlipTimeout, aAppState); |
| } |
| else |
| { |
| if (gFinalStatus != kIdle) |
| { |
| switch (gFinalStatus) |
| { |
| case kPublisherCancel: |
| case kPublisherAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorPublisherCurrentState, responder); |
| break; |
| case kClientCancel: |
| case kClientAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorClientCurrentState, responder); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| } |
| break; |
| |
| case SubscriptionHandler::kEvent_OnSubscriptionTerminated: |
| WeaveLogDetail(DataManagement, "Publisher->kEvent_OnSubscriptionTerminated. Reason: %u, peer = 0x%" PRIX64 "\n", |
| aInParam.mSubscriptionTerminated.mReason, |
| aInParam.mSubscriptionTerminated.mHandler->GetPeerNodeId()); |
| switch (gFinalStatus) |
| { |
| case kPublisherCancel: |
| case kPublisherAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(MonitorPublisherCurrentState, responder); |
| break; |
| case kClientCancel: |
| case kClientAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(MonitorClientCurrentState, responder); |
| break; |
| case kIdle: |
| default: |
| break; |
| } |
| |
| if (gNumDataChangeBeforeCancellation != 0) |
| { |
| //responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(HandleDataFlipTimeout, aAppState); |
| } |
| HandleClientRelease(responder); |
| HandlePublisherRelease(); |
| gResponderState.init(); |
| responder->onCompleteTest(); |
| break; |
| |
| default: |
| SubscriptionHandler::DefaultEventHandler(aEvent, aInParam, aOutParam); |
| break; |
| } |
| |
| exit: |
| if (err != WEAVE_NO_ERROR && gSubscriptionHandler) |
| { |
| // tell the handler to cancel |
| (void)gSubscriptionHandler->EndSubscription(); |
| } |
| |
| WeaveLogFunctError(err); |
| } |
| |
| void MockWdmSubscriptionResponderImpl::PrintVersionsLog() |
| { |
| for (int i = 0; i< kNumTraitHandles; i++) |
| { |
| VersionNode * pre = &mTraitVersionSet[i]; |
| VersionNode * curr = mTraitVersionSet[i].next; |
| |
| printf("Responder's trait %u versions log is : %" PRIu64, i, pre->versionInfo); |
| while (curr != NULL) |
| { |
| pre = curr; |
| curr = curr->next; |
| printf(" ==> %" PRIu64, pre->versionInfo); |
| } |
| printf("\n"); |
| mTraitVersionSet[i].next = NULL; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::ClearDataSinkState(void) |
| { |
| gClearDataSink = true; |
| } |
| |
| void MockWdmSubscriptionResponderImpl::ClearDataSinkIterator(void *aTraitInstance, TraitDataHandle aHandle, void *aContext) |
| { |
| MockTraitDataSink *traitInstance = static_cast<MockTraitDataSink *>(aTraitInstance); |
| traitInstance->ResetDataSink(); |
| } |
| |
| |
| void MockWdmSubscriptionResponderImpl::ClientEventCallback (void * const aAppState, SubscriptionClient::EventID aEvent, |
| const SubscriptionClient::InEventParam & aInParam, SubscriptionClient::OutEventParam & aOutParam) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| switch (aEvent) |
| { |
| case SubscriptionClient::kEvent_OnExchangeStart: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnExchangeStart"); |
| break; |
| |
| case SubscriptionClient::kEvent_OnSubscribeRequestPrepareNeeded: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscribeRequestPrepareNeeded"); |
| if (gSubscriptionHandler->GetSubscriptionId(&(aOutParam.mSubscribeRequestPrepareNeeded.mSubscriptionId)) |
| != WEAVE_NO_ERROR) |
| { |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscribeRequestPrepareNeeded invalid state"); |
| HandleClientRelease(aAppState); |
| } |
| else |
| { |
| if (responder->mTestCaseId >= kTestCase_CompatibleVersionedRequest && responder->mTestCaseId <= kTestCase_IncompatibleVersionedCommandRequest) { |
| aOutParam.mSubscribeRequestPrepareNeeded.mVersionedPathList = responder->mVersionedTraitPaths; |
| } |
| else { |
| aOutParam.mSubscribeRequestPrepareNeeded.mPathList = responder->mTraitPaths; |
| } |
| |
| aOutParam.mSubscribeRequestPrepareNeeded.mPathListSize = responder->mNumPaths; |
| aOutParam.mSubscribeRequestPrepareNeeded.mNeedAllEvents = true; |
| aOutParam.mSubscribeRequestPrepareNeeded.mLastObservedEventList = NULL; |
| aOutParam.mSubscribeRequestPrepareNeeded.mLastObservedEventListSize = 0; |
| } |
| |
| break; |
| |
| case SubscriptionClient::kEvent_OnSubscriptionEstablished: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscriptionEstablished"); |
| WeaveLogDetail(DataManagement, "Liveness Timeout: %u msec", aInParam.mSubscriptionEstablished.mClient->GetLivenessTimeoutMsec()); |
| if (gNumDataChangeBeforeCancellation != 0) |
| { |
| // alter data every gTimeBetweenDataChangeMsec milliseconds |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(gTimeBetweenDataChangeMsec, HandleDataFlipTimeout, aAppState); |
| } |
| else |
| { |
| if (gFinalStatus != kIdle) |
| { |
| switch (gFinalStatus) |
| { |
| case kPublisherCancel: |
| case kPublisherAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorPublisherCurrentState, responder); |
| break; |
| case kClientCancel: |
| case kClientAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorClientCurrentState, responder); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| break; |
| case SubscriptionClient::kEvent_OnNotificationRequest: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnNotificationRequest"); |
| break; |
| case SubscriptionClient::kEvent_OnNotificationProcessed: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnNotificationProcessed"); |
| switch (responder->mTestCaseId) |
| { |
| case kTestCase_IntegrationTrait: |
| responder->AddNewVersion(responder->kLocaleCapabilitiesTraitSinkIndex); |
| break; |
| case kTestCase_TestTrait: |
| case kTestCase_CompatibleVersionedRequest: |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| responder->AddNewVersion(responder->kTestADataSink0Index); |
| responder->AddNewVersion(responder->kTestADataSink1Index); |
| responder->AddNewVersion(responder->kTestBDataSinkIndex); |
| break; |
| case kTestCase_TestOversizeTrait1: |
| case kTestCase_TestOversizeTrait2: |
| responder->AddNewVersion(responder->kTestADataSink0Index); |
| responder->AddNewVersion(responder->kTestADataSink1Index); |
| break; |
| } |
| responder->DumpClientTraits(); |
| break; |
| case SubscriptionClient::kEvent_OnSubscriptionTerminated: |
| WeaveLogDetail(DataManagement, "Client->kEvent_OnSubscriptionTerminated, Reason: %u, peer = 0x%" PRIX64 "\n", |
| aInParam.mSubscriptionTerminated.mReason, |
| aInParam.mSubscriptionTerminated.mClient->GetPeerNodeId()); |
| |
| switch (gFinalStatus) |
| { |
| case kPublisherCancel: |
| case kPublisherAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(MonitorPublisherCurrentState, responder); |
| break; |
| case kClientCancel: |
| case kClientAbort: |
| responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(MonitorClientCurrentState, responder); |
| break; |
| case kIdle: |
| default: |
| break; |
| } |
| if (gNumDataChangeBeforeCancellation != 0) |
| { |
| responder->mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(HandleDataFlipTimeout, responder); |
| } |
| if (gClearDataSink) |
| { |
| responder->mSinkCatalog.Iterate(MockWdmSubscriptionResponderImpl::ClearDataSinkIterator, NULL); |
| } |
| HandleClientRelease(responder); |
| HandlePublisherRelease(); |
| gResponderState.init(); |
| responder->onCompleteTest(); |
| break; |
| default: |
| SubscriptionClient::DefaultEventHandler(aEvent, aInParam, aOutParam); |
| break; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandlePublisherComplete() |
| { |
| if (NULL != gSubscriptionHandler) |
| { |
| if (gFinalStatus == kPublisherCancel) |
| { |
| (void)gSubscriptionHandler->EndSubscription(); |
| } |
| if (gFinalStatus == kPublisherAbort) |
| { |
| (void)gSubscriptionHandler->AbortSubscription(); |
| } |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandleClientRelease(void *aAppState) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| if (NULL != responder->mSubscriptionClient) |
| { |
| responder->mSubscriptionClient->Free(); |
| responder->mSubscriptionClient = NULL; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandleClientComplete(void *aAppState) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| if (NULL != responder->mSubscriptionClient) |
| { |
| if (gFinalStatus == kClientCancel) |
| { |
| (void)responder->mSubscriptionClient->EndSubscription(); |
| } |
| if (gFinalStatus == kClientAbort) |
| { |
| (void)responder->mSubscriptionClient->AbortSubscription(); |
| } |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandlePublisherRelease() |
| { |
| |
| gSubscriptionHandler = NULL; |
| |
| if (NULL != gBinding) |
| { |
| gBinding->Release(); |
| gBinding = NULL; |
| } |
| |
| } |
| |
| void MockWdmSubscriptionResponderImpl::Command_End(const bool aAbort) |
| { |
| WeaveLogDetail(DataManagement, "Responder %s: state: %d", __func__, mCmdState); |
| |
| (void)mExchangeMgr->MessageLayer->SystemLayer->CancelTimer(HandleCustomCommandTimeout, this); |
| |
| mCmdState = kCmdState_Idle; |
| if (NULL != mEcCommand) |
| { |
| // this might be needed, for the test infrastructure re-init this object multiple times |
| // ExchangeContext::Close would gracefully close this exchange, while ExchangeContext::Abort |
| // would forcefully reclaim all resources |
| if (aAbort) |
| { |
| mEcCommand->Abort(); |
| } |
| else |
| { |
| mEcCommand->Close(); |
| } |
| mEcCommand = NULL; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandleCustomCommandTimeout(nl::Weave::System::Layer* aSystemLayer, void *aAppState, ::nl::Weave::System::Error aErr) |
| { |
| MockWdmSubscriptionResponderImpl * const pResponder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| |
| WeaveLogDetail(DataManagement, "Responder %s", __func__); |
| |
| 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) |
| { |
| static uint32_t num_update_iterations = 0; |
| static bool notification_first_ordering = false; |
| uint32_t num_update_tests = 7; |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| nl::Weave::TLV::TLVReader reader; |
| UpdateRequest::Parser parser; |
| uint8_t statusReportLen = 6; |
| uint8_t * p; |
| WeaveLogDetail(DataManagement, "Incoming Update Request"); |
| MockWdmSubscriptionResponderImpl * pResponder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(ec->AppState); |
| |
| reader.Init(payload); |
| reader.Next(); |
| parser.Init(reader); |
| parser.CheckSchemaValidity(); |
| |
| if (num_update_iterations == 0) |
| { |
| notification_first_ordering = ! notification_first_ordering; |
| } |
| |
| if (notification_first_ordering) |
| { |
| WeaveLogDetail(DataManagement, "notification first"); |
| switch (pResponder->mTestCaseId) |
| { |
| case kTestCase_TestUpdatableTrait1: |
| pResponder->mTestADataSource0.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| case kTestCase_TestUpdatableTrait2: |
| pResponder->mTestADataSource0.Mutate(); |
| pResponder->mLocaleSettingsDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| case kTestCase_TestUpdatableTrait3: |
| pResponder->mTestADataSource0.Mutate(); |
| pResponder->mTestBDataSource.Mutate(); |
| pResponder->mLocaleSettingsDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| default: |
| break; |
| } |
| |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "update response first"); |
| } |
| |
| num_update_iterations = num_update_iterations % num_update_tests; |
| |
| WeaveLogDetail(DataManagement, "dump status report"); |
| |
| reader.Init(payload); |
| DebugPrettyPrint(reader); |
| |
| PacketBuffer * msgBuf = PacketBuffer::NewWithAvailableSize(statusReportLen); |
| VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY); |
| |
| p = msgBuf->Start(); |
| nl::Weave::Encoding::LittleEndian::Write32(p, nl::Weave::Profiles::kWeaveProfile_Common); |
| nl::Weave::Encoding::LittleEndian::Write16(p, nl::Weave::Profiles::Common::kStatus_Success); |
| msgBuf->SetDataLength(statusReportLen); |
| |
| err = ec->SendMessage(nl::Weave::Profiles::kWeaveProfile_Common, nl::Weave::Profiles::Common::kMsgType_StatusReport, msgBuf, nl::Weave::ExchangeContext::kSendFlag_RequestAck); |
| msgBuf = NULL; |
| SuccessOrExit(err); |
| |
| if (!notification_first_ordering) |
| { |
| pResponder->mTestADataSource0.Mutate(); |
| pResponder->mLocaleSettingsDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| } |
| |
| num_update_iterations ++; |
| num_update_iterations = num_update_iterations % num_update_tests; |
| |
| exit: |
| WeaveLogFunctError(err); |
| |
| if (NULL != payload) |
| { |
| PacketBuffer::Free(payload); |
| payload = NULL; |
| } |
| |
| if (NULL != msgBuf) |
| { |
| PacketBuffer::Free(msgBuf); |
| msgBuf = 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) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| MockWdmSubscriptionResponderImpl * pResponder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aEC->AppState); |
| nl::Weave::Profiles::StatusReporting::StatusReport status; |
| enum |
| { |
| kMsgIdentified_Unknown = 0, |
| kMsgIdentified_StatusReport = 1, |
| kMsgIdentified_Response = 2, |
| kMsgIdentified_InProgress = 3, |
| } messageType = kMsgIdentified_Unknown; |
| |
| WeaveLogDetail(DataManagement, "Responder %s: state: %d", __func__, pResponder->mCmdState); |
| |
| VerifyOrExit(aEC == pResponder->mEcCommand, err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(kCmdState_Idle != pResponder->mCmdState, err = WEAVE_ERROR_INCORRECT_STATE); |
| |
| if ((nl::Weave::Profiles::kWeaveProfile_Common == aProfileId) && (nl::Weave::Profiles::Common::kMsgType_StatusReport == aMsgType)) |
| { |
| // Note that payload is not freed in this call to parse |
| err = nl::Weave::Profiles::StatusReporting::StatusReport::parse(aPayload, status); |
| SuccessOrExit(err); |
| messageType = kMsgIdentified_StatusReport; |
| WeaveLogError(DataManagement, "Received Status Report 0x%" PRIX32 " : 0x%" PRIX16, status.mProfileId, status.mStatusCode); |
| } |
| else if ((nl::Weave::Profiles::kWeaveProfile_WDM == aProfileId) && (kMsgType_CustomCommandResponse == aMsgType)) |
| { |
| // command response, implies the request succeeded to some degree |
| messageType = kMsgIdentified_Response; |
| } |
| else if ((nl::Weave::Profiles::kWeaveProfile_WDM == aProfileId) && (kMsgType_InProgress == aMsgType)) |
| { |
| messageType = kMsgIdentified_InProgress; |
| } |
| else |
| { |
| messageType = kMsgIdentified_Unknown; |
| } |
| |
| switch (pResponder->mCmdState) |
| { |
| case kCmdState_Requesting: |
| if (kMsgIdentified_InProgress == messageType) |
| { |
| // in progress, indicates the other side has received the request and is working on it |
| // note we could have different time out settings after receiving this in progress message. |
| // it's up to each individual trait. |
| WeaveLogDetail(DataManagement, "Received In Progress message. Waiting for a response"); |
| // there is no payload in "in progress" message, so there is nothing to parse |
| pResponder->mCmdState = kCmdState_Operating; |
| // do not close this EC when we leave this function |
| aEC = NULL; |
| break; |
| } |
| // fall through intentional |
| case kCmdState_Operating: |
| if (kMsgIdentified_Response == messageType) |
| { |
| // command response, implies the request succeeded to some degree |
| WeaveLogDetail(DataManagement, "Response message, end"); |
| |
| nl::Weave::TLV::TLVReader reader; |
| reader.Init(aPayload); |
| |
| err = reader.Next(); |
| SuccessOrExit(err); |
| |
| CustomCommandResponse::Parser response; |
| err = response.Init(reader); |
| SuccessOrExit(err); |
| |
| #if WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK |
| // this function only print out all recognized properties in the response |
| // check the parser class to see what else is available |
| err = response.CheckSchemaValidity(); |
| SuccessOrExit(err); |
| #endif // WEAVE_CONFIG_DATA_MANAGEMENT_ENABLE_SCHEMA_CHECK |
| } |
| else |
| { |
| if (kMsgIdentified_StatusReport == messageType) |
| { |
| // status report, implies the request failed |
| WeaveLogDetail(DataManagement, "Status Report, end"); |
| } |
| else |
| { |
| // unexpected message |
| WeaveLogDetail(DataManagement, "Unexpected message, end"); |
| } |
| } |
| // reset state and close the exchange |
| pResponder->Command_End(); |
| // aEC has been closed/aborted as part of Command_End |
| aEC = NULL; |
| break; |
| default: |
| // this is probably dead code |
| ExitNow(err = WEAVE_ERROR_INCORRECT_STATE); |
| } |
| |
| exit: |
| WeaveLogFunctError(err); |
| |
| if (WEAVE_NO_ERROR != err) |
| { |
| pResponder->Command_End(true); |
| // aEC has been closed/aborted as part of Command_End |
| aEC = NULL; |
| } |
| |
| if (NULL != aEC) |
| { |
| aEC->Abort(); |
| aEC = NULL; |
| } |
| |
| if (NULL != aPayload) |
| { |
| PacketBuffer::Free(aPayload); |
| aPayload = NULL; |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::Command_Send(void) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| PacketBuffer *msgBuf = PacketBuffer::New(); |
| static uint32_t commandType = 1; |
| static uint32_t signatureType = 0; // static dummy signature. Values: 0 == None, 1 -- Weave Signature, 2 -- Group Key Signature |
| |
| WeaveLogDetail(DataManagement, "Responder %s: state: %d", __func__, mCmdState); |
| |
| printf("<<< TestCaseId %u >>>\n", mTestCaseId); |
| |
| VerifyOrExit((NULL != gBinding) && (kCmdState_Idle == mCmdState) && (NULL == mEcCommand), err = WEAVE_ERROR_INCORRECT_STATE); |
| VerifyOrExit(NULL != msgBuf, err = WEAVE_ERROR_NO_MEMORY); |
| |
| err = gBinding->NewExchangeContext(mEcCommand); |
| SuccessOrExit(err); |
| |
| mEcCommand->AppState = this; |
| mEcCommand->OnMessageReceived = OnMessageReceivedForCustomCommand; |
| mEcCommand->OnResponseTimeout = NULL; |
| mEcCommand->OnSendError = NULL; |
| mEcCommand->OnAckRcvd = NULL; |
| |
| { |
| nl::Weave::TLV::TLVWriter writer; |
| CustomCommand::Builder request; |
| uint64_t nowMicroSecs, deadline; |
| |
| writer.Init(msgBuf); |
| err = request.Init(&writer); |
| SuccessOrExit(err); |
| |
| Path::Builder & path = request.CreatePathBuilder(); |
| |
| if (mTestCaseId == kTestCase_ForwardCompatibleVersionedRequest) { |
| path.ProfileID(Schema::Nest::Test::Trait::TestATrait::kWeaveProfileId, SchemaVersionRange(4, 1)).InstanceID(1).EndOfPath(); |
| } |
| else if (mTestCaseId == kTestCase_IncompatibleVersionedCommandRequest) { |
| path.ProfileID(Schema::Nest::Test::Trait::TestATrait::kWeaveProfileId, SchemaVersionRange(4, 2)).InstanceID(1).EndOfPath(); |
| } |
| else { |
| path.ProfileID(Schema::Nest::Test::Trait::TestATrait::kWeaveProfileId).InstanceID(1).EndOfPath(); |
| } |
| |
| SuccessOrExit(path.GetError()); |
| |
| // Command Type: alternating |
| commandType = (1 == commandType) ? 2 : 1; |
| request.CommandType(commandType); |
| request.MustBeVersion(mTestADataSink1.GetVersion()); |
| |
| // It's safe to bail out after a series of operation, for |
| // SubscriptionRequest::Builder would internally turn to NOP after error is logged |
| SuccessOrExit(err = request.GetError()); |
| |
| err = System::Layer::GetClock_RealTime(nowMicroSecs); |
| SuccessOrExit(err); |
| |
| deadline = nowMicroSecs + kCommandTimeoutMicroSecs; |
| request.ExpiryTimeMicroSecond((int64_t)deadline); |
| |
| SuccessOrExit(err = request.GetError()); |
| |
| // Add arguments here |
| { |
| uint32_t dummyUInt = 7; |
| bool dummyBool = false; |
| nl::Weave::TLV::TLVType dummyType = nl::Weave::TLV::kTLVType_NotSpecified; |
| err = writer.StartContainer(nl::Weave::TLV::ContextTag(CustomCommand::kCsTag_Argument), nl::Weave::TLV::kTLVType_Structure, dummyType); |
| SuccessOrExit(err); |
| |
| err = writer.Put(nl::Weave::TLV::ContextTag(1), dummyUInt); |
| SuccessOrExit(err); |
| err = writer.PutBoolean(nl::Weave::TLV::ContextTag(2), dummyBool); |
| SuccessOrExit(err); |
| |
| err = writer.EndContainer(dummyType); |
| SuccessOrExit(err); |
| } |
| |
| switch (signatureType) |
| { |
| case 0: // dummy signature -- No signature |
| WeaveLogDetail(DataManagement, "Command with no authenticator" ); |
| break; |
| case 1: // dummy signature -- Weave signature |
| { |
| nl::Weave::TLV::TLVType dummyType = nl::Weave::TLV::kTLVType_NotSpecified; |
| |
| WeaveLogDetail(DataManagement, "Command with dummy WeaveSignature authenticator" ); |
| |
| err = writer.StartContainer(nl::Weave::TLV::ProfileTag(nl::Weave::Profiles::kWeaveProfile_Security, nl::Weave::Profiles::Security::kTag_WeaveSignature), nl::Weave::TLV::kTLVType_Structure, dummyType); |
| SuccessOrExit(err); |
| |
| // dummy signature -- for now, just an algorithm specification |
| err = writer.Put(nl::Weave::TLV::ContextTag(nl::Weave::Profiles::Security::kTag_WeaveSignature_SignatureAlgorithm), nl::Weave::ASN1::kOID_SigAlgo_ECDSAWithSHA256); |
| SuccessOrExit(err); |
| |
| err = writer.EndContainer(dummyType); |
| SuccessOrExit(err); |
| break; |
| } |
| case 2: // dummy signature -- Group key signature |
| { |
| nl::Weave::TLV::TLVType dummyType = nl::Weave::TLV::kTLVType_NotSpecified; |
| |
| WeaveLogDetail(DataManagement, "Command with dummy Group Key Authenticator authenticator" ); |
| |
| err = writer.StartContainer(nl::Weave::TLV::ProfileTag(nl::Weave::Profiles::kWeaveProfile_Security, nl::Weave::Profiles::Security::kTag_GroupKeySignature), nl::Weave::TLV::kTLVType_Structure, dummyType); |
| SuccessOrExit(err); |
| |
| // dummy signature -- for now, just an algorithm specification |
| err = writer.Put(nl::Weave::TLV::ContextTag(nl::Weave::Profiles::Security::kTag_GroupKeySignature_SignatureAlgorithm), nl::Weave::ASN1::kOID_SigAlgo_HMACWithSHA256); |
| SuccessOrExit(err); |
| |
| err = writer.EndContainer(dummyType); |
| SuccessOrExit(err); |
| break; |
| } |
| } |
| |
| request.EndOfCustomCommand(); |
| SuccessOrExit(err = request.GetError()); |
| |
| err = writer.Finalize(); |
| SuccessOrExit(err); |
| |
| if (commandType == 1) |
| { |
| signatureType = (signatureType + 1) % 3; |
| } |
| |
| |
| err = mEcCommand->SendMessage(nl::Weave::Profiles::kWeaveProfile_WDM, kMsgType_CustomCommandRequest, |
| msgBuf, nl::Weave::ExchangeContext::kSendFlag_ExpectResponse); |
| msgBuf = NULL; |
| SuccessOrExit(err); |
| } |
| |
| err = mExchangeMgr->MessageLayer->SystemLayer->StartTimer(5000, HandleCustomCommandTimeout, this); |
| SuccessOrExit(err); |
| |
| mCmdState = kCmdState_Requesting; |
| |
| exit: |
| WeaveLogFunctError(err); |
| |
| if (NULL != msgBuf) |
| { |
| PacketBuffer::Free(msgBuf); |
| msgBuf = NULL; |
| } |
| |
| if (WEAVE_NO_ERROR != err) |
| { |
| Command_End(true); |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::HandleDataFlipTimeout(nl::Weave::System::Layer* aSystemLayer, void *aAppState, |
| nl::Weave::System::Error aErr) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| |
| IgnoreUnusedVariable(aErr); |
| |
| if (gEnableDataFlip == true) |
| { |
| WeaveLogDetail(DataManagement, "\n\n\n\n\nFlipping data..."); |
| |
| switch (responder->mTestCaseId) |
| { |
| case kTestCase_IntegrationTrait: |
| case kTestCase_RejectIncomingSubscribeRequest: |
| responder->mLocaleSettingsDataSource.Mutate(); |
| responder->mApplicationKeysTraitDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| case kTestCase_TestTrait: |
| case kTestCase_CompatibleVersionedRequest: |
| case kTestCase_ForwardCompatibleVersionedRequest: |
| responder->mTestADataSource0.Mutate(); |
| responder->mTestADataSource1.Mutate(); |
| responder->mTestBDataSource.Mutate(); |
| responder->mLocaleSettingsDataSource.Mutate(); |
| responder->Command_Send(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| case kTestCase_TestUpdatableTrait1: |
| case kTestCase_TestUpdatableTrait2: |
| case kTestCase_TestUpdatableTrait3: |
| break; |
| case kTestCase_IncompatibleVersionedCommandRequest: |
| responder->Command_Send(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| |
| case kTestCase_TestOversizeTrait1: |
| responder->mTestADataSource0.Mutate(); |
| responder->mTestADataSource1.Mutate(); |
| responder->mLocaleSettingsDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| |
| case kTestCase_TestOversizeTrait2: |
| responder->mTestADataSource0.Mutate(); |
| responder->mTestADataSource1.Mutate(); |
| responder->mLocaleSettingsDataSource.Mutate(); |
| SubscriptionEngine::GetInstance()->GetNotificationEngine()->Run(); |
| break; |
| } |
| responder->DumpPublisherTraits(); |
| } |
| |
| if (gNumDataChangeBeforeCancellation == -1) |
| { |
| WeaveLogDetail(DataManagement, "immortal, no cancel or abort, completed cycle %d", gResponderState.mDataflipCount); |
| // alter data every gTimeBetweenDataChangeMsec milliseconds |
| aSystemLayer->StartTimer(gTimeBetweenDataChangeMsec, HandleDataFlipTimeout, responder); |
| ++gResponderState.mDataflipCount; |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "Completed cycle %d per %d", gResponderState.mDataflipCount, gNumDataChangeBeforeCancellation); |
| if (gResponderState.mDataflipCount == gNumDataChangeBeforeCancellation) |
| { |
| gResponderState.mDataflipCount = 1; |
| if (gFinalStatus != kIdle) |
| { |
| switch (gFinalStatus) |
| { |
| case kPublisherCancel: |
| case kPublisherAbort: |
| aSystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorPublisherCurrentState, responder); |
| break; |
| case kClientCancel: |
| case kClientAbort: |
| aSystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorClientCurrentState, responder); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| else |
| { |
| // alter data every gTimeBetweenDataChangeMsec milliseconds |
| ++gResponderState.mDataflipCount; |
| aSystemLayer->StartTimer(gTimeBetweenDataChangeMsec, HandleDataFlipTimeout, responder); |
| } |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::MonitorPublisherCurrentState (nl::Weave::System::Layer* aSystemLayer, void *aAppState, INET_ERROR aErr) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| if (NULL != gSubscriptionHandler) |
| { |
| if (gSubscriptionHandler->IsEstablishedIdle() && (NULL == responder->mSubscriptionClient || responder->mSubscriptionClient->IsEstablishedIdle())) |
| { |
| WeaveLogDetail(DataManagement, "state transitions to idle within %d msec", kMonitorCurrentStateInterval * kMonitorCurrentStateCnt); |
| gResponderState.mPublisherStateCount = 1; |
| HandlePublisherComplete(); |
| if (!responder->mIsMutualSubscription) |
| { |
| HandlePublisherRelease(); |
| WeaveLogDetail(DataManagement, "One_way: Good Iteration"); |
| responder->onCompleteTest(); |
| } |
| } |
| else |
| { |
| if (gResponderState.mPublisherStateCount < kMonitorCurrentStateCnt) |
| { |
| gResponderState.mPublisherStateCount ++; |
| aSystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorPublisherCurrentState, responder); |
| } |
| else |
| { |
| gResponderState.mPublisherStateCount = 1; |
| WeaveLogDetail(DataManagement, "state is not idle or aborted within %d msec", kMonitorCurrentStateInterval * kMonitorCurrentStateCnt); |
| (void)gSubscriptionHandler->AbortSubscription(); |
| HandleClientRelease(responder); |
| HandlePublisherRelease(); |
| responder->onCompleteTest(); |
| } |
| } |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "gSubscriptionHandler is NULL, and current session is torn down"); |
| HandleClientRelease(responder); |
| HandlePublisherRelease(); |
| responder->onCompleteTest(); |
| } |
| } |
| |
| void MockWdmSubscriptionResponderImpl::MonitorClientCurrentState (nl::Weave::System::Layer* aSystemLayer, void *aAppState, INET_ERROR aErr) |
| { |
| MockWdmSubscriptionResponderImpl * const responder = reinterpret_cast<MockWdmSubscriptionResponderImpl *>(aAppState); |
| if (NULL != responder->mSubscriptionClient) |
| { |
| if (responder->mSubscriptionClient->IsEstablishedIdle() && (NULL == gSubscriptionHandler || gSubscriptionHandler->IsEstablishedIdle())) |
| { |
| WeaveLogDetail(DataManagement, "state transitions to idle within %d msec", kMonitorCurrentStateInterval * kMonitorCurrentStateCnt); |
| gResponderState.mClientStateCount = 1; |
| HandleClientComplete(responder); |
| } |
| else |
| { |
| if (gResponderState.mClientStateCount < kMonitorCurrentStateCnt) |
| { |
| gResponderState.mClientStateCount ++; |
| aSystemLayer->StartTimer(kMonitorCurrentStateInterval, MonitorClientCurrentState, responder); |
| } |
| else |
| { |
| gResponderState.mClientStateCount = 1; |
| WeaveLogDetail(DataManagement, "state is not idle or aborted within %d msec", kMonitorCurrentStateInterval * kMonitorCurrentStateCnt); |
| (void)gSubscriptionHandler->AbortSubscription(); |
| } |
| } |
| } |
| else |
| { |
| WeaveLogDetail(DataManagement, "mSubscriptionClient is NULL, and current session is torn down"); |
| (void)gSubscriptionHandler->AbortSubscription(); |
| HandleClientRelease(responder); |
| HandlePublisherRelease(); |
| responder->onCompleteTest(); |
| } |
| } |
| |
| #endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING |