LCOV - code coverage report
Current view: top level - app - WriteHandler.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 8 9 88.9 %
Date: 2024-02-15 08:20:41 Functions: 6 8 75.0 %

          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             : #pragma once
      20             : #include <app/AttributeAccessToken.h>
      21             : #include <app/AttributePathParams.h>
      22             : #include <app/MessageDef/WriteResponseMessage.h>
      23             : #include <lib/core/CHIPCore.h>
      24             : #include <lib/core/TLVDebug.h>
      25             : #include <lib/support/CodeUtils.h>
      26             : #include <lib/support/DLLUtil.h>
      27             : #include <lib/support/logging/CHIPLogging.h>
      28             : #include <messaging/ExchangeHolder.h>
      29             : #include <messaging/ExchangeMgr.h>
      30             : #include <messaging/Flags.h>
      31             : #include <protocols/Protocols.h>
      32             : #include <protocols/interaction_model/Constants.h>
      33             : #include <system/SystemPacketBuffer.h>
      34             : #include <system/TLVPacketBufferBackingStore.h>
      35             : 
      36             : namespace chip {
      37             : namespace app {
      38             : /**
      39             :  *  @brief The write handler is responsible for processing a write request and sending a write reply.
      40             :  */
      41             : class WriteHandler : public Messaging::ExchangeDelegate
      42             : {
      43             : public:
      44         100 :     WriteHandler() : mExchangeCtx(*this) {}
      45             : 
      46             :     /**
      47             :      *  Initialize the WriteHandler. Within the lifetime
      48             :      *  of this instance, this method is invoked once after object
      49             :      *  construction until a call to Close is made to terminate the
      50             :      *  instance.
      51             :      *
      52             :      *  @retval #CHIP_ERROR_INCORRECT_STATE If the state is not equal to
      53             :      *          kState_NotInitialized.
      54             :      *  @retval #CHIP_NO_ERROR On success.
      55             :      */
      56             :     CHIP_ERROR Init();
      57             : 
      58             :     /**
      59             :      *  Process a write request.  Parts of the processing may end up being asynchronous, but the WriteHandler
      60             :      *  guarantees that it will call Close on itself when processing is done (including if OnWriteRequest
      61             :      *  returns an error).
      62             :      *
      63             :      *  @param[in]    apExchangeContext    A pointer to the ExchangeContext.
      64             :      *  @param[in]    aPayload             A payload that has read request data
      65             :      *  @param[in]    aIsTimedWrite        Whether write is part of a timed interaction.
      66             :      *
      67             :      *  @retval Status.  Callers are expected to send a status response if the
      68             :      *  return status is not Status::Success.
      69             :      */
      70             :     Protocols::InteractionModel::Status OnWriteRequest(Messaging::ExchangeContext * apExchangeContext,
      71             :                                                        System::PacketBufferHandle && aPayload, bool aIsTimedWrite);
      72             : 
      73             :     /**
      74             :      *  Clean up state when we are done sending the write response.
      75             :      */
      76             :     void Close();
      77             : 
      78       11882 :     bool IsFree() const { return mState == State::Uninitialized; }
      79             : 
      80         100 :     ~WriteHandler() override = default;
      81             : 
      82             :     CHIP_ERROR ProcessAttributeDataIBs(TLV::TLVReader & aAttributeDataIBsReader);
      83             :     CHIP_ERROR ProcessGroupAttributeDataIBs(TLV::TLVReader & aAttributeDataIBsReader);
      84             : 
      85             :     CHIP_ERROR AddStatus(const ConcreteDataAttributePath & aPath, const Protocols::InteractionModel::Status aStatus);
      86             : 
      87             :     CHIP_ERROR AddClusterSpecificSuccess(const ConcreteDataAttributePath & aAttributePathParams, uint8_t aClusterStatus);
      88             : 
      89             :     CHIP_ERROR AddClusterSpecificFailure(const ConcreteDataAttributePath & aAttributePathParams, uint8_t aClusterStatus);
      90             : 
      91             :     FabricIndex GetAccessingFabricIndex() const;
      92             : 
      93             :     /**
      94             :      * Check whether the WriteRequest we are handling is a timed write.
      95             :      */
      96           0 :     bool IsTimedWrite() const { return mIsTimedRequest; }
      97             : 
      98             :     bool MatchesExchangeContext(Messaging::ExchangeContext * apExchangeContext) const
      99             :     {
     100             :         return !IsFree() && mExchangeCtx.Get() == apExchangeContext;
     101             :     }
     102             : 
     103        2434 :     void CacheACLCheckResult(const AttributeAccessToken & aToken) { mACLCheckCache.SetValue(aToken); }
     104             : 
     105        2434 :     bool ACLCheckCacheHit(const AttributeAccessToken & aToken)
     106             :     {
     107        2434 :         return mACLCheckCache.HasValue() && mACLCheckCache.Value() == aToken;
     108             :     }
     109             : 
     110          12 :     bool IsCurrentlyProcessingWritePath(const ConcreteAttributePath & aPath)
     111             :     {
     112          12 :         return mProcessingAttributePath.HasValue() && mProcessingAttributePath.Value() == aPath;
     113             :     }
     114             : 
     115             : private:
     116             :     friend class TestWriteInteraction;
     117             :     enum class State
     118             :     {
     119             :         Uninitialized = 0, // The handler has not been initialized
     120             :         Initialized,       // The handler has been initialized and is ready
     121             :         AddStatus,         // The handler has added status code
     122             :         Sending,           // The handler has sent out the write response
     123             :     };
     124             :     using Status = Protocols::InteractionModel::Status;
     125             :     Status ProcessWriteRequest(System::PacketBufferHandle && aPayload, bool aIsTimedWrite);
     126             :     Status HandleWriteRequestMessage(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload,
     127             :                                      bool aIsTimedWrite);
     128             : 
     129             :     CHIP_ERROR FinalizeMessage(System::PacketBufferTLVWriter && aMessageWriter, System::PacketBufferHandle & packet);
     130             :     CHIP_ERROR SendWriteResponse(System::PacketBufferTLVWriter && aMessageWriter);
     131             : 
     132             :     void MoveToState(const State aTargetState);
     133             :     const char * GetStateStr() const;
     134             : 
     135             :     void DeliverListWriteBegin(const ConcreteAttributePath & aPath);
     136             :     void DeliverListWriteEnd(const ConcreteAttributePath & aPath, bool writeWasSuccessful);
     137             : 
     138             :     // Deliver the signal that we have delivered all list entries to the AttributeAccessInterface. This function will be called
     139             :     // after handling the last chunk of a series of write requests. Or the write handler was shutdown (usually due to transport
     140             :     // timeout).
     141             :     // This function will become no-op on group writes, since DeliverFinalListWriteEndForGroupWrite will clear the
     142             :     // mProcessingAttributePath after processing the AttributeDataIBs from the request.
     143             :     void DeliverFinalListWriteEnd(bool writeWasSuccessful);
     144             : 
     145             :     // Deliver the signal that we have delivered all list entries to the AttributeAccessInterface. This function will be called
     146             :     // after handling the last attribute in a group write request (since group writes will never be chunked writes). Or we failed to
     147             :     // process the group write request (usually due to malformed messages). This function should only be called by
     148             :     // ProcessGroupAttributeDataIBs.
     149             :     CHIP_ERROR DeliverFinalListWriteEndForGroupWrite(bool writeWasSuccessful);
     150             : 
     151             :     CHIP_ERROR AddStatus(const ConcreteDataAttributePath & aPath, const StatusIB & aStatus);
     152             : 
     153             : private:
     154             :     // ExchangeDelegate
     155             :     CHIP_ERROR OnMessageReceived(Messaging::ExchangeContext * apExchangeContext, const PayloadHeader & aPayloadHeader,
     156             :                                  System::PacketBufferHandle && aPayload) override;
     157             :     void OnResponseTimeout(Messaging::ExchangeContext * apExchangeContext) override;
     158             : 
     159             :     Messaging::ExchangeHolder mExchangeCtx;
     160             :     WriteResponseMessage::Builder mWriteResponseBuilder;
     161             :     State mState           = State::Uninitialized;
     162             :     bool mIsTimedRequest   = false;
     163             :     bool mSuppressResponse = false;
     164             :     bool mHasMoreChunks    = false;
     165             :     Optional<ConcreteAttributePath> mProcessingAttributePath;
     166             :     bool mProcessingAttributeIsList = false;
     167             :     // We record the Status when AddStatus is called to determine whether all data of a list write is accepted.
     168             :     // This value will be used by DeliverListWriteEnd and DeliverFinalListWriteEnd but it won't be used by group writes based on the
     169             :     // fact that the errors that won't be delivered to AttributeAccessInterface are:
     170             :     //  (1) Attribute not found
     171             :     //  (2) Access control failed
     172             :     //  (3) Write request to a read-only attribute
     173             :     //  (4) Data version mismatch
     174             :     //  (5) Not using timed write.
     175             :     //  Where (1)-(3) will be consistent among the whole list write request, while (4) and (5) are not appliable to group writes.
     176             :     bool mAttributeWriteSuccessful                = false;
     177             :     Optional<AttributeAccessToken> mACLCheckCache = NullOptional;
     178             : };
     179             : } // namespace app
     180             : } // namespace chip

Generated by: LCOV version 1.14