Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: net/spdy/spdy_stream.h

Issue 2526003002: Disallow multiple HEADERS frames on pushed streams. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef NET_SPDY_SPDY_STREAM_H_ 5 #ifndef NET_SPDY_SPDY_STREAM_H_
6 #define NET_SPDY_SPDY_STREAM_H_ 6 #define NET_SPDY_SPDY_STREAM_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 SPDY_PUSH_STREAM 49 SPDY_PUSH_STREAM
50 }; 50 };
51 51
52 // Passed to some SpdyStream functions to indicate whether there's 52 // Passed to some SpdyStream functions to indicate whether there's
53 // more data to send. 53 // more data to send.
54 enum SpdySendStatus { 54 enum SpdySendStatus {
55 MORE_DATA_TO_SEND, 55 MORE_DATA_TO_SEND,
56 NO_MORE_DATA_TO_SEND 56 NO_MORE_DATA_TO_SEND
57 }; 57 };
58 58
59 // Returned by SpdyStream::OnResponseHeadersUpdated() to indicate
60 // whether the current response headers are complete or not, or whether
61 // trailers have been received. TRAILERS_RECEIVED denotes the state where
62 // headers are received after DATA frames. TRAILERS_RECEIVED is only used for
63 // SPDY_REQUEST_RESPONSE_STREAM, and this state also implies that the response
64 // headers are complete.
65 enum SpdyResponseHeadersStatus {
66 RESPONSE_HEADERS_ARE_INCOMPLETE,
67 RESPONSE_HEADERS_ARE_COMPLETE,
68 TRAILERS_RECEIVED,
69 };
70
71 // The SpdyStream is used by the SpdySession to represent each stream known 59 // The SpdyStream is used by the SpdySession to represent each stream known
72 // on the SpdySession. This class provides interfaces for SpdySession to use. 60 // on the SpdySession. This class provides interfaces for SpdySession to use.
73 // Streams can be created either by the client or by the server. When they 61 // Streams can be created either by the client or by the server. When they
74 // are initiated by the client, both the SpdySession and client object (such as 62 // are initiated by the client, both the SpdySession and client object (such as
75 // a SpdyNetworkTransaction) will maintain a reference to the stream. When 63 // a SpdyNetworkTransaction) will maintain a reference to the stream. When
76 // initiated by the server, only the SpdySession will maintain any reference, 64 // initiated by the server, only the SpdySession will maintain any reference,
77 // until such a time as a client object requests a stream for the path. 65 // until such a time as a client object requests a stream for the path.
78 class NET_EXPORT_PRIVATE SpdyStream { 66 class NET_EXPORT_PRIVATE SpdyStream {
79 public: 67 public:
80 // Delegate handles protocol specific behavior of spdy stream. 68 // Delegate handles protocol specific behavior of spdy stream.
81 class NET_EXPORT_PRIVATE Delegate { 69 class NET_EXPORT_PRIVATE Delegate {
82 public: 70 public:
83 Delegate() {} 71 Delegate() {}
84 72
85 // Called when the request headers have been sent. Never called 73 // Called when the request headers have been sent. Never called
86 // for push streams. Must not cause the stream to be closed. 74 // for push streams. Must not cause the stream to be closed.
87 virtual void OnRequestHeadersSent() = 0; 75 virtual void OnHeadersSent() = 0;
88 76
89 // WARNING: This function is complicated! Be sure to read the 77 // OnHeadersReceived(), OnDataReceived(), OnTrailers(), and OnClose()
90 // whole comment below if you're working with code that implements 78 // are guaranteed to be called in the following order:
91 // or calls this function. 79 // - OnHeadersReceived() exactly once;
92 // 80 // - OnDataReceived() zero or more times;
93 // Called when the response headers are updated from the 81 // - OnTrailers() zero or one times;
94 // server. |response_headers| contains the set of all headers 82 // - OnClose() exactly once.
95 // received up to this point; delegates can assume that any
96 // headers previously received remain unchanged.
97 //
98 // This is called at least once before any data is received. If
99 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this will be
100 // called again when more headers are received until
101 // RESPONSE_HEADERS_ARE_COMPLETE is returned, and any data
102 // received before then will be treated as a protocol error.
103 //
104 // If RESPONSE_HEADERS_ARE_INCOMPLETE is returned, the delegate
105 // must not have closed the stream. Otherwise, if
106 // RESPONSE_HEADERS_ARE_COMPLETE is returned, the delegate has
107 // processed the headers successfully. However, it still may have
108 // closed the stream, e.g. if the headers indicated an error
109 // condition.
110 //
111 // Some type-specific behavior:
112 //
113 // - For bidirectional streams, this may be called even after
114 // data is received, but it is expected that
115 // RESPONSE_HEADERS_ARE_COMPLETE is always returned. If
116 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
117 // treated as a protocol error.
118 //
119 // - For request/response streams, this function is called
120 // exactly once before data is received, and it is expected
121 // that RESPONSE_HEADERS_ARE_COMPLETE is returned. If
122 // RESPONSE_HEADERS_ARE_INCOMPLETE is returned, this is
123 // treated as a protocol error.
124 //
125 // - For push streams, it is expected that this function will be
126 // called until RESPONSE_HEADERS_ARE_COMPLETE is returned
127 // before any data is received; any deviation from this is
128 // treated as a protocol error.
129 //
130 // TODO(jgraettinger): This should be at the semantic (HTTP) rather
131 // than stream layer. Streams shouldn't have a notion of header
132 // completeness. Move to SpdyHttpStream/SpdyWebsocketStream.
133 virtual SpdyResponseHeadersStatus OnResponseHeadersUpdated(
134 const SpdyHeaderBlock& response_headers) = 0;
135 83
136 // Called when data is received after all required response 84 // Called when headers have been received.
Ryan Hamilton 2016/11/23 20:58:43 This comment is far to easy to understand compared
137 // headers have been received. |buffer| may be NULL, which signals 85 virtual void OnHeadersReceived(const SpdyHeaderBlock& response_headers) = 0;
138 // EOF. Must return OK if the data was received successfully, or 86
139 // a network error code otherwise. 87 // Called when data is received. |buffer| may be NULL, which signals EOF.
140 //
141 // May cause the stream to be closed. 88 // May cause the stream to be closed.
142 virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0; 89 virtual void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) = 0;
143 90
144 // Called when data is sent. Must not cause the stream to be 91 // Called when data is sent. Must not cause the stream to be closed.
145 // closed.
146 virtual void OnDataSent() = 0; 92 virtual void OnDataSent() = 0;
147 93
148 // Called when trailers are received. Note that trailers HEADER frame will 94 // Called when trailers are received.
149 // have END_STREAM flag set according to section 8.1 of the HTTP/2 RFC,
150 // so this will be followed by OnClose.
151 virtual void OnTrailers(const SpdyHeaderBlock& trailers) = 0; 95 virtual void OnTrailers(const SpdyHeaderBlock& trailers) = 0;
152 96
153 // Called when SpdyStream is closed. No other delegate functions 97 // Called when SpdyStream is closed. No other delegate functions
154 // will be called after this is called, and the delegate must not 98 // will be called after this is called, and the delegate must not
155 // access the stream after this is called. Must not cause the 99 // access the stream after this is called. Must not cause the
156 // stream to be be (re-)closed. 100 // stream to be (re-)closed.
157 // 101 //
158 // TODO(akalin): Allow this function to re-close the stream and 102 // TODO(akalin): Allow this function to re-close the stream and
159 // handle it gracefully. 103 // handle it gracefully.
160 virtual void OnClose(int status) = 0; 104 virtual void OnClose(int status) = 0;
161 105
162 protected: 106 protected:
163 virtual ~Delegate() {} 107 virtual ~Delegate() {}
164 108
165 private: 109 private:
166 DISALLOW_COPY_AND_ASSIGN(Delegate); 110 DISALLOW_COPY_AND_ASSIGN(Delegate);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 229
286 // Returns true if the underlying transport socket ever had any reads or 230 // Returns true if the underlying transport socket ever had any reads or
287 // writes. 231 // writes.
288 bool WasEverUsed() const; 232 bool WasEverUsed() const;
289 233
290 const NetLogWithSource& net_log() const { return net_log_; } 234 const NetLogWithSource& net_log() const { return net_log_; }
291 235
292 base::Time GetRequestTime() const; 236 base::Time GetRequestTime() const;
293 void SetRequestTime(base::Time t); 237 void SetRequestTime(base::Time t);
294 238
295 // Called at most once by the SpdySession when the initial response headers 239 // Called by SpdySession when headers are received for this stream. May close
296 // have been received for this stream. Returns a status code; if it is an 240 // the stream.
297 // error, the stream was closed by this function. 241 void OnHeadersReceived(const SpdyHeaderBlock& response_headers,
298 int OnInitialResponseHeadersReceived(const SpdyHeaderBlock& response_headers, 242 base::Time response_time,
299 base::Time response_time, 243 base::TimeTicks recv_first_byte_time);
300 base::TimeTicks recv_first_byte_time);
301
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);
308 244
309 // Called by the SpdySession when a frame carrying request headers opening a 245 // Called by the SpdySession when a frame carrying request headers opening a
310 // push stream is received. Stream transits to STATE_RESERVED_REMOTE state. 246 // push stream is received. Stream transits to STATE_RESERVED_REMOTE state.
311 void OnPushPromiseHeadersReceived(SpdyHeaderBlock headers); 247 void OnPushPromiseHeadersReceived(SpdyHeaderBlock headers);
312 248
313 // Called by the SpdySession when response data has been received 249 // Called by the SpdySession when response data has been received
314 // for this stream. This callback may be called multiple times as 250 // for this stream. This callback may be called multiple times as
315 // data arrives from the network, and will never be called prior to 251 // data arrives from the network, and will never be called prior to
316 // OnResponseHeadersReceived. 252 // OnResponseHeadersReceived.
317 // 253 //
318 // |buffer| contains the data received, or NULL if the stream is 254 // |buffer| contains the data received, or NULL if the stream is
319 // being closed. The stream must copy any data from this 255 // being closed. The stream must copy any data from this
320 // buffer before returning from this callback. 256 // buffer before returning from this callback.
321 // 257 //
322 // |length| is the number of bytes received (at most 2^24 - 1) or 0 if 258 // |length| is the number of bytes received (at most 2^24 - 1) or 0 if
323 // the stream is being closed. 259 // the stream is being closed.
324 void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer); 260 void OnDataReceived(std::unique_ptr<SpdyBuffer> buffer);
325 261
326 // Called by the SpdySession when padding is consumed to allow for the stream 262 // Called by the SpdySession when padding is consumed to allow for the stream
327 // receiving window to be updated. 263 // receiving window to be updated.
328 void OnPaddingConsumed(size_t len); 264 void OnPaddingConsumed(size_t len);
329 265
330 // Called by the SpdySession when a frame has been successfully and completely 266 // 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, 267 // 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 268 // including framing overhead. For fragmented headers, this is the total size
333 // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames. 269 // of the HEADERS or PUSH_PROMISE frame and subsequent CONTINUATION frames.
334 void OnFrameWriteComplete(SpdyFrameType frame_type, size_t frame_size); 270 void OnFrameWriteComplete(SpdyFrameType frame_type, size_t frame_size);
335 271
336 // HEADERS-specific write handler invoked by OnFrameWriteComplete(). 272 // HEADERS-specific write handler invoked by OnFrameWriteComplete().
337 int OnRequestHeadersSent(); 273 int OnHeadersSent();
338 274
339 // DATA-specific write handler invoked by OnFrameWriteComplete(). 275 // DATA-specific write handler invoked by OnFrameWriteComplete().
340 // If more data is already available to be written, the next write is 276 // If more data is already available to be written, the next write is
341 // queued and ERR_IO_PENDING is returned. Returns OK otherwise. 277 // queued and ERR_IO_PENDING is returned. Returns OK otherwise.
342 int OnDataSent(size_t frame_size); 278 int OnDataSent(size_t frame_size);
343 279
344 // Called by the SpdySession when the request is finished. This callback 280 // 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 281 // 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 282 // stream that the stream has no more network events. No further callbacks
347 // to the stream will be made after this call. 283 // to the stream will be made after this call.
(...skipping 12 matching lines...) Expand all
360 void Close(); 296 void Close();
361 297
362 // Must be used only by |session_|. 298 // Must be used only by |session_|.
363 base::WeakPtr<SpdyStream> GetWeakPtr(); 299 base::WeakPtr<SpdyStream> GetWeakPtr();
364 300
365 // Interface for the delegate to use. 301 // Interface for the delegate to use.
366 302
367 // Only one send can be in flight at a time, except for push 303 // Only one send can be in flight at a time, except for push
368 // streams, which must not send anything. 304 // streams, which must not send anything.
369 305
370 // Sends the request headers. The delegate is called back via 306 // Sends the request headers. The delegate is called back via OnHeadersSent()
371 // OnRequestHeadersSent() when the request headers have completed 307 // when the request headers have completed sending. |send_status| must be
372 // sending. |send_status| must be MORE_DATA_TO_SEND for 308 // MORE_DATA_TO_SEND for bidirectional streams; for request/response streams,
373 // bidirectional streams; for request/response streams, it must be 309 // it must be MORE_DATA_TO_SEND if the request has data to upload, or
374 // MORE_DATA_TO_SEND if the request has data to upload, or
375 // NO_MORE_DATA_TO_SEND if not. 310 // NO_MORE_DATA_TO_SEND if not.
376 int SendRequestHeaders(SpdyHeaderBlock request_headers, 311 int SendRequestHeaders(SpdyHeaderBlock request_headers,
377 SpdySendStatus send_status); 312 SpdySendStatus send_status);
378 313
379 // Sends a DATA frame. The delegate will be notified via 314 // Sends a DATA frame. The delegate will be notified via
380 // OnDataSent() when the send is complete. |send_status| must be 315 // OnDataSent() when the send is complete. |send_status| must be
381 // MORE_DATA_TO_SEND for bidirectional streams; for request/response 316 // 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 317 // streams, it must be MORE_DATA_TO_SEND if there is more data to
383 // upload, or NO_MORE_DATA_TO_SEND if not. 318 // upload, or NO_MORE_DATA_TO_SEND if not.
384 void SendData(IOBuffer* data, int length, SpdySendStatus send_status); 319 void SendData(IOBuffer* data, int length, SpdySendStatus send_status);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 enum State { 383 enum State {
449 STATE_IDLE, 384 STATE_IDLE,
450 STATE_OPEN, 385 STATE_OPEN,
451 STATE_HALF_CLOSED_LOCAL_UNCLAIMED, 386 STATE_HALF_CLOSED_LOCAL_UNCLAIMED,
452 STATE_HALF_CLOSED_LOCAL, 387 STATE_HALF_CLOSED_LOCAL,
453 STATE_HALF_CLOSED_REMOTE, 388 STATE_HALF_CLOSED_REMOTE,
454 STATE_RESERVED_REMOTE, 389 STATE_RESERVED_REMOTE,
455 STATE_CLOSED, 390 STATE_CLOSED,
456 }; 391 };
457 392
393 // Per RFC 7540 Section 8.1, an HTTP response consists of:
394 // * zero or more header blocks with informational (1xx) HTTP status,
395 // * one header block,
396 // * zero or more DATA frames,
397 // * zero or one header block ("trailers").
398 // Each header block must have a ":status" header field. SpdyStream enforces
399 // these requirements, and resets the stream if they are not met.
400 // TODO(bnc) https://crbug.com/662197 Add support for informational headers.
401 enum SpdyResponseHeadersStatus {
402 READY_FOR_HEADERS,
403 READY_FOR_DATA,
Ryan Hamilton 2016/11/23 20:58:43 nit: I think this should be renamed to: READY_FOR_
Bence 2016/11/23 21:15:58 Okay, I'll do this.
404 TRAILERS_RECEIVED
405 };
406
458 // Update the histograms. Can safely be called repeatedly, but should only 407 // Update the histograms. Can safely be called repeatedly, but should only
459 // be called after the stream has completed. 408 // be called after the stream has completed.
460 void UpdateHistograms(); 409 void UpdateHistograms();
461 410
462 // When a server-push stream is claimed by SetDelegate(), this function is 411 // When a server-push stream is claimed by SetDelegate(), this function is
463 // posted on the current MessageLoop to replay everything the server has sent. 412 // posted on the current MessageLoop to replay everything the server has sent.
464 // From the perspective of SpdyStream's state machine, headers, data, and 413 // From the perspective of SpdyStream's state machine, headers, data, and
465 // FIN states received prior to the delegate being attached have not yet been 414 // FIN states received prior to the delegate being attached have not yet been
466 // read. While buffered by |pending_recv_data_| it's not until 415 // read. While buffered by |pending_recv_data_| it's not until
467 // PushedStreamReplay() is invoked that reads are considered 416 // PushedStreamReplay() is invoked that reads are considered
468 // to have occurred, driving the state machine forward. 417 // to have occurred, driving the state machine forward.
469 void PushedStreamReplay(); 418 void PushedStreamReplay();
470 419
471 // Produces the HEADERS frame for the stream. The stream must 420 // Produces the HEADERS frame for the stream. The stream must
472 // already be activated. 421 // already be activated.
473 std::unique_ptr<SpdySerializedFrame> ProduceHeadersFrame(); 422 std::unique_ptr<SpdySerializedFrame> ProduceHeadersFrame();
474 423
475 // Queues the send for next frame of the remaining data in 424 // Queues the send for next frame of the remaining data in
476 // |pending_send_data_|. Must be called only when 425 // |pending_send_data_|. Must be called only when
477 // |pending_send_data_| is set. 426 // |pending_send_data_| is set.
478 void QueueNextDataFrame(); 427 void QueueNextDataFrame();
479 428
480 // Merge the given headers into |response_headers_| and calls 429 // Saves the given headers into |response_headers_| and calls
481 // OnResponseHeadersUpdated() on the delegate (if attached). 430 // OnHeadersReceived() on the delegate if attached.
482 // Returns a status code; if it is an error, the stream was closed 431 void SaveResponseHeaders(const SpdyHeaderBlock& response_headers);
483 // by this function.
484 int MergeWithResponseHeaders(const SpdyHeaderBlock& new_response_headers);
485 432
486 static std::string DescribeState(State state); 433 static std::string DescribeState(State state);
487 434
488 const SpdyStreamType type_; 435 const SpdyStreamType type_;
489 436
490 SpdyStreamId stream_id_; 437 SpdyStreamId stream_id_;
491 const GURL url_; 438 const GURL url_;
492 const RequestPriority priority_; 439 const RequestPriority priority_;
493 440
494 bool send_stalled_by_flow_control_; 441 bool send_stalled_by_flow_control_;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 bool write_handler_guard_; 519 bool write_handler_guard_;
573 520
574 base::WeakPtrFactory<SpdyStream> weak_ptr_factory_; 521 base::WeakPtrFactory<SpdyStream> weak_ptr_factory_;
575 522
576 DISALLOW_COPY_AND_ASSIGN(SpdyStream); 523 DISALLOW_COPY_AND_ASSIGN(SpdyStream);
577 }; 524 };
578 525
579 } // namespace net 526 } // namespace net
580 527
581 #endif // NET_SPDY_SPDY_STREAM_H_ 528 #endif // NET_SPDY_SPDY_STREAM_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698