blob: 7877f137b0a7c997494e1d0fdeaf2561f8416557 [file] [log] [blame]
// 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 "mojo/services/network/host_resolver_impl.h"
#include "mojo/services/network/net_adapters.h"
#include "mojo/services/network/net_address_type_converters.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/dns/host_resolver.h"
#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h"
namespace mojo {
namespace {
class HostResolverImplJob {
public:
// After creating a HostResolverImplJob, |Start| must be called.
HostResolverImplJob(net::HostResolver::RequestInfo request_info,
const HostResolver::GetHostAddressesCallback& callback)
: callback_(callback),
request_info_(request_info) {
}
// You are required to call |Start|. The object will automatically be deleted
// when OnResolveDone is called.
void Start(net::HostResolver* resolver) {
DCHECK(resolver);
net::BoundNetLog net_log;
int result = resolver->Resolve(
request_info_,
net::DEFAULT_PRIORITY,
&addresses_,
base::Bind(&HostResolverImplJob::OnResolveDone, base::Unretained(this)),
&handle_,
net_log);
if (result == net::ERR_IO_PENDING) {
return;
}
// Synchronous result.
OnResolveDone(result);
}
private:
~HostResolverImplJob() {
DCHECK(thread_checker_.CalledOnValidThread());
}
void OnResolveDone(int result) {
DCHECK(thread_checker_.CalledOnValidThread());
Array<NetAddressPtr> net_addresses;
if (result == net::OK) {
for (size_t i = 0; i < addresses_.size(); i++) {
net_addresses.push_back(NetAddress::From(addresses_[i]));
}
}
callback_.Run(MakeNetworkError(result), net_addresses.Pass());
delete this;
}
HostResolver::GetHostAddressesCallback callback_;
net::HostResolver::RequestInfo request_info_;
net::HostResolver::RequestHandle handle_;
net::AddressList addresses_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(HostResolverImplJob);
};
} // namespace
HostResolverImpl::HostResolverImpl(InterfaceRequest<HostResolver> request)
: binding_(this, request.Pass()),
resolver_(net::HostResolver::CreateDefaultResolver(nullptr).Pass()) {
DCHECK(resolver_);
}
HostResolverImpl::~HostResolverImpl() {
DCHECK(thread_checker_.CalledOnValidThread());
}
static net::AddressFamily ConvertFamily(NetAddressFamily family) {
switch (family) {
case NetAddressFamily::UNSPECIFIED:
return net::ADDRESS_FAMILY_UNSPECIFIED;
case NetAddressFamily::IPV4:
return net::ADDRESS_FAMILY_IPV4;
case NetAddressFamily::IPV6:
return net::ADDRESS_FAMILY_IPV6;
default:
NOTREACHED();
return net::ADDRESS_FAMILY_UNSPECIFIED;
}
}
void HostResolverImpl::GetHostAddresses(const mojo::String& host,
NetAddressFamily family,
const GetHostAddressesCallback& callback) {
DCHECK(thread_checker_.CalledOnValidThread());
net::HostPortPair host_port_pair(host, 0);
net::HostResolver::RequestInfo request_info(host_port_pair);
request_info.set_address_family(ConvertFamily(family));
HostResolverImplJob* job = new HostResolverImplJob(request_info, callback);
job->Start(resolver_.get());
}
} // namespace mojo