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