| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_session.h" | 5 #include "net/spdy/spdy_session.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 create_stream_queues_[priority].push( | 528 create_stream_queues_[priority].push( |
| 529 PendingCreateStream(url, priority, spdy_stream, | 529 PendingCreateStream(url, priority, spdy_stream, |
| 530 stream_net_log, callback)); | 530 stream_net_log, callback)); |
| 531 return ERR_IO_PENDING; | 531 return ERR_IO_PENDING; |
| 532 } | 532 } |
| 533 | 533 |
| 534 void SpdySession::ProcessPendingCreateStreams() { | 534 void SpdySession::ProcessPendingCreateStreams() { |
| 535 while (!max_concurrent_streams_ || | 535 while (!max_concurrent_streams_ || |
| 536 active_streams_.size() < max_concurrent_streams_) { | 536 active_streams_.size() < max_concurrent_streams_) { |
| 537 bool no_pending_create_streams = true; | 537 bool no_pending_create_streams = true; |
| 538 for (int i = 0;i < NUM_PRIORITIES;++i) { | 538 for (int i = NUM_PRIORITIES - 1; i >= MINIMUM_PRIORITY; --i) { |
| 539 if (!create_stream_queues_[i].empty()) { | 539 if (!create_stream_queues_[i].empty()) { |
| 540 PendingCreateStream pending_create = create_stream_queues_[i].front(); | 540 PendingCreateStream pending_create = create_stream_queues_[i].front(); |
| 541 create_stream_queues_[i].pop(); | 541 create_stream_queues_[i].pop(); |
| 542 no_pending_create_streams = false; | 542 no_pending_create_streams = false; |
| 543 int error = CreateStreamImpl(*pending_create.url, | 543 int error = CreateStreamImpl(*pending_create.url, |
| 544 pending_create.priority, | 544 pending_create.priority, |
| 545 pending_create.spdy_stream, | 545 pending_create.spdy_stream, |
| 546 *pending_create.stream_net_log); | 546 *pending_create.stream_net_log); |
| 547 scoped_refptr<SpdyStream>* stream = pending_create.spdy_stream; | 547 scoped_refptr<SpdyStream>* stream = pending_create.spdy_stream; |
| 548 DCHECK(!ContainsKey(pending_callback_map_, stream)); | 548 DCHECK(!ContainsKey(pending_callback_map_, stream)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 561 } | 561 } |
| 562 | 562 |
| 563 void SpdySession::CancelPendingCreateStreams( | 563 void SpdySession::CancelPendingCreateStreams( |
| 564 const scoped_refptr<SpdyStream>* spdy_stream) { | 564 const scoped_refptr<SpdyStream>* spdy_stream) { |
| 565 PendingCallbackMap::iterator it = pending_callback_map_.find(spdy_stream); | 565 PendingCallbackMap::iterator it = pending_callback_map_.find(spdy_stream); |
| 566 if (it != pending_callback_map_.end()) { | 566 if (it != pending_callback_map_.end()) { |
| 567 pending_callback_map_.erase(it); | 567 pending_callback_map_.erase(it); |
| 568 return; | 568 return; |
| 569 } | 569 } |
| 570 | 570 |
| 571 for (int i = 0;i < NUM_PRIORITIES;++i) { | 571 for (int i = 0; i < NUM_PRIORITIES; ++i) { |
| 572 PendingCreateStreamQueue tmp; | 572 PendingCreateStreamQueue tmp; |
| 573 // Make a copy removing this trans | 573 // Make a copy removing this trans |
| 574 while (!create_stream_queues_[i].empty()) { | 574 while (!create_stream_queues_[i].empty()) { |
| 575 PendingCreateStream pending_create = create_stream_queues_[i].front(); | 575 PendingCreateStream pending_create = create_stream_queues_[i].front(); |
| 576 create_stream_queues_[i].pop(); | 576 create_stream_queues_[i].pop(); |
| 577 if (pending_create.spdy_stream != spdy_stream) | 577 if (pending_create.spdy_stream != spdy_stream) |
| 578 tmp.push(pending_create); | 578 tmp.push(pending_create); |
| 579 } | 579 } |
| 580 // Now copy it back | 580 // Now copy it back |
| 581 while (!tmp.empty()) { | 581 while (!tmp.empty()) { |
| 582 create_stream_queues_[i].push(tmp.front()); | 582 create_stream_queues_[i].push(tmp.front()); |
| 583 tmp.pop(); | 583 tmp.pop(); |
| 584 } | 584 } |
| 585 } | 585 } |
| 586 } | 586 } |
| 587 | 587 |
| 588 int SpdySession::CreateStreamImpl( | 588 int SpdySession::CreateStreamImpl( |
| 589 const GURL& url, | 589 const GURL& url, |
| 590 RequestPriority priority, | 590 RequestPriority priority, |
| 591 scoped_refptr<SpdyStream>* spdy_stream, | 591 scoped_refptr<SpdyStream>* spdy_stream, |
| 592 const BoundNetLog& stream_net_log) { | 592 const BoundNetLog& stream_net_log) { |
| 593 DCHECK_GE(priority, MINIMUM_PRIORITY); |
| 594 DCHECK_LT(priority, NUM_PRIORITIES); |
| 595 |
| 593 // Make sure that we don't try to send https/wss over an unauthenticated, but | 596 // Make sure that we don't try to send https/wss over an unauthenticated, but |
| 594 // encrypted SSL socket. | 597 // encrypted SSL socket. |
| 595 if (is_secure_ && certificate_error_code_ != OK && | 598 if (is_secure_ && certificate_error_code_ != OK && |
| 596 (url.SchemeIs("https") || url.SchemeIs("wss"))) { | 599 (url.SchemeIs("https") || url.SchemeIs("wss"))) { |
| 597 CloseSessionOnError( | 600 CloseSessionOnError( |
| 598 static_cast<net::Error>(certificate_error_code_), | 601 static_cast<net::Error>(certificate_error_code_), |
| 599 true, | 602 true, |
| 600 "Tried to create SPDY stream for secure content over an " | 603 "Tried to create SPDY stream for secure content over an " |
| 601 "unauthenticated session."); | 604 "unauthenticated session."); |
| 602 return ERR_SPDY_PROTOCOL_ERROR; | 605 return ERR_SPDY_PROTOCOL_ERROR; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 615 stream->set_priority(priority); | 618 stream->set_priority(priority); |
| 616 stream->set_path(path); | 619 stream->set_path(path); |
| 617 stream->set_send_window_size(initial_send_window_size_); | 620 stream->set_send_window_size(initial_send_window_size_); |
| 618 stream->set_recv_window_size(initial_recv_window_size_); | 621 stream->set_recv_window_size(initial_recv_window_size_); |
| 619 ActivateStream(stream); | 622 ActivateStream(stream); |
| 620 | 623 |
| 621 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", | 624 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdyPriorityCount", |
| 622 static_cast<int>(priority), 0, 10, 11); | 625 static_cast<int>(priority), 0, 10, 11); |
| 623 | 626 |
| 624 // TODO(mbelshe): Optimize memory allocations | 627 // TODO(mbelshe): Optimize memory allocations |
| 625 DCHECK(priority >= net::HIGHEST && priority < net::NUM_PRIORITIES); | |
| 626 | 628 |
| 627 DCHECK_EQ(active_streams_[stream_id].get(), stream.get()); | 629 DCHECK_EQ(active_streams_[stream_id].get(), stream.get()); |
| 628 return OK; | 630 return OK; |
| 629 } | 631 } |
| 630 | 632 |
| 631 bool SpdySession::NeedsCredentials() const { | 633 bool SpdySession::NeedsCredentials() const { |
| 632 if (!is_secure_) | 634 if (!is_secure_) |
| 633 return false; | 635 return false; |
| 634 SSLClientSocket* ssl_socket = GetSSLClientSocket(); | 636 SSLClientSocket* ssl_socket = GetSSLClientSocket(); |
| 635 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) | 637 if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3) |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 net_log().AddEvent( | 829 net_log().AddEvent( |
| 828 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, | 830 NetLog::TYPE_SPDY_SESSION_SEND_RST_STREAM, |
| 829 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status, | 831 make_scoped_refptr(new NetLogSpdyRstParameter(stream_id, status, |
| 830 description))); | 832 description))); |
| 831 | 833 |
| 832 DCHECK(buffered_spdy_framer_.get()); | 834 DCHECK(buffered_spdy_framer_.get()); |
| 833 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( | 835 scoped_ptr<SpdyRstStreamControlFrame> rst_frame( |
| 834 buffered_spdy_framer_->CreateRstStream(stream_id, status)); | 836 buffered_spdy_framer_->CreateRstStream(stream_id, status)); |
| 835 | 837 |
| 836 // Default to lowest priority unless we know otherwise. | 838 // Default to lowest priority unless we know otherwise. |
| 837 int priority = 3; | 839 RequestPriority priority = net::IDLE; |
| 838 if(IsStreamActive(stream_id)) { | 840 if(IsStreamActive(stream_id)) { |
| 839 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; | 841 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; |
| 840 priority = stream->priority(); | 842 priority = stream->priority(); |
| 841 } | 843 } |
| 842 QueueFrame(rst_frame.get(), priority, NULL); | 844 QueueFrame(rst_frame.get(), priority, NULL); |
| 843 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); | 845 DeleteStream(stream_id, ERR_SPDY_PROTOCOL_ERROR); |
| 844 } | 846 } |
| 845 | 847 |
| 846 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { | 848 bool SpdySession::IsStreamActive(SpdyStreamId stream_id) const { |
| 847 return ContainsKey(active_streams_, stream_id); | 849 return ContainsKey(active_streams_, stream_id); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 | 1049 |
| 1048 size = compressed_frame->length() + SpdyFrame::kHeaderSize; | 1050 size = compressed_frame->length() + SpdyFrame::kHeaderSize; |
| 1049 | 1051 |
| 1050 DCHECK_GT(size, 0u); | 1052 DCHECK_GT(size, 0u); |
| 1051 | 1053 |
| 1052 // TODO(mbelshe): We have too much copying of data here. | 1054 // TODO(mbelshe): We have too much copying of data here. |
| 1053 IOBufferWithSize* buffer = new IOBufferWithSize(size); | 1055 IOBufferWithSize* buffer = new IOBufferWithSize(size); |
| 1054 memcpy(buffer->data(), compressed_frame->data(), size); | 1056 memcpy(buffer->data(), compressed_frame->data(), size); |
| 1055 | 1057 |
| 1056 // Attempt to send the frame. | 1058 // Attempt to send the frame. |
| 1057 in_flight_write_ = SpdyIOBuffer(buffer, size, 0, next_buffer.stream()); | 1059 in_flight_write_ = SpdyIOBuffer(buffer, size, HIGHEST, |
| 1060 next_buffer.stream()); |
| 1058 } else { | 1061 } else { |
| 1059 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize; | 1062 size = uncompressed_frame.length() + SpdyFrame::kHeaderSize; |
| 1060 in_flight_write_ = next_buffer; | 1063 in_flight_write_ = next_buffer; |
| 1061 } | 1064 } |
| 1062 } else { | 1065 } else { |
| 1063 DCHECK(in_flight_write_.buffer()->BytesRemaining()); | 1066 DCHECK(in_flight_write_.buffer()->BytesRemaining()); |
| 1064 } | 1067 } |
| 1065 | 1068 |
| 1066 write_pending_ = true; | 1069 write_pending_ = true; |
| 1067 int rv = connection_->socket()->Write( | 1070 int rv = connection_->socket()->Write( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1087 "spdy.abandoned_push_streams"); | 1090 "spdy.abandoned_push_streams"); |
| 1088 | 1091 |
| 1089 if (!active_streams_.empty()) | 1092 if (!active_streams_.empty()) |
| 1090 abandoned_streams.Add(active_streams_.size()); | 1093 abandoned_streams.Add(active_streams_.size()); |
| 1091 if (!unclaimed_pushed_streams_.empty()) { | 1094 if (!unclaimed_pushed_streams_.empty()) { |
| 1092 streams_abandoned_count_ += unclaimed_pushed_streams_.size(); | 1095 streams_abandoned_count_ += unclaimed_pushed_streams_.size(); |
| 1093 abandoned_push_streams.Add(unclaimed_pushed_streams_.size()); | 1096 abandoned_push_streams.Add(unclaimed_pushed_streams_.size()); |
| 1094 unclaimed_pushed_streams_.clear(); | 1097 unclaimed_pushed_streams_.clear(); |
| 1095 } | 1098 } |
| 1096 | 1099 |
| 1097 for (int i = 0;i < NUM_PRIORITIES;++i) { | 1100 for (int i = 0; i < NUM_PRIORITIES; ++i) { |
| 1098 while (!create_stream_queues_[i].empty()) { | 1101 while (!create_stream_queues_[i].empty()) { |
| 1099 PendingCreateStream pending_create = create_stream_queues_[i].front(); | 1102 PendingCreateStream pending_create = create_stream_queues_[i].front(); |
| 1100 create_stream_queues_[i].pop(); | 1103 create_stream_queues_[i].pop(); |
| 1101 pending_create.callback.Run(ERR_ABORTED); | 1104 pending_create.callback.Run(ERR_ABORTED); |
| 1102 } | 1105 } |
| 1103 } | 1106 } |
| 1104 | 1107 |
| 1105 while (!active_streams_.empty()) { | 1108 while (!active_streams_.empty()) { |
| 1106 ActiveStreamMap::iterator it = active_streams_.begin(); | 1109 ActiveStreamMap::iterator it = active_streams_.begin(); |
| 1107 const scoped_refptr<SpdyStream>& stream = it->second; | 1110 const scoped_refptr<SpdyStream>& stream = it->second; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1119 | 1122 |
| 1120 int SpdySession::GetNewStreamId() { | 1123 int SpdySession::GetNewStreamId() { |
| 1121 int id = stream_hi_water_mark_; | 1124 int id = stream_hi_water_mark_; |
| 1122 stream_hi_water_mark_ += 2; | 1125 stream_hi_water_mark_ += 2; |
| 1123 if (stream_hi_water_mark_ > 0x7fff) | 1126 if (stream_hi_water_mark_ > 0x7fff) |
| 1124 stream_hi_water_mark_ = 1; | 1127 stream_hi_water_mark_ = 1; |
| 1125 return id; | 1128 return id; |
| 1126 } | 1129 } |
| 1127 | 1130 |
| 1128 void SpdySession::QueueFrame(SpdyFrame* frame, | 1131 void SpdySession::QueueFrame(SpdyFrame* frame, |
| 1129 SpdyPriority priority, | 1132 RequestPriority priority, |
| 1130 SpdyStream* stream) { | 1133 SpdyStream* stream) { |
| 1131 int length = SpdyFrame::kHeaderSize + frame->length(); | 1134 int length = SpdyFrame::kHeaderSize + frame->length(); |
| 1132 IOBuffer* buffer = new IOBuffer(length); | 1135 IOBuffer* buffer = new IOBuffer(length); |
| 1133 memcpy(buffer->data(), frame->data(), length); | 1136 memcpy(buffer->data(), frame->data(), length); |
| 1134 queue_.push(SpdyIOBuffer(buffer, length, priority, stream)); | 1137 queue_.push(SpdyIOBuffer(buffer, length, priority, stream)); |
| 1135 | 1138 |
| 1136 WriteSocketLater(); | 1139 WriteSocketLater(); |
| 1137 } | 1140 } |
| 1138 | 1141 |
| 1139 void SpdySession::CloseSessionOnError(net::Error err, | 1142 void SpdySession::CloseSessionOnError(net::Error err, |
| (...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1734 | 1737 |
| 1735 net_log_.AddEvent( | 1738 net_log_.AddEvent( |
| 1736 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, | 1739 NetLog::TYPE_SPDY_SESSION_SEND_SETTINGS, |
| 1737 make_scoped_refptr(new NetLogSpdySettingsParameter(settings_map_new))); | 1740 make_scoped_refptr(new NetLogSpdySettingsParameter(settings_map_new))); |
| 1738 | 1741 |
| 1739 // Create the SETTINGS frame and send it. | 1742 // Create the SETTINGS frame and send it. |
| 1740 DCHECK(buffered_spdy_framer_.get()); | 1743 DCHECK(buffered_spdy_framer_.get()); |
| 1741 scoped_ptr<SpdySettingsControlFrame> settings_frame( | 1744 scoped_ptr<SpdySettingsControlFrame> settings_frame( |
| 1742 buffered_spdy_framer_->CreateSettings(settings_map_new)); | 1745 buffered_spdy_framer_->CreateSettings(settings_map_new)); |
| 1743 sent_settings_ = true; | 1746 sent_settings_ = true; |
| 1744 QueueFrame(settings_frame.get(), 0, NULL); | 1747 QueueFrame(settings_frame.get(), HIGHEST, NULL); |
| 1745 } | 1748 } |
| 1746 | 1749 |
| 1747 void SpdySession::HandleSetting(uint32 id, uint32 value) { | 1750 void SpdySession::HandleSetting(uint32 id, uint32 value) { |
| 1748 switch (id) { | 1751 switch (id) { |
| 1749 case SETTINGS_MAX_CONCURRENT_STREAMS: | 1752 case SETTINGS_MAX_CONCURRENT_STREAMS: |
| 1750 max_concurrent_streams_ = std::min(static_cast<size_t>(value), | 1753 max_concurrent_streams_ = std::min(static_cast<size_t>(value), |
| 1751 g_max_concurrent_stream_limit); | 1754 g_max_concurrent_stream_limit); |
| 1752 ProcessPendingCreateStreams(); | 1755 ProcessPendingCreateStreams(); |
| 1753 break; | 1756 break; |
| 1754 case SETTINGS_INITIAL_WINDOW_SIZE: | 1757 case SETTINGS_INITIAL_WINDOW_SIZE: |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1811 void SpdySession::SendTrailingPing() { | 1814 void SpdySession::SendTrailingPing() { |
| 1812 DCHECK(trailing_ping_pending_); | 1815 DCHECK(trailing_ping_pending_); |
| 1813 trailing_ping_pending_ = false; | 1816 trailing_ping_pending_ = false; |
| 1814 WritePingFrame(next_ping_id_); | 1817 WritePingFrame(next_ping_id_); |
| 1815 } | 1818 } |
| 1816 | 1819 |
| 1817 void SpdySession::WritePingFrame(uint32 unique_id) { | 1820 void SpdySession::WritePingFrame(uint32 unique_id) { |
| 1818 DCHECK(buffered_spdy_framer_.get()); | 1821 DCHECK(buffered_spdy_framer_.get()); |
| 1819 scoped_ptr<SpdyPingControlFrame> ping_frame( | 1822 scoped_ptr<SpdyPingControlFrame> ping_frame( |
| 1820 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); | 1823 buffered_spdy_framer_->CreatePingFrame(next_ping_id_)); |
| 1821 QueueFrame( | 1824 QueueFrame(ping_frame.get(), HIGHEST, NULL); |
| 1822 ping_frame.get(), buffered_spdy_framer_->GetHighestPriority(), NULL); | |
| 1823 | 1825 |
| 1824 if (net_log().IsLoggingAllEvents()) { | 1826 if (net_log().IsLoggingAllEvents()) { |
| 1825 net_log().AddEvent( | 1827 net_log().AddEvent( |
| 1826 NetLog::TYPE_SPDY_SESSION_PING, | 1828 NetLog::TYPE_SPDY_SESSION_PING, |
| 1827 make_scoped_refptr(new NetLogSpdyPingParameter(next_ping_id_, "sent"))); | 1829 make_scoped_refptr(new NetLogSpdyPingParameter(next_ping_id_, "sent"))); |
| 1828 } | 1830 } |
| 1829 if (unique_id % 2 != 0) { | 1831 if (unique_id % 2 != 0) { |
| 1830 next_ping_id_ += 2; | 1832 next_ping_id_ += 2; |
| 1831 ++pings_in_flight_; | 1833 ++pings_in_flight_; |
| 1832 need_to_send_ping_ = false; | 1834 need_to_send_ping_ = false; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1966 SSLClientSocket* SpdySession::GetSSLClientSocket() const { | 1968 SSLClientSocket* SpdySession::GetSSLClientSocket() const { |
| 1967 if (!is_secure_) | 1969 if (!is_secure_) |
| 1968 return NULL; | 1970 return NULL; |
| 1969 SSLClientSocket* ssl_socket = | 1971 SSLClientSocket* ssl_socket = |
| 1970 reinterpret_cast<SSLClientSocket*>(connection_->socket()); | 1972 reinterpret_cast<SSLClientSocket*>(connection_->socket()); |
| 1971 DCHECK(ssl_socket); | 1973 DCHECK(ssl_socket); |
| 1972 return ssl_socket; | 1974 return ssl_socket; |
| 1973 } | 1975 } |
| 1974 | 1976 |
| 1975 } // namespace net | 1977 } // namespace net |
| OLD | NEW |