Matter SDK Coverage Report
Current view: top level - protocols/bdx - BdxTransferSession.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 15.4 % 13 2
Test Date: 2025-01-17 19:00:11 Functions: 18.2 % 11 2

            Line data    Source code
       1              : /**
       2              :  *    @file
       3              :  *      This file defines a TransferSession state machine that contains the main logic governing a Bulk Data Transfer session. It
       4              :  *      provides APIs for starting a transfer or preparing to receive a transfer request, providing input to be processed, and
       5              :  *      accessing output data (including messages to be sent, message data received by the TransferSession, or state information).
       6              :  */
       7              : 
       8              : #pragma once
       9              : 
      10              : #include <lib/core/CHIPError.h>
      11              : #include <protocols/bdx/BdxMessages.h>
      12              : #include <system/SystemClock.h>
      13              : #include <system/SystemPacketBuffer.h>
      14              : #include <transport/raw/MessageHeader.h>
      15              : 
      16              : #include <type_traits>
      17              : 
      18              : namespace chip {
      19              : namespace bdx {
      20              : 
      21              : enum class TransferRole : uint8_t
      22              : {
      23              :     kReceiver = 0,
      24              :     kSender   = 1,
      25              : };
      26              : 
      27              : class DLL_EXPORT TransferSession
      28              : {
      29              : public:
      30              :     enum class OutputEventType : uint16_t
      31              :     {
      32              :         kNone = 0,
      33              :         kMsgToSend,
      34              :         kInitReceived,
      35              :         kAcceptReceived,
      36              :         kBlockReceived,
      37              :         kQueryReceived,
      38              :         kQueryWithSkipReceived,
      39              :         kAckReceived,
      40              :         kAckEOFReceived,
      41              :         kStatusReceived,
      42              :         kInternalError,
      43              :         kTransferTimeout
      44              :     };
      45              : 
      46              :     struct TransferInitData
      47              :     {
      48              :         TransferControlFlags TransferCtlFlags;
      49              : 
      50              :         uint16_t MaxBlockSize = 0;
      51              :         uint64_t StartOffset  = 0;
      52              :         uint64_t Length       = 0;
      53              : 
      54              :         const uint8_t * FileDesignator = nullptr;
      55              :         uint16_t FileDesLength         = 0;
      56              : 
      57              :         // Additional metadata (optional, TLV format)
      58              :         const uint8_t * Metadata = nullptr;
      59              :         size_t MetadataLength    = 0;
      60              :     };
      61              : 
      62              :     struct TransferAcceptData
      63              :     {
      64              :         TransferControlFlags ControlMode;
      65              : 
      66              :         uint16_t MaxBlockSize = 0;
      67              :         uint64_t StartOffset  = 0; ///< Not used for SendAccept message
      68              :         uint64_t Length       = 0; ///< Not used for SendAccept message
      69              : 
      70              :         // Additional metadata (optional, TLV format)
      71              :         const uint8_t * Metadata = nullptr;
      72              :         size_t MetadataLength    = 0;
      73              :     };
      74              : 
      75              :     struct StatusReportData
      76              :     {
      77              :         StatusCode statusCode;
      78              :     };
      79              : 
      80              :     struct BlockData
      81              :     {
      82              :         const uint8_t * Data  = nullptr;
      83              :         size_t Length         = 0;
      84              :         bool IsEof            = false;
      85              :         uint32_t BlockCounter = 0;
      86              :     };
      87              : 
      88              :     struct MessageTypeData
      89              :     {
      90              :         Protocols::Id ProtocolId; // Should only ever be SecureChannel or BDX
      91              :         uint8_t MessageType;
      92              : 
      93           11 :         MessageTypeData() : ProtocolId(Protocols::NotSpecified), MessageType(0) {}
      94              : 
      95            0 :         bool HasProtocol(Protocols::Id protocol) const { return ProtocolId == protocol; }
      96            0 :         bool HasMessageType(uint8_t type) const { return MessageType == type; }
      97              :         template <typename TMessageType, typename = std::enable_if_t<std::is_enum<TMessageType>::value>>
      98            0 :         bool HasMessageType(TMessageType type) const
      99              :         {
     100            0 :             return HasProtocol(Protocols::MessageTypeTraits<TMessageType>::ProtocolId()) && HasMessageType(to_underlying(type));
     101              :         }
     102              :     };
     103              : 
     104              :     struct TransferSkipData
     105              :     {
     106              :         uint64_t BytesToSkip = 0;
     107              :     };
     108              : 
     109              :     /**
     110              :      * @brief
     111              :      *   All output data processed by the TransferSession object will be passed to the caller using this struct via PollOutput().
     112              :      *
     113              :      *   NOTE: Some sub-structs may contain pointers to data in a PacketBuffer (see Blockdata). In this case, the MsgData field MUST
     114              :      *   be populated with a PacketBufferHandle that encapsulates the respective PacketBuffer, in order to ensure valid memory
     115              :      *   access.
     116              :      *
     117              :      *   NOTE: MsgData can contain messages that have been received or messages that should be sent by the caller. The underlying
     118              :      *   buffer will always start at the data, never at the payload header. Outgoing messages do not have a header prepended.
     119              :      */
     120              :     struct OutputEvent
     121              :     {
     122              :         OutputEventType EventType;
     123              :         System::PacketBufferHandle MsgData;
     124              :         union
     125              :         {
     126              :             TransferInitData transferInitData;
     127              :             TransferAcceptData transferAcceptData;
     128              :             BlockData blockdata;
     129              :             StatusReportData statusData;
     130              :             MessageTypeData msgTypeData;
     131              :             TransferSkipData bytesToSkip;
     132              :         };
     133              : 
     134            0 :         OutputEvent() : EventType(OutputEventType::kNone) { statusData = { StatusCode::kUnknown }; }
     135          387 :         OutputEvent(OutputEventType type) : EventType(type) { statusData = { StatusCode::kUnknown }; }
     136              : 
     137              :         const char * ToString(OutputEventType outputEventType);
     138              : 
     139              :         static const char * TypeToString(OutputEventType outputEventType);
     140              : 
     141              :         static OutputEvent TransferInitEvent(TransferInitData data, System::PacketBufferHandle msg);
     142              :         static OutputEvent TransferAcceptEvent(TransferAcceptData data);
     143              :         static OutputEvent TransferAcceptEvent(TransferAcceptData data, System::PacketBufferHandle msg);
     144              :         static OutputEvent BlockDataEvent(BlockData data, System::PacketBufferHandle msg);
     145              :         static OutputEvent StatusReportEvent(OutputEventType type, StatusReportData data);
     146              :         static OutputEvent MsgToSendEvent(MessageTypeData typeData, System::PacketBufferHandle msg);
     147              :         static OutputEvent QueryWithSkipEvent(TransferSkipData bytesToSkip);
     148              :     };
     149              : 
     150              :     /**
     151              :      * @brief
     152              :      *   Indicates the presence of pending output and includes any data for the caller to take action on.
     153              :      *
     154              :      *   This method should be called frequently in order to be notified about any messages received. It should also be called after
     155              :      *   most other methods in order to notify the user of any message that needs to be sent, or errors that occurred internally.
     156              :      *
     157              :      *   It is possible that consecutive calls to this method may emit different outputs depending on the state of the
     158              :      *   TransferSession object.
     159              :      *
     160              :      *   Note that if the type outputted is kMsgToSend, the caller is expected to send the message immediately, and the session
     161              :      *   timeout timer will begin at curTime.
     162              :      *
     163              :      *   See OutputEventType for all possible output event types.
     164              :      *
     165              :      * @param event     Reference to an OutputEvent struct that will be filled out with any pending output data
     166              :      * @param curTime   Current time
     167              :      */
     168              :     void PollOutput(OutputEvent & event, System::Clock::Timestamp curTime);
     169              : 
     170              :     /**
     171              :      * @brief
     172              :      *   Gets the pending output event from the transfer session in the event param passed in by the caller.
     173              :      *   The output event may contain some data for the caller to act upon. If there is no pending output event,
     174              :      *   the caller will get an event of type OutputEventType::kNone.
     175              :      *
     176              :      *   It is possible that consecutive calls to this method may emit different outputs depending on the state of the
     177              :      *   TransferSession object.  The caller is generally expected to keep calling this method until it gets an event of type
     178              :      * OutputEventType::kNone.
     179              :      *
     180              :      *   If the output event type is kMsgToSend, the caller is expected to send the message immediately on the
     181              :      *   relevant exchange.  In this case the BDX session timeout timer will start when GetNextAction is called.
     182              :      *
     183              :      *   See OutputEventType for all possible output event types.
     184              :      *
     185              :      * @param event     Reference to an OutputEvent struct that will be filled out with any pending output event data
     186              :      */
     187              :     void GetNextAction(OutputEvent & event);
     188              : 
     189              :     /**
     190              :      * @brief
     191              :      *   Initializes the TransferSession object and prepares a TransferInit message (emitted via PollOutput()).
     192              :      *
     193              :      *   A TransferSession object must be initialized with either StartTransfer() or WaitForTransfer().
     194              :      *
     195              :      * @param role      Inidcates whether this object will be sending or receiving data
     196              :      * @param initData  Data for initializing this object and for populating a TransferInit message
     197              :      *                  The role parameter will determine whether to populate a ReceiveInit or SendInit
     198              :      * @param timeout   The amount of time to wait for a response before considering the transfer failed
     199              :      *
     200              :      * @return CHIP_ERROR Result of initialization and preparation of a TransferInit message. May also indicate if the
     201              :      *                    TransferSession object is unable to handle this request.
     202              :      */
     203              :     CHIP_ERROR StartTransfer(TransferRole role, const TransferInitData & initData, System::Clock::Timeout timeout);
     204              : 
     205              :     /**
     206              :      * @brief
     207              :      *   Initialize the TransferSession object and prepare to receive a TransferInit message at some point.
     208              :      *
     209              :      *   A TransferSession object must be initialized with either StartTransfer() or WaitForTransfer().
     210              :      *
     211              :      * @param role            Inidcates whether this object will be sending or receiving data
     212              :      * @param xferControlOpts Indicates all supported control modes. Used to respond to a TransferInit message
     213              :      * @param maxBlockSize    The max Block size that this object supports.
     214              :      * @param timeout         The amount of time to wait for a response before considering the transfer failed
     215              :      *
     216              :      * @return CHIP_ERROR Result of initialization. May also indicate if the TransferSession object is unable to handle this
     217              :      *                    request.
     218              :      */
     219              :     CHIP_ERROR WaitForTransfer(TransferRole role, BitFlags<TransferControlFlags> xferControlOpts, uint16_t maxBlockSize,
     220              :                                System::Clock::Timeout timeout);
     221              : 
     222              :     /**
     223              :      * @brief
     224              :      *   Indicate that all transfer parameters are acceptable and prepare a SendAccept or ReceiveAccept message (depending on role).
     225              :      *
     226              :      * @param acceptData Data used to populate an Accept message (some fields may differ from the original Init message)
     227              :      *
     228              :      * @return CHIP_ERROR Result of preparation of an Accept message. May also indicate if the TransferSession object is unable to
     229              :      *                    handle this request.
     230              :      */
     231              :     CHIP_ERROR AcceptTransfer(const TransferAcceptData & acceptData);
     232              : 
     233              :     /**
     234              :      * @brief
     235              :      *   Reject a TransferInit message. Use Reset() to prepare this object for another transfer.
     236              :      *
     237              :      * @param reason A StatusCode indicating the reason for rejecting the transfer
     238              :      *
     239              :      * @return CHIP_ERROR The result of the preparation of a StatusReport message. May also indicate if the TransferSession object
     240              :      *                    is unable to handle this request.
     241              :      */
     242              :     CHIP_ERROR RejectTransfer(StatusCode reason);
     243              : 
     244              :     /**
     245              :      * @brief
     246              :      *   Prepare a BlockQuery message. The Block counter will be populated automatically.
     247              :      *
     248              :      * @return CHIP_ERROR The result of the preparation of a BlockQuery message. May also indicate if the TransferSession object
     249              :      *                    is unable to handle this request.
     250              :      */
     251              :     CHIP_ERROR PrepareBlockQuery();
     252              : 
     253              :     /**
     254              :      * @brief
     255              :      *   Prepare a BlockQueryWithSkip message. The Block counter will be populated automatically.
     256              :      *
     257              :      * @param bytesToSkip Number of bytes to seek skip
     258              :      *
     259              :      * @return CHIP_ERROR The result of the preparation of a BlockQueryWithSkip message. May also indicate if the TransferSession
     260              :      * object is unable to handle this request.
     261              :      */
     262              :     CHIP_ERROR PrepareBlockQueryWithSkip(const uint64_t & bytesToSkip);
     263              : 
     264              :     /**
     265              :      * @brief
     266              :      *   Prepare a Block message. The Block counter will be populated automatically.
     267              :      *
     268              :      * @param inData Contains data for filling out the Block message
     269              :      *
     270              :      * @return CHIP_ERROR The result of the preparation of a Block message. May also indicate if the TransferSession object
     271              :      *                    is unable to handle this request.
     272              :      */
     273              :     CHIP_ERROR PrepareBlock(const BlockData & inData);
     274              : 
     275              :     /**
     276              :      * @brief
     277              :      *   Prepare a BlockAck message. The Block counter will be populated automatically.
     278              :      *
     279              :      * @return CHIP_ERROR The result of the preparation of a BlockAck message. May also indicate if the TransferSession object
     280              :      *                    is unable to handle this request.
     281              :      */
     282              :     CHIP_ERROR PrepareBlockAck();
     283              : 
     284              :     /**
     285              :      * @brief
     286              :      *   Prematurely end a transfer with a StatusReport. Must still call Reset() to prepare the TransferSession for another
     287              :      *   transfer.
     288              :      *
     289              :      * @param reason The StatusCode reason for ending the transfer.
     290              :      *
     291              :      * @return CHIP_ERROR May return an error if there is no transfer in progress.
     292              :      */
     293              :     CHIP_ERROR AbortTransfer(StatusCode reason);
     294              : 
     295              :     /**
     296              :      * @brief
     297              :      *   Reset all TransferSession parameters. The TransferSession object must then be re-initialized with StartTransfer() or
     298              :      *   WaitForTransfer().
     299              :      */
     300              :     void Reset();
     301              : 
     302              :     /**
     303              :      * @brief
     304              :      *   Process a message intended for this TransferSession object.
     305              :      *
     306              :      * @param payloadHeader A PayloadHeader containing the Protocol type and Message Type
     307              :      * @param msg           A PacketBufferHandle pointing to the message buffer to process. May be BDX or StatusReport protocol.
     308              :      *                      Buffer is expected to start at data (not header).
     309              :      * @param curTime       Current time
     310              :      *
     311              :      * @return CHIP_ERROR Indicates any problems in decoding the message, or if the message is not of the BDX or StatusReport
     312              :      *                    protocols.
     313              :      */
     314              :     CHIP_ERROR HandleMessageReceived(const PayloadHeader & payloadHeader, System::PacketBufferHandle msg,
     315              :                                      System::Clock::Timestamp curTime);
     316              : 
     317              :     TransferControlFlags GetControlMode() const { return mControlMode; }
     318            0 :     uint64_t GetStartOffset() const { return mStartOffset; }
     319            0 :     uint64_t GetTransferLength() const { return mTransferLength; }
     320            0 :     uint16_t GetTransferBlockSize() const { return mTransferMaxBlockSize; }
     321              :     uint32_t GetNextBlockNum() const { return mNextBlockNum; }
     322              :     uint32_t GetNextQueryNum() const { return mNextQueryNum; }
     323              :     size_t GetNumBytesProcessed() const { return mNumBytesProcessed; }
     324            0 :     const uint8_t * GetFileDesignator(uint16_t & fileDesignatorLen) const
     325              :     {
     326            0 :         fileDesignatorLen = mTransferRequestData.FileDesLength;
     327            0 :         return mTransferRequestData.FileDesignator;
     328              :     }
     329              : 
     330              :     TransferSession();
     331              : 
     332              : private:
     333              :     enum class TransferState : uint8_t
     334              :     {
     335              :         kUnitialized,
     336              :         kAwaitingInitMsg,
     337              :         kAwaitingAccept,
     338              :         kNegotiateTransferParams,
     339              :         kTransferInProgress,
     340              :         kAwaitingEOFAck,
     341              :         kReceivedEOF,
     342              :         kTransferDone,
     343              :         kErrorState,
     344              :     };
     345              : 
     346              :     // Incoming message handlers
     347              :     CHIP_ERROR HandleBdxMessage(const PayloadHeader & header, System::PacketBufferHandle msg);
     348              :     CHIP_ERROR HandleStatusReportMessage(const PayloadHeader & header, System::PacketBufferHandle msg);
     349              :     void HandleTransferInit(MessageType msgType, System::PacketBufferHandle msgData);
     350              :     void HandleReceiveAccept(System::PacketBufferHandle msgData);
     351              :     void HandleSendAccept(System::PacketBufferHandle msgData);
     352              :     void HandleBlockQuery(System::PacketBufferHandle msgData);
     353              :     void HandleBlockQueryWithSkip(System::PacketBufferHandle msgData);
     354              :     void HandleBlock(System::PacketBufferHandle msgData);
     355              :     void HandleBlockEOF(System::PacketBufferHandle msgData);
     356              :     void HandleBlockAck(System::PacketBufferHandle msgData);
     357              :     void HandleBlockAckEOF(System::PacketBufferHandle msgData);
     358              : 
     359              :     /**
     360              :      * @brief
     361              :      *   Used when handling a TransferInit message. Determines if there are any compatible Transfer control modes between the two
     362              :      *   transfer peers.
     363              :      */
     364              :     void ResolveTransferControlOptions(const BitFlags<TransferControlFlags> & proposed);
     365              : 
     366              :     /**
     367              :      * @brief
     368              :      *   Used when handling an Accept message. Verifies that the chosen control mode is compatible with the orignal supported modes.
     369              :      */
     370              :     CHIP_ERROR VerifyProposedMode(const BitFlags<TransferControlFlags> & proposed);
     371              : 
     372              :     void PrepareStatusReport(StatusCode code);
     373              :     bool IsTransferLengthDefinite() const;
     374              : 
     375              :     OutputEventType mPendingOutput = OutputEventType::kNone;
     376              :     TransferState mState           = TransferState::kUnitialized;
     377              :     TransferRole mRole;
     378              : 
     379              :     // Indicate supported options pre- transfer accept
     380              :     BitFlags<TransferControlFlags> mSuppportedXferOpts;
     381              :     uint16_t mMaxSupportedBlockSize = 0;
     382              : 
     383              :     // Used to govern transfer once it has been accepted
     384              :     TransferControlFlags mControlMode;
     385              :     uint8_t mTransferVersion       = 0;
     386              :     uint64_t mStartOffset          = 0; ///< 0 represents no offset
     387              :     uint64_t mTransferLength       = 0; ///< 0 represents indefinite length
     388              :     uint16_t mTransferMaxBlockSize = 0;
     389              : 
     390              :     // Used to store event data before it is emitted via PollOutput()
     391              :     System::PacketBufferHandle mPendingMsgHandle;
     392              :     StatusReportData mStatusReportData;
     393              :     TransferInitData mTransferRequestData;
     394              :     TransferAcceptData mTransferAcceptData;
     395              :     BlockData mBlockEventData;
     396              :     MessageTypeData mMsgTypeData;
     397              :     TransferSkipData mBytesToSkip;
     398              : 
     399              :     size_t mNumBytesProcessed = 0;
     400              : 
     401              :     uint32_t mLastBlockNum = 0;
     402              :     uint32_t mNextBlockNum = 0;
     403              :     uint32_t mLastQueryNum = 0;
     404              :     uint32_t mNextQueryNum = 0;
     405              : 
     406              :     System::Clock::Timeout mTimeout            = System::Clock::kZero;
     407              :     System::Clock::Timestamp mTimeoutStartTime = System::Clock::kZero;
     408              :     bool mShouldInitTimeoutStart               = true;
     409              :     bool mAwaitingResponse                     = false;
     410              : };
     411              : 
     412              : } // namespace bdx
     413              : } // namespace chip
        

Generated by: LCOV version 2.0-1