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