15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_connection_helper.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/metrics/sparse_histogram.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/net_errors.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_utils.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass QuicChromeAlarm : public QuicAlarm {
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public:
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  QuicChromeAlarm(const QuicClock* clock,
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                  base::TaskRunner* task_runner,
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                  QuicAlarm::Delegate* delegate)
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      : QuicAlarm(delegate),
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        clock_(clock),
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        task_runner_(task_runner),
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        task_deadline_(QuicTime::Zero()),
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        weak_factory_(this) {}
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch protected:
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void SetImpl() OVERRIDE {
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(deadline().IsInitialized());
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (task_deadline_.IsInitialized()) {
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (task_deadline_ <= deadline()) {
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // Since tasks can not be un-posted, OnAlarm will be invoked which
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // will notice that deadline has not yet been reached, and will set
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        // the alarm for the new deadline.
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return;
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // The scheduled task is after new deadline.  Invalidate the weak ptrs
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // so that task does not execute when we're not expecting it.
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_factory_.InvalidateWeakPtrs();
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (delay_us < 0) {
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      delay_us = 0;
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    task_runner_->PostDelayedTask(
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        FROM_HERE,
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::TimeDelta::FromMicroseconds(delay_us));
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_deadline_ = deadline();
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void CancelImpl() OVERRIDE {
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    DCHECK(!deadline().IsInitialized());
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Since tasks can not be un-posted, OnAlarm will be invoked which
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // will notice that deadline is not Initialized and will do nothing.
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  void OnAlarm() {
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(task_deadline_.IsInitialized());
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_deadline_ = QuicTime::Zero();
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // The alarm may have been cancelled.
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!deadline().IsInitialized()) {
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // The alarm may have been re-set to a later time.
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (clock_->Now() < deadline()) {
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      SetImpl();
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return;
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Fire();
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  const QuicClock* clock_;
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::TaskRunner* task_runner_;
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If a task has been posted to the message loop, this is the time it
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // was scheduled to fire.  Tracking this allows us to avoid posting a
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // new tast if the new deadline is in the future, but permits us to
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // post a new task when the new deadline now earlier than when
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // previously posted.
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  QuicTime task_deadline_;
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const QuicClock* clock,
961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           QuicRandom* random_generator)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : weak_factory_(this),
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      task_runner_(task_runner),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      clock_(clock),
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      random_generator_(random_generator) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicConnectionHelper::~QuicConnectionHelper() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const QuicClock* QuicConnectionHelper::GetClock() const {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return clock_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicRandom* QuicConnectionHelper::GetRandomGenerator() {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return random_generator_;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochQuicAlarm* QuicConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return new QuicChromeAlarm(clock_, task_runner_, delegate);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
119