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

#include "net/http/http_basic_stream.h"

#include <set>
#include <utility>

#include "base/functional/bind.h"
#include "net/http/http_network_session.h"
#include "net/http/http_raw_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_body_drainer.h"
#include "net/http/http_stream_parser.h"
#include "net/socket/client_socket_handle.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_info.h"

namespace net {

HttpBasicStream::HttpBasicStream(std::unique_ptr<ClientSocketHandle> connection,
                                 bool using_proxy)
    : state_(std::move(connection), using_proxy) {}

HttpBasicStream::~HttpBasicStream() = default;

void HttpBasicStream::RegisterRequest(const HttpRequestInfo* request_info) {
  DCHECK(request_info);
  DCHECK(request_info->traffic_annotation.is_valid());
  request_info_ = request_info;
}

int HttpBasicStream::InitializeStream(bool can_send_early,
                                      RequestPriority priority,
                                      const NetLogWithSource& net_log,
                                      CompletionOnceCallback callback) {
  DCHECK(request_info_);
  state_.Initialize(request_info_, priority, net_log);
  int ret = OK;
  if (!can_send_early) {
    // parser() cannot outlive |this|, so we can use base::Unretained().
    ret = parser()->ConfirmHandshake(
        base::BindOnce(&HttpBasicStream::OnHandshakeConfirmed,
                       base::Unretained(this), std::move(callback)));
  }
  // RequestInfo is no longer needed after this point.
  request_info_ = nullptr;
  return ret;
}

int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
                                 HttpResponseInfo* response,
                                 CompletionOnceCallback callback) {
  DCHECK(parser());
  if (request_headers_callback_) {
    HttpRawRequestHeaders raw_headers;
    raw_headers.set_request_line(state_.GenerateRequestLine());
    for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();)
      raw_headers.Add(it.name(), it.value());
    request_headers_callback_.Run(std::move(raw_headers));
  }
  return parser()->SendRequest(
      state_.GenerateRequestLine(), headers,
      NetworkTrafficAnnotationTag(state_.traffic_annotation()), response,
      std::move(callback));
}

int HttpBasicStream::ReadResponseHeaders(CompletionOnceCallback callback) {
  return parser()->ReadResponseHeaders(std::move(callback));
}

int HttpBasicStream::ReadResponseBody(IOBuffer* buf,
                                      int buf_len,
                                      CompletionOnceCallback callback) {
  return parser()->ReadResponseBody(buf, buf_len, std::move(callback));
}

void HttpBasicStream::Close(bool not_reusable) {
  // parser() is null if |this| is created by an orphaned HttpStreamFactory::Job
  // in which case InitializeStream() will not have been called. This also
  // protects against null dereference in the case where
  // state_.ReleaseConnection() has been called.
  //
  // TODO(mmenke):  Can these cases be handled a bit more cleanly?
  // WebSocketHandshakeStream will need to be updated as well.
  if (!parser())
    return;
  StreamSocket* socket = state_.connection()->socket();
  if (not_reusable && socket)
    socket->Disconnect();
  parser()->OnConnectionClose();
  state_.connection()->Reset();
}

std::unique_ptr<HttpStream> HttpBasicStream::RenewStreamForAuth() {
  DCHECK(IsResponseBodyComplete());
  DCHECK(!parser()->IsMoreDataBuffered());
  // The HttpStreamParser object still has a pointer to the connection. Just to
  // be extra-sure it doesn't touch the connection again, delete it here rather
  // than leaving it until the destructor is called.
  state_.DeleteParser();
  return std::make_unique<HttpBasicStream>(state_.ReleaseConnection(),
                                           state_.using_proxy());
}

bool HttpBasicStream::IsResponseBodyComplete() const {
  return parser()->IsResponseBodyComplete();
}

bool HttpBasicStream::IsConnectionReused() const {
  return state_.IsConnectionReused();
}

void HttpBasicStream::SetConnectionReused() {
  state_.connection()->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
}

bool HttpBasicStream::CanReuseConnection() const {
  return parser() && state_.connection()->socket() &&
         parser()->CanReuseConnection();
}

int64_t HttpBasicStream::GetTotalReceivedBytes() const {
  if (parser())
    return parser()->received_bytes();
  return 0;
}

int64_t HttpBasicStream::GetTotalSentBytes() const {
  if (parser())
    return parser()->sent_bytes();
  return 0;
}

bool HttpBasicStream::GetLoadTimingInfo(
    LoadTimingInfo* load_timing_info) const {
  if (!state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
                                              load_timing_info) ||
      !parser()) {
    return false;
  }

  // If the request waited for handshake confirmation, shift |ssl_end| to
  // include that time.
  if (!load_timing_info->connect_timing.ssl_end.is_null() &&
      !confirm_handshake_end_.is_null()) {
    load_timing_info->connect_timing.ssl_end = confirm_handshake_end_;
    load_timing_info->connect_timing.connect_end = confirm_handshake_end_;
  }

  load_timing_info->receive_headers_start =
      parser()->first_response_start_time();
  load_timing_info->receive_non_informational_headers_start =
      parser()->non_informational_response_start_time();
  load_timing_info->first_early_hints_time = parser()->first_early_hints_time();
  return true;
}

bool HttpBasicStream::GetAlternativeService(
    AlternativeService* alternative_service) const {
  return false;
}

void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) {
  if (!state_.connection()->socket()) {
    ssl_info->Reset();
    return;
  }
  parser()->GetSSLInfo(ssl_info);
}

void HttpBasicStream::GetSSLCertRequestInfo(
    SSLCertRequestInfo* cert_request_info) {
  if (!state_.connection()->socket()) {
    cert_request_info->Reset();
    return;
  }
  parser()->GetSSLCertRequestInfo(cert_request_info);
}

int HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) {
  if (!state_.connection() || !state_.connection()->socket())
    return ERR_SOCKET_NOT_CONNECTED;

  return state_.connection()->socket()->GetPeerAddress(endpoint);
}

void HttpBasicStream::Drain(HttpNetworkSession* session) {
  session->StartResponseDrainer(
      std::make_unique<HttpResponseBodyDrainer>(this));
  // |drainer| will delete itself.
}

void HttpBasicStream::PopulateNetErrorDetails(NetErrorDetails* details) {
  // TODO(mmenke):  Consumers don't actually care about HTTP version, but seems
  // like the right version should be reported, if headers were received.
  details->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
  return;
}

void HttpBasicStream::SetPriority(RequestPriority priority) {
  // TODO(akalin): Plumb this through to |connection_|.
}

void HttpBasicStream::SetRequestHeadersCallback(
    RequestHeadersCallback callback) {
  request_headers_callback_ = std::move(callback);
}

const std::set<std::string>& HttpBasicStream::GetDnsAliases() const {
  return state_.GetDnsAliases();
}

base::StringPiece HttpBasicStream::GetAcceptChViaAlps() const {
  return {};
}

void HttpBasicStream::OnHandshakeConfirmed(CompletionOnceCallback callback,
                                           int rv) {
  if (rv == OK) {
    // Note this time is only recorded if ConfirmHandshake() completed
    // asynchronously. If it was synchronous, GetLoadTimingInfo() assumes the
    // handshake was already confirmed or there was nothing to confirm.
    confirm_handshake_end_ = base::TimeTicks::Now();
  }
  std::move(callback).Run(rv);
}

}  // namespace net
