| Index: net/spdy/spdy_session.cc
|
| ===================================================================
|
| --- net/spdy/spdy_session.cc (revision 80449)
|
| +++ net/spdy/spdy_session.cc (working copy)
|
| @@ -246,6 +246,8 @@
|
| initial_recv_window_size_(spdy::kSpdyStreamInitialWindowSize),
|
| net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)) {
|
| DCHECK(HttpStreamFactory::spdy_enabled());
|
| + // TODO(jtl): Do we need to set kMaxSpdyFrameChunkSize here based on which
|
| + // transport protocol we're using?
|
| net_log_.BeginEvent(
|
| NetLog::TYPE_SPDY_SESSION,
|
| make_scoped_refptr(
|
| @@ -764,7 +766,8 @@
|
| DCHECK_GT(size, 0u);
|
|
|
| // TODO(mbelshe): We have too much copying of data here.
|
| - IOBufferWithSize* buffer = new IOBufferWithSize(size);
|
| + // TODO(jtl): Why is this "WithSize"?
|
| + IOBuffer* buffer = new IOBufferWithSize(size);
|
| memcpy(buffer->data(), compressed_frame->data(), size);
|
|
|
| // Attempt to send the frame.
|
| @@ -773,11 +776,26 @@
|
| size = uncompressed_frame.length() + spdy::SpdyFrame::size();
|
| in_flight_write_ = next_buffer;
|
| }
|
| + // SCTP stream ID assignment is delayed until now, rather than done in
|
| + // QueueFrame, to be sure the association (connection) has been
|
| + // established. SCTP stream ID numbers can't be assigned until
|
| + // g_max_sctp_streams is set, and that can't happen until the association
|
| + // is established.
|
| + // TODO(jtl): In order to support piggy-backing DATA on the COOKIE_ECHO,
|
| + // as is allowed in FreeBSD and Mac OS X, we need to find a way to allow
|
| + // at least sctp stream ID 1 to be used prior to g_max_sctp_streams being
|
| + // set.
|
| + //
|
| + if (using_sctp()) {
|
| + spdy::SpdyFrame frame(in_flight_write_.buffer()->data(), false);
|
| + in_flight_write_.set_sctp_stream_id(GetSctpStreamID(frame));
|
| + }
|
| } else {
|
| DCHECK(in_flight_write_.buffer()->BytesRemaining());
|
| }
|
|
|
| write_pending_ = true;
|
| +
|
| int rv = connection_->socket()->Write(in_flight_write_.buffer(),
|
| in_flight_write_.buffer()->BytesRemaining(), &write_callback_);
|
| if (rv == net::ERR_IO_PENDING)
|
| @@ -836,12 +854,54 @@
|
| return id;
|
| }
|
|
|
| +uint16 SpdySession::GetSctpStreamID(const spdy::SpdyFrame& frame) {
|
| + uint32 stream_id = 0;
|
| + if (!frame.is_control_frame()) {
|
| + stream_id = reinterpret_cast<const spdy::SpdyDataFrame&>(frame).stream_id();
|
| + } else if (!using_sctp_control_stream()) {
|
| + spdy::SpdyControlType type =
|
| + reinterpret_cast<const spdy::SpdyControlFrame&>(frame).type();
|
| + // n.b. When not using an SCTP control stream, SETTINGS, NOOP, PING
|
| + // and GOAWAY control frames are still sent on SCTP stream 0 because
|
| + // they are not associated with a specific SPDY stream.
|
| + switch (type) {
|
| + case spdy::SYN_STREAM:
|
| + stream_id = static_cast<const spdy::SpdySynStreamControlFrame&>
|
| + (frame).stream_id();
|
| + break;
|
| + case spdy::SYN_REPLY:
|
| + stream_id = static_cast<const spdy::SpdySynReplyControlFrame&>
|
| + (frame).stream_id();
|
| + break;
|
| + case spdy::RST_STREAM:
|
| + stream_id = static_cast<const spdy::SpdyRstStreamControlFrame&>
|
| + (frame).stream_id();
|
| + break;
|
| + case spdy::HEADERS:
|
| + stream_id = static_cast<const spdy::SpdyHeadersControlFrame&>
|
| + (frame).stream_id();
|
| + break;
|
| + case spdy::WINDOW_UPDATE:
|
| + stream_id = static_cast<const spdy::SpdyWindowUpdateControlFrame&>
|
| + (frame).stream_id();
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + return stream_id ? MapSpdyToSctp(stream_id) : 0;
|
| +}
|
| +
|
| void SpdySession::QueueFrame(spdy::SpdyFrame* frame,
|
| spdy::SpdyPriority priority,
|
| SpdyStream* stream) {
|
| int length = spdy::SpdyFrame::size() + frame->length();
|
| - IOBuffer* buffer = new IOBuffer(length);
|
| + IOBuffer* buffer;
|
| + buffer = new IOBuffer(length);
|
| memcpy(buffer->data(), frame->data(), length);
|
| + // can't assign IOBuffer::sctp_stream_id_ here because the association may not
|
| + // be established yet. See comments in SpdySession::WriteSocket()
|
| queue_.push(SpdyIOBuffer(buffer, length, priority, stream));
|
|
|
| WriteSocketLater();
|
| @@ -1124,6 +1184,8 @@
|
| }
|
|
|
| scoped_refptr<SpdyStream> stream = active_streams_[stream_id];
|
| + if (using_sctp() && using_sctp_control_stream())
|
| + stream->set_syn_reply_received();
|
| CHECK_EQ(stream->stream_id(), stream_id);
|
| CHECK(!stream->cancelled());
|
|
|
| @@ -1143,6 +1205,14 @@
|
| }
|
|
|
| Respond(*headers, stream);
|
| +
|
| + // When using SCTP with a control stream, loss can result in the SYN_REPLY
|
| + // arriving after all the data. In this case close_pending() will be true
|
| + // and we need to call OnDataReceived to shutdown the metrics and close the
|
| + // stream.
|
| + if (using_sctp() && using_sctp_control_stream() &&
|
| + stream->close_pending())
|
| + stream->OnDataReceived(NULL, 0);
|
| }
|
|
|
| void SpdySession::OnHeaders(const spdy::SpdyHeadersControlFrame& frame,
|
|
|