| 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 "net/tools/quic/quic_dispatcher.h" | 5 #include "net/tools/quic/quic_dispatcher.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/debug/stack_trace.h" | 9 #include "base/debug/stack_trace.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/memory/ptr_util.h" |
| 13 #include "net/quic/core/crypto/quic_random.h" | 13 #include "net/quic/core/crypto/quic_random.h" |
| 14 #include "net/quic/core/quic_bug_tracker.h" | 14 #include "net/quic/core/quic_bug_tracker.h" |
| 15 #include "net/quic/core/quic_flags.h" | 15 #include "net/quic/core/quic_flags.h" |
| 16 #include "net/quic/core/quic_utils.h" | 16 #include "net/quic/core/quic_utils.h" |
| 17 | 17 |
| 18 #include "net/tools/quic/chlo_extractor.h" | 18 #include "net/tools/quic/chlo_extractor.h" |
| 19 #include "net/tools/quic/quic_per_connection_packet_writer.h" | 19 #include "net/tools/quic/quic_per_connection_packet_writer.h" |
| 20 #include "net/tools/quic/quic_simple_server_session.h" | 20 #include "net/tools/quic/quic_simple_server_session.h" |
| 21 #include "net/tools/quic/quic_simple_server_session.h" | 21 #include "net/tools/quic/quic_simple_server_session.h" |
| 22 #include "net/tools/quic/quic_time_wait_list_manager.h" | 22 #include "net/tools/quic/quic_time_wait_list_manager.h" |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 version_manager_(version_manager), | 212 version_manager_(version_manager), |
| 213 framer_(GetSupportedVersions(), | 213 framer_(GetSupportedVersions(), |
| 214 /*unused*/ QuicTime::Zero(), | 214 /*unused*/ QuicTime::Zero(), |
| 215 Perspective::IS_SERVER), | 215 Perspective::IS_SERVER), |
| 216 last_error_(QUIC_NO_ERROR), | 216 last_error_(QUIC_NO_ERROR), |
| 217 new_sessions_allowed_per_event_loop_(0u) { | 217 new_sessions_allowed_per_event_loop_(0u) { |
| 218 framer_.set_visitor(this); | 218 framer_.set_visitor(this); |
| 219 } | 219 } |
| 220 | 220 |
| 221 QuicDispatcher::~QuicDispatcher() { | 221 QuicDispatcher::~QuicDispatcher() { |
| 222 base::STLDeleteValues(&session_map_); | 222 session_map_.clear(); |
| 223 base::STLDeleteElements(&closed_session_list_); | 223 closed_session_list_.clear(); |
| 224 } | 224 } |
| 225 | 225 |
| 226 void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) { | 226 void QuicDispatcher::InitializeWithWriter(QuicPacketWriter* writer) { |
| 227 DCHECK(writer_ == nullptr); | 227 DCHECK(writer_ == nullptr); |
| 228 writer_.reset(writer); | 228 writer_.reset(writer); |
| 229 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager()); | 229 time_wait_list_manager_.reset(CreateQuicTimeWaitListManager()); |
| 230 } | 230 } |
| 231 | 231 |
| 232 void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address, | 232 void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address, |
| 233 const IPEndPoint& client_address, | 233 const IPEndPoint& client_address, |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 // All packets within a connection sent by a client before receiving a | 420 // All packets within a connection sent by a client before receiving a |
| 421 // response from the server are required to have the version negotiation flag | 421 // response from the server are required to have the version negotiation flag |
| 422 // set. Since this may be a client continuing a connection we lost track of | 422 // set. Since this may be a client continuing a connection we lost track of |
| 423 // via server restart, send a rejection to fast-fail the connection. | 423 // via server restart, send a rejection to fast-fail the connection. |
| 424 if (!header.public_header.version_flag) { | 424 if (!header.public_header.version_flag) { |
| 425 DVLOG(1) << "Packet without version arrived for unknown connection ID " | 425 DVLOG(1) << "Packet without version arrived for unknown connection ID " |
| 426 << header.public_header.connection_id; | 426 << header.public_header.connection_id; |
| 427 return kFateTimeWait; | 427 return kFateTimeWait; |
| 428 } | 428 } |
| 429 | 429 |
| 430 // Check that the sequence numer is within the range that the client is | 430 // Check that the sequence number is within the range that the client is |
| 431 // expected to send before receiving a response from the server. | 431 // expected to send before receiving a response from the server. |
| 432 if (header.packet_number == kInvalidPacketNumber || | 432 if (header.packet_number == kInvalidPacketNumber || |
| 433 header.packet_number > kMaxReasonableInitialPacketNumber) { | 433 header.packet_number > kMaxReasonableInitialPacketNumber) { |
| 434 return kFateTimeWait; | 434 return kFateTimeWait; |
| 435 } | 435 } |
| 436 | 436 |
| 437 return kFateProcess; | 437 return kFateProcess; |
| 438 } | 438 } |
| 439 | 439 |
| 440 void QuicDispatcher::CleanUpSession(SessionMap::iterator it, | 440 void QuicDispatcher::CleanUpSession(SessionMap::iterator it, |
| 441 QuicConnection* connection, |
| 441 bool should_close_statelessly) { | 442 bool should_close_statelessly) { |
| 442 QuicConnection* connection = it->second->connection(); | |
| 443 | |
| 444 write_blocked_list_.erase(connection); | 443 write_blocked_list_.erase(connection); |
| 445 if (should_close_statelessly) { | 444 if (should_close_statelessly) { |
| 446 DCHECK(connection->termination_packets() != nullptr && | 445 DCHECK(connection->termination_packets() != nullptr && |
| 447 !connection->termination_packets()->empty()); | 446 !connection->termination_packets()->empty()); |
| 448 } | 447 } |
| 449 time_wait_list_manager_->AddConnectionIdToTimeWait( | 448 time_wait_list_manager_->AddConnectionIdToTimeWait( |
| 450 it->first, connection->version(), should_close_statelessly, | 449 it->first, connection->version(), should_close_statelessly, |
| 451 connection->termination_packets()); | 450 connection->termination_packets()); |
| 452 session_map_.erase(it); | 451 session_map_.erase(it); |
| 453 } | 452 } |
| 454 | 453 |
| 455 void QuicDispatcher::DeleteSessions() { | 454 void QuicDispatcher::DeleteSessions() { |
| 456 base::STLDeleteElements(&closed_session_list_); | 455 closed_session_list_.clear(); |
| 457 } | 456 } |
| 458 | 457 |
| 459 void QuicDispatcher::OnCanWrite() { | 458 void QuicDispatcher::OnCanWrite() { |
| 460 // The socket is now writable. | 459 // The socket is now writable. |
| 461 writer_->SetWritable(); | 460 writer_->SetWritable(); |
| 462 | 461 |
| 463 // Give all the blocked writers one chance to write, until we're blocked again | 462 // Give all the blocked writers one chance to write, until we're blocked again |
| 464 // or there's no work left. | 463 // or there's no work left. |
| 465 while (!write_blocked_list_.empty() && !writer_->IsWriteBlocked()) { | 464 while (!write_blocked_list_.empty() && !writer_->IsWriteBlocked()) { |
| 466 QuicBlockedWriterInterface* blocked_writer = | 465 QuicBlockedWriterInterface* blocked_writer = |
| 467 write_blocked_list_.begin()->first; | 466 write_blocked_list_.begin()->first; |
| 468 write_blocked_list_.erase(write_blocked_list_.begin()); | 467 write_blocked_list_.erase(write_blocked_list_.begin()); |
| 469 blocked_writer->OnCanWrite(); | 468 blocked_writer->OnCanWrite(); |
| 470 } | 469 } |
| 471 } | 470 } |
| 472 | 471 |
| 473 bool QuicDispatcher::HasPendingWrites() const { | 472 bool QuicDispatcher::HasPendingWrites() const { |
| 474 return !write_blocked_list_.empty(); | 473 return !write_blocked_list_.empty(); |
| 475 } | 474 } |
| 476 | 475 |
| 477 void QuicDispatcher::Shutdown() { | 476 void QuicDispatcher::Shutdown() { |
| 478 while (!session_map_.empty()) { | 477 while (!session_map_.empty()) { |
| 479 QuicServerSessionBase* session = session_map_.begin()->second; | 478 QuicServerSessionBase* session = session_map_.begin()->second.get(); |
| 480 session->connection()->CloseConnection( | 479 session->connection()->CloseConnection( |
| 481 QUIC_PEER_GOING_AWAY, "Server shutdown imminent", | 480 QUIC_PEER_GOING_AWAY, "Server shutdown imminent", |
| 482 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | 481 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); |
| 483 // Validate that the session removes itself from the session map on close. | 482 // Validate that the session removes itself from the session map on close. |
| 484 DCHECK(session_map_.empty() || session_map_.begin()->second != session); | 483 DCHECK(session_map_.empty() || |
| 484 session_map_.begin()->second.get() != session); |
| 485 } | 485 } |
| 486 DeleteSessions(); | 486 DeleteSessions(); |
| 487 } | 487 } |
| 488 | 488 |
| 489 void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id, | 489 void QuicDispatcher::OnConnectionClosed(QuicConnectionId connection_id, |
| 490 QuicErrorCode error, | 490 QuicErrorCode error, |
| 491 const string& error_details) { | 491 const string& error_details) { |
| 492 SessionMap::iterator it = session_map_.find(connection_id); | 492 SessionMap::iterator it = session_map_.find(connection_id); |
| 493 if (it == session_map_.end()) { | 493 if (it == session_map_.end()) { |
| 494 QUIC_BUG << "ConnectionId " << connection_id | 494 QUIC_BUG << "ConnectionId " << connection_id |
| 495 << " does not exist in the session map. Error: " | 495 << " does not exist in the session map. Error: " |
| 496 << QuicUtils::ErrorToString(error); | 496 << QuicUtils::ErrorToString(error); |
| 497 QUIC_BUG << base::debug::StackTrace().ToString(); | 497 QUIC_BUG << base::debug::StackTrace().ToString(); |
| 498 return; | 498 return; |
| 499 } | 499 } |
| 500 | 500 |
| 501 DVLOG_IF(1, error != QUIC_NO_ERROR) | 501 DVLOG_IF(1, error != QUIC_NO_ERROR) |
| 502 << "Closing connection (" << connection_id | 502 << "Closing connection (" << connection_id |
| 503 << ") due to error: " << QuicUtils::ErrorToString(error) | 503 << ") due to error: " << QuicUtils::ErrorToString(error) |
| 504 << ", with details: " << error_details; | 504 << ", with details: " << error_details; |
| 505 | 505 |
| 506 if (closed_session_list_.empty()) { | 506 if (closed_session_list_.empty()) { |
| 507 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(), | 507 delete_sessions_alarm_->Update(helper()->GetClock()->ApproximateNow(), |
| 508 QuicTime::Delta::Zero()); | 508 QuicTime::Delta::Zero()); |
| 509 } | 509 } |
| 510 closed_session_list_.push_back(it->second); | 510 QuicConnection* connection = it->second->connection(); |
| 511 closed_session_list_.push_back(std::move(it->second)); |
| 511 const bool should_close_statelessly = | 512 const bool should_close_statelessly = |
| 512 (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT); | 513 (error == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT); |
| 513 CleanUpSession(it, should_close_statelessly); | 514 CleanUpSession(it, connection, should_close_statelessly); |
| 514 } | 515 } |
| 515 | 516 |
| 516 void QuicDispatcher::OnWriteBlocked( | 517 void QuicDispatcher::OnWriteBlocked( |
| 517 QuicBlockedWriterInterface* blocked_writer) { | 518 QuicBlockedWriterInterface* blocked_writer) { |
| 518 if (!writer_->IsWriteBlocked()) { | 519 if (!writer_->IsWriteBlocked()) { |
| 519 QUIC_BUG << "QuicDispatcher::OnWriteBlocked called when the writer is " | 520 QUIC_BUG << "QuicDispatcher::OnWriteBlocked called when the writer is " |
| 520 "not blocked."; | 521 "not blocked."; |
| 521 // Return without adding the connection to the blocked list, to avoid | 522 // Return without adding the connection to the blocked list, to avoid |
| 522 // infinite loops in OnCanWrite. | 523 // infinite loops in OnCanWrite. |
| 523 return; | 524 return; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 --new_sessions_allowed_per_event_loop_) { | 650 --new_sessions_allowed_per_event_loop_) { |
| 650 QuicConnectionId connection_id; | 651 QuicConnectionId connection_id; |
| 651 list<BufferedPacket> packets = | 652 list<BufferedPacket> packets = |
| 652 buffered_packets_.DeliverPacketsForNextConnection(&connection_id); | 653 buffered_packets_.DeliverPacketsForNextConnection(&connection_id); |
| 653 if (packets.empty()) { | 654 if (packets.empty()) { |
| 654 return; | 655 return; |
| 655 } | 656 } |
| 656 QuicServerSessionBase* session = | 657 QuicServerSessionBase* session = |
| 657 CreateQuicSession(connection_id, packets.front().client_address); | 658 CreateQuicSession(connection_id, packets.front().client_address); |
| 658 DVLOG(1) << "Created new session for " << connection_id; | 659 DVLOG(1) << "Created new session for " << connection_id; |
| 659 session_map_.insert(std::make_pair(connection_id, session)); | 660 session_map_.insert( |
| 661 std::make_pair(connection_id, base::WrapUnique(session))); |
| 660 DeliverPacketsToSession(packets, session); | 662 DeliverPacketsToSession(packets, session); |
| 661 } | 663 } |
| 662 } | 664 } |
| 663 | 665 |
| 664 bool QuicDispatcher::HasChlosBuffered() const { | 666 bool QuicDispatcher::HasChlosBuffered() const { |
| 665 return buffered_packets_.HasChlosBuffered(); | 667 return buffered_packets_.HasChlosBuffered(); |
| 666 } | 668 } |
| 667 | 669 |
| 668 bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection( | 670 bool QuicDispatcher::ShouldCreateOrBufferPacketForConnection( |
| 669 QuicConnectionId connection_id) { | 671 QuicConnectionId connection_id) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 745 is_new_connection) { | 747 is_new_connection) { |
| 746 ShouldCreateOrBufferPacketForConnection(current_connection_id_); | 748 ShouldCreateOrBufferPacketForConnection(current_connection_id_); |
| 747 } | 749 } |
| 748 } | 750 } |
| 749 return; | 751 return; |
| 750 } | 752 } |
| 751 // Creates a new session and process all buffered packets for this connection. | 753 // Creates a new session and process all buffered packets for this connection. |
| 752 QuicServerSessionBase* session = | 754 QuicServerSessionBase* session = |
| 753 CreateQuicSession(current_connection_id_, current_client_address_); | 755 CreateQuicSession(current_connection_id_, current_client_address_); |
| 754 DVLOG(1) << "Created new session for " << current_connection_id_; | 756 DVLOG(1) << "Created new session for " << current_connection_id_; |
| 755 session_map_.insert(std::make_pair(current_connection_id_, session)); | 757 session_map_.insert( |
| 758 std::make_pair(current_connection_id_, base::WrapUnique(session))); |
| 756 std::list<BufferedPacket> packets = | 759 std::list<BufferedPacket> packets = |
| 757 buffered_packets_.DeliverPackets(current_connection_id_); | 760 buffered_packets_.DeliverPackets(current_connection_id_); |
| 758 // Check if CHLO is the first packet arrived on this connection. | 761 // Check if CHLO is the first packet arrived on this connection. |
| 759 if (!FLAGS_quic_create_session_after_insertion && | 762 if (!FLAGS_quic_create_session_after_insertion && |
| 760 FLAGS_quic_buffer_packet_till_chlo && packets.empty()) { | 763 FLAGS_quic_buffer_packet_till_chlo && packets.empty()) { |
| 761 ShouldCreateOrBufferPacketForConnection(current_connection_id_); | 764 ShouldCreateOrBufferPacketForConnection(current_connection_id_); |
| 762 } | 765 } |
| 763 // Process CHLO at first. | 766 // Process CHLO at first. |
| 764 session->ProcessUdpPacket(current_server_address_, current_client_address_, | 767 session->ProcessUdpPacket(current_server_address_, current_client_address_, |
| 765 *current_packet_); | 768 *current_packet_); |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 void QuicDispatcher::DeliverPacketsToSession( | 1007 void QuicDispatcher::DeliverPacketsToSession( |
| 1005 const std::list<BufferedPacket>& packets, | 1008 const std::list<BufferedPacket>& packets, |
| 1006 QuicServerSessionBase* session) { | 1009 QuicServerSessionBase* session) { |
| 1007 for (const BufferedPacket& packet : packets) { | 1010 for (const BufferedPacket& packet : packets) { |
| 1008 session->ProcessUdpPacket(packet.server_address, packet.client_address, | 1011 session->ProcessUdpPacket(packet.server_address, packet.client_address, |
| 1009 *(packet.packet)); | 1012 *(packet.packet)); |
| 1010 } | 1013 } |
| 1011 } | 1014 } |
| 1012 | 1015 |
| 1013 } // namespace net | 1016 } // namespace net |
| OLD | NEW |