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