// Copyright (c) 2019 The Chromium 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 "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"

#include <sys/types.h>

#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"

namespace quic {

QuicTransportStream::QuicTransportStream(
    QuicStreamId id,
    QuicSession* session,
    QuicTransportSessionInterface* session_interface)
    : QuicStream(id,
                 session,
                 /*is_static=*/false,
                 QuicUtils::GetStreamType(id,
                                          session->connection()->perspective(),
                                          session->IsIncomingStream(id),
                                          session->version())),
      session_interface_(session_interface) {}

size_t QuicTransportStream::Read(char* buffer, size_t buffer_size) {
  if (!session_interface_->IsSessionReady()) {
    return 0;
  }

  iovec iov;
  iov.iov_base = buffer;
  iov.iov_len = buffer_size;
  const size_t result = sequencer()->Readv(&iov, 1);
  if (sequencer()->IsClosed()) {
    MaybeNotifyFinRead();
  }
  return result;
}

size_t QuicTransportStream::Read(std::string* output) {
  const size_t old_size = output->size();
  const size_t bytes_to_read = ReadableBytes();
  output->resize(old_size + bytes_to_read);
  size_t bytes_read = Read(&(*output)[old_size], bytes_to_read);
  DCHECK_EQ(bytes_to_read, bytes_read);
  output->resize(old_size + bytes_read);
  return bytes_read;
}

bool QuicTransportStream::Write(quiche::QuicheStringPiece data) {
  if (!CanWrite()) {
    return false;
  }

  QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
      session()->connection()->helper()->GetStreamSendBufferAllocator(),
      data.size());
  memcpy(buffer.get(), data.data(), data.size());
  QuicMemSlice memslice(std::move(buffer), data.size());
  QuicConsumedData consumed =
      WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);

  if (consumed.bytes_consumed == data.size()) {
    return true;
  }
  if (consumed.bytes_consumed == 0) {
    return false;
  }
  // QuicTransportStream::Write() is an all-or-nothing write API.  To achieve
  // that property, it relies on WriteMemSlices() being an all-or-nothing API.
  // If WriteMemSlices() fails to provide that guarantee, we have no way to
  // communicate a partial write to the caller, and thus it's safer to just
  // close the connection.
  QUIC_BUG << "WriteMemSlices() unexpectedly partially consumed the input "
              "data, provided: "
           << data.size() << ", written: " << consumed.bytes_consumed;
  OnUnrecoverableError(
      QUIC_INTERNAL_ERROR,
      "WriteMemSlices() unexpectedly partially consumed the input data");
  return false;
}

bool QuicTransportStream::SendFin() {
  if (!CanWrite()) {
    return false;
  }

  QuicMemSlice empty;
  QuicConsumedData consumed =
      WriteMemSlices(QuicMemSliceSpan(&empty), /*fin=*/true);
  DCHECK_EQ(consumed.bytes_consumed, 0u);
  return consumed.fin_consumed;
}

bool QuicTransportStream::CanWrite() const {
  return session_interface_->IsSessionReady() && CanWriteNewData() &&
         !write_side_closed();
}

size_t QuicTransportStream::ReadableBytes() const {
  if (!session_interface_->IsSessionReady()) {
    return 0;
  }

  return sequencer()->ReadableBytes();
}

void QuicTransportStream::OnDataAvailable() {
  if (sequencer()->IsClosed()) {
    MaybeNotifyFinRead();
    return;
  }

  if (visitor_ == nullptr) {
    return;
  }
  if (ReadableBytes() == 0) {
    return;
  }
  visitor_->OnCanRead();
}

void QuicTransportStream::OnCanWriteNewData() {
  // Ensure the origin check has been completed, as the stream can be notified
  // about being writable before that.
  if (!CanWrite()) {
    return;
  }
  if (visitor_ != nullptr) {
    visitor_->OnCanWrite();
  }
}

void QuicTransportStream::MaybeNotifyFinRead() {
  if (visitor_ == nullptr || fin_read_notified_) {
    return;
  }
  fin_read_notified_ = true;
  visitor_->OnFinRead();
  OnFinRead();
}

}  // namespace quic
