Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / browser / renderer_host / p2p / socket_dispatcher_host.cc
blobc450d31964a916ea511e74735d8ae263b38d4478
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.
5 #include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
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/network_interfaces.h"
16 #include "net/base/sys_addrinfo.h"
17 #include "net/dns/single_request_host_resolver.h"
18 #include "net/log/net_log.h"
19 #include "net/url_request/url_request_context_getter.h"
21 using content::BrowserMessageFilter;
22 using content::BrowserThread;
24 namespace content {
26 const size_t kMaximumPacketSize = 32768;
28 class P2PSocketDispatcherHost::DnsRequest {
29 public:
30 typedef base::Callback<void(const net::IPAddressList&)> DoneCallback;
32 DnsRequest(int32 request_id, net::HostResolver* host_resolver)
33 : request_id_(request_id),
34 resolver_(host_resolver) {
37 void Resolve(const std::string& host_name,
38 const DoneCallback& done_callback) {
39 DCHECK(!done_callback.is_null());
41 host_name_ = host_name;
42 done_callback_ = done_callback;
44 // Return an error if it's an empty string.
45 if (host_name_.empty()) {
46 net::IPAddressList address_list;
47 done_callback_.Run(address_list);
48 return;
51 // Add period at the end to make sure that we only resolve
52 // fully-qualified names.
53 if (host_name_.at(host_name_.size() - 1) != '.')
54 host_name_ = host_name_ + '.';
56 net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0));
57 int result = resolver_.Resolve(
58 info,
59 net::DEFAULT_PRIORITY,
60 &addresses_,
61 base::Bind(&P2PSocketDispatcherHost::DnsRequest::OnDone,
62 base::Unretained(this)),
63 net::BoundNetLog());
64 if (result != net::ERR_IO_PENDING)
65 OnDone(result);
68 int32 request_id() { return request_id_; }
70 private:
71 void OnDone(int result) {
72 net::IPAddressList list;
73 if (result != net::OK) {
74 LOG(ERROR) << "Failed to resolve address for " << host_name_
75 << ", errorcode: " << result;
76 done_callback_.Run(list);
77 return;
80 DCHECK(!addresses_.empty());
81 for (net::AddressList::iterator iter = addresses_.begin();
82 iter != addresses_.end(); ++iter) {
83 list.push_back(iter->address());
85 done_callback_.Run(list);
88 int32 request_id_;
89 net::AddressList addresses_;
91 std::string host_name_;
92 net::SingleRequestHostResolver resolver_;
94 DoneCallback done_callback_;
97 P2PSocketDispatcherHost::P2PSocketDispatcherHost(
98 content::ResourceContext* resource_context,
99 net::URLRequestContextGetter* url_context)
100 : BrowserMessageFilter(P2PMsgStart),
101 resource_context_(resource_context),
102 url_context_(url_context),
103 monitoring_networks_(false),
104 dump_incoming_rtp_packet_(false),
105 dump_outgoing_rtp_packet_(false) {
108 void P2PSocketDispatcherHost::OnChannelClosing() {
109 // Since the IPC sender is gone, close pending connections.
110 STLDeleteContainerPairSecondPointers(sockets_.begin(), sockets_.end());
111 sockets_.clear();
113 STLDeleteContainerPointers(dns_requests_.begin(), dns_requests_.end());
114 dns_requests_.clear();
116 if (monitoring_networks_) {
117 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
118 monitoring_networks_ = false;
122 void P2PSocketDispatcherHost::OnDestruct() const {
123 BrowserThread::DeleteOnIOThread::Destruct(this);
126 bool P2PSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
127 bool handled = true;
128 IPC_BEGIN_MESSAGE_MAP(P2PSocketDispatcherHost, message)
129 IPC_MESSAGE_HANDLER(P2PHostMsg_StartNetworkNotifications,
130 OnStartNetworkNotifications)
131 IPC_MESSAGE_HANDLER(P2PHostMsg_StopNetworkNotifications,
132 OnStopNetworkNotifications)
133 IPC_MESSAGE_HANDLER(P2PHostMsg_GetHostAddress, OnGetHostAddress)
134 IPC_MESSAGE_HANDLER(P2PHostMsg_CreateSocket, OnCreateSocket)
135 IPC_MESSAGE_HANDLER(P2PHostMsg_AcceptIncomingTcpConnection,
136 OnAcceptIncomingTcpConnection)
137 IPC_MESSAGE_HANDLER(P2PHostMsg_Send, OnSend)
138 IPC_MESSAGE_HANDLER(P2PHostMsg_SetOption, OnSetOption)
139 IPC_MESSAGE_HANDLER(P2PHostMsg_DestroySocket, OnDestroySocket)
140 IPC_MESSAGE_UNHANDLED(handled = false)
141 IPC_END_MESSAGE_MAP()
142 return handled;
145 void P2PSocketDispatcherHost::OnIPAddressChanged() {
146 // Notify the renderer about changes to list of network interfaces.
147 BrowserThread::PostTask(
148 BrowserThread::FILE, FROM_HERE, base::Bind(
149 &P2PSocketDispatcherHost::DoGetNetworkList, this));
152 void P2PSocketDispatcherHost::StartRtpDump(
153 bool incoming,
154 bool outgoing,
155 const RenderProcessHost::WebRtcRtpPacketCallback& packet_callback) {
156 DCHECK_CURRENTLY_ON(BrowserThread::IO);
158 if ((!dump_incoming_rtp_packet_ && incoming) ||
159 (!dump_outgoing_rtp_packet_ && outgoing)) {
160 if (incoming)
161 dump_incoming_rtp_packet_ = true;
163 if (outgoing)
164 dump_outgoing_rtp_packet_ = true;
166 packet_callback_ = packet_callback;
167 for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it)
168 it->second->StartRtpDump(incoming, outgoing, packet_callback);
172 void P2PSocketDispatcherHost::StopRtpDumpOnUIThread(bool incoming,
173 bool outgoing) {
174 DCHECK_CURRENTLY_ON(BrowserThread::UI);
175 BrowserThread::PostTask(
176 BrowserThread::IO,
177 FROM_HERE,
178 base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnIOThread,
179 this,
180 incoming,
181 outgoing));
184 P2PSocketDispatcherHost::~P2PSocketDispatcherHost() {
185 DCHECK(sockets_.empty());
186 DCHECK(dns_requests_.empty());
188 if (monitoring_networks_)
189 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
192 P2PSocketHost* P2PSocketDispatcherHost::LookupSocket(int socket_id) {
193 SocketsMap::iterator it = sockets_.find(socket_id);
194 return (it == sockets_.end()) ? NULL : it->second;
197 void P2PSocketDispatcherHost::OnStartNetworkNotifications() {
198 if (!monitoring_networks_) {
199 net::NetworkChangeNotifier::AddIPAddressObserver(this);
200 monitoring_networks_ = true;
203 BrowserThread::PostTask(
204 BrowserThread::FILE, FROM_HERE, base::Bind(
205 &P2PSocketDispatcherHost::DoGetNetworkList, this));
208 void P2PSocketDispatcherHost::OnStopNetworkNotifications() {
209 if (monitoring_networks_) {
210 net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
211 monitoring_networks_ = false;
215 void P2PSocketDispatcherHost::OnGetHostAddress(const std::string& host_name,
216 int32 request_id) {
217 DnsRequest* request = new DnsRequest(request_id,
218 resource_context_->GetHostResolver());
219 dns_requests_.insert(request);
220 request->Resolve(host_name, base::Bind(
221 &P2PSocketDispatcherHost::OnAddressResolved,
222 base::Unretained(this), request));
225 void P2PSocketDispatcherHost::OnCreateSocket(
226 P2PSocketType type, int socket_id,
227 const net::IPEndPoint& local_address,
228 const P2PHostAndIPEndPoint& remote_address) {
229 if (LookupSocket(socket_id)) {
230 LOG(ERROR) << "Received P2PHostMsg_CreateSocket for socket "
231 "that already exists.";
232 return;
235 scoped_ptr<P2PSocketHost> socket(P2PSocketHost::Create(
236 this, socket_id, type, url_context_.get(), &throttler_));
238 if (!socket) {
239 Send(new P2PMsg_OnError(socket_id));
240 return;
243 if (socket->Init(local_address, remote_address)) {
244 sockets_[socket_id] = socket.release();
246 if (dump_incoming_rtp_packet_ || dump_outgoing_rtp_packet_) {
247 sockets_[socket_id]->StartRtpDump(dump_incoming_rtp_packet_,
248 dump_outgoing_rtp_packet_,
249 packet_callback_);
254 void P2PSocketDispatcherHost::OnAcceptIncomingTcpConnection(
255 int listen_socket_id, const net::IPEndPoint& remote_address,
256 int connected_socket_id) {
257 P2PSocketHost* socket = LookupSocket(listen_socket_id);
258 if (!socket) {
259 LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection "
260 "for invalid listen_socket_id.";
261 return;
263 if (LookupSocket(connected_socket_id) != NULL) {
264 LOG(ERROR) << "Received P2PHostMsg_AcceptIncomingTcpConnection "
265 "for duplicated connected_socket_id.";
266 return;
269 P2PSocketHost* accepted_connection =
270 socket->AcceptIncomingTcpConnection(remote_address, connected_socket_id);
271 if (accepted_connection) {
272 sockets_[connected_socket_id] = accepted_connection;
276 void P2PSocketDispatcherHost::OnSend(int socket_id,
277 const net::IPEndPoint& socket_address,
278 const std::vector<char>& data,
279 const rtc::PacketOptions& options,
280 uint64 packet_id) {
281 P2PSocketHost* socket = LookupSocket(socket_id);
282 if (!socket) {
283 LOG(ERROR) << "Received P2PHostMsg_Send for invalid socket_id.";
284 return;
287 if (data.size() > kMaximumPacketSize) {
288 LOG(ERROR) << "Received P2PHostMsg_Send with a packet that is too big: "
289 << data.size();
290 Send(new P2PMsg_OnError(socket_id));
291 delete socket;
292 sockets_.erase(socket_id);
293 return;
296 socket->Send(socket_address, data, options, packet_id);
299 void P2PSocketDispatcherHost::OnSetOption(int socket_id,
300 P2PSocketOption option,
301 int value) {
302 P2PSocketHost* socket = LookupSocket(socket_id);
303 if (!socket) {
304 LOG(ERROR) << "Received P2PHostMsg_SetOption for invalid socket_id.";
305 return;
308 socket->SetOption(option, value);
311 void P2PSocketDispatcherHost::OnDestroySocket(int socket_id) {
312 SocketsMap::iterator it = sockets_.find(socket_id);
313 if (it != sockets_.end()) {
314 delete it->second;
315 sockets_.erase(it);
316 } else {
317 LOG(ERROR) << "Received P2PHostMsg_DestroySocket for invalid socket_id.";
321 void P2PSocketDispatcherHost::DoGetNetworkList() {
322 net::NetworkInterfaceList list;
323 net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
324 BrowserThread::PostTask(
325 BrowserThread::IO, FROM_HERE, base::Bind(
326 &P2PSocketDispatcherHost::SendNetworkList, this, list));
329 void P2PSocketDispatcherHost::SendNetworkList(
330 const net::NetworkInterfaceList& list) {
331 Send(new P2PMsg_NetworkListChanged(list));
334 void P2PSocketDispatcherHost::OnAddressResolved(
335 DnsRequest* request,
336 const net::IPAddressList& addresses) {
337 Send(new P2PMsg_GetHostAddressResult(request->request_id(), addresses));
339 dns_requests_.erase(request);
340 delete request;
343 void P2PSocketDispatcherHost::StopRtpDumpOnIOThread(bool incoming,
344 bool outgoing) {
345 if ((dump_incoming_rtp_packet_ && incoming) ||
346 (dump_outgoing_rtp_packet_ && outgoing)) {
347 if (incoming)
348 dump_incoming_rtp_packet_ = false;
350 if (outgoing)
351 dump_outgoing_rtp_packet_ = false;
353 if (!dump_incoming_rtp_packet_ && !dump_outgoing_rtp_packet_)
354 packet_callback_.Reset();
356 for (SocketsMap::iterator it = sockets_.begin(); it != sockets_.end(); ++it)
357 it->second->StopRtpDump(incoming, outgoing);
361 } // namespace content