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

Side by Side Diff: net/spdy/bidirectional_stream_spdy_impl.cc

Issue 2462463002: Make net::BidirectionalStream handle RST_STREAM_NO_ERROR (Closed)
Patch Set: Address comments Created 4 years, 1 month 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/bidirectional_stream_spdy_impl.h" 5 #include "net/spdy/bidirectional_stream_spdy_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 16 matching lines...) Expand all
27 } // namespace 27 } // namespace
28 28
29 BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl( 29 BidirectionalStreamSpdyImpl::BidirectionalStreamSpdyImpl(
30 const base::WeakPtr<SpdySession>& spdy_session) 30 const base::WeakPtr<SpdySession>& spdy_session)
31 : spdy_session_(spdy_session), 31 : spdy_session_(spdy_session),
32 request_info_(nullptr), 32 request_info_(nullptr),
33 delegate_(nullptr), 33 delegate_(nullptr),
34 negotiated_protocol_(kProtoUnknown), 34 negotiated_protocol_(kProtoUnknown),
35 more_read_data_pending_(false), 35 more_read_data_pending_(false),
36 read_buffer_len_(0), 36 read_buffer_len_(0),
37 written_end_of_stream_(false),
38 write_pending_(false),
37 stream_closed_(false), 39 stream_closed_(false),
38 closed_stream_status_(ERR_FAILED), 40 closed_stream_status_(ERR_FAILED),
39 closed_stream_received_bytes_(0), 41 closed_stream_received_bytes_(0),
40 closed_stream_sent_bytes_(0), 42 closed_stream_sent_bytes_(0),
41 closed_has_load_timing_info_(false), 43 closed_has_load_timing_info_(false),
42 weak_factory_(this) {} 44 weak_factory_(this) {}
43 45
44 BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() { 46 BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() {
45 // Sends a RST to the remote if the stream is destroyed before it completes. 47 // Sends a RST to the remote if the stream is destroyed before it completes.
46 ResetStream(); 48 ResetStream();
49 DCHECK(!write_pending_);
47 } 50 }
48 51
49 void BidirectionalStreamSpdyImpl::Start( 52 void BidirectionalStreamSpdyImpl::Start(
50 const BidirectionalStreamRequestInfo* request_info, 53 const BidirectionalStreamRequestInfo* request_info,
51 const NetLogWithSource& net_log, 54 const NetLogWithSource& net_log,
52 bool /*send_request_headers_automatically*/, 55 bool /*send_request_headers_automatically*/,
53 BidirectionalStreamImpl::Delegate* delegate, 56 BidirectionalStreamImpl::Delegate* delegate,
54 std::unique_ptr<base::Timer> timer) { 57 std::unique_ptr<base::Timer> timer) {
55 DCHECK(!stream_); 58 DCHECK(!stream_);
56 DCHECK(timer); 59 DCHECK(timer);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // called upon completion. 103 // called upon completion.
101 read_buffer_ = buf; 104 read_buffer_ = buf;
102 read_buffer_len_ = buf_len; 105 read_buffer_len_ = buf_len;
103 return ERR_IO_PENDING; 106 return ERR_IO_PENDING;
104 } 107 }
105 108
106 void BidirectionalStreamSpdyImpl::SendData(const scoped_refptr<IOBuffer>& data, 109 void BidirectionalStreamSpdyImpl::SendData(const scoped_refptr<IOBuffer>& data,
107 int length, 110 int length,
108 bool end_stream) { 111 bool end_stream) {
109 DCHECK(length > 0 || (length == 0 && end_stream)); 112 DCHECK(length > 0 || (length == 0 && end_stream));
113 DCHECK(!write_pending_);
110 114
kapishnikov 2016/10/31 17:03:07 Should we add DCHECK(!written_end_of_stream_) here
xunjieli 2016/10/31 17:18:03 The newly added test will crash instead of having
111 if (!stream_) { 115 write_pending_ = true;
112 LOG(ERROR) << "Trying to send data after stream has been destroyed."; 116 if (MaybeHandleStreamClosedInSendData()) {
113 base::ThreadTaskRunnerHandle::Get()->PostTask( 117 written_end_of_stream_ = end_stream;
114 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
115 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
116 return; 118 return;
117 } 119 }
118 120
119 DCHECK(!stream_closed_); 121 DCHECK(!stream_closed_);
122 written_end_of_stream_ = end_stream;
123
120 stream_->SendData(data.get(), length, 124 stream_->SendData(data.get(), length,
121 end_stream ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND); 125 end_stream ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND);
122 } 126 }
123 127
124 void BidirectionalStreamSpdyImpl::SendvData( 128 void BidirectionalStreamSpdyImpl::SendvData(
125 const std::vector<scoped_refptr<IOBuffer>>& buffers, 129 const std::vector<scoped_refptr<IOBuffer>>& buffers,
126 const std::vector<int>& lengths, 130 const std::vector<int>& lengths,
127 bool end_stream) { 131 bool end_stream) {
128 DCHECK_EQ(buffers.size(), lengths.size()); 132 DCHECK_EQ(buffers.size(), lengths.size());
133 DCHECK(!write_pending_);
129 134
kapishnikov 2016/10/31 17:03:07 Same DCHECK(!written_end_of_stream_) here
xunjieli 2016/10/31 17:18:02 Same as above. The newly added test will crash. We
130 if (!stream_) { 135 write_pending_ = true;
131 LOG(ERROR) << "Trying to send data after stream has been destroyed."; 136 if (MaybeHandleStreamClosedInSendData()) {
132 base::ThreadTaskRunnerHandle::Get()->PostTask( 137 written_end_of_stream_ = end_stream;
133 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
134 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
135 return; 138 return;
136 } 139 }
137 140
138 DCHECK(!stream_closed_); 141 DCHECK(!stream_closed_);
142 written_end_of_stream_ = end_stream;
143
139 int total_len = 0; 144 int total_len = 0;
140 for (int len : lengths) { 145 for (int len : lengths) {
141 total_len += len; 146 total_len += len;
142 } 147 }
143 148
144 pending_combined_buffer_ = new net::IOBuffer(total_len); 149 pending_combined_buffer_ = new net::IOBuffer(total_len);
145 int len = 0; 150 int len = 0;
146 // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames. 151 // TODO(xunjieli): Get rid of extra copy. Coalesce headers and data frames.
147 for (size_t i = 0; i < buffers.size(); ++i) { 152 for (size_t i = 0; i < buffers.size(); ++i) {
148 memcpy(pending_combined_buffer_->data() + len, buffers[i]->data(), 153 memcpy(pending_combined_buffer_->data() + len, buffers[i]->data(),
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 266
262 if (status != OK) { 267 if (status != OK) {
263 NotifyError(status); 268 NotifyError(status);
264 return; 269 return;
265 } 270 }
266 ResetStream(); 271 ResetStream();
267 // Complete any remaining read, as all data has been buffered. 272 // Complete any remaining read, as all data has been buffered.
268 // If user has not called ReadData (i.e |read_buffer_| is nullptr), this will 273 // If user has not called ReadData (i.e |read_buffer_| is nullptr), this will
269 // do nothing. 274 // do nothing.
270 timer_->Stop(); 275 timer_->Stop();
276
277 // |this| might get destroyed after calling into |delegate_| in
278 // DoBufferedRead().
279 auto weak_this = weak_factory_.GetWeakPtr();
271 DoBufferedRead(); 280 DoBufferedRead();
281 if (weak_this.get() && write_pending_)
282 NotifyDataSent();
272 } 283 }
273 284
274 int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() { 285 int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() {
275 SpdyHeaderBlock headers; 286 SpdyHeaderBlock headers;
276 HttpRequestInfo http_request_info; 287 HttpRequestInfo http_request_info;
277 http_request_info.url = request_info_->url; 288 http_request_info.url = request_info_->url;
278 http_request_info.method = request_info_->method; 289 http_request_info.method = request_info_->method;
279 http_request_info.extra_headers = request_info_->extra_headers; 290 http_request_info.extra_headers = request_info_->extra_headers;
280 291
281 CreateSpdyHeadersFromHttpRequest( 292 CreateSpdyHeadersFromHttpRequest(
282 http_request_info, http_request_info.extra_headers, true, &headers); 293 http_request_info, http_request_info.extra_headers, true, &headers);
294 written_end_of_stream_ = request_info_->end_stream_on_headers;
283 return stream_->SendRequestHeaders(std::move(headers), 295 return stream_->SendRequestHeaders(std::move(headers),
284 request_info_->end_stream_on_headers 296 request_info_->end_stream_on_headers
285 ? NO_MORE_DATA_TO_SEND 297 ? NO_MORE_DATA_TO_SEND
286 : MORE_DATA_TO_SEND); 298 : MORE_DATA_TO_SEND);
287 } 299 }
288 300
289 void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) { 301 void BidirectionalStreamSpdyImpl::OnStreamInitialized(int rv) {
290 DCHECK_NE(ERR_IO_PENDING, rv); 302 DCHECK_NE(ERR_IO_PENDING, rv);
291 if (rv == OK) { 303 if (rv == OK) {
292 stream_ = stream_request_.ReleaseStream(); 304 stream_ = stream_request_.ReleaseStream();
293 stream_->SetDelegate(this); 305 stream_->SetDelegate(this);
294 rv = SendRequestHeadersHelper(); 306 rv = SendRequestHeadersHelper();
295 if (rv == OK) { 307 if (rv == OK) {
296 OnRequestHeadersSent(); 308 OnRequestHeadersSent();
297 return; 309 return;
298 } else if (rv == ERR_IO_PENDING) { 310 } else if (rv == ERR_IO_PENDING) {
299 return; 311 return;
300 } 312 }
301 } 313 }
302 NotifyError(rv); 314 NotifyError(rv);
303 } 315 }
304 316
305 void BidirectionalStreamSpdyImpl::NotifyError(int rv) { 317 void BidirectionalStreamSpdyImpl::NotifyError(int rv) {
306 ResetStream(); 318 ResetStream();
319 write_pending_ = false;
307 if (delegate_) { 320 if (delegate_) {
308 BidirectionalStreamImpl::Delegate* delegate = delegate_; 321 BidirectionalStreamImpl::Delegate* delegate = delegate_;
309 delegate_ = nullptr; 322 delegate_ = nullptr;
310 // Cancel any pending callback. 323 // Cancel any pending callback.
311 weak_factory_.InvalidateWeakPtrs(); 324 weak_factory_.InvalidateWeakPtrs();
312 delegate->OnFailed(rv); 325 delegate->OnFailed(rv);
313 // |this| can be null when returned from delegate. 326 // |this| can be null when returned from delegate.
314 } 327 }
315 } 328 }
316 329
330 void BidirectionalStreamSpdyImpl::NotifyDataSent() {
331 DCHECK(write_pending_);
332
333 write_pending_ = false;
334 if (delegate_)
335 delegate_->OnDataSent();
336 }
337
317 void BidirectionalStreamSpdyImpl::ResetStream() { 338 void BidirectionalStreamSpdyImpl::ResetStream() {
318 if (!stream_) 339 if (!stream_)
319 return; 340 return;
320 if (!stream_->IsClosed()) { 341 if (!stream_->IsClosed()) {
321 // This sends a RST to the remote. 342 // This sends a RST to the remote.
322 stream_->DetachDelegate(); 343 stream_->DetachDelegate();
323 DCHECK(!stream_); 344 DCHECK(!stream_);
324 } else { 345 } else {
325 // Stream is already closed, so it is not legal to call DetachDelegate. 346 // Stream is already closed, so it is not legal to call DetachDelegate.
326 stream_.reset(); 347 stream_.reset();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 } 387 }
367 388
368 bool BidirectionalStreamSpdyImpl::ShouldWaitForMoreBufferedData() const { 389 bool BidirectionalStreamSpdyImpl::ShouldWaitForMoreBufferedData() const {
369 if (stream_closed_) 390 if (stream_closed_)
370 return false; 391 return false;
371 DCHECK_GT(read_buffer_len_, 0); 392 DCHECK_GT(read_buffer_len_, 0);
372 return read_data_queue_.GetTotalSize() < 393 return read_data_queue_.GetTotalSize() <
373 static_cast<size_t>(read_buffer_len_); 394 static_cast<size_t>(read_buffer_len_);
374 } 395 }
375 396
397 bool BidirectionalStreamSpdyImpl::MaybeHandleStreamClosedInSendData() {
398 if (stream_)
399 return false;
400 // If |stream_| is closed without an error before client half closes,
401 // blackhole any pending write data. crbug.com/650438.
402 if (!written_end_of_stream_ && stream_closed_ &&
kapishnikov 2016/10/31 17:03:07 To make the code easier to understand, I think we
xunjieli 2016/10/31 17:18:02 Done.
403 closed_stream_status_ == OK) {
404 base::ThreadTaskRunnerHandle::Get()->PostTask(
405 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyDataSent,
406 weak_factory_.GetWeakPtr()));
407 return true;
408 }
409 LOG(ERROR) << "Trying to send data after stream has been destroyed.";
410 base::ThreadTaskRunnerHandle::Get()->PostTask(
411 FROM_HERE, base::Bind(&BidirectionalStreamSpdyImpl::NotifyError,
412 weak_factory_.GetWeakPtr(), ERR_UNEXPECTED));
413 return true;
414 }
415
376 } // namespace net 416 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/bidirectional_stream_spdy_impl.h ('k') | net/spdy/bidirectional_stream_spdy_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698