Home | History | Annotate | Download | only in quic
      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