| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_ENHANCED_RETRANSMISSION_MODE_RX_ENGINE_H_ |
| #define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_ENHANCED_RETRANSMISSION_MODE_RX_ENGINE_H_ |
| |
| #include <variant> |
| |
| #include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/frame_headers.h" |
| #include "src/connectivity/bluetooth/core/bt-host/l2cap/rx_engine.h" |
| |
| namespace bt::l2cap::internal { |
| |
| // Implements the receiver state and logic for an L2CAP channel operating in |
| // Enhanced Retransmission Mode. |
| // |
| // THREAD-SAFETY: This class is not thread-safe. |
| class EnhancedRetransmissionModeRxEngine final : public RxEngine { |
| public: |
| using SendFrameCallback = fit::function<void(ByteBufferPtr pdu)>; |
| using ConnectionFailureCallback = fit::function<void()>; |
| |
| EnhancedRetransmissionModeRxEngine(SendFrameCallback send_frame_callback, |
| ConnectionFailureCallback connection_failure_callback); |
| ~EnhancedRetransmissionModeRxEngine() override = default; |
| |
| ByteBufferPtr ProcessPdu(PDU) override; |
| |
| // Set a callback to be invoked when any frame is received that indicates the peer's |
| // acknowledgment for the sequence of packets that it received from the local host. The values are |
| // not checked against the local sender's TxWindow. |is_poll_response| reflects the 'F' bit in the |
| // header of the received frame. |
| using ReceiveSeqNumCallback = fit::function<void(uint8_t receive_seq_num, bool is_poll_response)>; |
| void set_receive_seq_num_callback(ReceiveSeqNumCallback receive_seq_num_callback) { |
| receive_seq_num_callback_ = std::move(receive_seq_num_callback); |
| } |
| |
| // Set a callback to be invoked that reports our acknowledgment of inbound frames from the peer. |
| // |ack_seq_num| is the TxSeq of the next I-frame we expect from the peer. |
| using AckSeqNumCallback = fit::function<void(uint8_t ack_seq_num)>; |
| void set_ack_seq_num_callback(AckSeqNumCallback ack_seq_num_callback) { |
| ack_seq_num_callback_ = std::move(ack_seq_num_callback); |
| } |
| |
| // Set callbacks to be invoked when the RemoteBusy state variable (Core Spec v5.0, Vol 3, Part A, |
| // Section 8.6.5.3) changes to indicate whether the peer can receive additional I-Frames. |
| using RemoteBusyChangedCallback = fit::closure; |
| void set_remote_busy_set_callback(RemoteBusyChangedCallback remote_busy_set_callback) { |
| remote_busy_set_callback_ = std::move(remote_busy_set_callback); |
| } |
| |
| void set_remote_busy_cleared_callback(RemoteBusyChangedCallback remote_busy_cleared_callback) { |
| remote_busy_cleared_callback_ = std::move(remote_busy_cleared_callback); |
| } |
| |
| // Set a callback to be invoked when a Reject function (Core Spec v5.0, Vol 3, Part A, Sec |
| // 8.6.1.2) is received. This invocation precedes the ReceiveSeqNumCallback invocation, which |
| // delivers the SeqNum that the TxEngine is expected to retransmit first. |
| // |
| // |is_poll_request| reflects the 'P' bit in the header of the received frame. |
| using RangeRetransmitSetCallback = fit::function<void(bool is_poll_request)>; |
| void set_range_retransmit_set_callback(RangeRetransmitSetCallback range_retransmit_set_callback) { |
| range_retransmit_set_callback_ = std::move(range_retransmit_set_callback); |
| } |
| |
| // Set a callback to be invoked when a Selective Reject function (Core Spec v5.0, Vol 3, Part A, |
| // Sec 8.6.1.4) is received. This invocation precedes the ReceiveSeqNumCallback invocation, which |
| // delivers the SeqNum of the I-Frame that the TxEngine is expected to retransmit. |
| // |
| // |is_poll_request| reflects the 'P' bit in the header of the received frame. |
| using SingleRetransmitSetCallback = fit::function<void(bool is_poll_request)>; |
| void set_single_retransmit_set_callback( |
| SingleRetransmitSetCallback single_retransmit_set_callback) { |
| single_retransmit_set_callback_ = std::move(single_retransmit_set_callback); |
| } |
| |
| private: |
| ByteBufferPtr ProcessFrame(const SimpleInformationFrameHeader, PDU); |
| ByteBufferPtr ProcessFrame(const SimpleStartOfSduFrameHeader, PDU); |
| ByteBufferPtr ProcessFrame(const SimpleSupervisoryFrame, PDU); |
| ByteBufferPtr ProcessFrame(std::monostate, PDU); |
| void AdvanceSeqNum(); |
| |
| // We assume that the Extended Window Size option is _not_ enabled. In such |
| // cases, the sequence number is a 6-bit counter that wraps on overflow. See |
| // Core Spec Ver 5, Vol 3, Part A, Secs 5.7 and 8.3. |
| uint8_t next_seqnum_; // (AKA Expected-TxSeq) |
| |
| // Represents the RemoteBusy state variable (Core Spec v5.0, Vol 3, Part A, Section 8.6.5.3) for |
| // whether the peer has sent a Receiver Not Ready. |
| bool remote_is_busy_; |
| |
| SendFrameCallback send_frame_callback_; |
| |
| // Invoked when the connection encounters a fatal error. |
| const ConnectionFailureCallback connection_failure_callback_; |
| |
| // TODO(fxbug.dev/52554): Refactor these delegates into a single interface for TxEngine to implement. |
| ReceiveSeqNumCallback receive_seq_num_callback_; |
| AckSeqNumCallback ack_seq_num_callback_; |
| RemoteBusyChangedCallback remote_busy_set_callback_; |
| RemoteBusyChangedCallback remote_busy_cleared_callback_; |
| RangeRetransmitSetCallback range_retransmit_set_callback_; |
| SingleRetransmitSetCallback single_retransmit_set_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(EnhancedRetransmissionModeRxEngine); |
| }; |
| |
| } // namespace bt::l2cap::internal |
| |
| #endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_ENHANCED_RETRANSMISSION_MODE_RX_ENGINE_H_ |