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 |