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 |