1 // Copyright (c) 2016 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_CLIENT_PROMISED_INFO_H_ 6 #define QUICHE_QUIC_CORE_HTTP_QUIC_CLIENT_PROMISED_INFO_H_ 7 8 #include <cstddef> 9 #include <string> 10 11 #include "quiche/quic/core/http/quic_client_push_promise_index.h" 12 #include "quiche/quic/core/http/quic_spdy_client_session_base.h" 13 #include "quiche/quic/core/http/quic_spdy_stream.h" 14 #include "quiche/quic/core/quic_alarm.h" 15 #include "quiche/quic/core/quic_packets.h" 16 #include "quiche/quic/platform/api/quic_export.h" 17 #include "quiche/spdy/core/http2_header_block.h" 18 #include "quiche/spdy/core/spdy_framer.h" 19 20 namespace quic { 21 22 namespace test { 23 class QuicClientPromisedInfoPeer; 24 } // namespace test 25 26 // QuicClientPromisedInfo tracks the client state of a server push 27 // stream from the time a PUSH_PROMISE is received until rendezvous 28 // between the promised response and the corresponding client request 29 // is complete. 30 class QUIC_EXPORT_PRIVATE QuicClientPromisedInfo 31 : public QuicClientPushPromiseIndex::TryHandle { 32 public: 33 // Interface to QuicSpdyClientStream 34 QuicClientPromisedInfo(QuicSpdyClientSessionBase* session, QuicStreamId id, 35 std::string url); 36 QuicClientPromisedInfo(const QuicClientPromisedInfo&) = delete; 37 QuicClientPromisedInfo& operator=(const QuicClientPromisedInfo&) = delete; 38 virtual ~QuicClientPromisedInfo(); 39 40 void Init(); 41 42 // Validate promise headers etc. Returns true if headers are valid. 43 bool OnPromiseHeaders(const spdy::Http2HeaderBlock& headers); 44 45 // Store response, possibly proceed with final validation. 46 void OnResponseHeaders(const spdy::Http2HeaderBlock& headers); 47 48 // Rendezvous between this promised stream and a client request that 49 // has a matching URL. 50 virtual QuicAsyncStatus HandleClientRequest( 51 const spdy::Http2HeaderBlock& headers, 52 QuicClientPushPromiseIndex::Delegate* delegate); 53 54 void Cancel() override; 55 56 void Reset(QuicRstStreamErrorCode error_code); 57 58 // Client requests are initially associated to promises by matching 59 // URL in the client request against the URL in the promise headers, 60 // uing the |promised_by_url| map. The push can be cross-origin, so 61 // the client should validate that the session is authoritative for 62 // the promised URL. If not, it should call |RejectUnauthorized|. session()63 QuicSpdyClientSessionBase* session() { return session_; } 64 65 // If the promised response contains Vary header, then the fields 66 // specified by Vary must match between the client request header 67 // and the promise headers (see https://crbug.com//554220). Vary 68 // validation requires the response headers (for the actual Vary 69 // field list), the promise headers (taking the role of the "cached" 70 // request), and the client request headers. request_headers()71 spdy::Http2HeaderBlock* request_headers() { return &request_headers_; } 72 response_headers()73 spdy::Http2HeaderBlock* response_headers() { return response_headers_.get(); } 74 75 // After validation, client will use this to access the pushed stream. 76 id()77 QuicStreamId id() const { return id_; } 78 url()79 const std::string url() const { return url_; } 80 81 // Return true if there's a request pending matching this push promise. is_validating()82 bool is_validating() const { return client_request_delegate_ != nullptr; } 83 84 private: 85 friend class test::QuicClientPromisedInfoPeer; 86 87 class QUIC_EXPORT_PRIVATE CleanupAlarm 88 : public QuicAlarm::DelegateWithoutContext { 89 public: CleanupAlarm(QuicClientPromisedInfo * promised)90 explicit CleanupAlarm(QuicClientPromisedInfo* promised) 91 : promised_(promised) {} 92 93 void OnAlarm() override; 94 95 QuicClientPromisedInfo* promised_; 96 }; 97 98 QuicAsyncStatus FinalValidation(); 99 100 QuicSpdyClientSessionBase* session_; 101 QuicStreamId id_; 102 std::string url_; 103 spdy::Http2HeaderBlock request_headers_; 104 std::unique_ptr<spdy::Http2HeaderBlock> response_headers_; 105 spdy::Http2HeaderBlock client_request_headers_; 106 QuicClientPushPromiseIndex::Delegate* client_request_delegate_; 107 108 // The promise will commit suicide eventually if it is not claimed by a GET 109 // first. 110 std::unique_ptr<QuicAlarm> cleanup_alarm_; 111 }; 112 113 } // namespace quic 114 115 #endif // QUICHE_QUIC_CORE_HTTP_QUIC_CLIENT_PROMISED_INFO_H_ 116