• 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_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