// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/tools/quic/quic_spdy_client_stream.h"

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/quic/spdy_utils.h"
#include "net/spdy/spdy_protocol.h"
#include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/spdy_balsa_utils.h"

using base::StringPiece;
using std::string;
using base::StringToInt;

namespace net {
namespace tools {

QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
                                           QuicClientSession* session)
    : QuicDataStream(id, session),
      content_length_(-1),
      response_code_(0),
      header_bytes_read_(0),
      header_bytes_written_(0) {
}

QuicSpdyClientStream::~QuicSpdyClientStream() {
}

void QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
  if (!write_side_closed()) {
    DVLOG(1) << "Got a response before the request was complete.  "
             << "Aborting request.";
    CloseWriteSide();
  }
  QuicDataStream::OnStreamFrame(frame);
}

void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin,
                                                   size_t frame_len) {
  header_bytes_read_ = frame_len;
  QuicDataStream::OnStreamHeadersComplete(fin, frame_len);
}

uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 data_len) {
  if (!headers_decompressed()) {
    // Let the headers data accumulate in the underlying QuicDataStream.
    return 0;
  }
  if (response_headers_.empty()) {
    if (!ParseResponseHeaders(data, data_len)) {
      // Headers were invalid.
      Reset(QUIC_BAD_APPLICATION_PAYLOAD);
      return 0;
    }
  } else {
    data_.append(data, data_len);
  }
  DCHECK(!response_headers_.empty());
  if (content_length_ >= 0 &&
      static_cast<int>(data_.size()) > content_length_) {
    Reset(QUIC_BAD_APPLICATION_PAYLOAD);
    return 0;
  }
  DVLOG(1) << "Client processed " << data_len << " bytes for stream " << id();
  return data_len;
}

bool QuicSpdyClientStream::ParseResponseHeaders(const char* data,
                                                uint32 data_len) {
  DCHECK(headers_decompressed());
  SpdyFramer framer(SPDY3);
  size_t len = framer.ParseHeaderBlockInBuffer(data,
                                               data_len,
                                               &response_headers_);
  DCHECK_LE(len, data_len);
  if (len == 0 || response_headers_.empty()) {
    return false;  // Headers were invalid.
  }

  if (data_len > len) {
    data_.append(data + len, data_len - len);
  }
  if (ContainsKey(response_headers_, "content-length") &&
      !StringToInt(response_headers_["content-length"], &content_length_)) {
    return false;  // Invalid content-length.
  }
  string status = response_headers_[":status"];
  size_t end = status.find(" ");
  if (end != string::npos) {
    status.erase(end);
  }
  if (!StringToInt(status, &response_code_)) {
    return false;  // Invalid response code.
  }
  return true;
}

size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers,
                                         StringPiece body,
                                         bool fin) {
  bool send_fin_with_headers = fin && body.empty();
  size_t bytes_sent = body.size();
  header_bytes_written_ =
      WriteHeaders(headers, send_fin_with_headers, nullptr);
  bytes_sent += header_bytes_written_;

  if (!body.empty()) {
    WriteOrBufferData(body, fin, nullptr);
  }

  return bytes_sent;
}

void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
  SendBody(data, fin, nullptr);
}

void QuicSpdyClientStream::SendBody(
    const string& data, bool fin,
    QuicAckNotifier::DelegateInterface* delegate) {
  WriteOrBufferData(data, fin, delegate);
}

}  // namespace tools
}  // namespace net
