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/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/metrics/histogram_macros.h" | 11 #include "base/metrics/histogram_macros.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 #include "net/spdy/spdy_buffer_producer.h" | 15 #include "net/spdy/spdy_buffer_producer.h" |
16 #include "net/spdy/spdy_http_utils.h" | 16 #include "net/spdy/spdy_http_utils.h" |
17 #include "net/spdy/spdy_session.h" | 17 #include "net/spdy/spdy_session.h" |
18 | 18 |
19 namespace net { | 19 namespace net { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 base::Value* NetLogSpdyStreamErrorCallback( | 23 scoped_ptr<base::Value> NetLogSpdyStreamErrorCallback( |
24 SpdyStreamId stream_id, | 24 SpdyStreamId stream_id, |
25 int status, | 25 int status, |
26 const std::string* description, | 26 const std::string* description, |
27 NetLogCaptureMode /* capture_mode */) { | 27 NetLogCaptureMode /* capture_mode */) { |
28 base::DictionaryValue* dict = new base::DictionaryValue(); | 28 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
29 dict->SetInteger("stream_id", static_cast<int>(stream_id)); | 29 dict->SetInteger("stream_id", static_cast<int>(stream_id)); |
30 dict->SetInteger("status", status); | 30 dict->SetInteger("status", status); |
31 dict->SetString("description", *description); | 31 dict->SetString("description", *description); |
32 return dict; | 32 return dict.Pass(); |
33 } | 33 } |
34 | 34 |
35 base::Value* NetLogSpdyStreamWindowUpdateCallback( | 35 scoped_ptr<base::Value> NetLogSpdyStreamWindowUpdateCallback( |
36 SpdyStreamId stream_id, | 36 SpdyStreamId stream_id, |
37 int32 delta, | 37 int32 delta, |
38 int32 window_size, | 38 int32 window_size, |
39 NetLogCaptureMode /* capture_mode */) { | 39 NetLogCaptureMode /* capture_mode */) { |
40 base::DictionaryValue* dict = new base::DictionaryValue(); | 40 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
41 dict->SetInteger("stream_id", stream_id); | 41 dict->SetInteger("stream_id", stream_id); |
42 dict->SetInteger("delta", delta); | 42 dict->SetInteger("delta", delta); |
43 dict->SetInteger("window_size", window_size); | 43 dict->SetInteger("window_size", window_size); |
44 return dict; | 44 return dict.Pass(); |
45 } | 45 } |
46 | 46 |
47 bool ContainsUppercaseAscii(const std::string& str) { | 47 bool ContainsUppercaseAscii(const std::string& str) { |
48 for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) { | 48 for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) { |
49 if (*i >= 'A' && *i <= 'Z') { | 49 if (*i >= 'A' && *i <= 'Z') { |
50 return true; | 50 return true; |
51 } | 51 } |
52 } | 52 } |
53 return false; | 53 return false; |
54 } | 54 } |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " | 267 "Received WINDOW_UPDATE [delta: %d] for stream %d overflows " |
268 "send_window_size_ [current: %d]", delta_window_size, stream_id_, | 268 "send_window_size_ [current: %d]", delta_window_size, stream_id_, |
269 send_window_size_); | 269 send_window_size_); |
270 session_->ResetStream(stream_id_, RST_STREAM_FLOW_CONTROL_ERROR, desc); | 270 session_->ResetStream(stream_id_, RST_STREAM_FLOW_CONTROL_ERROR, desc); |
271 return; | 271 return; |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 send_window_size_ += delta_window_size; | 275 send_window_size_ += delta_window_size; |
276 | 276 |
277 net_log_.AddEvent( | 277 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_UPDATE_SEND_WINDOW, |
278 NetLog::TYPE_HTTP2_STREAM_UPDATE_SEND_WINDOW, | 278 base::Bind(NetLogSpdyStreamWindowUpdateCallback, stream_id_, |
279 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, stream_id_, | 279 delta_window_size, send_window_size_)); |
280 delta_window_size, send_window_size_)); | |
281 | 280 |
282 PossiblyResumeIfSendStalled(); | 281 PossiblyResumeIfSendStalled(); |
283 } | 282 } |
284 | 283 |
285 void SpdyStream::DecreaseSendWindowSize(int32 delta_window_size) { | 284 void SpdyStream::DecreaseSendWindowSize(int32 delta_window_size) { |
286 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); | 285 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); |
287 | 286 |
288 if (IsClosed()) | 287 if (IsClosed()) |
289 return; | 288 return; |
290 | 289 |
291 // We only call this method when sending a frame. Therefore, | 290 // We only call this method when sending a frame. Therefore, |
292 // |delta_window_size| should be within the valid frame size range. | 291 // |delta_window_size| should be within the valid frame size range. |
293 DCHECK_GE(delta_window_size, 1); | 292 DCHECK_GE(delta_window_size, 1); |
294 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); | 293 DCHECK_LE(delta_window_size, kMaxSpdyFrameChunkSize); |
295 | 294 |
296 // |send_window_size_| should have been at least |delta_window_size| for | 295 // |send_window_size_| should have been at least |delta_window_size| for |
297 // this call to happen. | 296 // this call to happen. |
298 DCHECK_GE(send_window_size_, delta_window_size); | 297 DCHECK_GE(send_window_size_, delta_window_size); |
299 | 298 |
300 send_window_size_ -= delta_window_size; | 299 send_window_size_ -= delta_window_size; |
301 | 300 |
302 net_log_.AddEvent( | 301 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_UPDATE_SEND_WINDOW, |
303 NetLog::TYPE_HTTP2_STREAM_UPDATE_SEND_WINDOW, | 302 base::Bind(NetLogSpdyStreamWindowUpdateCallback, stream_id_, |
304 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, stream_id_, | 303 -delta_window_size, send_window_size_)); |
305 -delta_window_size, send_window_size_)); | |
306 } | 304 } |
307 | 305 |
308 void SpdyStream::OnReadBufferConsumed( | 306 void SpdyStream::OnReadBufferConsumed( |
309 size_t consume_size, | 307 size_t consume_size, |
310 SpdyBuffer::ConsumeSource consume_source) { | 308 SpdyBuffer::ConsumeSource consume_source) { |
311 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); | 309 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); |
312 DCHECK_GE(consume_size, 1u); | 310 DCHECK_GE(consume_size, 1u); |
313 DCHECK_LE(consume_size, static_cast<size_t>(kint32max)); | 311 DCHECK_LE(consume_size, static_cast<size_t>(kint32max)); |
314 IncreaseRecvWindowSize(static_cast<int32>(consume_size)); | 312 IncreaseRecvWindowSize(static_cast<int32>(consume_size)); |
315 } | 313 } |
316 | 314 |
317 void SpdyStream::IncreaseRecvWindowSize(int32 delta_window_size) { | 315 void SpdyStream::IncreaseRecvWindowSize(int32 delta_window_size) { |
318 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); | 316 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); |
319 | 317 |
320 // By the time a read is processed by the delegate, this stream may | 318 // By the time a read is processed by the delegate, this stream may |
321 // already be inactive. | 319 // already be inactive. |
322 if (!session_->IsStreamActive(stream_id_)) | 320 if (!session_->IsStreamActive(stream_id_)) |
323 return; | 321 return; |
324 | 322 |
325 DCHECK_GE(unacked_recv_window_bytes_, 0); | 323 DCHECK_GE(unacked_recv_window_bytes_, 0); |
326 DCHECK_GE(recv_window_size_, unacked_recv_window_bytes_); | 324 DCHECK_GE(recv_window_size_, unacked_recv_window_bytes_); |
327 DCHECK_GE(delta_window_size, 1); | 325 DCHECK_GE(delta_window_size, 1); |
328 // Check for overflow. | 326 // Check for overflow. |
329 DCHECK_LE(delta_window_size, kint32max - recv_window_size_); | 327 DCHECK_LE(delta_window_size, kint32max - recv_window_size_); |
330 | 328 |
331 recv_window_size_ += delta_window_size; | 329 recv_window_size_ += delta_window_size; |
332 net_log_.AddEvent( | 330 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_UPDATE_RECV_WINDOW, |
333 NetLog::TYPE_HTTP2_STREAM_UPDATE_RECV_WINDOW, | 331 base::Bind(NetLogSpdyStreamWindowUpdateCallback, stream_id_, |
334 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, stream_id_, | 332 delta_window_size, recv_window_size_)); |
335 delta_window_size, recv_window_size_)); | |
336 | 333 |
337 unacked_recv_window_bytes_ += delta_window_size; | 334 unacked_recv_window_bytes_ += delta_window_size; |
338 if (unacked_recv_window_bytes_ > max_recv_window_size_ / 2) { | 335 if (unacked_recv_window_bytes_ > max_recv_window_size_ / 2) { |
339 session_->SendStreamWindowUpdate( | 336 session_->SendStreamWindowUpdate( |
340 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_)); | 337 stream_id_, static_cast<uint32>(unacked_recv_window_bytes_)); |
341 unacked_recv_window_bytes_ = 0; | 338 unacked_recv_window_bytes_ = 0; |
342 } | 339 } |
343 } | 340 } |
344 | 341 |
345 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) { | 342 void SpdyStream::DecreaseRecvWindowSize(int32 delta_window_size) { |
346 DCHECK(session_->IsStreamActive(stream_id_)); | 343 DCHECK(session_->IsStreamActive(stream_id_)); |
347 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); | 344 DCHECK_GE(session_->flow_control_state(), SpdySession::FLOW_CONTROL_STREAM); |
348 DCHECK_GE(delta_window_size, 1); | 345 DCHECK_GE(delta_window_size, 1); |
349 | 346 |
350 // The receiving window size as the peer knows it is | 347 // The receiving window size as the peer knows it is |
351 // |recv_window_size_ - unacked_recv_window_bytes_|, if more data are sent by | 348 // |recv_window_size_ - unacked_recv_window_bytes_|, if more data are sent by |
352 // the peer, that means that the receive window is not being respected. | 349 // the peer, that means that the receive window is not being respected. |
353 if (delta_window_size > recv_window_size_ - unacked_recv_window_bytes_) { | 350 if (delta_window_size > recv_window_size_ - unacked_recv_window_bytes_) { |
354 session_->ResetStream( | 351 session_->ResetStream( |
355 stream_id_, RST_STREAM_FLOW_CONTROL_ERROR, | 352 stream_id_, RST_STREAM_FLOW_CONTROL_ERROR, |
356 "delta_window_size is " + base::IntToString(delta_window_size) + | 353 "delta_window_size is " + base::IntToString(delta_window_size) + |
357 " in DecreaseRecvWindowSize, which is larger than the receive " + | 354 " in DecreaseRecvWindowSize, which is larger than the receive " + |
358 "window size of " + base::IntToString(recv_window_size_)); | 355 "window size of " + base::IntToString(recv_window_size_)); |
359 return; | 356 return; |
360 } | 357 } |
361 | 358 |
362 recv_window_size_ -= delta_window_size; | 359 recv_window_size_ -= delta_window_size; |
363 net_log_.AddEvent( | 360 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_UPDATE_RECV_WINDOW, |
364 NetLog::TYPE_HTTP2_STREAM_UPDATE_RECV_WINDOW, | 361 base::Bind(NetLogSpdyStreamWindowUpdateCallback, stream_id_, |
365 base::Bind(&NetLogSpdyStreamWindowUpdateCallback, stream_id_, | 362 -delta_window_size, recv_window_size_)); |
366 -delta_window_size, recv_window_size_)); | |
367 } | 363 } |
368 | 364 |
369 int SpdyStream::GetPeerAddress(IPEndPoint* address) const { | 365 int SpdyStream::GetPeerAddress(IPEndPoint* address) const { |
370 return session_->GetPeerAddress(address); | 366 return session_->GetPeerAddress(address); |
371 } | 367 } |
372 | 368 |
373 int SpdyStream::GetLocalAddress(IPEndPoint* address) const { | 369 int SpdyStream::GetLocalAddress(IPEndPoint* address) const { |
374 return session_->GetLocalAddress(address); | 370 return session_->GetLocalAddress(address); |
375 } | 371 } |
376 | 372 |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
620 return OK; | 616 return OK; |
621 } | 617 } |
622 } | 618 } |
623 | 619 |
624 SpdyMajorVersion SpdyStream::GetProtocolVersion() const { | 620 SpdyMajorVersion SpdyStream::GetProtocolVersion() const { |
625 return session_->GetProtocolVersion(); | 621 return session_->GetProtocolVersion(); |
626 } | 622 } |
627 | 623 |
628 void SpdyStream::LogStreamError(int status, const std::string& description) { | 624 void SpdyStream::LogStreamError(int status, const std::string& description) { |
629 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_ERROR, | 625 net_log_.AddEvent(NetLog::TYPE_HTTP2_STREAM_ERROR, |
630 base::Bind(&NetLogSpdyStreamErrorCallback, stream_id_, | 626 base::Bind(NetLogSpdyStreamErrorCallback, stream_id_, |
631 status, &description)); | 627 status, &description)); |
632 } | 628 } |
633 | 629 |
634 void SpdyStream::OnClose(int status) { | 630 void SpdyStream::OnClose(int status) { |
635 // In most cases, the stream should already be CLOSED. The exception is when a | 631 // In most cases, the stream should already be CLOSED. The exception is when a |
636 // SpdySession is shutting down while the stream is in an intermediate state. | 632 // SpdySession is shutting down while the stream is in an intermediate state. |
637 io_state_ = STATE_CLOSED; | 633 io_state_ = STATE_CLOSED; |
638 response_status_ = status; | 634 response_status_ = status; |
639 Delegate* delegate = delegate_; | 635 Delegate* delegate = delegate_; |
640 delegate_ = NULL; | 636 delegate_ = NULL; |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, | 920 description = base::StringPrintf("Unknown state 0x%08X (%u)", state, |
925 state); | 921 state); |
926 break; | 922 break; |
927 } | 923 } |
928 return description; | 924 return description; |
929 } | 925 } |
930 | 926 |
931 #undef STATE_CASE | 927 #undef STATE_CASE |
932 | 928 |
933 } // namespace net | 929 } // namespace net |
OLD | NEW |