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 20 using content::BrowserMessageFilter; 21 using content::BrowserThread; 22 23 namespace content { 24 25 const size_t kMaximumPacketSize = 32768; 26 27 class P2PSocketDispatcherHost::DnsRequest { 28 public: 29 typedef base::Callback<void(const net::IPAddressList&)> 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 net::IPAddressList address_list; 46 done_callback_.Run(address_list); 47 return; 48 } 49 50 // Add period at the end to make sure that we only resolve 51 // fully-qualified names. 52 if (host_name_.at(host_name_.size() - 1) != '.') 53 host_name_ = host_name_ + '.'; 54 55 net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0)); 56 int result = resolver_.Resolve( 57 info, 58 net::DEFAULT_PRIORITY, 59 &addresses_, 60 base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone, 61 base::Unretained(this)), 62 net::BoundNetLog()); 63 if (result != net::ERR_IO_PENDING) 64 OnDone(result); 65 } 66 67 int32 request_id() { return request_id_; } 68 69 private: 70 void OnDone(int result) { 71 net::IPAddressList list; 72 if (result != net::OK) { 73 LOG(ERROR) << "Failed to resolve address for " << host_name_ 74 << ", errorcode: " << result; 75 done_callback_.Run(list); 76 return; 77 } 78 79 DCHECK(!addresses_.empty()); 80 for (net::AddressList::iterator iter = addresses_.begin(); 81 iter != addresses_.end(); ++iter) { 82 list.push_back(iter->address()); 83 } 84 done_callback_.Run(list); 85 } 86 87 int32 request_id_; 88 net::AddressList addresses_; 89 90 std::string host_name_; 91 net::SingleRequestHostResolver resolver_; 92 93 DoneCallback done_callback_; 94 }; 95 96 P2PSocketDispatcherHost::P2PSocketDispatcherHost( 97 content::ResourceContext* resource_context, 98 net::URLRequestContextGetter* url_context) 99 : BrowserMessageFilter(P2PMsgStart), 100 resource_context_(resource_context), 101 url_context_(url_context), 102 monitoring_networks_(false), 103 dump_incoming_rtp_packet_(false), 104 dump_outgoing_rtp_packet_(false) { 105 } 106 107 void P2PSocketDispatcherHost::OnChannelClosing() { 108 // Since the IPC sender is gone, close pending connections. 109 STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end()); 110 sockets_.clear(); 111 112 STLDeleteContainerPointers(dns_requests_.begin(), dns_requests_.end()); 113 dns_requests_.clear(); 114 115 if (monitoring_networks_) { 116 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 117 monitoring_networks_ = false; 118 } 119 } 120 121 void P2PSocketDispatcherHost::OnDestruct() const { 122 BrowserThread::DeleteOnIOThread::Destruct(this); 123 } 124 125 bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) { 126 bool handled = true; 127 IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcherHost, message) 128 IPC_MESSAGE_HANDLER(P2PHostMsg_StartNetworkNotifications, 129 OnStartNetworkNotifications) 130 IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications, 131 OnStopNetworkNotifications) 132 IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress) 133 IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket) 134 IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection, 135 OnAcceptIncomingTcpConnection) 136 IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend) 137 IPC_MESSAGE_HANDLER(P2PHostMsg_SetOption, OnSetOption) 138 IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket) 139 IPC_MESSAGE_UNHANDLED(handled = false) 140 IPC_END_MESSAGE_MAP() 141 return handled; 142 } 143 144 void P2PSocketDispatcherHost::OnIPAddressChanged() { 145 // Notify the renderer about changes to list of network interfaces. 146 BrowserThread::PostTask( 147 BrowserThread::FILE, FROM_HERE, base::Bind( 148 &P2PSocketDispatcherHost::DoGetNetworkList, this)); 149 } 150 151 void P2PSocketDispatcherHost::StartRtpDump( 152 bool incoming, 153 bool outgoing, 154 const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback) { 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 156 157 if ((!dump_incoming_rtp_packet_ && incoming) || 158 (!dump_outgoing_rtp_packet_ && outgoing)) { 159 if (incoming) 160 dump_incoming_rtp_packet_ = true; 161 162 if (outgoing) 163 dump_outgoing_rtp_packet_ = true; 164 165 packet_callback_ = packet_callback; 166 for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it) 167 it->second->StartRtpDump(incoming, outgoing, packet_callback); 168 } 169 } 170 171 void P2PSocketDispatcherHost::StopRtpDumpOnUIThread(bool incoming, 172 bool outgoing) { 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 174 BrowserThread::PostTask( 175 BrowserThread::IO, 176 FROM_HERE, 177 base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnIOThread, 178 this, 179 incoming, 180 outgoing)); 181 } 182 183 P2PSocketDispatcherHost::~P2PSocketDispatcherHost() { 184 DCHECK(sockets_.empty()); 185 DCHECK(dns_requests_.empty()); 186 187 if (monitoring_networks_) 188 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 189 } 190 191 P2PSocketHost* P2PSocketDispatcherHost::LookupSocket(int socket_id) { 192 SocketsMap::iterator it = sockets_.find(socket_id); 193 return (it == sockets_.end()) ? NULL : it->second; 194 } 195 196 void P2PSocketDispatcherHost::OnStartNetworkNotifications() { 197 if (!monitoring_networks_) { 198 net::NetworkChangeNotifier::AddIPAddressObserver(this); 199 monitoring_networks_ = true; 200 } 201 202 BrowserThread::PostTask( 203 BrowserThread::FILE, FROM_HERE, base::Bind( 204 &P2PSocketDispatcherHost::DoGetNetworkList, this)); 205 } 206 207 void P2PSocketDispatcherHost::OnStopNetworkNotifications() { 208 if (monitoring_networks_) { 209 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 210 monitoring_networks_ = false; 211 } 212 } 213 214 void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name, 215 int32 request_id) { 216 DnsRequest* request = new DnsRequest(request_id, 217 resource_context_->GetHostResolver()); 218 dns_requests_.insert(request); 219 request->Resolve(host_name, base::Bind( 220 &P2PSocketDispatcherHost::OnAddressResolved, 221 base::Unretained(this), request)); 222 } 223 224 void P2PSocketDispatcherHost::OnCreateSocket( 225 P2PSocketType type, int socket_id, 226 const net::IPEndPoint& local_address, 227 const P2PHostAndIPEndPoint& remote_address) { 228 if (LookupSocket(socket_id)) { 229 LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket " 230 "that already exists."; 231 return; 232 } 233 234 scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create( 235 this, socket_id, type, url_context_.get(), &throttler_)); 236 237 if (!socket) { 238 Send(new P2PMsg_OnError(socket_id)); 239 return; 240 } 241 242 if (socket->Init(local_address, remote_address)) { 243 sockets_[socket_id] = socket.release(); 244 245 if (dump_incoming_rtp_packet_ || dump_outgoing_rtp_packet_) { 246 sockets_[socket_id]->StartRtpDump(dump_incoming_rtp_packet_, 247 dump_outgoing_rtp_packet_, 248 packet_callback_); 249 } 250 } 251 } 252 253 void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection( 254 int listen_socket_id, const net::IPEndPoint& remote_address, 255 int connected_socket_id) { 256 P2PSocketHost* socket = LookupSocket(listen_socket_id); 257 if (!socket) { 258 LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection " 259 "for invalid socket_id."; 260 return; 261 } 262 P2PSocketHost* accepted_connection = 263 socket->AcceptIncomingTcpConnection(remote_address, connected_socket_id); 264 if (accepted_connection) { 265 sockets_[connected_socket_id] = accepted_connection; 266 } 267 } 268 269 void P2PSocketDispatcherHost::OnSend(int socket_id, 270 const net::IPEndPoint& socket_address, 271 const std::vector<char>& data, 272 const talk_base::PacketOptions& options, 273 uint64 packet_id) { 274 P2PSocketHost* socket = LookupSocket(socket_id); 275 if (!socket) { 276 LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id."; 277 return; 278 } 279 280 if (data.size() > kMaximumPacketSize) { 281 LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: " 282 << data.size(); 283 Send(new P2PMsg_OnError(socket_id)); 284 delete socket; 285 sockets_.erase(socket_id); 286 return; 287 } 288 289 socket->Send(socket_address, data, options, packet_id); 290 } 291 292 void P2PSocketDispatcherHost::OnSetOption(int socket_id, 293 P2PSocketOption option, 294 int value) { 295 P2PSocketHost* socket = LookupSocket(socket_id); 296 if (!socket) { 297 LOG(ERROR) << "Received P2PHostMsg_SetOption for invalid socket_id."; 298 return; 299 } 300 301 socket->SetOption(option, value); 302 } 303 304 void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) { 305 SocketsMap::iterator it = sockets_.find(socket_id); 306 if (it != sockets_.end()) { 307 delete it->second; 308 sockets_.erase(it); 309 } else { 310 LOG(ERROR) << "Received P2PHostMsg_DestroySocket for invalid socket_id."; 311 } 312 } 313 314 void P2PSocketDispatcherHost::DoGetNetworkList() { 315 net::NetworkInterfaceList list; 316 net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES | 317 net::INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE); 318 BrowserThread::PostTask( 319 BrowserThread::IO, FROM_HERE, base::Bind( 320 &P2PSocketDispatcherHost::SendNetworkList, this, list)); 321 } 322 323 void P2PSocketDispatcherHost::SendNetworkList( 324 const net::NetworkInterfaceList& list) { 325 Send(new P2PMsg_NetworkListChanged(list)); 326 } 327 328 void P2PSocketDispatcherHost::OnAddressResolved( 329 DnsRequest* request, 330 const net::IPAddressList& addresses) { 331 Send(new P2PMsg_GetHostAddressResult(request->request_id(), addresses)); 332 333 dns_requests_.erase(request); 334 delete request; 335 } 336 337 void P2PSocketDispatcherHost::StopRtpDumpOnIOThread(bool incoming, 338 bool outgoing) { 339 if ((dump_incoming_rtp_packet_ && incoming) || 340 (dump_outgoing_rtp_packet_ && outgoing)) { 341 if (incoming) 342 dump_incoming_rtp_packet_ = false; 343 344 if (outgoing) 345 dump_outgoing_rtp_packet_ = false; 346 347 if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_) 348 packet_callback_.Reset(); 349 350 for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it) 351 it->second->StopRtpDump(incoming, outgoing); 352 } 353 } 354 355 } // namespace content 356