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

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

Merge "L2cap SignallingManager fix and improvement"

parents e325a3e8 a4be0ed8
Loading
Loading
Loading
Loading
+24 −23
Original line number Diff line number Diff line
@@ -152,7 +152,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc' * 34)
        assertThat(cert_channel).emits(
@@ -600,7 +600,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        assertThat(cert_channel).emits(
@@ -658,7 +658,7 @@ class L2capTest(GdBaseTestClass):
        self.cert_l2cap.turn_on_ertm()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        assertThat(cert_channel).emits(
@@ -675,7 +675,7 @@ class L2capTest(GdBaseTestClass):
        self.cert_l2cap.turn_on_ertm()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b"abc")
        assertThat(cert_channel).emits(
@@ -727,7 +727,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        assertThat(cert_channel).emits(
@@ -755,7 +755,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        for i in range(3):
            cert_channel.send_i_frame(
@@ -794,7 +794,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        for i in range(3):
            cert_channel.send_i_frame(
@@ -902,7 +902,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        cert_channel.send_s_frame(req_seq=0, p=Poll.POLL)
        assertThat(cert_channel).emits(
@@ -919,7 +919,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)
        dut_channel.send(b'abc')

        assertThat(cert_channel).emits(
@@ -989,8 +989,9 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_unconfigured_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
        config = CertL2cap.config_option_ertm(tx_window_size=2, max_transmit=2)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)
        config = CertL2cap.config_option_ertm(
            tx_window_size=2, max_transmit=2, fcs=FcsType.NO_FCS)
        cert_channel.verify_configuration_request_and_respond(options=config)
        cert_channel.send_configure_request(config)
        cert_channel.verify_configuration_response()
@@ -1087,7 +1088,7 @@ class L2capTest(GdBaseTestClass):
            tx_window_size=tx_window_size, max_transmit=2)

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        cert_channel.send_i_frame(
            tx_seq=0, req_seq=0, f=Final.NOT_SET, payload=SAMPLE_PACKET)
@@ -1122,7 +1123,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')

@@ -1145,7 +1146,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')

@@ -1233,7 +1234,7 @@ class L2capTest(GdBaseTestClass):
        ertm_tx_window_size = 5

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x41, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        cert_channel.send_i_frame(tx_seq=0, req_seq=0, payload=SAMPLE_PACKET)
        assertThat(cert_channel).emits(L2capMatchers.SFrame(req_seq=1))
@@ -1264,7 +1265,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        dut_channel.send(b'abc')
@@ -1297,7 +1298,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        dut_channel.send(b'abc')
@@ -1329,7 +1330,7 @@ class L2capTest(GdBaseTestClass):
        self._setup_link_from_cert()

        (dut_channel, cert_channel) = self._open_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
            mode=RetransmissionFlowControlMode.ERTM, fcs=FcsType.NO_FCS)

        dut_channel.send(b'abc')
        dut_channel.send(b'abc')
@@ -1375,6 +1376,8 @@ class L2capTest(GdBaseTestClass):
        Verify the IUT can accept a Configuration Request from the Lower Tester
        containing an F&EC option that specifies Enhanced Retransmission Mode
        """
        asserts.skip("Need to send ERTM config request when we open from DUT")

        self._setup_link_from_cert()

        self._open_channel_from_dut(
@@ -1435,9 +1438,7 @@ class L2capTest(GdBaseTestClass):
        """
        self._setup_link_from_cert()
        (dut_channel, cert_channel) = self._open_unconfigured_channel_from_cert(
            scid=0x41, psm=0x33, mode=RetransmissionFlowControlMode.ERTM)
        assertThat(self.cert_l2cap.get_control_channel()).emits(
            L2capMatchers.ConfigurationRequest())
        cert_channel.send_configure_request(
            CertL2cap.config_option_basic_explicit())
            mode=RetransmissionFlowControlMode.ERTM)
        cert_channel.verify_configuration_request_and_respond(
            options=CertL2cap.config_option_basic_explicit())
        cert_channel.verify_disconnect_request()
+16 −0
Original line number Diff line number Diff line
@@ -165,6 +165,13 @@ void Link::connect_to_pending_dynamic_channels() {
  }
}

void Link::send_pending_configuration_requests() {
  for (auto local_cid : pending_outgoing_configuration_request_list_) {
    signalling_manager_.SendInitialConfigRequest(local_cid);
  }
  pending_outgoing_configuration_request_list_.clear();
}

void Link::OnOutgoingConnectionRequestFail(Cid local_cid) {
  if (local_cid_to_pending_dynamic_channel_connection_map_.find(local_cid) !=
      local_cid_to_pending_dynamic_channel_connection_map_.end()) {
@@ -178,6 +185,14 @@ void Link::OnOutgoingConnectionRequestFail(Cid local_cid) {
  dynamic_channel_allocator_.FreeChannel(local_cid);
}

void Link::SendInitialConfigRequestOrQueue(Cid local_cid) {
  if (remote_extended_feature_received_) {
    signalling_manager_.SendInitialConfigRequest(local_cid);
  } else {
    pending_outgoing_configuration_request_list_.push_back(local_cid);
  }
}

void Link::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
  signalling_manager_.SendDisconnectionRequest(local_cid, remote_cid);
}
@@ -272,6 +287,7 @@ void Link::OnRemoteExtendedFeatureReceived(bool ertm_supported, bool fcs_support
  remote_supports_fcs_ = fcs_supported;
  remote_extended_feature_received_ = true;
  connect_to_pending_dynamic_channels();
  send_pending_configuration_requests();
}

void Link::AddChannelPendingingAuthentication(PendingAuthenticateDynamicChannelConnection pending_channel) {
+4 −0
Original line number Diff line number Diff line
@@ -105,6 +105,8 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall
  // Invoked by signalling manager to indicate an outgoing connection request failed and link shall free resources
  virtual void OnOutgoingConnectionRequestFail(Cid local_cid);

  virtual void SendInitialConfigRequestOrQueue(Cid local_cid);

  virtual void SendInformationRequest(InformationRequestInfoType type);

  virtual void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) override;
@@ -168,6 +170,7 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall

 private:
  void connect_to_pending_dynamic_channels();
  void send_pending_configuration_requests();

  os::Handler* l2cap_handler_;
  l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
@@ -188,6 +191,7 @@ class Link : public l2cap::internal::ILink, public hci::ConnectionManagementCall
  std::list<Link::PendingAuthenticateDynamicChannelConnection> pending_channel_list_;
  std::list<Psm> pending_dynamic_psm_list_;
  std::list<Link::PendingDynamicChannelConnection> pending_dynamic_channel_callback_list_;
  std::list<uint16_t> pending_outgoing_configuration_request_list_;
  DISALLOW_COPY_AND_ASSIGN(Link);
};

+85 −111
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ void ClassicSignallingManager::SendConnectionRequest(Psm psm, Cid local_cid) {
  }
}

void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid,
void ClassicSignallingManager::send_configuration_request(Cid remote_cid,
                                                          std::vector<std::unique_ptr<ConfigurationOption>> config) {
  PendingCommand pending_command = {next_signal_id_,  CommandCode::CONFIGURATION_REQUEST, {}, {}, remote_cid, {},
                                    std::move(config)};
@@ -93,16 +93,13 @@ void ClassicSignallingManager::SendConfigurationRequest(Cid remote_cid,
}

void ClassicSignallingManager::SendDisconnectionRequest(Cid local_cid, Cid remote_cid) {
  command_just_sent_ = {next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
  PendingCommand pending_command = {
      next_signal_id_, CommandCode::DISCONNECTION_REQUEST, {}, local_cid, remote_cid, {}, {}};
  next_signal_id_++;

  auto signal_id = command_just_sent_.signal_id_;
  auto source_cid = command_just_sent_.source_cid_;
  auto destination_cid = command_just_sent_.destination_cid_;

  auto builder = DisconnectionRequestBuilder::Create(signal_id.Value(), destination_cid, source_cid);
  enqueue_buffer_->Enqueue(std::move(builder), handler_);
  alarm_.Schedule(common::BindOnce(&ClassicSignallingManager::on_command_timeout, common::Unretained(this)), kTimeout);
  pending_commands_.push(std::move(pending_command));
  if (command_just_sent_.signal_id_ == kInvalidSignalId) {
    handle_send_next_command();
  }
}

void ClassicSignallingManager::SendInformationRequest(InformationRequestInfoType type) {
@@ -157,51 +154,8 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm,
  }
  send_connection_response(signal_id, remote_cid, new_channel->GetCid(), ConnectionResponseResult::SUCCESS,
                           ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
  auto& configuration_state = channel_configuration_[new_channel->GetCid()];
  auto* service = dynamic_service_manager_->GetService(psm);
  auto initial_config = service->GetConfigOption();

  auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
  mtu_configuration->mtu_ = initial_config.incoming_mtu;
  configuration_state.incoming_mtu_ = initial_config.incoming_mtu;

  auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
  fcs_option->fcs_type_ = FcsType::NO_FCS;
  configuration_state.fcs_type_ = FcsType::NO_FCS;
  if (link_->GetRemoteSupportsFcs()) {
    fcs_option->fcs_type_ = FcsType::DEFAULT;
    configuration_state.fcs_type_ = FcsType::DEFAULT;
  }

  auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
  switch (initial_config.channel_mode) {
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
      retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      break;
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION_OPTIONAL:
      retransmission_flow_control_configuration->mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      configuration_state.retransmission_and_flow_control_mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      // TODO: Decide where to put initial values
      retransmission_flow_control_configuration->tx_window_size_ = 10;
      retransmission_flow_control_configuration->max_transmit_ = 20;
      retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
      retransmission_flow_control_configuration->monitor_time_out_ = 12000;
      retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
      break;
  }
  configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;

  std::vector<std::unique_ptr<ConfigurationOption>> config;
  config.emplace_back(std::move(mtu_configuration));
  if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
    config.emplace_back(std::move(retransmission_flow_control_configuration));
    config.emplace_back(std::move(fcs_option));
  }
  SendConfigurationRequest(remote_cid, std::move(config));
  link_->SendInitialConfigRequestOrQueue(new_channel->GetCid());
}

void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remote_cid, Cid cid,
@@ -240,50 +194,7 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remo
    return;
  }

  auto& configuration_state = channel_configuration_[new_channel->GetCid()];
  auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid());

  auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
  mtu_configuration->mtu_ = initial_config.incoming_mtu;
  configuration_state.incoming_mtu_ = initial_config.incoming_mtu;

  auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
  fcs_option->fcs_type_ = FcsType::DEFAULT;
  configuration_state.fcs_type_ = FcsType::DEFAULT;
  if (!link_->GetRemoteSupportsFcs()) {
    fcs_option->fcs_type_ = FcsType::NO_FCS;
    configuration_state.fcs_type_ = FcsType::NO_FCS;
  }

  auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
  switch (initial_config.channel_mode) {
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
      retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      break;
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION_OPTIONAL:
      retransmission_flow_control_configuration->mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      configuration_state.retransmission_and_flow_control_mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      // TODO: Decide where to put initial values
      retransmission_flow_control_configuration->tx_window_size_ = 10;
      retransmission_flow_control_configuration->max_transmit_ = 20;
      retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
      retransmission_flow_control_configuration->monitor_time_out_ = 12000;
      retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
      break;
  }
  configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;

  std::vector<std::unique_ptr<ConfigurationOption>> config;
  config.emplace_back(std::move(mtu_configuration));
  if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
    config.emplace_back(std::move(retransmission_flow_control_configuration));
    config.emplace_back(std::move(fcs_option));
  }
  SendConfigurationRequest(remote_cid, std::move(config));
  link_->SendInitialConfigRequestOrQueue(cid);
}

void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid cid, Continuation is_continuation,
@@ -297,6 +208,7 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
  auto& configuration_state = channel_configuration_[cid];
  std::vector<std::unique_ptr<ConfigurationOption>> rsp_options;
  ConfigurationResponseResult result = ConfigurationResponseResult::SUCCESS;
  auto remote_rfc_mode = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;

  for (auto& option : options) {
    switch (option->type_) {
@@ -317,6 +229,7 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
      }
      case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
        auto* config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
        remote_rfc_mode = config->mode_;
        if (config->mode_ == RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION) {
          if (config->retransmission_time_out_ == 0) {
            config->retransmission_time_out_ = 2000;
@@ -324,14 +237,6 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
          if (config->monitor_time_out_ == 0) {
            config->monitor_time_out_ = 12000;
          }
        } else if (config->mode_ == RetransmissionAndFlowControlModeOption::L2CAP_BASIC) {
          auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();
          if (initial_config_option.channel_mode ==
              DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
            LOG_WARN("ERTM mandatory not allow mode configuration, disconnect channel.");
            SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
            return;
          }
        }
        configuration_state.remote_retransmission_and_flow_control_ = *config;
        configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
@@ -339,7 +244,7 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
        break;
      }
      case ConfigurationOptionType::FRAME_CHECK_SEQUENCE: {
        configuration_state.fcs_type_ = FrameCheckSequenceOption::Specialize(option.get())->fcs_type_;
        // We determine whether to use FCS or not when we send config request
        break;
      }
      default:
@@ -355,6 +260,16 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
    }
  }

  auto initial_config_option = dynamic_service_manager_->GetService(channel->GetPsm())->GetConfigOption();

  if (remote_rfc_mode == RetransmissionAndFlowControlModeOption::L2CAP_BASIC &&
      initial_config_option.channel_mode ==
          DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION) {
    LOG_WARN("ERTM mandatory not allow mode configuration, disconnect channel.");
    SendDisconnectionRequest(channel->GetCid(), channel->GetRemoteCid());
    return;
  }

  if (configuration_state.state_ == ChannelConfigurationState::State::WAIT_CONFIG_REQ) {
    std::unique_ptr<DynamicChannel> user_channel = std::make_unique<DynamicChannel>(channel, handler_);
    if (channel->local_initiated_) {
@@ -374,6 +289,56 @@ void ClassicSignallingManager::OnConfigurationRequest(SignalId signal_id, Cid ci
  enqueue_buffer_->Enqueue(std::move(response), handler_);
}

void ClassicSignallingManager::SendInitialConfigRequest(Cid local_cid) {
  auto channel = channel_allocator_->FindChannelByCid(local_cid);
  auto psm = channel->GetPsm();
  auto& configuration_state = channel_configuration_[local_cid];
  auto* service = dynamic_service_manager_->GetService(psm);
  auto initial_config = service->GetConfigOption();

  auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
  mtu_configuration->mtu_ = initial_config.incoming_mtu;
  configuration_state.incoming_mtu_ = initial_config.incoming_mtu;

  auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
  fcs_option->fcs_type_ = FcsType::NO_FCS;
  configuration_state.fcs_type_ = FcsType::NO_FCS;
  if (link_->GetRemoteSupportsFcs()) {
    fcs_option->fcs_type_ = FcsType::DEFAULT;
    configuration_state.fcs_type_ = FcsType::DEFAULT;
  }

  auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
  switch (initial_config.channel_mode) {
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC:
      retransmission_flow_control_configuration->mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      configuration_state.retransmission_and_flow_control_mode_ = RetransmissionAndFlowControlModeOption::L2CAP_BASIC;
      break;
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION:
    case DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::ENHANCED_RETRANSMISSION_OPTIONAL:
      retransmission_flow_control_configuration->mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      configuration_state.retransmission_and_flow_control_mode_ =
          RetransmissionAndFlowControlModeOption::ENHANCED_RETRANSMISSION;
      // TODO: Decide where to put initial values
      retransmission_flow_control_configuration->tx_window_size_ = 10;
      retransmission_flow_control_configuration->max_transmit_ = 20;
      retransmission_flow_control_configuration->retransmission_time_out_ = 2000;
      retransmission_flow_control_configuration->monitor_time_out_ = 12000;
      retransmission_flow_control_configuration->maximum_pdu_size_ = 1010;
      break;
  }
  configuration_state.local_retransmission_and_flow_control_ = *retransmission_flow_control_configuration;

  std::vector<std::unique_ptr<ConfigurationOption>> config;
  config.emplace_back(std::move(mtu_configuration));
  if (initial_config.channel_mode != DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC) {
    config.emplace_back(std::move(retransmission_flow_control_configuration));
    config.emplace_back(std::move(fcs_option));
  }
  send_configuration_request(channel->GetRemoteCid(), std::move(config));
}

void ClassicSignallingManager::negotiate_configuration(Cid cid, Continuation is_continuation,
                                                       std::vector<std::unique_ptr<ConfigurationOption>> options) {
  auto channel = channel_allocator_->FindChannelByCid(cid);
@@ -429,7 +394,9 @@ void ClassicSignallingManager::negotiate_configuration(Cid cid, Continuation is_
    }
  }
  if (can_negotiate) {
    SendConfigurationRequest(channel->GetRemoteCid(), std::move(negotiation_config));
    send_configuration_request(channel->GetRemoteCid(), std::move(negotiation_config));
  } else {
    LOG_DEBUG("No suggested parameter received");
  }
}

@@ -457,6 +424,7 @@ void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid c
    case ConfigurationResponseResult::UNKNOWN_OPTIONS:
    case ConfigurationResponseResult::FLOW_SPEC_REJECTED:
      LOG_WARN("Configuration response not SUCCESS: %s", ConfigurationResponseResultText(result).c_str());
      alarm_.Cancel();
      handle_send_next_command();
      return;

@@ -490,7 +458,12 @@ void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid c
      }
      case ConfigurationOptionType::RETRANSMISSION_AND_FLOW_CONTROL: {
        auto config = RetransmissionAndFlowControlConfigurationOption::Specialize(option.get());
        configuration_state.retransmission_and_flow_control_mode_ = config->mode_;
        if (configuration_state.retransmission_and_flow_control_mode_ != config->mode_) {
          SendDisconnectionRequest(cid, channel->GetRemoteCid());
          alarm_.Cancel();
          handle_send_next_command();
          return;
        }
        configuration_state.local_retransmission_and_flow_control_ = *config;
        break;
      }
@@ -500,6 +473,8 @@ void ClassicSignallingManager::OnConfigurationResponse(SignalId signal_id, Cid c
      }
      default:
        LOG_WARN("Received some unsupported configuration option: %d", static_cast<int>(option->type_));
        alarm_.Cancel();
        handle_send_next_command();
        return;
    }
  }
@@ -597,7 +572,6 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat
      break;
    }
    case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
      // TODO: implement this response
      auto response = InformationResponseExtendedFeaturesBuilder::Create(
          signal_id.Value(), InformationRequestResult::SUCCESS, 0, 0, 0, 1 /* ERTM */, 0 /* Streaming mode */,
          1 /* FCS */, 0, 1 /* Fixed Channels */, 0, 0);
+3 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ class ClassicSignallingManager {

  void SendConnectionRequest(Psm psm, Cid local_cid);

  void SendConfigurationRequest(Cid remote_cid, std::vector<std::unique_ptr<ConfigurationOption>> config);
  void SendInitialConfigRequest(Cid local_cid);

  void SendDisconnectionRequest(Cid local_cid, Cid remote_cid);

@@ -109,6 +109,8 @@ class ClassicSignallingManager {
  void negotiate_configuration(Cid cid, Continuation is_continuation,
                               std::vector<std::unique_ptr<ConfigurationOption>>);

  void send_configuration_request(Cid remote_cid, std::vector<std::unique_ptr<ConfigurationOption>> config);

  os::Handler* handler_;
  Link* link_;
  l2cap::internal::DataPipelineManager* data_pipeline_manager_;