Automated g4 rollback of changelist 466743774.
*** Reason for rollback ***
Broke //video/live/ingest/rush:rush_ingest_quic_server_test because it somehow has `QuicServer::quic_simple_server_backend_` uninitialized in QuicServer::~QuicServer(). Seems like a usage bug, but I'll rollback and figure it out.
*** Original change description ***
Create QUICHE toy CONNECT proxy server
***
PiperOrigin-RevId: 466782365
diff --git a/build/source_list.bzl b/build/source_list.bzl
index 90dd052..313dea4 100644
--- a/build/source_list.bzl
+++ b/build/source_list.bzl
@@ -693,7 +693,6 @@
"common/platform/api/quiche_file_utils.h",
"common/platform/api/quiche_system_event_loop.h",
"quic/platform/api/quic_default_proof_providers.h",
- "quic/tools/connect_server_backend.h",
"quic/tools/connect_tunnel.h",
"quic/tools/fake_proof_verifier.h",
"quic/tools/quic_backend_response.h",
@@ -718,7 +717,6 @@
]
quiche_tool_support_srcs = [
"common/platform/api/quiche_file_utils.cc",
- "quic/tools/connect_server_backend.cc",
"quic/tools/connect_tunnel.cc",
"quic/tools/quic_backend_response.cc",
"quic/tools/quic_client_base.cc",
diff --git a/build/source_list.gni b/build/source_list.gni
index 842512d..0c08a73 100644
--- a/build/source_list.gni
+++ b/build/source_list.gni
@@ -693,7 +693,6 @@
"src/quiche/common/platform/api/quiche_file_utils.h",
"src/quiche/common/platform/api/quiche_system_event_loop.h",
"src/quiche/quic/platform/api/quic_default_proof_providers.h",
- "src/quiche/quic/tools/connect_server_backend.h",
"src/quiche/quic/tools/connect_tunnel.h",
"src/quiche/quic/tools/fake_proof_verifier.h",
"src/quiche/quic/tools/quic_backend_response.h",
@@ -718,7 +717,6 @@
]
quiche_tool_support_srcs = [
"src/quiche/common/platform/api/quiche_file_utils.cc",
- "src/quiche/quic/tools/connect_server_backend.cc",
"src/quiche/quic/tools/connect_tunnel.cc",
"src/quiche/quic/tools/quic_backend_response.cc",
"src/quiche/quic/tools/quic_client_base.cc",
diff --git a/build/source_list.json b/build/source_list.json
index 6d14856..a7fdf5b 100644
--- a/build/source_list.json
+++ b/build/source_list.json
@@ -692,7 +692,6 @@
"quiche/common/platform/api/quiche_file_utils.h",
"quiche/common/platform/api/quiche_system_event_loop.h",
"quiche/quic/platform/api/quic_default_proof_providers.h",
- "quiche/quic/tools/connect_server_backend.h",
"quiche/quic/tools/connect_tunnel.h",
"quiche/quic/tools/fake_proof_verifier.h",
"quiche/quic/tools/quic_backend_response.h",
@@ -717,7 +716,6 @@
],
"quiche_tool_support_srcs": [
"quiche/common/platform/api/quiche_file_utils.cc",
- "quiche/quic/tools/connect_server_backend.cc",
"quiche/quic/tools/connect_tunnel.cc",
"quiche/quic/tools/quic_backend_response.cc",
"quiche/quic/tools/quic_client_base.cc",
diff --git a/quiche/quic/tools/connect_server_backend.cc b/quiche/quic/tools/connect_server_backend.cc
deleted file mode 100644
index baee9c1..0000000
--- a/quiche/quic/tools/connect_server_backend.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2022 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 "quiche/quic/tools/connect_server_backend.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "absl/container/flat_hash_set.h"
-#include "absl/strings/string_view.h"
-#include "quiche/quic/core/io/socket_factory.h"
-#include "quiche/quic/tools/connect_tunnel.h"
-#include "quiche/quic/tools/quic_simple_server_backend.h"
-#include "quiche/common/platform/api/quiche_bug_tracker.h"
-#include "quiche/common/platform/api/quiche_logging.h"
-#include "quiche/spdy/core/http2_header_block.h"
-
-namespace quic {
-
-namespace {
-
-void SendErrorResponse(QuicSimpleServerBackend::RequestHandler* request_handler,
- absl::string_view error_code) {
- spdy::Http2HeaderBlock headers;
- headers[":status"] = error_code;
- QuicBackendResponse response;
- response.set_headers(std::move(headers));
- request_handler->OnResponseBackendComplete(&response);
-}
-
-} // namespace
-
-ConnectServerBackend::ConnectServerBackend(
- std::unique_ptr<QuicSimpleServerBackend> non_connect_backend,
- absl::flat_hash_set<ConnectTunnel::HostAndPort> acceptable_destinations)
- : non_connect_backend_(std::move(non_connect_backend)),
- acceptable_destinations_(std::move(acceptable_destinations)) {
- QUICHE_DCHECK(non_connect_backend_);
-}
-
-ConnectServerBackend::~ConnectServerBackend() {
- // Expect all streams to be closed before destroying backend.
- QUICHE_DCHECK(tunnels_.empty());
-}
-
-bool ConnectServerBackend::InitializeBackend(const std::string&) {
- return true;
-}
-
-bool ConnectServerBackend::IsBackendInitialized() const { return true; }
-
-void ConnectServerBackend::SetSocketFactory(SocketFactory* socket_factory) {
- QUICHE_DCHECK_NE(socket_factory_, socket_factory);
- QUICHE_DCHECK(tunnels_.empty());
- socket_factory_ = socket_factory;
-}
-
-void ConnectServerBackend::FetchResponseFromBackend(
- const spdy::Http2HeaderBlock& request_headers,
- const std::string& request_body, RequestHandler* request_handler) {
- // Not a CONNECT request, so send to `non_connect_backend_`.
- non_connect_backend_->FetchResponseFromBackend(request_headers, request_body,
- request_handler);
-}
-
-void ConnectServerBackend::HandleConnectHeaders(
- const spdy::Http2HeaderBlock& request_headers,
- RequestHandler* request_handler) {
- QUICHE_DCHECK(request_headers.contains(":method") &&
- request_headers.find(":method")->second == "CONNECT");
-
- if (!socket_factory_) {
- QUICHE_BUG(connect_server_backend_no_socket_factory)
- << "Must set socket factory before ConnectServerBackend receives "
- "requests.";
- SendErrorResponse(request_handler, "500");
- return;
- }
-
- if (request_headers.contains(":protocol")) {
- // Anything other than normal CONNECT not supported.
- // TODO(ericorth): Add CONNECT-UDP support.
- non_connect_backend_->HandleConnectHeaders(request_headers,
- request_handler);
- return;
- }
-
- auto [tunnel_it, inserted] = tunnels_.emplace(
- request_handler->stream_id(),
- std::make_unique<ConnectTunnel>(request_handler, socket_factory_,
- acceptable_destinations_));
- QUICHE_DCHECK(inserted);
-
- tunnel_it->second->OpenTunnel(request_headers);
-}
-
-void ConnectServerBackend::HandleConnectData(absl::string_view data,
- bool data_complete,
- RequestHandler* request_handler) {
- auto tunnel_it = tunnels_.find(request_handler->stream_id());
- if (tunnel_it == tunnels_.end()) {
- // If tunnel not found, perhaps it's something being handled for
- // non-CONNECT. Possible because this method could be called for anything
- // with a ":method":"CONNECT" header, but this class does not handle such
- // requests if they have a ":protocol" header.
- non_connect_backend_->HandleConnectData(data, data_complete,
- request_handler);
- return;
- }
-
- if (!data.empty()) {
- tunnel_it->second->SendDataToDestination(data);
- }
- if (data_complete) {
- tunnel_it->second->OnClientStreamClose();
- tunnels_.erase(tunnel_it);
- }
-}
-
-void ConnectServerBackend::CloseBackendResponseStream(
- QuicSimpleServerBackend::RequestHandler* request_handler) {
- auto tunnel_it = tunnels_.find(request_handler->stream_id());
- if (tunnel_it != tunnels_.end()) {
- tunnel_it->second->OnClientStreamClose();
- tunnels_.erase(tunnel_it);
- }
-
- non_connect_backend_->CloseBackendResponseStream(request_handler);
-}
-
-} // namespace quic
diff --git a/quiche/quic/tools/connect_server_backend.h b/quiche/quic/tools/connect_server_backend.h
deleted file mode 100644
index a1cd843..0000000
--- a/quiche/quic/tools/connect_server_backend.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2022 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.
-
-#ifndef QUICHE_QUIC_CONNECT_PROXY_CONNECT_SERVER_BACKEND_H_
-#define QUICHE_QUIC_CONNECT_PROXY_CONNECT_SERVER_BACKEND_H_
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "absl/container/flat_hash_map.h"
-#include "absl/container/flat_hash_set.h"
-#include "quiche/quic/core/io/socket_factory.h"
-#include "quiche/quic/core/quic_types.h"
-#include "quiche/quic/tools/connect_tunnel.h"
-#include "quiche/quic/tools/quic_simple_server_backend.h"
-
-namespace quic {
-
-// QUIC server backend that handles CONNECT requests. Non-CONNECT requests are
-// delegated to a separate backend.
-class ConnectServerBackend : public QuicSimpleServerBackend {
- public:
- ConnectServerBackend(
- std::unique_ptr<QuicSimpleServerBackend> non_connect_backend,
- absl::flat_hash_set<ConnectTunnel::HostAndPort> acceptable_destinations);
-
- ConnectServerBackend(const ConnectServerBackend&) = delete;
- ConnectServerBackend& operator=(const ConnectServerBackend&) = delete;
-
- ~ConnectServerBackend() override;
-
- // QuicSimpleServerBackend:
- bool InitializeBackend(const std::string& backend_url) override;
- bool IsBackendInitialized() const override;
- void SetSocketFactory(SocketFactory* socket_factory) override;
- void FetchResponseFromBackend(const spdy::Http2HeaderBlock& request_headers,
- const std::string& request_body,
- RequestHandler* request_handler) override;
- void HandleConnectHeaders(const spdy::Http2HeaderBlock& request_headers,
- RequestHandler* request_handler) override;
- void HandleConnectData(absl::string_view data, bool data_complete,
- RequestHandler* request_handler) override;
- void CloseBackendResponseStream(
- QuicSimpleServerBackend::RequestHandler* request_handler) override;
-
- private:
- std::unique_ptr<QuicSimpleServerBackend> non_connect_backend_;
- const absl::flat_hash_set<ConnectTunnel::HostAndPort>
- acceptable_destinations_;
-
- SocketFactory* socket_factory_; // unowned
- absl::flat_hash_map<QuicStreamId, std::unique_ptr<ConnectTunnel>> tunnels_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CONNECT_PROXY_CONNECT_SERVER_BACKEND_H_
diff --git a/quiche/quic/tools/connect_tunnel.cc b/quiche/quic/tools/connect_tunnel.cc
index ef2a5eb..bd0b66e 100644
--- a/quiche/quic/tools/connect_tunnel.cc
+++ b/quiche/quic/tools/connect_tunnel.cc
@@ -81,8 +81,8 @@
}
QUICHE_DCHECK_LE(parsed_port_number, std::numeric_limits<uint16_t>::max());
- return ConnectTunnel::HostAndPort(std::move(hostname),
- static_cast<uint16_t>(parsed_port_number));
+ return std::make_pair(std::move(hostname),
+ static_cast<uint16_t>(parsed_port_number));
}
absl::optional<ConnectTunnel::HostAndPort> ValidateHeadersAndGetAuthority(
@@ -114,28 +114,22 @@
return ValidateAndParseAuthorityString(authority_it->second);
}
-bool ValidateAuthority(const ConnectTunnel::HostAndPort& authority,
- const absl::flat_hash_set<ConnectTunnel::HostAndPort>&
- acceptable_destinations) {
+bool ValidateAuthority(
+ const ConnectTunnel::HostAndPort& authority,
+ const absl::flat_hash_set<std::pair<std::string, uint16_t>>&
+ acceptable_destinations) {
if (acceptable_destinations.contains(authority)) {
return true;
}
QUICHE_DVLOG(1) << "CONNECT request authority: "
- << absl::StrCat(authority.host, ":", authority.port)
+ << absl::StrCat(authority.first, ":", authority.second)
<< " is not an acceptable allow-listed destiation ";
return false;
}
} // namespace
-ConnectTunnel::HostAndPort::HostAndPort(std::string host, uint16_t port)
- : host(std::move(host)), port(port) {}
-
-bool ConnectTunnel::HostAndPort::operator==(const HostAndPort& other) const {
- return host == other.host && port == other.port;
-}
-
ConnectTunnel::ConnectTunnel(
QuicSimpleServerBackend::RequestHandler* client_stream_request_handler,
SocketFactory* socket_factory,
@@ -174,8 +168,9 @@
return;
}
- QuicSocketAddress address = tools::LookupAddress(
- AF_UNSPEC, authority->host, absl::StrCat(authority->port));
+ QuicSocketAddress address =
+ tools::LookupAddress(AF_UNSPEC, authority.value().first,
+ absl::StrCat(authority.value().second));
if (!address.IsInitialized()) {
TerminateClientStream("host resolution error");
return;
@@ -198,7 +193,7 @@
QUICHE_DVLOG(1) << "CONNECT tunnel opened from stream "
<< client_stream_request_handler_->stream_id() << " to "
- << authority->host << ":" << authority->port;
+ << authority.value().first << ":" << authority.value().second;
SendConnectResponse();
BeginAsyncReadFromDestination();
diff --git a/quiche/quic/tools/connect_tunnel.h b/quiche/quic/tools/connect_tunnel.h
index d18d63f..f638324 100644
--- a/quiche/quic/tools/connect_tunnel.h
+++ b/quiche/quic/tools/connect_tunnel.h
@@ -26,19 +26,7 @@
// Manages a single connection tunneled over a CONNECT proxy.
class ConnectTunnel : public StreamClientSocket::AsyncVisitor {
public:
- struct HostAndPort {
- HostAndPort(std::string host, uint16_t port);
-
- bool operator==(const HostAndPort& other) const;
-
- template <typename H>
- friend H AbslHashValue(H h, const HostAndPort& host_and_port) {
- return H::combine(std::move(h), host_and_port.host, host_and_port.port);
- }
-
- std::string host;
- uint16_t port;
- };
+ using HostAndPort = std::pair<std::string, uint16_t>;
// `client_stream_request_handler` and `socket_factory` must both outlive the
// created ConnectTunnel.
diff --git a/quiche/quic/tools/quic_server.cc b/quiche/quic/tools/quic_server.cc
index 0c3233a..53985e7 100644
--- a/quiche/quic/tools/quic_server.cc
+++ b/quiche/quic/tools/quic_server.cc
@@ -16,7 +16,6 @@
#include "quiche/quic/core/crypto/crypto_handshake.h"
#include "quiche/quic/core/crypto/quic_random.h"
-#include "quiche/quic/core/io/event_loop_socket_factory.h"
#include "quiche/quic/core/io/quic_default_event_loop.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_clock.h"
@@ -33,7 +32,6 @@
#include "quiche/quic/tools/quic_simple_crypto_server_stream_helper.h"
#include "quiche/quic/tools/quic_simple_dispatcher.h"
#include "quiche/quic/tools/quic_simple_server_backend.h"
-#include "quiche/common/simple_buffer_allocator.h"
namespace quic {
@@ -105,20 +103,11 @@
QuicServer::~QuicServer() {
close(fd_);
fd_ = -1;
-
- // Should be fine without because nothing should send requests to the backend
- // after `this` is destroyed, but for extra pointer safety, clear the socket
- // factory from the backend before the socket factory is destroyed.
- quic_simple_server_backend_->SetSocketFactory(nullptr);
}
bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
event_loop_ = CreateEventLoop();
- socket_factory_ = std::make_unique<EventLoopSocketFactory>(
- event_loop_.get(), quiche::SimpleBufferAllocator::Get());
- quic_simple_server_backend_->SetSocketFactory(socket_factory_.get());
-
QuicUdpSocketApi socket_api;
fd_ = socket_api.Create(address.host().AddressFamilyToInt(),
/*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
diff --git a/quiche/quic/tools/quic_server.h b/quiche/quic/tools/quic_server.h
index d080cb1..7cb870f 100644
--- a/quiche/quic/tools/quic_server.h
+++ b/quiche/quic/tools/quic_server.h
@@ -16,7 +16,6 @@
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/quic_crypto_server_config.h"
#include "quiche/quic/core/io/quic_event_loop.h"
-#include "quiche/quic/core/io/socket_factory.h"
#include "quiche/quic/core/quic_config.h"
#include "quiche/quic/core/quic_packet_writer.h"
#include "quiche/quic/core/quic_udp_socket.h"
@@ -115,9 +114,6 @@
// Schedules alarms and notifies the server of the I/O events.
std::unique_ptr<QuicEventLoop> event_loop_;
- // Used by some backends to create additional sockets, e.g. for upstream
- // destination connections for proxying.
- std::unique_ptr<SocketFactory> socket_factory_;
// Accepts data from the framer and demuxes clients to sessions.
std::unique_ptr<QuicDispatcher> dispatcher_;
diff --git a/quiche/quic/tools/quic_simple_server_backend.h b/quiche/quic/tools/quic_simple_server_backend.h
index 26eaa65..bbb0d93 100644
--- a/quiche/quic/tools/quic_simple_server_backend.h
+++ b/quiche/quic/tools/quic_simple_server_backend.h
@@ -9,10 +9,10 @@
#include <memory>
#include "absl/strings/string_view.h"
-#include "quiche/quic/core/io/socket_factory.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/web_transport_interface.h"
+#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/tools/quic_backend_response.h"
#include "quiche/spdy/core/http2_header_block.h"
@@ -59,10 +59,6 @@
// Returns true if the backend has been successfully initialized
// and could be used to fetch HTTP requests
virtual bool IsBackendInitialized() const = 0;
- // Passes the socket factory in use by the QuicServer. Must live as long as
- // incoming requests/data are still sent to the backend, or until cleared by
- // calling with null. Must not be called while backend is handling requests.
- virtual void SetSocketFactory(SocketFactory* /*socket_factory*/) {}
// Triggers a HTTP request to be sent to the backend server or cache
// If response is immediately available, the function synchronously calls
// the `request_handler` with the HTTP response.
diff --git a/quiche/quic/tools/quic_toy_server.cc b/quiche/quic/tools/quic_toy_server.cc
index 500e5a1..6b3c76f 100644
--- a/quiche/quic/tools/quic_toy_server.cc
+++ b/quiche/quic/tools/quic_toy_server.cc
@@ -4,20 +4,14 @@
#include "quiche/quic/tools/quic_toy_server.h"
-#include <limits>
#include <utility>
#include <vector>
-#include "absl/strings/str_split.h"
-#include "url/third_party/mozilla/url_parse.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_default_proof_providers.h"
#include "quiche/quic/platform/api/quic_socket_address.h"
-#include "quiche/quic/tools/connect_server_backend.h"
-#include "quiche/quic/tools/connect_tunnel.h"
#include "quiche/quic/tools/quic_memory_cache_backend.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"
-#include "quiche/common/platform/api/quiche_logging.h"
DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, port, 6121,
"The port the quic server will listen on.");
@@ -45,54 +39,8 @@
DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, enable_webtransport, false,
"If true, WebTransport support is enabled.");
-DEFINE_QUICHE_COMMAND_LINE_FLAG(
- std::string, connect_proxy_destinations, "",
- "Specifies a comma-separated list of destinations (\"hostname:port\") to "
- "which the quic server will allow tunneling via CONNECT.");
-
namespace quic {
-namespace {
-
-ConnectTunnel::HostAndPort ParseProxyDestination(
- absl::string_view destination) {
- url::Component username_component;
- url::Component password_component;
- url::Component host_component;
- url::Component port_component;
-
- url::ParseAuthority(destination.data(), url::Component(0, destination.size()),
- &username_component, &password_component, &host_component,
- &port_component);
-
- // Only support "host:port"
- QUICHE_CHECK(!username_component.is_valid() &&
- !password_component.is_valid());
- QUICHE_CHECK(host_component.is_nonempty() && port_component.is_nonempty());
-
- QUICHE_CHECK_LT(static_cast<size_t>(host_component.end()),
- destination.size());
- if (host_component.len > 2 && destination[host_component.begin] == '[' &&
- destination[host_component.end() - 1] == ']') {
- // Strip "[]" off IPv6 literals.
- host_component.begin += 1;
- host_component.len -= 2;
- }
- std::string hostname(destination.data() + host_component.begin,
- host_component.len);
-
- int parsed_port_number = url::ParsePort(destination.data(), port_component);
-
- // Require specified and valid port.
- QUICHE_CHECK_GT(parsed_port_number, 0);
- QUICHE_CHECK_LE(parsed_port_number, std::numeric_limits<uint16_t>::max());
-
- return ConnectTunnel::HostAndPort(std::move(hostname),
- static_cast<uint16_t>(parsed_port_number));
-}
-
-} // namespace
-
std::unique_ptr<quic::QuicSimpleServerBackend>
QuicToyServer::MemoryCacheBackendFactory::CreateBackend() {
auto memory_cache_backend = std::make_unique<QuicMemoryCacheBackend>();
@@ -107,21 +55,6 @@
if (quiche::GetQuicheCommandLineFlag(FLAGS_enable_webtransport)) {
memory_cache_backend->EnableWebTransport();
}
-
- if (!quiche::GetQuicheCommandLineFlag(FLAGS_connect_proxy_destinations)
- .empty()) {
- absl::flat_hash_set<ConnectTunnel::HostAndPort> connect_proxy_destinations;
- for (absl::string_view destination : absl::StrSplit(
- quiche::GetQuicheCommandLineFlag(FLAGS_connect_proxy_destinations),
- ',', absl::SkipEmpty())) {
- connect_proxy_destinations.insert(ParseProxyDestination(destination));
- }
- QUICHE_CHECK(!connect_proxy_destinations.empty());
-
- return std::make_unique<ConnectServerBackend>(
- std::move(memory_cache_backend), std::move(connect_proxy_destinations));
- }
-
return memory_cache_backend;
}