// Copyright 2017 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include "object/mbuf.h"

#include <lib/counters.h>
#include <lib/user_copy/user_ptr.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <ktl/algorithm.h>
#include <ktl/type_traits.h>

#define LOCAL_TRACE 0

constexpr size_t MBufChain::MBuf::kHeaderSize;
constexpr size_t MBufChain::MBuf::kMallocSize;
constexpr size_t MBufChain::MBuf::kPayloadSize;
constexpr size_t MBufChain::kSizeMax;

// Total amount of memory occupied by MBuf objects.
KCOUNTER(mbuf_total_bytes_count, "mbuf.total_bytes")

// Amount of memory occupied by MBuf objects on free lists.
KCOUNTER(mbuf_free_list_bytes_count, "mbuf.free_list_bytes")

size_t MBufChain::MBuf::rem() const { return kPayloadSize - (off_ + len_); }

MBufChain::~MBufChain() {
  while (!tail_.is_empty()) {
    delete tail_.pop_front();
  }
  while (!freelist_.is_empty()) {
    kcounter_add(mbuf_free_list_bytes_count, -sizeof(MBufChain::MBuf));
    delete freelist_.pop_front();
  }
}

bool MBufChain::is_full() const { return size_ >= kSizeMax; }

bool MBufChain::is_empty() const { return size_ == 0; }

zx_status_t MBufChain::Read(user_out_ptr<char> dst, size_t len, bool datagram, size_t* actual) {
  return ReadHelper(this, dst, len, datagram, actual);
}

zx_status_t MBufChain::Peek(user_out_ptr<char> dst, size_t len, bool datagram,
                            size_t* actual) const {
  return ReadHelper(this, dst, len, datagram, actual);
}

template <class T>
zx_status_t MBufChain::ReadHelper(T* chain, user_out_ptr<char> dst, size_t len, bool datagram,
                                  size_t* actual) {
  if (chain->size_ == 0) {
    *actual = 0;
    return ZX_OK;
  }

  if (datagram && len > chain->tail_.front().pkt_len_)
    len = chain->tail_.front().pkt_len_;

  size_t pos = 0;
  auto iter = chain->tail_.begin();
  while (pos < len && iter != chain->tail_.end()) {
    const char* src = iter->data_ + iter->off_;
    size_t copy_len = ktl::min(static_cast<size_t>(iter->len_), len - pos);
    zx_status_t status = dst.byte_offset(pos).copy_array_to_user(src, copy_len);
    if (status != ZX_OK) {
      return status;
    }

    pos += copy_len;

    if constexpr (ktl::is_const<T>::value) {
      ++iter;
    } else {
      // TODO(fxbug.dev/34143): Note, we're advancing (consuming data) after each copy.  This means
      // that if a subsequent copy fails (perhaps because a the write to the user buffer
      // faults) data will be "dropped".  Consider changing this function to only advance (and
      // free) once all data has been successfully copied.

      iter->off_ += static_cast<uint32_t>(copy_len);
      iter->len_ -= static_cast<uint32_t>(copy_len);
      chain->size_ -= copy_len;

      if (iter->len_ == 0 || datagram) {
        chain->size_ -= iter->len_;
        if (chain->head_ == &(*iter))
          chain->head_ = nullptr;
        chain->FreeMBuf(chain->tail_.pop_front());
        iter = chain->tail_.begin();
      }
    }
  }

  // Drain any leftover mbufs in the datagram packet if we're consuming data.
  if constexpr (!ktl::is_const<T>::value) {
    if (datagram) {
      while (!chain->tail_.is_empty() && chain->tail_.front().pkt_len_ == 0) {
        MBuf* cur = chain->tail_.pop_front();
        chain->size_ -= cur->len_;
        if (chain->head_ == cur)
          chain->head_ = nullptr;
        chain->FreeMBuf(cur);
      }
    }
  }

  *actual = pos;
  return ZX_OK;
}

zx_status_t MBufChain::WriteDatagram(user_in_ptr<const char> src, size_t len, size_t* written) {
  if (len == 0) {
    return ZX_ERR_INVALID_ARGS;
  }
  if (len > kSizeMax)
    return ZX_ERR_OUT_OF_RANGE;
  if (len + size_ > kSizeMax)
    return ZX_ERR_SHOULD_WAIT;

  fbl::SinglyLinkedList<MBuf*> bufs;
  for (size_t need = 1 + ((len - 1) / MBuf::kPayloadSize); need != 0; need--) {
    auto buf = AllocMBuf();
    if (buf == nullptr) {
      while (!bufs.is_empty())
        FreeMBuf(bufs.pop_front());
      return ZX_ERR_SHOULD_WAIT;
    }
    bufs.push_front(buf);
  }

  size_t pos = 0;
  for (auto& buf : bufs) {
    size_t copy_len = ktl::min(MBuf::kPayloadSize, len - pos);
    if (src.byte_offset(pos).copy_array_from_user(buf.data_, copy_len) != ZX_OK) {
      while (!bufs.is_empty())
        FreeMBuf(bufs.pop_front());
      return ZX_ERR_INVALID_ARGS;  // Bad user buffer.
    }
    pos += copy_len;
    buf.len_ += static_cast<uint32_t>(copy_len);
  }

  bufs.front().pkt_len_ = static_cast<uint32_t>(len);

  // Successfully built the packet mbufs. Put it on the socket.
  while (!bufs.is_empty()) {
    auto next = bufs.pop_front();
    if (head_ == nullptr) {
      tail_.push_front(next);
    } else {
      tail_.insert_after(tail_.make_iterator(*head_), next);
    }
    head_ = next;
  }

  *written = len;
  size_ += len;
  return ZX_OK;
}

zx_status_t MBufChain::WriteStream(user_in_ptr<const char> src, size_t len, size_t* written) {
  if (head_ == nullptr) {
    head_ = AllocMBuf();
    if (head_ == nullptr)
      return ZX_ERR_SHOULD_WAIT;
    tail_.push_front(head_);
  }

  size_t pos = 0;
  while (pos < len) {
    if (head_->rem() == 0) {
      auto next = AllocMBuf();
      if (next == nullptr)
        break;
      tail_.insert_after(tail_.make_iterator(*head_), next);
      head_ = next;
    }
    char* dst = head_->data_ + head_->off_ + head_->len_;
    size_t copy_len = ktl::min(head_->rem(), len - pos);
    if (size_ + copy_len > kSizeMax) {
      copy_len = kSizeMax - size_;
      if (copy_len == 0)
        break;
    }
    zx_status_t status = src.byte_offset(pos).copy_array_from_user(dst, copy_len);
    if (status != ZX_OK) {
      // TODO(fxbug.dev/34143): Note, we're not indicating to the caller that data added so far in
      // previous copies was written successfully.  This means the caller may try to re-send
      // the same data again, leading to duplicate data.  Consider changing this function to
      // report that some data was written so far, or consider not committing any of the new
      // data until we can ensure success, or consider putting the socket in a state where it
      // can't succeed a subsequent write.
      return status;
    }

    pos += copy_len;
    head_->len_ += static_cast<uint32_t>(copy_len);
    size_ += copy_len;
  }

  if (pos == 0)
    return ZX_ERR_SHOULD_WAIT;

  *written = pos;
  return ZX_OK;
}

MBufChain::MBuf* MBufChain::AllocMBuf() {
  if (freelist_.is_empty()) {
    fbl::AllocChecker ac;
    MBuf* buf = new (&ac) MBuf();
    return (!ac.check()) ? nullptr : buf;
  }
  kcounter_add(mbuf_free_list_bytes_count, -sizeof(MBufChain::MBuf));
  return freelist_.pop_front();
}

void MBufChain::FreeMBuf(MBuf* buf) {
  buf->off_ = 0u;
  buf->len_ = 0u;
  freelist_.push_front(buf);
  kcounter_add(mbuf_free_list_bytes_count, sizeof(MBufChain::MBuf));
}

MBufChain::MBuf::MBuf() { kcounter_add(mbuf_total_bytes_count, sizeof(MBufChain::MBuf)); }

MBufChain::MBuf::~MBuf() { kcounter_add(mbuf_total_bytes_count, -sizeof(MBufChain::MBuf)); }
