xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/tools/web_transport_test_server.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 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 <memory>
6 
7 #include "absl/status/status.h"
8 #include "absl/status/statusor.h"
9 #include "absl/strings/numbers.h"
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/web_transport_interface.h"
12 #include "quiche/quic/platform/api/quic_socket_address.h"
13 #include "quiche/quic/tools/devious_baton.h"
14 #include "quiche/quic/tools/quic_server.h"
15 #include "quiche/quic/tools/web_transport_only_backend.h"
16 #include "quiche/quic/tools/web_transport_test_visitors.h"
17 #include "quiche/common/platform/api/quiche_command_line_flags.h"
18 #include "quiche/common/platform/api/quiche_default_proof_providers.h"
19 #include "quiche/common/platform/api/quiche_googleurl.h"
20 #include "quiche/common/platform/api/quiche_logging.h"
21 #include "quiche/common/platform/api/quiche_system_event_loop.h"
22 #include "quiche/common/quiche_random.h"
23 #include "quiche/web_transport/web_transport.h"
24 
25 DEFINE_QUICHE_COMMAND_LINE_FLAG(
26     int32_t, port, 6121, "The port the WebTransport server will listen on.");
27 
28 namespace quic {
29 namespace {
30 
ProcessRequest(absl::string_view path,WebTransportSession * session)31 absl::StatusOr<std::unique_ptr<webtransport::SessionVisitor>> ProcessRequest(
32     absl::string_view path, WebTransportSession* session) {
33   GURL url(absl::StrCat("https://localhost", path));
34   if (!url.is_valid()) {
35     return absl::InvalidArgumentError("Unable to parse the :path");
36   }
37 
38   if (url.path() == "/webtransport/echo") {
39     return std::make_unique<EchoWebTransportSessionVisitor>(session);
40   }
41   if (url.path() == "/webtransport/devious-baton") {
42     int count = 1;
43     DeviousBatonValue initial_value =
44         quiche::QuicheRandom::GetInstance()->RandUint64() % 256;
45     std::string query = url.query();
46     url::Component query_component, key_component, value_component;
47     query_component.begin = 0;
48     query_component.len = query.size();
49     while (url::ExtractQueryKeyValue(query.data(), &query_component,
50                                      &key_component, &value_component)) {
51       absl::string_view key(query.data() + key_component.begin,
52                             key_component.len);
53       absl::string_view value(query.data() + value_component.begin,
54                               value_component.len);
55       int parsed_value;
56       if (!absl::SimpleAtoi(value, &parsed_value) || parsed_value < 0 ||
57           parsed_value > 255) {
58         if (key == "count" || key == "baton") {
59           return absl::InvalidArgumentError(
60               absl::StrCat("Failed to parse query param ", key));
61         }
62         continue;
63       }
64       if (key == "count") {
65         count = parsed_value;
66       }
67       if (key == "baton") {
68         initial_value = parsed_value;
69       }
70     }
71     return std::make_unique<DeviousBatonSessionVisitor>(
72         session, /*is_server=*/true, initial_value, count);
73   }
74   return absl::NotFoundError("Path not found");
75 }
76 
Main(int argc,char ** argv)77 int Main(int argc, char** argv) {
78   quiche::QuicheSystemEventLoop event_loop("web_transport_test_server");
79   const char* usage = "Usage: web_transport_test_server [options]";
80   std::vector<std::string> non_option_args =
81       quiche::QuicheParseCommandLineFlags(usage, argc, argv);
82 
83   WebTransportOnlyBackend backend(ProcessRequest);
84   QuicServer server(quiche::CreateDefaultProofSource(), &backend);
85   quic::QuicSocketAddress addr(quic::QuicIpAddress::Any6(),
86                                quiche::GetQuicheCommandLineFlag(FLAGS_port));
87   if (!server.CreateUDPSocketAndListen(addr)) {
88     QUICHE_LOG(ERROR) << "Failed to bind the port address";
89   }
90   QUICHE_LOG(INFO) << "Bound the server on " << addr;
91   server.HandleEventsForever();
92   return 0;
93 }
94 
95 }  // namespace
96 }  // namespace quic
97 
main(int argc,char ** argv)98 int main(int argc, char** argv) { return quic::Main(argc, argv); }
99