Index: content/browser/renderer_host/p2p/socket_host_udp.cc |
diff --git a/content/browser/renderer_host/p2p/socket_host_udp.cc b/content/browser/renderer_host/p2p/socket_host_udp.cc |
index 7d511c88fec2c53fda620b794dae94d42b91b7da..012c2ed51936263d63ec09bc3832df7f606e7bac 100644 |
--- a/content/browser/renderer_host/p2p/socket_host_udp.cc |
+++ b/content/browser/renderer_host/p2p/socket_host_udp.cc |
@@ -270,23 +270,6 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to, |
return; |
} |
- if (!base::ContainsKey(connected_peers_, to)) { |
- P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); |
- bool stun = GetStunPacketType(&*data.begin(), data.size(), &type); |
- if (!stun || type == STUN_DATA_INDICATION) { |
- LOG(ERROR) << "Page tried to send a data packet to " << to.ToString() |
- << " before STUN binding is finished."; |
- OnError(); |
- return; |
- } |
- |
- if (throttler_->DropNextPacket(data.size())) { |
- VLOG(0) << "STUN message is dropped due to high volume."; |
- // Do not reset socket. |
- return; |
- } |
- } |
- |
IncrementTotalSentPackets(); |
if (send_pending_) { |
@@ -294,13 +277,42 @@ void P2PSocketHostUdp::Send(const net::IPEndPoint& to, |
IncrementDelayedBytes(data.size()); |
IncrementDelayedPackets(); |
} else { |
- // TODO(mallinath: Remove unnecessary memcpy in this case. |
PendingPacket packet(to, data, options, packet_id); |
DoSend(packet); |
} |
} |
void P2PSocketHostUdp::DoSend(const PendingPacket& packet) { |
+ base::TimeTicks send_time = base::TimeTicks::Now(); |
+ |
+ // The peer is considered not connected until the first incoming STUN |
+ // request/response. In that state the renderer is allowed to send only STUN |
+ // messages to that peer and they are throttled using the |throttler_|. This |
+ // has to be done here instead of Send() to ensure P2PMsg_OnSendComplete |
+ // messages are sent in correct order. |
+ if (!base::ContainsKey(connected_peers_, packet.to)) { |
+ P2PSocketHost::StunMessageType type = P2PSocketHost::StunMessageType(); |
+ bool stun = GetStunPacketType(packet.data->data(), packet.size, &type); |
+ if (!stun || type == STUN_DATA_INDICATION) { |
+ LOG(ERROR) << "Page tried to send a data packet to " |
+ << packet.to.ToString() << " before STUN binding is finished."; |
+ OnError(); |
+ return; |
+ } |
+ |
+ if (throttler_->DropNextPacket(packet.size)) { |
+ VLOG(0) << "Throttling outgoing STUN message."; |
+ // The renderer expects P2PMsg_OnSendComplete for all packets it generates |
+ // and in the same order it generates them, so we need to respond even |
+ // when the packet is dropped. |
+ message_sender_->Send(new P2PMsg_OnSendComplete( |
+ id_, P2PSendPacketMetrics(packet.id, packet.packet_options.packet_id, |
+ send_time))); |
+ // Do not reset the socket. |
+ return; |
+ } |
+ } |
+ |
TRACE_EVENT_ASYNC_STEP_INTO1("p2p", "Send", packet.id, "UdpAsyncSendTo", |
"size", packet.size); |
// Don't try to set DSCP in following conditions, |
@@ -322,7 +334,6 @@ void P2PSocketHostUdp::DoSend(const PendingPacket& packet) { |
} |
} |
- base::TimeTicks send_time = base::TimeTicks::Now(); |
cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()), |
packet.size, |
packet.packet_options.packet_time_params, |
@@ -366,8 +377,8 @@ void P2PSocketHostUdp::OnSend(uint64_t packet_id, |
// Send next packets if we have them waiting in the buffer. |
while (state_ == STATE_OPEN && !send_queue_.empty() && !send_pending_) { |
PendingPacket packet = send_queue_.front(); |
- DoSend(packet); |
send_queue_.pop_front(); |
+ DoSend(packet); |
DecrementDelayedBytes(packet.size); |
} |
} |