1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"
6 
7 #include <utility>
8 
9 #include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
10 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
11 #include "net/third_party/quiche/src/quic/quartc/quartc_connection_helper.h"
12 #include "net/third_party/quiche/src/quic/quartc/quartc_crypto_helpers.h"
13 #include "net/third_party/quiche/src/quic/quartc/quartc_dispatcher.h"
14 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
15 
16 namespace quic {
17 
18 namespace {
19 
20 // Wrapper around a QuicAlarmFactory which delegates to the wrapped factory.
21 // Usee to convert an unowned pointer into an owned pointer, so that the new
22 // "owner" does not delete the underlying factory.  Note that this is only valid
23 // when the unowned pointer is already guaranteed to outlive the new "owner".
24 class QuartcAlarmFactoryWrapper : public QuicAlarmFactory {
25  public:
QuartcAlarmFactoryWrapper(QuicAlarmFactory * impl)26   explicit QuartcAlarmFactoryWrapper(QuicAlarmFactory* impl) : impl_(impl) {}
27 
28   QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) override;
29   QuicArenaScopedPtr<QuicAlarm> CreateAlarm(
30       QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
31       QuicConnectionArena* arena) override;
32 
33  private:
34   QuicAlarmFactory* impl_;
35 };
36 
CreateAlarm(QuicAlarm::Delegate * delegate)37 QuicAlarm* QuartcAlarmFactoryWrapper::CreateAlarm(
38     QuicAlarm::Delegate* delegate) {
39   return impl_->CreateAlarm(delegate);
40 }
41 
CreateAlarm(QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,QuicConnectionArena * arena)42 QuicArenaScopedPtr<QuicAlarm> QuartcAlarmFactoryWrapper::CreateAlarm(
43     QuicArenaScopedPtr<QuicAlarm::Delegate> delegate,
44     QuicConnectionArena* arena) {
45   return impl_->CreateAlarm(std::move(delegate), arena);
46 }
47 
48 }  // namespace
49 
QuartcClientEndpoint(QuicAlarmFactory * alarm_factory,const QuicClock * clock,QuicRandom * random,QuartcEndpoint::Delegate * delegate,const QuartcSessionConfig & config,quiche::QuicheStringPiece serialized_server_config,std::unique_ptr<QuicVersionManager> version_manager)50 QuartcClientEndpoint::QuartcClientEndpoint(
51     QuicAlarmFactory* alarm_factory,
52     const QuicClock* clock,
53     QuicRandom* random,
54     QuartcEndpoint::Delegate* delegate,
55     const QuartcSessionConfig& config,
56     quiche::QuicheStringPiece serialized_server_config,
57     std::unique_ptr<QuicVersionManager> version_manager)
58     : alarm_factory_(alarm_factory),
59       clock_(clock),
60       delegate_(delegate),
61       serialized_server_config_(serialized_server_config),
62       version_manager_(version_manager ? std::move(version_manager)
63                                        : std::make_unique<QuicVersionManager>(
64                                              AllSupportedVersions())),
65       create_session_alarm_(QuicWrapUnique(
66           alarm_factory_->CreateAlarm(new CreateSessionDelegate(this)))),
67       connection_helper_(
68           std::make_unique<QuartcConnectionHelper>(clock_, random)),
69       config_(config) {}
70 
Connect(QuartcPacketTransport * packet_transport)71 void QuartcClientEndpoint::Connect(QuartcPacketTransport* packet_transport) {
72   packet_transport_ = packet_transport;
73   // For the first attempt to connect, use any version that the client supports.
74   current_versions_ = version_manager_->GetSupportedVersions();
75   create_session_alarm_->Set(clock_->Now());
76 }
77 
OnCreateSessionAlarm()78 void QuartcClientEndpoint::OnCreateSessionAlarm() {
79   session_ = CreateQuartcClientSession(
80       config_, clock_, alarm_factory_, connection_helper_.get(),
81       current_versions_, serialized_server_config_, packet_transport_);
82   session_->SetDelegate(this);
83   delegate_->OnSessionCreated(session_.get());
84 }
85 
OnCryptoHandshakeComplete()86 void QuartcClientEndpoint::OnCryptoHandshakeComplete() {
87   delegate_->OnCryptoHandshakeComplete();
88 }
89 
OnConnectionWritable()90 void QuartcClientEndpoint::OnConnectionWritable() {
91   delegate_->OnConnectionWritable();
92 }
93 
OnIncomingStream(QuartcStream * stream)94 void QuartcClientEndpoint::OnIncomingStream(QuartcStream* stream) {
95   delegate_->OnIncomingStream(stream);
96 }
97 
OnCongestionControlChange(QuicBandwidth bandwidth_estimate,QuicBandwidth pacing_rate,QuicTime::Delta latest_rtt)98 void QuartcClientEndpoint::OnCongestionControlChange(
99     QuicBandwidth bandwidth_estimate,
100     QuicBandwidth pacing_rate,
101     QuicTime::Delta latest_rtt) {
102   delegate_->OnCongestionControlChange(bandwidth_estimate, pacing_rate,
103                                        latest_rtt);
104 }
105 
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)106 void QuartcClientEndpoint::OnConnectionClosed(
107     const QuicConnectionCloseFrame& frame,
108     ConnectionCloseSource source) {
109   // First, see if we can restart the session with a mutually-supported version.
110   if (frame.quic_error_code == QUIC_INVALID_VERSION && session_ &&
111       session_->connection() &&
112       !session_->connection()->server_supported_versions().empty()) {
113     for (const auto& client_version :
114          version_manager_->GetSupportedVersions()) {
115       if (QuicContainsValue(session_->connection()->server_supported_versions(),
116                             client_version)) {
117         // Found a mutually-supported version.  Reconnect using that version.
118         current_versions_.clear();
119         current_versions_.push_back(client_version);
120         create_session_alarm_->Set(clock_->Now());
121         return;
122       }
123     }
124   }
125 
126   // Permanent version negotiation errors are forwarded to the |delegate_|,
127   // along with all other errors.
128   delegate_->OnConnectionClosed(frame, source);
129 }
130 
OnMessageReceived(quiche::QuicheStringPiece message)131 void QuartcClientEndpoint::OnMessageReceived(
132     quiche::QuicheStringPiece message) {
133   delegate_->OnMessageReceived(message);
134 }
135 
OnMessageSent(int64_t datagram_id)136 void QuartcClientEndpoint::OnMessageSent(int64_t datagram_id) {
137   delegate_->OnMessageSent(datagram_id);
138 }
139 
OnMessageAcked(int64_t datagram_id,QuicTime receive_timestamp)140 void QuartcClientEndpoint::OnMessageAcked(int64_t datagram_id,
141                                           QuicTime receive_timestamp) {
142   delegate_->OnMessageAcked(datagram_id, receive_timestamp);
143 }
144 
OnMessageLost(int64_t datagram_id)145 void QuartcClientEndpoint::OnMessageLost(int64_t datagram_id) {
146   delegate_->OnMessageLost(datagram_id);
147 }
148 
QuartcServerEndpoint(QuicAlarmFactory * alarm_factory,const QuicClock * clock,QuicRandom * random,QuartcEndpoint::Delegate * delegate,const QuartcSessionConfig & config,std::unique_ptr<QuicVersionManager> version_manager)149 QuartcServerEndpoint::QuartcServerEndpoint(
150     QuicAlarmFactory* alarm_factory,
151     const QuicClock* clock,
152     QuicRandom* random,
153     QuartcEndpoint::Delegate* delegate,
154     const QuartcSessionConfig& config,
155     std::unique_ptr<QuicVersionManager> version_manager)
156     : alarm_factory_(alarm_factory),
157       delegate_(delegate),
158       config_(config),
159       version_manager_(version_manager ? std::move(version_manager)
160                                        : std::make_unique<QuicVersionManager>(
161                                              AllSupportedVersions())),
162       pre_connection_helper_(
163           std::make_unique<QuartcConnectionHelper>(clock, random)),
164       crypto_config_(
165           CreateCryptoServerConfig(pre_connection_helper_->GetRandomGenerator(),
166                                    clock,
167                                    config.pre_shared_key)) {}
168 
Connect(QuartcPacketTransport * packet_transport)169 void QuartcServerEndpoint::Connect(QuartcPacketTransport* packet_transport) {
170   DCHECK(pre_connection_helper_ != nullptr);
171   dispatcher_ = std::make_unique<QuartcDispatcher>(
172       std::make_unique<QuicConfig>(CreateQuicConfig(config_)),
173       std::move(crypto_config_.config), version_manager_.get(),
174       std::move(pre_connection_helper_),
175       std::make_unique<QuartcCryptoServerStreamHelper>(),
176       std::make_unique<QuartcAlarmFactoryWrapper>(alarm_factory_),
177       std::make_unique<QuartcPacketWriter>(packet_transport,
178                                            config_.max_packet_size),
179       this);
180   // The dispatcher requires at least one call to |ProcessBufferedChlos| to
181   // set the number of connections it is allowed to create.
182   dispatcher_->ProcessBufferedChlos(/*max_connections_to_create=*/1);
183 }
184 
OnSessionCreated(QuartcSession * session)185 void QuartcServerEndpoint::OnSessionCreated(QuartcSession* session) {
186   session->SetDelegate(delegate_);
187   delegate_->OnSessionCreated(session);
188 }
189 
190 }  // namespace quic
191