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

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

L2CAP: Dequeue next request if previous response is invalid

If we drop the invalid response packet without dequeuing next request,
the outgoing request queue will stuck. We should dequeue it as long as
the signalling id matches.

Also fix the scid/dcid mismatch in cert stack.

Test: cert/run_cert.sh. test_open_two_channels should be fixed.
Bug: 141557006
Change-Id: Id4dd9f279ece55aa5e78443c8027df91af1dd7c8
parent b76d1fa9
Loading
Loading
Loading
Loading
+37 −1
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ class L2capModuleCertService : public L2capModuleCert::Service {
        ConnectionRequestView view = ConnectionRequestView::Create(control_view);
        ASSERT(view.IsValid());
        auto builder = ConnectionResponseBuilder::Create(
            view.GetIdentifier(), view.GetSourceCid(), next_incoming_request_cid_,
            view.GetIdentifier(), next_incoming_request_cid_, view.GetSourceCid(),
            accept_incoming_connection_ ? ConnectionResponseResult::SUCCESS : ConnectionResponseResult::INVALID_CID,
            ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
        auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
@@ -236,6 +236,42 @@ class L2capModuleCertService : public L2capModuleCert::Service {
        send_packet_from_queue();
        break;
      }
      case CommandCode::INFORMATION_REQUEST: {
        InformationRequestView information_request_view = InformationRequestView::Create(control_view);
        if (!information_request_view.IsValid()) {
          return;
        }
        auto type = information_request_view.GetInfoType();
        switch (type) {
          case InformationRequestInfoType::CONNECTIONLESS_MTU: {
            auto response = InformationResponseConnectionlessMtuBuilder::Create(
                information_request_view.GetIdentifier(), InformationRequestResult::NOT_SUPPORTED, 0);
            auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(response));
            outgoing_packet_queue_.push(std::move(l2cap_builder));
            send_packet_from_queue();
            break;
          }
          case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
            // TODO: implement this response
            auto response = InformationResponseExtendedFeaturesBuilder::Create(information_request_view.GetIdentifier(),
                                                                               InformationRequestResult::NOT_SUPPORTED,
                                                                               0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
            auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(response));
            outgoing_packet_queue_.push(std::move(l2cap_builder));
            send_packet_from_queue();
            break;
          }
          case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
            constexpr uint64_t kSignallingChannelMask = 0x02;
            auto response = InformationResponseFixedChannelsBuilder::Create(
                information_request_view.GetIdentifier(), InformationRequestResult::SUCCESS, kSignallingChannelMask);
            auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(response));
            outgoing_packet_queue_.push(std::move(l2cap_builder));
            send_packet_from_queue();
            break;
          }
        }
      }
      default:
        return;
    }
+9 −7
Original line number Diff line number Diff line
@@ -166,15 +166,18 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remo
  }
  if (last_sent_command.source_cid_ != cid) {
    LOG_WARN("SCID doesn't match: expected %d, received %d", last_sent_command.source_cid_, cid);
    handle_send_next_command();
    return;
  }
  if (result != ConnectionResponseResult::SUCCESS) {
    handle_send_next_command();
    return;
  }
  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");
    handle_send_next_command();
    return;
  }
  std::unique_ptr<DynamicChannel> channel = std::make_unique<DynamicChannel>(new_channel, handler_);
@@ -211,6 +214,7 @@ void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid c
  auto channel = channel_allocator_->FindChannelByRemoteCid(cid);
  if (channel == nullptr) {
    LOG_WARN("Configuration request for an unknown channel");
    handle_send_next_command();
    return;
  }
  // TODO(cmanton) verify configuration parameters are satisfied
@@ -248,6 +252,7 @@ void ClassicSignallingManager::OnDisconnectionResponse(SignalId signal_id, Cid c
  auto channel = channel_allocator_->FindChannelByCid(cid);
  if (channel == nullptr) {
    LOG_WARN("Disconnect response for an unknown channel");
    handle_send_next_command();
    return;
  }

@@ -286,23 +291,22 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat
      auto response = InformationResponseConnectionlessMtuBuilder::Create(signal_id.Value(),
                                                                          InformationRequestResult::NOT_SUPPORTED, 0);
      enqueue_buffer_->Enqueue(std::move(response), handler_);
      return;
      break;
    }
    case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
      // TODO: implement this response
      auto response = InformationResponseExtendedFeaturesBuilder::Create(
          signal_id.Value(), InformationRequestResult::NOT_SUPPORTED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
      enqueue_buffer_->Enqueue(std::move(response), handler_);
      return;
      break;
    }
    case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
      auto response = InformationResponseFixedChannelsBuilder::Create(
          signal_id.Value(), InformationRequestResult::SUCCESS, fixed_service_manager_->GetSupportedFixedChannelMask());
      enqueue_buffer_->Enqueue(std::move(response), handler_);
      return;
      break;
    }
  }
  handle_send_next_command();
}

void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) {
@@ -317,9 +321,7 @@ void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const I
      last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) {
    return;
  }
  if (view.GetResult() != InformationRequestResult::SUCCESS) {
    return;
  }
  // TODO (hsz): Store the information response
  handle_send_next_command();
}