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

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

Issue 10448083: Fix out of order SYN_STEAM frames. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix willchan's comments Created 8 years, 5 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
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 <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"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 173
174 NextProto g_default_protocol = kProtoUnknown; 174 NextProto g_default_protocol = kProtoUnknown;
175 size_t g_init_max_concurrent_streams = 100; 175 size_t g_init_max_concurrent_streams = 100;
176 size_t g_max_concurrent_stream_limit = 256; 176 size_t g_max_concurrent_stream_limit = 256;
177 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB 177 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB
178 bool g_enable_ping_based_connection_checking = true; 178 bool g_enable_ping_based_connection_checking = true;
179 179
180 } // namespace 180 } // namespace
181 181
182 // static 182 // static
183 void SpdySession::SpdyIOBufferProducer::ActivateStream(
184 SpdySession* spdy_session,
185 SpdyStream* spdy_stream) {
186 spdy_session->ActivateStream(spdy_stream);
187 }
188
189 // static
190 SpdyIOBuffer* SpdySession::SpdyIOBufferProducer::CreateIOBuffer(
191 SpdyFrame* frame,
192 RequestPriority priority,
193 SpdyStream* stream) {
194 size_t size = frame->length() + SpdyFrame::kHeaderSize;
195 DCHECK_GT(size, 0u);
196
197 // TODO(mbelshe): We have too much copying of data here.
198 IOBufferWithSize* buffer = new IOBufferWithSize(size);
199 memcpy(buffer->data(), frame->data(), size);
200
201 return new SpdyIOBuffer(buffer, size, priority, stream);
202 }
203
204 // static
183 void SpdySession::set_default_protocol(NextProto default_protocol) { 205 void SpdySession::set_default_protocol(NextProto default_protocol) {
184 g_default_protocol = default_protocol; 206 g_default_protocol = default_protocol;
185 } 207 }
186 208
187 // static 209 // static
188 void SpdySession::set_max_concurrent_streams(size_t value) { 210 void SpdySession::set_max_concurrent_streams(size_t value) {
189 g_max_concurrent_stream_limit = value; 211 g_max_concurrent_stream_limit = value;
190 } 212 }
191 213
192 // static 214 // static
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 370
349 SSLInfo ssl_info; 371 SSLInfo ssl_info;
350 bool was_npn_negotiated; 372 bool was_npn_negotiated;
351 NextProto protocol_negotiated = kProtoUnknown; 373 NextProto protocol_negotiated = kProtoUnknown;
352 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) 374 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated))
353 return true; // This is not a secure session, so all domains are okay. 375 return true; // This is not a secure session, so all domains are okay.
354 376
355 return !ssl_info.client_cert_sent && ssl_info.cert->VerifyNameMatch(domain); 377 return !ssl_info.client_cert_sent && ssl_info.cert->VerifyNameMatch(domain);
356 } 378 }
357 379
380 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream,
381 SpdyIOBufferProducer* producer) {
382 write_queue_.push(producer);
383 stream_producers_[producer] = stream;
384 WriteSocketLater();
385 }
386
358 int SpdySession::GetPushStream( 387 int SpdySession::GetPushStream(
359 const GURL& url, 388 const GURL& url,
360 scoped_refptr<SpdyStream>* stream, 389 scoped_refptr<SpdyStream>* stream,
361 const BoundNetLog& stream_net_log) { 390 const BoundNetLog& stream_net_log) {
362 CHECK_NE(state_, CLOSED); 391 CHECK_NE(state_, CLOSED);
363 392
364 *stream = NULL; 393 *stream = NULL;
365 394
366 // Don't allow access to secure push streams over an unauthenticated, but 395 // Don't allow access to secure push streams over an unauthenticated, but
367 // encrypted SSL socket. 396 // encrypted SSL socket.
(...skipping 18 matching lines...) Expand all
386 return 0; 415 return 0;
387 } 416 }
388 417
389 int SpdySession::CreateStream( 418 int SpdySession::CreateStream(
390 const GURL& url, 419 const GURL& url,
391 RequestPriority priority, 420 RequestPriority priority,
392 scoped_refptr<SpdyStream>* spdy_stream, 421 scoped_refptr<SpdyStream>* spdy_stream,
393 const BoundNetLog& stream_net_log, 422 const BoundNetLog& stream_net_log,
394 const CompletionCallback& callback) { 423 const CompletionCallback& callback) {
395 if (!max_concurrent_streams_ || 424 if (!max_concurrent_streams_ ||
396 active_streams_.size() < max_concurrent_streams_) { 425 (active_streams_.size() + created_streams_.size()
426 < max_concurrent_streams_)) {
397 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log); 427 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log);
ramant (doing other things) 2012/06/26 23:30:25 nit: "When expressions are wrapped, the operator s
Ryan Hamilton 2012/06/27 16:58:28 Done.
398 } 428 }
399 429
400 stalled_streams_++; 430 stalled_streams_++;
401 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS); 431 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS);
402 create_stream_queues_[priority].push( 432 create_stream_queues_[priority].push(
403 PendingCreateStream(url, priority, spdy_stream, 433 PendingCreateStream(url, priority, spdy_stream,
404 stream_net_log, callback)); 434 stream_net_log, callback));
405 return ERR_IO_PENDING; 435 return ERR_IO_PENDING;
406 } 436 }
407 437
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 CloseSessionOnError( 506 CloseSessionOnError(
477 static_cast<net::Error>(certificate_error_code_), 507 static_cast<net::Error>(certificate_error_code_),
478 true, 508 true,
479 "Tried to create SPDY stream for secure content over an " 509 "Tried to create SPDY stream for secure content over an "
480 "unauthenticated session."); 510 "unauthenticated session.");
481 return ERR_SPDY_PROTOCOL_ERROR; 511 return ERR_SPDY_PROTOCOL_ERROR;
482 } 512 }
483 513
484 const std::string& path = url.PathForRequest(); 514 const std::string& path = url.PathForRequest();
485 515
486 const SpdyStreamId stream_id = GetNewStreamId();
487
488 *spdy_stream = new SpdyStream(this, 516 *spdy_stream = new SpdyStream(this,
489 stream_id,
490 false, 517 false,
491 stream_net_log); 518 stream_net_log);
492 const scoped_refptr<SpdyStream>& stream = *spdy_stream; 519 const scoped_refptr<SpdyStream>& stream = *spdy_stream;
493 520
494 stream->set_priority(priority); 521 stream->set_priority(priority);
495 stream->set_path(path); 522 stream->set_path(path);
496 stream->set_send_window_size(initial_send_window_size_); 523 stream->set_send_window_size(initial_send_window_size_);
497 stream->set_recv_window_size(initial_recv_window_size_); 524 stream->set_recv_window_size(initial_recv_window_size_);
498 ActivateStream(stream); 525 created_streams_.insert(stream);
499 526
500 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", 527 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount",
501 static_cast<int>(priority), 0, 10, 11); 528 static_cast<int>(priority), 0, 10, 11);
502 529
503 // TODO(mbelshe): Optimize memory allocations 530 // TODO(mbelshe): Optimize memory allocations
504 531
505 DCHECK_EQ(active_streams_[stream_id].get(), stream.get());
506 return OK; 532 return OK;
507 } 533 }
508 534
509 bool SpdySession::NeedsCredentials() const { 535 bool SpdySession::NeedsCredentials() const {
510 if (!is_secure_) 536 if (!is_secure_)
511 return false; 537 return false;
512 SSLClientSocket* ssl_socket = GetSSLClientSocket(); 538 SSLClientSocket* ssl_socket = GetSSLClientSocket();
513 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) 539 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3)
514 return false; 540 return false;
515 return ssl_socket->WasDomainBoundCertSent(); 541 return ssl_socket->WasDomainBoundCertSent();
516 } 542 }
517 543
518 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { 544 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) {
519 pooled_aliases_.insert(alias); 545 pooled_aliases_.insert(alias);
520 } 546 }
521 547
522 int SpdySession::GetProtocolVersion() const { 548 int SpdySession::GetProtocolVersion() const {
523 DCHECK(buffered_spdy_framer_.get()); 549 DCHECK(buffered_spdy_framer_.get());
524 return buffered_spdy_framer_->protocol_version(); 550 return buffered_spdy_framer_->protocol_version();
525 } 551 }
526 552
527 int SpdySession::WriteSynStream( 553 SpdySynStreamControlFrame* SpdySession::CreateSynStream(
528 SpdyStreamId stream_id, 554 SpdyStreamId stream_id,
529 RequestPriority priority, 555 RequestPriority priority,
530 uint8 credential_slot, 556 uint8 credential_slot,
531 SpdyControlFlags flags, 557 SpdyControlFlags flags,
532 const linked_ptr<SpdyHeaderBlock>& headers) { 558 const linked_ptr<SpdyHeaderBlock>& headers) {
533 // Find our stream 559 CHECK(IsStreamActive(stream_id));
534 if (!IsStreamActive(stream_id))
535 return ERR_INVALID_SPDY_STREAM;
536 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; 560 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id];
537 CHECK_EQ(stream->stream_id(), stream_id); 561 CHECK_EQ(stream->stream_id(), stream_id);
538 562
539 SendPrefacePingIfNoneInFlight(); 563 SendPrefacePingIfNoneInFlight();
540 564
541 DCHECK(buffered_spdy_framer_.get()); 565 DCHECK(buffered_spdy_framer_.get());
542 scoped_ptr<SpdySynStreamControlFrame> syn_frame( 566 scoped_ptr<SpdySynStreamControlFrame> syn_frame(
543 buffered_spdy_framer_->CreateSynStream( 567 buffered_spdy_framer_->CreateSynStream(
544 stream_id, 0, 568 stream_id, 0,
545 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), 569 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()),
546 credential_slot, flags, false, headers.get())); 570 credential_slot, flags, true, headers.get()));
547 // We enqueue all SYN_STREAM frames at the same priority to ensure
548 // that we do not send them out-of-order.
549 // http://crbug.com/111708
550 QueueFrame(syn_frame.get(), HIGHEST, stream);
551 571
552 base::StatsCounter spdy_requests("spdy.requests"); 572 base::StatsCounter spdy_requests("spdy.requests");
553 spdy_requests.Increment(); 573 spdy_requests.Increment();
554 streams_initiated_count_++; 574 streams_initiated_count_++;
555 575
556 if (net_log().IsLoggingAllEvents()) { 576 if (net_log().IsLoggingAllEvents()) {
557 net_log().AddEvent( 577 net_log().AddEvent(
558 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, 578 NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
559 base::Bind(&NetLogSpdySynCallback, headers.get(), flags, stream_id, 0)); 579 base::Bind(&NetLogSpdySynCallback, headers.get(), flags, stream_id, 0));
560 } 580 }
561 581
562 return ERR_IO_PENDING; 582 return syn_frame.release();
563 } 583 }
564 584
565 int SpdySession::WriteCredentialFrame(const std::string& origin, 585 SpdyCredentialControlFrame* SpdySession::CreateCredentialFrame(
566 SSLClientCertType type, 586 const std::string& origin,
567 const std::string& key, 587 SSLClientCertType type,
568 const std::string& cert, 588 const std::string& key,
569 RequestPriority priority) { 589 const std::string& cert,
590 RequestPriority priority) {
570 DCHECK(is_secure_); 591 DCHECK(is_secure_);
571 unsigned char secret[32]; // 32 bytes from the spec 592 unsigned char secret[32]; // 32 bytes from the spec
572 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof", 593 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof",
573 true, origin, 594 true, origin,
574 secret, arraysize(secret)); 595 secret, arraysize(secret));
575 596
576 // Convert the key string into a vector<unit8> 597 // Convert the key string into a vector<unit8>
577 std::vector<uint8> key_data; 598 std::vector<uint8> key_data;
578 for (size_t i = 0; i < key.length(); i++) { 599 for (size_t i = 0; i < key.length(); i++) {
579 key_data.push_back(key[i]); 600 key_data.push_back(key[i]);
(...skipping 21 matching lines...) Expand all
601 SpdyCredential credential; 622 SpdyCredential credential;
602 GURL origin_url(origin); 623 GURL origin_url(origin);
603 credential.slot = 624 credential.slot =
604 credential_state_.SetHasCredential(origin_url); 625 credential_state_.SetHasCredential(origin_url);
605 credential.certs.push_back(cert); 626 credential.certs.push_back(cert);
606 credential.proof.assign(proof.begin(), proof.end()); 627 credential.proof.assign(proof.begin(), proof.end());
607 628
608 DCHECK(buffered_spdy_framer_.get()); 629 DCHECK(buffered_spdy_framer_.get());
609 scoped_ptr<SpdyCredentialControlFrame> credential_frame( 630 scoped_ptr<SpdyCredentialControlFrame> credential_frame(
610 buffered_spdy_framer_->CreateCredentialFrame(credential)); 631 buffered_spdy_framer_->CreateCredentialFrame(credential));
611 // We enqueue all SYN_STREAM frames at the same priority to ensure
612 // that we do not send them out-of-order, which means that we need
613 // to enqueue all CREDENTIAL frames at this priority to ensure that
614 // they are sent *before* the SYN_STREAM that references them.
615 // http://crbug.com/111708
616 QueueFrame(credential_frame.get(), HIGHEST, NULL);
617 632
618 if (net_log().IsLoggingAllEvents()) { 633 if (net_log().IsLoggingAllEvents()) {
619 net_log().AddEvent( 634 net_log().AddEvent(
620 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, 635 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL,
621 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); 636 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin));
622 } 637 }
623 return ERR_IO_PENDING; 638 return credential_frame.release();
624 } 639 }
625 640
626 int SpdySession::WriteStreamData(SpdyStreamId stream_id, 641 SpdyDataFrame* SpdySession::CreateDataFrame(SpdyStreamId stream_id,
627 net::IOBuffer* data, int len, 642 net::IOBuffer* data, int len,
628 SpdyDataFlags flags) { 643 SpdyDataFlags flags) {
629 // Find our stream 644 // Find our stream
630 CHECK(IsStreamActive(stream_id)); 645 CHECK(IsStreamActive(stream_id));
631 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 646 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
632 CHECK_EQ(stream->stream_id(), stream_id); 647 CHECK_EQ(stream->stream_id(), stream_id);
633 648
634 if (len > kMaxSpdyFrameChunkSize) { 649 if (len > kMaxSpdyFrameChunkSize) {
635 len = kMaxSpdyFrameChunkSize; 650 len = kMaxSpdyFrameChunkSize;
636 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 651 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
637 } 652 }
638 653
639 // Obey send window size of the stream if flow control is enabled. 654 // Obey send window size of the stream if flow control is enabled.
640 if (flow_control_) { 655 if (flow_control_) {
641 if (stream->send_window_size() <= 0) { 656 if (stream->send_window_size() <= 0) {
642 // Because we queue frames onto the session, it is possible that 657 // Because we queue frames onto the session, it is possible that
643 // a stream was not flow controlled at the time it attempted the 658 // a stream was not flow controlled at the time it attempted the
644 // write, but when we go to fulfill the write, it is now flow 659 // write, but when we go to fulfill the write, it is now flow
645 // controlled. This is why we need the session to mark the stream 660 // controlled. This is why we need the session to mark the stream
646 // as stalled - because only the session knows for sure when the 661 // as stalled - because only the session knows for sure when the
647 // stall occurs. 662 // stall occurs.
648 stream->set_stalled_by_flow_control(true); 663 stream->set_stalled_by_flow_control(true);
649 net_log().AddEvent( 664 net_log().AddEvent(
650 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW, 665 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW,
651 NetLog::IntegerCallback("stream_id", stream_id)); 666 NetLog::IntegerCallback("stream_id", stream_id));
652 return ERR_IO_PENDING; 667 return NULL;
653 } 668 }
654 int new_len = std::min(len, stream->send_window_size()); 669 int new_len = std::min(len, stream->send_window_size());
655 if (new_len < len) { 670 if (new_len < len) {
656 len = new_len; 671 len = new_len;
657 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); 672 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN);
658 } 673 }
659 stream->DecreaseSendWindowSize(len); 674 stream->DecreaseSendWindowSize(len);
660 } 675 }
661 676
662 if (net_log().IsLoggingAllEvents()) { 677 if (net_log().IsLoggingAllEvents()) {
663 net_log().AddEvent( 678 net_log().AddEvent(
664 NetLog::TYPE_SPDY_SESSION_SEND_DATA, 679 NetLog::TYPE_SPDY_SESSION_SEND_DATA,
665 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags)); 680 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags));
666 } 681 }
667 682
668 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. 683 // Send PrefacePing for DATA_FRAMEs with nonzero payload size.
669 if (len > 0) 684 if (len > 0)
670 SendPrefacePingIfNoneInFlight(); 685 SendPrefacePingIfNoneInFlight();
671 686
672 // TODO(mbelshe): reduce memory copies here. 687 // TODO(mbelshe): reduce memory copies here.
673 DCHECK(buffered_spdy_framer_.get()); 688 DCHECK(buffered_spdy_framer_.get());
674 scoped_ptr<SpdyDataFrame> frame( 689 scoped_ptr<SpdyDataFrame> frame(
675 buffered_spdy_framer_->CreateDataFrame( 690 buffered_spdy_framer_->CreateDataFrame(
676 stream_id, data->data(), len, flags)); 691 stream_id, data->data(), len, flags));
677 QueueFrame(frame.get(), stream->priority(), stream);
678 692
679 return ERR_IO_PENDING; 693 return frame.release();
680 } 694 }
681 695
682 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { 696 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) {
697 DCHECK_NE(0u, stream_id);
683 // TODO(mbelshe): We should send a RST_STREAM control frame here 698 // TODO(mbelshe): We should send a RST_STREAM control frame here
684 // so that the server can cancel a large send. 699 // so that the server can cancel a large send.
685 700
686 DeleteStream(stream_id, status); 701 DeleteStream(stream_id, status);
687 } 702 }
688 703
704 void SpdySession::CloseCreatedStream(SpdyStream* stream, int status) {
705 DCHECK_EQ(0u, stream->stream_id());
706 created_streams_.erase(scoped_refptr<SpdyStream>(stream));
707 }
708
689 void SpdySession::ResetStream(SpdyStreamId stream_id, 709 void SpdySession::ResetStream(SpdyStreamId stream_id,
690 SpdyStatusCodes status, 710 SpdyStatusCodes status,
691 const std::string& description) { 711 const std::string& description) {
692 net_log().AddEvent( 712 net_log().AddEvent(
693 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, 713 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM,
694 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); 714 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description));
695 715
696 DCHECK(buffered_spdy_framer_.get()); 716 DCHECK(buffered_spdy_framer_.get());
697 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( 717 scoped_ptr<SpdyRstStreamControlFrame> rst_frame(
698 buffered_spdy_framer_->CreateRstStream(stream_id, status)); 718 buffered_spdy_framer_->CreateRstStream(stream_id, status));
699 719
700 // Default to lowest priority unless we know otherwise. 720 // Default to lowest priority unless we know otherwise.
701 RequestPriority priority = net::IDLE; 721 RequestPriority priority = net::IDLE;
702 if(IsStreamActive(stream_id)) { 722 if(IsStreamActive(stream_id)) {
703 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 723 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
704 priority = stream->priority(); 724 priority = stream->priority();
705 } 725 }
706 QueueFrame(rst_frame.get(), priority, NULL); 726 QueueFrame(rst_frame.release(), priority);
707 RecordProtocolErrorHistogram( 727 RecordProtocolErrorHistogram(
708 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); 728 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID));
709 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); 729 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR);
710 } 730 }
711 731
712 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { 732 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const {
713 return ContainsKey(active_streams_, stream_id); 733 return ContainsKey(active_streams_, stream_id);
714 } 734 }
715 735
716 LoadState SpdySession::GetLoadState() const { 736 LoadState SpdySession::GetLoadState() const {
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 // closed, just return. 904 // closed, just return.
885 if (state_ < CONNECTED || state_ == CLOSED) 905 if (state_ < CONNECTED || state_ == CLOSED)
886 return; 906 return;
887 907
888 if (write_pending_) // Another write is in progress still. 908 if (write_pending_) // Another write is in progress still.
889 return; 909 return;
890 910
891 // Loop sending frames until we've sent everything or until the write 911 // Loop sending frames until we've sent everything or until the write
892 // returns error (or ERR_IO_PENDING). 912 // returns error (or ERR_IO_PENDING).
893 DCHECK(buffered_spdy_framer_.get()); 913 DCHECK(buffered_spdy_framer_.get());
894 while (in_flight_write_.buffer() || !queue_.empty()) { 914 while (in_flight_write_.buffer() || !write_queue_.empty()) {
895 if (!in_flight_write_.buffer()) { 915 if (!in_flight_write_.buffer()) {
896 // Grab the next SpdyFrame to send. 916 // Grab the next SpdyBuffer to send.
897 SpdyIOBuffer next_buffer = queue_.top(); 917 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top());
898 queue_.pop(); 918 scoped_ptr<SpdyIOBuffer> buffer(producer->ProduceNextBuffer(this));
919 stream_producers_.erase(producer.get());
920 write_queue_.pop();
921 // It is possible that a stream had data to write, but a
922 // WINDOW_UPDATE frame has been received which made that
923 // stream no longer writable.
924 // TODO(rch): consider handling that case by removing the
925 // stream from the writable queue?
926 if (buffer == NULL)
927 continue;
899 928
900 // We've deferred compression until just before we write it to the socket, 929 in_flight_write_ = *buffer;
901 // which is now. At this time, we don't compress our data frames.
902 SpdyFrame uncompressed_frame(next_buffer.buffer()->data(), false);
903 size_t size;
904 if (buffered_spdy_framer_->IsCompressible(uncompressed_frame)) {
905 DCHECK(uncompressed_frame.is_control_frame());
906 const SpdyControlFrame* uncompressed_control_frame =
907 reinterpret_cast<const SpdyControlFrame*>(&uncompressed_frame);
908 scoped_ptr<SpdyFrame> compressed_frame(
909 buffered_spdy_framer_->CompressControlFrame(
910 *uncompressed_control_frame));
911 if (!compressed_frame.get()) {
912 RecordProtocolErrorHistogram(
913 PROTOCOL_ERROR_SPDY_COMPRESSION_FAILURE);
914 CloseSessionOnError(
915 net::ERR_SPDY_PROTOCOL_ERROR, true, "SPDY Compression failure.");
916 return;
917 }
918
919 size = compressed_frame->length() + SpdyFrame::kHeaderSize;
920
921 DCHECK_GT(size, 0u);
922
923 if (uncompressed_control_frame->type() == SYN_STREAM) {
924 int uncompressed_size = uncompressed_control_frame->length();
925 int compressed_size = compressed_frame->length();
926 // Make sure we avoid early decimal truncation.
927 int compression_pct = 100 - (100* compressed_size)/uncompressed_size;
928 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage",
929 compression_pct);
930 }
931
932 // TODO(mbelshe): We have too much copying of data here.
933 IOBufferWithSize* buffer = new IOBufferWithSize(size);
934 memcpy(buffer->data(), compressed_frame->data(), size);
935
936 // Attempt to send the frame.
937 in_flight_write_ = SpdyIOBuffer(buffer, size, HIGHEST,
938 next_buffer.stream());
939 } else {
940 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize;
941 in_flight_write_ = next_buffer;
942 }
943 } else { 930 } else {
944 DCHECK(in_flight_write_.buffer()->BytesRemaining()); 931 DCHECK(in_flight_write_.buffer()->BytesRemaining());
945 } 932 }
946 933
947 write_pending_ = true; 934 write_pending_ = true;
948 int rv = connection_->socket()->Write( 935 int rv = connection_->socket()->Write(
949 in_flight_write_.buffer(), 936 in_flight_write_.buffer(),
950 in_flight_write_.buffer()->BytesRemaining(), 937 in_flight_write_.buffer()->BytesRemaining(),
951 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); 938 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this)));
952 if (rv == net::ERR_IO_PENDING) 939 if (rv == net::ERR_IO_PENDING)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 while (!active_streams_.empty()) { 973 while (!active_streams_.empty()) {
987 ActiveStreamMap::iterator it = active_streams_.begin(); 974 ActiveStreamMap::iterator it = active_streams_.begin();
988 const scoped_refptr<SpdyStream>& stream = it->second; 975 const scoped_refptr<SpdyStream>& stream = it->second;
989 DCHECK(stream); 976 DCHECK(stream);
990 std::string description = base::StringPrintf( 977 std::string description = base::StringPrintf(
991 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); 978 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path();
992 stream->LogStreamError(status, description); 979 stream->LogStreamError(status, description);
993 DeleteStream(stream->stream_id(), status); 980 DeleteStream(stream->stream_id(), status);
994 } 981 }
995 982
983 while (!created_streams_.empty()) {
984 CreatedStreamSet::iterator it = created_streams_.begin();
985 const scoped_refptr<SpdyStream>& stream = *it;
986 std::string description = base::StringPrintf(
987 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path();
988 stream->LogStreamError(status, description);
989 stream->OnClose(status);
ramant (doing other things) 2012/06/26 23:30:25 nit: consider sharing of code between lines 976-97
Ryan Hamilton 2012/06/27 16:58:28 Done.
990 created_streams_.erase(it);
991 }
992
996 // We also need to drain the queue. 993 // We also need to drain the queue.
997 while (queue_.size()) 994 while (!write_queue_.empty()) {
998 queue_.pop(); 995 SpdyIOBufferProducer* producer = write_queue_.top();
996 stream_producers_.erase(producer);
997 delete producer;
998 write_queue_.pop();
999 }
999 } 1000 }
1000 1001
1001 int SpdySession::GetNewStreamId() { 1002 int SpdySession::GetNewStreamId() {
1002 int id = stream_hi_water_mark_; 1003 int id = stream_hi_water_mark_;
1003 stream_hi_water_mark_ += 2; 1004 stream_hi_water_mark_ += 2;
1004 if (stream_hi_water_mark_ > 0x7fff) 1005 if (stream_hi_water_mark_ > 0x7fff)
1005 stream_hi_water_mark_ = 1; 1006 stream_hi_water_mark_ = 1;
1006 return id; 1007 return id;
1007 } 1008 }
1008 1009
1009 void SpdySession::QueueFrame(SpdyFrame* frame,
1010 RequestPriority priority,
1011 SpdyStream* stream) {
1012 int length = SpdyFrame::kHeaderSize + frame->length();
1013 IOBuffer* buffer = new IOBuffer(length);
1014 memcpy(buffer->data(), frame->data(), length);
1015 queue_.push(SpdyIOBuffer(buffer, length, priority, stream));
1016
1017 WriteSocketLater();
1018 }
1019
1020 void SpdySession::CloseSessionOnError(net::Error err, 1010 void SpdySession::CloseSessionOnError(net::Error err,
1021 bool remove_from_pool, 1011 bool remove_from_pool,
1022 const std::string& description) { 1012 const std::string& description) {
1023 // Closing all streams can have a side-effect of dropping the last reference 1013 // Closing all streams can have a side-effect of dropping the last reference
1024 // to |this|. Hold a reference through this function. 1014 // to |this|. Hold a reference through this function.
1025 scoped_refptr<SpdySession> self(this); 1015 scoped_refptr<SpdySession> self(this);
1026 1016
1027 DCHECK_LT(err, OK); 1017 DCHECK_LT(err, OK);
1028 net_log_.AddEvent( 1018 net_log_.AddEvent(
1029 NetLog::TYPE_SPDY_SESSION_CLOSE, 1019 NetLog::TYPE_SPDY_SESSION_CLOSE,
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1099 return connection_->socket()->GetPeerAddress(address); 1089 return connection_->socket()->GetPeerAddress(address);
1100 } 1090 }
1101 1091
1102 int SpdySession::GetLocalAddress(IPEndPoint* address) const { 1092 int SpdySession::GetLocalAddress(IPEndPoint* address) const {
1103 if (!connection_->socket()) 1093 if (!connection_->socket())
1104 return ERR_SOCKET_NOT_CONNECTED; 1094 return ERR_SOCKET_NOT_CONNECTED;
1105 1095
1106 return connection_->socket()->GetLocalAddress(address); 1096 return connection_->socket()->GetLocalAddress(address);
1107 } 1097 }
1108 1098
1099 class SimpleSpdyIOBufferProducer : public SpdySession::SpdyIOBufferProducer {
1100 public:
1101 SimpleSpdyIOBufferProducer(SpdyFrame* frame,
1102 RequestPriority priority)
1103 : frame_(frame),
ramant (doing other things) 2012/06/26 23:30:25 nit: indent "RequestPriority ..."
Ryan Hamilton 2012/06/27 16:58:28 Done.
1104 priority_(priority) {
1105 }
1106
1107 virtual RequestPriority GetPriority() const OVERRIDE {
1108 return priority_;
1109 }
1110
1111 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) {
1112 return SpdySession::SpdyIOBufferProducer::CreateIOBuffer(
1113 frame_, priority_, NULL);
1114 }
1115
1116 private:
1117 SpdyFrame* frame_;
1118 RequestPriority priority_;
1119 };
1120
1121 void SpdySession::QueueFrame(SpdyFrame* frame,
1122 RequestPriority priority) {
1123 SimpleSpdyIOBufferProducer* producer
1124 = new SimpleSpdyIOBufferProducer(frame, priority);
1125 write_queue_.push(producer);
ramant (doing other things) 2012/06/26 23:30:25 nit: " = " should be in the previous line.
Ryan Hamilton 2012/06/27 16:58:28 Done.
Ryan Hamilton 2012/06/27 16:58:28 Done.
1126 WriteSocketLater();
1127 }
1128
1109 void SpdySession::ActivateStream(SpdyStream* stream) { 1129 void SpdySession::ActivateStream(SpdyStream* stream) {
1130 if (stream->stream_id() == 0) {
1131 stream->set_stream_id(GetNewStreamId());
1132 created_streams_.erase(scoped_refptr<SpdyStream>(stream));
1133 }
1110 const SpdyStreamId id = stream->stream_id(); 1134 const SpdyStreamId id = stream->stream_id();
1111 DCHECK(!IsStreamActive(id)); 1135 DCHECK(!IsStreamActive(id));
1112 1136
1113 active_streams_[id] = stream; 1137 active_streams_[id] = stream;
1114 } 1138 }
1115 1139
1116 void SpdySession::DeleteStream(SpdyStreamId id, int status) { 1140 void SpdySession::DeleteStream(SpdyStreamId id, int status) {
1117 // For push streams, if they are being deleted normally, we leave 1141 // For push streams, if they are being deleted normally, we leave
1118 // the stream in the unclaimed_pushed_streams_ list. However, if 1142 // the stream in the unclaimed_pushed_streams_ list. However, if
1119 // the stream is errored out, clean it up entirely. 1143 // the stream is errored out, clean it up entirely.
1120 if (status != OK) { 1144 if (status != OK) {
1121 PushedStreamMap::iterator it; 1145 PushedStreamMap::iterator it;
1122 for (it = unclaimed_pushed_streams_.begin(); 1146 for (it = unclaimed_pushed_streams_.begin();
1123 it != unclaimed_pushed_streams_.end(); ++it) { 1147 it != unclaimed_pushed_streams_.end(); ++it) {
1124 scoped_refptr<SpdyStream> curr = it->second; 1148 scoped_refptr<SpdyStream> curr = it->second;
1125 if (id == curr->stream_id()) { 1149 if (id == curr->stream_id()) {
1126 unclaimed_pushed_streams_.erase(it); 1150 unclaimed_pushed_streams_.erase(it);
1127 break; 1151 break;
1128 } 1152 }
1129 } 1153 }
1130 } 1154 }
1131 1155
1132 // The stream might have been deleted. 1156 // The stream might have been deleted.
1133 ActiveStreamMap::iterator it2 = active_streams_.find(id); 1157 ActiveStreamMap::iterator it2 = active_streams_.find(id);
1134 if (it2 == active_streams_.end()) 1158 if (it2 == active_streams_.end())
1135 return; 1159 return;
1136 1160
1161 // Possibly remove from the write queue.
1162 WriteQueue old = write_queue_;
1163 write_queue_ = WriteQueue();
1164 while (!old.empty()) {
1165 SpdyIOBufferProducer* producer = old.top();
1166 StreamProducerMap::iterator it = stream_producers_.find(producer);
1167 if (it == stream_producers_.end() || it->second->stream_id() != id)
1168 write_queue_.push(producer);
1169 else
1170 delete producer;
1171 old.pop();
1172 }
1173
1137 // If this is an active stream, call the callback. 1174 // If this is an active stream, call the callback.
1138 const scoped_refptr<SpdyStream> stream(it2->second); 1175 const scoped_refptr<SpdyStream> stream(it2->second);
1139 active_streams_.erase(it2); 1176 active_streams_.erase(it2);
1140 if (stream) 1177 if (stream)
1141 stream->OnClose(status); 1178 stream->OnClose(status);
1142 ProcessPendingCreateStreams(); 1179 ProcessPendingCreateStreams();
1143 } 1180 }
1144 1181
1145 void SpdySession::RemoveFromPool() { 1182 void SpdySession::RemoveFromPool() {
1146 if (spdy_session_pool_) { 1183 if (spdy_session_pool_) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 value); 1279 value);
1243 received_settings_ = true; 1280 received_settings_ = true;
1244 1281
1245 // Log the setting. 1282 // Log the setting.
1246 net_log_.AddEvent( 1283 net_log_.AddEvent(
1247 NetLog::TYPE_SPDY_SESSION_RECV_SETTING, 1284 NetLog::TYPE_SPDY_SESSION_RECV_SETTING,
1248 base::Bind(&NetLogSpdySettingCallback, 1285 base::Bind(&NetLogSpdySettingCallback,
1249 id, static_cast<SpdySettingsFlags>(flags), value)); 1286 id, static_cast<SpdySettingsFlags>(flags), value));
1250 } 1287 }
1251 1288
1289 void SpdySession::OnControlFrameCompressed(
1290 const SpdyControlFrame& uncompressed_frame,
1291 const SpdyControlFrame& compressed_frame) {
1292 if (uncompressed_frame.type() == SYN_STREAM) {
1293 int uncompressed_size = uncompressed_frame.length();
1294 int compressed_size = compressed_frame.length();
1295 // Make sure we avoid early decimal truncation.
1296 int compression_pct = 100 - (100* compressed_size)/uncompressed_size;
1297 UMA_HISTOGRAM_PERCENTAGE("Net.SpdySynStreamCompressionPercentage",
1298 compression_pct);
1299 }
1300 }
1301
1302
1252 bool SpdySession::Respond(const SpdyHeaderBlock& headers, 1303 bool SpdySession::Respond(const SpdyHeaderBlock& headers,
1253 const scoped_refptr<SpdyStream> stream) { 1304 const scoped_refptr<SpdyStream> stream) {
1254 int rv = OK; 1305 int rv = OK;
1255 rv = stream->OnResponseReceived(headers); 1306 rv = stream->OnResponseReceived(headers);
1256 if (rv < 0) { 1307 if (rv < 0) {
1257 DCHECK_NE(rv, ERR_IO_PENDING); 1308 DCHECK_NE(rv, ERR_IO_PENDING);
1258 const SpdyStreamId stream_id = stream->stream_id(); 1309 const SpdyStreamId stream_id = stream->stream_id();
1259 DeleteStream(stream_id, rv); 1310 DeleteStream(stream_id, rv);
1260 return false; 1311 return false;
1261 } 1312 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1342 } 1393 }
1343 1394
1344 // There should not be an existing pushed stream with the same path. 1395 // There should not be an existing pushed stream with the same path.
1345 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); 1396 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url);
1346 if (it != unclaimed_pushed_streams_.end()) { 1397 if (it != unclaimed_pushed_streams_.end()) {
1347 ResetStream(stream_id, PROTOCOL_ERROR, 1398 ResetStream(stream_id, PROTOCOL_ERROR,
1348 "Received duplicate pushed stream with url: " + url); 1399 "Received duplicate pushed stream with url: " + url);
1349 return; 1400 return;
1350 } 1401 }
1351 1402
1352 scoped_refptr<SpdyStream> stream( 1403 scoped_refptr<SpdyStream> stream(new SpdyStream(this, true, net_log_));
1353 new SpdyStream(this, stream_id, true, net_log_)); 1404 stream->set_stream_id(stream_id);
1354 1405
1355 stream->set_path(gurl.PathForRequest()); 1406 stream->set_path(gurl.PathForRequest());
1356 stream->set_send_window_size(initial_send_window_size_); 1407 stream->set_send_window_size(initial_send_window_size_);
1357 stream->set_recv_window_size(initial_recv_window_size_); 1408 stream->set_recv_window_size(initial_recv_window_size_);
1358 1409
1359 unclaimed_pushed_streams_[url] = stream; 1410 unclaimed_pushed_streams_[url] = stream;
1360 1411
1361 ActivateStream(stream); 1412 ActivateStream(stream);
1362 stream->set_response_received(); 1413 stream->set_response_received();
1363 1414
1364 // Parse the headers. 1415 // Parse the headers.
1365 if (!Respond(*headers, stream)) 1416 if (!Respond(*headers, stream))
1366 return; 1417 return;
1367 1418
1368 base::StatsCounter push_requests("spdy.pushed_streams"); 1419 base::StatsCounter push_requests("spdy.pushed_streams");
1369 push_requests.Increment(); 1420 push_requests.Increment();
1370 } 1421 }
1371 1422
1372 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame, 1423 void SpdySession::OnSynReply(const SpdySynReplyControlFrame& frame,
1373 const linked_ptr<SpdyHeaderBlock>& headers) { 1424 const linked_ptr<SpdyHeaderBlock>& headers) {
1374 SpdyStreamId stream_id = frame.stream_id(); 1425 SpdyStreamId stream_id = frame.stream_id();
1375
1376 if (net_log().IsLoggingAllEvents()) { 1426 if (net_log().IsLoggingAllEvents()) {
1377 net_log().AddEvent( 1427 net_log().AddEvent(
1378 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, 1428 NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
1379 base::Bind(&NetLogSpdySynCallback, 1429 base::Bind(&NetLogSpdySynCallback,
1380 headers.get(), static_cast<SpdyControlFlags>(frame.flags()), 1430 headers.get(), static_cast<SpdyControlFlags>(frame.flags()),
1381 stream_id, 0)); 1431 stream_id, 0));
1382 } 1432 }
1383 1433
1384 if (!IsStreamActive(stream_id)) { 1434 if (!IsStreamActive(stream_id)) {
1385 // NOTE: it may just be that the stream was cancelled. 1435 // NOTE: it may just be that the stream was cancelled.
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 CHECK_EQ(stream->stream_id(), stream_id); 1599 CHECK_EQ(stream->stream_id(), stream_id);
1550 1600
1551 net_log_.AddEvent( 1601 net_log_.AddEvent(
1552 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, 1602 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE,
1553 base::Bind(&NetLogSpdyWindowUpdateCallback, 1603 base::Bind(&NetLogSpdyWindowUpdateCallback,
1554 stream_id, delta_window_size)); 1604 stream_id, delta_window_size));
1555 1605
1556 DCHECK(buffered_spdy_framer_.get()); 1606 DCHECK(buffered_spdy_framer_.get());
1557 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( 1607 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame(
1558 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); 1608 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size));
1559 QueueFrame(window_update_frame.get(), stream->priority(), NULL); 1609 QueueFrame(window_update_frame.release(), stream->priority());
1560 } 1610 }
1561 1611
1562 // Given a cwnd that we would have sent to the server, modify it based on the 1612 // Given a cwnd that we would have sent to the server, modify it based on the
1563 // field trial policy. 1613 // field trial policy.
1564 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { 1614 uint32 ApplyCwndFieldTrialPolicy(int cwnd) {
1565 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); 1615 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd");
1566 if (!trial) { 1616 if (!trial) {
1567 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; 1617 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList";
1568 return cwnd; 1618 return cwnd;
1569 } 1619 }
(...skipping 19 matching lines...) Expand all
1589 // Create a new settings frame notifying the sever of our 1639 // Create a new settings frame notifying the sever of our
1590 // max_concurrent_streams_ and initial window size. 1640 // max_concurrent_streams_ and initial window size.
1591 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = 1641 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] =
1592 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialMaxConcurrentStreams); 1642 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kInitialMaxConcurrentStreams);
1593 if (GetProtocolVersion() > 2 && 1643 if (GetProtocolVersion() > 2 &&
1594 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { 1644 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) {
1595 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = 1645 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] =
1596 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_); 1646 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_);
1597 } 1647 }
1598 sent_settings_ = true; 1648 sent_settings_ = true;
1599 SendSettings(settings_map); 1649 SendSettings(settings_map);
ramant (doing other things) 2012/06/26 23:30:25 nit: delete "sent_settings_ = true;"?
Ryan Hamilton 2012/06/27 16:58:28 Done.
1600 } 1650 }
1601 1651
1602 // Next notify the server about the settings they have previously 1652 // Next notify the server about the settings they have previously
1603 // told us to use when communicating with them. 1653 // told us to use when communicating with them.
1604 const SettingsMap& settings_map = 1654 const SettingsMap& settings_map =
1605 http_server_properties_->GetSpdySettings(host_port_pair()); 1655 http_server_properties_->GetSpdySettings(host_port_pair());
1606 if (settings_map.empty()) 1656 if (settings_map.empty())
1607 return; 1657 return;
1608 1658
1609 // Record Histogram Data and Apply the SpdyCwnd FieldTrial if applicable. 1659 // Record Histogram Data and Apply the SpdyCwnd FieldTrial if applicable.
(...skipping 12 matching lines...) Expand all
1622 const SettingsMap& settings_map_new = 1672 const SettingsMap& settings_map_new =
1623 http_server_properties_->GetSpdySettings(host_port_pair()); 1673 http_server_properties_->GetSpdySettings(host_port_pair());
1624 for (SettingsMap::const_iterator i = settings_map_new.begin(), 1674 for (SettingsMap::const_iterator i = settings_map_new.begin(),
1625 end = settings_map_new.end(); i != end; ++i) { 1675 end = settings_map_new.end(); i != end; ++i) {
1626 const SpdySettingsIds new_id = i->first; 1676 const SpdySettingsIds new_id = i->first;
1627 const uint32 new_val = i->second.second; 1677 const uint32 new_val = i->second.second;
1628 HandleSetting(new_id, new_val); 1678 HandleSetting(new_id, new_val);
1629 } 1679 }
1630 1680
1631 sent_settings_ = true; 1681 sent_settings_ = true;
1632 SendSettings(settings_map_new); 1682 SendSettings(settings_map_new);
ramant (doing other things) 2012/06/26 23:30:25 nit: delete "sent_settings_ = true;"?
Ryan Hamilton 2012/06/27 16:58:28 Done.
1633 } 1683 }
1634 1684
1635 1685
1636 void SpdySession::SendSettings(const SettingsMap& settings) { 1686 void SpdySession::SendSettings(const SettingsMap& settings) {
1637 net_log_.AddEvent( 1687 net_log_.AddEvent(
1638 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, 1688 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS,
1639 base::Bind(&NetLogSpdySettingsCallback, &settings)); 1689 base::Bind(&NetLogSpdySettingsCallback, &settings));
1640 1690
1641 // Create the SETTINGS frame and send it. 1691 // Create the SETTINGS frame and send it.
1642 DCHECK(buffered_spdy_framer_.get()); 1692 DCHECK(buffered_spdy_framer_.get());
1643 scoped_ptr<SpdySettingsControlFrame> settings_frame( 1693 scoped_ptr<SpdySettingsControlFrame> settings_frame(
1644 buffered_spdy_framer_->CreateSettings(settings)); 1694 buffered_spdy_framer_->CreateSettings(settings));
1645 QueueFrame(settings_frame.get(), HIGHEST, NULL); 1695 sent_settings_ = true;
1696 QueueFrame(settings_frame.release(), HIGHEST);
1646 } 1697 }
1647 1698
1648 void SpdySession::HandleSetting(uint32 id, uint32 value) { 1699 void SpdySession::HandleSetting(uint32 id, uint32 value) {
1649 switch (id) { 1700 switch (id) {
1650 case SETTINGS_MAX_CONCURRENT_STREAMS: 1701 case SETTINGS_MAX_CONCURRENT_STREAMS:
1651 max_concurrent_streams_ = std::min(static_cast<size_t>(value), 1702 max_concurrent_streams_ = std::min(static_cast<size_t>(value),
1652 g_max_concurrent_stream_limit); 1703 g_max_concurrent_stream_limit);
1653 ProcessPendingCreateStreams(); 1704 ProcessPendingCreateStreams();
1654 break; 1705 break;
1655 case SETTINGS_INITIAL_WINDOW_SIZE: 1706 case SETTINGS_INITIAL_WINDOW_SIZE:
(...skipping 14 matching lines...) Expand all
1670 } 1721 }
1671 } 1722 }
1672 1723
1673 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { 1724 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) {
1674 ActiveStreamMap::iterator it; 1725 ActiveStreamMap::iterator it;
1675 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { 1726 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) {
1676 const scoped_refptr<SpdyStream>& stream = it->second; 1727 const scoped_refptr<SpdyStream>& stream = it->second;
1677 DCHECK(stream); 1728 DCHECK(stream);
1678 stream->AdjustSendWindowSize(delta_window_size); 1729 stream->AdjustSendWindowSize(delta_window_size);
1679 } 1730 }
1731
1732 CreatedStreamSet::iterator i;
1733 for (i = created_streams_.begin(); i != created_streams_.end(); i++) {
1734 const scoped_refptr<SpdyStream>& stream = *i;
1735 stream->AdjustSendWindowSize(delta_window_size);
1736 }
1680 } 1737 }
1681 1738
1682 void SpdySession::SendPrefacePingIfNoneInFlight() { 1739 void SpdySession::SendPrefacePingIfNoneInFlight() {
1683 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) 1740 if (pings_in_flight_ || !g_enable_ping_based_connection_checking)
1684 return; 1741 return;
1685 1742
1686 base::TimeTicks now = base::TimeTicks::Now(); 1743 base::TimeTicks now = base::TimeTicks::Now();
1687 // If there is no activity in the session, then send a preface-PING. 1744 // If there is no activity in the session, then send a preface-PING.
1688 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) 1745 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_)
1689 SendPrefacePing(); 1746 SendPrefacePing();
1690 } 1747 }
1691 1748
1692 void SpdySession::SendPrefacePing() { 1749 void SpdySession::SendPrefacePing() {
1693 WritePingFrame(next_ping_id_); 1750 WritePingFrame(next_ping_id_);
1694 } 1751 }
1695 1752
1696 void SpdySession::WritePingFrame(uint32 unique_id) { 1753 void SpdySession::WritePingFrame(uint32 unique_id) {
1697 DCHECK(buffered_spdy_framer_.get()); 1754 DCHECK(buffered_spdy_framer_.get());
1698 scoped_ptr<SpdyPingControlFrame> ping_frame( 1755 scoped_ptr<SpdyPingControlFrame> ping_frame(
1699 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); 1756 buffered_spdy_framer_->CreatePingFrame(next_ping_id_));
1700 QueueFrame(ping_frame.get(), HIGHEST, NULL); 1757 QueueFrame(ping_frame.release(), HIGHEST);
1701 1758
1702 if (net_log().IsLoggingAllEvents()) { 1759 if (net_log().IsLoggingAllEvents()) {
1703 net_log().AddEvent( 1760 net_log().AddEvent(
1704 NetLog::TYPE_SPDY_SESSION_PING, 1761 NetLog::TYPE_SPDY_SESSION_PING,
1705 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); 1762 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent"));
1706 } 1763 }
1707 if (unique_id % 2 != 0) { 1764 if (unique_id % 2 != 0) {
1708 next_ping_id_ += 2; 1765 next_ping_id_ += 2;
1709 ++pings_in_flight_; 1766 ++pings_in_flight_;
1710 PlanToCheckPingStatus(); 1767 PlanToCheckPingStatus();
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 SSLClientSocket* SpdySession::GetSSLClientSocket() const { 1910 SSLClientSocket* SpdySession::GetSSLClientSocket() const {
1854 if (!is_secure_) 1911 if (!is_secure_)
1855 return NULL; 1912 return NULL;
1856 SSLClientSocket* ssl_socket = 1913 SSLClientSocket* ssl_socket =
1857 reinterpret_cast<SSLClientSocket*>(connection_->socket()); 1914 reinterpret_cast<SSLClientSocket*>(connection_->socket());
1858 DCHECK(ssl_socket); 1915 DCHECK(ssl_socket);
1859 return ssl_socket; 1916 return ssl_socket;
1860 } 1917 }
1861 1918
1862 } // namespace net 1919 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698