123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- // Copyright 2016 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 "net/test/quic_simple_test_server.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/message_loop/message_pump_type.h"
- #include "base/path_service.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/stringprintf.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/threading/thread.h"
- #include "net/base/ip_address.h"
- #include "net/base/ip_endpoint.h"
- #include "net/quic/crypto/proof_source_chromium.h"
- #include "net/test/test_data_directory.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_dispatcher.h"
- #include "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h"
- #include "net/tools/quic/quic_simple_server.h"
- namespace {
- const char kTestServerDomain[] = "example.com";
- // This must match the certificate used (quic-chain.pem and quic-leaf-cert.key).
- const char kTestServerHost[] = "test.example.com";
- const char kStatusHeader[] = ":status";
- const char kHelloPath[] = "/hello.txt";
- const char kHelloBodyValue[] = "Hello from QUIC Server";
- const char kHelloStatus[] = "200";
- const char kHelloHeaderName[] = "hello_header";
- const char kHelloHeaderValue[] = "hello header value";
- const char kHelloTrailerName[] = "hello_trailer";
- const char kHelloTrailerValue[] = "hello trailer value";
- const char kSimplePath[] = "/simple.txt";
- const char kSimpleBodyValue[] = "Simple Hello from QUIC Server";
- const char kSimpleStatus[] = "200";
- const char kSimpleHeaderName[] = "hello_header";
- const char kSimpleHeaderValue[] = "hello header value";
- const std::string kCombinedHelloHeaderValue = std::string("foo\0bar", 7);
- const char kCombinedHeaderName[] = "combined";
- base::Thread* g_quic_server_thread = nullptr;
- quic::QuicMemoryCacheBackend* g_quic_cache_backend = nullptr;
- net::QuicSimpleServer* g_quic_server = nullptr;
- int g_quic_server_port = 0;
- } // namespace
- namespace net {
- std::string const QuicSimpleTestServer::GetDomain() {
- return kTestServerDomain;
- }
- std::string const QuicSimpleTestServer::GetHost() {
- return kTestServerHost;
- }
- HostPortPair const QuicSimpleTestServer::GetHostPort() {
- return HostPortPair(kTestServerHost, GetPort());
- }
- GURL QuicSimpleTestServer::GetFileURL(const std::string& file_path) {
- return GURL("https://test.example.com:" + base::NumberToString(GetPort()))
- .Resolve(file_path);
- }
- GURL QuicSimpleTestServer::GetHelloURL() {
- // Don't include |port| into Hello URL as it is mapped differently.
- return GURL("https://test.example.com").Resolve(kHelloPath);
- }
- std::string const QuicSimpleTestServer::GetStatusHeaderName() {
- return kStatusHeader;
- }
- // Hello Url returns response with HTTP/2 headers and trailers.
- std::string const QuicSimpleTestServer::GetHelloPath() {
- return kHelloPath;
- }
- std::string const QuicSimpleTestServer::GetHelloBodyValue() {
- return kHelloBodyValue;
- }
- std::string const QuicSimpleTestServer::GetHelloStatus() {
- return kHelloStatus;
- }
- std::string const QuicSimpleTestServer::GetHelloHeaderName() {
- return kHelloHeaderName;
- }
- std::string const QuicSimpleTestServer::GetHelloHeaderValue() {
- return kHelloHeaderValue;
- }
- std::string const QuicSimpleTestServer::GetCombinedHeaderName() {
- return kCombinedHeaderName;
- }
- std::string const QuicSimpleTestServer::GetHelloTrailerName() {
- return kHelloTrailerName;
- }
- std::string const QuicSimpleTestServer::GetHelloTrailerValue() {
- return kHelloTrailerValue;
- }
- // Simple Url returns response without HTTP/2 trailers.
- GURL QuicSimpleTestServer::GetSimpleURL() {
- // Don't include |port| into Simple URL as it is mapped differently.
- return GURL("https://test.example.com").Resolve(kSimplePath);
- }
- std::string const QuicSimpleTestServer::GetSimpleBodyValue() {
- return kSimpleBodyValue;
- }
- std::string const QuicSimpleTestServer::GetSimpleStatus() {
- return kSimpleStatus;
- }
- std::string const QuicSimpleTestServer::GetSimpleHeaderName() {
- return kSimpleHeaderName;
- }
- std::string const QuicSimpleTestServer::GetSimpleHeaderValue() {
- return kSimpleHeaderValue;
- }
- void SetupQuicMemoryCacheBackend() {
- spdy::Http2HeaderBlock headers;
- headers[kHelloHeaderName] = kHelloHeaderValue;
- headers[kStatusHeader] = kHelloStatus;
- headers[kCombinedHeaderName] = kCombinedHelloHeaderValue;
- spdy::Http2HeaderBlock trailers;
- trailers[kHelloTrailerName] = kHelloTrailerValue;
- g_quic_cache_backend = new quic::QuicMemoryCacheBackend();
- g_quic_cache_backend->AddResponse(base::StringPrintf("%s", kTestServerHost),
- kHelloPath, std::move(headers),
- kHelloBodyValue, std::move(trailers));
- headers[kSimpleHeaderName] = kSimpleHeaderValue;
- headers[kStatusHeader] = kSimpleStatus;
- g_quic_cache_backend->AddResponse(base::StringPrintf("%s", kTestServerHost),
- kSimplePath, std::move(headers),
- kSimpleBodyValue);
- }
- void StartQuicServerOnServerThread(const base::FilePath& test_files_root,
- base::WaitableEvent* server_started_event) {
- DCHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
- DCHECK(!g_quic_server);
- quic::QuicConfig config;
- // Set up server certs.
- base::FilePath directory;
- directory = test_files_root;
- auto proof_source = std::make_unique<ProofSourceChromium>();
- CHECK(proof_source->Initialize(directory.AppendASCII("quic-chain.pem"),
- directory.AppendASCII("quic-leaf-cert.key"),
- base::FilePath()));
- SetupQuicMemoryCacheBackend();
- g_quic_server =
- new QuicSimpleServer(std::move(proof_source), config,
- quic::QuicCryptoServerConfig::ConfigOptions(),
- quic::AllSupportedVersions(), g_quic_cache_backend);
- // Start listening on an unbound port.
- int rv = g_quic_server->Listen(IPEndPoint(IPAddress::IPv4AllZeros(), 0));
- CHECK_GE(rv, 0) << "Quic server fails to start";
- g_quic_server_port = g_quic_server->server_address().port();
- server_started_event->Signal();
- }
- void ShutdownOnServerThread(base::WaitableEvent* server_stopped_event) {
- DCHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
- g_quic_server->Shutdown();
- delete g_quic_server;
- g_quic_server = nullptr;
- delete g_quic_cache_backend;
- g_quic_cache_backend = nullptr;
- server_stopped_event->Signal();
- }
- void ShutdownDispatcherOnServerThread(
- base::WaitableEvent* dispatcher_stopped_event) {
- DCHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
- g_quic_server->dispatcher()->Shutdown();
- dispatcher_stopped_event->Signal();
- }
- bool QuicSimpleTestServer::Start() {
- DVLOG(3) << g_quic_server_thread;
- DCHECK(!g_quic_server_thread);
- g_quic_server_thread = new base::Thread("quic server thread");
- base::Thread::Options thread_options;
- thread_options.message_pump_type = base::MessagePumpType::IO;
- bool started =
- g_quic_server_thread->StartWithOptions(std::move(thread_options));
- DCHECK(started);
- base::FilePath test_files_root = GetTestCertsDirectory();
- base::WaitableEvent server_started_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- g_quic_server_thread->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&StartQuicServerOnServerThread, test_files_root,
- &server_started_event));
- server_started_event.Wait();
- return true;
- }
- void QuicSimpleTestServer::AddResponseWithEarlyHints(
- const std::string& path,
- const spdy::Http2HeaderBlock& response_headers,
- const std::string& response_body,
- const std::vector<spdy::Http2HeaderBlock>& early_hints) {
- g_quic_cache_backend->AddResponseWithEarlyHints(kTestServerHost, path,
- response_headers.Clone(),
- response_body, early_hints);
- }
- // Shut down the server dispatcher, and the stream should error out.
- void QuicSimpleTestServer::ShutdownDispatcherForTesting() {
- if (!g_quic_server)
- return;
- DCHECK(!g_quic_server_thread->task_runner()->BelongsToCurrentThread());
- base::WaitableEvent dispatcher_stopped_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- g_quic_server_thread->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ShutdownDispatcherOnServerThread,
- &dispatcher_stopped_event));
- dispatcher_stopped_event.Wait();
- }
- void QuicSimpleTestServer::Shutdown() {
- if (!g_quic_server)
- return;
- DCHECK(!g_quic_server_thread->task_runner()->BelongsToCurrentThread());
- base::WaitableEvent server_stopped_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- g_quic_server_thread->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&ShutdownOnServerThread, &server_stopped_event));
- server_stopped_event.Wait();
- delete g_quic_server_thread;
- g_quic_server_thread = nullptr;
- }
- int QuicSimpleTestServer::GetPort() {
- return g_quic_server_port;
- }
- } // namespace net
|