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 3 // found in the LICENSE file. 4 5 #include "net/quic/quic_http_stream.h" 6 7 #include "base/callback_helpers.h" 8 #include "base/metrics/histogram.h" 9 #include "base/strings/stringprintf.h" 10 #include "net/base/io_buffer.h" 11 #include "net/base/net_errors.h" 12 #include "net/http/http_response_headers.h" 13 #include "net/http/http_util.h" 14 #include "net/quic/quic_client_session.h" 15 #include "net/quic/quic_http_utils.h" 16 #include "net/quic/quic_reliable_client_stream.h" 17 #include "net/quic/quic_utils.h" 18 #include "net/socket/next_proto.h" 19 #include "net/spdy/spdy_frame_builder.h" 20 #include "net/spdy/spdy_framer.h" 21 #include "net/spdy/spdy_http_utils.h" 22 #include "net/ssl/ssl_info.h" 23 24 namespace net { 25 26 static const size_t kHeaderBufInitialSize = 4096; 27 28 QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession>& session) 29 : next_state_(STATE_NONE), 30 session_(session), 31 session_error_(OK), 32 was_handshake_confirmed_(session->IsCryptoHandshakeConfirmed()), 33 stream_(NULL), 34 request_info_(NULL), 35 request_body_stream_(NULL), 36 priority_(MINIMUM_PRIORITY), 37 response_info_(NULL), 38 response_status_(OK), 39 response_headers_received_(false), 40 read_buf_(new GrowableIOBuffer()), 41 closed_stream_received_bytes_(0), 42 user_buffer_len_(0), 43 weak_factory_(this) { 44 DCHECK(session_); 45 session_->AddObserver(this); 46 } 47 48 QuicHttpStream::~QuicHttpStream() { 49 Close(false); 50 if (session_) 51 session_->RemoveObserver(this); 52 } 53 54 int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info, 55 RequestPriority priority, 56 const BoundNetLog& stream_net_log, 57 const CompletionCallback& callback) { 58 DCHECK(!stream_); 59 if (!session_) 60 return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED : 61 ERR_QUIC_HANDSHAKE_FAILED; 62 63 if (request_info->url.SchemeIsSecure()) { 64 SSLInfo ssl_info; 65 bool secure_session = session_->GetSSLInfo(&ssl_info) && ssl_info.cert; 66 UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.SecureResourceSecureSession", 67 secure_session); 68 if (!secure_session) 69 return ERR_REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC; 70 } 71 72 stream_net_log_ = stream_net_log; 73 request_info_ = request_info; 74 request_time_ = base::Time::Now(); 75 priority_ = priority; 76 77 int rv = stream_request_.StartRequest( 78 session_, &stream_, base::Bind(&QuicHttpStream::OnStreamReady, 79 weak_factory_.GetWeakPtr())); 80 if (rv == ERR_IO_PENDING) { 81 callback_ = callback; 82 } else if (rv == OK) { 83 stream_->SetDelegate(this); 84 } else if (!was_handshake_confirmed_) { 85 rv = ERR_QUIC_HANDSHAKE_FAILED; 86 } 87 88 return rv; 89 } 90 91 void QuicHttpStream::OnStreamReady(int rv) { 92 DCHECK(rv == OK || !stream_); 93 if (rv == OK) { 94 stream_->SetDelegate(this); 95 } else if (!was_handshake_confirmed_) { 96 rv = ERR_QUIC_HANDSHAKE_FAILED; 97 } 98 99 ResetAndReturn(&callback_).Run(rv); 100 } 101 102 int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers, 103 HttpResponseInfo* response, 104 const CompletionCallback& callback) { 105 CHECK(stream_); 106 CHECK(!request_body_stream_); 107 CHECK(!response_info_); 108 CHECK(!callback.is_null()); 109 CHECK(response); 110 111 QuicPriority priority = ConvertRequestPriorityToQuicPriority(priority_); 112 stream_->set_priority(priority); 113 // Store the serialized request headers. 114 CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers, 115 &request_headers_, SPDY3, /*direct=*/true); 116 117 // Store the request body. 118 request_body_stream_ = request_info_->upload_data_stream; 119 if (request_body_stream_) { 120 // TODO(rch): Can we be more precise about when to allocate 121 // raw_request_body_buf_. Removed the following check. DoReadRequestBody() 122 // was being called even if we didn't yet allocate raw_request_body_buf_. 123 // && (request_body_stream_->size() || 124 // request_body_stream_->is_chunked())) 125 // Use 10 packets as the body buffer size to give enough space to 126 // help ensure we don't often send out partial packets. 127 raw_request_body_buf_ = new IOBufferWithSize(10 * kMaxPacketSize); 128 // The request body buffer is empty at first. 129 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), 0); 130 } 131 132 // Store the response info. 133 response_info_ = response; 134 135 next_state_ = STATE_SEND_HEADERS; 136 int rv = DoLoop(OK); 137 if (rv == ERR_IO_PENDING) 138 callback_ = callback; 139 140 return rv > 0 ? OK : rv; 141 } 142 143 UploadProgress QuicHttpStream::GetUploadProgress() const { 144 if (!request_body_stream_) 145 return UploadProgress(); 146 147 return UploadProgress(request_body_stream_->position(), 148 request_body_stream_->size()); 149 } 150 151 int QuicHttpStream::ReadResponseHeaders(const CompletionCallback& callback) { 152 CHECK(!callback.is_null()); 153 154 if (stream_ == NULL) 155 return response_status_; 156 157 // Check if we already have the response headers. If so, return synchronously. 158 if (response_headers_received_) 159 return OK; 160 161 // Still waiting for the response, return IO_PENDING. 162 CHECK(callback_.is_null()); 163 callback_ = callback; 164 return ERR_IO_PENDING; 165 } 166 167 int QuicHttpStream::ReadResponseBody( 168 IOBuffer* buf, int buf_len, const CompletionCallback& callback) { 169 CHECK(buf); 170 CHECK(buf_len); 171 CHECK(!callback.is_null()); 172 173 // If we have data buffered, complete the IO immediately. 174 if (!response_body_.empty()) { 175 int bytes_read = 0; 176 while (!response_body_.empty() && buf_len > 0) { 177 scoped_refptr<IOBufferWithSize> data = response_body_.front(); 178 const int bytes_to_copy = std::min(buf_len, data->size()); 179 memcpy(&(buf->data()[bytes_read]), data->data(), bytes_to_copy); 180 buf_len -= bytes_to_copy; 181 if (bytes_to_copy == data->size()) { 182 response_body_.pop_front(); 183 } else { 184 const int bytes_remaining = data->size() - bytes_to_copy; 185 IOBufferWithSize* new_buffer = new IOBufferWithSize(bytes_remaining); 186 memcpy(new_buffer->data(), &(data->data()[bytes_to_copy]), 187 bytes_remaining); 188 response_body_.pop_front(); 189 response_body_.push_front(make_scoped_refptr(new_buffer)); 190 } 191 bytes_read += bytes_to_copy; 192 } 193 return bytes_read; 194 } 195 196 if (!stream_) { 197 // If the stream is already closed, there is no body to read. 198 return response_status_; 199 } 200 201 CHECK(callback_.is_null()); 202 CHECK(!user_buffer_.get()); 203 CHECK_EQ(0, user_buffer_len_); 204 205 callback_ = callback; 206 user_buffer_ = buf; 207 user_buffer_len_ = buf_len; 208 return ERR_IO_PENDING; 209 } 210 211 void QuicHttpStream::Close(bool not_reusable) { 212 // Note: the not_reusable flag has no meaning for SPDY streams. 213 if (stream_) { 214 closed_stream_received_bytes_ = stream_->stream_bytes_read(); 215 stream_->SetDelegate(NULL); 216 stream_->Reset(QUIC_STREAM_CANCELLED); 217 stream_ = NULL; 218 } 219 } 220 221 HttpStream* QuicHttpStream::RenewStreamForAuth() { 222 return NULL; 223 } 224 225 bool QuicHttpStream::IsResponseBodyComplete() const { 226 return next_state_ == STATE_OPEN && !stream_; 227 } 228 229 bool QuicHttpStream::CanFindEndOfResponse() const { 230 return true; 231 } 232 233 bool QuicHttpStream::IsConnectionReused() const { 234 // TODO(rch): do something smarter here. 235 return stream_ && stream_->id() > 1; 236 } 237 238 void QuicHttpStream::SetConnectionReused() { 239 // QUIC doesn't need an indicator here. 240 } 241 242 bool QuicHttpStream::IsConnectionReusable() const { 243 // QUIC streams aren't considered reusable. 244 return false; 245 } 246 247 int64 QuicHttpStream::GetTotalReceivedBytes() const { 248 if (stream_) { 249 return stream_->stream_bytes_read(); 250 } 251 252 return closed_stream_received_bytes_; 253 } 254 255 bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const { 256 // TODO(mmenke): Figure out what to do here. 257 return true; 258 } 259 260 void QuicHttpStream::GetSSLInfo(SSLInfo* ssl_info) { 261 DCHECK(stream_); 262 stream_->GetSSLInfo(ssl_info); 263 } 264 265 void QuicHttpStream::GetSSLCertRequestInfo( 266 SSLCertRequestInfo* cert_request_info) { 267 DCHECK(stream_); 268 NOTIMPLEMENTED(); 269 } 270 271 bool QuicHttpStream::IsSpdyHttpStream() const { 272 return false; 273 } 274 275 void QuicHttpStream::Drain(HttpNetworkSession* session) { 276 Close(false); 277 delete this; 278 } 279 280 void QuicHttpStream::SetPriority(RequestPriority priority) { 281 priority_ = priority; 282 } 283 284 int QuicHttpStream::OnDataReceived(const char* data, int length) { 285 DCHECK_NE(0, length); 286 // Are we still reading the response headers. 287 if (!response_headers_received_) { 288 // Grow the read buffer if necessary. 289 if (read_buf_->RemainingCapacity() < length) { 290 size_t additional_capacity = length - read_buf_->RemainingCapacity(); 291 if (additional_capacity < kHeaderBufInitialSize) 292 additional_capacity = kHeaderBufInitialSize; 293 read_buf_->SetCapacity(read_buf_->capacity() + additional_capacity); 294 } 295 memcpy(read_buf_->data(), data, length); 296 read_buf_->set_offset(read_buf_->offset() + length); 297 int rv = ParseResponseHeaders(); 298 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 299 DoCallback(rv); 300 } 301 return OK; 302 } 303 304 if (callback_.is_null()) { 305 BufferResponseBody(data, length); 306 return OK; 307 } 308 309 if (length <= user_buffer_len_) { 310 memcpy(user_buffer_->data(), data, length); 311 } else { 312 memcpy(user_buffer_->data(), data, user_buffer_len_); 313 int delta = length - user_buffer_len_; 314 BufferResponseBody(data + user_buffer_len_, delta); 315 length = user_buffer_len_; 316 } 317 318 user_buffer_ = NULL; 319 user_buffer_len_ = 0; 320 DoCallback(length); 321 return OK; 322 } 323 324 void QuicHttpStream::OnClose(QuicErrorCode error) { 325 if (error != QUIC_NO_ERROR) { 326 response_status_ = was_handshake_confirmed_ ? 327 ERR_QUIC_PROTOCOL_ERROR : ERR_QUIC_HANDSHAKE_FAILED; 328 } else if (!response_headers_received_) { 329 response_status_ = ERR_ABORTED; 330 } 331 332 closed_stream_received_bytes_ = stream_->stream_bytes_read(); 333 stream_ = NULL; 334 if (!callback_.is_null()) 335 DoCallback(response_status_); 336 } 337 338 void QuicHttpStream::OnError(int error) { 339 stream_ = NULL; 340 response_status_ = was_handshake_confirmed_ ? 341 error : ERR_QUIC_HANDSHAKE_FAILED; 342 if (!callback_.is_null()) 343 DoCallback(response_status_); 344 } 345 346 bool QuicHttpStream::HasSendHeadersComplete() { 347 return next_state_ > STATE_SEND_HEADERS_COMPLETE; 348 } 349 350 void QuicHttpStream::OnCryptoHandshakeConfirmed() { 351 was_handshake_confirmed_ = true; 352 } 353 354 void QuicHttpStream::OnSessionClosed(int error) { 355 session_error_ = error; 356 session_.reset(); 357 } 358 359 void QuicHttpStream::OnIOComplete(int rv) { 360 rv = DoLoop(rv); 361 362 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 363 DoCallback(rv); 364 } 365 } 366 367 void QuicHttpStream::DoCallback(int rv) { 368 CHECK_NE(rv, ERR_IO_PENDING); 369 CHECK(!callback_.is_null()); 370 371 // The client callback can do anything, including destroying this class, 372 // so any pending callback must be issued after everything else is done. 373 base::ResetAndReturn(&callback_).Run(rv); 374 } 375 376 int QuicHttpStream::DoLoop(int rv) { 377 do { 378 State state = next_state_; 379 next_state_ = STATE_NONE; 380 switch (state) { 381 case STATE_SEND_HEADERS: 382 CHECK_EQ(OK, rv); 383 rv = DoSendHeaders(); 384 break; 385 case STATE_SEND_HEADERS_COMPLETE: 386 rv = DoSendHeadersComplete(rv); 387 break; 388 case STATE_READ_REQUEST_BODY: 389 CHECK_EQ(OK, rv); 390 rv = DoReadRequestBody(); 391 break; 392 case STATE_READ_REQUEST_BODY_COMPLETE: 393 rv = DoReadRequestBodyComplete(rv); 394 break; 395 case STATE_SEND_BODY: 396 CHECK_EQ(OK, rv); 397 rv = DoSendBody(); 398 break; 399 case STATE_SEND_BODY_COMPLETE: 400 rv = DoSendBodyComplete(rv); 401 break; 402 case STATE_OPEN: 403 CHECK_EQ(OK, rv); 404 break; 405 default: 406 NOTREACHED() << "next_state_: " << next_state_; 407 break; 408 } 409 } while (next_state_ != STATE_NONE && next_state_ != STATE_OPEN && 410 rv != ERR_IO_PENDING); 411 412 return rv; 413 } 414 415 int QuicHttpStream::DoSendHeaders() { 416 if (!stream_) 417 return ERR_UNEXPECTED; 418 419 // Log the actual request with the URL Request's net log. 420 stream_net_log_.AddEvent( 421 NetLog::TYPE_HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS, 422 base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_, 423 priority_)); 424 // Also log to the QuicSession's net log. 425 stream_->net_log().AddEvent( 426 NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS, 427 base::Bind(&QuicRequestNetLogCallback, stream_->id(), &request_headers_, 428 priority_)); 429 430 bool has_upload_data = request_body_stream_ != NULL; 431 432 next_state_ = STATE_SEND_HEADERS_COMPLETE; 433 int rv = stream_->WriteHeaders(request_headers_, !has_upload_data, NULL); 434 request_headers_.clear(); 435 return rv; 436 } 437 438 int QuicHttpStream::DoSendHeadersComplete(int rv) { 439 if (rv < 0) 440 return rv; 441 442 next_state_ = request_body_stream_ ? 443 STATE_READ_REQUEST_BODY : STATE_OPEN; 444 445 return OK; 446 } 447 448 int QuicHttpStream::DoReadRequestBody() { 449 next_state_ = STATE_READ_REQUEST_BODY_COMPLETE; 450 return request_body_stream_->Read( 451 raw_request_body_buf_.get(), 452 raw_request_body_buf_->size(), 453 base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 454 } 455 456 int QuicHttpStream::DoReadRequestBodyComplete(int rv) { 457 // |rv| is the result of read from the request body from the last call to 458 // DoSendBody(). 459 if (rv < 0) 460 return rv; 461 462 request_body_buf_ = new DrainableIOBuffer(raw_request_body_buf_.get(), rv); 463 if (rv == 0) { // Reached the end. 464 DCHECK(request_body_stream_->IsEOF()); 465 } 466 467 next_state_ = STATE_SEND_BODY; 468 return OK; 469 } 470 471 int QuicHttpStream::DoSendBody() { 472 if (!stream_) 473 return ERR_UNEXPECTED; 474 475 CHECK(request_body_stream_); 476 CHECK(request_body_buf_.get()); 477 const bool eof = request_body_stream_->IsEOF(); 478 int len = request_body_buf_->BytesRemaining(); 479 if (len > 0 || eof) { 480 next_state_ = STATE_SEND_BODY_COMPLETE; 481 base::StringPiece data(request_body_buf_->data(), len); 482 return stream_->WriteStreamData( 483 data, eof, 484 base::Bind(&QuicHttpStream::OnIOComplete, weak_factory_.GetWeakPtr())); 485 } 486 487 next_state_ = STATE_OPEN; 488 return OK; 489 } 490 491 int QuicHttpStream::DoSendBodyComplete(int rv) { 492 if (rv < 0) 493 return rv; 494 495 request_body_buf_->DidConsume(request_body_buf_->BytesRemaining()); 496 497 if (!request_body_stream_->IsEOF()) { 498 next_state_ = STATE_READ_REQUEST_BODY; 499 return OK; 500 } 501 502 next_state_ = STATE_OPEN; 503 return OK; 504 } 505 506 int QuicHttpStream::ParseResponseHeaders() { 507 size_t read_buf_len = static_cast<size_t>(read_buf_->offset()); 508 SpdyFramer framer(SPDY3); 509 SpdyHeaderBlock headers; 510 char* data = read_buf_->StartOfBuffer(); 511 size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(), 512 &headers); 513 514 if (len == 0) { 515 return ERR_IO_PENDING; 516 } 517 518 // Save the remaining received data. 519 size_t delta = read_buf_len - len; 520 if (delta > 0) { 521 BufferResponseBody(data + len, delta); 522 } 523 524 // The URLRequest logs these headers, so only log to the QuicSession's 525 // net log. 526 stream_->net_log().AddEvent( 527 NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS, 528 base::Bind(&SpdyHeaderBlockNetLogCallback, &headers)); 529 530 if (!SpdyHeadersToHttpResponse(headers, SPDY3, response_info_)) { 531 DLOG(WARNING) << "Invalid headers"; 532 return ERR_QUIC_PROTOCOL_ERROR; 533 } 534 // Put the peer's IP address and port into the response. 535 IPEndPoint address = stream_->GetPeerAddress(); 536 response_info_->socket_address = HostPortPair::FromIPEndPoint(address); 537 response_info_->connection_info = 538 HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3; 539 response_info_->vary_data 540 .Init(*request_info_, *response_info_->headers.get()); 541 response_info_->was_npn_negotiated = true; 542 response_info_->npn_negotiated_protocol = "quic/1+spdy/3"; 543 response_info_->response_time = base::Time::Now(); 544 response_info_->request_time = request_time_; 545 response_headers_received_ = true; 546 547 return OK; 548 } 549 550 void QuicHttpStream::BufferResponseBody(const char* data, int length) { 551 if (length == 0) 552 return; 553 IOBufferWithSize* io_buffer = new IOBufferWithSize(length); 554 memcpy(io_buffer->data(), data, length); 555 response_body_.push_back(make_scoped_refptr(io_buffer)); 556 } 557 558 } // namespace net 559