Chromium Code Reviews| 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_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/debug/trace_event.h" | |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/message_loop.h" | 14 #include "base/message_loop.h" |
| 14 #include "base/metrics/field_trial.h" | 15 #include "base/metrics/field_trial.h" |
| 15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 16 #include "base/metrics/stats_counters.h" | 17 #include "base/metrics/stats_counters.h" |
| 17 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
| 18 #include "base/string_number_conversions.h" | 19 #include "base/string_number_conversions.h" |
| 19 #include "base/string_util.h" | 20 #include "base/string_util.h" |
| 20 #include "base/stringprintf.h" | 21 #include "base/stringprintf.h" |
| 21 #include "base/time.h" | 22 #include "base/time.h" |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 http_server_properties_(http_server_properties), | 231 http_server_properties_(http_server_properties), |
| 231 connection_(new ClientSocketHandle), | 232 connection_(new ClientSocketHandle), |
| 232 read_buffer_(new IOBuffer(kReadBufferSize)), | 233 read_buffer_(new IOBuffer(kReadBufferSize)), |
| 233 read_pending_(false), | 234 read_pending_(false), |
| 234 stream_hi_water_mark_(1), // Always start at 1 for the first stream id. | 235 stream_hi_water_mark_(1), // Always start at 1 for the first stream id. |
| 235 write_pending_(false), | 236 write_pending_(false), |
| 236 delayed_write_pending_(false), | 237 delayed_write_pending_(false), |
| 237 is_secure_(false), | 238 is_secure_(false), |
| 238 certificate_error_code_(OK), | 239 certificate_error_code_(OK), |
| 239 error_(OK), | 240 error_(OK), |
| 240 state_(IDLE), | 241 state_(STATE_IDLE), |
| 241 max_concurrent_streams_(initial_max_concurrent_streams == 0 ? | 242 max_concurrent_streams_(initial_max_concurrent_streams == 0 ? |
| 242 kInitialMaxConcurrentStreams : | 243 kInitialMaxConcurrentStreams : |
| 243 initial_max_concurrent_streams), | 244 initial_max_concurrent_streams), |
| 244 max_concurrent_streams_limit_(max_concurrent_streams_limit == 0 ? | 245 max_concurrent_streams_limit_(max_concurrent_streams_limit == 0 ? |
| 245 kMaxConcurrentStreamLimit : | 246 kMaxConcurrentStreamLimit : |
| 246 max_concurrent_streams_limit), | 247 max_concurrent_streams_limit), |
| 247 streams_initiated_count_(0), | 248 streams_initiated_count_(0), |
| 248 streams_pushed_count_(0), | 249 streams_pushed_count_(0), |
| 249 streams_pushed_and_claimed_count_(0), | 250 streams_pushed_and_claimed_count_(0), |
| 250 streams_abandoned_count_(0), | 251 streams_abandoned_count_(0), |
| 251 bytes_received_(0), | 252 total_bytes_received_(0), |
| 253 bytes_read_(0), | |
| 252 sent_settings_(false), | 254 sent_settings_(false), |
| 253 received_settings_(false), | 255 received_settings_(false), |
| 254 stalled_streams_(0), | 256 stalled_streams_(0), |
| 255 pings_in_flight_(0), | 257 pings_in_flight_(0), |
| 256 next_ping_id_(1), | 258 next_ping_id_(1), |
| 257 last_activity_time_(base::TimeTicks::Now()), | 259 last_activity_time_(base::TimeTicks::Now()), |
| 258 check_ping_status_pending_(false), | 260 check_ping_status_pending_(false), |
| 259 flow_control_(false), | 261 flow_control_(false), |
| 260 initial_send_window_size_(kSpdyStreamInitialWindowSize), | 262 initial_send_window_size_(kSpdyStreamInitialWindowSize), |
| 261 initial_recv_window_size_(initial_recv_window_size == 0 ? | 263 initial_recv_window_size_(initial_recv_window_size == 0 ? |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 | 303 |
| 302 SpdySession::CallbackResultPair::CallbackResultPair( | 304 SpdySession::CallbackResultPair::CallbackResultPair( |
| 303 const CompletionCallback& callback_in, int result_in) | 305 const CompletionCallback& callback_in, int result_in) |
| 304 : callback(callback_in), | 306 : callback(callback_in), |
| 305 result(result_in) { | 307 result(result_in) { |
| 306 } | 308 } |
| 307 | 309 |
| 308 SpdySession::CallbackResultPair::~CallbackResultPair() {} | 310 SpdySession::CallbackResultPair::~CallbackResultPair() {} |
| 309 | 311 |
| 310 SpdySession::~SpdySession() { | 312 SpdySession::~SpdySession() { |
| 311 if (state_ != CLOSED) { | 313 if (state_ != STATE_CLOSED) { |
| 312 state_ = CLOSED; | 314 state_ = STATE_CLOSED; |
| 313 | 315 |
| 314 // Cleanup all the streams. | 316 // Cleanup all the streams. |
| 315 CloseAllStreams(net::ERR_ABORTED); | 317 CloseAllStreams(net::ERR_ABORTED); |
| 316 } | 318 } |
| 317 | 319 |
| 318 if (connection_->is_initialized()) { | 320 if (connection_->is_initialized()) { |
| 319 // With SPDY we can't recycle sockets. | 321 // With SPDY we can't recycle sockets. |
| 320 connection_->socket()->Disconnect(); | 322 connection_->socket()->Disconnect(); |
| 321 } | 323 } |
| 322 | 324 |
| 323 // Streams should all be gone now. | 325 // Streams should all be gone now. |
| 324 DCHECK_EQ(0u, num_active_streams()); | 326 DCHECK_EQ(0u, num_active_streams()); |
| 325 DCHECK_EQ(0u, num_unclaimed_pushed_streams()); | 327 DCHECK_EQ(0u, num_unclaimed_pushed_streams()); |
| 326 | 328 |
| 327 DCHECK(pending_callback_map_.empty()); | 329 DCHECK(pending_callback_map_.empty()); |
| 328 | 330 |
| 329 RecordHistograms(); | 331 RecordHistograms(); |
| 330 | 332 |
| 331 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); | 333 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); |
| 332 } | 334 } |
| 333 | 335 |
| 334 net::Error SpdySession::InitializeWithSocket( | 336 net::Error SpdySession::InitializeWithSocket( |
| 335 ClientSocketHandle* connection, | 337 ClientSocketHandle* connection, |
| 336 bool is_secure, | 338 bool is_secure, |
| 337 int certificate_error_code) { | 339 int certificate_error_code) { |
| 338 base::StatsCounter spdy_sessions("spdy.sessions"); | 340 base::StatsCounter spdy_sessions("spdy.sessions"); |
| 339 spdy_sessions.Increment(); | 341 spdy_sessions.Increment(); |
| 340 | 342 |
| 341 state_ = CONNECTED; | 343 state_ = STATE_DO_READ; |
| 342 connection_.reset(connection); | 344 connection_.reset(connection); |
| 343 is_secure_ = is_secure; | 345 is_secure_ = is_secure; |
| 344 certificate_error_code_ = certificate_error_code; | 346 certificate_error_code_ = certificate_error_code; |
| 345 | 347 |
| 346 NextProto protocol = default_protocol_; | 348 NextProto protocol = default_protocol_; |
| 347 NextProto protocol_negotiated = connection->socket()->GetNegotiatedProtocol(); | 349 NextProto protocol_negotiated = connection->socket()->GetNegotiatedProtocol(); |
| 348 if (protocol_negotiated != kProtoUnknown) { | 350 if (protocol_negotiated != kProtoUnknown) { |
| 349 protocol = protocol_negotiated; | 351 protocol = protocol_negotiated; |
| 350 } | 352 } |
| 351 | 353 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 363 flow_control_ = (protocol >= kProtoSPDY3); | 365 flow_control_ = (protocol >= kProtoSPDY3); |
| 364 | 366 |
| 365 buffered_spdy_framer_.reset(new BufferedSpdyFramer(version, | 367 buffered_spdy_framer_.reset(new BufferedSpdyFramer(version, |
| 366 enable_compression_)); | 368 enable_compression_)); |
| 367 buffered_spdy_framer_->set_visitor(this); | 369 buffered_spdy_framer_->set_visitor(this); |
| 368 SendInitialSettings(); | 370 SendInitialSettings(); |
| 369 UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol, kProtoMaximumVersion); | 371 UMA_HISTOGRAM_ENUMERATION("Net.SpdyVersion", protocol, kProtoMaximumVersion); |
| 370 | 372 |
| 371 // Write out any data that we might have to send, such as the settings frame. | 373 // Write out any data that we might have to send, such as the settings frame. |
| 372 WriteSocketLater(); | 374 WriteSocketLater(); |
| 373 net::Error error = ReadSocket(); | 375 net::Error error = static_cast<net::Error>(DoLoop(OK)); |
|
Ryan Hamilton
2012/12/29 18:41:52
nit: int rv = DoLoop(OK);
ramant (doing other things)
2013/01/16 00:31:58
Done.
| |
| 374 if (error == ERR_IO_PENDING) | 376 if (error == ERR_IO_PENDING) |
| 375 return OK; | 377 return OK; |
| 376 return error; | 378 return error; |
| 377 } | 379 } |
| 378 | 380 |
| 379 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { | 381 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) { |
| 380 if (!verify_domain_authentication_) | 382 if (!verify_domain_authentication_) |
| 381 return true; | 383 return true; |
| 382 | 384 |
| 383 if (state_ != CONNECTED) | 385 if (!IsConnected()) |
| 384 return false; | 386 return false; |
| 385 | 387 |
| 386 SSLInfo ssl_info; | 388 SSLInfo ssl_info; |
| 387 bool was_npn_negotiated; | 389 bool was_npn_negotiated; |
| 388 NextProto protocol_negotiated = kProtoUnknown; | 390 NextProto protocol_negotiated = kProtoUnknown; |
| 389 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) | 391 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) |
| 390 return true; // This is not a secure session, so all domains are okay. | 392 return true; // This is not a secure session, so all domains are okay. |
| 391 | 393 |
| 392 return !ssl_info.client_cert_sent && | 394 return !ssl_info.client_cert_sent && |
| 393 (enable_credential_frames_ || !ssl_info.channel_id_sent || | 395 (enable_credential_frames_ || !ssl_info.channel_id_sent || |
| 394 ServerBoundCertService::GetDomainForHost(domain) == | 396 ServerBoundCertService::GetDomainForHost(domain) == |
| 395 ServerBoundCertService::GetDomainForHost( | 397 ServerBoundCertService::GetDomainForHost( |
| 396 host_port_proxy_pair_.first.host())) && | 398 host_port_proxy_pair_.first.host())) && |
| 397 ssl_info.cert->VerifyNameMatch(domain); | 399 ssl_info.cert->VerifyNameMatch(domain); |
| 398 } | 400 } |
| 399 | 401 |
| 400 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream, | 402 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream, |
| 401 SpdyIOBufferProducer* producer) { | 403 SpdyIOBufferProducer* producer) { |
| 402 write_queue_.push(producer); | 404 write_queue_.push(producer); |
| 403 stream_producers_[producer] = stream; | 405 stream_producers_[producer] = stream; |
| 404 WriteSocketLater(); | 406 WriteSocketLater(); |
| 405 } | 407 } |
| 406 | 408 |
| 407 int SpdySession::GetPushStream( | 409 int SpdySession::GetPushStream( |
| 408 const GURL& url, | 410 const GURL& url, |
| 409 scoped_refptr<SpdyStream>* stream, | 411 scoped_refptr<SpdyStream>* stream, |
| 410 const BoundNetLog& stream_net_log) { | 412 const BoundNetLog& stream_net_log) { |
| 411 CHECK_NE(state_, CLOSED); | 413 CHECK_NE(state_, STATE_CLOSED); |
| 412 | 414 |
| 413 *stream = NULL; | 415 *stream = NULL; |
| 414 | 416 |
| 415 // Don't allow access to secure push streams over an unauthenticated, but | 417 // Don't allow access to secure push streams over an unauthenticated, but |
| 416 // encrypted SSL socket. | 418 // encrypted SSL socket. |
| 417 if (is_secure_ && certificate_error_code_ != OK && | 419 if (is_secure_ && certificate_error_code_ != OK && |
| 418 (url.SchemeIs("https") || url.SchemeIs("wss"))) { | 420 (url.SchemeIs("https") || url.SchemeIs("wss"))) { |
| 419 RecordProtocolErrorHistogram( | 421 RecordProtocolErrorHistogram( |
| 420 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); | 422 PROTOCOL_ERROR_REQUEST_FOR_SECURE_CONTENT_OVER_INSECURE_SESSION); |
| 421 CloseSessionOnError( | 423 CloseSessionOnError( |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 757 return ContainsKey(active_streams_, stream_id); | 759 return ContainsKey(active_streams_, stream_id); |
| 758 } | 760 } |
| 759 | 761 |
| 760 LoadState SpdySession::GetLoadState() const { | 762 LoadState SpdySession::GetLoadState() const { |
| 761 // NOTE: The application only queries the LoadState via the | 763 // NOTE: The application only queries the LoadState via the |
| 762 // SpdyNetworkTransaction, and details are only needed when | 764 // SpdyNetworkTransaction, and details are only needed when |
| 763 // we're in the process of connecting. | 765 // we're in the process of connecting. |
| 764 | 766 |
| 765 // If we're connecting, defer to the connection to give us the actual | 767 // If we're connecting, defer to the connection to give us the actual |
| 766 // LoadState. | 768 // LoadState. |
| 767 if (state_ == CONNECTING) | 769 if (state_ == STATE_CONNECTING) |
| 768 return connection_->GetLoadState(); | 770 return connection_->GetLoadState(); |
| 769 | 771 |
| 770 // Just report that we're idle since the session could be doing | 772 // Just report that we're idle since the session could be doing |
| 771 // many things concurrently. | 773 // many things concurrently. |
| 772 return LOAD_STATE_IDLE; | 774 return LOAD_STATE_IDLE; |
| 773 } | 775 } |
| 774 | 776 |
| 775 void SpdySession::OnReadComplete(int bytes_read) { | 777 void SpdySession::OnReadComplete(int bytes_read) { |
| 778 DCHECK_NE(state_, STATE_DO_READ); | |
| 779 read_pending_ = false; | |
| 780 DoLoop(bytes_read); | |
| 781 } | |
| 782 | |
| 783 void SpdySession::StartRead() { | |
| 784 DCHECK_NE(state_, STATE_DO_READ_COMPLETE); | |
| 785 read_pending_ = false; | |
| 786 DoLoop(OK); | |
| 787 } | |
| 788 | |
| 789 int SpdySession::DoLoop(int result) { | |
| 790 TRACE_EVENT0("spdy", "SpdySession::DoLoop"); | |
| 791 bytes_read_ = 0; | |
| 792 do { | |
| 793 if (read_pending_) | |
| 794 return OK; | |
| 795 | |
| 796 switch (state_) { | |
| 797 case STATE_DO_READ: | |
| 798 DCHECK_EQ(result, OK); | |
| 799 result = DoRead(); | |
| 800 break; | |
| 801 case STATE_DO_READ_COMPLETE: | |
| 802 result = DoReadComplete(result); | |
| 803 break; | |
| 804 case STATE_CLOSED: | |
| 805 result = ERR_CONNECTION_CLOSED; | |
| 806 break; | |
| 807 default: | |
| 808 NOTREACHED() << "state_: " << state_; | |
| 809 break; | |
| 810 } | |
| 811 } while (result != ERR_IO_PENDING && result != ERR_CONNECTION_CLOSED); | |
| 812 | |
| 813 if (result == net::ERR_IO_PENDING) | |
| 814 read_pending_ = true; | |
|
Ryan Hamilton
2012/12/29 18:41:52
nit: I would move these two lines to DoRead.
ramant (doing other things)
2013/01/16 00:31:58
Done.
| |
| 815 return result; | |
| 816 } | |
| 817 | |
| 818 int SpdySession::DoRead() { | |
| 819 TRACE_EVENT0("spdy", "SpdySession::DoRead"); | |
| 820 const int kMaxReadBytes = 32 * 1024; | |
| 821 if (bytes_read_ > kMaxReadBytes) { | |
|
Ryan Hamilton
2012/12/29 18:41:52
bytes_read_ is currently being set to 0 in DoLoop(
ramant (doing other things)
2013/01/16 00:31:58
We increment bytes_read_ in DoReadComplete. It is
| |
| 822 state_ = STATE_DO_READ; | |
| 823 MessageLoop::current()->PostTask( | |
| 824 FROM_HERE, | |
| 825 base::Bind(&SpdySession::StartRead, | |
| 826 weak_factory_.GetWeakPtr())); | |
| 827 return ERR_IO_PENDING; | |
| 828 } | |
| 829 | |
| 830 DCHECK(!read_pending_); | |
|
Ryan Hamilton
2012/12/29 18:41:52
nit Should this be moved above the if()?
ramant (doing other things)
2013/01/16 00:31:58
Done.
| |
| 831 CHECK(connection_.get()); | |
| 832 CHECK(connection_->socket()); | |
| 833 state_ = STATE_DO_READ_COMPLETE; | |
| 834 return connection_->socket()->Read( | |
| 835 read_buffer_.get(), | |
| 836 kReadBufferSize, | |
| 837 base::Bind(&SpdySession::OnReadComplete, base::Unretained(this))); | |
| 838 } | |
| 839 | |
| 840 int SpdySession::DoReadComplete(int bytes_read) { | |
| 776 // Parse a frame. For now this code requires that the frame fit into our | 841 // Parse a frame. For now this code requires that the frame fit into our |
| 777 // buffer (32KB). | 842 // buffer (32KB). |
| 778 // TODO(mbelshe): support arbitrarily large frames! | 843 // TODO(mbelshe): support arbitrarily large frames! |
| 779 | 844 |
| 780 read_pending_ = false; | 845 TRACE_EVENT0("spdy", "SpdySession::DoReadComplete"); |
| 846 DCHECK(!read_pending_); | |
| 781 | 847 |
| 782 if (bytes_read <= 0) { | 848 if (bytes_read <= 0) { |
| 783 // Session is tearing down. | 849 // Session is tearing down. |
| 784 net::Error error = static_cast<net::Error>(bytes_read); | 850 net::Error error = static_cast<net::Error>(bytes_read); |
|
Ryan Hamilton
2012/12/29 18:41:52
nit: please get rid of this cast and assignment.
ramant (doing other things)
2013/01/16 00:31:58
"CloseSessionOnError(error,..." use net::Error. On
| |
| 785 if (bytes_read == 0) | 851 if (bytes_read == 0) |
| 786 error = ERR_CONNECTION_CLOSED; | 852 error = ERR_CONNECTION_CLOSED; |
| 787 CloseSessionOnError(error, true, "bytes_read is <= 0."); | 853 CloseSessionOnError(error, true, "bytes_read is <= 0."); |
| 788 return; | 854 return ERR_CONNECTION_CLOSED; |
|
Ryan Hamilton
2012/12/29 18:41:52
Shouldn't this say "return error;"?
ramant (doing other things)
2013/01/16 00:31:58
CloseSessionOnError is logging the error. Thought
| |
| 789 } | 855 } |
| 790 | 856 |
| 791 bytes_received_ += bytes_read; | 857 total_bytes_received_ += bytes_read; |
| 858 bytes_read_ += bytes_read; | |
|
Ryan Hamilton
2012/12/29 18:41:52
I'm confused about the difference between bytes_re
ramant (doing other things)
2013/01/16 00:31:58
Added a comment in the header file.
Done.
| |
| 792 | 859 |
| 793 last_activity_time_ = base::TimeTicks::Now(); | 860 last_activity_time_ = base::TimeTicks::Now(); |
| 794 | 861 |
| 795 // The SpdyFramer will use callbacks onto |this| as it parses frames. | 862 // The SpdyFramer will use callbacks onto |this| as it parses frames. |
| 796 // When errors occur, those callbacks can lead to teardown of all references | 863 // When errors occur, those callbacks can lead to teardown of all references |
| 797 // to |this|, so maintain a reference to self during this call for safe | 864 // to |this|, so maintain a reference to self during this call for safe |
| 798 // cleanup. | 865 // cleanup. |
| 799 scoped_refptr<SpdySession> self(this); | 866 scoped_refptr<SpdySession> self(this); |
| 800 | 867 |
| 801 DCHECK(buffered_spdy_framer_.get()); | 868 DCHECK(buffered_spdy_framer_.get()); |
| 802 char *data = read_buffer_->data(); | 869 char *data = read_buffer_->data(); |
| 803 while (bytes_read && | 870 while (bytes_read && |
| 804 buffered_spdy_framer_->error_code() == | 871 buffered_spdy_framer_->error_code() == |
| 805 SpdyFramer::SPDY_NO_ERROR) { | 872 SpdyFramer::SPDY_NO_ERROR) { |
| 806 uint32 bytes_processed = | 873 uint32 bytes_processed = |
| 807 buffered_spdy_framer_->ProcessInput(data, bytes_read); | 874 buffered_spdy_framer_->ProcessInput(data, bytes_read); |
| 808 bytes_read -= bytes_processed; | 875 bytes_read -= bytes_processed; |
| 809 data += bytes_processed; | 876 data += bytes_processed; |
| 810 if (buffered_spdy_framer_->state() == SpdyFramer::SPDY_DONE) | 877 if (buffered_spdy_framer_->state() == SpdyFramer::SPDY_DONE) |
| 811 buffered_spdy_framer_->Reset(); | 878 buffered_spdy_framer_->Reset(); |
| 812 } | 879 } |
| 813 | 880 |
| 814 if (state_ != CLOSED) | 881 if (state_ != STATE_CLOSED) |
| 815 ReadSocket(); | 882 state_ = STATE_DO_READ; |
| 883 return OK; | |
| 816 } | 884 } |
| 817 | 885 |
| 818 void SpdySession::OnWriteComplete(int result) { | 886 void SpdySession::OnWriteComplete(int result) { |
| 819 DCHECK(write_pending_); | 887 DCHECK(write_pending_); |
| 820 DCHECK(in_flight_write_.size()); | 888 DCHECK(in_flight_write_.size()); |
| 821 | 889 |
| 822 last_activity_time_ = base::TimeTicks::Now(); | 890 last_activity_time_ = base::TimeTicks::Now(); |
| 823 write_pending_ = false; | 891 write_pending_ = false; |
| 824 | 892 |
| 825 scoped_refptr<SpdyStream> stream = in_flight_write_.stream(); | 893 scoped_refptr<SpdyStream> stream = in_flight_write_.stream(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 WriteSocketLater(); | 928 WriteSocketLater(); |
| 861 } else { | 929 } else { |
| 862 in_flight_write_.release(); | 930 in_flight_write_.release(); |
| 863 | 931 |
| 864 // The stream is now errored. Close it down. | 932 // The stream is now errored. Close it down. |
| 865 CloseSessionOnError( | 933 CloseSessionOnError( |
| 866 static_cast<net::Error>(result), true, "The stream has errored."); | 934 static_cast<net::Error>(result), true, "The stream has errored."); |
| 867 } | 935 } |
| 868 } | 936 } |
| 869 | 937 |
| 870 net::Error SpdySession::ReadSocket() { | |
| 871 if (read_pending_) | |
| 872 return OK; | |
| 873 | |
| 874 if (state_ == CLOSED) { | |
| 875 NOTREACHED(); | |
| 876 return ERR_UNEXPECTED; | |
| 877 } | |
| 878 | |
| 879 CHECK(connection_.get()); | |
| 880 CHECK(connection_->socket()); | |
| 881 int bytes_read = connection_->socket()->Read( | |
| 882 read_buffer_.get(), | |
| 883 kReadBufferSize, | |
| 884 base::Bind(&SpdySession::OnReadComplete, base::Unretained(this))); | |
| 885 switch (bytes_read) { | |
| 886 case 0: | |
| 887 // Socket is closed! | |
| 888 CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "bytes_read is 0."); | |
| 889 return ERR_CONNECTION_CLOSED; | |
| 890 case net::ERR_IO_PENDING: | |
| 891 // Waiting for data. Nothing to do now. | |
| 892 read_pending_ = true; | |
| 893 return ERR_IO_PENDING; | |
| 894 default: | |
| 895 // Data was read, process it. | |
| 896 // Schedule the work through the message loop to avoid recursive | |
| 897 // callbacks. | |
| 898 read_pending_ = true; | |
| 899 MessageLoop::current()->PostTask( | |
| 900 FROM_HERE, | |
| 901 base::Bind(&SpdySession::OnReadComplete, | |
| 902 weak_factory_.GetWeakPtr(), bytes_read)); | |
| 903 break; | |
| 904 } | |
| 905 return OK; | |
| 906 } | |
| 907 | |
| 908 void SpdySession::WriteSocketLater() { | 938 void SpdySession::WriteSocketLater() { |
| 909 if (delayed_write_pending_) | 939 if (delayed_write_pending_) |
| 910 return; | 940 return; |
| 911 | 941 |
| 912 if (state_ < CONNECTED) | 942 if (!IsConnected()) |
| 913 return; | 943 return; |
| 914 | 944 |
| 915 delayed_write_pending_ = true; | 945 delayed_write_pending_ = true; |
| 916 MessageLoop::current()->PostTask( | 946 MessageLoop::current()->PostTask( |
| 917 FROM_HERE, | 947 FROM_HERE, |
| 918 base::Bind(&SpdySession::WriteSocket, weak_factory_.GetWeakPtr())); | 948 base::Bind(&SpdySession::WriteSocket, weak_factory_.GetWeakPtr())); |
| 919 } | 949 } |
| 920 | 950 |
| 921 void SpdySession::WriteSocket() { | 951 void SpdySession::WriteSocket() { |
| 922 // This function should only be called via WriteSocketLater. | 952 // This function should only be called via WriteSocketLater. |
| 923 DCHECK(delayed_write_pending_); | 953 DCHECK(delayed_write_pending_); |
| 924 delayed_write_pending_ = false; | 954 delayed_write_pending_ = false; |
| 925 | 955 |
| 926 // If the socket isn't connected yet, just wait; we'll get called | 956 // If the socket isn't connected yet, just wait; we'll get called |
| 927 // again when the socket connection completes. If the socket is | 957 // again when the socket connection completes. If the socket is |
| 928 // closed, just return. | 958 // closed, just return. |
| 929 if (state_ < CONNECTED || state_ == CLOSED) | 959 if (!IsConnected()) |
| 930 return; | 960 return; |
| 931 | 961 |
| 932 if (write_pending_) // Another write is in progress still. | 962 if (write_pending_) // Another write is in progress still. |
| 933 return; | 963 return; |
| 934 | 964 |
| 935 // Loop sending frames until we've sent everything or until the write | 965 // Loop sending frames until we've sent everything or until the write |
| 936 // returns error (or ERR_IO_PENDING). | 966 // returns error (or ERR_IO_PENDING). |
| 937 DCHECK(buffered_spdy_framer_.get()); | 967 DCHECK(buffered_spdy_framer_.get()); |
| 938 while (in_flight_write_.buffer() || !write_queue_.empty()) { | 968 while (in_flight_write_.buffer() || !write_queue_.empty()) { |
| 939 if (!in_flight_write_.buffer()) { | 969 if (!in_flight_write_.buffer()) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 scoped_refptr<SpdySession> self(this); | 1071 scoped_refptr<SpdySession> self(this); |
| 1042 | 1072 |
| 1043 DCHECK_LT(err, OK); | 1073 DCHECK_LT(err, OK); |
| 1044 net_log_.AddEvent( | 1074 net_log_.AddEvent( |
| 1045 NetLog::TYPE_SPDY_SESSION_CLOSE, | 1075 NetLog::TYPE_SPDY_SESSION_CLOSE, |
| 1046 base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); | 1076 base::Bind(&NetLogSpdySessionCloseCallback, err, &description)); |
| 1047 | 1077 |
| 1048 // Don't close twice. This can occur because we can have both | 1078 // Don't close twice. This can occur because we can have both |
| 1049 // a read and a write outstanding, and each can complete with | 1079 // a read and a write outstanding, and each can complete with |
| 1050 // an error. | 1080 // an error. |
| 1051 if (state_ != CLOSED) { | 1081 if (state_ != STATE_CLOSED) { |
|
Ryan Hamilton
2012/12/29 18:41:52
if (!IsConnected()) {
ramant (doing other things)
2013/01/16 00:31:58
Changed it to !IsClosed() (in case connect failed)
| |
| 1052 state_ = CLOSED; | 1082 state_ = STATE_CLOSED; |
| 1053 error_ = err; | 1083 error_ = err; |
| 1054 if (remove_from_pool) | 1084 if (remove_from_pool) |
| 1055 RemoveFromPool(); | 1085 RemoveFromPool(); |
| 1056 CloseAllStreams(err); | 1086 CloseAllStreams(err); |
| 1057 } | 1087 } |
| 1058 } | 1088 } |
| 1059 | 1089 |
| 1060 Value* SpdySession::GetInfoAsValue() const { | 1090 Value* SpdySession::GetInfoAsValue() const { |
| 1061 DictionaryValue* dict = new DictionaryValue(); | 1091 DictionaryValue* dict = new DictionaryValue(); |
| 1062 | 1092 |
| (...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1901 SettingsMap::const_iterator it; | 1931 SettingsMap::const_iterator it; |
| 1902 for (it = settings_map.begin(); it != settings_map.end(); ++it) { | 1932 for (it = settings_map.begin(); it != settings_map.end(); ++it) { |
| 1903 const SpdySettingsIds id = it->first; | 1933 const SpdySettingsIds id = it->first; |
| 1904 const uint32 val = it->second.second; | 1934 const uint32 val = it->second.second; |
| 1905 switch (id) { | 1935 switch (id) { |
| 1906 case SETTINGS_CURRENT_CWND: | 1936 case SETTINGS_CURRENT_CWND: |
| 1907 // Record several different histograms to see if cwnd converges | 1937 // Record several different histograms to see if cwnd converges |
| 1908 // for larger volumes of data being sent. | 1938 // for larger volumes of data being sent. |
| 1909 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd", | 1939 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd", |
| 1910 val, 1, 200, 100); | 1940 val, 1, 200, 100); |
| 1911 if (bytes_received_ > 10 * 1024) { | 1941 if (total_bytes_received_ > 10 * 1024) { |
| 1912 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd10K", | 1942 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd10K", |
| 1913 val, 1, 200, 100); | 1943 val, 1, 200, 100); |
| 1914 if (bytes_received_ > 25 * 1024) { | 1944 if (total_bytes_received_ > 25 * 1024) { |
| 1915 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd25K", | 1945 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd25K", |
| 1916 val, 1, 200, 100); | 1946 val, 1, 200, 100); |
| 1917 if (bytes_received_ > 50 * 1024) { | 1947 if (total_bytes_received_ > 50 * 1024) { |
| 1918 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd50K", | 1948 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd50K", |
| 1919 val, 1, 200, 100); | 1949 val, 1, 200, 100); |
| 1920 if (bytes_received_ > 100 * 1024) { | 1950 if (total_bytes_received_ > 100 * 1024) { |
| 1921 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd100K", | 1951 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwnd100K", |
| 1922 val, 1, 200, 100); | 1952 val, 1, 200, 100); |
| 1923 } | 1953 } |
| 1924 } | 1954 } |
| 1925 } | 1955 } |
| 1926 } | 1956 } |
| 1927 break; | 1957 break; |
| 1928 case SETTINGS_ROUND_TRIP_TIME: | 1958 case SETTINGS_ROUND_TRIP_TIME: |
| 1929 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT", | 1959 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsRTT", |
| 1930 val, 1, 1200, 100); | 1960 val, 1, 1200, 100); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1957 SSLClientSocket* SpdySession::GetSSLClientSocket() const { | 1987 SSLClientSocket* SpdySession::GetSSLClientSocket() const { |
| 1958 if (!is_secure_) | 1988 if (!is_secure_) |
| 1959 return NULL; | 1989 return NULL; |
| 1960 SSLClientSocket* ssl_socket = | 1990 SSLClientSocket* ssl_socket = |
| 1961 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 1991 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
| 1962 DCHECK(ssl_socket); | 1992 DCHECK(ssl_socket); |
| 1963 return ssl_socket; | 1993 return ssl_socket; |
| 1964 } | 1994 } |
| 1965 | 1995 |
| 1966 } // namespace net | 1996 } // namespace net |
| OLD | NEW |