| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 | 54 |
| 55 namespace { | 55 namespace { |
| 56 | 56 |
| 57 const int kReadBufferSize = 8 * 1024; | 57 const int kReadBufferSize = 8 * 1024; |
| 58 const int kDefaultConnectionAtRiskOfLossSeconds = 10; | 58 const int kDefaultConnectionAtRiskOfLossSeconds = 10; |
| 59 const int kHungIntervalSeconds = 10; | 59 const int kHungIntervalSeconds = 10; |
| 60 | 60 |
| 61 // Minimum seconds that unclaimed pushed streams will be kept in memory. | 61 // Minimum seconds that unclaimed pushed streams will be kept in memory. |
| 62 const int kMinPushedStreamLifetimeSeconds = 300; | 62 const int kMinPushedStreamLifetimeSeconds = 300; |
| 63 | 63 |
| 64 std::unique_ptr<base::Value> NetLogSpdySynStreamSentCallback( | |
| 65 const SpdyHeaderBlock* headers, | |
| 66 bool fin, | |
| 67 bool unidirectional, | |
| 68 SpdyPriority spdy_priority, | |
| 69 SpdyStreamId stream_id, | |
| 70 NetLogCaptureMode capture_mode) { | |
| 71 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | |
| 72 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); | |
| 73 dict->SetBoolean("fin", fin); | |
| 74 dict->SetBoolean("unidirectional", unidirectional); | |
| 75 dict->SetInteger("priority", static_cast<int>(spdy_priority)); | |
| 76 dict->SetInteger("stream_id", stream_id); | |
| 77 return std::move(dict); | |
| 78 } | |
| 79 | |
| 80 std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback( | 64 std::unique_ptr<base::Value> NetLogSpdyHeadersSentCallback( |
| 81 const SpdyHeaderBlock* headers, | 65 const SpdyHeaderBlock* headers, |
| 82 bool fin, | 66 bool fin, |
| 83 SpdyStreamId stream_id, | 67 SpdyStreamId stream_id, |
| 84 bool has_priority, | 68 bool has_priority, |
| 85 int weight, | 69 int weight, |
| 86 SpdyStreamId parent_stream_id, | 70 SpdyStreamId parent_stream_id, |
| 87 bool exclusive, | 71 bool exclusive, |
| 88 NetLogCaptureMode capture_mode) { | 72 NetLogCaptureMode capture_mode) { |
| 89 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 73 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 90 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); | 74 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); |
| 91 dict->SetBoolean("fin", fin); | 75 dict->SetBoolean("fin", fin); |
| 92 dict->SetInteger("stream_id", stream_id); | 76 dict->SetInteger("stream_id", stream_id); |
| 93 dict->SetBoolean("has_priority", has_priority); | 77 dict->SetBoolean("has_priority", has_priority); |
| 94 if (has_priority) { | 78 if (has_priority) { |
| 95 dict->SetInteger("parent_stream_id", parent_stream_id); | 79 dict->SetInteger("parent_stream_id", parent_stream_id); |
| 96 dict->SetInteger("weight", weight); | 80 dict->SetInteger("weight", weight); |
| 97 dict->SetBoolean("exclusive", exclusive); | 81 dict->SetBoolean("exclusive", exclusive); |
| 98 } | 82 } |
| 99 return std::move(dict); | 83 return std::move(dict); |
| 100 } | 84 } |
| 101 | 85 |
| 102 std::unique_ptr<base::Value> NetLogSpdySynStreamReceivedCallback( | |
| 103 const SpdyHeaderBlock* headers, | |
| 104 bool fin, | |
| 105 bool unidirectional, | |
| 106 SpdyPriority spdy_priority, | |
| 107 SpdyStreamId stream_id, | |
| 108 SpdyStreamId associated_stream, | |
| 109 NetLogCaptureMode capture_mode) { | |
| 110 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | |
| 111 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); | |
| 112 dict->SetBoolean("fin", fin); | |
| 113 dict->SetBoolean("unidirectional", unidirectional); | |
| 114 dict->SetInteger("priority", static_cast<int>(spdy_priority)); | |
| 115 dict->SetInteger("stream_id", stream_id); | |
| 116 dict->SetInteger("associated_stream", associated_stream); | |
| 117 return std::move(dict); | |
| 118 } | |
| 119 | |
| 120 std::unique_ptr<base::Value> NetLogSpdySynReplyOrHeadersReceivedCallback( | 86 std::unique_ptr<base::Value> NetLogSpdySynReplyOrHeadersReceivedCallback( |
| 121 const SpdyHeaderBlock* headers, | 87 const SpdyHeaderBlock* headers, |
| 122 bool fin, | 88 bool fin, |
| 123 SpdyStreamId stream_id, | 89 SpdyStreamId stream_id, |
| 124 NetLogCaptureMode capture_mode) { | 90 NetLogCaptureMode capture_mode) { |
| 125 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 91 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 126 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); | 92 dict->Set("headers", ElideSpdyHeaderBlockForNetLog(*headers, capture_mode)); |
| 127 dict->SetBoolean("fin", fin); | 93 dict->SetBoolean("fin", fin); |
| 128 dict->SetInteger("stream_id", stream_id); | 94 dict->SetInteger("stream_id", stream_id); |
| 129 return std::move(dict); | 95 return std::move(dict); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 143 const HostPortProxyPair* host_pair, | 109 const HostPortProxyPair* host_pair, |
| 144 NetLogCaptureMode /* capture_mode */) { | 110 NetLogCaptureMode /* capture_mode */) { |
| 145 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 111 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 146 dict->SetString("host", host_pair->first.ToString()); | 112 dict->SetString("host", host_pair->first.ToString()); |
| 147 dict->SetString("proxy", host_pair->second.ToPacString()); | 113 dict->SetString("proxy", host_pair->second.ToPacString()); |
| 148 return std::move(dict); | 114 return std::move(dict); |
| 149 } | 115 } |
| 150 | 116 |
| 151 std::unique_ptr<base::Value> NetLogSpdyInitializedCallback( | 117 std::unique_ptr<base::Value> NetLogSpdyInitializedCallback( |
| 152 NetLog::Source source, | 118 NetLog::Source source, |
| 153 const NextProto protocol_version, | |
| 154 NetLogCaptureMode /* capture_mode */) { | 119 NetLogCaptureMode /* capture_mode */) { |
| 155 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 120 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 156 if (source.IsValid()) { | 121 if (source.IsValid()) { |
| 157 source.AddToEventParameters(dict.get()); | 122 source.AddToEventParameters(dict.get()); |
| 158 } | 123 } |
| 159 dict->SetString("protocol", | 124 dict->SetString("protocol", SSLClientSocket::NextProtoToString(kProtoHTTP2)); |
| 160 SSLClientSocket::NextProtoToString(protocol_version)); | |
| 161 return std::move(dict); | 125 return std::move(dict); |
| 162 } | 126 } |
| 163 | 127 |
| 164 std::unique_ptr<base::Value> NetLogSpdySettingsCallback( | 128 std::unique_ptr<base::Value> NetLogSpdySettingsCallback( |
| 165 const HostPortPair& host_port_pair, | 129 const HostPortPair& host_port_pair, |
| 166 bool clear_persisted, | 130 bool clear_persisted, |
| 167 NetLogCaptureMode /* capture_mode */) { | 131 NetLogCaptureMode /* capture_mode */) { |
| 168 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 132 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 169 dict->SetString("host", host_port_pair.ToString()); | 133 dict->SetString("host", host_port_pair.ToString()); |
| 170 dict->SetBoolean("clear_persisted", clear_persisted); | 134 dict->SetBoolean("clear_persisted", clear_persisted); |
| 171 return std::move(dict); | 135 return std::move(dict); |
| 172 } | 136 } |
| 173 | 137 |
| 174 std::unique_ptr<base::Value> NetLogSpdySettingCallback( | 138 std::unique_ptr<base::Value> NetLogSpdySettingCallback( |
| 175 SpdySettingsIds id, | 139 SpdySettingsIds id, |
| 176 const SpdyMajorVersion protocol_version, | |
| 177 SpdySettingsFlags flags, | 140 SpdySettingsFlags flags, |
| 178 uint32_t value, | 141 uint32_t value, |
| 179 NetLogCaptureMode /* capture_mode */) { | 142 NetLogCaptureMode /* capture_mode */) { |
| 180 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 143 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 181 dict->SetInteger("id", | 144 dict->SetInteger("id", SpdyConstants::SerializeSettingId(HTTP2, id)); |
| 182 SpdyConstants::SerializeSettingId(protocol_version, id)); | |
| 183 dict->SetInteger("flags", flags); | 145 dict->SetInteger("flags", flags); |
| 184 dict->SetInteger("value", value); | 146 dict->SetInteger("value", value); |
| 185 return std::move(dict); | 147 return std::move(dict); |
| 186 } | 148 } |
| 187 | 149 |
| 188 std::unique_ptr<base::Value> NetLogSpdySendSettingsCallback( | 150 std::unique_ptr<base::Value> NetLogSpdySendSettingsCallback( |
| 189 const SettingsMap* settings, | 151 const SettingsMap* settings, |
| 190 const SpdyMajorVersion protocol_version, | |
| 191 NetLogCaptureMode /* capture_mode */) { | 152 NetLogCaptureMode /* capture_mode */) { |
| 192 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 153 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 193 std::unique_ptr<base::ListValue> settings_list(new base::ListValue()); | 154 std::unique_ptr<base::ListValue> settings_list(new base::ListValue()); |
| 194 for (SettingsMap::const_iterator it = settings->begin(); | 155 for (SettingsMap::const_iterator it = settings->begin(); |
| 195 it != settings->end(); ++it) { | 156 it != settings->end(); ++it) { |
| 196 const SpdySettingsIds id = it->first; | 157 const SpdySettingsIds id = it->first; |
| 197 const SpdySettingsFlags flags = it->second.first; | 158 const SpdySettingsFlags flags = it->second.first; |
| 198 const uint32_t value = it->second.second; | 159 const uint32_t value = it->second.second; |
| 199 settings_list->AppendString(base::StringPrintf( | 160 settings_list->AppendString(base::StringPrintf( |
| 200 "[id:%u flags:%u value:%u]", | 161 "[id:%u flags:%u value:%u]", |
| 201 SpdyConstants::SerializeSettingId(protocol_version, id), flags, value)); | 162 SpdyConstants::SerializeSettingId(HTTP2, id), flags, value)); |
| 202 } | 163 } |
| 203 dict->Set("settings", std::move(settings_list)); | 164 dict->Set("settings", std::move(settings_list)); |
| 204 return std::move(dict); | 165 return std::move(dict); |
| 205 } | 166 } |
| 206 | 167 |
| 207 std::unique_ptr<base::Value> NetLogSpdyWindowUpdateFrameCallback( | 168 std::unique_ptr<base::Value> NetLogSpdyWindowUpdateFrameCallback( |
| 208 SpdyStreamId stream_id, | 169 SpdyStreamId stream_id, |
| 209 uint32_t delta, | 170 uint32_t delta, |
| 210 NetLogCaptureMode /* capture_mode */) { | 171 NetLogCaptureMode /* capture_mode */) { |
| 211 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 172 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 return GOAWAY_FRAME_SIZE_ERROR; | 426 return GOAWAY_FRAME_SIZE_ERROR; |
| 466 case ERR_SPDY_COMPRESSION_ERROR: | 427 case ERR_SPDY_COMPRESSION_ERROR: |
| 467 return GOAWAY_COMPRESSION_ERROR; | 428 return GOAWAY_COMPRESSION_ERROR; |
| 468 case ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY: | 429 case ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY: |
| 469 return GOAWAY_INADEQUATE_SECURITY; | 430 return GOAWAY_INADEQUATE_SECURITY; |
| 470 default: | 431 default: |
| 471 return GOAWAY_PROTOCOL_ERROR; | 432 return GOAWAY_PROTOCOL_ERROR; |
| 472 } | 433 } |
| 473 } | 434 } |
| 474 | 435 |
| 475 void SplitPushedHeadersToRequestAndResponse(const SpdyHeaderBlock& headers, | |
| 476 SpdyMajorVersion protocol_version, | |
| 477 SpdyHeaderBlock* request_headers, | |
| 478 SpdyHeaderBlock* response_headers) { | |
| 479 DCHECK(response_headers); | |
| 480 DCHECK(request_headers); | |
| 481 for (SpdyHeaderBlock::const_iterator it = headers.begin(); | |
| 482 it != headers.end(); | |
| 483 ++it) { | |
| 484 SpdyHeaderBlock* to_insert = response_headers; | |
| 485 const char* host = protocol_version >= HTTP2 ? ":authority" : ":host"; | |
| 486 static const char scheme[] = ":scheme"; | |
| 487 static const char path[] = ":path"; | |
| 488 if (it->first == host || it->first == scheme || it->first == path) { | |
| 489 to_insert = request_headers; | |
| 490 } | |
| 491 to_insert->insert(*it); | |
| 492 } | |
| 493 } | |
| 494 | |
| 495 SpdyStreamRequest::SpdyStreamRequest() : weak_ptr_factory_(this) { | 436 SpdyStreamRequest::SpdyStreamRequest() : weak_ptr_factory_(this) { |
| 496 Reset(); | 437 Reset(); |
| 497 } | 438 } |
| 498 | 439 |
| 499 SpdyStreamRequest::~SpdyStreamRequest() { | 440 SpdyStreamRequest::~SpdyStreamRequest() { |
| 500 CancelRequest(); | 441 CancelRequest(); |
| 501 } | 442 } |
| 502 | 443 |
| 503 int SpdyStreamRequest::StartRequest( | 444 int SpdyStreamRequest::StartRequest( |
| 504 SpdyStreamType type, | 445 SpdyStreamType type, |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 return true; | 621 return true; |
| 681 } | 622 } |
| 682 | 623 |
| 683 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key, | 624 SpdySession::SpdySession(const SpdySessionKey& spdy_session_key, |
| 684 HttpServerProperties* http_server_properties, | 625 HttpServerProperties* http_server_properties, |
| 685 TransportSecurityState* transport_security_state, | 626 TransportSecurityState* transport_security_state, |
| 686 bool verify_domain_authentication, | 627 bool verify_domain_authentication, |
| 687 bool enable_sending_initial_data, | 628 bool enable_sending_initial_data, |
| 688 bool enable_ping_based_connection_checking, | 629 bool enable_ping_based_connection_checking, |
| 689 bool enable_priority_dependencies, | 630 bool enable_priority_dependencies, |
| 690 NextProto default_protocol, | |
| 691 size_t session_max_recv_window_size, | 631 size_t session_max_recv_window_size, |
| 692 size_t stream_max_recv_window_size, | 632 size_t stream_max_recv_window_size, |
| 693 TimeFunc time_func, | 633 TimeFunc time_func, |
| 694 ProxyDelegate* proxy_delegate, | 634 ProxyDelegate* proxy_delegate, |
| 695 NetLog* net_log) | 635 NetLog* net_log) |
| 696 : in_io_loop_(false), | 636 : in_io_loop_(false), |
| 697 spdy_session_key_(spdy_session_key), | 637 spdy_session_key_(spdy_session_key), |
| 698 pool_(NULL), | 638 pool_(NULL), |
| 699 http_server_properties_(http_server_properties), | 639 http_server_properties_(http_server_properties), |
| 700 transport_security_state_(transport_security_state), | 640 transport_security_state_(transport_security_state), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 720 streams_abandoned_count_(0), | 660 streams_abandoned_count_(0), |
| 721 total_bytes_received_(0), | 661 total_bytes_received_(0), |
| 722 sent_settings_(false), | 662 sent_settings_(false), |
| 723 received_settings_(false), | 663 received_settings_(false), |
| 724 stalled_streams_(0), | 664 stalled_streams_(0), |
| 725 pings_in_flight_(0), | 665 pings_in_flight_(0), |
| 726 next_ping_id_(1), | 666 next_ping_id_(1), |
| 727 last_activity_time_(time_func()), | 667 last_activity_time_(time_func()), |
| 728 last_compressed_frame_len_(0), | 668 last_compressed_frame_len_(0), |
| 729 check_ping_status_pending_(false), | 669 check_ping_status_pending_(false), |
| 730 send_connection_header_prefix_(false), | |
| 731 session_send_window_size_(0), | 670 session_send_window_size_(0), |
| 732 session_max_recv_window_size_(session_max_recv_window_size), | 671 session_max_recv_window_size_(session_max_recv_window_size), |
| 733 session_recv_window_size_(0), | 672 session_recv_window_size_(0), |
| 734 session_unacked_recv_window_bytes_(0), | 673 session_unacked_recv_window_bytes_(0), |
| 735 stream_initial_send_window_size_( | 674 stream_initial_send_window_size_(kDefaultInitialWindowSize), |
| 736 GetDefaultInitialWindowSize(default_protocol)), | |
| 737 stream_max_recv_window_size_(stream_max_recv_window_size), | 675 stream_max_recv_window_size_(stream_max_recv_window_size), |
| 738 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP2_SESSION)), | 676 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP2_SESSION)), |
| 739 verify_domain_authentication_(verify_domain_authentication), | 677 verify_domain_authentication_(verify_domain_authentication), |
| 740 enable_sending_initial_data_(enable_sending_initial_data), | 678 enable_sending_initial_data_(enable_sending_initial_data), |
| 741 enable_ping_based_connection_checking_( | 679 enable_ping_based_connection_checking_( |
| 742 enable_ping_based_connection_checking), | 680 enable_ping_based_connection_checking), |
| 743 protocol_(default_protocol), | |
| 744 connection_at_risk_of_loss_time_( | 681 connection_at_risk_of_loss_time_( |
| 745 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), | 682 base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)), |
| 746 hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), | 683 hung_interval_(base::TimeDelta::FromSeconds(kHungIntervalSeconds)), |
| 747 proxy_delegate_(proxy_delegate), | 684 proxy_delegate_(proxy_delegate), |
| 748 time_func_(time_func), | 685 time_func_(time_func), |
| 749 priority_dependencies_enabled_(enable_priority_dependencies), | 686 priority_dependencies_enabled_(enable_priority_dependencies), |
| 750 weak_factory_(this) { | 687 weak_factory_(this) { |
| 751 DCHECK_GE(protocol_, kProtoSPDYMinimumVersion); | |
| 752 DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); | |
| 753 DCHECK(HttpStreamFactory::spdy_enabled()); | 688 DCHECK(HttpStreamFactory::spdy_enabled()); |
| 754 net_log_.BeginEvent( | 689 net_log_.BeginEvent( |
| 755 NetLog::TYPE_HTTP2_SESSION, | 690 NetLog::TYPE_HTTP2_SESSION, |
| 756 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); | 691 base::Bind(&NetLogSpdySessionCallback, &host_port_proxy_pair())); |
| 757 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 692 next_unclaimed_push_stream_sweep_time_ = time_func_() + |
| 758 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 693 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 759 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. | 694 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. |
| 760 } | 695 } |
| 761 | 696 |
| 762 SpdySession::~SpdySession() { | 697 SpdySession::~SpdySession() { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 788 DCHECK(certificate_error_code == OK || | 723 DCHECK(certificate_error_code == OK || |
| 789 certificate_error_code < ERR_IO_PENDING); | 724 certificate_error_code < ERR_IO_PENDING); |
| 790 // TODO(akalin): Check connection->is_initialized() instead. This | 725 // TODO(akalin): Check connection->is_initialized() instead. This |
| 791 // requires re-working CreateFakeSpdySession(), though. | 726 // requires re-working CreateFakeSpdySession(), though. |
| 792 DCHECK(connection->socket()); | 727 DCHECK(connection->socket()); |
| 793 | 728 |
| 794 connection_ = std::move(connection); | 729 connection_ = std::move(connection); |
| 795 is_secure_ = is_secure; | 730 is_secure_ = is_secure; |
| 796 certificate_error_code_ = certificate_error_code; | 731 certificate_error_code_ = certificate_error_code; |
| 797 | 732 |
| 798 NextProto protocol_negotiated = | 733 session_send_window_size_ = kDefaultInitialWindowSize; |
| 799 connection_->socket()->GetNegotiatedProtocol(); | 734 session_recv_window_size_ = kDefaultInitialWindowSize; |
| 800 if (protocol_negotiated != kProtoUnknown) { | |
| 801 protocol_ = protocol_negotiated; | |
| 802 stream_initial_send_window_size_ = GetDefaultInitialWindowSize(protocol_); | |
| 803 } | |
| 804 DCHECK_GE(protocol_, kProtoSPDYMinimumVersion); | |
| 805 DCHECK_LE(protocol_, kProtoSPDYMaximumVersion); | |
| 806 | 735 |
| 807 if (protocol_ == kProtoHTTP2) | 736 buffered_spdy_framer_.reset(new BufferedSpdyFramer()); |
| 808 send_connection_header_prefix_ = true; | |
| 809 | |
| 810 session_send_window_size_ = GetDefaultInitialWindowSize(protocol_); | |
| 811 session_recv_window_size_ = GetDefaultInitialWindowSize(protocol_); | |
| 812 | |
| 813 buffered_spdy_framer_.reset( | |
| 814 new BufferedSpdyFramer(NextProtoToSpdyMajorVersion(protocol_))); | |
| 815 buffered_spdy_framer_->set_visitor(this); | 737 buffered_spdy_framer_->set_visitor(this); |
| 816 buffered_spdy_framer_->set_debug_visitor(this); | 738 buffered_spdy_framer_->set_debug_visitor(this); |
| 817 UMA_HISTOGRAM_ENUMERATION( | |
| 818 "Net.SpdyVersion3", protocol_ - kProtoSPDYHistogramOffset, | |
| 819 kProtoSPDYMaximumVersion - kProtoSPDYHistogramOffset + 1); | |
| 820 | 739 |
| 821 net_log_.AddEvent( | 740 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_INITIALIZED, |
| 822 NetLog::TYPE_HTTP2_SESSION_INITIALIZED, | 741 base::Bind(&NetLogSpdyInitializedCallback, |
| 823 base::Bind(&NetLogSpdyInitializedCallback, | 742 connection_->socket()->NetLog().source())); |
| 824 connection_->socket()->NetLog().source(), protocol_)); | |
| 825 | 743 |
| 826 DCHECK_EQ(availability_state_, STATE_AVAILABLE); | 744 DCHECK_EQ(availability_state_, STATE_AVAILABLE); |
| 827 connection_->AddHigherLayeredPool(this); | 745 connection_->AddHigherLayeredPool(this); |
| 828 if (enable_sending_initial_data_) | 746 if (enable_sending_initial_data_) |
| 829 SendInitialData(); | 747 SendInitialData(); |
| 830 pool_ = pool; | 748 pool_ = pool; |
| 831 | 749 |
| 832 // Bootstrap the read loop. | 750 // Bootstrap the read loop. |
| 833 base::ThreadTaskRunnerHandle::Get()->PostTask( | 751 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 834 FROM_HERE, | 752 FROM_HERE, |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1027 base::ThreadTaskRunnerHandle::Get()->PostTask( | 945 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 1028 FROM_HERE, base::Bind(&SpdySession::CompleteStreamRequest, | 946 FROM_HERE, base::Bind(&SpdySession::CompleteStreamRequest, |
| 1029 weak_factory_.GetWeakPtr(), pending_request)); | 947 weak_factory_.GetWeakPtr(), pending_request)); |
| 1030 } | 948 } |
| 1031 } | 949 } |
| 1032 | 950 |
| 1033 void SpdySession::AddPooledAlias(const SpdySessionKey& alias_key) { | 951 void SpdySession::AddPooledAlias(const SpdySessionKey& alias_key) { |
| 1034 pooled_aliases_.insert(alias_key); | 952 pooled_aliases_.insert(alias_key); |
| 1035 } | 953 } |
| 1036 | 954 |
| 1037 SpdyMajorVersion SpdySession::GetProtocolVersion() const { | |
| 1038 DCHECK(buffered_spdy_framer_.get()); | |
| 1039 return buffered_spdy_framer_->protocol_version(); | |
| 1040 } | |
| 1041 | |
| 1042 bool SpdySession::HasAcceptableTransportSecurity() const { | 955 bool SpdySession::HasAcceptableTransportSecurity() const { |
| 1043 // If we're not even using TLS, we have no standards to meet. | 956 // If we're not even using TLS, we have no standards to meet. |
| 1044 if (!is_secure_) { | 957 if (!is_secure_) { |
| 1045 return true; | 958 return true; |
| 1046 } | 959 } |
| 1047 | 960 |
| 1048 // We don't enforce transport security standards for older SPDY versions. | |
| 1049 if (GetProtocolVersion() < HTTP2) { | |
| 1050 return true; | |
| 1051 } | |
| 1052 | |
| 1053 SSLInfo ssl_info; | 961 SSLInfo ssl_info; |
| 1054 CHECK(connection_->socket()->GetSSLInfo(&ssl_info)); | 962 CHECK(connection_->socket()->GetSSLInfo(&ssl_info)); |
| 1055 | 963 |
| 1056 // HTTP/2 requires TLS 1.2+ | 964 // HTTP/2 requires TLS 1.2+ |
| 1057 if (SSLConnectionStatusToVersion(ssl_info.connection_status) < | 965 if (SSLConnectionStatusToVersion(ssl_info.connection_status) < |
| 1058 SSL_CONNECTION_VERSION_TLS1_2) { | 966 SSL_CONNECTION_VERSION_TLS1_2) { |
| 1059 return false; | 967 return false; |
| 1060 } | 968 } |
| 1061 | 969 |
| 1062 if (!IsTLSCipherSuiteAllowedByHTTP2( | 970 if (!IsTLSCipherSuiteAllowedByHTTP2( |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 RequestPriority priority, | 1004 RequestPriority priority, |
| 1097 SpdyControlFlags flags, | 1005 SpdyControlFlags flags, |
| 1098 SpdyHeaderBlock block) { | 1006 SpdyHeaderBlock block) { |
| 1099 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 1007 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 1100 CHECK(it != active_streams_.end()); | 1008 CHECK(it != active_streams_.end()); |
| 1101 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 1009 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 1102 | 1010 |
| 1103 SendPrefacePingIfNoneInFlight(); | 1011 SendPrefacePingIfNoneInFlight(); |
| 1104 | 1012 |
| 1105 DCHECK(buffered_spdy_framer_.get()); | 1013 DCHECK(buffered_spdy_framer_.get()); |
| 1106 SpdyPriority spdy_priority = | 1014 SpdyPriority spdy_priority = ConvertRequestPriorityToSpdyPriority(priority); |
| 1107 ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()); | |
| 1108 | 1015 |
| 1109 std::unique_ptr<SpdySerializedFrame> syn_frame; | 1016 std::unique_ptr<SpdySerializedFrame> syn_frame; |
| 1110 if (GetProtocolVersion() <= SPDY3) { | 1017 bool has_priority = true; |
| 1111 if (net_log().IsCapturing()) { | 1018 int weight = Spdy3PriorityToHttp2Weight(spdy_priority); |
| 1112 net_log().AddEvent(NetLog::TYPE_HTTP2_SESSION_SYN_STREAM, | 1019 SpdyStreamId dependent_stream_id = 0; |
| 1113 base::Bind(&NetLogSpdySynStreamSentCallback, &block, | 1020 bool exclusive = false; |
| 1114 (flags & CONTROL_FLAG_FIN) != 0, | |
| 1115 (flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0, | |
| 1116 spdy_priority, stream_id)); | |
| 1117 } | |
| 1118 | 1021 |
| 1119 SpdySynStreamIR syn_stream(stream_id, std::move(block)); | 1022 if (priority_dependencies_enabled_) { |
| 1120 syn_stream.set_associated_to_stream_id(0); | 1023 priority_dependency_state_.OnStreamSynSent( |
| 1121 syn_stream.set_priority(spdy_priority); | 1024 stream_id, spdy_priority, &dependent_stream_id, &exclusive); |
| 1122 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); | 1025 } |
| 1123 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); | |
| 1124 syn_frame.reset(new SpdySerializedFrame( | |
| 1125 buffered_spdy_framer_->SerializeFrame(syn_stream))); | |
| 1126 | 1026 |
| 1127 } else { | 1027 if (net_log().IsCapturing()) { |
| 1128 bool has_priority = true; | 1028 net_log().AddEvent( |
| 1129 int weight = Spdy3PriorityToHttp2Weight(spdy_priority); | 1029 NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS, |
| 1130 SpdyStreamId dependent_stream_id = 0; | 1030 base::Bind(&NetLogSpdyHeadersSentCallback, &block, |
| 1131 bool exclusive = false; | 1031 (flags & CONTROL_FLAG_FIN) != 0, stream_id, has_priority, |
| 1032 weight, dependent_stream_id, exclusive)); |
| 1033 } |
| 1132 | 1034 |
| 1133 if (priority_dependencies_enabled_) { | 1035 SpdyHeadersIR headers(stream_id, std::move(block)); |
| 1134 priority_dependency_state_.OnStreamSynSent( | 1036 headers.set_has_priority(has_priority); |
| 1135 stream_id, spdy_priority, &dependent_stream_id, &exclusive); | 1037 headers.set_weight(weight); |
| 1136 } | 1038 headers.set_parent_stream_id(dependent_stream_id); |
| 1137 | 1039 headers.set_exclusive(exclusive); |
| 1138 if (net_log().IsCapturing()) { | 1040 headers.set_fin((flags & CONTROL_FLAG_FIN) != 0); |
| 1139 net_log().AddEvent( | 1041 syn_frame.reset( |
| 1140 NetLog::TYPE_HTTP2_SESSION_SEND_HEADERS, | 1042 new SpdySerializedFrame(buffered_spdy_framer_->SerializeFrame(headers))); |
| 1141 base::Bind(&NetLogSpdyHeadersSentCallback, &block, | |
| 1142 (flags & CONTROL_FLAG_FIN) != 0, stream_id, has_priority, | |
| 1143 weight, dependent_stream_id, exclusive)); | |
| 1144 } | |
| 1145 | |
| 1146 SpdyHeadersIR headers(stream_id, std::move(block)); | |
| 1147 headers.set_has_priority(has_priority); | |
| 1148 headers.set_weight(weight); | |
| 1149 headers.set_parent_stream_id(dependent_stream_id); | |
| 1150 headers.set_exclusive(exclusive); | |
| 1151 headers.set_fin((flags & CONTROL_FLAG_FIN) != 0); | |
| 1152 syn_frame.reset(new SpdySerializedFrame( | |
| 1153 buffered_spdy_framer_->SerializeFrame(headers))); | |
| 1154 } | |
| 1155 | 1043 |
| 1156 streams_initiated_count_++; | 1044 streams_initiated_count_++; |
| 1157 | 1045 |
| 1158 return syn_frame; | 1046 return syn_frame; |
| 1159 } | 1047 } |
| 1160 | 1048 |
| 1161 std::unique_ptr<SpdyBuffer> SpdySession::CreateDataBuffer( | 1049 std::unique_ptr<SpdyBuffer> SpdySession::CreateDataBuffer( |
| 1162 SpdyStreamId stream_id, | 1050 SpdyStreamId stream_id, |
| 1163 IOBuffer* data, | 1051 IOBuffer* data, |
| 1164 int len, | 1052 int len, |
| (...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2219 | 2107 |
| 2220 if (clear_persisted) | 2108 if (clear_persisted) |
| 2221 http_server_properties_->ClearSpdySettings(GetServer()); | 2109 http_server_properties_->ClearSpdySettings(GetServer()); |
| 2222 | 2110 |
| 2223 if (net_log_.IsCapturing()) { | 2111 if (net_log_.IsCapturing()) { |
| 2224 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTINGS, | 2112 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTINGS, |
| 2225 base::Bind(&NetLogSpdySettingsCallback, host_port_pair(), | 2113 base::Bind(&NetLogSpdySettingsCallback, host_port_pair(), |
| 2226 clear_persisted)); | 2114 clear_persisted)); |
| 2227 } | 2115 } |
| 2228 | 2116 |
| 2229 if (GetProtocolVersion() >= HTTP2) { | 2117 // Send an acknowledgment of the setting. |
| 2230 // Send an acknowledgment of the setting. | 2118 SpdySettingsIR settings_ir; |
| 2231 SpdySettingsIR settings_ir; | 2119 settings_ir.set_is_ack(true); |
| 2232 settings_ir.set_is_ack(true); | 2120 EnqueueSessionWrite( |
| 2233 EnqueueSessionWrite( | 2121 HIGHEST, SETTINGS, |
| 2234 HIGHEST, SETTINGS, | 2122 std::unique_ptr<SpdySerializedFrame>(new SpdySerializedFrame( |
| 2235 std::unique_ptr<SpdySerializedFrame>(new SpdySerializedFrame( | 2123 buffered_spdy_framer_->SerializeFrame(settings_ir)))); |
| 2236 buffered_spdy_framer_->SerializeFrame(settings_ir)))); | |
| 2237 } | |
| 2238 } | 2124 } |
| 2239 | 2125 |
| 2240 void SpdySession::OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) { | 2126 void SpdySession::OnSetting(SpdySettingsIds id, uint8_t flags, uint32_t value) { |
| 2241 CHECK(in_io_loop_); | 2127 CHECK(in_io_loop_); |
| 2242 | 2128 |
| 2243 HandleSetting(id, value); | 2129 HandleSetting(id, value); |
| 2244 http_server_properties_->SetSpdySetting( | 2130 http_server_properties_->SetSpdySetting( |
| 2245 GetServer(), id, static_cast<SpdySettingsFlags>(flags), value); | 2131 GetServer(), id, static_cast<SpdySettingsFlags>(flags), value); |
| 2246 received_settings_ = true; | 2132 received_settings_ = true; |
| 2247 | 2133 |
| 2248 // Log the setting. | 2134 // Log the setting. |
| 2249 const SpdyMajorVersion protocol_version = GetProtocolVersion(); | |
| 2250 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTING, | 2135 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_RECV_SETTING, |
| 2251 base::Bind(&NetLogSpdySettingCallback, id, protocol_version, | 2136 base::Bind(&NetLogSpdySettingCallback, id, |
| 2252 static_cast<SpdySettingsFlags>(flags), value)); | 2137 static_cast<SpdySettingsFlags>(flags), value)); |
| 2253 } | 2138 } |
| 2254 | 2139 |
| 2255 void SpdySession::OnSendCompressedFrame( | 2140 void SpdySession::OnSendCompressedFrame( |
| 2256 SpdyStreamId stream_id, | 2141 SpdyStreamId stream_id, |
| 2257 SpdyFrameType type, | 2142 SpdyFrameType type, |
| 2258 size_t payload_len, | 2143 size_t payload_len, |
| 2259 size_t frame_len) { | 2144 size_t frame_len) { |
| 2260 if (type != SYN_STREAM && type != HEADERS) | 2145 if (type != SYN_STREAM && type != HEADERS) |
| 2261 return; | 2146 return; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2307 int rv = stream->OnInitialResponseHeadersReceived( | 2192 int rv = stream->OnInitialResponseHeadersReceived( |
| 2308 response_headers, response_time, recv_first_byte_time); | 2193 response_headers, response_time, recv_first_byte_time); |
| 2309 if (rv < 0) { | 2194 if (rv < 0) { |
| 2310 DCHECK_NE(rv, ERR_IO_PENDING); | 2195 DCHECK_NE(rv, ERR_IO_PENDING); |
| 2311 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); | 2196 DCHECK(active_streams_.find(stream_id) == active_streams_.end()); |
| 2312 } | 2197 } |
| 2313 | 2198 |
| 2314 return rv; | 2199 return rv; |
| 2315 } | 2200 } |
| 2316 | 2201 |
| 2317 void SpdySession::OnSynStream(SpdyStreamId stream_id, | |
| 2318 SpdyStreamId associated_stream_id, | |
| 2319 SpdyPriority priority, | |
| 2320 bool fin, | |
| 2321 bool unidirectional, | |
| 2322 const SpdyHeaderBlock& headers) { | |
| 2323 CHECK(in_io_loop_); | |
| 2324 | |
| 2325 DCHECK_LE(GetProtocolVersion(), SPDY3); | |
| 2326 | |
| 2327 base::Time response_time = base::Time::Now(); | |
| 2328 base::TimeTicks recv_first_byte_time = time_func_(); | |
| 2329 | |
| 2330 if (net_log_.IsCapturing()) { | |
| 2331 net_log_.AddEvent( | |
| 2332 NetLog::TYPE_HTTP2_SESSION_PUSHED_SYN_STREAM, | |
| 2333 base::Bind(&NetLogSpdySynStreamReceivedCallback, &headers, fin, | |
| 2334 unidirectional, priority, stream_id, associated_stream_id)); | |
| 2335 } | |
| 2336 | |
| 2337 // Split headers to simulate push promise and response. | |
| 2338 SpdyHeaderBlock request_headers; | |
| 2339 SpdyHeaderBlock response_headers; | |
| 2340 SplitPushedHeadersToRequestAndResponse( | |
| 2341 headers, GetProtocolVersion(), &request_headers, &response_headers); | |
| 2342 | |
| 2343 if (!TryCreatePushStream( | |
| 2344 stream_id, associated_stream_id, priority, request_headers)) | |
| 2345 return; | |
| 2346 | |
| 2347 ActiveStreamMap::iterator active_it = active_streams_.find(stream_id); | |
| 2348 if (active_it == active_streams_.end()) { | |
| 2349 NOTREACHED(); | |
| 2350 return; | |
| 2351 } | |
| 2352 | |
| 2353 OnInitialResponseHeadersReceived(response_headers, response_time, | |
| 2354 recv_first_byte_time, | |
| 2355 active_it->second.stream); | |
| 2356 } | |
| 2357 | |
| 2358 void SpdySession::DeleteExpiredPushedStreams() { | 2202 void SpdySession::DeleteExpiredPushedStreams() { |
| 2359 if (unclaimed_pushed_streams_.empty()) | 2203 if (unclaimed_pushed_streams_.empty()) |
| 2360 return; | 2204 return; |
| 2361 | 2205 |
| 2362 // Check that adequate time has elapsed since the last sweep. | 2206 // Check that adequate time has elapsed since the last sweep. |
| 2363 if (time_func_() < next_unclaimed_push_stream_sweep_time_) | 2207 if (time_func_() < next_unclaimed_push_stream_sweep_time_) |
| 2364 return; | 2208 return; |
| 2365 | 2209 |
| 2366 // Gather old streams to delete. | 2210 // Gather old streams to delete. |
| 2367 base::TimeTicks minimum_freshness = time_func_() - | 2211 base::TimeTicks minimum_freshness = time_func_() - |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2385 // CloseActiveStreamIterator() will remove the stream from | 2229 // CloseActiveStreamIterator() will remove the stream from |
| 2386 // |unclaimed_pushed_streams_|. | 2230 // |unclaimed_pushed_streams_|. |
| 2387 ResetStreamIterator( | 2231 ResetStreamIterator( |
| 2388 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); | 2232 active_it, RST_STREAM_REFUSED_STREAM, "Stream not claimed."); |
| 2389 } | 2233 } |
| 2390 | 2234 |
| 2391 next_unclaimed_push_stream_sweep_time_ = time_func_() + | 2235 next_unclaimed_push_stream_sweep_time_ = time_func_() + |
| 2392 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); | 2236 base::TimeDelta::FromSeconds(kMinPushedStreamLifetimeSeconds); |
| 2393 } | 2237 } |
| 2394 | 2238 |
| 2395 void SpdySession::OnSynReply(SpdyStreamId stream_id, | |
| 2396 bool fin, | |
| 2397 const SpdyHeaderBlock& headers) { | |
| 2398 CHECK(in_io_loop_); | |
| 2399 | |
| 2400 base::Time response_time = base::Time::Now(); | |
| 2401 base::TimeTicks recv_first_byte_time = time_func_(); | |
| 2402 | |
| 2403 if (net_log().IsCapturing()) { | |
| 2404 net_log().AddEvent(NetLog::TYPE_HTTP2_SESSION_SYN_REPLY, | |
| 2405 base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback, | |
| 2406 &headers, fin, stream_id)); | |
| 2407 } | |
| 2408 | |
| 2409 ActiveStreamMap::iterator it = active_streams_.find(stream_id); | |
| 2410 if (it == active_streams_.end()) { | |
| 2411 // NOTE: it may just be that the stream was cancelled. | |
| 2412 return; | |
| 2413 } | |
| 2414 | |
| 2415 SpdyStream* stream = it->second.stream; | |
| 2416 CHECK_EQ(stream->stream_id(), stream_id); | |
| 2417 | |
| 2418 stream->AddRawReceivedBytes(last_compressed_frame_len_); | |
| 2419 last_compressed_frame_len_ = 0; | |
| 2420 | |
| 2421 if (GetProtocolVersion() >= HTTP2) { | |
| 2422 const std::string& error = "HTTP/2 wasn't expecting SYN_REPLY."; | |
| 2423 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | |
| 2424 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | |
| 2425 return; | |
| 2426 } | |
| 2427 if (!it->second.waiting_for_syn_reply) { | |
| 2428 const std::string& error = | |
| 2429 "Received duplicate SYN_REPLY for stream."; | |
| 2430 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | |
| 2431 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | |
| 2432 return; | |
| 2433 } | |
| 2434 it->second.waiting_for_syn_reply = false; | |
| 2435 | |
| 2436 ignore_result(OnInitialResponseHeadersReceived( | |
| 2437 headers, response_time, recv_first_byte_time, stream)); | |
| 2438 } | |
| 2439 | |
| 2440 void SpdySession::OnHeaders(SpdyStreamId stream_id, | 2239 void SpdySession::OnHeaders(SpdyStreamId stream_id, |
| 2441 bool has_priority, | 2240 bool has_priority, |
| 2442 int weight, | 2241 int weight, |
| 2443 SpdyStreamId parent_stream_id, | 2242 SpdyStreamId parent_stream_id, |
| 2444 bool exclusive, | 2243 bool exclusive, |
| 2445 bool fin, | 2244 bool fin, |
| 2446 const SpdyHeaderBlock& headers) { | 2245 const SpdyHeaderBlock& headers) { |
| 2447 CHECK(in_io_loop_); | 2246 CHECK(in_io_loop_); |
| 2448 | 2247 |
| 2449 if (net_log().IsCapturing()) { | 2248 if (net_log().IsCapturing()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2462 SpdyStream* stream = it->second.stream; | 2261 SpdyStream* stream = it->second.stream; |
| 2463 CHECK_EQ(stream->stream_id(), stream_id); | 2262 CHECK_EQ(stream->stream_id(), stream_id); |
| 2464 | 2263 |
| 2465 stream->AddRawReceivedBytes(last_compressed_frame_len_); | 2264 stream->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2466 last_compressed_frame_len_ = 0; | 2265 last_compressed_frame_len_ = 0; |
| 2467 | 2266 |
| 2468 base::Time response_time = base::Time::Now(); | 2267 base::Time response_time = base::Time::Now(); |
| 2469 base::TimeTicks recv_first_byte_time = time_func_(); | 2268 base::TimeTicks recv_first_byte_time = time_func_(); |
| 2470 | 2269 |
| 2471 if (it->second.waiting_for_syn_reply) { | 2270 if (it->second.waiting_for_syn_reply) { |
| 2472 if (GetProtocolVersion() < HTTP2) { | |
| 2473 const std::string& error = | |
| 2474 "Was expecting SYN_REPLY, not HEADERS."; | |
| 2475 stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error); | |
| 2476 ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, error); | |
| 2477 return; | |
| 2478 } | |
| 2479 | |
| 2480 it->second.waiting_for_syn_reply = false; | 2271 it->second.waiting_for_syn_reply = false; |
| 2481 ignore_result(OnInitialResponseHeadersReceived( | 2272 ignore_result(OnInitialResponseHeadersReceived( |
| 2482 headers, response_time, recv_first_byte_time, stream)); | 2273 headers, response_time, recv_first_byte_time, stream)); |
| 2483 } else if (it->second.stream->IsReservedRemote()) { | 2274 } else if (it->second.stream->IsReservedRemote()) { |
| 2484 ignore_result(OnInitialResponseHeadersReceived( | 2275 ignore_result(OnInitialResponseHeadersReceived( |
| 2485 headers, response_time, recv_first_byte_time, stream)); | 2276 headers, response_time, recv_first_byte_time, stream)); |
| 2486 } else { | 2277 } else { |
| 2487 int rv = stream->OnAdditionalResponseHeadersReceived(headers); | 2278 int rv = stream->OnAdditionalResponseHeadersReceived(headers); |
| 2488 if (rv < 0) { | 2279 if (rv < 0) { |
| 2489 DCHECK_NE(rv, ERR_IO_PENDING); | 2280 DCHECK_NE(rv, ERR_IO_PENDING); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2627 } | 2418 } |
| 2628 | 2419 |
| 2629 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { | 2420 void SpdySession::OnPing(SpdyPingId unique_id, bool is_ack) { |
| 2630 CHECK(in_io_loop_); | 2421 CHECK(in_io_loop_); |
| 2631 | 2422 |
| 2632 net_log_.AddEvent( | 2423 net_log_.AddEvent( |
| 2633 NetLog::TYPE_HTTP2_SESSION_PING, | 2424 NetLog::TYPE_HTTP2_SESSION_PING, |
| 2634 base::Bind(&NetLogSpdyPingCallback, unique_id, is_ack, "received")); | 2425 base::Bind(&NetLogSpdyPingCallback, unique_id, is_ack, "received")); |
| 2635 | 2426 |
| 2636 // Send response to a PING from server. | 2427 // Send response to a PING from server. |
| 2637 if ((protocol_ == kProtoHTTP2 && !is_ack) || | 2428 if (!is_ack) { |
| 2638 (protocol_ < kProtoHTTP2 && unique_id % 2 == 0)) { | |
| 2639 WritePingFrame(unique_id, true); | 2429 WritePingFrame(unique_id, true); |
| 2640 return; | 2430 return; |
| 2641 } | 2431 } |
| 2642 | 2432 |
| 2643 --pings_in_flight_; | 2433 --pings_in_flight_; |
| 2644 if (pings_in_flight_ < 0) { | 2434 if (pings_in_flight_ < 0) { |
| 2645 RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING); | 2435 RecordProtocolErrorHistogram(PROTOCOL_ERROR_UNEXPECTED_PING); |
| 2646 DoDrainSession(ERR_SPDY_PROTOCOL_ERROR, "pings_in_flight_ is < 0."); | 2436 DoDrainSession(ERR_SPDY_PROTOCOL_ERROR, "pings_in_flight_ is < 0."); |
| 2647 pings_in_flight_ = 0; | 2437 pings_in_flight_ = 0; |
| 2648 return; | 2438 return; |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2724 if (stream_id <= last_accepted_push_stream_id_) { | 2514 if (stream_id <= last_accepted_push_stream_id_) { |
| 2725 LOG(WARNING) << "Received push stream id lesser or equal to the last " | 2515 LOG(WARNING) << "Received push stream id lesser or equal to the last " |
| 2726 << "accepted before " << stream_id; | 2516 << "accepted before " << stream_id; |
| 2727 CloseSessionOnError( | 2517 CloseSessionOnError( |
| 2728 ERR_SPDY_PROTOCOL_ERROR, | 2518 ERR_SPDY_PROTOCOL_ERROR, |
| 2729 "New push stream id must be greater than the last accepted."); | 2519 "New push stream id must be greater than the last accepted."); |
| 2730 return false; | 2520 return false; |
| 2731 } | 2521 } |
| 2732 | 2522 |
| 2733 if (IsStreamActive(stream_id)) { | 2523 if (IsStreamActive(stream_id)) { |
| 2734 // For SPDY3 and higher we should not get here, we'll start going away | 2524 // We should not get here, we'll start going away earlier on |
| 2735 // earlier on |last_seen_push_stream_id_| check. | 2525 // |last_seen_push_stream_id_| check. |
| 2736 CHECK_GT(SPDY3, GetProtocolVersion()); | |
| 2737 LOG(WARNING) << "Received push for active stream " << stream_id; | 2526 LOG(WARNING) << "Received push for active stream " << stream_id; |
| 2738 return false; | 2527 return false; |
| 2739 } | 2528 } |
| 2740 | 2529 |
| 2741 last_accepted_push_stream_id_ = stream_id; | 2530 last_accepted_push_stream_id_ = stream_id; |
| 2742 | 2531 |
| 2743 RequestPriority request_priority = | 2532 RequestPriority request_priority = |
| 2744 ConvertSpdyPriorityToRequestPriority(priority, GetProtocolVersion()); | 2533 ConvertSpdyPriorityToRequestPriority(priority); |
| 2745 | 2534 |
| 2746 if (availability_state_ == STATE_GOING_AWAY) { | 2535 if (availability_state_ == STATE_GOING_AWAY) { |
| 2747 // TODO(akalin): This behavior isn't in the SPDY spec, although it | 2536 // TODO(akalin): This behavior isn't in the SPDY spec, although it |
| 2748 // probably should be. | 2537 // probably should be. |
| 2749 EnqueueResetStreamFrame(stream_id, | 2538 EnqueueResetStreamFrame(stream_id, |
| 2750 request_priority, | 2539 request_priority, |
| 2751 RST_STREAM_REFUSED_STREAM, | 2540 RST_STREAM_REFUSED_STREAM, |
| 2752 "push stream request received when going away"); | 2541 "push stream request received when going away"); |
| 2753 return false; | 2542 return false; |
| 2754 } | 2543 } |
| 2755 | 2544 |
| 2756 if (associated_stream_id == 0) { | 2545 if (associated_stream_id == 0) { |
| 2757 // In HTTP/2 0 stream id in PUSH_PROMISE frame leads to framer error and | 2546 // In HTTP/2 0 stream id in PUSH_PROMISE frame leads to framer error and |
| 2758 // session going away. We should never get here. | 2547 // session going away. We should never get here. |
| 2759 CHECK_GT(HTTP2, GetProtocolVersion()); | |
| 2760 std::string description = base::StringPrintf( | 2548 std::string description = base::StringPrintf( |
| 2761 "Received invalid associated stream id %d for pushed stream %d", | 2549 "Received invalid associated stream id %d for pushed stream %d", |
| 2762 associated_stream_id, | 2550 associated_stream_id, |
| 2763 stream_id); | 2551 stream_id); |
| 2764 EnqueueResetStreamFrame( | 2552 EnqueueResetStreamFrame( |
| 2765 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description); | 2553 stream_id, request_priority, RST_STREAM_REFUSED_STREAM, description); |
| 2766 return false; | 2554 return false; |
| 2767 } | 2555 } |
| 2768 | 2556 |
| 2769 streams_pushed_count_++; | 2557 streams_pushed_count_++; |
| 2770 | 2558 |
| 2771 // TODO(mbelshe): DCHECK that this is a GET method? | 2559 // TODO(mbelshe): DCHECK that this is a GET method? |
| 2772 | 2560 |
| 2773 // Verify that the response had a URL for us. | 2561 // Verify that the response had a URL for us. |
| 2774 GURL gurl = GetUrlFromHeaderBlock(headers, GetProtocolVersion()); | 2562 GURL gurl = GetUrlFromHeaderBlock(headers); |
| 2775 if (!gurl.is_valid()) { | 2563 if (!gurl.is_valid()) { |
| 2776 EnqueueResetStreamFrame(stream_id, | 2564 EnqueueResetStreamFrame(stream_id, |
| 2777 request_priority, | 2565 request_priority, |
| 2778 RST_STREAM_PROTOCOL_ERROR, | 2566 RST_STREAM_PROTOCOL_ERROR, |
| 2779 "Pushed stream url was invalid: " + gurl.spec()); | 2567 "Pushed stream url was invalid: " + gurl.spec()); |
| 2780 return false; | 2568 return false; |
| 2781 } | 2569 } |
| 2782 | 2570 |
| 2783 // Verify we have a valid stream association. | 2571 // Verify we have a valid stream association. |
| 2784 ActiveStreamMap::iterator associated_it = | 2572 ActiveStreamMap::iterator associated_it = |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2853 return false; | 2641 return false; |
| 2854 } | 2642 } |
| 2855 | 2643 |
| 2856 std::unique_ptr<SpdyStream> stream( | 2644 std::unique_ptr<SpdyStream> stream( |
| 2857 new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, request_priority, | 2645 new SpdyStream(SPDY_PUSH_STREAM, GetWeakPtr(), gurl, request_priority, |
| 2858 stream_initial_send_window_size_, | 2646 stream_initial_send_window_size_, |
| 2859 stream_max_recv_window_size_, net_log_)); | 2647 stream_max_recv_window_size_, net_log_)); |
| 2860 stream->set_stream_id(stream_id); | 2648 stream->set_stream_id(stream_id); |
| 2861 | 2649 |
| 2862 // In spdy4/http2 PUSH_PROMISE arrives on associated stream. | 2650 // In spdy4/http2 PUSH_PROMISE arrives on associated stream. |
| 2863 if (associated_it != active_streams_.end() && GetProtocolVersion() >= HTTP2) { | 2651 if (associated_it != active_streams_.end()) { |
| 2864 associated_it->second.stream->AddRawReceivedBytes( | 2652 associated_it->second.stream->AddRawReceivedBytes( |
| 2865 last_compressed_frame_len_); | 2653 last_compressed_frame_len_); |
| 2866 } else { | 2654 } else { |
| 2867 stream->AddRawReceivedBytes(last_compressed_frame_len_); | 2655 stream->AddRawReceivedBytes(last_compressed_frame_len_); |
| 2868 } | 2656 } |
| 2869 | 2657 |
| 2870 last_compressed_frame_len_ = 0; | 2658 last_compressed_frame_len_ = 0; |
| 2871 | 2659 |
| 2872 UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it = | 2660 UnclaimedPushedStreamContainer::const_iterator inserted_pushed_it = |
| 2873 unclaimed_pushed_streams_.insert(pushed_it, gurl, stream_id, | 2661 unclaimed_pushed_streams_.insert(pushed_it, gurl, stream_id, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2911 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); | 2699 ActiveStreamMap::const_iterator it = active_streams_.find(stream_id); |
| 2912 CHECK(it != active_streams_.end()); | 2700 CHECK(it != active_streams_.end()); |
| 2913 CHECK_EQ(it->second.stream->stream_id(), stream_id); | 2701 CHECK_EQ(it->second.stream->stream_id(), stream_id); |
| 2914 SendWindowUpdateFrame( | 2702 SendWindowUpdateFrame( |
| 2915 stream_id, delta_window_size, it->second.stream->priority()); | 2703 stream_id, delta_window_size, it->second.stream->priority()); |
| 2916 } | 2704 } |
| 2917 | 2705 |
| 2918 void SpdySession::SendInitialData() { | 2706 void SpdySession::SendInitialData() { |
| 2919 DCHECK(enable_sending_initial_data_); | 2707 DCHECK(enable_sending_initial_data_); |
| 2920 | 2708 |
| 2921 if (send_connection_header_prefix_) { | 2709 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( |
| 2922 DCHECK_EQ(protocol_, kProtoHTTP2); | 2710 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), |
| 2923 std::unique_ptr<SpdySerializedFrame> connection_header_prefix_frame( | 2711 kHttp2ConnectionHeaderPrefixSize, |
| 2924 new SpdySerializedFrame(const_cast<char*>(kHttp2ConnectionHeaderPrefix), | 2712 false /* take_ownership */)); |
| 2925 kHttp2ConnectionHeaderPrefixSize, | 2713 // Count the prefix as part of the subsequent SETTINGS frame. |
| 2926 false /* take_ownership */)); | 2714 EnqueueSessionWrite(HIGHEST, SETTINGS, |
| 2927 // Count the prefix as part of the subsequent SETTINGS frame. | 2715 std::move(connection_header_prefix_frame)); |
| 2928 EnqueueSessionWrite(HIGHEST, SETTINGS, | |
| 2929 std::move(connection_header_prefix_frame)); | |
| 2930 } | |
| 2931 | 2716 |
| 2932 // First, notify the server about the settings they should use when | 2717 // First, notify the server about the settings they should use when |
| 2933 // communicating with us. | 2718 // communicating with us. |
| 2934 SettingsMap settings_map; | 2719 SettingsMap settings_map; |
| 2935 // Create a new settings frame notifying the server of our | 2720 // Create a new settings frame notifying the server of our |
| 2936 // max concurrent streams and initial window size. | 2721 // max concurrent streams and initial window size. |
| 2937 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = | 2722 settings_map[SETTINGS_MAX_CONCURRENT_STREAMS] = |
| 2938 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); | 2723 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, kMaxConcurrentPushedStreams); |
| 2939 if (stream_max_recv_window_size_ != GetDefaultInitialWindowSize(protocol_)) { | 2724 if (stream_max_recv_window_size_ != kDefaultInitialWindowSize) { |
| 2940 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = | 2725 settings_map[SETTINGS_INITIAL_WINDOW_SIZE] = |
| 2941 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size_); | 2726 SettingsFlagsAndValue(SETTINGS_FLAG_NONE, stream_max_recv_window_size_); |
| 2942 } | 2727 } |
| 2943 SendSettings(settings_map); | 2728 SendSettings(settings_map); |
| 2944 | 2729 |
| 2945 // Next, notify the server about our initial recv window size. | 2730 // Next, notify the server about our initial recv window size. |
| 2946 // Bump up the receive window size to the real initial value. This | 2731 // Bump up the receive window size to the real initial value. This |
| 2947 // has to go here since the WINDOW_UPDATE frame sent by | 2732 // has to go here since the WINDOW_UPDATE frame sent by |
| 2948 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. | 2733 // IncreaseRecvWindowSize() call uses |buffered_spdy_framer_|. |
| 2949 // This condition implies that |session_max_recv_window_size_| - | 2734 // This condition implies that |session_max_recv_window_size_| - |
| 2950 // |session_recv_window_size_| doesn't overflow. | 2735 // |session_recv_window_size_| doesn't overflow. |
| 2951 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); | 2736 DCHECK_GE(session_max_recv_window_size_, session_recv_window_size_); |
| 2952 DCHECK_GE(session_recv_window_size_, 0); | 2737 DCHECK_GE(session_recv_window_size_, 0); |
| 2953 if (session_max_recv_window_size_ > session_recv_window_size_) { | 2738 if (session_max_recv_window_size_ > session_recv_window_size_) { |
| 2954 IncreaseRecvWindowSize(session_max_recv_window_size_ - | 2739 IncreaseRecvWindowSize(session_max_recv_window_size_ - |
| 2955 session_recv_window_size_); | 2740 session_recv_window_size_); |
| 2956 } | 2741 } |
| 2957 | |
| 2958 if (protocol_ == kProtoSPDY31) { | |
| 2959 // Finally, notify the server about the settings they have | |
| 2960 // previously told us to use when communicating with them (after | |
| 2961 // applying them). | |
| 2962 const SettingsMap& server_settings_map = | |
| 2963 http_server_properties_->GetSpdySettings(GetServer()); | |
| 2964 if (server_settings_map.empty()) | |
| 2965 return; | |
| 2966 | |
| 2967 SettingsMap::const_iterator it = | |
| 2968 server_settings_map.find(SETTINGS_CURRENT_CWND); | |
| 2969 uint32_t cwnd = (it != server_settings_map.end()) ? it->second.second : 0; | |
| 2970 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySettingsCwndSent", cwnd, 1, 200, 100); | |
| 2971 | |
| 2972 for (SettingsMap::const_iterator it = server_settings_map.begin(); | |
| 2973 it != server_settings_map.end(); ++it) { | |
| 2974 const SpdySettingsIds new_id = it->first; | |
| 2975 const uint32_t new_val = it->second.second; | |
| 2976 HandleSetting(new_id, new_val); | |
| 2977 } | |
| 2978 | |
| 2979 SendSettings(server_settings_map); | |
| 2980 } | |
| 2981 } | 2742 } |
| 2982 | 2743 |
| 2983 | |
| 2984 void SpdySession::SendSettings(const SettingsMap& settings) { | 2744 void SpdySession::SendSettings(const SettingsMap& settings) { |
| 2985 const SpdyMajorVersion protocol_version = GetProtocolVersion(); | 2745 net_log_.AddEvent(NetLog::TYPE_HTTP2_SESSION_SEND_SETTINGS, |
| 2986 net_log_.AddEvent( | 2746 base::Bind(&NetLogSpdySendSettingsCallback, &settings)); |
| 2987 NetLog::TYPE_HTTP2_SESSION_SEND_SETTINGS, | |
| 2988 base::Bind(&NetLogSpdySendSettingsCallback, &settings, protocol_version)); | |
| 2989 // Create the SETTINGS frame and send it. | 2747 // Create the SETTINGS frame and send it. |
| 2990 DCHECK(buffered_spdy_framer_.get()); | 2748 DCHECK(buffered_spdy_framer_.get()); |
| 2991 std::unique_ptr<SpdySerializedFrame> settings_frame( | 2749 std::unique_ptr<SpdySerializedFrame> settings_frame( |
| 2992 buffered_spdy_framer_->CreateSettings(settings)); | 2750 buffered_spdy_framer_->CreateSettings(settings)); |
| 2993 sent_settings_ = true; | 2751 sent_settings_ = true; |
| 2994 EnqueueSessionWrite(HIGHEST, SETTINGS, std::move(settings_frame)); | 2752 EnqueueSessionWrite(HIGHEST, SETTINGS, std::move(settings_frame)); |
| 2995 } | 2753 } |
| 2996 | 2754 |
| 2997 void SpdySession::HandleSetting(uint32_t id, uint32_t value) { | 2755 void SpdySession::HandleSetting(uint32_t id, uint32_t value) { |
| 2998 switch (id) { | 2756 switch (id) { |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3398 if (!queue->empty()) { | 3156 if (!queue->empty()) { |
| 3399 SpdyStreamId stream_id = queue->front(); | 3157 SpdyStreamId stream_id = queue->front(); |
| 3400 queue->pop_front(); | 3158 queue->pop_front(); |
| 3401 return stream_id; | 3159 return stream_id; |
| 3402 } | 3160 } |
| 3403 } | 3161 } |
| 3404 return 0; | 3162 return 0; |
| 3405 } | 3163 } |
| 3406 | 3164 |
| 3407 } // namespace net | 3165 } // namespace net |
| OLD | NEW |