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.
5 #ifndef NET_SPDY_SPDY_STREAM_H_
6 #define NET_SPDY_SPDY_STREAM_H_
12 #include "base/basictypes.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/memory/weak_ptr.h"
17 #include "net/base/io_buffer.h"
18 #include "net/base/net_export.h"
19 #include "net/base/request_priority.h"
20 #include "net/log/net_log.h"
21 #include "net/socket/ssl_client_socket.h"
22 #include "net/spdy/spdy_buffer.h"
23 #include "net/spdy/spdy_framer.h"
24 #include "net/spdy/spdy_header_block.h"
25 #include "net/spdy/spdy_protocol.h"
26 #include "net/ssl/ssl_client_cert_type.h"
33 struct LoadTimingInfo
;
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.
49 // Passed to some SpdyStream functions to indicate whether there's
56 // Returned by SpdyStream::OnResponseHeadersUpdated() to indicate
57 // whether the current response headers are complete or not, or whether
58 // trailers have been received. TRAILERS_RECEIVED denotes the state where
59 // headers are received after DATA frames. TRAILERS_RECEIVED is only used for
60 // SPDY_REQUEST_RESPONSE_STREAM, and this state also implies that the response
61 // headers are complete.
62 enum SpdyResponseHeadersStatus
{
63 RESPONSE_HEADERS_ARE_INCOMPLETE
,
64 RESPONSE_HEADERS_ARE_COMPLETE
,
68 // The SpdyStream is used by the SpdySession to represent each stream known
69 // on the SpdySession. This class provides interfaces for SpdySession to use.
70 // Streams can be created either by the client or by the server. When they
71 // are initiated by the client, both the SpdySession and client object (such as
72 // a SpdyNetworkTransaction) will maintain a reference to the stream. When
73 // initiated by the server, only the SpdySession will maintain any reference,
74 // until such a time as a client object requests a stream for the path.
75 class NET_EXPORT_PRIVATE SpdyStream
{
77 // Delegate handles protocol specific behavior of spdy stream.
78 class NET_EXPORT_PRIVATE Delegate
{
82 // Called when the request headers have been sent. Never called
83 // for push streams. Must not cause the stream to be closed.
84 virtual void OnRequestHeadersSent() = 0;
86 // WARNING: This function is complicated! Be sure to read the
87 // whole comment below if you're working with code that implements
88 // or calls this function.
90 // Called when the response headers are updated from the
91 // server. |response_headers| contains the set of all headers
92 // received up to this point; delegates can assume that any
93 // headers previously received remain unchanged.
95 // This is called at least once before any data is received. If
96 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be
97 // called again when more headers are received until
98 // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data
99 // received before then will be treated as a protocol error.
101 // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate
102 // must not have closed the stream. Otherwise, if
103 // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has
104 // processed the headers successfully. However, it still may have
105 // closed the stream, e.g. if the headers indicated an error
108 // Some type-specific behavior:
110 // - For bidirectional streams, this may be called even after
111 // data is received, but it is expected that
112 // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If
113 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
114 // treated as a protocol error.
116 // - For request/response streams, this function is called
117 // exactly once before data is received, and it is expected
118 // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If
119 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
120 // treated as a protocol error.
122 // - For push streams, it is expected that this function will be
123 // called until RESPONSE_HEADERS_ARE_COMPLETE is returned
124 // before any data is received; any deviation from this is
125 // treated as a protocol error.
127 // TODO(jgraettinger): This should be at the semantic (HTTP) rather
128 // than stream layer. Streams shouldn't have a notion of header
129 // completeness. Move to SpdyHttpStream/SpdyWebsocketStream.
130 virtual SpdyResponseHeadersStatus
OnResponseHeadersUpdated(
131 const SpdyHeaderBlock
& response_headers
) = 0;
133 // Called when data is received after all required response
134 // headers have been received. |buffer| may be NULL, which signals
135 // EOF. Must return OK if the data was received successfully, or
136 // a network error code otherwise.
138 // May cause the stream to be closed.
139 virtual void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
) = 0;
141 // Called when data is sent. Must not cause the stream to be
143 virtual void OnDataSent() = 0;
145 // Called when trailers are received. Note that trailers HEADER frame will
146 // have END_STREAM flag set according to section 8.1 of the HTTP/2 RFC,
147 // so this will be followed by OnClose.
148 virtual void OnTrailers(const SpdyHeaderBlock
& trailers
) = 0;
150 // Called when SpdyStream is closed. No other delegate functions
151 // will be called after this is called, and the delegate must not
152 // access the stream after this is called. Must not cause the
153 // stream to be be (re-)closed.
155 // TODO(akalin): Allow this function to re-close the stream and
156 // handle it gracefully.
157 virtual void OnClose(int status
) = 0;
160 virtual ~Delegate() {}
163 DISALLOW_COPY_AND_ASSIGN(Delegate
);
166 // SpdyStream constructor
167 SpdyStream(SpdyStreamType type
,
168 const base::WeakPtr
<SpdySession
>& session
,
170 RequestPriority priority
,
171 int32 initial_send_window_size
,
172 int32 max_recv_window_size
,
173 const BoundNetLog
& net_log
);
177 // Set the delegate, which must not be NULL. Must not be called more
178 // than once. For push streams, calling this may cause buffered data
179 // to be sent to the delegate (from a posted task).
180 void SetDelegate(Delegate
* delegate
);
182 // Detach the delegate from the stream, which must not yet be
183 // closed, and cancel it.
184 void DetachDelegate();
186 // The time at which the first bytes of the response were received
187 // from the server, or null if the response hasn't been received
189 base::Time
response_time() const { return response_time_
; }
191 SpdyStreamType
type() const { return type_
; }
193 SpdyStreamId
stream_id() const { return stream_id_
; }
194 void set_stream_id(SpdyStreamId stream_id
) { stream_id_
= stream_id
; }
196 const GURL
& url() const { return url_
; }
198 RequestPriority
priority() const { return priority_
; }
200 int32
send_window_size() const { return send_window_size_
; }
202 int32
recv_window_size() const { return recv_window_size_
; }
204 bool send_stalled_by_flow_control() const {
205 return send_stalled_by_flow_control_
;
208 void set_send_stalled_by_flow_control(bool stalled
) {
209 send_stalled_by_flow_control_
= stalled
;
212 // Called by the session to adjust this stream's send window size by
213 // |delta_window_size|, which is the difference between the
214 // SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame
215 // and the previous initial send window size, possibly unstalling
216 // this stream. Although |delta_window_size| may cause this stream's
217 // send window size to go negative, it must not cause it to wrap
218 // around in either direction. Does nothing if the stream is already
221 // If stream flow control is turned off, this must not be called.
222 void AdjustSendWindowSize(int32 delta_window_size
);
224 // Called when bytes are consumed from a SpdyBuffer for a DATA frame
225 // that is to be written or is being written. Increases the send
226 // window size accordingly if some or all of the SpdyBuffer is being
229 // If stream flow control is turned off, this must not be called.
230 void OnWriteBufferConsumed(size_t frame_payload_size
,
232 SpdyBuffer::ConsumeSource consume_source
);
234 // Called by the session to increase this stream's send window size
235 // by |delta_window_size| (which must be at least 1) from a received
236 // WINDOW_UPDATE frame or from a dropped DATA frame that was
237 // intended to be sent, possibly unstalling this stream. If
238 // |delta_window_size| would cause this stream's send window size to
239 // overflow, calls into the session to reset this stream. Does
240 // nothing if the stream is already closed.
242 // If stream flow control is turned off, this must not be called.
243 void IncreaseSendWindowSize(int32 delta_window_size
);
245 // If stream flow control is turned on, called by the session to
246 // decrease this stream's send window size by |delta_window_size|,
247 // which must be at least 0 and at most kMaxSpdyFrameChunkSize.
248 // |delta_window_size| must not cause this stream's send window size
249 // to go negative. Does nothing if the stream is already closed.
251 // If stream flow control is turned off, this must not be called.
252 void DecreaseSendWindowSize(int32 delta_window_size
);
254 // Called when bytes are consumed by the delegate from a SpdyBuffer
255 // containing received data. Increases the receive window size
258 // If stream flow control is turned off, this must not be called.
259 void OnReadBufferConsumed(size_t consume_size
,
260 SpdyBuffer::ConsumeSource consume_source
);
262 // Called by OnReadBufferConsume to increase this stream's receive
263 // window size by |delta_window_size|, which must be at least 1 and
264 // must not cause this stream's receive window size to overflow,
265 // possibly also sending a WINDOW_UPDATE frame. Does nothing if the
266 // stream is not active.
268 // If stream flow control is turned off, this must not be called.
269 void IncreaseRecvWindowSize(int32 delta_window_size
);
271 // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by
272 // the session) to decrease this stream's receive window size by
273 // |delta_window_size|, which must be at least 1. May close the stream on
274 // flow control error.
276 // If stream flow control is turned off or the stream is not active,
277 // this must not be called.
278 void DecreaseRecvWindowSize(int32 delta_window_size
);
280 int GetPeerAddress(IPEndPoint
* address
) const;
281 int GetLocalAddress(IPEndPoint
* address
) const;
283 // Returns true if the underlying transport socket ever had any reads or
285 bool WasEverUsed() const;
287 const BoundNetLog
& net_log() const { return net_log_
; }
289 base::Time
GetRequestTime() const;
290 void SetRequestTime(base::Time t
);
292 // Called at most once by the SpdySession when the initial response
293 // headers have been received for this stream, i.e., a SYN_REPLY (or
294 // SYN_STREAM for push streams) frame has been received. Returns a status
295 // code; if it is an error, the stream was closed by this function.
296 int OnInitialResponseHeadersReceived(const SpdyHeaderBlock
& response_headers
,
297 base::Time response_time
,
298 base::TimeTicks recv_first_byte_time
);
300 // Called by the SpdySession (only after
301 // OnInitialResponseHeadersReceived() has been called) when
302 // late-bound headers are received for a stream. Returns a status
303 // code; if it is an error, the stream was closed by this function.
304 int OnAdditionalResponseHeadersReceived(
305 const SpdyHeaderBlock
& additional_response_headers
);
307 // Called by the SpdySession when a frame carrying request headers opening a
308 // push stream is received. Stream transits to STATE_RESERVED_REMOTE state.
309 void OnPushPromiseHeadersReceived(const SpdyHeaderBlock
& headers
);
311 // Called by the SpdySession when response data has been received
312 // for this stream. This callback may be called multiple times as
313 // data arrives from the network, and will never be called prior to
314 // OnResponseHeadersReceived.
316 // |buffer| contains the data received, or NULL if the stream is
317 // being closed. The stream must copy any data from this
318 // buffer before returning from this callback.
320 // |length| is the number of bytes received (at most 2^24 - 1) or 0 if
321 // the stream is being closed.
322 void OnDataReceived(scoped_ptr
<SpdyBuffer
> buffer
);
324 // Called by the SpdySession when padding is consumed to allow for the stream
325 // receiving window to be updated.
326 void OnPaddingConsumed(size_t len
);
328 // Called by the SpdySession when a frame has been successfully and completely
329 // written. |frame_size| is the total size of the logical frame in bytes,
330 // including framing overhead. For fragmented headers, this is the total size
331 // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames.
332 void OnFrameWriteComplete(SpdyFrameType frame_type
, size_t frame_size
);
334 // SYN_STREAM-specific write handler invoked by OnFrameWriteComplete().
335 int OnRequestHeadersSent();
337 // DATA-specific write handler invoked by OnFrameWriteComplete().
338 // If more data is already available to be written, the next write is
339 // queued and ERR_IO_PENDING is returned. Returns OK otherwise.
340 int OnDataSent(size_t frame_size
);
342 // Called by the SpdySession when the request is finished. This callback
343 // will always be called at the end of the request and signals to the
344 // stream that the stream has no more network events. No further callbacks
345 // to the stream will be made after this call.
346 // |status| is an error code or OK.
347 void OnClose(int status
);
349 // Called by the SpdySession to log stream related errors.
350 void LogStreamError(int status
, const std::string
& description
);
352 // If this stream is active, reset it, and close it otherwise. In
353 // either case the stream is deleted.
356 // Close this stream without sending a RST_STREAM and delete
360 // Must be used only by |session_|.
361 base::WeakPtr
<SpdyStream
> GetWeakPtr();
363 // Interface for the delegate to use.
365 // Only one send can be in flight at a time, except for push
366 // streams, which must not send anything.
368 // Sends the request headers. The delegate is called back via
369 // OnRequestHeadersSent() when the request headers have completed
370 // sending. |send_status| must be MORE_DATA_TO_SEND for
371 // bidirectional streams; for request/response streams, it must be
372 // MORE_DATA_TO_SEND if the request has data to upload, or
373 // NO_MORE_DATA_TO_SEND if not.
374 int SendRequestHeaders(scoped_ptr
<SpdyHeaderBlock
> request_headers
,
375 SpdySendStatus send_status
);
377 // Sends a DATA frame. The delegate will be notified via
378 // OnDataSent() when the send is complete. |send_status| must be
379 // MORE_DATA_TO_SEND for bidirectional streams; for request/response
380 // streams, it must be MORE_DATA_TO_SEND if there is more data to
381 // upload, or NO_MORE_DATA_TO_SEND if not.
382 void SendData(IOBuffer
* data
, int length
, SpdySendStatus send_status
);
384 // Fills SSL info in |ssl_info| and returns true when SSL is in use.
385 bool GetSSLInfo(SSLInfo
* ssl_info
,
386 bool* was_npn_negotiated
,
387 NextProto
* protocol_negotiated
);
389 // If the stream is stalled on sending data, but the session is not
390 // stalled on sending data and |send_window_size_| is positive, then
391 // set |send_stalled_by_flow_control_| to false and unstall the data
392 // sending. Called by the session or by the stream itself. Must be
393 // called only when the stream is still open.
394 void PossiblyResumeIfSendStalled();
396 // Returns whether or not this stream is closed. Note that the only
397 // time a stream is closed and not deleted is in its delegate's
399 bool IsClosed() const;
401 // Returns whether the streams local endpoint is closed.
402 // The remote endpoint may still be active.
403 bool IsLocallyClosed() const;
405 // Returns whether this stream is IDLE: request and response headers
406 // have neither been sent nor receieved.
409 // Returns whether or not this stream is fully open: that request and
410 // response headers are complete, and it is not in a half-closed state.
413 // Returns whether the stream is reserved by remote endpoint: server has sent
414 // intended request headers for a pushed stream, but haven't started response
416 bool IsReservedRemote() const;
418 // Returns the protocol used by this stream. Always between
419 // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
420 NextProto
GetProtocol() const;
422 int response_status() const { return response_status_
; }
424 void IncrementRawReceivedBytes(size_t received_bytes
) {
425 raw_received_bytes_
+= received_bytes
;
428 int64
raw_received_bytes() const { return raw_received_bytes_
; }
430 bool GetLoadTimingInfo(LoadTimingInfo
* load_timing_info
) const;
432 // Get the URL from the appropriate stream headers, or the empty
433 // GURL() if it is unknown.
435 // TODO(akalin): Figure out if we really need this function,
436 // i.e. can we just use the URL this stream was created with and/or
437 // one we receive headers validate that the URL from them is the
439 GURL
GetUrlFromHeaders() const;
441 // Returns whether the URL for this stream is known.
443 // TODO(akalin): Remove this, as it's only used in tests.
444 bool HasUrlFromHeaders() const;
446 SpdyMajorVersion
GetProtocolVersion() const;
449 class SynStreamBufferProducer
;
450 class HeaderBufferProducer
;
452 // SpdyStream states and transitions are modeled
453 // on the HTTP/2 stream state machine. All states and transitions
454 // are modeled, with the exceptions of RESERVED_LOCAL (the client
455 // cannot initate push streams), and the transition to OPEN due to
456 // a remote SYN_STREAM (the client can only initate streams).
460 STATE_HALF_CLOSED_LOCAL_UNCLAIMED
,
461 STATE_HALF_CLOSED_LOCAL
,
462 STATE_HALF_CLOSED_REMOTE
,
463 STATE_RESERVED_REMOTE
,
467 // Update the histograms. Can safely be called repeatedly, but should only
468 // be called after the stream has completed.
469 void UpdateHistograms();
471 // When a server-push stream is claimed by SetDelegate(), this function is
472 // posted on the current MessageLoop to replay everything the server has sent.
473 // From the perspective of SpdyStream's state machine, headers, data, and
474 // FIN states received prior to the delegate being attached have not yet been
475 // read. While buffered by |pending_recv_data_| it's not until
476 // PushedStreamReplay() is invoked that reads are considered
477 // to have occurred, driving the state machine forward.
478 void PushedStreamReplay();
480 // Produces the SYN_STREAM frame for the stream. The stream must
481 // already be activated.
482 scoped_ptr
<SpdyFrame
> ProduceSynStreamFrame();
484 // Produce the initial HEADER frame for the stream with the given
485 // block. The stream must already be activated.
486 scoped_ptr
<SpdyFrame
> ProduceHeaderFrame(
487 scoped_ptr
<SpdyHeaderBlock
> header_block
);
489 // Queues the send for next frame of the remaining data in
490 // |pending_send_data_|. Must be called only when
491 // |pending_send_data_| is set.
492 void QueueNextDataFrame();
494 // Merge the given headers into |response_headers_| and calls
495 // OnResponseHeadersUpdated() on the delegate (if attached).
496 // Returns a status code; if it is an error, the stream was closed
498 int MergeWithResponseHeaders(const SpdyHeaderBlock
& new_response_headers
);
500 static std::string
DescribeState(State state
);
502 const SpdyStreamType type_
;
504 SpdyStreamId stream_id_
;
506 const RequestPriority priority_
;
508 bool send_stalled_by_flow_control_
;
510 // Current send window size.
511 int32 send_window_size_
;
513 // Maximum receive window size. Each time a WINDOW_UPDATE is sent, it
514 // restores the receive window size to this value.
515 int32 max_recv_window_size_
;
517 // Sum of |session_unacked_recv_window_bytes_| and current receive window
519 // TODO(bnc): Rename or change semantics so that |window_size_| is actual
521 int32 recv_window_size_
;
523 // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession,
524 // and this member keeps count of them until the corresponding WINDOW_UPDATEs
526 int32 unacked_recv_window_bytes_
;
528 const base::WeakPtr
<SpdySession
> session_
;
530 // The transaction should own the delegate.
531 SpdyStream::Delegate
* delegate_
;
533 // The headers for the request to send.
535 // TODO(akalin): Hang onto this only until we send it. This
536 // necessitates stashing the URL separately.
537 scoped_ptr
<SpdyHeaderBlock
> request_headers_
;
539 // Data waiting to be sent, and the close state of the local endpoint
540 // after the data is fully written.
541 scoped_refptr
<DrainableIOBuffer
> pending_send_data_
;
542 SpdySendStatus pending_send_status_
;
544 // Data waiting to be received, and the close state of the remote endpoint
545 // after the data is fully read. Specifically, data received before the
546 // delegate is attached must be buffered and later replayed. A remote FIN
547 // is represented by a final, zero-length buffer.
548 ScopedVector
<SpdyBuffer
> pending_recv_data_
;
550 // The time at which the request was made that resulted in this response.
551 // For cached responses, this time could be "far" in the past.
552 base::Time request_time_
;
554 SpdyHeaderBlock response_headers_
;
555 SpdyResponseHeadersStatus response_headers_status_
;
556 base::Time response_time_
;
560 // Since we buffer the response, we also buffer the response status.
561 // Not valid until the stream is closed.
562 int response_status_
;
564 BoundNetLog net_log_
;
566 base::TimeTicks send_time_
;
567 base::TimeTicks recv_first_byte_time_
;
568 base::TimeTicks recv_last_byte_time_
;
570 // Number of bytes that have been received on this stream, including frame
571 // overhead and headers.
572 int64 raw_received_bytes_
;
574 // Number of data bytes that have been sent/received on this stream, not
575 // including frame overhead. Note that this does not count headers.
579 // Guards calls of delegate write handlers ensuring |this| is not destroyed.
580 // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked
582 bool write_handler_guard_
;
584 base::WeakPtrFactory
<SpdyStream
> weak_ptr_factory_
;
586 DISALLOW_COPY_AND_ASSIGN(SpdyStream
);
591 #endif // NET_SPDY_SPDY_STREAM_H_