| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/quic/quic_headers_stream.h" | 5 #include "net/quic/quic_headers_stream.h" |
| 6 | 6 |
| 7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
| 8 #include "net/quic/quic_session.h" | 8 #include "net/quic/quic_session.h" |
| 9 | 9 |
| 10 using base::StringPiece; | 10 using base::StringPiece; |
| 11 using std::string; | 11 using std::string; |
| 12 | 12 |
| 13 namespace net { | 13 namespace net { |
| 14 | 14 |
| 15 namespace { | 15 namespace { |
| 16 | 16 |
| 17 const QuicStreamId kInvalidStreamId = 0; | 17 const QuicStreamId kInvalidStreamId = 0; |
| 18 | 18 |
| 19 } // namespace | 19 } // namespace |
| 20 | 20 |
| 21 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to | 21 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to |
| 22 // the QuicDataStream, and closes the connection if any unexpected frames | 22 // the QuicDataStream, and closes the connection if any unexpected frames |
| 23 // are received. | 23 // are received. |
| 24 class QuicHeadersStream::SpdyFramerVisitor | 24 class QuicHeadersStream::SpdyFramerVisitor |
| 25 : public SpdyFramerVisitorInterface, | 25 : public SpdyFramerVisitorInterface, |
| 26 public SpdyFramerDebugVisitorInterface { | 26 public SpdyFramerDebugVisitorInterface { |
| 27 public: | 27 public: |
| 28 explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {} | 28 SpdyFramerVisitor(SpdyMajorVersion spdy_version, QuicHeadersStream* stream) |
| 29 : spdy_version_(spdy_version), stream_(stream) {} |
| 29 | 30 |
| 30 // SpdyFramerVisitorInterface implementation | 31 // SpdyFramerVisitorInterface implementation |
| 31 void OnSynStream(SpdyStreamId stream_id, | 32 void OnSynStream(SpdyStreamId stream_id, |
| 32 SpdyStreamId associated_stream_id, | 33 SpdyStreamId associated_stream_id, |
| 33 SpdyPriority priority, | 34 SpdyPriority priority, |
| 34 bool fin, | 35 bool fin, |
| 35 bool unidirectional) override { | 36 bool unidirectional) override { |
| 37 if (spdy_version_ != SPDY3) { |
| 38 CloseConnection("SPDY SYN_STREAM frame received."); |
| 39 return; |
| 40 } |
| 41 |
| 36 if (!stream_->IsConnected()) { | 42 if (!stream_->IsConnected()) { |
| 37 return; | 43 return; |
| 38 } | 44 } |
| 39 | 45 |
| 40 if (associated_stream_id != 0) { | 46 if (associated_stream_id != 0) { |
| 41 CloseConnection("associated_stream_id != 0"); | 47 CloseConnection("associated_stream_id != 0"); |
| 42 return; | 48 return; |
| 43 } | 49 } |
| 44 | 50 |
| 45 if (unidirectional != 0) { | 51 if (unidirectional != 0) { |
| 46 CloseConnection("unidirectional != 0"); | 52 CloseConnection("unidirectional != 0"); |
| 47 return; | 53 return; |
| 48 } | 54 } |
| 49 | 55 |
| 50 stream_->OnSynStream(stream_id, priority, fin); | 56 stream_->OnSynStream(stream_id, priority, fin); |
| 51 } | 57 } |
| 52 | 58 |
| 53 void OnSynReply(SpdyStreamId stream_id, bool fin) override { | 59 void OnSynReply(SpdyStreamId stream_id, bool fin) override { |
| 60 if (spdy_version_ != SPDY3) { |
| 61 CloseConnection("SPDY SYN_REPLY frame received."); |
| 62 return; |
| 63 } |
| 64 |
| 54 if (!stream_->IsConnected()) { | 65 if (!stream_->IsConnected()) { |
| 55 return; | 66 return; |
| 56 } | 67 } |
| 57 | 68 |
| 58 stream_->OnSynReply(stream_id, fin); | 69 stream_->OnSynReply(stream_id, fin); |
| 59 } | 70 } |
| 60 | 71 |
| 61 bool OnControlFrameHeaderData(SpdyStreamId stream_id, | 72 bool OnControlFrameHeaderData(SpdyStreamId stream_id, |
| 62 const char* header_data, | 73 const char* header_data, |
| 63 size_t len) override { | 74 size_t len) override { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 void OnGoAway(SpdyStreamId last_accepted_stream_id, | 128 void OnGoAway(SpdyStreamId last_accepted_stream_id, |
| 118 SpdyGoAwayStatus status) override { | 129 SpdyGoAwayStatus status) override { |
| 119 CloseConnection("SPDY GOAWAY frame received."); | 130 CloseConnection("SPDY GOAWAY frame received."); |
| 120 } | 131 } |
| 121 | 132 |
| 122 void OnHeaders(SpdyStreamId stream_id, | 133 void OnHeaders(SpdyStreamId stream_id, |
| 123 bool has_priority, | 134 bool has_priority, |
| 124 SpdyPriority priority, | 135 SpdyPriority priority, |
| 125 bool fin, | 136 bool fin, |
| 126 bool end) override { | 137 bool end) override { |
| 127 CloseConnection("SPDY HEADERS frame received."); | 138 if (spdy_version_ == SPDY3) { |
| 139 CloseConnection("SPDY HEADERS frame received."); |
| 140 return; |
| 141 } |
| 142 if (!stream_->IsConnected()) { |
| 143 return; |
| 144 } |
| 145 if (has_priority) { |
| 146 stream_->OnSynStream(stream_id, priority, fin); |
| 147 } else { |
| 148 stream_->OnSynReply(stream_id, fin); |
| 149 } |
| 128 } | 150 } |
| 129 | 151 |
| 130 void OnWindowUpdate(SpdyStreamId stream_id, | 152 void OnWindowUpdate(SpdyStreamId stream_id, |
| 131 uint32 delta_window_size) override { | 153 uint32 delta_window_size) override { |
| 132 CloseConnection("SPDY WINDOW_UPDATE frame received."); | 154 CloseConnection("SPDY WINDOW_UPDATE frame received."); |
| 133 } | 155 } |
| 134 | 156 |
| 135 void OnPushPromise(SpdyStreamId stream_id, | 157 void OnPushPromise(SpdyStreamId stream_id, |
| 136 SpdyStreamId promised_stream_id, | 158 SpdyStreamId promised_stream_id, |
| 137 bool end) override { | 159 bool end) override { |
| 138 LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer"; | 160 LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer"; |
| 139 CloseConnection("SPDY PUSH_PROMISE frame received."); | 161 CloseConnection("SPDY PUSH_PROMISE frame received."); |
| 140 } | 162 } |
| 141 | 163 |
| 142 void OnContinuation(SpdyStreamId stream_id, bool end) override { | 164 void OnContinuation(SpdyStreamId stream_id, bool end) override { |
| 143 CloseConnection("SPDY CONTINUATION frame received."); | 165 if (spdy_version_ == SPDY3) { |
| 166 LOG(DFATAL) << "CONTINUATION frame received from a SPDY/3 framer"; |
| 167 CloseConnection("SPDY CONTINUATION frame received."); |
| 168 } |
| 144 } | 169 } |
| 145 | 170 |
| 146 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { | 171 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { |
| 147 CloseConnection("Unknown frame type received."); | 172 CloseConnection("Unknown frame type received."); |
| 148 return false; | 173 return false; |
| 149 } | 174 } |
| 150 | 175 |
| 151 // SpdyFramerDebugVisitorInterface implementation | 176 // SpdyFramerDebugVisitorInterface implementation |
| 152 void OnSendCompressedFrame(SpdyStreamId stream_id, | 177 void OnSendCompressedFrame(SpdyStreamId stream_id, |
| 153 SpdyFrameType type, | 178 SpdyFrameType type, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 164 | 189 |
| 165 private: | 190 private: |
| 166 void CloseConnection(const string& details) { | 191 void CloseConnection(const string& details) { |
| 167 if (stream_->IsConnected()) { | 192 if (stream_->IsConnected()) { |
| 168 stream_->CloseConnectionWithDetails( | 193 stream_->CloseConnectionWithDetails( |
| 169 QUIC_INVALID_HEADERS_STREAM_DATA, details); | 194 QUIC_INVALID_HEADERS_STREAM_DATA, details); |
| 170 } | 195 } |
| 171 } | 196 } |
| 172 | 197 |
| 173 private: | 198 private: |
| 199 SpdyMajorVersion spdy_version_; |
| 174 QuicHeadersStream* stream_; | 200 QuicHeadersStream* stream_; |
| 175 | 201 |
| 176 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); | 202 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); |
| 177 }; | 203 }; |
| 178 | 204 |
| 179 QuicHeadersStream::QuicHeadersStream(QuicSession* session) | 205 QuicHeadersStream::QuicHeadersStream(QuicSession* session) |
| 180 : ReliableQuicStream(kHeadersStreamId, session), | 206 : ReliableQuicStream(kHeadersStreamId, session), |
| 181 stream_id_(kInvalidStreamId), | 207 stream_id_(kInvalidStreamId), |
| 182 fin_(false), | 208 fin_(false), |
| 183 frame_len_(0), | 209 frame_len_(0) { |
| 184 spdy_framer_(SPDY3), | 210 InitializeFramer(session->connection()->version()); |
| 185 spdy_framer_visitor_(new SpdyFramerVisitor(this)) { | |
| 186 spdy_framer_.set_visitor(spdy_framer_visitor_.get()); | |
| 187 spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get()); | |
| 188 // The headers stream is exempt from connection level flow control. | 211 // The headers stream is exempt from connection level flow control. |
| 189 DisableConnectionFlowControlForThisStream(); | 212 DisableConnectionFlowControlForThisStream(); |
| 190 } | 213 } |
| 191 | 214 |
| 192 QuicHeadersStream::~QuicHeadersStream() {} | 215 QuicHeadersStream::~QuicHeadersStream() {} |
| 193 | 216 |
| 194 size_t QuicHeadersStream::WriteHeaders( | 217 size_t QuicHeadersStream::WriteHeaders( |
| 195 QuicStreamId stream_id, | 218 QuicStreamId stream_id, |
| 196 const SpdyHeaderBlock& headers, | 219 const SpdyHeaderBlock& headers, |
| 197 bool fin, | 220 bool fin, |
| 221 QuicPriority priority, |
| 198 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | 222 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { |
| 199 scoped_ptr<SpdySerializedFrame> frame; | 223 scoped_ptr<SpdySerializedFrame> frame; |
| 200 if (session()->is_server()) { | 224 if (spdy_framer_->protocol_version() == SPDY3) { |
| 201 SpdySynReplyIR syn_reply(stream_id); | 225 if (session()->is_server()) { |
| 202 syn_reply.set_name_value_block(headers); | 226 SpdySynReplyIR syn_reply(stream_id); |
| 203 syn_reply.set_fin(fin); | 227 syn_reply.set_name_value_block(headers); |
| 204 frame.reset(spdy_framer_.SerializeFrame(syn_reply)); | 228 syn_reply.set_fin(fin); |
| 229 frame.reset(spdy_framer_->SerializeFrame(syn_reply)); |
| 230 } else { |
| 231 SpdySynStreamIR syn_stream(stream_id); |
| 232 syn_stream.set_name_value_block(headers); |
| 233 syn_stream.set_fin(fin); |
| 234 syn_stream.set_priority(priority); |
| 235 frame.reset(spdy_framer_->SerializeFrame(syn_stream)); |
| 236 } |
| 205 } else { | 237 } else { |
| 206 SpdySynStreamIR syn_stream(stream_id); | 238 SpdyHeadersIR headers_frame(stream_id); |
| 207 syn_stream.set_name_value_block(headers); | 239 headers_frame.set_name_value_block(headers); |
| 208 syn_stream.set_fin(fin); | 240 headers_frame.set_fin(fin); |
| 209 frame.reset(spdy_framer_.SerializeFrame(syn_stream)); | 241 if (!session()->is_server()) { |
| 242 headers_frame.set_has_priority(true); |
| 243 headers_frame.set_priority(priority); |
| 244 } |
| 245 frame.reset(spdy_framer_->SerializeFrame(headers_frame)); |
| 210 } | 246 } |
| 211 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, | 247 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, |
| 212 ack_notifier_delegate); | 248 ack_notifier_delegate); |
| 213 return frame->size(); | 249 return frame->size(); |
| 214 } | 250 } |
| 215 | 251 |
| 216 uint32 QuicHeadersStream::ProcessRawData(const char* data, | 252 uint32 QuicHeadersStream::ProcessRawData(const char* data, |
| 217 uint32 data_len) { | 253 uint32 data_len) { |
| 218 return spdy_framer_.ProcessInput(data, data_len); | 254 return spdy_framer_->ProcessInput(data, data_len); |
| 219 } | 255 } |
| 220 | 256 |
| 221 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; } | 257 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; } |
| 222 | 258 |
| 259 void QuicHeadersStream::OnSuccessfulVersionNegotiation(QuicVersion version) { |
| 260 InitializeFramer(version); |
| 261 } |
| 262 |
| 263 void QuicHeadersStream::InitializeFramer(QuicVersion version) { |
| 264 SpdyMajorVersion spdy_version = version > QUIC_VERSION_23 ? SPDY4 : SPDY3; |
| 265 if (spdy_framer_.get() != nullptr && |
| 266 spdy_framer_->protocol_version() == spdy_version) { |
| 267 return; |
| 268 } |
| 269 spdy_framer_.reset(new SpdyFramer(spdy_version)); |
| 270 spdy_framer_visitor_.reset(new SpdyFramerVisitor(spdy_version, this)); |
| 271 spdy_framer_->set_visitor(spdy_framer_visitor_.get()); |
| 272 spdy_framer_->set_debug_visitor(spdy_framer_visitor_.get()); |
| 273 } |
| 274 |
| 223 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id, | 275 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id, |
| 224 SpdyPriority priority, | 276 SpdyPriority priority, |
| 225 bool fin) { | 277 bool fin) { |
| 226 if (!session()->is_server()) { | 278 if (!session()->is_server()) { |
| 227 CloseConnectionWithDetails( | 279 CloseConnectionWithDetails( |
| 228 QUIC_INVALID_HEADERS_STREAM_DATA, | 280 QUIC_INVALID_HEADERS_STREAM_DATA, |
| 229 "SPDY SYN_STREAM frame received at the client"); | 281 "SPDY SYN_STREAM frame received at the client"); |
| 230 return; | 282 return; |
| 231 } | 283 } |
| 232 DCHECK_EQ(kInvalidStreamId, stream_id_); | 284 DCHECK_EQ(kInvalidStreamId, stream_id_); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 258 // Reset state for the next frame. | 310 // Reset state for the next frame. |
| 259 stream_id_ = kInvalidStreamId; | 311 stream_id_ = kInvalidStreamId; |
| 260 fin_ = false; | 312 fin_ = false; |
| 261 frame_len_ = 0; | 313 frame_len_ = 0; |
| 262 } else { | 314 } else { |
| 263 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); | 315 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
| 264 } | 316 } |
| 265 } | 317 } |
| 266 | 318 |
| 267 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { | 319 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { |
| 268 DCHECK_EQ(kInvalidStreamId, stream_id_); | 320 if (spdy_framer_->protocol_version() == SPDY3) { |
| 269 DCHECK_EQ(0u, frame_len_); | 321 // SPDY/3 headers always fit into a single frame, so the previous headers |
| 270 frame_len_ = frame_len; | 322 // should be completely processed when a new frame is received. |
| 323 DCHECK_EQ(kInvalidStreamId, stream_id_); |
| 324 DCHECK_EQ(0u, frame_len_); |
| 325 } |
| 326 frame_len_ += frame_len; |
| 271 } | 327 } |
| 272 | 328 |
| 273 bool QuicHeadersStream::IsConnected() { | 329 bool QuicHeadersStream::IsConnected() { |
| 274 return session()->connection()->connected(); | 330 return session()->connection()->connected(); |
| 275 } | 331 } |
| 276 | 332 |
| 277 } // namespace net | 333 } // namespace net |
| OLD | NEW |