http2_push_promise_index.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2017 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. #ifndef NET_SPDY_HTTP2_PUSH_PROMISE_INDEX_H_
  5. #define NET_SPDY_HTTP2_PUSH_PROMISE_INDEX_H_
  6. #include <set>
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "net/base/net_export.h"
  10. #include "net/http/http_request_info.h"
  11. #include "net/spdy/spdy_session_key.h"
  12. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
  13. #include "url/gurl.h"
  14. namespace net {
  15. class SpdySession;
  16. namespace test {
  17. class Http2PushPromiseIndexPeer;
  18. } // namespace test
  19. // Value returned by ClaimPushedStream() and FindStream() if no stream is found.
  20. const spdy::SpdyStreamId kNoPushedStreamFound = 0;
  21. // This class manages unclaimed pushed streams (push promises) from the receipt
  22. // of PUSH_PROMISE frame until they are matched to a request.
  23. // Each SpdySessionPool owns one instance of this class.
  24. // SpdySession uses this class to register, unregister and query pushed streams.
  25. // HttpStreamFactory::Job uses this class to find a SpdySession with a pushed
  26. // stream matching the request, if such exists.
  27. class NET_EXPORT Http2PushPromiseIndex {
  28. public:
  29. // Interface for validating pushed streams, signaling when a pushed stream is
  30. // claimed, and generating SpdySession weak pointer.
  31. class NET_EXPORT Delegate {
  32. public:
  33. Delegate() = default;
  34. Delegate(const Delegate&) = delete;
  35. Delegate& operator=(const Delegate&) = delete;
  36. virtual ~Delegate() = default;
  37. // Return true if a pushed stream with |url| can be used for a request with
  38. // |key|.
  39. virtual bool ValidatePushedStream(spdy::SpdyStreamId stream_id,
  40. const GURL& url,
  41. const HttpRequestInfo& request_info,
  42. const SpdySessionKey& key) const = 0;
  43. // Generate weak pointer. Guaranateed to be called synchronously after
  44. // ValidatePushedStream() is called and returns true.
  45. virtual base::WeakPtr<SpdySession> GetWeakPtrToSession() = 0;
  46. };
  47. Http2PushPromiseIndex();
  48. Http2PushPromiseIndex(const Http2PushPromiseIndex&) = delete;
  49. Http2PushPromiseIndex& operator=(const Http2PushPromiseIndex&) = delete;
  50. ~Http2PushPromiseIndex();
  51. // Tries to register a Delegate with an unclaimed pushed stream for |url|.
  52. // Caller must make sure |delegate| stays valid by unregistering the exact
  53. // same entry before |delegate| is destroyed.
  54. // Returns true if there is no unclaimed pushed stream with the same URL for
  55. // the same Delegate, in which case the stream is registered.
  56. [[nodiscard]] bool RegisterUnclaimedPushedStream(const GURL& url,
  57. spdy::SpdyStreamId stream_id,
  58. Delegate* delegate);
  59. // Tries to unregister a Delegate with an unclaimed pushed stream for |url|
  60. // with given |stream_id|.
  61. // Returns true if this exact entry is found, in which case it is removed.
  62. [[nodiscard]] bool UnregisterUnclaimedPushedStream(
  63. const GURL& url,
  64. spdy::SpdyStreamId stream_id,
  65. Delegate* delegate);
  66. // Returns the number of pushed streams registered for |delegate|.
  67. size_t CountStreamsForSession(const Delegate* delegate) const;
  68. // Returns the stream ID of the entry registered for |delegate| with |url|,
  69. // or kNoPushedStreamFound if no such entry exists.
  70. spdy::SpdyStreamId FindStream(const GURL& url,
  71. const Delegate* delegate) const;
  72. // If there exists a session compatible with |key| that has an unclaimed push
  73. // stream for |url|, then sets |*session| and |*stream| to one such session
  74. // and stream, and removes entry from index. Makes no guarantee on which
  75. // (session, stream_id) pair is claimed if there are multiple matches. Sets
  76. // |*session| to nullptr and |*stream| to kNoPushedStreamFound if no such
  77. // session exists.
  78. void ClaimPushedStream(const SpdySessionKey& key,
  79. const GURL& url,
  80. const HttpRequestInfo& request_info,
  81. base::WeakPtr<SpdySession>* session,
  82. spdy::SpdyStreamId* stream_id);
  83. private:
  84. friend test::Http2PushPromiseIndexPeer;
  85. // An unclaimed pushed stream entry.
  86. struct NET_EXPORT UnclaimedPushedStream {
  87. GURL url;
  88. raw_ptr<Delegate> delegate;
  89. spdy::SpdyStreamId stream_id;
  90. };
  91. // Function object satisfying the requirements of "Compare", see
  92. // http://en.cppreference.com/w/cpp/concept/Compare.
  93. // A set ordered by this function object supports O(log n) lookup
  94. // of the first entry with a given URL, by calling lower_bound() with an entry
  95. // with that URL and with delegate = nullptr.
  96. struct NET_EXPORT CompareByUrl {
  97. bool operator()(const UnclaimedPushedStream& a,
  98. const UnclaimedPushedStream& b) const;
  99. };
  100. // Collection of all unclaimed pushed streams. Delegate must unregister
  101. // its streams before destruction, so that all pointers remain valid.
  102. // Each Delegate can have at most one pushed stream for each URL (but each
  103. // Delegate can have pushed streams for different URLs, and different
  104. // Delegates can have pushed streams for the same GURL).
  105. std::set<UnclaimedPushedStream, CompareByUrl> unclaimed_pushed_streams_;
  106. };
  107. } // namespace net
  108. #endif // NET_SPDY_HTTP2_PUSH_PROMISE_INDEX_H_