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