| // Copyright 2019 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_ | |
| #define QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_ | |
| #include <cstdint> | |
| #include <list> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/container/flat_hash_map.h" | |
| #include "absl/strings/string_view.h" | |
| #include "openssl/curve25519.h" | |
| #include "quiche/quic/core/http/quic_spdy_session.h" | |
| #include "quiche/quic/core/quic_connection_id.h" | |
| #include "quiche/quic/masque/masque_utils.h" | |
| #include "quiche/quic/platform/api/quic_export.h" | |
| #include "quiche/quic/platform/api/quic_ip_address.h" | |
| #include "quiche/quic/tools/quic_backend_response.h" | |
| #include "quiche/quic/tools/quic_memory_cache_backend.h" | |
| #include "quiche/quic/tools/quic_simple_server_backend.h" | |
| #include "quiche/common/http/http_header_block.h" | |
| namespace quic { | |
| // QUIC server backend that understands MASQUE requests, but otherwise answers | |
| // HTTP queries using an in-memory cache. | |
| class QUIC_NO_EXPORT MasqueServerBackend : public QuicMemoryCacheBackend { | |
| public: | |
| // Interface meant to be implemented by the owner of the MasqueServerBackend | |
| // instance. | |
| class QUIC_NO_EXPORT BackendClient { | |
| public: | |
| virtual std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( | |
| const quiche::HttpHeaderBlock& request_headers, | |
| QuicSimpleServerBackend::RequestHandler* request_handler) = 0; | |
| virtual QuicSpdySession* GetQuicSpdySession() = 0; | |
| virtual ~BackendClient() = default; | |
| }; | |
| explicit MasqueServerBackend(MasqueMode masque_mode, | |
| const std::string& server_authority, | |
| const std::string& cache_directory); | |
| // Disallow copy and assign. | |
| MasqueServerBackend(const MasqueServerBackend&) = delete; | |
| MasqueServerBackend& operator=(const MasqueServerBackend&) = delete; | |
| // From QuicMemoryCacheBackend. | |
| void FetchResponseFromBackend( | |
| const quiche::HttpHeaderBlock& request_headers, | |
| const std::string& request_body, | |
| QuicSimpleServerBackend::RequestHandler* request_handler) override; | |
| void HandleConnectHeaders(const quiche::HttpHeaderBlock& request_headers, | |
| RequestHandler* request_handler) override; | |
| void CloseBackendResponseStream( | |
| QuicSimpleServerBackend::RequestHandler* request_handler) override; | |
| // Register backend client that can handle MASQUE requests. | |
| void RegisterBackendClient(BackendClient* backend_client); | |
| // Unregister backend client. | |
| void RemoveBackendClient(BackendClient* backend_client); | |
| // Provides a unique client IP address for each CONNECT-IP client. | |
| QuicIpAddress GetNextClientIpAddress(); | |
| // Pass in a list of key identifiers and hex-encoded public keys, separated | |
| // with colons and semicolons. For example: "kid1:0123...f;kid2:0123...f". | |
| void SetConcealedAuth(absl::string_view concealed_auth); | |
| // Returns whether any concealed auth credentials are configured. | |
| bool IsConcealedAuthEnabled() const { | |
| return !concealed_auth_credentials_.empty(); | |
| } | |
| // If the key ID is known, copies the corresponding public key to | |
| // out_public_key and returns true. Otherwise returns false. | |
| bool GetConcealedAuthKeyForId( | |
| absl::string_view key_id, | |
| uint8_t out_public_key[ED25519_PUBLIC_KEY_LEN]) const; | |
| // Enable concealed auth on all requests (e.g., GET) instead of just MASQUE. | |
| void SetConcealedAuthOnAllRequests(bool concealed_auth_on_all_requests) { | |
| concealed_auth_on_all_requests_ = concealed_auth_on_all_requests; | |
| } | |
| // Whether concealed auth is enabled on all requests (e.g., GET). | |
| bool IsConcealedAuthOnAllRequests() const { | |
| return concealed_auth_on_all_requests_; | |
| } | |
| // Configured DNS_ASSIGN capsule to send to CONNECT-IP clients upon | |
| // connection. | |
| void SetDnsAssignCapsule(const DnsAssignCapsule& capsule) { | |
| dns_assign_capsule_ = capsule; | |
| } | |
| const std::optional<DnsAssignCapsule>& dns_assign_capsule() const { | |
| return dns_assign_capsule_; | |
| } | |
| // Configured PREF64 capsule to send to CONNECT-IP clients upon connection. | |
| void SetPref64Capsule(const Pref64Capsule& capsule) { | |
| pref64_capsule_ = capsule; | |
| } | |
| const std::optional<Pref64Capsule>& pref64_capsule() const { | |
| return pref64_capsule_; | |
| } | |
| private: | |
| // Handle MASQUE request. | |
| bool MaybeHandleMasqueRequest( | |
| const quiche::HttpHeaderBlock& request_headers, | |
| QuicSimpleServerBackend::RequestHandler* request_handler); | |
| MasqueMode masque_mode_; | |
| std::string server_authority_; | |
| struct QUIC_NO_EXPORT BackendClientState { | |
| BackendClient* backend_client; | |
| std::vector<std::unique_ptr<QuicBackendResponse>> responses; | |
| }; | |
| std::vector<BackendClientState> backend_client_states_; | |
| uint8_t connect_ip_next_client_ip_[4]; | |
| struct QUIC_NO_EXPORT ConcealedAuthCredential { | |
| std::string key_id; | |
| uint8_t public_key[ED25519_PUBLIC_KEY_LEN]; | |
| }; | |
| std::list<ConcealedAuthCredential> concealed_auth_credentials_; | |
| bool concealed_auth_on_all_requests_ = false; | |
| std::optional<DnsAssignCapsule> dns_assign_capsule_; | |
| std::optional<Pref64Capsule> pref64_capsule_; | |
| }; | |
| } // namespace quic | |
| #endif // QUICHE_QUIC_MASQUE_MASQUE_SERVER_BACKEND_H_ |