| 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 CloseConnection("SPDY CONTINUATION frame received."); |
| 167 } |
| 144 } | 168 } |
| 145 | 169 |
| 146 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { | 170 bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override { |
| 147 CloseConnection("Unknown frame type received."); | 171 CloseConnection("Unknown frame type received."); |
| 148 return false; | 172 return false; |
| 149 } | 173 } |
| 150 | 174 |
| 151 // SpdyFramerDebugVisitorInterface implementation | 175 // SpdyFramerDebugVisitorInterface implementation |
| 152 void OnSendCompressedFrame(SpdyStreamId stream_id, | 176 void OnSendCompressedFrame(SpdyStreamId stream_id, |
| 153 SpdyFrameType type, | 177 SpdyFrameType type, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 164 | 188 |
| 165 private: | 189 private: |
| 166 void CloseConnection(const string& details) { | 190 void CloseConnection(const string& details) { |
| 167 if (stream_->IsConnected()) { | 191 if (stream_->IsConnected()) { |
| 168 stream_->CloseConnectionWithDetails( | 192 stream_->CloseConnectionWithDetails( |
| 169 QUIC_INVALID_HEADERS_STREAM_DATA, details); | 193 QUIC_INVALID_HEADERS_STREAM_DATA, details); |
| 170 } | 194 } |
| 171 } | 195 } |
| 172 | 196 |
| 173 private: | 197 private: |
| 198 SpdyMajorVersion spdy_version_; |
| 174 QuicHeadersStream* stream_; | 199 QuicHeadersStream* stream_; |
| 175 | 200 |
| 176 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); | 201 DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor); |
| 177 }; | 202 }; |
| 178 | 203 |
| 179 QuicHeadersStream::QuicHeadersStream(QuicSession* session) | 204 QuicHeadersStream::QuicHeadersStream(QuicSession* session) |
| 180 : ReliableQuicStream(kHeadersStreamId, session), | 205 : ReliableQuicStream(kHeadersStreamId, session), |
| 181 stream_id_(kInvalidStreamId), | 206 stream_id_(kInvalidStreamId), |
| 182 fin_(false), | 207 fin_(false), |
| 183 frame_len_(0), | 208 frame_len_(0) { |
| 184 spdy_framer_(SPDY3), | 209 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. | 210 // The headers stream is exempt from connection level flow control. |
| 189 DisableConnectionFlowControlForThisStream(); | 211 DisableConnectionFlowControlForThisStream(); |
| 190 } | 212 } |
| 191 | 213 |
| 192 QuicHeadersStream::~QuicHeadersStream() {} | 214 QuicHeadersStream::~QuicHeadersStream() {} |
| 193 | 215 |
| 194 size_t QuicHeadersStream::WriteHeaders( | 216 size_t QuicHeadersStream::WriteHeaders( |
| 195 QuicStreamId stream_id, | 217 QuicStreamId stream_id, |
| 196 const SpdyHeaderBlock& headers, | 218 const SpdyHeaderBlock& headers, |
| 197 bool fin, | 219 bool fin, |
| 198 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { | 220 QuicAckNotifier::DelegateInterface* ack_notifier_delegate) { |
| 199 scoped_ptr<SpdySerializedFrame> frame; | 221 scoped_ptr<SpdySerializedFrame> frame; |
| 200 if (session()->is_server()) { | 222 if (spdy_framer_->protocol_version() == SPDY3) { |
| 201 SpdySynReplyIR syn_reply(stream_id); | 223 if (session()->is_server()) { |
| 202 syn_reply.set_name_value_block(headers); | 224 SpdySynReplyIR syn_reply(stream_id); |
| 203 syn_reply.set_fin(fin); | 225 syn_reply.set_name_value_block(headers); |
| 204 frame.reset(spdy_framer_.SerializeFrame(syn_reply)); | 226 syn_reply.set_fin(fin); |
| 227 frame.reset(spdy_framer_->SerializeFrame(syn_reply)); |
| 228 } else { |
| 229 SpdySynStreamIR syn_stream(stream_id); |
| 230 syn_stream.set_name_value_block(headers); |
| 231 syn_stream.set_fin(fin); |
| 232 frame.reset(spdy_framer_->SerializeFrame(syn_stream)); |
| 233 } |
| 205 } else { | 234 } else { |
| 206 SpdySynStreamIR syn_stream(stream_id); | 235 SpdyHeadersIR headers_frame(stream_id); |
| 207 syn_stream.set_name_value_block(headers); | 236 headers_frame.set_name_value_block(headers); |
| 208 syn_stream.set_fin(fin); | 237 headers_frame.set_fin(fin); |
| 209 frame.reset(spdy_framer_.SerializeFrame(syn_stream)); | 238 if (!session()->is_server()) { |
| 239 headers_frame.set_has_priority(true); |
| 240 } |
| 241 frame.reset(spdy_framer_->SerializeFrame(headers_frame)); |
| 210 } | 242 } |
| 211 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, | 243 WriteOrBufferData(StringPiece(frame->data(), frame->size()), false, |
| 212 ack_notifier_delegate); | 244 ack_notifier_delegate); |
| 213 return frame->size(); | 245 return frame->size(); |
| 214 } | 246 } |
| 215 | 247 |
| 216 uint32 QuicHeadersStream::ProcessRawData(const char* data, | 248 uint32 QuicHeadersStream::ProcessRawData(const char* data, |
| 217 uint32 data_len) { | 249 uint32 data_len) { |
| 218 return spdy_framer_.ProcessInput(data, data_len); | 250 return spdy_framer_->ProcessInput(data, data_len); |
| 219 } | 251 } |
| 220 | 252 |
| 221 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; } | 253 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; } |
| 222 | 254 |
| 255 void QuicHeadersStream::OnSuccessfulVersionNegotiation(QuicVersion version) { |
| 256 InitializeFramer(version); |
| 257 } |
| 258 |
| 259 void QuicHeadersStream::InitializeFramer(QuicVersion version) { |
| 260 SpdyMajorVersion spdy_version = version > QUIC_VERSION_23 ? SPDY4 : SPDY3; |
| 261 if (spdy_framer_.get() != nullptr && |
| 262 spdy_framer_->protocol_version() == spdy_version) { |
| 263 return; |
| 264 } |
| 265 spdy_framer_.reset(new SpdyFramer(spdy_version)); |
| 266 spdy_framer_visitor_.reset(new SpdyFramerVisitor(spdy_version, this)); |
| 267 spdy_framer_->set_visitor(spdy_framer_visitor_.get()); |
| 268 spdy_framer_->set_debug_visitor(spdy_framer_visitor_.get()); |
| 269 } |
| 270 |
| 223 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id, | 271 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id, |
| 224 SpdyPriority priority, | 272 SpdyPriority priority, |
| 225 bool fin) { | 273 bool fin) { |
| 226 if (!session()->is_server()) { | 274 if (!session()->is_server()) { |
| 227 CloseConnectionWithDetails( | 275 CloseConnectionWithDetails( |
| 228 QUIC_INVALID_HEADERS_STREAM_DATA, | 276 QUIC_INVALID_HEADERS_STREAM_DATA, |
| 229 "SPDY SYN_STREAM frame received at the client"); | 277 "SPDY SYN_STREAM frame received at the client"); |
| 230 return; | 278 return; |
| 231 } | 279 } |
| 232 DCHECK_EQ(kInvalidStreamId, stream_id_); | 280 DCHECK_EQ(kInvalidStreamId, stream_id_); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 258 // Reset state for the next frame. | 306 // Reset state for the next frame. |
| 259 stream_id_ = kInvalidStreamId; | 307 stream_id_ = kInvalidStreamId; |
| 260 fin_ = false; | 308 fin_ = false; |
| 261 frame_len_ = 0; | 309 frame_len_ = 0; |
| 262 } else { | 310 } else { |
| 263 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); | 311 session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len)); |
| 264 } | 312 } |
| 265 } | 313 } |
| 266 | 314 |
| 267 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { | 315 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) { |
| 268 DCHECK_EQ(kInvalidStreamId, stream_id_); | 316 // DCHECK_EQ(kInvalidStreamId, stream_id_); |
| 269 DCHECK_EQ(0u, frame_len_); | 317 // DCHECK_EQ(0u, frame_len_); |
| 270 frame_len_ = frame_len; | 318 frame_len_ += frame_len; |
| 271 } | 319 } |
| 272 | 320 |
| 273 bool QuicHeadersStream::IsConnected() { | 321 bool QuicHeadersStream::IsConnected() { |
| 274 return session()->connection()->connected(); | 322 return session()->connection()->connected(); |
| 275 } | 323 } |
| 276 | 324 |
| 277 } // namespace net | 325 } // namespace net |
| OLD | NEW |