• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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