Index: net/tools/quic/quic_dispatcher.cc |
diff --git a/net/tools/quic/quic_dispatcher.cc b/net/tools/quic/quic_dispatcher.cc |
index 6100b5909f8a377753f7fd0e31950ed3b9a1c9fb..752fc5457cfde4f1bb74661c5a755bacec2f6f35 100644 |
--- a/net/tools/quic/quic_dispatcher.cc |
+++ b/net/tools/quic/quic_dispatcher.cc |
@@ -25,6 +25,10 @@ using std::string; |
namespace net { |
+typedef QuicBufferedPacketStore::BufferedPacket BufferedPacket; |
+typedef QuicBufferedPacketStore::BufferedPacketList BufferedPacketList; |
+typedef QuicBufferedPacketStore::EnqueuePacketResult EnqueuePacketResult; |
+ |
namespace { |
// An alarm that informs the QuicDispatcher to delete old sessions. |
@@ -327,23 +331,7 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
} |
switch (fate) { |
case kFateProcess: { |
- // Create a session and process the packet. |
- QuicServerSessionBase* session = |
- CreateQuicSession(connection_id, current_client_address_); |
- DVLOG(1) << "Created new session for " << connection_id; |
- session_map_.insert(std::make_pair(connection_id, session)); |
- session->ProcessUdpPacket(current_server_address_, |
- current_client_address_, *current_packet_); |
- std::list<QuicBufferedPacketStore::BufferedPacket> packets = |
- buffered_packets_.DeliverPackets(connection_id); |
- for (const auto& packet : packets) { |
- SessionMap::iterator it = session_map_.find(connection_id); |
- if (it == session_map_.end()) { |
- break; |
- } |
- it->second->ProcessUdpPacket(packet.server_address, |
- packet.client_address, *packet.packet); |
- } |
+ ProcessChlo(); |
break; |
} |
case kFateTimeWait: |
@@ -367,6 +355,11 @@ bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) { |
header.public_header.connection_id, header.packet_number, |
*current_packet_); |
break; |
+ case kFateBuffer: |
+ // This packet is a non-CHLO packet which has arrived out of order. |
+ // Buffer it. |
+ BufferEarlyPacket(connection_id); |
+ break; |
case kFateDrop: |
// Do nothing with the packet. |
break; |
@@ -606,7 +599,25 @@ void QuicDispatcher::OnPacketComplete() { |
void QuicDispatcher::OnExpiredPackets( |
QuicConnectionId connection_id, |
- QuicBufferedPacketStore::BufferedPacketList early_arrived_packets) {} |
+ BufferedPacketList early_arrived_packets) { |
+ time_wait_list_manager_->AddConnectionIdToTimeWait( |
+ connection_id, framer_.version(), false, nullptr); |
+} |
+ |
+void QuicDispatcher::OnNewConnectionAdded(QuicConnectionId connection_id) { |
+ VLOG(1) << "Received packet from new connection " << connection_id; |
+} |
+ |
+// Return true if there is any packet buffered in the store. |
+bool QuicDispatcher::HasBufferedPackets(QuicConnectionId connection_id) { |
+ return buffered_packets_.HasBufferedPackets(connection_id); |
+} |
+ |
+void QuicDispatcher::OnBufferPacketFailure(EnqueuePacketResult result, |
+ QuicConnectionId connection_id) { |
+ DVLOG(1) << "Fail to buffer packet on connection " << connection_id |
+ << " because of " << result; |
+} |
void QuicDispatcher::OnConnectionRejectedStatelessly() {} |
@@ -621,6 +632,43 @@ QuicTimeWaitListManager* QuicDispatcher::CreateQuicTimeWaitListManager() { |
alarm_factory_.get()); |
} |
+void QuicDispatcher::BufferEarlyPacket(QuicConnectionId connection_id) { |
+ bool is_new_connection = !buffered_packets_.HasBufferedPackets(connection_id); |
+ EnqueuePacketResult rs = buffered_packets_.EnqueuePacket( |
+ connection_id, *current_packet_, current_server_address_, |
+ current_client_address_); |
+ if (rs != EnqueuePacketResult::SUCCESS) { |
+ OnBufferPacketFailure(rs, connection_id); |
+ } else if (is_new_connection) { |
+ OnNewConnectionAdded(connection_id); |
+ } |
+} |
+ |
+void QuicDispatcher::ProcessChlo() { |
+ // Creates a new session and process all buffered packets for this connection. |
+ QuicServerSessionBase* session = |
+ CreateQuicSession(current_connection_id_, current_client_address_); |
+ DVLOG(1) << "Created new session for " << current_connection_id_; |
+ session_map_.insert(std::make_pair(current_connection_id_, session)); |
+ std::list<BufferedPacket> packets = |
+ buffered_packets_.DeliverPackets(current_connection_id_); |
+ // Check if CHLO is the first packet arrived on this connection. |
+ if (FLAGS_quic_buffer_packet_till_chlo && packets.empty()) { |
+ OnNewConnectionAdded(current_connection_id_); |
+ } |
+ // Process CHLO at first. |
+ session->ProcessUdpPacket(current_server_address_, current_client_address_, |
+ *current_packet_); |
+ |
+ // Deliver queued-up packets in the same order as they arrived. |
+ // Do this even when flag is off because there might be still some packets |
+ // buffered in the store before flag is turned off. |
+ for (const BufferedPacket& packet : packets) { |
+ session->ProcessUdpPacket(packet.server_address, packet.client_address, |
+ *(packet.packet)); |
+ } |
+} |
+ |
bool QuicDispatcher::HandlePacketForTimeWait( |
const QuicPacketPublicHeader& header) { |
if (header.reset_flag) { |
@@ -659,23 +707,34 @@ QuicDispatcher::QuicPacketFate QuicDispatcher::MaybeRejectStatelessly( |
!FLAGS_enable_quic_stateless_reject_support || |
header.public_header.versions.front() <= QUIC_VERSION_32 || |
!ShouldAttemptCheapStatelessRejection()) { |
+ // Not use cheap stateless reject. |
+ if (FLAGS_quic_buffer_packet_till_chlo && |
+ !ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
+ nullptr)) { |
+ // Buffer non-CHLO packets. |
+ return kFateBuffer; |
+ } |
return kFateProcess; |
} |
- StatelessRejector rejector(header.public_header.versions.front(), |
- GetSupportedVersions(), crypto_config_, |
- &compressed_certs_cache_, helper()->GetClock(), |
- helper()->GetRandomGenerator(), |
- current_client_address_, current_server_address_); |
+ StatelessRejector rejector( |
+ header.public_header.versions.front(), GetSupportedVersions(), |
+ crypto_config_, &compressed_certs_cache_, helper()->GetClock(), |
+ helper()->GetRandomGenerator(), current_packet_->length(), |
+ current_client_address_, current_server_address_); |
ChloValidator validator(session_helper_.get(), current_server_address_, |
&rejector); |
if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(), |
&validator)) { |
- DVLOG(1) << "Buffering undecryptable packet."; |
- buffered_packets_.EnqueuePacket(connection_id, *current_packet_, |
- current_server_address_, |
- current_client_address_); |
- return kFateDrop; |
+ if (!FLAGS_quic_buffer_packet_till_chlo) { |
+ QUIC_BUG |
+ << "Have to drop packet because buffering non-chlo packet is " |
+ "not supported while trying to do stateless reject. " |
+ "--gfe2_reloadable_flag_quic_buffer_packet_till_chlo false" |
+ " --gfe2_reloadable_flag_quic_use_cheap_stateless_rejects true"; |
+ return kFateDrop; |
+ } |
+ return kFateBuffer; |
} |
if (!validator.can_accept()) { |