| // 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) | 
 |                                        : QuicMakeUnique<QuicVersionManager>( | 
 |                                              AllSupportedVersions())), | 
 |       create_session_alarm_(QuicWrapUnique( | 
 |           alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))), | 
 |       connection_helper_( | 
 |           QuicMakeUnique<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(QuicErrorCode error_code, | 
 |                                               const std::string& error_details, | 
 |                                               ConnectionCloseSource source) { | 
 |   // First, see if we can restart the session with a mutually-supported version. | 
 |   if (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(error_code, error_details, source); | 
 | } | 
 |  | 
 | void QuartcClientEndpoint::OnMessageReceived(QuicStringPiece message) { | 
 |   delegate_->OnMessageReceived(message); | 
 | } | 
 |  | 
 | void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) { | 
 |   delegate_->OnMessageSent(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) | 
 |                                        : QuicMakeUnique<QuicVersionManager>( | 
 |                                              AllSupportedVersions())), | 
 |       pre_connection_helper_( | 
 |           QuicMakeUnique<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_ = QuicMakeUnique<QuartcDispatcher>( | 
 |       QuicMakeUnique<QuicConfig>(CreateQuicConfig(config_)), | 
 |       std::move(crypto_config_.config), crypto_config_.serialized_crypto_config, | 
 |       version_manager_.get(), std::move(pre_connection_helper_), | 
 |       QuicMakeUnique<QuartcCryptoServerStreamHelper>(), | 
 |       QuicMakeUnique<QuartcAlarmFactoryWrapper>(alarm_factory_), | 
 |       QuicMakeUnique<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 |