// Copyright (c) 2017 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.

#ifndef NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_H_
#define NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_H_

#include <stddef.h>
#include <limits>

#include "net/third_party/quic/core/quic_ack_listener_interface.h"
#include "net/third_party/quic/core/quic_session.h"
#include "net/third_party/quic/core/quic_stream.h"
#include "net/third_party/quic/core/quic_types.h"
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/platform/api/quic_mem_slice_span.h"
#include "net/third_party/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quic/platform/impl/quic_export_impl.h"
#include "net/third_party/quic/quartc/quartc_interval_counter.h"

namespace quic {

// Sends and receives data with a particular QUIC stream ID, reliably and
// in-order. To send/receive data out of order, use separate streams. To
// send/receive unreliably, close a stream after reliability is no longer
// needed.
class QUIC_EXPORT_PRIVATE QuartcStream : public QuicStream {
 public:
  QuartcStream(QuicStreamId id, QuicSession* session);
  explicit QuartcStream(PendingStream pending);

  ~QuartcStream() override;

  // QuicStream overrides.
  void OnDataAvailable() override;

  void OnClose() override;

  void OnStreamDataConsumed(size_t bytes_consumed) override;

  void OnDataBuffered(
      QuicStreamOffset offset,
      QuicByteCount data_length,
      const QuicReferenceCountedPointer<QuicAckListenerInterface>& ack_listener)
      override;

  bool OnStreamFrameAcked(QuicStreamOffset offset,
                          QuicByteCount data_length,
                          bool fin_acked,
                          QuicTime::Delta ack_delay_time) override;

  void OnStreamFrameRetransmitted(QuicStreamOffset offset,
                                  QuicByteCount data_length,
                                  bool fin_retransmitted) override;

  void OnStreamFrameLost(QuicStreamOffset offset,
                         QuicByteCount data_length,
                         bool fin_lost) override;

  void OnCanWrite() override;

  // QuartcStream interface methods.

  // Whether the stream should be cancelled instead of retransmitted on loss.
  // If set to true, the stream will reset itself instead of retransmitting lost
  // stream frames.  Defaults to false.  Setting it to true is equivalent to
  // setting |max_retransmission_count| to zero.
  bool cancel_on_loss();
  void set_cancel_on_loss(bool cancel_on_loss);

  // Maximum number of times this stream's data may be retransmitted.  Each byte
  // of stream data may be retransmitted this many times.  If any byte (or range
  // of bytes) is lost and would be retransmitted more than this number of
  // times, the stream resets itself instead of retransmitting the data again.
  // Setting this value to zero disables retransmissions.
  //
  // Note that this limit applies only to stream data, not to the FIN bit.  If
  // only the FIN bit needs to be retransmitted, there is no benefit to
  // cancelling the stream and sending a reset frame instead.
  int max_retransmission_count() const;
  void set_max_retransmission_count(int max_retransmission_count);

  QuicByteCount BytesPendingRetransmission();

  // Returns the current read offset for this stream.  During a call to
  // Delegate::OnReceived, this value is the offset of the first byte read.
  QuicStreamOffset ReadOffset();

  // Marks this stream as finished writing.  Asynchronously sends a FIN and
  // closes the write-side.  It is not necessary to call FinishWriting() if the
  // last call to Write() sends a FIN.
  void FinishWriting();

  // Implemented by the user of the QuartcStream to receive incoming
  // data and be notified of state changes.
  class Delegate {
   public:
    virtual ~Delegate() {}

    // Called when the stream receives data. |iov| is a pointer to the first of
    // |iov_length| readable regions. |iov| points to readable data within
    // |stream|'s sequencer buffer. QUIC may modify or delete this data after
    // the application consumes it. |fin| indicates the end of stream data.
    // Returns the number of bytes consumed. May return 0 if the delegate is
    // unable to consume any bytes at this time.
    virtual size_t OnReceived(QuartcStream* stream,
                              iovec* iov,
                              size_t iov_length,
                              bool fin) = 0;

    // Called when the stream is closed, either locally or by the remote
    // endpoint.  Streams close when (a) fin bits are both sent and received,
    // (b) Close() is called, or (c) the stream is reset.
    // TODO(zhihuang) Creates a map from the integer error_code to WebRTC native
    // error code.
    virtual void OnClose(QuartcStream* stream) = 0;

    // Called when the contents of the stream's buffer changes.
    virtual void OnBufferChanged(QuartcStream* stream) = 0;
  };

  // The |delegate| is not owned by QuartcStream.
  void SetDelegate(Delegate* delegate);

 private:
  Delegate* delegate_ = nullptr;

  // Maximum number of times this stream's data may be retransmitted.
  int max_retransmission_count_ = std::numeric_limits<int>::max();

  // Counter which tracks the number of times each frame has been lost
  // (accounting for the possibility of overlapping frames).
  //
  // If the maximum count of any lost frame exceeds |max_retransmission_count_|,
  // the stream will cancel itself on the next attempt to retransmit data (the
  // next call to |OnCanWrite|).
  QuartcIntervalCounter<QuicStreamOffset> lost_frame_counter_;
};

}  // namespace quic

#endif  // NET_THIRD_PARTY_QUIC_QUARTC_QUARTC_STREAM_H_
