• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "pw_bluetooth_sapphire/internal/host/l2cap/bredr_dynamic_channel.h"
16 
17 #include <endian.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_configuration.h"
22 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
23 
24 #pragma clang diagnostic ignored "-Wswitch-enum"
25 
26 namespace bt::l2cap::internal {
27 namespace {
28 
29 ChannelConfiguration::RetransmissionAndFlowControlOption
WriteRfcOutboundTimeouts(ChannelConfiguration::RetransmissionAndFlowControlOption rfc_option)30 WriteRfcOutboundTimeouts(
31     ChannelConfiguration::RetransmissionAndFlowControlOption rfc_option) {
32   rfc_option.set_rtx_timeout(kErtmReceiverReadyPollTimerMsecs);
33   rfc_option.set_monitor_timeout(kErtmMonitorTimerMsecs);
34   return rfc_option;
35 }
36 
37 constexpr uint16_t kBrEdrDynamicChannelCount =
38     kLastACLDynamicChannelId - kFirstDynamicChannelId + 1;
39 
40 const uint8_t kMaxNumBasicConfigRequests = 2;
41 }  // namespace
42 
BrEdrDynamicChannelRegistry(SignalingChannelInterface * sig,DynamicChannelCallback close_cb,ServiceRequestCallback service_request_cb,bool random_channel_ids)43 BrEdrDynamicChannelRegistry::BrEdrDynamicChannelRegistry(
44     SignalingChannelInterface* sig,
45     DynamicChannelCallback close_cb,
46     ServiceRequestCallback service_request_cb,
47     bool random_channel_ids)
48     : DynamicChannelRegistry(kBrEdrDynamicChannelCount,
49                              std::move(close_cb),
50                              std::move(service_request_cb),
51                              random_channel_ids),
52       state_(0u),
53       sig_(sig) {
54   BT_DEBUG_ASSERT(sig_);
55   BrEdrCommandHandler cmd_handler(sig_);
56   cmd_handler.ServeConnectionRequest(
57       fit::bind_member<&BrEdrDynamicChannelRegistry::OnRxConnReq>(this));
58   cmd_handler.ServeConfigurationRequest(
59       fit::bind_member<&BrEdrDynamicChannelRegistry::OnRxConfigReq>(this));
60   cmd_handler.ServeDisconnectionRequest(
61       fit::bind_member<&BrEdrDynamicChannelRegistry::OnRxDisconReq>(this));
62   cmd_handler.ServeInformationRequest(
63       fit::bind_member<&BrEdrDynamicChannelRegistry::OnRxInfoReq>(this));
64   SendInformationRequests();
65 }
66 
MakeOutbound(Psm psm,ChannelId local_cid,ChannelParameters params)67 DynamicChannelPtr BrEdrDynamicChannelRegistry::MakeOutbound(
68     Psm psm, ChannelId local_cid, ChannelParameters params) {
69   return BrEdrDynamicChannel::MakeOutbound(
70       this, sig_, psm, local_cid, params, PeerSupportsERTM());
71 }
72 
MakeInbound(Psm psm,ChannelId local_cid,ChannelId remote_cid,ChannelParameters params)73 DynamicChannelPtr BrEdrDynamicChannelRegistry::MakeInbound(
74     Psm psm,
75     ChannelId local_cid,
76     ChannelId remote_cid,
77     ChannelParameters params) {
78   return BrEdrDynamicChannel::MakeInbound(
79       this, sig_, psm, local_cid, remote_cid, params, PeerSupportsERTM());
80 }
81 
OnRxConnReq(Psm psm,ChannelId remote_cid,BrEdrCommandHandler::ConnectionResponder * responder)82 void BrEdrDynamicChannelRegistry::OnRxConnReq(
83     Psm psm,
84     ChannelId remote_cid,
85     BrEdrCommandHandler::ConnectionResponder* responder) {
86   bt_log(TRACE,
87          "l2cap-bredr",
88          "Got Connection Request for PSM %#.4x from channel %#.4x",
89          psm,
90          remote_cid);
91 
92   if (remote_cid == kInvalidChannelId) {
93     bt_log(DEBUG,
94            "l2cap-bredr",
95            "Invalid source CID; rejecting connection for PSM %#.4x from "
96            "channel %#.4x",
97            psm,
98            remote_cid);
99     responder->Send(kInvalidChannelId,
100                     ConnectionResult::kInvalidSourceCID,
101                     ConnectionStatus::kNoInfoAvailable);
102     return;
103   }
104 
105   if (FindChannelByRemoteId(remote_cid) != nullptr) {
106     bt_log(DEBUG,
107            "l2cap-bredr",
108            "Remote CID already in use; rejecting connection for PSM %#.4x from "
109            "channel %#.4x",
110            psm,
111            remote_cid);
112     responder->Send(kInvalidChannelId,
113                     ConnectionResult::kSourceCIDAlreadyAllocated,
114                     ConnectionStatus::kNoInfoAvailable);
115     return;
116   }
117 
118   ChannelId local_cid = FindAvailableChannelId();
119   if (local_cid == kInvalidChannelId) {
120     bt_log(DEBUG,
121            "l2cap-bredr",
122            "Out of IDs; rejecting connection for PSM %#.4x from channel %#.4x",
123            psm,
124            remote_cid);
125     responder->Send(kInvalidChannelId,
126                     ConnectionResult::kNoResources,
127                     ConnectionStatus::kNoInfoAvailable);
128     return;
129   }
130 
131   auto dyn_chan = RequestService(psm, local_cid, remote_cid);
132   if (!dyn_chan) {
133     bt_log(DEBUG,
134            "l2cap-bredr",
135            "Rejecting connection for unsupported PSM %#.4x from channel %#.4x",
136            psm,
137            remote_cid);
138     responder->Send(kInvalidChannelId,
139                     ConnectionResult::kPsmNotSupported,
140                     ConnectionStatus::kNoInfoAvailable);
141     return;
142   }
143 
144   static_cast<BrEdrDynamicChannel*>(dyn_chan)->CompleteInboundConnection(
145       responder);
146 }
147 
OnRxConfigReq(ChannelId local_cid,uint16_t flags,ChannelConfiguration config,BrEdrCommandHandler::ConfigurationResponder * responder)148 void BrEdrDynamicChannelRegistry::OnRxConfigReq(
149     ChannelId local_cid,
150     uint16_t flags,
151     ChannelConfiguration config,
152     BrEdrCommandHandler::ConfigurationResponder* responder) {
153   auto channel =
154       static_cast<BrEdrDynamicChannel*>(FindChannelByLocalId(local_cid));
155   if (channel == nullptr) {
156     bt_log(WARN,
157            "l2cap-bredr",
158            "ID %#.4x not found for Configuration Request",
159            local_cid);
160     responder->RejectInvalidChannelId();
161     return;
162   }
163 
164   channel->OnRxConfigReq(flags, std::move(config), responder);
165 }
166 
OnRxDisconReq(ChannelId local_cid,ChannelId remote_cid,BrEdrCommandHandler::DisconnectionResponder * responder)167 void BrEdrDynamicChannelRegistry::OnRxDisconReq(
168     ChannelId local_cid,
169     ChannelId remote_cid,
170     BrEdrCommandHandler::DisconnectionResponder* responder) {
171   auto channel =
172       static_cast<BrEdrDynamicChannel*>(FindChannelByLocalId(local_cid));
173   if (channel == nullptr || channel->remote_cid() != remote_cid) {
174     bt_log(WARN,
175            "l2cap-bredr",
176            "ID %#.4x not found for Disconnection Request (remote ID %#.4x)",
177            local_cid,
178            remote_cid);
179     responder->RejectInvalidChannelId();
180     return;
181   }
182 
183   channel->OnRxDisconReq(responder);
184 }
185 
OnRxInfoReq(InformationType type,BrEdrCommandHandler::InformationResponder * responder)186 void BrEdrDynamicChannelRegistry::OnRxInfoReq(
187     InformationType type,
188     BrEdrCommandHandler::InformationResponder* responder) {
189   bt_log(TRACE,
190          "l2cap-bredr",
191          "Got Information Request for type %#.4hx",
192          static_cast<unsigned short>(type));
193 
194   // TODO(fxbug.dev/42175069): The responses here will likely remain hardcoded
195   // magics, but maybe they should live elsewhere.
196   switch (type) {
197     case InformationType::kConnectionlessMTU: {
198       responder->SendNotSupported();
199       break;
200     }
201 
202     case InformationType::kExtendedFeaturesSupported: {
203       const ExtendedFeatures extended_features =
204           kExtendedFeaturesBitFixedChannels | kExtendedFeaturesBitFCSOption |
205           kExtendedFeaturesBitEnhancedRetransmission;
206 
207       // Express support for the Fixed Channel Supported feature
208       responder->SendExtendedFeaturesSupported(extended_features);
209       break;
210     }
211 
212     case InformationType::kFixedChannelsSupported: {
213       const FixedChannelsSupported channels_supported =
214           kFixedChannelsSupportedBitSignaling;
215 
216       // Express support for the ACL-U Signaling Channel (as required)
217       // TODO(fxbug.dev/42175069): Set the bit for SM's fixed channel
218       responder->SendFixedChannelsSupported(channels_supported);
219       break;
220     }
221 
222     default:
223       responder->RejectNotUnderstood();
224       bt_log(DEBUG,
225              "l2cap-bredr",
226              "Rejecting Information Request type %#.4hx",
227              static_cast<unsigned short>(type));
228   }
229 }
230 
OnRxExtendedFeaturesInfoRsp(const BrEdrCommandHandler::InformationResponse & rsp)231 void BrEdrDynamicChannelRegistry::OnRxExtendedFeaturesInfoRsp(
232     const BrEdrCommandHandler::InformationResponse& rsp) {
233   if (rsp.status() == BrEdrCommandHandler::Status::kReject) {
234     bt_log(ERROR,
235            "l2cap-bredr",
236            "Extended Features Information Request rejected, reason %#.4hx, "
237            "disconnecting",
238            static_cast<unsigned short>(rsp.reject_reason()));
239     return;
240   }
241 
242   if (rsp.result() != InformationResult::kSuccess) {
243     bt_log(DEBUG,
244            "l2cap-bredr",
245            "Extended Features Information Response failure result (result: "
246            "%#.4hx)",
247            static_cast<uint16_t>(rsp.result()));
248     // Treat failure result as if feature mask indicated no ERTM support so that
249     // configuration can fall back to basic mode.
250     ForEach([](DynamicChannel* chan) {
251       static_cast<BrEdrDynamicChannel*>(chan)->SetEnhancedRetransmissionSupport(
252           false);
253     });
254     return;
255   }
256 
257   if (rsp.type() != InformationType::kExtendedFeaturesSupported) {
258     bt_log(
259         ERROR,
260         "l2cap-bredr",
261         "Incorrect extended features information response type (type: %#.4hx)",
262         static_cast<unsigned short>(rsp.type()));
263     return;
264   }
265 
266   if ((state_ & kExtendedFeaturesReceived) ||
267       !(state_ & kExtendedFeaturesSent)) {
268     bt_log(ERROR,
269            "l2cap-bredr",
270            "Unexpected extended features information response (state: %#x)",
271            state_);
272     return;
273   }
274 
275   bt_log(
276       TRACE,
277       "l2cap-bredr",
278       "Received Extended Features Information Response (feature mask: %#.4x)",
279       rsp.extended_features());
280 
281   state_ |= kExtendedFeaturesReceived;
282 
283   extended_features_ = rsp.extended_features();
284 
285   // Notify all channels created before extended features received.
286   bool ertm_support =
287       *extended_features_ & kExtendedFeaturesBitEnhancedRetransmission;
288   ForEach([ertm_support](DynamicChannel* chan) {
289     static_cast<BrEdrDynamicChannel*>(chan)->SetEnhancedRetransmissionSupport(
290         ertm_support);
291   });
292 }
293 
SendInformationRequests()294 void BrEdrDynamicChannelRegistry::SendInformationRequests() {
295   if (state_ & kExtendedFeaturesSent) {
296     bt_log(
297         DEBUG, "l2cap-bredr", "Skipping sending info requests, already sent");
298     return;
299   }
300   BrEdrCommandHandler cmd_handler(sig_);
301   auto on_rx_info_rsp = [self = GetWeakPtr(), this](auto& rsp) {
302     if (self.is_alive()) {
303       OnRxExtendedFeaturesInfoRsp(rsp);
304     }
305   };
306   if (!cmd_handler.SendInformationRequest(
307           InformationType::kExtendedFeaturesSupported,
308           std::move(on_rx_info_rsp))) {
309     bt_log(ERROR,
310            "l2cap-bredr",
311            "Failed to send Extended Features Information Request");
312     return;
313   }
314 
315   state_ |= kExtendedFeaturesSent;
316 }
317 
PeerSupportsERTM() const318 std::optional<bool> BrEdrDynamicChannelRegistry::PeerSupportsERTM() const {
319   if (!extended_features_) {
320     return std::nullopt;
321   }
322   return *extended_features_ & kExtendedFeaturesBitEnhancedRetransmission;
323 }
324 
MakeOutbound(DynamicChannelRegistry * registry,SignalingChannelInterface * signaling_channel,Psm psm,ChannelId local_cid,ChannelParameters params,std::optional<bool> peer_supports_ertm)325 BrEdrDynamicChannelPtr BrEdrDynamicChannel::MakeOutbound(
326     DynamicChannelRegistry* registry,
327     SignalingChannelInterface* signaling_channel,
328     Psm psm,
329     ChannelId local_cid,
330     ChannelParameters params,
331     std::optional<bool> peer_supports_ertm) {
332   return std::unique_ptr<BrEdrDynamicChannel>(
333       new BrEdrDynamicChannel(registry,
334                               signaling_channel,
335                               psm,
336                               local_cid,
337                               kInvalidChannelId,
338                               params,
339                               peer_supports_ertm));
340 }
341 
MakeInbound(DynamicChannelRegistry * registry,SignalingChannelInterface * signaling_channel,Psm psm,ChannelId local_cid,ChannelId remote_cid,ChannelParameters params,std::optional<bool> peer_supports_ertm)342 BrEdrDynamicChannelPtr BrEdrDynamicChannel::MakeInbound(
343     DynamicChannelRegistry* registry,
344     SignalingChannelInterface* signaling_channel,
345     Psm psm,
346     ChannelId local_cid,
347     ChannelId remote_cid,
348     ChannelParameters params,
349     std::optional<bool> peer_supports_ertm) {
350   auto channel = std::unique_ptr<BrEdrDynamicChannel>(
351       new BrEdrDynamicChannel(registry,
352                               signaling_channel,
353                               psm,
354                               local_cid,
355                               remote_cid,
356                               params,
357                               peer_supports_ertm));
358   channel->state_ |= kConnRequested;
359   return channel;
360 }
361 
Open(fit::closure open_result_cb)362 void BrEdrDynamicChannel::Open(fit::closure open_result_cb) {
363   open_result_cb_ = std::move(open_result_cb);
364 
365   if (state_ & kConnRequested) {
366     return;
367   }
368 
369   auto on_conn_rsp = [self = weak_self_.GetWeakPtr()](
370                          const BrEdrCommandHandler::ConnectionResponse& rsp) {
371     if (self.is_alive()) {
372       return self->OnRxConnRsp(rsp);
373     }
374     return BrEdrCommandHandler::ResponseHandlerAction::
375         kCompleteOutboundTransaction;
376   };
377 
378   auto on_conn_rsp_timeout = [this, self = weak_self_.GetWeakPtr()] {
379     if (self.is_alive()) {
380       bt_log(WARN,
381              "l2cap-bredr",
382              "Channel %#.4x: Timed out waiting for Connection Response",
383              local_cid());
384       PassOpenError();
385     }
386   };
387 
388   BrEdrCommandHandler cmd_handler(signaling_channel_,
389                                   std::move(on_conn_rsp_timeout));
390   if (!cmd_handler.SendConnectionRequest(
391           psm(), local_cid(), std::move(on_conn_rsp))) {
392     bt_log(ERROR,
393            "l2cap-bredr",
394            "Channel %#.4x: Failed to send Connection Request",
395            local_cid());
396     PassOpenError();
397     return;
398   }
399 
400   bt_log(TRACE,
401          "l2cap-bredr",
402          "Channel %#.4x: Sent Connection Request",
403          local_cid());
404 
405   state_ |= kConnRequested;
406 }
407 
Disconnect(DisconnectDoneCallback done_cb)408 void BrEdrDynamicChannel::Disconnect(DisconnectDoneCallback done_cb) {
409   BT_ASSERT(done_cb);
410   if (!IsConnected()) {
411     done_cb();
412     return;
413   }
414 
415   state_ |= kDisconnected;
416 
417   // Don't send disconnect request if the peer never responded (also can't,
418   // because we don't have their end's ID).
419   if (remote_cid() == kInvalidChannelId) {
420     done_cb();
421     return;
422   }
423 
424   auto on_discon_rsp =
425       [local_cid = local_cid(),
426        remote_cid = remote_cid(),
427        self = weak_self_.GetWeakPtr(),
428        done_cb = done_cb.share()](
429           const BrEdrCommandHandler::DisconnectionResponse& rsp) mutable {
430         if (rsp.local_cid() != local_cid || rsp.remote_cid() != remote_cid) {
431           bt_log(WARN,
432                  "l2cap-bredr",
433                  "Channel %#.4x: Got Disconnection Response with ID %#.4x/"
434                  "remote ID %#.4x on channel with remote ID %#.4x",
435                  local_cid,
436                  rsp.local_cid(),
437                  rsp.remote_cid(),
438                  remote_cid);
439         } else {
440           bt_log(TRACE,
441                  "l2cap-bredr",
442                  "Channel %#.4x: Got Disconnection Response",
443                  local_cid);
444         }
445 
446         if (self.is_alive()) {
447           done_cb();
448         }
449       };
450 
451   auto on_discon_rsp_timeout = [local_cid = local_cid(),
452                                 self = weak_self_.GetWeakPtr(),
453                                 done_cb = done_cb.share()]() mutable {
454     bt_log(WARN,
455            "l2cap-bredr",
456            "Channel %#.4x: Timed out waiting for Disconnection Response; "
457            "completing disconnection",
458            local_cid);
459     if (self.is_alive()) {
460       done_cb();
461     }
462   };
463 
464   BrEdrCommandHandler cmd_handler(signaling_channel_,
465                                   std::move(on_discon_rsp_timeout));
466   if (!cmd_handler.SendDisconnectionRequest(
467           remote_cid(), local_cid(), std::move(on_discon_rsp))) {
468     bt_log(WARN,
469            "l2cap-bredr",
470            "Channel %#.4x: Failed to send Disconnection Request",
471            local_cid());
472     done_cb();
473     return;
474   }
475 
476   bt_log(TRACE,
477          "l2cap-bredr",
478          "Channel %#.4x: Sent Disconnection Request",
479          local_cid());
480 }
481 
IsConnected() const482 bool BrEdrDynamicChannel::IsConnected() const {
483   // Remote-initiated channels have remote_cid_ already set.
484   return (state_ & kConnRequested) && (state_ & kConnResponded) &&
485          (remote_cid() != kInvalidChannelId) && !(state_ & kDisconnected);
486 }
487 
IsOpen() const488 bool BrEdrDynamicChannel::IsOpen() const {
489   return IsConnected() && BothConfigsAccepted() &&
490          AcceptedChannelModesAreConsistent();
491 }
492 
info() const493 ChannelInfo BrEdrDynamicChannel::info() const {
494   BT_ASSERT(local_config().retransmission_flow_control_option().has_value());
495   BT_ASSERT(local_config().mtu_option().has_value());
496 
497   const auto max_rx_sdu_size = local_config().mtu_option()->mtu();
498   const auto peer_mtu = remote_config().mtu_option()->mtu();
499   const auto flush_timeout = parameters_.flush_timeout;
500   if (local_config().retransmission_flow_control_option()->mode() ==
501       RetransmissionAndFlowControlMode::kBasic) {
502     const auto max_tx_sdu_size = peer_mtu;
503     return ChannelInfo::MakeBasicMode(
504         max_rx_sdu_size, max_tx_sdu_size, psm(), flush_timeout);
505   }
506   const auto n_frames_in_tx_window =
507       remote_config().retransmission_flow_control_option()->tx_window_size();
508   const auto max_transmissions =
509       remote_config().retransmission_flow_control_option()->max_transmit();
510   const auto max_tx_pdu_payload_size =
511       remote_config().retransmission_flow_control_option()->mps();
512   const auto max_tx_sdu_size = std::min(peer_mtu, max_tx_pdu_payload_size);
513   if (max_tx_pdu_payload_size < peer_mtu) {
514     bt_log(DEBUG,
515            "l2cap-bredr",
516            "Channel %#.4x: reporting MPS of %hu to service to avoid segmenting "
517            "outbound SDUs, "
518            "which would otherwise be %hu according to MTU",
519            local_cid(),
520            max_tx_sdu_size,
521            peer_mtu);
522   }
523   auto info =
524       ChannelInfo::MakeEnhancedRetransmissionMode(max_rx_sdu_size,
525                                                   max_tx_sdu_size,
526                                                   n_frames_in_tx_window,
527                                                   max_transmissions,
528                                                   max_tx_pdu_payload_size,
529                                                   psm(),
530                                                   flush_timeout);
531   return info;
532 }
533 
OnRxConfigReq(uint16_t flags,ChannelConfiguration config,BrEdrCommandHandler::ConfigurationResponder * responder)534 void BrEdrDynamicChannel::OnRxConfigReq(
535     uint16_t flags,
536     ChannelConfiguration config,
537     BrEdrCommandHandler::ConfigurationResponder* responder) {
538   bool continuation = flags & kConfigurationContinuation;
539   bt_log(TRACE,
540          "l2cap-bredr",
541          "Channel %#.4x: Got Configuration Request (C: %d, options: %s)",
542          local_cid(),
543          continuation,
544          bt_str(config));
545 
546   if (!IsConnected()) {
547     bt_log(WARN,
548            "l2cap-bredr",
549            "Channel %#.4x: Unexpected Configuration Request, state %x",
550            local_cid(),
551            state_);
552     return;
553   }
554 
555   // Always add options to accumulator, even if C = 0, for later code
556   // simplicity.
557   if (remote_config_accum_.has_value()) {
558     remote_config_accum_->Merge(std::move(config));
559   } else {
560     // TODO(fxbug.dev/42115983): if channel is being re-configured, merge with
561     // existing configuration
562     remote_config_accum_ = std::move(config);
563   }
564 
565   if (continuation) {
566     // keep responding with success until all options have been received (C flag
567     // is 0)
568     responder->Send(remote_cid(),
569                     kConfigurationContinuation,
570                     ConfigurationResult::kSuccess,
571                     ChannelConfiguration::ConfigurationOptions());
572     bt_log(TRACE,
573            "l2cap-bredr",
574            "Channel %#.4x: Sent Configuration Response (C: 1)",
575            local_cid());
576     return;
577   }
578 
579   auto req_config = std::exchange(remote_config_accum_, std::nullopt).value();
580 
581   const auto req_mode =
582       req_config.retransmission_flow_control_option()
583           ? req_config.retransmission_flow_control_option()->mode()
584           : RetransmissionAndFlowControlMode::kBasic;
585 
586   // Record peer support for ERTM even if they haven't sent a Extended Features
587   // Mask.
588   if (req_mode == RetransmissionAndFlowControlMode::kEnhancedRetransmission) {
589     SetEnhancedRetransmissionSupport(true);
590   }
591 
592   // Set default config options if not already in request.
593   if (!req_config.mtu_option()) {
594     req_config.set_mtu_option(ChannelConfiguration::MtuOption(kDefaultMTU));
595   }
596 
597   if (state_ & kRemoteConfigReceived) {
598     // Disconnect if second configuration request does not contain desired mode.
599     const auto local_mode =
600         local_config_.retransmission_flow_control_option()->mode();
601     if (req_mode != local_mode) {
602       bt_log(TRACE,
603              "l2cap-bredr",
604              "Channel %#.4x: second configuration request doesn't have desired "
605              "mode, sending unacceptable parameters response and disconnecting "
606              "(req mode: %#.2x, desired: %#.2x)",
607              local_cid(),
608              static_cast<uint8_t>(req_mode),
609              static_cast<uint8_t>(local_mode));
610       ChannelConfiguration::ConfigurationOptions options;
611       options.push_back(
612           std::make_unique<
613               ChannelConfiguration::RetransmissionAndFlowControlOption>(
614               *local_config().retransmission_flow_control_option()));
615       responder->Send(remote_cid(),
616                       0x0000,
617                       ConfigurationResult::kUnacceptableParameters,
618                       std::move(options));
619       PassOpenError();
620       return;
621     }
622 
623     bt_log(DEBUG,
624            "l2cap-bredr",
625            "Channel %#.4x: Reconfiguring, state %x",
626            local_cid(),
627            state_);
628   }
629 
630   state_ |= kRemoteConfigReceived;
631 
632   // Reject request if it contains unknown options.
633   // See Core Spec v5.1, Volume 3, Section 4.5: Configuration Options
634   if (!req_config.unknown_options().empty()) {
635     ChannelConfiguration::ConfigurationOptions unknown_options;
636     std::string unknown_string;
637     for (auto& option : req_config.unknown_options()) {
638       unknown_options.push_back(
639           std::make_unique<ChannelConfiguration::UnknownOption>(option));
640       unknown_string += std::string(" ") + option.ToString();
641     }
642 
643     bt_log(DEBUG,
644            "l2cap-bredr",
645            "Channel %#.4x: config request contained unknown options (options: "
646            "%s)\n",
647            local_cid(),
648            unknown_string.c_str());
649 
650     responder->Send(remote_cid(),
651                     0x0000,
652                     ConfigurationResult::kUnknownOptions,
653                     std::move(unknown_options));
654     return;
655   }
656 
657   auto unacceptable_config = CheckForUnacceptableConfigReqOptions(req_config);
658   auto unacceptable_options = unacceptable_config.Options();
659   if (!unacceptable_options.empty()) {
660     responder->Send(remote_cid(),
661                     0x0000,
662                     ConfigurationResult::kUnacceptableParameters,
663                     std::move(unacceptable_options));
664     bt_log(TRACE,
665            "l2cap-bredr",
666            "Channel %#.4x: Sent unacceptable parameters configuration response "
667            "(options: %s)",
668            local_cid(),
669            bt_str(unacceptable_config));
670     return;
671   }
672 
673   // TODO(fxbug.dev/42057179): Defer accepting config req using a Pending
674   // response
675   state_ |= kRemoteConfigAccepted;
676 
677   ChannelConfiguration response_config;
678 
679   // Successful response should include actual MTU local device will use. This
680   // must be min(received MTU, local outgoing MTU capability). Currently, we
681   // accept any MTU.
682   // TODO(fxbug.dev/42117452): determine the upper bound of what we are actually
683   // capable of sending
684   uint16_t actual_mtu = req_config.mtu_option()->mtu();
685   response_config.set_mtu_option(ChannelConfiguration::MtuOption(actual_mtu));
686   req_config.set_mtu_option(response_config.mtu_option());
687 
688   if (req_mode == RetransmissionAndFlowControlMode::kEnhancedRetransmission) {
689     auto outbound_rfc_option = WriteRfcOutboundTimeouts(
690         req_config.retransmission_flow_control_option().value());
691     response_config.set_retransmission_flow_control_option(
692         std::move(outbound_rfc_option));
693   } else {
694     response_config.set_retransmission_flow_control_option(
695         req_config.retransmission_flow_control_option());
696   }
697 
698   responder->Send(remote_cid(),
699                   0x0000,
700                   ConfigurationResult::kSuccess,
701                   response_config.Options());
702 
703   bt_log(TRACE,
704          "l2cap-bredr",
705          "Channel %#.4x: Sent Configuration Response (options: %s)",
706          local_cid(),
707          bt_str(response_config));
708 
709   // Save accepted options.
710   remote_config_.Merge(std::move(req_config));
711 
712   if (!remote_config_.retransmission_flow_control_option()) {
713     remote_config_.set_retransmission_flow_control_option(
714         ChannelConfiguration::RetransmissionAndFlowControlOption::
715             MakeBasicMode());
716   }
717 
718   if (BothConfigsAccepted() && !AcceptedChannelModesAreConsistent()) {
719     bt_log(WARN,
720            "l2cap-bredr",
721            "Channel %#.4x: inconsistent channel mode negotiation (local mode: "
722            "%#.2x, remote "
723            "mode: %#.2x); falling back to Basic Mode",
724            local_cid(),
725            static_cast<uint8_t>(
726                local_config().retransmission_flow_control_option()->mode()),
727            static_cast<uint8_t>(
728                remote_config().retransmission_flow_control_option()->mode()));
729 
730     // The most applicable guidance for the case where the peer send conflicting
731     // modes is in Core Spec v5.0 Vol 3, Part A, Sec 5.4: "If the mode proposed
732     // by the remote device has a higher precedence (according to the state 1
733     // precedence) then the algorithm will operate such that creation of a
734     // channel using the remote device's mode has higher priority than
735     // disconnecting the channel."
736     //
737     // Note also that, "In state 1, Basic L2CAP mode has the highest precedence
738     // and shall take precedence over Enhanced Retransmission mode..."
739     //
740     // So, if we are to continue the connection, it makes the most sense to use
741     // Basic Mode.
742     local_config_.set_retransmission_flow_control_option(
743         ChannelConfiguration::RetransmissionAndFlowControlOption::
744             MakeBasicMode());
745     remote_config_.set_retransmission_flow_control_option(
746         ChannelConfiguration::RetransmissionAndFlowControlOption::
747             MakeBasicMode());
748     PassOpenResult();
749     return;
750   }
751 
752   if (IsOpen()) {
753     set_opened();
754     PassOpenResult();
755   }
756 }
757 
OnRxDisconReq(BrEdrCommandHandler::DisconnectionResponder * responder)758 void BrEdrDynamicChannel::OnRxDisconReq(
759     BrEdrCommandHandler::DisconnectionResponder* responder) {
760   bt_log(TRACE,
761          "l2cap-bredr",
762          "Channel %#.4x: Got Disconnection Request",
763          local_cid());
764 
765   // Unconnected channels only exist if they are waiting for a Connection
766   // Response from the peer or are disconnected yet undestroyed for some reason.
767   // Getting a Disconnection Request implies some error condition or misbehavior
768   // but the reaction should still be to terminate this channel.
769   if (!IsConnected()) {
770     bt_log(WARN,
771            "l2cap-bredr",
772            "Channel %#.4x: Unexpected Disconnection Request",
773            local_cid());
774   }
775 
776   state_ |= kDisconnected;
777   responder->Send();
778   if (opened()) {
779     OnDisconnected();
780   } else {
781     PassOpenError();
782   }
783 }
784 
CompleteInboundConnection(BrEdrCommandHandler::ConnectionResponder * responder)785 void BrEdrDynamicChannel::CompleteInboundConnection(
786     BrEdrCommandHandler::ConnectionResponder* responder) {
787   bt_log(DEBUG,
788          "l2cap-bredr",
789          "Channel %#.4x: connected for PSM %#.4x from remote channel %#.4x",
790          local_cid(),
791          psm(),
792          remote_cid());
793 
794   responder->Send(local_cid(),
795                   ConnectionResult::kSuccess,
796                   ConnectionStatus::kNoInfoAvailable);
797   bt_log(TRACE,
798          "l2cap-bredr",
799          "Channel %#.4x: Sent Connection Response",
800          local_cid());
801   state_ |= kConnResponded;
802 
803   UpdateLocalConfigForErtm();
804   if (!IsWaitingForPeerErtmSupport()) {
805     TrySendLocalConfig();
806   }
807 }
808 
BrEdrDynamicChannel(DynamicChannelRegistry * registry,SignalingChannelInterface * signaling_channel,Psm psm,ChannelId local_cid,ChannelId remote_cid,ChannelParameters params,std::optional<bool> peer_supports_ertm)809 BrEdrDynamicChannel::BrEdrDynamicChannel(
810     DynamicChannelRegistry* registry,
811     SignalingChannelInterface* signaling_channel,
812     Psm psm,
813     ChannelId local_cid,
814     ChannelId remote_cid,
815     ChannelParameters params,
816     std::optional<bool> peer_supports_ertm)
817     : DynamicChannel(registry, psm, local_cid, remote_cid),
818       signaling_channel_(signaling_channel),
819       parameters_(params),
820       state_(0u),
821       peer_supports_ertm_(peer_supports_ertm),
822       weak_self_(this) {
823   BT_DEBUG_ASSERT(signaling_channel_);
824   BT_DEBUG_ASSERT(local_cid != kInvalidChannelId);
825 
826   UpdateLocalConfigForErtm();
827 }
828 
PassOpenResult()829 void BrEdrDynamicChannel::PassOpenResult() {
830   if (open_result_cb_) {
831     // Guard against use-after-free if this object's owner destroys it while
832     // running |open_result_cb_|.
833     auto cb = std::move(open_result_cb_);
834     cb();
835   }
836 }
837 
838 // This only checks that the channel had failed to open before passing to the
839 // client. The channel may still be connected, in case it's useful to perform
840 // channel configuration at this point.
PassOpenError()841 void BrEdrDynamicChannel::PassOpenError() {
842   BT_ASSERT(!IsOpen());
843   PassOpenResult();
844 }
845 
UpdateLocalConfigForErtm()846 void BrEdrDynamicChannel::UpdateLocalConfigForErtm() {
847   local_config_.set_mtu_option(
848       ChannelConfiguration::MtuOption(CalculateLocalMtu()));
849 
850   if (ShouldRequestEnhancedRetransmission()) {
851     // Core Spec v5.0 Vol 3, Part A, Sec 8.6.2.1 "When configuring a channel
852     // over an ACL-U logical link the values sent in a Configuration Request
853     // packet for Retransmission timeout and Monitor timeout shall be 0."
854     auto option = ChannelConfiguration::RetransmissionAndFlowControlOption::
855         MakeEnhancedRetransmissionMode(
856             /*tx_window_size=*/kErtmMaxUnackedInboundFrames,
857             /*max_transmit=*/kErtmMaxInboundRetransmissions,
858             /*rtx_timeout=*/0,
859             /*monitor_timeout=*/0,
860             /*mps=*/kMaxInboundPduPayloadSize);
861     local_config_.set_retransmission_flow_control_option(option);
862   } else {
863     local_config_.set_retransmission_flow_control_option(
864         ChannelConfiguration::RetransmissionAndFlowControlOption::
865             MakeBasicMode());
866   }
867 }
868 
CalculateLocalMtu() const869 uint16_t BrEdrDynamicChannel::CalculateLocalMtu() const {
870   const bool request_ertm = ShouldRequestEnhancedRetransmission();
871   const auto kDefaultPreferredMtu =
872       request_ertm ? kMaxInboundPduPayloadSize : kMaxMTU;
873   uint16_t mtu = parameters_.max_rx_sdu_size.value_or(kDefaultPreferredMtu);
874   if (mtu < kMinACLMTU) {
875     bt_log(WARN,
876            "l2cap-bredr",
877            "Channel %#.4x: preferred MTU channel parameter below minimum "
878            "allowed, using minimum "
879            "instead (mtu param: %#x, min mtu: %#x)",
880            local_cid(),
881            mtu,
882            kMinACLMTU);
883     mtu = kMinACLMTU;
884   }
885   if (request_ertm && mtu > kMaxInboundPduPayloadSize) {
886     bt_log(DEBUG,
887            "l2cap-bredr",
888            "Channel %#.4x: preferred MTU channel parameter above MPS; using "
889            "MPS instead to avoid "
890            "segmentation (mtu param: %#x, max pdu: %#x)",
891            local_cid(),
892            mtu,
893            kMaxInboundPduPayloadSize);
894     mtu = kMaxInboundPduPayloadSize;
895   }
896   return mtu;
897 }
898 
ShouldRequestEnhancedRetransmission() const899 bool BrEdrDynamicChannel::ShouldRequestEnhancedRetransmission() const {
900   return parameters_.mode &&
901          *parameters_.mode ==
902              RetransmissionAndFlowControlMode::kEnhancedRetransmission &&
903          peer_supports_ertm_.value_or(false);
904 }
905 
IsWaitingForPeerErtmSupport()906 bool BrEdrDynamicChannel::IsWaitingForPeerErtmSupport() {
907   const auto local_mode =
908       parameters_.mode.value_or(RetransmissionAndFlowControlMode::kBasic);
909   return !peer_supports_ertm_.has_value() &&
910          (local_mode != RetransmissionAndFlowControlMode::kBasic);
911 }
912 
TrySendLocalConfig()913 void BrEdrDynamicChannel::TrySendLocalConfig() {
914   if (state_ & kLocalConfigSent) {
915     return;
916   }
917 
918   BT_ASSERT(!IsWaitingForPeerErtmSupport());
919 
920   SendLocalConfig();
921 }
922 
SendLocalConfig()923 void BrEdrDynamicChannel::SendLocalConfig() {
924   auto on_config_rsp_timeout = [this, self = weak_self_.GetWeakPtr()] {
925     if (self.is_alive()) {
926       bt_log(WARN,
927              "l2cap-bredr",
928              "Channel %#.4x: Timed out waiting for Configuration Response",
929              local_cid());
930       PassOpenError();
931     }
932   };
933 
934   BrEdrCommandHandler cmd_handler(signaling_channel_,
935                                   std::move(on_config_rsp_timeout));
936 
937   auto request_config = local_config_;
938 
939   // Don't send Retransmission & Flow Control option for basic mode
940   if (request_config.retransmission_flow_control_option()->mode() ==
941       RetransmissionAndFlowControlMode::kBasic) {
942     request_config.set_retransmission_flow_control_option(std::nullopt);
943   }
944 
945   if (!request_config.retransmission_flow_control_option()) {
946     num_basic_config_requests_++;
947   }
948 
949   if (!cmd_handler.SendConfigurationRequest(
950           remote_cid(),
951           0,
952           request_config.Options(),
953           [self = weak_self_.GetWeakPtr()](auto& rsp) {
954             if (self.is_alive()) {
955               return self->OnRxConfigRsp(rsp);
956             }
957             return ResponseHandlerAction::kCompleteOutboundTransaction;
958           })) {
959     bt_log(ERROR,
960            "l2cap-bredr",
961            "Channel %#.4x: Failed to send Configuration Request",
962            local_cid());
963     PassOpenError();
964     return;
965   }
966 
967   bt_log(TRACE,
968          "l2cap-bredr",
969          "Channel %#.4x: Sent Configuration Request (options: %s)",
970          local_cid(),
971          bt_str(request_config));
972 
973   state_ |= kLocalConfigSent;
974 }
975 
BothConfigsAccepted() const976 bool BrEdrDynamicChannel::BothConfigsAccepted() const {
977   return (state_ & kLocalConfigAccepted) && (state_ & kRemoteConfigAccepted);
978 }
979 
AcceptedChannelModesAreConsistent() const980 bool BrEdrDynamicChannel::AcceptedChannelModesAreConsistent() const {
981   BT_ASSERT(BothConfigsAccepted());
982   auto local_mode = local_config_.retransmission_flow_control_option()->mode();
983   auto remote_mode =
984       remote_config_.retransmission_flow_control_option()->mode();
985   return local_mode == remote_mode;
986 }
987 
CheckForUnacceptableConfigReqOptions(const ChannelConfiguration & config) const988 ChannelConfiguration BrEdrDynamicChannel::CheckForUnacceptableConfigReqOptions(
989     const ChannelConfiguration& config) const {
990   // TODO(fxbug.dev/42115983): reject reconfiguring MTU if mode is Enhanced
991   // Retransmission or Streaming mode.
992   ChannelConfiguration unacceptable;
993 
994   // Reject MTUs below minimum size
995   if (config.mtu_option()->mtu() < kMinACLMTU) {
996     bt_log(DEBUG,
997            "l2cap",
998            "Channel %#.4x: config request contains MTU below minimum (mtu: "
999            "%hu, min: %hu)",
1000            local_cid(),
1001            config.mtu_option()->mtu(),
1002            kMinACLMTU);
1003     // Respond back with a proposed MTU value of the required minimum (Core Spec
1004     // v5.1, Vol 3, Part A, Section 5.1: "It is implementation specific whether
1005     // the local device continues the configuration process or disconnects the
1006     // channel.")
1007     unacceptable.set_mtu_option(ChannelConfiguration::MtuOption(kMinACLMTU));
1008   }
1009 
1010   const auto req_mode =
1011       config.retransmission_flow_control_option()
1012           ? config.retransmission_flow_control_option()->mode()
1013           : RetransmissionAndFlowControlMode::kBasic;
1014   const auto local_mode =
1015       local_config().retransmission_flow_control_option()->mode();
1016   switch (req_mode) {
1017     case RetransmissionAndFlowControlMode::kBasic:
1018       // Local device must accept, as basic mode has highest precedence.
1019       if (local_mode ==
1020           RetransmissionAndFlowControlMode::kEnhancedRetransmission) {
1021         bt_log(DEBUG,
1022                "l2cap-bredr",
1023                "Channel %#.4x: accepting peer basic mode configuration option "
1024                "when preferred mode "
1025                "was ERTM",
1026                local_cid());
1027       }
1028       break;
1029     case RetransmissionAndFlowControlMode::kEnhancedRetransmission:
1030       // Basic mode has highest precedence, so if local mode is basic, reject
1031       // ERTM and send local mode.
1032       if (local_mode == RetransmissionAndFlowControlMode::kBasic) {
1033         bt_log(DEBUG,
1034                "l2cap-bredr",
1035                "Channel %#.4x: rejecting peer ERTM mode configuration option "
1036                "because preferred "
1037                "mode is basic",
1038                local_cid());
1039         unacceptable.set_retransmission_flow_control_option(
1040             ChannelConfiguration::RetransmissionAndFlowControlOption::
1041                 MakeBasicMode());
1042         break;
1043       }
1044       unacceptable.set_retransmission_flow_control_option(
1045           CheckForUnacceptableErtmOptions(config));
1046       break;
1047     default:
1048       bt_log(DEBUG,
1049              "l2cap-bredr",
1050              "Channel %#.4x: rejecting unsupported retransmission and flow "
1051              "control configuration "
1052              "option (mode: %#.2x)",
1053              local_cid(),
1054              static_cast<uint8_t>(req_mode));
1055 
1056       // All other modes are lower precedence than what local device supports,
1057       // so send local mode.
1058       if (local_mode ==
1059           RetransmissionAndFlowControlMode::kEnhancedRetransmission) {
1060         // Retransmission & Flow Control fields for ERTM are not negotiable, so
1061         // do not propose acceptable values per Core Spec v5.0, Vol 3, Part A,
1062         // Sec 7.1.4.
1063         unacceptable.set_retransmission_flow_control_option(
1064             ChannelConfiguration::RetransmissionAndFlowControlOption::
1065                 MakeEnhancedRetransmissionMode(
1066                     /*tx_window_size=*/0,
1067                     /*max_transmit=*/0,
1068                     /*rtx_timeout=*/0,
1069                     /*monitor_timeout=*/0,
1070                     /*mps=*/0));
1071       } else {
1072         unacceptable.set_retransmission_flow_control_option(
1073             local_config().retransmission_flow_control_option());
1074       }
1075   }
1076 
1077   return unacceptable;
1078 }
1079 
1080 std::optional<ChannelConfiguration::RetransmissionAndFlowControlOption>
CheckForUnacceptableErtmOptions(const ChannelConfiguration & config) const1081 BrEdrDynamicChannel::CheckForUnacceptableErtmOptions(
1082     const ChannelConfiguration& config) const {
1083   BT_ASSERT(config.retransmission_flow_control_option()->mode() ==
1084             RetransmissionAndFlowControlMode::kEnhancedRetransmission);
1085   BT_ASSERT(local_config().retransmission_flow_control_option()->mode() ==
1086             RetransmissionAndFlowControlMode::kEnhancedRetransmission);
1087 
1088   std::optional<ChannelConfiguration::RetransmissionAndFlowControlOption>
1089       unacceptable_rfc_option;
1090   const auto& peer_rfc_option =
1091       config.retransmission_flow_control_option().value();
1092 
1093   // TxWindow has a range of 1 to 63 (Core Spec v5.0, Vol 3, Part A, Sec 5.4).
1094   if (peer_rfc_option.tx_window_size() < kErtmMinUnackedInboundFrames) {
1095     bt_log(DEBUG,
1096            "l2cap-bredr",
1097            "Channel %#.4x: rejecting too-small ERTM TxWindow of %hhu",
1098            local_cid(),
1099            peer_rfc_option.tx_window_size());
1100     unacceptable_rfc_option = unacceptable_rfc_option.value_or(peer_rfc_option);
1101     unacceptable_rfc_option->set_tx_window_size(kErtmMinUnackedInboundFrames);
1102   } else if (peer_rfc_option.tx_window_size() > kErtmMaxUnackedInboundFrames) {
1103     bt_log(DEBUG,
1104            "l2cap-bredr",
1105            "Channel %#.4x: rejecting too-small ERTM TxWindow of %hhu",
1106            local_cid(),
1107            peer_rfc_option.tx_window_size());
1108     unacceptable_rfc_option = unacceptable_rfc_option.value_or(peer_rfc_option);
1109     unacceptable_rfc_option->set_tx_window_size(kErtmMaxUnackedInboundFrames);
1110   }
1111 
1112   // NOTE(fxbug.dev/42054330): MPS must be large enough to fit the largest SDU
1113   // in the minimum MTU case, because ERTM does not segment in the outbound
1114   // direction.
1115   if (peer_rfc_option.mps() < kMinACLMTU) {
1116     bt_log(DEBUG,
1117            "l2cap-bredr",
1118            "Channel %#.4x: rejecting too-small ERTM MPS of %hu",
1119            local_cid(),
1120            peer_rfc_option.mps());
1121     unacceptable_rfc_option = unacceptable_rfc_option.value_or(peer_rfc_option);
1122     unacceptable_rfc_option->set_mps(kMinACLMTU);
1123   }
1124 
1125   return unacceptable_rfc_option;
1126 }
1127 
TryRecoverFromUnacceptableParametersConfigRsp(const ChannelConfiguration & rsp_config)1128 bool BrEdrDynamicChannel::TryRecoverFromUnacceptableParametersConfigRsp(
1129     const ChannelConfiguration& rsp_config) {
1130   // Check if channel mode was unacceptable.
1131   if (rsp_config.retransmission_flow_control_option()) {
1132     // Check if peer rejected basic mode. Do not disconnect, in case peer will
1133     // accept resending basic mode (as is the case with PTS test
1134     // L2CAP/COS/CFD/BV-02-C).
1135     if (local_config().retransmission_flow_control_option()->mode() ==
1136         RetransmissionAndFlowControlMode::kBasic) {
1137       bt_log(WARN,
1138              "l2cap-bredr",
1139              "Channel %#.4x: Peer rejected basic mode with unacceptable "
1140              "parameters result (rsp mode: %#.2x)",
1141              local_cid(),
1142              static_cast<uint8_t>(
1143                  rsp_config.retransmission_flow_control_option()->mode()));
1144     }
1145 
1146     // Core Spec v5.1, Vol 3, Part A, Sec 5.4:
1147     // If the mode in the remote device's negative Configuration Response does
1148     // not match the mode in the remote device's Configuration Request then the
1149     // local device shall disconnect the channel.
1150     if (state_ & kRemoteConfigAccepted) {
1151       const auto rsp_mode =
1152           rsp_config.retransmission_flow_control_option()->mode();
1153       const auto remote_mode =
1154           remote_config_.retransmission_flow_control_option()->mode();
1155       if (rsp_mode != remote_mode) {
1156         bt_log(ERROR,
1157                "l2cap-bredr",
1158                "Channel %#.4x: Unsuccessful config: mode in unacceptable "
1159                "parameters config "
1160                "response does not match mode in remote config request (rsp "
1161                "mode: %#.2x, req mode: "
1162                "%#.2x)",
1163                local_cid(),
1164                static_cast<uint8_t>(rsp_mode),
1165                static_cast<uint8_t>(remote_mode));
1166         return false;
1167       }
1168     }
1169 
1170     bt_log(TRACE,
1171            "l2cap-bredr",
1172            "Channel %#.4x: Attempting to recover from unacceptable parameters "
1173            "config response by "
1174            "falling back to basic mode and resending config request",
1175            local_cid());
1176 
1177     // Fall back to basic mode and try sending config again up to
1178     // kMaxNumBasicConfigRequests times
1179     peer_supports_ertm_ = false;
1180     if (num_basic_config_requests_ == kMaxNumBasicConfigRequests) {
1181       bt_log(WARN,
1182              "l2cap-bredr",
1183              "Channel %#.4x: Peer rejected config request. Channel's limit of "
1184              "%#.2x basic mode config request attempts has been met",
1185              local_cid(),
1186              kMaxNumBasicConfigRequests);
1187       return false;
1188     }
1189     UpdateLocalConfigForErtm();
1190     SendLocalConfig();
1191     return true;
1192   }
1193 
1194   // Other unacceptable parameters cannot be recovered from.
1195   bt_log(WARN,
1196          "l2cap-bredr",
1197          "Channel %#.4x: Unsuccessful config: could not recover from "
1198          "unacceptable parameters config "
1199          "response",
1200          local_cid());
1201   return false;
1202 }
1203 
OnRxConnRsp(const BrEdrCommandHandler::ConnectionResponse & rsp)1204 BrEdrDynamicChannel::ResponseHandlerAction BrEdrDynamicChannel::OnRxConnRsp(
1205     const BrEdrCommandHandler::ConnectionResponse& rsp) {
1206   if (rsp.status() == BrEdrCommandHandler::Status::kReject) {
1207     bt_log(ERROR,
1208            "l2cap-bredr",
1209            "Channel %#.4x: Connection Request rejected reason %#.4hx",
1210            local_cid(),
1211            static_cast<unsigned short>(rsp.reject_reason()));
1212     PassOpenError();
1213     return ResponseHandlerAction::kCompleteOutboundTransaction;
1214   }
1215 
1216   if (rsp.local_cid() != local_cid()) {
1217     bt_log(
1218         ERROR,
1219         "l2cap-bredr",
1220         "Channel %#.4x: Got Connection Response for another channel ID %#.4x",
1221         local_cid(),
1222         rsp.local_cid());
1223     PassOpenError();
1224     return ResponseHandlerAction::kCompleteOutboundTransaction;
1225   }
1226 
1227   if ((state_ & kConnResponded) || !(state_ & kConnRequested)) {
1228     bt_log(ERROR,
1229            "l2cap-bredr",
1230            "Channel %#.4x: Unexpected Connection Response, state %#x",
1231            local_cid(),
1232            state_);
1233     PassOpenError();
1234     return ResponseHandlerAction::kCompleteOutboundTransaction;
1235   }
1236 
1237   if (rsp.result() == ConnectionResult::kPending) {
1238     bt_log(TRACE,
1239            "l2cap-bredr",
1240            "Channel %#.4x: Remote is pending open, status %#.4hx",
1241            local_cid(),
1242            static_cast<unsigned short>(rsp.conn_status()));
1243 
1244     if (rsp.remote_cid() == kInvalidChannelId) {
1245       return ResponseHandlerAction::kExpectAdditionalResponse;
1246     }
1247 
1248     // If the remote provides a channel ID, then we store it. It can be used for
1249     // disconnection from this point forward.
1250     if (!SetRemoteChannelId(rsp.remote_cid())) {
1251       bt_log(ERROR,
1252              "l2cap-bredr",
1253              "Channel %#.4x: Remote channel ID %#.4x is not unique",
1254              local_cid(),
1255              rsp.remote_cid());
1256       PassOpenError();
1257       return ResponseHandlerAction::kCompleteOutboundTransaction;
1258     }
1259 
1260     bt_log(TRACE,
1261            "l2cap-bredr",
1262            "Channel %#.4x: Got remote channel ID %#.4x",
1263            local_cid(),
1264            remote_cid());
1265     return ResponseHandlerAction::kExpectAdditionalResponse;
1266   }
1267 
1268   if (rsp.result() != ConnectionResult::kSuccess) {
1269     bt_log(ERROR,
1270            "l2cap-bredr",
1271            "Channel %#.4x: Unsuccessful Connection Response result %#.4hx, "
1272            "status %#.4x",
1273            local_cid(),
1274            static_cast<unsigned short>(rsp.result()),
1275            static_cast<unsigned int>(rsp.status()));
1276     PassOpenError();
1277     return ResponseHandlerAction::kCompleteOutboundTransaction;
1278   }
1279 
1280   if (rsp.remote_cid() < kFirstDynamicChannelId) {
1281     bt_log(ERROR,
1282            "l2cap-bredr",
1283            "Channel %#.4x: received Connection Response with invalid channel "
1284            "ID %#.4x, disconnecting",
1285            local_cid(),
1286            remote_cid());
1287 
1288     // This results in sending a Disconnection Request for non-zero remote IDs,
1289     // which is probably what we want because there's no other way to send back
1290     // a failure in this case.
1291     PassOpenError();
1292     return ResponseHandlerAction::kCompleteOutboundTransaction;
1293   }
1294 
1295   // TODO(xow): To be stricter, we can disconnect if the remote ID changes on us
1296   // during connection like this, but not sure if that would be beneficial.
1297   if (remote_cid() != kInvalidChannelId && remote_cid() != rsp.remote_cid()) {
1298     bt_log(WARN,
1299            "l2cap-bredr",
1300            "Channel %#.4x: using new remote ID %#.4x after previous Connection "
1301            "Response provided %#.4x",
1302            local_cid(),
1303            rsp.remote_cid(),
1304            remote_cid());
1305   }
1306 
1307   state_ |= kConnResponded;
1308 
1309   if (!SetRemoteChannelId(rsp.remote_cid())) {
1310     bt_log(ERROR,
1311            "l2cap-bredr",
1312            "Channel %#.4x: Remote channel ID %#.4x is not unique",
1313            local_cid(),
1314            rsp.remote_cid());
1315     PassOpenError();
1316     return ResponseHandlerAction::kCompleteOutboundTransaction;
1317   }
1318 
1319   bt_log(TRACE,
1320          "l2cap-bredr",
1321          "Channel %#.4x: Got remote channel ID %#.4x",
1322          local_cid(),
1323          rsp.remote_cid());
1324 
1325   UpdateLocalConfigForErtm();
1326   if (!IsWaitingForPeerErtmSupport()) {
1327     TrySendLocalConfig();
1328   }
1329   return ResponseHandlerAction::kCompleteOutboundTransaction;
1330 }
1331 
OnRxConfigRsp(const BrEdrCommandHandler::ConfigurationResponse & rsp)1332 BrEdrDynamicChannel::ResponseHandlerAction BrEdrDynamicChannel::OnRxConfigRsp(
1333     const BrEdrCommandHandler::ConfigurationResponse& rsp) {
1334   if (rsp.status() == BrEdrCommandHandler::Status::kReject) {
1335     bt_log(ERROR,
1336            "l2cap-bredr",
1337            "Channel %#.4x: Configuration Request rejected, reason %#.4hx, "
1338            "disconnecting",
1339            local_cid(),
1340            static_cast<unsigned short>(rsp.reject_reason()));
1341 
1342     // Configuration Request being rejected is fatal because the remote is not
1343     // trying to negotiate parameters (any more).
1344     PassOpenError();
1345     return ResponseHandlerAction::kCompleteOutboundTransaction;
1346   }
1347 
1348   // Pending responses may contain return values and adjustments to
1349   // non-negotiated values.
1350   if (rsp.result() == ConfigurationResult::kPending) {
1351     bt_log(TRACE,
1352            "l2cap-bredr",
1353            "Channel %#.4x: remote pending config (options: %s)",
1354            local_cid(),
1355            bt_str(rsp.config()));
1356 
1357     if (rsp.config().mtu_option()) {
1358       local_config_.set_mtu_option(rsp.config().mtu_option());
1359     }
1360 
1361     return ResponseHandlerAction::kExpectAdditionalResponse;
1362   }
1363 
1364   if (rsp.result() == ConfigurationResult::kUnacceptableParameters) {
1365     bt_log(DEBUG,
1366            "l2cap-bredr",
1367            "Channel %#.4x: Received unacceptable parameters config response "
1368            "(options: %s)",
1369            local_cid(),
1370            bt_str(rsp.config()));
1371 
1372     if (!TryRecoverFromUnacceptableParametersConfigRsp(rsp.config())) {
1373       PassOpenError();
1374     }
1375     return ResponseHandlerAction::kCompleteOutboundTransaction;
1376   }
1377 
1378   if (rsp.result() != ConfigurationResult::kSuccess) {
1379     bt_log(ERROR,
1380            "l2cap-bredr",
1381            "Channel %#.4x: unsuccessful config (result: %#.4hx, options: %s)",
1382            local_cid(),
1383            static_cast<unsigned short>(rsp.result()),
1384            bt_str(rsp.config()));
1385     PassOpenError();
1386     return ResponseHandlerAction::kCompleteOutboundTransaction;
1387   }
1388 
1389   if (rsp.local_cid() != local_cid()) {
1390     bt_log(ERROR,
1391            "l2cap-bredr",
1392            "Channel %#.4x: dropping Configuration Response for %#.4x",
1393            local_cid(),
1394            rsp.local_cid());
1395     PassOpenError();
1396     return ResponseHandlerAction::kCompleteOutboundTransaction;
1397   }
1398 
1399   state_ |= kLocalConfigAccepted;
1400 
1401   bt_log(TRACE,
1402          "l2cap-bredr",
1403          "Channel %#.4x: Got Configuration Response (options: %s)",
1404          local_cid(),
1405          bt_str(rsp.config()));
1406 
1407   if (rsp.config().mtu_option()) {
1408     local_config_.set_mtu_option(rsp.config().mtu_option());
1409   }
1410 
1411   if (BothConfigsAccepted() && !AcceptedChannelModesAreConsistent()) {
1412     bt_log(WARN,
1413            "l2cap-bredr",
1414            "Channel %#.4x: inconsistent channel mode negotiation (local mode: "
1415            "%#.2x, remote "
1416            "mode: %#.2x); falling back to Basic Mode",
1417            local_cid(),
1418            static_cast<uint8_t>(
1419                local_config().retransmission_flow_control_option()->mode()),
1420            static_cast<uint8_t>(
1421                remote_config().retransmission_flow_control_option()->mode()));
1422 
1423     // See spec justification in OnRxConfigReq.
1424     local_config_.set_retransmission_flow_control_option(
1425         ChannelConfiguration::RetransmissionAndFlowControlOption::
1426             MakeBasicMode());
1427     remote_config_.set_retransmission_flow_control_option(
1428         ChannelConfiguration::RetransmissionAndFlowControlOption::
1429             MakeBasicMode());
1430     PassOpenResult();
1431     return ResponseHandlerAction::kCompleteOutboundTransaction;
1432   }
1433 
1434   if (IsOpen()) {
1435     set_opened();
1436     PassOpenResult();
1437   }
1438 
1439   return ResponseHandlerAction::kCompleteOutboundTransaction;
1440 }
1441 
SetEnhancedRetransmissionSupport(bool supported)1442 void BrEdrDynamicChannel::SetEnhancedRetransmissionSupport(bool supported) {
1443   peer_supports_ertm_ = supported;
1444 
1445   UpdateLocalConfigForErtm();
1446 
1447   // Don't send local config before connection response.
1448   if (state_ & kConnResponded) {
1449     TrySendLocalConfig();
1450   }
1451 }
1452 
1453 }  // namespace bt::l2cap::internal
1454