// Copyright 2014 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.
//
// A convenience class to store rtt samples and calculate smoothed rtt.

#ifndef NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_
#define NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_

#include <algorithm>

#include "base/basictypes.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"

namespace net {

namespace test {
class RttStatsPeer;
}  // namespace test

class NET_EXPORT_PRIVATE RttStats {
 public:
  RttStats();

  // Returns true if any RTT measurements have been made.
  bool HasUpdates() const;

  // Updates the RTT from an incoming ack which is received |send_delta| after
  // the packet is sent and the peer reports the ack being delayed |ack_delay|.
  void UpdateRtt(QuicTime::Delta send_delta,
                 QuicTime::Delta ack_delay,
                 QuicTime now);

  // Forces RttStats to sample a new recent min rtt within the next
  // |num_samples| UpdateRtt calls.
  void SampleNewRecentMinRtt(uint32 num_samples);

  QuicTime::Delta SmoothedRtt() const;

  int64 initial_rtt_us() const {
    return initial_rtt_us_;
  }

  // Sets an initial RTT to be used for SmoothedRtt before any RTT updates.
  void set_initial_rtt_us(int64 initial_rtt_us) {
    initial_rtt_us_ = initial_rtt_us;
  }

  QuicTime::Delta latest_rtt() const {
    return latest_rtt_;
  }

  // Returns the min_rtt for the entire connection.
  QuicTime::Delta min_rtt() const {
    return min_rtt_;
  }

  // Returns the min_rtt since SampleNewRecentMinRtt has been called, or the
  // min_rtt for the entire connection if SampleNewMinRtt was never called.
  QuicTime::Delta recent_min_rtt() const {
    return recent_min_rtt_.rtt;
  }

  QuicTime::Delta mean_deviation() const {
    return mean_deviation_;
  }

  // Sets how old a recent min rtt sample can be.
  void set_recent_min_rtt_window(QuicTime::Delta recent_min_rtt_window) {
    recent_min_rtt_window_ = recent_min_rtt_window;
  }

 private:
  friend class test::RttStatsPeer;

  // Used to track a sampled RTT window.
  struct RttSample {
    RttSample() : rtt(QuicTime::Delta::Zero()), time(QuicTime::Zero()) { }
    RttSample(QuicTime::Delta rtt, QuicTime time) : rtt(rtt), time(time) { }

    QuicTime::Delta rtt;
    QuicTime time;  // Time the rtt sample was recorded.
  };

  // Implements the resampling algorithm and the windowed min rtt algorithm.
  void UpdateRecentMinRtt(QuicTime::Delta rtt_sample, QuicTime now);

  QuicTime::Delta latest_rtt_;
  QuicTime::Delta min_rtt_;
  QuicTime::Delta smoothed_rtt_;
  // Mean RTT deviation during this session.
  // Approximation of standard deviation, the error is roughly 1.25 times
  // larger than the standard deviation, for a normally distributed signal.
  QuicTime::Delta mean_deviation_;
  int64 initial_rtt_us_;

  RttSample new_min_rtt_;
  uint32 num_min_rtt_samples_remaining_;

  // State variables for Kathleen Nichols MinRTT algorithm.
  QuicTime::Delta recent_min_rtt_window_;
  RttSample recent_min_rtt_;  // a in the windowed algorithm.
  RttSample half_window_rtt_;  // b in the sampled algorithm.
  RttSample quarter_window_rtt_;  // c in the sampled algorithm.

  DISALLOW_COPY_AND_ASSIGN(RttStats);
};

}  // namespace net

#endif  // NET_QUIC_CONGESTION_CONTROL_RTT_STATS_H_