// Copyright (c) 2016 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/third_party/quiche/src/quic/core/http/quic_client_promised_info.h"

#include <string>
#include <utility>

#include "net/third_party/quiche/src/quic/core/http/spdy_server_push_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"

using spdy::SpdyHeaderBlock;

namespace quic {

QuicClientPromisedInfo::QuicClientPromisedInfo(
    QuicSpdyClientSessionBase* session,
    QuicStreamId id,
    std::string url)
    : session_(session),
      id_(id),
      url_(std::move(url)),
      client_request_delegate_(nullptr) {}

QuicClientPromisedInfo::~QuicClientPromisedInfo() {}

void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() {
  QUIC_DVLOG(1) << "self GC alarm for stream " << promised_->id_;
  promised_->session()->OnPushStreamTimedOut(promised_->id_);
  promised_->Reset(QUIC_PUSH_STREAM_TIMED_OUT);
}

void QuicClientPromisedInfo::Init() {
  cleanup_alarm_.reset(session_->connection()->alarm_factory()->CreateAlarm(
      new QuicClientPromisedInfo::CleanupAlarm(this)));
  cleanup_alarm_->Set(
      session_->connection()->helper()->GetClock()->ApproximateNow() +
      QuicTime::Delta::FromSeconds(kPushPromiseTimeoutSecs));
}

bool QuicClientPromisedInfo::OnPromiseHeaders(const SpdyHeaderBlock& headers) {
  // RFC7540, Section 8.2, requests MUST be safe [RFC7231], Section
  // 4.2.1.  GET and HEAD are the methods that are safe and required.
  SpdyHeaderBlock::const_iterator it = headers.find(spdy::kHttp2MethodHeader);
  if (it == headers.end()) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has no method";
    Reset(QUIC_INVALID_PROMISE_METHOD);
    return false;
  }
  if (!(it->second == "GET" || it->second == "HEAD")) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid method "
                  << it->second;
    Reset(QUIC_INVALID_PROMISE_METHOD);
    return false;
  }
  if (!SpdyServerPushUtils::PromisedUrlIsValid(headers)) {
    QUIC_DVLOG(1) << "Promise for stream " << id_ << " has invalid URL "
                  << url_;
    Reset(QUIC_INVALID_PROMISE_URL);
    return false;
  }
  if (!session_->IsAuthorized(
          SpdyServerPushUtils::GetPromisedHostNameFromHeaders(headers))) {
    Reset(QUIC_UNAUTHORIZED_PROMISE_URL);
    return false;
  }
  request_headers_ = headers.Clone();
  return true;
}

void QuicClientPromisedInfo::OnResponseHeaders(const SpdyHeaderBlock& headers) {
  response_headers_ = QuicMakeUnique<SpdyHeaderBlock>(headers.Clone());
  if (client_request_delegate_) {
    // We already have a client request waiting.
    FinalValidation();
  }
}

void QuicClientPromisedInfo::Reset(QuicRstStreamErrorCode error_code) {
  QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
  session_->ResetPromised(id_, error_code);
  session_->DeletePromised(this);
  if (delegate) {
    delegate->OnRendezvousResult(nullptr);
  }
}

QuicAsyncStatus QuicClientPromisedInfo::FinalValidation() {
  if (!client_request_delegate_->CheckVary(
          client_request_headers_, request_headers_, *response_headers_)) {
    Reset(QUIC_PROMISE_VARY_MISMATCH);
    return QUIC_FAILURE;
  }
  QuicSpdyStream* stream = session_->GetPromisedStream(id_);
  if (!stream) {
    // This shouldn't be possible, as |ClientRequest| guards against
    // closed stream for the synchronous case.  And in the
    // asynchronous case, a RST can only be caught by |OnAlarm()|.
    QUIC_BUG << "missing promised stream" << id_;
  }
  QuicClientPushPromiseIndex::Delegate* delegate = client_request_delegate_;
  session_->DeletePromised(this);
  // Stream can start draining now
  if (delegate) {
    delegate->OnRendezvousResult(stream);
  }
  return QUIC_SUCCESS;
}

QuicAsyncStatus QuicClientPromisedInfo::HandleClientRequest(
    const SpdyHeaderBlock& request_headers,
    QuicClientPushPromiseIndex::Delegate* delegate) {
  if (session_->IsClosedStream(id_)) {
    // There was a RST on the response stream.
    session_->DeletePromised(this);
    return QUIC_FAILURE;
  }

  if (is_validating()) {
    // The push promise has already been matched to another request though
    // pending for validation. Returns QUIC_FAILURE to the caller as it couldn't
    // match a new request any more. This will not affect the validation of the
    // other request.
    return QUIC_FAILURE;
  }

  client_request_delegate_ = delegate;
  client_request_headers_ = request_headers.Clone();
  if (response_headers_ == nullptr) {
    return QUIC_PENDING;
  }
  return FinalValidation();
}

void QuicClientPromisedInfo::Cancel() {
  // Don't fire OnRendezvousResult() for client initiated cancel.
  client_request_delegate_ = nullptr;
  Reset(QUIC_STREAM_CANCELLED);
}

}  // namespace quic
