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

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

Issue 2300983003: Fix P2PSocketHostUdp to handle dropped packets properly. (Closed)
Patch Set: update unittests Created 4 years, 3 months 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
« no previous file with comments | « no previous file | content/browser/renderer_host/p2p/socket_host_udp_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 void P2PSocketHostUdp::Send(const net::IPEndPoint& to, 263 void P2PSocketHostUdp::Send(const net::IPEndPoint& to,
264 const std::vector<char>& data, 264 const std::vector<char>& data,
265 const rtc::PacketOptions& options, 265 const rtc::PacketOptions& options,
266 uint64_t packet_id) { 266 uint64_t packet_id) {
267 if (!socket_) { 267 if (!socket_) {
268 // The Send message may be sent after the an OnError message was 268 // The Send message may be sent after the an OnError message was
269 // sent by hasn't been processed the renderer. 269 // sent by hasn't been processed the renderer.
270 return; 270 return;
271 } 271 }
272 272
273 if (!base::ContainsKey(connected_peers_, to)) {
274 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
275 bool stun = GetStunPacketType(&*data.begin(), data.size(), &type);
276 if (!stun || type == STUN_DATA_INDICATION) {
277 LOG(ERROR) << "Page tried to send a data packet to " << to.ToString()
278 << " before STUN binding is finished.";
279 OnError();
280 return;
281 }
282
283 if (throttler_->DropNextPacket(data.size())) {
284 VLOG(0) << "STUN message is dropped due to high volume.";
285 // Do not reset socket.
286 return;
287 }
288 }
289
290 IncrementTotalSentPackets(); 273 IncrementTotalSentPackets();
291 274
292 if (send_pending_) { 275 if (send_pending_) {
293 send_queue_.push_back(PendingPacket(to, data, options, packet_id)); 276 send_queue_.push_back(PendingPacket(to, data, options, packet_id));
294 IncrementDelayedBytes(data.size()); 277 IncrementDelayedBytes(data.size());
295 IncrementDelayedPackets(); 278 IncrementDelayedPackets();
296 } else { 279 } else {
297 // TODO(mallinath: Remove unnecessary memcpy in this case.
298 PendingPacket packet(to, data, options, packet_id); 280 PendingPacket packet(to, data, options, packet_id);
299 DoSend(packet); 281 DoSend(packet);
300 } 282 }
301 } 283 }
302 284
303 void P2PSocketHostUdp::DoSend(const PendingPacket& packet) { 285 void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
286 base::TimeTicks send_time = base::TimeTicks::Now();
287
288 // The peer is considered not connected until the first incoming STUN
289 // request/response. In that state the renderer is allowed to send only STUN
290 // messages to that peer and they are throttled using the |throttler_|. This
291 // has to be done here instead of Send() to ensure P2PMsg_OnSendComplete
292 // messages are sent in correct order.
293 if (!base::ContainsKey(connected_peers_, packet.to)) {
294 P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType();
295 bool stun = GetStunPacketType(packet.data->data(), packet.size, &type);
296 if (!stun || type == STUN_DATA_INDICATION) {
297 LOG(ERROR) << "Page tried to send a data packet to "
298 << packet.to.ToString() << " before STUN binding is finished.";
299 OnError();
300 return;
301 }
302
303 if (throttler_->DropNextPacket(packet.size)) {
304 VLOG(0) << "Throttling outgoing STUN message.";
305 // The renderer expects P2PMsg_OnSendComplete for all packets it generates
306 // and in the same order it generates them, so we need to respond even
307 // when the packet is dropped.
308 message_sender_->Send(new P2PMsg_OnSendComplete(
309 id_, P2PSendPacketMetrics(packet.id, packet.packet_options.packet_id,
310 send_time)));
311 // Do not reset the socket.
312 return;
313 }
314 }
315
304 TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo", 316 TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo",
305 "size", packet.size); 317 "size", packet.size);
306 // Don't try to set DSCP in following conditions, 318 // Don't try to set DSCP in following conditions,
307 // 1. If the outgoing packet is set to DSCP_NO_CHANGE 319 // 1. If the outgoing packet is set to DSCP_NO_CHANGE
308 // 2. If no change in DSCP value from last packet 320 // 2. If no change in DSCP value from last packet
309 // 3. If there is any error in setting DSCP on socket. 321 // 3. If there is any error in setting DSCP on socket.
310 net::DiffServCodePoint dscp = 322 net::DiffServCodePoint dscp =
311 static_cast<net::DiffServCodePoint>(packet.packet_options.dscp); 323 static_cast<net::DiffServCodePoint>(packet.packet_options.dscp);
312 if (dscp != net::DSCP_NO_CHANGE && last_dscp_ != dscp && 324 if (dscp != net::DSCP_NO_CHANGE && last_dscp_ != dscp &&
313 last_dscp_ != net::DSCP_NO_CHANGE) { 325 last_dscp_ != net::DSCP_NO_CHANGE) {
314 int result = socket_->SetDiffServCodePoint(dscp); 326 int result = socket_->SetDiffServCodePoint(dscp);
315 if (result == net::OK) { 327 if (result == net::OK) {
316 last_dscp_ = dscp; 328 last_dscp_ = dscp;
317 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) { 329 } else if (!IsTransientError(result) && last_dscp_ != net::DSCP_CS0) {
318 // We receieved a non-transient error, and it seems we have 330 // We receieved a non-transient error, and it seems we have
319 // not changed the DSCP in the past, disable DSCP as it unlikely 331 // not changed the DSCP in the past, disable DSCP as it unlikely
320 // to work in the future. 332 // to work in the future.
321 last_dscp_ = net::DSCP_NO_CHANGE; 333 last_dscp_ = net::DSCP_NO_CHANGE;
322 } 334 }
323 } 335 }
324 336
325 base::TimeTicks send_time = base::TimeTicks::Now();
326 cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()), 337 cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()),
327 packet.size, 338 packet.size,
328 packet.packet_options.packet_time_params, 339 packet.packet_options.packet_time_params,
329 (send_time - base::TimeTicks()).InMicroseconds()); 340 (send_time - base::TimeTicks()).InMicroseconds());
330 auto callback_binding = 341 auto callback_binding =
331 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id, 342 base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id,
332 packet.packet_options.packet_id, send_time); 343 packet.packet_options.packet_id, send_time);
333 int result = socket_->SendTo(packet.data.get(), packet.size, packet.to, 344 int result = socket_->SendTo(packet.data.get(), packet.size, packet.to,
334 callback_binding); 345 callback_binding);
335 346
(...skipping 23 matching lines...) Expand all
359 DCHECK(send_pending_); 370 DCHECK(send_pending_);
360 DCHECK_NE(result, net::ERR_IO_PENDING); 371 DCHECK_NE(result, net::ERR_IO_PENDING);
361 372
362 send_pending_ = false; 373 send_pending_ = false;
363 374
364 HandleSendResult(packet_id, transport_sequence_number, send_time, result); 375 HandleSendResult(packet_id, transport_sequence_number, send_time, result);
365 376
366 // Send next packets if we have them waiting in the buffer. 377 // Send next packets if we have them waiting in the buffer.
367 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) { 378 while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) {
368 PendingPacket packet = send_queue_.front(); 379 PendingPacket packet = send_queue_.front();
380 send_queue_.pop_front();
369 DoSend(packet); 381 DoSend(packet);
370 send_queue_.pop_front();
371 DecrementDelayedBytes(packet.size); 382 DecrementDelayedBytes(packet.size);
372 } 383 }
373 } 384 }
374 385
375 void P2PSocketHostUdp::HandleSendResult(uint64_t packet_id, 386 void P2PSocketHostUdp::HandleSendResult(uint64_t packet_id,
376 int32_t transport_sequence_number, 387 int32_t transport_sequence_number,
377 base::TimeTicks send_time, 388 base::TimeTicks send_time,
378 int result) { 389 int result) {
379 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, 390 TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id,
380 "result", result); 391 "result", result);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 net::UDPServerSocket* socket = new net::UDPServerSocket( 447 net::UDPServerSocket* socket = new net::UDPServerSocket(
437 GetContentClient()->browser()->GetNetLog(), net::NetLog::Source()); 448 GetContentClient()->browser()->GetNetLog(), net::NetLog::Source());
438 #if defined(OS_WIN) 449 #if defined(OS_WIN)
439 socket->UseNonBlockingIO(); 450 socket->UseNonBlockingIO();
440 #endif 451 #endif
441 452
442 return base::WrapUnique(socket); 453 return base::WrapUnique(socket);
443 } 454 }
444 455
445 } // namespace content 456 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/browser/renderer_host/p2p/socket_host_udp_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698