| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 | 62 |
| 63 namespace { | 63 namespace { |
| 64 | 64 |
| 65 const int kReadBufferSize = 8 * 1024; | 65 const int kReadBufferSize = 8 * 1024; |
| 66 const int kDefaultConnectionAtRiskOfLossSeconds = 10; | 66 const int kDefaultConnectionAtRiskOfLossSeconds = 10; |
| 67 const int kHungIntervalSeconds = 10; | 67 const int kHungIntervalSeconds = 10; |
| 68 | 68 |
| 69 // Minimum seconds that unclaimed pushed streams will be kept in memory. | 69 // Minimum seconds that unclaimed pushed streams will be kept in memory. |
| 70 const int kMinPushedStreamLifetimeSeconds = 300; | 70 const int kMinPushedStreamLifetimeSeconds = 300; |
| 71 | 71 |
| 72 // Default initial value for HTTP/2 SETTINGS. |
| 73 const uint32_t kDefaultInitialHeaderTableSize = 4096; |
| 74 const uint32_t kDefaultInitialEnablePush = 1; |
| 75 const uint32_t kDefaultInitialInitialWindowSize = 65535; |
| 76 const uint32_t kDefaultInitialMaxFrameSize = 16384; |
| 77 |
| 78 bool IsSpdySettingAtDefaultInitialValue(SpdySettingsIds setting_id, |
| 79 uint32_t value) { |
| 80 switch (setting_id) { |
| 81 case SETTINGS_HEADER_TABLE_SIZE: |
| 82 return value == kDefaultInitialHeaderTableSize; |
| 83 case SETTINGS_ENABLE_PUSH: |
| 84 return value == kDefaultInitialEnablePush; |
| 85 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 86 // There is no initial limit on the number of concurrent streams. |
| 87 return false; |
| 88 case SETTINGS_INITIAL_WINDOW_SIZE: |
| 89 return value == kDefaultInitialInitialWindowSize; |
| 90 case SETTINGS_MAX_FRAME_SIZE: |
| 91 return value == kDefaultInitialMaxFrameSize; |
| 92 case SETTINGS_MAX_HEADER_LIST_SIZE: |
| 93 // There is no initial limit on the size of the header list. |
| 94 return false; |
| 95 default: |
| 96 // Undefined parameters have no initial value. |
| 97 return false; |
| 98 } |
| 99 } |
| 100 |
| 72 std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback( | 101 std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback( |
| 73 const SpdyHeaderBlock* headers, | 102 const SpdyHeaderBlock* headers, |
| 74 bool fin, | 103 bool fin, |
| 75 SpdyStreamId stream_id, | 104 SpdyStreamId stream_id, |
| 76 bool has_priority, | 105 bool has_priority, |
| 77 int weight, | 106 int weight, |
| 78 SpdyStreamId parent_stream_id, | 107 SpdyStreamId parent_stream_id, |
| 79 bool exclusive, | 108 bool exclusive, |
| 80 NetLogCaptureMode capture_mode) { | 109 NetLogCaptureMode capture_mode) { |
| 81 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 110 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 | 677 |
| 649 return true; | 678 return true; |
| 650 } | 679 } |
| 651 | 680 |
| 652 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key, | 681 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key, |
| 653 HttpServerProperties* http_server_properties, | 682 HttpServerProperties* http_server_properties, |
| 654 TransportSecurityState* transport_security_state, | 683 TransportSecurityState* transport_security_state, |
| 655 bool enable_sending_initial_data, | 684 bool enable_sending_initial_data, |
| 656 bool enable_ping_based_connection_checking, | 685 bool enable_ping_based_connection_checking, |
| 657 size_t session_max_recv_window_size, | 686 size_t session_max_recv_window_size, |
| 658 size_t stream_max_recv_window_size, | 687 const SettingsMap& initial_settings, |
| 659 TimeFunc time_func, | 688 TimeFunc time_func, |
| 660 ServerPushDelegate* push_delegate, | 689 ServerPushDelegate* push_delegate, |
| 661 ProxyDelegate* proxy_delegate, | 690 ProxyDelegate* proxy_delegate, |
| 662 NetLog* net_log) | 691 NetLog* net_log) |
| 663 : in_io_loop_(false), | 692 : in_io_loop_(false), |
| 664 spdy_session_key_(spdy_session_key), | 693 spdy_session_key_(spdy_session_key), |
| 665 pool_(NULL), | 694 pool_(NULL), |
| 666 http_server_properties_(http_server_properties), | 695 http_server_properties_(http_server_properties), |
| 667 transport_security_state_(transport_security_state), | 696 transport_security_state_(transport_security_state), |
| 668 read_buffer_(new IOBuffer(kReadBufferSize)), | 697 read_buffer_(new IOBuffer(kReadBufferSize)), |
| 669 stream_hi_water_mark_(kFirstStreamId), | 698 stream_hi_water_mark_(kFirstStreamId), |
| 670 last_accepted_push_stream_id_(0), | 699 last_accepted_push_stream_id_(0), |
| 671 unclaimed_pushed_streams_(this), | 700 unclaimed_pushed_streams_(this), |
| 672 push_delegate_(push_delegate), | 701 push_delegate_(push_delegate), |
| 673 num_pushed_streams_(0u), | 702 num_pushed_streams_(0u), |
| 674 num_active_pushed_streams_(0u), | 703 num_active_pushed_streams_(0u), |
| 675 bytes_pushed_count_(0u), | 704 bytes_pushed_count_(0u), |
| 676 bytes_pushed_and_unclaimed_count_(0u), | 705 bytes_pushed_and_unclaimed_count_(0u), |
| 677 in_flight_write_frame_type_(DATA), | 706 in_flight_write_frame_type_(DATA), |
| 678 in_flight_write_frame_size_(0), | 707 in_flight_write_frame_size_(0), |
| 679 is_secure_(false), | 708 is_secure_(false), |
| 680 availability_state_(STATE_AVAILABLE), | 709 availability_state_(STATE_AVAILABLE), |
| 681 read_state_(READ_STATE_DO_READ), | 710 read_state_(READ_STATE_DO_READ), |
| 682 write_state_(WRITE_STATE_IDLE), | 711 write_state_(WRITE_STATE_IDLE), |
| 683 error_on_close_(OK), | 712 error_on_close_(OK), |
| 713 initial_settings_(initial_settings), |
| 684 max_concurrent_streams_(kInitialMaxConcurrentStreams), | 714 max_concurrent_streams_(kInitialMaxConcurrentStreams), |
| 685 max_concurrent_pushed_streams_(kMaxConcurrentPushedStreams), | 715 max_concurrent_pushed_streams_( |
| 716 initial_settings.at(SETTINGS_MAX_CONCURRENT_STREAMS)), |
| 686 streams_initiated_count_(0), | 717 streams_initiated_count_(0), |
| 687 streams_pushed_count_(0), | 718 streams_pushed_count_(0), |
| 688 streams_pushed_and_claimed_count_(0), | 719 streams_pushed_and_claimed_count_(0), |
| 689 streams_abandoned_count_(0), | 720 streams_abandoned_count_(0), |
| 690 pings_in_flight_(0), | 721 pings_in_flight_(0), |
| 691 next_ping_id_(1), | 722 next_ping_id_(1), |
| 692 last_activity_time_(time_func()), | 723 last_activity_time_(time_func()), |
| 693 last_compressed_frame_len_(0), | 724 last_compressed_frame_len_(0), |
| 694 check_ping_status_pending_(false), | 725 check_ping_status_pending_(false), |
| 695 session_send_window_size_(0), | 726 session_send_window_size_(0), |
| 696 session_max_recv_window_size_(session_max_recv_window_size), | 727 session_max_recv_window_size_(session_max_recv_window_size), |
| 697 session_recv_window_size_(0), | 728 session_recv_window_size_(0), |
| 698 session_unacked_recv_window_bytes_(0), | 729 session_unacked_recv_window_bytes_(0), |
| 699 stream_initial_send_window_size_(kDefaultInitialWindowSize), | 730 stream_initial_send_window_size_(kDefaultInitialWindowSize), |
| 700 stream_max_recv_window_size_(stream_max_recv_window_size), | 731 max_header_table_size_(initial_settings.at(SETTINGS_HEADER_TABLE_SIZE)), |
| 732 stream_max_recv_window_size_( |
| 733 initial_settings.at(SETTINGS_INITIAL_WINDOW_SIZE)), |
| 701 net_log_( | 734 net_log_( |
| 702 NetLogWithSource::Make(net_log, NetLogSourceType::HTTP2_SESSION)), | 735 NetLogWithSource::Make(net_log, NetLogSourceType::HTTP2_SESSION)), |
| 703 enable_sending_initial_data_(enable_sending_initial_data), | 736 enable_sending_initial_data_(enable_sending_initial_data), |
| 704 enable_ping_based_connection_checking_( | 737 enable_ping_based_connection_checking_( |
| 705 enable_ping_based_connection_checking), | 738 enable_ping_based_connection_checking), |
| 706 connection_at_risk_of_loss_time_( | 739 connection_at_risk_of_loss_time_( |
| 707 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), | 740 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), |
| 708 hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), | 741 hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), |
| 709 proxy_delegate_(proxy_delegate), | 742 proxy_delegate_(proxy_delegate), |
| 710 time_func_(time_func), | 743 time_func_(time_func), |
| 711 weak_factory_(this) { | 744 weak_factory_(this) { |
| 712 net_log_.BeginEvent( | 745 net_log_.BeginEvent( |
| 713 NetLogEventType::HTTP2_SESSION, | 746 NetLogEventType::HTTP2_SESSION, |
| 714 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); | 747 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); |
| 715 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 748 next_unclaimed_push_stream_sweep_time_ = time_func_() + |
| 716 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 749 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 750 |
| 751 DCHECK(base::ContainsKey(initial_settings_, SETTINGS_HEADER_TABLE_SIZE)); |
| 752 DCHECK(base::ContainsKey(initial_settings_, SETTINGS_MAX_CONCURRENT_STREAMS)); |
| 753 DCHECK(base::ContainsKey(initial_settings_, SETTINGS_INITIAL_WINDOW_SIZE)); |
| 754 |
| 717 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. | 755 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. |
| 718 } | 756 } |
| 719 | 757 |
| 720 SpdySession::~SpdySession() { | 758 SpdySession::~SpdySession() { |
| 721 CHECK(!in_io_loop_); | 759 CHECK(!in_io_loop_); |
| 722 DcheckDraining(); | 760 DcheckDraining(); |
| 723 | 761 |
| 724 // TODO(akalin): Check connection->is_initialized() instead. This | 762 // TODO(akalin): Check connection->is_initialized() instead. This |
| 725 // requires re-working CreateFakeSpdySession(), though. | 763 // requires re-working CreateFakeSpdySession(), though. |
| 726 DCHECK(connection_->socket()); | 764 DCHECK(connection_->socket()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 748 | 786 |
| 749 connection_ = std::move(connection); | 787 connection_ = std::move(connection); |
| 750 is_secure_ = is_secure; | 788 is_secure_ = is_secure; |
| 751 | 789 |
| 752 session_send_window_size_ = kDefaultInitialWindowSize; | 790 session_send_window_size_ = kDefaultInitialWindowSize; |
| 753 session_recv_window_size_ = kDefaultInitialWindowSize; | 791 session_recv_window_size_ = kDefaultInitialWindowSize; |
| 754 | 792 |
| 755 buffered_spdy_framer_.reset(new BufferedSpdyFramer()); | 793 buffered_spdy_framer_.reset(new BufferedSpdyFramer()); |
| 756 buffered_spdy_framer_->set_visitor(this); | 794 buffered_spdy_framer_->set_visitor(this); |
| 757 buffered_spdy_framer_->set_debug_visitor(this); | 795 buffered_spdy_framer_->set_debug_visitor(this); |
| 758 buffered_spdy_framer_->UpdateHeaderDecoderTableSize(kMaxHeaderTableSize); | 796 buffered_spdy_framer_->UpdateHeaderDecoderTableSize(max_header_table_size_); |
| 759 | 797 |
| 760 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_INITIALIZED, | 798 net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_INITIALIZED, |
| 761 base::Bind(&NetLogSpdyInitializedCallback, | 799 base::Bind(&NetLogSpdyInitializedCallback, |
| 762 connection_->socket()->NetLog().source())); | 800 connection_->socket()->NetLog().source())); |
| 763 | 801 |
| 764 DCHECK_EQ(availability_state_, STATE_AVAILABLE); | 802 DCHECK_EQ(availability_state_, STATE_AVAILABLE); |
| 765 connection_->AddHigherLayeredPool(this); | 803 connection_->AddHigherLayeredPool(this); |
| 766 if (enable_sending_initial_data_) | 804 if (enable_sending_initial_data_) |
| 767 SendInitialData(); | 805 SendInitialData(); |
| 768 pool_ = pool; | 806 pool_ = pool; |
| (...skipping 1870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2639 | 2677 |
| 2640 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( | 2678 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( |
| 2641 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), | 2679 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), |
| 2642 kHttp2ConnectionHeaderPrefixSize, | 2680 kHttp2ConnectionHeaderPrefixSize, |
| 2643 false /* take_ownership */)); | 2681 false /* take_ownership */)); |
| 2644 // Count the prefix as part of the subsequent SETTINGS frame. | 2682 // Count the prefix as part of the subsequent SETTINGS frame. |
| 2645 EnqueueSessionWrite(HIGHEST, SETTINGS, | 2683 EnqueueSessionWrite(HIGHEST, SETTINGS, |
| 2646 std::move(connection_header_prefix_frame)); | 2684 std::move(connection_header_prefix_frame)); |
| 2647 | 2685 |
| 2648 // First, notify the server about the settings they should use when | 2686 // First, notify the server about the settings they should use when |
| 2649 // communicating with us. | 2687 // communicating with us. Only send settings that have a value different from |
| 2688 // the protocol default value. |
| 2650 SettingsMap settings_map; | 2689 SettingsMap settings_map; |
| 2651 settings_map[SETTINGS_HEADER_TABLE_SIZE] = kMaxHeaderTableSize; | 2690 for (auto setting : initial_settings_) { |
| 2652 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = kMaxConcurrentPushedStreams; | 2691 if (!IsSpdySettingAtDefaultInitialValue(setting.first, setting.second)) { |
| 2653 if (stream_max_recv_window_size_ != kDefaultInitialWindowSize) { | 2692 settings_map.insert(setting); |
| 2654 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = stream_max_recv_window_size_; | 2693 } |
| 2655 } | 2694 } |
| 2656 SendSettings(settings_map); | 2695 SendSettings(settings_map); |
| 2657 | 2696 |
| 2658 // Next, notify the server about our initial recv window size. | 2697 // Next, notify the server about our initial recv window size. |
| 2659 // Bump up the receive window size to the real initial value. This | 2698 // Bump up the receive window size to the real initial value. This |
| 2660 // has to go here since the WINDOW_UPDATE frame sent by | 2699 // has to go here since the WINDOW_UPDATE frame sent by |
| 2661 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. | 2700 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. |
| 2662 // This condition implies that |session_max_recv_window_size_| - | 2701 // This condition implies that |session_max_recv_window_size_| - |
| 2663 // |session_recv_window_size_| doesn't overflow. | 2702 // |session_recv_window_size_| doesn't overflow. |
| 2664 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); | 2703 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3028 if (!queue->empty()) { | 3067 if (!queue->empty()) { |
| 3029 SpdyStreamId stream_id = queue->front(); | 3068 SpdyStreamId stream_id = queue->front(); |
| 3030 queue->pop_front(); | 3069 queue->pop_front(); |
| 3031 return stream_id; | 3070 return stream_id; |
| 3032 } | 3071 } |
| 3033 } | 3072 } |
| 3034 return 0; | 3073 return 0; |
| 3035 } | 3074 } |
| 3036 | 3075 |
| 3037 } // namespace net | 3076 } // namespace net |
| OLD | NEW |