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

Commit 5d8e3894 authored by Chris Manton's avatar Chris Manton
Browse files

Synchronize l2cap channel for client apps

Respond immediately with a connection interface
descriptor rather than wait for the actual
connection in order to avoid a race.

Bug: 146565627
Test: CtsVerifier insecure connections

Change-Id: Ie6eeda50a01ee7fda076330d5583b9793578b1bb
parent 23604ea8
Loading
Loading
Loading
Loading
+50 −20
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
#include <memory>
#include <memory>
#include <mutex>
#include <mutex>
#include <queue>
#include <queue>
#include <set>
#include <unordered_map>
#include <unordered_map>
#include <vector>
#include <vector>


@@ -156,6 +157,8 @@ class ConnectionInterface {
struct ConnectionInterfaceManager {
struct ConnectionInterfaceManager {
 public:
 public:
  ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  ConnectionInterfaceDescriptor AddChannel(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  ConnectionInterfaceDescriptor AddChannel(ConnectionInterfaceDescriptor cid,
                                           std::unique_ptr<l2cap::classic::DynamicChannel> channel);
  void RemoveConnection(ConnectionInterfaceDescriptor cid);
  void RemoveConnection(ConnectionInterfaceDescriptor cid);


  void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
  void SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid, ReadDataReadyCallback on_data_ready);
@@ -181,40 +184,57 @@ struct ConnectionInterfaceManager {
    // There may be multiple, so only remove one
    // There may be multiple, so only remove one
  }
  }


  void ConnectionFailed(hci::Address address, l2cap::Psm psm) {
  void ConnectionFailed(ConnectionOpenCallback on_open, hci::Address address, l2cap::Psm psm) {
    LOG_DEBUG("Connection Failed");
    LOG_DEBUG("Connection Failed");
    // TODO(cmanton) queue this pending connection address/psm tuple up for deletion
    // TODO(cmanton) queue this pending connection address/psm tuple up for deletion
    // There may be multiple, so only remove one
    // There may be multiple, so only remove one
    handler_->Post(common::BindOnce(&ConnectionInterfaceManager::GeneralCallback, common::Unretained(this), on_open,
                                    address, psm, kInvalidConnectionInterfaceDescriptor));
  }
  }


  ConnectionInterfaceManager(os::Handler* handler);
  ConnectionInterfaceManager(os::Handler* handler);


  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
  void FreeConnectionInterfaceDescriptor(ConnectionInterfaceDescriptor cid);

 private:
 private:
  os::Handler* handler_;
  os::Handler* handler_;
  ConnectionInterfaceDescriptor current_connection_interface_descriptor_;
  ConnectionInterfaceDescriptor current_connection_interface_descriptor_;


  bool HasResources() const;
  bool HasResources() const;
  bool Exists(ConnectionInterfaceDescriptor id) const;
  bool ChannelExists(ConnectionInterfaceDescriptor id) const;
  bool CidExists(ConnectionInterfaceDescriptor id) const;


  std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
  std::unordered_map<ConnectionInterfaceDescriptor, std::unique_ptr<ConnectionInterface>> cid_to_interface_map_;
  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
  std::set<ConnectionInterfaceDescriptor> active_cid_set_;

  ConnectionInterfaceManager() = delete;
  ConnectionInterfaceManager() = delete;
};
};


ConnectionInterfaceManager::ConnectionInterfaceManager(os::Handler* handler)
ConnectionInterfaceManager::ConnectionInterfaceManager(os::Handler* handler)
    : handler_(handler), current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}
    : handler_(handler), current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}


bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
bool ConnectionInterfaceManager::ChannelExists(ConnectionInterfaceDescriptor cid) const {
  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
}
}


bool ConnectionInterfaceManager::CidExists(ConnectionInterfaceDescriptor cid) const {
  return active_cid_set_.find(cid) != active_cid_set_.end();
}

void ConnectionInterfaceManager::FreeConnectionInterfaceDescriptor(ConnectionInterfaceDescriptor cid) {
  ASSERT(CidExists(cid));
  active_cid_set_.erase(cid);
}

ConnectionInterfaceDescriptor ConnectionInterfaceManager::AllocateConnectionInterfaceDescriptor() {
ConnectionInterfaceDescriptor ConnectionInterfaceManager::AllocateConnectionInterfaceDescriptor() {
  ASSERT(HasResources());
  ASSERT(HasResources());
  while (Exists(current_connection_interface_descriptor_)) {
  while (CidExists(current_connection_interface_descriptor_)) {
    if (++current_connection_interface_descriptor_ == kInvalidConnectionInterfaceDescriptor) {
    if (++current_connection_interface_descriptor_ == kInvalidConnectionInterfaceDescriptor) {
      current_connection_interface_descriptor_ = kStartConnectionInterfaceDescriptor;
      current_connection_interface_descriptor_ = kStartConnectionInterfaceDescriptor;
    }
    }
  }
  }
  active_cid_set_.insert(current_connection_interface_descriptor_);
  return current_connection_interface_descriptor_++;
  return current_connection_interface_descriptor_++;
}
}


@@ -224,7 +244,11 @@ ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
    return kInvalidConnectionInterfaceDescriptor;
    return kInvalidConnectionInterfaceDescriptor;
  }
  }
  ConnectionInterfaceDescriptor cid = AllocateConnectionInterfaceDescriptor();
  ConnectionInterfaceDescriptor cid = AllocateConnectionInterfaceDescriptor();
  return AddChannel(cid, std::move(channel));
}


ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
    ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
  auto channel_interface = std::make_unique<ConnectionInterface>(cid, std::move(channel), handler_);
  auto channel_interface = std::make_unique<ConnectionInterface>(cid, std::move(channel), handler_);
  cid_to_interface_map_[cid] = std::move(channel_interface);
  cid_to_interface_map_[cid] = std::move(channel_interface);
  return cid;
  return cid;
@@ -234,6 +258,7 @@ void ConnectionInterfaceManager::RemoveConnection(ConnectionInterfaceDescriptor
  ASSERT(cid_to_interface_map_.count(cid) == 1);
  ASSERT(cid_to_interface_map_.count(cid) == 1);
  cid_to_interface_map_.find(cid)->second->Close();
  cid_to_interface_map_.find(cid)->second->Close();
  cid_to_interface_map_.erase(cid);
  cid_to_interface_map_.erase(cid);
  FreeConnectionInterfaceDescriptor(cid);
}
}


bool ConnectionInterfaceManager::HasResources() const {
bool ConnectionInterfaceManager::HasResources() const {
@@ -242,18 +267,18 @@ bool ConnectionInterfaceManager::HasResources() const {


void ConnectionInterfaceManager::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid,
void ConnectionInterfaceManager::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid,
                                                          ReadDataReadyCallback on_data_ready) {
                                                          ReadDataReadyCallback on_data_ready) {
  ASSERT(Exists(cid));
  ASSERT(ChannelExists(cid));
  return cid_to_interface_map_[cid]->SetReadDataReadyCallback(on_data_ready);
  return cid_to_interface_map_[cid]->SetReadDataReadyCallback(on_data_ready);
}
}


void ConnectionInterfaceManager::SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid,
void ConnectionInterfaceManager::SetConnectionClosedCallback(ConnectionInterfaceDescriptor cid,
                                                             ConnectionClosedCallback on_closed) {
                                                             ConnectionClosedCallback on_closed) {
  ASSERT(Exists(cid));
  ASSERT(ChannelExists(cid));
  return cid_to_interface_map_[cid]->SetConnectionClosedCallback(on_closed);
  return cid_to_interface_map_[cid]->SetConnectionClosedCallback(on_closed);
}
}


bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
  if (!Exists(cid)) {
  if (!ChannelExists(cid)) {
    return false;
    return false;
  }
  }
  cid_to_interface_map_[cid]->Write(std::move(packet));
  cid_to_interface_map_[cid]->Write(std::move(packet));
@@ -262,18 +287,16 @@ bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::u


class PendingConnection {
class PendingConnection {
 public:
 public:
  PendingConnection(ConnectionInterfaceManager* connection_interface_manager, l2cap::Psm psm, hci::Address address,
  PendingConnection(ConnectionInterfaceManager* connection_interface_manager, ConnectionInterfaceDescriptor cid,
                    ConnectionOpenCallback on_open, std::promise<uint16_t> completed)
                    l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
      : connection_interface_manager_(connection_interface_manager), psm_(psm), address_(address),
                    std::promise<uint16_t> completed)
      : connection_interface_manager_(connection_interface_manager), cid_(cid), psm_(psm), address_(address),
        on_open_(std::move(on_open)), completed_(std::move(completed)) {}
        on_open_(std::move(on_open)), completed_(std::move(completed)) {}


  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
    LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
    LOG_DEBUG("Local initiated connection is open to device:%s for psm:%hd", address_.ToString().c_str(), psm_);
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    connection_interface_manager_->AddChannel(cid_, std::move(channel));
    completed_.set_value(cid);
    connection_interface_manager_->ConnectionOpened(std::move(on_open_), address_, psm_, cid_);
    // Attempt to avoid async race condition with upper stack
    std::this_thread::yield();
    connection_interface_manager_->ConnectionOpened(std::move(on_open_), address_, psm_, cid);
  }
  }


  void OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
  void OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
@@ -295,11 +318,13 @@ class PendingConnection {
        break;
        break;
    }
    }
    completed_.set_value(kInvalidConnectionInterfaceDescriptor);
    completed_.set_value(kInvalidConnectionInterfaceDescriptor);
    connection_interface_manager_->ConnectionFailed(address_, psm_);
    connection_interface_manager_->ConnectionFailed(std::move(on_open_), address_, psm_);
    connection_interface_manager_->FreeConnectionInterfaceDescriptor(cid_);
  }
  }


 private:
 private:
  ConnectionInterfaceManager* connection_interface_manager_;
  ConnectionInterfaceManager* connection_interface_manager_;
  const ConnectionInterfaceDescriptor cid_;
  const l2cap::Psm psm_;
  const l2cap::Psm psm_;
  const hci::Address address_;
  const hci::Address address_;
  ConnectionOpenCallback on_open_;
  ConnectionOpenCallback on_open_;
@@ -326,7 +351,8 @@ class ServiceInterface {
    LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
    LOG_DEBUG("Remote initiated connection is open from device:%s for psm:%hd", channel->GetDevice().ToString().c_str(),
              psm_);
              psm_);
    hci::Address address = channel->GetDevice();
    hci::Address address = channel->GetDevice();
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AddChannel(std::move(channel));
    ConnectionInterfaceDescriptor cid = connection_interface_manager_->AllocateConnectionInterfaceDescriptor();
    connection_interface_manager_->AddChannel(cid, std::move(channel));
    connection_interface_manager_->ConnectionOpened(on_open_, address, psm_, cid);
    connection_interface_manager_->ConnectionOpened(on_open_, address, psm_, cid);
  }
  }


@@ -414,13 +440,17 @@ void L2cap::impl::UnregisterService(l2cap::Psm psm) {


void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, ConnectionOpenCallback on_open,
                                   std::promise<uint16_t> completed) {
                                   std::promise<uint16_t> completed) {
  LOG_DEBUG("Initiating classic connection to psm:%hd device:%s", psm, address.ToString().c_str());
  ConnectionInterfaceDescriptor cid = connection_interface_manager_.AllocateConnectionInterfaceDescriptor();
  auto pending_connection = std::make_shared<PendingConnection>(&connection_interface_manager_, psm, address,
  completed.set_value(cid);

  auto pending_connection = std::make_shared<PendingConnection>(&connection_interface_manager_, cid, psm, address,
                                                                std::move(on_open), std::move(completed));
                                                                std::move(on_open), std::move(completed));
  // TODO(cmanton) hash psm/address pair into unordered map for pending_connection
  // TODO(cmanton) hash psm/address pair into unordered map for pending_connection
  // This is ok for now
  // This is ok for now
  psm_to_pending_connection_map_[psm] = pending_connection;
  psm_to_pending_connection_map_[psm] = pending_connection;
  // TODO(cmanton): Add ERTM mode support by changing configuratio_option in ConnectChannel()
  // TODO(cmanton): Add ERTM mode support by changing configuratio_option in ConnectChannel()
  //
  LOG_DEBUG("Initiating classic connection to psm:%hd device:%s cifd:%hu", psm, address.ToString().c_str(), cid);
  bool rc = dynamic_channel_manager_->ConnectChannel(
  bool rc = dynamic_channel_manager_->ConnectChannel(
      address, l2cap::classic::DynamicChannelConfigurationOption(), psm,
      address, l2cap::classic::DynamicChannelConfigurationOption(), psm,
      common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
      common::Bind(&PendingConnection::OnConnectionOpen, common::Unretained(pending_connection.get())),
+6 −22
Original line number Original line Diff line number Diff line
@@ -56,8 +56,6 @@ uint16_t bluetooth::shim::L2CA_Register(uint16_t client_psm,
              __func__, client_psm, psm);
              __func__, client_psm, psm);
    return 0;
    return 0;
  }
  }
  shim_l2cap.Classic().RegisterPsm(psm, callbacks);

  LOG_INFO(LOG_TAG, "%s classic client_psm:%hd psm:%hd", __func__, client_psm,
  LOG_INFO(LOG_TAG, "%s classic client_psm:%hd psm:%hd", __func__, client_psm,
           psm);
           psm);


@@ -74,39 +72,25 @@ void bluetooth::shim::L2CA_Deregister(uint16_t client_psm) {
  }
  }
  uint16_t psm = shim_l2cap.ConvertClientToRealPsm(client_psm);
  uint16_t psm = shim_l2cap.ConvertClientToRealPsm(client_psm);


  if (!shim_l2cap.Classic().IsPsmRegistered(psm)) {
  shim_l2cap.UnregisterService(psm);
    LOG_ERROR(LOG_TAG,
              "%s Not previously registered classic client_psm:%hd psm:%hd",
              __func__, client_psm, psm);
    return;
  }
  shim_l2cap.Classic().UnregisterPsm(psm);
  shim_l2cap.RemoveClientPsm(psm);
  shim_l2cap.RemoveClientPsm(psm);
}
}


uint16_t bluetooth::shim::L2CA_AllocatePSM(void) {
uint16_t bluetooth::shim::L2CA_AllocatePSM(void) {
  uint16_t psm = shim_l2cap.GetNextDynamicClassicPsm();
  return shim_l2cap.GetNextDynamicClassicPsm();
  shim_l2cap.Classic().AllocatePsm(psm);
  return psm;
}
}


uint16_t bluetooth::shim::L2CA_AllocateLePSM(void) {
uint16_t bluetooth::shim::L2CA_AllocateLePSM(void) {
  uint16_t psm = shim_l2cap.GetNextDynamicLePsm();
  return shim_l2cap.GetNextDynamicLePsm();
  shim_l2cap.Le().AllocatePsm(psm);
  return psm;
}
}


void bluetooth::shim::L2CA_FreeLePSM(uint16_t psm) {
void bluetooth::shim::L2CA_FreeLePSM(uint16_t psm) {
  if (!shim_l2cap.Le().IsPsmAllocated(psm)) {
    LOG_ERROR(LOG_TAG, "%s Not previously allocated le psm:%hd", __func__, psm);
    return;
  }
  if (!shim_l2cap.Le().IsPsmRegistered(psm)) {
  if (!shim_l2cap.Le().IsPsmRegistered(psm)) {
    LOG_ERROR(LOG_TAG, "%s Must deregister psm before deallocation psm:%hd",
    LOG_ERROR(LOG_TAG, "%s Not previously registered le psm:%hd", __func__,
              __func__, psm);
              psm);
    return;
    return;
  }
  }
  shim_l2cap.Le().DeallocatePsm(psm);
  shim_l2cap.Le().UnregisterPsm(psm);
}
}


/**
/**
+43 −80
Original line number Original line Diff line number Diff line
@@ -23,42 +23,40 @@
#include "osi/include/allocator.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
#include "osi/include/log.h"


constexpr size_t kBtHdrSize = sizeof(BT_HDR);
constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
constexpr bool kDisconnectResponseRequired = false;
constexpr bool kDisconnectResponseRequired = false;
constexpr size_t kBtHdrSize = sizeof(BT_HDR);
constexpr uint16_t kConnectionFail = 1;
constexpr uint16_t kConnectionSuccess = 0;
constexpr uint16_t kConnectionSuccess = 0;

constexpr uint16_t kInvalidConnectionInterfaceDescriptor = 0;
bool bluetooth::legacy::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
constexpr uint8_t kUnusedId = 0;
  return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
constexpr uint16_t kUnusedResult = 0;
}


bool bluetooth::legacy::shim::PsmData::IsPsmRegistered(uint16_t psm) const {
bool bluetooth::legacy::shim::PsmData::IsPsmRegistered(uint16_t psm) const {
  return IsPsmAllocated(psm) && psm_to_callback_map_.at(psm) != nullptr;
  return psm_to_callback_map_.find(psm) != psm_to_callback_map_.end();
}
}


void bluetooth::legacy::shim::PsmData::AllocatePsm(uint16_t psm) {
bool bluetooth::legacy::shim::PsmData::HasClient(uint16_t psm) const {
  RegisterPsm(psm, nullptr);
  return IsPsmRegistered(psm) && psm_to_callback_map_.at(psm) != nullptr;
}
}


void bluetooth::legacy::shim::PsmData::RegisterPsm(
void bluetooth::legacy::shim::PsmData::RegisterPsm(
    uint16_t psm, const tL2CAP_APPL_INFO* callbacks) {
    uint16_t psm, const tL2CAP_APPL_INFO* callbacks) {
  CHECK(!HasClient(psm));
  psm_to_callback_map_[psm] = callbacks;
  psm_to_callback_map_[psm] = callbacks;
}
}


void bluetooth::legacy::shim::PsmData::UnregisterPsm(uint16_t psm) {
void bluetooth::legacy::shim::PsmData::RegisterPsm(uint16_t psm) {
  psm_to_callback_map_[psm] = nullptr;
  RegisterPsm(psm, nullptr);
}
}


void bluetooth::legacy::shim::PsmData::DeallocatePsm(uint16_t psm) {
void bluetooth::legacy::shim::PsmData::UnregisterPsm(uint16_t psm) {
  CHECK(IsPsmRegistered(psm));
  psm_to_callback_map_.erase(psm);
  psm_to_callback_map_.erase(psm);
}
}


const tL2CAP_APPL_INFO* bluetooth::legacy::shim::PsmData::Callbacks(
const tL2CAP_APPL_INFO* bluetooth::legacy::shim::PsmData::Callbacks(
    uint16_t psm) {
    uint16_t psm) {
  if (psm_to_callback_map_.find(psm) == psm_to_callback_map_.end()) {
  CHECK(HasClient(psm));
    LOG_WARN(LOG_TAG, "Accessing unknown psm:%hd:", psm);
    return nullptr;
  }
  return psm_to_callback_map_[psm];
  return psm_to_callback_map_[psm];
}
}


@@ -108,7 +106,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
    return real_psm;
    return real_psm;
  }
  }


  while (Classic().IsPsmAllocated(classic_virtual_psm_)) {
  while (Classic().IsPsmRegistered(classic_virtual_psm_)) {
    classic_virtual_psm_ += 2;
    classic_virtual_psm_ += 2;
    if (classic_virtual_psm_ >= kFinalClassicVirtualPsm) {
    if (classic_virtual_psm_ >= kFinalClassicVirtualPsm) {
      classic_virtual_psm_ = kInitialClassicVirtualPsm;
      classic_virtual_psm_ = kInitialClassicVirtualPsm;
@@ -118,7 +116,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextVirtualPsm(uint16_t real_psm) {
}
}


uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
  while (Le().IsPsmAllocated(le_dynamic_psm_)) {
  while (Le().IsPsmRegistered(le_dynamic_psm_)) {
    le_dynamic_psm_++;
    le_dynamic_psm_++;
    if (le_dynamic_psm_ > kFinalLeDynamicPsm) {
    if (le_dynamic_psm_ > kFinalLeDynamicPsm) {
      le_dynamic_psm_ = kInitialLeDynamicPsm;
      le_dynamic_psm_ = kInitialLeDynamicPsm;
@@ -128,7 +126,7 @@ uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicLePsm() {
}
}


uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicClassicPsm() {
uint16_t bluetooth::legacy::shim::L2cap::GetNextDynamicClassicPsm() {
  while (Classic().IsPsmAllocated(classic_dynamic_psm_)) {
  while (Classic().IsPsmRegistered(classic_dynamic_psm_)) {
    classic_dynamic_psm_ += 2;
    classic_dynamic_psm_ += 2;
    if (classic_dynamic_psm_ > kFinalClassicDynamicPsm) {
    if (classic_dynamic_psm_ > kFinalClassicDynamicPsm) {
      classic_dynamic_psm_ = kInitialClassicDynamicPsm;
      classic_dynamic_psm_ = kInitialClassicDynamicPsm;
@@ -154,7 +152,6 @@ void bluetooth::legacy::shim::L2cap::RegisterService(
  if (!enable_snoop) {
  if (!enable_snoop) {
    LOG_WARN(LOG_TAG, "UNIMPLEMENTED Cannot disable snooping on psm:%d", psm);
    LOG_WARN(LOG_TAG, "UNIMPLEMENTED Cannot disable snooping on psm:%d", psm);
  }
  }

  Classic().RegisterPsm(psm, callbacks);
  Classic().RegisterPsm(psm, callbacks);


  std::promise<void> register_completed;
  std::promise<void> register_completed;
@@ -188,11 +185,9 @@ void bluetooth::legacy::shim::L2cap::OnRemoteInitiatedConnectionCreated(


  CHECK(!ConnectionExists(cid));
  CHECK(!ConnectionExists(cid));
  cid_to_psm_map_[cid] = psm;
  cid_to_psm_map_[cid] = psm;
  SetCallbacks(cid, Classic().Callbacks(psm));
  SetDownstreamCallbacks(cid);
  const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
  Classic().Callbacks(psm)->pL2CA_ConnectInd_Cb(raw_address, cid, psm,
  CHECK(callbacks != nullptr);
                                                kUnusedId);
  callbacks->pL2CA_ConnectInd_Cb(raw_address, cid, psm /* UNUSED */,
                                 0 /* UNUSED */);
}
}


void bluetooth::legacy::shim::L2cap::UnregisterService(uint16_t psm) {
void bluetooth::legacy::shim::L2cap::UnregisterService(uint16_t psm) {
@@ -205,7 +200,6 @@ void bluetooth::legacy::shim::L2cap::UnregisterService(uint16_t psm) {
  // TODO(cmanton) Check for open channels before unregistering
  // TODO(cmanton) Check for open channels before unregistering
  bluetooth::shim::GetL2cap()->UnregisterService(psm);
  bluetooth::shim::GetL2cap()->UnregisterService(psm);
  Classic().UnregisterPsm(psm);
  Classic().UnregisterPsm(psm);
  Classic().DeallocatePsm(psm);
}
}


uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
@@ -241,8 +235,8 @@ uint16_t bluetooth::legacy::shim::L2cap::CreateConnection(
              " connection_interface_descriptor:%hd",
              " connection_interface_descriptor:%hd",
              psm, raw_address.ToString().c_str(), cid);
              psm, raw_address.ToString().c_str(), cid);
    CHECK(!ConnectionExists(cid));
    CHECK(!ConnectionExists(cid));
    cid_to_callback_map_[cid] = Classic().Callbacks(psm);
    cid_to_psm_map_[cid] = psm;
    cid_to_psm_map_[cid] = psm;
    SetCallbacks(cid, Classic().Callbacks(psm));
  }
  }
  return cid;
  return cid;
}
}
@@ -253,11 +247,13 @@ void bluetooth::legacy::shim::L2cap::OnLocalInitiatedConnectionCreated(
            "Sending connection confirm to the upper stack but really "
            "Sending connection confirm to the upper stack but really "
            "a connection to %s has already been done cid:%hd",
            "a connection to %s has already been done cid:%hd",
            string_address.c_str(), cid);
            string_address.c_str(), cid);
  // TODO(cmanton) Make sure the device is correct for locally initiated
  uint16_t status = kConnectionFail;
  const tL2CAP_APPL_INFO* callbacks = Classic().Callbacks(psm);
  if (cid != kInvalidConnectionInterfaceDescriptor) {
  CHECK(callbacks != nullptr);
    SetDownstreamCallbacks(cid);
  callbacks->pL2CA_ConnectCfm_Cb(cid, kConnectionSuccess);
    status = kConnectionSuccess;
};
  }
  Classic().Callbacks(psm)->pL2CA_ConnectCfm_Cb(cid, status);
}


bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
  CHECK(bt_hdr != nullptr);
@@ -271,40 +267,7 @@ bool bluetooth::legacy::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
  return true;
  return true;
}
}


bool bluetooth::legacy::shim::L2cap::WriteFlushable(uint16_t cid,
void bluetooth::legacy::shim::L2cap::SetDownstreamCallbacks(uint16_t cid) {
                                                    BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
  size_t len = bt_hdr->len;
  if (!ConnectionExists(cid) || len == 0) {
    return false;
  }
  bluetooth::shim::GetL2cap()->WriteFlushable(cid, data, len);
  return true;
}

bool bluetooth::legacy::shim::L2cap::WriteNonFlushable(uint16_t cid,
                                                       BT_HDR* bt_hdr) {
  CHECK(bt_hdr != nullptr);
  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
  size_t len = bt_hdr->len;
  if (!ConnectionExists(cid) || len == 0) {
    return false;
  }
  bluetooth::shim::GetL2cap()->WriteNonFlushable(cid, data, len);
  return true;
}

bool bluetooth::legacy::shim::L2cap::SetCallbacks(
    uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
  CHECK(callbacks != nullptr);
  CHECK(ConnectionExists(cid));
  LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
      << "Already have callbacks registered for "
         "connection_interface_descriptor:"
      << cid;
  cid_to_callback_map_[cid] = callbacks;

  bluetooth::shim::GetL2cap()->SetReadDataReadyCallback(
  bluetooth::shim::GetL2cap()->SetReadDataReadyCallback(
      cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
      cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
        LOG_DEBUG(LOG_TAG, "OnDataReady cid:%hd len:%zd", cid, data.size());
        LOG_DEBUG(LOG_TAG, "OnDataReady cid:%hd len:%zd", cid, data.size());
@@ -319,20 +282,23 @@ bool bluetooth::legacy::shim::L2cap::SetCallbacks(
  bluetooth::shim::GetL2cap()->SetConnectionClosedCallback(
  bluetooth::shim::GetL2cap()->SetConnectionClosedCallback(
      cid, [this](uint16_t cid, int error_code) {
      cid, [this](uint16_t cid, int error_code) {
        LOG_DEBUG(LOG_TAG, "OnChannel closed callback cid:%hd", cid);
        LOG_DEBUG(LOG_TAG, "OnChannel closed callback cid:%hd", cid);
        if (cid_to_callback_map_.find(cid) != cid_to_callback_map_.end()) {
        if (cid_to_callback_map_.find(cid) == cid_to_callback_map_.end()) {
          cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(
              cid, kDisconnectResponseRequired);
          cid_to_callback_map_.erase(cid);
        } else if (cid_closing_set_.count(cid) == 1) {
          cid_closing_set_.erase(cid);
        } else {
          LOG_WARN(LOG_TAG, "%s Unexpected channel closure cid:%hd", __func__,
          LOG_WARN(LOG_TAG, "%s Unexpected channel closure cid:%hd", __func__,
                   cid);
                   cid);
          return;
        }
        }
        CHECK(cid_to_psm_map_.find(cid) != cid_to_psm_map_.end());
        CHECK(cid_to_psm_map_.find(cid) != cid_to_psm_map_.end());
        cid_to_psm_map_.erase(cid);
        cid_to_psm_map_.erase(cid);

        if (cid_closing_set_.count(cid) == 1) {
          cid_closing_set_.erase(cid);
          cid_to_callback_map_[cid]->pL2CA_DisconnectCfm_Cb(cid, kUnusedResult);
        } else {
          cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(
              cid, kDisconnectResponseRequired);
        }
        cid_to_callback_map_.erase(cid);
      });
      });
  return true;
}
}


bool bluetooth::legacy::shim::L2cap::ConnectResponse(
bool bluetooth::legacy::shim::L2cap::ConnectResponse(
@@ -353,8 +319,6 @@ bool bluetooth::legacy::shim::L2cap::ConfigRequest(


  bluetooth::shim::GetL2cap()->SendLoopbackResponse([this, cid]() {
  bluetooth::shim::GetL2cap()->SendLoopbackResponse([this, cid]() {
    CHECK(ConnectionExists(cid));
    CHECK(ConnectionExists(cid));
    const tL2CAP_APPL_INFO* callbacks = cid_to_callback_map_[cid];
    CHECK(callbacks != nullptr);
    tL2CAP_CFG_INFO cfg_info{
    tL2CAP_CFG_INFO cfg_info{
        .result = L2CAP_CFG_OK,
        .result = L2CAP_CFG_OK,
        .mtu_present = false,
        .mtu_present = false,
@@ -365,8 +329,8 @@ bool bluetooth::legacy::shim::L2cap::ConfigRequest(
        .ext_flow_spec_present = false,
        .ext_flow_spec_present = false,
        .flags = 0,
        .flags = 0,
    };
    };
    callbacks->pL2CA_ConfigCfm_Cb(cid, &cfg_info);
    cid_to_callback_map_[cid]->pL2CA_ConfigCfm_Cb(cid, &cfg_info);
    callbacks->pL2CA_ConfigInd_Cb(cid, &cfg_info);
    cid_to_callback_map_[cid]->pL2CA_ConfigInd_Cb(cid, &cfg_info);
  });
  });
  return true;
  return true;
}
}
@@ -384,9 +348,8 @@ bool bluetooth::legacy::shim::L2cap::ConfigResponse(
bool bluetooth::legacy::shim::L2cap::DisconnectRequest(uint16_t cid) {
bool bluetooth::legacy::shim::L2cap::DisconnectRequest(uint16_t cid) {
  CHECK(ConnectionExists(cid));
  CHECK(ConnectionExists(cid));
  LOG_DEBUG(LOG_TAG, "%s cid:%hu", __func__, cid);
  LOG_DEBUG(LOG_TAG, "%s cid:%hu", __func__, cid);
  bluetooth::shim::GetL2cap()->CloseConnection(cid);
  cid_to_callback_map_.erase(cid);
  cid_closing_set_.insert(cid);
  cid_closing_set_.insert(cid);
  bluetooth::shim::GetL2cap()->CloseConnection(cid);
  return true;
  return true;
}
}


+14 −10
Original line number Original line Diff line number Diff line
@@ -33,19 +33,25 @@ static constexpr uint16_t kFinalClassicVirtualPsm = 0x8000;
static constexpr uint16_t kInitialLeDynamicPsm = 0x0080;
static constexpr uint16_t kInitialLeDynamicPsm = 0x0080;
static constexpr uint16_t kFinalLeDynamicPsm = 0x00ff;
static constexpr uint16_t kFinalLeDynamicPsm = 0x00ff;


using PsmData = struct {
struct PsmData {
  bool IsPsmAllocated(uint16_t psm) const;
  bool IsPsmRegistered(uint16_t psm) const;
  bool IsPsmRegistered(uint16_t psm) const;

  bool HasClient(uint16_t psm) const;
  void AllocatePsm(uint16_t psm);
  void RegisterPsm(uint16_t psm, const tL2CAP_APPL_INFO* callbacks);
  void RegisterPsm(uint16_t psm, const tL2CAP_APPL_INFO* callbacks);

  void RegisterPsm(uint16_t psm);
  void UnregisterPsm(uint16_t psm);
  void UnregisterPsm(uint16_t psm);
  void DeallocatePsm(uint16_t psm);

  const tL2CAP_APPL_INFO* Callbacks(uint16_t psm);
  const tL2CAP_APPL_INFO* Callbacks(uint16_t psm);


 private:
 private:
  /**
   * Mapping of psm to client callback.
   *
   * The current API allows a client may reserve a psm but not
   * provide a callback which is reflected in a mapping of a
   * valid psm key entry but a nullptr value.
   *
   * A valid client is indicated with a valid psm key entry and a
   * non-nullptr value.
   */
  std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> psm_to_callback_map_;
  std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> psm_to_callback_map_;
};
};


@@ -58,8 +64,6 @@ class L2cap {
  uint16_t CreateConnection(uint16_t psm, const RawAddress& raw_address);
  uint16_t CreateConnection(uint16_t psm, const RawAddress& raw_address);


  bool Write(uint16_t cid, BT_HDR* bt_hdr);
  bool Write(uint16_t cid, BT_HDR* bt_hdr);
  bool WriteFlushable(uint16_t cid, BT_HDR* bt_hdr);
  bool WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr);


  void OnLocalInitiatedConnectionCreated(std::string string_address,
  void OnLocalInitiatedConnectionCreated(std::string string_address,
                                         uint16_t psm, uint16_t cid);
                                         uint16_t psm, uint16_t cid);
@@ -90,7 +94,7 @@ class L2cap {


 private:
 private:
  uint16_t GetNextVirtualPsm(uint16_t real_psm);
  uint16_t GetNextVirtualPsm(uint16_t real_psm);
  bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* callbacks);
  void SetDownstreamCallbacks(uint16_t cid);


  PsmData classic_;
  PsmData classic_;
  PsmData le_;
  PsmData le_;