1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" 6 7#include "base/bind.h" 8#include "base/stl_util.h" 9#include "content/browser/renderer_host/p2p/socket_host.h" 10#include "content/common/p2p_messages.h" 11#include "content/public/browser/resource_context.h" 12#include "net/base/address_list.h" 13#include "net/base/completion_callback.h" 14#include "net/base/net_errors.h" 15#include "net/base/net_log.h" 16#include "net/base/sys_addrinfo.h" 17#include "net/dns/single_request_host_resolver.h" 18#include "net/url_request/url_request_context_getter.h" 19 20using content::BrowserMessageFilter; 21using content::BrowserThread; 22 23namespace content { 24 25const size_t kMaximumPacketSize = 32768; 26 27class P2PSocketDispatcherHost::DnsRequest { 28 public: 29 typedef base::Callback<void(const net::IPAddressNumber&)> DoneCallback; 30 31 DnsRequest(int32 request_id, net::HostResolver* host_resolver) 32 : request_id_(request_id), 33 resolver_(host_resolver) { 34 } 35 36 void Resolve(const std::string& host_name, 37 const DoneCallback& done_callback) { 38 DCHECK(!done_callback.is_null()); 39 40 host_name_ = host_name; 41 done_callback_ = done_callback; 42 43 // Return an error if it's an empty string. 44 if (host_name_.empty()) { 45 done_callback_.Run(net::IPAddressNumber()); 46 return; 47 } 48 49 // Add period at the end to make sure that we only resolve 50 // fully-qualified names. 51 if (host_name_.at(host_name_.size() - 1) != '.') 52 host_name_ = host_name_ + '.'; 53 54 net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0)); 55 int result = resolver_.Resolve( 56 info, 57 net::DEFAULT_PRIORITY, 58 &addresses_, 59 base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone, 60 base::Unretained(this)), 61 net::BoundNetLog()); 62 if (result != net::ERR_IO_PENDING) 63 OnDone(result); 64 } 65 66 int32 request_id() { return request_id_; } 67 68 private: 69 void OnDone(int result) { 70 if (result != net::OK) { 71 LOG(ERROR) << "Failed to resolve address for " << host_name_ 72 << ", errorcode: " << result; 73 done_callback_.Run(net::IPAddressNumber()); 74 return; 75 } 76 77 DCHECK(!addresses_.empty()); 78 done_callback_.Run(addresses_.front().address()); 79 } 80 81 int32 request_id_; 82 net::AddressList addresses_; 83 84 std::string host_name_; 85 net::SingleRequestHostResolver resolver_; 86 87 DoneCallback done_callback_; 88}; 89 90P2PSocketDispatcherHost::P2PSocketDispatcherHost( 91 content::ResourceContext* resource_context, 92 net::URLRequestContextGetter* url_context) 93 : resource_context_(resource_context), 94 url_context_(url_context), 95 monitoring_networks_(false) { 96} 97 98void P2PSocketDispatcherHost::OnChannelClosing() { 99 // Since the IPC channel is gone, close pending connections. 100 STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end()); 101 sockets_.clear(); 102 103 STLDeleteContainerPointers(dns_requests_.begin(), dns_requests_.end()); 104 dns_requests_.clear(); 105 106 if (monitoring_networks_) { 107 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 108 monitoring_networks_ = false; 109 } 110} 111 112void P2PSocketDispatcherHost::OnDestruct() const { 113 BrowserThread::DeleteOnIOThread::Destruct(this); 114} 115 116bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message, 117 bool* message_was_ok) { 118 bool handled = true; 119 IPC_BEGIN_MESSAGE_MAP_EX(P2PSocketDispatcherHost, message, *message_was_ok) 120 IPC_MESSAGE_HANDLER(P2PHostMsg_StartNetworkNotifications, 121 OnStartNetworkNotifications) 122 IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications, 123 OnStopNetworkNotifications) 124 IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress) 125 IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket) 126 IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection, 127 OnAcceptIncomingTcpConnection) 128 IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend) 129 IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket) 130 IPC_MESSAGE_UNHANDLED(handled = false) 131 IPC_END_MESSAGE_MAP_EX() 132 return handled; 133} 134 135void P2PSocketDispatcherHost::OnIPAddressChanged() { 136 // Notify the renderer about changes to list of network interfaces. 137 BrowserThread::PostTask( 138 BrowserThread::FILE, FROM_HERE, base::Bind( 139 &P2PSocketDispatcherHost::DoGetNetworkList, this)); 140} 141 142P2PSocketDispatcherHost::~P2PSocketDispatcherHost() { 143 DCHECK(sockets_.empty()); 144 DCHECK(dns_requests_.empty()); 145 146 if (monitoring_networks_) 147 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 148} 149 150P2PSocketHost* P2PSocketDispatcherHost::LookupSocket(int socket_id) { 151 SocketsMap::iterator it = sockets_.find(socket_id); 152 return (it == sockets_.end()) ? NULL : it->second; 153} 154 155void P2PSocketDispatcherHost::OnStartNetworkNotifications( 156 const IPC::Message& msg) { 157 if (!monitoring_networks_) { 158 net::NetworkChangeNotifier::AddIPAddressObserver(this); 159 monitoring_networks_ = true; 160 } 161 162 BrowserThread::PostTask( 163 BrowserThread::FILE, FROM_HERE, base::Bind( 164 &P2PSocketDispatcherHost::DoGetNetworkList, this)); 165} 166 167void P2PSocketDispatcherHost::OnStopNetworkNotifications( 168 const IPC::Message& msg) { 169 if (monitoring_networks_) { 170 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 171 monitoring_networks_ = false; 172 } 173} 174 175void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name, 176 int32 request_id) { 177 DnsRequest* request = new DnsRequest(request_id, 178 resource_context_->GetHostResolver()); 179 dns_requests_.insert(request); 180 request->Resolve(host_name, base::Bind( 181 &P2PSocketDispatcherHost::OnAddressResolved, 182 base::Unretained(this), request)); 183} 184 185void P2PSocketDispatcherHost::OnCreateSocket( 186 P2PSocketType type, int socket_id, 187 const net::IPEndPoint& local_address, 188 const net::IPEndPoint& remote_address) { 189 if (LookupSocket(socket_id)) { 190 LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket " 191 "that already exists."; 192 return; 193 } 194 195 scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create( 196 this, socket_id, type, url_context_.get(), &throttler_)); 197 198 if (!socket) { 199 Send(new P2PMsg_OnError(socket_id)); 200 return; 201 } 202 203 if (socket->Init(local_address, remote_address)) { 204 sockets_[socket_id] = socket.release(); 205 } 206} 207 208void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection( 209 int listen_socket_id, const net::IPEndPoint& remote_address, 210 int connected_socket_id) { 211 P2PSocketHost* socket = LookupSocket(listen_socket_id); 212 if (!socket) { 213 LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection " 214 "for invalid socket_id."; 215 return; 216 } 217 P2PSocketHost* accepted_connection = 218 socket->AcceptIncomingTcpConnection(remote_address, connected_socket_id); 219 if (accepted_connection) { 220 sockets_[connected_socket_id] = accepted_connection; 221 } 222} 223 224void P2PSocketDispatcherHost::OnSend(int socket_id, 225 const net::IPEndPoint& socket_address, 226 const std::vector<char>& data, 227 net::DiffServCodePoint dscp, 228 uint64 packet_id) { 229 P2PSocketHost* socket = LookupSocket(socket_id); 230 if (!socket) { 231 LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id."; 232 return; 233 } 234 235 if (data.size() > kMaximumPacketSize) { 236 LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: " 237 << data.size(); 238 Send(new P2PMsg_OnError(socket_id)); 239 delete socket; 240 sockets_.erase(socket_id); 241 return; 242 } 243 244 socket->Send(socket_address, data, dscp, packet_id); 245} 246 247void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) { 248 SocketsMap::iterator it = sockets_.find(socket_id); 249 if (it != sockets_.end()) { 250 delete it->second; 251 sockets_.erase(it); 252 } else { 253 LOG(ERROR) << "Received P2PHostMsg_DestroySocket for invalid socket_id."; 254 } 255} 256 257void P2PSocketDispatcherHost::DoGetNetworkList() { 258 net::NetworkInterfaceList list; 259 net::GetNetworkList(&list); 260 BrowserThread::PostTask( 261 BrowserThread::IO, FROM_HERE, base::Bind( 262 &P2PSocketDispatcherHost::SendNetworkList, this, list)); 263} 264 265void P2PSocketDispatcherHost::SendNetworkList( 266 const net::NetworkInterfaceList& list) { 267 Send(new P2PMsg_NetworkListChanged(list)); 268} 269 270void P2PSocketDispatcherHost::OnAddressResolved( 271 DnsRequest* request, 272 const net::IPAddressNumber& result) { 273 Send(new P2PMsg_GetHostAddressResult(request->request_id(), result)); 274 275 dns_requests_.erase(request); 276 delete request; 277} 278 279} // namespace content 280