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

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 18 matching lines...) Expand all
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 50
51 struct AsyncCallRecord {
52 AsyncCallRecord(uint64 packet_id, uint64 ticks_received) {
53 this->packet_id = packet_id;
54 this->ticks_received = ticks_received;
55 }
56 uint64 packet_id;
57 uint64 ticks_received;
58 };
48 } // namespace 59 } // namespace
49 60
50 namespace content { 61 namespace content {
51 62
52 P2PSocketHostUdp::PendingPacket::PendingPacket( 63 P2PSocketHostUdp::PendingPacket::PendingPacket(
53 const net::IPEndPoint& to, 64 const net::IPEndPoint& to,
54 const std::vector<char>& content, 65 const std::vector<char>& content,
55 const rtc::PacketOptions& options, 66 const rtc::PacketOptions& options,
56 uint64 id) 67 uint64 id)
57 : to(to), 68 : to(to),
(...skipping 19 matching lines...) Expand all
77 throttler_(throttler) { 88 throttler_(throttler) {
78 } 89 }
79 90
80 P2PSocketHostUdp::~P2PSocketHostUdp() { 91 P2PSocketHostUdp::~P2PSocketHostUdp() {
81 if (state_ == STATE_OPEN) { 92 if (state_ == STATE_OPEN) {
82 DCHECK(socket_.get()); 93 DCHECK(socket_.get());
83 socket_.reset(); 94 socket_.reset();
84 } 95 }
85 } 96 }
86 97
98 void P2PSocketHostUdp::SetSendBufferSize() {
99 unsigned send_buffer_size = 0;
juberti2 2014/11/07 22:24:59 unsigned int
100
101 // In the finch experiment, groups will be named like "2K", "64K",
juberti2 2014/11/07 22:24:59 OOC, would it make more sense to just name the gro
102 // etc. The StringToUint will convert the leading number part.
103 if (base::StringToUint(
104 base::FieldTrialList::FindFullName("WebRTC-SystemUDPSendSocketSize"),
105 &send_buffer_size) &&
Alexei Svitkine (slow) 2014/11/07 22:24:35 I don't think checking the return value of this fu
106 send_buffer_size > 0) {
107 if (!SetOption(P2P_SOCKET_OPT_SNDBUF, send_buffer_size * 1024)) {
108 LOG(WARNING) << "Failed to set socket send buffer size to "
109 << send_buffer_size * 1024;
110 }
111 }
112 }
113
87 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address, 114 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
88 const P2PHostAndIPEndPoint& remote_address) { 115 const P2PHostAndIPEndPoint& remote_address) {
89 DCHECK_EQ(state_, STATE_UNINITIALIZED); 116 DCHECK_EQ(state_, STATE_UNINITIALIZED);
90 117
91 int result = socket_->Listen(local_address); 118 int result = socket_->Listen(local_address);
92 if (result < 0) { 119 if (result < 0) {
93 LOG(ERROR) << "bind() failed: " << result; 120 LOG(ERROR) << "bind() failed: " << result;
94 OnError(); 121 OnError();
95 return false; 122 return false;
96 } 123 }
97 124
98 // Setting recv socket buffer size. 125 // Setting recv socket buffer size.
99 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) { 126 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) {
100 LOG(WARNING) << "Failed to set socket receive buffer size to " 127 LOG(WARNING) << "Failed to set socket receive buffer size to "
101 << kRecvSocketBufferSize; 128 << kRecvSocketBufferSize;
102 } 129 }
103 130
104 net::IPEndPoint address; 131 net::IPEndPoint address;
105 result = socket_->GetLocalAddress(&address); 132 result = socket_->GetLocalAddress(&address);
106 if (result < 0) { 133 if (result < 0) {
107 LOG(ERROR) << "P2PSocketHostUdp::Init(): unable to get local address: " 134 LOG(ERROR) << "P2PSocketHostUdp::Init(): unable to get local address: "
108 << result; 135 << result;
109 OnError(); 136 OnError();
110 return false; 137 return false;
111 } 138 }
112 VLOG(1) << "Local address: " << address.ToString(); 139 VLOG(1) << "Local address: " << address.ToString();
113 140
114 state_ = STATE_OPEN; 141 state_ = STATE_OPEN;
115 142
143 SetSendBufferSize();
144
116 // NOTE: Remote address will be same as what renderer provided. 145 // NOTE: Remote address will be same as what renderer provided.
117 message_sender_->Send(new P2PMsg_OnSocketCreated( 146 message_sender_->Send(new P2PMsg_OnSocketCreated(
118 id_, address, remote_address.ip_address)); 147 id_, address, remote_address.ip_address));
119 148
120 recv_buffer_ = new net::IOBuffer(kReadBufferSize); 149 recv_buffer_ = new net::IOBuffer(kReadBufferSize);
121 DoRead(); 150 DoRead();
122 151
123 return true; 152 return true;
124 } 153 }
125 154
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 int result = socket_->SetDiffServCodePoint(dscp); 267 int result = socket_->SetDiffServCodePoint(dscp);
239 if (result == net::OK) { 268 if (result == net::OK) {
240 last_dscp_ = dscp; 269 last_dscp_ = dscp;
241 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) { 270 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
242 // We receieved a non-transient error, and it seems we have 271 // We receieved a non-transient error, and it seems we have
243 // not changed the DSCP in the past, disable DSCP as it unlikely 272 // not changed the DSCP in the past, disable DSCP as it unlikely
244 // to work in the future. 273 // to work in the future.
245 last_dscp_ = net::DSCP_NO_CHANGE; 274 last_dscp_ = net::DSCP_NO_CHANGE;
246 } 275 }
247 } 276 }
277
278 uint64 call_record = reinterpret_cast<uint64>(
279 new AsyncCallRecord(packet.id, base::TimeTicks::Now().ToInternalValue()));
280
248 packet_processing_helpers::ApplyPacketOptions( 281 packet_processing_helpers::ApplyPacketOptions(
249 packet.data->data(), packet.size, packet.packet_options, 0); 282 packet.data->data(), packet.size, packet.packet_options, 0);
250 int result = socket_->SendTo( 283 int result = socket_->SendTo(
251 packet.data.get(), 284 packet.data.get(),
252 packet.size, 285 packet.size,
253 packet.to, 286 packet.to,
254 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id)); 287 base::Bind(
288 &P2PSocketHostUdp::OnSend, base::Unretained(this), call_record));
Alexei Svitkine (slow) 2014/11/07 22:24:35 I think you should be able to bind to the params d
255 289
256 // sendto() may return an error, e.g. if we've received an ICMP Destination 290 // 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, 291 // Unreachable message. When this happens try sending the same packet again,
258 // and just drop it if it fails again. 292 // and just drop it if it fails again.
259 if (IsTransientError(result)) { 293 if (IsTransientError(result)) {
260 result = socket_->SendTo( 294 result = socket_->SendTo(
261 packet.data.get(), 295 packet.data.get(),
262 packet.size, 296 packet.size,
263 packet.to, 297 packet.to,
264 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), 298 base::Bind(
265 packet.id)); 299 &P2PSocketHostUdp::OnSend, base::Unretained(this), call_record));
266 } 300 }
267 301
268 if (result == net::ERR_IO_PENDING) { 302 if (result == net::ERR_IO_PENDING) {
269 send_pending_ = true; 303 send_pending_ = true;
270 } else { 304 } else {
271 HandleSendResult(packet.id, result); 305 HandleSendResult(call_record, result);
272 } 306 }
273 307
274 if (dump_outgoing_rtp_packet_) 308 if (dump_outgoing_rtp_packet_)
275 DumpRtpPacket(packet.data->data(), packet.size, false); 309 DumpRtpPacket(packet.data->data(), packet.size, false);
276 } 310 }
277 311
278 void P2PSocketHostUdp::OnSend(uint64 packet_id, int result) { 312 void P2PSocketHostUdp::OnSend(uint64 call_record, int result) {
279 DCHECK(send_pending_); 313 DCHECK(send_pending_);
314
280 DCHECK_NE(result, net::ERR_IO_PENDING); 315 DCHECK_NE(result, net::ERR_IO_PENDING);
281 316
282 send_pending_ = false; 317 send_pending_ = false;
283 318
284 HandleSendResult(packet_id, result); 319 HandleSendResult(call_record, result);
285 320
286 // Send next packets if we have them waiting in the buffer. 321 // Send next packets if we have them waiting in the buffer.
287 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) { 322 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
288 PendingPacket packet = send_queue_.front(); 323 PendingPacket packet = send_queue_.front();
289 DoSend(packet); 324 DoSend(packet);
290 send_queue_.pop_front(); 325 send_queue_.pop_front();
291 DecrementDelayedBytes(packet.size); 326 DecrementDelayedBytes(packet.size);
292 } 327 }
293 } 328 }
294 329
295 void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) { 330 void P2PSocketHostUdp::HandleSendResult(uint64 call_record, int result) {
331 scoped_ptr<AsyncCallRecord> call_record_ptr(
332 reinterpret_cast<AsyncCallRecord*>(call_record));
333 uint64 packet_id = call_record_ptr->packet_id;
334 uint64 ticks_received = call_record_ptr->ticks_received;
335
296 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, 336 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
297 "result", result); 337 "result", result);
298 if (result < 0) { 338 if (result < 0) {
299 if (!IsTransientError(result)) { 339 if (!IsTransientError(result)) {
300 LOG(ERROR) << "Error when sending data in UDP socket: " << result; 340 LOG(ERROR) << "Error when sending data in UDP socket: " << result;
301 OnError(); 341 OnError();
302 return; 342 return;
303 } 343 }
304 VLOG(0) << "sendto() has failed twice returning a " 344 VLOG(0) << "sendto() has failed twice returning a "
305 " transient error. Dropping the packet."; 345 " transient error. Dropping the packet.";
306 } 346 }
347
348 // UMA to track the histograms from 1ms to 1 sec for how long a packet spends
349 // in the browser process.
350 UMA_HISTOGRAM_TIMES(
351 "WebRTC.SystemSendPacketDuration_UDP" /* name */,
352 base::TimeTicks::Now() -
353 base::TimeTicks::FromInternalValue(ticks_received) /* sample */);
354
307 message_sender_->Send(new P2PMsg_OnSendComplete(id_)); 355 message_sender_->Send(new P2PMsg_OnSendComplete(id_));
308 } 356 }
309 357
310 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection( 358 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection(
311 const net::IPEndPoint& remote_address, int id) { 359 const net::IPEndPoint& remote_address, int id) {
312 NOTREACHED(); 360 NOTREACHED();
313 OnError(); 361 OnError();
314 return NULL; 362 return NULL;
315 } 363 }
316 364
317 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) { 365 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) {
318 DCHECK_EQ(STATE_OPEN, state_); 366 DCHECK_EQ(STATE_OPEN, state_);
319 switch (option) { 367 switch (option) {
320 case P2P_SOCKET_OPT_RCVBUF: 368 case P2P_SOCKET_OPT_RCVBUF:
321 return socket_->SetReceiveBufferSize(value) == net::OK; 369 return socket_->SetReceiveBufferSize(value) == net::OK;
322 case P2P_SOCKET_OPT_SNDBUF: 370 case P2P_SOCKET_OPT_SNDBUF:
323 return socket_->SetSendBufferSize(value) == net::OK; 371 return socket_->SetSendBufferSize(value) == net::OK;
324 case P2P_SOCKET_OPT_DSCP: 372 case P2P_SOCKET_OPT_DSCP:
325 return (net::OK == socket_->SetDiffServCodePoint( 373 return (net::OK == socket_->SetDiffServCodePoint(
326 static_cast<net::DiffServCodePoint>(value))) ? true : false; 374 static_cast<net::DiffServCodePoint>(value))) ? true : false;
327 default: 375 default:
328 NOTREACHED(); 376 NOTREACHED();
329 return false; 377 return false;
330 } 378 }
331 } 379 }
332 380
333 } // namespace content 381 } // 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