1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/quic/quic_connection_helper.h" 6 7 #include "base/location.h" 8 #include "base/logging.h" 9 #include "base/task_runner.h" 10 #include "base/time/time.h" 11 #include "net/base/io_buffer.h" 12 #include "net/base/net_errors.h" 13 #include "net/quic/quic_utils.h" 14 15 namespace net { 16 17 namespace { 18 19 class QuicChromeAlarm : public QuicAlarm { 20 public: 21 QuicChromeAlarm(const QuicClock* clock, 22 base::TaskRunner* task_runner, 23 QuicAlarm::Delegate* delegate) 24 : QuicAlarm(delegate), 25 clock_(clock), 26 task_runner_(task_runner), 27 task_posted_(false), 28 weak_factory_(this) {} 29 30 protected: 31 virtual void SetImpl() OVERRIDE { 32 DCHECK(deadline().IsInitialized()); 33 if (task_posted_) { 34 // Since tasks can not be un-posted, OnAlarm will be invoked which 35 // will notice that deadline has not yet been reached, and will set 36 // the alarm for the new deadline. 37 return; 38 } 39 40 int64 delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds(); 41 if (delay_us < 0) { 42 delay_us = 0; 43 } 44 task_runner_->PostDelayedTask( 45 FROM_HERE, 46 base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()), 47 base::TimeDelta::FromMicroseconds(delay_us)); 48 task_posted_ = true; 49 } 50 51 virtual void CancelImpl() OVERRIDE { 52 DCHECK(!deadline().IsInitialized()); 53 // Since tasks can not be un-posted, OnAlarm will be invoked which 54 // will notice that deadline is not Initialized and will do nothing. 55 } 56 57 private: 58 void OnAlarm() { 59 DCHECK(task_posted_); 60 task_posted_ = false; 61 // The alarm may have been cancelled. 62 if (!deadline().IsInitialized()) { 63 return; 64 } 65 66 // The alarm may have been re-set to a later time. 67 if (clock_->Now() < deadline()) { 68 SetImpl(); 69 return; 70 } 71 72 Fire(); 73 } 74 75 const QuicClock* clock_; 76 base::TaskRunner* task_runner_; 77 bool task_posted_; 78 base::WeakPtrFactory<QuicChromeAlarm> weak_factory_; 79 }; 80 81 } // namespace 82 83 QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner, 84 const QuicClock* clock, 85 QuicRandom* random_generator, 86 DatagramClientSocket* socket) 87 : weak_factory_(this), 88 task_runner_(task_runner), 89 socket_(socket), 90 clock_(clock), 91 random_generator_(random_generator) { 92 } 93 94 QuicConnectionHelper::~QuicConnectionHelper() { 95 } 96 97 void QuicConnectionHelper::SetConnection(QuicConnection* connection) { 98 connection_ = connection; 99 } 100 101 const QuicClock* QuicConnectionHelper::GetClock() const { 102 return clock_; 103 } 104 105 QuicRandom* QuicConnectionHelper::GetRandomGenerator() { 106 return random_generator_; 107 } 108 109 int QuicConnectionHelper::WritePacketToWire( 110 const QuicEncryptedPacket& packet, 111 int* error) { 112 if (connection_->ShouldSimulateLostPacket()) { 113 DLOG(INFO) << "Dropping packet due to fake packet loss."; 114 *error = 0; 115 return packet.length(); 116 } 117 118 scoped_refptr<StringIOBuffer> buf( 119 new StringIOBuffer(std::string(packet.data(), 120 packet.length()))); 121 int rv = socket_->Write(buf.get(), 122 packet.length(), 123 base::Bind(&QuicConnectionHelper::OnWriteComplete, 124 weak_factory_.GetWeakPtr())); 125 if (rv >= 0) { 126 *error = 0; 127 } else { 128 *error = rv; 129 rv = -1; 130 } 131 return rv; 132 } 133 134 bool QuicConnectionHelper::IsWriteBlockedDataBuffered() { 135 // Chrome sockets' Write() methods buffer the data until the Write is 136 // permitted. 137 return true; 138 } 139 140 bool QuicConnectionHelper::IsWriteBlocked(int error) { 141 return error == ERR_IO_PENDING; 142 } 143 144 QuicAlarm* QuicConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) { 145 return new QuicChromeAlarm(clock_, task_runner_, delegate); 146 } 147 148 void QuicConnectionHelper::OnWriteComplete(int result) { 149 // TODO(rch): Inform the connection about the result. 150 connection_->OnCanWrite(); 151 } 152 153 } // namespace net 154