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 | |
| 5 | #include "net/third_party/quiche/src/quic/test_tools/quic_test_server.h" |
| 6 | |
bnc | 463f235 | 2019-10-10 04:49:34 -0700 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 9 | #include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h" |
| 10 | #include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h" |
| 11 | #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" |
| 12 | #include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h" |
| 13 | #include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h" |
| 14 | #include "net/third_party/quiche/src/quic/tools/quic_simple_server_session.h" |
QUICHE team | 6dcf6ab | 2019-12-11 10:10:51 -0800 | [diff] [blame] | 15 | #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.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, |
| 28 | QuicCryptoServerStream::Helper* helper, |
| 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, |
| 80 | std::unique_ptr<QuicCryptoServerStream::Helper> session_helper, |
| 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, |
| 98 | const QuicSocketAddress& client, |
QUICHE team | 6dcf6ab | 2019-12-11 10:10:51 -0800 | [diff] [blame] | 99 | quiche::QuicheStringPiece alpn, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 100 | const ParsedQuicVersion& version) override { |
| 101 | QuicReaderMutexLock lock(&factory_lock_); |
| 102 | if (session_factory_ == nullptr && stream_factory_ == nullptr && |
| 103 | crypto_stream_factory_ == nullptr) { |
| 104 | return QuicSimpleDispatcher::CreateQuicSession(id, client, alpn, version); |
| 105 | } |
| 106 | QuicConnection* connection = |
| 107 | new QuicConnection(id, client, helper(), alarm_factory(), writer(), |
| 108 | /* owns_writer= */ false, Perspective::IS_SERVER, |
| 109 | ParsedQuicVersionVector{version}); |
| 110 | |
wub | 89490e0 | 2019-12-12 12:45:58 -0800 | [diff] [blame] | 111 | std::unique_ptr<QuicServerSessionBase> session; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 112 | if (stream_factory_ != nullptr || crypto_stream_factory_ != nullptr) { |
wub | 89490e0 | 2019-12-12 12:45:58 -0800 | [diff] [blame] | 113 | session = std::make_unique<CustomStreamSession>( |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 114 | config(), GetSupportedVersions(), connection, this, session_helper(), |
| 115 | crypto_config(), compressed_certs_cache(), stream_factory_, |
| 116 | crypto_stream_factory_, server_backend()); |
| 117 | } else { |
| 118 | session = session_factory_->CreateSession( |
| 119 | config(), connection, this, session_helper(), crypto_config(), |
| 120 | compressed_certs_cache(), server_backend()); |
| 121 | } |
rch | 4e7e60f | 2019-10-16 07:24:00 -0700 | [diff] [blame] | 122 | // TODO(b/142715651): Figure out how to use QPACK in tests. |
| 123 | // Do not use the QPACK dynamic table in tests to avoid flakiness due to the |
| 124 | // uncertain order of receiving the SETTINGS frame and sending headers. |
| 125 | session->set_qpack_maximum_dynamic_table_capacity(0); |
| 126 | session->set_qpack_maximum_blocked_streams(0); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 127 | session->Initialize(); |
| 128 | return session; |
| 129 | } |
| 130 | |
| 131 | void SetSessionFactory(QuicTestServer::SessionFactory* factory) { |
| 132 | QuicWriterMutexLock lock(&factory_lock_); |
| 133 | DCHECK(session_factory_ == nullptr); |
| 134 | DCHECK(stream_factory_ == nullptr); |
| 135 | DCHECK(crypto_stream_factory_ == nullptr); |
| 136 | session_factory_ = factory; |
| 137 | } |
| 138 | |
| 139 | void SetStreamFactory(QuicTestServer::StreamFactory* factory) { |
| 140 | QuicWriterMutexLock lock(&factory_lock_); |
| 141 | DCHECK(session_factory_ == nullptr); |
| 142 | DCHECK(stream_factory_ == nullptr); |
| 143 | stream_factory_ = factory; |
| 144 | } |
| 145 | |
| 146 | void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) { |
| 147 | QuicWriterMutexLock lock(&factory_lock_); |
| 148 | DCHECK(session_factory_ == nullptr); |
| 149 | DCHECK(crypto_stream_factory_ == nullptr); |
| 150 | crypto_stream_factory_ = factory; |
| 151 | } |
| 152 | |
| 153 | private: |
| 154 | QuicMutex factory_lock_; |
| 155 | QuicTestServer::SessionFactory* session_factory_; // Not owned. |
| 156 | QuicTestServer::StreamFactory* stream_factory_; // Not owned. |
| 157 | QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. |
| 158 | }; |
| 159 | |
| 160 | QuicTestServer::QuicTestServer( |
| 161 | std::unique_ptr<ProofSource> proof_source, |
| 162 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 163 | : QuicServer(std::move(proof_source), quic_simple_server_backend) {} |
| 164 | |
| 165 | QuicTestServer::QuicTestServer( |
| 166 | std::unique_ptr<ProofSource> proof_source, |
| 167 | const QuicConfig& config, |
| 168 | const ParsedQuicVersionVector& supported_versions, |
| 169 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 170 | : QuicTestServer(std::move(proof_source), |
| 171 | config, |
| 172 | supported_versions, |
| 173 | quic_simple_server_backend, |
| 174 | kQuicDefaultConnectionIdLength) {} |
| 175 | |
| 176 | QuicTestServer::QuicTestServer( |
| 177 | std::unique_ptr<ProofSource> proof_source, |
| 178 | const QuicConfig& config, |
| 179 | const ParsedQuicVersionVector& supported_versions, |
| 180 | QuicSimpleServerBackend* quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 181 | uint8_t expected_server_connection_id_length) |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 182 | : QuicServer(std::move(proof_source), |
| 183 | config, |
| 184 | QuicCryptoServerConfig::ConfigOptions(), |
| 185 | supported_versions, |
| 186 | quic_simple_server_backend, |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 187 | expected_server_connection_id_length) {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 188 | |
| 189 | QuicDispatcher* QuicTestServer::CreateQuicDispatcher() { |
| 190 | return new QuicTestDispatcher( |
| 191 | &config(), &crypto_config(), version_manager(), |
vasilvv | 0fc587f | 2019-09-06 13:33:08 -0700 | [diff] [blame] | 192 | std::make_unique<QuicEpollConnectionHelper>(epoll_server(), |
| 193 | QuicAllocator::BUFFER_POOL), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 194 | std::unique_ptr<QuicCryptoServerStream::Helper>( |
wub | 662a3d6 | 2019-08-16 14:10:50 -0700 | [diff] [blame] | 195 | new QuicSimpleCryptoServerStreamHelper()), |
vasilvv | 0fc587f | 2019-09-06 13:33:08 -0700 | [diff] [blame] | 196 | std::make_unique<QuicEpollAlarmFactory>(epoll_server()), server_backend(), |
dschinazi | 8ff7482 | 2019-05-28 16:37:20 -0700 | [diff] [blame] | 197 | expected_server_connection_id_length()); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | void QuicTestServer::SetSessionFactory(SessionFactory* factory) { |
| 201 | DCHECK(dispatcher()); |
| 202 | static_cast<QuicTestDispatcher*>(dispatcher())->SetSessionFactory(factory); |
| 203 | } |
| 204 | |
| 205 | void QuicTestServer::SetSpdyStreamFactory(StreamFactory* factory) { |
| 206 | static_cast<QuicTestDispatcher*>(dispatcher())->SetStreamFactory(factory); |
| 207 | } |
| 208 | |
| 209 | void QuicTestServer::SetCryptoStreamFactory(CryptoStreamFactory* factory) { |
| 210 | static_cast<QuicTestDispatcher*>(dispatcher()) |
| 211 | ->SetCryptoStreamFactory(factory); |
| 212 | } |
| 213 | |
| 214 | /////////////////////////// TEST SESSIONS /////////////////////////////// |
| 215 | |
| 216 | ImmediateGoAwaySession::ImmediateGoAwaySession( |
| 217 | const QuicConfig& config, |
| 218 | QuicConnection* connection, |
| 219 | QuicSession::Visitor* visitor, |
| 220 | QuicCryptoServerStream::Helper* helper, |
| 221 | const QuicCryptoServerConfig* crypto_config, |
| 222 | QuicCompressedCertsCache* compressed_certs_cache, |
| 223 | QuicSimpleServerBackend* quic_simple_server_backend) |
| 224 | : QuicSimpleServerSession(config, |
| 225 | CurrentSupportedVersions(), |
| 226 | connection, |
| 227 | visitor, |
| 228 | helper, |
| 229 | crypto_config, |
| 230 | compressed_certs_cache, |
| 231 | quic_simple_server_backend) {} |
| 232 | |
| 233 | void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) { |
renjietang | 686ce58 | 2019-10-17 14:28:16 -0700 | [diff] [blame] | 234 | if (VersionUsesHttp3(transport_version())) { |
| 235 | SendHttp3GoAway(); |
| 236 | } else { |
| 237 | SendGoAway(QUIC_PEER_GOING_AWAY, ""); |
| 238 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 239 | QuicSimpleServerSession::OnStreamFrame(frame); |
| 240 | } |
| 241 | |
nharper | e5415ca | 2019-10-04 15:14:54 -0700 | [diff] [blame] | 242 | void ImmediateGoAwaySession::OnCryptoFrame(const QuicCryptoFrame& frame) { |
renjietang | 686ce58 | 2019-10-17 14:28:16 -0700 | [diff] [blame] | 243 | // In IETF QUIC, GOAWAY lives up in HTTP/3 layer. Even if it's a immediate |
| 244 | // goaway session, goaway shouldn't be sent when crypto frame is received. |
| 245 | if (!VersionUsesHttp3(transport_version())) { |
| 246 | SendGoAway(QUIC_PEER_GOING_AWAY, ""); |
| 247 | } |
nharper | e5415ca | 2019-10-04 15:14:54 -0700 | [diff] [blame] | 248 | QuicSimpleServerSession::OnCryptoFrame(frame); |
| 249 | } |
| 250 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 251 | } // namespace test |
| 252 | |
| 253 | } // namespace quic |