Home | History | Annotate | Download | only in dns
      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 #ifndef NET_DNS_DNS_SESSION_H_
      6 #define NET_DNS_DNS_SESSION_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/lazy_instance.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/scoped_vector.h"
     14 #include "base/metrics/bucket_ranges.h"
     15 #include "base/time/time.h"
     16 #include "net/base/net_export.h"
     17 #include "net/base/rand_callback.h"
     18 #include "net/dns/dns_config_service.h"
     19 #include "net/dns/dns_socket_pool.h"
     20 
     21 namespace base {
     22 class BucketRanges;
     23 class SampleVector;
     24 }
     25 
     26 namespace net {
     27 
     28 class ClientSocketFactory;
     29 class DatagramClientSocket;
     30 class NetLog;
     31 class StreamSocket;
     32 
     33 // Session parameters and state shared between DNS transactions.
     34 // Ref-counted so that DnsClient::Request can keep working in absence of
     35 // DnsClient. A DnsSession must be recreated when DnsConfig changes.
     36 class NET_EXPORT_PRIVATE DnsSession
     37     : NON_EXPORTED_BASE(public base::RefCounted<DnsSession>) {
     38  public:
     39   typedef base::Callback<int()> RandCallback;
     40 
     41   class NET_EXPORT_PRIVATE SocketLease {
     42    public:
     43     SocketLease(scoped_refptr<DnsSession> session,
     44                 unsigned server_index,
     45                 scoped_ptr<DatagramClientSocket> socket);
     46     ~SocketLease();
     47 
     48     unsigned server_index() const { return server_index_; }
     49 
     50     DatagramClientSocket* socket() { return socket_.get(); }
     51 
     52    private:
     53     scoped_refptr<DnsSession> session_;
     54     unsigned server_index_;
     55     scoped_ptr<DatagramClientSocket> socket_;
     56 
     57     DISALLOW_COPY_AND_ASSIGN(SocketLease);
     58   };
     59 
     60   DnsSession(const DnsConfig& config,
     61              scoped_ptr<DnsSocketPool> socket_pool,
     62              const RandIntCallback& rand_int_callback,
     63              NetLog* net_log);
     64 
     65   const DnsConfig& config() const { return config_; }
     66   NetLog* net_log() const { return net_log_; }
     67 
     68   // Return the next random query ID.
     69   int NextQueryId() const;
     70 
     71   // Return the index of the first configured server to use on first attempt.
     72   unsigned NextFirstServerIndex();
     73 
     74   // Start with |server_index| and find the index of the next known good server
     75   // to use on this attempt. Returns |server_index| if this server has no
     76   // recorded failures, or if there are no other servers that have not failed
     77   // or have failed longer time ago.
     78   unsigned NextGoodServerIndex(unsigned server_index);
     79 
     80   // Record that server failed to respond (due to SRV_FAIL or timeout).
     81   void RecordServerFailure(unsigned server_index);
     82 
     83   // Record that server responded successfully.
     84   void RecordServerSuccess(unsigned server_index);
     85 
     86   // Record how long it took to receive a response from the server.
     87   void RecordRTT(unsigned server_index, base::TimeDelta rtt);
     88 
     89   // Record suspected loss of a packet for a specific server.
     90   void RecordLostPacket(unsigned server_index, int attempt);
     91 
     92   // Record server stats before it is destroyed.
     93   void RecordServerStats();
     94 
     95   // Return the timeout for the next query. |attempt| counts from 0 and is used
     96   // for exponential backoff.
     97   base::TimeDelta NextTimeout(unsigned server_index, int attempt);
     98 
     99   // Allocate a socket, already connected to the server address.
    100   // When the SocketLease is destroyed, the socket will be freed.
    101   scoped_ptr<SocketLease> AllocateSocket(unsigned server_index,
    102                                          const NetLog::Source& source);
    103 
    104   // Creates a StreamSocket from the factory for a transaction over TCP. These
    105   // sockets are not pooled.
    106   scoped_ptr<StreamSocket> CreateTCPSocket(unsigned server_index,
    107                                            const NetLog::Source& source);
    108 
    109  private:
    110   friend class base::RefCounted<DnsSession>;
    111   ~DnsSession();
    112 
    113   // Release a socket.
    114   void FreeSocket(unsigned server_index,
    115                   scoped_ptr<DatagramClientSocket> socket);
    116 
    117   // Return the timeout using the TCP timeout method.
    118   base::TimeDelta NextTimeoutFromJacobson(unsigned server_index, int attempt);
    119 
    120   // Compute the timeout using the histogram method.
    121   base::TimeDelta NextTimeoutFromHistogram(unsigned server_index, int attempt);
    122 
    123   const DnsConfig config_;
    124   scoped_ptr<DnsSocketPool> socket_pool_;
    125   RandCallback rand_callback_;
    126   NetLog* net_log_;
    127 
    128   // Current index into |config_.nameservers| to begin resolution with.
    129   int server_index_;
    130 
    131   struct ServerStats;
    132 
    133   // Track runtime statistics of each DNS server.
    134   ScopedVector<ServerStats> server_stats_;
    135 
    136   // Buckets shared for all |ServerStats::rtt_histogram|.
    137   struct RttBuckets : public base::BucketRanges {
    138     RttBuckets();
    139   };
    140   static base::LazyInstance<RttBuckets>::Leaky rtt_buckets_;
    141 
    142   DISALLOW_COPY_AND_ASSIGN(DnsSession);
    143 };
    144 
    145 }  // namespace net
    146 
    147 #endif  // NET_DNS_DNS_SESSION_H_
    148