| Index: net/dns/dns_session.cc
|
| diff --git a/net/dns/dns_session.cc b/net/dns/dns_session.cc
|
| index fb6c4b4c5ba269157bf7ca29cc7d5c06052ccda1..3d1b9d050e5f4e90282a874ed8ab8432ebe0f03e 100644
|
| --- a/net/dns/dns_session.cc
|
| +++ b/net/dns/dns_session.cc
|
| @@ -6,13 +6,25 @@
|
|
|
| #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,
|
| @@ -21,6 +33,7 @@ DnsSession::DnsSession(const DnsConfig& config,
|
| socket_factory_(factory),
|
| rand_callback_(base::Bind(rand_int_callback, 0, kuint16max)),
|
| net_log_(net_log),
|
| + sockets_(config.nameservers.size()),
|
| server_index_(0) {
|
| }
|
|
|
| @@ -41,7 +54,58 @@ base::TimeDelta DnsSession::NextTimeout(int attempt) {
|
| return config_.timeout * (1 << (attempt / config_.nameservers.size()));
|
| }
|
|
|
| -DnsSession::~DnsSession() {}
|
| +// Allocate a socket, already connected to the server address.
|
| +scoped_ptr<DnsSession::SocketLease> DnsSession::AllocateSocket(int index) {
|
| +#if defined(OS_WIN)
|
| + // TODO(szym): Require N sockets for entropy. (N = 1000?)
|
| + if (!sockets_[index].empty()) {
|
| + // TODO(szym): Pick a random socket.
|
| + return scoped_ptr<SocketLease>(new SocketLease(this, index,
|
| + sockets_[index].pop_back()));
|
| + }
|
| + // Allocate a socket.
|
| + scoped_ptr<DatagramClientSocket> socket(
|
| + socket_factory_->CreateDatagramClientSocket(
|
| + DatagramSocket::DEFAULT_BIND,
|
| + base::Bind(&base::RandInt),
|
| + net_log_,
|
| + NetLog::Source()));
|
| +
|
| +#else
|
| + scoped_ptr<DatagramClientSocket> socket(
|
| + socket_factory_->CreateDatagramClientSocket(
|
| + DatagramSocket::RANDOM_BIND,
|
| + base::Bind(&base::RandInt),
|
| + net_log_,
|
| + NetLog::Source()));
|
| +#endif
|
| +
|
| + if (!socket.get())
|
| + return scoped_ptr<SocketLease>(NULL);
|
| +
|
| + int rv = socket->Connect(config_.nameservers[index]);
|
| + if (rv != OK)
|
| + 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) {
|
| +#if defined(OS_WIN)
|
| + // TODO(szym): DCHECK(config.nameservers[index] == socket.GetPeerAddress())
|
| + sockets_[index].push_back(socket.release());
|
| +#endif
|
| + // else: Do nothing. This destroys the socket.
|
| +}
|
| +
|
| +DnsSession::~DnsSession() {
|
| + for (size_t i = 0; i < sockets_.size(); ++i) {
|
| + STLDeleteElements(&sockets_[i]);
|
| + }
|
| +}
|
| +
|
|
|
| } // namespace net
|
|
|
|
|