| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "net/spdy/spdy_frame_producer.h" |
| 13 #include "net/spdy/spdy_http_utils.h" | 14 #include "net/spdy/spdy_http_utils.h" |
| 14 #include "net/spdy/spdy_session.h" | 15 #include "net/spdy/spdy_session.h" |
| 15 | 16 |
| 16 namespace net { | 17 namespace net { |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 Value* NetLogSpdyStreamErrorCallback(SpdyStreamId stream_id, | 21 Value* NetLogSpdyStreamErrorCallback(SpdyStreamId stream_id, |
| 21 int status, | 22 int status, |
| 22 const std::string* description, | 23 const std::string* description, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 43 for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) { | 44 for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) { |
| 44 if (*i >= 'A' && *i <= 'Z') { | 45 if (*i >= 'A' && *i <= 'Z') { |
| 45 return true; | 46 return true; |
| 46 } | 47 } |
| 47 } | 48 } |
| 48 return false; | 49 return false; |
| 49 } | 50 } |
| 50 | 51 |
| 51 } // namespace | 52 } // namespace |
| 52 | 53 |
| 54 // A wrapper around a stream that calls into ProduceSynStreamFrame(). |
| 55 class SpdyStream::SynStreamFrameProducer : public SpdyFrameProducer { |
| 56 public: |
| 57 SynStreamFrameProducer(const base::WeakPtr<SpdyStream>& stream) |
| 58 : stream_(stream) { |
| 59 DCHECK(stream_); |
| 60 } |
| 61 |
| 62 virtual ~SynStreamFrameProducer() {} |
| 63 |
| 64 virtual scoped_ptr<SpdyFrame> ProduceFrame() OVERRIDE { |
| 65 if (!stream_) { |
| 66 NOTREACHED(); |
| 67 return scoped_ptr<SpdyFrame>(); |
| 68 } |
| 69 DCHECK_GT(stream_->stream_id(), 0u); |
| 70 return stream_->ProduceSynStreamFrame(); |
| 71 } |
| 72 |
| 73 private: |
| 74 const base::WeakPtr<SpdyStream> stream_; |
| 75 }; |
| 76 |
| 77 // A wrapper around a stream that calls into ProduceHeaderFrame() with |
| 78 // a given header block. |
| 79 class SpdyStream::HeaderFrameProducer : public SpdyFrameProducer { |
| 80 public: |
| 81 HeaderFrameProducer(const base::WeakPtr<SpdyStream>& stream, |
| 82 scoped_ptr<SpdyHeaderBlock> headers) |
| 83 : stream_(stream), |
| 84 headers_(headers.Pass()) { |
| 85 DCHECK(stream_); |
| 86 DCHECK(headers_); |
| 87 } |
| 88 |
| 89 virtual ~HeaderFrameProducer() {} |
| 90 |
| 91 virtual scoped_ptr<SpdyFrame> ProduceFrame() OVERRIDE { |
| 92 if (!stream_) { |
| 93 NOTREACHED(); |
| 94 return scoped_ptr<SpdyFrame>(); |
| 95 } |
| 96 DCHECK_GT(stream_->stream_id(), 0u); |
| 97 return stream_->ProduceHeaderFrame(headers_.Pass()); |
| 98 } |
| 99 |
| 100 private: |
| 101 const base::WeakPtr<SpdyStream> stream_; |
| 102 scoped_ptr<SpdyHeaderBlock> headers_; |
| 103 }; |
| 104 |
| 53 SpdyStream::SpdyStream(SpdySession* session, | 105 SpdyStream::SpdyStream(SpdySession* session, |
| 54 const std::string& path, | 106 const std::string& path, |
| 55 RequestPriority priority, | 107 RequestPriority priority, |
| 56 int32 initial_send_window_size, | 108 int32 initial_send_window_size, |
| 57 int32 initial_recv_window_size, | 109 int32 initial_recv_window_size, |
| 58 bool pushed, | 110 bool pushed, |
| 59 const BoundNetLog& net_log) | 111 const BoundNetLog& net_log) |
| 60 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 112 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 61 continue_buffering_data_(true), | 113 continue_buffering_data_(true), |
| 62 stream_id_(0), | 114 stream_id_(0), |
| (...skipping 13 matching lines...) Expand all Loading... |
| 76 io_state_(STATE_NONE), | 128 io_state_(STATE_NONE), |
| 77 response_status_(OK), | 129 response_status_(OK), |
| 78 cancelled_(false), | 130 cancelled_(false), |
| 79 has_upload_data_(false), | 131 has_upload_data_(false), |
| 80 net_log_(net_log), | 132 net_log_(net_log), |
| 81 send_bytes_(0), | 133 send_bytes_(0), |
| 82 recv_bytes_(0), | 134 recv_bytes_(0), |
| 83 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { | 135 domain_bound_cert_type_(CLIENT_CERT_INVALID_TYPE) { |
| 84 } | 136 } |
| 85 | 137 |
| 86 class SpdyStream::SpdyStreamIOBufferProducer | |
| 87 : public SpdySession::SpdyIOBufferProducer { | |
| 88 public: | |
| 89 SpdyStreamIOBufferProducer(SpdyStream* stream) : stream_(stream) {} | |
| 90 | |
| 91 // SpdyFrameProducer | |
| 92 virtual RequestPriority GetPriority() const OVERRIDE { | |
| 93 return stream_->priority(); | |
| 94 } | |
| 95 | |
| 96 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE { | |
| 97 if (stream_->cancelled()) | |
| 98 return NULL; | |
| 99 if (stream_->stream_id() == 0) | |
| 100 SpdySession::SpdyIOBufferProducer::ActivateStream(session, stream_); | |
| 101 frame_ = stream_->ProduceNextFrame(); | |
| 102 return frame_ == NULL ? NULL : | |
| 103 SpdySession::SpdyIOBufferProducer::CreateIOBuffer( | |
| 104 frame_.get(), GetPriority(), stream_); | |
| 105 } | |
| 106 | |
| 107 private: | |
| 108 scoped_refptr<SpdyStream> stream_; | |
| 109 scoped_ptr<SpdyFrame> frame_; | |
| 110 }; | |
| 111 | |
| 112 void SpdyStream::SetHasWriteAvailable() { | |
| 113 session_->SetStreamHasWriteAvailable(this, | |
| 114 new SpdyStreamIOBufferProducer(this)); | |
| 115 } | |
| 116 | |
| 117 scoped_ptr<SpdyFrame> SpdyStream::ProduceNextFrame() { | |
| 118 if (io_state_ == STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE) { | |
| 119 CHECK(request_.get()); | |
| 120 CHECK_GT(stream_id_, 0u); | |
| 121 | |
| 122 std::string origin = GetUrl().GetOrigin().spec(); | |
| 123 DCHECK(origin[origin.length() - 1] == '/'); | |
| 124 origin.erase(origin.length() - 1); // Trim trailing slash. | |
| 125 scoped_ptr<SpdyFrame> frame(session_->CreateCredentialFrame( | |
| 126 origin, domain_bound_cert_type_, domain_bound_private_key_, | |
| 127 domain_bound_cert_, priority_)); | |
| 128 return frame.Pass(); | |
| 129 } else if (io_state_ == STATE_SEND_HEADERS_COMPLETE) { | |
| 130 CHECK(request_.get()); | |
| 131 CHECK_GT(stream_id_, 0u); | |
| 132 | |
| 133 SpdyControlFlags flags = | |
| 134 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; | |
| 135 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( | |
| 136 stream_id_, priority_, slot_, flags, *request_)); | |
| 137 send_time_ = base::TimeTicks::Now(); | |
| 138 return frame.Pass(); | |
| 139 } else { | |
| 140 CHECK(!cancelled()); | |
| 141 // We must need to write stream data. | |
| 142 // Until the headers have been completely sent, we can not be sure | |
| 143 // that our stream_id is correct. | |
| 144 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | |
| 145 DCHECK_GT(stream_id_, 0u); | |
| 146 DCHECK(!pending_frames_.empty()); | |
| 147 | |
| 148 PendingFrame frame = pending_frames_.front(); | |
| 149 pending_frames_.pop_front(); | |
| 150 | |
| 151 waiting_completions_.push_back(frame.type); | |
| 152 | |
| 153 if (frame.type == TYPE_DATA) { | |
| 154 // Send queued data frame. | |
| 155 return scoped_ptr<SpdyFrame>(frame.data_frame); | |
| 156 } else { | |
| 157 DCHECK(frame.type == TYPE_HEADERS); | |
| 158 // Create actual HEADERS frame just in time because it depends on | |
| 159 // compression context and should not be reordered after the creation. | |
| 160 scoped_ptr<SpdyFrame> header_frame(session_->CreateHeadersFrame( | |
| 161 stream_id_, *frame.header_block, SpdyControlFlags())); | |
| 162 delete frame.header_block; | |
| 163 return header_frame.Pass(); | |
| 164 } | |
| 165 } | |
| 166 NOTREACHED(); | |
| 167 } | |
| 168 | |
| 169 SpdyStream::~SpdyStream() { | 138 SpdyStream::~SpdyStream() { |
| 170 UpdateHistograms(); | 139 UpdateHistograms(); |
| 171 while (!pending_frames_.empty()) { | |
| 172 PendingFrame frame = pending_frames_.back(); | |
| 173 pending_frames_.pop_back(); | |
| 174 if (frame.type == TYPE_DATA) | |
| 175 delete frame.data_frame; | |
| 176 else | |
| 177 delete frame.header_block; | |
| 178 } | |
| 179 } | 140 } |
| 180 | 141 |
| 181 void SpdyStream::SetDelegate(Delegate* delegate) { | 142 void SpdyStream::SetDelegate(Delegate* delegate) { |
| 182 CHECK(delegate); | 143 CHECK(delegate); |
| 183 delegate_ = delegate; | 144 delegate_ = delegate; |
| 184 | 145 |
| 185 if (pushed_) { | 146 if (pushed_) { |
| 186 CHECK(response_received()); | 147 CHECK(response_received()); |
| 187 MessageLoop::current()->PostTask( | 148 MessageLoop::current()->PostTask( |
| 188 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); | 149 FROM_HERE, base::Bind(&SpdyStream::PushedStreamReplayData, this)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); | 182 delegate_->OnDataReceived(buffers[i]->data(), buffers[i]->size()); |
| 222 } else { | 183 } else { |
| 223 delegate_->OnDataReceived(NULL, 0); | 184 delegate_->OnDataReceived(NULL, 0); |
| 224 session_->CloseStream(stream_id_, net::OK); | 185 session_->CloseStream(stream_id_, net::OK); |
| 225 // Note: |this| may be deleted after calling CloseStream. | 186 // Note: |this| may be deleted after calling CloseStream. |
| 226 DCHECK_EQ(buffers.size() - 1, i); | 187 DCHECK_EQ(buffers.size() - 1, i); |
| 227 } | 188 } |
| 228 } | 189 } |
| 229 } | 190 } |
| 230 | 191 |
| 192 scoped_ptr<SpdyFrame> SpdyStream::ProduceSynStreamFrame() { |
| 193 CHECK_EQ(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 194 CHECK(request_.get()); |
| 195 CHECK_GT(stream_id_, 0u); |
| 196 |
| 197 SpdyControlFlags flags = |
| 198 has_upload_data_ ? CONTROL_FLAG_NONE : CONTROL_FLAG_FIN; |
| 199 scoped_ptr<SpdyFrame> frame(session_->CreateSynStream( |
| 200 stream_id_, priority_, slot_, flags, *request_)); |
| 201 send_time_ = base::TimeTicks::Now(); |
| 202 return frame.Pass(); |
| 203 } |
| 204 |
| 205 scoped_ptr<SpdyFrame> SpdyStream::ProduceHeaderFrame( |
| 206 scoped_ptr<SpdyHeaderBlock> header_block) { |
| 207 CHECK(!cancelled()); |
| 208 // We must need to write stream data. |
| 209 // Until the headers have been completely sent, we can not be sure |
| 210 // that our stream_id is correct. |
| 211 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 212 DCHECK_GT(stream_id_, 0u); |
| 213 |
| 214 // Create actual HEADERS frame just in time because it depends on |
| 215 // compression context and should not be reordered after the creation. |
| 216 scoped_ptr<SpdyFrame> header_frame(session_->CreateHeadersFrame( |
| 217 stream_id_, *header_block, SpdyControlFlags())); |
| 218 return header_frame.Pass(); |
| 219 } |
| 220 |
| 231 void SpdyStream::DetachDelegate() { | 221 void SpdyStream::DetachDelegate() { |
| 232 delegate_ = NULL; | 222 delegate_ = NULL; |
| 233 if (!closed()) | 223 if (!closed()) |
| 234 Cancel(); | 224 Cancel(); |
| 235 } | 225 } |
| 236 | 226 |
| 237 const SpdyHeaderBlock& SpdyStream::spdy_headers() const { | 227 const SpdyHeaderBlock& SpdyStream::spdy_headers() const { |
| 238 DCHECK(request_ != NULL); | 228 DCHECK(request_ != NULL); |
| 239 return *request_.get(); | 229 return *request_.get(); |
| 240 } | 230 } |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; | 561 io_state_ = STATE_GET_DOMAIN_BOUND_CERT; |
| 572 return DoLoop(OK); | 562 return DoLoop(OK); |
| 573 } | 563 } |
| 574 | 564 |
| 575 void SpdyStream::QueueHeaders(scoped_ptr<SpdyHeaderBlock> headers) { | 565 void SpdyStream::QueueHeaders(scoped_ptr<SpdyHeaderBlock> headers) { |
| 576 // Until the first headers by SYN_STREAM have been completely sent, we can | 566 // Until the first headers by SYN_STREAM have been completely sent, we can |
| 577 // not be sure that our stream_id is correct. | 567 // not be sure that our stream_id is correct. |
| 578 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 568 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 579 CHECK_GT(stream_id_, 0u); | 569 CHECK_GT(stream_id_, 0u); |
| 580 | 570 |
| 581 PendingFrame frame; | 571 waiting_completions_.push_back(TYPE_HEADERS); |
| 582 frame.type = TYPE_HEADERS; | |
| 583 // |frame.header_block| is deleted by either ProduceNextFrame() or | |
| 584 // the destructor. | |
| 585 frame.header_block = headers.release(); | |
| 586 pending_frames_.push_back(frame); | |
| 587 | 572 |
| 588 SetHasWriteAvailable(); | 573 session_->EnqueueStreamWrite( |
| 574 this, |
| 575 scoped_ptr<SpdyFrameProducer>( |
| 576 new HeaderFrameProducer( |
| 577 weak_ptr_factory_.GetWeakPtr(), headers.Pass()))); |
| 589 } | 578 } |
| 590 | 579 |
| 591 void SpdyStream::QueueStreamData(IOBuffer* data, | 580 void SpdyStream::QueueStreamData(IOBuffer* data, |
| 592 int length, | 581 int length, |
| 593 SpdyDataFlags flags) { | 582 SpdyDataFlags flags) { |
| 594 // Until the headers have been completely sent, we can not be sure | 583 // Until the headers have been completely sent, we can not be sure |
| 595 // that our stream_id is correct. | 584 // that our stream_id is correct. |
| 596 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); | 585 DCHECK_GT(io_state_, STATE_SEND_HEADERS_COMPLETE); |
| 597 CHECK_GT(stream_id_, 0u); | 586 CHECK_GT(stream_id_, 0u); |
| 587 CHECK(!cancelled()); |
| 598 | 588 |
| 599 scoped_ptr<SpdyFrame> data_frame(session_->CreateDataFrame( | 589 scoped_ptr<SpdyFrame> data_frame(session_->CreateDataFrame( |
| 600 stream_id_, data, length, flags)); | 590 stream_id_, data, length, flags)); |
| 601 if (!data_frame) | 591 if (!data_frame) |
| 602 return; | 592 return; |
| 603 | 593 |
| 604 PendingFrame frame; | 594 waiting_completions_.push_back(TYPE_DATA); |
| 605 frame.type = TYPE_DATA; | |
| 606 // |frame.data_frame| is either returned by ProduceNextFrame() or | |
| 607 // deleted in the destructor. | |
| 608 frame.data_frame = data_frame.release(); | |
| 609 pending_frames_.push_back(frame); | |
| 610 | 595 |
| 611 SetHasWriteAvailable(); | 596 session_->EnqueueStreamWrite( |
| 597 this, |
| 598 scoped_ptr<SpdyFrameProducer>( |
| 599 new SimpleFrameProducer(data_frame.Pass()))); |
| 612 } | 600 } |
| 613 | 601 |
| 614 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, | 602 bool SpdyStream::GetSSLInfo(SSLInfo* ssl_info, |
| 615 bool* was_npn_negotiated, | 603 bool* was_npn_negotiated, |
| 616 NextProto* protocol_negotiated) { | 604 NextProto* protocol_negotiated) { |
| 617 return session_->GetSSLInfo( | 605 return session_->GetSSLInfo( |
| 618 ssl_info, was_npn_negotiated, protocol_negotiated); | 606 ssl_info, was_npn_negotiated, protocol_negotiated); |
| 619 } | 607 } |
| 620 | 608 |
| 621 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { | 609 bool SpdyStream::GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 result = DoSendBodyComplete(result); | 674 result = DoSendBodyComplete(result); |
| 687 break; | 675 break; |
| 688 // This is an intermediary waiting state. This state is reached when all | 676 // This is an intermediary waiting state. This state is reached when all |
| 689 // data has been sent, but no data has been received. | 677 // data has been sent, but no data has been received. |
| 690 case STATE_WAITING_FOR_RESPONSE: | 678 case STATE_WAITING_FOR_RESPONSE: |
| 691 io_state_ = STATE_WAITING_FOR_RESPONSE; | 679 io_state_ = STATE_WAITING_FOR_RESPONSE; |
| 692 result = ERR_IO_PENDING; | 680 result = ERR_IO_PENDING; |
| 693 break; | 681 break; |
| 694 // State machine 2: connection is established. | 682 // State machine 2: connection is established. |
| 695 // In STATE_OPEN, OnResponseReceived has already been called. | 683 // In STATE_OPEN, OnResponseReceived has already been called. |
| 696 // OnDataReceived, OnClose and OnWriteCompelte can be called. | 684 // OnDataReceived, OnClose and OnWriteComplete can be called. |
| 697 // Only OnWriteComplete calls DoLoop((). | 685 // Only OnWriteComplete calls DoLoop((). |
| 698 // | 686 // |
| 699 // For HTTP streams, no data is sent from the client while in the OPEN | 687 // For HTTP streams, no data is sent from the client while in the OPEN |
| 700 // state, so OnWriteComplete is never called here. The HTTP body is | 688 // state, so OnWriteComplete is never called here. The HTTP body is |
| 701 // handled in the OnDataReceived callback, which does not call into | 689 // handled in the OnDataReceived callback, which does not call into |
| 702 // DoLoop. | 690 // DoLoop. |
| 703 // | 691 // |
| 704 // For WebSocket streams, which are bi-directional, we'll send and | 692 // For WebSocket streams, which are bi-directional, we'll send and |
| 705 // receive data once the connection is established. Received data is | 693 // receive data once the connection is established. Received data is |
| 706 // handled in OnDataReceived. Sent data is handled in OnWriteComplete, | 694 // handled in OnDataReceived. Sent data is handled in OnWriteComplete, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 return result; | 744 return result; |
| 757 | 745 |
| 758 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; | 746 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT; |
| 759 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); | 747 slot_ = session_->credential_state()->SetHasCredential(GetUrl()); |
| 760 return OK; | 748 return OK; |
| 761 } | 749 } |
| 762 | 750 |
| 763 int SpdyStream::DoSendDomainBoundCert() { | 751 int SpdyStream::DoSendDomainBoundCert() { |
| 764 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; | 752 io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE; |
| 765 CHECK(request_.get()); | 753 CHECK(request_.get()); |
| 766 SetHasWriteAvailable(); | 754 |
| 755 std::string origin = GetUrl().GetOrigin().spec(); |
| 756 DCHECK(origin[origin.length() - 1] == '/'); |
| 757 origin.erase(origin.length() - 1); // Trim trailing slash. |
| 758 scoped_ptr<SpdyFrame> frame; |
| 759 int rv = session_->CreateCredentialFrame( |
| 760 origin, domain_bound_cert_type_, domain_bound_private_key_, |
| 761 domain_bound_cert_, priority_, &frame); |
| 762 if (rv != OK) { |
| 763 DCHECK_NE(rv, ERR_IO_PENDING); |
| 764 return rv; |
| 765 } |
| 766 |
| 767 DCHECK(frame); |
| 768 // TODO(akalin): Fix a couple of race conditions: |
| 769 // |
| 770 // 1) Since this counts as a write for this stream, the stream will |
| 771 // be activated (and hence allocated a stream ID) before this frame |
| 772 // is sent, even though the ID should only be activated for the |
| 773 // SYN_STREAM frame. This can be solved by signalling to the session |
| 774 // when we're sending a SYN_STREAM frame, and have it only activate |
| 775 // the stream then. |
| 776 // |
| 777 // 2) Since this is decoupled from sending the SYN_STREAM frame, it |
| 778 // is possible that other domain-bound cert frames will clobber ours |
| 779 // before our SYN_STREAM frame gets sent. This can be solved by |
| 780 // immediately enqueueing the SYN_STREAM frame here and adjusting |
| 781 // the state machine appropriately. |
| 782 session_->EnqueueStreamWrite( |
| 783 this, |
| 784 scoped_ptr<SpdyFrameProducer>(new SimpleFrameProducer(frame.Pass()))); |
| 767 return ERR_IO_PENDING; | 785 return ERR_IO_PENDING; |
| 768 } | 786 } |
| 769 | 787 |
| 770 int SpdyStream::DoSendDomainBoundCertComplete(int result) { | 788 int SpdyStream::DoSendDomainBoundCertComplete(int result) { |
| 771 if (result < 0) | 789 if (result < 0) |
| 772 return result; | 790 return result; |
| 773 | 791 |
| 774 io_state_ = STATE_SEND_HEADERS; | 792 io_state_ = STATE_SEND_HEADERS; |
| 775 return OK; | 793 return OK; |
| 776 } | 794 } |
| 777 | 795 |
| 778 int SpdyStream::DoSendHeaders() { | 796 int SpdyStream::DoSendHeaders() { |
| 779 CHECK(!cancelled_); | 797 CHECK(!cancelled_); |
| 798 io_state_ = STATE_SEND_HEADERS_COMPLETE; |
| 780 | 799 |
| 781 SetHasWriteAvailable(); | 800 session_->EnqueueStreamWrite( |
| 782 io_state_ = STATE_SEND_HEADERS_COMPLETE; | 801 this, |
| 802 scoped_ptr<SpdyFrameProducer>( |
| 803 new SynStreamFrameProducer(weak_ptr_factory_.GetWeakPtr()))); |
| 783 return ERR_IO_PENDING; | 804 return ERR_IO_PENDING; |
| 784 } | 805 } |
| 785 | 806 |
| 786 int SpdyStream::DoSendHeadersComplete(int result) { | 807 int SpdyStream::DoSendHeadersComplete(int result) { |
| 787 if (result < 0) | 808 if (result < 0) |
| 788 return result; | 809 return result; |
| 789 | 810 |
| 790 CHECK_GT(result, 0); | 811 CHECK_GT(result, 0); |
| 791 | 812 |
| 792 if (!delegate_) | 813 if (!delegate_) |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 883 } | 904 } |
| 884 | 905 |
| 885 recv_window_size_ -= delta_window_size; | 906 recv_window_size_ -= delta_window_size; |
| 886 net_log_.AddEvent( | 907 net_log_.AddEvent( |
| 887 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, | 908 NetLog::TYPE_SPDY_STREAM_UPDATE_RECV_WINDOW, |
| 888 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, | 909 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, |
| 889 stream_id_, -delta_window_size, recv_window_size_)); | 910 stream_id_, -delta_window_size, recv_window_size_)); |
| 890 } | 911 } |
| 891 | 912 |
| 892 } // namespace net | 913 } // namespace net |
| OLD | NEW |