| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |