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) 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : task_runner_(task_runner), 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clock_(clock), 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci random_generator_(random_generator), 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci weak_factory_(this) { 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