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