diff --git a/src/protocols/bdx/BdxTransferSession.cpp b/src/protocols/bdx/BdxTransferSession.cpp index f6c54985ab5cd1..99588f0770a72e 100644 --- a/src/protocols/bdx/BdxTransferSession.cpp +++ b/src/protocols/bdx/BdxTransferSession.cpp @@ -261,6 +261,17 @@ CHIP_ERROR TransferSession::AcceptTransfer(const TransferAcceptData & acceptData return CHIP_NO_ERROR; } +CHIP_ERROR TransferSession::RejectTransfer(StatusCode reason) +{ + VerifyOrReturnError(mState == TransferState::kNegotiateTransferParams, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mPendingOutput == OutputEventType::kNone, CHIP_ERROR_INCORRECT_STATE); + + PrepareStatusReport(reason); + mState = TransferState::kTransferDone; + + return CHIP_NO_ERROR; +} + CHIP_ERROR TransferSession::PrepareBlockQuery() { const MessageType msgType = MessageType::BlockQuery; diff --git a/src/protocols/bdx/tests/TestBdxTransferSession.cpp b/src/protocols/bdx/tests/TestBdxTransferSession.cpp index 8fcc4fab312f26..9a383752551064 100644 --- a/src/protocols/bdx/tests/TestBdxTransferSession.cpp +++ b/src/protocols/bdx/tests/TestBdxTransferSession.cpp @@ -124,6 +124,13 @@ void VerifyNoMoreOutput(TransferSession & transferSession) EXPECT_EQ(event.EventType, TransferSession::OutputEventType::kNone); } +void VerifyInternalError(TransferSession & transferSession) +{ + TransferSession::OutputEvent event; + transferSession.PollOutput(event, kNoAdvanceTime); + EXPECT_EQ(event.EventType, TransferSession::OutputEventType::kInternalError); +} + // Helper method for initializing two TransferSession objects, generating a TransferInit message, and passing it to a responding // TransferSession. void SendAndVerifyTransferInit(TransferSession::OutputEvent & outEvent, System::Clock::Timeout timeout, TransferSession & initiator, @@ -235,6 +242,30 @@ void SendAndVerifyAcceptMsg(TransferSession::OutputEvent & outEvent, TransferSes EXPECT_LE(acceptReceiver.GetTransferBlockSize(), initData.MaxBlockSize); } +void SendAndVerifyRejectMsg(TransferSession::OutputEvent & outEvent, TransferSession & rejectSender, StatusCode reason, + TransferSession & rejectReceiver) +{ + CHIP_ERROR err = rejectSender.RejectTransfer(reason); + EXPECT_EQ(err, CHIP_NO_ERROR); + + // Verify Sender emits status message for sending + rejectSender.PollOutput(outEvent, kNoAdvanceTime); + VerifyNoMoreOutput(rejectSender); + EXPECT_EQ(outEvent.EventType, TransferSession::OutputEventType::kMsgToSend); + System::PacketBufferHandle statusReportMsg = outEvent.MsgData.Retain(); + VerifyStatusReport(std::move(outEvent.MsgData), reason); + + // Pass status message to rejectReceiver + err = AttachHeaderAndSend(outEvent.msgTypeData, std::move(outEvent.MsgData), rejectReceiver); + EXPECT_EQ(err, CHIP_NO_ERROR); + + // Verify received status message. + rejectReceiver.PollOutput(outEvent, kNoAdvanceTime); + VerifyInternalError(rejectReceiver); + EXPECT_EQ(outEvent.EventType, TransferSession::OutputEventType::kStatusReceived); + EXPECT_EQ(outEvent.statusData.statusCode, reason); +} + // Helper method for preparing a sending a BlockQuery message between two TransferSession objects. void SendAndVerifyQuery(TransferSession & queryReceiver, TransferSession & querySender, TransferSession::OutputEvent & outEvent) { @@ -698,3 +729,33 @@ TEST_F(TestBdxTransferSession, TestDuplicateBlockError) EXPECT_EQ(outEvent.statusData.statusCode, StatusCode::kBadBlockCounter); } } + +TEST_F(TestBdxTransferSession, TestRejectTransfer) +{ + TransferSession::OutputEvent outEvent; + TransferSession initiatingReceiver; + TransferSession respondingSender; + + // Chosen arbitrarily for this test + uint16_t proposedBlockSize = 128; + System::Clock::Timeout timeout = System::Clock::Seconds16(24); + TransferControlFlags driveMode = TransferControlFlags::kReceiverDrive; + + // ReceiveInit parameters + TransferSession::TransferInitData initOptions; + initOptions.TransferCtlFlags = driveMode; + initOptions.MaxBlockSize = proposedBlockSize; + char testFileDes[9] = { "test.txt" }; + initOptions.FileDesLength = static_cast(strlen(testFileDes)); + initOptions.FileDesignator = reinterpret_cast(testFileDes); + + // Initialize respondingSender and pass ReceiveInit message + BitFlags senderOpts; + senderOpts.Set(driveMode); + + SendAndVerifyTransferInit(outEvent, timeout, initiatingReceiver, TransferRole::kReceiver, initOptions, respondingSender, + senderOpts, proposedBlockSize); + + // Reject the transfer with a status + SendAndVerifyRejectMsg(outEvent, respondingSender, StatusCode::kResponderBusy, initiatingReceiver); +}