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 |