Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f664ba0 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2cap: Send connection req after received info resp

We need to wait for information response extended features supported to
check ERTM support before we send connection request. If ERTM isn't
supported, we drop the connection request and notify client.

Test: cert/run --host
Test: L2CAP/CMC/BV-02-C
Change-Id: I2c1ef869af04a1cfede995fd3040f5b5c396b06b
parent e64f7df8
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -1337,9 +1337,6 @@ class L2capTest(GdBaseTestClass):
        Verify the IUT can accept a Configuration Request from the Lower Tester
        containing an F&EC option that specifies Enhanced Retransmission Mode
        """
        asserts.skip(
            "This doesn't work. Currently if DUT sends connection request before information response is received, DUT assumes remote doesn't support ERTM, and drops request"
        )
        self._setup_link_from_cert()
        self.cert_l2cap.turn_on_ertm()

@@ -1358,6 +1355,7 @@ class L2capTest(GdBaseTestClass):
        Information Response [Extended Features]
        """
        self._setup_link_from_cert()
        self.cert_l2cap.disable_ertm()
        dut_channel_future = self.dut_l2cap.connect_dynamic_channel_to_cert(
            psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
        assertThat(self.cert_l2cap.get_control_channel()).emitsNone(
+28 −1
Original line number Diff line number Diff line
@@ -125,6 +125,14 @@ void Link::SendConnectionRequest(Psm psm, Cid local_cid,
                                 PendingDynamicChannelConnection pending_dynamic_channel_connection) {
  if (pending_dynamic_channel_connection.configuration_.channel_mode ==
          RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION &&
      !remote_extended_feature_received_) {
    pending_dynamic_psm_list_.push_back(psm);
    pending_dynamic_channel_callback_list_.push_back(std::move(pending_dynamic_channel_connection));
    LOG_INFO("Will connect after information response ERTM feature support is received");
    dynamic_channel_allocator_.FreeChannel(local_cid);
    return;
  } else if (pending_dynamic_channel_connection.configuration_.channel_mode ==
                 RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION &&
             !GetRemoteSupportsErtm()) {
    LOG_WARN("Remote doesn't support ERTM. Dropping connection request");
    ConnectionResult result{
@@ -132,6 +140,7 @@ void Link::SendConnectionRequest(Psm psm, Cid local_cid,
    };
    pending_dynamic_channel_connection.handler_->Post(
        common::BindOnce(std::move(pending_dynamic_channel_connection.on_fail_callback_), result));
    dynamic_channel_allocator_.FreeChannel(local_cid);
    return;
  } else {
    local_cid_to_pending_dynamic_channel_connection_map_[local_cid] = std::move(pending_dynamic_channel_connection);
@@ -139,6 +148,23 @@ void Link::SendConnectionRequest(Psm psm, Cid local_cid,
  }
}

void Link::SetPendingDynamicChannels(std::list<Psm> psm_list,
                                     std::list<Link::PendingDynamicChannelConnection> callback_list) {
  ASSERT(psm_list.size() == callback_list.size());
  pending_dynamic_psm_list_ = std::move(psm_list);
  pending_dynamic_channel_callback_list_ = std::move(callback_list);
}

void Link::connect_to_pending_dynamic_channels() {
  auto psm = pending_dynamic_psm_list_.begin();
  auto callback = pending_dynamic_channel_callback_list_.begin();
  while (psm != pending_dynamic_psm_list_.end()) {
    SendConnectionRequest(*psm, ReserveDynamicChannel(), std::move(*callback));
    psm++;
    callback++;
  }
}

void Link::OnOutgoingConnectionRequestFail(Cid local_cid) {
  if (local_cid_to_pending_dynamic_channel_connection_map_.find(local_cid) !=
      local_cid_to_pending_dynamic_channel_connection_map_.end()) {
@@ -245,6 +271,7 @@ void Link::OnRemoteExtendedFeatureReceived(bool ertm_supported, bool fcs_support
  remote_supports_ertm_ = ertm_supported;
  remote_supports_fcs_ = fcs_supported;
  remote_extended_feature_received_ = true;
  connect_to_pending_dynamic_channels();
}

void Link::AddChannelPendingingAuthentication(PendingAuthenticateDynamicChannelConnection pending_channel) {
+8 −0
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall
  virtual void SendConnectionRequest(Psm psm, Cid local_cid,
                                     PendingDynamicChannelConnection pending_dynamic_channel_connection);

  // When a Link is established, LinkManager notifies pending dynamic channels to connect
  virtual void SetPendingDynamicChannels(std::list<Psm> psm_list,
                                         std::list<Link::PendingDynamicChannelConnection> callback_list);

  // Invoked by signalling manager to indicate an outgoing connection request failed and link shall free resources
  virtual void OnOutgoingConnectionRequestFail(Cid local_cid);

@@ -161,6 +165,8 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall
  virtual void OnReadClockComplete(uint32_t clock, uint16_t accuracy) override;

 private:
  void connect_to_pending_dynamic_channels();

  os::Handler* l2cap_handler_;
  l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
  l2cap::internal::DynamicChannelAllocator dynamic_channel_allocator_{this, l2cap_handler_};
@@ -178,6 +184,8 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall
  bool remote_supports_fcs_ = false;
  hci::EncryptionEnabled encryption_enabled_ = hci::EncryptionEnabled::OFF;
  std::list<Link::PendingAuthenticateDynamicChannelConnection> pending_channel_list_;
  std::list<Psm> pending_dynamic_psm_list_;
  std::list<Link::PendingDynamicChannelConnection> pending_dynamic_channel_callback_list_;
  DISALLOW_COPY_AND_ASSIGN(Link);
};

+4 −12
Original line number Diff line number Diff line
@@ -151,22 +151,14 @@ void LinkManager::OnConnectSuccess(std::unique_ptr<hci::AclConnection> acl_conne
    }
  }
  if (pending_dynamic_channels_.find(device) != pending_dynamic_channels_.end()) {
    for (Psm psm : pending_dynamic_channels_[device]) {
      auto& callbacks = pending_dynamic_channels_callbacks_[device].front();
      link->SendConnectionRequest(psm, link->ReserveDynamicChannel(), std::move(callbacks));
      pending_dynamic_channels_callbacks_[device].pop_front();
    }
    auto psm_list = pending_dynamic_channels_[device];
    auto& callback_list = pending_dynamic_channels_callbacks_[device];
    link->SetPendingDynamicChannels(psm_list, std::move(callback_list));
    pending_dynamic_channels_.erase(device);
    pending_dynamic_channels_callbacks_.erase(device);
  }
  // Remove device from pending links list, if any
  auto pending_link = pending_links_.find(device);
  if (pending_link == pending_links_.end()) {
    // This an incoming connection, exit
    return;
  }
  // This is an outgoing connection, remove entry in pending link list
  pending_links_.erase(pending_link);
  pending_links_.erase(device);
}

void LinkManager::OnConnectFail(hci::Address device, hci::ErrorCode reason) {
+1 −1
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ class DynamicChannelAllocator {
  // longer needed, use FreeChannel.
  Cid ReserveChannel();

  // Frees a channel. If psm doesn't exist, it will crash
  // Frees a channel (existing or reserved)
  void FreeChannel(Cid cid);

  bool IsPsmUsed(Psm psm) const;
Loading