xref: /aosp_15_r20/external/cronet/components/cronet/android/test/quic_test_server.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2015 The Chromium Authors
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 <memory>
6 #include "base/android/jni_android.h"
7 #include "base/android/jni_string.h"
8 #include "base/android/path_utils.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/functional/bind.h"
12 #include "base/functional/callback_forward.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_pump_type.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/test/test_support_android.h"
18 #include "base/threading/thread.h"
19 #include "components/cronet/android/cronet_test_apk_jni/QuicTestServer_jni.h"
20 #include "components/cronet/android/test/cronet_test_util.h"
21 #include "net/base/ip_address.h"
22 #include "net/base/ip_endpoint.h"
23 #include "net/quic/crypto/proof_source_chromium.h"
24 #include "net/test/test_data_directory.h"
25 #include "net/third_party/quiche/src/quiche/quic/tools/quic_memory_cache_backend.h"
26 #include "net/tools/quic/quic_simple_server.h"
27 
28 using base::android::JavaParamRef;
29 using base::android::ScopedJavaLocalRef;
30 
31 namespace cronet {
32 
33 namespace {
34 
35 static const int kServerPort = 6121;
36 
37 std::unique_ptr<base::Thread> g_quic_server_thread;
38 std::unique_ptr<quic::QuicMemoryCacheBackend> g_quic_memory_cache_backend;
39 std::unique_ptr<net::QuicSimpleServer> g_quic_server;
40 base::WaitableEvent wait_for_callback(
41     base::WaitableEvent::ResetPolicy::AUTOMATIC);
42 
43 template <typename T>
WrapCallbackWithSignal(base::OnceCallback<T> callback)44 base::OnceCallback<void()> WrapCallbackWithSignal(
45     base::OnceCallback<T> callback) {
46   return base::BindOnce(base::IgnoreResult(std::move(callback)))
47       .Then(base::BindOnce([] { wait_for_callback.Signal(); }));
48 }
49 
50 template <typename T>
ExecuteSynchronouslyOnServerThread(base::OnceCallback<T> callback,base::Location from_here=FROM_HERE)51 void ExecuteSynchronouslyOnServerThread(base::OnceCallback<T> callback,
52                                         base::Location from_here = FROM_HERE) {
53   CHECK(g_quic_server_thread);
54   g_quic_server_thread->task_runner()->PostTask(
55       from_here, WrapCallbackWithSignal(std::move(callback)));
56   wait_for_callback.Wait();
57 }
58 
StartOnServerThread(const base::FilePath & test_files_root,const base::FilePath & test_data_dir)59 void StartOnServerThread(const base::FilePath& test_files_root,
60                          const base::FilePath& test_data_dir) {
61   CHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
62   CHECK(!g_quic_server);
63   CHECK(!g_quic_memory_cache_backend);
64 
65   // Set up in-memory cache.
66   base::FilePath file_dir = test_files_root.Append("quic_data");
67   CHECK(base::PathExists(file_dir)) << "Quic data does not exist";
68   g_quic_memory_cache_backend =
69       std::make_unique<quic::QuicMemoryCacheBackend>();
70   g_quic_memory_cache_backend->InitializeBackend(file_dir.value());
71   quic::QuicConfig config;
72 
73   // Set up server certs.
74   base::FilePath directory = test_data_dir.Append("net/data/ssl/certificates");
75   std::unique_ptr<net::ProofSourceChromium> proof_source(
76       new net::ProofSourceChromium());
77   CHECK(proof_source->Initialize(directory.Append("quic-chain.pem"),
78                                  directory.Append("quic-leaf-cert.key"),
79                                  base::FilePath()));
80   g_quic_server = std::make_unique<net::QuicSimpleServer>(
81       std::move(proof_source), config,
82       quic::QuicCryptoServerConfig::ConfigOptions(),
83       quic::AllSupportedVersions(), g_quic_memory_cache_backend.get());
84 
85   // Start listening.
86   int rv = g_quic_server->Listen(
87       net::IPEndPoint(net::IPAddress::IPv4AllZeros(), kServerPort));
88   CHECK_GE(rv, 0) << "Quic server fails to start";
89 }
90 
SetResponseDelayOnServerThread(const std::string & path,base::TimeDelta delay)91 void SetResponseDelayOnServerThread(const std::string& path,
92                                     base::TimeDelta delay) {
93   CHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
94   CHECK(g_quic_memory_cache_backend);
95 
96   // TODO(crbug.com/40283192): Stop hardcoding server hostname.
97   CHECK(g_quic_memory_cache_backend->SetResponseDelay(
98       base::StringPrintf("%s:%d", "test.example.com", kServerPort), path,
99       quic::QuicTime::Delta::FromMicroseconds(delay.InMicroseconds())));
100 }
101 
ShutdownOnServerThread()102 void ShutdownOnServerThread() {
103   CHECK(g_quic_server_thread->task_runner()->BelongsToCurrentThread());
104   CHECK(g_quic_server);
105   CHECK(g_quic_memory_cache_backend);
106   g_quic_server->Shutdown();
107   g_quic_server.reset();
108   g_quic_memory_cache_backend.reset();
109 }
110 
111 }  // namespace
112 
113 // Quic server is currently hardcoded to run on port 6121 of the localhost on
114 // the device.
JNI_QuicTestServer_StartQuicTestServer(JNIEnv * env,const JavaParamRef<jstring> & jtest_files_root,const JavaParamRef<jstring> & jtest_data_dir)115 void JNI_QuicTestServer_StartQuicTestServer(
116     JNIEnv* env,
117     const JavaParamRef<jstring>& jtest_files_root,
118     const JavaParamRef<jstring>& jtest_data_dir) {
119   CHECK(!g_quic_server_thread);
120   base::FilePath test_data_dir(
121       base::android::ConvertJavaStringToUTF8(env, jtest_data_dir));
122   base::InitAndroidTestPaths(test_data_dir);
123   g_quic_server_thread = std::make_unique<base::Thread>("quic server thread");
124   base::Thread::Options thread_options;
125   thread_options.message_pump_type = base::MessagePumpType::IO;
126   bool started =
127       g_quic_server_thread->StartWithOptions(std::move(thread_options));
128   CHECK(started);
129   base::FilePath test_files_root(
130       base::android::ConvertJavaStringToUTF8(env, jtest_files_root));
131   ExecuteSynchronouslyOnServerThread(
132       base::BindOnce(&StartOnServerThread, test_files_root, test_data_dir));
133 }
134 
JNI_QuicTestServer_ShutdownQuicTestServer(JNIEnv * env)135 void JNI_QuicTestServer_ShutdownQuicTestServer(JNIEnv* env) {
136   CHECK(!g_quic_server_thread->task_runner()->BelongsToCurrentThread());
137   ExecuteSynchronouslyOnServerThread(base::BindOnce(&ShutdownOnServerThread));
138   g_quic_server_thread.reset();
139 }
140 
JNI_QuicTestServer_GetServerPort(JNIEnv * env)141 int JNI_QuicTestServer_GetServerPort(JNIEnv* env) {
142   return kServerPort;
143 }
144 
JNI_QuicTestServer_DelayResponse(JNIEnv * env,const JavaParamRef<jstring> & jpath,int delayInSeconds)145 void JNI_QuicTestServer_DelayResponse(JNIEnv* env,
146                                       const JavaParamRef<jstring>& jpath,
147                                       int delayInSeconds) {
148   CHECK(!g_quic_server_thread->task_runner()->BelongsToCurrentThread());
149   std::string path = base::android::ConvertJavaStringToUTF8(env, jpath);
150   base::TimeDelta delay = base::Seconds(delayInSeconds);
151   ExecuteSynchronouslyOnServerThread(
152       base::BindOnce(&SetResponseDelayOnServerThread, path, delay));
153 }
154 
155 }  // namespace cronet
156