| /* |
| * |
| * 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 defines subscription client for Weave |
| * Data Management (WDM) profile. |
| * |
| */ |
| |
| #ifndef _WEAVE_DATA_MANAGEMENT_SUBSCRIPTION_CLIENT_CURRENT_H |
| #define _WEAVE_DATA_MANAGEMENT_SUBSCRIPTION_CLIENT_CURRENT_H |
| |
| #include <Weave/Core/WeaveCore.h> |
| |
| #include <Weave/Profiles/data-management/TraitCatalog.h> |
| #include <Weave/Profiles/data-management/EventLogging.h> |
| #include <Weave/Profiles/status-report/StatusReportProfile.h> |
| |
| namespace nl { |
| namespace Weave { |
| namespace Profiles { |
| namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) { |
| |
| class SubscriptionClient |
| { |
| public: |
| enum |
| { |
| kNoTimeOut = 0, |
| |
| // Note the WDM spec says 0x7FFFFFFF, but Weave implementation can only hold timeout of much shorter |
| // 32-bit in milliseconds, which is about 1200 hours |
| kMaxTimeoutSec = 3600000, |
| }; |
| |
| enum EventID |
| { |
| // Marks the end of this subscription. The parameters sent to |
| // the EventCallback will indicate whether a resubscribe will |
| // be automatically attempted. |
| // If no retry will be attempted, the state of the client will |
| // be Aborted. No more downcalls into the application will |
| // be made. |
| // Otherwise, the state will not be aborted or freed. Downcalls |
| // will continue. |
| // The application is allowed to abort or free in this state. |
| // The parameters sent will also include an error code indicating |
| // the reason for ending the subscription. There are no guarantees |
| // for the state of mBinding or mEC. |
| // The subscription could have been terminated for a number of reasons |
| // (WRM ACK missing, EC allocation failure, response timeout,...) |
| // Some possible error codes generated by the client: |
| // WEAVE_ERROR_INVALID_MESSAGE_TYPE if some unrecognized message is received |
| // WEAVE_ERROR_TIMEOUT if an ack is not received or if a liveness check fails |
| // WEAVE_ERROR_INVALID_STATE if messages are received in an unexpected state |
| // WEAVE_ERROR_STATUS_REPORT_RECEIVED if a status report is received |
| // WEAVE_ERROR_INVALID_ARGUMENT if subscribe request fields are invalid |
| kEvent_OnSubscriptionTerminated = 1, |
| |
| // Last chance to adjust EC, mEC is valid and can be tuned for timeout settings |
| // Don't touch anything else, and don't close the EC |
| kEvent_OnExchangeStart = 2, |
| |
| // Sent as the client is creating the subscribe request |
| kEvent_OnSubscribeRequestPrepareNeeded = 3, |
| |
| // cancel, abort, and free are allowed |
| kEvent_OnSubscriptionEstablished = 4, |
| |
| // cancel, abort, and free are allowed |
| kEvent_OnNotificationRequest = 5, |
| |
| // cancel, abort, and free are allowed |
| kEvent_OnNotificationProcessed = 6, |
| |
| // An event stream has been received |
| kEvent_OnEventStreamReceived = 7, |
| }; |
| |
| struct LastObservedEvent |
| { |
| uint64_t mSourceId; |
| uint8_t mImportance; |
| uint64_t mEventId; |
| }; |
| |
| // union of structures for each event some of them might be empty |
| union InEventParam |
| { |
| void Clear(void) { memset(this, 0, sizeof(*this)); } |
| |
| struct |
| { |
| WEAVE_ERROR mReason; |
| |
| bool mIsStatusCodeValid; |
| uint32_t mStatusProfileId; |
| uint16_t mStatusCode; |
| ReferencedTLVData *mAdditionalInfoPtr; |
| bool mWillRetry; |
| |
| SubscriptionClient * mClient; |
| } mSubscriptionTerminated; |
| |
| struct |
| { |
| // Do not close the EC |
| nl::Weave::ExchangeContext * mEC; |
| SubscriptionClient * mClient; |
| } mExchangeStart; |
| |
| struct |
| { |
| SubscriptionClient * mClient; |
| } mSubscribeRequestPrepareNeeded; |
| |
| struct |
| { |
| uint64_t mSubscriptionId; |
| SubscriptionClient * mClient; |
| } mSubscriptionEstablished; |
| |
| struct |
| { |
| // Do not close the EC |
| nl::Weave::ExchangeContext * mEC; |
| |
| // Do not modify the message content |
| PacketBuffer * mMessage; |
| SubscriptionClient * mClient; |
| } mNotificationRequest; |
| |
| struct |
| { |
| SubscriptionClient * mClient; |
| } mNotificationProcessed; |
| |
| struct |
| { |
| nl::Weave::TLV::TLVReader *mReader; |
| SubscriptionClient * mClient; |
| } mEventStreamReceived; |
| }; |
| |
| union OutEventParam |
| { |
| void Clear(void) { memset(this, 0, sizeof(*this)); } |
| |
| struct |
| { |
| TraitPath *mPathList; //< Pointer to a list of trait paths |
| VersionedTraitPath *mVersionedPathList; //< Pointer to a list of versioned trait paths. If both this and mPathList are non-NULL, the versioned path list is selected |
| size_t mPathListSize; //< Number of trait paths in mPathList |
| LastObservedEvent *mLastObservedEventList; //< A list of the last known events received by the subscriber |
| size_t mLastObservedEventListSize; //< Number of observed events in mLastObservedEventList |
| uint32_t mTimeoutSecMin; //< Field specifying lower bound of liveness timeout |
| uint32_t mTimeoutSecMax; //< Field specifying upper bound of liveness timeout |
| uint64_t mSubscriptionId; //< The subscription ID to use for a mutual subscription |
| bool mNeedAllEvents; //< Indicates whether the subscriber is interested in events |
| } mSubscribeRequestPrepareNeeded; |
| }; |
| |
| struct ResubscribeParam |
| { |
| WEAVE_ERROR mReason; //< Error received on most recent failure |
| uint32_t mNumRetries; //< Number of retries, reset on a successful subscription |
| }; |
| |
| /** |
| * @brief Callback to pass subscription events to application. |
| * |
| * @param aAppState[in] App state pointer set during initialization of |
| * the SubscriptionClient. |
| * |
| * @param aEvent[in] Indicates which event is happening |
| * |
| * @param aInParam[in] Struct with additional details about the event |
| * |
| * @param aOutParam[out] Information passed back by the application |
| */ |
| typedef void (*EventCallback) (void * const aAppState, EventID aEvent, const InEventParam & aInParam, OutEventParam & aOutParam); |
| |
| static void DefaultEventHandler(EventID aEvent, const InEventParam & aInParam, OutEventParam & aOutParam); |
| |
| /** |
| * @brief Callback to fetch the interval of time to wait before the next |
| * resubscribe. Applications are allowed to abort/free in this function |
| * if they've decided to give up on resubscribing. |
| * |
| * @param aAppState[in] App state pointer set during initialization of |
| * the SubscriptionClient. |
| * |
| * @param aInParam[in] Struct with additional details about the retry |
| * |
| * @param aOutIntervalMsec[out] Time in milliseconds to wait before next retry |
| */ |
| typedef void (*ResubscribePolicyCallback) (void * const aAppState, ResubscribeParam & aInParam, uint32_t & aOutIntervalMsec); |
| |
| static void DefaultResubscribePolicyCallback(void * const aAppState, ResubscribeParam & aInParam, uint32_t & aOutIntervalMsec); |
| |
| void InitiateSubscription(void); |
| void InitiateCounterSubscription(const uint32_t aLivenessTimeoutSec); |
| |
| Binding * GetBinding(void) const; |
| |
| uint64_t GetPeerNodeId(void) const; |
| |
| WEAVE_ERROR EndSubscription(void); |
| void AbortSubscription(void); |
| |
| void Free (void); |
| |
| WEAVE_ERROR GetSubscriptionId (uint64_t * const apSubscriptionId); |
| |
| uint32_t GetLivenessTimeoutMsec (void) const { return mLivenessTimeoutMsec; }; |
| void SetLivenessTimeoutMsec(uint32_t val) { mLivenessTimeoutMsec = val; } |
| |
| void EnableResubscribe(ResubscribePolicyCallback aCallback); |
| void DisableResubscribe(void); |
| void ResetResubscribe(void); |
| |
| bool IsEstablishedIdle () { return (mCurrentState == kState_SubscriptionEstablished_Idle); } |
| bool IsAborted () { return (mCurrentState == kState_Aborted); } |
| bool IsFree () { return (mCurrentState == kState_Free); } |
| |
| bool IsRetryEnabled() { return (mResubscribePolicyCallback != NULL); } |
| |
| private: |
| friend class SubscriptionEngine; |
| friend class TestTdm; |
| friend class TestWdm; |
| |
| enum ClientState |
| { |
| kState_Free = 0, |
| kState_Initialized = 1, |
| |
| kState_Subscribing = 2, |
| kState_Subscribing_IdAssigned = 3, |
| kState_SubscriptionEstablished_Idle = 4, |
| kState_SubscriptionEstablished_Confirming = 5, |
| kState_Canceling = 6, |
| |
| kState_Resubscribe_Holdoff = 7, |
| |
| kState_NotifyDataSinkOnAbort_Begin = kState_Subscribing, |
| kState_NotifyDataSinkOnAbort_End = kState_Canceling, |
| kState_TimerTick_Begin = kState_Subscribing, |
| kState_TimerTick_End = kState_Resubscribe_Holdoff, |
| |
| kState_Aborting = 8, |
| kState_Aborted = 9, |
| }; |
| |
| ClientState mCurrentState; |
| bool mIsInitiator; |
| bool mPrevIsPartialChange; |
| #if WDM_ENABLE_PROTOCOL_CHECKS |
| TraitDataHandle mPrevTraitDataHandle; |
| #endif |
| |
| int8_t mRefCount; |
| |
| Binding * mBinding; |
| nl::Weave::ExchangeContext * mEC; |
| |
| void * mAppState; |
| EventCallback mEventCallback; |
| |
| Binding::EventCallback mAppBindingCallback; |
| void * mAppBindingState; |
| |
| ResubscribePolicyCallback mResubscribePolicyCallback; |
| |
| const TraitCatalogBase<TraitDataSink>* mDataSinkCatalog; |
| |
| ExchangeContext::Timeout mInactivityTimeoutDuringSubscribingMsec; |
| uint32_t mLivenessTimeoutMsec; |
| uint64_t mSubscriptionId; |
| |
| // retry params |
| uint32_t mRetryCounter; |
| |
| // Do nothing |
| SubscriptionClient (void); |
| |
| void InitAsFree(void); |
| void Reset(void); |
| |
| // AddRef to Binding |
| // store pointers to binding and delegate |
| // null out EC |
| WEAVE_ERROR Init (Binding * const apBinding, |
| void * const apAppState, |
| EventCallback const aEventCallback, |
| const TraitCatalogBase<TraitDataSink>* const apCatalog, |
| const uint32_t aInactivityTimeoutDuringSubscribingMsec); |
| |
| void _InitiateSubscription(void); |
| WEAVE_ERROR SendSubscribeRequest(void); |
| |
| WEAVE_ERROR ProcessDataList(nl::Weave::TLV::TLVReader &aReader); |
| |
| void _AddRef (void); |
| void _Release (void); |
| |
| void HandleSubscriptionTerminated(bool aWillRetry, WEAVE_ERROR aReason, |
| nl::Weave::Profiles::StatusReporting::StatusReport *aStatusReportPtr); |
| |
| WEAVE_ERROR ReplaceExchangeContext (void); |
| |
| void FlushExistingExchangeContext (const bool aAbortNow = false); |
| |
| void NotificationRequestHandler (nl::Weave::ExchangeContext *aEC, const nl::Inet::IPPacketInfo *aPktInfo, |
| const nl::Weave::WeaveMessageInfo *aMsgInfo, PacketBuffer *aPayload); |
| |
| #if WDM_ENABLE_SUBSCRIPTION_CANCEL |
| void CancelRequestHandler (nl::Weave::ExchangeContext *aEC, const nl::Inet::IPPacketInfo *aPktInfo, |
| const nl::Weave::WeaveMessageInfo *aMsgInfo, PacketBuffer *aPayload); |
| #endif // WDM_ENABLE_SUBSCRIPTION_CANCEL |
| |
| void TimerEventHandler (void); |
| WEAVE_ERROR RefreshTimer (void); |
| |
| void SetRetryTimer (WEAVE_ERROR aReason); |
| |
| void MoveToState(const ClientState aTargetState); |
| const char * GetStateStr(void) const; |
| |
| static void BindingEventCallback(void * const apAppState, const Binding::EventType aEvent, |
| const Binding::InEventParam & aInParam, |
| Binding::OutEventParam & aOutParam); |
| static void OnTimerCallback(System::Layer* aSystemLayer, void *aAppState, System::Error aErrorCode); |
| static void DataSinkOperation_NoMoreData (void * const apOpState, TraitDataSink * const apDataSink); |
| static void OnSendError (ExchangeContext *aEC, WEAVE_ERROR aErrorCode, void *aMsgSpecificContext); |
| static void OnResponseTimeout (nl::Weave::ExchangeContext *aEC); |
| static void OnMessageReceivedFromLocallyInitiatedExchange (nl::Weave::ExchangeContext *aEC, const nl::Inet::IPPacketInfo *aPktInfo, |
| const nl::Weave::WeaveMessageInfo *aMsgInfo, uint32_t aProfileId, |
| uint8_t aMsgType, PacketBuffer *aPayload); |
| }; |
| |
| }; // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) |
| }; // Profiles |
| }; // Weave |
| }; // nl |
| |
| #endif // _WEAVE_DATA_MANAGEMENT_SUBSCRIPTION_CLIENT_CURRENT_H |