summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 01:02:45 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-11 01:02:45 +0000
commitdfa5899df4fe3f38219670935d0654049837539a (patch)
tree2590b02cc5a77fd3e23b6d46319b28476a5ced65
parent276a1a27897fdd5ca8dce3090388f95f44f8165f (diff)
downloadchromium_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.cc3
-rw-r--r--content/browser/renderer_host/p2p/socket_dispatcher_host.cc118
-rw-r--r--content/browser/renderer_host/p2p/socket_dispatcher_host.h19
-rw-r--r--content/common/p2p_messages.h8
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/renderer/p2p/host_address_request.cc77
-rw-r--r--content/renderer/p2p/host_address_request.h68
-rw-r--r--content/renderer/p2p/socket_dispatcher.cc28
-rw-r--r--content/renderer/p2p/socket_dispatcher.h21
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_;