blob: a7c1794048701d5952ad3fc132afaa71726a97fc [file] [log] [blame]
// Copyright 2023 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 <memory>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/web_transport_interface.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
#include "quiche/quic/tools/devious_baton.h"
#include "quiche/quic/tools/quic_server.h"
#include "quiche/quic/tools/web_transport_only_backend.h"
#include "quiche/quic/tools/web_transport_test_visitors.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"
#include "quiche/common/platform/api/quiche_default_proof_providers.h"
#include "quiche/common/platform/api/quiche_googleurl.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_system_event_loop.h"
#include "quiche/common/quiche_random.h"
#include "quiche/web_transport/web_transport.h"
DEFINE_QUICHE_COMMAND_LINE_FLAG(
int32_t, port, 6121, "The port the WebTransport server will listen on.");
namespace quic {
namespace {
absl::StatusOr<std::unique_ptr<webtransport::SessionVisitor>> ProcessRequest(
absl::string_view path, WebTransportSession* session) {
GURL url(absl::StrCat("https://localhost", path));
if (!url.is_valid()) {
return absl::InvalidArgumentError("Unable to parse the :path");
}
if (url.path() == "/webtransport/echo") {
return std::make_unique<EchoWebTransportSessionVisitor>(session);
}
if (url.path() == "/webtransport/devious-baton") {
int count = 1;
DeviousBatonValue initial_value =
quiche::QuicheRandom::GetInstance()->RandUint64() % 256;
std::string query = url.query();
url::Component query_component, key_component, value_component;
query_component.begin = 0;
query_component.len = query.size();
while (url::ExtractQueryKeyValue(query.data(), &query_component,
&key_component, &value_component)) {
absl::string_view key(query.data() + key_component.begin,
key_component.len);
absl::string_view value(query.data() + value_component.begin,
value_component.len);
int parsed_value;
if (!absl::SimpleAtoi(value, &parsed_value) || parsed_value < 0 ||
parsed_value > 255) {
if (key == "count" || key == "baton") {
return absl::InvalidArgumentError(
absl::StrCat("Failed to parse query param ", key));
}
continue;
}
if (key == "count") {
count = parsed_value;
}
if (key == "baton") {
initial_value = parsed_value;
}
}
return std::make_unique<DeviousBatonSessionVisitor>(
session, /*is_server=*/true, initial_value, count);
}
return absl::NotFoundError("Path not found");
}
int Main(int argc, char** argv) {
quiche::QuicheSystemEventLoop event_loop("web_transport_test_server");
const char* usage = "Usage: web_transport_test_server [options]";
std::vector<std::string> non_option_args =
quiche::QuicheParseCommandLineFlags(usage, argc, argv);
WebTransportOnlyBackend backend(ProcessRequest);
QuicServer server(quiche::CreateDefaultProofSource(), &backend);
quic::QuicSocketAddress addr(quic::QuicIpAddress::Any6(),
quiche::GetQuicheCommandLineFlag(FLAGS_port));
if (!server.CreateUDPSocketAndListen(addr)) {
QUICHE_LOG(ERROR) << "Failed to bind the port address";
}
QUICHE_LOG(INFO) << "Bound the server on " << addr;
server.HandleEventsForever();
return 0;
}
} // namespace
} // namespace quic
int main(int argc, char** argv) { return quic::Main(argc, argv); }