36eac6aee8ae1fffbf1c5d122c10ceae7c5ea891
[platform/framework/web/crosswalk.git] / src / net / quic / quic_http_stream.cc
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                                    SPDY3, /*direct=*/true, &request_headers_);
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