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

Commit b42d6d7a authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2CAP Reassembler: Keep a reference to DynamicChannelImpl

Since we store configuration in ChannelImpl now, we can store a
reference in Reassembler to read the configuration, and in the future,
signal ReqSeq.

Bug: 141557006
Test: bluetooth_test_gd and run_cert.sh
Change-Id: I353f27c3296f289858ea03da7f8f6ddd1af67ad0
parent 95a82cca
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ class DynamicChannelImpl {
  Mtu incoming_mtu_ = kDefaultClassicMtu;
  RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
  // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
  FcsType fcs_type_ = FcsType::NO_FCS;
  FcsType fcs_type_ = FcsType::DEFAULT;

  DISALLOW_COPY_AND_ASSIGN(DynamicChannelImpl);
};
+3 −3
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ void Link::Disconnect() {
std::shared_ptr<FixedChannelImpl> Link::AllocateFixedChannel(Cid cid, SecurityPolicy security_policy) {
  auto channel = fixed_channel_allocator_.AllocateChannel(cid, security_policy);
  scheduler_->AttachChannel(cid, channel->GetQueueDownEnd(), cid);
  reassembler_.AttachChannel(cid, channel->GetQueueDownEnd(), {});
  reassembler_.AttachChannel(cid, channel->GetQueueDownEnd(), nullptr);
  return channel;
}

@@ -89,7 +89,7 @@ std::shared_ptr<DynamicChannelImpl> Link::AllocateDynamicChannel(Psm psm, Cid re
  auto channel = dynamic_channel_allocator_.AllocateChannel(psm, remote_cid, security_policy);
  if (channel != nullptr) {
    scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel);
  }
  return channel;
}
@@ -99,7 +99,7 @@ std::shared_ptr<DynamicChannelImpl> Link::AllocateReservedDynamicChannel(Cid res
  auto channel = dynamic_channel_allocator_.AllocateReservedChannel(reserved_cid, psm, remote_cid, security_policy);
  if (channel != nullptr) {
    scheduler_->AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel->GetRemoteCid());
    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), {});
    reassembler_.AttachChannel(channel->GetCid(), channel->GetQueueDownEnd(), channel);
  }
  return channel;
}
+7 −7
Original line number Diff line number Diff line
@@ -15,12 +15,12 @@
 */

#include "l2cap/internal/reassembler.h"

#include "common/bidi_queue.h"
#include "l2cap/cid.h"
#include "l2cap/classic/internal/dynamic_channel_impl.h"
#include "l2cap/l2cap_packets.h"
#include "packet/base_packet_builder.h"
#include "packet/packet_view.h"
#

namespace bluetooth {
namespace l2cap {
@@ -37,11 +37,10 @@ Reassembler::~Reassembler() {
}

void Reassembler::AttachChannel(Cid cid, Reassembler::UpperQueueDownEnd* channel_down_end,
                                Reassembler::ChannelConfigurationOptions options) {
                                std::shared_ptr<classic::internal::DynamicChannelImpl> channel) {
  ASSERT_LOG(channel_map_.find(cid) == channel_map_.end(), "Channel is already attached");
  auto pair = ChannelBufferAndOptions(channel_down_end, options);
  channel_map_.emplace(std::piecewise_construct, std::forward_as_tuple(cid),
                       std::forward_as_tuple(channel_down_end, options));
                       std::forward_as_tuple(channel_down_end, channel));
}

void Reassembler::DetachChannel(Cid cid) {
@@ -58,12 +57,13 @@ void Reassembler::link_queue_dequeue_callback() {
  }
  Cid cid = static_cast<Cid>(basic_frame_view.GetChannelId());
  auto channel = channel_map_.find(cid);
  if (channel == channel_map_.end()) {
  if (channel == channel_map_.end() || (cid >= kFirstDynamicChannel && channel->second.channel_ == nullptr)) {
    LOG_WARN("Received a packet with invalid cid: %d", cid);
    return;  // Channel is not attached to scheduler
  }

  auto channel_mode = channel->second.options_.mode_;
  auto channel_mode = cid < kFirstDynamicChannel ? RetransmissionAndFlowControlModeOption::L2CAP_BASIC
                                                 : channel->second.channel_->GetMode();
  switch (channel_mode) {
    case RetransmissionAndFlowControlModeOption::L2CAP_BASIC:
      handle_basic_mode_packet(cid, basic_frame_view);
+18 −14
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <memory>
#include <unordered_map>
#include <utility>

@@ -29,6 +30,13 @@

namespace bluetooth {
namespace l2cap {

namespace classic {
namespace internal {
class DynamicChannelImpl;
}
}  // namespace classic

namespace internal {

/**
@@ -50,18 +58,14 @@ class Reassembler {
  Reassembler(LowerQueueUpEnd* link_queue_up_end, os::Handler* handler);
  ~Reassembler();

  struct ChannelConfigurationOptions {
    Mtu incoming_mtu_ = kDefaultClassicMtu;
    RetransmissionAndFlowControlModeOption mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
    // TODO: Add all RetransmissionAndFlowControlConfigurationOptions
    FcsType fcs_type_ = FcsType::NO_FCS;
  };

  /**
   * Attach a channel for packet reassembly.
   * If the channel is reconfigured, signalling manager should detach channel and attach channel again.
   * If the channel is a dynamic channel, a shared_ptr reference to DynamicChannelImpl is needed to read necessary
   * config. If the channel is a fixed channel, use nullptr.
   * TODO (b/144503952): Rethink about channel abstraction
   */
  void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end, ChannelConfigurationOptions options);
  void AttachChannel(Cid cid, UpperQueueDownEnd* channel_down_end,
                     std::shared_ptr<classic::internal::DynamicChannelImpl> channel);

  /**
   * Detach a channel for packet reassembly. Incoming packets won't be delivered to the specified cid.
@@ -69,16 +73,16 @@ class Reassembler {
  void DetachChannel(Cid cid);

 private:
  struct ChannelBufferAndOptions {
    ChannelBufferAndOptions(UpperQueueDownEnd* queue_end, ChannelConfigurationOptions options)
        : enqueue_buffer_(queue_end), options_(std::move(options)) {}
  struct ChannelBuffer {
    ChannelBuffer(UpperQueueDownEnd* queue_end, std::shared_ptr<classic::internal::DynamicChannelImpl> channel)
        : enqueue_buffer_(queue_end), channel_(std::move(channel)) {}
    os::EnqueueBuffer<UpperEnqueue> enqueue_buffer_;
    ChannelConfigurationOptions options_;
    std::shared_ptr<classic::internal::DynamicChannelImpl> channel_;
  };

  LowerQueueUpEnd* link_queue_up_end_;
  os::Handler* handler_;
  std::unordered_map<Cid, ChannelBufferAndOptions> channel_map_;
  std::unordered_map<Cid, ChannelBuffer> channel_map_;

  void link_queue_dequeue_callback();
  void handle_basic_mode_packet(Cid cid, const BasicFrameView& view);
+3 −3
Original line number Diff line number Diff line
@@ -76,11 +76,11 @@ class L2capClassicReassemblerTest : public ::testing::Test {
  Reassembler* reassembler_ = nullptr;
};

TEST_F(L2capClassicReassemblerTest, receive_basic_mode_packet) {
TEST_F(L2capClassicReassemblerTest, receive_basic_mode_packet_for_fixed_channel) {
  common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_one_queue_{10};
  common::BidiQueue<Reassembler::UpperEnqueue, Reassembler::UpperDequeue> channel_two_queue_{10};
  reassembler_->AttachChannel(1, channel_one_queue_.GetDownEnd(), {});
  reassembler_->AttachChannel(2, channel_two_queue_.GetDownEnd(), {});
  reassembler_->AttachChannel(1, channel_one_queue_.GetDownEnd(), nullptr);
  reassembler_->AttachChannel(2, channel_two_queue_.GetDownEnd(), nullptr);
  os::EnqueueBuffer<Reassembler::UpperEnqueue> link_queue_enqueue_buffer{link_queue_.GetDownEnd()};
  auto packet_one = CreateSampleL2capPacket(1, {1, 2, 3});
  auto packet_two = CreateSampleL2capPacket(2, {4, 5, 6, 7});