blob: 1ec2b8949a848cda65cab775d0806d03a18cd3b3 [file] [log] [blame]
// 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_TX_ENGINE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_ENHANCED_RETRANSMISSION_MODE_TX_ENGINE_H_
#include "lib/async/cpp/task.h"
#include "lib/fit/function.h"
#include "lib/zx/time.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/tx_engine.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt {
namespace l2cap {
namespace internal {
// Implements the sender-side functionality of L2CAP Enhanced Retransmission
// Mode. See Bluetooth Core Spec v5.0, Volume 3, Part A, Sec 2.4, "Modes of
// Operation".
//
// THREAD-SAFETY: This class may is _not_ thread-safe. In particular:
// * the class assumes that some other party ensures that QueueSdu() is not
// invoked concurrently with the destructor, and
// * the class assumes that all calls to QueueSdu occur on a single thread,
// for the entire lifetime of an object.
class EnhancedRetransmissionModeTxEngine final : public TxEngine {
public:
using ConnectionFailureCallback = fit::function<void()>;
// Create a transmit engine.
//
// The engine will invoke |send_basic_frame_callback| when a PDU is ready for
// transmission; see tx_engine.h for further detail.
//
// The engine will invoke |connection_failure_callback| when a fatal error
// occurs on this connection. This callback will never occur synchronously.
EnhancedRetransmissionModeTxEngine(
ChannelId channel_id, uint16_t tx_mtu, uint8_t max_transmissions,
uint8_t n_frames_in_tx_window,
SendBasicFrameCallback send_basic_frame_callback,
ConnectionFailureCallback connection_failure_callback);
~EnhancedRetransmissionModeTxEngine() override = default;
bool QueueSdu(ByteBufferPtr sdu) override;
// Updates the Engine's knowledge of the last frame acknowledged by our peer.
// The value of |is_final| should reflect the 'F' bit in header of the frame
// which led to this call.
void UpdateAckSeq(uint8_t new_seq, bool is_final);
// Updates the Engine's knowledge of the next frame we expect to receive from
// our peer.
void UpdateReqSeq(uint8_t new_seq);
private:
// See Core Spec v5.0, Volume 3, Part A, Sec 8.6.2.1. Note that we assume
// there is no flush timeout on the underlying logical link.
//
// TODO(quiche): This value should be dynamic, and based on the parameters
// from the L2CAP configuration process. See Core Spec v5.0, Volume 3, Part A,
// Sec 5.4.
static constexpr auto kReceiverReadyPollTimerDuration = zx::sec(2);
// See Core Spec v5.0, Volume 3, Part A, Sec 8.6.2.1. Note that we assume
// there is no flush timeout on the underlying logical link. If the link
// _does_ have a flush timeout, then our implementation will be slower to
// trigger the monitor timeout than the specification recommends.
//
// TODO(quiche): This value should be dynamic, and based on the parameters
// from the L2CAP configuration process. See Core Spec v5.0, Volume 3, Part A,
// Sec 5.4.
static constexpr auto kMonitorTimerDuration = zx::sec(12);
// Starts the receiver ready poll timer. If already running, the existing
// timer is cancelled, and a new timer is started.
// Notes:
// * The specification refers to this as the "retransmission timer". However,
// the expiry of this timer doesn't immediately trigger
// retransmission. Rather, the timer expiration triggers us asking the
// receiver to acknowledge all previously received data. See
// "RetransTimer-Expires", in Core Spec v5.0, Volume 3, Part A, Table 8.4.
// * Replacing the existing timer is required per Core Spec v5.0, Volume 3,
// Part A, Section 8.6.5.6, "Start-RetransTimer".
void StartReceiverReadyPollTimer();
// Starts the monitor timer. If already running, the existing timer is
// cancelled, and a new timer is started.
//
// Note that replacing the existing timer is required per Core Spec v5.0,
// Volume 3, Part A, Section 8.6.5.6, "Start-MonitorTimer".
void StartMonitorTimer();
void SendReceiverReadyPoll();
// Return and consume the next sequence number.
uint8_t GetNextSeqnum();
const uint8_t max_transmissions_;
// TODO(quiche): Remove |maybe_unused| after adding transmit window logic.
[[maybe_unused]] const uint8_t n_frames_in_tx_window_;
// Invoked when the connection encounters a fatal error.
const ConnectionFailureCallback connection_failure_callback_;
// The sequence number we expect in the next acknowledgement from our peer.
//
// 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 v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
uint8_t ack_seqnum_; // (AKA ExpectedAckSeq)
// The sequence number we will use for the next new outbound I-frame.
//
// 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 v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
uint8_t next_seqnum_; // (AKA NextTxSeq)
// The sequence number we expect for the next packet sent _to_ us.
//
// 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 v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
uint8_t req_seqnum_;
uint8_t n_receiver_ready_polls_sent_;
async::Task receiver_ready_poll_task_;
async::Task monitor_task_;
fxl::WeakPtrFactory<EnhancedRetransmissionModeTxEngine>
weak_factory_; // Keep last
FXL_DISALLOW_COPY_AND_ASSIGN(EnhancedRetransmissionModeTxEngine);
};
} // namespace internal
} // namespace l2cap
} // namespace bt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_ENHANCED_RETRANSMISSION_MODE_TX_ENGINE_H_