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 |