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

Commit f4443955 authored by Rahul Arya's avatar Rahul Arya
Browse files

[RootCanal] Add heartbeats to handle remote disconnections

Ping the peer if we haven't heard anything from it in a while. Respond
to all pings with an ignored PING_RESPONSE. If no packet is received for
some duration, drop the connection.

The LSTO duration is not currently configurable. We will also "panic"
and keep sending pings if the peer takes a while to respond, but that's
probably fine (since ticks aren't that frequent).

Bug: 243698555
Tag: #feature
Test: manual
Change-Id: Id5f7310c5322adfd8548953228ab44c6e7d861b8
parent 508ea0a3
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@ AclConnection::AclConnection(AddressWithType address,
    : address_(address),
      own_address_(own_address),
      resolved_address_(resolved_address),
      type_(phy_type) {}
      type_(phy_type),
      last_packet_timestamp_(std::chrono::steady_clock::now()),
      timeout_(std::chrono::seconds(1)) {}

void AclConnection::Encrypt() { encrypted_ = true; };

@@ -58,4 +60,26 @@ bluetooth::hci::Role AclConnection::GetRole() const { return role_; };

void AclConnection::SetRole(bluetooth::hci::Role role) { role_ = role; }

void AclConnection::ResetLinkTimer() {
  last_packet_timestamp_ = std::chrono::steady_clock::now();
}

std::chrono::steady_clock::duration AclConnection::TimeUntilNearExpiring()
    const {
  return (last_packet_timestamp_ + timeout_ / 2) -
         std::chrono::steady_clock::now();
}

bool AclConnection::IsNearExpiring() const {
  return TimeUntilNearExpiring() < std::chrono::steady_clock::duration::zero();
}

std::chrono::steady_clock::duration AclConnection::TimeUntilExpired() const {
  return (last_packet_timestamp_ + timeout_) - std::chrono::steady_clock::now();
}

bool AclConnection::HasExpired() const {
  return TimeUntilExpired() < std::chrono::steady_clock::duration::zero();
}

}  // namespace rootcanal
+13 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <chrono>
#include <cstdint>

#include "hci/address_with_type.h"
@@ -57,6 +58,16 @@ class AclConnection {

  void SetRole(bluetooth::hci::Role role);

  void ResetLinkTimer();

  std::chrono::steady_clock::duration TimeUntilNearExpiring() const;

  bool IsNearExpiring() const;

  std::chrono::steady_clock::duration TimeUntilExpired() const;

  bool HasExpired() const;

 private:
  AddressWithType address_;
  AddressWithType own_address_;
@@ -67,6 +78,8 @@ class AclConnection {
  bool encrypted_{false};
  uint16_t link_policy_settings_{0};
  bluetooth::hci::Role role_{bluetooth::hci::Role::CENTRAL};
  std::chrono::steady_clock::time_point last_packet_timestamp_;
  std::chrono::steady_clock::duration timeout_;
};

}  // namespace rootcanal
+22 −0
Original line number Diff line number Diff line
@@ -564,4 +564,26 @@ std::vector<uint16_t> AclConnectionHandler::GetAclHandles() const {
  return keys;
}

void AclConnectionHandler::ResetLinkTimer(uint16_t handle) {
  acl_connections_.at(handle).ResetLinkTimer();
}

std::chrono::steady_clock::duration
AclConnectionHandler::TimeUntilLinkNearExpiring(uint16_t handle) const {
  return acl_connections_.at(handle).TimeUntilNearExpiring();
}

bool AclConnectionHandler::IsLinkNearExpiring(uint16_t handle) const {
  return acl_connections_.at(handle).IsNearExpiring();
}

std::chrono::steady_clock::duration AclConnectionHandler::TimeUntilLinkExpired(
    uint16_t handle) const {
  return acl_connections_.at(handle).TimeUntilExpired();
}

bool AclConnectionHandler::HasLinkExpired(uint16_t handle) const {
  return acl_connections_.at(handle).HasExpired();
}

}  // namespace rootcanal
+8 −0
Original line number Diff line number Diff line
@@ -130,6 +130,14 @@ class AclConnectionHandler {

  std::vector<uint16_t> GetAclHandles() const;

  void ResetLinkTimer(uint16_t handle);
  std::chrono::steady_clock::duration TimeUntilLinkNearExpiring(
      uint16_t handle) const;
  bool IsLinkNearExpiring(uint16_t handle) const;
  std::chrono::steady_clock::duration TimeUntilLinkExpired(
      uint16_t handle) const;
  bool HasLinkExpired(uint16_t handle) const;

 private:
  std::unordered_map<uint16_t, AclConnection> acl_connections_;
  std::unordered_map<uint16_t, ScoConnection> sco_connections_;
+2 −2
Original line number Diff line number Diff line
@@ -2285,9 +2285,9 @@ void DualModeController::Disconnect(CommandView command) {
  ASSERT(command_view.IsValid());

  uint16_t handle = command_view.GetConnectionHandle();
  uint8_t reason = static_cast<uint8_t>(command_view.GetReason());

  auto status = link_layer_controller_.Disconnect(handle, reason);
  auto status = link_layer_controller_.Disconnect(
      handle, ErrorCode(command_view.GetReason()));

  send_event_(bluetooth::hci::DisconnectStatusBuilder::Create(
      status, kNumCommandPackets));
Loading