| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "crypto/ec_private_key.h" | 25 #include "crypto/ec_private_key.h" |
| 26 #include "crypto/ec_signature_creator.h" | 26 #include "crypto/ec_signature_creator.h" |
| 27 #include "net/base/connection_type_histograms.h" | 27 #include "net/base/connection_type_histograms.h" |
| 28 #include "net/base/net_log.h" | 28 #include "net/base/net_log.h" |
| 29 #include "net/base/net_util.h" | 29 #include "net/base/net_util.h" |
| 30 #include "net/cert/asn1_util.h" | 30 #include "net/cert/asn1_util.h" |
| 31 #include "net/http/http_network_session.h" | 31 #include "net/http/http_network_session.h" |
| 32 #include "net/http/http_server_properties.h" | 32 #include "net/http/http_server_properties.h" |
| 33 #include "net/spdy/spdy_credential_builder.h" | 33 #include "net/spdy/spdy_credential_builder.h" |
| 34 #include "net/spdy/spdy_frame_builder.h" | 34 #include "net/spdy/spdy_frame_builder.h" |
| 35 #include "net/spdy/spdy_frame_producer.h" |
| 35 #include "net/spdy/spdy_http_utils.h" | 36 #include "net/spdy/spdy_http_utils.h" |
| 36 #include "net/spdy/spdy_protocol.h" | 37 #include "net/spdy/spdy_protocol.h" |
| 37 #include "net/spdy/spdy_session_pool.h" | 38 #include "net/spdy/spdy_session_pool.h" |
| 38 #include "net/spdy/spdy_stream.h" | 39 #include "net/spdy/spdy_stream.h" |
| 39 #include "net/ssl/server_bound_cert_service.h" | 40 #include "net/ssl/server_bound_cert_service.h" |
| 40 | 41 |
| 41 namespace net { | 42 namespace net { |
| 42 | 43 |
| 43 namespace { | 44 namespace { |
| 44 | 45 |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 | 280 |
| 280 void SpdyStreamRequest::Reset() { | 281 void SpdyStreamRequest::Reset() { |
| 281 session_ = NULL; | 282 session_ = NULL; |
| 282 stream_ = NULL; | 283 stream_ = NULL; |
| 283 url_ = GURL(); | 284 url_ = GURL(); |
| 284 priority_ = MINIMUM_PRIORITY; | 285 priority_ = MINIMUM_PRIORITY; |
| 285 net_log_ = BoundNetLog(); | 286 net_log_ = BoundNetLog(); |
| 286 callback_.Reset(); | 287 callback_.Reset(); |
| 287 } | 288 } |
| 288 | 289 |
| 289 // static | |
| 290 void SpdySession::SpdyIOBufferProducer::ActivateStream( | |
| 291 SpdySession* spdy_session, | |
| 292 SpdyStream* spdy_stream) { | |
| 293 spdy_session->ActivateStream(spdy_stream); | |
| 294 } | |
| 295 | |
| 296 // static | |
| 297 SpdyIOBuffer* SpdySession::SpdyIOBufferProducer::CreateIOBuffer( | |
| 298 SpdyFrame* frame, | |
| 299 RequestPriority priority, | |
| 300 SpdyStream* stream) { | |
| 301 size_t size = frame->size(); | |
| 302 DCHECK_GT(size, 0u); | |
| 303 | |
| 304 // TODO(mbelshe): We have too much copying of data here. | |
| 305 IOBufferWithSize* buffer = new IOBufferWithSize(size); | |
| 306 memcpy(buffer->data(), frame->data(), size); | |
| 307 | |
| 308 return new SpdyIOBuffer(buffer, size, priority, stream); | |
| 309 } | |
| 310 | |
| 311 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, | 290 SpdySession::SpdySession(const HostPortProxyPair& host_port_proxy_pair, |
| 312 SpdySessionPool* spdy_session_pool, | 291 SpdySessionPool* spdy_session_pool, |
| 313 HttpServerProperties* http_server_properties, | 292 HttpServerProperties* http_server_properties, |
| 314 bool verify_domain_authentication, | 293 bool verify_domain_authentication, |
| 315 bool enable_sending_initial_settings, | 294 bool enable_sending_initial_settings, |
| 316 bool enable_credential_frames, | 295 bool enable_credential_frames, |
| 317 bool enable_compression, | 296 bool enable_compression, |
| 318 bool enable_ping_based_connection_checking, | 297 bool enable_ping_based_connection_checking, |
| 319 NextProto default_protocol, | 298 NextProto default_protocol, |
| 320 size_t stream_initial_recv_window_size, | 299 size_t stream_initial_recv_window_size, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 | 376 |
| 398 if (connection_->is_initialized()) { | 377 if (connection_->is_initialized()) { |
| 399 // With SPDY we can't recycle sockets. | 378 // With SPDY we can't recycle sockets. |
| 400 connection_->socket()->Disconnect(); | 379 connection_->socket()->Disconnect(); |
| 401 } | 380 } |
| 402 | 381 |
| 403 // Streams should all be gone now. | 382 // Streams should all be gone now. |
| 404 DCHECK_EQ(0u, num_active_streams()); | 383 DCHECK_EQ(0u, num_active_streams()); |
| 405 DCHECK_EQ(0u, num_unclaimed_pushed_streams()); | 384 DCHECK_EQ(0u, num_unclaimed_pushed_streams()); |
| 406 | 385 |
| 407 for (int i = NUM_PRIORITIES - 1; i >= MINIMUM_PRIORITY; --i) { | 386 for (int i = 0; i < NUM_PRIORITIES; ++i) { |
| 408 DCHECK(pending_create_stream_queues_[i].empty()); | 387 DCHECK(pending_create_stream_queues_[i].empty()); |
| 409 } | 388 } |
| 410 DCHECK(pending_stream_request_completions_.empty()); | 389 DCHECK(pending_stream_request_completions_.empty()); |
| 411 | 390 |
| 412 RecordHistograms(); | 391 RecordHistograms(); |
| 413 | 392 |
| 414 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); | 393 net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION); |
| 415 } | 394 } |
| 416 | 395 |
| 417 net::Error SpdySession::InitializeWithSocket( | 396 net::Error SpdySession::InitializeWithSocket( |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 return true; // This is not a secure session, so all domains are okay. | 471 return true; // This is not a secure session, so all domains are okay. |
| 493 | 472 |
| 494 return !ssl_info.client_cert_sent && | 473 return !ssl_info.client_cert_sent && |
| 495 (enable_credential_frames_ || !ssl_info.channel_id_sent || | 474 (enable_credential_frames_ || !ssl_info.channel_id_sent || |
| 496 ServerBoundCertService::GetDomainForHost(domain) == | 475 ServerBoundCertService::GetDomainForHost(domain) == |
| 497 ServerBoundCertService::GetDomainForHost( | 476 ServerBoundCertService::GetDomainForHost( |
| 498 host_port_proxy_pair_.first.host())) && | 477 host_port_proxy_pair_.first.host())) && |
| 499 ssl_info.cert->VerifyNameMatch(domain); | 478 ssl_info.cert->VerifyNameMatch(domain); |
| 500 } | 479 } |
| 501 | 480 |
| 502 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream, | |
| 503 SpdyIOBufferProducer* producer) { | |
| 504 write_queue_.push(producer); | |
| 505 stream_producers_[producer] = stream; | |
| 506 WriteSocketLater(); | |
| 507 } | |
| 508 | |
| 509 int SpdySession::GetPushStream( | 481 int SpdySession::GetPushStream( |
| 510 const GURL& url, | 482 const GURL& url, |
| 511 scoped_refptr<SpdyStream>* stream, | 483 scoped_refptr<SpdyStream>* stream, |
| 512 const BoundNetLog& stream_net_log) { | 484 const BoundNetLog& stream_net_log) { |
| 513 CHECK_NE(state_, CLOSED); | 485 CHECK_NE(state_, CLOSED); |
| 514 | 486 |
| 515 *stream = NULL; | 487 *stream = NULL; |
| 516 | 488 |
| 517 // Don't allow access to secure push streams over an unauthenticated, but | 489 // Don't allow access to secure push streams over an unauthenticated, but |
| 518 // encrypted SSL socket. | 490 // encrypted SSL socket. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 | 624 |
| 653 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { | 625 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { |
| 654 pooled_aliases_.insert(alias); | 626 pooled_aliases_.insert(alias); |
| 655 } | 627 } |
| 656 | 628 |
| 657 int SpdySession::GetProtocolVersion() const { | 629 int SpdySession::GetProtocolVersion() const { |
| 658 DCHECK(buffered_spdy_framer_.get()); | 630 DCHECK(buffered_spdy_framer_.get()); |
| 659 return buffered_spdy_framer_->protocol_version(); | 631 return buffered_spdy_framer_->protocol_version(); |
| 660 } | 632 } |
| 661 | 633 |
| 662 SpdyFrame* SpdySession::CreateSynStream( | 634 void SpdySession::EnqueueStreamWrite( |
| 635 SpdyStream* stream, |
| 636 scoped_ptr<SpdyFrameProducer> producer) { |
| 637 EnqueueWrite(stream->priority(), producer.Pass(), stream); |
| 638 } |
| 639 |
| 640 scoped_ptr<SpdyFrame> SpdySession::CreateSynStream( |
| 663 SpdyStreamId stream_id, | 641 SpdyStreamId stream_id, |
| 664 RequestPriority priority, | 642 RequestPriority priority, |
| 665 uint8 credential_slot, | 643 uint8 credential_slot, |
| 666 SpdyControlFlags flags, | 644 SpdyControlFlags flags, |
| 667 const SpdyHeaderBlock& headers) { | 645 const SpdyHeaderBlock& headers) { |
| 668 CHECK(IsStreamActive(stream_id)); | 646 CHECK(IsStreamActive(stream_id)); |
| 669 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | 647 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; |
| 670 CHECK_EQ(stream->stream_id(), stream_id); | 648 CHECK_EQ(stream->stream_id(), stream_id); |
| 671 | 649 |
| 672 SendPrefacePingIfNoneInFlight(); | 650 SendPrefacePingIfNoneInFlight(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 684 | 662 |
| 685 if (net_log().IsLoggingAllEvents()) { | 663 if (net_log().IsLoggingAllEvents()) { |
| 686 net_log().AddEvent( | 664 net_log().AddEvent( |
| 687 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 665 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
| 688 base::Bind(&NetLogSpdySynCallback, &headers, | 666 base::Bind(&NetLogSpdySynCallback, &headers, |
| 689 (flags & CONTROL_FLAG_FIN) != 0, | 667 (flags & CONTROL_FLAG_FIN) != 0, |
| 690 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, | 668 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, |
| 691 stream_id, 0)); | 669 stream_id, 0)); |
| 692 } | 670 } |
| 693 | 671 |
| 694 return syn_frame.release(); | 672 return syn_frame.Pass(); |
| 695 } | 673 } |
| 696 | 674 |
| 697 SpdyFrame* SpdySession::CreateCredentialFrame( | 675 int SpdySession::CreateCredentialFrame( |
| 698 const std::string& origin, | 676 const std::string& origin, |
| 699 SSLClientCertType type, | 677 SSLClientCertType type, |
| 700 const std::string& key, | 678 const std::string& key, |
| 701 const std::string& cert, | 679 const std::string& cert, |
| 702 RequestPriority priority) { | 680 RequestPriority priority, |
| 681 scoped_ptr<SpdyFrame>* credential_frame) { |
| 703 DCHECK(is_secure_); | 682 DCHECK(is_secure_); |
| 704 SSLClientSocket* ssl_socket = GetSSLClientSocket(); | 683 SSLClientSocket* ssl_socket = GetSSLClientSocket(); |
| 705 DCHECK(ssl_socket); | 684 DCHECK(ssl_socket); |
| 706 DCHECK(ssl_socket->WasChannelIDSent()); | 685 DCHECK(ssl_socket->WasChannelIDSent()); |
| 707 | 686 |
| 708 SpdyCredential credential; | 687 SpdyCredential credential; |
| 709 std::string tls_unique; | 688 std::string tls_unique; |
| 710 ssl_socket->GetTLSUniqueChannelBinding(&tls_unique); | 689 ssl_socket->GetTLSUniqueChannelBinding(&tls_unique); |
| 711 size_t slot = credential_state_.SetHasCredential(GURL(origin)); | 690 size_t slot = credential_state_.SetHasCredential(GURL(origin)); |
| 712 int rv = SpdyCredentialBuilder::Build(tls_unique, type, key, cert, slot, | 691 int rv = SpdyCredentialBuilder::Build(tls_unique, type, key, cert, slot, |
| 713 &credential); | 692 &credential); |
| 714 DCHECK_EQ(OK, rv); | 693 DCHECK_NE(rv, ERR_IO_PENDING); |
| 715 if (rv != OK) | 694 if (rv != OK) |
| 716 return NULL; | 695 return rv; |
| 717 | 696 |
| 718 DCHECK(buffered_spdy_framer_.get()); | 697 DCHECK(buffered_spdy_framer_.get()); |
| 719 scoped_ptr<SpdyFrame> credential_frame( | 698 credential_frame->reset( |
| 720 buffered_spdy_framer_->CreateCredentialFrame(credential)); | 699 buffered_spdy_framer_->CreateCredentialFrame(credential)); |
| 721 | 700 |
| 722 if (net_log().IsLoggingAllEvents()) { | 701 if (net_log().IsLoggingAllEvents()) { |
| 723 net_log().AddEvent( | 702 net_log().AddEvent( |
| 724 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, | 703 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, |
| 725 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); | 704 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); |
| 726 } | 705 } |
| 727 return credential_frame.release(); | 706 return OK; |
| 728 } | 707 } |
| 729 | 708 |
| 730 SpdyFrame* SpdySession::CreateHeadersFrame( | 709 scoped_ptr<SpdyFrame> SpdySession::CreateHeadersFrame( |
| 731 SpdyStreamId stream_id, | 710 SpdyStreamId stream_id, |
| 732 const SpdyHeaderBlock& headers, | 711 const SpdyHeaderBlock& headers, |
| 733 SpdyControlFlags flags) { | 712 SpdyControlFlags flags) { |
| 734 // Find our stream | 713 // Find our stream |
| 735 CHECK(IsStreamActive(stream_id)); | 714 CHECK(IsStreamActive(stream_id)); |
| 736 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 715 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 737 CHECK_EQ(stream->stream_id(), stream_id); | 716 CHECK_EQ(stream->stream_id(), stream_id); |
| 738 | 717 |
| 739 // Create a HEADER frame. | 718 // Create a HEADER frame. |
| 740 scoped_ptr<SpdyFrame> frame( | 719 scoped_ptr<SpdyFrame> frame( |
| 741 buffered_spdy_framer_->CreateHeaders( | 720 buffered_spdy_framer_->CreateHeaders( |
| 742 stream_id, flags, enable_compression_, &headers)); | 721 stream_id, flags, enable_compression_, &headers)); |
| 743 | 722 |
| 744 if (net_log().IsLoggingAllEvents()) { | 723 if (net_log().IsLoggingAllEvents()) { |
| 745 bool fin = flags & CONTROL_FLAG_FIN; | 724 bool fin = flags & CONTROL_FLAG_FIN; |
| 746 net_log().AddEvent( | 725 net_log().AddEvent( |
| 747 NetLog::TYPE_SPDY_SESSION_SEND_HEADERS, | 726 NetLog::TYPE_SPDY_SESSION_SEND_HEADERS, |
| 748 base::Bind(&NetLogSpdySynCallback, | 727 base::Bind(&NetLogSpdySynCallback, |
| 749 &headers, fin, /*unidirectional=*/false, | 728 &headers, fin, /*unidirectional=*/false, |
| 750 stream_id, 0)); | 729 stream_id, 0)); |
| 751 } | 730 } |
| 752 return frame.release(); | 731 return frame.Pass(); |
| 753 } | 732 } |
| 754 | 733 |
| 755 SpdyFrame* SpdySession::CreateDataFrame(SpdyStreamId stream_id, | 734 scoped_ptr<SpdyFrame> SpdySession::CreateDataFrame(SpdyStreamId stream_id, |
| 756 net::IOBuffer* data, int len, | 735 net::IOBuffer* data, |
| 757 SpdyDataFlags flags) { | 736 int len, |
| 737 SpdyDataFlags flags) { |
| 758 // Find our stream | 738 // Find our stream |
| 759 CHECK(IsStreamActive(stream_id)); | 739 CHECK(IsStreamActive(stream_id)); |
| 760 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 740 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 761 CHECK_EQ(stream->stream_id(), stream_id); | 741 CHECK_EQ(stream->stream_id(), stream_id); |
| 762 | 742 |
| 763 if (len < 0) { | 743 if (len < 0) { |
| 764 NOTREACHED(); | 744 NOTREACHED(); |
| 765 return NULL; | 745 return scoped_ptr<SpdyFrame>(); |
| 766 } | 746 } |
| 767 | 747 |
| 768 if (len > kMaxSpdyFrameChunkSize) { | 748 if (len > kMaxSpdyFrameChunkSize) { |
| 769 len = kMaxSpdyFrameChunkSize; | 749 len = kMaxSpdyFrameChunkSize; |
| 770 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 750 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
| 771 } | 751 } |
| 772 | 752 |
| 773 // Obey send window size of the stream (and session, if applicable) | 753 // Obey send window size of the stream (and session, if applicable) |
| 774 // if flow control is enabled. | 754 // if flow control is enabled. |
| 775 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { | 755 if (flow_control_state_ >= FLOW_CONTROL_STREAM) { |
| 776 int32 effective_window_size = stream->send_window_size(); | 756 int32 effective_window_size = stream->send_window_size(); |
| 777 if (effective_window_size <= 0) { | 757 if (effective_window_size <= 0) { |
| 778 // Because we queue frames onto the session, it is possible that | 758 // Because we queue frames onto the session, it is possible that |
| 779 // a stream was not flow controlled at the time it attempted the | 759 // a stream was not flow controlled at the time it attempted the |
| 780 // write, but when we go to fulfill the write, it is now flow | 760 // write, but when we go to fulfill the write, it is now flow |
| 781 // controlled. This is why we need the session to mark the stream | 761 // controlled. This is why we need the session to mark the stream |
| 782 // as stalled - because only the session knows for sure when the | 762 // as stalled - because only the session knows for sure when the |
| 783 // stall occurs. | 763 // stall occurs. |
| 784 stream->set_send_stalled_by_flow_control(true); | 764 stream->set_send_stalled_by_flow_control(true); |
| 785 net_log().AddEvent( | 765 net_log().AddEvent( |
| 786 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_STREAM_SEND_WINDOW, | 766 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_STREAM_SEND_WINDOW, |
| 787 NetLog::IntegerCallback("stream_id", stream_id)); | 767 NetLog::IntegerCallback("stream_id", stream_id)); |
| 788 return NULL; | 768 return scoped_ptr<SpdyFrame>(); |
| 789 } | 769 } |
| 790 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { | 770 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) { |
| 791 effective_window_size = | 771 effective_window_size = |
| 792 std::min(effective_window_size, session_send_window_size_); | 772 std::min(effective_window_size, session_send_window_size_); |
| 793 if (effective_window_size <= 0) { | 773 if (effective_window_size <= 0) { |
| 794 DCHECK(IsSendStalled()); | 774 DCHECK(IsSendStalled()); |
| 795 stream->set_send_stalled_by_flow_control(true); | 775 stream->set_send_stalled_by_flow_control(true); |
| 796 QueueSendStalledStream(stream); | 776 QueueSendStalledStream(stream); |
| 797 net_log().AddEvent( | 777 net_log().AddEvent( |
| 798 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_SESSION_SEND_WINDOW, | 778 NetLog::TYPE_SPDY_SESSION_STREAM_STALLED_ON_SESSION_SEND_WINDOW, |
| 799 NetLog::IntegerCallback("stream_id", stream_id)); | 779 NetLog::IntegerCallback("stream_id", stream_id)); |
| 800 return NULL; | 780 return scoped_ptr<SpdyFrame>(); |
| 801 } | 781 } |
| 802 } | 782 } |
| 803 | 783 |
| 804 int new_len = std::min(len, effective_window_size); | 784 int new_len = std::min(len, effective_window_size); |
| 805 if (new_len < len) { | 785 if (new_len < len) { |
| 806 len = new_len; | 786 len = new_len; |
| 807 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 787 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
| 808 } | 788 } |
| 809 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) | 789 if (flow_control_state_ == FLOW_CONTROL_STREAM_AND_SESSION) |
| 810 DecreaseSendWindowSize(static_cast<int32>(len)); | 790 DecreaseSendWindowSize(static_cast<int32>(len)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 821 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. | 801 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. |
| 822 if (len > 0) | 802 if (len > 0) |
| 823 SendPrefacePingIfNoneInFlight(); | 803 SendPrefacePingIfNoneInFlight(); |
| 824 | 804 |
| 825 // TODO(mbelshe): reduce memory copies here. | 805 // TODO(mbelshe): reduce memory copies here. |
| 826 DCHECK(buffered_spdy_framer_.get()); | 806 DCHECK(buffered_spdy_framer_.get()); |
| 827 scoped_ptr<SpdyFrame> frame( | 807 scoped_ptr<SpdyFrame> frame( |
| 828 buffered_spdy_framer_->CreateDataFrame( | 808 buffered_spdy_framer_->CreateDataFrame( |
| 829 stream_id, data->data(), static_cast<uint32>(len), flags)); | 809 stream_id, data->data(), static_cast<uint32>(len), flags)); |
| 830 | 810 |
| 831 return frame.release(); | 811 return frame.Pass(); |
| 832 } | 812 } |
| 833 | 813 |
| 834 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { | 814 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { |
| 835 DCHECK_NE(0u, stream_id); | 815 DCHECK_NE(0u, stream_id); |
| 836 // TODO(mbelshe): We should send a RST_STREAM control frame here | 816 // TODO(mbelshe): We should send a RST_STREAM control frame here |
| 837 // so that the server can cancel a large send. | 817 // so that the server can cancel a large send. |
| 838 | 818 |
| 839 DeleteStream(stream_id, status); | 819 DeleteStream(stream_id, status); |
| 840 } | 820 } |
| 841 | 821 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 856 DCHECK(buffered_spdy_framer_.get()); | 836 DCHECK(buffered_spdy_framer_.get()); |
| 857 scoped_ptr<SpdyFrame> rst_frame( | 837 scoped_ptr<SpdyFrame> rst_frame( |
| 858 buffered_spdy_framer_->CreateRstStream(stream_id, status)); | 838 buffered_spdy_framer_->CreateRstStream(stream_id, status)); |
| 859 | 839 |
| 860 // Default to lowest priority unless we know otherwise. | 840 // Default to lowest priority unless we know otherwise. |
| 861 RequestPriority priority = net::IDLE; | 841 RequestPriority priority = net::IDLE; |
| 862 if (IsStreamActive(stream_id)) { | 842 if (IsStreamActive(stream_id)) { |
| 863 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 843 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 864 priority = stream->priority(); | 844 priority = stream->priority(); |
| 865 } | 845 } |
| 866 QueueFrame(rst_frame.release(), priority); | 846 EnqueueSessionWrite(priority, rst_frame.Pass()); |
| 867 RecordProtocolErrorHistogram( | 847 RecordProtocolErrorHistogram( |
| 868 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); | 848 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); |
| 869 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); | 849 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
| 870 } | 850 } |
| 871 | 851 |
| 872 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { | 852 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { |
| 873 return ContainsKey(active_streams_, stream_id); | 853 return ContainsKey(active_streams_, stream_id); |
| 874 } | 854 } |
| 875 | 855 |
| 876 LoadState SpdySession::GetLoadState() const { | 856 LoadState SpdySession::GetLoadState() const { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 buffered_spdy_framer_->ProcessInput(data, bytes_read); | 903 buffered_spdy_framer_->ProcessInput(data, bytes_read); |
| 924 bytes_read -= bytes_processed; | 904 bytes_read -= bytes_processed; |
| 925 data += bytes_processed; | 905 data += bytes_processed; |
| 926 } | 906 } |
| 927 | 907 |
| 928 if (state_ != CLOSED) | 908 if (state_ != CLOSED) |
| 929 ReadSocket(); | 909 ReadSocket(); |
| 930 } | 910 } |
| 931 | 911 |
| 932 void SpdySession::OnWriteComplete(int result) { | 912 void SpdySession::OnWriteComplete(int result) { |
| 913 // Releasing the in-flight write can have a side-effect of dropping |
| 914 // the last reference to |this|. Hold a reference through this |
| 915 // function. |
| 916 scoped_refptr<SpdySession> self(this); |
| 917 |
| 933 DCHECK(write_pending_); | 918 DCHECK(write_pending_); |
| 934 DCHECK(in_flight_write_.size()); | 919 DCHECK_GT(in_flight_write_.buffer()->BytesRemaining(), 0); |
| 935 | 920 |
| 936 last_activity_time_ = base::TimeTicks::Now(); | 921 last_activity_time_ = base::TimeTicks::Now(); |
| 937 write_pending_ = false; | 922 write_pending_ = false; |
| 938 | 923 |
| 939 scoped_refptr<SpdyStream> stream = in_flight_write_.stream(); | 924 if (result < 0) { |
| 925 in_flight_write_.Release(); |
| 926 CloseSessionOnError(static_cast<net::Error>(result), true, "Write error"); |
| 927 return; |
| 928 } |
| 940 | 929 |
| 941 if (result >= 0) { | 930 // It should not be possible to have written more bytes than our |
| 942 // It should not be possible to have written more bytes than our | 931 // in_flight_write_. |
| 943 // in_flight_write_. | 932 DCHECK_LE(result, in_flight_write_.buffer()->BytesRemaining()); |
| 944 DCHECK_LE(result, in_flight_write_.buffer()->BytesRemaining()); | |
| 945 | 933 |
| 946 in_flight_write_.buffer()->DidConsume(result); | 934 in_flight_write_.buffer()->DidConsume(result); |
| 947 | 935 |
| 948 // We only notify the stream when we've fully written the pending frame. | 936 // We only notify the stream when we've fully written the pending frame. |
| 949 if (!in_flight_write_.buffer()->BytesRemaining()) { | 937 if (in_flight_write_.buffer()->BytesRemaining() == 0) { |
| 950 if (stream) { | 938 DCHECK_GT(result, 0); |
| 951 // Report the number of bytes written to the caller, but exclude the | |
| 952 // frame size overhead. NOTE: if this frame was compressed the | |
| 953 // reported bytes written is the compressed size, not the original | |
| 954 // size. | |
| 955 if (result > 0) { | |
| 956 result = in_flight_write_.buffer()->size(); | |
| 957 DCHECK_GE(result, | |
| 958 static_cast<int>( | |
| 959 buffered_spdy_framer_->GetControlFrameHeaderSize())); | |
| 960 result -= buffered_spdy_framer_->GetControlFrameHeaderSize(); | |
| 961 } | |
| 962 | 939 |
| 963 // It is possible that the stream was cancelled while we were writing | 940 scoped_refptr<SpdyStream> stream = in_flight_write_.stream(); |
| 964 // to the socket. | |
| 965 if (!stream->cancelled()) | |
| 966 stream->OnWriteComplete(result); | |
| 967 } | |
| 968 | 941 |
| 969 // Cleanup the write which just completed. | 942 // It is possible that the stream was cancelled while we were writing |
| 970 in_flight_write_.release(); | 943 // to the socket. |
| 944 if (stream && !stream->cancelled()) { |
| 945 // Report the number of bytes written to the caller, but exclude the |
| 946 // frame size overhead. NOTE: if this frame was compressed the |
| 947 // reported bytes written is the compressed size, not the original |
| 948 // size. |
| 949 result = in_flight_write_.buffer()->size(); |
| 950 DCHECK_GE(result, |
| 951 static_cast<int>( |
| 952 buffered_spdy_framer_->GetControlFrameHeaderSize())); |
| 953 result -= buffered_spdy_framer_->GetControlFrameHeaderSize(); |
| 954 |
| 955 stream->OnWriteComplete(result); |
| 971 } | 956 } |
| 972 | 957 |
| 973 // Write more data. We're already in a continuation, so we can | 958 // Cleanup the write which just completed. |
| 974 // go ahead and write it immediately (without going back to the | 959 in_flight_write_.Release(); |
| 975 // message loop). | 960 } |
| 976 WriteSocketLater(); | |
| 977 } else { | |
| 978 in_flight_write_.release(); | |
| 979 | 961 |
| 980 // The stream is now errored. Close it down. | 962 // Write more data. We're already in a continuation, so we can go |
| 981 CloseSessionOnError( | 963 // ahead and write it immediately (without going back to the message |
| 982 static_cast<net::Error>(result), true, "The stream has errored."); | 964 // loop). |
| 983 } | 965 WriteSocketLater(); |
| 984 } | 966 } |
| 985 | 967 |
| 986 net::Error SpdySession::ReadSocket() { | 968 net::Error SpdySession::ReadSocket() { |
| 987 if (read_pending_) | 969 if (read_pending_) |
| 988 return OK; | 970 return OK; |
| 989 | 971 |
| 990 if (state_ == CLOSED) { | 972 if (state_ == CLOSED) { |
| 991 NOTREACHED(); | 973 NOTREACHED(); |
| 992 return ERR_UNEXPECTED; | 974 return ERR_UNEXPECTED; |
| 993 } | 975 } |
| 994 | 976 |
| 995 CHECK(connection_.get()); | 977 CHECK(connection_.get()); |
| 996 CHECK(connection_->socket()); | 978 CHECK(connection_->socket()); |
| 997 int bytes_read = connection_->socket()->Read( | 979 int bytes_read = connection_->socket()->Read( |
| 998 read_buffer_.get(), | 980 read_buffer_.get(), |
| 999 kReadBufferSize, | 981 kReadBufferSize, |
| 1000 base::Bind(&SpdySession::OnReadComplete, base::Unretained(this))); | 982 base::Bind(&SpdySession::OnReadComplete, weak_factory_.GetWeakPtr())); |
| 1001 switch (bytes_read) { | 983 switch (bytes_read) { |
| 1002 case 0: | 984 case 0: |
| 1003 // Socket is closed! | 985 // Socket is closed! |
| 1004 CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "bytes_read is 0."); | 986 CloseSessionOnError(ERR_CONNECTION_CLOSED, true, "bytes_read is 0."); |
| 1005 return ERR_CONNECTION_CLOSED; | 987 return ERR_CONNECTION_CLOSED; |
| 1006 case net::ERR_IO_PENDING: | 988 case net::ERR_IO_PENDING: |
| 1007 // Waiting for data. Nothing to do now. | 989 // Waiting for data. Nothing to do now. |
| 1008 read_pending_ = true; | 990 read_pending_ = true; |
| 1009 return ERR_IO_PENDING; | 991 return ERR_IO_PENDING; |
| 1010 default: | 992 default: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 // closed, just return. | 1026 // closed, just return. |
| 1045 if (state_ < CONNECTED || state_ == CLOSED) | 1027 if (state_ < CONNECTED || state_ == CLOSED) |
| 1046 return; | 1028 return; |
| 1047 | 1029 |
| 1048 if (write_pending_) // Another write is in progress still. | 1030 if (write_pending_) // Another write is in progress still. |
| 1049 return; | 1031 return; |
| 1050 | 1032 |
| 1051 // Loop sending frames until we've sent everything or until the write | 1033 // Loop sending frames until we've sent everything or until the write |
| 1052 // returns error (or ERR_IO_PENDING). | 1034 // returns error (or ERR_IO_PENDING). |
| 1053 DCHECK(buffered_spdy_framer_.get()); | 1035 DCHECK(buffered_spdy_framer_.get()); |
| 1054 while (in_flight_write_.buffer() || !write_queue_.empty()) { | 1036 while (true) { |
| 1055 if (!in_flight_write_.buffer()) { | 1037 if (in_flight_write_.buffer()) { |
| 1056 // Grab the next SpdyBuffer to send. | 1038 DCHECK_GT(in_flight_write_.buffer()->BytesRemaining(), 0); |
| 1057 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top()); | 1039 } else { |
| 1058 write_queue_.pop(); | 1040 // Grab the next frame to send. |
| 1059 scoped_ptr<SpdyIOBuffer> buffer(producer->ProduceNextBuffer(this)); | 1041 scoped_ptr<SpdyFrameProducer> producer; |
| 1060 stream_producers_.erase(producer.get()); | 1042 scoped_refptr<SpdyStream> stream; |
| 1043 if (!write_queue_.Dequeue(&producer, &stream)) |
| 1044 break; |
| 1045 |
| 1061 // It is possible that a stream had data to write, but a | 1046 // It is possible that a stream had data to write, but a |
| 1062 // WINDOW_UPDATE frame has been received which made that | 1047 // WINDOW_UPDATE frame has been received which made that |
| 1063 // stream no longer writable. | 1048 // stream no longer writable. |
| 1064 // TODO(rch): consider handling that case by removing the | 1049 // TODO(rch): consider handling that case by removing the |
| 1065 // stream from the writable queue? | 1050 // stream from the writable queue? |
| 1066 if (buffer == NULL) | 1051 if (stream.get() && stream->cancelled()) |
| 1067 continue; | 1052 continue; |
| 1068 | 1053 |
| 1069 in_flight_write_ = *buffer; | 1054 if (stream.get() && stream->stream_id() == 0) |
| 1070 } else { | 1055 ActivateStream(stream); |
| 1071 DCHECK(in_flight_write_.buffer()->BytesRemaining()); | 1056 |
| 1057 scoped_ptr<SpdyFrame> frame = producer->ProduceFrame(); |
| 1058 if (!frame) { |
| 1059 NOTREACHED(); |
| 1060 continue; |
| 1061 } |
| 1062 DCHECK_GT(frame->size(), 0u); |
| 1063 |
| 1064 // TODO(mbelshe): We have too much copying of data here. |
| 1065 scoped_refptr<IOBufferWithSize> buffer = |
| 1066 new IOBufferWithSize(frame->size()); |
| 1067 memcpy(buffer->data(), frame->data(), frame->size()); |
| 1068 in_flight_write_ = SpdyIOBuffer(buffer, frame->size(), stream); |
| 1072 } | 1069 } |
| 1073 | 1070 |
| 1074 write_pending_ = true; | 1071 write_pending_ = true; |
| 1075 int rv = connection_->socket()->Write( | 1072 int rv = connection_->socket()->Write( |
| 1076 in_flight_write_.buffer(), | 1073 in_flight_write_.buffer(), |
| 1077 in_flight_write_.buffer()->BytesRemaining(), | 1074 in_flight_write_.buffer()->BytesRemaining(), |
| 1078 base::Bind(&SpdySession::OnWriteComplete, weak_factory_.GetWeakPtr())); | 1075 base::Bind(&SpdySession::OnWriteComplete, weak_factory_.GetWeakPtr())); |
| 1079 if (rv == net::ERR_IO_PENDING) | 1076 if (rv == net::ERR_IO_PENDING) |
| 1080 break; | 1077 break; |
| 1081 | 1078 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 } | 1116 } |
| 1120 | 1117 |
| 1121 while (!created_streams_.empty()) { | 1118 while (!created_streams_.empty()) { |
| 1122 CreatedStreamSet::iterator it = created_streams_.begin(); | 1119 CreatedStreamSet::iterator it = created_streams_.begin(); |
| 1123 const scoped_refptr<SpdyStream> stream = *it; | 1120 const scoped_refptr<SpdyStream> stream = *it; |
| 1124 created_streams_.erase(it); | 1121 created_streams_.erase(it); |
| 1125 LogAbandonedStream(stream, status); | 1122 LogAbandonedStream(stream, status); |
| 1126 stream->OnClose(status); | 1123 stream->OnClose(status); |
| 1127 } | 1124 } |
| 1128 | 1125 |
| 1129 // We also need to drain the queue. | 1126 write_queue_.Clear(); |
| 1130 while (!write_queue_.empty()) { | |
| 1131 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top()); | |
| 1132 write_queue_.pop(); | |
| 1133 stream_producers_.erase(producer.get()); | |
| 1134 } | |
| 1135 } | 1127 } |
| 1136 | 1128 |
| 1137 void SpdySession::LogAbandonedStream(const scoped_refptr<SpdyStream>& stream, | 1129 void SpdySession::LogAbandonedStream(const scoped_refptr<SpdyStream>& stream, |
| 1138 net::Error status) { | 1130 net::Error status) { |
| 1139 DCHECK(stream); | 1131 DCHECK(stream); |
| 1140 std::string description = base::StringPrintf( | 1132 std::string description = base::StringPrintf( |
| 1141 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); | 1133 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); |
| 1142 stream->LogStreamError(status, description); | 1134 stream->LogStreamError(status, description); |
| 1143 } | 1135 } |
| 1144 | 1136 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 if (connection_->socket()) { | 1242 if (connection_->socket()) { |
| 1251 rv = connection_->socket()->GetLocalAddress(address); | 1243 rv = connection_->socket()->GetLocalAddress(address); |
| 1252 } | 1244 } |
| 1253 | 1245 |
| 1254 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetLocalAddress", | 1246 UMA_HISTOGRAM_BOOLEAN("Net.SpdySessionSocketNotConnectedGetLocalAddress", |
| 1255 rv == ERR_SOCKET_NOT_CONNECTED); | 1247 rv == ERR_SOCKET_NOT_CONNECTED); |
| 1256 | 1248 |
| 1257 return rv; | 1249 return rv; |
| 1258 } | 1250 } |
| 1259 | 1251 |
| 1260 class SimpleSpdyIOBufferProducer : public SpdySession::SpdyIOBufferProducer { | 1252 void SpdySession::EnqueueSessionWrite(RequestPriority priority, |
| 1261 public: | 1253 scoped_ptr<SpdyFrame> frame) { |
| 1262 SimpleSpdyIOBufferProducer(SpdyFrame* frame, | 1254 EnqueueWrite( |
| 1263 RequestPriority priority) | 1255 priority, |
| 1264 : frame_(frame), | 1256 scoped_ptr<SpdyFrameProducer>(new SimpleFrameProducer(frame.Pass())), |
| 1265 priority_(priority) { | 1257 NULL); |
| 1266 } | 1258 } |
| 1267 | 1259 |
| 1268 virtual RequestPriority GetPriority() const OVERRIDE { | 1260 void SpdySession::EnqueueWrite(RequestPriority priority, |
| 1269 return priority_; | 1261 scoped_ptr<SpdyFrameProducer> producer, |
| 1270 } | 1262 const scoped_refptr<SpdyStream>& stream) { |
| 1271 | 1263 write_queue_.Enqueue(priority, producer.Pass(), stream); |
| 1272 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) OVERRIDE { | |
| 1273 return SpdySession::SpdyIOBufferProducer::CreateIOBuffer( | |
| 1274 frame_.get(), priority_, NULL); | |
| 1275 } | |
| 1276 | |
| 1277 private: | |
| 1278 scoped_ptr<SpdyFrame> frame_; | |
| 1279 RequestPriority priority_; | |
| 1280 }; | |
| 1281 | |
| 1282 void SpdySession::QueueFrame(SpdyFrame* frame, | |
| 1283 RequestPriority priority) { | |
| 1284 SimpleSpdyIOBufferProducer* producer = | |
| 1285 new SimpleSpdyIOBufferProducer(frame, priority); | |
| 1286 write_queue_.push(producer); | |
| 1287 WriteSocketLater(); | 1264 WriteSocketLater(); |
| 1288 } | 1265 } |
| 1289 | 1266 |
| 1290 void SpdySession::ActivateStream(SpdyStream* stream) { | 1267 void SpdySession::ActivateStream(SpdyStream* stream) { |
| 1291 if (stream->stream_id() == 0) { | 1268 if (stream->stream_id() == 0) { |
| 1292 stream->set_stream_id(GetNewStreamId()); | 1269 stream->set_stream_id(GetNewStreamId()); |
| 1293 created_streams_.erase(scoped_refptr<SpdyStream>(stream)); | 1270 created_streams_.erase(scoped_refptr<SpdyStream>(stream)); |
| 1294 } | 1271 } |
| 1295 const SpdyStreamId id = stream->stream_id(); | 1272 const SpdyStreamId id = stream->stream_id(); |
| 1296 DCHECK(!IsStreamActive(id)); | 1273 DCHECK(!IsStreamActive(id)); |
| 1297 | 1274 |
| 1298 active_streams_[id] = stream; | 1275 active_streams_[id] = stream; |
| 1299 } | 1276 } |
| 1300 | 1277 |
| 1301 void SpdySession::DeleteStream(SpdyStreamId id, int status) { | 1278 void SpdySession::DeleteStream(SpdyStreamId id, int status) { |
| 1302 // For push streams, if they are being deleted normally, we leave | 1279 // For push streams, if they are being deleted normally, we leave |
| 1303 // the stream in the unclaimed_pushed_streams_ list. However, if | 1280 // the stream in the unclaimed_pushed_streams_ list. However, if |
| 1304 // the stream is errored out, clean it up entirely. | 1281 // the stream is errored out, clean it up entirely. |
| 1305 if (status != OK) { | 1282 if (status != OK) { |
| 1306 PushedStreamMap::iterator it; | 1283 for (PushedStreamMap::iterator it = unclaimed_pushed_streams_.begin(); |
| 1307 for (it = unclaimed_pushed_streams_.begin(); | |
| 1308 it != unclaimed_pushed_streams_.end(); ++it) { | 1284 it != unclaimed_pushed_streams_.end(); ++it) { |
| 1309 scoped_refptr<SpdyStream> curr = it->second.first; | 1285 scoped_refptr<SpdyStream> curr = it->second.first; |
| 1310 if (id == curr->stream_id()) { | 1286 if (id == curr->stream_id()) { |
| 1311 unclaimed_pushed_streams_.erase(it); | 1287 unclaimed_pushed_streams_.erase(it); |
| 1312 break; | 1288 break; |
| 1313 } | 1289 } |
| 1314 } | 1290 } |
| 1315 } | 1291 } |
| 1316 | 1292 |
| 1317 // The stream might have been deleted. | 1293 // The stream might have been deleted. |
| 1318 ActiveStreamMap::iterator it2 = active_streams_.find(id); | 1294 ActiveStreamMap::iterator it = active_streams_.find(id); |
| 1319 if (it2 == active_streams_.end()) | 1295 if (it == active_streams_.end()) |
| 1320 return; | 1296 return; |
| 1321 | 1297 |
| 1322 // Possibly remove from the write queue. | 1298 const scoped_refptr<SpdyStream> stream(it->second); |
| 1323 WriteQueue old = write_queue_; | 1299 active_streams_.erase(it); |
| 1324 write_queue_ = WriteQueue(); | 1300 DCHECK(stream); |
| 1325 while (!old.empty()) { | 1301 |
| 1326 scoped_ptr<SpdyIOBufferProducer> producer(old.top()); | 1302 write_queue_.RemovePendingWritesForStream(stream); |
| 1327 old.pop(); | |
| 1328 StreamProducerMap::iterator it = stream_producers_.find(producer.get()); | |
| 1329 if (it == stream_producers_.end() || it->second->stream_id() != id) { | |
| 1330 write_queue_.push(producer.release()); | |
| 1331 } else { | |
| 1332 stream_producers_.erase(producer.get()); | |
| 1333 producer.reset(NULL); | |
| 1334 } | |
| 1335 } | |
| 1336 | 1303 |
| 1337 // If this is an active stream, call the callback. | 1304 // If this is an active stream, call the callback. |
| 1338 const scoped_refptr<SpdyStream> stream(it2->second); | |
| 1339 active_streams_.erase(it2); | |
| 1340 DCHECK(stream); | |
| 1341 stream->OnClose(status); | 1305 stream->OnClose(status); |
| 1342 ProcessPendingStreamRequests(); | 1306 ProcessPendingStreamRequests(); |
| 1343 } | 1307 } |
| 1344 | 1308 |
| 1345 void SpdySession::RemoveFromPool() { | 1309 void SpdySession::RemoveFromPool() { |
| 1346 if (spdy_session_pool_) { | 1310 if (spdy_session_pool_) { |
| 1347 SpdySessionPool* pool = spdy_session_pool_; | 1311 SpdySessionPool* pool = spdy_session_pool_; |
| 1348 spdy_session_pool_ = NULL; | 1312 spdy_session_pool_ = NULL; |
| 1349 pool->Remove(make_scoped_refptr(this)); | 1313 pool->Remove(make_scoped_refptr(this)); |
| 1350 } | 1314 } |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1914 void SpdySession::SendSettings(const SettingsMap& settings) { | 1878 void SpdySession::SendSettings(const SettingsMap& settings) { |
| 1915 net_log_.AddEvent( | 1879 net_log_.AddEvent( |
| 1916 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 1880 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
| 1917 base::Bind(&NetLogSpdySettingsCallback, &settings)); | 1881 base::Bind(&NetLogSpdySettingsCallback, &settings)); |
| 1918 | 1882 |
| 1919 // Create the SETTINGS frame and send it. | 1883 // Create the SETTINGS frame and send it. |
| 1920 DCHECK(buffered_spdy_framer_.get()); | 1884 DCHECK(buffered_spdy_framer_.get()); |
| 1921 scoped_ptr<SpdyFrame> settings_frame( | 1885 scoped_ptr<SpdyFrame> settings_frame( |
| 1922 buffered_spdy_framer_->CreateSettings(settings)); | 1886 buffered_spdy_framer_->CreateSettings(settings)); |
| 1923 sent_settings_ = true; | 1887 sent_settings_ = true; |
| 1924 QueueFrame(settings_frame.release(), HIGHEST); | 1888 EnqueueSessionWrite(HIGHEST, settings_frame.Pass()); |
| 1925 } | 1889 } |
| 1926 | 1890 |
| 1927 void SpdySession::HandleSetting(uint32 id, uint32 value) { | 1891 void SpdySession::HandleSetting(uint32 id, uint32 value) { |
| 1928 switch (id) { | 1892 switch (id) { |
| 1929 case SETTINGS_MAX_CONCURRENT_STREAMS: | 1893 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 1930 max_concurrent_streams_ = std::min(static_cast<size_t>(value), | 1894 max_concurrent_streams_ = std::min(static_cast<size_t>(value), |
| 1931 kMaxConcurrentStreamLimit); | 1895 kMaxConcurrentStreamLimit); |
| 1932 ProcessPendingStreamRequests(); | 1896 ProcessPendingStreamRequests(); |
| 1933 break; | 1897 break; |
| 1934 case SETTINGS_INITIAL_WINDOW_SIZE: { | 1898 case SETTINGS_INITIAL_WINDOW_SIZE: { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 } | 1966 } |
| 2003 | 1967 |
| 2004 net_log_.AddEvent( | 1968 net_log_.AddEvent( |
| 2005 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, | 1969 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE_FRAME, |
| 2006 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, | 1970 base::Bind(&NetLogSpdyWindowUpdateFrameCallback, |
| 2007 stream_id, delta_window_size)); | 1971 stream_id, delta_window_size)); |
| 2008 | 1972 |
| 2009 DCHECK(buffered_spdy_framer_.get()); | 1973 DCHECK(buffered_spdy_framer_.get()); |
| 2010 scoped_ptr<SpdyFrame> window_update_frame( | 1974 scoped_ptr<SpdyFrame> window_update_frame( |
| 2011 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); | 1975 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); |
| 2012 QueueFrame(window_update_frame.release(), priority); | 1976 EnqueueSessionWrite(priority, window_update_frame.Pass()); |
| 2013 } | 1977 } |
| 2014 | 1978 |
| 2015 void SpdySession::WritePingFrame(uint32 unique_id) { | 1979 void SpdySession::WritePingFrame(uint32 unique_id) { |
| 2016 DCHECK(buffered_spdy_framer_.get()); | 1980 DCHECK(buffered_spdy_framer_.get()); |
| 2017 scoped_ptr<SpdyFrame> ping_frame( | 1981 scoped_ptr<SpdyFrame> ping_frame( |
| 2018 buffered_spdy_framer_->CreatePingFrame(unique_id)); | 1982 buffered_spdy_framer_->CreatePingFrame(unique_id)); |
| 2019 QueueFrame(ping_frame.release(), HIGHEST); | 1983 EnqueueSessionWrite(HIGHEST, ping_frame.Pass()); |
| 2020 | 1984 |
| 2021 if (net_log().IsLoggingAllEvents()) { | 1985 if (net_log().IsLoggingAllEvents()) { |
| 2022 net_log().AddEvent( | 1986 net_log().AddEvent( |
| 2023 NetLog::TYPE_SPDY_SESSION_PING, | 1987 NetLog::TYPE_SPDY_SESSION_PING, |
| 2024 base::Bind(&NetLogSpdyPingCallback, unique_id, "sent")); | 1988 base::Bind(&NetLogSpdyPingCallback, unique_id, "sent")); |
| 2025 } | 1989 } |
| 2026 if (unique_id % 2 != 0) { | 1990 if (unique_id % 2 != 0) { |
| 2027 next_ping_id_ += 2; | 1991 next_ping_id_ += 2; |
| 2028 ++pings_in_flight_; | 1992 ++pings_in_flight_; |
| 2029 PlanToCheckPingStatus(); | 1993 PlanToCheckPingStatus(); |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2304 } | 2268 } |
| 2305 | 2269 |
| 2306 session_recv_window_size_ -= delta_window_size; | 2270 session_recv_window_size_ -= delta_window_size; |
| 2307 net_log_.AddEvent( | 2271 net_log_.AddEvent( |
| 2308 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, | 2272 NetLog::TYPE_SPDY_SESSION_UPDATE_RECV_WINDOW, |
| 2309 base::Bind(&NetLogSpdySessionWindowUpdateCallback, | 2273 base::Bind(&NetLogSpdySessionWindowUpdateCallback, |
| 2310 -delta_window_size, session_recv_window_size_)); | 2274 -delta_window_size, session_recv_window_size_)); |
| 2311 } | 2275 } |
| 2312 | 2276 |
| 2313 } // namespace net | 2277 } // namespace net |
| OLD | NEW |