OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB | 187 size_t g_default_initial_rcv_window_size = 10 * 1024 * 1024; // 10MB |
188 bool g_enable_ping_based_connection_checking = true; | 188 bool g_enable_ping_based_connection_checking = true; |
189 | 189 |
190 typedef base::TimeTicks (*ExternalTimeFunc)(void); | 190 typedef base::TimeTicks (*ExternalTimeFunc)(void); |
191 | 191 |
192 static ExternalTimeFunc g_time_func = base::TimeTicks::Now; | 192 static ExternalTimeFunc g_time_func = base::TimeTicks::Now; |
193 | 193 |
194 } // namespace | 194 } // namespace |
195 | 195 |
196 // static | 196 // static |
| 197 void SpdySession::SpdyIOBufferProducer::ActivateStream( |
| 198 SpdySession* spdy_session, |
| 199 SpdyStream* spdy_stream) { |
| 200 spdy_session->ActivateStream(spdy_stream); |
| 201 } |
| 202 |
| 203 // static |
| 204 SpdyIOBuffer* SpdySession::SpdyIOBufferProducer::CreateIOBuffer( |
| 205 SpdyFrame* frame, |
| 206 RequestPriority priority, |
| 207 SpdyStream* stream) { |
| 208 size_t size = frame->length() + SpdyFrame::kHeaderSize; |
| 209 DCHECK_GT(size, 0u); |
| 210 |
| 211 // TODO(mbelshe): We have too much copying of data here. |
| 212 IOBufferWithSize* buffer = new IOBufferWithSize(size); |
| 213 memcpy(buffer->data(), frame->data(), size); |
| 214 |
| 215 return new SpdyIOBuffer(buffer, size, priority, stream); |
| 216 } |
| 217 |
| 218 // static |
197 void SpdySession::set_default_protocol(NextProto default_protocol) { | 219 void SpdySession::set_default_protocol(NextProto default_protocol) { |
198 g_default_protocol = default_protocol; | 220 g_default_protocol = default_protocol; |
199 } | 221 } |
200 | 222 |
201 // static | 223 // static |
202 void SpdySession::set_max_concurrent_streams(size_t value) { | 224 void SpdySession::set_max_concurrent_streams(size_t value) { |
203 g_max_concurrent_stream_limit = value; | 225 g_max_concurrent_stream_limit = value; |
204 } | 226 } |
205 | 227 |
206 // static | 228 // static |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 SSLInfo ssl_info; | 404 SSLInfo ssl_info; |
383 bool was_npn_negotiated; | 405 bool was_npn_negotiated; |
384 NextProto protocol_negotiated = kProtoUnknown; | 406 NextProto protocol_negotiated = kProtoUnknown; |
385 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) | 407 if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated)) |
386 return true; // This is not a secure session, so all domains are okay. | 408 return true; // This is not a secure session, so all domains are okay. |
387 | 409 |
388 return !ssl_info.channel_id_sent && !ssl_info.client_cert_sent && | 410 return !ssl_info.channel_id_sent && !ssl_info.client_cert_sent && |
389 ssl_info.cert->VerifyNameMatch(domain); | 411 ssl_info.cert->VerifyNameMatch(domain); |
390 } | 412 } |
391 | 413 |
| 414 void SpdySession::SetStreamHasWriteAvailable(SpdyStream* stream, |
| 415 SpdyIOBufferProducer* producer) { |
| 416 write_queue_.push(producer); |
| 417 stream_producers_[producer] = stream; |
| 418 WriteSocketLater(); |
| 419 } |
| 420 |
392 int SpdySession::GetPushStream( | 421 int SpdySession::GetPushStream( |
393 const GURL& url, | 422 const GURL& url, |
394 scoped_refptr<SpdyStream>* stream, | 423 scoped_refptr<SpdyStream>* stream, |
395 const BoundNetLog& stream_net_log) { | 424 const BoundNetLog& stream_net_log) { |
396 CHECK_NE(state_, CLOSED); | 425 CHECK_NE(state_, CLOSED); |
397 | 426 |
398 *stream = NULL; | 427 *stream = NULL; |
399 | 428 |
400 // Don't allow access to secure push streams over an unauthenticated, but | 429 // Don't allow access to secure push streams over an unauthenticated, but |
401 // encrypted SSL socket. | 430 // encrypted SSL socket. |
(...skipping 18 matching lines...) Expand all Loading... |
420 return 0; | 449 return 0; |
421 } | 450 } |
422 | 451 |
423 int SpdySession::CreateStream( | 452 int SpdySession::CreateStream( |
424 const GURL& url, | 453 const GURL& url, |
425 RequestPriority priority, | 454 RequestPriority priority, |
426 scoped_refptr<SpdyStream>* spdy_stream, | 455 scoped_refptr<SpdyStream>* spdy_stream, |
427 const BoundNetLog& stream_net_log, | 456 const BoundNetLog& stream_net_log, |
428 const CompletionCallback& callback) { | 457 const CompletionCallback& callback) { |
429 if (!max_concurrent_streams_ || | 458 if (!max_concurrent_streams_ || |
430 active_streams_.size() < max_concurrent_streams_) { | 459 (active_streams_.size() + created_streams_.size() < |
| 460 max_concurrent_streams_)) { |
431 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log); | 461 return CreateStreamImpl(url, priority, spdy_stream, stream_net_log); |
432 } | 462 } |
433 | 463 |
434 stalled_streams_++; | 464 stalled_streams_++; |
435 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS); | 465 net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS); |
436 create_stream_queues_[priority].push( | 466 create_stream_queues_[priority].push( |
437 PendingCreateStream(url, priority, spdy_stream, | 467 PendingCreateStream(url, priority, spdy_stream, |
438 stream_net_log, callback)); | 468 stream_net_log, callback)); |
439 return ERR_IO_PENDING; | 469 return ERR_IO_PENDING; |
440 } | 470 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 CloseSessionOnError( | 540 CloseSessionOnError( |
511 static_cast<net::Error>(certificate_error_code_), | 541 static_cast<net::Error>(certificate_error_code_), |
512 true, | 542 true, |
513 "Tried to create SPDY stream for secure content over an " | 543 "Tried to create SPDY stream for secure content over an " |
514 "unauthenticated session."); | 544 "unauthenticated session."); |
515 return ERR_SPDY_PROTOCOL_ERROR; | 545 return ERR_SPDY_PROTOCOL_ERROR; |
516 } | 546 } |
517 | 547 |
518 const std::string& path = url.PathForRequest(); | 548 const std::string& path = url.PathForRequest(); |
519 | 549 |
520 const SpdyStreamId stream_id = GetNewStreamId(); | |
521 | |
522 *spdy_stream = new SpdyStream(this, | 550 *spdy_stream = new SpdyStream(this, |
523 stream_id, | |
524 false, | 551 false, |
525 stream_net_log); | 552 stream_net_log); |
526 const scoped_refptr<SpdyStream>& stream = *spdy_stream; | 553 const scoped_refptr<SpdyStream>& stream = *spdy_stream; |
527 | 554 |
528 stream->set_priority(priority); | 555 stream->set_priority(priority); |
529 stream->set_path(path); | 556 stream->set_path(path); |
530 stream->set_send_window_size(initial_send_window_size_); | 557 stream->set_send_window_size(initial_send_window_size_); |
531 stream->set_recv_window_size(initial_recv_window_size_); | 558 stream->set_recv_window_size(initial_recv_window_size_); |
532 ActivateStream(stream); | 559 created_streams_.insert(stream); |
533 | 560 |
534 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", | 561 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", |
535 static_cast<int>(priority), 0, 10, 11); | 562 static_cast<int>(priority), 0, 10, 11); |
536 | 563 |
537 // TODO(mbelshe): Optimize memory allocations | 564 // TODO(mbelshe): Optimize memory allocations |
538 | 565 |
539 DCHECK_EQ(active_streams_[stream_id].get(), stream.get()); | |
540 return OK; | 566 return OK; |
541 } | 567 } |
542 | 568 |
543 bool SpdySession::NeedsCredentials() const { | 569 bool SpdySession::NeedsCredentials() const { |
544 if (!is_secure_) | 570 if (!is_secure_) |
545 return false; | 571 return false; |
546 SSLClientSocket* ssl_socket = GetSSLClientSocket(); | 572 SSLClientSocket* ssl_socket = GetSSLClientSocket(); |
547 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) | 573 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) |
548 return false; | 574 return false; |
549 return ssl_socket->WasChannelIDSent(); | 575 return ssl_socket->WasChannelIDSent(); |
550 } | 576 } |
551 | 577 |
552 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { | 578 void SpdySession::AddPooledAlias(const HostPortProxyPair& alias) { |
553 pooled_aliases_.insert(alias); | 579 pooled_aliases_.insert(alias); |
554 } | 580 } |
555 | 581 |
556 int SpdySession::GetProtocolVersion() const { | 582 int SpdySession::GetProtocolVersion() const { |
557 DCHECK(buffered_spdy_framer_.get()); | 583 DCHECK(buffered_spdy_framer_.get()); |
558 return buffered_spdy_framer_->protocol_version(); | 584 return buffered_spdy_framer_->protocol_version(); |
559 } | 585 } |
560 | 586 |
561 int SpdySession::WriteSynStream( | 587 SpdySynStreamControlFrame* SpdySession::CreateSynStream( |
562 SpdyStreamId stream_id, | 588 SpdyStreamId stream_id, |
563 RequestPriority priority, | 589 RequestPriority priority, |
564 uint8 credential_slot, | 590 uint8 credential_slot, |
565 SpdyControlFlags flags, | 591 SpdyControlFlags flags, |
566 const SpdyHeaderBlock& headers) { | 592 const SpdyHeaderBlock& headers) { |
567 // Find our stream | 593 CHECK(IsStreamActive(stream_id)); |
568 if (!IsStreamActive(stream_id)) | |
569 return ERR_INVALID_SPDY_STREAM; | |
570 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; | 594 const scoped_refptr<SpdyStream>& stream = active_streams_[stream_id]; |
571 CHECK_EQ(stream->stream_id(), stream_id); | 595 CHECK_EQ(stream->stream_id(), stream_id); |
572 | 596 |
573 SendPrefacePingIfNoneInFlight(); | 597 SendPrefacePingIfNoneInFlight(); |
574 | 598 |
575 DCHECK(buffered_spdy_framer_.get()); | 599 DCHECK(buffered_spdy_framer_.get()); |
576 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 600 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
577 buffered_spdy_framer_->CreateSynStream( | 601 buffered_spdy_framer_->CreateSynStream( |
578 stream_id, 0, | 602 stream_id, 0, |
579 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), | 603 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()), |
580 credential_slot, flags, false, &headers)); | 604 credential_slot, flags, true, &headers)); |
581 // We enqueue all SYN_STREAM frames at the same priority to ensure | |
582 // that we do not send them out-of-order. | |
583 // http://crbug.com/111708 | |
584 QueueFrame(syn_frame.get(), HIGHEST, stream); | |
585 | 605 |
586 base::StatsCounter spdy_requests("spdy.requests"); | 606 base::StatsCounter spdy_requests("spdy.requests"); |
587 spdy_requests.Increment(); | 607 spdy_requests.Increment(); |
588 streams_initiated_count_++; | 608 streams_initiated_count_++; |
589 | 609 |
590 if (net_log().IsLoggingAllEvents()) { | 610 if (net_log().IsLoggingAllEvents()) { |
591 net_log().AddEvent( | 611 net_log().AddEvent( |
592 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, | 612 NetLog::TYPE_SPDY_SESSION_SYN_STREAM, |
593 base::Bind(&NetLogSpdySynCallback, &headers, | 613 base::Bind(&NetLogSpdySynCallback, &headers, |
594 (flags & CONTROL_FLAG_FIN) != 0, | 614 (flags & CONTROL_FLAG_FIN) != 0, |
595 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, | 615 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, |
596 stream_id, 0)); | 616 stream_id, 0)); |
597 } | 617 } |
598 | 618 |
599 return ERR_IO_PENDING; | 619 return syn_frame.release(); |
600 } | 620 } |
601 | 621 |
602 int SpdySession::WriteCredentialFrame(const std::string& origin, | 622 SpdyCredentialControlFrame* SpdySession::CreateCredentialFrame( |
603 SSLClientCertType type, | 623 const std::string& origin, |
604 const std::string& key, | 624 SSLClientCertType type, |
605 const std::string& cert, | 625 const std::string& key, |
606 RequestPriority priority) { | 626 const std::string& cert, |
| 627 RequestPriority priority) { |
607 DCHECK(is_secure_); | 628 DCHECK(is_secure_); |
608 unsigned char secret[32]; // 32 bytes from the spec | 629 unsigned char secret[32]; // 32 bytes from the spec |
609 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof", | 630 GetSSLClientSocket()->ExportKeyingMaterial("SPDY certificate proof", |
610 true, origin, | 631 true, origin, |
611 secret, arraysize(secret)); | 632 secret, arraysize(secret)); |
612 | 633 |
613 // Convert the key string into a vector<unit8> | 634 // Convert the key string into a vector<unit8> |
614 std::vector<uint8> key_data; | 635 std::vector<uint8> key_data; |
615 for (size_t i = 0; i < key.length(); i++) { | 636 for (size_t i = 0; i < key.length(); i++) { |
616 key_data.push_back(key[i]); | 637 key_data.push_back(key[i]); |
(...skipping 21 matching lines...) Expand all Loading... |
638 SpdyCredential credential; | 659 SpdyCredential credential; |
639 GURL origin_url(origin); | 660 GURL origin_url(origin); |
640 credential.slot = | 661 credential.slot = |
641 credential_state_.SetHasCredential(origin_url); | 662 credential_state_.SetHasCredential(origin_url); |
642 credential.certs.push_back(cert); | 663 credential.certs.push_back(cert); |
643 credential.proof.assign(proof.begin(), proof.end()); | 664 credential.proof.assign(proof.begin(), proof.end()); |
644 | 665 |
645 DCHECK(buffered_spdy_framer_.get()); | 666 DCHECK(buffered_spdy_framer_.get()); |
646 scoped_ptr<SpdyCredentialControlFrame> credential_frame( | 667 scoped_ptr<SpdyCredentialControlFrame> credential_frame( |
647 buffered_spdy_framer_->CreateCredentialFrame(credential)); | 668 buffered_spdy_framer_->CreateCredentialFrame(credential)); |
648 // We enqueue all SYN_STREAM frames at the same priority to ensure | |
649 // that we do not send them out-of-order, which means that we need | |
650 // to enqueue all CREDENTIAL frames at this priority to ensure that | |
651 // they are sent *before* the SYN_STREAM that references them. | |
652 // http://crbug.com/111708 | |
653 QueueFrame(credential_frame.get(), HIGHEST, NULL); | |
654 | 669 |
655 if (net_log().IsLoggingAllEvents()) { | 670 if (net_log().IsLoggingAllEvents()) { |
656 net_log().AddEvent( | 671 net_log().AddEvent( |
657 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, | 672 NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL, |
658 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); | 673 base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin)); |
659 } | 674 } |
660 return ERR_IO_PENDING; | 675 return credential_frame.release(); |
661 } | 676 } |
662 | 677 |
663 int SpdySession::WriteStreamData(SpdyStreamId stream_id, | 678 SpdyDataFrame* SpdySession::CreateDataFrame(SpdyStreamId stream_id, |
664 net::IOBuffer* data, int len, | 679 net::IOBuffer* data, int len, |
665 SpdyDataFlags flags) { | 680 SpdyDataFlags flags) { |
666 // Find our stream | 681 // Find our stream |
667 CHECK(IsStreamActive(stream_id)); | 682 CHECK(IsStreamActive(stream_id)); |
668 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 683 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
669 CHECK_EQ(stream->stream_id(), stream_id); | 684 CHECK_EQ(stream->stream_id(), stream_id); |
670 | 685 |
671 if (len > kMaxSpdyFrameChunkSize) { | 686 if (len > kMaxSpdyFrameChunkSize) { |
672 len = kMaxSpdyFrameChunkSize; | 687 len = kMaxSpdyFrameChunkSize; |
673 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 688 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
674 } | 689 } |
675 | 690 |
676 // Obey send window size of the stream if flow control is enabled. | 691 // Obey send window size of the stream if flow control is enabled. |
677 if (flow_control_) { | 692 if (flow_control_) { |
678 if (stream->send_window_size() <= 0) { | 693 if (stream->send_window_size() <= 0) { |
679 // Because we queue frames onto the session, it is possible that | 694 // Because we queue frames onto the session, it is possible that |
680 // a stream was not flow controlled at the time it attempted the | 695 // a stream was not flow controlled at the time it attempted the |
681 // write, but when we go to fulfill the write, it is now flow | 696 // write, but when we go to fulfill the write, it is now flow |
682 // controlled. This is why we need the session to mark the stream | 697 // controlled. This is why we need the session to mark the stream |
683 // as stalled - because only the session knows for sure when the | 698 // as stalled - because only the session knows for sure when the |
684 // stall occurs. | 699 // stall occurs. |
685 stream->set_stalled_by_flow_control(true); | 700 stream->set_stalled_by_flow_control(true); |
686 net_log().AddEvent( | 701 net_log().AddEvent( |
687 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW, | 702 NetLog::TYPE_SPDY_SESSION_STALLED_ON_SEND_WINDOW, |
688 NetLog::IntegerCallback("stream_id", stream_id)); | 703 NetLog::IntegerCallback("stream_id", stream_id)); |
689 return ERR_IO_PENDING; | 704 return NULL; |
690 } | 705 } |
691 int new_len = std::min(len, stream->send_window_size()); | 706 int new_len = std::min(len, stream->send_window_size()); |
692 if (new_len < len) { | 707 if (new_len < len) { |
693 len = new_len; | 708 len = new_len; |
694 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); | 709 flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_FIN); |
695 } | 710 } |
696 stream->DecreaseSendWindowSize(len); | 711 stream->DecreaseSendWindowSize(len); |
697 } | 712 } |
698 | 713 |
699 if (net_log().IsLoggingAllEvents()) { | 714 if (net_log().IsLoggingAllEvents()) { |
700 net_log().AddEvent( | 715 net_log().AddEvent( |
701 NetLog::TYPE_SPDY_SESSION_SEND_DATA, | 716 NetLog::TYPE_SPDY_SESSION_SEND_DATA, |
702 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags)); | 717 base::Bind(&NetLogSpdyDataCallback, stream_id, len, flags)); |
703 } | 718 } |
704 | 719 |
705 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. | 720 // Send PrefacePing for DATA_FRAMEs with nonzero payload size. |
706 if (len > 0) | 721 if (len > 0) |
707 SendPrefacePingIfNoneInFlight(); | 722 SendPrefacePingIfNoneInFlight(); |
708 | 723 |
709 // TODO(mbelshe): reduce memory copies here. | 724 // TODO(mbelshe): reduce memory copies here. |
710 DCHECK(buffered_spdy_framer_.get()); | 725 DCHECK(buffered_spdy_framer_.get()); |
711 scoped_ptr<SpdyDataFrame> frame( | 726 scoped_ptr<SpdyDataFrame> frame( |
712 buffered_spdy_framer_->CreateDataFrame( | 727 buffered_spdy_framer_->CreateDataFrame( |
713 stream_id, data->data(), len, flags)); | 728 stream_id, data->data(), len, flags)); |
714 QueueFrame(frame.get(), stream->priority(), stream); | |
715 | 729 |
716 return ERR_IO_PENDING; | 730 return frame.release(); |
717 } | 731 } |
718 | 732 |
719 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { | 733 void SpdySession::CloseStream(SpdyStreamId stream_id, int status) { |
| 734 DCHECK_NE(0u, stream_id); |
720 // TODO(mbelshe): We should send a RST_STREAM control frame here | 735 // TODO(mbelshe): We should send a RST_STREAM control frame here |
721 // so that the server can cancel a large send. | 736 // so that the server can cancel a large send. |
722 | 737 |
723 DeleteStream(stream_id, status); | 738 DeleteStream(stream_id, status); |
724 } | 739 } |
725 | 740 |
| 741 void SpdySession::CloseCreatedStream(SpdyStream* stream, int status) { |
| 742 DCHECK_EQ(0u, stream->stream_id()); |
| 743 created_streams_.erase(scoped_refptr<SpdyStream>(stream)); |
| 744 } |
| 745 |
726 void SpdySession::ResetStream(SpdyStreamId stream_id, | 746 void SpdySession::ResetStream(SpdyStreamId stream_id, |
727 SpdyStatusCodes status, | 747 SpdyStatusCodes status, |
728 const std::string& description) { | 748 const std::string& description) { |
729 net_log().AddEvent( | 749 net_log().AddEvent( |
730 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, | 750 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, |
731 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); | 751 base::Bind(&NetLogSpdyRstCallback, stream_id, status, &description)); |
732 | 752 |
733 DCHECK(buffered_spdy_framer_.get()); | 753 DCHECK(buffered_spdy_framer_.get()); |
734 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( | 754 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( |
735 buffered_spdy_framer_->CreateRstStream(stream_id, status)); | 755 buffered_spdy_framer_->CreateRstStream(stream_id, status)); |
736 | 756 |
737 // Default to lowest priority unless we know otherwise. | 757 // Default to lowest priority unless we know otherwise. |
738 RequestPriority priority = net::IDLE; | 758 RequestPriority priority = net::IDLE; |
739 if(IsStreamActive(stream_id)) { | 759 if(IsStreamActive(stream_id)) { |
740 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 760 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
741 priority = stream->priority(); | 761 priority = stream->priority(); |
742 } | 762 } |
743 QueueFrame(rst_frame.get(), priority, NULL); | 763 QueueFrame(rst_frame.release(), priority); |
744 RecordProtocolErrorHistogram( | 764 RecordProtocolErrorHistogram( |
745 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); | 765 static_cast<SpdyProtocolErrorDetails>(status + STATUS_CODE_INVALID)); |
746 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); | 766 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
747 } | 767 } |
748 | 768 |
749 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { | 769 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { |
750 return ContainsKey(active_streams_, stream_id); | 770 return ContainsKey(active_streams_, stream_id); |
751 } | 771 } |
752 | 772 |
753 LoadState SpdySession::GetLoadState() const { | 773 LoadState SpdySession::GetLoadState() const { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 // closed, just return. | 941 // closed, just return. |
922 if (state_ < CONNECTED || state_ == CLOSED) | 942 if (state_ < CONNECTED || state_ == CLOSED) |
923 return; | 943 return; |
924 | 944 |
925 if (write_pending_) // Another write is in progress still. | 945 if (write_pending_) // Another write is in progress still. |
926 return; | 946 return; |
927 | 947 |
928 // Loop sending frames until we've sent everything or until the write | 948 // Loop sending frames until we've sent everything or until the write |
929 // returns error (or ERR_IO_PENDING). | 949 // returns error (or ERR_IO_PENDING). |
930 DCHECK(buffered_spdy_framer_.get()); | 950 DCHECK(buffered_spdy_framer_.get()); |
931 while (in_flight_write_.buffer() || !queue_.empty()) { | 951 while (in_flight_write_.buffer() || !write_queue_.empty()) { |
932 if (!in_flight_write_.buffer()) { | 952 if (!in_flight_write_.buffer()) { |
933 // Grab the next SpdyFrame to send. | 953 // Grab the next SpdyBuffer to send. |
934 SpdyIOBuffer next_buffer = queue_.top(); | 954 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top()); |
935 queue_.pop(); | 955 write_queue_.pop(); |
| 956 scoped_ptr<SpdyIOBuffer> buffer(producer->ProduceNextBuffer(this)); |
| 957 stream_producers_.erase(producer.get()); |
| 958 // It is possible that a stream had data to write, but a |
| 959 // WINDOW_UPDATE frame has been received which made that |
| 960 // stream no longer writable. |
| 961 // TODO(rch): consider handling that case by removing the |
| 962 // stream from the writable queue? |
| 963 if (buffer == NULL) |
| 964 continue; |
936 | 965 |
937 // We've deferred compression until just before we write it to the socket, | 966 in_flight_write_ = *buffer; |
938 // which is now. At this time, we don't compress our data frames. | |
939 SpdyFrame uncompressed_frame(next_buffer.buffer()->data(), false); | |
940 size_t size; | |
941 if (buffered_spdy_framer_->IsCompressible(uncompressed_frame)) { | |
942 DCHECK(uncompressed_frame.is_control_frame()); | |
943 const SpdyControlFrame* uncompressed_control_frame = | |
944 reinterpret_cast<const SpdyControlFrame*>(&uncompressed_frame); | |
945 scoped_ptr<SpdyFrame> compressed_frame( | |
946 buffered_spdy_framer_->CompressControlFrame( | |
947 *uncompressed_control_frame)); | |
948 if (!compressed_frame.get()) { | |
949 RecordProtocolErrorHistogram( | |
950 PROTOCOL_ERROR_SPDY_COMPRESSION_FAILURE); | |
951 CloseSessionOnError( | |
952 net::ERR_SPDY_PROTOCOL_ERROR, true, "SPDY Compression failure."); | |
953 return; | |
954 } | |
955 | |
956 size = compressed_frame->length() + SpdyFrame::kHeaderSize; | |
957 | |
958 DCHECK_GT(size, 0u); | |
959 | |
960 // TODO(mbelshe): We have too much copying of data here. | |
961 IOBufferWithSize* buffer = new IOBufferWithSize(size); | |
962 memcpy(buffer->data(), compressed_frame->data(), size); | |
963 | |
964 // Attempt to send the frame. | |
965 in_flight_write_ = SpdyIOBuffer(buffer, size, HIGHEST, | |
966 next_buffer.stream()); | |
967 } else { | |
968 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize; | |
969 in_flight_write_ = next_buffer; | |
970 } | |
971 } else { | 967 } else { |
972 DCHECK(in_flight_write_.buffer()->BytesRemaining()); | 968 DCHECK(in_flight_write_.buffer()->BytesRemaining()); |
973 } | 969 } |
974 | 970 |
975 write_pending_ = true; | 971 write_pending_ = true; |
976 int rv = connection_->socket()->Write( | 972 int rv = connection_->socket()->Write( |
977 in_flight_write_.buffer(), | 973 in_flight_write_.buffer(), |
978 in_flight_write_.buffer()->BytesRemaining(), | 974 in_flight_write_.buffer()->BytesRemaining(), |
979 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); | 975 base::Bind(&SpdySession::OnWriteComplete, base::Unretained(this))); |
980 if (rv == net::ERR_IO_PENDING) | 976 if (rv == net::ERR_IO_PENDING) |
(...skipping 26 matching lines...) Expand all Loading... |
1007 while (!create_stream_queues_[i].empty()) { | 1003 while (!create_stream_queues_[i].empty()) { |
1008 PendingCreateStream pending_create = create_stream_queues_[i].front(); | 1004 PendingCreateStream pending_create = create_stream_queues_[i].front(); |
1009 create_stream_queues_[i].pop(); | 1005 create_stream_queues_[i].pop(); |
1010 pending_create.callback.Run(ERR_ABORTED); | 1006 pending_create.callback.Run(ERR_ABORTED); |
1011 } | 1007 } |
1012 } | 1008 } |
1013 | 1009 |
1014 while (!active_streams_.empty()) { | 1010 while (!active_streams_.empty()) { |
1015 ActiveStreamMap::iterator it = active_streams_.begin(); | 1011 ActiveStreamMap::iterator it = active_streams_.begin(); |
1016 const scoped_refptr<SpdyStream>& stream = it->second; | 1012 const scoped_refptr<SpdyStream>& stream = it->second; |
1017 DCHECK(stream); | 1013 LogAbandonedStream(stream, status); |
1018 std::string description = base::StringPrintf( | |
1019 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); | |
1020 stream->LogStreamError(status, description); | |
1021 DeleteStream(stream->stream_id(), status); | 1014 DeleteStream(stream->stream_id(), status); |
1022 } | 1015 } |
1023 | 1016 |
| 1017 while (!created_streams_.empty()) { |
| 1018 CreatedStreamSet::iterator it = created_streams_.begin(); |
| 1019 const scoped_refptr<SpdyStream>& stream = *it; |
| 1020 LogAbandonedStream(stream, status); |
| 1021 stream->OnClose(status); |
| 1022 created_streams_.erase(it); |
| 1023 } |
| 1024 |
1024 // We also need to drain the queue. | 1025 // We also need to drain the queue. |
1025 while (queue_.size()) | 1026 while (!write_queue_.empty()) { |
1026 queue_.pop(); | 1027 scoped_ptr<SpdyIOBufferProducer> producer(write_queue_.top()); |
| 1028 write_queue_.pop(); |
| 1029 stream_producers_.erase(producer.get()); |
| 1030 } |
| 1031 } |
| 1032 |
| 1033 void SpdySession::LogAbandonedStream(const scoped_refptr<SpdyStream>& stream, |
| 1034 net::Error status) { |
| 1035 DCHECK(stream); |
| 1036 std::string description = base::StringPrintf( |
| 1037 "ABANDONED (stream_id=%d): ", stream->stream_id()) + stream->path(); |
| 1038 stream->LogStreamError(status, description); |
1027 } | 1039 } |
1028 | 1040 |
1029 int SpdySession::GetNewStreamId() { | 1041 int SpdySession::GetNewStreamId() { |
1030 int id = stream_hi_water_mark_; | 1042 int id = stream_hi_water_mark_; |
1031 stream_hi_water_mark_ += 2; | 1043 stream_hi_water_mark_ += 2; |
1032 if (stream_hi_water_mark_ > 0x7fff) | 1044 if (stream_hi_water_mark_ > 0x7fff) |
1033 stream_hi_water_mark_ = 1; | 1045 stream_hi_water_mark_ = 1; |
1034 return id; | 1046 return id; |
1035 } | 1047 } |
1036 | 1048 |
1037 void SpdySession::QueueFrame(SpdyFrame* frame, | |
1038 RequestPriority priority, | |
1039 SpdyStream* stream) { | |
1040 int length = SpdyFrame::kHeaderSize + frame->length(); | |
1041 IOBuffer* buffer = new IOBuffer(length); | |
1042 memcpy(buffer->data(), frame->data(), length); | |
1043 queue_.push(SpdyIOBuffer(buffer, length, priority, stream)); | |
1044 | |
1045 WriteSocketLater(); | |
1046 } | |
1047 | |
1048 void SpdySession::CloseSessionOnError(net::Error err, | 1049 void SpdySession::CloseSessionOnError(net::Error err, |
1049 bool remove_from_pool, | 1050 bool remove_from_pool, |
1050 const std::string& description) { | 1051 const std::string& description) { |
1051 // Closing all streams can have a side-effect of dropping the last reference | 1052 // Closing all streams can have a side-effect of dropping the last reference |
1052 // to |this|. Hold a reference through this function. | 1053 // to |this|. Hold a reference through this function. |
1053 scoped_refptr<SpdySession> self(this); | 1054 scoped_refptr<SpdySession> self(this); |
1054 | 1055 |
1055 DCHECK_LT(err, OK); | 1056 DCHECK_LT(err, OK); |
1056 net_log_.AddEvent( | 1057 net_log_.AddEvent( |
1057 NetLog::TYPE_SPDY_SESSION_CLOSE, | 1058 NetLog::TYPE_SPDY_SESSION_CLOSE, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1124 return connection_->socket()->GetPeerAddress(address); | 1125 return connection_->socket()->GetPeerAddress(address); |
1125 } | 1126 } |
1126 | 1127 |
1127 int SpdySession::GetLocalAddress(IPEndPoint* address) const { | 1128 int SpdySession::GetLocalAddress(IPEndPoint* address) const { |
1128 if (!connection_->socket()) | 1129 if (!connection_->socket()) |
1129 return ERR_SOCKET_NOT_CONNECTED; | 1130 return ERR_SOCKET_NOT_CONNECTED; |
1130 | 1131 |
1131 return connection_->socket()->GetLocalAddress(address); | 1132 return connection_->socket()->GetLocalAddress(address); |
1132 } | 1133 } |
1133 | 1134 |
| 1135 class SimpleSpdyIOBufferProducer : public SpdySession::SpdyIOBufferProducer { |
| 1136 public: |
| 1137 SimpleSpdyIOBufferProducer(SpdyFrame* frame, |
| 1138 RequestPriority priority) |
| 1139 : frame_(frame), |
| 1140 priority_(priority) { |
| 1141 } |
| 1142 |
| 1143 virtual RequestPriority GetPriority() const OVERRIDE { |
| 1144 return priority_; |
| 1145 } |
| 1146 |
| 1147 virtual SpdyIOBuffer* ProduceNextBuffer(SpdySession* session) { |
| 1148 return SpdySession::SpdyIOBufferProducer::CreateIOBuffer( |
| 1149 frame_.get(), priority_, NULL); |
| 1150 } |
| 1151 |
| 1152 private: |
| 1153 scoped_ptr<SpdyFrame> frame_; |
| 1154 RequestPriority priority_; |
| 1155 }; |
| 1156 |
| 1157 void SpdySession::QueueFrame(SpdyFrame* frame, |
| 1158 RequestPriority priority) { |
| 1159 SimpleSpdyIOBufferProducer* producer = |
| 1160 new SimpleSpdyIOBufferProducer(frame, priority); |
| 1161 write_queue_.push(producer); |
| 1162 WriteSocketLater(); |
| 1163 } |
| 1164 |
1134 void SpdySession::ActivateStream(SpdyStream* stream) { | 1165 void SpdySession::ActivateStream(SpdyStream* stream) { |
| 1166 if (stream->stream_id() == 0) { |
| 1167 stream->set_stream_id(GetNewStreamId()); |
| 1168 created_streams_.erase(scoped_refptr<SpdyStream>(stream)); |
| 1169 } |
1135 const SpdyStreamId id = stream->stream_id(); | 1170 const SpdyStreamId id = stream->stream_id(); |
1136 DCHECK(!IsStreamActive(id)); | 1171 DCHECK(!IsStreamActive(id)); |
1137 | 1172 |
1138 active_streams_[id] = stream; | 1173 active_streams_[id] = stream; |
1139 } | 1174 } |
1140 | 1175 |
1141 void SpdySession::DeleteStream(SpdyStreamId id, int status) { | 1176 void SpdySession::DeleteStream(SpdyStreamId id, int status) { |
1142 // For push streams, if they are being deleted normally, we leave | 1177 // For push streams, if they are being deleted normally, we leave |
1143 // the stream in the unclaimed_pushed_streams_ list. However, if | 1178 // the stream in the unclaimed_pushed_streams_ list. However, if |
1144 // the stream is errored out, clean it up entirely. | 1179 // the stream is errored out, clean it up entirely. |
1145 if (status != OK) { | 1180 if (status != OK) { |
1146 PushedStreamMap::iterator it; | 1181 PushedStreamMap::iterator it; |
1147 for (it = unclaimed_pushed_streams_.begin(); | 1182 for (it = unclaimed_pushed_streams_.begin(); |
1148 it != unclaimed_pushed_streams_.end(); ++it) { | 1183 it != unclaimed_pushed_streams_.end(); ++it) { |
1149 scoped_refptr<SpdyStream> curr = it->second.first; | 1184 scoped_refptr<SpdyStream> curr = it->second.first; |
1150 if (id == curr->stream_id()) { | 1185 if (id == curr->stream_id()) { |
1151 unclaimed_pushed_streams_.erase(it); | 1186 unclaimed_pushed_streams_.erase(it); |
1152 break; | 1187 break; |
1153 } | 1188 } |
1154 } | 1189 } |
1155 } | 1190 } |
1156 | 1191 |
1157 // The stream might have been deleted. | 1192 // The stream might have been deleted. |
1158 ActiveStreamMap::iterator it2 = active_streams_.find(id); | 1193 ActiveStreamMap::iterator it2 = active_streams_.find(id); |
1159 if (it2 == active_streams_.end()) | 1194 if (it2 == active_streams_.end()) |
1160 return; | 1195 return; |
1161 | 1196 |
| 1197 // Possibly remove from the write queue. |
| 1198 WriteQueue old = write_queue_; |
| 1199 write_queue_ = WriteQueue(); |
| 1200 while (!old.empty()) { |
| 1201 scoped_ptr<SpdyIOBufferProducer> producer(old.top()); |
| 1202 old.pop(); |
| 1203 StreamProducerMap::iterator it = stream_producers_.find(producer.get()); |
| 1204 if (it == stream_producers_.end() || it->second->stream_id() != id) { |
| 1205 write_queue_.push(producer.release()); |
| 1206 } else { |
| 1207 stream_producers_.erase(producer.get()); |
| 1208 producer.reset(NULL); |
| 1209 } |
| 1210 } |
| 1211 |
1162 // If this is an active stream, call the callback. | 1212 // If this is an active stream, call the callback. |
1163 const scoped_refptr<SpdyStream> stream(it2->second); | 1213 const scoped_refptr<SpdyStream> stream(it2->second); |
1164 active_streams_.erase(it2); | 1214 active_streams_.erase(it2); |
1165 if (stream) | 1215 if (stream) |
1166 stream->OnClose(status); | 1216 stream->OnClose(status); |
1167 ProcessPendingCreateStreams(); | 1217 ProcessPendingCreateStreams(); |
1168 } | 1218 } |
1169 | 1219 |
1170 void SpdySession::RemoveFromPool() { | 1220 void SpdySession::RemoveFromPool() { |
1171 if (spdy_session_pool_) { | 1221 if (spdy_session_pool_) { |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 } | 1422 } |
1373 | 1423 |
1374 // There should not be an existing pushed stream with the same path. | 1424 // There should not be an existing pushed stream with the same path. |
1375 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); | 1425 PushedStreamMap::iterator it = unclaimed_pushed_streams_.find(url); |
1376 if (it != unclaimed_pushed_streams_.end()) { | 1426 if (it != unclaimed_pushed_streams_.end()) { |
1377 ResetStream(stream_id, PROTOCOL_ERROR, | 1427 ResetStream(stream_id, PROTOCOL_ERROR, |
1378 "Received duplicate pushed stream with url: " + url); | 1428 "Received duplicate pushed stream with url: " + url); |
1379 return; | 1429 return; |
1380 } | 1430 } |
1381 | 1431 |
1382 scoped_refptr<SpdyStream> stream( | 1432 scoped_refptr<SpdyStream> stream(new SpdyStream(this, true, net_log_)); |
1383 new SpdyStream(this, stream_id, true, net_log_)); | 1433 stream->set_stream_id(stream_id); |
1384 | 1434 |
1385 stream->set_path(gurl.PathForRequest()); | 1435 stream->set_path(gurl.PathForRequest()); |
1386 stream->set_send_window_size(initial_send_window_size_); | 1436 stream->set_send_window_size(initial_send_window_size_); |
1387 stream->set_recv_window_size(initial_recv_window_size_); | 1437 stream->set_recv_window_size(initial_recv_window_size_); |
1388 | 1438 |
1389 DeleteExpiredPushedStreams(); | 1439 DeleteExpiredPushedStreams(); |
1390 unclaimed_pushed_streams_[url] = | 1440 unclaimed_pushed_streams_[url] = |
1391 std::pair<scoped_refptr<SpdyStream>, base::TimeTicks> ( | 1441 std::pair<scoped_refptr<SpdyStream>, base::TimeTicks> ( |
1392 stream, g_time_func()); | 1442 stream, g_time_func()); |
1393 | 1443 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1611 CHECK_EQ(stream->stream_id(), stream_id); | 1661 CHECK_EQ(stream->stream_id(), stream_id); |
1612 | 1662 |
1613 net_log_.AddEvent( | 1663 net_log_.AddEvent( |
1614 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, | 1664 NetLog::TYPE_SPDY_SESSION_SENT_WINDOW_UPDATE, |
1615 base::Bind(&NetLogSpdyWindowUpdateCallback, | 1665 base::Bind(&NetLogSpdyWindowUpdateCallback, |
1616 stream_id, delta_window_size)); | 1666 stream_id, delta_window_size)); |
1617 | 1667 |
1618 DCHECK(buffered_spdy_framer_.get()); | 1668 DCHECK(buffered_spdy_framer_.get()); |
1619 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( | 1669 scoped_ptr<SpdyWindowUpdateControlFrame> window_update_frame( |
1620 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); | 1670 buffered_spdy_framer_->CreateWindowUpdate(stream_id, delta_window_size)); |
1621 QueueFrame(window_update_frame.get(), stream->priority(), NULL); | 1671 QueueFrame(window_update_frame.release(), stream->priority()); |
1622 } | 1672 } |
1623 | 1673 |
1624 // Given a cwnd that we would have sent to the server, modify it based on the | 1674 // Given a cwnd that we would have sent to the server, modify it based on the |
1625 // field trial policy. | 1675 // field trial policy. |
1626 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { | 1676 uint32 ApplyCwndFieldTrialPolicy(int cwnd) { |
1627 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); | 1677 base::FieldTrial* trial = base::FieldTrialList::Find("SpdyCwnd"); |
1628 if (!trial) { | 1678 if (!trial) { |
1629 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; | 1679 LOG(WARNING) << "Could not find \"SpdyCwnd\" in FieldTrialList"; |
1630 return cwnd; | 1680 return cwnd; |
1631 } | 1681 } |
(...skipping 18 matching lines...) Expand all Loading... |
1650 SettingsMap settings_map; | 1700 SettingsMap settings_map; |
1651 // Create a new settings frame notifying the sever of our | 1701 // Create a new settings frame notifying the sever of our |
1652 // max_concurrent_streams_ and initial window size. | 1702 // max_concurrent_streams_ and initial window size. |
1653 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = | 1703 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = |
1654 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); | 1704 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); |
1655 if (GetProtocolVersion() > 2 && | 1705 if (GetProtocolVersion() > 2 && |
1656 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { | 1706 initial_recv_window_size_ != kSpdyStreamInitialWindowSize) { |
1657 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = | 1707 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = |
1658 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_); | 1708 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, initial_recv_window_size_); |
1659 } | 1709 } |
1660 sent_settings_ = true; | |
1661 SendSettings(settings_map); | 1710 SendSettings(settings_map); |
1662 } | 1711 } |
1663 | 1712 |
1664 // Next notify the server about the settings they have previously | 1713 // Next notify the server about the settings they have previously |
1665 // told us to use when communicating with them. | 1714 // told us to use when communicating with them. |
1666 const SettingsMap& settings_map = | 1715 const SettingsMap& settings_map = |
1667 http_server_properties_->GetSpdySettings(host_port_pair()); | 1716 http_server_properties_->GetSpdySettings(host_port_pair()); |
1668 if (settings_map.empty()) | 1717 if (settings_map.empty()) |
1669 return; | 1718 return; |
1670 | 1719 |
(...skipping 12 matching lines...) Expand all Loading... |
1683 | 1732 |
1684 const SettingsMap& settings_map_new = | 1733 const SettingsMap& settings_map_new = |
1685 http_server_properties_->GetSpdySettings(host_port_pair()); | 1734 http_server_properties_->GetSpdySettings(host_port_pair()); |
1686 for (SettingsMap::const_iterator i = settings_map_new.begin(), | 1735 for (SettingsMap::const_iterator i = settings_map_new.begin(), |
1687 end = settings_map_new.end(); i != end; ++i) { | 1736 end = settings_map_new.end(); i != end; ++i) { |
1688 const SpdySettingsIds new_id = i->first; | 1737 const SpdySettingsIds new_id = i->first; |
1689 const uint32 new_val = i->second.second; | 1738 const uint32 new_val = i->second.second; |
1690 HandleSetting(new_id, new_val); | 1739 HandleSetting(new_id, new_val); |
1691 } | 1740 } |
1692 | 1741 |
1693 sent_settings_ = true; | |
1694 SendSettings(settings_map_new); | 1742 SendSettings(settings_map_new); |
1695 } | 1743 } |
1696 | 1744 |
1697 | 1745 |
1698 void SpdySession::SendSettings(const SettingsMap& settings) { | 1746 void SpdySession::SendSettings(const SettingsMap& settings) { |
1699 net_log_.AddEvent( | 1747 net_log_.AddEvent( |
1700 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 1748 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
1701 base::Bind(&NetLogSpdySettingsCallback, &settings)); | 1749 base::Bind(&NetLogSpdySettingsCallback, &settings)); |
1702 | 1750 |
1703 // Create the SETTINGS frame and send it. | 1751 // Create the SETTINGS frame and send it. |
1704 DCHECK(buffered_spdy_framer_.get()); | 1752 DCHECK(buffered_spdy_framer_.get()); |
1705 scoped_ptr<SpdySettingsControlFrame> settings_frame( | 1753 scoped_ptr<SpdySettingsControlFrame> settings_frame( |
1706 buffered_spdy_framer_->CreateSettings(settings)); | 1754 buffered_spdy_framer_->CreateSettings(settings)); |
1707 QueueFrame(settings_frame.get(), HIGHEST, NULL); | 1755 sent_settings_ = true; |
| 1756 QueueFrame(settings_frame.release(), HIGHEST); |
1708 } | 1757 } |
1709 | 1758 |
1710 void SpdySession::HandleSetting(uint32 id, uint32 value) { | 1759 void SpdySession::HandleSetting(uint32 id, uint32 value) { |
1711 switch (id) { | 1760 switch (id) { |
1712 case SETTINGS_MAX_CONCURRENT_STREAMS: | 1761 case SETTINGS_MAX_CONCURRENT_STREAMS: |
1713 max_concurrent_streams_ = std::min(static_cast<size_t>(value), | 1762 max_concurrent_streams_ = std::min(static_cast<size_t>(value), |
1714 g_max_concurrent_stream_limit); | 1763 g_max_concurrent_stream_limit); |
1715 ProcessPendingCreateStreams(); | 1764 ProcessPendingCreateStreams(); |
1716 break; | 1765 break; |
1717 case SETTINGS_INITIAL_WINDOW_SIZE: | 1766 case SETTINGS_INITIAL_WINDOW_SIZE: |
(...skipping 14 matching lines...) Expand all Loading... |
1732 } | 1781 } |
1733 } | 1782 } |
1734 | 1783 |
1735 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { | 1784 void SpdySession::UpdateStreamsSendWindowSize(int32 delta_window_size) { |
1736 ActiveStreamMap::iterator it; | 1785 ActiveStreamMap::iterator it; |
1737 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { | 1786 for (it = active_streams_.begin(); it != active_streams_.end(); ++it) { |
1738 const scoped_refptr<SpdyStream>& stream = it->second; | 1787 const scoped_refptr<SpdyStream>& stream = it->second; |
1739 DCHECK(stream); | 1788 DCHECK(stream); |
1740 stream->AdjustSendWindowSize(delta_window_size); | 1789 stream->AdjustSendWindowSize(delta_window_size); |
1741 } | 1790 } |
| 1791 |
| 1792 CreatedStreamSet::iterator i; |
| 1793 for (i = created_streams_.begin(); i != created_streams_.end(); i++) { |
| 1794 const scoped_refptr<SpdyStream>& stream = *i; |
| 1795 stream->AdjustSendWindowSize(delta_window_size); |
| 1796 } |
1742 } | 1797 } |
1743 | 1798 |
1744 void SpdySession::SendPrefacePingIfNoneInFlight() { | 1799 void SpdySession::SendPrefacePingIfNoneInFlight() { |
1745 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) | 1800 if (pings_in_flight_ || !g_enable_ping_based_connection_checking) |
1746 return; | 1801 return; |
1747 | 1802 |
1748 base::TimeTicks now = base::TimeTicks::Now(); | 1803 base::TimeTicks now = base::TimeTicks::Now(); |
1749 // If there is no activity in the session, then send a preface-PING. | 1804 // If there is no activity in the session, then send a preface-PING. |
1750 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) | 1805 if ((now - last_activity_time_) > connection_at_risk_of_loss_time_) |
1751 SendPrefacePing(); | 1806 SendPrefacePing(); |
1752 } | 1807 } |
1753 | 1808 |
1754 void SpdySession::SendPrefacePing() { | 1809 void SpdySession::SendPrefacePing() { |
1755 WritePingFrame(next_ping_id_); | 1810 WritePingFrame(next_ping_id_); |
1756 } | 1811 } |
1757 | 1812 |
1758 void SpdySession::WritePingFrame(uint32 unique_id) { | 1813 void SpdySession::WritePingFrame(uint32 unique_id) { |
1759 DCHECK(buffered_spdy_framer_.get()); | 1814 DCHECK(buffered_spdy_framer_.get()); |
1760 scoped_ptr<SpdyPingControlFrame> ping_frame( | 1815 scoped_ptr<SpdyPingControlFrame> ping_frame( |
1761 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); | 1816 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); |
1762 QueueFrame(ping_frame.get(), HIGHEST, NULL); | 1817 QueueFrame(ping_frame.release(), HIGHEST); |
1763 | 1818 |
1764 if (net_log().IsLoggingAllEvents()) { | 1819 if (net_log().IsLoggingAllEvents()) { |
1765 net_log().AddEvent( | 1820 net_log().AddEvent( |
1766 NetLog::TYPE_SPDY_SESSION_PING, | 1821 NetLog::TYPE_SPDY_SESSION_PING, |
1767 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); | 1822 base::Bind(&NetLogSpdyPingCallback, next_ping_id_, "sent")); |
1768 } | 1823 } |
1769 if (unique_id % 2 != 0) { | 1824 if (unique_id % 2 != 0) { |
1770 next_ping_id_ += 2; | 1825 next_ping_id_ += 2; |
1771 ++pings_in_flight_; | 1826 ++pings_in_flight_; |
1772 PlanToCheckPingStatus(); | 1827 PlanToCheckPingStatus(); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1915 SSLClientSocket* SpdySession::GetSSLClientSocket() const { | 1970 SSLClientSocket* SpdySession::GetSSLClientSocket() const { |
1916 if (!is_secure_) | 1971 if (!is_secure_) |
1917 return NULL; | 1972 return NULL; |
1918 SSLClientSocket* ssl_socket = | 1973 SSLClientSocket* ssl_socket = |
1919 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 1974 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
1920 DCHECK(ssl_socket); | 1975 DCHECK(ssl_socket); |
1921 return ssl_socket; | 1976 return ssl_socket; |
1922 } | 1977 } |
1923 | 1978 |
1924 } // namespace net | 1979 } // namespace net |
OLD | NEW |