| // Copyright 2015 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. |
| |
| #include "net/dns/mojo_host_resolver_impl.h" |
| |
| #include <utility> |
| |
| #include "net/base/address_list.h" |
| #include "net/base/net_errors.h" |
| #include "net/base/network_interfaces.h" |
| #include "net/dns/host_resolver.h" |
| |
| namespace net { |
| |
| // Handles host resolution for a single request and sends a response when done. |
| // Also detects connection errors for HostResolverRequestClient and cancels the |
| // outstanding resolve request. Owned by MojoHostResolverImpl. |
| class MojoHostResolverImpl::Job { |
| public: |
| Job(MojoHostResolverImpl* resolver_service, |
| net::HostResolver* resolver, |
| const net::HostResolver::RequestInfo& request_info, |
| const NetLogWithSource& net_log, |
| interfaces::HostResolverRequestClientPtr client); |
| ~Job(); |
| |
| void set_iter(std::list<Job>::iterator iter) { iter_ = iter; } |
| |
| void Start(); |
| |
| private: |
| // Completion callback for the HostResolver::Resolve request. |
| void OnResolveDone(int result); |
| |
| // Mojo error handler. |
| void OnConnectionError(); |
| |
| MojoHostResolverImpl* resolver_service_; |
| // This Job's iterator in |resolver_service_|, so the Job may be removed on |
| // completion. |
| std::list<Job>::iterator iter_; |
| net::HostResolver* resolver_; |
| net::HostResolver::RequestInfo request_info_; |
| const NetLogWithSource net_log_; |
| interfaces::HostResolverRequestClientPtr client_; |
| std::unique_ptr<net::HostResolver::Request> request_; |
| AddressList result_; |
| base::ThreadChecker thread_checker_; |
| }; |
| |
| MojoHostResolverImpl::MojoHostResolverImpl(net::HostResolver* resolver, |
| const NetLogWithSource& net_log) |
| : resolver_(resolver), net_log_(net_log) {} |
| |
| MojoHostResolverImpl::~MojoHostResolverImpl() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| } |
| |
| void MojoHostResolverImpl::Resolve( |
| std::unique_ptr<HostResolver::RequestInfo> request_info, |
| interfaces::HostResolverRequestClientPtr client) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| if (request_info->is_my_ip_address()) { |
| // The proxy resolver running inside a sandbox may not be able to get the |
| // correct host name. Instead, fill it ourself if the request is for our own |
| // IP address. |
| request_info->set_host_port_pair(HostPortPair(GetHostName(), 80)); |
| } |
| |
| pending_jobs_.emplace_front(this, resolver_, *request_info, net_log_, |
| std::move(client)); |
| auto job = pending_jobs_.begin(); |
| job->set_iter(job); |
| job->Start(); |
| } |
| |
| void MojoHostResolverImpl::DeleteJob(std::list<Job>::iterator job) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| pending_jobs_.erase(job); |
| } |
| |
| MojoHostResolverImpl::Job::Job( |
| MojoHostResolverImpl* resolver_service, |
| net::HostResolver* resolver, |
| const net::HostResolver::RequestInfo& request_info, |
| const NetLogWithSource& net_log, |
| interfaces::HostResolverRequestClientPtr client) |
| : resolver_service_(resolver_service), |
| resolver_(resolver), |
| request_info_(request_info), |
| net_log_(net_log), |
| client_(std::move(client)) { |
| client_.set_connection_error_handler(base::Bind( |
| &MojoHostResolverImpl::Job::OnConnectionError, base::Unretained(this))); |
| } |
| |
| void MojoHostResolverImpl::Job::Start() { |
| // The caller is responsible for setting up |iter_|. |
| DCHECK_EQ(this, &*iter_); |
| |
| DVLOG(1) << "Resolve " << request_info_.host_port_pair().ToString(); |
| int result = |
| resolver_->Resolve(request_info_, DEFAULT_PRIORITY, &result_, |
| base::Bind(&MojoHostResolverImpl::Job::OnResolveDone, |
| base::Unretained(this)), |
| &request_, net_log_); |
| |
| if (result != ERR_IO_PENDING) |
| OnResolveDone(result); |
| } |
| |
| MojoHostResolverImpl::Job::~Job() = default; |
| |
| void MojoHostResolverImpl::Job::OnResolveDone(int result) { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| request_.reset(); |
| DVLOG(1) << "Resolved " << request_info_.host_port_pair().ToString() |
| << " with error " << result << " and " << result_.size() |
| << " results!"; |
| for (const auto& address : result_) { |
| DVLOG(1) << address.ToString(); |
| } |
| client_->ReportResult(result, result_); |
| resolver_service_->DeleteJob(iter_); |
| } |
| |
| void MojoHostResolverImpl::Job::OnConnectionError() { |
| DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
| // |resolver_service_| should always outlive us. |
| DCHECK(resolver_service_); |
| DVLOG(1) << "Connection error on request for " |
| << request_info_.host_port_pair().ToString(); |
| resolver_service_->DeleteJob(iter_); |
| } |
| |
| } // namespace net |