Chromium Code Reviews| Index: net/dns/dns_session.cc |
| diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc |
| index fb6c4b4c5ba269157bf7ca29cc7d5c06052ccda1..6fa277fd616b4dc60370f875b7fbf884b64fd394 100644 |
| --- a/net/dns/dns_session.cc |
| +++ b/net/dns/dns_session.cc |
| @@ -6,21 +6,36 @@ |
| #include "base/basictypes.h" |
| #include "base/bind.h" |
| +#include "base/rand_util.h" |
| +#include "base/stl_util.h" |
| #include "base/time.h" |
| #include "net/base/ip_endpoint.h" |
| +#include "net/base/net_errors.h" |
| #include "net/dns/dns_config_service.h" |
| #include "net/socket/client_socket_factory.h" |
| namespace net { |
| +DnsSession::SocketLease::SocketLease(scoped_refptr<DnsSession> session, |
| + int server_index, |
| + scoped_ptr<DatagramClientSocket> socket) |
| + : session_(session), server_index_(server_index), socket_(socket.Pass()) {} |
| + |
| +DnsSession::SocketLease::~SocketLease() { |
| + session_->FreeSocket(server_index_, socket_.Pass()); |
| +} |
| + |
| DnsSession::DnsSession(const DnsConfig& config, |
| ClientSocketFactory* factory, |
| const RandIntCallback& rand_int_callback, |
| + bool bypass_pools, |
| NetLog* net_log) |
| : config_(config), |
| socket_factory_(factory), |
| rand_callback_(base::Bind(rand_int_callback, 0, kuint16max)), |
| + bypass_pools_(bypass_pools), |
| net_log_(net_log), |
| + pools_(config.nameservers.size()), |
| server_index_(0) { |
| } |
| @@ -41,7 +56,68 @@ base::TimeDelta DnsSession::NextTimeout(int attempt) { |
| return config_.timeout * (1 << (attempt / config_.nameservers.size())); |
| } |
| -DnsSession::~DnsSession() {} |
| +DnsSession::~DnsSession() { |
| + for (size_t i = 0; i < pools_.size(); ++i) |
| + STLDeleteElements(&pools_[i]); |
| +} |
| + |
| +// TODO(ttuttle): Pool and reuse sockets. |
| + |
| +#if defined(OS_WIN) |
| +// Don't request a specific port, since that will trigger firewall prompts. |
| +static const DatagramSocket::BindType kBindType = DatagramSocket::DEFAULT_BIND; |
| +// Since we can't request random ports, keep a pool of the arbitrary ones |
| +// we've been given, to add entropy. |
| +static const size_t kMinPoolSize = 512; |
| +static const size_t kMaxPoolSize = 1024; |
| +#else |
| +static const DatagramSocket::BindType kBindType = DatagramSocket::RANDOM_BIND; |
| +static const size_t kMinPoolSize = 0; |
| +static const size_t kMaxPoolSize = 0; |
| +#endif |
| + |
| +// Allocate a socket, already connected to the server address. |
| +scoped_ptr<DnsSession::SocketLease> DnsSession::AllocateSocket(int index) { |
| + scoped_ptr<DatagramClientSocket> socket; |
| + |
| + std::vector<DatagramClientSocket*>& pool = pools_[index]; |
| + |
| + if (!bypass_pools_ && (pool.size() > kMinPoolSize)) { |
| + int pool_index = 0; // TODO(ttuttle): Random. |
| + socket.reset(pool[pool_index]); |
| + pool[pool_index] = pool.back(); |
| + pool.pop_back(); |
| + } |
| + |
| + if (!socket.get()) { |
| + socket.reset( |
| + socket_factory_->CreateDatagramClientSocket( |
| + kBindType, |
| + base::Bind(&base::RandInt), |
| + net_log_, |
| + NetLog::Source())); |
| + |
| + int rv = socket->Connect(config_.nameservers[index]); |
| + if (rv != OK) |
| + socket.reset(NULL); |
|
cbentzel
2012/08/29 16:48:06
Is this always guaranteed to complete synchronousl
szym
2012/08/29 16:57:08
Connect? Yes. Note that it does not take a Complet
|
| + } |
| + |
| + if (!socket.get()) |
| + return scoped_ptr<SocketLease>(NULL); |
| + |
| + |
| + return scoped_ptr<SocketLease>(new SocketLease(this, index, socket.Pass())); |
| +} |
| + |
| +// Release a socket. |
| +void DnsSession::FreeSocket(int index, |
| + scoped_ptr<DatagramClientSocket> socket) { |
| + std::vector<DatagramClientSocket*>& pool = pools_[index]; |
| + |
| + if (!bypass_pools_ && (pool.size() < kMaxPoolSize)) |
| + pool.push_back(socket.release()); |
| +} |
| + |
| } // namespace net |