• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
NON_EXPORTED_BASE(public base::RefCounted<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