Commit efa5d938 authored by sergeyu@chromium.org's avatar sergeyu@chromium.org

Add IPC for DNS host address resolution.

TEST=None
BUG=83242

Review URL: http://codereview.chromium.org/7599003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96047 0039d316-1c4b-4281-b951-d872f2087c98
parent cbee9362
......@@ -402,7 +402,8 @@ void BrowserRenderProcessHost::CreateMessageFilters() {
widget_helper_.get(), &RenderWidgetHelper::GetNextRoutingID)));
#if defined(ENABLE_P2P_APIS)
channel_->AddFilter(new P2PSocketDispatcherHost());
channel_->AddFilter(new P2PSocketDispatcherHost(
&browser_context()->GetResourceContext()));
#endif
channel_->AddFilter(new TraceMessageFilter());
......
......@@ -4,16 +4,105 @@
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "base/bind.h"
#include "base/stl_util.h"
#include "content/browser/renderer_host/p2p/socket_host.h"
#include "content/browser/resource_context.h"
#include "content/common/p2p_messages.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/base/single_request_host_resolver.h"
#include "net/base/sys_addrinfo.h"
P2PSocketDispatcherHost::P2PSocketDispatcherHost()
: monitoring_networks_(false) {
class P2PSocketDispatcherHost::DnsRequest {
public:
typedef base::Callback<void(const net::IPAddressNumber&)> DoneCallback;
DnsRequest(int32 routing_id, int32 request_id,
net::HostResolver* host_resolver)
: routing_id_(routing_id),
request_id_(request_id),
resolver_(host_resolver),
ALLOW_THIS_IN_INITIALIZER_LIST(completion_callback_(
this, &P2PSocketDispatcherHost::DnsRequest::OnDone)) {
}
void Resolve(const std::string& host_name,
const DoneCallback& done_callback) {
DCHECK(!done_callback.is_null());
host_name_ = host_name;
done_callback_ = done_callback;
// Return an error if it's an empty string.
if (host_name_.empty()) {
done_callback_.Run(net::IPAddressNumber());
return;
}
// Add period at the end to make sure that we only resolve
// fully-qualified names.
if (host_name_.at(host_name_.size() - 1) != '.')
host_name_ = host_name_ + '.';
net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
resolver_.Resolve(info, &addresses_, &completion_callback_,
net::BoundNetLog());
}
int32 routing_id() { return routing_id_; }
int32 request_id() { return request_id_; }
private:
void OnDone(int result) {
if (result != net::OK) {
LOG(ERROR) << "Failed to resolve address for " << host_name_
<< ", errorcode: " << result;
done_callback_.Run(net::IPAddressNumber());
return;
}
if (addresses_.head() == NULL) {
LOG(ERROR) << "Received 0 addresses when trying to resolve address for "
<< host_name_;
done_callback_.Run(net::IPAddressNumber());
return;
}
net::IPEndPoint end_point;
if (!end_point.FromSockAddr(addresses_.head()->ai_addr,
addresses_.head()->ai_addrlen)) {
LOG(ERROR) << "Received invalid address for " << host_name_;
done_callback_.Run(net::IPAddressNumber());
return;
}
done_callback_.Run(end_point.address());
}
int32 routing_id_;
int32 request_id_;
net::AddressList addresses_;
std::string host_name_;
net::SingleRequestHostResolver resolver_;
DoneCallback done_callback_;
net::CompletionCallbackImpl<DnsRequest> completion_callback_;
};
P2PSocketDispatcherHost::P2PSocketDispatcherHost(
const content::ResourceContext* resource_context)
: resource_context_(resource_context),
monitoring_networks_(false) {
}
P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {
DCHECK(sockets_.empty());
DCHECK(dns_requests_.empty());
if (monitoring_networks_)
net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
......@@ -25,6 +114,9 @@ void P2PSocketDispatcherHost::OnChannelClosing() {
// Since the IPC channel is gone, close pending connections.
STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end());
sockets_.clear();
STLDeleteContainerPointers(dns_requests_.begin(), dns_requests_.end());
dns_requests_.clear();
}
void P2PSocketDispatcherHost::OnDestruct() const {
......@@ -39,6 +131,7 @@ bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message,
OnStartNetworkNotifications)
IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications,
OnStopNetworkNotifications)
IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress)
IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket)
IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection,
OnAcceptIncomingTcpConnection)
......@@ -101,6 +194,27 @@ void P2PSocketDispatcherHost::SendNetworkList(
}
}
void P2PSocketDispatcherHost::OnGetHostAddress(const IPC::Message& msg,
const std::string& host_name,
int32 request_id) {
DnsRequest* request = new DnsRequest(
msg.routing_id(), request_id, resource_context_->host_resolver());
request->Resolve(host_name, base::Bind(
&P2PSocketDispatcherHost::OnAddressResolved,
base::Unretained(this), request));
dns_requests_.insert(request);
}
void P2PSocketDispatcherHost::OnAddressResolved(
DnsRequest* request,
const net::IPAddressNumber& result) {
Send(new P2PMsg_GetHostAddressResult(
request->routing_id(), request->request_id(), result));
dns_requests_.erase(request);
delete request;
}
void P2PSocketDispatcherHost::OnCreateSocket(
const IPC::Message& msg, P2PSocketType type, int socket_id,
const net::IPEndPoint& local_address,
......
......@@ -12,13 +12,17 @@
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
namespace content {
class ResourceContext;
} // namespace content
class P2PSocketHost;
class P2PSocketDispatcherHost
: public BrowserMessageFilter,
public net::NetworkChangeNotifier::IPAddressObserver {
public:
P2PSocketDispatcherHost();
P2PSocketDispatcherHost(const content::ResourceContext* resource_context);
virtual ~P2PSocketDispatcherHost();
// BrowserMessageFilter overrides.
......@@ -34,12 +38,18 @@ class P2PSocketDispatcherHost
typedef std::pair<int32, int> ExtendedSocketId;
typedef std::map<ExtendedSocketId, P2PSocketHost*> SocketsMap;
class DnsRequest;
P2PSocketHost* LookupSocket(int32 routing_id, int socket_id);
// Handlers for the messages coming from the renderer.
void OnStartNetworkNotifications(const IPC::Message& msg);
void OnStopNetworkNotifications(const IPC::Message& msg);
void OnGetHostAddress(const IPC::Message& msg,
const std::string& host_name,
int32 request_id);
void OnCreateSocket(const IPC::Message& msg,
P2PSocketType type,
int socket_id,
......@@ -57,6 +67,11 @@ class P2PSocketDispatcherHost
void DoGetNetworkList();
void SendNetworkList(const net::NetworkInterfaceList& list);
void OnAddressResolved(DnsRequest* request,
const net::IPAddressNumber& result);
const content::ResourceContext* resource_context_;
SocketsMap sockets_;
bool monitoring_networks_;
......@@ -65,6 +80,8 @@ class P2PSocketDispatcherHost
// network list notifications.
std::set<int> notifications_routing_ids_;
std::set<DnsRequest*> dns_requests_;
DISALLOW_COPY_AND_ASSIGN(P2PSocketDispatcherHost);
};
......
......@@ -24,6 +24,10 @@ IPC_STRUCT_TRAITS_END()
IPC_MESSAGE_ROUTED1(P2PMsg_NetworkListChanged,
net::NetworkInterfaceList /* networks */)
IPC_MESSAGE_ROUTED2(P2PMsg_GetHostAddressResult,
int32 /* request_id */,
net::IPAddressNumber /* address */)
IPC_MESSAGE_ROUTED2(P2PMsg_OnSocketCreated,
int /* socket_id */,
net::IPEndPoint /* socket_address */)
......@@ -47,6 +51,10 @@ IPC_MESSAGE_ROUTED3(P2PMsg_OnDataReceived,
IPC_MESSAGE_ROUTED0(P2PHostMsg_StartNetworkNotifications)
IPC_MESSAGE_ROUTED0(P2PHostMsg_StopNetworkNotifications)
IPC_MESSAGE_ROUTED2(P2PHostMsg_GetHostAddress,
std::string /* host_name */,
int32 /* request_id */)
IPC_MESSAGE_ROUTED4(P2PHostMsg_CreateSocket,
P2PSocketType /* type */,
int /* socket_id */,
......
......@@ -181,6 +181,8 @@
'conditions': [
['p2p_apis==1', {
'sources': [
'renderer/p2p/host_address_request.cc',
'renderer/p2p/host_address_request.h',
'renderer/p2p/ipc_network_manager.cc',
'renderer/p2p/ipc_network_manager.h',
'renderer/p2p/ipc_socket_factory.cc',
......
// Copyright (c) 2011 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 "content/renderer/p2p/host_address_request.h"
#include "base/bind.h"
#include "base/message_loop_proxy.h"
#include "content/common/p2p_messages.h"
#include "content/renderer/p2p/socket_dispatcher.h"
P2PHostAddressRequest::P2PHostAddressRequest(P2PSocketDispatcher* dispatcher)
: dispatcher_(dispatcher),
ipc_message_loop_(dispatcher->message_loop()),
delegate_message_loop_(base::MessageLoopProxy::CreateForCurrentThread()),
state_(STATE_CREATED),
request_id_(0),
registered_(false) {
}
P2PHostAddressRequest::~P2PHostAddressRequest() {
DCHECK(state_ == STATE_CREATED || state_ == STATE_FINISHED);
}
void P2PHostAddressRequest::Request(const std::string& host_name,
const DoneCallback& done_callback) {
DCHECK(delegate_message_loop_->BelongsToCurrentThread());
state_ = STATE_SENT;
ipc_message_loop_->PostTask(FROM_HERE, base::Bind(
&P2PHostAddressRequest::DoSendRequest, this, host_name, done_callback));
}
void P2PHostAddressRequest::Cancel() {
DCHECK(delegate_message_loop_->BelongsToCurrentThread());
if (state_ != STATE_FINISHED) {
state_ = STATE_FINISHED;
ipc_message_loop_->PostTask(FROM_HERE, base::Bind(
&P2PHostAddressRequest::DoUnregister, this));
}
}
void P2PHostAddressRequest::DoSendRequest(const std::string& host_name,
const DoneCallback& done_callback) {
DCHECK(ipc_message_loop_->BelongsToCurrentThread());
done_callback_ = done_callback;
request_id_ = dispatcher_->RegisterHostAddressRequest(this);
registered_ = true;
dispatcher_->SendP2PMessage(
new P2PHostMsg_GetHostAddress(0, host_name, request_id_));
}
void P2PHostAddressRequest::DoUnregister() {
DCHECK(ipc_message_loop_->BelongsToCurrentThread());
if (registered_) {
dispatcher_->UnregisterHostAddressRequest(request_id_);
registered_ = false;
}
}
void P2PHostAddressRequest::OnResponse(const net::IPAddressNumber& address) {
DCHECK(ipc_message_loop_->BelongsToCurrentThread());
delegate_message_loop_->PostTask(FROM_HERE, base::Bind(
&P2PHostAddressRequest::DeliverResponse, this, address));
dispatcher_->UnregisterHostAddressRequest(request_id_);
registered_ = false;
}
void P2PHostAddressRequest::DeliverResponse(
const net::IPAddressNumber& address) {
DCHECK(delegate_message_loop_->BelongsToCurrentThread());
if (state_ == STATE_SENT) {
done_callback_.Run(address);
state_ = STATE_FINISHED;
}
}
// Copyright (c) 2011 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.
#ifndef CONTENT_RENDERER_P2P_HOST_ADDRESS_REQUEST_H_
#define CONTENT_RENDERER_P2P_HOST_ADDRESS_REQUEST_H_
#include <string>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_util.h"
namespace base {
class MessageLoopProxy;
} // namespace base
class P2PSocketDispatcher;
class P2PHostAddressRequest :
public base::RefCountedThreadSafe<P2PHostAddressRequest> {
public:
typedef base::Callback<void(const net::IPAddressNumber&)> DoneCallback;
P2PHostAddressRequest(P2PSocketDispatcher* dispatcher);
// Sends host address request.
void Request(const std::string& host_name,
const DoneCallback& done_callback);
// Cancels the request. The callback passed to Request() will not be
// called after Cancel() is called.
void Cancel();
private:
enum State {
STATE_CREATED,
STATE_SENT,
STATE_FINISHED,
};
friend class P2PSocketDispatcher;
friend class base::RefCountedThreadSafe<P2PHostAddressRequest>;
virtual ~P2PHostAddressRequest();
void DoSendRequest(const std::string& host_name,
const DoneCallback& done_callback);
void DoUnregister();
void OnResponse(const net::IPAddressNumber& address);
void DeliverResponse(const net::IPAddressNumber& address);
P2PSocketDispatcher* dispatcher_;
scoped_refptr<base::MessageLoopProxy> ipc_message_loop_;
scoped_refptr<base::MessageLoopProxy> delegate_message_loop_;
DoneCallback done_callback_;
// State must be accessed from delegate thread only.
State state_;
// Accessed on the IPC thread only.
int32 request_id_;
bool registered_;
DISALLOW_COPY_AND_ASSIGN(P2PHostAddressRequest);
};
#endif // CONTENT_RENDERER_P2P_HOST_ADDRESS_REQUEST_H_
......@@ -6,6 +6,8 @@
#include "base/message_loop_proxy.h"
#include "content/common/p2p_messages.h"
#include "content/renderer/p2p/host_address_request.h"
#include "content/renderer/p2p/socket_client.h"
P2PSocketDispatcher::P2PSocketDispatcher(RenderView* render_view)
: RenderViewObserver(render_view),
......@@ -42,6 +44,7 @@ bool P2PSocketDispatcher::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcher, message)
IPC_MESSAGE_HANDLER(P2PMsg_NetworkListChanged, OnNetworkListChanged)
IPC_MESSAGE_HANDLER(P2PMsg_GetHostAddressResult, OnGetHostAddressResult)
IPC_MESSAGE_HANDLER(P2PMsg_OnSocketCreated, OnSocketCreated)
IPC_MESSAGE_HANDLER(P2PMsg_OnIncomingTcpConnection, OnIncomingTcpConnection)
IPC_MESSAGE_HANDLER(P2PMsg_OnError, OnError)
......@@ -51,6 +54,10 @@ bool P2PSocketDispatcher::OnMessageReceived(const IPC::Message& message) {
return handled;
}
base::MessageLoopProxy* P2PSocketDispatcher::message_loop() {
return message_loop_;
}
int P2PSocketDispatcher::RegisterClient(P2PSocketClient* client) {
return clients_.Add(client);
}
......@@ -64,8 +71,13 @@ void P2PSocketDispatcher::SendP2PMessage(IPC::Message* msg) {
Send(msg);
}
base::MessageLoopProxy* P2PSocketDispatcher::message_loop() {
return message_loop_;
int P2PSocketDispatcher::RegisterHostAddressRequest(
P2PHostAddressRequest* request) {
return host_address_requests_.Add(request);
}
void P2PSocketDispatcher::UnregisterHostAddressRequest(int id) {
host_address_requests_.Remove(id);
}
void P2PSocketDispatcher::OnNetworkListChanged(
......@@ -74,6 +86,18 @@ void P2PSocketDispatcher::OnNetworkListChanged(
networks);
}
void P2PSocketDispatcher::OnGetHostAddressResult(
int32 request_id,
const net::IPAddressNumber& address) {
P2PHostAddressRequest* request = host_address_requests_.Lookup(request_id);
if (!request) {
VLOG(1) << "Received P2P message for socket that doesn't exist.";
return;
}
request->OnResponse(address);
}
void P2PSocketDispatcher::OnSocketCreated(
int socket_id, const net::IPEndPoint& address) {
P2PSocketClient* client = GetClient(socket_id);
......
......@@ -27,13 +27,20 @@
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
#include "content/common/p2p_sockets.h"
#include "content/renderer/p2p/socket_client.h"
#include "content/renderer/render_view_observer.h"
#include "net/base/net_util.h"
namespace base {
class MessageLoopProxy;
} // namespace base
namespace net {
class IPEndPoint;
} // namespace net
class P2PHostAddressRequest;
class P2PSocketClient;
// P2PSocketDispatcher works on the renderer thread. It dispatches all
// messages on that thread, and all its methods must be called on the
// same thread.
......@@ -68,16 +75,24 @@ class P2PSocketDispatcher : public RenderViewObserver {
virtual bool OnMessageReceived(const IPC::Message& message);
private:
friend class P2PHostAddressRequest;
friend class P2PSocketClient;
base::MessageLoopProxy* message_loop();
// Called by P2PSocketClient.
int RegisterClient(P2PSocketClient* client);
void UnregisterClient(int id);
void SendP2PMessage(IPC::Message* msg);
base::MessageLoopProxy* message_loop();
// Called by DnsRequest.
int RegisterHostAddressRequest(P2PHostAddressRequest* request);
void UnregisterHostAddressRequest(int id);
// Incoming message handlers.
void OnNetworkListChanged(const net::NetworkInterfaceList& networks);
void OnGetHostAddressResult(int32 request_id,
const net::IPAddressNumber& address);
void OnSocketCreated(int socket_id, const net::IPEndPoint& address);
void OnIncomingTcpConnection(int socket_id, const net::IPEndPoint& address);
void OnError(int socket_id);
......@@ -89,6 +104,8 @@ class P2PSocketDispatcher : public RenderViewObserver {
scoped_refptr<base::MessageLoopProxy> message_loop_;
IDMap<P2PSocketClient> clients_;
IDMap<P2PHostAddressRequest> host_address_requests_;
bool network_notifications_started_;
scoped_refptr<ObserverListThreadSafe<NetworkListObserver> >
network_list_observers_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment