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

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

L2CAP SignallingManager: Store command_just_sent

Instead of storing it in pending_commands_ *after* a command is sent, we
use a separate variable command_just_sent_ to store it, to avoid state
corruption

Test: bluetooth_test_gd and run_cert.sh
Bug: 145622504
Change-Id: I5992b3545c04ec2bc36fcc43ae84b81a6b26eb8f
parent d91d1b19
Loading
Loading
Loading
Loading
+50 −70
Original line number Diff line number Diff line
@@ -56,18 +56,11 @@ ClassicSignallingManager::~ClassicSignallingManager() {
}

void ClassicSignallingManager::OnCommandReject(CommandRejectView command_reject_view) {
  if (pending_commands_.empty()) {
  if (command_just_sent_.signal_id_ != command_reject_view.GetIdentifier() ||
      command_just_sent_.command_code_ != command_reject_view.GetCode()) {
    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) {
    LOG_WARN("Unknown command reject");
    return;
  }
  alarm_.Cancel();
  handle_send_next_command();

@@ -78,7 +71,7 @@ void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
  PendingCommand pending_command = {next_signal_id_, CommandCode::CONNECTION_REQUEST, psm, local_cid, {}, {}, {}};
  next_signal_id_++;
  pending_commands_.push(std::move(pending_command));
  if (pending_commands_.size() == 1) {
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    handle_send_next_command();
  }
}
@@ -89,7 +82,7 @@ void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid,
                                    std::move(config)};
  next_signal_id_++;
  pending_commands_.push(std::move(pending_command));
  if (pending_commands_.size() == 1) {
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    handle_send_next_command();
  }
}
@@ -99,7 +92,7 @@ void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remot
      next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
  next_signal_id_++;
  pending_commands_.push(std::move(pending_command));
  if (pending_commands_.size() == 1) {
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    handle_send_next_command();
  }
}
@@ -108,7 +101,7 @@ void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType
  PendingCommand pending_command = {next_signal_id_, CommandCode::INFORMATION_REQUEST, {}, {}, {}, type, {}};
  next_signal_id_++;
  pending_commands_.push(std::move(pending_command));
  if (pending_commands_.size() == 1) {
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    handle_send_next_command();
  }
}
@@ -200,28 +193,26 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm,

void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
                                                    ConnectionResponseResult result, ConnectionResponseStatus status) {
  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");
  if (command_just_sent_.signal_id_ != signal_id ||
      command_just_sent_.command_code_ != CommandCode::CONNECTION_REQUEST) {
    LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
             command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
             signal_id.Value());
    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 (command_just_sent_.source_cid_ != cid) {
    LOG_WARN("SCID doesn't match: expected %d, received %d", command_just_sent_.source_cid_, cid);
    handle_send_next_command();
    return;
  }
  command_just_sent_.signal_id_ = kInvalidSignalId;
  alarm_.Cancel();
  if (result != ConnectionResponseResult::SUCCESS) {
    link_->OnOutgoingConnectionRequestFail(cid);
    handle_send_next_command();
    return;
  }
  Psm pending_psm = last_sent_command.psm_;
  Psm pending_psm = command_just_sent_.psm_;
  auto new_channel = link_->AllocateReservedDynamicChannel(cid, pending_psm, remote_cid, {});
  if (new_channel == nullptr) {
    LOG_WARN("Can't allocate dynamic channel");
@@ -336,14 +327,14 @@ 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>> options) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
  if (command_just_sent_.signal_id_ != signal_id ||
      command_just_sent_.command_code_ != CommandCode::CONFIGURATION_REQUEST) {
    LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
             command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
             signal_id.Value());
    return;
  }

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

  auto channel = channel_allocator_->FindChannelByCid(cid);
  if (channel == nullptr) {
    LOG_WARN("Configuration request for an unknown channel");
@@ -413,18 +404,15 @@ void ClassicSignallingManager::OnDisconnectionRequest(SignalId signal_id, Cid ci
}

void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
  if (command_just_sent_.signal_id_ != signal_id ||
      command_just_sent_.command_code_ != CommandCode::DISCONNECTION_REQUEST) {
    LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
             command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
             signal_id.Value());
    return;
  }
  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();
  alarm_.Cancel();

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

  auto channel = channel_allocator_->FindChannelByCid(cid);
  if (channel == nullptr) {
@@ -447,14 +435,10 @@ void ClassicSignallingManager::OnEchoRequest(SignalId signal_id, const PacketVie
}

void ClassicSignallingManager::OnEchoResponse(SignalId signal_id, const PacketView<kLittleEndian>& packet) {
  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) {
  if (command_just_sent_.signal_id_ != signal_id || command_just_sent_.command_code_ != CommandCode::ECHO_REQUEST) {
    LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
             command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
             signal_id.Value());
    return;
  }
  LOG_INFO("Echo response received");
@@ -487,15 +471,11 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat
}

void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
  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) {
  if (command_just_sent_.signal_id_ != signal_id ||
      command_just_sent_.command_code_ != CommandCode::INFORMATION_REQUEST) {
    LOG_WARN("Unexpected response: no pending request. Expected signal id %d type %s, got %d",
             command_just_sent_.signal_id_.Value(), CommandCodeText(command_just_sent_.command_code_).data(),
             signal_id.Value());
    return;
  }

@@ -659,20 +639,18 @@ void ClassicSignallingManager::send_connection_response(SignalId signal_id, Cid

void ClassicSignallingManager::on_command_timeout() {
  LOG_WARN("Response time out");
  if (pending_commands_.empty()) {
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    LOG_ERROR("No pending command");
    return;
  }

  auto last_sent_command = std::move(pending_commands_.front());
  pending_commands_.pop();
  switch (last_sent_command.command_code_) {
  switch (command_just_sent_.command_code_) {
    case CommandCode::CONNECTION_REQUEST: {
      link_->OnOutgoingConnectionRequestFail(last_sent_command.source_cid_);
      link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_);
      break;
    }
    case CommandCode::CONFIGURATION_REQUEST: {
      SendDisconnectionRequest(last_sent_command.source_cid_, last_sent_command.destination_cid_);
      SendDisconnectionRequest(command_just_sent_.source_cid_, command_just_sent_.destination_cid_);
      break;
    }
    default:
@@ -682,18 +660,20 @@ void ClassicSignallingManager::on_command_timeout() {
}

void ClassicSignallingManager::handle_send_next_command() {
  command_just_sent_.signal_id_ = kInvalidSignalId;
  if (pending_commands_.empty()) {
    return;
  }
  auto& last_sent_command = pending_commands_.front();
  command_just_sent_ = std::move(pending_commands_.front());
  pending_commands_.pop();

  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 = command_just_sent_.signal_id_;
  auto psm = command_just_sent_.psm_;
  auto source_cid = command_just_sent_.source_cid_;
  auto destination_cid = command_just_sent_.destination_cid_;
  auto info_type = command_just_sent_.info_type_;
  auto config = std::move(command_just_sent_.config_);
  switch (command_just_sent_.command_code_) {
    case CommandCode::CONNECTION_REQUEST: {
      auto builder = ConnectionRequestBuilder::Create(signal_id.Value(), psm, source_cid);
      enqueue_buffer_->Enqueue(std::move(builder), handler_);
@@ -724,7 +704,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>(command_just_sent_.command_code_));
  }
}

+2 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ namespace classic {
namespace internal {

struct PendingCommand {
  SignalId signal_id_;
  SignalId signal_id_ = kInvalidSignalId;
  CommandCode command_code_;
  Psm psm_;
  Cid source_cid_;
@@ -113,6 +113,7 @@ class ClassicSignallingManager {
  FixedChannelServiceManagerImpl* fixed_service_manager_;
  std::unique_ptr<os::EnqueueBuffer<packet::BasePacketBuilder>> enqueue_buffer_;
  std::queue<PendingCommand> pending_commands_;
  PendingCommand command_just_sent_;
  os::Alarm alarm_;
  SignalId next_signal_id_ = kInitialSignalId;
  std::unordered_map<Cid, ChannelConfigurationState> channel_configuration_;
+1 −2
Original line number Diff line number Diff line
@@ -98,7 +98,6 @@ void LeSignallingManager::OnCommandReject(LeCommandRejectView command_reject_vie
    return;
  }
  alarm_.Cancel();
  command_just_sent_.signal_id_ = kInitialSignalId;
  handle_send_next_command();

  LOG_WARN("Command rejected");
@@ -365,7 +364,6 @@ void LeSignallingManager::on_command_timeout() {
    LOG_ERROR("No pending command");
    return;
  }
  command_just_sent_.signal_id_ = kInvalidSignalId;
  switch (command_just_sent_.command_code_) {
    case LeCommandCode::CONNECTION_PARAMETER_UPDATE_REQUEST: {
      link_->OnOutgoingConnectionRequestFail(command_just_sent_.source_cid_);
@@ -378,6 +376,7 @@ void LeSignallingManager::on_command_timeout() {
}

void LeSignallingManager::handle_send_next_command() {
  command_just_sent_.signal_id_ = kInvalidSignalId;
  if (pending_commands_.empty()) {
    return;
  }
+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ namespace le {
namespace internal {

struct PendingCommand {
  SignalId signal_id_ = kInitialSignalId;
  SignalId signal_id_ = kInvalidSignalId;
  LeCommandCode command_code_;
  Psm psm_;
  Cid source_cid_;
@@ -99,7 +99,7 @@ class LeSignallingManager {

  os::Handler* handler_;
  Link* link_;
  [[maybe_unused]] l2cap::internal::DataPipelineManager* data_pipeline_manager_;
  l2cap::internal::DataPipelineManager* data_pipeline_manager_;
  std::shared_ptr<le::internal::FixedChannelImpl> signalling_channel_;
  DynamicChannelServiceManagerImpl* dynamic_service_manager_;
  l2cap::internal::DynamicChannelAllocator* channel_allocator_;