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