| 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 | 
|---|