QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2015 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 | |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 5 | #include "quic/test_tools/quic_test_server.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 6 | |
bnc | 463f235 | 2019-10-10 04:49:34 -0700 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 9 | #include "absl/strings/string_view.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 10 | #include "quic/core/quic_epoll_alarm_factory.h" |
| 11 | #include "quic/core/quic_epoll_connection_helper.h" |
| 12 | #include "quic/platform/api/quic_ptr_util.h" |
| 13 | #include "quic/tools/quic_simple_crypto_server_stream_helper.h" |
| 14 | #include "quic/tools/quic_simple_dispatcher.h" |
| 15 | #include "quic/tools/quic_simple_server_session.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 16 | |
| 17 | namespace quic { |
| 18 | |
| 19 | namespace test { |
| 20 | |
| 21 | class CustomStreamSession : public QuicSimpleServerSession { |
| 22 | public: |
| 23 | CustomStreamSession( |
| 24 | const QuicConfig& config, |
| 25 | const ParsedQuicVersionVector& supported_versions, |
| 26 | QuicConnection* connection, |
| 27 | QuicSession::Visitor* visitor, |
nharper | 5f23a2d | 2020-02-20 10:44:09 -0800 | [diff] [blame] | 28 | QuicCryptoServerStreamBase::Helper* helper, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 29 | const QuicCryptoServerConfig* crypto_config, |
| 30 | QuicCompressedCertsCache* compressed_certs_cache, |
| 31 | QuicTestServer::StreamFactory* stream_factory, |
| 32 | QuicTestServer::CryptoStreamFactory* crypto_stream_factory, |
| 33 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 34 | : QuicSimpleServerSession(config, |
| 35 | supported_versions, |
| 36 | connection, |
| 37 | visitor, |
| 38 | helper, |
| 39 | crypto_config, |
| 40 | compressed_certs_cache, |
| 41 | quic_simple_server_backend), |
| 42 | stream_factory_(stream_factory), |
| 43 | crypto_stream_factory_(crypto_stream_factory) {} |
| 44 | |
| 45 | QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override { |
| 46 | if (!ShouldCreateIncomingStream(id)) { |
| 47 | return nullptr; |
| 48 | } |
| 49 | if (stream_factory_) { |
| 50 | QuicSpdyStream* stream = |
| 51 | stream_factory_->CreateStream(id, this, server_backend()); |
| 52 | ActivateStream(QuicWrapUnique(stream)); |
| 53 | return stream; |
| 54 | } |
| 55 | return QuicSimpleServerSession::CreateIncomingStream(id); |
| 56 | } |
| 57 | |
nharper | e5e28f9 | 2020-01-03 14:10:07 -0800 | [diff] [blame] | 58 | std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 59 | const QuicCryptoServerConfig* crypto_config, |
| 60 | QuicCompressedCertsCache* compressed_certs_cache) override { |
| 61 | if (crypto_stream_factory_) { |
| 62 | return crypto_stream_factory_->CreateCryptoStream(crypto_config, this); |
| 63 | } |
| 64 | return QuicSimpleServerSession::CreateQuicCryptoServerStream( |
| 65 | crypto_config, compressed_certs_cache); |
| 66 | } |
| 67 | |
| 68 | private: |
| 69 | QuicTestServer::StreamFactory* stream_factory_; // Not owned. |
| 70 | QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. |
| 71 | }; |
| 72 | |
| 73 | class QuicTestDispatcher : public QuicSimpleDispatcher { |
| 74 | public: |
| 75 | QuicTestDispatcher( |
| 76 | const QuicConfig* config, |
| 77 | const QuicCryptoServerConfig* crypto_config, |
| 78 | QuicVersionManager* version_manager, |
| 79 | std::unique_ptr<QuicConnectionHelperInterface> helper, |
nharper | 5f23a2d | 2020-02-20 10:44:09 -0800 | [diff] [blame] | 80 | std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 81 | std::unique_ptr<QuicAlarmFactory> alarm_factory, |
| 82 | QuicSimpleServerBackend* quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 83 | uint8_t expected_server_connection_id_length) |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 84 | : QuicSimpleDispatcher(config, |
| 85 | crypto_config, |
| 86 | version_manager, |
| 87 | std::move(helper), |
| 88 | std::move(session_helper), |
| 89 | std::move(alarm_factory), |
| 90 | quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 91 | expected_server_connection_id_length), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 92 | session_factory_(nullptr), |
| 93 | stream_factory_(nullptr), |
| 94 | crypto_stream_factory_(nullptr) {} |
| 95 | |
wub | 89490e0 | 2019-12-12 12:45:58 -0800 | [diff] [blame] | 96 | std::unique_ptr<QuicSession> CreateQuicSession( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 97 | QuicConnectionId id, |
wub | 4e3fb90 | 2020-07-15 13:37:29 -0700 | [diff] [blame] | 98 | const QuicSocketAddress& self_address, |
| 99 | const QuicSocketAddress& peer_address, |
vasilvv | 5f225b0 | 2020-10-08 11:49:09 -0400 | [diff] [blame] | 100 | absl::string_view alpn, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 101 | const ParsedQuicVersion& version) override { |
| 102 | QuicReaderMutexLock lock(&factory_lock_); |
| 103 | if (session_factory_ == nullptr && stream_factory_ == nullptr && |
| 104 | crypto_stream_factory_ == nullptr) { |
wub | 4e3fb90 | 2020-07-15 13:37:29 -0700 | [diff] [blame] | 105 | return QuicSimpleDispatcher::CreateQuicSession( |
| 106 | id, self_address, peer_address, alpn, version); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 107 | } |
wub | 4e3fb90 | 2020-07-15 13:37:29 -0700 | [diff] [blame] | 108 | QuicConnection* connection = new QuicConnection( |
wub | 5df3663 | 2020-10-01 14:42:17 -0700 | [diff] [blame] | 109 | id, self_address, peer_address, helper(), alarm_factory(), writer(), |
wub | 4e3fb90 | 2020-07-15 13:37:29 -0700 | [diff] [blame] | 110 | /* owns_writer= */ false, Perspective::IS_SERVER, |
| 111 | ParsedQuicVersionVector{version}); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 112 | |
wub | 89490e0 | 2019-12-12 12:45:58 -0800 | [diff] [blame] | 113 | std::unique_ptr<QuicServerSessionBase> session; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 114 | if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) { |
wub | 89490e0 | 2019-12-12 12:45:58 -0800 | [diff] [blame] | 115 | session = std::make_unique<CustomStreamSession>( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 116 | config(), GetSupportedVersions(), connection, this, session_helper(), |
| 117 | crypto_config(), compressed_certs_cache(), stream_factory_, |
| 118 | crypto_stream_factory_, server_backend()); |
| 119 | } else { |
| 120 | session = session_factory_->CreateSession( |
| 121 | config(), connection, this, session_helper(), crypto_config(), |
| 122 | compressed_certs_cache(), server_backend()); |
| 123 | } |
| 124 | session->Initialize(); |
| 125 | return session; |
| 126 | } |
| 127 | |
| 128 | void SetSessionFactory(QuicTestServer::SessionFactory* factory) { |
| 129 | QuicWriterMutexLock lock(&factory_lock_); |
| 130 | DCHECK(session_factory_ == nullptr); |
| 131 | DCHECK(stream_factory_ == nullptr); |
| 132 | DCHECK(crypto_stream_factory_ == nullptr); |
| 133 | session_factory_ = factory; |
| 134 | } |
| 135 | |
| 136 | void SetStreamFactory(QuicTestServer::StreamFactory* factory) { |
| 137 | QuicWriterMutexLock lock(&factory_lock_); |
| 138 | DCHECK(session_factory_ == nullptr); |
| 139 | DCHECK(stream_factory_ == nullptr); |
| 140 | stream_factory_ = factory; |
| 141 | } |
| 142 | |
| 143 | void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) { |
| 144 | QuicWriterMutexLock lock(&factory_lock_); |
| 145 | DCHECK(session_factory_ == nullptr); |
| 146 | DCHECK(crypto_stream_factory_ == nullptr); |
| 147 | crypto_stream_factory_ = factory; |
| 148 | } |
| 149 | |
| 150 | private: |
| 151 | QuicMutex factory_lock_; |
| 152 | QuicTestServer::SessionFactory* session_factory_; // Not owned. |
| 153 | QuicTestServer::StreamFactory* stream_factory_; // Not owned. |
| 154 | QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. |
| 155 | }; |
| 156 | |
| 157 | QuicTestServer::QuicTestServer( |
| 158 | std::unique_ptr<ProofSource> proof_source, |
| 159 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 160 | : QuicServer(std::move(proof_source), quic_simple_server_backend) {} |
| 161 | |
| 162 | QuicTestServer::QuicTestServer( |
| 163 | std::unique_ptr<ProofSource> proof_source, |
| 164 | const QuicConfig& config, |
| 165 | const ParsedQuicVersionVector& supported_versions, |
| 166 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 167 | : QuicTestServer(std::move(proof_source), |
| 168 | config, |
| 169 | supported_versions, |
| 170 | quic_simple_server_backend, |
| 171 | kQuicDefaultConnectionIdLength) {} |
| 172 | |
| 173 | QuicTestServer::QuicTestServer( |
| 174 | std::unique_ptr<ProofSource> proof_source, |
| 175 | const QuicConfig& config, |
| 176 | const ParsedQuicVersionVector& supported_versions, |
| 177 | QuicSimpleServerBackend* quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 178 | uint8_t expected_server_connection_id_length) |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 179 | : QuicServer(std::move(proof_source), |
| 180 | config, |
| 181 | QuicCryptoServerConfig::ConfigOptions(), |
| 182 | supported_versions, |
| 183 | quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 184 | expected_server_connection_id_length) {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 185 | |
| 186 | QuicDispatcher* QuicTestServer::CreateQuicDispatcher() { |
| 187 | return new QuicTestDispatcher( |
| 188 | &config(), &crypto_config(), version_manager(), |
vasilvv | 0fc587f | 2019-09-06 13:33:08 -0700 | [diff] [blame] | 189 | std::make_unique<QuicEpollConnectionHelper>(epoll_server(), |
| 190 | QuicAllocator::BUFFER_POOL), |
nharper | 5f23a2d | 2020-02-20 10:44:09 -0800 | [diff] [blame] | 191 | std::unique_ptr<QuicCryptoServerStreamBase::Helper>( |
wub | 662a3d6 | 2019-08-16 14:10:50 -0700 | [diff] [blame] | 192 | new QuicSimpleCryptoServerStreamHelper()), |
vasilvv | 0fc587f | 2019-09-06 13:33:08 -0700 | [diff] [blame] | 193 | std::make_unique<QuicEpollAlarmFactory>(epoll_server()), server_backend(), |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 194 | expected_server_connection_id_length()); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | void QuicTestServer::SetSessionFactory(SessionFactory* factory) { |
| 198 | DCHECK(dispatcher()); |
| 199 | static_cast<QuicTestDispatcher*>(dispatcher())->SetSessionFactory(factory); |
| 200 | } |
| 201 | |
| 202 | void QuicTestServer::SetSpdyStreamFactory(StreamFactory* factory) { |
| 203 | static_cast<QuicTestDispatcher*>(dispatcher())->SetStreamFactory(factory); |
| 204 | } |
| 205 | |
| 206 | void QuicTestServer::SetCryptoStreamFactory(CryptoStreamFactory* factory) { |
| 207 | static_cast<QuicTestDispatcher*>(dispatcher()) |
| 208 | ->SetCryptoStreamFactory(factory); |
| 209 | } |
| 210 | |
| 211 | /////////////////////////// TEST SESSIONS /////////////////////////////// |
| 212 | |
| 213 | ImmediateGoAwaySession::ImmediateGoAwaySession( |
| 214 | const QuicConfig& config, |
| 215 | QuicConnection* connection, |
| 216 | QuicSession::Visitor* visitor, |
nharper | 5f23a2d | 2020-02-20 10:44:09 -0800 | [diff] [blame] | 217 | QuicCryptoServerStreamBase::Helper* helper, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 218 | const QuicCryptoServerConfig* crypto_config, |
| 219 | QuicCompressedCertsCache* compressed_certs_cache, |
| 220 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 221 | : QuicSimpleServerSession(config, |
| 222 | CurrentSupportedVersions(), |
| 223 | connection, |
| 224 | visitor, |
| 225 | helper, |
| 226 | crypto_config, |
| 227 | compressed_certs_cache, |
| 228 | quic_simple_server_backend) {} |
| 229 | |
| 230 | void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) { |
renjietang | 686ce58 | 2019-10-17 14:28:16 -0700 | [diff] [blame] | 231 | if (VersionUsesHttp3(transport_version())) { |
fayang | b6daf21 | 2020-12-08 12:00:40 -0800 | [diff] [blame] | 232 | SendHttp3GoAway(QUIC_PEER_GOING_AWAY, ""); |
renjietang | 686ce58 | 2019-10-17 14:28:16 -0700 | [diff] [blame] | 233 | } else { |
| 234 | SendGoAway(QUIC_PEER_GOING_AWAY, ""); |
| 235 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 236 | QuicSimpleServerSession::OnStreamFrame(frame); |
| 237 | } |
| 238 | |
nharper | e5415ca | 2019-10-04 15:14:54 -0700 | [diff] [blame] | 239 | void ImmediateGoAwaySession::OnCryptoFrame(const QuicCryptoFrame& frame) { |
renjietang | d538f02 | 2020-05-11 11:29:42 -0700 | [diff] [blame] | 240 | // In IETF QUIC, GOAWAY lives up in HTTP/3 layer. It's sent in a QUIC stream |
| 241 | // and requires encryption. Thus the sending is done in |
| 242 | // OnNewEncryptionKeyAvailable(). |
renjietang | 686ce58 | 2019-10-17 14:28:16 -0700 | [diff] [blame] | 243 | if (!VersionUsesHttp3(transport_version())) { |
| 244 | SendGoAway(QUIC_PEER_GOING_AWAY, ""); |
| 245 | } |
nharper | e5415ca | 2019-10-04 15:14:54 -0700 | [diff] [blame] | 246 | QuicSimpleServerSession::OnCryptoFrame(frame); |
| 247 | } |
| 248 | |
renjietang | d538f02 | 2020-05-11 11:29:42 -0700 | [diff] [blame] | 249 | void ImmediateGoAwaySession::OnNewEncryptionKeyAvailable( |
| 250 | EncryptionLevel level, |
| 251 | std::unique_ptr<QuicEncrypter> encrypter) { |
| 252 | QuicSimpleServerSession::OnNewEncryptionKeyAvailable(level, |
| 253 | std::move(encrypter)); |
| 254 | if (VersionUsesHttp3(transport_version())) { |
bnc | 3988f57 | 2020-08-27 05:27:04 -0700 | [diff] [blame] | 255 | if (IsEncryptionEstablished() && !goaway_sent()) { |
fayang | b6daf21 | 2020-12-08 12:00:40 -0800 | [diff] [blame] | 256 | SendHttp3GoAway(QUIC_PEER_GOING_AWAY, ""); |
renjietang | d538f02 | 2020-05-11 11:29:42 -0700 | [diff] [blame] | 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 261 | } // namespace test |
| 262 | |
| 263 | } // namespace quic |