1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #pragma once 16 #include <variant> 17 18 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 19 #include "pw_bluetooth_sapphire/internal/host/l2cap/frame_headers.h" 20 #include "pw_bluetooth_sapphire/internal/host/l2cap/rx_engine.h" 21 22 namespace bt::l2cap::internal { 23 24 // Implements the receiver state and logic for an L2CAP channel operating in 25 // Enhanced Retransmission Mode. 26 // 27 // THREAD-SAFETY: This class is not thread-safe. 28 class EnhancedRetransmissionModeRxEngine final : public RxEngine { 29 public: 30 using SendFrameCallback = fit::function<void(ByteBufferPtr pdu)>; 31 using ConnectionFailureCallback = fit::function<void()>; 32 33 EnhancedRetransmissionModeRxEngine( 34 SendFrameCallback send_frame_callback, 35 ConnectionFailureCallback connection_failure_callback); 36 ~EnhancedRetransmissionModeRxEngine() override = default; 37 38 ByteBufferPtr ProcessPdu(PDU) override; 39 40 // Set a callback to be invoked when any frame is received that indicates the 41 // peer's acknowledgment for the sequence of packets that it received from the 42 // local host. The values are not checked against the local sender's TxWindow. 43 // |is_poll_response| reflects the 'F' bit in the header of the received 44 // frame. 45 using ReceiveSeqNumCallback = 46 fit::function<void(uint8_t receive_seq_num, bool is_poll_response)>; set_receive_seq_num_callback(ReceiveSeqNumCallback receive_seq_num_callback)47 void set_receive_seq_num_callback( 48 ReceiveSeqNumCallback receive_seq_num_callback) { 49 receive_seq_num_callback_ = std::move(receive_seq_num_callback); 50 } 51 52 // Set a callback to be invoked that reports our acknowledgment of inbound 53 // frames from the peer. |ack_seq_num| is the TxSeq of the next I-frame we 54 // expect from the peer. 55 using AckSeqNumCallback = fit::function<void(uint8_t ack_seq_num)>; set_ack_seq_num_callback(AckSeqNumCallback ack_seq_num_callback)56 void set_ack_seq_num_callback(AckSeqNumCallback ack_seq_num_callback) { 57 ack_seq_num_callback_ = std::move(ack_seq_num_callback); 58 } 59 60 // Set callbacks to be invoked when the RemoteBusy state variable (Core Spec 61 // v5.0, Vol 3, Part A, Section 8.6.5.3) changes to indicate whether the peer 62 // can receive additional I-Frames. 63 using RemoteBusyChangedCallback = fit::closure; set_remote_busy_set_callback(RemoteBusyChangedCallback remote_busy_set_callback)64 void set_remote_busy_set_callback( 65 RemoteBusyChangedCallback remote_busy_set_callback) { 66 remote_busy_set_callback_ = std::move(remote_busy_set_callback); 67 } 68 set_remote_busy_cleared_callback(RemoteBusyChangedCallback remote_busy_cleared_callback)69 void set_remote_busy_cleared_callback( 70 RemoteBusyChangedCallback remote_busy_cleared_callback) { 71 remote_busy_cleared_callback_ = std::move(remote_busy_cleared_callback); 72 } 73 74 // Set a callback to be invoked when a Reject function (Core Spec v5.0, Vol 3, 75 // Part A, Sec 8.6.1.2) is received. This invocation precedes the 76 // ReceiveSeqNumCallback invocation, which delivers the SeqNum that the 77 // TxEngine is expected to retransmit first. 78 // 79 // |is_poll_request| reflects the 'P' bit in the header of the received frame. 80 using RangeRetransmitSetCallback = fit::function<void(bool is_poll_request)>; set_range_retransmit_set_callback(RangeRetransmitSetCallback range_retransmit_set_callback)81 void set_range_retransmit_set_callback( 82 RangeRetransmitSetCallback range_retransmit_set_callback) { 83 range_retransmit_set_callback_ = std::move(range_retransmit_set_callback); 84 } 85 86 // Set a callback to be invoked when a Selective Reject function (Core Spec 87 // v5.0, Vol 3, Part A, Sec 8.6.1.4) is received. This invocation precedes the 88 // ReceiveSeqNumCallback invocation, which delivers the SeqNum of the I-Frame 89 // that the TxEngine is expected to retransmit. 90 // 91 // |is_poll_request| reflects the 'P' bit in the header of the received frame. 92 using SingleRetransmitSetCallback = fit::function<void(bool is_poll_request)>; set_single_retransmit_set_callback(SingleRetransmitSetCallback single_retransmit_set_callback)93 void set_single_retransmit_set_callback( 94 SingleRetransmitSetCallback single_retransmit_set_callback) { 95 single_retransmit_set_callback_ = std::move(single_retransmit_set_callback); 96 } 97 98 private: 99 ByteBufferPtr ProcessFrame(const SimpleInformationFrameHeader, PDU); 100 ByteBufferPtr ProcessFrame(const SimpleStartOfSduFrameHeader, PDU); 101 ByteBufferPtr ProcessFrame(const SimpleSupervisoryFrame, PDU); 102 ByteBufferPtr ProcessFrame(std::monostate, PDU); 103 void AdvanceSeqNum(); 104 105 // We assume that the Extended Window Size option is _not_ enabled. In such 106 // cases, the sequence number is a 6-bit counter that wraps on overflow. See 107 // Core Spec Ver 5, Vol 3, Part A, Secs 5.7 and 8.3. 108 uint8_t next_seqnum_; // (AKA Expected-TxSeq) 109 110 // Represents the RemoteBusy state variable (Core Spec v5.0, Vol 3, Part A, 111 // Section 8.6.5.3) for whether the peer has sent a Receiver Not Ready. 112 bool remote_is_busy_; 113 114 SendFrameCallback send_frame_callback_; 115 116 // Invoked when the connection encounters a fatal error. 117 const ConnectionFailureCallback connection_failure_callback_; 118 119 // TODO(fxbug.dev/42129869): Refactor these delegates into a single interface 120 // for TxEngine to implement. 121 ReceiveSeqNumCallback receive_seq_num_callback_; 122 AckSeqNumCallback ack_seq_num_callback_; 123 RemoteBusyChangedCallback remote_busy_set_callback_; 124 RemoteBusyChangedCallback remote_busy_cleared_callback_; 125 RangeRetransmitSetCallback range_retransmit_set_callback_; 126 SingleRetransmitSetCallback single_retransmit_set_callback_; 127 128 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(EnhancedRetransmissionModeRxEngine); 129 }; 130 131 } // namespace bt::l2cap::internal 132