spdy_stream.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. // Copyright (c) 2012 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_SPDY_STREAM_H_
  5. #define NET_SPDY_SPDY_STREAM_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/time/time.h"
  15. #include "net/base/io_buffer.h"
  16. #include "net/base/net_export.h"
  17. #include "net/base/request_priority.h"
  18. #include "net/log/net_log_source.h"
  19. #include "net/log/net_log_with_source.h"
  20. #include "net/socket/next_proto.h"
  21. #include "net/socket/ssl_client_socket.h"
  22. #include "net/spdy/spdy_buffer.h"
  23. #include "net/ssl/ssl_client_cert_type.h"
  24. #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h"
  25. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h"
  26. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h"
  27. #include "net/traffic_annotation/network_traffic_annotation.h"
  28. #include "url/gurl.h"
  29. namespace net {
  30. namespace test {
  31. class SpdyStreamTest;
  32. }
  33. class IPEndPoint;
  34. struct LoadTimingInfo;
  35. class SSLInfo;
  36. class SpdySession;
  37. enum SpdyStreamType {
  38. // The most general type of stream; there are no restrictions on
  39. // when data can be sent and received.
  40. SPDY_BIDIRECTIONAL_STREAM,
  41. // A stream where the client sends a request with possibly a body,
  42. // and the server then sends a response with a body.
  43. SPDY_REQUEST_RESPONSE_STREAM,
  44. // A server-initiated stream where the server just sends a response
  45. // with a body and the client does not send anything.
  46. SPDY_PUSH_STREAM
  47. };
  48. // Passed to some SpdyStream functions to indicate whether there's
  49. // more data to send.
  50. enum SpdySendStatus {
  51. MORE_DATA_TO_SEND,
  52. NO_MORE_DATA_TO_SEND
  53. };
  54. // SpdyStream is owned by SpdySession and is used to represent each stream known
  55. // on the SpdySession. This class provides interfaces for SpdySession to use.
  56. // Streams can be created either by the client or by the server. When they
  57. // are initiated by the client, both the SpdySession and client object (such as
  58. // a SpdyNetworkTransaction) will maintain a reference to the stream. When
  59. // initiated by the server, only the SpdySession will maintain any reference,
  60. // until such a time as a client object requests a stream for the path.
  61. class NET_EXPORT_PRIVATE SpdyStream {
  62. public:
  63. // Delegate handles protocol specific behavior of spdy stream.
  64. class NET_EXPORT_PRIVATE Delegate {
  65. public:
  66. Delegate() = default;
  67. Delegate(const Delegate&) = delete;
  68. Delegate& operator=(const Delegate&) = delete;
  69. // Called when the request headers have been sent. Never called
  70. // for push streams. Must not cause the stream to be closed.
  71. virtual void OnHeadersSent() = 0;
  72. // OnEarlyHintsReceived(), OnHeadersReceived(), OnDataReceived(),
  73. // OnTrailers(), and OnClose() are guaranteed to be called in the following
  74. // order:
  75. // - OnEarlyHintsReceived() zero or more times;
  76. // - OnHeadersReceived() exactly once;
  77. // - OnDataReceived() zero or more times;
  78. // - OnTrailers() zero or one times;
  79. // - OnClose() exactly once.
  80. // Called when a 103 Early Hints response is received.
  81. virtual void OnEarlyHintsReceived(
  82. const spdy::Http2HeaderBlock& headers) = 0;
  83. // Called when response headers have been received. In case of a pushed
  84. // stream, the pushed request headers are also passed.
  85. virtual void OnHeadersReceived(
  86. const spdy::Http2HeaderBlock& response_headers,
  87. const spdy::Http2HeaderBlock* pushed_request_headers) = 0;
  88. // Called when data is received. |buffer| may be NULL, which signals EOF.
  89. // May cause the stream to be closed.
  90. virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0;
  91. // Called when data is sent. Must not cause the stream to be closed.
  92. virtual void OnDataSent() = 0;
  93. // Called when trailers are received.
  94. virtual void OnTrailers(const spdy::Http2HeaderBlock& trailers) = 0;
  95. // Called when SpdyStream is closed. No other delegate functions
  96. // will be called after this is called, and the delegate must not
  97. // access the stream after this is called. Must not cause the
  98. // stream to be (re-)closed.
  99. //
  100. // TODO(akalin): Allow this function to re-close the stream and
  101. // handle it gracefully.
  102. virtual void OnClose(int status) = 0;
  103. // Returns whether it is allowed to send greased (reserved type) frames on
  104. // the HTTP/2 stream.
  105. virtual bool CanGreaseFrameType() const = 0;
  106. virtual NetLogSource source_dependency() const = 0;
  107. protected:
  108. virtual ~Delegate() = default;
  109. };
  110. // SpdyStream constructor
  111. SpdyStream(SpdyStreamType type,
  112. const base::WeakPtr<SpdySession>& session,
  113. const GURL& url,
  114. RequestPriority priority,
  115. int32_t initial_send_window_size,
  116. int32_t max_recv_window_size,
  117. const NetLogWithSource& net_log,
  118. const NetworkTrafficAnnotationTag& traffic_annotation,
  119. bool detect_broken_connection);
  120. SpdyStream(const SpdyStream&) = delete;
  121. SpdyStream& operator=(const SpdyStream&) = delete;
  122. ~SpdyStream();
  123. // Set the delegate, which must not be NULL. Must not be called more
  124. // than once. For push streams, calling this may cause buffered data
  125. // to be sent to the delegate (from a posted task).
  126. void SetDelegate(Delegate* delegate);
  127. // Detach the delegate from the stream, which must not yet be
  128. // closed, and cancel it.
  129. void DetachDelegate();
  130. // The time at which the first bytes of the response were received
  131. // from the server, or null if the response hasn't been received
  132. // yet.
  133. base::Time response_time() const { return response_time_; }
  134. SpdyStreamType type() const { return type_; }
  135. spdy::SpdyStreamId stream_id() const { return stream_id_; }
  136. void set_stream_id(spdy::SpdyStreamId stream_id) { stream_id_ = stream_id; }
  137. const GURL& url() const { return url_; }
  138. RequestPriority priority() const { return priority_; }
  139. // Update priority and send PRIORITY frames on the wire if necessary.
  140. void SetPriority(RequestPriority priority);
  141. int32_t send_window_size() const { return send_window_size_; }
  142. int32_t recv_window_size() const { return recv_window_size_; }
  143. bool send_stalled_by_flow_control() const {
  144. return send_stalled_by_flow_control_;
  145. }
  146. void set_send_stalled_by_flow_control(bool stalled) {
  147. send_stalled_by_flow_control_ = stalled;
  148. }
  149. // Called by the session to adjust this stream's send window size by
  150. // |delta_window_size|, which is the difference between the
  151. // spdy::SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame
  152. // and the previous initial send window size, possibly unstalling
  153. // this stream. Although |delta_window_size| may cause this stream's
  154. // send window size to go negative, it must not cause it to wrap
  155. // around in either direction. Does nothing if the stream is already
  156. // closed.
  157. // Returns true if successful. Returns false if |send_window_size_|
  158. // would exceed 2^31-1 after the update, see RFC7540 Section 6.9.2.
  159. // Note that |send_window_size_| should not possibly underflow.
  160. [[nodiscard]] bool AdjustSendWindowSize(int32_t delta_window_size);
  161. // Called when bytes are consumed from a SpdyBuffer for a DATA frame
  162. // that is to be written or is being written. Increases the send
  163. // window size accordingly if some or all of the SpdyBuffer is being
  164. // discarded.
  165. //
  166. // If stream flow control is turned off, this must not be called.
  167. void OnWriteBufferConsumed(size_t frame_payload_size,
  168. size_t consume_size,
  169. SpdyBuffer::ConsumeSource consume_source);
  170. // Called by the session to increase this stream's send window size
  171. // by |delta_window_size| (which must be at least 1) from a received
  172. // WINDOW_UPDATE frame or from a dropped DATA frame that was
  173. // intended to be sent, possibly unstalling this stream. If
  174. // |delta_window_size| would cause this stream's send window size to
  175. // overflow, calls into the session to reset this stream. Does
  176. // nothing if the stream is already closed.
  177. //
  178. // If stream flow control is turned off, this must not be called.
  179. void IncreaseSendWindowSize(int32_t delta_window_size);
  180. // If stream flow control is turned on, called by the session to
  181. // decrease this stream's send window size by |delta_window_size|,
  182. // which must be at least 0 and at most kMaxSpdyFrameChunkSize.
  183. // |delta_window_size| must not cause this stream's send window size
  184. // to go negative. Does nothing if the stream is already closed.
  185. //
  186. // If stream flow control is turned off, this must not be called.
  187. void DecreaseSendWindowSize(int32_t delta_window_size);
  188. // Called when bytes are consumed by the delegate from a SpdyBuffer
  189. // containing received data. Increases the receive window size
  190. // accordingly.
  191. //
  192. // If stream flow control is turned off, this must not be called.
  193. void OnReadBufferConsumed(size_t consume_size,
  194. SpdyBuffer::ConsumeSource consume_source);
  195. // Called by OnReadBufferConsume to increase this stream's receive
  196. // window size by |delta_window_size|, which must be at least 1 and
  197. // must not cause this stream's receive window size to overflow,
  198. // possibly also sending a WINDOW_UPDATE frame. Does nothing if the
  199. // stream is not active.
  200. //
  201. // If stream flow control is turned off, this must not be called.
  202. void IncreaseRecvWindowSize(int32_t delta_window_size);
  203. // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by
  204. // the session) to decrease this stream's receive window size by
  205. // |delta_window_size|, which must be at least 1. May close the stream on
  206. // flow control error.
  207. //
  208. // If stream flow control is turned off or the stream is not active,
  209. // this must not be called.
  210. void DecreaseRecvWindowSize(int32_t delta_window_size);
  211. int GetPeerAddress(IPEndPoint* address) const;
  212. int GetLocalAddress(IPEndPoint* address) const;
  213. // Returns true if the underlying transport socket ever had any reads or
  214. // writes.
  215. bool WasEverUsed() const;
  216. const NetLogWithSource& net_log() const { return net_log_; }
  217. base::Time GetRequestTime() const;
  218. void SetRequestTime(base::Time t);
  219. // Called by SpdySession when headers are received for this stream. May close
  220. // the stream.
  221. void OnHeadersReceived(const spdy::Http2HeaderBlock& response_headers,
  222. base::Time response_time,
  223. base::TimeTicks recv_first_byte_time);
  224. // Called by the SpdySession when a frame carrying request headers opening a
  225. // push stream is received. Stream transits to STATE_RESERVED_REMOTE state.
  226. void OnPushPromiseHeadersReceived(spdy::Http2HeaderBlock headers, GURL url);
  227. // Called by the SpdySession when response data has been received
  228. // for this stream. This callback may be called multiple times as
  229. // data arrives from the network, and will never be called prior to
  230. // OnResponseHeadersReceived.
  231. //
  232. // |buffer| contains the data received, or NULL if the stream is
  233. // being closed. The stream must copy any data from this
  234. // buffer before returning from this callback.
  235. //
  236. // |length| is the number of bytes received (at most 2^24 - 1) or 0 if
  237. // the stream is being closed.
  238. void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer);
  239. // Called by the SpdySession when padding is consumed to allow for the stream
  240. // receiving window to be updated.
  241. void OnPaddingConsumed(size_t len);
  242. // Called by the SpdySession when a frame has been successfully and completely
  243. // written. |frame_size| is the total size of the logical frame in bytes,
  244. // including framing overhead. For fragmented headers, this is the total size
  245. // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames.
  246. void OnFrameWriteComplete(spdy::SpdyFrameType frame_type, size_t frame_size);
  247. // HEADERS-specific write handler invoked by OnFrameWriteComplete().
  248. int OnHeadersSent();
  249. // DATA-specific write handler invoked by OnFrameWriteComplete().
  250. // If more data is already available to be written, the next write is
  251. // queued and ERR_IO_PENDING is returned. Returns OK otherwise.
  252. int OnDataSent(size_t frame_size);
  253. // Called by the SpdySession when the request is finished. This callback
  254. // will always be called at the end of the request and signals to the
  255. // stream that the stream has no more network events. No further callbacks
  256. // to the stream will be made after this call. Must be called before
  257. // SpdyStream is destroyed.
  258. // |status| is an error code or OK.
  259. void OnClose(int status);
  260. // Called by the SpdySession to log stream related errors.
  261. void LogStreamError(int error, base::StringPiece description);
  262. // If this stream is active, reset it, and close it otherwise. In
  263. // either case the stream is deleted.
  264. void Cancel(int error);
  265. // Close this stream without sending a RST_STREAM and delete
  266. // it.
  267. void Close();
  268. // Must be used only by |session_|.
  269. base::WeakPtr<SpdyStream> GetWeakPtr();
  270. // Interface for the delegate to use.
  271. // Only one send can be in flight at a time, except for push
  272. // streams, which must not send anything.
  273. // Sends the request headers. The delegate is called back via OnHeadersSent()
  274. // when the request headers have completed sending. |send_status| must be
  275. // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams,
  276. // it must be MORE_DATA_TO_SEND if the request has data to upload, or
  277. // NO_MORE_DATA_TO_SEND if not.
  278. int SendRequestHeaders(spdy::Http2HeaderBlock request_headers,
  279. SpdySendStatus send_status);
  280. // Sends a DATA frame. The delegate will be notified via
  281. // OnDataSent() when the send is complete. |send_status| must be
  282. // MORE_DATA_TO_SEND for bidirectional streams; for request/response
  283. // streams, it must be MORE_DATA_TO_SEND if there is more data to
  284. // upload, or NO_MORE_DATA_TO_SEND if not.
  285. // Must not be called until Delegate::OnHeadersSent() is called.
  286. void SendData(IOBuffer* data, int length, SpdySendStatus send_status);
  287. // Fills SSL info in |ssl_info| and returns true when SSL is in use.
  288. bool GetSSLInfo(SSLInfo* ssl_info) const;
  289. // Returns true if ALPN was negotiated for the underlying socket.
  290. bool WasAlpnNegotiated() const;
  291. // Returns the protocol negotiated via ALPN for the underlying socket.
  292. NextProto GetNegotiatedProtocol() const;
  293. // If the stream is stalled on sending data, but the session is not
  294. // stalled on sending data and |send_window_size_| is positive, then
  295. // set |send_stalled_by_flow_control_| to false and unstall the data
  296. // sending. Called by the session or by the stream itself. Must be
  297. // called only when the stream is still open.
  298. enum ShouldRequeueStream { Requeue, DoNotRequeue };
  299. ShouldRequeueStream PossiblyResumeIfSendStalled();
  300. // Returns whether or not this stream is closed. Note that the only
  301. // time a stream is closed and not deleted is in its delegate's
  302. // OnClose() method.
  303. bool IsClosed() const;
  304. // Returns whether the streams local endpoint is closed.
  305. // The remote endpoint may still be active.
  306. bool IsLocallyClosed() const;
  307. // Returns whether this stream is IDLE: request and response headers
  308. // have neither been sent nor receieved.
  309. bool IsIdle() const;
  310. // Returns whether or not this stream is fully open: that request and
  311. // response headers are complete, and it is not in a half-closed state.
  312. bool IsOpen() const;
  313. // Returns whether the stream is reserved by remote endpoint: server has sent
  314. // intended request headers for a pushed stream, but haven't started response
  315. // yet.
  316. bool IsReservedRemote() const;
  317. void AddRawReceivedBytes(size_t received_bytes);
  318. void AddRawSentBytes(size_t sent_bytes);
  319. int64_t raw_received_bytes() const { return raw_received_bytes_; }
  320. int64_t raw_sent_bytes() const { return raw_sent_bytes_; }
  321. int recv_bytes() const { return recv_bytes_; }
  322. bool ShouldRetryRSTPushStream() const;
  323. bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
  324. const spdy::Http2HeaderBlock& request_headers() const {
  325. return request_headers_;
  326. }
  327. const spdy::Http2HeaderBlock& response_headers() const {
  328. return response_headers_;
  329. }
  330. const NetworkTrafficAnnotationTag traffic_annotation() const {
  331. return traffic_annotation_;
  332. }
  333. bool detect_broken_connection() const { return detect_broken_connection_; }
  334. private:
  335. friend class test::SpdyStreamTest;
  336. class HeadersBufferProducer;
  337. // SpdyStream states and transitions are modeled
  338. // on the HTTP/2 stream state machine. All states and transitions
  339. // are modeled, with the exceptions of RESERVED_LOCAL (the client
  340. // cannot initate push streams), and the transition to OPEN due to
  341. // a remote HEADERS (the client can only initate streams).
  342. enum State {
  343. STATE_IDLE,
  344. STATE_OPEN,
  345. STATE_HALF_CLOSED_LOCAL_UNCLAIMED,
  346. STATE_HALF_CLOSED_LOCAL,
  347. STATE_HALF_CLOSED_REMOTE,
  348. STATE_RESERVED_REMOTE,
  349. STATE_CLOSED,
  350. };
  351. // Per RFC 7540 Section 8.1, an HTTP response consists of:
  352. // * zero or more header blocks with informational (1xx) HTTP status,
  353. // * one header block,
  354. // * zero or more DATA frames,
  355. // * zero or one header block ("trailers").
  356. // Each header block must have a ":status" header field. SpdyStream enforces
  357. // these requirements, and resets the stream if they are not met.
  358. enum ResponseState {
  359. READY_FOR_HEADERS,
  360. READY_FOR_DATA_OR_TRAILERS,
  361. TRAILERS_RECEIVED
  362. };
  363. // When a server-push stream is claimed by SetDelegate(), this function is
  364. // posted on the current MessageLoop to replay everything the server has sent.
  365. // From the perspective of SpdyStream's state machine, headers, data, and
  366. // FIN states received prior to the delegate being attached have not yet been
  367. // read. While buffered by |pending_recv_data_| it's not until
  368. // PushedStreamReplay() is invoked that reads are considered
  369. // to have occurred, driving the state machine forward.
  370. void PushedStreamReplay();
  371. // Produces the HEADERS frame for the stream. The stream must
  372. // already be activated.
  373. std::unique_ptr<spdy::SpdySerializedFrame> ProduceHeadersFrame();
  374. // Queues the send for next frame of the remaining data in
  375. // |pending_send_data_|. Must be called only when
  376. // |pending_send_data_| is set.
  377. void QueueNextDataFrame();
  378. void OnEarlyHintsReceived(const spdy::Http2HeaderBlock& response_headers,
  379. base::TimeTicks recv_first_byte_time);
  380. // Saves the given headers into |response_headers_| and calls
  381. // OnHeadersReceived() on the delegate if attached.
  382. void SaveResponseHeaders(const spdy::Http2HeaderBlock& response_headers,
  383. int status);
  384. static std::string DescribeState(State state);
  385. const SpdyStreamType type_;
  386. spdy::SpdyStreamId stream_id_ = 0;
  387. const GURL url_;
  388. RequestPriority priority_;
  389. bool send_stalled_by_flow_control_ = false;
  390. // Current send window size.
  391. int32_t send_window_size_;
  392. // Maximum receive window size. Each time a WINDOW_UPDATE is sent, it
  393. // restores the receive window size to this value.
  394. int32_t max_recv_window_size_;
  395. // Sum of |session_unacked_recv_window_bytes_| and current receive window
  396. // size.
  397. // TODO(bnc): Rename or change semantics so that |window_size_| is actual
  398. // window size.
  399. int32_t recv_window_size_;
  400. // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession,
  401. // and this member keeps count of them until the corresponding WINDOW_UPDATEs
  402. // are sent.
  403. int32_t unacked_recv_window_bytes_ = 0;
  404. // Time of the last WINDOW_UPDATE for the receive window
  405. base::TimeTicks last_recv_window_update_;
  406. const base::WeakPtr<SpdySession> session_;
  407. // The transaction should own the delegate.
  408. raw_ptr<SpdyStream::Delegate> delegate_ = nullptr;
  409. // The headers for the request to send.
  410. bool request_headers_valid_ = false;
  411. spdy::Http2HeaderBlock request_headers_;
  412. // Data waiting to be sent, and the close state of the local endpoint
  413. // after the data is fully written.
  414. scoped_refptr<DrainableIOBuffer> pending_send_data_;
  415. SpdySendStatus pending_send_status_ = MORE_DATA_TO_SEND;
  416. // Data waiting to be received, and the close state of the remote endpoint
  417. // after the data is fully read. Specifically, data received before the
  418. // delegate is attached must be buffered and later replayed. A remote FIN
  419. // is represented by a final, zero-length buffer.
  420. std::vector<std::unique_ptr<SpdyBuffer>> pending_recv_data_;
  421. // The time at which the request was made that resulted in this response.
  422. // For cached responses, this time could be "far" in the past.
  423. base::Time request_time_;
  424. spdy::Http2HeaderBlock response_headers_;
  425. ResponseState response_state_ = READY_FOR_HEADERS;
  426. base::Time response_time_;
  427. State io_state_ = STATE_IDLE;
  428. NetLogWithSource net_log_;
  429. base::TimeTicks send_time_;
  430. // The time at which the first / last byte of the HTTP headers were received.
  431. //
  432. // These correspond to |LoadTimingInfo::receive_headers_start| and
  433. // |LoadTimingInfo::receive_headers_end|. See also comments there.
  434. base::TimeTicks recv_first_byte_time_;
  435. base::TimeTicks recv_last_byte_time_;
  436. // The time at which the first byte of the HTTP headers for the
  437. // non-informational response (non-1xx). This corresponds to
  438. // |LoadTimingInfo::receive_non_informational_headers_start|. See also
  439. // comments there.
  440. base::TimeTicks recv_first_byte_time_for_non_informational_response_;
  441. // The time at which the first 103 Early Hints response is received.
  442. base::TimeTicks first_early_hints_time_;
  443. // Number of bytes that have been received on this stream, including frame
  444. // overhead and headers.
  445. int64_t raw_received_bytes_ = 0;
  446. // Number of bytes that have been sent on this stream, including frame
  447. // overhead and headers.
  448. int64_t raw_sent_bytes_ = 0;
  449. // Number of data bytes that have been received on this stream, not including
  450. // frame overhead. Note that this does not count headers.
  451. int recv_bytes_ = 0;
  452. // Guards calls of delegate write handlers ensuring |this| is not destroyed.
  453. // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked
  454. // down.
  455. bool write_handler_guard_ = false;
  456. const NetworkTrafficAnnotationTag traffic_annotation_;
  457. // Used by SpdySession to remember if this stream requested broken connection
  458. // detection.
  459. bool detect_broken_connection_;
  460. base::WeakPtrFactory<SpdyStream> weak_ptr_factory_{this};
  461. };
  462. } // namespace net
  463. #endif // NET_SPDY_SPDY_STREAM_H_