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 <lib/fit/function.h>
17 
18 #include <list>
19 
20 #include "pw_bluetooth_sapphire/internal/host/common/smart_task.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/tx_engine.h"
22 
23 namespace bt::l2cap::internal {
24 
25 // Implements the sender-side functionality of L2CAP Enhanced Retransmission
26 // Mode. See Bluetooth Core Spec v5.0, Volume 3, Part A, Sec 2.4, "Modes of
27 // Operation".
28 //
29 // THREAD-SAFETY: This class may is _not_ thread-safe. In particular:
30 // * the class assumes that some other party ensures that QueueSdu() is not
31 //   invoked concurrently with the destructor, and
32 // * the class assumes that all calls to QueueSdu occur on a single thread,
33 //   for the entire lifetime of an object.
34 class EnhancedRetransmissionModeTxEngine final : public TxEngine {
35  public:
36   using ConnectionFailureCallback = fit::function<void()>;
37 
38   // Create a transmit engine.
39   //
40   // The engine will invoke channel->SendFrame() when a PDU is ready for
41   // transmission; see tx_engine.h for further detail.
42   //
43   // The engine will invoke |connection_failure_callback| when a fatal error
44   // occurs on this connection. This callback _may_ occur synchronously. For
45   // example, a call to UpdateAckSeq() may synchronously invoke
46   // |connection_failure_callback|.
47   EnhancedRetransmissionModeTxEngine(
48       ChannelId channel_id,
49       uint16_t max_tx_sdu_size,
50       uint8_t max_transmissions,
51       uint8_t n_frames_in_tx_window,
52       TxChannel& channel,
53       ConnectionFailureCallback connection_failure_callback,
54       pw::async::Dispatcher& dispatcher);
55   ~EnhancedRetransmissionModeTxEngine() override = default;
56 
57   void NotifySduQueued() override;
58 
59   // Updates the Engine's knowledge of the last frame acknowledged by our peer.
60   // The value of |is_poll_response| should reflect the 'F' bit in header of the
61   // frame which led to this call.
62   //
63   // * This _may_ trigger retransmission of previously transmitted data.
64   // * This _may_ cause the (initial) transmission of queued data.
65   void UpdateAckSeq(uint8_t new_seq, bool is_poll_response);
66 
67   // Updates the Engine's knowledge of the next frame we expect to receive from
68   // our peer.
69   void UpdateReqSeq(uint8_t new_seq);
70 
71   // Informs the Engine that the peer is able to receive frames.
72   void ClearRemoteBusy();
73 
74   // Informs the Engine that the peer is unable to receive additional frames at
75   // this time.
76   void SetRemoteBusy();
77 
78   // Requests that the next UpdateAckSeq always retransmit the frame identified
79   // by its |new_seq| parameter, even if it's not a poll response. This path
80   // fulfills the requirements of receiving the SREJ function.
81   //
82   // Only one of Set{Single,Range}Retransmit can be called before each
83   // UpdateAckSeq.
84   //
85   // |is_poll_request| should be set if the request to retransmit has its P bit
86   // set and will cause the first retransmitted frame to have its
87   // |is_poll_response| bit (F bit) set per the Retransmit-Requested-I-frame
88   // action in Core Spec v5.0 Vol 3, Part A, Sec 8.6.5.6.
89   //
90   // If |is_poll_request| is false, UpdateAckSeq will be inhibited from dropping
91   // the unacked packets from ExpectedAckSeq to |new_seq| because this action is
92   // used to selectively retransmit missing frames that precede frames that the
93   // peer has already received.
94   //
95   // ClearRemoteBusy should be called if necessary because RemoteBusy is cleared
96   // as the first action to take when receiving an SREJ per Core Spec v5.0 Vol
97   // 3, Part A, Sec 8.6.5.9–11.
98   void SetSingleRetransmit(bool is_poll_request);
99 
100   // Requests that the next UpdateAckSeq always retransmit starting at its
101   // |new_seq| parameter, even if it's not a poll response. This path fulfills
102   // the requirements of receiving the REJ function.
103   //
104   // Only one of Set{Single,Range}Retransmit can be called before each
105   // UpdateAckSeq.
106   //
107   // |is_poll_request| should be set if the request to retransmit has its P bit
108   // set and will cause the first retransmitted frame to have its
109   // |is_poll_response| bit (F bit) set per the Retransmit-I-frames action in
110   // Core Spec v5.0 Vol 3, Part A, Sec 8.6.5.6.
111   //
112   // ClearRemoteBusy should be called if necessary because RemoteBusy is cleared
113   // as the first action to take when receiving a REJ per Core Spec v5.0 Vol 3,
114   // Part A, Sec 8.6.5.9–11.
115   void SetRangeRetransmit(bool is_poll_request);
116 
117   // Transmits data that has been queued, but which has never been previously
118   // sent to our peer. The transmissions are subject to remote-busy and transmit
119   // window constraints.
120   void MaybeSendQueuedData();
121 
122  private:
123   struct PendingPdu {
PendingPduPendingPdu124     PendingPdu(DynamicByteBuffer buf_in)
125         : buf(std::move(buf_in)), tx_count(0) {}
126     DynamicByteBuffer buf;
127     uint8_t tx_count;
128   };
129 
130   // State of a request from a peer to retransmit a frame of unacked data (SREJ
131   // per Core Spec v5.0, Vol 3, Part A, Sec 8.6.1.4).
132   struct SingleRetransmitRequest {
133     // True if the request to retransmit has its P bit set.
134     bool is_poll_request;
135   };
136 
137   // State of a request from a peer to retransmit a range of unacked data (REJ
138   // per Core Spec v5.0, Vol 3, Part A, Sec 8.6.1.2).
139   struct RangeRetransmitRequest {
140     // True if the request to retransmit has its P bit set.
141     bool is_poll_request;
142   };
143 
144   // Actions to take with a new AckSeq from the peer.
145   enum class UpdateAckSeqAction {
146     kConsumeAckSeq,        // Done with the received AckSeq.
147     kDiscardAcknowledged,  // Discard frames prior to AckSeq then send pending
148                            // frames.
149   };
150 
151   // Called from UpdateAckSeq to check if a SingleRetransmitRequest is pending.
152   // Retransmits if necessary and returns the action to take with |new_seq|.
153   //
154   // This call clears |single_request_| if set, so it is not idempotent.
155   UpdateAckSeqAction ProcessSingleRetransmitRequest(uint8_t new_seq,
156                                                     bool is_poll_response);
157 
158   // Starts the receiver ready poll timer. If already running, the existing
159   // timer is cancelled, and a new timer is started.
160   // Notes:
161   // * The specification refers to this as the "retransmission timer". However,
162   //   the expiry of this timer doesn't immediately trigger
163   //   retransmission. Rather, the timer expiration triggers us asking the
164   //   receiver to acknowledge all previously received data. See
165   //   "RetransTimer-Expires", in Core Spec v5.0, Volume 3, Part A, Table 8.4.
166   // * Replacing the existing timer is required per Core Spec v5.0, Volume 3,
167   //   Part A, Section 8.6.5.6, "Start-RetransTimer".
168   void StartReceiverReadyPollTimer();
169 
170   // Starts the monitor timer.  If already running, the existing timer is
171   // cancelled, and a new timer is started.
172   //
173   // Note that replacing the existing timer is required per Core Spec v5.0,
174   // Volume 3, Part A, Section 8.6.5.6, "Start-MonitorTimer".
175   void StartMonitorTimer();
176 
177   void SendReceiverReadyPoll();
178 
179   // Return and consume the next sequence number.
180   uint8_t GetNextTxSeq();
181 
182   // Returns the number of frames that have been transmitted but not yet
183   // acknowledged.
184   uint8_t NumUnackedFrames();
185 
186   void SendPdu(PendingPdu* pdu);
187 
188   // Retransmits frames from |pending_pdus_|. Invokes
189   // |connection_failure_callback_| on error and returns false. Cancels
190   // |monitor_task_| if it's running.
191   //
192   // If |only_with_seq| is set, then only the unacked frame with that TxSeq will
193   // be retransmitted.
194   //
195   // If |set_is_poll_response| is true, then the first frame to be sent will
196   // have its |is_poll_response| field set.
197   //
198   // Notes:
199   // * The caller must ensure that |!remote_is_busy_|.
200   // * When return value is an error, |this| may be invalid.
201   [[nodiscard]] bool RetransmitUnackedData(std::optional<uint8_t> only_with_seq,
202                                            bool set_is_poll_response);
203 
204   // Process a new SDU from the channel queue.
205   void ProcessSdu(ByteBufferPtr sdu);
206 
207   pw::async::Dispatcher& pw_dispatcher_;
208 
209   const uint8_t max_transmissions_;
210   const uint8_t n_frames_in_tx_window_;
211 
212   // Invoked when the connection encounters a fatal error.
213   const ConnectionFailureCallback connection_failure_callback_;
214 
215   // The sequence number we expect in the next acknowledgement from our peer.
216   //
217   // We assume that the Extended Window Size option is _not_ enabled. In such
218   // cases, the sequence number is a 6-bit counter that wraps on overflow. See
219   // Core Spec v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
220   uint8_t expected_ack_seq_;
221 
222   // The sequence number we will use for the next new outbound I-frame.
223   //
224   // We assume that the Extended Window Size option is _not_ enabled. In such
225   // cases, the sequence number is a 6-bit counter that wraps on overflow. See
226   // Core Spec v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
227   uint8_t next_tx_seq_;
228 
229   // The sequence number of the "newest" transmitted frame.
230   //
231   // This sequence number is updated when a new frame is transmitted. This
232   // excludes cases where a frame is queued but not transmitted (due to transmit
233   // window limitations), and cases where a frame is retransmitted.
234   //
235   // This value is useful for determining the number of frames than are
236   // in-flight to our peer (frames that have been transmitted but not
237   // acknowledged).
238   //
239   // We assume that the Extended Window Size option is _not_ enabled. In such
240   // cases, the sequence number is a 6-bit counter that wraps on overflow. See
241   // Core Spec v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
242   uint8_t last_tx_seq_;  // (AKA TxSeq)
243 
244   // The sequence number we expect for the next packet sent _to_ us.
245   //
246   // We assume that the Extended Window Size option is _not_ enabled. In such
247   // cases, the sequence number is a 6-bit counter that wraps on overflow. See
248   // Core Spec v5.0, Vol 3, Part A, Secs 5.7 and 8.3.
249   uint8_t req_seqnum_;
250 
251   // Filled by SetSingleRetransmit and cleared by UpdateAckSeq.
252   std::optional<SingleRetransmitRequest> single_request_;
253 
254   // Filled by SetRangeRetransmit and cleared by UpdateAckSeq.
255   std::optional<RangeRetransmitRequest> range_request_;
256 
257   // Set to AckSeq of the most recent frame retransmitted after sending a poll
258   // request but before receiving a poll response. Corresponds to the
259   // SrejActioned and SrejSaveReqSeq variables defined in Core Spec v5.0, Vol 3,
260   // Part A, Sec 8.6.5.3.
261   std::optional<uint8_t> retransmitted_single_during_poll_;
262 
263   // True if we retransmitted a range of unacked data after sending a poll
264   // request but before receiving a poll response. Corresponds to the
265   // RejActioned variable defined in Core Spec v5.0 Vol 3, Part A, Sec 8.6.5.3.
266   bool retransmitted_range_during_poll_;
267 
268   uint8_t n_receiver_ready_polls_sent_;
269   bool remote_is_busy_;
270   std::list<PendingPdu> pending_pdus_;
271   SmartTask receiver_ready_poll_task_{pw_dispatcher_};
272   SmartTask monitor_task_{pw_dispatcher_};
273 
274   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(EnhancedRetransmissionModeTxEngine);
275 };
276 
277 }  // namespace bt::l2cap::internal
278