diff --git a/src/protocols/bdx/AsyncTransferFacilitator.cpp b/src/protocols/bdx/AsyncTransferFacilitator.cpp index 2e3a0f03794319..51bd0fd51e27ba 100644 --- a/src/protocols/bdx/AsyncTransferFacilitator.cpp +++ b/src/protocols/bdx/AsyncTransferFacilitator.cpp @@ -63,6 +63,17 @@ void AsyncTransferFacilitator::ProcessOutputEvents() mTransfer.GetNextAction(outEvent); while (outEvent.EventType != TransferSession::OutputEventType::kNone) { + + // If the transfer session state machine generates an event of type TransferSession::OutputEventType::kInternalError, + // indicating that the session is in a bad state, it will keep doing that thereafter. + // + // So stop trying to process events, and go ahead and destroy ourselves to clean up the transfer. + if (outEvent.EventType == TransferSession::OutputEventType::kInternalError) + { + mDestroySelfAfterProcessingEvents = true; + break; + } + if (outEvent.EventType == TransferSession::OutputEventType::kMsgToSend) { CHIP_ERROR err = SendMessage(outEvent.msgTypeData, outEvent.MsgData); @@ -170,21 +181,20 @@ void AsyncResponder::NotifyEventHandled(const TransferSession::OutputEventType e ChipLogDetail(BDX, "NotifyEventHandled : Event %s Error %" CHIP_ERROR_FORMAT, TransferSession::OutputEvent::TypeToString(eventType), status.Format()); - // If this is the end of the transfer (whether a clean end, or some sort of error condition), ensure that - // we destroy ourselves after processing any output events that might have been generated by - // the transfer session to handle end-of-transfer (e.g. in some error conditions it might want to send - // out a status report). + // If this is the end of the transfer (whether a clean end, or some sort of error condition), ensure + // that we destroy ourselves after unwinding the processing loop in the ProcessOutputEvents API. + // We can ignore the status for these messages since the state machine is in a bad, unrecoverable + // state and we should stop processing events and clean up. if (eventType == TransferSession::OutputEventType::kAckEOFReceived || + eventType == TransferSession::OutputEventType::kStatusReceived || eventType == TransferSession::OutputEventType::kInternalError || - eventType == TransferSession::OutputEventType::kTransferTimeout || - eventType == TransferSession::OutputEventType::kStatusReceived) + eventType == TransferSession::OutputEventType::kTransferTimeout) { mDestroySelfAfterProcessingEvents = true; } - // If there was an error handling the output event, this should notify the transfer object to abort transfer so it can send a // status report across the exchange when we call ProcessOutputEvents below. - if (status != CHIP_NO_ERROR) + else if (status != CHIP_NO_ERROR) { mTransfer.AbortTransfer(GetBdxStatusCodeFromChipError(status)); } diff --git a/src/protocols/bdx/AsyncTransferFacilitator.h b/src/protocols/bdx/AsyncTransferFacilitator.h index 1ad95d39e98d2d..39f87b741160c9 100644 --- a/src/protocols/bdx/AsyncTransferFacilitator.h +++ b/src/protocols/bdx/AsyncTransferFacilitator.h @@ -72,7 +72,11 @@ class AsyncTransferFacilitator : public Messaging::ExchangeDelegate */ virtual void DestroySelf() = 0; - // Calling ProcessOutputEvents can destroy this object before the call returns. + /** + * Calling ProcessOutputEvents can destroy this object before the call returns for certain cases + * where the state machine either receives a message indicating termination of the transfer session + * or some error cases where the state machine goes to a bad, unrecoverable state. + */ void ProcessOutputEvents(); // The transfer session corresponding to this AsyncTransferFacilitator object.