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_backend.h"
6
7 #include "absl/strings/str_cat.h"
8 #include "absl/strings/string_view.h"
9
10 namespace quic {
11
MasqueServerBackend(MasqueMode masque_mode,const std::string & server_authority,const std::string & cache_directory)12 MasqueServerBackend::MasqueServerBackend(MasqueMode masque_mode,
13 const std::string& server_authority,
14 const std::string& cache_directory)
15 : masque_mode_(masque_mode), server_authority_(server_authority) {
16 // Start with client IP 10.1.1.2.
17 connect_ip_next_client_ip_[0] = 10;
18 connect_ip_next_client_ip_[1] = 1;
19 connect_ip_next_client_ip_[2] = 1;
20 connect_ip_next_client_ip_[3] = 2;
21
22 if (!cache_directory.empty()) {
23 QuicMemoryCacheBackend::InitializeBackend(cache_directory);
24 }
25 }
26
MaybeHandleMasqueRequest(const spdy::Http2HeaderBlock & request_headers,QuicSimpleServerBackend::RequestHandler * request_handler)27 bool MasqueServerBackend::MaybeHandleMasqueRequest(
28 const spdy::Http2HeaderBlock& request_headers,
29 QuicSimpleServerBackend::RequestHandler* request_handler) {
30 auto method_pair = request_headers.find(":method");
31 if (method_pair == request_headers.end()) {
32 // Request is missing a method.
33 return false;
34 }
35 absl::string_view method = method_pair->second;
36 std::string masque_path = "";
37 auto protocol_pair = request_headers.find(":protocol");
38 if (method != "CONNECT" || protocol_pair == request_headers.end() ||
39 (protocol_pair->second != "connect-udp" &&
40 protocol_pair->second != "connect-ip" &&
41 protocol_pair->second != "connect-ethernet")) {
42 // This is not a MASQUE request.
43 return false;
44 }
45
46 if (!server_authority_.empty()) {
47 auto authority_pair = request_headers.find(":authority");
48 if (authority_pair == request_headers.end()) {
49 // Cannot enforce missing authority.
50 return false;
51 }
52 absl::string_view authority = authority_pair->second;
53 if (server_authority_ != authority) {
54 // This request does not match server_authority.
55 return false;
56 }
57 }
58
59 auto it = backend_client_states_.find(request_handler->connection_id());
60 if (it == backend_client_states_.end()) {
61 QUIC_LOG(ERROR) << "Could not find backend client for " << masque_path
62 << request_headers.DebugString();
63 return false;
64 }
65
66 BackendClient* backend_client = it->second.backend_client;
67
68 std::unique_ptr<QuicBackendResponse> response =
69 backend_client->HandleMasqueRequest(request_headers, request_handler);
70 if (response == nullptr) {
71 QUIC_LOG(ERROR) << "Backend client did not process request for "
72 << masque_path << request_headers.DebugString();
73 return false;
74 }
75
76 QUIC_DLOG(INFO) << "Sending MASQUE response for "
77 << request_headers.DebugString();
78
79 request_handler->OnResponseBackendComplete(response.get());
80 it->second.responses.emplace_back(std::move(response));
81
82 return true;
83 }
84
FetchResponseFromBackend(const spdy::Http2HeaderBlock & request_headers,const std::string & request_body,QuicSimpleServerBackend::RequestHandler * request_handler)85 void MasqueServerBackend::FetchResponseFromBackend(
86 const spdy::Http2HeaderBlock& request_headers,
87 const std::string& request_body,
88 QuicSimpleServerBackend::RequestHandler* request_handler) {
89 if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
90 // Request was handled as a MASQUE request.
91 return;
92 }
93 QUIC_DLOG(INFO) << "Fetching non-MASQUE response for "
94 << request_headers.DebugString();
95 QuicMemoryCacheBackend::FetchResponseFromBackend(
96 request_headers, request_body, request_handler);
97 }
98
HandleConnectHeaders(const spdy::Http2HeaderBlock & request_headers,RequestHandler * request_handler)99 void MasqueServerBackend::HandleConnectHeaders(
100 const spdy::Http2HeaderBlock& request_headers,
101 RequestHandler* request_handler) {
102 if (MaybeHandleMasqueRequest(request_headers, request_handler)) {
103 // Request was handled as a MASQUE request.
104 return;
105 }
106 QUIC_DLOG(INFO) << "Fetching non-MASQUE CONNECT response for "
107 << request_headers.DebugString();
108 QuicMemoryCacheBackend::HandleConnectHeaders(request_headers,
109 request_handler);
110 }
111
CloseBackendResponseStream(QuicSimpleServerBackend::RequestHandler * request_handler)112 void MasqueServerBackend::CloseBackendResponseStream(
113 QuicSimpleServerBackend::RequestHandler* request_handler) {
114 QUIC_DLOG(INFO) << "Closing response stream";
115 QuicMemoryCacheBackend::CloseBackendResponseStream(request_handler);
116 }
117
RegisterBackendClient(QuicConnectionId connection_id,BackendClient * backend_client)118 void MasqueServerBackend::RegisterBackendClient(QuicConnectionId connection_id,
119 BackendClient* backend_client) {
120 QUIC_DLOG(INFO) << "Registering backend client for " << connection_id;
121 QUIC_BUG_IF(quic_bug_12005_1, backend_client_states_.find(connection_id) !=
122 backend_client_states_.end())
123 << connection_id << " already in backend clients map";
124 backend_client_states_[connection_id] =
125 BackendClientState{backend_client, {}};
126 }
127
RemoveBackendClient(QuicConnectionId connection_id)128 void MasqueServerBackend::RemoveBackendClient(QuicConnectionId connection_id) {
129 QUIC_DLOG(INFO) << "Removing backend client for " << connection_id;
130 backend_client_states_.erase(connection_id);
131 }
132
GetNextClientIpAddress()133 QuicIpAddress MasqueServerBackend::GetNextClientIpAddress() {
134 // Makes sure all addresses are in 10.(1-254).(1-254).(2-254)
135 QuicIpAddress address;
136 address.FromPackedString(
137 reinterpret_cast<char*>(&connect_ip_next_client_ip_[0]),
138 sizeof(connect_ip_next_client_ip_));
139 connect_ip_next_client_ip_[3]++;
140 if (connect_ip_next_client_ip_[3] >= 255) {
141 connect_ip_next_client_ip_[3] = 2;
142 connect_ip_next_client_ip_[2]++;
143 if (connect_ip_next_client_ip_[2] >= 255) {
144 connect_ip_next_client_ip_[2] = 1;
145 connect_ip_next_client_ip_[1]++;
146 if (connect_ip_next_client_ip_[1] >= 255) {
147 QUIC_LOG(FATAL) << "Ran out of IP addresses, restarting process.";
148 }
149 }
150 }
151 return address;
152 }
153
154 } // namespace quic
155