// Copyright 2019 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/l2cap/channel_configuration.h"

#include <endian.h>
#include <lib/fit/function.h>

#include <iterator>
#include <optional>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/common/packet_view.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace bt {
namespace l2cap {
namespace internal {

template <typename OptionT, typename PayloadT>
DynamicByteBuffer EncodeOption(PayloadT payload) {
  DynamicByteBuffer buffer(OptionT::kEncodedSize);
  MutablePacketView<ConfigurationOption> option(&buffer, OptionT::kPayloadLength);
  option.mutable_header()->type = OptionT::kType;
  option.mutable_header()->length = OptionT::kPayloadLength;
  option.mutable_payload_data().WriteObj(payload);
  return buffer;
}

// Compares length field in option header with expected option payload length for that option type.
// Returns true if lengths match, false otherwise.
template <typename OptionT>
bool CheckHeaderLengthField(PacketView<ConfigurationOption> option) {
  if (option.header().length != OptionT::kPayloadLength) {
    bt_log(WARN, "l2cap",
           "received channel configuration option with incorrect length (type: %#.2x, "
           "length: %hhu, expected length: %hhu)",
           static_cast<uint8_t>(option.header().type), option.header().length,
           OptionT::kPayloadLength);
    return false;
  }
  return true;
}

// ChannelConfiguration::Reader implementation
bool ChannelConfiguration::ReadOptions(const ByteBuffer& options_payload) {
  auto remaining_view = options_payload.view();
  while (remaining_view.size() != 0) {
    size_t bytes_read = ReadNextOption(remaining_view);

    // Check for read failure
    if (bytes_read == 0) {
      return false;
    }

    remaining_view = remaining_view.view(bytes_read);
  }
  return true;
}

size_t ChannelConfiguration::ReadNextOption(const ByteBuffer& options) {
  if (options.size() < sizeof(ConfigurationOption)) {
    bt_log(WARN, "l2cap",
           "tried to decode channel configuration option from buffer with invalid size (size: %lu)",
           options.size());
    return 0;
  }

  size_t remaining_size = options.size() - sizeof(ConfigurationOption);
  PacketView<ConfigurationOption> option(&options, remaining_size);

  // Check length against buffer bounds.
  if (option.header().length > remaining_size) {
    bt_log(WARN, "l2cap",
           "decoded channel configuration option with length greater than remaining buffer size "
           "(length: %hhu, remaining: %zu)",
           option.header().length, remaining_size);
    return 0;
  }

  switch (option.header().type) {
    case OptionType::kMTU:
      if (!CheckHeaderLengthField<MtuOption>(option)) {
        return 0;
      }
      OnReadMtuOption(MtuOption(option.payload_data()));
      return MtuOption::kEncodedSize;
    case OptionType::kRetransmissionAndFlowControl:
      if (!CheckHeaderLengthField<RetransmissionAndFlowControlOption>(option)) {
        return 0;
      }
      OnReadRetransmissionAndFlowControlOption(
          RetransmissionAndFlowControlOption(option.payload_data()));
      return RetransmissionAndFlowControlOption::kEncodedSize;
    case OptionType::kFlushTimeout:
      if (!CheckHeaderLengthField<FlushTimeoutOption>(option)) {
        return 0;
      }
      OnReadFlushTimeoutOption(FlushTimeoutOption(option.payload_data()));
      return FlushTimeoutOption::kEncodedSize;
    default:
      bt_log(TRACE, "l2cap", "decoded unsupported channel configuration option (type: %#.2x)",
             static_cast<uint8_t>(option.header().type));

      UnknownOption unknown_option(option.header().type, option.header().length,
                                   option.payload_data());
      size_t option_size = unknown_option.size();

      OnReadUnknownOption(std::move(unknown_option));

      return option_size;
  }
}

// MtuOption implementation

ChannelConfiguration::MtuOption::MtuOption(const ByteBuffer& data_buf) {
  auto& data = data_buf.As<MtuOptionPayload>();
  mtu_ = letoh16(data.mtu);
}

DynamicByteBuffer ChannelConfiguration::MtuOption::Encode() const {
  return EncodeOption<MtuOption>(MtuOptionPayload{htole16(mtu_)});
}

std::string ChannelConfiguration::MtuOption::ToString() const {
  return fxl::StringPrintf("[type: MTU, mtu: %hu]", mtu_);
}

// RetransmissionAndFlowControlOption implementation

ChannelConfiguration::RetransmissionAndFlowControlOption
ChannelConfiguration::RetransmissionAndFlowControlOption::MakeBasicMode() {
  return RetransmissionAndFlowControlOption(ChannelMode::kBasic, 0, 0, 0, 0, 0);
}

ChannelConfiguration::RetransmissionAndFlowControlOption
ChannelConfiguration::RetransmissionAndFlowControlOption::MakeEnhancedRetransmissionMode(
    uint8_t tx_window_size, uint8_t max_transmit, uint16_t rtx_timeout, uint16_t monitor_timeout,
    uint16_t mps) {
  return RetransmissionAndFlowControlOption(ChannelMode::kEnhancedRetransmission, tx_window_size,
                                            max_transmit, rtx_timeout, monitor_timeout, mps);
}
ChannelConfiguration::RetransmissionAndFlowControlOption::RetransmissionAndFlowControlOption(
    ChannelMode mode, uint8_t tx_window_size, uint8_t max_transmit, uint16_t rtx_timeout,
    uint16_t monitor_timeout, uint16_t mps)
    : mode_(mode),
      tx_window_size_(tx_window_size),
      max_transmit_(max_transmit),
      rtx_timeout_(rtx_timeout),
      monitor_timeout_(monitor_timeout),
      mps_(mps) {}

ChannelConfiguration::RetransmissionAndFlowControlOption::RetransmissionAndFlowControlOption(
    const ByteBuffer& data_buf) {
  auto& option_payload = data_buf.As<RetransmissionAndFlowControlOptionPayload>();
  mode_ = option_payload.mode;
  tx_window_size_ = option_payload.tx_window_size;
  max_transmit_ = option_payload.max_transmit;
  rtx_timeout_ = letoh16(option_payload.rtx_timeout);
  monitor_timeout_ = letoh16(option_payload.monitor_timeout);
  mps_ = letoh16(option_payload.mps);
}

DynamicByteBuffer ChannelConfiguration::RetransmissionAndFlowControlOption::Encode() const {
  RetransmissionAndFlowControlOptionPayload payload;
  payload.mode = mode_;
  payload.tx_window_size = tx_window_size_;
  payload.max_transmit = max_transmit_;
  payload.rtx_timeout = htole16(rtx_timeout_);
  payload.monitor_timeout = htole16(monitor_timeout_);
  payload.mps = mps_;
  return EncodeOption<RetransmissionAndFlowControlOption>(payload);
}

std::string ChannelConfiguration::RetransmissionAndFlowControlOption::ToString() const {
  return fxl::StringPrintf(
      "[type: RtxFlowControl, mode: %hhu, tx window size: %hhu, max transmit: %hhu, rtx timeout: "
      "%hu, monitor timeout: %hu, max pdu payload size: %hu]",
      static_cast<uint8_t>(mode_), tx_window_size_, max_transmit_, rtx_timeout_, monitor_timeout_,
      mps_);
}

// FlushTimeoutOption implementation

ChannelConfiguration::FlushTimeoutOption::FlushTimeoutOption(const ByteBuffer& data_buf) {
  auto& option_payload = data_buf.As<FlushTimeoutOptionPayload>();
  flush_timeout_ = letoh16(option_payload.flush_timeout);
}

DynamicByteBuffer ChannelConfiguration::FlushTimeoutOption::Encode() const {
  FlushTimeoutOptionPayload payload;
  payload.flush_timeout = htole16(flush_timeout_);
  return EncodeOption<FlushTimeoutOption>(payload);
}

std::string ChannelConfiguration::FlushTimeoutOption::ToString() const {
  return fxl::StringPrintf("[type: FlushTimeout, flush timeout: %hu]", flush_timeout_);
}

// UnknownOption implementation

ChannelConfiguration::UnknownOption::UnknownOption(OptionType type, uint8_t length,
                                                   const ByteBuffer& data)
    : type_(type), payload_(BufferView(data, length)) {}

DynamicByteBuffer ChannelConfiguration::UnknownOption::Encode() const {
  DynamicByteBuffer buffer(size());
  MutablePacketView<ConfigurationOption> option(&buffer, payload_.size());
  option.mutable_header()->type = type_;
  option.mutable_header()->length = payload_.size();

  // Raw data is already in little endian
  option.mutable_payload_data().Write(payload_);

  return buffer;
}

bool ChannelConfiguration::UnknownOption::IsHint() const {
  // An option is a hint if its MSB is 1.
  const uint8_t kMSBMask = 0x80;
  return static_cast<uint8_t>(type_) & kMSBMask;
}

std::string ChannelConfiguration::UnknownOption::ToString() const {
  return fxl::StringPrintf("[type: %#.2hhx, length: %zu]", type_, payload_.size());
}

// ChannelConfiguration implementation

ChannelConfiguration::ConfigurationOptions ChannelConfiguration::Options() const {
  ConfigurationOptions options;
  if (mtu_option_) {
    options.push_back(ConfigurationOptionPtr(new MtuOption(*mtu_option_)));
  }

  if (retransmission_flow_control_option_) {
    options.push_back(ConfigurationOptionPtr(
        new RetransmissionAndFlowControlOption(*retransmission_flow_control_option_)));
  }

  if (flush_timeout_option_) {
    options.push_back(ConfigurationOptionPtr(new FlushTimeoutOption(*flush_timeout_option_)));
  }

  return options;
}

std::string ChannelConfiguration::ToString() const {
  std::string str("{");

  std::vector<std::string> options;
  if (mtu_option_) {
    options.push_back(mtu_option_->ToString());
  }
  if (retransmission_flow_control_option_) {
    options.push_back(retransmission_flow_control_option_->ToString());
  }
  if (flush_timeout_option_) {
    options.push_back(flush_timeout_option_->ToString());
  }
  for (auto& option : unknown_options_) {
    options.push_back(option.ToString());
  }

  for (auto it = options.begin(); it != options.end(); it++) {
    str += *it;
    if (it != options.end() - 1) {
      str += ", ";
    }
  }
  str += "}";
  return str;
}

void ChannelConfiguration::Merge(ChannelConfiguration other) {
  if (other.mtu_option_) {
    mtu_option_ = other.mtu_option_;
  }

  if (other.retransmission_flow_control_option_) {
    retransmission_flow_control_option_ = other.retransmission_flow_control_option_;
  }

  if (other.flush_timeout_option_) {
    flush_timeout_option_ = other.flush_timeout_option_;
  }

  unknown_options_.insert(unknown_options_.end(),
                          std::make_move_iterator(other.unknown_options_.begin()),
                          std::make_move_iterator(other.unknown_options_.end()));
}

void ChannelConfiguration::OnReadUnknownOption(UnknownOption option) {
  // Drop unknown hint options
  if (!option.IsHint()) {
    unknown_options_.push_back(std::move(option));
  }
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bt
