quic_connection_helper.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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 15namespace net { 16 17QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner, 18 const QuicClock* clock, 19 QuicRandom* random_generator, 20 DatagramClientSocket* socket) 21 : weak_factory_(this), 22 task_runner_(task_runner), 23 socket_(socket), 24 clock_(clock), 25 random_generator_(random_generator), 26 send_alarm_registered_(false), 27 timeout_alarm_registered_(false), 28 retransmission_alarm_registered_(false), 29 retransmission_alarm_running_(false), 30 ack_alarm_registered_(false), 31 ack_alarm_time_(QuicTime::Zero()) { 32} 33 34QuicConnectionHelper::~QuicConnectionHelper() { 35} 36 37void QuicConnectionHelper::SetConnection(QuicConnection* connection) { 38 connection_ = connection; 39} 40 41const QuicClock* QuicConnectionHelper::GetClock() const { 42 return clock_; 43} 44 45QuicRandom* QuicConnectionHelper::GetRandomGenerator() { 46 return random_generator_; 47} 48 49int QuicConnectionHelper::WritePacketToWire( 50 const QuicEncryptedPacket& packet, 51 int* error) { 52 if (connection_->ShouldSimulateLostPacket()) { 53 DLOG(INFO) << "Dropping packet due to fake packet loss."; 54 *error = 0; 55 return packet.length(); 56 } 57 58 scoped_refptr<StringIOBuffer> buf( 59 new StringIOBuffer(std::string(packet.data(), 60 packet.length()))); 61 int rv = socket_->Write(buf.get(), 62 packet.length(), 63 base::Bind(&QuicConnectionHelper::OnWriteComplete, 64 weak_factory_.GetWeakPtr())); 65 if (rv >= 0) { 66 *error = 0; 67 } else { 68 *error = rv; 69 rv = -1; 70 } 71 return rv; 72} 73 74bool QuicConnectionHelper::IsWriteBlockedDataBuffered() { 75 // Chrome sockets' Write() methods buffer the data until the Write is 76 // permitted. 77 return true; 78} 79 80bool QuicConnectionHelper::IsWriteBlocked(int error) { 81 return error == ERR_IO_PENDING; 82} 83 84void QuicConnectionHelper::SetRetransmissionAlarm(QuicTime::Delta delay) { 85 if (!retransmission_alarm_registered_) { 86 task_runner_->PostDelayedTask( 87 FROM_HERE, 88 base::Bind(&QuicConnectionHelper::OnRetransmissionAlarm, 89 weak_factory_.GetWeakPtr()), 90 base::TimeDelta::FromMicroseconds(delay.ToMicroseconds())); 91 } 92} 93 94void QuicConnectionHelper::SetAckAlarm(QuicTime::Delta delay) { 95 ack_alarm_time_ = clock_->Now().Add(delay); 96 if (!ack_alarm_registered_) { 97 task_runner_->PostDelayedTask( 98 FROM_HERE, 99 base::Bind(&QuicConnectionHelper::OnAckAlarm, 100 weak_factory_.GetWeakPtr()), 101 base::TimeDelta::FromMicroseconds(delay.ToMicroseconds())); 102 } 103 ack_alarm_registered_ = true; 104} 105 106void QuicConnectionHelper::ClearAckAlarm() { 107 ack_alarm_time_ = QuicTime::Zero(); 108} 109 110void QuicConnectionHelper::SetSendAlarm(QuicTime alarm_time) { 111 send_alarm_registered_ = true; 112 int64 delay_us = alarm_time.Subtract(clock_->Now()).ToMicroseconds(); 113 if (delay_us < 0) { 114 delay_us = 0; 115 } 116 task_runner_->PostDelayedTask( 117 FROM_HERE, 118 base::Bind(&QuicConnectionHelper::OnSendAlarm, 119 weak_factory_.GetWeakPtr()), 120 base::TimeDelta::FromMicroseconds(delay_us)); 121} 122 123void QuicConnectionHelper::SetTimeoutAlarm(QuicTime::Delta delay) { 124 // CheckForTimeout will call SetTimeoutAlarm for the remaining time if alarm 125 // goes off before the delay. 126 if (timeout_alarm_registered_) 127 return; 128 timeout_alarm_registered_ = true; 129 task_runner_->PostDelayedTask( 130 FROM_HERE, 131 base::Bind(&QuicConnectionHelper::OnTimeoutAlarm, 132 weak_factory_.GetWeakPtr()), 133 base::TimeDelta::FromMicroseconds(delay.ToMicroseconds())); 134} 135 136bool QuicConnectionHelper::IsSendAlarmSet() { 137 return send_alarm_registered_; 138} 139 140void QuicConnectionHelper::UnregisterSendAlarmIfRegistered() { 141 send_alarm_registered_ = false; 142} 143 144void QuicConnectionHelper::OnRetransmissionAlarm() { 145 QuicTime when = connection_->OnRetransmissionTimeout(); 146 if (!when.IsInitialized()) { 147 return; 148 } 149 QuicTime now = clock_->Now(); 150 QuicTime::Delta delta(when.Subtract(now)); 151 if (delta < QuicTime::Delta::FromSeconds(0)) { 152 delta = QuicTime::Delta::FromSeconds(0); 153 } 154 SetRetransmissionAlarm(delta); 155} 156 157void QuicConnectionHelper::OnSendAlarm() { 158 if (send_alarm_registered_) { 159 send_alarm_registered_ = false; 160 connection_->OnCanWrite(); 161 } 162} 163 164void QuicConnectionHelper::OnTimeoutAlarm() { 165 timeout_alarm_registered_ = false; 166 connection_->CheckForTimeout(); 167} 168 169void QuicConnectionHelper::OnAckAlarm() { 170 ack_alarm_registered_ = false; 171 // Alarm may have been cleared. 172 if (!ack_alarm_time_.IsInitialized()) { 173 return; 174 } 175 176 // Alarm may have been reset to a later time. 177 QuicTime now = clock_->Now(); 178 if (now < ack_alarm_time_) { 179 SetAckAlarm(ack_alarm_time_.Subtract(now)); 180 return; 181 } 182 183 ack_alarm_time_ = QuicTime::Zero(); 184 connection_->SendAck(); 185} 186 187void QuicConnectionHelper::OnWriteComplete(int result) { 188 // TODO(rch): Inform the connection about the result. 189 connection_->OnCanWrite(); 190} 191 192} // namespace net 193