1 // Copyright 2022 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 #ifndef QUICHE_QUIC_TOOLS_CONNECT_TUNNEL_H_ 6 #define QUICHE_QUIC_TOOLS_CONNECT_TUNNEL_H_ 7 8 #include <cstdint> 9 #include <memory> 10 #include <string> 11 #include <utility> 12 13 #include "absl/container/flat_hash_set.h" 14 #include "absl/status/status.h" 15 #include "absl/status/statusor.h" 16 #include "absl/strings/string_view.h" 17 #include "quiche/quic/core/connecting_client_socket.h" 18 #include "quiche/quic/core/quic_error_codes.h" 19 #include "quiche/quic/core/quic_server_id.h" 20 #include "quiche/quic/core/socket_factory.h" 21 #include "quiche/quic/tools/quic_simple_server_backend.h" 22 #include "quiche/common/platform/api/quiche_mem_slice.h" 23 #include "quiche/spdy/core/http2_header_block.h" 24 25 namespace quic { 26 27 // Manages a single connection tunneled over a CONNECT proxy. 28 class ConnectTunnel : public ConnectingClientSocket::AsyncVisitor { 29 public: 30 // `client_stream_request_handler` and `socket_factory` must both outlive the 31 // created ConnectTunnel. 32 ConnectTunnel( 33 QuicSimpleServerBackend::RequestHandler* client_stream_request_handler, 34 SocketFactory* socket_factory, 35 absl::flat_hash_set<QuicServerId> acceptable_destinations); 36 ~ConnectTunnel(); 37 ConnectTunnel(const ConnectTunnel&) = delete; 38 ConnectTunnel& operator=(const ConnectTunnel&) = delete; 39 40 // Attempts to open TCP connection to destination server and then sends 41 // appropriate success/error response to the request stream. `request_headers` 42 // must represent headers from a CONNECT request, that is ":method"="CONNECT" 43 // and no ":protocol". 44 void OpenTunnel(const spdy::Http2HeaderBlock& request_headers); 45 46 // Returns true iff the connection to the destination server is currently open 47 bool IsConnectedToDestination() const; 48 49 void SendDataToDestination(absl::string_view data); 50 51 // Called when the client stream has been closed. Connection to destination 52 // server is closed if connected. The RequestHandler will no longer be 53 // interacted with after completion. 54 void OnClientStreamClose(); 55 56 // ConnectingClientSocket::AsyncVisitor: 57 void ConnectComplete(absl::Status status) override; 58 void ReceiveComplete(absl::StatusOr<quiche::QuicheMemSlice> data) override; 59 void SendComplete(absl::Status status) override; 60 61 private: 62 void BeginAsyncReadFromDestination(); 63 void OnDataReceivedFromDestination(bool success); 64 65 // For normal (FIN) closure. Errors (RST) should result in directly calling 66 // TerminateClientStream(). 67 void OnDestinationConnectionClosed(); 68 69 void SendConnectResponse(); 70 void TerminateClientStream( 71 absl::string_view error_description, 72 QuicResetStreamError error_code = 73 QuicResetStreamError::FromIetf(QuicHttp3ErrorCode::CONNECT_ERROR)); 74 75 const absl::flat_hash_set<QuicServerId> acceptable_destinations_; 76 SocketFactory* const socket_factory_; 77 78 // Null when client stream closed. 79 QuicSimpleServerBackend::RequestHandler* client_stream_request_handler_; 80 81 // Null when destination connection disconnected. 82 std::unique_ptr<ConnectingClientSocket> destination_socket_; 83 84 bool receive_started_ = false; 85 }; 86 87 } // namespace quic 88 89 #endif // QUICHE_QUIC_TOOLS_CONNECT_TUNNEL_H_ 90