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

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2024 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              : #include "BdxTransferDiagnosticLog.h"
      20              : 
      21              : #include <protocols/bdx/BdxTransferDiagnosticLogPool.h>
      22              : 
      23              : namespace chip {
      24              : namespace bdx {
      25              : 
      26              : namespace {
      27              : // Max block size for the BDX transfer.
      28              : constexpr uint32_t kMaxBdxBlockSize = 1024;
      29              : 
      30              : // How often we poll our transfer session.  Sadly, we get allocated on
      31              : // unsolicited message, which makes it hard for our clients to configure this.
      32              : // But the default poll interval is 500ms, which makes log downloads extremely
      33              : // slow.
      34              : constexpr System::Clock::Timeout kBdxPollInterval = System::Clock::Milliseconds32(50);
      35              : 
      36              : // Timeout for the BDX transfer session..
      37              : constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60);
      38              : constexpr TransferRole kBdxRole              = TransferRole::kReceiver;
      39              : } // namespace
      40              : 
      41            0 : void BdxTransferDiagnosticLog::HandleTransferSessionOutput(TransferSession::OutputEvent & event)
      42              : {
      43            0 :     assertChipStackLockedByCurrentThread();
      44              : 
      45            0 :     ChipLogDetail(BDX, "Got an event %s", event.ToString(event.EventType));
      46              : 
      47            0 :     switch (event.EventType)
      48              :     {
      49            0 :     case TransferSession::OutputEventType::kInitReceived:
      50            0 :         AbortTransferOnFailure(OnTransferSessionBegin(event));
      51            0 :         break;
      52            0 :     case TransferSession::OutputEventType::kStatusReceived:
      53            0 :         ChipLogError(BDX, "Got StatusReport %x", static_cast<uint16_t>(event.statusData.statusCode));
      54            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
      55            0 :         break;
      56            0 :     case TransferSession::OutputEventType::kInternalError:
      57            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
      58            0 :         break;
      59            0 :     case TransferSession::OutputEventType::kTransferTimeout:
      60            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_TIMEOUT));
      61            0 :         break;
      62            0 :     case TransferSession::OutputEventType::kBlockReceived:
      63            0 :         AbortTransferOnFailure(OnBlockReceived(event));
      64            0 :         break;
      65            0 :     case TransferSession::OutputEventType::kMsgToSend:
      66            0 :         LogErrorOnFailure(OnMessageToSend(event));
      67              : 
      68            0 :         if (event.msgTypeData.HasMessageType(MessageType::BlockAckEOF))
      69              :         {
      70            0 :             LogErrorOnFailure(OnTransferSessionEnd(CHIP_NO_ERROR));
      71              :         }
      72            0 :         break;
      73            0 :     case TransferSession::OutputEventType::kAckEOFReceived:
      74              :     case TransferSession::OutputEventType::kNone:
      75              :     case TransferSession::OutputEventType::kQueryWithSkipReceived:
      76              :     case TransferSession::OutputEventType::kQueryReceived:
      77              :     case TransferSession::OutputEventType::kAckReceived:
      78              :     case TransferSession::OutputEventType::kAcceptReceived:
      79              :         // Nothing to do.
      80            0 :         break;
      81            0 :     default:
      82              :         // Should never happen.
      83            0 :         chipDie();
      84              :         break;
      85              :     }
      86            0 : }
      87              : 
      88            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
      89              :                                                        System::PacketBufferHandle && payload)
      90              : {
      91            0 :     assertChipStackLockedByCurrentThread();
      92              : 
      93            0 :     VerifyOrReturnError(ec != nullptr, CHIP_ERROR_INCORRECT_STATE);
      94              : 
      95              :     // If we receive a SendInit message, then we prepare for transfer
      96            0 :     if (payloadHeader.HasMessageType(MessageType::SendInit))
      97              :     {
      98            0 :         FabricIndex fabricIndex = ec->GetSessionHandle()->GetFabricIndex();
      99            0 :         NodeId peerNodeId       = ec->GetSessionHandle()->GetPeer().GetNodeId();
     100            0 :         VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
     101            0 :         VerifyOrReturnError(peerNodeId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
     102              : 
     103            0 :         mTransferProxy.SetFabricIndex(fabricIndex);
     104            0 :         mTransferProxy.SetPeerNodeId(peerNodeId);
     105            0 :         auto flags(TransferControlFlags::kSenderDrive);
     106            0 :         ReturnLogErrorOnFailure(
     107              :             Responder::PrepareForTransfer(mSystemLayer, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollInterval));
     108              :     }
     109              : 
     110            0 :     return TransferFacilitator::OnMessageReceived(ec, payloadHeader, std::move(payload));
     111              : }
     112              : 
     113            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnMessageToSend(TransferSession::OutputEvent & event)
     114              : {
     115            0 :     assertChipStackLockedByCurrentThread();
     116              : 
     117            0 :     VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE);
     118              : 
     119            0 :     auto & msgTypeData  = event.msgTypeData;
     120            0 :     bool isStatusReport = msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport);
     121              : 
     122              :     // All messages sent from the Sender expect a response, except for a StatusReport which would indicate an error and
     123              :     // the end of the transfer.
     124            0 :     Messaging::SendFlags sendFlags;
     125            0 :     VerifyOrDo(isStatusReport, sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse));
     126              : 
     127              :     // If there's an error sending the message, close the exchange by calling Reset.
     128            0 :     auto err = mExchangeCtx->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(event.MsgData), sendFlags);
     129            0 :     VerifyOrDo(CHIP_NO_ERROR == err, OnTransferSessionEnd(err));
     130              : 
     131            0 :     return err;
     132              : }
     133              : 
     134            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnTransferSessionBegin(TransferSession::OutputEvent & event)
     135              : {
     136            0 :     assertChipStackLockedByCurrentThread();
     137            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     138              : 
     139            0 :     ReturnErrorOnFailure(mTransferProxy.Init(&mTransfer));
     140            0 :     return mDelegate->OnTransferBegin(&mTransferProxy);
     141              : }
     142              : 
     143            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnTransferSessionEnd(CHIP_ERROR error)
     144              : {
     145            0 :     assertChipStackLockedByCurrentThread();
     146            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     147              : 
     148            0 :     LogErrorOnFailure(mDelegate->OnTransferEnd(&mTransferProxy, error));
     149            0 :     Reset();
     150            0 :     return CHIP_NO_ERROR;
     151              : }
     152              : 
     153            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnBlockReceived(TransferSession::OutputEvent & event)
     154              : {
     155            0 :     assertChipStackLockedByCurrentThread();
     156            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     157              : 
     158            0 :     ByteSpan blockData(event.blockdata.Data, event.blockdata.Length);
     159            0 :     return mDelegate->OnTransferData(&mTransferProxy, blockData);
     160              : }
     161              : 
     162            0 : void BdxTransferDiagnosticLog::AbortTransferOnFailure(CHIP_ERROR error)
     163              : {
     164            0 :     VerifyOrReturn(CHIP_NO_ERROR != error);
     165            0 :     LogErrorOnFailure(error);
     166            0 :     LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(error)));
     167              : }
     168              : 
     169            0 : void BdxTransferDiagnosticLog::Reset()
     170              : {
     171            0 :     assertChipStackLockedByCurrentThread();
     172              : 
     173            0 :     Responder::ResetTransfer();
     174              : 
     175            0 :     if (mExchangeCtx)
     176              :     {
     177            0 :         mIsExchangeClosing = true;
     178            0 :         mExchangeCtx->Close();
     179            0 :         mIsExchangeClosing = false;
     180            0 :         mExchangeCtx       = nullptr;
     181              :     }
     182              : 
     183            0 :     mTransferProxy.Reset();
     184            0 : }
     185              : 
     186            0 : void BdxTransferDiagnosticLog::OnExchangeClosing(Messaging::ExchangeContext * ec)
     187              : {
     188              :     // The exchange can be closing while TransferFacilitator is still accessing us, so
     189              :     // the BdxTransferDiagnosticLog can not be released "right now".
     190            0 :     mSystemLayer->ScheduleWork(
     191            0 :         [](auto * systemLayer, auto * appState) -> void {
     192            0 :             auto * _this = static_cast<BdxTransferDiagnosticLog *>(appState);
     193            0 :             _this->mPoolDelegate->Release(_this);
     194            0 :         },
     195              :         this);
     196              : 
     197              :     // This block checks and handles the scenario where the exchange is closed externally (e.g., receiving a StatusReport).
     198              :     // Continuing to use it could lead to a use-after-free error and such an error might occur when the poll timer triggers and
     199              :     // OnTransferSessionEnd is called.
     200              :     // We know it's not just us normally closing the exchange if mIsExchangeClosing is false.
     201            0 :     VerifyOrReturn(!mIsExchangeClosing);
     202            0 :     mExchangeCtx = nullptr;
     203            0 :     LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
     204              : }
     205              : 
     206            0 : bool BdxTransferDiagnosticLog::IsForFabric(FabricIndex fabricIndex) const
     207              : {
     208            0 :     if (mExchangeCtx == nullptr || !mExchangeCtx->HasSessionHandle())
     209              :     {
     210            0 :         return false;
     211              :     }
     212              : 
     213            0 :     auto session = mExchangeCtx->GetSessionHandle();
     214            0 :     return session->GetFabricIndex() == fabricIndex;
     215            0 : }
     216              : 
     217            0 : void BdxTransferDiagnosticLog::AbortTransfer()
     218              : {
     219              :     // No need to mTransfer.AbortTransfer() here, since that just tries to async
     220              :     // send a StatusReport to the other side, but we are going away here.
     221            0 :     Reset();
     222            0 : }
     223              : 
     224              : } // namespace bdx
     225              : } // namespace chip
        

Generated by: LCOV version 2.0-1