xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/tools/connect_udp_tunnel.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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 #ifndef QUICHE_QUIC_TOOLS_CONNECT_UDP_TUNNEL_H_
6 #define QUICHE_QUIC_TOOLS_CONNECT_UDP_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/http/quic_spdy_stream.h"
19 #include "quiche/quic/core/quic_error_codes.h"
20 #include "quiche/quic/core/quic_server_id.h"
21 #include "quiche/quic/core/quic_types.h"
22 #include "quiche/quic/core/socket_factory.h"
23 #include "quiche/quic/tools/quic_simple_server_backend.h"
24 #include "quiche/common/platform/api/quiche_mem_slice.h"
25 #include "quiche/spdy/core/http2_header_block.h"
26 
27 namespace quic {
28 
29 // Manages a single UDP tunnel for a CONNECT-UDP proxy (see RFC 9298).
30 class ConnectUdpTunnel : public ConnectingClientSocket::AsyncVisitor,
31                          public QuicSpdyStream::Http3DatagramVisitor {
32  public:
33   // `client_stream_request_handler` and `socket_factory` must both outlive the
34   // created ConnectUdpTunnel. `server_label` is an identifier (typically
35   // randomly generated) to indentify the server or backend in error headers,
36   // per the requirements of RFC 9209, Section 2.
37   ConnectUdpTunnel(
38       QuicSimpleServerBackend::RequestHandler* client_stream_request_handler,
39       SocketFactory* socket_factory, std::string server_label,
40       absl::flat_hash_set<QuicServerId> acceptable_targets);
41   ~ConnectUdpTunnel();
42   ConnectUdpTunnel(const ConnectUdpTunnel&) = delete;
43   ConnectUdpTunnel& operator=(const ConnectUdpTunnel&) = delete;
44 
45   // Attempts to open UDP tunnel to target server and then sends appropriate
46   // success/error response to the request stream. `request_headers` must
47   // represent headers from a CONNECT-UDP request, that is ":method"="CONNECT"
48   // and ":protocol"="connect-udp".
49   void OpenTunnel(const spdy::Http2HeaderBlock& request_headers);
50 
51   // Returns true iff the tunnel to the target server is currently open
52   bool IsTunnelOpenToTarget() const;
53 
54   // Called when the client stream has been closed.  Tunnel to target
55   // server is closed if open.  The RequestHandler will no longer be
56   // interacted with after completion.
57   void OnClientStreamClose();
58 
59   // ConnectingClientSocket::AsyncVisitor:
60   void ConnectComplete(absl::Status status) override;
61   void ReceiveComplete(absl::StatusOr<quiche::QuicheMemSlice> data) override;
62   void SendComplete(absl::Status status) override;
63 
64   // QuicSpdyStream::Http3DatagramVisitor:
65   void OnHttp3Datagram(QuicStreamId stream_id,
66                        absl::string_view payload) override;
OnUnknownCapsule(QuicStreamId,const quiche::UnknownCapsule &)67   void OnUnknownCapsule(QuicStreamId /*stream_id*/,
68                         const quiche::UnknownCapsule& /*capsule*/) override {}
69 
70  private:
71   void BeginAsyncReadFromTarget();
72   void OnDataReceivedFromTarget(bool success);
73 
74   void SendUdpPacketToTarget(absl::string_view packet);
75 
76   void SendConnectResponse();
77   void SendErrorResponse(absl::string_view status,
78                          absl::string_view proxy_status_error,
79                          absl::string_view error_details);
80   void TerminateClientStream(absl::string_view error_description,
81                              QuicResetStreamError error_code);
82 
83   const absl::flat_hash_set<QuicServerId> acceptable_targets_;
84   SocketFactory* const socket_factory_;
85   const std::string server_label_;
86 
87   // Null when client stream closed.
88   QuicSimpleServerBackend::RequestHandler* client_stream_request_handler_;
89 
90   // Null when target connection disconnected.
91   std::unique_ptr<ConnectingClientSocket> target_socket_;
92 
93   bool receive_started_ = false;
94   bool datagram_visitor_registered_ = false;
95 };
96 
97 }  // namespace quic
98 
99 #endif  // QUICHE_QUIC_TOOLS_CONNECT_UDP_TUNNEL_H_
100