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

Commit b16c44c5 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I9693f8e4,I3568a3dc

* changes:
  L2CAP Classic Cert: Auto generate cid for incoming request
  L2CAP: Fix SignallingManager request queuing
parents 66f6fddc 5e216093
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -59,5 +59,6 @@ message DisconnectionRequest {
message FetchOpenedChannelsRequest {}

message FetchOpenedChannelsResponse {
  repeated uint32 cid = 1;
  repeated uint32 scid = 1;
  repeated uint32 dcid = 2;
}
 No newline at end of file
+44 −35
Original line number Diff line number Diff line
@@ -92,48 +92,52 @@ class L2capModuleCertService : public L2capModuleCert::Service {
    packet->AddOctets(std::vector<uint8_t>(req_string.begin(), req_string.end()));
    std::unique_ptr<BasicFrameBuilder> l2cap_builder = BasicFrameBuilder::Create(request->channel(), std::move(packet));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }
    send_packet_from_queue();
    return ::grpc::Status::OK;
  }

  static constexpr Cid kFirstDynamicChannelForIncomingRequest = kFirstDynamicChannel + 0x100;

  ::grpc::Status SendConnectionRequest(::grpc::ServerContext* context, const cert::ConnectionRequest* request,
                                       ::google::protobuf::Empty* response) override {
    auto builder = ConnectionRequestBuilder::Create(1, 1, request->scid());
    auto scid = request->scid();
    if (last_connection_request_scid_ != kInvalidCid) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Another connection request is pending");
    }
    if (scid >= kFirstDynamicChannelForIncomingRequest) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Use scid < kFirstDynamicChannelForIncomingRequest");
    }
    for (const auto& cid_pair : open_channels_scid_dcid_) {
      if (cid_pair.first == scid) {
        return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "SCID already taken");
      }
    }
    auto builder = ConnectionRequestBuilder::Create(1, request->psm(), scid);
    auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }

    send_packet_from_queue();
    last_connection_request_scid_ = scid;
    return ::grpc::Status::OK;
  }
  Cid last_connection_request_scid_ = kInvalidCid;
  Cid next_incoming_request_cid_ = kFirstDynamicChannelForIncomingRequest;

  ::grpc::Status SendConfigurationRequest(
      ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::ConfigurationRequest* request,
      ::bluetooth::l2cap::classic::cert::SendConfigurationRequestResult* response) override {
    auto builder = ConfigurationRequestBuilder::Create(1, request->scid(), Continuation::END, {});
    auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder));
    auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }
    send_packet_from_queue();
    return ::grpc::Status::OK;
  }

  ::grpc::Status SendDisconnectionRequest(::grpc::ServerContext* context, const cert::DisconnectionRequest* request,
                                          ::google::protobuf::Empty* response) override {
    auto builder = DisconnectionRequestBuilder::Create(3, 0x40, 101);
    auto l2cap_builder = BasicFrameBuilder::Create(1, std::move(builder));
    auto builder = DisconnectionRequestBuilder::Create(3, request->dcid(), request->scid());
    auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
    outgoing_packet_queue_.push(std::move(l2cap_builder));
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }
    send_packet_from_queue();

    return ::grpc::Status::OK;
  }
@@ -141,10 +145,13 @@ class L2capModuleCertService : public L2capModuleCert::Service {
  ::grpc::Status FetchOpenedChannels(
      ::grpc::ServerContext* context, const ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsRequest* request,
      ::bluetooth::l2cap::classic::cert::FetchOpenedChannelsResponse* response) override {
    response->mutable_cid()->Add(open_channels_.begin(), open_channels_.end());
    for (const auto& cid_pair : open_channels_scid_dcid_) {
      response->mutable_scid()->Add(cid_pair.first);
      response->mutable_dcid()->Add(cid_pair.second);
    }
    return ::grpc::Status::OK;
  }
  std::vector<uint16_t> open_channels_;
  std::vector<std::pair<uint16_t, uint16_t>> open_channels_scid_dcid_;

  std::unique_ptr<packet::BasePacketBuilder> enqueue_packet_to_acl() {
    auto basic_frame_builder = std::move(outgoing_packet_queue_.front());
@@ -186,30 +193,35 @@ class L2capModuleCertService : public L2capModuleCert::Service {
    }
  }

  void send_packet_from_queue() {
    if (outgoing_packet_queue_.size() == 1) {
      acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
          handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
    }
  }

  void handle_signalling_packet(ControlView control_view) {
    auto code = control_view.GetCode();
    switch (code) {
      case CommandCode::CONNECTION_REQUEST: {
        ConnectionRequestView view = ConnectionRequestView::Create(control_view);
        ASSERT(view.IsValid());
        open_channels_.push_back(view.GetSourceCid());
        auto builder = ConnectionResponseBuilder::Create(
            view.GetIdentifier(), view.GetSourceCid(), view.GetSourceCid(),
            view.GetIdentifier(), view.GetSourceCid(), next_incoming_request_cid_,
            accept_incoming_connection_ ? ConnectionResponseResult::SUCCESS : ConnectionResponseResult::INVALID_CID,
            ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
        auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
        outgoing_packet_queue_.push(std::move(l2cap_builder));
        if (outgoing_packet_queue_.size() == 1) {
          acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
              handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
        }

        send_packet_from_queue();
        open_channels_scid_dcid_.emplace_back(next_incoming_request_cid_, view.GetSourceCid());
        next_incoming_request_cid_++;
        break;
      }
      case CommandCode::CONNECTION_RESPONSE: {
        ConnectionResponseView view = ConnectionResponseView::Create(control_view);
        ASSERT(view.IsValid());
        open_channels_.push_back(view.GetSourceCid());
        open_channels_scid_dcid_.emplace_back(last_connection_request_scid_, view.GetSourceCid());
        last_connection_request_scid_ = kInvalidCid;
        break;
      }

@@ -221,10 +233,7 @@ class L2capModuleCertService : public L2capModuleCert::Service {
                                                 ConfigurationResponseResult::SUCCESS, {});
        auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
        outgoing_packet_queue_.push(std::move(l2cap_builder));
        if (outgoing_packet_queue_.size() == 1) {
          acl_connection_->GetAclQueueEnd()->RegisterEnqueue(
              handler_, common::Bind(&L2capModuleCertService::enqueue_packet_to_acl, common::Unretained(this)));
        }
        send_packet_from_queue();
        break;
      }
      default:
+17 −8
Original line number Diff line number Diff line
@@ -84,11 +84,11 @@ class SimpleL2capTest(GdBaseTestClass):
        )
        dut_connection_stream.unsubscribe()

        self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101))
        self.cert_device.l2cap.SendConnectionRequest(l2cap_cert_pb2.ConnectionRequest(scid=0x101, psm=1))
        time.sleep(1)

        open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest())
        cid = open_channels.cid[0]
        cid = open_channels.dcid[0]

        dut_packet_stream.subscribe()
        cert_packet_stream.subscribe()
@@ -113,28 +113,37 @@ class SimpleL2capTest(GdBaseTestClass):
            lambda packet: b"abc" in packet.payload
        )

        self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest())
        self.cert_device.l2cap.SendDisconnectionRequest(l2cap_cert_pb2.DisconnectionRequest(dcid=0x40, scid=101))
        time.sleep(1)
        dut_packet_stream.unsubscribe()
        cert_packet_stream.unsubscribe()

    def test_open_two_channels(self):
        cert_connection_stream = self.cert_device.l2cap.connection_complete_stream
        cert_connection_stream.subscribe()
        self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01))
        self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x03))
        cert_connection_stream.assert_event_occurs(
            lambda device: device.remote == self.dut_address
        )
        cert_connection_stream.unsubscribe()
        time.sleep(1)
        open_channels = self.cert_device.l2cap.FetchOpenedChannels(l2cap_cert_pb2.FetchOpenedChannelsRequest())
        assert len(open_channels.dcid) == 2

    def test_basic_operation_request_connection(self):
        """
        L2CAP/COS/CED/BV-01-C [Request Connection]
        Verify that the IUT is able to request the connection establishment for an L2CAP data channel and
        initiate the configuration procedure.
        """
        self.device_under_test.l2cap.RegisterChannel(l2cap_facade_pb2.RegisterChannelRequest(channel=2))
        cert_connection_stream = self.cert_device.l2cap.connection_complete_stream
        cert_connection_stream.subscribe()
        self.device_under_test.l2cap.Connect(self.cert_address)
        self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01))
        cert_connection_stream.assert_event_occurs(
            lambda device: device.remote == self.dut_address
        )
        cert_connection_stream.unsubscribe()
        self.device_under_test.l2cap.OpenChannel(l2cap_facade_pb2.OpenChannelRequest(remote=self.cert_address, psm=0x01))
        time.sleep(1)


    def test_respond_to_echo_request(self):
        """
+63 −24
Original line number Diff line number Diff line
@@ -52,8 +52,15 @@ ClassicSignallingManager::~ClassicSignallingManager() {
}

void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected command reject: no pending request");
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();

  SignalId signal_id = command_reject_view.GetIdentifier();
  if (last_sent_command_.signal_id_ != signal_id) {
  if (last_sent_command.signal_id_ != signal_id) {
    LOG_WARN("Unknown command reject");
    return;
  }
@@ -147,20 +154,24 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm,

void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid,
                                                    ConnectionResponseResult result, ConnectionResponseStatus status) {
  if (last_sent_command_.signal_id_ != signal_id ||
      last_sent_command_.command_code_ != CommandCode::CONNECTION_REQUEST) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();
  if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::CONNECTION_REQUEST) {
    LOG_WARN("Received unexpected connection response");
    return;
  }
  if (last_sent_command_.source_cid_ != cid) {
    LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command_.source_cid_, cid);
  if (last_sent_command.source_cid_ != cid) {
    LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command.source_cid_, cid);
    return;
  }
  if (result != ConnectionResponseResult::SUCCESS) {
    return;
  }
  Psm pending_psm = last_sent_command_.psm_;
  last_sent_command_ = {};
  Psm pending_psm = last_sent_command.psm_;
  auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {});
  if (new_channel == nullptr) {
    LOG_WARN("Can't allocate dynamic channel");
@@ -188,7 +199,15 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci

void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid cid, Continuation is_continuation,
                                                       ConfigurationResponseResult result,
                                                       std::vector<std::unique_ptr<ConfigurationOption>> option) {}
                                                       std::vector<std::unique_ptr<ConfigurationOption>> option) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
  }

  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();
}

void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid cid, Cid remote_cid) {
  // TODO: check cid match
@@ -204,8 +223,15 @@ void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid ci
}

void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid cid, Cid remote_cid) {
  if (last_sent_command_.signal_id_ != signal_id ||
      last_sent_command_.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();

  if (last_sent_command.signal_id_ != signal_id ||
      last_sent_command.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
    return;
  }

@@ -228,7 +254,14 @@ void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketVie
}

void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
  if (last_sent_command_.signal_id_ != signal_id || last_sent_command_.command_code_ != CommandCode::ECHO_REQUEST) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();

  if (last_sent_command.signal_id_ != signal_id || last_sent_command.command_code_ != CommandCode::ECHO_REQUEST) {
    return;
  }
  LOG_INFO("Echo response received");
@@ -259,8 +292,15 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat
}

void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) {
  if (last_sent_command_.signal_id_ != signal_id ||
      last_sent_command_.command_code_ != CommandCode::INFORMATION_REQUEST) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();

  if (last_sent_command.signal_id_ != signal_id ||
      last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) {
    return;
  }
  if (view.GetResult() != InformationRequestResult::SUCCESS) {
@@ -395,16 +435,15 @@ void ClassicSignallingManager::handle_send_next_command() {
  if (pending_commands_.empty()) {
    return;
  }
  last_sent_command_ = std::move(pending_commands_.front());
  pending_commands_.pop();
  auto& last_sent_command = pending_commands_.front();

  auto signal_id = last_sent_command_.signal_id_;
  auto psm = last_sent_command_.psm_;
  auto source_cid = last_sent_command_.source_cid_;
  auto destination_cid = last_sent_command_.destination_cid_;
  auto info_type = last_sent_command_.info_type_;
  auto config = std::move(last_sent_command_.config_);
  switch (last_sent_command_.command_code_) {
  auto signal_id = last_sent_command.signal_id_;
  auto psm = last_sent_command.psm_;
  auto source_cid = last_sent_command.source_cid_;
  auto destination_cid = last_sent_command.destination_cid_;
  auto info_type = last_sent_command.info_type_;
  auto config = std::move(last_sent_command.config_);
  switch (last_sent_command.command_code_) {
    case CommandCode::CONNECTION_REQUEST: {
      auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
      enqueue_buffer_->Enqueue(std::move(builder), handler_);
@@ -435,7 +474,7 @@ void ClassicSignallingManager::handle_send_next_command() {
      break;
    }
    default:
      LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command_.command_code_));
      LOG_WARN("Unsupported command code 0x%x", static_cast<int>(last_sent_command.command_code_));
  }
}