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

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

Issue 13009012: [SPDY] Refactor SpdySession's write queue (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix use-after-free (crbug.com/230259) Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_spdy2_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_session_spdy2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698