Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / net / spdy / spdy_stream.h
blob011363ab5feb105cada1a94ef091005c24e6a248
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_
8 #include <stdint.h>
10 #include <deque>
11 #include <string>
12 #include <vector>
14 #include "base/basictypes.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/memory/weak_ptr.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.h"
23 #include "net/socket/ssl_client_socket.h"
24 #include "net/spdy/spdy_buffer.h"
25 #include "net/spdy/spdy_framer.h"
26 #include "net/spdy/spdy_header_block.h"
27 #include "net/spdy/spdy_protocol.h"
28 #include "net/ssl/ssl_client_cert_type.h"
29 #include "url/gurl.h"
31 namespace net {
33 class AddressList;
34 class IPEndPoint;
35 struct LoadTimingInfo;
36 class SSLInfo;
37 class SpdySession;
39 enum SpdyStreamType {
40 // The most general type of stream; there are no restrictions on
41 // when data can be sent and received.
42 SPDY_BIDIRECTIONAL_STREAM,
43 // A stream where the client sends a request with possibly a body,
44 // and the server then sends a response with a body.
45 SPDY_REQUEST_RESPONSE_STREAM,
46 // A server-initiated stream where the server just sends a response
47 // with a body and the client does not send anything.
48 SPDY_PUSH_STREAM
51 // Passed to some SpdyStream functions to indicate whether there's
52 // more data to send.
53 enum SpdySendStatus {
54 MORE_DATA_TO_SEND,
55 NO_MORE_DATA_TO_SEND
58 // Returned by SpdyStream::OnResponseHeadersUpdated() to indicate
59 // whether the current response headers are complete or not, or whether
60 // trailers have been received. TRAILERS_RECEIVED denotes the state where
61 // headers are received after DATA frames. TRAILERS_RECEIVED is only used for
62 // SPDY_REQUEST_RESPONSE_STREAM, and this state also implies that the response
63 // headers are complete.
64 enum SpdyResponseHeadersStatus {
65 RESPONSE_HEADERS_ARE_INCOMPLETE,
66 RESPONSE_HEADERS_ARE_COMPLETE,
67 TRAILERS_RECEIVED,
70 // The SpdyStream is used by the SpdySession to represent each stream known
71 // on the SpdySession. This class provides interfaces for SpdySession to use.
72 // Streams can be created either by the client or by the server. When they
73 // are initiated by the client, both the SpdySession and client object (such as
74 // a SpdyNetworkTransaction) will maintain a reference to the stream. When
75 // initiated by the server, only the SpdySession will maintain any reference,
76 // until such a time as a client object requests a stream for the path.
77 class NET_EXPORT_PRIVATE SpdyStream {
78 public:
79 // Delegate handles protocol specific behavior of spdy stream.
80 class NET_EXPORT_PRIVATE Delegate {
81 public:
82 Delegate() {}
84 // Called when the request headers have been sent. Never called
85 // for push streams. Must not cause the stream to be closed.
86 virtual void OnRequestHeadersSent() = 0;
88 // WARNING: This function is complicated! Be sure to read the
89 // whole comment below if you're working with code that implements
90 // or calls this function.
92 // Called when the response headers are updated from the
93 // server. |response_headers| contains the set of all headers
94 // received up to this point; delegates can assume that any
95 // headers previously received remain unchanged.
97 // This is called at least once before any data is received. If
98 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be
99 // called again when more headers are received until
100 // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data
101 // received before then will be treated as a protocol error.
103 // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate
104 // must not have closed the stream. Otherwise, if
105 // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has
106 // processed the headers successfully. However, it still may have
107 // closed the stream, e.g. if the headers indicated an error
108 // condition.
110 // Some type-specific behavior:
112 // - For bidirectional streams, this may be called even after
113 // data is received, but it is expected that
114 // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If
115 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
116 // treated as a protocol error.
118 // - For request/response streams, this function is called
119 // exactly once before data is received, and it is expected
120 // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If
121 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
122 // treated as a protocol error.
124 // - For push streams, it is expected that this function will be
125 // called until RESPONSE_HEADERS_ARE_COMPLETE is returned
126 // before any data is received; any deviation from this is
127 // treated as a protocol error.
129 // TODO(jgraettinger): This should be at the semantic (HTTP) rather
130 // than stream layer. Streams shouldn't have a notion of header
131 // completeness. Move to SpdyHttpStream/SpdyWebsocketStream.
132 virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated(
133 const SpdyHeaderBlock& response_headers) = 0;
135 // Called when data is received after all required response
136 // headers have been received. |buffer| may be NULL, which signals
137 // EOF. Must return OK if the data was received successfully, or
138 // a network error code otherwise.
140 // May cause the stream to be closed.
141 virtual void OnDataReceived(scoped_ptr<SpdyBuffer> buffer) = 0;
143 // Called when data is sent. Must not cause the stream to be
144 // closed.
145 virtual void OnDataSent() = 0;
147 // Called when trailers are received. Note that trailers HEADER frame will
148 // have END_STREAM flag set according to section 8.1 of the HTTP/2 RFC,
149 // so this will be followed by OnClose.
150 virtual void OnTrailers(const SpdyHeaderBlock& trailers) = 0;
152 // Called when SpdyStream is closed. No other delegate functions
153 // will be called after this is called, and the delegate must not
154 // access the stream after this is called. Must not cause the
155 // stream to be be (re-)closed.
157 // TODO(akalin): Allow this function to re-close the stream and
158 // handle it gracefully.
159 virtual void OnClose(int status) = 0;
161 protected:
162 virtual ~Delegate() {}
164 private:
165 DISALLOW_COPY_AND_ASSIGN(Delegate);
168 // SpdyStream constructor
169 SpdyStream(SpdyStreamType type,
170 const base::WeakPtr<SpdySession>& session,
171 const GURL& url,
172 RequestPriority priority,
173 int32 initial_send_window_size,
174 int32 max_recv_window_size,
175 const BoundNetLog& net_log);
177 ~SpdyStream();
179 // Set the delegate, which must not be NULL. Must not be called more
180 // than once. For push streams, calling this may cause buffered data
181 // to be sent to the delegate (from a posted task).
182 void SetDelegate(Delegate* delegate);
184 // Detach the delegate from the stream, which must not yet be
185 // closed, and cancel it.
186 void DetachDelegate();
188 // The time at which the first bytes of the response were received
189 // from the server, or null if the response hasn't been received
190 // yet.
191 base::Time response_time() const { return response_time_; }
193 SpdyStreamType type() const { return type_; }
195 SpdyStreamId stream_id() const { return stream_id_; }
196 void set_stream_id(SpdyStreamId stream_id) { stream_id_ = stream_id; }
198 const GURL& url() const { return url_; }
200 RequestPriority priority() const { return priority_; }
202 int32 send_window_size() const { return send_window_size_; }
204 int32 recv_window_size() const { return recv_window_size_; }
206 bool send_stalled_by_flow_control() const {
207 return send_stalled_by_flow_control_;
210 void set_send_stalled_by_flow_control(bool stalled) {
211 send_stalled_by_flow_control_ = stalled;
214 // Called by the session to adjust this stream's send window size by
215 // |delta_window_size|, which is the difference between the
216 // SETTINGS_INITIAL_WINDOW_SIZE in the most recent SETTINGS frame
217 // and the previous initial send window size, possibly unstalling
218 // this stream. Although |delta_window_size| may cause this stream's
219 // send window size to go negative, it must not cause it to wrap
220 // around in either direction. Does nothing if the stream is already
221 // closed.
223 // If stream flow control is turned off, this must not be called.
224 void AdjustSendWindowSize(int32 delta_window_size);
226 // Called when bytes are consumed from a SpdyBuffer for a DATA frame
227 // that is to be written or is being written. Increases the send
228 // window size accordingly if some or all of the SpdyBuffer is being
229 // discarded.
231 // If stream flow control is turned off, this must not be called.
232 void OnWriteBufferConsumed(size_t frame_payload_size,
233 size_t consume_size,
234 SpdyBuffer::ConsumeSource consume_source);
236 // Called by the session to increase this stream's send window size
237 // by |delta_window_size| (which must be at least 1) from a received
238 // WINDOW_UPDATE frame or from a dropped DATA frame that was
239 // intended to be sent, possibly unstalling this stream. If
240 // |delta_window_size| would cause this stream's send window size to
241 // overflow, calls into the session to reset this stream. Does
242 // nothing if the stream is already closed.
244 // If stream flow control is turned off, this must not be called.
245 void IncreaseSendWindowSize(int32 delta_window_size);
247 // If stream flow control is turned on, called by the session to
248 // decrease this stream's send window size by |delta_window_size|,
249 // which must be at least 0 and at most kMaxSpdyFrameChunkSize.
250 // |delta_window_size| must not cause this stream's send window size
251 // to go negative. Does nothing if the stream is already closed.
253 // If stream flow control is turned off, this must not be called.
254 void DecreaseSendWindowSize(int32 delta_window_size);
256 // Called when bytes are consumed by the delegate from a SpdyBuffer
257 // containing received data. Increases the receive window size
258 // accordingly.
260 // If stream flow control is turned off, this must not be called.
261 void OnReadBufferConsumed(size_t consume_size,
262 SpdyBuffer::ConsumeSource consume_source);
264 // Called by OnReadBufferConsume to increase this stream's receive
265 // window size by |delta_window_size|, which must be at least 1 and
266 // must not cause this stream's receive window size to overflow,
267 // possibly also sending a WINDOW_UPDATE frame. Does nothing if the
268 // stream is not active.
270 // If stream flow control is turned off, this must not be called.
271 void IncreaseRecvWindowSize(int32 delta_window_size);
273 // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by
274 // the session) to decrease this stream's receive window size by
275 // |delta_window_size|, which must be at least 1. May close the stream on
276 // flow control error.
278 // If stream flow control is turned off or the stream is not active,
279 // this must not be called.
280 void DecreaseRecvWindowSize(int32 delta_window_size);
282 int GetPeerAddress(IPEndPoint* address) const;
283 int GetLocalAddress(IPEndPoint* address) const;
285 // Returns true if the underlying transport socket ever had any reads or
286 // writes.
287 bool WasEverUsed() const;
289 const BoundNetLog& net_log() const { return net_log_; }
291 base::Time GetRequestTime() const;
292 void SetRequestTime(base::Time t);
294 // Called at most once by the SpdySession when the initial response
295 // headers have been received for this stream, i.e., a SYN_REPLY (or
296 // SYN_STREAM for push streams) frame has been received. Returns a status
297 // code; if it is an error, the stream was closed by this function.
298 int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers,
299 base::Time response_time,
300 base::TimeTicks recv_first_byte_time);
302 // Called by the SpdySession (only after
303 // OnInitialResponseHeadersReceived() has been called) when
304 // late-bound headers are received for a stream. Returns a status
305 // code; if it is an error, the stream was closed by this function.
306 int OnAdditionalResponseHeadersReceived(
307 const SpdyHeaderBlock& additional_response_headers);
309 // Called by the SpdySession when a frame carrying request headers opening a
310 // push stream is received. Stream transits to STATE_RESERVED_REMOTE state.
311 void OnPushPromiseHeadersReceived(const SpdyHeaderBlock& headers);
313 // Called by the SpdySession when response data has been received
314 // for this stream. This callback may be called multiple times as
315 // data arrives from the network, and will never be called prior to
316 // OnResponseHeadersReceived.
318 // |buffer| contains the data received, or NULL if the stream is
319 // being closed. The stream must copy any data from this
320 // buffer before returning from this callback.
322 // |length| is the number of bytes received (at most 2^24 - 1) or 0 if
323 // the stream is being closed.
324 void OnDataReceived(scoped_ptr<SpdyBuffer> buffer);
326 // Called by the SpdySession when padding is consumed to allow for the stream
327 // receiving window to be updated.
328 void OnPaddingConsumed(size_t len);
330 // Called by the SpdySession when a frame has been successfully and completely
331 // written. |frame_size| is the total size of the logical frame in bytes,
332 // including framing overhead. For fragmented headers, this is the total size
333 // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames.
334 void OnFrameWriteComplete(SpdyFrameType frame_type, size_t frame_size);
336 // SYN_STREAM-specific write handler invoked by OnFrameWriteComplete().
337 int OnRequestHeadersSent();
339 // DATA-specific write handler invoked by OnFrameWriteComplete().
340 // If more data is already available to be written, the next write is
341 // queued and ERR_IO_PENDING is returned. Returns OK otherwise.
342 int OnDataSent(size_t frame_size);
344 // Called by the SpdySession when the request is finished. This callback
345 // will always be called at the end of the request and signals to the
346 // stream that the stream has no more network events. No further callbacks
347 // to the stream will be made after this call.
348 // |status| is an error code or OK.
349 void OnClose(int status);
351 // Called by the SpdySession to log stream related errors.
352 void LogStreamError(int status, const std::string& description);
354 // If this stream is active, reset it, and close it otherwise. In
355 // either case the stream is deleted.
356 void Cancel();
358 // Close this stream without sending a RST_STREAM and delete
359 // it.
360 void Close();
362 // Must be used only by |session_|.
363 base::WeakPtr<SpdyStream> GetWeakPtr();
365 // Interface for the delegate to use.
367 // Only one send can be in flight at a time, except for push
368 // streams, which must not send anything.
370 // Sends the request headers. The delegate is called back via
371 // OnRequestHeadersSent() when the request headers have completed
372 // sending. |send_status| must be MORE_DATA_TO_SEND for
373 // bidirectional streams; for request/response streams, it must be
374 // MORE_DATA_TO_SEND if the request has data to upload, or
375 // NO_MORE_DATA_TO_SEND if not.
376 int SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers,
377 SpdySendStatus send_status);
379 // Sends a DATA frame. The delegate will be notified via
380 // OnDataSent() when the send is complete. |send_status| must be
381 // MORE_DATA_TO_SEND for bidirectional streams; for request/response
382 // streams, it must be MORE_DATA_TO_SEND if there is more data to
383 // upload, or NO_MORE_DATA_TO_SEND if not.
384 void SendData(IOBuffer* data, int length, SpdySendStatus send_status);
386 // Fills SSL info in |ssl_info| and returns true when SSL is in use.
387 bool GetSSLInfo(SSLInfo* ssl_info,
388 bool* was_npn_negotiated,
389 NextProto* protocol_negotiated);
391 // If the stream is stalled on sending data, but the session is not
392 // stalled on sending data and |send_window_size_| is positive, then
393 // set |send_stalled_by_flow_control_| to false and unstall the data
394 // sending. Called by the session or by the stream itself. Must be
395 // called only when the stream is still open.
396 void PossiblyResumeIfSendStalled();
398 // Returns whether or not this stream is closed. Note that the only
399 // time a stream is closed and not deleted is in its delegate's
400 // OnClose() method.
401 bool IsClosed() const;
403 // Returns whether the streams local endpoint is closed.
404 // The remote endpoint may still be active.
405 bool IsLocallyClosed() const;
407 // Returns whether this stream is IDLE: request and response headers
408 // have neither been sent nor receieved.
409 bool IsIdle() const;
411 // Returns whether or not this stream is fully open: that request and
412 // response headers are complete, and it is not in a half-closed state.
413 bool IsOpen() const;
415 // Returns whether the stream is reserved by remote endpoint: server has sent
416 // intended request headers for a pushed stream, but haven't started response
417 // yet.
418 bool IsReservedRemote() const;
420 // Returns the protocol used by this stream. Always between
421 // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
422 NextProto GetProtocol() const;
424 int response_status() const { return response_status_; }
426 void AddRawReceivedBytes(size_t received_bytes);
427 void AddRawSentBytes(size_t sent_bytes);
429 int64 raw_received_bytes() const { return raw_received_bytes_; }
430 int64_t raw_sent_bytes() const { return raw_sent_bytes_; }
432 bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
434 // Get the URL from the appropriate stream headers, or the empty
435 // GURL() if it is unknown.
437 // TODO(akalin): Figure out if we really need this function,
438 // i.e. can we just use the URL this stream was created with and/or
439 // one we receive headers validate that the URL from them is the
440 // same.
441 GURL GetUrlFromHeaders() const;
443 // Returns whether the URL for this stream is known.
445 // TODO(akalin): Remove this, as it's only used in tests.
446 bool HasUrlFromHeaders() const;
448 SpdyMajorVersion GetProtocolVersion() const;
450 private:
451 class SynStreamBufferProducer;
452 class HeaderBufferProducer;
454 // SpdyStream states and transitions are modeled
455 // on the HTTP/2 stream state machine. All states and transitions
456 // are modeled, with the exceptions of RESERVED_LOCAL (the client
457 // cannot initate push streams), and the transition to OPEN due to
458 // a remote SYN_STREAM (the client can only initate streams).
459 enum State {
460 STATE_IDLE,
461 STATE_OPEN,
462 STATE_HALF_CLOSED_LOCAL_UNCLAIMED,
463 STATE_HALF_CLOSED_LOCAL,
464 STATE_HALF_CLOSED_REMOTE,
465 STATE_RESERVED_REMOTE,
466 STATE_CLOSED,
469 // Update the histograms. Can safely be called repeatedly, but should only
470 // be called after the stream has completed.
471 void UpdateHistograms();
473 // When a server-push stream is claimed by SetDelegate(), this function is
474 // posted on the current MessageLoop to replay everything the server has sent.
475 // From the perspective of SpdyStream's state machine, headers, data, and
476 // FIN states received prior to the delegate being attached have not yet been
477 // read. While buffered by |pending_recv_data_| it's not until
478 // PushedStreamReplay() is invoked that reads are considered
479 // to have occurred, driving the state machine forward.
480 void PushedStreamReplay();
482 // Produces the SYN_STREAM frame for the stream. The stream must
483 // already be activated.
484 scoped_ptr<SpdyFrame> ProduceSynStreamFrame();
486 // Produce the initial HEADER frame for the stream with the given
487 // block. The stream must already be activated.
488 scoped_ptr<SpdyFrame> ProduceHeaderFrame(
489 scoped_ptr<SpdyHeaderBlock> header_block);
491 // Queues the send for next frame of the remaining data in
492 // |pending_send_data_|. Must be called only when
493 // |pending_send_data_| is set.
494 void QueueNextDataFrame();
496 // Merge the given headers into |response_headers_| and calls
497 // OnResponseHeadersUpdated() on the delegate (if attached).
498 // Returns a status code; if it is an error, the stream was closed
499 // by this function.
500 int MergeWithResponseHeaders(const SpdyHeaderBlock& new_response_headers);
502 static std::string DescribeState(State state);
504 const SpdyStreamType type_;
506 SpdyStreamId stream_id_;
507 const GURL url_;
508 const RequestPriority priority_;
510 bool send_stalled_by_flow_control_;
512 // Current send window size.
513 int32 send_window_size_;
515 // Maximum receive window size. Each time a WINDOW_UPDATE is sent, it
516 // restores the receive window size to this value.
517 int32 max_recv_window_size_;
519 // Sum of |session_unacked_recv_window_bytes_| and current receive window
520 // size.
521 // TODO(bnc): Rename or change semantics so that |window_size_| is actual
522 // window size.
523 int32 recv_window_size_;
525 // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession,
526 // and this member keeps count of them until the corresponding WINDOW_UPDATEs
527 // are sent.
528 int32 unacked_recv_window_bytes_;
530 const base::WeakPtr<SpdySession> session_;
532 // The transaction should own the delegate.
533 SpdyStream::Delegate* delegate_;
535 // The headers for the request to send.
537 // TODO(akalin): Hang onto this only until we send it. This
538 // necessitates stashing the URL separately.
539 scoped_ptr<SpdyHeaderBlock> request_headers_;
541 // Data waiting to be sent, and the close state of the local endpoint
542 // after the data is fully written.
543 scoped_refptr<DrainableIOBuffer> pending_send_data_;
544 SpdySendStatus pending_send_status_;
546 // Data waiting to be received, and the close state of the remote endpoint
547 // after the data is fully read. Specifically, data received before the
548 // delegate is attached must be buffered and later replayed. A remote FIN
549 // is represented by a final, zero-length buffer.
550 ScopedVector<SpdyBuffer> pending_recv_data_;
552 // The time at which the request was made that resulted in this response.
553 // For cached responses, this time could be "far" in the past.
554 base::Time request_time_;
556 SpdyHeaderBlock response_headers_;
557 SpdyResponseHeadersStatus response_headers_status_;
558 base::Time response_time_;
560 State io_state_;
562 // Since we buffer the response, we also buffer the response status.
563 // Not valid until the stream is closed.
564 int response_status_;
566 BoundNetLog net_log_;
568 base::TimeTicks send_time_;
569 base::TimeTicks recv_first_byte_time_;
570 base::TimeTicks recv_last_byte_time_;
572 // Number of bytes that have been received on this stream, including frame
573 // overhead and headers.
574 int64 raw_received_bytes_;
575 // Number of bytes that have been sent on this stream, including frame
576 // overhead and headers.
577 int64_t raw_sent_bytes_;
579 // Number of data bytes that have been sent/received on this stream, not
580 // including frame overhead. Note that this does not count headers.
581 int send_bytes_;
582 int recv_bytes_;
584 // Guards calls of delegate write handlers ensuring |this| is not destroyed.
585 // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked
586 // down.
587 bool write_handler_guard_;
589 base::WeakPtrFactory<SpdyStream> weak_ptr_factory_;
591 DISALLOW_COPY_AND_ASSIGN(SpdyStream);
594 } // namespace net
596 #endif // NET_SPDY_SPDY_STREAM_H_