Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: net/spdy/spdy_session.cc

Issue 6800009: Attn: Mike Belshe Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/memory/linked_ptr.h" 9 #include "base/memory/linked_ptr.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 streams_abandoned_count_(0), 239 streams_abandoned_count_(0),
240 frames_received_(0), 240 frames_received_(0),
241 bytes_received_(0), 241 bytes_received_(0),
242 sent_settings_(false), 242 sent_settings_(false),
243 received_settings_(false), 243 received_settings_(false),
244 stalled_streams_(0), 244 stalled_streams_(0),
245 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize), 245 initial_send_window_size_(spdy::kSpdyStreamInitialWindowSize),
246 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize), 246 initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize),
247 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) { 247 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) {
248 DCHECK(HttpStreamFactory::spdy_enabled()); 248 DCHECK(HttpStreamFactory::spdy_enabled());
249 // TODO(jtl): Do we need to set kMaxSpdyFrameChunkSize here based on which
250 // transport protocol we're using?
249 net_log_.BeginEvent( 251 net_log_.BeginEvent(
250 NetLog::TYPE_SPDY_SESSION, 252 NetLog::TYPE_SPDY_SESSION,
251 make_scoped_refptr( 253 make_scoped_refptr(
252 new NetLogSpdySessionParameter(host_port_proxy_pair_))); 254 new NetLogSpdySessionParameter(host_port_proxy_pair_)));
253 255
254 // TODO(mbelshe): consider randomization of the stream_hi_water_mark. 256 // TODO(mbelshe): consider randomization of the stream_hi_water_mark.
255 257
256 spdy_framer_.set_visitor(this); 258 spdy_framer_.set_visitor(this);
257 259
258 SendSettings(); 260 SendSettings();
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 LOG(ERROR) << "SPDY Compression failure"; 759 LOG(ERROR) << "SPDY Compression failure";
758 CloseSessionOnError(net::ERR_SPDY_PROTOCOL_ERROR, true); 760 CloseSessionOnError(net::ERR_SPDY_PROTOCOL_ERROR, true);
759 return; 761 return;
760 } 762 }
761 763
762 size = compressed_frame->length() + spdy::SpdyFrame::size(); 764 size = compressed_frame->length() + spdy::SpdyFrame::size();
763 765
764 DCHECK_GT(size, 0u); 766 DCHECK_GT(size, 0u);
765 767
766 // TODO(mbelshe): We have too much copying of data here. 768 // TODO(mbelshe): We have too much copying of data here.
767 IOBufferWithSize* buffer = new IOBufferWithSize(size); 769 // TODO(jtl): Why is this "WithSize"?
770 IOBuffer* buffer = new IOBufferWithSize(size);
768 memcpy(buffer->data(), compressed_frame->data(), size); 771 memcpy(buffer->data(), compressed_frame->data(), size);
769 772
770 // Attempt to send the frame. 773 // Attempt to send the frame.
771 in_flight_write_ = SpdyIOBuffer(buffer, size, 0, next_buffer.stream()); 774 in_flight_write_ = SpdyIOBuffer(buffer, size, 0, next_buffer.stream());
772 } else { 775 } else {
773 size = uncompressed_frame.length() + spdy::SpdyFrame::size(); 776 size = uncompressed_frame.length() + spdy::SpdyFrame::size();
774 in_flight_write_ = next_buffer; 777 in_flight_write_ = next_buffer;
775 } 778 }
779 // SCTP stream ID assignment is delayed until now, rather than done in
780 // QueueFrame, to be sure the association (connection) has been
781 // established. SCTP stream ID numbers can't be assigned until
782 // g_max_sctp_streams is set, and that can't happen until the association
783 // is established.
784 // TODO(jtl): In order to support piggy-backing DATA on the COOKIE_ECHO,
785 // as is allowed in FreeBSD and Mac OS X, we need to find a way to allow
786 // at least sctp stream ID 1 to be used prior to g_max_sctp_streams being
787 // set.
788 //
789 if (using_sctp()) {
790 spdy::SpdyFrame frame(in_flight_write_.buffer()->data(), false);
791 in_flight_write_.set_sctp_stream_id(GetSctpStreamID(frame));
792 }
776 } else { 793 } else {
777 DCHECK(in_flight_write_.buffer()->BytesRemaining()); 794 DCHECK(in_flight_write_.buffer()->BytesRemaining());
778 } 795 }
779 796
780 write_pending_ = true; 797 write_pending_ = true;
798
781 int rv = connection_->socket()->Write(in_flight_write_.buffer(), 799 int rv = connection_->socket()->Write(in_flight_write_.buffer(),
782 in_flight_write_.buffer()->BytesRemaining(), &write_callback_); 800 in_flight_write_.buffer()->BytesRemaining(), &write_callback_);
783 if (rv == net::ERR_IO_PENDING) 801 if (rv == net::ERR_IO_PENDING)
784 break; 802 break;
785 803
786 // We sent the frame successfully. 804 // We sent the frame successfully.
787 OnWriteComplete(rv); 805 OnWriteComplete(rv);
788 806
789 // TODO(mbelshe): Test this error case. Maybe we should mark the socket 807 // TODO(mbelshe): Test this error case. Maybe we should mark the socket
790 // as in an error state. 808 // as in an error state.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 } 847 }
830 848
831 int SpdySession::GetNewStreamId() { 849 int SpdySession::GetNewStreamId() {
832 int id = stream_hi_water_mark_; 850 int id = stream_hi_water_mark_;
833 stream_hi_water_mark_ += 2; 851 stream_hi_water_mark_ += 2;
834 if (stream_hi_water_mark_ > 0x7fff) 852 if (stream_hi_water_mark_ > 0x7fff)
835 stream_hi_water_mark_ = 1; 853 stream_hi_water_mark_ = 1;
836 return id; 854 return id;
837 } 855 }
838 856
857 uint16 SpdySession::GetSctpStreamID(const spdy::SpdyFrame& frame) {
858 uint32 stream_id = 0;
859 if (!frame.is_control_frame()) {
860 stream_id = reinterpret_cast<const spdy::SpdyDataFrame&>(frame).stream_id();
861 } else if (!using_sctp_control_stream()) {
862 spdy::SpdyControlType type =
863 reinterpret_cast<const spdy::SpdyControlFrame&>(frame).type();
864 // n.b. When not using an SCTP control stream, SETTINGS, NOOP, PING
865 // and GOAWAY control frames are still sent on SCTP stream 0 because
866 // they are not associated with a specific SPDY stream.
867 switch (type) {
868 case spdy::SYN_STREAM:
869 stream_id = static_cast<const spdy::SpdySynStreamControlFrame&>
870 (frame).stream_id();
871 break;
872 case spdy::SYN_REPLY:
873 stream_id = static_cast<const spdy::SpdySynReplyControlFrame&>
874 (frame).stream_id();
875 break;
876 case spdy::RST_STREAM:
877 stream_id = static_cast<const spdy::SpdyRstStreamControlFrame&>
878 (frame).stream_id();
879 break;
880 case spdy::HEADERS:
881 stream_id = static_cast<const spdy::SpdyHeadersControlFrame&>
882 (frame).stream_id();
883 break;
884 case spdy::WINDOW_UPDATE:
885 stream_id = static_cast<const spdy::SpdyWindowUpdateControlFrame&>
886 (frame).stream_id();
887 break;
888 default:
889 break;
890 }
891 }
892
893 return stream_id ? MapSpdyToSctp(stream_id) : 0;
894 }
895
839 void SpdySession::QueueFrame(spdy::SpdyFrame* frame, 896 void SpdySession::QueueFrame(spdy::SpdyFrame* frame,
840 spdy::SpdyPriority priority, 897 spdy::SpdyPriority priority,
841 SpdyStream* stream) { 898 SpdyStream* stream) {
842 int length = spdy::SpdyFrame::size() + frame->length(); 899 int length = spdy::SpdyFrame::size() + frame->length();
843 IOBuffer* buffer = new IOBuffer(length); 900 IOBuffer* buffer;
901 buffer = new IOBuffer(length);
844 memcpy(buffer->data(), frame->data(), length); 902 memcpy(buffer->data(), frame->data(), length);
903 // can't assign IOBuffer::sctp_stream_id_ here because the association may not
904 // be established yet. See comments in SpdySession::WriteSocket()
845 queue_.push(SpdyIOBuffer(buffer, length, priority, stream)); 905 queue_.push(SpdyIOBuffer(buffer, length, priority, stream));
846 906
847 WriteSocketLater(); 907 WriteSocketLater();
848 } 908 }
849 909
850 void SpdySession::CloseSessionOnError(net::Error err, bool remove_from_pool) { 910 void SpdySession::CloseSessionOnError(net::Error err, bool remove_from_pool) {
851 // Closing all streams can have a side-effect of dropping the last reference 911 // Closing all streams can have a side-effect of dropping the last reference
852 // to |this|. Hold a reference through this function. 912 // to |this|. Hold a reference through this function.
853 scoped_refptr<SpdySession> self(this); 913 scoped_refptr<SpdySession> self(this);
854 914
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
1117 spdy::SpdyStreamId stream_id = frame.stream_id(); 1177 spdy::SpdyStreamId stream_id = frame.stream_id();
1118 1178
1119 bool valid_stream = IsStreamActive(stream_id); 1179 bool valid_stream = IsStreamActive(stream_id);
1120 if (!valid_stream) { 1180 if (!valid_stream) {
1121 // NOTE: it may just be that the stream was cancelled. 1181 // NOTE: it may just be that the stream was cancelled.
1122 LOG(WARNING) << "Received SYN_REPLY for invalid stream " << stream_id; 1182 LOG(WARNING) << "Received SYN_REPLY for invalid stream " << stream_id;
1123 return; 1183 return;
1124 } 1184 }
1125 1185
1126 scoped_refptr<SpdyStream> stream = active_streams_[stream_id]; 1186 scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
1187 if (using_sctp() && using_sctp_control_stream())
1188 stream->set_syn_reply_received();
1127 CHECK_EQ(stream->stream_id(), stream_id); 1189 CHECK_EQ(stream->stream_id(), stream_id);
1128 CHECK(!stream->cancelled()); 1190 CHECK(!stream->cancelled());
1129 1191
1130 if (stream->response_received()) { 1192 if (stream->response_received()) {
1131 LOG(WARNING) << "Received duplicate SYN_REPLY for stream " << stream_id; 1193 LOG(WARNING) << "Received duplicate SYN_REPLY for stream " << stream_id;
1132 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR); 1194 CloseStream(stream->stream_id(), ERR_SPDY_PROTOCOL_ERROR);
1133 return; 1195 return;
1134 } 1196 }
1135 stream->set_response_received(); 1197 stream->set_response_received();
1136 1198
1137 if (net_log().IsLoggingAllEvents()) { 1199 if (net_log().IsLoggingAllEvents()) {
1138 net_log().AddEvent( 1200 net_log().AddEvent(
1139 NetLog::TYPE_SPDY_SESSION_SYN_REPLY, 1201 NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
1140 make_scoped_refptr(new NetLogSpdySynParameter( 1202 make_scoped_refptr(new NetLogSpdySynParameter(
1141 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()), 1203 headers, static_cast<spdy::SpdyControlFlags>(frame.flags()),
1142 stream_id, 0))); 1204 stream_id, 0)));
1143 } 1205 }
1144 1206
1145 Respond(*headers, stream); 1207 Respond(*headers, stream);
1208
1209 // When using SCTP with a control stream, loss can result in the SYN_REPLY
1210 // arriving after all the data. In this case close_pending() will be true
1211 // and we need to call OnDataReceived to shutdown the metrics and close the
1212 // stream.
1213 if (using_sctp() && using_sctp_control_stream() &&
1214 stream->close_pending())
1215 stream->OnDataReceived(NULL, 0);
1146 } 1216 }
1147 1217
1148 void SpdySession::OnHeaders(const spdy::SpdyHeadersControlFrame& frame, 1218 void SpdySession::OnHeaders(const spdy::SpdyHeadersControlFrame& frame,
1149 const linked_ptr<spdy::SpdyHeaderBlock>& headers) { 1219 const linked_ptr<spdy::SpdyHeaderBlock>& headers) {
1150 spdy::SpdyStreamId stream_id = frame.stream_id(); 1220 spdy::SpdyStreamId stream_id = frame.stream_id();
1151 1221
1152 bool valid_stream = IsStreamActive(stream_id); 1222 bool valid_stream = IsStreamActive(stream_id);
1153 if (!valid_stream) { 1223 if (!valid_stream) {
1154 // NOTE: it may just be that the stream was cancelled. 1224 // NOTE: it may just be that the stream was cancelled.
1155 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id; 1225 LOG(WARNING) << "Received HEADERS for invalid stream " << stream_id;
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1497 if (it == pending_callback_map_.end()) 1567 if (it == pending_callback_map_.end())
1498 return; 1568 return;
1499 1569
1500 CompletionCallback* callback = it->second.callback; 1570 CompletionCallback* callback = it->second.callback;
1501 int result = it->second.result; 1571 int result = it->second.result;
1502 pending_callback_map_.erase(it); 1572 pending_callback_map_.erase(it);
1503 callback->Run(result); 1573 callback->Run(result);
1504 } 1574 }
1505 1575
1506 } // namespace net 1576 } // namespace net
OLDNEW
« net/spdy/spdy_framer.cc ('K') | « net/spdy/spdy_session.h ('k') | net/spdy/spdy_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698