1 // Copyright 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_PUSH_PROMISE_INDEX_H_ 6 #define QUICHE_QUIC_CORE_HTTP_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_ 7 8 #include <string> 9 10 #include "quiche/quic/core/http/quic_spdy_client_session_base.h" 11 #include "quiche/quic/core/quic_types.h" 12 #include "quiche/quic/platform/api/quic_export.h" 13 #include "quiche/spdy/core/http2_header_block.h" 14 15 namespace quic { 16 17 // QuicClientPushPromiseIndex is the interface to support rendezvous 18 // between client requests and resources delivered via server push. 19 // The same index can be shared across multiple sessions (e.g. for the 20 // same browser users profile), since cross-origin pushes are allowed 21 // (subject to authority constraints). 22 23 class QUIC_EXPORT_PRIVATE QuicClientPushPromiseIndex { 24 public: 25 // Delegate is used to complete the rendezvous that began with 26 // |Try()|. 27 class QUIC_EXPORT_PRIVATE Delegate { 28 public: ~Delegate()29 virtual ~Delegate() {} 30 31 // The primary lookup matched request with push promise by URL. A 32 // secondary match is necessary to ensure Vary (RFC 2616, 14.14) 33 // is honored. If Vary is not present, return true. If Vary is 34 // present, return whether designated header fields of 35 // |promise_request| and |client_request| match. 36 virtual bool CheckVary(const spdy::Http2HeaderBlock& client_request, 37 const spdy::Http2HeaderBlock& promise_request, 38 const spdy::Http2HeaderBlock& promise_response) = 0; 39 40 // On rendezvous success, provides the promised |stream|. Callee 41 // does not inherit ownership of |stream|. On rendezvous failure, 42 // |stream| is |nullptr| and the client should retry the request. 43 // Rendezvous can fail due to promise validation failure or RST on 44 // promised stream. |url| will have been removed from the index 45 // before |OnRendezvousResult()| is invoked, so a recursive call to 46 // |Try()| will return |QUIC_FAILURE|, which may be convenient for 47 // retry purposes. 48 virtual void OnRendezvousResult(QuicSpdyStream* stream) = 0; 49 }; 50 51 class QUIC_EXPORT_PRIVATE TryHandle { 52 public: 53 // Cancel the request. 54 virtual void Cancel() = 0; 55 56 protected: TryHandle()57 TryHandle() {} 58 TryHandle(const TryHandle&) = delete; 59 TryHandle& operator=(const TryHandle&) = delete; 60 ~TryHandle(); 61 }; 62 63 QuicClientPushPromiseIndex(); 64 QuicClientPushPromiseIndex(const QuicClientPushPromiseIndex&) = delete; 65 QuicClientPushPromiseIndex& operator=(const QuicClientPushPromiseIndex&) = 66 delete; 67 virtual ~QuicClientPushPromiseIndex(); 68 69 // Called by client code, used to enforce affinity between requests 70 // for promised streams and the session the promise came from. 71 QuicClientPromisedInfo* GetPromised(const std::string& url); 72 73 // Called by client code, to initiate rendezvous between a request 74 // and a server push stream. If |request|'s url is in the index, 75 // rendezvous will be attempted and may complete immediately or 76 // asynchronously. If the matching promise and response headers 77 // have already arrived, the delegate's methods will fire 78 // recursively from within |Try()|. Returns |QUIC_SUCCESS| if the 79 // rendezvous was a success. Returns |QUIC_FAILURE| if there was no 80 // matching promise, or if there was but the rendezvous has failed. 81 // Returns QUIC_PENDING if a matching promise was found, but the 82 // rendezvous needs to complete asynchronously because the promised 83 // response headers are not yet available. If result is 84 // QUIC_PENDING, then |*handle| will set so that the caller may 85 // cancel the request if need be. The caller does not inherit 86 // ownership of |*handle|, and it ceases to be valid if the caller 87 // invokes |handle->Cancel()| or if |delegate->OnReponse()| fires. 88 QuicAsyncStatus Try(const spdy::Http2HeaderBlock& request, Delegate* delegate, 89 TryHandle** handle); 90 promised_by_url()91 QuicPromisedByUrlMap* promised_by_url() { return &promised_by_url_; } 92 93 private: 94 QuicPromisedByUrlMap promised_by_url_; 95 }; 96 97 } // namespace quic 98 99 #endif // QUICHE_QUIC_CORE_HTTP_QUIC_CLIENT_PUSH_PROMISE_INDEX_H_ 100