| OLD | NEW |
| 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 #include "net/spdy/spdy_stream.h" | 5 #include "net/spdy/spdy_stream.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 dict->SetInteger("window_size", window_size); | 52 dict->SetInteger("window_size", window_size); |
| 53 return std::move(dict); | 53 return std::move(dict); |
| 54 } | 54 } |
| 55 | 55 |
| 56 bool ContainsUppercaseAscii(base::StringPiece str) { | 56 bool ContainsUppercaseAscii(base::StringPiece str) { |
| 57 return std::any_of(str.begin(), str.end(), base::IsAsciiUpper<char>); | 57 return std::any_of(str.begin(), str.end(), base::IsAsciiUpper<char>); |
| 58 } | 58 } |
| 59 | 59 |
| 60 } // namespace | 60 } // namespace |
| 61 | 61 |
| 62 void SpdyStream::Delegate::OnTrailers(const SpdyHeaderBlock& trailers) {} | |
| 63 | |
| 64 // A wrapper around a stream that calls into ProduceHeadersFrame(). | 62 // A wrapper around a stream that calls into ProduceHeadersFrame(). |
| 65 class SpdyStream::HeadersBufferProducer : public SpdyBufferProducer { | 63 class SpdyStream::HeadersBufferProducer : public SpdyBufferProducer { |
| 66 public: | 64 public: |
| 67 HeadersBufferProducer(const base::WeakPtr<SpdyStream>& stream) | 65 HeadersBufferProducer(const base::WeakPtr<SpdyStream>& stream) |
| 68 : stream_(stream) { | 66 : stream_(stream) { |
| 69 DCHECK(stream_.get()); | 67 DCHECK(stream_.get()); |
| 70 } | 68 } |
| 71 | 69 |
| 72 ~HeadersBufferProducer() override {} | 70 ~HeadersBufferProducer() override {} |
| 73 | 71 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 99 send_stalled_by_flow_control_(false), | 97 send_stalled_by_flow_control_(false), |
| 100 send_window_size_(initial_send_window_size), | 98 send_window_size_(initial_send_window_size), |
| 101 max_recv_window_size_(max_recv_window_size), | 99 max_recv_window_size_(max_recv_window_size), |
| 102 recv_window_size_(max_recv_window_size), | 100 recv_window_size_(max_recv_window_size), |
| 103 unacked_recv_window_bytes_(0), | 101 unacked_recv_window_bytes_(0), |
| 104 session_(session), | 102 session_(session), |
| 105 delegate_(NULL), | 103 delegate_(NULL), |
| 106 request_headers_valid_(false), | 104 request_headers_valid_(false), |
| 107 pending_send_status_(MORE_DATA_TO_SEND), | 105 pending_send_status_(MORE_DATA_TO_SEND), |
| 108 request_time_(base::Time::Now()), | 106 request_time_(base::Time::Now()), |
| 109 response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE), | 107 response_state_(READY_FOR_HEADERS), |
| 110 io_state_(STATE_IDLE), | 108 io_state_(STATE_IDLE), |
| 111 response_status_(OK), | 109 response_status_(OK), |
| 112 net_log_(net_log), | 110 net_log_(net_log), |
| 113 raw_received_bytes_(0), | 111 raw_received_bytes_(0), |
| 114 raw_sent_bytes_(0), | 112 raw_sent_bytes_(0), |
| 115 send_bytes_(0), | 113 send_bytes_(0), |
| 116 recv_bytes_(0), | 114 recv_bytes_(0), |
| 117 write_handler_guard_(false), | 115 write_handler_guard_(false), |
| 118 weak_ptr_factory_(this) { | 116 weak_ptr_factory_(this) { |
| 119 CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM || | 117 CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM || |
| (...skipping 30 matching lines...) Expand all Loading... |
| 150 CHECK_EQ(stream_id_ % 2, 0u); | 148 CHECK_EQ(stream_id_ % 2, 0u); |
| 151 | 149 |
| 152 CHECK_EQ(io_state_, STATE_HALF_CLOSED_LOCAL_UNCLAIMED); | 150 CHECK_EQ(io_state_, STATE_HALF_CLOSED_LOCAL_UNCLAIMED); |
| 153 io_state_ = STATE_HALF_CLOSED_LOCAL; | 151 io_state_ = STATE_HALF_CLOSED_LOCAL; |
| 154 | 152 |
| 155 // The delegate methods called below may delete |this|, so use | 153 // The delegate methods called below may delete |this|, so use |
| 156 // |weak_this| to detect that. | 154 // |weak_this| to detect that. |
| 157 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); | 155 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); |
| 158 | 156 |
| 159 CHECK(delegate_); | 157 CHECK(delegate_); |
| 160 SpdyResponseHeadersStatus status = | 158 delegate_->OnHeadersReceived(response_headers_); |
| 161 delegate_->OnResponseHeadersUpdated(response_headers_); | |
| 162 if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) { | |
| 163 // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not | |
| 164 // have been closed. Since we don't have complete headers, assume | |
| 165 // we're waiting for another HEADERS frame, and we had better not | |
| 166 // have any pending data frames. | |
| 167 CHECK(weak_this); | |
| 168 if (!pending_recv_data_.empty()) { | |
| 169 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, | |
| 170 "Data received with incomplete headers."); | |
| 171 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); | |
| 172 } | |
| 173 return; | |
| 174 } | |
| 175 | 159 |
| 176 // OnResponseHeadersUpdated() may have closed |this|. | 160 // OnHeadersReceived() may have closed |this|. |
| 177 if (!weak_this) | 161 if (!weak_this) |
| 178 return; | 162 return; |
| 179 | 163 |
| 180 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; | |
| 181 | |
| 182 while (!pending_recv_data_.empty()) { | 164 while (!pending_recv_data_.empty()) { |
| 183 // Take ownership of the first element of |pending_recv_data_|. | 165 // Take ownership of the first element of |pending_recv_data_|. |
| 184 std::unique_ptr<SpdyBuffer> buffer = std::move(pending_recv_data_.at(0)); | 166 std::unique_ptr<SpdyBuffer> buffer = std::move(pending_recv_data_.at(0)); |
| 185 pending_recv_data_.erase(pending_recv_data_.begin()); | 167 pending_recv_data_.erase(pending_recv_data_.begin()); |
| 186 | 168 |
| 187 bool eof = (buffer == NULL); | 169 bool eof = (buffer == NULL); |
| 188 | 170 |
| 189 CHECK(delegate_); | 171 CHECK(delegate_); |
| 190 delegate_->OnDataReceived(std::move(buffer)); | 172 delegate_->OnDataReceived(std::move(buffer)); |
| 191 | 173 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 } | 364 } |
| 383 | 365 |
| 384 base::Time SpdyStream::GetRequestTime() const { | 366 base::Time SpdyStream::GetRequestTime() const { |
| 385 return request_time_; | 367 return request_time_; |
| 386 } | 368 } |
| 387 | 369 |
| 388 void SpdyStream::SetRequestTime(base::Time t) { | 370 void SpdyStream::SetRequestTime(base::Time t) { |
| 389 request_time_ = t; | 371 request_time_ = t; |
| 390 } | 372 } |
| 391 | 373 |
| 392 int SpdyStream::OnInitialResponseHeadersReceived( | 374 void SpdyStream::OnHeadersReceived(const SpdyHeaderBlock& response_headers, |
| 393 const SpdyHeaderBlock& initial_response_headers, | 375 base::Time response_time, |
| 394 base::Time response_time, | 376 base::TimeTicks recv_first_byte_time) { |
| 395 base::TimeTicks recv_first_byte_time) { | 377 switch (response_state_) { |
| 396 // SpdySession guarantees that this is called at most once. | 378 case READY_FOR_HEADERS: |
| 397 CHECK(response_headers_.empty()); | 379 // No header block has been received yet. |
| 380 DCHECK(response_headers_.empty()); |
| 398 | 381 |
| 399 // Check to make sure that we don't receive the response headers | 382 if (response_headers.find(":status") == response_headers.end()) { |
| 400 // before we're ready for it. | 383 const std::string error("Response headers do not include :status."); |
| 401 switch (type_) { | 384 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 402 case SPDY_BIDIRECTIONAL_STREAM: | 385 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 403 // For a bidirectional stream, we're ready for the response | 386 return; |
| 404 // headers once we've finished sending the request headers. | |
| 405 if (io_state_ == STATE_IDLE) { | |
| 406 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 407 "Response received before request sent"); | |
| 408 return ERR_SPDY_PROTOCOL_ERROR; | |
| 409 } | 387 } |
| 388 |
| 389 response_state_ = READY_FOR_DATA_OR_TRAILERS; |
| 390 |
| 391 switch (type_) { |
| 392 case SPDY_BIDIRECTIONAL_STREAM: |
| 393 case SPDY_REQUEST_RESPONSE_STREAM: |
| 394 // A bidirectional stream or a request/response stream is ready for |
| 395 // the response headers only after request headers are sent. |
| 396 if (io_state_ == STATE_IDLE) { |
| 397 const std::string error("Response received before request sent."); |
| 398 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 399 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 400 return; |
| 401 } |
| 402 break; |
| 403 |
| 404 case SPDY_PUSH_STREAM: |
| 405 // Push streams transition to a locally half-closed state upon |
| 406 // headers. We must continue to buffer data while waiting for a call |
| 407 // to SetDelegate() (which may not ever happen). |
| 408 DCHECK_EQ(io_state_, STATE_RESERVED_REMOTE); |
| 409 if (!delegate_) { |
| 410 io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED; |
| 411 } else { |
| 412 io_state_ = STATE_HALF_CLOSED_LOCAL; |
| 413 } |
| 414 break; |
| 415 } |
| 416 |
| 417 DCHECK_NE(io_state_, STATE_IDLE); |
| 418 |
| 419 response_time_ = response_time; |
| 420 recv_first_byte_time_ = recv_first_byte_time; |
| 421 SaveResponseHeaders(response_headers); |
| 422 |
| 410 break; | 423 break; |
| 411 | 424 |
| 412 case SPDY_REQUEST_RESPONSE_STREAM: | 425 case READY_FOR_DATA_OR_TRAILERS: |
| 413 // For a request/response stream, we're ready for the response | 426 // Second header block is trailers. |
| 414 // headers once we've finished sending the request headers. | 427 if (type_ == SPDY_PUSH_STREAM) { |
| 415 if (io_state_ == STATE_IDLE) { | 428 const std::string error("Trailers not supported for push stream."); |
| 416 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | 429 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 417 "Response received before request sent"); | 430 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 418 return ERR_SPDY_PROTOCOL_ERROR; | 431 return; |
| 419 } | 432 } |
| 433 |
| 434 response_state_ = TRAILERS_RECEIVED; |
| 435 delegate_->OnTrailers(response_headers); |
| 420 break; | 436 break; |
| 421 | 437 |
| 422 case SPDY_PUSH_STREAM: | 438 case TRAILERS_RECEIVED: |
| 423 // Push streams transition to a locally half-closed state upon headers. | 439 // No further header blocks are allowed after trailers. |
| 424 // We must continue to buffer data while waiting for a call to | 440 const std::string error("Header block received after trailers."); |
| 425 // SetDelegate() (which may not ever happen). | 441 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 426 CHECK_EQ(io_state_, STATE_RESERVED_REMOTE); | 442 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 427 if (!delegate_) { | 443 return; |
| 428 io_state_ = STATE_HALF_CLOSED_LOCAL_UNCLAIMED; | |
| 429 } else { | |
| 430 io_state_ = STATE_HALF_CLOSED_LOCAL; | |
| 431 } | |
| 432 break; | |
| 433 } | 444 } |
| 434 | |
| 435 DCHECK_NE(io_state_, STATE_IDLE); | |
| 436 | |
| 437 response_time_ = response_time; | |
| 438 recv_first_byte_time_ = recv_first_byte_time; | |
| 439 return MergeWithResponseHeaders(initial_response_headers); | |
| 440 } | |
| 441 | |
| 442 int SpdyStream::OnAdditionalResponseHeadersReceived( | |
| 443 const SpdyHeaderBlock& additional_response_headers) { | |
| 444 if (type_ == SPDY_REQUEST_RESPONSE_STREAM) { | |
| 445 if (response_headers_status_ != RESPONSE_HEADERS_ARE_COMPLETE) { | |
| 446 session_->ResetStream( | |
| 447 stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 448 "Additional headers received for request/response stream"); | |
| 449 return ERR_SPDY_PROTOCOL_ERROR; | |
| 450 } | |
| 451 response_headers_status_ = TRAILERS_RECEIVED; | |
| 452 delegate_->OnTrailers(additional_response_headers); | |
| 453 return OK; | |
| 454 } | |
| 455 if (type_ == SPDY_BIDIRECTIONAL_STREAM) { | |
| 456 DCHECK_EQ(RESPONSE_HEADERS_ARE_COMPLETE, response_headers_status_); | |
| 457 response_headers_status_ = TRAILERS_RECEIVED; | |
| 458 delegate_->OnTrailers(additional_response_headers); | |
| 459 return OK; | |
| 460 } | |
| 461 if (type_ == SPDY_PUSH_STREAM && | |
| 462 response_headers_status_ == RESPONSE_HEADERS_ARE_COMPLETE) { | |
| 463 session_->ResetStream( | |
| 464 stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 465 "Additional headers received for push stream"); | |
| 466 return ERR_SPDY_PROTOCOL_ERROR; | |
| 467 } | |
| 468 return MergeWithResponseHeaders(additional_response_headers); | |
| 469 } | 445 } |
| 470 | 446 |
| 471 void SpdyStream::OnPushPromiseHeadersReceived(SpdyHeaderBlock headers) { | 447 void SpdyStream::OnPushPromiseHeadersReceived(SpdyHeaderBlock headers) { |
| 472 CHECK(!request_headers_valid_); | 448 CHECK(!request_headers_valid_); |
| 473 CHECK_EQ(io_state_, STATE_IDLE); | 449 CHECK_EQ(io_state_, STATE_IDLE); |
| 474 CHECK_EQ(type_, SPDY_PUSH_STREAM); | 450 CHECK_EQ(type_, SPDY_PUSH_STREAM); |
| 475 DCHECK(!delegate_); | 451 DCHECK(!delegate_); |
| 476 | 452 |
| 477 io_state_ = STATE_RESERVED_REMOTE; | 453 io_state_ = STATE_RESERVED_REMOTE; |
| 478 request_headers_ = std::move(headers); | 454 request_headers_ = std::move(headers); |
| 479 request_headers_valid_ = true; | 455 request_headers_valid_ = true; |
| 480 url_from_header_block_ = GetUrlFromHeaderBlock(request_headers_); | 456 url_from_header_block_ = GetUrlFromHeaderBlock(request_headers_); |
| 481 } | 457 } |
| 482 | 458 |
| 483 void SpdyStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) { | 459 void SpdyStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) { |
| 484 DCHECK(session_->IsStreamActive(stream_id_)); | 460 DCHECK(session_->IsStreamActive(stream_id_)); |
| 485 | 461 |
| 462 if (response_state_ == READY_FOR_HEADERS) { |
| 463 const std::string error("DATA received before headers."); |
| 464 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 465 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 466 return; |
| 467 } |
| 468 |
| 469 if (response_state_ == TRAILERS_RECEIVED && buffer) { |
| 470 const std::string error("DATA received after trailers."); |
| 471 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); |
| 472 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, error); |
| 473 return; |
| 474 } |
| 475 |
| 486 // Track our bandwidth. | 476 // Track our bandwidth. |
| 487 recv_bytes_ += buffer ? buffer->GetRemainingSize() : 0; | 477 recv_bytes_ += buffer ? buffer->GetRemainingSize() : 0; |
| 488 recv_last_byte_time_ = base::TimeTicks::Now(); | 478 recv_last_byte_time_ = base::TimeTicks::Now(); |
| 489 | 479 |
| 490 // If we're still buffering data for a push stream, we will do the | 480 // If we're still buffering data for a push stream, we will do the check for |
| 491 // check for data received with incomplete headers in | 481 // data received with incomplete headers in PushedStreamReplay(). |
| 492 // PushedStreamReplayData(). | |
| 493 if (io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED) { | 482 if (io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED) { |
| 494 DCHECK_EQ(type_, SPDY_PUSH_STREAM); | 483 DCHECK_EQ(type_, SPDY_PUSH_STREAM); |
| 495 // It should be valid for this to happen in the server push case. | 484 // It should be valid for this to happen in the server push case. |
| 496 // We'll return received data when delegate gets attached to the stream. | 485 // We'll return received data when delegate gets attached to the stream. |
| 497 if (buffer) { | 486 if (buffer) { |
| 498 pending_recv_data_.push_back(std::move(buffer)); | 487 pending_recv_data_.push_back(std::move(buffer)); |
| 499 } else { | 488 } else { |
| 500 pending_recv_data_.push_back(NULL); | 489 pending_recv_data_.push_back(NULL); |
| 501 // Note: we leave the stream open in the session until the stream | 490 // Note: we leave the stream open in the session until the stream |
| 502 // is claimed. | 491 // is claimed. |
| 503 } | 492 } |
| 504 return; | 493 return; |
| 505 } | 494 } |
| 506 | 495 |
| 507 if (response_headers_status_ == TRAILERS_RECEIVED && buffer) { | |
| 508 // TRAILERS_RECEIVED is only used in SPDY_REQUEST_RESPONSE_STREAM and | |
| 509 // SPDY_BIDIRECTIONAL_STREAM. | |
| 510 DCHECK(type_ == SPDY_REQUEST_RESPONSE_STREAM || | |
| 511 type_ == SPDY_BIDIRECTIONAL_STREAM); | |
| 512 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 513 "Data received after trailers"); | |
| 514 return; | |
| 515 } | |
| 516 | |
| 517 // If we have response headers but the delegate has indicated that | |
| 518 // it's still incomplete, then that's a protocol error. | |
| 519 if (response_headers_status_ == RESPONSE_HEADERS_ARE_INCOMPLETE) { | |
| 520 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, | |
| 521 "Data received with incomplete headers."); | |
| 522 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); | |
| 523 return; | |
| 524 } | |
| 525 | |
| 526 CHECK(!IsClosed()); | 496 CHECK(!IsClosed()); |
| 527 | 497 |
| 528 if (!buffer) { | 498 if (!buffer) { |
| 529 if (io_state_ == STATE_OPEN) { | 499 if (io_state_ == STATE_OPEN) { |
| 530 io_state_ = STATE_HALF_CLOSED_REMOTE; | 500 io_state_ = STATE_HALF_CLOSED_REMOTE; |
| 531 } else if (io_state_ == STATE_HALF_CLOSED_LOCAL) { | 501 } else if (io_state_ == STATE_HALF_CLOSED_LOCAL) { |
| 532 io_state_ = STATE_CLOSED; | 502 io_state_ = STATE_CLOSED; |
| 533 // Deletes |this|. | 503 // Deletes |this|. |
| 534 session_->CloseActiveStream(stream_id_, OK); | 504 session_->CloseActiveStream(stream_id_, OK); |
| 535 } else { | 505 } else { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 564 return; | 534 return; |
| 565 IncreaseRecvWindowSize(static_cast<int32_t>(len)); | 535 IncreaseRecvWindowSize(static_cast<int32_t>(len)); |
| 566 } | 536 } |
| 567 | 537 |
| 568 void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type, | 538 void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type, |
| 569 size_t frame_size) { | 539 size_t frame_size) { |
| 570 DCHECK_NE(type_, SPDY_PUSH_STREAM); | 540 DCHECK_NE(type_, SPDY_PUSH_STREAM); |
| 571 CHECK(frame_type == HEADERS || frame_type == DATA) << frame_type; | 541 CHECK(frame_type == HEADERS || frame_type == DATA) << frame_type; |
| 572 | 542 |
| 573 int result = | 543 int result = |
| 574 (frame_type == HEADERS) ? OnRequestHeadersSent() : OnDataSent(frame_size); | 544 (frame_type == HEADERS) ? OnHeadersSent() : OnDataSent(frame_size); |
| 575 if (result == ERR_IO_PENDING) { | 545 if (result == ERR_IO_PENDING) { |
| 576 // The write operation hasn't completed yet. | 546 // The write operation hasn't completed yet. |
| 577 return; | 547 return; |
| 578 } | 548 } |
| 579 | 549 |
| 580 if (pending_send_status_ == NO_MORE_DATA_TO_SEND) { | 550 if (pending_send_status_ == NO_MORE_DATA_TO_SEND) { |
| 581 if (io_state_ == STATE_OPEN) { | 551 if (io_state_ == STATE_OPEN) { |
| 582 io_state_ = STATE_HALF_CLOSED_LOCAL; | 552 io_state_ = STATE_HALF_CLOSED_LOCAL; |
| 583 } else if (io_state_ == STATE_HALF_CLOSED_REMOTE) { | 553 } else if (io_state_ == STATE_HALF_CLOSED_REMOTE) { |
| 584 io_state_ = STATE_CLOSED; | 554 io_state_ = STATE_CLOSED; |
| 585 } else { | 555 } else { |
| 586 NOTREACHED() << io_state_; | 556 NOTREACHED() << io_state_; |
| 587 } | 557 } |
| 588 } | 558 } |
| 589 // Notify delegate of write completion. Must not destroy |this|. | 559 // Notify delegate of write completion. Must not destroy |this|. |
| 590 CHECK(delegate_); | 560 CHECK(delegate_); |
| 591 { | 561 { |
| 592 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); | 562 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); |
| 593 write_handler_guard_ = true; | 563 write_handler_guard_ = true; |
| 594 if (frame_type == HEADERS) { | 564 if (frame_type == HEADERS) { |
| 595 delegate_->OnRequestHeadersSent(); | 565 delegate_->OnHeadersSent(); |
| 596 } else { | 566 } else { |
| 597 delegate_->OnDataSent(); | 567 delegate_->OnDataSent(); |
| 598 } | 568 } |
| 599 CHECK(weak_this); | 569 CHECK(weak_this); |
| 600 write_handler_guard_ = false; | 570 write_handler_guard_ = false; |
| 601 } | 571 } |
| 602 | 572 |
| 603 if (io_state_ == STATE_CLOSED) { | 573 if (io_state_ == STATE_CLOSED) { |
| 604 // Deletes |this|. | 574 // Deletes |this|. |
| 605 session_->CloseActiveStream(stream_id_, OK); | 575 session_->CloseActiveStream(stream_id_, OK); |
| 606 } | 576 } |
| 607 } | 577 } |
| 608 | 578 |
| 609 int SpdyStream::OnRequestHeadersSent() { | 579 int SpdyStream::OnHeadersSent() { |
| 610 CHECK_EQ(io_state_, STATE_IDLE); | 580 CHECK_EQ(io_state_, STATE_IDLE); |
| 611 CHECK_NE(stream_id_, 0u); | 581 CHECK_NE(stream_id_, 0u); |
| 612 | 582 |
| 613 io_state_ = STATE_OPEN; | 583 io_state_ = STATE_OPEN; |
| 614 return OK; | 584 return OK; |
| 615 } | 585 } |
| 616 | 586 |
| 617 int SpdyStream::OnDataSent(size_t frame_size) { | 587 int SpdyStream::OnDataSent(size_t frame_size) { |
| 618 CHECK(io_state_ == STATE_OPEN || | 588 CHECK(io_state_ == STATE_OPEN || |
| 619 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; | 589 io_state_ == STATE_HALF_CLOSED_REMOTE) << io_state_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 641 net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ERROR, | 611 net_log_.AddEvent(NetLogEventType::HTTP2_STREAM_ERROR, |
| 642 base::Bind(&NetLogSpdyStreamErrorCallback, stream_id_, | 612 base::Bind(&NetLogSpdyStreamErrorCallback, stream_id_, |
| 643 status, &description)); | 613 status, &description)); |
| 644 } | 614 } |
| 645 | 615 |
| 646 void SpdyStream::OnClose(int status) { | 616 void SpdyStream::OnClose(int status) { |
| 647 // In most cases, the stream should already be CLOSED. The exception is when a | 617 // In most cases, the stream should already be CLOSED. The exception is when a |
| 648 // SpdySession is shutting down while the stream is in an intermediate state. | 618 // SpdySession is shutting down while the stream is in an intermediate state. |
| 649 io_state_ = STATE_CLOSED; | 619 io_state_ = STATE_CLOSED; |
| 650 if (status == ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED) { | 620 if (status == ERR_SPDY_RST_STREAM_NO_ERROR_RECEIVED) { |
| 651 if (response_headers_status_ == RESPONSE_HEADERS_ARE_INCOMPLETE) { | 621 if (response_state_ == READY_FOR_HEADERS) { |
| 652 status = ERR_SPDY_PROTOCOL_ERROR; | 622 status = ERR_SPDY_PROTOCOL_ERROR; |
| 653 } else { | 623 } else { |
| 654 status = OK; | 624 status = OK; |
| 655 } | 625 } |
| 656 } | 626 } |
| 657 response_status_ = status; | 627 response_status_ = status; |
| 658 Delegate* delegate = delegate_; | 628 Delegate* delegate = delegate_; |
| 659 delegate_ = NULL; | 629 delegate_ = NULL; |
| 660 if (delegate) | 630 if (delegate) |
| 661 delegate->OnClose(status); | 631 delegate->OnClose(status); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 862 data_buffer->AddConsumeCallback(base::Bind( | 832 data_buffer->AddConsumeCallback(base::Bind( |
| 863 &SpdyStream::OnWriteBufferConsumed, GetWeakPtr(), payload_size)); | 833 &SpdyStream::OnWriteBufferConsumed, GetWeakPtr(), payload_size)); |
| 864 } | 834 } |
| 865 | 835 |
| 866 session_->EnqueueStreamWrite( | 836 session_->EnqueueStreamWrite( |
| 867 GetWeakPtr(), DATA, | 837 GetWeakPtr(), DATA, |
| 868 std::unique_ptr<SpdyBufferProducer>( | 838 std::unique_ptr<SpdyBufferProducer>( |
| 869 new SimpleBufferProducer(std::move(data_buffer)))); | 839 new SimpleBufferProducer(std::move(data_buffer)))); |
| 870 } | 840 } |
| 871 | 841 |
| 872 int SpdyStream::MergeWithResponseHeaders( | 842 void SpdyStream::SaveResponseHeaders(const SpdyHeaderBlock& response_headers) { |
| 873 const SpdyHeaderBlock& new_response_headers) { | 843 DCHECK(response_headers_.empty()); |
| 874 if (new_response_headers.find("transfer-encoding") != | 844 if (response_headers.find("transfer-encoding") != response_headers.end()) { |
| 875 new_response_headers.end()) { | |
| 876 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | 845 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, |
| 877 "Received transfer-encoding header"); | 846 "Received transfer-encoding header"); |
| 878 return ERR_SPDY_PROTOCOL_ERROR; | 847 return; |
| 879 } | 848 } |
| 880 | 849 |
| 881 for (SpdyHeaderBlock::const_iterator it = new_response_headers.begin(); | 850 for (SpdyHeaderBlock::const_iterator it = response_headers.begin(); |
| 882 it != new_response_headers.end(); ++it) { | 851 it != response_headers.end(); ++it) { |
| 883 // Disallow uppercase headers. | 852 // Disallow uppercase headers. |
| 884 if (ContainsUppercaseAscii(it->first)) { | 853 if (ContainsUppercaseAscii(it->first)) { |
| 885 session_->ResetStream( | 854 session_->ResetStream( |
| 886 stream_id_, RST_STREAM_PROTOCOL_ERROR, | 855 stream_id_, RST_STREAM_PROTOCOL_ERROR, |
| 887 "Upper case characters in header: " + it->first.as_string()); | 856 "Upper case characters in header: " + it->first.as_string()); |
| 888 return ERR_SPDY_PROTOCOL_ERROR; | 857 return; |
| 889 } | |
| 890 | |
| 891 SpdyHeaderBlock::iterator it2 = response_headers_.find(it->first); | |
| 892 // Disallow duplicate headers. This is just to be conservative. | |
| 893 if (it2 != response_headers_.end()) { | |
| 894 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 895 "Duplicate header: " + it->first.as_string()); | |
| 896 return ERR_SPDY_PROTOCOL_ERROR; | |
| 897 } | 858 } |
| 898 | 859 |
| 899 response_headers_.insert(*it); | 860 response_headers_.insert(*it); |
| 900 } | 861 } |
| 901 | 862 |
| 902 // If delegate_ is not yet attached, we'll call | 863 // If delegate is not yet attached, OnHeadersReceived() will be called after |
| 903 // OnResponseHeadersUpdated() after the delegate gets attached to | 864 // the delegate gets attached to the stream. |
| 904 // the stream. | 865 if (delegate_) |
| 905 if (delegate_) { | 866 delegate_->OnHeadersReceived(response_headers_); |
| 906 // The call to OnResponseHeadersUpdated() below may delete |this|, | |
| 907 // so use |weak_this| to detect that. | |
| 908 base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); | |
| 909 | |
| 910 SpdyResponseHeadersStatus status = | |
| 911 delegate_->OnResponseHeadersUpdated(response_headers_); | |
| 912 if (status == RESPONSE_HEADERS_ARE_INCOMPLETE) { | |
| 913 // Since RESPONSE_HEADERS_ARE_INCOMPLETE was returned, we must not | |
| 914 // have been closed. | |
| 915 CHECK(weak_this); | |
| 916 // Incomplete headers are OK only for push streams. | |
| 917 if (type_ != SPDY_PUSH_STREAM) { | |
| 918 session_->ResetStream(stream_id_, RST_STREAM_PROTOCOL_ERROR, | |
| 919 "Incomplete headers"); | |
| 920 return ERR_INCOMPLETE_SPDY_HEADERS; | |
| 921 } | |
| 922 } else if (weak_this) { | |
| 923 response_headers_status_ = RESPONSE_HEADERS_ARE_COMPLETE; | |
| 924 } | |
| 925 } | |
| 926 | |
| 927 return OK; | |
| 928 } | 867 } |
| 929 | 868 |
| 930 #define STATE_CASE(s) \ | 869 #define STATE_CASE(s) \ |
| 931 case s: \ | 870 case s: \ |
| 932 description = base::StringPrintf("%s (0x%08X)", #s, s); \ | 871 description = base::StringPrintf("%s (0x%08X)", #s, s); \ |
| 933 break | 872 break |
| 934 | 873 |
| 935 std::string SpdyStream::DescribeState(State state) { | 874 std::string SpdyStream::DescribeState(State state) { |
| 936 std::string description; | 875 std::string description; |
| 937 switch (state) { | 876 switch (state) { |
| 938 STATE_CASE(STATE_IDLE); | 877 STATE_CASE(STATE_IDLE); |
| 939 STATE_CASE(STATE_OPEN); | 878 STATE_CASE(STATE_OPEN); |
| 940 STATE_CASE(STATE_HALF_CLOSED_LOCAL_UNCLAIMED); | 879 STATE_CASE(STATE_HALF_CLOSED_LOCAL_UNCLAIMED); |
| 941 STATE_CASE(STATE_HALF_CLOSED_LOCAL); | 880 STATE_CASE(STATE_HALF_CLOSED_LOCAL); |
| 942 STATE_CASE(STATE_CLOSED); | 881 STATE_CASE(STATE_CLOSED); |
| 943 default: | 882 default: |
| 944 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | 883 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
| 945 state); | 884 state); |
| 946 break; | 885 break; |
| 947 } | 886 } |
| 948 return description; | 887 return description; |
| 949 } | 888 } |
| 950 | 889 |
| 951 #undef STATE_CASE | 890 #undef STATE_CASE |
| 952 | 891 |
| 953 } // namespace net | 892 } // namespace net |
| OLD | NEW |