Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: content/browser/renderer_host/p2p/socket_host_udp.cc

Issue 693433003: Add a new finch experiment to control the system buffer size. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/renderer_host/p2p/socket_host_udp.h" 5 #include "content/browser/renderer_host/p2p/socket_host_udp.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h"
9 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
10 #include "content/browser/renderer_host/p2p/socket_host_throttler.h" 13 #include "content/browser/renderer_host/p2p/socket_host_throttler.h"
11 #include "content/common/p2p_messages.h" 14 #include "content/common/p2p_messages.h"
12 #include "content/public/browser/content_browser_client.h" 15 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/common/content_client.h" 16 #include "content/public/common/content_client.h"
14 #include "ipc/ipc_sender.h" 17 #include "ipc/ipc_sender.h"
15 #include "net/base/io_buffer.h" 18 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h" 20 #include "net/base/net_util.h"
18 #include "third_party/webrtc/base/asyncpacketsocket.h" 21 #include "third_party/webrtc/base/asyncpacketsocket.h"
19 22
(...skipping 17 matching lines...) Expand all
37 // This is caused by WSAENETRESET or WSAECONNRESET which means the 40 // This is caused by WSAENETRESET or WSAECONNRESET which means the
38 // last send resulted in an "ICMP Port Unreachable" message. 41 // last send resulted in an "ICMP Port Unreachable" message.
39 bool IsTransientError(int error) { 42 bool IsTransientError(int error) {
40 return error == net::ERR_ADDRESS_UNREACHABLE || 43 return error == net::ERR_ADDRESS_UNREACHABLE ||
41 error == net::ERR_ADDRESS_INVALID || 44 error == net::ERR_ADDRESS_INVALID ||
42 error == net::ERR_ACCESS_DENIED || 45 error == net::ERR_ACCESS_DENIED ||
43 error == net::ERR_CONNECTION_RESET || 46 error == net::ERR_CONNECTION_RESET ||
44 error == net::ERR_OUT_OF_MEMORY || 47 error == net::ERR_OUT_OF_MEMORY ||
45 error == net::ERR_INTERNET_DISCONNECTED; 48 error == net::ERR_INTERNET_DISCONNECTED;
46 } 49 }
47
Alexei Svitkine (slow) 2014/11/07 22:40:19 Nit: Don't remove an empty line here.
48 } // namespace 50 } // namespace
49 51
50 namespace content { 52 namespace content {
51 53
52 P2PSocketHostUdp::PendingPacket::PendingPacket( 54 P2PSocketHostUdp::PendingPacket::PendingPacket(
53 const net::IPEndPoint& to, 55 const net::IPEndPoint& to,
54 const std::vector<char>& content, 56 const std::vector<char>& content,
55 const rtc::PacketOptions& options, 57 const rtc::PacketOptions& options,
56 uint64 id) 58 uint64 id)
57 : to(to), 59 : to(to),
(...skipping 19 matching lines...) Expand all
77 throttler_(throttler) { 79 throttler_(throttler) {
78 } 80 }
79 81
80 P2PSocketHostUdp::~P2PSocketHostUdp() { 82 P2PSocketHostUdp::~P2PSocketHostUdp() {
81 if (state_ == STATE_OPEN) { 83 if (state_ == STATE_OPEN) {
82 DCHECK(socket_.get()); 84 DCHECK(socket_.get());
83 socket_.reset(); 85 socket_.reset();
84 } 86 }
85 } 87 }
86 88
89 void P2PSocketHostUdp::SetSendBufferSize() {
90 unsigned int send_buffer_size = 0;
91
92 if (base::StringToUint(
93 base::FieldTrialList::FindFullName("WebRTC-SystemUDPSendSocketSize"),
94 &send_buffer_size) &&
95 send_buffer_size > 0) {
96 if (!SetOption(P2P_SOCKET_OPT_SNDBUF, send_buffer_size)) {
97 LOG(WARNING) << "Failed to set socket send buffer size to "
98 << send_buffer_size;
99 }
100 }
101 }
102
87 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address, 103 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
88 const P2PHostAndIPEndPoint& remote_address) { 104 const P2PHostAndIPEndPoint& remote_address) {
89 DCHECK_EQ(state_, STATE_UNINITIALIZED); 105 DCHECK_EQ(state_, STATE_UNINITIALIZED);
90 106
91 int result = socket_->Listen(local_address); 107 int result = socket_->Listen(local_address);
92 if (result < 0) { 108 if (result < 0) {
93 LOG(ERROR) << "bind() failed: " << result; 109 LOG(ERROR) << "bind() failed: " << result;
94 OnError(); 110 OnError();
95 return false; 111 return false;
96 } 112 }
97 113
98 // Setting recv socket buffer size. 114 // Setting recv socket buffer size.
99 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) { 115 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) {
100 LOG(WARNING) << "Failed to set socket receive buffer size to " 116 LOG(WARNING) << "Failed to set socket receive buffer size to "
101 << kRecvSocketBufferSize; 117 << kRecvSocketBufferSize;
102 } 118 }
103 119
104 net::IPEndPoint address; 120 net::IPEndPoint address;
105 result = socket_->GetLocalAddress(&address); 121 result = socket_->GetLocalAddress(&address);
106 if (result < 0) { 122 if (result < 0) {
107 LOG(ERROR) << "P2PSocketHostUdp::Init(): unable to get local address: " 123 LOG(ERROR) << "P2PSocketHostUdp::Init(): unable to get local address: "
108 << result; 124 << result;
109 OnError(); 125 OnError();
110 return false; 126 return false;
111 } 127 }
112 VLOG(1) << "Local address: " << address.ToString(); 128 VLOG(1) << "Local address: " << address.ToString();
113 129
114 state_ = STATE_OPEN; 130 state_ = STATE_OPEN;
115 131
132 SetSendBufferSize();
133
116 // NOTE: Remote address will be same as what renderer provided. 134 // NOTE: Remote address will be same as what renderer provided.
117 message_sender_->Send(new P2PMsg_OnSocketCreated( 135 message_sender_->Send(new P2PMsg_OnSocketCreated(
118 id_, address, remote_address.ip_address)); 136 id_, address, remote_address.ip_address));
119 137
120 recv_buffer_ = new net::IOBuffer(kReadBufferSize); 138 recv_buffer_ = new net::IOBuffer(kReadBufferSize);
121 DoRead(); 139 DoRead();
122 140
123 return true; 141 return true;
124 } 142 }
125 143
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 int result = socket_->SetDiffServCodePoint(dscp); 256 int result = socket_->SetDiffServCodePoint(dscp);
239 if (result == net::OK) { 257 if (result == net::OK) {
240 last_dscp_ = dscp; 258 last_dscp_ = dscp;
241 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) { 259 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
242 // We receieved a non-transient error, and it seems we have 260 // We receieved a non-transient error, and it seems we have
243 // not changed the DSCP in the past, disable DSCP as it unlikely 261 // not changed the DSCP in the past, disable DSCP as it unlikely
244 // to work in the future. 262 // to work in the future.
245 last_dscp_ = net::DSCP_NO_CHANGE; 263 last_dscp_ = net::DSCP_NO_CHANGE;
246 } 264 }
247 } 265 }
266
267 uint64 tick_received = base::TimeTicks::Now().ToInternalValue();
268
248 packet_processing_helpers::ApplyPacketOptions( 269 packet_processing_helpers::ApplyPacketOptions(
249 packet.data->data(), packet.size, packet.packet_options, 0); 270 packet.data->data(), packet.size, packet.packet_options, 0);
250 int result = socket_->SendTo( 271 int result = socket_->SendTo(packet.data.get(),
251 packet.data.get(), 272 packet.size,
252 packet.size, 273 packet.to,
253 packet.to, 274 base::Bind(&P2PSocketHostUdp::OnSend,
254 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id)); 275 base::Unretained(this),
276 packet.id,
277 tick_received));
255 278
256 // sendto() may return an error, e.g. if we've received an ICMP Destination 279 // sendto() may return an error, e.g. if we've received an ICMP Destination
257 // Unreachable message. When this happens try sending the same packet again, 280 // Unreachable message. When this happens try sending the same packet again,
258 // and just drop it if it fails again. 281 // and just drop it if it fails again.
259 if (IsTransientError(result)) { 282 if (IsTransientError(result)) {
260 result = socket_->SendTo( 283 result = socket_->SendTo(packet.data.get(),
261 packet.data.get(), 284 packet.size,
262 packet.size, 285 packet.to,
263 packet.to, 286 base::Bind(&P2PSocketHostUdp::OnSend,
264 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), 287 base::Unretained(this),
265 packet.id)); 288 packet.id,
289 tick_received));
266 } 290 }
267 291
268 if (result == net::ERR_IO_PENDING) { 292 if (result == net::ERR_IO_PENDING) {
269 send_pending_ = true; 293 send_pending_ = true;
270 } else { 294 } else {
271 HandleSendResult(packet.id, result); 295 HandleSendResult(packet.id, tick_received, result);
272 } 296 }
273 297
274 if (dump_outgoing_rtp_packet_) 298 if (dump_outgoing_rtp_packet_)
275 DumpRtpPacket(packet.data->data(), packet.size, false); 299 DumpRtpPacket(packet.data->data(), packet.size, false);
276 } 300 }
277 301
278 void P2PSocketHostUdp::OnSend(uint64 packet_id, int result) { 302 void P2PSocketHostUdp::OnSend(uint64 packet_id,
303 uint64 tick_received,
304 int result) {
279 DCHECK(send_pending_); 305 DCHECK(send_pending_);
306
Alexei Svitkine (slow) 2014/11/07 22:40:19 Nit: Looks like you add an extra new line here. Pl
280 DCHECK_NE(result, net::ERR_IO_PENDING); 307 DCHECK_NE(result, net::ERR_IO_PENDING);
281 308
282 send_pending_ = false; 309 send_pending_ = false;
283 310
284 HandleSendResult(packet_id, result); 311 HandleSendResult(packet_id, tick_received, result);
285 312
286 // Send next packets if we have them waiting in the buffer. 313 // Send next packets if we have them waiting in the buffer.
287 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) { 314 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
288 PendingPacket packet = send_queue_.front(); 315 PendingPacket packet = send_queue_.front();
289 DoSend(packet); 316 DoSend(packet);
290 send_queue_.pop_front(); 317 send_queue_.pop_front();
291 DecrementDelayedBytes(packet.size); 318 DecrementDelayedBytes(packet.size);
292 } 319 }
293 } 320 }
294 321
295 void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) { 322 void P2PSocketHostUdp::HandleSendResult(uint64 packet_id,
323 uint64 tick_received,
324 int result) {
296 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, 325 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
297 "result", result); 326 "result", result);
298 if (result < 0) { 327 if (result < 0) {
299 if (!IsTransientError(result)) { 328 if (!IsTransientError(result)) {
300 LOG(ERROR) << "Error when sending data in UDP socket: " << result; 329 LOG(ERROR) << "Error when sending data in UDP socket: " << result;
301 OnError(); 330 OnError();
302 return; 331 return;
303 } 332 }
304 VLOG(0) << "sendto() has failed twice returning a " 333 VLOG(0) << "sendto() has failed twice returning a "
305 " transient error. Dropping the packet."; 334 " transient error. Dropping the packet.";
306 } 335 }
336
337 // UMA to track the histograms from 1ms to 1 sec for how long a packet spends
338 // in the browser process.
339 UMA_HISTOGRAM_TIMES(
340 "WebRTC.SystemSendPacketDuration_UDP" /* name */,
341 base::TimeTicks::Now() -
342 base::TimeTicks::FromInternalValue(tick_received) /* sample */);
343
307 message_sender_->Send(new P2PMsg_OnSendComplete(id_)); 344 message_sender_->Send(new P2PMsg_OnSendComplete(id_));
308 } 345 }
309 346
310 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection( 347 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection(
311 const net::IPEndPoint& remote_address, int id) { 348 const net::IPEndPoint& remote_address, int id) {
312 NOTREACHED(); 349 NOTREACHED();
313 OnError(); 350 OnError();
314 return NULL; 351 return NULL;
315 } 352 }
316 353
317 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) { 354 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) {
318 DCHECK_EQ(STATE_OPEN, state_); 355 DCHECK_EQ(STATE_OPEN, state_);
319 switch (option) { 356 switch (option) {
320 case P2P_SOCKET_OPT_RCVBUF: 357 case P2P_SOCKET_OPT_RCVBUF:
321 return socket_->SetReceiveBufferSize(value) == net::OK; 358 return socket_->SetReceiveBufferSize(value) == net::OK;
322 case P2P_SOCKET_OPT_SNDBUF: 359 case P2P_SOCKET_OPT_SNDBUF:
323 return socket_->SetSendBufferSize(value) == net::OK; 360 return socket_->SetSendBufferSize(value) == net::OK;
324 case P2P_SOCKET_OPT_DSCP: 361 case P2P_SOCKET_OPT_DSCP:
325 return (net::OK == socket_->SetDiffServCodePoint( 362 return (net::OK == socket_->SetDiffServCodePoint(
326 static_cast<net::DiffServCodePoint>(value))) ? true : false; 363 static_cast<net::DiffServCodePoint>(value))) ? true : false;
327 default: 364 default:
328 NOTREACHED(); 365 NOTREACHED();
329 return false; 366 return false;
330 } 367 }
331 } 368 }
332 369
333 } // namespace content 370 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/p2p/socket_host_udp.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698