Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: net/dns/dns_socket_pool.cc

Issue 10878090: Keep pool of pre-connected DNS sockets (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/dns/dns_socket_pool.h ('k') | net/dns/dns_transaction.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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/dns/dns_socket_pool.h"
6
7 #include "base/logging.h"
8 #include "base/rand_util.h"
9 #include "base/stl_util.h"
10 #include "net/base/ip_endpoint.h"
11 #include "net/base/net_errors.h"
12 #include "net/base/rand_callback.h"
13 #include "net/socket/client_socket_factory.h"
14 #include "net/udp/datagram_client_socket.h"
15
16 namespace net {
17
18 namespace {
19
20 // When we initialize the SocketPool, we allocate kInitialPoolSize sockets.
21 // When we allocate a socket, we ensure we have at least kAllocateMinSize
22 // sockets to choose from. When we free a socket, we retain it if we have
23 // less than kRetainMaxSize sockets in the pool.
24
25 // On Windows, we can't request specific (random) ports, since that will
26 // trigger firewall prompts, so request default ones, but keep a pile of
27 // them. Everywhere else, request fresh, random ports each time.
28 #if defined(OS_WIN)
29 const DatagramSocket::BindType kBindType = DatagramSocket::DEFAULT_BIND;
30 const unsigned kInitialPoolSize = 256;
31 const unsigned kAllocateMinSize = 256;
32 const unsigned kRetainMaxSize = 0;
33 #else
34 const DatagramSocket::BindType kBindType = DatagramSocket::RANDOM_BIND;
35 const unsigned kInitialPoolSize = 0;
36 const unsigned kAllocateMinSize = 1;
37 const unsigned kRetainMaxSize = 0;
38 #endif
39
40 } // namespace
41
42 DnsSocketPool::DnsSocketPool(ClientSocketFactory* socket_factory)
43 : socket_factory_(socket_factory),
44 net_log_(NULL),
45 nameservers_(NULL),
46 initialized_(false) {
47 }
48
49 void DnsSocketPool::InitializeInternal(
50 const std::vector<IPEndPoint>* nameservers,
51 NetLog* net_log) {
52 DCHECK(nameservers);
53 DCHECK(!initialized_);
54
55 net_log_ = net_log;
56 nameservers_ = nameservers;
57 initialized_ = true;
58 }
59
60 scoped_ptr<DatagramClientSocket> DnsSocketPool::CreateConnectedSocket(
61 unsigned server_index) {
62 DCHECK_LT(server_index, nameservers_->size());
63
64 scoped_ptr<DatagramClientSocket> socket;
65
66 NetLog::Source no_source;
67 socket.reset(socket_factory_->CreateDatagramClientSocket(
68 kBindType, base::Bind(&base::RandInt), net_log_, no_source));
69
70 if (socket.get()) {
71 int rv = socket->Connect((*nameservers_)[server_index]);
72 if (rv != OK) {
73 LOG(WARNING) << "Failed to connect socket: " << rv;
74 socket.reset();
75 }
76 } else {
77 LOG(WARNING) << "Failed to create socket.";
78 }
79
80 return socket.Pass();
81 }
82
83 class NullDnsSocketPool : public DnsSocketPool {
84 public:
85 NullDnsSocketPool(ClientSocketFactory* factory)
86 : DnsSocketPool(factory) {
87 }
88
89 virtual void Initialize(
90 const std::vector<IPEndPoint>* nameservers,
91 NetLog* net_log) OVERRIDE {
92 InitializeInternal(nameservers, net_log);
93 }
94
95 virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
96 unsigned server_index) OVERRIDE {
97 return CreateConnectedSocket(server_index);
98 }
99
100 virtual void FreeSocket(
101 unsigned server_index,
102 scoped_ptr<DatagramClientSocket> socket) OVERRIDE {
103 }
104
105 private:
106 DISALLOW_COPY_AND_ASSIGN(NullDnsSocketPool);
107 };
108
109 // static
110 scoped_ptr<DnsSocketPool> DnsSocketPool::CreateNull(
111 ClientSocketFactory* factory) {
112 return scoped_ptr<DnsSocketPool>(new NullDnsSocketPool(factory));
113 }
114
115 class DefaultDnsSocketPool : public DnsSocketPool {
116 public:
117 DefaultDnsSocketPool(ClientSocketFactory* factory)
118 : DnsSocketPool(factory) {
119 };
120
121 virtual ~DefaultDnsSocketPool();
122
123 virtual void Initialize(
124 const std::vector<IPEndPoint>* nameservers,
125 NetLog* net_log) OVERRIDE;
126
127 virtual scoped_ptr<DatagramClientSocket> AllocateSocket(
128 unsigned server_index) OVERRIDE;
129
130 virtual void FreeSocket(
131 unsigned server_index,
132 scoped_ptr<DatagramClientSocket> socket) OVERRIDE;
133
134 private:
135 void FillPool(unsigned server_index, unsigned size);
136
137 typedef std::vector<DatagramClientSocket*> SocketVector;
138
139 std::vector<SocketVector> pools_;
140
141 DISALLOW_COPY_AND_ASSIGN(DefaultDnsSocketPool);
142 };
143
144 // static
145 scoped_ptr<DnsSocketPool> DnsSocketPool::CreateDefault(
146 ClientSocketFactory* factory) {
147 return scoped_ptr<DnsSocketPool>(new DefaultDnsSocketPool(factory));
148 }
149
150 void DefaultDnsSocketPool::Initialize(
151 const std::vector<IPEndPoint>* nameservers,
152 NetLog* net_log) OVERRIDE {
szym 2012/10/08 19:32:16 OVERRIDE is only used/allowed on declaration not d
153 InitializeInternal(nameservers, net_log);
154
155 DCHECK(pools_.empty());
156 const unsigned num_servers = nameservers->size();
157 pools_.resize(num_servers);
158 for (unsigned server_index = 0; server_index < num_servers; ++server_index)
159 FillPool(server_index, kInitialPoolSize);
160 }
161
162 DefaultDnsSocketPool::~DefaultDnsSocketPool() {
163 unsigned num_servers = pools_.size();
164 for (unsigned server_index = 0; server_index < num_servers; ++server_index) {
165 SocketVector& pool = pools_[server_index];
166 STLDeleteElements(&pool);
167 }
168 }
169
170 scoped_ptr<DatagramClientSocket> DefaultDnsSocketPool::AllocateSocket(
171 unsigned server_index) {
172 DCHECK_LT(server_index, pools_.size());
173 SocketVector& pool = pools_[server_index];
174
175 FillPool(server_index, kAllocateMinSize);
176 if (pool.size() == 0) {
177 LOG(WARNING) << "No DNS sockets available in pool " << server_index << "!";
178 return scoped_ptr<DatagramClientSocket>(NULL);
179 }
180
181 if (pool.size() < kAllocateMinSize) {
182 LOG(WARNING) << "Low DNS port entropy: wanted " << kAllocateMinSize
183 << " sockets to choose from, but only have " << pool.size()
184 << " in pool " << server_index << ".";
185 }
186
187 unsigned socket_index = base::RandInt(0, pool.size() - 1);
188 DatagramClientSocket* socket = pool[socket_index];
189 pool[socket_index] = pool.back();
190 pool.pop_back();
191
192 return scoped_ptr<DatagramClientSocket>(socket);
193 }
194
195 void DefaultDnsSocketPool::FreeSocket(
196 unsigned server_index,
197 scoped_ptr<DatagramClientSocket> socket) {
198 DCHECK_LT(server_index, pools_.size());
199 SocketVector& pool = pools_[server_index];
200
201 if (pool.size() < kRetainMaxSize)
202 pool.push_back(socket.release());
203 }
204
205 void DefaultDnsSocketPool::FillPool(unsigned server_index, unsigned size) {
206 SocketVector& pool = pools_[server_index];
207
208 for (unsigned pool_index = pool.size(); pool_index < size; ++pool_index) {
209 DatagramClientSocket* socket =
210 CreateConnectedSocket(server_index).release();
211 if (!socket)
212 break;
213 pool.push_back(socket);
214 }
215 }
216
217 } // namespace net
OLDNEW
« no previous file with comments | « net/dns/dns_socket_pool.h ('k') | net/dns/dns_transaction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698