| // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h" | |
| #include "net/third_party/quiche/src/quic/core/quic_version_manager.h" | |
| #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" | |
| #include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h" | |
| #include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h" | |
| #include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h" | |
| namespace quic { | |
| namespace { | |
| // Wrapper around a QuicAlarmFactory which delegates to the wrapped factory. | |
| // Usee to convert an unowned pointer into an owned pointer, so that the new | |
| // "owner" does not delete the underlying factory. Note that this is only valid | |
| // when the unowned pointer is already guaranteed to outlive the new "owner". | |
| class QuartcAlarmFactoryWrapper : public QuicAlarmFactory { | |
| public: | |
| explicit QuartcAlarmFactoryWrapper(QuicAlarmFactory* impl) : impl_(impl) {} | |
| QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override; | |
| QuicArenaScopedPtr<QuicAlarm> CreateAlarm( | |
| QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, | |
| QuicConnectionArena* arena) override; | |
| private: | |
| QuicAlarmFactory* impl_; | |
| }; | |
| QuicAlarm* QuartcAlarmFactoryWrapper::CreateAlarm( | |
| QuicAlarm::Delegate* delegate) { | |
| return impl_->CreateAlarm(delegate); | |
| } | |
| QuicArenaScopedPtr<QuicAlarm> QuartcAlarmFactoryWrapper::CreateAlarm( | |
| QuicArenaScopedPtr<QuicAlarm::Delegate> delegate, | |
| QuicConnectionArena* arena) { | |
| return impl_->CreateAlarm(std::move(delegate), arena); | |
| } | |
| } // namespace | |
| QuartcClientEndpoint::QuartcClientEndpoint( | |
| QuicAlarmFactory* alarm_factory, | |
| const QuicClock* clock, | |
| QuicRandom* random, | |
| QuartcEndpoint::Delegate* delegate, | |
| const QuartcSessionConfig& config, | |
| QuicStringPiece serialized_server_config, | |
| std::unique_ptr<QuicVersionManager> version_manager) | |
| : alarm_factory_(alarm_factory), | |
| clock_(clock), | |
| delegate_(delegate), | |
| serialized_server_config_(serialized_server_config), | |
| version_manager_(version_manager ? std::move(version_manager) | |
| : std::make_unique<QuicVersionManager>( | |
| AllSupportedVersions())), | |
| create_session_alarm_(QuicWrapUnique( | |
| alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))), | |
| connection_helper_( | |
| std::make_unique<QuartcConnectionHelper>(clock_, random)), | |
| config_(config) {} | |
| void QuartcClientEndpoint::Connect(QuartcPacketTransport* packet_transport) { | |
| packet_transport_ = packet_transport; | |
| // For the first attempt to connect, use any version that the client supports. | |
| current_versions_ = version_manager_->GetSupportedVersions(); | |
| create_session_alarm_->Set(clock_->Now()); | |
| } | |
| void QuartcClientEndpoint::OnCreateSessionAlarm() { | |
| session_ = CreateQuartcClientSession( | |
| config_, clock_, alarm_factory_, connection_helper_.get(), | |
| current_versions_, serialized_server_config_, packet_transport_); | |
| session_->SetDelegate(this); | |
| delegate_->OnSessionCreated(session_.get()); | |
| } | |
| void QuartcClientEndpoint::OnCryptoHandshakeComplete() { | |
| delegate_->OnCryptoHandshakeComplete(); | |
| } | |
| void QuartcClientEndpoint::OnConnectionWritable() { | |
| delegate_->OnConnectionWritable(); | |
| } | |
| void QuartcClientEndpoint::OnIncomingStream(QuartcStream* stream) { | |
| delegate_->OnIncomingStream(stream); | |
| } | |
| void QuartcClientEndpoint::OnCongestionControlChange( | |
| QuicBandwidth bandwidth_estimate, | |
| QuicBandwidth pacing_rate, | |
| QuicTime::Delta latest_rtt) { | |
| delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate, | |
| latest_rtt); | |
| } | |
| void QuartcClientEndpoint::OnConnectionClosed( | |
| const QuicConnectionCloseFrame& frame, | |
| ConnectionCloseSource source) { | |
| // First, see if we can restart the session with a mutually-supported version. | |
| if (frame.quic_error_code == QUIC_INVALID_VERSION && session_ && | |
| session_->connection() && | |
| !session_->connection()->server_supported_versions().empty()) { | |
| for (const auto& client_version : | |
| version_manager_->GetSupportedVersions()) { | |
| if (QuicContainsValue(session_->connection()->server_supported_versions(), | |
| client_version)) { | |
| // Found a mutually-supported version. Reconnect using that version. | |
| current_versions_.clear(); | |
| current_versions_.push_back(client_version); | |
| create_session_alarm_->Set(clock_->Now()); | |
| return; | |
| } | |
| } | |
| } | |
| // Permanent version negotiation errors are forwarded to the |delegate_|, | |
| // along with all other errors. | |
| delegate_->OnConnectionClosed(frame, source); | |
| } | |
| void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) { | |
| delegate_->OnMessageReceived(message); | |
| } | |
| void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) { | |
| delegate_->OnMessageSent(datagram_id); | |
| } | |
| void QuartcClientEndpoint::OnMessageAcked(int64_t datagram_id, | |
| QuicTime receive_timestamp) { | |
| delegate_->OnMessageAcked(datagram_id, receive_timestamp); | |
| } | |
| void QuartcClientEndpoint::OnMessageLost(int64_t datagram_id) { | |
| delegate_->OnMessageLost(datagram_id); | |
| } | |
| QuartcServerEndpoint::QuartcServerEndpoint( | |
| QuicAlarmFactory* alarm_factory, | |
| const QuicClock* clock, | |
| QuicRandom* random, | |
| QuartcEndpoint::Delegate* delegate, | |
| const QuartcSessionConfig& config, | |
| std::unique_ptr<QuicVersionManager> version_manager) | |
| : alarm_factory_(alarm_factory), | |
| delegate_(delegate), | |
| config_(config), | |
| version_manager_(version_manager ? std::move(version_manager) | |
| : std::make_unique<QuicVersionManager>( | |
| AllSupportedVersions())), | |
| pre_connection_helper_( | |
| std::make_unique<QuartcConnectionHelper>(clock, random)), | |
| crypto_config_( | |
| CreateCryptoServerConfig(pre_connection_helper_->GetRandomGenerator(), | |
| clock, | |
| config.pre_shared_key)) {} | |
| void QuartcServerEndpoint::Connect(QuartcPacketTransport* packet_transport) { | |
| DCHECK(pre_connection_helper_ != nullptr); | |
| dispatcher_ = std::make_unique<QuartcDispatcher>( | |
| std::make_unique<QuicConfig>(CreateQuicConfig(config_)), | |
| std::move(crypto_config_.config), version_manager_.get(), | |
| std::move(pre_connection_helper_), | |
| std::make_unique<QuartcCryptoServerStreamHelper>(), | |
| std::make_unique<QuartcAlarmFactoryWrapper>(alarm_factory_), | |
| std::make_unique<QuartcPacketWriter>(packet_transport, | |
| config_.max_packet_size), | |
| this); | |
| // The dispatcher requires at least one call to |ProcessBufferedChlos| to | |
| // set the number of connections it is allowed to create. | |
| dispatcher_->ProcessBufferedChlos(/*max_connections_to_create=*/1); | |
| } | |
| void QuartcServerEndpoint::OnSessionCreated(QuartcSession* session) { | |
| session->SetDelegate(delegate_); | |
| delegate_->OnSessionCreated(session); | |
| } | |
| } // namespace quic |