diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-11 01:02:45 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-11 01:02:45 +0000 |
commit | dfa5899df4fe3f38219670935d0654049837539a (patch) | |
tree | 2590b02cc5a77fd3e23b6d46319b28476a5ced65 | |
parent | 276a1a27897fdd5ca8dce3090388f95f44f8165f (diff) | |
download | chromium_src-dfa5899df4fe3f38219670935d0654049837539a.zip chromium_src-dfa5899df4fe3f38219670935d0654049837539a.tar.gz chromium_src-dfa5899df4fe3f38219670935d0654049837539a.tar.bz2 |
Merge 96047 - Add IPC for DNS host address resolution.
TEST=None
BUG=83242
Review URL: http://codereview.chromium.org/7599003
TBR=sergeyu@chromium.org
Review URL: http://codereview.chromium.org/7587018
git-svn-id: svn://svn.chromium.org/chrome/branches/835/src@96286 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/browser_render_process_host.cc | 3 | ||||
-rw-r--r-- | content/browser/renderer_host/p2p/socket_dispatcher_host.cc | 118 | ||||
-rw-r--r-- | content/browser/renderer_host/p2p/socket_dispatcher_host.h | 19 | ||||
-rw-r--r-- | content/common/p2p_messages.h | 8 | ||||
-rw-r--r-- | content/content_renderer.gypi | 2 | ||||
-rw-r--r-- | content/renderer/p2p/host_address_request.cc | 77 | ||||
-rw-r--r-- | content/renderer/p2p/host_address_request.h | 68 | ||||
-rw-r--r-- | content/renderer/p2p/socket_dispatcher.cc | 28 | ||||
-rw-r--r-- | content/renderer/p2p/socket_dispatcher.h | 21 |
9 files changed, 336 insertions, 8 deletions
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc index d93f0f2..45dea6a 100644 --- a/content/browser/renderer_host/browser_render_process_host.cc +++ b/content/browser/renderer_host/browser_render_process_host.cc @@ -399,7 +399,8 @@ void BrowserRenderProcessHost::CreateMessageFilters() { widget_helper_.get(), &RenderWidgetHelper::GetNextRoutingID))); #if defined(ENABLE_P2P_APIS) - channel_->AddFilter(new P2PSocketDispatcherHost()); + channel_->AddFilter(new P2PSocketDispatcherHost( + &profile()->->GetResourceContext())); #endif channel_->AddFilter(new TraceMessageFilter()); diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc index da92782..728556e 100644 --- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc +++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc @@ -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, diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.h b/content/browser/renderer_host/p2p/socket_dispatcher_host.h index e704e9d..54a91c6 100644 --- a/content/browser/renderer_host/p2p/socket_dispatcher_host.h +++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.h @@ -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); }; diff --git a/content/common/p2p_messages.h b/content/common/p2p_messages.h index cf6ddca..7f2ec2e 100644 --- a/content/common/p2p_messages.h +++ b/content/common/p2p_messages.h @@ -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 */, diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 64c2f8a..10e0c69 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -179,6 +179,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', diff --git a/content/renderer/p2p/host_address_request.cc b/content/renderer/p2p/host_address_request.cc new file mode 100644 index 0000000..92b9f33 --- /dev/null +++ b/content/renderer/p2p/host_address_request.cc @@ -0,0 +1,77 @@ +// 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/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, NewRunnableMethod( + this, &P2PHostAddressRequest::DoSendRequest, 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, NewRunnableMethod( + this, &P2PHostAddressRequest::DoUnregister)); + } +} + +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, NewRunnableMethod( + this, &P2PHostAddressRequest::DeliverResponse, 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; + } +} diff --git a/content/renderer/p2p/host_address_request.h b/content/renderer/p2p/host_address_request.h new file mode 100644 index 0000000..14a5ae0 --- /dev/null +++ b/content/renderer/p2p/host_address_request.h @@ -0,0 +1,68 @@ +// 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_ diff --git a/content/renderer/p2p/socket_dispatcher.cc b/content/renderer/p2p/socket_dispatcher.cc index 43c9de3..ba00e99 100644 --- a/content/renderer/p2p/socket_dispatcher.cc +++ b/content/renderer/p2p/socket_dispatcher.cc @@ -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); diff --git a/content/renderer/p2p/socket_dispatcher.h b/content/renderer/p2p/socket_dispatcher.h index c4b71cd..3dbc49d 100644 --- a/content/renderer/p2p/socket_dispatcher.h +++ b/content/renderer/p2p/socket_dispatcher.h @@ -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_; |