| 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/quic/reliable_quic_stream.h" | 5 #include "net/quic/reliable_quic_stream.h" |
| 6 | 6 |
| 7 #include "net/quic/quic_session.h" | 7 #include "net/quic/quic_session.h" |
| 8 #include "net/quic/quic_spdy_decompressor.h" | 8 #include "net/quic/quic_spdy_decompressor.h" |
| 9 #include "net/spdy/write_blocked_list.h" |
| 9 | 10 |
| 10 using base::StringPiece; | 11 using base::StringPiece; |
| 11 using std::min; | 12 using std::min; |
| 12 | 13 |
| 13 namespace net { | 14 namespace net { |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 | 17 |
| 17 // This is somewhat arbitrary. It's possible, but unlikely, we will either fail | 18 // This is somewhat arbitrary. It's possible, but unlikely, we will either fail |
| 18 // to set a priority client-side, or cancel a stream before stripping the | 19 // to set a priority client-side, or cancel a stream before stripping the |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 | 187 |
| 187 bool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) { | 188 bool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) { |
| 188 return session_->GetSSLInfo(ssl_info); | 189 return session_->GetSSLInfo(ssl_info); |
| 189 } | 190 } |
| 190 | 191 |
| 191 QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) { | 192 QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) { |
| 192 DCHECK(data.size() > 0 || fin); | 193 DCHECK(data.size() > 0 || fin); |
| 193 return WriteOrBuffer(data, fin); | 194 return WriteOrBuffer(data, fin); |
| 194 } | 195 } |
| 195 | 196 |
| 197 |
| 198 void ReliableQuicStream::set_priority(QuicPriority priority) { |
| 199 DCHECK_EQ(0u, stream_bytes_written_); |
| 200 priority_ = priority; |
| 201 } |
| 202 |
| 196 QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) { | 203 QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) { |
| 197 DCHECK(!fin_buffered_); | 204 DCHECK(!fin_buffered_); |
| 198 | 205 |
| 199 QuicConsumedData consumed_data(0, false); | 206 QuicConsumedData consumed_data(0, false); |
| 200 fin_buffered_ = fin; | 207 fin_buffered_ = fin; |
| 201 | 208 |
| 202 if (queued_data_.empty()) { | 209 if (queued_data_.empty()) { |
| 203 consumed_data = WriteDataInternal(string(data.data(), data.length()), fin); | 210 consumed_data = WriteDataInternal(string(data.data(), data.length()), fin); |
| 204 DCHECK_LE(consumed_data.bytes_consumed, data.length()); | 211 DCHECK_LE(consumed_data.bytes_consumed, data.length()); |
| 205 } | 212 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 228 queued_data_.pop_front(); | 235 queued_data_.pop_front(); |
| 229 } else { | 236 } else { |
| 230 queued_data_.front().erase(0, consumed_data.bytes_consumed); | 237 queued_data_.front().erase(0, consumed_data.bytes_consumed); |
| 231 break; | 238 break; |
| 232 } | 239 } |
| 233 } | 240 } |
| 234 } | 241 } |
| 235 | 242 |
| 236 QuicConsumedData ReliableQuicStream::WriteDataInternal( | 243 QuicConsumedData ReliableQuicStream::WriteDataInternal( |
| 237 StringPiece data, bool fin) { | 244 StringPiece data, bool fin) { |
| 245 struct iovec iov = {const_cast<char*>(data.data()), |
| 246 static_cast<size_t>(data.size())}; |
| 247 return WritevDataInternal(&iov, 1, fin); |
| 248 } |
| 249 |
| 250 QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov, |
| 251 int count, |
| 252 bool fin) { |
| 238 if (write_side_closed_) { | 253 if (write_side_closed_) { |
| 239 DLOG(ERROR) << "Attempt to write when the write side is closed"; | 254 DLOG(ERROR) << "Attempt to write when the write side is closed"; |
| 240 return QuicConsumedData(0, false); | 255 return QuicConsumedData(0, false); |
| 241 } | 256 } |
| 242 | 257 |
| 258 size_t write_length = 0u; |
| 259 for (int i = 0; i < count; ++i) { |
| 260 write_length += iov[i].iov_len; |
| 261 } |
| 243 QuicConsumedData consumed_data = | 262 QuicConsumedData consumed_data = |
| 244 session()->WriteData(id(), data, stream_bytes_written_, fin); | 263 session()->WritevData(id(), iov, count, stream_bytes_written_, fin); |
| 245 stream_bytes_written_ += consumed_data.bytes_consumed; | 264 stream_bytes_written_ += consumed_data.bytes_consumed; |
| 246 if (consumed_data.bytes_consumed == data.length()) { | 265 if (consumed_data.bytes_consumed == write_length) { |
| 247 if (fin && consumed_data.fin_consumed) { | 266 if (fin && consumed_data.fin_consumed) { |
| 248 fin_sent_ = true; | 267 fin_sent_ = true; |
| 249 CloseWriteSide(); | 268 CloseWriteSide(); |
| 250 } else if (fin && !consumed_data.fin_consumed) { | 269 } else if (fin && !consumed_data.fin_consumed) { |
| 251 session_->MarkWriteBlocked(id()); | 270 session_->MarkWriteBlocked(id(), EffectivePriority()); |
| 252 } | 271 } |
| 253 } else { | 272 } else { |
| 254 session_->MarkWriteBlocked(id()); | 273 session_->MarkWriteBlocked(id(), EffectivePriority()); |
| 255 } | 274 } |
| 256 return consumed_data; | 275 return consumed_data; |
| 257 } | 276 } |
| 258 | 277 |
| 278 QuicPriority ReliableQuicStream::EffectivePriority() const { |
| 279 return priority(); |
| 280 } |
| 281 |
| 259 void ReliableQuicStream::CloseReadSide() { | 282 void ReliableQuicStream::CloseReadSide() { |
| 260 if (read_side_closed_) { | 283 if (read_side_closed_) { |
| 261 return; | 284 return; |
| 262 } | 285 } |
| 263 DLOG(INFO) << "Done reading from stream " << id(); | 286 DLOG(INFO) << "Done reading from stream " << id(); |
| 264 | 287 |
| 265 read_side_closed_ = true; | 288 read_side_closed_ = true; |
| 266 if (write_side_closed_) { | 289 if (write_side_closed_) { |
| 267 DLOG(INFO) << "Closing stream: " << id(); | 290 DLOG(INFO) << "Closing stream: " << id(); |
| 268 session_->CloseStream(id()); | 291 session_->CloseStream(id()); |
| 269 } | 292 } |
| 270 } | 293 } |
| 271 | 294 |
| 272 uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) { | 295 uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) { |
| 273 if (id() == kCryptoStreamId) { | 296 if (id() == kCryptoStreamId) { |
| 274 if (data_len == 0) { | 297 if (data_len == 0) { |
| 275 return 0; | 298 return 0; |
| 276 } | 299 } |
| 277 // The crypto stream does not use compression. | 300 // The crypto stream does not use compression. |
| 278 return ProcessData(data, data_len); | 301 return ProcessData(data, data_len); |
| 279 } | 302 } |
| 280 | 303 |
| 281 uint32 total_bytes_consumed = 0; | 304 uint32 total_bytes_consumed = 0; |
| 282 if (headers_id_ == 0u) { | 305 if (headers_id_ == 0u) { |
| 283 total_bytes_consumed += StripPriorityAndHeaderId(data, data_len); | 306 total_bytes_consumed += StripPriorityAndHeaderId(data, data_len); |
| 284 data += total_bytes_consumed; | 307 data += total_bytes_consumed; |
| 285 data_len -= total_bytes_consumed; | 308 data_len -= total_bytes_consumed; |
| 286 if (data_len == 0) { | 309 if (data_len == 0 || !session_->connection()->connected()) { |
| 287 return total_bytes_consumed; | 310 return total_bytes_consumed; |
| 288 } | 311 } |
| 289 } | 312 } |
| 290 DCHECK_NE(0u, headers_id_); | 313 DCHECK_NE(0u, headers_id_); |
| 291 | 314 |
| 292 // Once the headers are finished, we simply pass the data through. | 315 // Once the headers are finished, we simply pass the data through. |
| 293 if (headers_decompressed_) { | 316 if (headers_decompressed_) { |
| 294 // Some buffered header data remains. | 317 // Some buffered header data remains. |
| 295 if (!decompressed_headers_.empty()) { | 318 if (!decompressed_headers_.empty()) { |
| 296 ProcessHeaderData(); | 319 ProcessHeaderData(); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } | 481 } |
| 459 } | 482 } |
| 460 | 483 |
| 461 uint32 ReliableQuicStream::StripPriorityAndHeaderId( | 484 uint32 ReliableQuicStream::StripPriorityAndHeaderId( |
| 462 const char* data, uint32 data_len) { | 485 const char* data, uint32 data_len) { |
| 463 uint32 total_bytes_parsed = 0; | 486 uint32 total_bytes_parsed = 0; |
| 464 | 487 |
| 465 if (!priority_parsed_ && | 488 if (!priority_parsed_ && |
| 466 session_->connection()->version() >= QUIC_VERSION_9 && | 489 session_->connection()->version() >= QUIC_VERSION_9 && |
| 467 session_->connection()->is_server()) { | 490 session_->connection()->is_server()) { |
| 491 QuicPriority temporary_priority = priority_; |
| 468 total_bytes_parsed = StripUint32( | 492 total_bytes_parsed = StripUint32( |
| 469 data, data_len, &headers_id_and_priority_buffer_, &priority_); | 493 data, data_len, &headers_id_and_priority_buffer_, &temporary_priority); |
| 470 if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) { | 494 if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) { |
| 471 // TODO(alyssar) check for priority out of bounds. | |
| 472 priority_parsed_ = true; | 495 priority_parsed_ = true; |
| 496 // Spdy priorities are inverted, so the highest numerical value is the |
| 497 // lowest legal priority. |
| 498 if (temporary_priority > static_cast<QuicPriority>(kLowestPriority)) { |
| 499 session_->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY); |
| 500 return 0; |
| 501 } |
| 502 priority_ = temporary_priority; |
| 473 } | 503 } |
| 474 data += total_bytes_parsed; | 504 data += total_bytes_parsed; |
| 475 data_len -= total_bytes_parsed; | 505 data_len -= total_bytes_parsed; |
| 476 } | 506 } |
| 477 if (data_len > 0 && headers_id_ == 0u) { | 507 if (data_len > 0 && headers_id_ == 0u) { |
| 478 // The headers ID has not yet been read. Strip it from the beginning of | 508 // The headers ID has not yet been read. Strip it from the beginning of |
| 479 // the data stream. | 509 // the data stream. |
| 480 total_bytes_parsed += StripUint32( | 510 total_bytes_parsed += StripUint32( |
| 481 data, data_len, &headers_id_and_priority_buffer_, &headers_id_); | 511 data, data_len, &headers_id_and_priority_buffer_, &headers_id_); |
| 482 } | 512 } |
| 483 return total_bytes_parsed; | 513 return total_bytes_parsed; |
| 484 } | 514 } |
| 485 | 515 |
| 486 } // namespace net | 516 } // namespace net |
| OLD | NEW |