Matter SDK Coverage Report
Current view: top level - protocols/bdx - BdxTransferDiagnosticLog.cpp (source / functions) Coverage Total Hit
Test: SHA:f84fe08d06f240e801b5d923f8a938a9938ca110 Lines: 0.0 % 102 0
Test Date: 2025-02-22 08:08:07 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 :     if (event.EventType == TransferSession::OutputEventType::kNone)
      46              :     {
      47              :         // Because we are polling for output every 50ms on our transfer session,
      48              :         // we will get a lot of kNone events coming through here: one for every
      49              :         // time we poll but the other side has not sent anything new yet.  Just
      50              :         // ignore those here, for now, and make sure not to log them, because
      51              :         // that bloats the logs pretty quickly.
      52            0 :         return;
      53              :     }
      54              : 
      55            0 :     ChipLogDetail(BDX, "Got an event %s", event.ToString(event.EventType));
      56              : 
      57            0 :     switch (event.EventType)
      58              :     {
      59            0 :     case TransferSession::OutputEventType::kInitReceived:
      60            0 :         AbortTransferOnFailure(OnTransferSessionBegin(event));
      61            0 :         break;
      62            0 :     case TransferSession::OutputEventType::kStatusReceived:
      63            0 :         ChipLogError(BDX, "Got StatusReport %x", static_cast<uint16_t>(event.statusData.statusCode));
      64            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
      65            0 :         break;
      66            0 :     case TransferSession::OutputEventType::kInternalError:
      67            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
      68            0 :         break;
      69            0 :     case TransferSession::OutputEventType::kTransferTimeout:
      70            0 :         LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_TIMEOUT));
      71            0 :         break;
      72            0 :     case TransferSession::OutputEventType::kBlockReceived:
      73            0 :         AbortTransferOnFailure(OnBlockReceived(event));
      74            0 :         break;
      75            0 :     case TransferSession::OutputEventType::kMsgToSend:
      76            0 :         LogErrorOnFailure(OnMessageToSend(event));
      77              : 
      78            0 :         if (event.msgTypeData.HasMessageType(MessageType::BlockAckEOF))
      79              :         {
      80            0 :             LogErrorOnFailure(OnTransferSessionEnd(CHIP_NO_ERROR));
      81              :         }
      82            0 :         break;
      83            0 :     case TransferSession::OutputEventType::kAckEOFReceived:
      84              :     // case TransferSession::OutputEventType::kNone: handled above.
      85              :     case TransferSession::OutputEventType::kQueryWithSkipReceived:
      86              :     case TransferSession::OutputEventType::kQueryReceived:
      87              :     case TransferSession::OutputEventType::kAckReceived:
      88              :     case TransferSession::OutputEventType::kAcceptReceived:
      89              :         // Nothing to do.
      90            0 :         break;
      91            0 :     default:
      92              :         // Should never happen.
      93            0 :         chipDie();
      94              :         break;
      95              :     }
      96              : }
      97              : 
      98            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
      99              :                                                        System::PacketBufferHandle && payload)
     100              : {
     101            0 :     assertChipStackLockedByCurrentThread();
     102              : 
     103            0 :     VerifyOrReturnError(ec != nullptr, CHIP_ERROR_INCORRECT_STATE);
     104              : 
     105              :     // If we receive a SendInit message, then we prepare for transfer
     106            0 :     if (payloadHeader.HasMessageType(MessageType::SendInit))
     107              :     {
     108            0 :         FabricIndex fabricIndex = ec->GetSessionHandle()->GetFabricIndex();
     109            0 :         NodeId peerNodeId       = ec->GetSessionHandle()->GetPeer().GetNodeId();
     110            0 :         VerifyOrReturnError(fabricIndex != kUndefinedFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
     111            0 :         VerifyOrReturnError(peerNodeId != kUndefinedNodeId, CHIP_ERROR_INVALID_ARGUMENT);
     112              : 
     113            0 :         mTransferProxy.SetFabricIndex(fabricIndex);
     114            0 :         mTransferProxy.SetPeerNodeId(peerNodeId);
     115            0 :         auto flags(TransferControlFlags::kSenderDrive);
     116            0 :         ReturnLogErrorOnFailure(
     117              :             Responder::PrepareForTransfer(mSystemLayer, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout, kBdxPollInterval));
     118              :     }
     119              : 
     120            0 :     return TransferFacilitator::OnMessageReceived(ec, payloadHeader, std::move(payload));
     121              : }
     122              : 
     123            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnMessageToSend(TransferSession::OutputEvent & event)
     124              : {
     125            0 :     assertChipStackLockedByCurrentThread();
     126              : 
     127            0 :     VerifyOrReturnError(mExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE);
     128              : 
     129            0 :     auto & msgTypeData  = event.msgTypeData;
     130            0 :     bool isStatusReport = msgTypeData.HasMessageType(Protocols::SecureChannel::MsgType::StatusReport);
     131              : 
     132              :     // All messages sent from the Sender expect a response, except for a StatusReport which would indicate an error and
     133              :     // the end of the transfer.
     134            0 :     Messaging::SendFlags sendFlags;
     135            0 :     VerifyOrDo(isStatusReport, sendFlags.Set(Messaging::SendMessageFlags::kExpectResponse));
     136              : 
     137              :     // If there's an error sending the message, close the exchange by calling Reset.
     138            0 :     auto err = mExchangeCtx->SendMessage(msgTypeData.ProtocolId, msgTypeData.MessageType, std::move(event.MsgData), sendFlags);
     139            0 :     VerifyOrDo(CHIP_NO_ERROR == err, OnTransferSessionEnd(err));
     140              : 
     141            0 :     return err;
     142              : }
     143              : 
     144            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnTransferSessionBegin(TransferSession::OutputEvent & event)
     145              : {
     146            0 :     assertChipStackLockedByCurrentThread();
     147            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     148              : 
     149            0 :     ReturnErrorOnFailure(mTransferProxy.Init(&mTransfer));
     150            0 :     return mDelegate->OnTransferBegin(&mTransferProxy);
     151              : }
     152              : 
     153            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnTransferSessionEnd(CHIP_ERROR error)
     154              : {
     155            0 :     assertChipStackLockedByCurrentThread();
     156            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     157              : 
     158            0 :     LogErrorOnFailure(mDelegate->OnTransferEnd(&mTransferProxy, error));
     159            0 :     Reset();
     160            0 :     return CHIP_NO_ERROR;
     161              : }
     162              : 
     163            0 : CHIP_ERROR BdxTransferDiagnosticLog::OnBlockReceived(TransferSession::OutputEvent & event)
     164              : {
     165            0 :     assertChipStackLockedByCurrentThread();
     166            0 :     VerifyOrReturnError(nullptr != mDelegate, CHIP_ERROR_INCORRECT_STATE);
     167              : 
     168            0 :     ByteSpan blockData(event.blockdata.Data, event.blockdata.Length);
     169            0 :     return mDelegate->OnTransferData(&mTransferProxy, blockData);
     170              : }
     171              : 
     172            0 : void BdxTransferDiagnosticLog::AbortTransferOnFailure(CHIP_ERROR error)
     173              : {
     174            0 :     VerifyOrReturn(CHIP_NO_ERROR != error);
     175            0 :     LogErrorOnFailure(error);
     176            0 :     LogErrorOnFailure(mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(error)));
     177              : }
     178              : 
     179            0 : void BdxTransferDiagnosticLog::Reset()
     180              : {
     181            0 :     assertChipStackLockedByCurrentThread();
     182              : 
     183            0 :     Responder::ResetTransfer();
     184              : 
     185            0 :     if (mExchangeCtx)
     186              :     {
     187            0 :         mIsExchangeClosing = true;
     188            0 :         mExchangeCtx->Close();
     189            0 :         mIsExchangeClosing = false;
     190            0 :         mExchangeCtx       = nullptr;
     191              :     }
     192              : 
     193            0 :     mTransferProxy.Reset();
     194            0 : }
     195              : 
     196            0 : void BdxTransferDiagnosticLog::OnExchangeClosing(Messaging::ExchangeContext * ec)
     197              : {
     198              :     // The exchange can be closing while TransferFacilitator is still accessing us, so
     199              :     // the BdxTransferDiagnosticLog can not be released "right now".
     200            0 :     mSystemLayer->ScheduleWork(
     201            0 :         [](auto * systemLayer, auto * appState) -> void {
     202            0 :             auto * _this = static_cast<BdxTransferDiagnosticLog *>(appState);
     203            0 :             _this->mPoolDelegate->Release(_this);
     204            0 :         },
     205              :         this);
     206              : 
     207              :     // This block checks and handles the scenario where the exchange is closed externally (e.g., receiving a StatusReport).
     208              :     // Continuing to use it could lead to a use-after-free error and such an error might occur when the poll timer triggers and
     209              :     // OnTransferSessionEnd is called.
     210              :     // We know it's not just us normally closing the exchange if mIsExchangeClosing is false.
     211            0 :     VerifyOrReturn(!mIsExchangeClosing);
     212            0 :     mExchangeCtx = nullptr;
     213            0 :     LogErrorOnFailure(OnTransferSessionEnd(CHIP_ERROR_INTERNAL));
     214              : }
     215              : 
     216            0 : bool BdxTransferDiagnosticLog::IsForFabric(FabricIndex fabricIndex) const
     217              : {
     218            0 :     if (mExchangeCtx == nullptr || !mExchangeCtx->HasSessionHandle())
     219              :     {
     220            0 :         return false;
     221              :     }
     222              : 
     223            0 :     auto session = mExchangeCtx->GetSessionHandle();
     224            0 :     return session->GetFabricIndex() == fabricIndex;
     225            0 : }
     226              : 
     227            0 : void BdxTransferDiagnosticLog::AbortTransfer()
     228              : {
     229              :     // No need to mTransfer.AbortTransfer() here, since that just tries to async
     230              :     // send a StatusReport to the other side, but we are going away here.
     231            0 :     Reset();
     232            0 : }
     233              : 
     234              : } // namespace bdx
     235              : } // namespace chip
        

Generated by: LCOV version 2.0-1