Matter SDK Coverage Report
Current view: top level - app - ReadHandler.h (source / functions) Coverage Total Hit
Test: SHA:e021a368d10ac6f3f201c101585146211fdcdaa2 Lines: 93.2 % 59 55
Test Date: 2026-02-13 08:13:38 Functions: 85.7 % 42 36

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *     This file defines read handler for a CHIP Interaction Data model
      22              :  *
      23              :  */
      24              : 
      25              : #pragma once
      26              : 
      27              : #include <access/AccessControl.h>
      28              : #include <app/AttributePathExpandIterator.h>
      29              : #include <app/AttributePathParams.h>
      30              : #include <app/AttributeValueEncoder.h>
      31              : #include <app/CASESessionManager.h>
      32              : #include <app/DataVersionFilter.h>
      33              : #include <app/EventManagement.h>
      34              : #include <app/EventPathParams.h>
      35              : #include <app/MessageDef/AttributePathIBs.h>
      36              : #include <app/MessageDef/DataVersionFilterIBs.h>
      37              : #include <app/MessageDef/EventFilterIBs.h>
      38              : #include <app/MessageDef/EventPathIBs.h>
      39              : #include <app/OperationalSessionSetup.h>
      40              : #include <app/SubscriptionResumptionSessionEstablisher.h>
      41              : #include <app/SubscriptionResumptionStorage.h>
      42              : #include <app/reporting/Generations.h>
      43              : #include <lib/core/CHIPCallback.h>
      44              : #include <lib/core/CHIPCore.h>
      45              : #include <lib/core/TLVDebug.h>
      46              : #include <lib/support/CodeUtils.h>
      47              : #include <lib/support/DLLUtil.h>
      48              : #include <lib/support/LinkedList.h>
      49              : #include <lib/support/logging/CHIPLogging.h>
      50              : #include <messaging/ExchangeHolder.h>
      51              : #include <messaging/ExchangeMgr.h>
      52              : #include <messaging/Flags.h>
      53              : #include <protocols/Protocols.h>
      54              : #include <system/SystemPacketBuffer.h>
      55              : 
      56              : // https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/61a9d19e6af12fdfb0872bcff26d19de6c680a1a/src/Ch02_Architecture.adoc#1122-subscribe-interaction-limits
      57              : inline constexpr uint16_t kSubscriptionMaxIntervalPublisherLimit = 3600; // seconds (60 minutes)
      58              : 
      59              : namespace chip {
      60              : namespace app {
      61              : 
      62              : //
      63              : // Forward declare the Engine (which is in a different namespace) to be able to use
      64              : // it as a friend class below.
      65              : //
      66              : namespace reporting {
      67              : class Engine;
      68              : class TestReportingEngine;
      69              : class ReportScheduler;
      70              : class TestReportScheduler;
      71              : } // namespace reporting
      72              : 
      73              : class InteractionModelEngine;
      74              : class TestInteractionModelEngine;
      75              : 
      76              : /**
      77              :  *  @class ReadHandler
      78              :  *
      79              :  *  @brief The read handler is responsible for processing a read request, asking the attribute/event store
      80              :  *         for the relevant data, and sending a reply.
      81              :  *
      82              :  */
      83              : class ReadHandler : public Messaging::ExchangeDelegate
      84              : {
      85              : public:
      86              :     using SubjectDescriptor = Access::SubjectDescriptor;
      87              : 
      88              :     enum class InteractionType : uint8_t
      89              :     {
      90              :         Read,
      91              :         Subscribe,
      92              :     };
      93              : 
      94              :     /*
      95              :      * A callback used to interact with the application.
      96              :      */
      97              :     class ApplicationCallback
      98              :     {
      99              :     public:
     100           46 :         virtual ~ApplicationCallback() = default;
     101              : 
     102              :         /*
     103              :          * Called right after a SubscribeRequest has been parsed and processed. This notifies an interested application
     104              :          * of a subscription that is about to be established. It also provides an avenue for altering the parameters of the
     105              :          * subscription (specifically, the min/max negotiated intervals) or even outright rejecting the subscription for
     106              :          * application-specific reasons.
     107              :          *
     108              :          * TODO: Need a new IM status code to convey application-rejected subscribes. Currently, a Failure IM status code is sent
     109              :          * back to the subscriber, which isn't sufficient.
     110              :          *
     111              :          * To reject the subscription, a CHIP_ERROR code that is not equivalent to CHIP_NO_ERROR should be returned.
     112              :          *
     113              :          * More information about the set of paths associated with this subscription can be retrieved by calling the appropriate
     114              :          * Get* methods below.
     115              :          *
     116              :          * aReadHandler:            Reference to the ReadHandler associated with the subscription.
     117              :          * aSecureSession:          A reference to the underlying secure session associated with the subscription.
     118              :          *
     119              :          */
     120            0 :         virtual CHIP_ERROR OnSubscriptionRequested(ReadHandler & aReadHandler, Transport::SecureSession & aSecureSession)
     121              :         {
     122            0 :             return CHIP_NO_ERROR;
     123              :         }
     124              : 
     125              :         /*
     126              :          * Called after a subscription has been fully established.
     127              :          */
     128            0 :         virtual void OnSubscriptionEstablished(ReadHandler & aReadHandler){};
     129              : 
     130              :         /*
     131              :          * Called right before a subscription is about to get terminated. This is only called on subscriptions that were terminated
     132              :          * after they had been fully established (and therefore had called OnSubscriptionEstablished).
     133              :          * OnSubscriptionEstablishment().
     134              :          */
     135            0 :         virtual void OnSubscriptionTerminated(ReadHandler & aReadHandler){};
     136              :     };
     137              : 
     138              :     /*
     139              :      * A callback used to manage the lifetime of the ReadHandler object.
     140              :      */
     141              :     class ManagementCallback
     142              :     {
     143              :     public:
     144          113 :         virtual ~ManagementCallback() = default;
     145              : 
     146              :         /*
     147              :          * Method that signals to a registered callback that this object
     148              :          * has completed doing useful work and is now safe for release/destruction.
     149              :          */
     150              :         virtual void OnDone(ReadHandler & apReadHandlerObj) = 0;
     151              : 
     152              :         /*
     153              :          * Retrieve the ApplicationCallback (if a valid one exists) from our management entity. This avoids
     154              :          * storing multiple references to the application provided callback and having to subsequently manage lifetime
     155              :          * issues w.r.t the ReadHandler itself.
     156              :          */
     157              :         virtual ApplicationCallback * GetAppCallback() = 0;
     158              : 
     159              :         /*
     160              :          * Retrieve the InteractionalModelEngine that holds this ReadHandler.
     161              :          */
     162              :         virtual InteractionModelEngine * GetInteractionModelEngine() = 0;
     163              :     };
     164              : 
     165              :     // TODO (#27675) : Merge existing callback and observer into one class and have an observer pool in the Readhandler to notify
     166              :     // every
     167              :     /*
     168              :      * Observer class for ReadHandler, meant to allow multiple objects to observe the ReadHandler. Currently only one observer is
     169              :      * supported but all above callbacks should be merged into observer type and an observer pool should be added to allow multiple
     170              :      * objects to observe ReadHandler
     171              :      */
     172              :     class Observer
     173              :     {
     174              :     public:
     175           70 :         virtual ~Observer() = default;
     176              : 
     177              :         /// @brief Callback invoked to notify a subscription was successfully established for the ReadHandler
     178              :         /// @param[in] apReadHandler  ReadHandler that completed its subscription
     179              :         virtual void OnSubscriptionEstablished(ReadHandler * apReadHandler) = 0;
     180              : 
     181              :         /// @brief Callback invoked when a ReadHandler went from a non reportable state to a reportable state. Indicates to the
     182              :         /// observer that a report should be emitted when the min interval allows it.
     183              :         ///
     184              :         /// This will only be invoked for subscribe-type ReadHandler objects, and only after
     185              :         /// OnSubscriptionEstablished has been called.
     186              :         ///
     187              :         /// @param[in] apReadHandler  ReadHandler that became dirty and in HandlerState::CanStartReporting state
     188              :         virtual void OnBecameReportable(ReadHandler * apReadHandler) = 0;
     189              : 
     190              :         /// @brief Callback invoked when the read handler needs to make sure to send a message to the subscriber within the next
     191              :         /// maxInterval time period.
     192              :         /// @param[in] apReadHandler ReadHandler that has generated a report
     193              :         virtual void OnSubscriptionReportSent(ReadHandler * apReadHandler) = 0;
     194              : 
     195              :         /// @brief Callback invoked when a ReadHandler is getting removed so it can be unregistered
     196              :         /// @param[in] apReadHandler  ReadHandler getting destroyed
     197              :         virtual void OnReadHandlerDestroyed(ReadHandler * apReadHandler) = 0;
     198              :     };
     199              : 
     200              :     /*
     201              :      * Destructor - as part of destruction, it will abort the exchange context
     202              :      * if a valid one still exists.
     203              :      *
     204              :      * See Abort() for details on when that might occur.
     205              :      */
     206              :     ~ReadHandler() override;
     207              : 
     208              :     /**
     209              :      *
     210              :      *  Constructor.
     211              :      *
     212              :      *  The callback passed in has to outlive this handler object.
     213              :      *
     214              :      */
     215              :     ReadHandler(ManagementCallback & apCallback, Messaging::ExchangeContext * apExchangeContext, InteractionType aInteractionType,
     216              :                 Observer * observer);
     217              : 
     218              : #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
     219              :     /**
     220              :      *
     221              :      *  Constructor in preparation for resuming a persisted subscription
     222              :      *
     223              :      *  The callback passed in has to outlive this handler object.
     224              :      *
     225              :      */
     226              :     ReadHandler(ManagementCallback & apCallback, Observer * observer);
     227              : #endif
     228              : 
     229          477 :     const SingleLinkedListNode<AttributePathParams> * GetAttributePathList() const { return mpAttributePathList; }
     230         2884 :     const SingleLinkedListNode<EventPathParams> * GetEventPathList() const { return mpEventPathList; }
     231         4722 :     const SingleLinkedListNode<DataVersionFilter> * GetDataVersionFilterList() const { return mpDataVersionFilterList; }
     232              : 
     233              :     /**
     234              :      * @brief Returns the reporting intervals that will used by the ReadHandler for the subscription being requested.
     235              :      *        After the subscription is established, these will be the set reporting intervals and cannot be changed.
     236              :      *
     237              :      * @param[out] aMinInterval minimum time delta between two reports for the subscription
     238              :      * @param[in] aMaxInterval maximum time delta between two reports for the subscription
     239              :      */
     240          449 :     void GetReportingIntervals(uint16_t & aMinInterval, uint16_t & aMaxInterval) const
     241              :     {
     242          449 :         aMinInterval = mMinIntervalFloorSeconds;
     243          449 :         aMaxInterval = mMaxInterval;
     244          449 :     }
     245              : 
     246              :     /**
     247              :      * @brief Returns the maximum reporting interval that was initially requested by the subscriber
     248              :      *        This is the same value as the mMaxInterval member if the max interval is not changed by the publisher.
     249              :      *
     250              :      * @note If the device is an ICD, the MaxInterval of a subscription is automatically set to a multiple of the IdleModeDuration.
     251              :      *       This function is the only way to get the requested max interval once the OnSubscriptionRequested application callback
     252              :      *       is called.
     253              :      *
     254              :      * @return uint16_t subscriber requested maximum reporting interval
     255              :      */
     256           10 :     inline uint16_t GetSubscriberRequestedMaxInterval() const { return mSubscriberRequestedMaxInterval; }
     257              : 
     258           10 :     CHIP_ERROR SetMinReportingIntervalForTests(uint16_t aMinInterval)
     259              :     {
     260           10 :         VerifyOrReturnError(IsIdle(), CHIP_ERROR_INCORRECT_STATE);
     261           10 :         VerifyOrReturnError(aMinInterval <= mMaxInterval, CHIP_ERROR_INVALID_ARGUMENT);
     262              :         // Ensures the new min interval is higher than the subscriber established one.
     263           10 :         mMinIntervalFloorSeconds = std::max(mMinIntervalFloorSeconds, aMinInterval);
     264           10 :         return CHIP_NO_ERROR;
     265              :     }
     266              : 
     267              :     /*
     268              :      * Set the maximum reporting interval for the subscription. This SHALL only be called
     269              :      * from the OnSubscriptionRequested callback above. The restriction is as below
     270              :      * MinIntervalFloor ≤ MaxInterval ≤ MAX(SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT, MaxIntervalCeiling)
     271              :      * Where SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT is set to 60m in the spec.
     272              :      * For ICD publishers, this is set to the IdleModeDuration defined in the ICD Management Cluster.
     273              :      * If the new max interval is less than the idle mode duration for an ICD device, the function will return
     274              :      * CHIP_ERROR_INVALID_ARGUMENT.
     275              :      */
     276           31 :     CHIP_ERROR SetMaxReportingInterval(uint16_t aMaxInterval)
     277              :     {
     278              : #if CHIP_CONFIG_ENABLE_ICD_SERVER
     279              :         if (aMaxInterval < mMaxInterval)
     280              :         {
     281              :             ChipLogProgress(DataManagement,
     282              :                             "Fail to set MaxReportingInterval to %d as it is less than the current MaxInterval %d for ICD device",
     283              :                             aMaxInterval, mMaxInterval);
     284              :             return CHIP_ERROR_INVALID_ARGUMENT;
     285              :         }
     286              : #endif // CHIP_CONFIG_ENABLE_ICD_SERVER
     287           31 :         VerifyOrReturnError(IsIdle(), CHIP_ERROR_INCORRECT_STATE);
     288           29 :         VerifyOrReturnError(mMinIntervalFloorSeconds <= aMaxInterval, CHIP_ERROR_INVALID_ARGUMENT);
     289           27 :         VerifyOrReturnError(aMaxInterval <= std::max(GetPublisherSelectedIntervalLimit(), mSubscriberRequestedMaxInterval),
     290              :                             CHIP_ERROR_INVALID_ARGUMENT);
     291           21 :         mMaxInterval = aMaxInterval;
     292           21 :         return CHIP_NO_ERROR;
     293              :     }
     294              : 
     295              : #if CHIP_CONFIG_PERSIST_SUBSCRIPTIONS
     296              :     /**
     297              :      *
     298              :      *  @brief Initialize a ReadHandler for a resumed subsciption
     299              :      *
     300              :      *  Used after the SubscriptionResumptionSessionEstablisher establishs the CASE session
     301              :      */
     302              :     void OnSubscriptionResumed(const SessionHandle & sessionHandle, SubscriptionResumptionSessionEstablisher & sessionEstablisher);
     303              : #endif
     304              : 
     305              : private:
     306              :     PriorityLevel GetCurrentPriority() const { return mCurrentPriority; }
     307         1980 :     EventNumber & GetEventMin() { return mEventMin; }
     308              : 
     309              :     /**
     310              :      * Returns SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT
     311              :      * For an ICD publisher, this SHALL be set to the idle mode duration.
     312              :      * Otherwise, this SHALL be set to 60 minutes.
     313              :      */
     314              :     uint16_t GetPublisherSelectedIntervalLimit();
     315              : 
     316              :     enum class ReadHandlerFlags : uint8_t
     317              :     {
     318              :         // The flag indicating we are in the middle of a series of chunked report messages, this flag will be cleared during
     319              :         // sending last chunked message.
     320              :         ChunkedReport = (1 << 0),
     321              : 
     322              :         // Tracks whether we're in the initial phase of receiving priming
     323              :         // reports, which is always true for reads and true for subscriptions
     324              :         // prior to receiving a subscribe response.
     325              :         PrimingReports     = (1 << 1),
     326              :         ActiveSubscription = (1 << 2),
     327              :         FabricFiltered     = (1 << 3),
     328              :         // For subscriptions, we record the dirty set generation when we started to generate the last report.
     329              :         // The mCurrentReportsBeginGeneration records the generation at the start of the current report.  This only/
     330              :         // has a meaningful value while IsReporting() is true.
     331              :         //
     332              :         // mPreviousReportsBeginGeneration will be set to mCurrentReportsBeginGeneration after we send the last
     333              :         // chunk of the current report.  Anything that was dirty with a generation earlier than
     334              :         // mPreviousReportsBeginGeneration has had its value sent to the client.
     335              :         // when receiving initial request, it needs mark current handler as dirty.
     336              :         // when there is urgent event, it needs mark current handler as dirty.
     337              :         ForceDirty = (1 << 4),
     338              : 
     339              :         // Don't need the response for report data if true
     340              :         SuppressResponse = (1 << 5),
     341              :     };
     342              : 
     343              :     /**
     344              :      *  Process a read/subscribe request.  Parts of the processing may end up being asynchronous, but the ReadHandler
     345              :      *  guarantees that it will call Shutdown on itself when processing is done (including if OnReadInitialRequest
     346              :      *  returns an error).
     347              :      *
     348              :      *  @retval #Others If fails to process read request
     349              :      *  @retval #CHIP_NO_ERROR On success.
     350              :      *
     351              :      */
     352              :     void OnInitialRequest(System::PacketBufferHandle && aPayload);
     353              : 
     354              :     /**
     355              :      *  Send ReportData to initiator
     356              :      *
     357              :      *  @param[in]    aPayload             A payload that has read request data
     358              :      *  @param[in]    aMoreChunks          A flags indicating there will be more chunks expected to be sent for this read request
     359              :      *
     360              :      *  @retval #Others If fails to send report data
     361              :      *  @retval #CHIP_NO_ERROR On success.
     362              :      *
     363              :      *  If an error is returned, the ReadHandler guarantees that it is not in
     364              :      *  a state where it's waiting for a response.
     365              :      */
     366              :     CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks);
     367              : 
     368              :     /*
     369              :      * Get the appropriate size of a packet buffer to allocate for encoding a Report message.
     370              :      * This size might depend on the underlying session used by the ReadHandler.
     371              :      *
     372              :      * The size returned here is the size not including the various prepended headers
     373              :      * (what System::PacketBuffer calls the "available size").
     374              :      */
     375              :     size_t GetReportBufferMaxSize();
     376              : 
     377              :     /**
     378              :      *  Returns whether this ReadHandler represents a subscription that was created by the other side of the provided exchange.
     379              :      */
     380              :     bool IsFromSubscriber(Messaging::ExchangeContext & apExchangeContext) const;
     381              : 
     382           41 :     bool IsIdle() const { return mState == HandlerState::Idle; }
     383              : 
     384              :     /// @brief Returns whether the ReadHandler is in a state where it can send a report and there is data to report.
     385        10806 :     bool ShouldStartReporting() const
     386              :     {
     387              :         // Important: Anything that changes ShouldStartReporting() from false to true
     388              :         // (which can only happen for subscriptions) must call
     389              :         // mObserver->OnBecameReportable(this).
     390        10806 :         return CanStartReporting() && (ShouldReportUnscheduled() || IsDirty());
     391              :     }
     392              :     /// @brief CanStartReporting() is true if the ReadHandler is in a state where it could generate
     393              :     /// a (possibly empty) report if someone asked it to.
     394        21307 :     bool CanStartReporting() const { return mState == HandlerState::CanStartReporting; }
     395              :     /// @brief ShouldReportUnscheduled() is true if the ReadHandler should be asked to generate reports
     396              :     /// without consulting the report scheduler.
     397         8828 :     bool ShouldReportUnscheduled() const
     398              :     {
     399         8828 :         return CanStartReporting() && (IsType(ReadHandler::InteractionType::Read) || IsPriming());
     400              :     }
     401         7791 :     bool IsAwaitingReportResponse() const { return mState == HandlerState::AwaitingReportResponse; }
     402              : 
     403              :     // Resets the path iterator to the beginning of the whole report for generating a series of new reports.
     404              :     void ResetPathIterator();
     405              : 
     406              :     CHIP_ERROR ProcessDataVersionFilterList(DataVersionFilterIBs::Parser & aDataVersionFilterListParser);
     407              : 
     408              :     // if current priority is in the middle, it has valid snapshoted last event number, it check cleaness via comparing
     409              :     // with snapshotted last event number. if current priority  is in the end, no valid
     410              :     // sanpshotted last event, check with latest last event number, re-setup snapshoted checkpoint, and compare again.
     411              :     bool CheckEventClean(EventManagement & aEventManager);
     412              : 
     413        27924 :     bool IsType(InteractionType type) const { return (mInteractionType == type); }
     414         1513 :     bool IsChunkedReport() const { return mFlags.Has(ReadHandlerFlags::ChunkedReport); }
     415              :     // Is reporting indicates whether we are in the middle of a series chunks. As we will set mIsChunkedReport on the first chunk
     416              :     // and clear that flag on the last chunk, we can use mIsChunkedReport to indicate this state.
     417         3927 :     bool IsReporting() const { return mFlags.Has(ReadHandlerFlags::ChunkedReport); }
     418        10852 :     bool IsPriming() const { return mFlags.Has(ReadHandlerFlags::PrimingReports); }
     419           42 :     bool IsActiveSubscription() const { return mFlags.Has(ReadHandlerFlags::ActiveSubscription); }
     420         4925 :     bool IsFabricFiltered() const { return mFlags.Has(ReadHandlerFlags::FabricFiltered); }
     421              :     CHIP_ERROR OnSubscribeRequest(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload);
     422          441 :     void GetSubscriptionId(SubscriptionId & aSubscriptionId) const { aSubscriptionId = mSubscriptionId; }
     423         1980 :     AttributePathExpandIterator::Position & AttributeIterationPosition() { return mAttributePathExpandPosition; }
     424              : 
     425              :     /// @brief Notifies the read handler that a set of attribute paths has been marked dirty. This will schedule a reporting engine
     426              :     /// run if the change to the attribute path makes the ReadHandler reportable.
     427              :     /// @param aAttributeChanged Path to the attribute that was changed.
     428              :     void AttributePathIsDirty(DataModel::Provider * apDataModel, const AttributePathParams & aAttributeChanged);
     429         4497 :     bool IsDirty() const
     430              :     {
     431         4497 :         return mDirtyGeneration.After(mPreviousReportsBeginGeneration) || mFlags.Has(ReadHandlerFlags::ForceDirty);
     432              :     }
     433         1088 :     void ClearForceDirtyFlag() { ClearStateFlag(ReadHandlerFlags::ForceDirty); }
     434          144 :     NodeId GetInitiatorNodeId() const
     435              :     {
     436          144 :         auto session = GetSession();
     437          144 :         return session == nullptr ? kUndefinedNodeId : session->GetPeerNodeId();
     438              :     }
     439              : 
     440          300 :     FabricIndex GetAccessingFabricIndex() const
     441              :     {
     442          300 :         auto session = GetSession();
     443          300 :         return session == nullptr ? kUndefinedFabricIndex : session->GetFabricIndex();
     444              :     }
     445              : 
     446              :     Transport::SecureSession * GetSession() const;
     447         5916 :     SubjectDescriptor GetSubjectDescriptor() const { return GetSession()->GetSubjectDescriptor(); }
     448         4925 :     bool AllowsLargePayload() const { return GetSession()->AllowsLargePayload(); }
     449              : 
     450           82 :     auto GetTransactionStartGeneration() const { return mTransactionStartGeneration; }
     451              : 
     452              :     /// @brief Forces the read handler into a dirty state, regardless of what's going on with attributes.
     453              :     /// This can lead to scheduling of a reporting run immediately, if the min interval has been reached,
     454              :     /// or after the min interval is reached if it has not yet been reached.
     455              :     void ForceDirtyState();
     456              : 
     457         4925 :     const AttributeEncodeState & GetAttributeEncodeState() const { return mAttributeEncoderState; }
     458         4927 :     void SetAttributeEncodeState(const AttributeEncodeState & aState) { mAttributeEncoderState = aState; }
     459           20 :     uint32_t GetLastWrittenEventsBytes() const { return mLastWrittenEventsBytes; }
     460              : 
     461              :     // Returns the number of interested paths, including wildcard and concrete paths.
     462         6593 :     size_t GetAttributePathCount() const { return mpAttributePathList == nullptr ? 0 : mpAttributePathList->Count(); };
     463         6593 :     size_t GetEventPathCount() const { return mpEventPathList == nullptr ? 0 : mpEventPathList->Count(); };
     464              :     size_t GetDataVersionFilterCount() const { return mpDataVersionFilterList == nullptr ? 0 : mpDataVersionFilterList->Count(); };
     465              : 
     466              :     CHIP_ERROR SendStatusReport(Protocols::InteractionModel::Status aStatus);
     467              : 
     468              :     friend class TestReadInteraction;
     469              :     friend class chip::app::reporting::TestReportingEngine;
     470              :     friend class chip::app::reporting::TestReportScheduler;
     471              : 
     472              :     //
     473              :     // The engine needs to be able to Abort/Close a ReadHandler instance upon completion of work for a given read/subscribe
     474              :     // interaction. We do not want to make these methods public just to give an adjacent class in the IM access, since public
     475              :     // should really be taking application usage considerations as well. Hence, make it a friend.
     476              :     //
     477              :     friend class chip::app::reporting::Engine;
     478              :     friend class chip::app::InteractionModelEngine;
     479              :     friend class TestInteractionModelEngine;
     480              : 
     481              :     // The report scheduler needs to be able to access StateFlag private functions ShouldStartReporting(), CanStartReporting(),
     482              :     // ForceDirtyState() and IsDirty() to know when to schedule a run so it is declared as a friend class.
     483              :     friend class chip::app::reporting::ReportScheduler;
     484              : 
     485              :     enum class HandlerState : uint8_t
     486              :     {
     487              :         Idle,                   ///< The handler has been initialized and is ready
     488              :         CanStartReporting,      ///< The handler has is now capable of generating reports and may generate one immediately
     489              :                                 ///< or later when other criteria are satisfied (e.g hold-off for min reporting interval).
     490              :         AwaitingReportResponse, ///< The handler has sent the report to the client and is awaiting a status response.
     491              :         AwaitingDestruction,    ///< The object has completed its work and is awaiting destruction by the application.
     492              :     };
     493              : 
     494              :     enum class CloseOptions
     495              :     {
     496              :         kDropPersistedSubscription,
     497              :         kKeepPersistedSubscription
     498              :     };
     499              :     /**
     500              :      * Called internally to signal the completion of all work on this objecta and signal to a registered callback that it's
     501              :      * safe to release this object.
     502              :      *
     503              :      *  @param    options             This specifies whether to drop or keep the subscription
     504              :      *
     505              :      */
     506              :     void Close(CloseOptions options = CloseOptions::kDropPersistedSubscription);
     507              : 
     508              :     CHIP_ERROR SendSubscribeResponse();
     509              :     CHIP_ERROR ProcessSubscribeRequest(System::PacketBufferHandle && aPayload);
     510              :     CHIP_ERROR ProcessReadRequest(System::PacketBufferHandle && aPayload);
     511              :     CHIP_ERROR ProcessAttributePaths(AttributePathIBs::Parser & aAttributePathListParser);
     512              :     CHIP_ERROR ProcessEventPaths(EventPathIBs::Parser & aEventPathsParser);
     513              :     CHIP_ERROR ProcessEventFilters(EventFilterIBs::Parser & aEventFiltersParser);
     514              :     CHIP_ERROR OnStatusResponse(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload,
     515              :                                 bool & aSendStatusResponse);
     516              :     CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
     517              :                                  System::PacketBufferHandle && aPayload) override;
     518              :     void OnResponseTimeout(Messaging::ExchangeContext * apExchangeContext) override;
     519              :     void MoveToState(const HandlerState aTargetState);
     520              : 
     521              :     const char * GetStateStr() const;
     522              : 
     523              :     void PersistSubscription();
     524              : 
     525              :     /// @brief Modifies a state flag in the read handler. If the read handler went from a
     526              :     /// non-reportable state to a reportable state, schedules a reporting engine run.
     527              :     /// @param aFlag Flag to set
     528              :     /// @param aValue Flag new value
     529              :     void SetStateFlag(ReadHandlerFlags aFlag, bool aValue = true);
     530              : 
     531              :     /// @brief This function call SetStateFlag with the flag value set to false, thus possibly emitting a report
     532              :     /// generation.
     533              :     /// @param aFlag Flag to clear
     534              :     void ClearStateFlag(ReadHandlerFlags aFlag);
     535              : 
     536              :     SubscriptionId mSubscriptionId = 0;
     537              : 
     538              :     // The current generation of the reporting engine dirty set the last time we were notified that a path we're interested in was
     539              :     // marked dirty.
     540              :     //
     541              :     // This allows us to detemine whether any paths we care about might have
     542              :     // been marked dirty after we had already sent reports for them, which would
     543              :     // mean we should report those paths again, by comparing this generation to the
     544              :     // current generation when we started sending the last set reports that we completed.
     545              :     //
     546              :     // This allows us to reset the iterator to the beginning of the current
     547              :     // cluster instead of the beginning of the whole report in AttributePathIsDirty, without
     548              :     // permanently missing dirty any paths.
     549              :     reporting::AttributeGeneration mDirtyGeneration{ 0 };
     550              : 
     551              :     // For subscriptions, we record the timestamp when we started to generate the last report.
     552              :     // The mCurrentReportsBeginGeneration records the timestamp for the current report, which won;t be used for checking if this
     553              :     // ReadHandler is dirty.
     554              :     // mPreviousReportsBeginGeneration will be set to mCurrentReportsBeginGeneration after we sent the last chunk of the current
     555              :     // report.
     556              :     reporting::AttributeGeneration mPreviousReportsBeginGeneration{ 0 };
     557              :     reporting::AttributeGeneration mCurrentReportsBeginGeneration{ 0 };
     558              :     /*
     559              :      *           (mDirtyGeneration = b > a, this is a dirty read handler)
     560              :      *        +- Start Report -> mCurrentReportsBeginGeneration = c
     561              :      *        |      +- AttributePathIsDirty (Attribute Y) -> mDirtyGeneration = d
     562              :      *        |      |     +- Last Chunk -> mPreviousReportsBeginGeneration = mCurrentReportsBeginGeneration = c
     563              :      *        |      |     |   +- (mDirtyGeneration = d) > (mPreviousReportsBeginGeneration = c), this is a dirty read handler
     564              :      *        |      |     |   |  Attribute X has a dirty generation less than c, Attribute Y has a dirty generation larger than c
     565              :      *        |      |     |   |  So Y will be included in the report but X will not be inclued in this report.
     566              :      * -a--b--c------d-----e---f---> Generation
     567              :      *  |  |
     568              :      *  |  +- AttributePathIsDirty (Attribute X) (mDirtyGeneration = b)
     569              :      *  +- mPreviousReportsBeginGeneration
     570              :      * For read handler, if mDirtyGeneration > mPreviousReportsBeginGeneration, then we regard it as a dirty read handler, and it
     571              :      * should generate report on timeout reached.
     572              :      */
     573              : 
     574              :     // When we don't have enough resources for a new subscription, the oldest subscription might be evicted by interaction model
     575              :     // engine, the "oldest" subscription is the subscription with the smallest generation.
     576              :     reporting::AttributeGeneration mTransactionStartGeneration{ 0 };
     577              : 
     578              :     EventNumber mEventMin = 0;
     579              : 
     580              :     // The last schedule event number snapshoted in the beginning when preparing to fill new events to reports
     581              :     EventNumber mLastScheduledEventNumber = 0;
     582              : 
     583              :     /// Iterator position state for any ongoing path expansion for handling wildcard reads/subscriptions.
     584              :     AttributePathExpandIterator::Position mAttributePathExpandPosition;
     585              : 
     586              :     Messaging::ExchangeHolder mExchangeCtx;
     587              : #if CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
     588              :     // TODO: this should be replaced by a pointer to the InteractionModelEngine that created the ReadHandler
     589              :     // once InteractionModelEngine is no longer a singleton (see issue 23625)
     590              :     Messaging::ExchangeManager * mExchangeMgr = nullptr;
     591              : #endif // CHIP_CONFIG_UNSAFE_SUBSCRIPTION_EXCHANGE_MANAGER_USE
     592              : 
     593              :     SingleLinkedListNode<AttributePathParams> * mpAttributePathList   = nullptr;
     594              :     SingleLinkedListNode<EventPathParams> * mpEventPathList           = nullptr;
     595              :     SingleLinkedListNode<DataVersionFilter> * mpDataVersionFilterList = nullptr;
     596              : 
     597              :     ManagementCallback & mManagementCallback;
     598              : 
     599              :     // TODO (#27675): Merge all observers into one and that one will dispatch the callbacks to the right place.
     600              :     Observer * mObserver = nullptr;
     601              : 
     602              :     uint32_t mLastWrittenEventsBytes = 0;
     603              : 
     604              :     // The detailed encoding state for a single attribute, used by list chunking feature.
     605              :     // The size of AttributeEncoderState is 2 bytes for now.
     606              :     AttributeEncodeState mAttributeEncoderState;
     607              : 
     608              :     uint16_t mMinIntervalFloorSeconds        = 0;
     609              :     uint16_t mMaxInterval                    = 0;
     610              :     uint16_t mSubscriberRequestedMaxInterval = 0;
     611              : 
     612              :     // Current Handler state
     613              :     HandlerState mState            = HandlerState::Idle;
     614              :     PriorityLevel mCurrentPriority = PriorityLevel::Invalid;
     615              :     BitFlags<ReadHandlerFlags> mFlags;
     616              :     InteractionType mInteractionType = InteractionType::Read;
     617              : 
     618              :     SessionHolder mSessionHandle;
     619              : };
     620              : 
     621              : } // namespace app
     622              : } // namespace chip
        

Generated by: LCOV version 2.0-1