| 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 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 } | 134 } |
| 135 | 135 |
| 136 void SpdyStream::PushedStreamReplayData() { | 136 void SpdyStream::PushedStreamReplayData() { |
| 137 DCHECK_NE(stream_id_, 0u); | 137 DCHECK_NE(stream_id_, 0u); |
| 138 | 138 |
| 139 if (!delegate_) | 139 if (!delegate_) |
| 140 return; | 140 return; |
| 141 | 141 |
| 142 continue_buffering_data_ = false; | 142 continue_buffering_data_ = false; |
| 143 | 143 |
| 144 // TODO(akalin): This call may delete this object. Figure out what |
| 145 // to do in that case. |
| 144 int rv = delegate_->OnResponseReceived(*response_, response_time_, OK); | 146 int rv = delegate_->OnResponseReceived(*response_, response_time_, OK); |
| 145 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) { | 147 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) { |
| 146 // We don't have complete headers. Assume we're waiting for another | 148 // We don't have complete headers. Assume we're waiting for another |
| 147 // HEADERS frame. Since we don't have headers, we had better not have | 149 // HEADERS frame. Since we don't have headers, we had better not have |
| 148 // any pending data frames. | 150 // any pending data frames. |
| 149 if (pending_buffers_.size() != 0U) { | 151 if (pending_buffers_.size() != 0U) { |
| 150 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, | 152 LogStreamError(ERR_SPDY_PROTOCOL_ERROR, |
| 151 "HEADERS incomplete headers, but pending data frames."); | 153 "HEADERS incomplete headers, but pending data frames."); |
| 152 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); | 154 session_->CloseActiveStream(stream_id_, ERR_SPDY_PROTOCOL_ERROR); |
| 153 } | 155 } |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 *response_ = response; // TODO(ukai): avoid copy. | 384 *response_ = response; // TODO(ukai): avoid copy. |
| 383 | 385 |
| 384 recv_first_byte_time_ = base::TimeTicks::Now(); | 386 recv_first_byte_time_ = base::TimeTicks::Now(); |
| 385 response_time_ = base::Time::Now(); | 387 response_time_ = base::Time::Now(); |
| 386 | 388 |
| 387 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then | 389 // If we receive a response before we are in STATE_WAITING_FOR_RESPONSE, then |
| 388 // the server has sent the SYN_REPLY too early. | 390 // the server has sent the SYN_REPLY too early. |
| 389 if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) | 391 if (!pushed_ && io_state_ != STATE_WAITING_FOR_RESPONSE) |
| 390 return ERR_SPDY_PROTOCOL_ERROR; | 392 return ERR_SPDY_PROTOCOL_ERROR; |
| 391 if (pushed_) | 393 if (pushed_) |
| 392 CHECK(io_state_ == STATE_NONE); | 394 CHECK_EQ(io_state_, STATE_NONE); |
| 393 io_state_ = STATE_OPEN; | 395 io_state_ = STATE_OPEN; |
| 394 | 396 |
| 395 // Append all the headers into the response header block. | 397 // Append all the headers into the response header block. |
| 396 for (SpdyHeaderBlock::const_iterator it = response.begin(); | 398 for (SpdyHeaderBlock::const_iterator it = response.begin(); |
| 397 it != response.end(); ++it) { | 399 it != response.end(); ++it) { |
| 398 // Disallow uppercase headers. | 400 // Disallow uppercase headers. |
| 399 if (ContainsUpperAscii(it->first)) { | 401 if (ContainsUpperAscii(it->first)) { |
| 400 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, | 402 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, |
| 401 "Upper case characters in header: " + it->first); | 403 "Upper case characters in header: " + it->first); |
| 402 return ERR_SPDY_PROTOCOL_ERROR; | 404 return ERR_SPDY_PROTOCOL_ERROR; |
| 403 } | 405 } |
| 404 } | 406 } |
| 405 | 407 |
| 406 if ((*response_).find("transfer-encoding") != (*response_).end()) { | 408 if ((*response_).find("transfer-encoding") != (*response_).end()) { |
| 407 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, | 409 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, |
| 408 "Received transfer-encoding header"); | 410 "Received transfer-encoding header"); |
| 409 return ERR_SPDY_PROTOCOL_ERROR; | 411 return ERR_SPDY_PROTOCOL_ERROR; |
| 410 } | 412 } |
| 411 | 413 |
| 412 if (delegate_) | 414 if (delegate_) { |
| 415 // May delete this object. |
| 413 rv = delegate_->OnResponseReceived(*response_, response_time_, rv); | 416 rv = delegate_->OnResponseReceived(*response_, response_time_, rv); |
| 417 } |
| 414 // If delegate_ is not yet attached, we'll call OnResponseReceived after the | 418 // If delegate_ is not yet attached, we'll call OnResponseReceived after the |
| 415 // delegate gets attached to the stream. | 419 // delegate gets attached to the stream. |
| 416 | 420 |
| 417 return rv; | 421 return rv; |
| 418 } | 422 } |
| 419 | 423 |
| 420 int SpdyStream::OnHeaders(const SpdyHeaderBlock& headers) { | 424 int SpdyStream::OnHeaders(const SpdyHeaderBlock& headers) { |
| 421 DCHECK(!response_->empty()); | 425 DCHECK(!response_->empty()); |
| 422 | 426 |
| 423 // Append all the headers into the response header block. | 427 // Append all the headers into the response header block. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 441 } | 445 } |
| 442 | 446 |
| 443 if ((*response_).find("transfer-encoding") != (*response_).end()) { | 447 if ((*response_).find("transfer-encoding") != (*response_).end()) { |
| 444 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, | 448 session_->ResetStream(stream_id_, priority_, RST_STREAM_PROTOCOL_ERROR, |
| 445 "Received transfer-encoding header"); | 449 "Received transfer-encoding header"); |
| 446 return ERR_SPDY_PROTOCOL_ERROR; | 450 return ERR_SPDY_PROTOCOL_ERROR; |
| 447 } | 451 } |
| 448 | 452 |
| 449 int rv = OK; | 453 int rv = OK; |
| 450 if (delegate_) { | 454 if (delegate_) { |
| 455 // May delete this object. |
| 451 rv = delegate_->OnResponseReceived(*response_, response_time_, rv); | 456 rv = delegate_->OnResponseReceived(*response_, response_time_, rv); |
| 452 // ERR_INCOMPLETE_SPDY_HEADERS means that we are waiting for more | 457 // ERR_INCOMPLETE_SPDY_HEADERS means that we are waiting for more |
| 453 // headers before the response header block is complete. | 458 // headers before the response header block is complete. |
| 454 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) | 459 if (rv == ERR_INCOMPLETE_SPDY_HEADERS) |
| 455 rv = OK; | 460 rv = OK; |
| 456 } | 461 } |
| 457 return rv; | 462 return rv; |
| 458 } | 463 } |
| 459 | 464 |
| 460 void SpdyStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { | 465 void SpdyStream::OnDataReceived(scoped_ptr<SpdyBuffer> buffer) { |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 // DoSendBody is called to send the optional body for the request. This call | 826 // DoSendBody is called to send the optional body for the request. This call |
| 822 // will also be called as each write of a chunk of the body completes. | 827 // will also be called as each write of a chunk of the body completes. |
| 823 int SpdyStream::DoSendBody() { | 828 int SpdyStream::DoSendBody() { |
| 824 io_state_ = STATE_SEND_BODY_COMPLETE; | 829 io_state_ = STATE_SEND_BODY_COMPLETE; |
| 825 CHECK(delegate_); | 830 CHECK(delegate_); |
| 826 delegate_->OnSendBody(); | 831 delegate_->OnSendBody(); |
| 827 return ERR_IO_PENDING; | 832 return ERR_IO_PENDING; |
| 828 } | 833 } |
| 829 | 834 |
| 830 int SpdyStream::DoSendBodyComplete(int result) { | 835 int SpdyStream::DoSendBodyComplete(int result) { |
| 836 result = ProcessJustCompletedFrame(result, STATE_SEND_BODY_COMPLETE); |
| 837 |
| 831 if (result != OK) | 838 if (result != OK) |
| 832 return result; | 839 return result; |
| 833 | 840 |
| 841 SpdySendStatus send_status = delegate_->OnSendBodyComplete(); |
| 842 |
| 843 io_state_ = |
| 844 (send_status == MORE_DATA_TO_SEND) ? |
| 845 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; |
| 846 |
| 847 return OK; |
| 848 } |
| 849 |
| 850 int SpdyStream::DoOpen() { |
| 851 int result = ProcessJustCompletedFrame(OK, STATE_OPEN); |
| 852 |
| 853 if (result != OK) |
| 854 return result; |
| 855 |
| 856 // Set |io_state_| first as |delegate_| may check it. |
| 857 io_state_ = STATE_OPEN; |
| 858 |
| 859 delegate_->OnDataSent(); |
| 860 |
| 861 return OK; |
| 862 } |
| 863 |
| 864 int SpdyStream::ProcessJustCompletedFrame(int result, State io_pending_state) { |
| 865 if (result != OK) |
| 866 return result; |
| 867 |
| 834 if (just_completed_frame_type_ != DATA) { | 868 if (just_completed_frame_type_ != DATA) { |
| 835 NOTREACHED(); | 869 NOTREACHED(); |
| 836 return ERR_UNEXPECTED; | 870 return ERR_UNEXPECTED; |
| 837 } | 871 } |
| 838 | 872 |
| 839 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | 873 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { |
| 840 NOTREACHED(); | 874 NOTREACHED(); |
| 841 return ERR_UNEXPECTED; | 875 return ERR_UNEXPECTED; |
| 842 } | 876 } |
| 843 | 877 |
| 844 size_t frame_payload_size = | 878 size_t frame_payload_size = |
| 845 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | 879 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); |
| 846 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | 880 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { |
| 847 NOTREACHED(); | 881 NOTREACHED(); |
| 848 return ERR_UNEXPECTED; | 882 return ERR_UNEXPECTED; |
| 849 } | 883 } |
| 850 | 884 |
| 851 send_bytes_ += frame_payload_size; | 885 send_bytes_ += frame_payload_size; |
| 852 | 886 |
| 853 pending_send_data_->DidConsume(frame_payload_size); | 887 pending_send_data_->DidConsume(frame_payload_size); |
| 854 if (pending_send_data_->BytesRemaining() > 0) { | 888 if (pending_send_data_->BytesRemaining() > 0) { |
| 855 io_state_ = STATE_SEND_BODY_COMPLETE; | 889 io_state_ = io_pending_state; |
| 856 QueueNextDataFrame(); | 890 QueueNextDataFrame(); |
| 857 return ERR_IO_PENDING; | 891 return ERR_IO_PENDING; |
| 858 } | 892 } |
| 859 | 893 |
| 860 pending_send_data_ = NULL; | 894 pending_send_data_ = NULL; |
| 861 pending_send_flags_ = DATA_FLAG_NONE; | 895 pending_send_flags_ = DATA_FLAG_NONE; |
| 862 | 896 |
| 863 if (!delegate_) { | 897 if (!delegate_) { |
| 864 NOTREACHED(); | 898 NOTREACHED(); |
| 865 return ERR_UNEXPECTED; | 899 return ERR_UNEXPECTED; |
| 866 } | 900 } |
| 867 | 901 |
| 868 io_state_ = | |
| 869 (delegate_->OnSendBodyComplete() == MORE_DATA_TO_SEND) ? | |
| 870 STATE_SEND_BODY : STATE_WAITING_FOR_RESPONSE; | |
| 871 | |
| 872 return OK; | |
| 873 } | |
| 874 | |
| 875 int SpdyStream::DoOpen() { | |
| 876 io_state_ = STATE_OPEN; | |
| 877 | |
| 878 switch (just_completed_frame_type_) { | |
| 879 case DATA: { | |
| 880 if (just_completed_frame_size_ < session_->GetDataFrameMinimumSize()) { | |
| 881 NOTREACHED(); | |
| 882 return ERR_UNEXPECTED; | |
| 883 } | |
| 884 | |
| 885 size_t frame_payload_size = | |
| 886 just_completed_frame_size_ - session_->GetDataFrameMinimumSize(); | |
| 887 if (frame_payload_size > session_->GetDataFrameMaximumPayload()) { | |
| 888 NOTREACHED(); | |
| 889 return ERR_UNEXPECTED; | |
| 890 } | |
| 891 | |
| 892 send_bytes_ += frame_payload_size; | |
| 893 | |
| 894 pending_send_data_->DidConsume(frame_payload_size); | |
| 895 if (pending_send_data_->BytesRemaining() > 0) { | |
| 896 QueueNextDataFrame(); | |
| 897 return ERR_IO_PENDING; | |
| 898 } | |
| 899 | |
| 900 pending_send_data_ = NULL; | |
| 901 pending_send_flags_ = DATA_FLAG_NONE; | |
| 902 | |
| 903 if (delegate_) | |
| 904 delegate_->OnDataSent(); | |
| 905 | |
| 906 break; | |
| 907 } | |
| 908 | |
| 909 case HEADERS: | |
| 910 if (delegate_) | |
| 911 delegate_->OnHeadersSent(); | |
| 912 break; | |
| 913 | |
| 914 default: | |
| 915 NOTREACHED(); | |
| 916 return ERR_UNEXPECTED; | |
| 917 } | |
| 918 | |
| 919 return OK; | 902 return OK; |
| 920 } | 903 } |
| 921 | 904 |
| 922 void SpdyStream::UpdateHistograms() { | 905 void SpdyStream::UpdateHistograms() { |
| 923 // We need all timers to be filled in, otherwise metrics can be bogus. | 906 // We need all timers to be filled in, otherwise metrics can be bogus. |
| 924 if (send_time_.is_null() || recv_first_byte_time_.is_null() || | 907 if (send_time_.is_null() || recv_first_byte_time_.is_null() || |
| 925 recv_last_byte_time_.is_null()) | 908 recv_last_byte_time_.is_null()) |
| 926 return; | 909 return; |
| 927 | 910 |
| 928 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", | 911 UMA_HISTOGRAM_TIMES("Net.SpdyStreamTimeToFirstByte", |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 967 GetWeakPtr(), payload_size)); | 950 GetWeakPtr(), payload_size)); |
| 968 } | 951 } |
| 969 | 952 |
| 970 session_->EnqueueStreamWrite( | 953 session_->EnqueueStreamWrite( |
| 971 GetWeakPtr(), DATA, | 954 GetWeakPtr(), DATA, |
| 972 scoped_ptr<SpdyBufferProducer>( | 955 scoped_ptr<SpdyBufferProducer>( |
| 973 new SimpleBufferProducer(data_buffer.Pass()))); | 956 new SimpleBufferProducer(data_buffer.Pass()))); |
| 974 } | 957 } |
| 975 | 958 |
| 976 } // namespace net | 959 } // namespace net |
| OLD | NEW |