blob: e8aee790f2368bfd8b869b3c02715b3f4c5621eb [file] [log] [blame]
// Copyright (c) 2015 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 "quic/test_tools/quic_test_server.h"
#include <utility>
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_epoll_alarm_factory.h"
#include "quic/core/quic_epoll_connection_helper.h"
#include "quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "quic/tools/quic_simple_dispatcher.h"
#include "quic/tools/quic_simple_server_session.h"
namespace quic {
namespace test {
class CustomStreamSession : public QuicSimpleServerSession {
public:
CustomStreamSession(
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicConnection* connection,
QuicSession::Visitor* visitor,
QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicTestServer::StreamFactory* stream_factory,
QuicTestServer::CryptoStreamFactory* crypto_stream_factory,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSimpleServerSession(config,
supported_versions,
connection,
visitor,
helper,
crypto_config,
compressed_certs_cache,
quic_simple_server_backend),
stream_factory_(stream_factory),
crypto_stream_factory_(crypto_stream_factory) {}
QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override {
if (!ShouldCreateIncomingStream(id)) {
return nullptr;
}
if (stream_factory_) {
QuicSpdyStream* stream =
stream_factory_->CreateStream(id, this, server_backend());
ActivateStream(absl::WrapUnique(stream));
return stream;
}
return QuicSimpleServerSession::CreateIncomingStream(id);
}
std::unique_ptr<QuicCryptoServerStreamBase> CreateQuicCryptoServerStream(
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache) override {
if (crypto_stream_factory_) {
return crypto_stream_factory_->CreateCryptoStream(crypto_config, this);
}
return QuicSimpleServerSession::CreateQuicCryptoServerStream(
crypto_config, compressed_certs_cache);
}
private:
QuicTestServer::StreamFactory* stream_factory_; // Not owned.
QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned.
};
class QuicTestDispatcher : public QuicSimpleDispatcher {
public:
QuicTestDispatcher(
const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
std::unique_ptr<QuicCryptoServerStreamBase::Helper> session_helper,
std::unique_ptr<QuicAlarmFactory> alarm_factory,
QuicSimpleServerBackend* quic_simple_server_backend,
uint8_t expected_server_connection_id_length)
: QuicSimpleDispatcher(config,
crypto_config,
version_manager,
std::move(helper),
std::move(session_helper),
std::move(alarm_factory),
quic_simple_server_backend,
expected_server_connection_id_length),
session_factory_(nullptr),
stream_factory_(nullptr),
crypto_stream_factory_(nullptr) {}
std::unique_ptr<QuicSession> CreateQuicSession(
QuicConnectionId id, const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address, absl::string_view /*alpn*/,
const ParsedQuicVersion& version,
const ParsedClientHello& /*parsed_chlo*/) override {
QuicReaderMutexLock lock(&factory_lock_);
// The QuicServerSessionBase takes ownership of |connection| below.
QuicConnection* connection = new QuicConnection(
id, self_address, peer_address, helper(), alarm_factory(), writer(),
/* owns_writer= */ false, Perspective::IS_SERVER,
ParsedQuicVersionVector{version});
std::unique_ptr<QuicServerSessionBase> session;
if (session_factory_ == nullptr && stream_factory_ == nullptr &&
crypto_stream_factory_ == nullptr) {
session = std::make_unique<QuicSimpleServerSession>(
config(), GetSupportedVersions(), connection, this, session_helper(),
crypto_config(), compressed_certs_cache(), server_backend());
} else if (stream_factory_ != nullptr ||
crypto_stream_factory_ != nullptr) {
session = std::make_unique<CustomStreamSession>(
config(), GetSupportedVersions(), connection, this, session_helper(),
crypto_config(), compressed_certs_cache(), stream_factory_,
crypto_stream_factory_, server_backend());
} else {
session = session_factory_->CreateSession(
config(), connection, this, session_helper(), crypto_config(),
compressed_certs_cache(), server_backend());
}
if (VersionUsesHttp3(version.transport_version) &&
GetQuicReloadableFlag(quic_verify_request_headers_2)) {
QUICHE_DCHECK(session->allow_extended_connect());
// Do not allow extended CONNECT request if the backend doesn't support
// it.
session->set_allow_extended_connect(
server_backend()->SupportsExtendedConnect());
}
session->Initialize();
return session;
}
void SetSessionFactory(QuicTestServer::SessionFactory* factory) {
QuicWriterMutexLock lock(&factory_lock_);
QUICHE_DCHECK(session_factory_ == nullptr);
QUICHE_DCHECK(stream_factory_ == nullptr);
QUICHE_DCHECK(crypto_stream_factory_ == nullptr);
session_factory_ = factory;
}
void SetStreamFactory(QuicTestServer::StreamFactory* factory) {
QuicWriterMutexLock lock(&factory_lock_);
QUICHE_DCHECK(session_factory_ == nullptr);
QUICHE_DCHECK(stream_factory_ == nullptr);
stream_factory_ = factory;
}
void SetCryptoStreamFactory(QuicTestServer::CryptoStreamFactory* factory) {
QuicWriterMutexLock lock(&factory_lock_);
QUICHE_DCHECK(session_factory_ == nullptr);
QUICHE_DCHECK(crypto_stream_factory_ == nullptr);
crypto_stream_factory_ = factory;
}
private:
QuicMutex factory_lock_;
QuicTestServer::SessionFactory* session_factory_; // Not owned.
QuicTestServer::StreamFactory* stream_factory_; // Not owned.
QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned.
};
QuicTestServer::QuicTestServer(
std::unique_ptr<ProofSource> proof_source,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicServer(std::move(proof_source), quic_simple_server_backend) {}
QuicTestServer::QuicTestServer(
std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicTestServer(std::move(proof_source),
config,
supported_versions,
quic_simple_server_backend,
kQuicDefaultConnectionIdLength) {}
QuicTestServer::QuicTestServer(
std::unique_ptr<ProofSource> proof_source,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
QuicSimpleServerBackend* quic_simple_server_backend,
uint8_t expected_server_connection_id_length)
: QuicServer(std::move(proof_source),
config,
QuicCryptoServerConfig::ConfigOptions(),
supported_versions,
quic_simple_server_backend,
expected_server_connection_id_length) {}
QuicDispatcher* QuicTestServer::CreateQuicDispatcher() {
return new QuicTestDispatcher(
&config(), &crypto_config(), version_manager(),
std::make_unique<QuicEpollConnectionHelper>(epoll_server(),
QuicAllocator::BUFFER_POOL),
std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
new QuicSimpleCryptoServerStreamHelper()),
std::make_unique<QuicEpollAlarmFactory>(epoll_server()), server_backend(),
expected_server_connection_id_length());
}
void QuicTestServer::SetSessionFactory(SessionFactory* factory) {
QUICHE_DCHECK(dispatcher());
static_cast<QuicTestDispatcher*>(dispatcher())->SetSessionFactory(factory);
}
void QuicTestServer::SetSpdyStreamFactory(StreamFactory* factory) {
static_cast<QuicTestDispatcher*>(dispatcher())->SetStreamFactory(factory);
}
void QuicTestServer::SetCryptoStreamFactory(CryptoStreamFactory* factory) {
static_cast<QuicTestDispatcher*>(dispatcher())
->SetCryptoStreamFactory(factory);
}
/////////////////////////// TEST SESSIONS ///////////////////////////////
ImmediateGoAwaySession::ImmediateGoAwaySession(
const QuicConfig& config,
QuicConnection* connection,
QuicSession::Visitor* visitor,
QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
QuicSimpleServerBackend* quic_simple_server_backend)
: QuicSimpleServerSession(config,
CurrentSupportedVersions(),
connection,
visitor,
helper,
crypto_config,
compressed_certs_cache,
quic_simple_server_backend) {}
void ImmediateGoAwaySession::OnStreamFrame(const QuicStreamFrame& frame) {
if (VersionUsesHttp3(transport_version())) {
SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "");
} else {
SendGoAway(QUIC_PEER_GOING_AWAY, "");
}
QuicSimpleServerSession::OnStreamFrame(frame);
}
void ImmediateGoAwaySession::OnCryptoFrame(const QuicCryptoFrame& frame) {
// In IETF QUIC, GOAWAY lives up in HTTP/3 layer. It's sent in a QUIC stream
// and requires encryption. Thus the sending is done in
// OnNewEncryptionKeyAvailable().
if (!VersionUsesHttp3(transport_version())) {
SendGoAway(QUIC_PEER_GOING_AWAY, "");
}
QuicSimpleServerSession::OnCryptoFrame(frame);
}
void ImmediateGoAwaySession::OnNewEncryptionKeyAvailable(
EncryptionLevel level,
std::unique_ptr<QuicEncrypter> encrypter) {
QuicSimpleServerSession::OnNewEncryptionKeyAvailable(level,
std::move(encrypter));
if (VersionUsesHttp3(transport_version())) {
if (IsEncryptionEstablished() && !goaway_sent()) {
SendHttp3GoAway(QUIC_PEER_GOING_AWAY, "");
}
}
}
} // namespace test
} // namespace quic