1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_spdy_client_stream.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_framer.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_client_session.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/spdy_utils.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using base::StringPiece;
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::string;
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const size_t kHeaderBufInitialSize = 4096;
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                           QuicClientSession* session)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : QuicDataStream(id, session),
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      read_buf_(new GrowableIOBuffer()),
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      response_headers_received_(false),
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      header_bytes_read_(0),
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      header_bytes_written_(0) {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicSpdyClientStream::~QuicSpdyClientStream() {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!write_side_closed()) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Got a response before the request was complete.  "
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             << "Aborting request.";
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CloseWriteSide();
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  QuicDataStream::OnStreamFrame(frame);
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                   size_t frame_len) {
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  header_bytes_read_ = frame_len;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicDataStream::OnStreamHeadersComplete(fin, frame_len);
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)uint32 QuicSpdyClientStream::ProcessData(const char* data,
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         uint32 data_len) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int total_bytes_processed = 0;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Are we still reading the response headers.
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!response_headers_received_) {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Grow the read buffer if necessary.
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (read_buf_->RemainingCapacity() < (int)data_len) {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      read_buf_->SetCapacity(read_buf_->capacity() + kHeaderBufInitialSize);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    memcpy(read_buf_->data(), data, data_len);
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    read_buf_->set_offset(read_buf_->offset() + data_len);
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ParseResponseHeaders();
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    data_.append(data + total_bytes_processed,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 data_len - total_bytes_processed);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return data_len;
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void QuicSpdyClientStream::OnFinRead() {
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ReliableQuicStream::OnFinRead();
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!response_headers_received_) {
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if ((headers().content_length_status() ==
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             data_.size() != headers().content_length()) {
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers,
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          StringPiece body,
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          bool fin) {
80b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  SpdyHeaderBlock header_block =
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      SpdyUtils::RequestHeadersToSpdyHeaders(headers);
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool send_fin_with_headers = fin && body.empty();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  size_t bytes_sent = body.size();
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  header_bytes_written_ = WriteHeaders(
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      header_block, send_fin_with_headers, NULL);
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bytes_sent += header_bytes_written_;
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!body.empty()) {
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    WriteOrBufferData(body, fin, NULL);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return bytes_sent;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int QuicSpdyClientStream::ParseResponseHeaders() {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SpdyFramer framer(SPDY3);
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyHeaderBlock headers;
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char* data = read_buf_->StartOfBuffer();
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t len = framer.ParseHeaderBlockInBuffer(data, read_buf_->offset(),
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                               &headers);
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (len == 0) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return -1;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) {
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return -1;
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  response_headers_received_ = true;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t delta = read_buf_len - len;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (delta > 0) {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    data_.append(data + len, delta);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return len;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Sends body data to the server and returns the number of bytes sent.
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WriteOrBufferData(data, fin, NULL);
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
128