Matter SDK Coverage Report
Current view: top level - protocols/bdx - AsyncTransferFacilitator.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 0.0 % 70 0
Test Date: 2025-01-17 19:00:11 Functions: 0.0 % 9 0

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2024 Project CHIP Authors
       3              :  *
       4              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       5              :  *    you may not use this file except in compliance with the License.
       6              :  *    You may obtain a copy of the License at
       7              :  *
       8              :  *        http://www.apache.org/licenses/LICENSE-2.0
       9              :  *
      10              :  *    Unless required by applicable law or agreed to in writing, software
      11              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      12              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              :  *    See the License for the specific language governing permissions and
      14              :  *    limitations under the License.
      15              :  */
      16              : 
      17              : #include "AsyncTransferFacilitator.h"
      18              : 
      19              : #include <protocols/bdx/StatusCode.h>
      20              : #include <system/SystemClock.h>
      21              : 
      22              : namespace chip {
      23              : namespace bdx {
      24              : 
      25            0 : AsyncTransferFacilitator::~AsyncTransferFacilitator() {}
      26              : 
      27            0 : CHIP_ERROR AsyncTransferFacilitator::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx,
      28              :                                           System::Clock::Timeout timeout)
      29              : {
      30            0 :     VerifyOrReturnError(layer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      31            0 :     VerifyOrReturnError(exchangeCtx != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      32            0 :     VerifyOrReturnError(!mExchange, CHIP_ERROR_INCORRECT_STATE);
      33              : 
      34            0 :     mSystemLayer = layer;
      35            0 :     mExchange.Grab(exchangeCtx);
      36            0 :     mTimeout                          = timeout;
      37            0 :     mProcessingOutputEvents           = false;
      38            0 :     mDestroySelfAfterProcessingEvents = false;
      39            0 :     return CHIP_NO_ERROR;
      40              : }
      41              : 
      42              : /**
      43              :  * Get events one by one from the TransferSession and process them,
      44              :  * until there are no more events to process.
      45              :  */
      46            0 : void AsyncTransferFacilitator::ProcessOutputEvents()
      47              : {
      48            0 :     if (mProcessingOutputEvents)
      49              :     {
      50            0 :         ChipLogDetail(BDX,
      51              :                       "ProcessOutputEvents: we are already in the middle of processing events, so nothing to do here; when we "
      52              :                       "unwind to the processing loop the events will get processed.");
      53            0 :         return;
      54              :     }
      55              : 
      56            0 :     mProcessingOutputEvents = true;
      57              : 
      58              :     // Get the next output event and handle it based on the type of event.
      59              :     // If its of type kMsgToSend send it over the exchange, otherwise call the HandleTransferSessionOutput
      60              :     // virtual method that must be implemeted by the subclass of this class to handle the BDX message.
      61            0 :     TransferSession::OutputEvent outEvent;
      62              : 
      63            0 :     mTransfer.GetNextAction(outEvent);
      64            0 :     while (outEvent.EventType != TransferSession::OutputEventType::kNone)
      65              :     {
      66            0 :         if (outEvent.EventType == TransferSession::OutputEventType::kMsgToSend)
      67              :         {
      68            0 :             CHIP_ERROR err = SendMessage(outEvent.msgTypeData, outEvent.MsgData);
      69              : 
      70              :             // If we failed to send the message across the exchange, just abort the transfer.
      71              :             // We have no way to notify our peer we are doing that (we can't send them a
      72              :             // message!) but eventually they will time out.
      73            0 :             if (err != CHIP_NO_ERROR)
      74              :             {
      75            0 :                 DestroySelf();
      76            0 :                 return;
      77              :             }
      78              : 
      79              :             // If we send out a status report across the exchange, that means there was an error.
      80              :             // We've sent our report about that error and can now abort the transfer.  Our peer
      81              :             // will respond to the status report by tearing down their side.
      82            0 :             if (outEvent.msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport))
      83              :             {
      84            0 :                 mDestroySelfAfterProcessingEvents = true;
      85            0 :                 break;
      86              :             }
      87              :         }
      88              :         else
      89              :         {
      90            0 :             HandleTransferSessionOutput(outEvent);
      91              :         }
      92            0 :         mTransfer.GetNextAction(outEvent);
      93              :     }
      94              : 
      95            0 :     mProcessingOutputEvents = false;
      96              : 
      97              :     // If mDestroySelfAfterProcessingEvents is set (by our code above or by NotifyEventHandled), we need
      98              :     // to call DestroySelf() after processing all pending output events.
      99            0 :     if (mDestroySelfAfterProcessingEvents)
     100              :     {
     101            0 :         DestroySelf();
     102              :     }
     103            0 : }
     104              : 
     105            0 : CHIP_ERROR AsyncTransferFacilitator::SendMessage(const TransferSession::MessageTypeData msgTypeData,
     106              :                                                  System::PacketBufferHandle & msgBuf)
     107              : {
     108            0 :     VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE);
     109              : 
     110            0 :     Messaging::SendFlags sendFlags;
     111              : 
     112              :     // All messages that are sent expect a response, except for a StatusReport which would indicate an error and
     113              :     // the end of the transfer.
     114            0 :     if (!msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport))
     115              :     {
     116            0 :         sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse);
     117              :     }
     118              : 
     119            0 :     Messaging::ExchangeContext * ec = mExchange.Get();
     120              : 
     121              :     // Set the response timeout on the exchange before sending the message.
     122            0 :     ec->SetResponseTimeout(mTimeout);
     123            0 :     return ec->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(msgBuf), sendFlags);
     124              : }
     125              : 
     126            0 : CHIP_ERROR AsyncTransferFacilitator::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
     127              :                                                        System::PacketBufferHandle && payload)
     128              : {
     129            0 :     VerifyOrReturnError(mExchange, CHIP_ERROR_INCORRECT_STATE);
     130              : 
     131            0 :     VerifyOrReturnError(ec == mExchange.Get(), CHIP_ERROR_INCORRECT_STATE);
     132              : 
     133              :     CHIP_ERROR err =
     134            0 :         mTransfer.HandleMessageReceived(payloadHeader, std::move(payload), System::SystemClock().GetMonotonicTimestamp());
     135            0 :     if (err != CHIP_NO_ERROR)
     136              :     {
     137            0 :         ChipLogError(BDX, "OnMessageReceived: Failed to handle message: %" CHIP_ERROR_FORMAT, err.Format());
     138              : 
     139              :         // This should notify the transfer object to abort transfer so it can send a status report across the exchange
     140              :         // when we call ProcessOutputEvents below.
     141            0 :         mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(err));
     142              :     }
     143            0 :     else if (!payloadHeader.HasMessageType(MessageType::BlockAckEOF))
     144              :     {
     145              :         // Almost every BDX message expect BlockAckEOF will follow up with a response on the exchange.
     146            0 :         ec->WillSendMessage();
     147              :     }
     148              : 
     149            0 :     ProcessOutputEvents();
     150            0 :     return err;
     151              : }
     152              : 
     153            0 : void AsyncTransferFacilitator::OnResponseTimeout(Messaging::ExchangeContext * ec)
     154              : {
     155            0 :     ChipLogDetail(BDX, "OnResponseTimeout, ec: " ChipLogFormatExchange, ChipLogValueExchange(ec));
     156            0 :     DestroySelf();
     157            0 : }
     158              : 
     159            0 : CHIP_ERROR AsyncResponder::Init(System::Layer * layer, Messaging::ExchangeContext * exchangeCtx, TransferRole role,
     160              :                                 BitFlags<TransferControlFlags> xferControlOpts, uint16_t maxBlockSize,
     161              :                                 System::Clock::Timeout timeout)
     162              : {
     163            0 :     ReturnErrorOnFailure(AsyncTransferFacilitator::Init(layer, exchangeCtx, timeout));
     164            0 :     ReturnErrorOnFailure(mTransfer.WaitForTransfer(role, xferControlOpts, maxBlockSize, timeout));
     165            0 :     return CHIP_NO_ERROR;
     166              : }
     167              : 
     168            0 : void AsyncResponder::NotifyEventHandled(const TransferSession::OutputEventType eventType, CHIP_ERROR status)
     169              : {
     170            0 :     ChipLogDetail(BDX, "NotifyEventHandled : Event %s Error %" CHIP_ERROR_FORMAT,
     171              :                   TransferSession::OutputEvent::TypeToString(eventType), status.Format());
     172              : 
     173              :     // If this is the end of the transfer (whether a clean end, or some sort of error condition), ensure that
     174              :     // we destroy ourselves after processing any output events that might have been generated by
     175              :     // the transfer session to handle end-of-transfer (e.g. in some error conditions it might want to send
     176              :     // out a status report).
     177            0 :     if (eventType == TransferSession::OutputEventType::kAckEOFReceived ||
     178            0 :         eventType == TransferSession::OutputEventType::kInternalError ||
     179            0 :         eventType == TransferSession::OutputEventType::kTransferTimeout ||
     180              :         eventType == TransferSession::OutputEventType::kStatusReceived)
     181              :     {
     182            0 :         mDestroySelfAfterProcessingEvents = true;
     183              :     }
     184              : 
     185              :     // If there was an error handling the output event, this should notify the transfer object to abort transfer so it can send a
     186              :     // status report across the exchange when we call ProcessOutputEvents below.
     187            0 :     if (status != CHIP_NO_ERROR)
     188              :     {
     189            0 :         mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(status));
     190              :     }
     191              : 
     192            0 :     ProcessOutputEvents();
     193            0 : }
     194              : 
     195              : } // namespace bdx
     196              : } // namespace chip
        

Generated by: LCOV version 2.0-1