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(¶m_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(¶m_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