// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gatt/remote_service.h"

#include "lib/fit/defer.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/slab_allocator.h"

#pragma clang diagnostic ignored "-Wshadow"

namespace bt::gatt {
namespace {

bool IsInternalUuid(const UUID& uuid) {
  // clang-format off
  return
    uuid == types::kPrimaryService ||
    uuid == types::kSecondaryService ||
    uuid == types::kIncludeDeclaration ||
    uuid == types::kCharacteristicDeclaration ||
    uuid == types::kCharacteristicExtProperties ||
    uuid == types::kCharacteristicUserDescription ||
    uuid == types::kClientCharacteristicConfig ||
    uuid == types::kServerCharacteristicConfig ||
    uuid == types::kCharacteristicFormat ||
    uuid == types::kCharacteristicAggregateFormat;
  // clang-format on
}

void ReportReadValueError(att::Result<> status,
                          RemoteService::ReadValueCallback callback) {
  callback(status, BufferView(), /*maybe_truncated=*/false);
}

CharacteristicMap CharacteristicsToCharacteristicMap(
    const std::map<CharacteristicHandle, RemoteCharacteristic>&
        characteristics) {
  CharacteristicMap characteristic_map;
  for (const auto& [_handle, chrc] : characteristics) {
    characteristic_map.try_emplace(_handle, chrc.info(), chrc.descriptors());
  }
  return characteristic_map;
}

}  // namespace

RemoteService::RemoteService(const ServiceData& service_data,
                             Client::WeakPtr client)
    : service_data_(service_data),
      client_(std::move(client)),
      remaining_descriptor_requests_(kSentinel) {
  BT_DEBUG_ASSERT(client_.is_alive());
}

RemoteService::~RemoteService() {
  for (auto& chr : characteristics_) {
    chr.second.set_service_changed(service_changed_);
  }
  characteristics_.clear();

  std::vector<fit::callback<void()>> rm_handlers = std::move(rm_handlers_);
  for (auto& handler : rm_handlers) {
    handler();
  }
}

bool RemoteService::AddRemovedHandler(fit::closure handler) {
  rm_handlers_.emplace_back(std::move(handler));
  return true;
}

void RemoteService::DiscoverCharacteristics(CharacteristicCallback callback) {
  // Characteristics already discovered. Return success.
  if (HasCharacteristics()) {
    // We return a new copy of only the immutable data of our characteristics
    // and their descriptors. This requires a copy, which *could* be expensive
    // in the (unlikely) case that a service has a very large number of
    // characteristics.
    callback(fit::ok(), CharacteristicsToCharacteristicMap(characteristics_));
    return;
  }

  // Queue this request.
  pending_discov_reqs_.emplace_back(std::move(callback));

  // Nothing to do if a write request is already pending.
  if (pending_discov_reqs_.size() > 1u)
    return;

  auto self = GetWeakPtr();
  auto chrc_cb = [self](const CharacteristicData& chr) {
    if (!self.is_alive()) {
      return;
    }
    // try_emplace should not fail here; our GATT::Client explicitly ensures
    // that handles are strictly ascending (as described in the spec) so we
    // should never see a handle collision
    self->characteristics_.try_emplace(
        CharacteristicHandle(chr.value_handle), self->client_, chr);
  };

  auto res_cb = [self](att::Result<> status) mutable {
    if (!self.is_alive()) {
      return;
    }

    if (bt_is_error(status, TRACE, "gatt", "characteristic discovery failed")) {
      self->characteristics_.clear();
    }

    if (self->characteristics_.empty()) {
      if (status.is_ok()) {
        // This marks that characteristic discovery has completed
        // successfully.
        self->remaining_descriptor_requests_ = 0u;
      }

      // Skip descriptor discovery and end the procedure as no characteristics
      // were found (or the operation failed).
      self->CompleteCharacteristicDiscovery(status);
      return;
    }

    self->StartDescriptorDiscovery();
  };

  client_->DiscoverCharacteristics(service_data_.range_start,
                                   service_data_.range_end,
                                   std::move(chrc_cb),
                                   std::move(res_cb));
}

bool RemoteService::IsDiscovered() const {
  // TODO(armansito): Return true only if included services have also been
  // discovered.
  return HasCharacteristics();
}

void RemoteService::ReadCharacteristic(CharacteristicHandle id,
                                       ReadValueCallback callback) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    ReportReadValueError(status, std::move(callback));
    return;
  }

  if (!(chrc->info().properties & Property::kRead)) {
    bt_log(DEBUG, "gatt", "characteristic does not support \"read\"");
    ReportReadValueError(ToResult(HostError::kNotSupported),
                         std::move(callback));
    return;
  }

  client_->ReadRequest(chrc->info().value_handle, std::move(callback));
}

void RemoteService::ReadLongCharacteristic(CharacteristicHandle id,
                                           uint16_t offset,
                                           size_t max_bytes,
                                           ReadValueCallback callback) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    ReportReadValueError(status, std::move(callback));
    return;
  }

  if (!(chrc->info().properties & Property::kRead)) {
    bt_log(DEBUG, "gatt", "characteristic does not support \"read\"");
    ReportReadValueError(ToResult(HostError::kNotSupported),
                         std::move(callback));
    return;
  }

  if (max_bytes == 0) {
    bt_log(TRACE, "gatt", "invalid value for |max_bytes|: 0");
    ReportReadValueError(ToResult(HostError::kInvalidParameters),
                         std::move(callback));
    return;
  }

  // Set up the buffer in which we'll accumulate the blobs.
  auto buffer = NewBuffer(std::min(max_bytes, att::kMaxAttributeValueLength));
  if (!buffer) {
    ReportReadValueError(ToResult(HostError::kOutOfMemory),
                         std::move(callback));
    return;
  }

  ReadLongHelper(chrc->info().value_handle,
                 offset,
                 std::move(buffer),
                 0u /* bytes_read */,
                 std::move(callback));
}

void RemoteService::ReadByType(const UUID& type, ReadByTypeCallback callback) {
  // Caller should not request a UUID of an internal attribute (e.g. service
  // declaration).
  if (IsInternalUuid(type)) {
    bt_log(TRACE,
           "gatt",
           "ReadByType called with internal GATT type (type: %s)",
           bt_str(type));
    callback(ToResult(HostError::kInvalidParameters), {});
    return;
  }

  // Read range is entire service range.
  ReadByTypeHelper(type,
                   service_data_.range_start,
                   service_data_.range_end,
                   {},
                   std::move(callback));
}

void RemoteService::WriteCharacteristic(CharacteristicHandle id,
                                        std::vector<uint8_t> value,
                                        att::ResultFunction<> cb) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    cb(status);
    return;
  }

  if (!(chrc->info().properties & Property::kWrite)) {
    bt_log(DEBUG, "gatt", "characteristic does not support \"write\"");
    cb(ToResult(HostError::kNotSupported));
    return;
  }

  client_->WriteRequest(chrc->info().value_handle,
                        BufferView(value.data(), value.size()),
                        std::move(cb));
}

void RemoteService::WriteLongCharacteristic(CharacteristicHandle id,
                                            uint16_t offset,
                                            std::vector<uint8_t> value,
                                            ReliableMode reliable_mode,
                                            att::ResultFunction<> callback) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    callback(status);
    return;
  }

  if (!(chrc->info().properties & Property::kWrite)) {
    bt_log(DEBUG, "gatt", "characteristic does not support \"write\"");
    callback(ToResult(HostError::kNotSupported));
    return;
  }

  if ((reliable_mode == ReliableMode::kEnabled) &&
      ((!chrc->extended_properties().has_value()) ||
       (!(chrc->extended_properties().value() &
          ExtendedProperty::kReliableWrite)))) {
    bt_log(DEBUG,
           "gatt",
           "characteristic does not support \"reliable write\"; attempting "
           "request anyway");
  }

  SendLongWriteRequest(chrc->info().value_handle,
                       offset,
                       BufferView(value.data(), value.size()),
                       reliable_mode,
                       std::move(callback));
}

void RemoteService::WriteCharacteristicWithoutResponse(
    CharacteristicHandle id,
    std::vector<uint8_t> value,
    att::ResultFunction<> cb) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    cb(status);
    return;
  }

  if (!(chrc->info().properties &
        (Property::kWrite | Property::kWriteWithoutResponse))) {
    bt_log(DEBUG,
           "gatt",
           "characteristic does not support \"write without response\"");
    cb(ToResult(HostError::kNotSupported));
    return;
  }

  client_->WriteWithoutResponse(chrc->info().value_handle,
                                BufferView(value.data(), value.size()),
                                std::move(cb));
}

void RemoteService::ReadDescriptor(DescriptorHandle id,
                                   ReadValueCallback callback) {
  const DescriptorData* desc;
  fit::result status = GetDescriptor(id, &desc);
  BT_DEBUG_ASSERT(desc || status.is_error());
  if (status.is_error()) {
    ReportReadValueError(status, std::move(callback));
    return;
  }

  client_->ReadRequest(desc->handle, std::move(callback));
}

void RemoteService::ReadLongDescriptor(DescriptorHandle id,
                                       uint16_t offset,
                                       size_t max_bytes,
                                       ReadValueCallback callback) {
  const DescriptorData* desc;
  att::Result<> status = GetDescriptor(id, &desc);
  BT_DEBUG_ASSERT(desc || status.is_error());
  if (status.is_error()) {
    ReportReadValueError(status, std::move(callback));
    return;
  }

  if (max_bytes == 0) {
    bt_log(TRACE, "gatt", "invalid value for |max_bytes|: 0");
    ReportReadValueError(ToResult(HostError::kInvalidParameters),
                         std::move(callback));
    return;
  }

  // Set up the buffer in which we'll accumulate the blobs.
  auto buffer = NewBuffer(std::min(max_bytes, att::kMaxAttributeValueLength));
  if (!buffer) {
    ReportReadValueError(ToResult(HostError::kOutOfMemory),
                         std::move(callback));
    return;
  }

  ReadLongHelper(desc->handle,
                 offset,
                 std::move(buffer),
                 0u /* bytes_read */,
                 std::move(callback));
}

void RemoteService::WriteDescriptor(DescriptorHandle id,
                                    std::vector<uint8_t> value,
                                    att::ResultFunction<> callback) {
  const DescriptorData* desc;
  fit::result status = GetDescriptor(id, &desc);
  BT_DEBUG_ASSERT(desc || status.is_error());
  if (status.is_error()) {
    callback(status);
    return;
  }

  // Do not allow writing to internally reserved descriptors.
  if (desc->type == types::kClientCharacteristicConfig) {
    bt_log(DEBUG, "gatt", "writing to CCC descriptor not allowed");
    callback(ToResult(HostError::kNotSupported));
    return;
  }

  client_->WriteRequest(desc->handle,
                        BufferView(value.data(), value.size()),
                        std::move(callback));
}

void RemoteService::WriteLongDescriptor(DescriptorHandle id,
                                        uint16_t offset,
                                        std::vector<uint8_t> value,
                                        att::ResultFunction<> callback) {
  const DescriptorData* desc;
  fit::result status = GetDescriptor(id, &desc);
  BT_DEBUG_ASSERT(desc || status.is_error());
  if (status.is_error()) {
    callback(status);
    return;
  }

  // Do not allow writing to internally reserved descriptors.
  if (desc->type == types::kClientCharacteristicConfig) {
    bt_log(DEBUG, "gatt", "writing to CCC descriptor not allowed");
    callback(ToResult(HostError::kNotSupported));
    return;
  }

  // For writing long descriptors, reliable mode is not supported.
  auto mode = ReliableMode::kDisabled;
  SendLongWriteRequest(desc->handle,
                       offset,
                       BufferView(value.data(), value.size()),
                       mode,
                       std::move(callback));
}

void RemoteService::EnableNotifications(CharacteristicHandle id,
                                        ValueCallback callback,
                                        NotifyStatusCallback status_callback) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_error()) {
    status_callback(status, kInvalidId);
    return;
  }

  chrc->EnableNotifications(std::move(callback), std::move(status_callback));
}

void RemoteService::DisableNotifications(
    CharacteristicHandle id,
    IdType handler_id,
    att::ResultFunction<> status_callback) {
  RemoteCharacteristic* chrc;
  fit::result status = GetCharacteristic(id, &chrc);
  BT_DEBUG_ASSERT(chrc || status.is_error());
  if (status.is_ok() && !chrc->DisableNotifications(handler_id)) {
    status = ToResult(HostError::kNotFound);
  }
  status_callback(status);
}

void RemoteService::StartDescriptorDiscovery() {
  BT_DEBUG_ASSERT(!pending_discov_reqs_.empty());

  BT_ASSERT(!characteristics_.empty());
  remaining_descriptor_requests_ = characteristics_.size();

  auto self = GetWeakPtr();

  // Callback called for each characteristic. This may be called in any
  // order since we request the descriptors of all characteristics all at
  // once.
  auto desc_done_callback = [self](att::Result<> status) {
    if (!self.is_alive()) {
      return;
    }

    // Do nothing if discovery was concluded earlier (which would have cleared
    // the pending discovery requests).
    if (self->pending_discov_reqs_.empty()) {
      return;
    }

    if (status.is_ok()) {
      self->remaining_descriptor_requests_ -= 1;

      // Defer handling
      if (self->remaining_descriptor_requests_ > 0) {
        return;
      }

      // HasCharacteristics() should return true now.
      BT_DEBUG_ASSERT(self->HasCharacteristics());

      // Fall through and notify clients below.
    } else {
      BT_DEBUG_ASSERT(!self->HasCharacteristics());
      bt_log(DEBUG, "gatt", "descriptor discovery failed %s", bt_str(status));
      self->characteristics_.clear();

      // Fall through and notify the clients below.
    }

    self->CompleteCharacteristicDiscovery(status);
  };

  // Characteristics are stored in an (ordered) std::map by value_handle, so we
  // iterate in order; according to the spec (BT 5.0 Vol 3, part G, 3.3), the
  // value handle must appear immediately after the characteristic handle so the
  // handles are also guaranteed to be in order. Therefore we can use the next
  // in the iteration to calculate the handle range.
  for (auto iter = characteristics_.begin(); iter != characteristics_.end();
       ++iter) {
    auto next = iter;
    ++next;
    att::Handle end_handle;
    if (next == characteristics_.end()) {
      end_handle = service_data_.range_end;
    } else {
      end_handle = next->second.info().handle - 1;
    }

    BT_DEBUG_ASSERT(client_.is_alive());
    iter->second.DiscoverDescriptors(end_handle, desc_done_callback);
  }
}

fit::result<Error<>> RemoteService::GetCharacteristic(
    CharacteristicHandle id, RemoteCharacteristic** out_char) {
  BT_DEBUG_ASSERT(out_char);

  if (!HasCharacteristics()) {
    *out_char = nullptr;
    return fit::error(HostError::kNotReady);
  }

  auto chr = characteristics_.find(id);
  if (chr == characteristics_.end()) {
    *out_char = nullptr;
    return fit::error(HostError::kNotFound);
  }

  *out_char = &chr->second;
  return fit::ok();
}

fit::result<Error<>> RemoteService::GetDescriptor(
    DescriptorHandle id, const DescriptorData** out_desc) {
  BT_DEBUG_ASSERT(out_desc);

  if (!HasCharacteristics()) {
    *out_desc = nullptr;
    return fit::error(HostError::kNotReady);
  }

  for (auto iter = characteristics_.begin(); iter != characteristics_.end();
       ++iter) {
    auto next = iter;
    ++next;
    if (next == characteristics_.end() ||
        next->second.info().handle > id.value) {
      const auto& descriptors = iter->second.descriptors();
      auto desc = descriptors.find(id);
      if (desc != descriptors.end()) {
        *out_desc = &desc->second;
        return fit::ok();
      }
    }
  }

  *out_desc = nullptr;
  return fit::error(HostError::kNotFound);
}

void RemoteService::CompleteCharacteristicDiscovery(att::Result<> status) {
  BT_DEBUG_ASSERT(!pending_discov_reqs_.empty());
  BT_DEBUG_ASSERT(status.is_error() || remaining_descriptor_requests_ == 0u);

  // We return a new copy of only the immutable data of our characteristics and
  // their descriptors. This requires a copy, which *could* be expensive in the
  // (unlikely) case that a service has a very large number of characteristics.
  CharacteristicMap characteristic_map =
      CharacteristicsToCharacteristicMap(characteristics_);

  auto pending = std::move(pending_discov_reqs_);
  for (auto& discovery_req_cb : pending) {
    discovery_req_cb(status, characteristic_map);
  }
}

void RemoteService::SendLongWriteRequest(att::Handle handle,
                                         uint16_t offset,
                                         BufferView value,
                                         ReliableMode reliable_mode,
                                         att::ResultFunction<> final_cb) {
  att::PrepareWriteQueue long_write_queue;
  auto header_ln = sizeof(att::PrepareWriteRequestParams) + sizeof(att::OpCode);
  uint16_t bytes_written = 0;

  // Divide up the long write into it's constituent PreparedWrites and add them
  // to the queue.
  while (bytes_written < value.size()) {
    uint16_t part_value_size = static_cast<uint16_t>(
        std::min(client_->mtu() - header_ln, value.size() - bytes_written));
    auto part_buffer = value.view(bytes_written, part_value_size);

    long_write_queue.push(att::QueuedWrite(handle, offset, part_buffer));

    bytes_written += part_value_size;
    offset += part_value_size;
  }

  client_->ExecutePrepareWrites(std::move(long_write_queue),
                                std::move(reliable_mode),
                                std::move(final_cb));
}

void RemoteService::ReadLongHelper(att::Handle value_handle,
                                   uint16_t offset,
                                   MutableByteBufferPtr buffer,
                                   size_t bytes_read,
                                   ReadValueCallback callback) {
  BT_DEBUG_ASSERT(callback);
  BT_DEBUG_ASSERT(buffer);

  auto self = GetWeakPtr();
  auto read_cb = [self,
                  value_handle,
                  offset,
                  buffer = std::move(buffer),
                  bytes_read,
                  cb = std::move(callback)](
                     att::Result<> status,
                     const ByteBuffer& blob,
                     bool maybe_truncated_by_mtu) mutable {
    if (!self.is_alive()) {
      return;
    }

    if (status.is_error()) {
      // "If the Characteristic Value is not longer than (ATT_MTU – 1) an
      // ATT_ERROR_RSP PDU with the error code set to kAttributeNotLong shall be
      // received on the first ATT_READ_BLOB_REQ PDU." (Core Spec v5.2, Vol 3,
      // Part G, Sec 4.8.3). Report the short value read in the previous
      // ATT_READ_REQ in this case.
      if (status.error_value().is(att::ErrorCode::kAttributeNotLong) &&
          offset == self->client_->mtu() - sizeof(att::OpCode)) {
        cb(fit::ok(),
           buffer->view(0, bytes_read),
           /*maybe_truncated=*/false);
        return;
      }

      ReportReadValueError(status, std::move(cb));
      return;
    }

    // Copy the blob into our |buffer|. |blob| may be truncated depending on the
    // size of |buffer|.
    BT_ASSERT(bytes_read < buffer->size());
    size_t copy_size = std::min(blob.size(), buffer->size() - bytes_read);
    bool truncated_by_max_bytes = (blob.size() != copy_size);
    buffer->Write(blob.view(0, copy_size), bytes_read);
    bytes_read += copy_size;

    // We are done if the read was not truncated by the MTU or we have read the
    // maximum number of bytes requested.
    BT_ASSERT(bytes_read <= buffer->size());
    if (!maybe_truncated_by_mtu || bytes_read == buffer->size()) {
      cb(fit::ok(),
         buffer->view(0, bytes_read),
         maybe_truncated_by_mtu || truncated_by_max_bytes);
      return;
    }

    // We have more bytes to read. Read the next blob.
    self->ReadLongHelper(value_handle,
                         static_cast<uint16_t>(offset + blob.size()),
                         std::move(buffer),
                         bytes_read,
                         std::move(cb));
  };

  // "To read the complete Characteristic Value an ATT_READ_REQ PDU should be
  // used for the first part of the value and ATT_READ_BLOB_REQ PDUs shall used
  // for the rest." (Core Spec v5.2, Vol 3, part G, Sec 4.8.3).
  if (offset == 0) {
    client_->ReadRequest(value_handle, std::move(read_cb));
    return;
  }

  client_->ReadBlobRequest(value_handle, offset, std::move(read_cb));
}

void RemoteService::ReadByTypeHelper(
    const UUID& type,
    att::Handle start,
    att::Handle end,
    std::vector<RemoteService::ReadByTypeResult> values,
    ReadByTypeCallback callback) {
  if (start > end) {
    callback(fit::ok(), std::move(values));
    return;
  }

  auto read_cb = [self = GetWeakPtr(),
                  type,
                  start,
                  end,
                  values_accum = std::move(values),
                  cb = std::move(callback)](
                     Client::ReadByTypeResult result) mutable {
    if (!self.is_alive()) {
      return;
    }

    // Pass results to client when this goes out of scope.
    auto deferred_cb =
        fit::defer_callback([&]() { cb(fit::ok(), std::move(values_accum)); });
    if (result.is_error()) {
      const att::Error& error = result.error_value().error;
      deferred_cb = [&cb, error] { cb(fit::error(error), /*values=*/{}); };
      if (error.is(att::ErrorCode::kAttributeNotFound)) {
        // Treat kAttributeNotFound error as success, since it's used to
        // indicate when a sequence of reads has successfully read all matching
        // attributes.
        deferred_cb = [&cb, &values_accum]() {
          cb(fit::ok(), std::move(values_accum));
        };
        return;
      }
      if (error.is_any_of(att::ErrorCode::kRequestNotSupported,
                          att::ErrorCode::kInsufficientResources,
                          att::ErrorCode::kInvalidPDU)) {
        // Pass up these protocol errors as they aren't handle specific or
        // recoverable.
        return;
      }
      if (error.is_protocol_error()) {
        // Other errors may correspond to reads of specific handles, so treat
        // them as a result and continue reading after the error.

        // A handle must be provided and in the requested read handle range.
        if (!result.error_value().handle.has_value()) {
          return;
        }
        att::Handle error_handle = result.error_value().handle.value();
        if (error_handle < start || error_handle > end) {
          deferred_cb = [&cb] {
            cb(fit::error(Error(HostError::kPacketMalformed)), /*values=*/{});
          };
          return;
        }

        values_accum.push_back(
            RemoteService::ReadByTypeResult{CharacteristicHandle(error_handle),
                                            fit::error(error.protocol_error()),
                                            /*maybe_truncated=*/false});

        // Do not attempt to read from the next handle if the error handle is
        // the max handle, as this would cause an overflow.
        if (error_handle == std::numeric_limits<att::Handle>::max()) {
          deferred_cb = [&cb, &values_accum]() {
            cb(fit::ok(), std::move(values_accum));
          };
          return;
        }

        // Start next read right after attribute causing error.
        att::Handle start_next = error_handle + 1;

        self->ReadByTypeHelper(
            type, start_next, end, std::move(values_accum), std::move(cb));
        deferred_cb.cancel();
        return;
      }
      return;
    }

    const std::vector<Client::ReadByTypeValue>& values = result.value();
    // Client already checks for invalid response where status is success but no
    // values are returned.
    BT_ASSERT(!values.empty());

    // Convert and accumulate values.
    for (const auto& result : values) {
      auto buffer = NewBuffer(result.value.size());
      result.value.Copy(buffer.get());
      values_accum.push_back(
          ReadByTypeResult{CharacteristicHandle(result.handle),
                           fit::ok(std::move(buffer)),
                           result.maybe_truncated});
    }

    // Do not attempt to read from the next handle if the last value handle is
    // the max handle, as this would cause an overflow.
    if (values.back().handle == std::numeric_limits<att::Handle>::max()) {
      return;
    }

    // Start next read right after last returned attribute. Client already
    // checks that value handles are ascending and in range, so we are
    // guaranteed to make progress.
    att::Handle start_next = values.back().handle + 1;

    self->ReadByTypeHelper(
        type, start_next, end, std::move(values_accum), std::move(cb));
    deferred_cb.cancel();
  };
  client_->ReadByTypeRequest(type, start, end, std::move(read_cb));
}

void RemoteService::HandleNotification(att::Handle value_handle,
                                       const ByteBuffer& value,
                                       bool maybe_truncated) {
  auto iter = characteristics_.find(CharacteristicHandle(value_handle));
  if (iter != characteristics_.end()) {
    iter->second.HandleNotification(value, maybe_truncated);
  }
}

}  // namespace bt::gatt
