blob: 74e8a2f65d90aad158b1955da20804c455602ad5 [file] [log] [blame]
Hansong Zhangb0960762019-11-14 17:57:10 -08001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "l2cap/internal/enhanced_retransmission_mode_channel_data_controller.h"
18
Hansong Zhang65941942019-11-16 23:48:30 -080019#include <map>
20#include <queue>
21#include <vector>
22
23#include "common/bind.h"
Hansong Zhang98b5baa2019-11-26 10:54:07 -080024#include "l2cap/internal/ilink.h"
Hansong Zhang65941942019-11-16 23:48:30 -080025#include "os/alarm.h"
26#include "packet/fragmenting_inserter.h"
27#include "packet/raw_builder.h"
28
Hansong Zhangb0960762019-11-14 17:57:10 -080029namespace bluetooth {
30namespace l2cap {
31namespace internal {
Hansong Zhang98b5baa2019-11-26 10:54:07 -080032ErtmController::ErtmController(ILink* link, Cid cid, Cid remote_cid, UpperQueueDownEnd* channel_queue_end,
33 os::Handler* handler, Scheduler* scheduler)
34 : link_(link), cid_(cid), remote_cid_(remote_cid), enqueue_buffer_(channel_queue_end), handler_(handler),
35 scheduler_(scheduler), pimpl_(std::make_unique<impl>(this, handler)) {}
Hansong Zhangb0960762019-11-14 17:57:10 -080036
Hansong Zhang65941942019-11-16 23:48:30 -080037ErtmController::~ErtmController() = default;
38
39struct ErtmController::impl {
40 impl(ErtmController* controller, os::Handler* handler)
41 : controller_(controller), handler_(handler), retrans_timer_(handler), monitor_timer_(handler) {}
42
43 ErtmController* controller_;
44 os::Handler* handler_;
45
46 // We don't support extended window
47 static constexpr uint8_t kMaxTxWin = 64;
48
49 // We don't support sending SREJ
50 static constexpr bool kSendSrej = false;
51
52 // States (@see 8.6.5.2): Transmitter state and receiver state
53
54 enum class TxState {
55 XMIT,
56 WAIT_F,
57 };
58 TxState tx_state_ = TxState::XMIT;
59
60 enum class RxState {
61 RECV,
62 REJ_SENT,
63 SREJ_SENT,
64 };
65 RxState rx_state_ = RxState::RECV;
66
67 // Variables and Timers (@see 8.6.5.3)
68
69 uint8_t tx_seq_ = 0;
70 uint8_t next_tx_seq_ = 0;
71 uint8_t expected_ack_seq_ = 0;
72 uint8_t req_seq_ = 0;
73 uint8_t expected_tx_seq_ = 0;
74 uint8_t buffer_seq_ = 0;
75
76 bool remote_busy_ = false;
77 bool local_busy_ = false;
78 int unacked_frames_ = 0;
79 // TODO: Instead of having a map, we may consider about a better data structure
Hansong Zhanga6312532019-11-19 14:01:36 -080080 // Map from TxSeq to (SAR, SDU size for START packet, information payload)
81 std::map<uint8_t, std::tuple<SegmentationAndReassembly, uint16_t, std::shared_ptr<packet::RawBuilder>>> unacked_list_;
82 // Stores (SAR, SDU size for START packet, information payload)
83 std::queue<std::tuple<SegmentationAndReassembly, uint16_t, std::unique_ptr<packet::RawBuilder>>> pending_frames_;
Hansong Zhang65941942019-11-16 23:48:30 -080084 int retry_count_ = 0;
85 std::map<uint8_t /* tx_seq, */, int /* count */> retry_i_frames_;
86 bool rnr_sent_ = false;
87 bool rej_actioned_ = false;
88 bool srej_actioned_ = false;
89 uint16_t srej_save_req_seq_ = 0;
90 bool send_rej_ = false;
91 int buffer_seq_srej_ = 0;
92 int frames_sent_ = 0;
93 os::Alarm retrans_timer_;
94 os::Alarm monitor_timer_;
95
96 // Events (@see 8.6.5.4)
97
Hansong Zhanga6312532019-11-19 14:01:36 -080098 void data_request(SegmentationAndReassembly sar, std::unique_ptr<packet::RawBuilder> pdu, uint16_t sdu_size = 0) {
99 // Note: sdu_size only applies to START packet
Hansong Zhang65941942019-11-16 23:48:30 -0800100 if (tx_state_ == TxState::XMIT && !remote_busy() && rem_window_not_full()) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800101 send_data(sar, sdu_size, std::move(pdu));
Hansong Zhang65941942019-11-16 23:48:30 -0800102 } else if (tx_state_ == TxState::XMIT && (remote_busy() || rem_window_full())) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800103 pend_data(sar, sdu_size, std::move(pdu));
Hansong Zhang65941942019-11-16 23:48:30 -0800104 } else if (tx_state_ == TxState::WAIT_F) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800105 pend_data(sar, sdu_size, std::move(pdu));
Hansong Zhang65941942019-11-16 23:48:30 -0800106 }
107 }
108
109 void local_busy_detected() {
110 local_busy_ = true;
111 }
112
113 void local_busy_clear() {
114 if (tx_state_ == TxState::XMIT && rnr_sent()) {
115 local_busy_ = false;
116 rnr_sent_ = false;
117 send_rr(Poll::POLL);
118 retry_count_ = 1;
119 stop_retrans_timer();
120 start_monitor_timer();
121 } else if (tx_state_ == TxState::XMIT) {
122 local_busy_ = false;
123 rnr_sent_ = false;
124 }
125 }
126
127 void recv_req_seq_and_f_bit(uint8_t req_seq, Final f) {
128 if (tx_state_ == TxState::XMIT) {
129 process_req_seq(req_seq);
130 } else if (f == Final::POLL_RESPONSE) {
131 process_req_seq(req_seq);
132 stop_monitor_timer();
133 if (unacked_frames_ > 0) {
134 start_retrans_timer();
135 }
136 tx_state_ = TxState::XMIT;
137 } else {
138 process_req_seq(req_seq);
139 }
140 }
141
142 void recv_f_bit(Final f) {
143 if (tx_state_ == TxState::WAIT_F && f == Final::POLL_RESPONSE) {
144 stop_monitor_timer();
145 if (unacked_frames_ > 0) {
146 start_retrans_timer();
147 }
148 tx_state_ = TxState::XMIT;
149 }
150 }
151
152 void retrans_timer_expires() {
153 if (tx_state_ == TxState::XMIT) {
154 send_rr_or_rnr(Poll::POLL);
155 // send rr or rnr(p=1)
156 retry_count_ = 1;
Hansong Zhangd0c47e62019-11-26 14:00:37 -0800157 start_monitor_timer();
Hansong Zhang65941942019-11-16 23:48:30 -0800158 tx_state_ = TxState::WAIT_F;
159 }
160 }
161
162 void monitor_timer_expires() {
163 if (tx_state_ == TxState::WAIT_F && retry_count_less_than_max_transmit()) {
164 retry_count_++;
165 send_rr_or_rnr(Poll::POLL);
166 start_monitor_timer();
167 } else if (tx_state_ == TxState::WAIT_F) {
168 CloseChannel();
169 }
170 }
171
Hansong Zhang2392dff2019-11-22 11:14:49 -0800172 void recv_i_frame(Final f, uint8_t tx_seq, uint8_t req_seq, SegmentationAndReassembly sar, uint16_t sdu_size,
Hansong Zhang65941942019-11-16 23:48:30 -0800173 const packet::PacketView<true>& payload) {
174 if (rx_state_ == RxState::RECV) {
175 if (f == Final::NOT_SET && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f) &&
176 !local_busy()) {
177 increment_expected_tx_seq();
178 pass_to_tx(req_seq, f);
Hansong Zhang2392dff2019-11-22 11:14:49 -0800179 data_indication(sar, sdu_size, payload);
Hansong Zhang65941942019-11-16 23:48:30 -0800180 send_ack(Final::NOT_SET);
181 } else if (f == Final::POLL_RESPONSE && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) &&
182 with_valid_f_bit(f) && !local_busy()) {
183 increment_expected_tx_seq();
184 pass_to_tx(req_seq, f);
Hansong Zhang2392dff2019-11-22 11:14:49 -0800185 data_indication(sar, sdu_size, payload);
Hansong Zhang65941942019-11-16 23:48:30 -0800186 if (!rej_actioned_) {
187 retransmit_i_frames(req_seq);
188 send_pending_i_frames();
189 } else {
190 rej_actioned_ = false;
191 }
192 send_ack(Final::NOT_SET);
193 } else if (with_duplicate_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f) && !local_busy()) {
194 pass_to_tx(req_seq, f);
195 } else if (with_unexpected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f) &&
196 !local_busy()) {
197 if constexpr (kSendSrej) {
198 // We don't support sending SREJ
199 } else {
200 pass_to_tx(req_seq, f);
201 send_rej();
202 rx_state_ = RxState::REJ_SENT;
203 }
204 } else if (with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f) && local_busy()) {
205 pass_to_tx(req_seq, f);
206 store_or_ignore();
207 } else if (with_valid_req_seq(req_seq) && not_with_expected_tx_seq(tx_seq) && with_valid_f_bit(f) &&
208 local_busy()) {
209 pass_to_tx(req_seq, f);
210 } else if ((with_invalid_tx_seq(tx_seq) && controller_->local_tx_window_ > kMaxTxWin / 2) ||
211 with_invalid_req_seq(req_seq)) {
212 CloseChannel();
213 } else if (with_invalid_tx_seq(tx_seq) && controller_->local_tx_window_ <= kMaxTxWin / 2) {
214 // We decided to ignore
215 }
216 } else if (rx_state_ == RxState::REJ_SENT) {
217 if (f == Final::NOT_SET && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
218 increment_expected_tx_seq();
219 pass_to_tx(req_seq, f);
Hansong Zhang2392dff2019-11-22 11:14:49 -0800220 data_indication(sar, sdu_size, payload);
Hansong Zhang65941942019-11-16 23:48:30 -0800221 send_ack(Final::NOT_SET);
222 rx_state_ = RxState::RECV;
223 } else if (f == Final::POLL_RESPONSE && with_expected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) &&
224 with_valid_f_bit(f)) {
225 increment_expected_tx_seq();
226 pass_to_tx(req_seq, f);
Hansong Zhang2392dff2019-11-22 11:14:49 -0800227 data_indication(sar, sdu_size, payload);
Hansong Zhang65941942019-11-16 23:48:30 -0800228 if (!rej_actioned_) {
229 retransmit_i_frames(req_seq);
230 send_pending_i_frames();
231 } else {
232 rej_actioned_ = false;
233 }
234 send_ack(Final::NOT_SET);
235 rx_state_ = RxState::RECV;
236 } else if (with_unexpected_tx_seq(tx_seq) && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
237 pass_to_tx(req_seq, f);
238 }
239 } else if (rx_state_ == RxState::SREJ_SENT) {
240 // SREJ NOT SUPPORTED
241 }
242 }
243
244 void recv_rr(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
245 if (rx_state_ == RxState::RECV) {
246 if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
247 pass_to_tx(req_seq, f);
248 if (remote_busy() && unacked_frames_ > 0) {
249 start_retrans_timer();
250 }
251 remote_busy_ = false;
252 send_pending_i_frames();
253 } else if (f == Final::POLL_RESPONSE && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
254 remote_busy_ = false;
255 pass_to_tx(req_seq, f);
256 if (!rej_actioned_) {
257 retransmit_i_frames(req_seq, p);
258 } else {
259 rej_actioned_ = false;
260 }
261 send_pending_i_frames();
262 } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
263 pass_to_tx(req_seq, f);
264 send_i_or_rr_or_rnr(Final::POLL_RESPONSE);
265 } else if (with_invalid_req_seq(req_seq)) {
266 CloseChannel();
267 }
268 } else if (rx_state_ == RxState::REJ_SENT) {
269 if (f == Final::POLL_RESPONSE && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
270 remote_busy_ = false;
271 pass_to_tx(req_seq, f);
272 if (!rej_actioned_) {
273 retransmit_i_frames(req_seq, p);
274 } else {
275 rej_actioned_ = false;
276 }
277 send_pending_i_frames();
278 } else if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
279 pass_to_tx(req_seq, f);
280 if (remote_busy() and unacked_frames_ > 0) {
281 start_retrans_timer();
282 }
283 remote_busy_ = false;
284 send_ack(Final::NOT_SET);
285 } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
286 pass_to_tx(req_seq, f);
287 if (remote_busy() and unacked_frames_ > 0) {
288 start_retrans_timer();
289 }
290 remote_busy_ = false;
291 send_rr(Final::POLL_RESPONSE);
292 } else if (with_invalid_req_seq(req_seq)) {
293 CloseChannel();
294 }
295 } else if (rx_state_ == RxState::SREJ_SENT) {
296 // SREJ NOT SUPPORTED
297 }
298 }
299
300 void recv_rej(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
301 if (rx_state_ == RxState::RECV) {
302 if (f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) &&
303 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
304 remote_busy_ = false;
305 pass_to_tx(req_seq, f);
306 retransmit_i_frames(req_seq, p);
307 send_pending_i_frames();
308 if (p_bit_outstanding()) {
309 rej_actioned_ = true;
310 }
311 } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) &&
312 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
313 remote_busy_ = false;
314 pass_to_tx(req_seq, f);
315 if (!rej_actioned_) {
316 retransmit_i_frames(req_seq, p);
317 } else {
318 rej_actioned_ = false;
319 }
320 send_pending_i_frames();
321 } else if (with_valid_req_seq_retrans(req_seq) && !retry_i_frames_less_than_max_transmit(req_seq)) {
322 CloseChannel();
323 } else if (with_invalid_req_seq_retrans(req_seq)) {
324 CloseChannel();
325 }
326 } else if (rx_state_ == RxState::REJ_SENT) {
327 if (f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) &&
328 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
329 remote_busy_ = false;
330 pass_to_tx(req_seq, f);
331 retransmit_i_frames(req_seq, p);
332 send_pending_i_frames();
333 if (p_bit_outstanding()) {
334 rej_actioned_ = true;
335 }
336 } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) &&
337 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
338 remote_busy_ = false;
339 pass_to_tx(req_seq, f);
340 if (!rej_actioned_) {
341 retransmit_i_frames(req_seq, p);
342 } else {
343 rej_actioned_ = false;
344 }
345 send_pending_i_frames();
346 } else if (with_valid_req_seq_retrans(req_seq) && !retry_i_frames_less_than_max_transmit(req_seq)) {
347 CloseChannel();
348 } else if (with_invalid_req_seq_retrans(req_seq)) {
349 CloseChannel();
350 }
351 } else if (rx_state_ == RxState::SREJ_SENT) {
352 // SREJ NOT SUPPORTED
353 }
354 }
355
356 void recv_rnr(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
357 if (rx_state_ == RxState::RECV) {
358 if (p == Poll::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
359 remote_busy_ = true;
360 pass_to_tx(req_seq, f);
361 stop_retrans_timer();
362 } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
363 remote_busy_ = true;
364 pass_to_tx(req_seq, f);
365 stop_retrans_timer();
366 send_rr_or_rnr(Poll::NOT_SET, Final::POLL_RESPONSE);
367 } else if (with_invalid_req_seq_retrans(req_seq)) {
368 CloseChannel();
369 }
370 } else if (rx_state_ == RxState::REJ_SENT) {
371 if (p == Poll::NOT_SET && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
372 remote_busy_ = true;
373 pass_to_tx(req_seq, f);
374 send_rr(Final::POLL_RESPONSE);
375 } else if (p == Poll::POLL && with_valid_req_seq(req_seq) && with_valid_f_bit(f)) {
376 remote_busy_ = true;
377 pass_to_tx(req_seq, f);
378 send_rr(Final::NOT_SET);
379 } else if (with_invalid_req_seq_retrans(req_seq)) {
380 CloseChannel();
381 }
382 } else if (rx_state_ == RxState::SREJ_SENT) {
383 // SREJ NOT SUPPORTED
384 }
385 }
386
387 void recv_srej(uint8_t req_seq, Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
388 if (rx_state_ == RxState::RECV) {
389 if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) &&
390 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
391 remote_busy_ = false;
392 pass_to_tx_f_bit(f);
393 retransmit_requested_i_frame(req_seq, p);
394 if (p_bit_outstanding()) {
395 srej_actioned_ = true;
396 srej_save_req_seq_ = req_seq;
397 }
398 } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) &&
399 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
400 remote_busy_ = false;
401 pass_to_tx_f_bit(f);
402 if (srej_actioned_ && srej_save_req_seq_ == req_seq) {
403 srej_actioned_ = false;
404 } else {
405 retransmit_requested_i_frame(req_seq, p);
406 }
407 } else if (p == Poll::POLL && with_valid_req_seq_retrans(req_seq) &&
408 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
409 remote_busy_ = false;
410 pass_to_tx(req_seq, f);
411 retransmit_requested_i_frame(req_seq, p);
412 if (p_bit_outstanding()) {
413 srej_actioned_ = true;
414 srej_save_req_seq_ = req_seq;
415 }
416 } else if (with_valid_req_seq_retrans(req_seq) && !retry_i_frames_less_than_max_transmit(req_seq)) {
417 CloseChannel();
418 } else if (with_invalid_req_seq_retrans(req_seq)) {
419 CloseChannel();
420 }
421 } else if (rx_state_ == RxState::REJ_SENT) {
422 if (p == Poll::NOT_SET && f == Final::NOT_SET && with_valid_req_seq_retrans(req_seq) &&
423 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
424 remote_busy_ = false;
425 pass_to_tx_f_bit(f);
426 retransmit_requested_i_frame(req_seq, p);
427 if (p_bit_outstanding()) {
428 srej_actioned_ = true;
429 srej_save_req_seq_ = req_seq;
430 }
431 } else if (f == Final::POLL_RESPONSE && with_valid_req_seq_retrans(req_seq) &&
432 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
433 remote_busy_ = false;
434 pass_to_tx_f_bit(f);
435 if (srej_actioned_ && srej_save_req_seq_ == req_seq) {
436 srej_actioned_ = false;
437 } else {
438 retransmit_requested_i_frame(req_seq, p);
439 }
440 } else if (p == Poll::POLL && with_valid_req_seq_retrans(req_seq) &&
441 retry_i_frames_less_than_max_transmit(req_seq) && with_valid_f_bit(f)) {
442 remote_busy_ = false;
443 pass_to_tx(req_seq, f);
444 retransmit_requested_i_frame(req_seq, p);
445 send_pending_i_frames();
446 if (p_bit_outstanding()) {
447 srej_actioned_ = true;
448 srej_save_req_seq_ = req_seq;
449 }
450 } else if (with_valid_req_seq_retrans(req_seq) && !retry_i_frames_less_than_max_transmit(req_seq)) {
451 CloseChannel();
452 } else if (with_invalid_req_seq_retrans(req_seq)) {
453 CloseChannel();
454 }
455 } else if (rx_state_ == RxState::SREJ_SENT) {
456 // SREJ NOT SUPPORTED
457 }
458 }
459
460 // Conditions (@see 8.6.5.5)
461 bool remote_busy() {
462 return remote_busy_;
463 }
464
465 bool local_busy() {
466 return local_busy_;
467 }
468
469 bool rem_window_not_full() {
470 return unacked_frames_ < controller_->remote_tx_window_;
471 }
472
473 bool rem_window_full() {
474 return unacked_frames_ == controller_->remote_tx_window_;
475 }
476
477 bool rnr_sent() {
478 return rnr_sent_;
479 }
480
481 bool retry_i_frames_less_than_max_transmit(uint8_t req_seq) {
482 return retry_i_frames_[req_seq] < controller_->local_max_transmit_;
483 }
484
485 bool retry_count_less_than_max_transmit() {
486 return retry_count_ < controller_->local_max_transmit_;
487 }
488
489 bool with_expected_tx_seq(uint8_t tx_seq) {
490 return tx_seq == expected_tx_seq_;
491 }
492
493 bool with_valid_req_seq(uint8_t req_seq) {
Hansong Zhangba616242019-11-20 21:30:39 -0800494 return expected_ack_seq_ <= req_seq && req_seq <= next_tx_seq_;
Hansong Zhang65941942019-11-16 23:48:30 -0800495 }
496
497 bool with_valid_req_seq_retrans(uint8_t req_seq) {
Hansong Zhangba616242019-11-20 21:30:39 -0800498 return expected_ack_seq_ <= req_seq && req_seq <= next_tx_seq_;
Hansong Zhang65941942019-11-16 23:48:30 -0800499 }
500
501 bool with_valid_f_bit(Final f) {
502 return f == Final::NOT_SET || tx_state_ == TxState::WAIT_F;
503 }
504
505 bool with_unexpected_tx_seq(uint8_t tx_seq) {
506 return tx_seq > expected_tx_seq_ && tx_seq <= expected_tx_seq_ + controller_->local_tx_window_;
507 }
508
509 bool with_duplicate_tx_seq(uint8_t tx_seq) {
510 return tx_seq < expected_tx_seq_ && tx_seq >= expected_tx_seq_ - controller_->local_tx_window_;
511 }
512
513 bool with_invalid_tx_seq(uint8_t tx_seq) {
514 return tx_seq < expected_tx_seq_ - controller_->local_tx_window_ ||
515 tx_seq > expected_tx_seq_ + controller_->local_tx_window_;
516 }
517
518 bool with_invalid_req_seq(uint8_t req_seq) {
519 return req_seq < expected_ack_seq_ || req_seq >= next_tx_seq_;
520 }
521
522 bool with_invalid_req_seq_retrans(uint8_t req_seq) {
523 return req_seq < expected_ack_seq_ || req_seq >= next_tx_seq_;
524 }
525
526 bool not_with_expected_tx_seq(uint8_t tx_seq) {
527 return !with_invalid_tx_seq(tx_seq) && !with_expected_tx_seq(tx_seq);
528 }
529
530 bool with_expected_tx_seq_srej() {
531 // We don't support sending SREJ
532 return false;
533 }
534
535 bool send_req_is_true() {
536 // We don't support sending SREJ
537 return false;
538 }
539
540 bool srej_list_is_one() {
541 // We don't support sending SREJ
542 return false;
543 }
544
545 bool with_unexpected_tx_seq_srej() {
546 // We don't support sending SREJ
547 return false;
548 }
549
550 bool with_duplicate_tx_seq_srej() {
551 // We don't support sending SREJ
552 return false;
553 }
554
555 // Actions (@see 8.6.5.6)
556
Hansong Zhanga6312532019-11-19 14:01:36 -0800557 void _send_i_frame(SegmentationAndReassembly sar, std::unique_ptr<CopyablePacketBuilder> segment, uint8_t req_seq,
558 uint8_t tx_seq, uint16_t sdu_size = 0, Final f = Final::NOT_SET) {
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800559 std::unique_ptr<packet::BasePacketBuilder> builder;
Hansong Zhanga6312532019-11-19 14:01:36 -0800560 if (sar == SegmentationAndReassembly::START) {
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800561 if (controller_->fcs_enabled_) {
562 builder = EnhancedInformationStartFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq,
563 sdu_size, std::move(segment));
564 } else {
565 builder = EnhancedInformationStartFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sdu_size,
566 std::move(segment));
567 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800568 } else {
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800569 if (controller_->fcs_enabled_) {
570 builder = EnhancedInformationFrameWithFcsBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar,
571 std::move(segment));
572 } else {
573 builder = EnhancedInformationFrameBuilder::Create(controller_->remote_cid_, tx_seq, f, req_seq, sar,
574 std::move(segment));
575 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800576 }
Hansong Zhang65941942019-11-16 23:48:30 -0800577 controller_->send_pdu(std::move(builder));
578 }
579
Hansong Zhanga6312532019-11-19 14:01:36 -0800580 void send_data(SegmentationAndReassembly sar, uint16_t sdu_size, std::unique_ptr<packet::RawBuilder> segment,
Hansong Zhang65941942019-11-16 23:48:30 -0800581 Final f = Final::NOT_SET) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800582 std::shared_ptr<packet::RawBuilder> shared_segment(segment.release());
Hansong Zhang65941942019-11-16 23:48:30 -0800583 unacked_list_.emplace(std::piecewise_construct, std::forward_as_tuple(next_tx_seq_),
Hansong Zhanga6312532019-11-19 14:01:36 -0800584 std::forward_as_tuple(sar, sdu_size, shared_segment));
585
586 std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
587 std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(next_tx_seq_)->second));
588 _send_i_frame(sar, std::move(copyable_packet_builder), buffer_seq_, next_tx_seq_, sdu_size, f);
Hansong Zhang65941942019-11-16 23:48:30 -0800589 unacked_frames_++;
590 frames_sent_++;
591 retry_i_frames_[next_tx_seq_] = 1;
592 next_tx_seq_ = (next_tx_seq_ + 1) % kMaxTxWin;
593 start_retrans_timer();
594 }
595
Hansong Zhanga6312532019-11-19 14:01:36 -0800596 void pend_data(SegmentationAndReassembly sar, uint16_t sdu_size, std::unique_ptr<packet::RawBuilder> data) {
597 pending_frames_.emplace(std::make_tuple(sar, sdu_size, std::move(data)));
Hansong Zhang65941942019-11-16 23:48:30 -0800598 }
599
600 void process_req_seq(uint8_t req_seq) {
601 for (int i = expected_ack_seq_; i < req_seq; i++) {
602 unacked_list_.erase(i);
603 retry_i_frames_[i] = 0;
604 }
605 unacked_frames_ -= ((req_seq - expected_ack_seq_) + kMaxTxWin) % kMaxTxWin;
606 if (unacked_frames_ == 0) {
607 stop_retrans_timer();
608 }
609 }
610
611 void _send_s_frame(SupervisoryFunction s, uint8_t req_seq, Poll p, Final f) {
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800612 std::unique_ptr<packet::BasePacketBuilder> builder;
613 if (controller_->fcs_enabled_) {
614 builder = EnhancedSupervisoryFrameWithFcsBuilder::Create(controller_->remote_cid_, s, p, f, req_seq);
615 } else {
616 builder = EnhancedSupervisoryFrameBuilder::Create(controller_->remote_cid_, s, p, f, req_seq);
617 }
Hansong Zhang65941942019-11-16 23:48:30 -0800618 controller_->send_pdu(std::move(builder));
619 }
620
621 void send_rr(Poll p) {
622 _send_s_frame(SupervisoryFunction::RECEIVER_READY, expected_tx_seq_, p, Final::NOT_SET);
623 }
624
625 void send_rr(Final f) {
626 _send_s_frame(SupervisoryFunction::RECEIVER_READY, expected_tx_seq_, Poll::NOT_SET, f);
627 }
628
629 void send_rnr(Poll p) {
630 _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, expected_tx_seq_, p, Final::NOT_SET);
631 }
632
633 void send_rnr(Final f) {
634 _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, expected_tx_seq_, Poll::NOT_SET, f);
635 }
636
637 void send_rej(Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
638 _send_s_frame(SupervisoryFunction::REJECT, expected_tx_seq_, p, f);
639 }
640
641 void send_rr_or_rnr(Poll p = Poll::NOT_SET, Final f = Final::NOT_SET) {
642 if (local_busy()) {
643 _send_s_frame(SupervisoryFunction::RECEIVER_NOT_READY, buffer_seq_, p, f);
644 } else {
645 _send_s_frame(SupervisoryFunction::RECEIVER_READY, buffer_seq_, p, f);
646 }
647 }
648
649 void send_i_or_rr_or_rnr(Final f = Final::POLL_RESPONSE) {
650 auto frames_sent = 0;
651 if (local_busy()) {
652 send_rnr(Final::POLL_RESPONSE);
653 }
654 if (remote_busy() && unacked_frames_ > 0) {
655 start_retrans_timer();
656 }
657 remote_busy_ = false;
658 send_pending_i_frames(f); // TODO: Only first has f = 1, other f = 0. Also increase frames_sent
659 if (!local_busy() && frames_sent == 0) {
660 send_rr(Final::POLL_RESPONSE);
661 }
662 }
663
664 void send_srej() {
665 // Sending SREJ is not supported
666 }
667
668 void start_retrans_timer() {
669 retrans_timer_.Schedule(common::BindOnce(&impl::retrans_timer_expires, common::Unretained(this)),
670 std::chrono::milliseconds(controller_->local_retransmit_timeout_ms_));
671 }
672
673 void start_monitor_timer() {
674 monitor_timer_.Schedule(common::BindOnce(&impl::monitor_timer_expires, common::Unretained(this)),
675 std::chrono::milliseconds(controller_->local_monitor_timeout_ms_));
676 }
677
678 void pass_to_tx(uint8_t req_seq, Final f) {
679 recv_req_seq_and_f_bit(req_seq, f);
680 }
681
682 void pass_to_tx_f_bit(Final f) {
683 recv_f_bit(f);
684 }
685
Hansong Zhang2392dff2019-11-22 11:14:49 -0800686 void data_indication(SegmentationAndReassembly sar, uint16_t sdu_size, const packet::PacketView<true>& segment) {
687 controller_->stage_for_reassembly(sar, sdu_size, segment);
Hansong Zhang65941942019-11-16 23:48:30 -0800688 buffer_seq_ = (buffer_seq_ + 1) % kMaxTxWin;
689 }
690
691 void increment_expected_tx_seq() {
692 expected_tx_seq_ = (expected_tx_seq_ + 1) % kMaxTxWin;
693 }
694
695 void stop_retrans_timer() {
696 retrans_timer_.Cancel();
697 }
698
699 void stop_monitor_timer() {
700 monitor_timer_.Cancel();
701 }
702
703 void send_ack(Final f = Final::NOT_SET) {
704 if (local_busy()) {
705 send_rnr(f);
706 } else if (!remote_busy() && /* pending i frames exist */ rem_window_not_full()) {
707 send_pending_i_frames(f);
708 } else {
709 send_rr(f);
710 }
711 }
712
713 void init_srej() {
714 // We don't support sending SREJ
715 }
716
717 void save_i_frame_srej() {
718 // We don't support sending SREJ
719 }
720
721 void store_or_ignore() {
722 // We choose to ignore. We don't support local busy so far.
723 }
724
725 bool p_bit_outstanding() {
726 return tx_state_ == TxState::WAIT_F;
727 }
728
729 void retransmit_i_frames(uint8_t req_seq, Poll p = Poll::NOT_SET) {
730 uint8_t i = req_seq;
731 Final f = (p == Poll::NOT_SET ? Final::NOT_SET : Final::POLL_RESPONSE);
732 while (unacked_list_.find(i) == unacked_list_.end()) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800733 std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
734 std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(i)->second));
735 _send_i_frame(std::get<0>(unacked_list_.find(i)->second), std::move(copyable_packet_builder), buffer_seq_, i,
736 std::get<1>(unacked_list_.find(i)->second), f);
Hansong Zhang65941942019-11-16 23:48:30 -0800737 retry_i_frames_[i]++;
738 if (retry_i_frames_[i] == controller_->local_max_transmit_) {
739 CloseChannel();
740 }
741 frames_sent_++;
742 f = Final::NOT_SET;
743 }
744 start_retrans_timer();
745 }
746
747 void retransmit_requested_i_frame(uint8_t req_seq, Poll p) {
748 Final f = p == Poll::POLL ? Final::POLL_RESPONSE : Final::NOT_SET;
749 if (unacked_list_.find(req_seq) == unacked_list_.end()) {
750 LOG_ERROR("Received invalid SREJ");
751 return;
752 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800753 std::unique_ptr<CopyablePacketBuilder> copyable_packet_builder =
754 std::make_unique<CopyablePacketBuilder>(std::get<2>(unacked_list_.find(req_seq)->second));
755 _send_i_frame(std::get<0>(unacked_list_.find(req_seq)->second), std::move(copyable_packet_builder), buffer_seq_,
756 req_seq, std::get<1>(unacked_list_.find(req_seq)->second), f);
Hansong Zhang65941942019-11-16 23:48:30 -0800757 retry_i_frames_[req_seq]++;
758 start_retrans_timer();
759 }
760
761 void send_pending_i_frames(Final f = Final::NOT_SET) {
762 if (p_bit_outstanding()) {
763 return;
764 }
765 while (rem_window_not_full() && !pending_frames_.empty()) {
766 auto& frame = pending_frames_.front();
Hansong Zhanga6312532019-11-19 14:01:36 -0800767 send_data(std::get<0>(frame), std::get<1>(frame), std::move(std::get<2>(frame)), f);
Hansong Zhang65941942019-11-16 23:48:30 -0800768 pending_frames_.pop();
769 f = Final::NOT_SET;
770 }
771 }
772
773 void CloseChannel() {
Hansong Zhang98b5baa2019-11-26 10:54:07 -0800774 controller_->close_channel();
Hansong Zhang65941942019-11-16 23:48:30 -0800775 }
776
777 void pop_srej_list() {
778 // We don't support sending SREJ
779 }
780
781 void data_indication_srej() {
782 // We don't support sending SREJ
783 }
784};
785
786// Segmentation is handled here
Hansong Zhangb0960762019-11-14 17:57:10 -0800787void ErtmController::OnSdu(std::unique_ptr<packet::BasePacketBuilder> sdu) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800788 auto sdu_size = sdu->size();
Hansong Zhang65941942019-11-16 23:48:30 -0800789 std::vector<std::unique_ptr<packet::RawBuilder>> segments;
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800790 packet::FragmentingInserter fragmenting_inserter(size_each_packet_, std::back_insert_iterator(segments));
Hansong Zhang65941942019-11-16 23:48:30 -0800791 sdu->Serialize(fragmenting_inserter);
Hansong Zhanga6312532019-11-19 14:01:36 -0800792 fragmenting_inserter.finalize();
Hansong Zhang65941942019-11-16 23:48:30 -0800793 if (segments.size() == 1) {
Hansong Zhanga6312532019-11-19 14:01:36 -0800794 pimpl_->data_request(SegmentationAndReassembly::UNSEGMENTED, std::move(segments[0]));
Hansong Zhang65941942019-11-16 23:48:30 -0800795 return;
796 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800797 pimpl_->data_request(SegmentationAndReassembly::START, std::move(segments[0]), sdu_size);
798 for (auto i = 1; i < segments.size() - 1; i++) {
799 pimpl_->data_request(SegmentationAndReassembly::CONTINUATION, std::move(segments[i]));
Hansong Zhang65941942019-11-16 23:48:30 -0800800 }
Hansong Zhanga6312532019-11-19 14:01:36 -0800801 pimpl_->data_request(SegmentationAndReassembly::END, std::move(segments.back()));
Hansong Zhangb0960762019-11-14 17:57:10 -0800802}
803
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800804void ErtmController::OnPdu(packet::PacketView<true> pdu) {
805 if (fcs_enabled_) {
806 on_pdu_fcs(pdu);
807 } else {
808 on_pdu_no_fcs(pdu);
809 }
810}
811
812void ErtmController::on_pdu_no_fcs(const packet::PacketView<true>& pdu) {
813 auto basic_frame_view = BasicFrameView::Create(pdu);
814 if (!basic_frame_view.IsValid()) {
815 return;
816 }
817 auto standard_frame_view = StandardFrameView::Create(basic_frame_view);
Hansong Zhang65941942019-11-16 23:48:30 -0800818 if (!standard_frame_view.IsValid()) {
819 LOG_WARN("Received invalid frame");
820 return;
821 }
822 auto type = standard_frame_view.GetFrameType();
823 if (type == FrameType::I_FRAME) {
824 auto i_frame_view = EnhancedInformationFrameView::Create(standard_frame_view);
825 if (!i_frame_view.IsValid()) {
826 LOG_WARN("Received invalid frame");
827 return;
828 }
Hansong Zhang2392dff2019-11-22 11:14:49 -0800829 Final f = i_frame_view.GetF();
830 uint8_t tx_seq = i_frame_view.GetTxSeq();
831 uint8_t req_seq = i_frame_view.GetReqSeq();
832 auto sar = i_frame_view.GetSar();
833 if (sar == SegmentationAndReassembly::START) {
834 auto i_frame_start_view = EnhancedInformationStartFrameView::Create(i_frame_view);
835 if (!i_frame_start_view.IsValid()) {
836 LOG_WARN("Received invalid I-Frame START");
837 return;
838 }
839 pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, i_frame_start_view.GetL2capSduLength(),
840 i_frame_start_view.GetPayload());
841 } else {
842 pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, 0, i_frame_view.GetPayload());
843 }
Hansong Zhang65941942019-11-16 23:48:30 -0800844 } else if (type == FrameType::S_FRAME) {
845 auto s_frame_view = EnhancedSupervisoryFrameView::Create(standard_frame_view);
846 if (!s_frame_view.IsValid()) {
847 LOG_WARN("Received invalid frame");
848 return;
849 }
850 auto req_seq = s_frame_view.GetReqSeq();
851 auto f = s_frame_view.GetF();
852 auto p = s_frame_view.GetP();
853 switch (s_frame_view.GetS()) {
854 case SupervisoryFunction::RECEIVER_READY:
855 pimpl_->recv_rr(req_seq, p, f);
856 break;
857 case SupervisoryFunction::RECEIVER_NOT_READY:
858 pimpl_->recv_rnr(req_seq, p, f);
859 break;
860 case SupervisoryFunction::REJECT:
861 pimpl_->recv_rej(req_seq, p, f);
862 break;
863 case SupervisoryFunction::SELECT_REJECT:
864 pimpl_->recv_srej(req_seq, p, f);
865 break;
866 }
867 } else {
868 LOG_WARN("Received invalid frame");
869 }
Hansong Zhangb0960762019-11-14 17:57:10 -0800870}
871
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800872void ErtmController::on_pdu_fcs(const packet::PacketView<true>& pdu) {
873 auto basic_frame_view = BasicFrameWithFcsView::Create(pdu);
874 if (!basic_frame_view.IsValid()) {
875 return;
876 }
877 auto standard_frame_view = StandardFrameWithFcsView::Create(basic_frame_view);
878 if (!standard_frame_view.IsValid()) {
879 LOG_WARN("Received invalid frame");
880 return;
881 }
882 auto type = standard_frame_view.GetFrameType();
883 if (type == FrameType::I_FRAME) {
884 auto i_frame_view = EnhancedInformationFrameWithFcsView::Create(standard_frame_view);
885 if (!i_frame_view.IsValid()) {
886 LOG_WARN("Received invalid frame");
887 return;
888 }
Hansong Zhang2392dff2019-11-22 11:14:49 -0800889 Final f = i_frame_view.GetF();
890 uint8_t tx_seq = i_frame_view.GetTxSeq();
891 uint8_t req_seq = i_frame_view.GetReqSeq();
892 auto sar = i_frame_view.GetSar();
893 if (sar == SegmentationAndReassembly::START) {
894 auto i_frame_start_view = EnhancedInformationStartFrameWithFcsView::Create(i_frame_view);
895 if (!i_frame_start_view.IsValid()) {
896 LOG_WARN("Received invalid I-Frame START");
897 return;
898 }
899 pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, i_frame_start_view.GetL2capSduLength(),
900 i_frame_start_view.GetPayload());
901 } else {
902 pimpl_->recv_i_frame(f, tx_seq, req_seq, sar, 0, i_frame_view.GetPayload());
903 }
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800904 } else if (type == FrameType::S_FRAME) {
905 auto s_frame_view = EnhancedSupervisoryFrameWithFcsView::Create(standard_frame_view);
906 if (!s_frame_view.IsValid()) {
907 LOG_WARN("Received invalid frame");
908 return;
909 }
910 auto req_seq = s_frame_view.GetReqSeq();
911 auto f = s_frame_view.GetF();
912 auto p = s_frame_view.GetP();
913 switch (s_frame_view.GetS()) {
914 case SupervisoryFunction::RECEIVER_READY:
915 pimpl_->recv_rr(req_seq, p, f);
916 break;
917 case SupervisoryFunction::RECEIVER_NOT_READY:
918 pimpl_->recv_rnr(req_seq, p, f);
919 break;
920 case SupervisoryFunction::REJECT:
921 pimpl_->recv_rej(req_seq, p, f);
922 break;
923 case SupervisoryFunction::SELECT_REJECT:
924 pimpl_->recv_srej(req_seq, p, f);
925 break;
926 }
927 } else {
928 LOG_WARN("Received invalid frame");
929 }
930}
931
932std::unique_ptr<packet::BasePacketBuilder> ErtmController::GetNextPacket() {
Hansong Zhangb0960762019-11-14 17:57:10 -0800933 auto next = std::move(pdu_queue_.front());
934 pdu_queue_.pop();
935 return next;
936}
937
Hansong Zhang2392dff2019-11-22 11:14:49 -0800938void ErtmController::stage_for_reassembly(SegmentationAndReassembly sar, uint16_t sdu_size,
Hansong Zhang65941942019-11-16 23:48:30 -0800939 const packet::PacketView<kLittleEndian>& payload) {
940 switch (sar) {
941 case SegmentationAndReassembly::UNSEGMENTED:
Hansong Zhang2392dff2019-11-22 11:14:49 -0800942 if (sar_state_ != SegmentationAndReassembly::END) {
943 LOG_WARN("Received invalid SAR");
944 close_channel();
945 return;
946 }
947 // TODO: Enforce MTU
Hansong Zhang65941942019-11-16 23:48:30 -0800948 enqueue_buffer_.Enqueue(std::make_unique<packet::PacketView<kLittleEndian>>(payload), handler_);
949 break;
950 case SegmentationAndReassembly::START:
951 if (sar_state_ != SegmentationAndReassembly::END) {
952 LOG_WARN("Received invalid SAR");
953 close_channel();
954 return;
955 }
Hansong Zhang2392dff2019-11-22 11:14:49 -0800956 // TODO: Enforce MTU
Hansong Zhang65941942019-11-16 23:48:30 -0800957 sar_state_ = SegmentationAndReassembly::START;
958 reassembly_stage_ = payload;
Hansong Zhang2392dff2019-11-22 11:14:49 -0800959 remaining_sdu_continuation_packet_size_ = sdu_size - payload.size();
Hansong Zhang65941942019-11-16 23:48:30 -0800960 break;
961 case SegmentationAndReassembly::CONTINUATION:
962 if (sar_state_ == SegmentationAndReassembly::END) {
963 LOG_WARN("Received invalid SAR");
964 close_channel();
965 return;
966 }
967 reassembly_stage_.AppendPacketView(payload);
Hansong Zhang2392dff2019-11-22 11:14:49 -0800968 remaining_sdu_continuation_packet_size_ -= payload.size();
Hansong Zhang65941942019-11-16 23:48:30 -0800969 break;
970 case SegmentationAndReassembly::END:
971 if (sar_state_ == SegmentationAndReassembly::END) {
972 LOG_WARN("Received invalid SAR");
973 close_channel();
974 return;
975 }
Hansong Zhang2392dff2019-11-22 11:14:49 -0800976 sar_state_ = SegmentationAndReassembly::END;
977 remaining_sdu_continuation_packet_size_ -= payload.size();
978 if (remaining_sdu_continuation_packet_size_ != 0) {
979 LOG_WARN("Received invalid END I-Frame");
980 reassembly_stage_ = PacketViewForReassembly(std::make_shared<std::vector<uint8_t>>());
981 remaining_sdu_continuation_packet_size_ = 0;
982 close_channel();
983 return;
984 }
Hansong Zhang65941942019-11-16 23:48:30 -0800985 reassembly_stage_.AppendPacketView(payload);
986 enqueue_buffer_.Enqueue(std::make_unique<packet::PacketView<kLittleEndian>>(reassembly_stage_), handler_);
Hansong Zhang65941942019-11-16 23:48:30 -0800987 break;
988 }
989}
990
Hansong Zhang7394ae72019-11-21 10:57:04 -0800991void ErtmController::EnableFcs(bool enabled) {
992 fcs_enabled_ = enabled;
993}
994
Hansong Zhangd164e1b2019-11-21 15:33:22 -0800995void ErtmController::send_pdu(std::unique_ptr<packet::BasePacketBuilder> pdu) {
Hansong Zhang65941942019-11-16 23:48:30 -0800996 pdu_queue_.emplace(std::move(pdu));
997 scheduler_->OnPacketsReady(cid_, 1);
998}
999
Hansong Zhang7394ae72019-11-21 10:57:04 -08001000void ErtmController::SetRetransmissionAndFlowControlOptions(
1001 const RetransmissionAndFlowControlConfigurationOption& option) {
1002 local_tx_window_ = option.tx_window_size_;
1003 local_max_transmit_ = option.max_transmit_;
1004 local_retransmit_timeout_ms_ = option.retransmission_time_out_;
1005 local_monitor_timeout_ms_ = option.monitor_time_out_;
1006}
1007
Hansong Zhang65941942019-11-16 23:48:30 -08001008void ErtmController::close_channel() {
Hansong Zhang98b5baa2019-11-26 10:54:07 -08001009 link_->SendDisconnectionRequest(cid_, remote_cid_);
Hansong Zhang65941942019-11-16 23:48:30 -08001010}
1011
1012size_t ErtmController::CopyablePacketBuilder::size() const {
1013 return builder_->size();
1014}
1015
1016void ErtmController::CopyablePacketBuilder::Serialize(BitInserter& it) const {
1017 builder_->Serialize(it);
1018}
1019
Hansong Zhangb0960762019-11-14 17:57:10 -08001020} // namespace internal
1021} // namespace l2cap
1022} // namespace bluetooth