xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/masque/masque_server_session.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2019 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 "quiche/quic/masque/masque_server_session.h"
6 
7 #include <fcntl.h>
8 #include <netdb.h>
9 #include <netinet/ip.h>
10 #include <netinet/ip_icmp.h>
11 #include <netinet/udp.h>
12 
13 #include <cstdint>
14 #include <limits>
15 #include <memory>
16 #include <optional>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 
22 #include "absl/algorithm/container.h"
23 #include "absl/cleanup/cleanup.h"
24 #include "absl/strings/escaping.h"
25 #include "absl/strings/numbers.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_split.h"
28 #include "absl/strings/string_view.h"
29 #include "openssl/curve25519.h"
30 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
31 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
32 #include "quiche/quic/core/frames/quic_connection_close_frame.h"
33 #include "quiche/quic/core/http/http_frames.h"
34 #include "quiche/quic/core/http/quic_spdy_stream.h"
35 #include "quiche/quic/core/io/quic_event_loop.h"
36 #include "quiche/quic/core/quic_config.h"
37 #include "quiche/quic/core/quic_connection.h"
38 #include "quiche/quic/core/quic_constants.h"
39 #include "quiche/quic/core/quic_crypto_server_stream_base.h"
40 #include "quiche/quic/core/quic_data_reader.h"
41 #include "quiche/quic/core/quic_session.h"
42 #include "quiche/quic/core/quic_time.h"
43 #include "quiche/quic/core/quic_types.h"
44 #include "quiche/quic/core/quic_udp_socket.h"
45 #include "quiche/quic/core/quic_versions.h"
46 #include "quiche/quic/masque/masque_server_backend.h"
47 #include "quiche/quic/masque/masque_utils.h"
48 #include "quiche/quic/platform/api/quic_bug_tracker.h"
49 #include "quiche/quic/platform/api/quic_ip_address.h"
50 #include "quiche/quic/platform/api/quic_logging.h"
51 #include "quiche/quic/platform/api/quic_socket_address.h"
52 #include "quiche/quic/tools/quic_backend_response.h"
53 #include "quiche/quic/tools/quic_simple_server_backend.h"
54 #include "quiche/quic/tools/quic_simple_server_session.h"
55 #include "quiche/quic/tools/quic_url.h"
56 #include "quiche/common/capsule.h"
57 #include "quiche/common/platform/api/quiche_logging.h"
58 #include "quiche/common/platform/api/quiche_url_utils.h"
59 #include "quiche/common/quiche_ip_address.h"
60 #include "quiche/common/quiche_text_utils.h"
61 #include "quiche/spdy/core/http2_header_block.h"
62 
63 namespace quic {
64 
65 namespace {
66 
67 using ::quiche::AddressAssignCapsule;
68 using ::quiche::AddressRequestCapsule;
69 using ::quiche::Capsule;
70 using ::quiche::IpAddressRange;
71 using ::quiche::PrefixWithId;
72 using ::quiche::RouteAdvertisementCapsule;
73 
74 // RAII wrapper for QuicUdpSocketFd.
75 class FdWrapper {
76  public:
77   // Takes ownership of |fd| and closes the file descriptor on destruction.
FdWrapper(int address_family)78   explicit FdWrapper(int address_family) {
79     QuicUdpSocketApi socket_api;
80     fd_ =
81         socket_api.Create(address_family,
82                           /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
83                           /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
84   }
85 
~FdWrapper()86   ~FdWrapper() {
87     if (fd_ == kQuicInvalidSocketFd) {
88       return;
89     }
90     QuicUdpSocketApi socket_api;
91     socket_api.Destroy(fd_);
92   }
93 
94   // Hands ownership of the file descriptor to the caller.
extract_fd()95   QuicUdpSocketFd extract_fd() {
96     QuicUdpSocketFd fd = fd_;
97     fd_ = kQuicInvalidSocketFd;
98     return fd;
99   }
100 
101   // Keeps ownership of the file descriptor.
fd()102   QuicUdpSocketFd fd() { return fd_; }
103 
104   // Disallow copy and move.
105   FdWrapper(const FdWrapper&) = delete;
106   FdWrapper(FdWrapper&&) = delete;
107   FdWrapper& operator=(const FdWrapper&) = delete;
108   FdWrapper& operator=(FdWrapper&&) = delete;
109 
110  private:
111   QuicUdpSocketFd fd_;
112 };
113 
CreateBackendErrorResponse(absl::string_view status,absl::string_view error_details)114 std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse(
115     absl::string_view status, absl::string_view error_details) {
116   spdy::Http2HeaderBlock response_headers;
117   response_headers[":status"] = status;
118   response_headers["masque-debug-info"] = error_details;
119   auto response = std::make_unique<QuicBackendResponse>();
120   response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE);
121   response->set_headers(std::move(response_headers));
122   return response;
123 }
124 
125 }  // namespace
126 
MasqueServerSession(MasqueMode masque_mode,const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicConnection * connection,QuicSession::Visitor * visitor,QuicEventLoop * event_loop,QuicCryptoServerStreamBase::Helper * helper,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache,MasqueServerBackend * masque_server_backend)127 MasqueServerSession::MasqueServerSession(
128     MasqueMode masque_mode, const QuicConfig& config,
129     const ParsedQuicVersionVector& supported_versions,
130     QuicConnection* connection, QuicSession::Visitor* visitor,
131     QuicEventLoop* event_loop, QuicCryptoServerStreamBase::Helper* helper,
132     const QuicCryptoServerConfig* crypto_config,
133     QuicCompressedCertsCache* compressed_certs_cache,
134     MasqueServerBackend* masque_server_backend)
135     : QuicSimpleServerSession(config, supported_versions, connection, visitor,
136                               helper, crypto_config, compressed_certs_cache,
137                               masque_server_backend),
138       masque_server_backend_(masque_server_backend),
139       event_loop_(event_loop),
140       masque_mode_(masque_mode) {
141   // Artificially increase the max packet length to 1350 to ensure we can fit
142   // QUIC packets inside DATAGRAM frames.
143   // TODO(b/181606597) Remove this workaround once we use PMTUD.
144   connection->SetMaxPacketLength(kMasqueMaxOuterPacketSize);
145 
146   masque_server_backend_->RegisterBackendClient(connection_id(), this);
147   QUICHE_DCHECK_NE(event_loop_, nullptr);
148 
149   // We don't currently use `masque_mode_` but will in the future. To silence
150   // clang's `-Wunused-private-field` warning for this when building QUICHE for
151   // Chrome, add a use of it here.
152   (void)masque_mode_;
153 }
154 
OnMessageAcked(QuicMessageId message_id,QuicTime)155 void MasqueServerSession::OnMessageAcked(QuicMessageId message_id,
156                                          QuicTime /*receive_timestamp*/) {
157   QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id;
158 }
159 
OnMessageLost(QuicMessageId message_id)160 void MasqueServerSession::OnMessageLost(QuicMessageId message_id) {
161   QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost";
162 }
163 
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)164 void MasqueServerSession::OnConnectionClosed(
165     const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
166   QuicSimpleServerSession::OnConnectionClosed(frame, source);
167   QUIC_DLOG(INFO) << "Closing connection for " << connection_id();
168   masque_server_backend_->RemoveBackendClient(connection_id());
169   // Clearing this state will close all sockets.
170   connect_udp_server_states_.clear();
171 }
172 
OnStreamClosed(QuicStreamId stream_id)173 void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) {
174   connect_udp_server_states_.remove_if(
175       [stream_id](const ConnectUdpServerState& connect_udp) {
176         return connect_udp.stream()->id() == stream_id;
177       });
178   connect_ip_server_states_.remove_if(
179       [stream_id](const ConnectIpServerState& connect_ip) {
180         return connect_ip.stream()->id() == stream_id;
181       });
182   connect_ethernet_server_states_.remove_if(
183       [stream_id](const ConnectEthernetServerState& connect_ethernet) {
184         return connect_ethernet.stream()->id() == stream_id;
185       });
186 
187   QuicSimpleServerSession::OnStreamClosed(stream_id);
188 }
189 
190 std::unique_ptr<QuicBackendResponse>
MaybeCheckSignatureAuth(const spdy::Http2HeaderBlock & request_headers,absl::string_view authority,absl::string_view scheme,QuicSimpleServerBackend::RequestHandler * request_handler)191 MasqueServerSession::MaybeCheckSignatureAuth(
192     const spdy::Http2HeaderBlock& request_headers, absl::string_view authority,
193     absl::string_view scheme,
194     QuicSimpleServerBackend::RequestHandler* request_handler) {
195   // TODO(dschinazi) Add command-line flag that makes this implementation
196   // probe-resistant by returning the usual failure instead of 401.
197   constexpr absl::string_view kSignatureAuthStatus = "401";
198   if (!masque_server_backend_->IsSignatureAuthEnabled()) {
199     return nullptr;
200   }
201   auto authorization_pair = request_headers.find("authorization");
202   if (authorization_pair == request_headers.end()) {
203     return CreateBackendErrorResponse(kSignatureAuthStatus,
204                                       "Missing authorization header");
205   }
206   absl::string_view credentials = authorization_pair->second;
207   quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&credentials);
208   std::vector<absl::string_view> v =
209       absl::StrSplit(credentials, absl::MaxSplits(' ', 1));
210   if (v.size() != 2) {
211     return CreateBackendErrorResponse(kSignatureAuthStatus,
212                                       "Authorization header missing space");
213   }
214   absl::string_view auth_scheme = v[0];
215   if (auth_scheme != "Signature") {
216     return CreateBackendErrorResponse(kSignatureAuthStatus,
217                                       "Unexpected auth scheme");
218   }
219   absl::string_view auth_parameters = v[1];
220   std::vector<absl::string_view> auth_parameters_split =
221       absl::StrSplit(auth_parameters, ',');
222   std::optional<std::string> key_id;
223   std::optional<std::string> header_public_key;
224   std::optional<std::string> proof;
225   std::optional<uint16_t> signature_scheme;
226   std::optional<std::string> verification;
227   for (absl::string_view auth_parameter : auth_parameters_split) {
228     std::vector<absl::string_view> auth_parameter_split =
229         absl::StrSplit(auth_parameter, absl::MaxSplits('=', 1));
230     if (auth_parameter_split.size() != 2) {
231       continue;
232     }
233     absl::string_view param_name = auth_parameter_split[0];
234     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&param_name);
235     if (param_name.size() != 1) {
236       // All currently known authentication parameters are one character long.
237       continue;
238     }
239     absl::string_view param_value = auth_parameter_split[1];
240     quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&param_value);
241     std::string decoded_param;
242     switch (param_name[0]) {
243       case 'k': {
244         if (key_id.has_value()) {
245           return CreateBackendErrorResponse(kSignatureAuthStatus,
246                                             "Duplicate k");
247         }
248         if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) {
249           return CreateBackendErrorResponse(kSignatureAuthStatus,
250                                             "Failed to base64 decode k");
251         }
252         key_id = decoded_param;
253       } break;
254       case 'a': {
255         if (header_public_key.has_value()) {
256           return CreateBackendErrorResponse(kSignatureAuthStatus,
257                                             "Duplicate a");
258         }
259         if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) {
260           return CreateBackendErrorResponse(kSignatureAuthStatus,
261                                             "Failed to base64 decode a");
262         }
263         header_public_key = decoded_param;
264       } break;
265       case 'p': {
266         if (proof.has_value()) {
267           return CreateBackendErrorResponse(kSignatureAuthStatus,
268                                             "Duplicate p");
269         }
270         if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) {
271           return CreateBackendErrorResponse(kSignatureAuthStatus,
272                                             "Failed to base64 decode p");
273         }
274         proof = decoded_param;
275       } break;
276       case 's': {
277         if (signature_scheme.has_value()) {
278           return CreateBackendErrorResponse(kSignatureAuthStatus,
279                                             "Duplicate s");
280         }
281         int signature_scheme_int = 0;
282         if (!absl::SimpleAtoi(param_value, &signature_scheme_int) ||
283             signature_scheme_int < 0 ||
284             signature_scheme_int > std::numeric_limits<uint16_t>::max()) {
285           return CreateBackendErrorResponse(kSignatureAuthStatus,
286                                             "Failed to parse s");
287         }
288         signature_scheme = static_cast<uint16_t>(signature_scheme_int);
289       } break;
290       case 'v': {
291         if (verification.has_value()) {
292           return CreateBackendErrorResponse(kSignatureAuthStatus,
293                                             "Duplicate v");
294         }
295         if (!absl::WebSafeBase64Unescape(param_value, &decoded_param)) {
296           return CreateBackendErrorResponse(kSignatureAuthStatus,
297                                             "Failed to base64 decode v");
298         }
299         verification = decoded_param;
300       } break;
301     }
302   }
303   if (!key_id.has_value()) {
304     return CreateBackendErrorResponse(kSignatureAuthStatus,
305                                       "Missing k auth parameter");
306   }
307   if (!header_public_key.has_value()) {
308     return CreateBackendErrorResponse(kSignatureAuthStatus,
309                                       "Missing a auth parameter");
310   }
311   if (!proof.has_value()) {
312     return CreateBackendErrorResponse(kSignatureAuthStatus,
313                                       "Missing p auth parameter");
314   }
315   if (!signature_scheme.has_value()) {
316     return CreateBackendErrorResponse(kSignatureAuthStatus,
317                                       "Missing s auth parameter");
318   }
319   if (!verification.has_value()) {
320     return CreateBackendErrorResponse(kSignatureAuthStatus,
321                                       "Missing v auth parameter");
322   }
323   uint8_t config_public_key[ED25519_PUBLIC_KEY_LEN];
324   if (!masque_server_backend_->GetSignatureAuthKeyForId(*key_id,
325                                                         config_public_key)) {
326     return CreateBackendErrorResponse(kSignatureAuthStatus,
327                                       "Unexpected key id");
328   }
329   if (*header_public_key !=
330       std::string(reinterpret_cast<const char*>(config_public_key),
331                   sizeof(config_public_key))) {
332     return CreateBackendErrorResponse(kSignatureAuthStatus,
333                                       "Unexpected public key in header");
334   }
335   std::string realm = "";
336   QuicUrl url(absl::StrCat(scheme, "://", authority, "/"));
337   std::optional<std::string> key_exporter_context = ComputeSignatureAuthContext(
338       kEd25519SignatureScheme, *key_id, *header_public_key, scheme, url.host(),
339       url.port(), realm);
340   if (!key_exporter_context.has_value()) {
341     return CreateBackendErrorResponse(
342         "500", "Failed to generate key exporter context");
343   }
344   QUIC_DVLOG(1) << "key_exporter_context: "
345                 << absl::WebSafeBase64Escape(*key_exporter_context);
346   QUICHE_DCHECK(!key_exporter_context->empty());
347   std::string key_exporter_output;
348   if (!GetMutableCryptoStream()->ExportKeyingMaterial(
349           kSignatureAuthLabel, *key_exporter_context,
350           kSignatureAuthExporterSize, &key_exporter_output)) {
351     return CreateBackendErrorResponse("500", "Key exporter failed");
352   }
353   QUICHE_CHECK_EQ(key_exporter_output.size(), kSignatureAuthExporterSize);
354   std::string signature_input =
355       key_exporter_output.substr(0, kSignatureAuthSignatureInputSize);
356   QUIC_DVLOG(1) << "signature_input: "
357                 << absl::WebSafeBase64Escape(signature_input);
358   std::string expected_verification = key_exporter_output.substr(
359       kSignatureAuthSignatureInputSize, kSignatureAuthVerificationSize);
360   if (verification != expected_verification) {
361     return CreateBackendErrorResponse(
362         kSignatureAuthStatus,
363         absl::StrCat("Unexpected verification, expected ",
364                      absl::WebSafeBase64Escape(expected_verification),
365                      " but got ", absl::WebSafeBase64Escape(*verification),
366                      " - key exporter context was ",
367                      absl::WebSafeBase64Escape(*key_exporter_context)));
368   }
369   std::string data_covered_by_signature =
370       SignatureAuthDataCoveredBySignature(signature_input);
371   QUIC_DVLOG(1) << "data_covered_by_signature: "
372                 << absl::WebSafeBase64Escape(data_covered_by_signature);
373   if (*signature_scheme != kEd25519SignatureScheme) {
374     return CreateBackendErrorResponse(kSignatureAuthStatus,
375                                       "Unexpected signature scheme");
376   }
377   if (proof->size() != ED25519_SIGNATURE_LEN) {
378     return CreateBackendErrorResponse(kSignatureAuthStatus,
379                                       "Unexpected proof length");
380   }
381   if (ED25519_verify(
382           reinterpret_cast<const uint8_t*>(data_covered_by_signature.data()),
383           data_covered_by_signature.size(),
384           reinterpret_cast<const uint8_t*>(proof->data()),
385           config_public_key) != 1) {
386     return CreateBackendErrorResponse(kSignatureAuthStatus,
387                                       "Signature failed to validate");
388   }
389   QUIC_LOG(INFO) << "Successfully validated signature auth for stream ID "
390                  << request_handler->stream_id();
391   return nullptr;
392 }
393 
HandleMasqueRequest(const spdy::Http2HeaderBlock & request_headers,QuicSimpleServerBackend::RequestHandler * request_handler)394 std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
395     const spdy::Http2HeaderBlock& request_headers,
396     QuicSimpleServerBackend::RequestHandler* request_handler) {
397   // Authority.
398   auto authority_pair = request_headers.find(":authority");
399   if (authority_pair == request_headers.end()) {
400     QUIC_DLOG(ERROR) << "MASQUE request is missing :authority";
401     return CreateBackendErrorResponse("400", "Missing :authority");
402   }
403   absl::string_view authority = authority_pair->second;
404   // Scheme.
405   auto scheme_pair = request_headers.find(":scheme");
406   if (scheme_pair == request_headers.end()) {
407     QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme";
408     return CreateBackendErrorResponse("400", "Missing :scheme");
409   }
410   absl::string_view scheme = scheme_pair->second;
411   if (scheme.empty()) {
412     return CreateBackendErrorResponse("400", "Empty scheme");
413   }
414   // Signature authentication.
415   auto signature_auth_reply = MaybeCheckSignatureAuth(
416       request_headers, authority, scheme, request_handler);
417   if (signature_auth_reply) {
418     return signature_auth_reply;
419   }
420   // Path.
421   auto path_pair = request_headers.find(":path");
422   if (path_pair == request_headers.end()) {
423     QUIC_DLOG(ERROR) << "MASQUE request is missing :path";
424     return CreateBackendErrorResponse("400", "Missing :path");
425   }
426   absl::string_view path = path_pair->second;
427   if (path.empty()) {
428     QUIC_DLOG(ERROR) << "MASQUE request with empty path";
429     return CreateBackendErrorResponse("400", "Empty path");
430   }
431   // Method.
432   auto method_pair = request_headers.find(":method");
433   if (method_pair == request_headers.end()) {
434     QUIC_DLOG(ERROR) << "MASQUE request is missing :method";
435     return CreateBackendErrorResponse("400", "Missing :method");
436   }
437   absl::string_view method = method_pair->second;
438   if (method != "CONNECT") {
439     QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\"";
440     if (masque_server_backend_->IsSignatureAuthOnAllRequests()) {
441       return nullptr;
442     } else {
443       return CreateBackendErrorResponse("400", "Bad method");
444     }
445   }
446   // Protocol.
447   auto protocol_pair = request_headers.find(":protocol");
448   if (protocol_pair == request_headers.end()) {
449     QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol";
450     if (masque_server_backend_->IsSignatureAuthOnAllRequests()) {
451       return nullptr;
452     } else {
453       return CreateBackendErrorResponse("400", "Missing :protocol");
454     }
455   }
456   absl::string_view protocol = protocol_pair->second;
457   if (protocol != "connect-udp" && protocol != "connect-ip" &&
458       protocol != "connect-ethernet") {
459     QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol
460                      << "\"";
461     if (masque_server_backend_->IsSignatureAuthOnAllRequests()) {
462       return nullptr;
463     } else {
464       return CreateBackendErrorResponse("400", "Bad protocol");
465     }
466   }
467 
468   if (protocol == "connect-ip") {
469     QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(
470         GetActiveStream(request_handler->stream_id()));
471     if (stream == nullptr) {
472       QUIC_BUG(bad masque server stream type)
473           << "Unexpected stream type for stream ID "
474           << request_handler->stream_id();
475       return CreateBackendErrorResponse("500", "Bad stream type");
476     }
477     QuicIpAddress client_ip = masque_server_backend_->GetNextClientIpAddress();
478     QUIC_DLOG(INFO) << "Using client IP " << client_ip.ToString()
479                     << " for CONNECT-IP stream ID "
480                     << request_handler->stream_id();
481     int fd = CreateTunInterface(client_ip);
482     if (fd < 0) {
483       QUIC_LOG(ERROR) << "Failed to create TUN interface for stream ID "
484                       << request_handler->stream_id();
485       return CreateBackendErrorResponse("500",
486                                         "Failed to create TUN interface");
487     }
488     if (!event_loop_->RegisterSocket(fd, kSocketEventReadable, this)) {
489       QUIC_DLOG(ERROR) << "Failed to register TUN fd with the event loop";
490       close(fd);
491       return CreateBackendErrorResponse("500", "Registering TUN socket failed");
492     }
493     connect_ip_server_states_.push_back(
494         ConnectIpServerState(client_ip, stream, fd, this));
495 
496     spdy::Http2HeaderBlock response_headers;
497     response_headers[":status"] = "200";
498     auto response = std::make_unique<QuicBackendResponse>();
499     response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
500     response->set_headers(std::move(response_headers));
501     response->set_body("");
502 
503     return response;
504   }
505   if (protocol == "connect-ethernet") {
506     QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(
507         GetActiveStream(request_handler->stream_id()));
508     if (stream == nullptr) {
509       QUIC_BUG(bad masque server stream type)
510           << "Unexpected stream type for stream ID "
511           << request_handler->stream_id();
512       return CreateBackendErrorResponse("500", "Bad stream type");
513     }
514     int fd = CreateTapInterface();
515     if (fd < 0) {
516       QUIC_LOG(ERROR) << "Failed to create TAP interface for stream ID "
517                       << request_handler->stream_id();
518       return CreateBackendErrorResponse("500",
519                                         "Failed to create TAP interface");
520     }
521     if (!event_loop_->RegisterSocket(fd, kSocketEventReadable, this)) {
522       QUIC_DLOG(ERROR) << "Failed to register TAP fd with the event loop";
523       close(fd);
524       return CreateBackendErrorResponse("500", "Registering TAP socket failed");
525     }
526     connect_ethernet_server_states_.push_back(
527         ConnectEthernetServerState(stream, fd, this));
528 
529     spdy::Http2HeaderBlock response_headers;
530     response_headers[":status"] = "200";
531     auto response = std::make_unique<QuicBackendResponse>();
532     response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
533     response->set_headers(std::move(response_headers));
534     response->set_body("");
535 
536     return response;
537   }
538   // Extract target host and port from path using default template.
539   std::vector<absl::string_view> path_split = absl::StrSplit(path, '/');
540   if (path_split.size() != 7 || !path_split[0].empty() ||
541       path_split[1] != ".well-known" || path_split[2] != "masque" ||
542       path_split[3] != "udp" || path_split[4].empty() ||
543       path_split[5].empty() || !path_split[6].empty()) {
544     QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\"";
545     return CreateBackendErrorResponse("400", "Bad path");
546   }
547   std::optional<std::string> host = quiche::AsciiUrlDecode(path_split[4]);
548   if (!host.has_value()) {
549     QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[4] << "\"";
550     return CreateBackendErrorResponse("500", "Failed to decode host");
551   }
552   std::optional<std::string> port = quiche::AsciiUrlDecode(path_split[5]);
553   if (!port.has_value()) {
554     QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[5] << "\"";
555     return CreateBackendErrorResponse("500", "Failed to decode port");
556   }
557 
558   // Perform DNS resolution.
559   addrinfo hint = {};
560   hint.ai_protocol = IPPROTO_UDP;
561 
562   addrinfo* info_list = nullptr;
563   int result = getaddrinfo(host->c_str(), port->c_str(), &hint, &info_list);
564   if (result != 0 || info_list == nullptr) {
565     QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": "
566                      << gai_strerror(result);
567     return CreateBackendErrorResponse("500", "DNS resolution failed");
568   }
569 
570   std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list,
571                                                                  freeaddrinfo);
572   QuicSocketAddress target_server_address(info_list->ai_addr,
573                                           info_list->ai_addrlen);
574   QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID "
575                   << request_handler->stream_id() << " target_server_address=\""
576                   << target_server_address << "\"";
577 
578   FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt());
579   if (fd_wrapper.fd() == kQuicInvalidSocketFd) {
580     QUIC_DLOG(ERROR) << "Socket creation failed";
581     return CreateBackendErrorResponse("500", "Socket creation failed");
582   }
583   QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0);
584   if (target_server_address.host().IsIPv4()) {
585     empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0);
586   }
587   QuicUdpSocketApi socket_api;
588   if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) {
589     QUIC_DLOG(ERROR) << "Socket bind failed";
590     return CreateBackendErrorResponse("500", "Socket bind failed");
591   }
592   if (!event_loop_->RegisterSocket(fd_wrapper.fd(), kSocketEventReadable,
593                                    this)) {
594     QUIC_DLOG(ERROR) << "Failed to register socket with the event loop";
595     return CreateBackendErrorResponse("500", "Registering socket failed");
596   }
597 
598   QuicSpdyStream* stream =
599       static_cast<QuicSpdyStream*>(GetActiveStream(request_handler->stream_id()));
600   if (stream == nullptr) {
601     QUIC_BUG(bad masque server stream type)
602         << "Unexpected stream type for stream ID "
603         << request_handler->stream_id();
604     return CreateBackendErrorResponse("500", "Bad stream type");
605   }
606   connect_udp_server_states_.push_back(ConnectUdpServerState(
607       stream, target_server_address, fd_wrapper.extract_fd(), this));
608 
609   spdy::Http2HeaderBlock response_headers;
610   response_headers[":status"] = "200";
611   auto response = std::make_unique<QuicBackendResponse>();
612   response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
613   response->set_headers(std::move(response_headers));
614   response->set_body("");
615 
616   return response;
617 }
618 
OnSocketEvent(QuicEventLoop *,QuicUdpSocketFd fd,QuicSocketEventMask events)619 void MasqueServerSession::OnSocketEvent(QuicEventLoop* /*event_loop*/,
620                                         QuicUdpSocketFd fd,
621                                         QuicSocketEventMask events) {
622   if ((events & kSocketEventReadable) == 0) {
623     QUIC_DVLOG(1) << "Ignoring OnEvent fd " << fd << " event mask " << events;
624     return;
625   }
626 
627   auto rearm = absl::MakeCleanup([&]() {
628     if (!event_loop_->SupportsEdgeTriggered()) {
629       if (!event_loop_->RearmSocket(fd, kSocketEventReadable)) {
630         QUIC_BUG(MasqueServerSession_OnSocketEvent_Rearm)
631             << "Failed to re-arm socket " << fd << " for reading";
632       }
633     }
634   });
635 
636   if (!(HandleConnectUdpSocketEvent(fd, events) ||
637         HandleConnectIpSocketEvent(fd, events) ||
638         HandleConnectEthernetSocketEvent(fd, events))) {
639     QUIC_BUG(MasqueServerSession_OnSocketEvent_UnhandledEvent)
640         << "Got unexpected event mask " << events << " on unknown fd " << fd;
641     std::move(rearm).Cancel();
642   }
643 }
644 
HandleConnectUdpSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)645 bool MasqueServerSession::HandleConnectUdpSocketEvent(
646     QuicUdpSocketFd fd, QuicSocketEventMask events) {
647   auto it = absl::c_find_if(connect_udp_server_states_,
648                             [fd](const ConnectUdpServerState& connect_udp) {
649                               return connect_udp.fd() == fd;
650                             });
651   if (it == connect_udp_server_states_.end()) {
652     return false;
653   }
654   QuicSocketAddress expected_target_server_address =
655       it->target_server_address();
656   QUICHE_DCHECK(expected_target_server_address.IsInitialized());
657   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
658                 << ") stream ID " << it->stream()->id() << " server "
659                 << expected_target_server_address;
660   QuicUdpSocketApi socket_api;
661   QuicUdpPacketInfoBitMask packet_info_interested(
662       {QuicUdpPacketInfoBit::PEER_ADDRESS});
663   char packet_buffer[1 + kMaxIncomingPacketSize];
664   packet_buffer[0] = 0;  // context ID.
665   char control_buffer[kDefaultUdpPacketControlBufferSize];
666   while (true) {
667     QuicUdpSocketApi::ReadPacketResult read_result;
668     read_result.packet_buffer = {packet_buffer + 1, sizeof(packet_buffer) - 1};
669     read_result.control_buffer = {control_buffer, sizeof(control_buffer)};
670     socket_api.ReadPacket(fd, packet_info_interested, &read_result);
671     if (!read_result.ok) {
672       // Most likely there is nothing left to read, break out of read loop.
673       break;
674     }
675     if (!read_result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
676       QUIC_BUG(MasqueServerSession_HandleConnectUdpSocketEvent_MissingPeer)
677           << "Missing peer address when reading from fd " << fd;
678       continue;
679     }
680     if (read_result.packet_info.peer_address() !=
681         expected_target_server_address) {
682       QUIC_DLOG(ERROR) << "Ignoring UDP packet on fd " << fd
683                        << " from unexpected server address "
684                        << read_result.packet_info.peer_address()
685                        << " (expected " << expected_target_server_address
686                        << ")";
687       continue;
688     }
689     if (!connection()->connected()) {
690       QUIC_BUG(MasqueServerSession_HandleConnectUdpSocketEvent_ConnectionClosed)
691           << "Unexpected incoming UDP packet on fd " << fd << " from "
692           << expected_target_server_address
693           << " because MASQUE connection is closed";
694       return true;
695     }
696     // The packet is valid, send it to the client in a DATAGRAM frame.
697     MessageStatus message_status =
698         it->stream()->SendHttp3Datagram(absl::string_view(
699             packet_buffer, read_result.packet_buffer.buffer_len + 1));
700     QUIC_DVLOG(1) << "Sent UDP packet from " << expected_target_server_address
701                   << " of length " << read_result.packet_buffer.buffer_len
702                   << " with stream ID " << it->stream()->id()
703                   << " and got message status "
704                   << MessageStatusToString(message_status);
705   }
706   return true;
707 }
708 
HandleConnectIpSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)709 bool MasqueServerSession::HandleConnectIpSocketEvent(
710     QuicUdpSocketFd fd, QuicSocketEventMask events) {
711   auto it = absl::c_find_if(connect_ip_server_states_,
712                             [fd](const ConnectIpServerState& connect_ip) {
713                               return connect_ip.fd() == fd;
714                             });
715   if (it == connect_ip_server_states_.end()) {
716     return false;
717   }
718   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
719                 << ") stream ID " << it->stream()->id();
720   char datagram[kMasqueIpPacketBufferSize];
721   datagram[0] = 0;  // Context ID.
722   while (true) {
723     ssize_t read_size = read(fd, datagram + 1, sizeof(datagram) - 1);
724     if (read_size < 0) {
725       break;
726     }
727     MessageStatus message_status = it->stream()->SendHttp3Datagram(
728         absl::string_view(datagram, 1 + read_size));
729     QUIC_DVLOG(1) << "Encapsulated IP packet of length " << read_size
730                   << " with stream ID " << it->stream()->id()
731                   << " and got message status "
732                   << MessageStatusToString(message_status);
733   }
734   return true;
735 }
736 
HandleConnectEthernetSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)737 bool MasqueServerSession::HandleConnectEthernetSocketEvent(
738     QuicUdpSocketFd fd, QuicSocketEventMask events) {
739   auto it =
740       absl::c_find_if(connect_ethernet_server_states_,
741                       [fd](const ConnectEthernetServerState& connect_ethernet) {
742                         return connect_ethernet.fd() == fd;
743                       });
744   if (it == connect_ethernet_server_states_.end()) {
745     return false;
746   }
747   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
748                 << ") stream ID " << it->stream()->id();
749   char datagram[kMasqueEthernetFrameBufferSize];
750   datagram[0] = 0;  // Context ID.
751   while (true) {
752     ssize_t read_size = read(fd, datagram + 1, sizeof(datagram) - 1);
753     if (read_size < 0) {
754       break;
755     }
756     MessageStatus message_status = it->stream()->SendHttp3Datagram(
757         absl::string_view(datagram, 1 + read_size));
758     QUIC_DVLOG(1) << "Encapsulated Ethernet frame of length " << read_size
759                   << " with stream ID " << it->stream()->id()
760                   << " and got message status "
761                   << MessageStatusToString(message_status);
762   }
763   return true;
764 }
765 
OnSettingsFrame(const SettingsFrame & frame)766 bool MasqueServerSession::OnSettingsFrame(const SettingsFrame& frame) {
767   QUIC_DLOG(INFO) << "Received SETTINGS: " << frame;
768   if (!QuicSimpleServerSession::OnSettingsFrame(frame)) {
769     return false;
770   }
771   if (!SupportsH3Datagram()) {
772     QUIC_DLOG(ERROR) << "Refusing to use MASQUE without HTTP Datagrams";
773     return false;
774   }
775   QUIC_DLOG(INFO) << "Using HTTP Datagram: " << http_datagram_support();
776   return true;
777 }
778 
ConnectUdpServerState(QuicSpdyStream * stream,const QuicSocketAddress & target_server_address,QuicUdpSocketFd fd,MasqueServerSession * masque_session)779 MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
780     QuicSpdyStream* stream, const QuicSocketAddress& target_server_address,
781     QuicUdpSocketFd fd, MasqueServerSession* masque_session)
782     : stream_(stream),
783       target_server_address_(target_server_address),
784       fd_(fd),
785       masque_session_(masque_session) {
786   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
787   QUICHE_DCHECK_NE(masque_session_, nullptr);
788   this->stream()->RegisterHttp3DatagramVisitor(this);
789 }
790 
~ConnectUdpServerState()791 MasqueServerSession::ConnectUdpServerState::~ConnectUdpServerState() {
792   if (stream() != nullptr) {
793     stream()->UnregisterHttp3DatagramVisitor();
794   }
795   if (fd_ == kQuicInvalidSocketFd) {
796     return;
797   }
798   QuicUdpSocketApi socket_api;
799   QUIC_DLOG(INFO) << "Closing fd " << fd_;
800   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
801     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
802   }
803   socket_api.Destroy(fd_);
804 }
805 
ConnectUdpServerState(MasqueServerSession::ConnectUdpServerState && other)806 MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
807     MasqueServerSession::ConnectUdpServerState&& other) {
808   fd_ = kQuicInvalidSocketFd;
809   *this = std::move(other);
810 }
811 
812 MasqueServerSession::ConnectUdpServerState&
operator =(MasqueServerSession::ConnectUdpServerState && other)813 MasqueServerSession::ConnectUdpServerState::operator=(
814     MasqueServerSession::ConnectUdpServerState&& other) {
815   if (fd_ != kQuicInvalidSocketFd) {
816     QuicUdpSocketApi socket_api;
817     QUIC_DLOG(INFO) << "Closing fd " << fd_;
818     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
819       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
820     }
821     socket_api.Destroy(fd_);
822   }
823   stream_ = other.stream_;
824   other.stream_ = nullptr;
825   target_server_address_ = other.target_server_address_;
826   fd_ = other.fd_;
827   masque_session_ = other.masque_session_;
828   other.fd_ = kQuicInvalidSocketFd;
829   if (stream() != nullptr) {
830     stream()->ReplaceHttp3DatagramVisitor(this);
831   }
832   return *this;
833 }
834 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)835 void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram(
836     QuicStreamId stream_id, absl::string_view payload) {
837   QUICHE_DCHECK_EQ(stream_id, stream()->id());
838   QuicDataReader reader(payload);
839   uint64_t context_id;
840   if (!reader.ReadVarInt62(&context_id)) {
841     QUIC_DLOG(ERROR) << "Failed to read context ID";
842     return;
843   }
844   if (context_id != 0) {
845     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
846                      << context_id;
847     return;
848   }
849   absl::string_view http_payload = reader.ReadRemainingPayload();
850   QuicUdpSocketApi socket_api;
851   QuicUdpPacketInfo packet_info;
852   packet_info.SetPeerAddress(target_server_address_);
853   WriteResult write_result = socket_api.WritePacket(
854       fd_, http_payload.data(), http_payload.length(), packet_info);
855   QUIC_DVLOG(1) << "Wrote packet of length " << http_payload.length() << " to "
856                 << target_server_address_ << " with result " << write_result;
857 }
858 
ConnectIpServerState(QuicIpAddress client_ip,QuicSpdyStream * stream,QuicUdpSocketFd fd,MasqueServerSession * masque_session)859 MasqueServerSession::ConnectIpServerState::ConnectIpServerState(
860     QuicIpAddress client_ip, QuicSpdyStream* stream, QuicUdpSocketFd fd,
861     MasqueServerSession* masque_session)
862     : client_ip_(client_ip),
863       stream_(stream),
864       fd_(fd),
865       masque_session_(masque_session) {
866   QUICHE_DCHECK(client_ip_.IsIPv4());
867   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
868   QUICHE_DCHECK_NE(masque_session_, nullptr);
869   this->stream()->RegisterHttp3DatagramVisitor(this);
870   this->stream()->RegisterConnectIpVisitor(this);
871 }
872 
~ConnectIpServerState()873 MasqueServerSession::ConnectIpServerState::~ConnectIpServerState() {
874   if (stream() != nullptr) {
875     stream()->UnregisterHttp3DatagramVisitor();
876     stream()->UnregisterConnectIpVisitor();
877   }
878   if (fd_ == kQuicInvalidSocketFd) {
879     return;
880   }
881   QuicUdpSocketApi socket_api;
882   QUIC_DLOG(INFO) << "Closing fd " << fd_;
883   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
884     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
885   }
886   socket_api.Destroy(fd_);
887 }
888 
ConnectIpServerState(MasqueServerSession::ConnectIpServerState && other)889 MasqueServerSession::ConnectIpServerState::ConnectIpServerState(
890     MasqueServerSession::ConnectIpServerState&& other) {
891   fd_ = kQuicInvalidSocketFd;
892   *this = std::move(other);
893 }
894 
895 MasqueServerSession::ConnectIpServerState&
operator =(MasqueServerSession::ConnectIpServerState && other)896 MasqueServerSession::ConnectIpServerState::operator=(
897     MasqueServerSession::ConnectIpServerState&& other) {
898   if (fd_ != kQuicInvalidSocketFd) {
899     QuicUdpSocketApi socket_api;
900     QUIC_DLOG(INFO) << "Closing fd " << fd_;
901     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
902       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
903     }
904     socket_api.Destroy(fd_);
905   }
906   client_ip_ = other.client_ip_;
907   stream_ = other.stream_;
908   other.stream_ = nullptr;
909   fd_ = other.fd_;
910   masque_session_ = other.masque_session_;
911   other.fd_ = kQuicInvalidSocketFd;
912   if (stream() != nullptr) {
913     stream()->ReplaceHttp3DatagramVisitor(this);
914     stream()->ReplaceConnectIpVisitor(this);
915   }
916   return *this;
917 }
918 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)919 void MasqueServerSession::ConnectIpServerState::OnHttp3Datagram(
920     QuicStreamId stream_id, absl::string_view payload) {
921   QUICHE_DCHECK_EQ(stream_id, stream()->id());
922   QuicDataReader reader(payload);
923   uint64_t context_id;
924   if (!reader.ReadVarInt62(&context_id)) {
925     QUIC_DLOG(ERROR) << "Failed to read context ID";
926     return;
927   }
928   if (context_id != 0) {
929     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
930                      << context_id;
931     return;
932   }
933   absl::string_view ip_packet = reader.ReadRemainingPayload();
934   ssize_t written = write(fd(), ip_packet.data(), ip_packet.size());
935   if (written != static_cast<ssize_t>(ip_packet.size())) {
936     QUIC_DLOG(ERROR) << "Failed to write CONNECT-IP packet of length "
937                      << ip_packet.size();
938   } else {
939     QUIC_DLOG(INFO) << "Decapsulated CONNECT-IP packet of length "
940                     << ip_packet.size();
941   }
942 }
943 
OnAddressAssignCapsule(const AddressAssignCapsule & capsule)944 bool MasqueServerSession::ConnectIpServerState::OnAddressAssignCapsule(
945     const AddressAssignCapsule& capsule) {
946   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
947   return true;
948 }
949 
OnAddressRequestCapsule(const AddressRequestCapsule & capsule)950 bool MasqueServerSession::ConnectIpServerState::OnAddressRequestCapsule(
951     const AddressRequestCapsule& capsule) {
952   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
953   return true;
954 }
955 
OnRouteAdvertisementCapsule(const RouteAdvertisementCapsule & capsule)956 bool MasqueServerSession::ConnectIpServerState::OnRouteAdvertisementCapsule(
957     const RouteAdvertisementCapsule& capsule) {
958   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
959   return true;
960 }
961 
OnHeadersWritten()962 void MasqueServerSession::ConnectIpServerState::OnHeadersWritten() {
963   QUICHE_DCHECK(client_ip_.IsIPv4()) << client_ip_.ToString();
964   Capsule address_assign_capsule = Capsule::AddressAssign();
965   PrefixWithId assigned_address;
966   assigned_address.ip_prefix = quiche::QuicheIpPrefix(client_ip_, 32);
967   assigned_address.request_id = 0;
968   address_assign_capsule.address_assign_capsule().assigned_addresses.push_back(
969       assigned_address);
970   stream()->WriteCapsule(address_assign_capsule);
971   IpAddressRange default_route;
972   default_route.start_ip_address.FromString("0.0.0.0");
973   default_route.end_ip_address.FromString("255.255.255.255");
974   default_route.ip_protocol = 0;
975   Capsule route_advertisement = Capsule::RouteAdvertisement();
976   route_advertisement.route_advertisement_capsule().ip_address_ranges.push_back(
977       default_route);
978   stream()->WriteCapsule(route_advertisement);
979 }
980 
981 // Connect Ethernet
ConnectEthernetServerState(QuicSpdyStream * stream,QuicUdpSocketFd fd,MasqueServerSession * masque_session)982 MasqueServerSession::ConnectEthernetServerState::ConnectEthernetServerState(
983     QuicSpdyStream* stream, QuicUdpSocketFd fd,
984     MasqueServerSession* masque_session)
985     : stream_(stream), fd_(fd), masque_session_(masque_session) {
986   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
987   QUICHE_DCHECK_NE(masque_session_, nullptr);
988   this->stream()->RegisterHttp3DatagramVisitor(this);
989 }
990 
~ConnectEthernetServerState()991 MasqueServerSession::ConnectEthernetServerState::~ConnectEthernetServerState() {
992   if (stream() != nullptr) {
993     stream()->UnregisterHttp3DatagramVisitor();
994   }
995   if (fd_ == kQuicInvalidSocketFd) {
996     return;
997   }
998   QuicUdpSocketApi socket_api;
999   QUIC_DLOG(INFO) << "Closing fd " << fd_;
1000   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
1001     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
1002   }
1003   socket_api.Destroy(fd_);
1004 }
1005 
ConnectEthernetServerState(MasqueServerSession::ConnectEthernetServerState && other)1006 MasqueServerSession::ConnectEthernetServerState::ConnectEthernetServerState(
1007     MasqueServerSession::ConnectEthernetServerState&& other) {
1008   fd_ = kQuicInvalidSocketFd;
1009   *this = std::move(other);
1010 }
1011 
1012 MasqueServerSession::ConnectEthernetServerState&
operator =(MasqueServerSession::ConnectEthernetServerState && other)1013 MasqueServerSession::ConnectEthernetServerState::operator=(
1014     MasqueServerSession::ConnectEthernetServerState&& other) {
1015   if (fd_ != kQuicInvalidSocketFd) {
1016     QuicUdpSocketApi socket_api;
1017     QUIC_DLOG(INFO) << "Closing fd " << fd_;
1018     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
1019       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
1020     }
1021     socket_api.Destroy(fd_);
1022   }
1023   stream_ = other.stream_;
1024   other.stream_ = nullptr;
1025   fd_ = other.fd_;
1026   masque_session_ = other.masque_session_;
1027   other.fd_ = kQuicInvalidSocketFd;
1028   if (stream() != nullptr) {
1029     stream()->ReplaceHttp3DatagramVisitor(this);
1030   }
1031   return *this;
1032 }
1033 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)1034 void MasqueServerSession::ConnectEthernetServerState::OnHttp3Datagram(
1035     QuicStreamId stream_id, absl::string_view payload) {
1036   QUICHE_DCHECK_EQ(stream_id, stream()->id());
1037   QuicDataReader reader(payload);
1038   uint64_t context_id;
1039   if (!reader.ReadVarInt62(&context_id)) {
1040     QUIC_DLOG(ERROR) << "Failed to read context ID";
1041     return;
1042   }
1043   if (context_id != 0) {
1044     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
1045                      << context_id;
1046     return;
1047   }
1048   absl::string_view ethernet_frame = reader.ReadRemainingPayload();
1049   ssize_t written = write(fd(), ethernet_frame.data(), ethernet_frame.size());
1050   if (written != static_cast<ssize_t>(ethernet_frame.size())) {
1051     QUIC_DLOG(ERROR) << "Failed to write CONNECT-ETHERNET packet of length "
1052                      << ethernet_frame.size();
1053   } else {
1054     QUIC_DLOG(INFO) << "Decapsulated CONNECT-ETHERNET packet of length "
1055                     << ethernet_frame.size();
1056   }
1057 }
1058 
1059 }  // namespace quic
1060