Matter SDK Coverage Report
Current view: top level - app - ReadClient.h (source / functions) Coverage Total Hit
Test: SHA:4cbce7f768f16e614f5a8ccb8cd93c92cbeae70d Lines: 45.9 % 37 17
Test Date: 2025-04-26 07:09:35 Functions: 44.8 % 29 13

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 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 client for a CHIP Interaction Data model
      22              :  *
      23              :  */
      24              : 
      25              : #pragma once
      26              : #include "system/SystemClock.h"
      27              : #include <app/AppConfig.h>
      28              : #include <app/AttributePathParams.h>
      29              : #include <app/ConcreteAttributePath.h>
      30              : #include <app/EventHeader.h>
      31              : #include <app/EventPathParams.h>
      32              : #include <app/MessageDef/ReadRequestMessage.h>
      33              : #include <app/MessageDef/StatusIB.h>
      34              : #include <app/MessageDef/StatusResponseMessage.h>
      35              : #include <app/MessageDef/SubscribeRequestMessage.h>
      36              : #include <app/MessageDef/SubscribeResponseMessage.h>
      37              : #include <app/OperationalSessionSetup.h>
      38              : #include <app/ReadPrepareParams.h>
      39              : #include <app/data-model/Decode.h>
      40              : #include <lib/core/CHIPCallback.h>
      41              : #include <lib/core/CHIPCore.h>
      42              : #include <lib/core/TLVDebug.h>
      43              : #include <lib/support/CodeUtils.h>
      44              : #include <lib/support/DLLUtil.h>
      45              : #include <lib/support/logging/CHIPLogging.h>
      46              : #include <messaging/ExchangeContext.h>
      47              : #include <messaging/ExchangeHolder.h>
      48              : #include <messaging/ExchangeMgr.h>
      49              : #include <messaging/Flags.h>
      50              : #include <protocols/Protocols.h>
      51              : #include <system/SystemPacketBuffer.h>
      52              : 
      53              : #if CHIP_CONFIG_ENABLE_READ_CLIENT
      54              : namespace chip {
      55              : namespace app {
      56              : 
      57              : class InteractionModelEngine;
      58              : 
      59              : /**
      60              :  *  @class ReadClient
      61              :  *
      62              :  *  @brief The read client represents the initiator side of a Read Or Subscribe Interaction (depending on the APIs invoked).
      63              :  *
      64              :  *         When used to manage subscriptions, the client provides functionality to automatically re-subscribe as needed,
      65              :  *         including re-establishing CASE under certain conditions (see Callback::OnResubscriptionNeeded for more info).
      66              :  *         This is the default behavior. A consumer can completely opt-out of this behavior by over-riding
      67              :  *         Callback::OnResubscriptionNeeded and providing an alternative implementation.
      68              :  *
      69              :  */
      70              : class ReadClient : public Messaging::ExchangeDelegate
      71              : {
      72              : public:
      73              :     class Callback
      74              :     {
      75              :     public:
      76            0 :         Callback() = default;
      77              : 
      78              :         // Callbacks are not expected to be copyable or movable.
      79              :         Callback(const Callback &)             = delete;
      80              :         Callback(Callback &&)                  = delete;
      81              :         Callback & operator=(const Callback &) = delete;
      82              :         Callback & operator=(Callback &&)      = delete;
      83              : 
      84            0 :         virtual ~Callback() = default;
      85              : 
      86              :         /**
      87              :          * Used to notify a (maybe empty) report data is received from peer and the subscription and the peer is alive.
      88              :          *
      89              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
      90              :          *
      91              :          */
      92            0 :         virtual void NotifySubscriptionStillActive(const ReadClient & apReadClient) {}
      93              : 
      94              :         /**
      95              :          * Used to signal the commencement of processing of the first attribute or event report received in a given exchange.
      96              :          *
      97              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
      98              :          *
      99              :          * Once OnReportBegin has been called, either OnReportEnd or OnError will be called before OnDone.
     100              :          *
     101              :          */
     102            0 :         virtual void OnReportBegin() {}
     103              : 
     104              :         /**
     105              :          * Used to signal the completion of processing of the last attribute or event report in a given exchange.
     106              :          *
     107              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     108              :          *
     109              :          */
     110            0 :         virtual void OnReportEnd() {}
     111              : 
     112              :         /**
     113              :          * Used to deliver event data received through the Read and Subscribe interactions
     114              :          *
     115              :          * Only one of the apData and apStatus can be non-null.
     116              :          *
     117              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     118              :          *
     119              :          * @param[in] aEventHeader The event header in report response.
     120              :          * @param[in] apData A TLVReader positioned right on the payload of the event.
     121              :          * @param[in] apStatus Event-specific status, containing an InteractionModel::Status code as well as an optional
     122              :          *                     cluster-specific status code.
     123              :          */
     124            0 :         virtual void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) {}
     125              : 
     126              :         /**
     127              :          * Used to deliver attribute data received through the Read and Subscribe interactions.
     128              :          *
     129              :          * This callback will be called when:
     130              :          *   - Receiving attribute data as response of Read interactions
     131              :          *   - Receiving attribute data as reports of subscriptions
     132              :          *   - Receiving attribute data as initial reports of subscriptions
     133              :          *
     134              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     135              :          *
     136              :          * @param[in] aPath        The attribute path field in report response.
     137              :          * @param[in] apData       The attribute data of the given path, will be a nullptr if status is not Success.
     138              :          * @param[in] aStatus      Attribute-specific status, containing an InteractionModel::Status code as well as an
     139              :          *                         optional cluster-specific status code.
     140              :          */
     141            0 :         virtual void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) {}
     142              : 
     143              :         /**
     144              :          * OnSubscriptionEstablished will be called when a subscription is established for the given subscription transaction.
     145              :          * If using auto resubscription, OnSubscriptionEstablished will be called whenever resubscription is established.
     146              :          *
     147              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     148              :          *
     149              :          * @param[in] aSubscriptionId The identifier of the subscription that was established.
     150              :          */
     151            0 :         virtual void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) {}
     152              : 
     153              :         /**
     154              :          * OnResubscriptionNeeded will be called when a subscription that was started with SendAutoResubscribeRequest has terminated
     155              :          * and re-subscription is needed. The termination cause is provided to help inform subsequent re-subscription logic.
     156              :          *
     157              :          * The base implementation automatically re-subscribes at appropriate intervals taking the termination cause into account
     158              :          * (see ReadClient::DefaultResubscribePolicy for more details). If the default implementation doesn't suffice, the logic of
     159              :          * ReadClient::DefaultResubscribePolicy is broken down into its constituent methods that are publicly available for
     160              :          * applications to call and sequence.
     161              :          *
     162              :          * If the peer is LIT ICD, and the timeout is reached, `aTerminationCause` will be
     163              :          * `CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT`. In this case, returning `CHIP_NO_ERROR` will still trigger a resubscribe
     164              :          * attempt, while returning `CHIP_ERROR_LIT_SUBSCRIBE_INACTIVE_TIMEOUT` will put the subscription in the
     165              :          * `InactiveICDSubscription` state.  In the latter case, OnResubscriptionNeeded will be called again when
     166              :          * `OnActiveModeNotification` is called.
     167              :          *
     168              :          * If the method is over-ridden, it's the application's responsibility to take the appropriate steps needed to eventually
     169              :          * call-back into the ReadClient object to schedule a re-subscription (by invoking ReadClient::ScheduleResubscription).
     170              :          *
     171              :          * If the application DOES NOT want re-subscription to happen on a particular invocation of this method, returning anything
     172              :          * other than CHIP_NO_ERROR will terminate the interaction and result in OnError, OnDeallocatePaths and OnDone being called
     173              :          * in that sequence.
     174              :          *
     175              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     176              :          *
     177              :          * @param[in] aTerminationCause The cause of failure of the subscription that just terminated.
     178              :          */
     179            0 :         virtual CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause)
     180              :         {
     181            0 :             return apReadClient->DefaultResubscribePolicy(aTerminationCause);
     182              :         }
     183              : 
     184              :         /**
     185              :          * OnError will be called when an error occurs *after* a successful call to SendRequest(). The following
     186              :          * errors will be delivered through this call in the aError field:
     187              :          *
     188              :          * - CHIP_ERROR_TIMEOUT: A response was not received within the expected response timeout.
     189              :          * - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from the server.
     190              :          * - CHIP_ERROR encapsulating a StatusIB: If we got a non-path-specific
     191              :          *   status response from the server.  In that case, constructing
     192              :          *   a StatusIB from the error can be used to extract the status.
     193              :          * - CHIP_ERROR*: All other cases.
     194              :          *
     195              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     196              :          *
     197              :          * @param[in] aError       A system error code that conveys the overall error code.
     198              :          */
     199            0 :         virtual void OnError(CHIP_ERROR aError) {}
     200              : 
     201              :         /**
     202              :          * OnDone will be called when ReadClient has finished all work and it is
     203              :          * safe to destroy and free the allocated ReadClient object and any
     204              :          * other objects associated with the Read or Subscribe interaction.
     205              :          *
     206              :          * The ReadClient is allowed to be destroyed during execution of this callback.
     207              :          *
     208              :          * This function will:
     209              :          *      - Only be called after a successful call to SendRequest or
     210              :          *        SendAutoResubscribeRequest has been made, when the read completes or
     211              :          *        the subscription is shut down.
     212              :          *      - Not be called if the ReadClient instance is destroyed before
     213              :          *        the OnDone call happens.
     214              :          *      - Always be called exactly *once* for a given ReadClient instance,
     215              :          *        if it's called at all.
     216              :          *      - Be called even in error circumstances.
     217              :          *
     218              :          * @param[in] apReadClient the ReadClient for the completed interaction.
     219              :          */
     220              :         virtual void OnDone(ReadClient * apReadClient) = 0;
     221              : 
     222              :         /**
     223              :          * This function is invoked when using SendAutoResubscribeRequest, where the ReadClient was configured to auto re-subscribe
     224              :          * and the ReadPrepareParams was moved into this client for management. This will have to be free'ed appropriately by the
     225              :          * application. If SendAutoResubscribeRequest fails, this function will be called before it returns the failure. If
     226              :          * SendAutoResubscribeRequest succeeds, this function will be called immediately before calling OnDone, or
     227              :          * when the ReadClient is destroyed, if that happens before OnDone. If  SendAutoResubscribeRequest is not called,
     228              :          * this function will not be called.
     229              :          */
     230            0 :         virtual void OnDeallocatePaths(ReadPrepareParams && aReadPrepareParams) {}
     231              : 
     232              :         /**
     233              :          * This function is invoked when constructing a read/subscribeRequest that does not have data
     234              :          * version filters specified, to give the callback a chance to provide some.
     235              :          *
     236              :          * This function is expected to encode as many complete data version filters as will fit into
     237              :          * the buffer, rolling back any partially-encoded filters if it runs out of space, and set the
     238              :          * aEncodedDataVersionList boolean to true if it has successfully encoded at least one data version filter.
     239              :          *
     240              :          * Otherwise aEncodedDataVersionList will be set to false.
     241              :          *
     242              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     243              :          */
     244            0 :         virtual CHIP_ERROR OnUpdateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder,
     245              :                                                          const Span<AttributePathParams> & aAttributePaths,
     246              :                                                          bool & aEncodedDataVersionList)
     247              :         {
     248            0 :             aEncodedDataVersionList = false;
     249            0 :             return CHIP_NO_ERROR;
     250              :         }
     251              : 
     252              :         /**
     253              :          * Get highest received event number.
     254              :          * If the application does not want to filter events by event number, it should call ClearValue() on aEventNumber
     255              :          * and return CHIP_NO_ERROR.  An error return from this function will fail the entire read client interaction.
     256              :          *
     257              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     258              :          */
     259            0 :         virtual CHIP_ERROR GetHighestReceivedEventNumber(Optional<EventNumber> & aEventNumber)
     260              :         {
     261            0 :             aEventNumber.ClearValue();
     262            0 :             return CHIP_NO_ERROR;
     263              :         }
     264              : 
     265              :         /**
     266              :          * OnUnsolicitedMessageFromPublisher will be called for a subscription
     267              :          * ReadClient when any incoming message is received from a matching
     268              :          * node on the fabric.
     269              :          *
     270              :          * This callback will be called:
     271              :          *   - When receiving any unsolicited communication from the node
     272              :          *   - Even for disconnected subscriptions.
     273              :          *
     274              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     275              :          *
     276              :          * @param[in] apReadClient the ReadClient for the subscription.
     277              :          */
     278            0 :         virtual void OnUnsolicitedMessageFromPublisher(ReadClient * apReadClient) {}
     279              : 
     280              :         /**
     281              :          * OnCASESessionEstablished will be called for a subscription ReadClient when
     282              :          * it finishes setting up a CASE session, as part of either automatic
     283              :          * re-subscription or doing an initial subscribe based on ScopedNodeId.
     284              :          *
     285              :          * The callee is allowed to modify the ReadPrepareParams (e.g. to change
     286              :          * things like min/max intervals based on the session parameters).
     287              :          *
     288              :          * The ReadClient MUST NOT be destroyed during execution of this callback (i.e. before the callback returns).
     289              :          */
     290            0 :         virtual void OnCASESessionEstablished(const SessionHandle & aSession, ReadPrepareParams & aSubscriptionParams) {}
     291              :     };
     292              : 
     293              :     enum class InteractionType : uint8_t
     294              :     {
     295              :         Read,
     296              :         Subscribe,
     297              :     };
     298              : 
     299              :     enum class PeerType : uint8_t
     300              :     {
     301              :         kNormal,
     302              :         kLITICD,
     303              :     };
     304              : 
     305              :     /**
     306              :      *
     307              :      *  Constructor.
     308              :      *
     309              :      *  The callback passed in has to outlive this ReadClient object.
     310              :      *
     311              :      *  This object can outlive the InteractionModelEngine passed in. However, upon shutdown of the engine,
     312              :      *  this object will cease to function correctly since it depends on the engine for a number of critical functions.
     313              :      *
     314              :      *  @param[in]    apImEngine       A valid pointer to the IM engine.
     315              :      *  @param[in]    apExchangeMgr    A pointer to the ExchangeManager object. Allowed to be null
     316              :      *                                 if the version of SendAutoResubscribeRequest that takes a
     317              :      *                                 ScopedNodeId is used.
     318              :      *  @param[in]    apCallback       Callback set by application.
     319              :      *  @param[in]    aInteractionType Type of interaction (read or subscribe)
     320              :      *
     321              :      *  @retval #CHIP_ERROR_INCORRECT_STATE incorrect state if it is already initialized
     322              :      *  @retval #CHIP_NO_ERROR On success.
     323              :      *
     324              :      */
     325              :     ReadClient(InteractionModelEngine * apImEngine, Messaging::ExchangeManager * apExchangeMgr, Callback & apCallback,
     326              :                InteractionType aInteractionType);
     327              : 
     328              :     /**
     329              :      * Destructor.
     330              :      *
     331              :      * The ReadClient object may be destroyed at any time while not in the middle of executing a ReadClient::Callback
     332              :      * callback, and may also be destroyed from inside the OnDone callback.
     333              :      *
     334              :      * Destroying the ReadClient will abort the exchange context if a valid one still exists. It will also cancel any
     335              :      * liveness timers that may be active.
     336              :      *
     337              :      * OnDone() will not be called if the ReadClient is destroyed before that call would have happened.
     338              :      */
     339              :     ~ReadClient() override;
     340              : 
     341              :     /**
     342              :      *  Send a request.  There can be one request outstanding on a given ReadClient.
     343              :      *  If SendRequest returns success, no more SendRequest calls can happen on this ReadClient
     344              :      *  until the corresponding OnDone call has happened.
     345              :      *
     346              :      *  This will send either a Read Request or a Subscribe Request depending on
     347              :      *  the InteractionType this read client was initialized with.
     348              :      *
     349              :      *  If the params contain more data version filters than can fit in the request packet
     350              :      *  the list will be truncated as needed, i.e. filter inclusion is on a best effort basis.
     351              :      *
     352              :      *  @retval #others fail to send read request
     353              :      *  @retval #CHIP_NO_ERROR On success.
     354              :      */
     355              :     CHIP_ERROR SendRequest(ReadPrepareParams & aReadPrepareParams);
     356              : 
     357              :     /**
     358              :      *  Re-activate an inactive subscription.
     359              :      *
     360              :      *  This function should be called when the peer is an ICD that is checking in and this ReadClient represents a subscription
     361              :      * that would cause that ICD to not need to check in anymore.
     362              :      *
     363              :      *  This API only works when issuing subscription via SendAutoResubscribeRequest.
     364              :      */
     365              :     void OnActiveModeNotification();
     366              : 
     367              :     void OnUnsolicitedReportData(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload);
     368              : 
     369          195 :     void OnUnsolicitedMessageFromPublisher()
     370              :     {
     371          195 :         TriggerResubscribeIfScheduled("unsolicited message");
     372              : 
     373              :         // Then notify callbacks
     374          195 :         mpCallback.OnUnsolicitedMessageFromPublisher(this);
     375          195 :     }
     376              : 
     377              :     auto GetSubscriptionId() const
     378              :     {
     379              :         using returnType = Optional<decltype(mSubscriptionId)>;
     380              :         return mInteractionType == InteractionType::Subscribe ? returnType(mSubscriptionId) : returnType::Missing();
     381              :     }
     382              : 
     383           41 :     FabricIndex GetFabricIndex() const { return mPeer.GetFabricIndex(); }
     384           71 :     NodeId GetPeerNodeId() const { return mPeer.GetNodeId(); }
     385          645 :     bool IsReadType() { return mInteractionType == InteractionType::Read; }
     386         5006 :     bool IsSubscriptionType() const { return mInteractionType == InteractionType::Subscribe; };
     387              : 
     388              :     /*
     389              :      * Retrieve the reporting intervals associated with an active subscription. This should only be called if we're of subscription
     390              :      * interaction type and after a subscription has been established.
     391              :      */
     392              :     CHIP_ERROR GetReportingIntervals(uint16_t & aMinIntervalFloorSeconds, uint16_t & aMaxIntervalCeilingSeconds) const
     393              :     {
     394              :         VerifyOrReturnError(IsSubscriptionType(), CHIP_ERROR_INCORRECT_STATE);
     395              :         VerifyOrReturnError(IsSubscriptionActive(), CHIP_ERROR_INCORRECT_STATE);
     396              : 
     397              :         aMinIntervalFloorSeconds   = mMinIntervalFloorSeconds;
     398              :         aMaxIntervalCeilingSeconds = mMaxInterval;
     399              : 
     400              :         return CHIP_NO_ERROR;
     401              :     }
     402              : 
     403          161 :     ReadClient * GetNextClient() { return mpNext; }
     404          154 :     void SetNextClient(ReadClient * apClient) { mpNext = apClient; }
     405              : 
     406              :     /**
     407              :      *  Like SendSubscribeRequest, but the ReadClient will automatically attempt to re-establish the subscription if
     408              :      *  we decide that the subscription has dropped.  The exact behavior of the re-establishment can be controlled
     409              :      *  by overriding Callback::OnResubscriptionNeeded().  If not overridden, a default behavior with exponential
     410              :      *  backoff from will be used.
     411              :      *
     412              :      *  The application has to know to
     413              :      *  a) allocate a ReadPrepareParams object that will have fields mpEventPathParamsList and mpAttributePathParamsList and
     414              :      *  mpDataVersionFilterList with lifetimes as long as the ReadClient itself and b) free those up later in the call to
     415              :      *  OnDeallocatePaths. Note: At a given time in the system, you can either have a single subscription with re-sub enabled that
     416              :      *  has mKeepSubscriptions = false, OR, multiple subs with re-sub enabled with mKeepSubscriptions = true. You shall not
     417              :      *  have a mix of both simultaneously. If SendAutoResubscribeRequest is called at all, it guarantees that it will call
     418              :      *  OnDeallocatePaths (either before returning error, or when OnDone is called or the ReadClient is destroyed).
     419              :      *  SendAutoResubscribeRequest is the only case that calls OnDeallocatePaths, since that's the only case when the consumer
     420              :      *  moved a ReadParams into the client.
     421              :      *
     422              :      */
     423              :     CHIP_ERROR SendAutoResubscribeRequest(ReadPrepareParams && aReadPrepareParams);
     424              : 
     425              :     /**
     426              :      * Like SendAutoResubscribeRequest above, but without a session being
     427              :      * available in the ReadPrepareParams.  When this is used, the ReadClient is
     428              :      * responsible for setting up the CASE session itself.
     429              :      *
     430              :      * When using this version of SendAutoResubscribeRequest, any session to
     431              :      * which ReadPrepareParams has a reference will be ignored.
     432              :      */
     433              :     CHIP_ERROR SendAutoResubscribeRequest(const ScopedNodeId & aPublisherId, ReadPrepareParams && aReadPrepareParams);
     434              : 
     435              :     /**
     436              :      *   This provides a standard re-subscription policy implementation that given a termination cause, does the following:
     437              :      *   - Calculates the time till next subscription with fibonacci back-off (implemented by ComputeTimeTillNextSubscription()).
     438              :      *   - Schedules the next subscription attempt at the computed interval from the previous step. Operational discovery and
     439              :      *     CASE establishment will be attempted if aTerminationCause was CHIP_ERROR_TIMEOUT. In all other cases, it will attempt
     440              :      *     to re-use a previously established session.
     441              :      */
     442              :     CHIP_ERROR DefaultResubscribePolicy(CHIP_ERROR aTerminationCause);
     443              : 
     444              :     /**
     445              :      * Computes the time, in milliseconds, until the next re-subscription over
     446              :      * an ever increasing window following a fibonacci sequence with the current retry count
     447              :      * used as input to the fibonacci algorithm.
     448              :      *
     449              :      * CHIP_RESUBSCRIBE_MAX_FIBONACCI_STEP_INDEX is the maximum value the retry count can tick up to.
     450              :      *
     451              :      */
     452              :     uint32_t ComputeTimeTillNextSubscription();
     453              : 
     454              :     /**
     455              :      * Schedules a re-subscription aTimeTillNextResubscriptionMs into the future.
     456              :      *
     457              :      * If an application wants to set up CASE on their own, they should call ComputeTimeTillNextSubscription() to compute the next
     458              :      * interval at which they should attempt CASE and attempt CASE at that time. On successful CASE establishment, this method
     459              :      * should be called with the new SessionHandle provided through 'aNewSessionHandle', 'aTimeTillNextResubscriptionMs' set to 0
     460              :      * (i.e async, but as soon as possible) and 'aReestablishCASE' set to false.
     461              :      *
     462              :      * Otherwise, if aReestablishCASE is true, operational discovery and CASE will be attempted at that time before
     463              :      * the actual IM interaction is initiated.
     464              :      *
     465              :      * aReestablishCASE SHALL NOT be set to true if a valid SessionHandle is provided through newSessionHandle.
     466              :      */
     467              :     CHIP_ERROR ScheduleResubscription(uint32_t aTimeTillNextResubscriptionMs, Optional<SessionHandle> aNewSessionHandle,
     468              :                                       bool aReestablishCASE);
     469              : 
     470              :     // Like SendSubscribeRequest, but allows sending certain forms of invalid
     471              :     // subscribe requests that servers are expected to reject, for testing
     472              :     // purposes.  Should only be called from tests.
     473              : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
     474              :     CHIP_ERROR SendSubscribeRequestWithoutValidation(const ReadPrepareParams & aReadPrepareParams)
     475              :     {
     476              :         return SendSubscribeRequestImpl(aReadPrepareParams);
     477              :     }
     478              : #endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
     479              : 
     480              :     /**
     481              :      * Override the interval at which liveness of the subscription is assessed.
     482              :      * By default, this is set set to the max interval of the subscription + ACK timeout of the underlying session.
     483              :      *
     484              :      * This can be only be called once a subscription has been established and is active. Once called, this will cancel any existing
     485              :      * liveness timers and schedule a new one.
     486              :      *
     487              :      * This can be called from the Callback::OnSubscriptionEstablished callback.
     488              :      *
     489              :      */
     490              :     void OverrideLivenessTimeout(System::Clock::Timeout aLivenessTimeout);
     491              : 
     492              :     /**
     493              :      * If the ReadClient currently has a resubscription attempt scheduled,
     494              :      * trigger that attempt right now.  This is generally useful when a consumer
     495              :      * has some sort of indication that the server side is currently up and
     496              :      * communicating, so right now is a good time to try to resubscribe.
     497              :      *
     498              :      * The reason string is used for logging if a resubscribe is triggered.
     499              :      */
     500              :     void TriggerResubscribeIfScheduled(const char * reason);
     501              : 
     502              :     /**
     503              :      * Returns the timeout after which we consider the subscription to have
     504              :      * dropped, if we have received no messages within that amount of time.
     505              :      *
     506              :      * Returns NullOptional if a subscription has not yet been established (and
     507              :      * hence the MaxInterval is not yet known), or if the subscription session
     508              :      * is gone and hence the relevant MRP parameters can no longer be determined.
     509              :      */
     510              :     Optional<System::Clock::Timeout> GetSubscriptionTimeout();
     511              : 
     512              : private:
     513              :     friend class TestReadInteraction;
     514              :     friend class InteractionModelEngine;
     515              : 
     516              :     enum class ClientState : uint8_t
     517              :     {
     518              :         Idle,                      ///< The client has been initialized and is ready for a SendRequest
     519              :         AwaitingInitialReport,     ///< The client is waiting for initial report
     520              :         AwaitingSubscribeResponse, ///< The client is waiting for subscribe response
     521              :         SubscriptionActive,        ///< The client is maintaining subscription
     522              :         InactiveICDSubscription,   ///< The client is waiting to resubscribe for LIT device
     523              :     };
     524              : 
     525              :     enum class ReportType
     526              :     {
     527              :         // kUnsolicited reports are the first message in an exchange.
     528              :         kUnsolicited,
     529              :         // kContinuingTransaction reports are responses to a message we sent.
     530              :         kContinuingTransaction
     531              :     };
     532              : 
     533          611 :     bool IsMatchingSubscriptionId(SubscriptionId aSubscriptionId)
     534              :     {
     535          611 :         return aSubscriptionId == mSubscriptionId && mInteractionType == InteractionType::Subscribe;
     536              :     }
     537              : 
     538              :     CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
     539              :                                  System::PacketBufferHandle && aPayload) override;
     540              :     void OnResponseTimeout(Messaging::ExchangeContext * apExchangeContext) override;
     541              : 
     542              :     /**
     543              :      *  Updates the type (LIT ICD or not) of the peer.
     544              :      *
     545              :      *  When the subscription is active, this function will just set the flag. When the subscription is an InactiveICDSubscription,
     546              :      * setting the peer type to SIT or normal devices will also trigger a resubscription attempt.
     547              :      *
     548              :      */
     549              :     void OnPeerTypeChange(PeerType aType);
     550              : 
     551              :     /**
     552              :      *  Check if current read client is being used
     553              :      *
     554              :      */
     555         2043 :     bool IsIdle() const { return mState == ClientState::Idle; }
     556         2189 :     bool IsInactiveICDSubscription() const { return mState == ClientState::InactiveICDSubscription; }
     557         1153 :     bool IsSubscriptionActive() const { return mState == ClientState::SubscriptionActive; }
     558          700 :     bool IsAwaitingInitialReport() const { return mState == ClientState::AwaitingInitialReport; }
     559          253 :     bool IsAwaitingSubscribeResponse() const { return mState == ClientState::AwaitingSubscribeResponse; }
     560              : 
     561              :     CHIP_ERROR GenerateEventPaths(EventPathIBs::Builder & aEventPathsBuilder, const Span<EventPathParams> & aEventPaths);
     562              :     CHIP_ERROR GenerateAttributePaths(AttributePathIBs::Builder & aAttributePathIBsBuilder,
     563              :                                       const Span<AttributePathParams> & aAttributePaths);
     564              : 
     565              :     CHIP_ERROR GenerateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder,
     566              :                                              const Span<AttributePathParams> & aAttributePaths,
     567              :                                              const Span<DataVersionFilter> & aDataVersionFilters, bool & aEncodedDataVersionList);
     568              :     CHIP_ERROR BuildDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder,
     569              :                                           const Span<AttributePathParams> & aAttributePaths,
     570              :                                           const Span<DataVersionFilter> & aDataVersionFilters, bool & aEncodedDataVersionList);
     571              :     CHIP_ERROR ReadICDOperatingModeFromAttributeDataIB(TLV::TLVReader && aReader, PeerType & aType);
     572              :     CHIP_ERROR ProcessAttributeReportIBs(TLV::TLVReader & aAttributeDataIBsReader);
     573              :     CHIP_ERROR ProcessEventReportIBs(TLV::TLVReader & aEventReportIBsReader);
     574              : 
     575              :     static void OnLivenessTimeoutCallback(System::Layer * apSystemLayer, void * apAppState);
     576              :     CHIP_ERROR ProcessSubscribeResponse(System::PacketBufferHandle && aPayload);
     577              :     CHIP_ERROR RefreshLivenessCheckTimer();
     578              :     CHIP_ERROR ComputeLivenessCheckTimerTimeout(System::Clock::Timeout * aTimeout);
     579              :     void CancelLivenessCheckTimer();
     580              :     void CancelResubscribeTimer();
     581              :     void TriggerResubscriptionForLivenessTimeout(CHIP_ERROR aReason);
     582              :     void MoveToState(const ClientState aTargetState);
     583              :     CHIP_ERROR ProcessAttributePath(AttributePathIB::Parser & aAttributePath, ConcreteDataAttributePath & aClusterInfo);
     584              :     CHIP_ERROR ProcessReportData(System::PacketBufferHandle && aPayload, ReportType aReportType);
     585              :     const char * GetStateStr() const;
     586              : 
     587              :     /*
     588              :      * Checks if we should re-subscribe based on the specified re-subscription policy. If we should, re-subscription is scheduled
     589              :      * aNextResubscribeIntervalMsec is updated accordingly, and true is returned.
     590              :      *
     591              :      * If we should not resubscribe, false is returned.
     592              :      *
     593              :      *  @param[out]    aNextResubscribeIntervalMsec    How long we will wait before trying to auto-resubscribe.
     594              :      */
     595              :     bool ResubscribeIfNeeded(uint32_t & aNextResubscribeIntervalMsec);
     596              : 
     597              :     // Specialized request-sending functions.
     598              :     CHIP_ERROR SendReadRequest(ReadPrepareParams & aReadPrepareParams);
     599              :     // SendSubscribeRequest performs som validation on aSubscribePrepareParams
     600              :     // and then calls SendSubscribeRequestImpl.
     601              :     CHIP_ERROR SendSubscribeRequest(const ReadPrepareParams & aSubscribePrepareParams);
     602              :     CHIP_ERROR SendSubscribeRequestImpl(const ReadPrepareParams & aSubscribePrepareParams);
     603              :     void UpdateDataVersionFilters(const ConcreteDataAttributePath & aPath);
     604              :     static void OnResubscribeTimerCallback(System::Layer * apSystemLayer, void * apAppState);
     605              :     // Called to ensure OnReportBegin is called before calling OnEventData or OnAttributeData
     606              :     void NoteReportingData();
     607              : 
     608              :     /*
     609              :      * Called internally to signal the completion of all work on this object, gracefully close the
     610              :      * exchange and finally, signal to the application that it's
     611              :      * safe to release this object.
     612              :      *
     613              :      * If aError != CHIP_NO_ERROR, this will trigger re-subscriptions if allowResubscription is true
     614              :      * AND if this ReadClient instance is tracking a subscription AND the applications decides to do so
     615              :      * in their implementation of Callback::OnResubscriptionNeeded().
     616              :      */
     617              :     void Close(CHIP_ERROR aError, bool allowResubscription = true);
     618              : 
     619              :     void StopResubscription();
     620              :     void ClearActiveSubscriptionState();
     621              : 
     622              :     static void HandleDeviceConnected(void * context, Messaging::ExchangeManager & exchangeMgr,
     623              :                                       const SessionHandle & sessionHandle);
     624              :     static void HandleDeviceConnectionFailure(void * context, const OperationalSessionSetup::ConnectionFailureInfo & failureInfo);
     625              : 
     626              :     CHIP_ERROR GetMinEventNumber(const ReadPrepareParams & aReadPrepareParams, Optional<EventNumber> & aEventMin);
     627              : 
     628              :     /**
     629              :      * Start setting up a CASE session to our peer, if we can locate a
     630              :      * CASESessionManager.  Returns error if we did not even manage to kick off
     631              :      * a CASE attempt.
     632              :      */
     633              :     CHIP_ERROR EstablishSessionToPeer();
     634              : 
     635              :     Messaging::ExchangeManager * mpExchangeMgr = nullptr;
     636              :     Messaging::ExchangeHolder mExchange;
     637              :     Callback & mpCallback;
     638              :     ClientState mState    = ClientState::Idle;
     639              :     bool mIsReporting     = false;
     640              :     bool mIsInitialReport = true;
     641              :     // boolean to check if client is waiting for the first priming report
     642              :     bool mWaitingForFirstPrimingReport = true;
     643              :     bool mPendingMoreChunks            = false;
     644              :     uint16_t mMinIntervalFloorSeconds  = 0;
     645              :     uint16_t mMaxInterval              = 0;
     646              :     SubscriptionId mSubscriptionId     = 0;
     647              :     ScopedNodeId mPeer;
     648              :     InteractionType mInteractionType = InteractionType::Read;
     649              :     Timestamp mEventTimestamp;
     650              : 
     651              :     bool mForceCaseOnNextResub      = true;
     652              :     bool mIsResubscriptionScheduled = false;
     653              : 
     654              :     // mMinimalResubscribeDelay is used to store the delay returned with a BUSY
     655              :     // response to a Sigma1 message.
     656              :     System::Clock::Milliseconds16 mMinimalResubscribeDelay = System::Clock::kZero;
     657              : 
     658              :     chip::Callback::Callback<OnDeviceConnected> mOnConnectedCallback;
     659              :     chip::Callback::Callback<OperationalSessionSetup::OnSetupFailure> mOnConnectionFailureCallback;
     660              : 
     661              :     ReadClient * mpNext                 = nullptr;
     662              :     InteractionModelEngine * mpImEngine = nullptr;
     663              : 
     664              :     //
     665              :     // This stores the params associated with the interaction in a specific set of cases:
     666              :     //      1. Stores all parameters when used with subscriptions initiated using SendAutoResubscribeRequest.
     667              :     //      2. Stores just the SessionHolder when used with any subscriptions.
     668              :     //
     669              :     ReadPrepareParams mReadPrepareParams;
     670              :     uint32_t mNumRetries = 0;
     671              : 
     672              :     System::Clock::Timeout mLivenessTimeoutOverride = System::Clock::kZero;
     673              : 
     674              :     bool mIsPeerLIT = false;
     675              : 
     676              :     // End Of Container (0x18) uses one byte.
     677              :     static constexpr uint16_t kReservedSizeForEndOfContainer = 1;
     678              :     // Reserved size for the uint8_t InteractionModelRevision flag, which takes up 1 byte for the control tag and 1 byte for the
     679              :     // context tag, 1 byte for value
     680              :     static constexpr uint16_t kReservedSizeForIMRevision = 1 + 1 + 1;
     681              :     // Reserved buffer for TLV level overhead (the overhead for data version filter IBs EndOfContainer, IM reversion end
     682              :     // of RequestMessage (another end of container)).
     683              :     static constexpr uint16_t kReservedSizeForTLVEncodingOverhead =
     684              :         kReservedSizeForEndOfContainer + kReservedSizeForIMRevision + kReservedSizeForEndOfContainer;
     685              : 
     686              : #if CHIP_PROGRESS_LOGGING
     687              :     // Tracks the time when a subscribe request is successfully sent.
     688              :     // This timestamp allows for logging the duration taken to established the subscription.
     689              :     System::Clock::Timestamp mSubscribeRequestTime = System::Clock::kZero;
     690              : #endif
     691              : };
     692              : 
     693              : };     // namespace app
     694              : };     // namespace chip
     695              : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
        

Generated by: LCOV version 2.0-1