Index: content/browser/renderer_host/p2p/socket_dispatcher_host.cc |
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc |
index da92782a4a6f398d2e56f112f02d614c7c19dad0..728556ec6ca59f646fd918a2bb0c30d28ff0bcbe 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, |