1 // Copyright 2014 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 #ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_ 6 #define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_ 7 8 #include <string> 9 10 #include "absl/container/flat_hash_map.h" 11 #include "quiche/quic/core/http/quic_spdy_session.h" 12 #include "quiche/quic/core/quic_crypto_client_stream.h" 13 #include "quiche/quic/platform/api/quic_export.h" 14 #include "quiche/spdy/core/http2_header_block.h" 15 16 namespace quic { 17 18 class QuicClientPromisedInfo; 19 class QuicClientPushPromiseIndex; 20 class QuicSpdyClientStream; 21 22 // For client/http layer code. Lookup promised streams based on 23 // matching promised request url. The same map can be shared across 24 // multiple sessions, since cross-origin pushes are allowed (subject 25 // to authority constraints). Clients should use this map to enforce 26 // session affinity for requests corresponding to cross-origin push 27 // promised streams. 28 using QuicPromisedByUrlMap = 29 absl::flat_hash_map<std::string, QuicClientPromisedInfo*>; 30 31 // The maximum time a promises stream can be reserved without being 32 // claimed by a client request. 33 const int64_t kPushPromiseTimeoutSecs = 60; 34 35 // Base class for all client-specific QuicSession subclasses. 36 class QUIC_EXPORT_PRIVATE QuicSpdyClientSessionBase 37 : public QuicSpdySession, 38 public QuicCryptoClientStream::ProofHandler { 39 public: 40 // Takes ownership of |connection|. Caller retains ownership of 41 // |promised_by_url|. 42 QuicSpdyClientSessionBase(QuicConnection* connection, 43 QuicSession::Visitor* visitor, 44 QuicClientPushPromiseIndex* push_promise_index, 45 const QuicConfig& config, 46 const ParsedQuicVersionVector& supported_versions); 47 QuicSpdyClientSessionBase(const QuicSpdyClientSessionBase&) = delete; 48 QuicSpdyClientSessionBase& operator=(const QuicSpdyClientSessionBase&) = 49 delete; 50 51 ~QuicSpdyClientSessionBase() override; 52 53 void OnConfigNegotiated() override; 54 55 // Called by |headers_stream_| when push promise headers have been 56 // completely received. 57 void OnPromiseHeaderList(QuicStreamId stream_id, 58 QuicStreamId promised_stream_id, size_t frame_len, 59 const QuicHeaderList& header_list) override; 60 61 // Called by |QuicSpdyClientStream| on receipt of response headers, 62 // needed to detect promised server push streams, as part of 63 // client-request to push-stream rendezvous. 64 void OnInitialHeadersComplete(QuicStreamId stream_id, 65 const spdy::Http2HeaderBlock& response_headers); 66 67 // Called by |QuicSpdyClientStream| on receipt of PUSH_PROMISE, does 68 // some session level validation and creates the 69 // |QuicClientPromisedInfo| inserting into maps by (promised) id and 70 // url. Returns true if a new push promise is accepted. Resets the promised 71 // stream and returns false otherwise. 72 virtual bool HandlePromised(QuicStreamId associated_id, 73 QuicStreamId promised_id, 74 const spdy::Http2HeaderBlock& headers); 75 76 // For cross-origin server push, this should verify the server is 77 // authoritative per [RFC2818], Section 3. Roughly, subjectAltName 78 // list in the certificate should contain a matching DNS name, or IP 79 // address. |hostname| is derived from the ":authority" header field of 80 // the PUSH_PROMISE frame, port if present there will be dropped. 81 virtual bool IsAuthorized(const std::string& hostname) = 0; 82 83 // Session retains ownership. 84 QuicClientPromisedInfo* GetPromisedByUrl(const std::string& url); 85 // Session retains ownership. 86 QuicClientPromisedInfo* GetPromisedById(const QuicStreamId id); 87 88 // 89 QuicSpdyStream* GetPromisedStream(const QuicStreamId id); 90 91 // Removes |promised| from the maps by url. 92 void ErasePromisedByUrl(QuicClientPromisedInfo* promised); 93 94 // Removes |promised| from the maps by url and id and destroys 95 // promised. 96 virtual void DeletePromised(QuicClientPromisedInfo* promised); 97 98 virtual void OnPushStreamTimedOut(QuicStreamId stream_id); 99 100 // Sends Rst for the stream, and makes sure that future calls to 101 // IsClosedStream(id) return true, which ensures that any subsequent 102 // frames related to this stream will be ignored (modulo flow 103 // control accounting). 104 void ResetPromised(QuicStreamId id, QuicRstStreamErrorCode error_code); 105 106 // Release headers stream's sequencer buffer if it's empty. 107 void OnStreamClosed(QuicStreamId stream_id) override; 108 109 // Returns true if there are no active requests and no promised streams. 110 bool ShouldReleaseHeadersStreamSequencerBuffer() override; 111 112 // Override to wait for all received responses to be consumed by application. 113 bool ShouldKeepConnectionAlive() const override; 114 get_max_promises()115 size_t get_max_promises() const { 116 return max_open_incoming_unidirectional_streams() * 117 kMaxPromisedStreamsMultiplier; 118 } 119 push_promise_index()120 QuicClientPushPromiseIndex* push_promise_index() { 121 return push_promise_index_; 122 } 123 124 // Override to serialize the settings and pass it down to the handshaker. 125 bool OnSettingsFrame(const SettingsFrame& frame) override; 126 127 private: 128 // For QuicSpdyClientStream to detect that a response corresponds to a 129 // promise. 130 using QuicPromisedByIdMap = 131 absl::flat_hash_map<QuicStreamId, 132 std::unique_ptr<QuicClientPromisedInfo>>; 133 134 // As per rfc7540, section 10.5: track promise streams in "reserved 135 // (remote)". The primary key is URL from the promise request 136 // headers. The promised stream id is a secondary key used to get 137 // promise info when the response headers of the promised stream 138 // arrive. 139 QuicClientPushPromiseIndex* push_promise_index_; 140 QuicPromisedByIdMap promised_by_id_; 141 QuicStreamId largest_promised_stream_id_; 142 }; 143 144 } // namespace quic 145 146 #endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_CLIENT_SESSION_BASE_H_ 147