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

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: change from uL to uLL for 64 bit number 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"
10 #include "content/browser/renderer_host/p2p/socket_host_throttler.h" 12 #include "content/browser/renderer_host/p2p/socket_host_throttler.h"
11 #include "content/common/p2p_messages.h" 13 #include "content/common/p2p_messages.h"
12 #include "content/public/browser/content_browser_client.h" 14 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/common/content_client.h" 15 #include "content/public/common/content_client.h"
14 #include "ipc/ipc_sender.h" 16 #include "ipc/ipc_sender.h"
15 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
17 #include "net/base/net_util.h" 19 #include "net/base/net_util.h"
18 #include "third_party/webrtc/base/asyncpacketsocket.h" 20 #include "third_party/webrtc/base/asyncpacketsocket.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 69
68 P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender, 70 P2PSocketHostUdp::P2PSocketHostUdp(IPC::Sender* message_sender,
69 int socket_id, 71 int socket_id,
70 P2PMessageThrottler* throttler) 72 P2PMessageThrottler* throttler)
71 : P2PSocketHost(message_sender, socket_id, P2PSocketHost::UDP), 73 : P2PSocketHost(message_sender, socket_id, P2PSocketHost::UDP),
72 socket_( 74 socket_(
73 new net::UDPServerSocket(GetContentClient()->browser()->GetNetLog(), 75 new net::UDPServerSocket(GetContentClient()->browser()->GetNetLog(),
74 net::NetLog::Source())), 76 net::NetLog::Source())),
75 send_pending_(false), 77 send_pending_(false),
76 last_dscp_(net::DSCP_CS0), 78 last_dscp_(net::DSCP_CS0),
79 random_socket_id_prefix_(0),
77 throttler_(throttler) { 80 throttler_(throttler) {
78 } 81 }
79 82
80 P2PSocketHostUdp::~P2PSocketHostUdp() { 83 P2PSocketHostUdp::~P2PSocketHostUdp() {
81 if (state_ == STATE_OPEN) { 84 if (state_ == STATE_OPEN) {
82 DCHECK(socket_.get()); 85 DCHECK(socket_.get());
83 socket_.reset(); 86 socket_.reset();
84 } 87 }
85 } 88 }
86 89
90 void P2PSocketHostUdp::SetSendBufferSize() {
91 int send_buffer_size = 0;
92 if (base::FieldTrialList::FindFullName("WebRTC-SystemUDPSendSocketSize") ==
juberti2 2014/11/04 06:00:18 Seems like we should read FindFullName into a stri
Alexei Svitkine (slow) 2014/11/04 15:17:50 Agreed.
guoweis2 2014/11/07 22:18:19 Done.
93 "2K") {
94 send_buffer_size = 2048;
95 } else if (base::FieldTrialList::FindFullName(
96 "WebRTC-SystemUDPSendSocketSize") == "64K") {
Alexei Svitkine (slow) 2014/11/04 15:17:50 I would normally suggest to use variation params h
guoweis2 2014/11/07 22:18:19 Variation is not allowed so following the pattern
97 send_buffer_size = 65536;
98 } else if (base::FieldTrialList::FindFullName(
99 "WebRTC-SystemUDPSendSocketSize") == "256K") {
100 send_buffer_size = 262144;
Alexei Svitkine (slow) 2014/11/04 15:17:50 Nit: It would be more readable to have these be 25
guoweis2 2014/11/07 22:18:19 Done.
101 }
102
103 if (send_buffer_size > 0) {
juberti2 2014/11/04 06:00:18 Probably want to invalidate the experiment if this
guoweis2 2014/11/07 22:18:19 Alexei, is there a way to invalidate this instance
104 // Setting send socket buffer size.
105 if (socket_->SetSendBufferSize(send_buffer_size) != net::OK) {
106 LOG(WARNING) << "Failed to set socket send buffer size to "
107 << send_buffer_size;
108 }
109 }
110 }
111
87 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address, 112 bool P2PSocketHostUdp::Init(const net::IPEndPoint& local_address,
88 const P2PHostAndIPEndPoint& remote_address) { 113 const P2PHostAndIPEndPoint& remote_address) {
89 DCHECK_EQ(state_, STATE_UNINITIALIZED); 114 DCHECK_EQ(state_, STATE_UNINITIALIZED);
90 115
91 int result = socket_->Listen(local_address); 116 int result = socket_->Listen(local_address);
92 if (result < 0) { 117 if (result < 0) {
93 LOG(ERROR) << "bind() failed: " << result; 118 LOG(ERROR) << "bind() failed: " << result;
94 OnError(); 119 OnError();
95 return false; 120 return false;
96 } 121 }
97 122
98 // Setting recv socket buffer size. 123 // Setting recv socket buffer size.
99 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) { 124 if (socket_->SetReceiveBufferSize(kRecvSocketBufferSize) != net::OK) {
100 LOG(WARNING) << "Failed to set socket receive buffer size to " 125 LOG(WARNING) << "Failed to set socket receive buffer size to "
101 << kRecvSocketBufferSize; 126 << kRecvSocketBufferSize;
102 } 127 }
103 128
129 SetSendBufferSize();
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
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 void P2PSocketHostUdp::Send(const net::IPEndPoint& to, 214 void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
188 const std::vector<char>& data, 215 const std::vector<char>& data,
189 const rtc::PacketOptions& options, 216 const rtc::PacketOptions& options,
190 uint64 packet_id) { 217 uint64 packet_id) {
191 if (!socket_) { 218 if (!socket_) {
192 // The Send message may be sent after the an OnError message was 219 // The Send message may be sent after the an OnError message was
193 // sent by hasn't been processed the renderer. 220 // sent by hasn't been processed the renderer.
194 return; 221 return;
195 } 222 }
196 223
224 // The lower 32 bits of packet id is a sequence number. 2^32 bits is a large
225 // number space. If we send 1000 packets per second, it'll take 49 days to
226 // finish 2^32 bits.
227 if (random_socket_id_prefix_ == 0) {
228 random_socket_id_prefix_ = (packet_id >> 32) << 32;
229 } else {
230 DCHECK_EQ((random_socket_id_prefix_ >> 32), (packet_id >> 32));
231 }
232
197 if (!ContainsKey(connected_peers_, to)) { 233 if (!ContainsKey(connected_peers_, to)) {
198 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); 234 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
199 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); 235 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
200 if (!stun || type == STUN_DATA_INDICATION) { 236 if (!stun || type == STUN_DATA_INDICATION) {
201 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() 237 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
202 << " before STUN binding is finished."; 238 << " before STUN binding is finished.";
203 OnError(); 239 OnError();
204 return; 240 return;
205 } 241 }
206 242
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 int result = socket_->SetDiffServCodePoint(dscp); 274 int result = socket_->SetDiffServCodePoint(dscp);
239 if (result == net::OK) { 275 if (result == net::OK) {
240 last_dscp_ = dscp; 276 last_dscp_ = dscp;
241 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) { 277 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
242 // We receieved a non-transient error, and it seems we have 278 // We receieved a non-transient error, and it seems we have
243 // not changed the DSCP in the past, disable DSCP as it unlikely 279 // not changed the DSCP in the past, disable DSCP as it unlikely
244 // to work in the future. 280 // to work in the future.
245 last_dscp_ = net::DSCP_NO_CHANGE; 281 last_dscp_ = net::DSCP_NO_CHANGE;
246 } 282 }
247 } 283 }
284
285 uint64 call_record =
juberti2 2014/11/04 06:00:18 For the future, I think it would be better to allo
guoweis2 2014/11/07 22:18:19 Changed to allocate memory.
286 PackCallRecord(packet.id, base::TimeTicks::Now().ToInternalValue());
287
248 packet_processing_helpers::ApplyPacketOptions( 288 packet_processing_helpers::ApplyPacketOptions(
249 packet.data->data(), packet.size, packet.packet_options, 0); 289 packet.data->data(), packet.size, packet.packet_options, 0);
250 int result = socket_->SendTo( 290 int result = socket_->SendTo(
251 packet.data.get(), 291 packet.data.get(),
252 packet.size, 292 packet.size,
253 packet.to, 293 packet.to,
254 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id)); 294 base::Bind(
295 &P2PSocketHostUdp::OnSend, base::Unretained(this), call_record));
255 296
256 // sendto() may return an error, e.g. if we've received an ICMP Destination 297 // 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, 298 // Unreachable message. When this happens try sending the same packet again,
258 // and just drop it if it fails again. 299 // and just drop it if it fails again.
259 if (IsTransientError(result)) { 300 if (IsTransientError(result)) {
260 result = socket_->SendTo( 301 result = socket_->SendTo(
261 packet.data.get(), 302 packet.data.get(),
262 packet.size, 303 packet.size,
263 packet.to, 304 packet.to,
264 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), 305 base::Bind(
265 packet.id)); 306 &P2PSocketHostUdp::OnSend, base::Unretained(this), call_record));
266 } 307 }
267 308
268 if (result == net::ERR_IO_PENDING) { 309 if (result == net::ERR_IO_PENDING) {
269 send_pending_ = true; 310 send_pending_ = true;
270 } else { 311 } else {
271 HandleSendResult(packet.id, result); 312 HandleSendResult(call_record, result);
272 } 313 }
273 314
274 if (dump_outgoing_rtp_packet_) 315 if (dump_outgoing_rtp_packet_)
275 DumpRtpPacket(packet.data->data(), packet.size, false); 316 DumpRtpPacket(packet.data->data(), packet.size, false);
276 } 317 }
277 318
278 void P2PSocketHostUdp::OnSend(uint64 packet_id, int result) { 319 void P2PSocketHostUdp::OnSend(uint64 call_record, int result) {
279 DCHECK(send_pending_); 320 DCHECK(send_pending_);
321
280 DCHECK_NE(result, net::ERR_IO_PENDING); 322 DCHECK_NE(result, net::ERR_IO_PENDING);
281 323
282 send_pending_ = false; 324 send_pending_ = false;
283 325
284 HandleSendResult(packet_id, result); 326 HandleSendResult(call_record, result);
285 327
286 // Send next packets if we have them waiting in the buffer. 328 // Send next packets if we have them waiting in the buffer.
287 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) { 329 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
288 PendingPacket packet = send_queue_.front(); 330 PendingPacket packet = send_queue_.front();
289 DoSend(packet); 331 DoSend(packet);
290 send_queue_.pop_front(); 332 send_queue_.pop_front();
291 DecrementDelayedBytes(packet.size); 333 DecrementDelayedBytes(packet.size);
292 } 334 }
293 } 335 }
294 336
295 void P2PSocketHostUdp::HandleSendResult(uint64 packet_id, int result) { 337 void P2PSocketHostUdp::HandleSendResult(uint64 call_record, int result) {
338 uint64 packet_id;
339 uint64 ticks;
340 UnpackCallRecord(call_record,
341 random_socket_id_prefix_,
342 base::TimeTicks::Now().ToInternalValue(),
343 &packet_id,
344 &ticks);
345
296 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, 346 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
297 "result", result); 347 "result", result);
298 if (result < 0) { 348 if (result < 0) {
299 if (!IsTransientError(result)) { 349 if (!IsTransientError(result)) {
300 LOG(ERROR) << "Error when sending data in UDP socket: " << result; 350 LOG(ERROR) << "Error when sending data in UDP socket: " << result;
301 OnError(); 351 OnError();
302 return; 352 return;
303 } 353 }
304 VLOG(0) << "sendto() has failed twice returning a " 354 VLOG(0) << "sendto() has failed twice returning a "
305 " transient error. Dropping the packet."; 355 " transient error. Dropping the packet.";
306 } 356 }
357
358 // UMA to track the histograms from 1ms to 1 sec for how long a packet spends
359 // in the browser process.
360 UMA_HISTOGRAM_CUSTOM_TIMES(
361 "WebRTC.SystemSendPacketDuration_UDP" /* name */,
362 base::TimeDelta::FromInternalValue(ticks) /* sample */,
363 base::TimeDelta::FromMilliseconds(1) /* min */,
364 base::TimeDelta::FromSeconds(1) /* max */,
365 100 /* bucket_count */);
Alexei Svitkine (slow) 2014/11/04 15:17:50 I suggest just using UMA_HISTOGRAM_TIMES() here, w
guoweis2 2014/11/07 22:18:19 Done.
366
307 message_sender_->Send(new P2PMsg_OnSendComplete(id_)); 367 message_sender_->Send(new P2PMsg_OnSendComplete(id_));
308 } 368 }
309 369
310 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection( 370 P2PSocketHost* P2PSocketHostUdp::AcceptIncomingTcpConnection(
311 const net::IPEndPoint& remote_address, int id) { 371 const net::IPEndPoint& remote_address, int id) {
312 NOTREACHED(); 372 NOTREACHED();
313 OnError(); 373 OnError();
314 return NULL; 374 return NULL;
315 } 375 }
316 376
317 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) { 377 bool P2PSocketHostUdp::SetOption(P2PSocketOption option, int value) {
318 DCHECK_EQ(STATE_OPEN, state_); 378 DCHECK_EQ(STATE_OPEN, state_);
319 switch (option) { 379 switch (option) {
320 case P2P_SOCKET_OPT_RCVBUF: 380 case P2P_SOCKET_OPT_RCVBUF:
321 return socket_->SetReceiveBufferSize(value) == net::OK; 381 return socket_->SetReceiveBufferSize(value) == net::OK;
322 case P2P_SOCKET_OPT_SNDBUF: 382 case P2P_SOCKET_OPT_SNDBUF:
323 return socket_->SetSendBufferSize(value) == net::OK; 383 return socket_->SetSendBufferSize(value) == net::OK;
324 case P2P_SOCKET_OPT_DSCP: 384 case P2P_SOCKET_OPT_DSCP:
325 return (net::OK == socket_->SetDiffServCodePoint( 385 return (net::OK == socket_->SetDiffServCodePoint(
326 static_cast<net::DiffServCodePoint>(value))) ? true : false; 386 static_cast<net::DiffServCodePoint>(value))) ? true : false;
327 default: 387 default:
328 NOTREACHED(); 388 NOTREACHED();
329 return false; 389 return false;
330 } 390 }
331 } 391 }
332 392
393 #define ALL_ONES_LOWER_32_BITS ((1uLL << 32) - 1)
394
395 uint64 P2PSocketHostUdp::PackCallRecord(const uint64 packet_id,
396 const uint64 ticks_now) {
397 // Lower 32 bits is the packet id.
398 uint64 call_record = packet_id & ALL_ONES_LOWER_32_BITS;
399 uint64 ticks_now_lower = ticks_now & ALL_ONES_LOWER_32_BITS;
400 return (ticks_now_lower << 32) + call_record;
401 }
402
403 void P2PSocketHostUdp::UnpackCallRecord(const uint64 packed_call_record,
404 const uint64 random_socket_id_prefix,
405 const uint64 ticks_now,
406 uint64* packet_id,
407 uint64* ticks_diff) {
408 // Prefix the random prefix to the packet id.
409 *packet_id =
410 (packed_call_record & ALL_ONES_LOWER_32_BITS) | random_socket_id_prefix;
411
412 // Calculate the tick spent.
413 int64 ticks_duration =
414 (ticks_now & ALL_ONES_LOWER_32_BITS) - (packed_call_record >> 32);
415
416 if (ticks_duration < 0) {
417 ticks_duration = ALL_ONES_LOWER_32_BITS + ticks_duration + 1;
418 }
419 *ticks_diff = ticks_duration;
420 }
421
333 } // namespace content 422 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698