• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstddef>
14 #include <cstdint>
15 #include <limits>
16 #include <optional>
17 
18 
19 #include "absl/cleanup/cleanup.h"
20 #include "absl/strings/str_cat.h"
21 #include "absl/strings/str_split.h"
22 #include "absl/strings/string_view.h"
23 #include "quiche/quic/core/http/spdy_utils.h"
24 #include "quiche/quic/core/io/quic_event_loop.h"
25 #include "quiche/quic/core/quic_data_reader.h"
26 #include "quiche/quic/core/quic_udp_socket.h"
27 #include "quiche/quic/masque/masque_utils.h"
28 #include "quiche/quic/platform/api/quic_ip_address.h"
29 #include "quiche/quic/tools/quic_url.h"
30 #include "quiche/common/capsule.h"
31 #include "quiche/common/platform/api/quiche_url_utils.h"
32 #include "quiche/common/quiche_ip_address.h"
33 
34 namespace quic {
35 
36 namespace {
37 
38 using ::quiche::AddressAssignCapsule;
39 using ::quiche::AddressRequestCapsule;
40 using ::quiche::Capsule;
41 using ::quiche::IpAddressRange;
42 using ::quiche::PrefixWithId;
43 using ::quiche::RouteAdvertisementCapsule;
44 
45 // RAII wrapper for QuicUdpSocketFd.
46 class FdWrapper {
47  public:
48   // Takes ownership of |fd| and closes the file descriptor on destruction.
FdWrapper(int address_family)49   explicit FdWrapper(int address_family) {
50     QuicUdpSocketApi socket_api;
51     fd_ =
52         socket_api.Create(address_family,
53                           /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
54                           /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
55   }
56 
~FdWrapper()57   ~FdWrapper() {
58     if (fd_ == kQuicInvalidSocketFd) {
59       return;
60     }
61     QuicUdpSocketApi socket_api;
62     socket_api.Destroy(fd_);
63   }
64 
65   // Hands ownership of the file descriptor to the caller.
extract_fd()66   QuicUdpSocketFd extract_fd() {
67     QuicUdpSocketFd fd = fd_;
68     fd_ = kQuicInvalidSocketFd;
69     return fd;
70   }
71 
72   // Keeps ownership of the file descriptor.
fd()73   QuicUdpSocketFd fd() { return fd_; }
74 
75   // Disallow copy and move.
76   FdWrapper(const FdWrapper&) = delete;
77   FdWrapper(FdWrapper&&) = delete;
78   FdWrapper& operator=(const FdWrapper&) = delete;
79   FdWrapper& operator=(FdWrapper&&) = delete;
80 
81  private:
82   QuicUdpSocketFd fd_;
83 };
84 
CreateBackendErrorResponse(absl::string_view status,absl::string_view error_details)85 std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse(
86     absl::string_view status, absl::string_view error_details) {
87   spdy::Http2HeaderBlock response_headers;
88   response_headers[":status"] = status;
89   response_headers["masque-debug-info"] = error_details;
90   auto response = std::make_unique<QuicBackendResponse>();
91   response->set_response_type(QuicBackendResponse::REGULAR_RESPONSE);
92   response->set_headers(std::move(response_headers));
93   return response;
94 }
95 
96 }  // namespace
97 
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)98 MasqueServerSession::MasqueServerSession(
99     MasqueMode masque_mode, const QuicConfig& config,
100     const ParsedQuicVersionVector& supported_versions,
101     QuicConnection* connection, QuicSession::Visitor* visitor,
102     QuicEventLoop* event_loop, QuicCryptoServerStreamBase::Helper* helper,
103     const QuicCryptoServerConfig* crypto_config,
104     QuicCompressedCertsCache* compressed_certs_cache,
105     MasqueServerBackend* masque_server_backend)
106     : QuicSimpleServerSession(config, supported_versions, connection, visitor,
107                               helper, crypto_config, compressed_certs_cache,
108                               masque_server_backend),
109       masque_server_backend_(masque_server_backend),
110       event_loop_(event_loop),
111       masque_mode_(masque_mode) {
112   // Artificially increase the max packet length to 1350 to ensure we can fit
113   // QUIC packets inside DATAGRAM frames.
114   // TODO(b/181606597) Remove this workaround once we use PMTUD.
115   connection->SetMaxPacketLength(kMasqueMaxOuterPacketSize);
116 
117   masque_server_backend_->RegisterBackendClient(connection_id(), this);
118   QUICHE_DCHECK_NE(event_loop_, nullptr);
119 }
120 
OnMessageAcked(QuicMessageId message_id,QuicTime)121 void MasqueServerSession::OnMessageAcked(QuicMessageId message_id,
122                                          QuicTime /*receive_timestamp*/) {
123   QUIC_DVLOG(1) << "Received ack for DATAGRAM frame " << message_id;
124 }
125 
OnMessageLost(QuicMessageId message_id)126 void MasqueServerSession::OnMessageLost(QuicMessageId message_id) {
127   QUIC_DVLOG(1) << "We believe DATAGRAM frame " << message_id << " was lost";
128 }
129 
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)130 void MasqueServerSession::OnConnectionClosed(
131     const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
132   QuicSimpleServerSession::OnConnectionClosed(frame, source);
133   QUIC_DLOG(INFO) << "Closing connection for " << connection_id();
134   masque_server_backend_->RemoveBackendClient(connection_id());
135   // Clearing this state will close all sockets.
136   connect_udp_server_states_.clear();
137 }
138 
OnStreamClosed(QuicStreamId stream_id)139 void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) {
140   connect_udp_server_states_.remove_if(
141       [stream_id](const ConnectUdpServerState& connect_udp) {
142         return connect_udp.stream()->id() == stream_id;
143       });
144   connect_ip_server_states_.remove_if(
145       [stream_id](const ConnectIpServerState& connect_ip) {
146         return connect_ip.stream()->id() == stream_id;
147       });
148   connect_ethernet_server_states_.remove_if(
149       [stream_id](const ConnectEthernetServerState& connect_ethernet) {
150         return connect_ethernet.stream()->id() == stream_id;
151       });
152 
153   QuicSimpleServerSession::OnStreamClosed(stream_id);
154 }
155 
HandleMasqueRequest(const spdy::Http2HeaderBlock & request_headers,QuicSimpleServerBackend::RequestHandler * request_handler)156 std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
157     const spdy::Http2HeaderBlock& request_headers,
158     QuicSimpleServerBackend::RequestHandler* request_handler) {
159   auto path_pair = request_headers.find(":path");
160   auto scheme_pair = request_headers.find(":scheme");
161   auto method_pair = request_headers.find(":method");
162   auto protocol_pair = request_headers.find(":protocol");
163   auto authority_pair = request_headers.find(":authority");
164   if (path_pair == request_headers.end()) {
165     QUIC_DLOG(ERROR) << "MASQUE request is missing :path";
166     return CreateBackendErrorResponse("400", "Missing :path");
167   }
168   if (scheme_pair == request_headers.end()) {
169     QUIC_DLOG(ERROR) << "MASQUE request is missing :scheme";
170     return CreateBackendErrorResponse("400", "Missing :scheme");
171   }
172   if (method_pair == request_headers.end()) {
173     QUIC_DLOG(ERROR) << "MASQUE request is missing :method";
174     return CreateBackendErrorResponse("400", "Missing :method");
175   }
176   if (protocol_pair == request_headers.end()) {
177     QUIC_DLOG(ERROR) << "MASQUE request is missing :protocol";
178     return CreateBackendErrorResponse("400", "Missing :protocol");
179   }
180   if (authority_pair == request_headers.end()) {
181     QUIC_DLOG(ERROR) << "MASQUE request is missing :authority";
182     return CreateBackendErrorResponse("400", "Missing :authority");
183   }
184   absl::string_view path = path_pair->second;
185   absl::string_view scheme = scheme_pair->second;
186   absl::string_view method = method_pair->second;
187   absl::string_view protocol = protocol_pair->second;
188   absl::string_view authority = authority_pair->second;
189   if (path.empty()) {
190     QUIC_DLOG(ERROR) << "MASQUE request with empty path";
191     return CreateBackendErrorResponse("400", "Empty path");
192   }
193   if (scheme.empty()) {
194     return CreateBackendErrorResponse("400", "Empty scheme");
195   }
196   if (method != "CONNECT") {
197     QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\"";
198     return CreateBackendErrorResponse("400", "Bad method");
199   }
200   if (protocol != "connect-udp" && protocol != "connect-ip" &&
201       protocol != "connect-ethernet") {
202     QUIC_DLOG(ERROR) << "MASQUE request with bad protocol \"" << protocol
203                      << "\"";
204     return CreateBackendErrorResponse("400", "Bad protocol");
205   }
206   if (protocol == "connect-ip") {
207     QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(
208         GetActiveStream(request_handler->stream_id()));
209     if (stream == nullptr) {
210       QUIC_BUG(bad masque server stream type)
211           << "Unexpected stream type for stream ID "
212           << request_handler->stream_id();
213       return CreateBackendErrorResponse("500", "Bad stream type");
214     }
215     QuicIpAddress client_ip = masque_server_backend_->GetNextClientIpAddress();
216     QUIC_DLOG(INFO) << "Using client IP " << client_ip.ToString()
217                     << " for CONNECT-IP stream ID "
218                     << request_handler->stream_id();
219     int fd = CreateTunInterface(client_ip);
220     if (fd < 0) {
221       QUIC_LOG(ERROR) << "Failed to create TUN interface for stream ID "
222                       << request_handler->stream_id();
223       return CreateBackendErrorResponse("500",
224                                         "Failed to create TUN interface");
225     }
226     if (!event_loop_->RegisterSocket(fd, kSocketEventReadable, this)) {
227       QUIC_DLOG(ERROR) << "Failed to register TUN fd with the event loop";
228       close(fd);
229       return CreateBackendErrorResponse("500", "Registering TUN socket failed");
230     }
231     connect_ip_server_states_.push_back(
232         ConnectIpServerState(client_ip, stream, fd, this));
233 
234     spdy::Http2HeaderBlock response_headers;
235     response_headers[":status"] = "200";
236     auto response = std::make_unique<QuicBackendResponse>();
237     response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
238     response->set_headers(std::move(response_headers));
239     response->set_body("");
240 
241     return response;
242   }
243   if (protocol == "connect-ethernet") {
244     QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(
245         GetActiveStream(request_handler->stream_id()));
246     if (stream == nullptr) {
247       QUIC_BUG(bad masque server stream type)
248           << "Unexpected stream type for stream ID "
249           << request_handler->stream_id();
250       return CreateBackendErrorResponse("500", "Bad stream type");
251     }
252     int fd = CreateTapInterface();
253     if (fd < 0) {
254       QUIC_LOG(ERROR) << "Failed to create TAP interface for stream ID "
255                       << request_handler->stream_id();
256       return CreateBackendErrorResponse("500",
257                                         "Failed to create TAP interface");
258     }
259     if (!event_loop_->RegisterSocket(fd, kSocketEventReadable, this)) {
260       QUIC_DLOG(ERROR) << "Failed to register TAP fd with the event loop";
261       close(fd);
262       return CreateBackendErrorResponse("500", "Registering TAP socket failed");
263     }
264     connect_ethernet_server_states_.push_back(
265         ConnectEthernetServerState(stream, fd, this));
266 
267     spdy::Http2HeaderBlock response_headers;
268     response_headers[":status"] = "200";
269     auto response = std::make_unique<QuicBackendResponse>();
270     response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
271     response->set_headers(std::move(response_headers));
272     response->set_body("");
273 
274     return response;
275   }
276   // Extract target host and port from path using default template.
277   std::vector<absl::string_view> path_split = absl::StrSplit(path, '/');
278   if (path_split.size() != 7 || !path_split[0].empty() ||
279       path_split[1] != ".well-known" || path_split[2] != "masque" ||
280       path_split[3] != "udp" || path_split[4].empty() ||
281       path_split[5].empty() || !path_split[6].empty()) {
282     QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\"";
283     return CreateBackendErrorResponse("400", "Bad path");
284   }
285   std::optional<std::string> host = quiche::AsciiUrlDecode(path_split[4]);
286   if (!host.has_value()) {
287     QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[4] << "\"";
288     return CreateBackendErrorResponse("500", "Failed to decode host");
289   }
290   std::optional<std::string> port = quiche::AsciiUrlDecode(path_split[5]);
291   if (!port.has_value()) {
292     QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[5] << "\"";
293     return CreateBackendErrorResponse("500", "Failed to decode port");
294   }
295 
296   // Perform DNS resolution.
297   addrinfo hint = {};
298   hint.ai_protocol = IPPROTO_UDP;
299 
300   addrinfo* info_list = nullptr;
301   int result = getaddrinfo(host->c_str(), port->c_str(), &hint, &info_list);
302   if (result != 0 || info_list == nullptr) {
303     QUIC_DLOG(ERROR) << "Failed to resolve " << authority << ": "
304                      << gai_strerror(result);
305     return CreateBackendErrorResponse("500", "DNS resolution failed");
306   }
307 
308   std::unique_ptr<addrinfo, void (*)(addrinfo*)> info_list_owned(info_list,
309                                                                  freeaddrinfo);
310   QuicSocketAddress target_server_address(info_list->ai_addr,
311                                           info_list->ai_addrlen);
312   QUIC_DLOG(INFO) << "Got CONNECT_UDP request on stream ID "
313                   << request_handler->stream_id() << " target_server_address=\""
314                   << target_server_address << "\"";
315 
316   FdWrapper fd_wrapper(target_server_address.host().AddressFamilyToInt());
317   if (fd_wrapper.fd() == kQuicInvalidSocketFd) {
318     QUIC_DLOG(ERROR) << "Socket creation failed";
319     return CreateBackendErrorResponse("500", "Socket creation failed");
320   }
321   QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0);
322   if (target_server_address.host().IsIPv4()) {
323     empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0);
324   }
325   QuicUdpSocketApi socket_api;
326   if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) {
327     QUIC_DLOG(ERROR) << "Socket bind failed";
328     return CreateBackendErrorResponse("500", "Socket bind failed");
329   }
330   if (!event_loop_->RegisterSocket(fd_wrapper.fd(), kSocketEventReadable,
331                                    this)) {
332     QUIC_DLOG(ERROR) << "Failed to register socket with the event loop";
333     return CreateBackendErrorResponse("500", "Registering socket failed");
334   }
335 
336   QuicSpdyStream* stream =
337       static_cast<QuicSpdyStream*>(GetActiveStream(request_handler->stream_id()));
338   if (stream == nullptr) {
339     QUIC_BUG(bad masque server stream type)
340         << "Unexpected stream type for stream ID "
341         << request_handler->stream_id();
342     return CreateBackendErrorResponse("500", "Bad stream type");
343   }
344   connect_udp_server_states_.push_back(ConnectUdpServerState(
345       stream, target_server_address, fd_wrapper.extract_fd(), this));
346 
347   spdy::Http2HeaderBlock response_headers;
348   response_headers[":status"] = "200";
349   auto response = std::make_unique<QuicBackendResponse>();
350   response->set_response_type(QuicBackendResponse::INCOMPLETE_RESPONSE);
351   response->set_headers(std::move(response_headers));
352   response->set_body("");
353 
354   return response;
355 }
356 
OnSocketEvent(QuicEventLoop *,QuicUdpSocketFd fd,QuicSocketEventMask events)357 void MasqueServerSession::OnSocketEvent(QuicEventLoop* /*event_loop*/,
358                                         QuicUdpSocketFd fd,
359                                         QuicSocketEventMask events) {
360   if ((events & kSocketEventReadable) == 0) {
361     QUIC_DVLOG(1) << "Ignoring OnEvent fd " << fd << " event mask " << events;
362     return;
363   }
364 
365   auto rearm = absl::MakeCleanup([&]() {
366     if (!event_loop_->SupportsEdgeTriggered()) {
367       if (!event_loop_->RearmSocket(fd, kSocketEventReadable)) {
368         QUIC_BUG(MasqueServerSession_OnSocketEvent_Rearm)
369             << "Failed to re-arm socket " << fd << " for reading";
370       }
371     }
372   });
373 
374   if (!(HandleConnectUdpSocketEvent(fd, events) ||
375         HandleConnectIpSocketEvent(fd, events) ||
376         HandleConnectEthernetSocketEvent(fd, events))) {
377     QUIC_BUG(MasqueServerSession_OnSocketEvent_UnhandledEvent)
378         << "Got unexpected event mask " << events << " on unknown fd " << fd;
379     std::move(rearm).Cancel();
380   }
381 }
382 
HandleConnectUdpSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)383 bool MasqueServerSession::HandleConnectUdpSocketEvent(
384     QuicUdpSocketFd fd, QuicSocketEventMask events) {
385   auto it = absl::c_find_if(connect_udp_server_states_,
386                             [fd](const ConnectUdpServerState& connect_udp) {
387                               return connect_udp.fd() == fd;
388                             });
389   if (it == connect_udp_server_states_.end()) {
390     return false;
391   }
392   QuicSocketAddress expected_target_server_address =
393       it->target_server_address();
394   QUICHE_DCHECK(expected_target_server_address.IsInitialized());
395   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
396                 << ") stream ID " << it->stream()->id() << " server "
397                 << expected_target_server_address;
398   QuicUdpSocketApi socket_api;
399   QuicUdpPacketInfoBitMask packet_info_interested(
400       {QuicUdpPacketInfoBit::PEER_ADDRESS});
401   char packet_buffer[1 + kMaxIncomingPacketSize];
402   packet_buffer[0] = 0;  // context ID.
403   char control_buffer[kDefaultUdpPacketControlBufferSize];
404   while (true) {
405     QuicUdpSocketApi::ReadPacketResult read_result;
406     read_result.packet_buffer = {packet_buffer + 1, sizeof(packet_buffer) - 1};
407     read_result.control_buffer = {control_buffer, sizeof(control_buffer)};
408     socket_api.ReadPacket(fd, packet_info_interested, &read_result);
409     if (!read_result.ok) {
410       // Most likely there is nothing left to read, break out of read loop.
411       break;
412     }
413     if (!read_result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
414       QUIC_BUG(MasqueServerSession_HandleConnectUdpSocketEvent_MissingPeer)
415           << "Missing peer address when reading from fd " << fd;
416       continue;
417     }
418     if (read_result.packet_info.peer_address() !=
419         expected_target_server_address) {
420       QUIC_DLOG(ERROR) << "Ignoring UDP packet on fd " << fd
421                        << " from unexpected server address "
422                        << read_result.packet_info.peer_address()
423                        << " (expected " << expected_target_server_address
424                        << ")";
425       continue;
426     }
427     if (!connection()->connected()) {
428       QUIC_BUG(MasqueServerSession_HandleConnectUdpSocketEvent_ConnectionClosed)
429           << "Unexpected incoming UDP packet on fd " << fd << " from "
430           << expected_target_server_address
431           << " because MASQUE connection is closed";
432       return true;
433     }
434     // The packet is valid, send it to the client in a DATAGRAM frame.
435     MessageStatus message_status =
436         it->stream()->SendHttp3Datagram(absl::string_view(
437             packet_buffer, read_result.packet_buffer.buffer_len + 1));
438     QUIC_DVLOG(1) << "Sent UDP packet from " << expected_target_server_address
439                   << " of length " << read_result.packet_buffer.buffer_len
440                   << " with stream ID " << it->stream()->id()
441                   << " and got message status "
442                   << MessageStatusToString(message_status);
443   }
444   return true;
445 }
446 
HandleConnectIpSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)447 bool MasqueServerSession::HandleConnectIpSocketEvent(
448     QuicUdpSocketFd fd, QuicSocketEventMask events) {
449   auto it = absl::c_find_if(connect_ip_server_states_,
450                             [fd](const ConnectIpServerState& connect_ip) {
451                               return connect_ip.fd() == fd;
452                             });
453   if (it == connect_ip_server_states_.end()) {
454     return false;
455   }
456   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
457                 << ") stream ID " << it->stream()->id();
458   char datagram[kMasqueIpPacketBufferSize];
459   datagram[0] = 0;  // Context ID.
460   while (true) {
461     ssize_t read_size = read(fd, datagram + 1, sizeof(datagram) - 1);
462     if (read_size < 0) {
463       break;
464     }
465     MessageStatus message_status = it->stream()->SendHttp3Datagram(
466         absl::string_view(datagram, 1 + read_size));
467     QUIC_DVLOG(1) << "Encapsulated IP packet of length " << read_size
468                   << " with stream ID " << it->stream()->id()
469                   << " and got message status "
470                   << MessageStatusToString(message_status);
471   }
472   return true;
473 }
474 
HandleConnectEthernetSocketEvent(QuicUdpSocketFd fd,QuicSocketEventMask events)475 bool MasqueServerSession::HandleConnectEthernetSocketEvent(
476     QuicUdpSocketFd fd, QuicSocketEventMask events) {
477   auto it =
478       absl::c_find_if(connect_ethernet_server_states_,
479                       [fd](const ConnectEthernetServerState& connect_ethernet) {
480                         return connect_ethernet.fd() == fd;
481                       });
482   if (it == connect_ethernet_server_states_.end()) {
483     return false;
484   }
485   QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask " << events
486                 << ") stream ID " << it->stream()->id();
487   char datagram[kMasqueEthernetFrameBufferSize];
488   datagram[0] = 0;  // Context ID.
489   while (true) {
490     ssize_t read_size = read(fd, datagram + 1, sizeof(datagram) - 1);
491     if (read_size < 0) {
492       break;
493     }
494     MessageStatus message_status = it->stream()->SendHttp3Datagram(
495         absl::string_view(datagram, 1 + read_size));
496     QUIC_DVLOG(1) << "Encapsulated Ethernet frame of length " << read_size
497                   << " with stream ID " << it->stream()->id()
498                   << " and got message status "
499                   << MessageStatusToString(message_status);
500   }
501   return true;
502 }
503 
OnSettingsFrame(const SettingsFrame & frame)504 bool MasqueServerSession::OnSettingsFrame(const SettingsFrame& frame) {
505   QUIC_DLOG(INFO) << "Received SETTINGS: " << frame;
506   if (!QuicSimpleServerSession::OnSettingsFrame(frame)) {
507     return false;
508   }
509   if (!SupportsH3Datagram()) {
510     QUIC_DLOG(ERROR) << "Refusing to use MASQUE without HTTP Datagrams";
511     return false;
512   }
513   QUIC_DLOG(INFO) << "Using HTTP Datagram: " << http_datagram_support();
514   return true;
515 }
516 
ConnectUdpServerState(QuicSpdyStream * stream,const QuicSocketAddress & target_server_address,QuicUdpSocketFd fd,MasqueServerSession * masque_session)517 MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
518     QuicSpdyStream* stream, const QuicSocketAddress& target_server_address,
519     QuicUdpSocketFd fd, MasqueServerSession* masque_session)
520     : stream_(stream),
521       target_server_address_(target_server_address),
522       fd_(fd),
523       masque_session_(masque_session) {
524   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
525   QUICHE_DCHECK_NE(masque_session_, nullptr);
526   this->stream()->RegisterHttp3DatagramVisitor(this);
527 }
528 
~ConnectUdpServerState()529 MasqueServerSession::ConnectUdpServerState::~ConnectUdpServerState() {
530   if (stream() != nullptr) {
531     stream()->UnregisterHttp3DatagramVisitor();
532   }
533   if (fd_ == kQuicInvalidSocketFd) {
534     return;
535   }
536   QuicUdpSocketApi socket_api;
537   QUIC_DLOG(INFO) << "Closing fd " << fd_;
538   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
539     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
540   }
541   socket_api.Destroy(fd_);
542 }
543 
ConnectUdpServerState(MasqueServerSession::ConnectUdpServerState && other)544 MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
545     MasqueServerSession::ConnectUdpServerState&& other) {
546   fd_ = kQuicInvalidSocketFd;
547   *this = std::move(other);
548 }
549 
550 MasqueServerSession::ConnectUdpServerState&
operator =(MasqueServerSession::ConnectUdpServerState && other)551 MasqueServerSession::ConnectUdpServerState::operator=(
552     MasqueServerSession::ConnectUdpServerState&& other) {
553   if (fd_ != kQuicInvalidSocketFd) {
554     QuicUdpSocketApi socket_api;
555     QUIC_DLOG(INFO) << "Closing fd " << fd_;
556     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
557       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
558     }
559     socket_api.Destroy(fd_);
560   }
561   stream_ = other.stream_;
562   other.stream_ = nullptr;
563   target_server_address_ = other.target_server_address_;
564   fd_ = other.fd_;
565   masque_session_ = other.masque_session_;
566   other.fd_ = kQuicInvalidSocketFd;
567   if (stream() != nullptr) {
568     stream()->ReplaceHttp3DatagramVisitor(this);
569   }
570   return *this;
571 }
572 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)573 void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram(
574     QuicStreamId stream_id, absl::string_view payload) {
575   QUICHE_DCHECK_EQ(stream_id, stream()->id());
576   QuicDataReader reader(payload);
577   uint64_t context_id;
578   if (!reader.ReadVarInt62(&context_id)) {
579     QUIC_DLOG(ERROR) << "Failed to read context ID";
580     return;
581   }
582   if (context_id != 0) {
583     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
584                      << context_id;
585     return;
586   }
587   absl::string_view http_payload = reader.ReadRemainingPayload();
588   QuicUdpSocketApi socket_api;
589   QuicUdpPacketInfo packet_info;
590   packet_info.SetPeerAddress(target_server_address_);
591   WriteResult write_result = socket_api.WritePacket(
592       fd_, http_payload.data(), http_payload.length(), packet_info);
593   QUIC_DVLOG(1) << "Wrote packet of length " << http_payload.length() << " to "
594                 << target_server_address_ << " with result " << write_result;
595 }
596 
ConnectIpServerState(QuicIpAddress client_ip,QuicSpdyStream * stream,QuicUdpSocketFd fd,MasqueServerSession * masque_session)597 MasqueServerSession::ConnectIpServerState::ConnectIpServerState(
598     QuicIpAddress client_ip, QuicSpdyStream* stream, QuicUdpSocketFd fd,
599     MasqueServerSession* masque_session)
600     : client_ip_(client_ip),
601       stream_(stream),
602       fd_(fd),
603       masque_session_(masque_session) {
604   QUICHE_DCHECK(client_ip_.IsIPv4());
605   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
606   QUICHE_DCHECK_NE(masque_session_, nullptr);
607   this->stream()->RegisterHttp3DatagramVisitor(this);
608   this->stream()->RegisterConnectIpVisitor(this);
609 }
610 
~ConnectIpServerState()611 MasqueServerSession::ConnectIpServerState::~ConnectIpServerState() {
612   if (stream() != nullptr) {
613     stream()->UnregisterHttp3DatagramVisitor();
614     stream()->UnregisterConnectIpVisitor();
615   }
616   if (fd_ == kQuicInvalidSocketFd) {
617     return;
618   }
619   QuicUdpSocketApi socket_api;
620   QUIC_DLOG(INFO) << "Closing fd " << fd_;
621   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
622     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
623   }
624   socket_api.Destroy(fd_);
625 }
626 
ConnectIpServerState(MasqueServerSession::ConnectIpServerState && other)627 MasqueServerSession::ConnectIpServerState::ConnectIpServerState(
628     MasqueServerSession::ConnectIpServerState&& other) {
629   fd_ = kQuicInvalidSocketFd;
630   *this = std::move(other);
631 }
632 
633 MasqueServerSession::ConnectIpServerState&
operator =(MasqueServerSession::ConnectIpServerState && other)634 MasqueServerSession::ConnectIpServerState::operator=(
635     MasqueServerSession::ConnectIpServerState&& other) {
636   if (fd_ != kQuicInvalidSocketFd) {
637     QuicUdpSocketApi socket_api;
638     QUIC_DLOG(INFO) << "Closing fd " << fd_;
639     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
640       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
641     }
642     socket_api.Destroy(fd_);
643   }
644   client_ip_ = other.client_ip_;
645   stream_ = other.stream_;
646   other.stream_ = nullptr;
647   fd_ = other.fd_;
648   masque_session_ = other.masque_session_;
649   other.fd_ = kQuicInvalidSocketFd;
650   if (stream() != nullptr) {
651     stream()->ReplaceHttp3DatagramVisitor(this);
652     stream()->ReplaceConnectIpVisitor(this);
653   }
654   return *this;
655 }
656 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)657 void MasqueServerSession::ConnectIpServerState::OnHttp3Datagram(
658     QuicStreamId stream_id, absl::string_view payload) {
659   QUICHE_DCHECK_EQ(stream_id, stream()->id());
660   QuicDataReader reader(payload);
661   uint64_t context_id;
662   if (!reader.ReadVarInt62(&context_id)) {
663     QUIC_DLOG(ERROR) << "Failed to read context ID";
664     return;
665   }
666   if (context_id != 0) {
667     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
668                      << context_id;
669     return;
670   }
671   absl::string_view ip_packet = reader.ReadRemainingPayload();
672   ssize_t written = write(fd(), ip_packet.data(), ip_packet.size());
673   if (written != static_cast<ssize_t>(ip_packet.size())) {
674     QUIC_DLOG(ERROR) << "Failed to write CONNECT-IP packet of length "
675                      << ip_packet.size();
676   } else {
677     QUIC_DLOG(INFO) << "Decapsulated CONNECT-IP packet of length "
678                     << ip_packet.size();
679   }
680 }
681 
OnAddressAssignCapsule(const AddressAssignCapsule & capsule)682 bool MasqueServerSession::ConnectIpServerState::OnAddressAssignCapsule(
683     const AddressAssignCapsule& capsule) {
684   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
685   return true;
686 }
687 
OnAddressRequestCapsule(const AddressRequestCapsule & capsule)688 bool MasqueServerSession::ConnectIpServerState::OnAddressRequestCapsule(
689     const AddressRequestCapsule& capsule) {
690   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
691   return true;
692 }
693 
OnRouteAdvertisementCapsule(const RouteAdvertisementCapsule & capsule)694 bool MasqueServerSession::ConnectIpServerState::OnRouteAdvertisementCapsule(
695     const RouteAdvertisementCapsule& capsule) {
696   QUIC_DLOG(INFO) << "Ignoring received capsule " << capsule.ToString();
697   return true;
698 }
699 
OnHeadersWritten()700 void MasqueServerSession::ConnectIpServerState::OnHeadersWritten() {
701   QUICHE_DCHECK(client_ip_.IsIPv4()) << client_ip_.ToString();
702   Capsule address_assign_capsule = Capsule::AddressAssign();
703   PrefixWithId assigned_address;
704   assigned_address.ip_prefix = quiche::QuicheIpPrefix(client_ip_, 32);
705   assigned_address.request_id = 0;
706   address_assign_capsule.address_assign_capsule().assigned_addresses.push_back(
707       assigned_address);
708   stream()->WriteCapsule(address_assign_capsule);
709   IpAddressRange default_route;
710   default_route.start_ip_address.FromString("0.0.0.0");
711   default_route.end_ip_address.FromString("255.255.255.255");
712   default_route.ip_protocol = 0;
713   Capsule route_advertisement = Capsule::RouteAdvertisement();
714   route_advertisement.route_advertisement_capsule().ip_address_ranges.push_back(
715       default_route);
716   stream()->WriteCapsule(route_advertisement);
717 }
718 
719 // Connect Ethernet
ConnectEthernetServerState(QuicSpdyStream * stream,QuicUdpSocketFd fd,MasqueServerSession * masque_session)720 MasqueServerSession::ConnectEthernetServerState::ConnectEthernetServerState(
721     QuicSpdyStream* stream, QuicUdpSocketFd fd,
722     MasqueServerSession* masque_session)
723     : stream_(stream), fd_(fd), masque_session_(masque_session) {
724   QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
725   QUICHE_DCHECK_NE(masque_session_, nullptr);
726   this->stream()->RegisterHttp3DatagramVisitor(this);
727 }
728 
~ConnectEthernetServerState()729 MasqueServerSession::ConnectEthernetServerState::~ConnectEthernetServerState() {
730   if (stream() != nullptr) {
731     stream()->UnregisterHttp3DatagramVisitor();
732   }
733   if (fd_ == kQuicInvalidSocketFd) {
734     return;
735   }
736   QuicUdpSocketApi socket_api;
737   QUIC_DLOG(INFO) << "Closing fd " << fd_;
738   if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
739     QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
740   }
741   socket_api.Destroy(fd_);
742 }
743 
ConnectEthernetServerState(MasqueServerSession::ConnectEthernetServerState && other)744 MasqueServerSession::ConnectEthernetServerState::ConnectEthernetServerState(
745     MasqueServerSession::ConnectEthernetServerState&& other) {
746   fd_ = kQuicInvalidSocketFd;
747   *this = std::move(other);
748 }
749 
750 MasqueServerSession::ConnectEthernetServerState&
operator =(MasqueServerSession::ConnectEthernetServerState && other)751 MasqueServerSession::ConnectEthernetServerState::operator=(
752     MasqueServerSession::ConnectEthernetServerState&& other) {
753   if (fd_ != kQuicInvalidSocketFd) {
754     QuicUdpSocketApi socket_api;
755     QUIC_DLOG(INFO) << "Closing fd " << fd_;
756     if (!masque_session_->event_loop()->UnregisterSocket(fd_)) {
757       QUIC_DLOG(ERROR) << "Failed to unregister FD " << fd_;
758     }
759     socket_api.Destroy(fd_);
760   }
761   stream_ = other.stream_;
762   other.stream_ = nullptr;
763   fd_ = other.fd_;
764   masque_session_ = other.masque_session_;
765   other.fd_ = kQuicInvalidSocketFd;
766   if (stream() != nullptr) {
767     stream()->ReplaceHttp3DatagramVisitor(this);
768   }
769   return *this;
770 }
771 
OnHttp3Datagram(QuicStreamId stream_id,absl::string_view payload)772 void MasqueServerSession::ConnectEthernetServerState::OnHttp3Datagram(
773     QuicStreamId stream_id, absl::string_view payload) {
774   QUICHE_DCHECK_EQ(stream_id, stream()->id());
775   QuicDataReader reader(payload);
776   uint64_t context_id;
777   if (!reader.ReadVarInt62(&context_id)) {
778     QUIC_DLOG(ERROR) << "Failed to read context ID";
779     return;
780   }
781   if (context_id != 0) {
782     QUIC_DLOG(ERROR) << "Ignoring HTTP Datagram with unexpected context ID "
783                      << context_id;
784     return;
785   }
786   absl::string_view ethernet_frame = reader.ReadRemainingPayload();
787   ssize_t written = write(fd(), ethernet_frame.data(), ethernet_frame.size());
788   if (written != static_cast<ssize_t>(ethernet_frame.size())) {
789     QUIC_DLOG(ERROR) << "Failed to write CONNECT-ETHERNET packet of length "
790                      << ethernet_frame.size();
791   } else {
792     QUIC_DLOG(INFO) << "Decapsulated CONNECT-ETHERNET packet of length "
793                     << ethernet_frame.size();
794   }
795 }
796 
797 }  // namespace quic
798