// Copyright 2017 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/http/http_proxy_client_socket_wrapper.h"

// This file has been discontinued by m74 Chromium net.
#if !defined(QUIC_DISABLED_FOR_STARBOARD) && !defined(COBALT_QUIC46)

#include <cstdio>
#include <memory>

#include "build/build_config.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/do_nothing_ct_verifier.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_cache.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/transport_security_state.h"
#include "net/quic/mock_crypto_client_stream_factory.h"
#include "net/quic/mock_quic_data.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_test_packet_maker.h"
#include "net/socket/socket_tag.h"
#include "net/socket/socket_test_util.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/default_channel_id_store.h"
#include "net/test/cert_test_util.h"
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_scoped_task_environment.h"
#include "net/third_party/quic/core/quic_versions.h"
#include "net/third_party/quic/test_tools/mock_clock.h"
#include "net/third_party/quic/test_tools/mock_random.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace net {

namespace {

const char kProxyHost[] = "proxy.example.org";
const int kProxyPort = 6121;
const char kOriginHost[] = "www.google.org";
const int kOriginPort = 443;
const char kUserAgent[] = "Mozilla/1.0";

const quic::QuicStreamId kClientDataStreamId1 = quic::kHeadersStreamId + 2;

class MockSSLConfigService : public SSLConfigService {
 public:
  MockSSLConfigService() = default;
  ~MockSSLConfigService() override = default;

  void GetSSLConfig(SSLConfig* config) override { *config = config_; }

  bool CanShareConnectionWithClientCerts(
      const std::string& hostname) const override {
    return false;
  }

 private:
  SSLConfig config_;
};

};  // namespace

namespace test {

class HttpProxyClientSocketWrapperTest
    : public ::testing::TestWithParam<
          std::tuple<quic::QuicTransportVersion, bool>>,
      public WithScopedTaskEnvironment {
 protected:
  static const bool kFin = true;
  static const bool kIncludeVersion = true;
  static const bool kSendFeedback = true;

  HttpProxyClientSocketWrapperTest()
      : proxy_host_port_(kProxyHost, kProxyPort),
        endpoint_host_port_(kOriginHost, kOriginPort),
        ssl_config_service_(new MockSSLConfigService()),
        cert_verifier_(new MockCertVerifier()),
        channel_id_service_(
            new ChannelIDService(new DefaultChannelIDStore(nullptr))),
        cert_transparency_verifier_(new DoNothingCTVerifier()),
        random_generator_(0),
        quic_version_(std::get<0>(GetParam())),
        client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
        client_maker_(quic_version_,
                      0,
                      &clock_,
                      kProxyHost,
                      quic::Perspective::IS_CLIENT,
                      client_headers_include_h2_stream_dependency_),
        server_maker_(quic_version_,
                      0,
                      &clock_,
                      kProxyHost,
                      quic::Perspective::IS_SERVER,
                      false),
        header_stream_offset_(0),
        response_offset_(0),
        store_server_configs_in_properties_(false),
        idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds),
        reduced_ping_timeout_seconds_(quic::kPingTimeoutSecs),
        allow_server_migration_(false),
        race_cert_verification_(false),
        estimate_initial_rtt_(false),
        quic_stream_factory_(nullptr),
        privacy_mode_(PRIVACY_MODE_DISABLED),
        http_auth_handler_factory_(
            HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
        client_socket_wrapper_(nullptr) {
    clock_.AdvanceTime(
        quic::QuicTime::Delta::FromSeconds(1));  // why is this here???
  }

  void Initialize() {
    DCHECK(!quic_stream_factory_);
    quic_stream_factory_.reset(new QuicStreamFactory(
        net_log_.net_log(), &host_resolver_, ssl_config_service_.get(),
        &socket_factory_, &http_server_properties_, cert_verifier_.get(),
        &ct_policy_enforcer_, channel_id_service_.get(),
        &transport_security_state_, cert_transparency_verifier_.get(),
        /*SocketPerformanceWatcherFactory=*/nullptr,
        &crypto_client_stream_factory_, &random_generator_, &clock_,
        quic::kDefaultMaxPacketSize, /*user_agent_id=*/kUserAgent,
        store_server_configs_in_properties_,
        /*close_sessions_on_ip_change=*/true,
        /*goaway_sessions_on_ip_change=*/false,
        /*mark_quic_broken_when_network_blackholes=*/false,
        idle_connection_timeout_seconds_, reduced_ping_timeout_seconds_,
        /*max_time_before_crypto_handshake_seconds=*/
        quic::kMaxTimeForCryptoHandshakeSecs,
        /*max_idle_time_before_crypto_handshake_seconds=*/
        quic::kInitialIdleTimeoutSecs,
        /*migrate_sessions_on_network_change_v2=*/false,
        /*migrate_sessions_early_v2=*/false,
        /*retry_on_alternate_network_before_handshake=*/false,
        /*race_stale_dns_on_connection=*/false,
        /*go_away_on_path_degrading=*/false,
        base::TimeDelta::FromSeconds(kMaxTimeOnNonDefaultNetworkSecs),
        kMaxMigrationsToNonDefaultNetworkOnWriteError,
        kMaxMigrationsToNonDefaultNetworkOnPathDegrading,
        allow_server_migration_, race_cert_verification_, estimate_initial_rtt_,
        client_headers_include_h2_stream_dependency_, connection_options_,
        client_connection_options_, /*enable_channel_id=*/false,
        /*enable_socket_recv_optimization=*/false));
  }

  void PopulateConnectRequestIR(spdy::SpdyHeaderBlock* block) {
    (*block)[":method"] = "CONNECT";
    (*block)[":authority"] = endpoint_host_port_.ToString();
    (*block)["user-agent"] = kUserAgent;
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructSettingsPacket(
      quic::QuicPacketNumber packet_number) {
    return client_maker_.MakeInitialSettingsPacket(packet_number,
                                                   &header_stream_offset_);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructConnectRequestPacket(
      quic::QuicPacketNumber packet_number) {
    spdy::SpdyHeaderBlock block;
    PopulateConnectRequestIR(&block);
    return client_maker_.MakeRequestHeadersPacket(
        packet_number, kClientDataStreamId1, kIncludeVersion, !kFin,
        ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
        std::move(block), 0, nullptr, &header_stream_offset_);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructServerConnectReplyPacket(
      quic::QuicPacketNumber packet_number,
      bool fin) {
    spdy::SpdyHeaderBlock block;
    block[":status"] = "200";

    return server_maker_.MakeResponseHeadersPacket(
        packet_number, kClientDataStreamId1, !kIncludeVersion, fin,
        std::move(block), nullptr, &response_offset_);
  }

  std::unique_ptr<quic::QuicReceivedPacket> ConstructAckAndRstPacket(
      quic::QuicPacketNumber packet_number,
      quic::QuicRstStreamErrorCode error_code,
      quic::QuicPacketNumber largest_received,
      quic::QuicPacketNumber smallest_received,
      quic::QuicPacketNumber least_unacked) {
    return client_maker_.MakeAckAndRstPacket(
        packet_number, !kIncludeVersion, kClientDataStreamId1, error_code,
        largest_received, smallest_received, least_unacked, kSendFeedback);
  }

  static ProofVerifyDetailsChromium DefaultProofVerifyDetails() {
    // Load a certificate that is valid for *.example.org
    scoped_refptr<X509Certificate> test_cert(
        ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
    EXPECT_TRUE(test_cert.get());
    ProofVerifyDetailsChromium verify_details;
    verify_details.cert_verify_result.verified_cert = test_cert;
    verify_details.cert_verify_result.is_issued_by_known_root = true;
    return verify_details;
  }

  HostPortPair proxy_host_port_;
  HostPortPair endpoint_host_port_;

  quic::MockClock clock_;
  MockQuicData mock_quic_data_;

  // QuicStreamFactory environment
  NetLogWithSource net_log_;
  MockHostResolver host_resolver_;
  std::unique_ptr<SSLConfigService> ssl_config_service_;
  MockTaggingClientSocketFactory socket_factory_;
  HttpServerPropertiesImpl http_server_properties_;
  std::unique_ptr<MockCertVerifier> cert_verifier_;
  DefaultCTPolicyEnforcer ct_policy_enforcer_;
  std::unique_ptr<ChannelIDService> channel_id_service_;
  TransportSecurityState transport_security_state_;
  std::unique_ptr<DoNothingCTVerifier> cert_transparency_verifier_;
  MockCryptoClientStreamFactory crypto_client_stream_factory_;
  quic::test::MockRandom random_generator_;

  const quic::QuicTransportVersion quic_version_;
  const bool client_headers_include_h2_stream_dependency_;
  QuicTestPacketMaker client_maker_;
  QuicTestPacketMaker server_maker_;
  quic::QuicStreamOffset header_stream_offset_;
  quic::QuicStreamOffset response_offset_;

  // Variables to configure QuicStreamFactory.
  bool store_server_configs_in_properties_;
  int idle_connection_timeout_seconds_;
  int reduced_ping_timeout_seconds_;
  bool allow_server_migration_;
  bool race_cert_verification_;
  bool estimate_initial_rtt_;
  quic::QuicTagVector connection_options_;
  quic::QuicTagVector client_connection_options_;

  std::unique_ptr<QuicStreamFactory> quic_stream_factory_;

  // HttpProxyClientSocketWrapper environment
  PrivacyMode privacy_mode_;
  HttpAuthCache http_auth_cache_;
  std::unique_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory_;

  std::unique_ptr<HttpProxyClientSocketWrapper> client_socket_wrapper_;
};

TEST_P(HttpProxyClientSocketWrapperTest, QuicProxy) {
  Initialize();
  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);

  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
  mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
  mock_quic_data_.AddWrite(
      SYNCHRONOUS,
      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
  mock_quic_data_.AddWrite(
      SYNCHRONOUS, client_maker_.MakeAckAndConnectionClosePacket(
                       4, false, quic::QuicTime::Delta::FromMilliseconds(0), 1,
                       1, 1, quic::QUIC_CONNECTION_CANCELLED, "net error"));
  mock_quic_data_.AddSocketDataToFactory(&socket_factory_);

  scoped_refptr<TransportSocketParams> transport_params =
      new TransportSocketParams(
          proxy_host_port_, false, OnHostResolutionCallback(),
          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);

  scoped_refptr<SSLSocketParams> ssl_params =
      new SSLSocketParams(transport_params, nullptr, nullptr, proxy_host_port_,
                          SSLConfig(), privacy_mode_, 0);
  transport_params = nullptr;

  client_socket_wrapper_.reset(new HttpProxyClientSocketWrapper(
      /*group_name=*/std::string(), /*requiest_priority=*/DEFAULT_PRIORITY,
      /*socket_tag=*/SocketTag(),
      /*respect_limits=*/ClientSocketPool::RespectLimits::DISABLED,
      /*connect_timeout_duration=*/base::TimeDelta::FromHours(1),
      /*proxy_negotiation_timeout_duration=*/base::TimeDelta::FromHours(1),
      /*transport_pool=*/nullptr, /*ssl_pool=*/nullptr,
      /*transport_params=*/nullptr, ssl_params, quic_version_, kUserAgent,
      endpoint_host_port_, &http_auth_cache_, http_auth_handler_factory_.get(),
      /*spdy_session_pool=*/nullptr, quic_stream_factory_.get(),
      /*is_trusted_proxy=*/false, /*tunnel=*/true, TRAFFIC_ANNOTATION_FOR_TESTS,
      net_log_));

  TestCompletionCallback callback;
  client_socket_wrapper_->Connect(callback.callback());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  client_socket_wrapper_.reset();
  EXPECT_TRUE(mock_quic_data_.AllReadDataConsumed());
}

// Test that the SocketTag is appropriately applied to the underlying socket
// for QUIC proxies.
#if defined(OS_ANDROID)
TEST_P(HttpProxyClientSocketWrapperTest, QuicProxySocketTag) {
  Initialize();
  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);

  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructSettingsPacket(1));
  mock_quic_data_.AddWrite(SYNCHRONOUS, ConstructConnectRequestPacket(2));
  mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
  mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
  mock_quic_data_.AddWrite(
      SYNCHRONOUS,
      ConstructAckAndRstPacket(3, quic::QUIC_STREAM_CANCELLED, 1, 1, 1));
  mock_quic_data_.AddWrite(
      SYNCHRONOUS, client_maker_.MakeAckAndConnectionClosePacket(
                       4, false, quic::QuicTime::Delta::FromMilliseconds(0), 1,
                       1, 1, quic::QUIC_CONNECTION_CANCELLED, "net error"));
  mock_quic_data_.AddSocketDataToFactory(&socket_factory_);

  scoped_refptr<TransportSocketParams> transport_params =
      new TransportSocketParams(
          proxy_host_port_, false, OnHostResolutionCallback(),
          TransportSocketParams::COMBINE_CONNECT_AND_WRITE_DEFAULT);

  scoped_refptr<SSLSocketParams> ssl_params =
      new SSLSocketParams(transport_params, nullptr, nullptr, proxy_host_port_,
                          SSLConfig(), privacy_mode_, 0);
  transport_params = nullptr;
  SocketTag tag(getuid(), 0x87654321);

  client_socket_wrapper_.reset(new HttpProxyClientSocketWrapper(
      /*group_name=*/std::string(), /*requiest_priority=*/DEFAULT_PRIORITY,
      /*socket_tag=*/tag,
      /*respect_limits=*/ClientSocketPool::RespectLimits::DISABLED,
      /*connect_timeout_duration=*/base::TimeDelta::FromHours(1),
      /*proxy_negotiation_timeout_duration=*/base::TimeDelta::FromHours(1),
      /*transport_pool=*/nullptr, /*ssl_pool=*/nullptr,
      /*transport_params=*/nullptr, ssl_params, quic_version_, kUserAgent,
      endpoint_host_port_, &http_auth_cache_, http_auth_handler_factory_.get(),
      /*spdy_session_pool=*/nullptr, quic_stream_factory_.get(),
      /*is_trusted_proxy=*/false, /*tunnel=*/true, TRAFFIC_ANNOTATION_FOR_TESTS,
      net_log_));

  TestCompletionCallback callback;
  client_socket_wrapper_->Connect(callback.callback());

  EXPECT_THAT(callback.WaitForResult(), IsOk());

  EXPECT_EQ(socket_factory_.GetLastProducedUDPSocket()->tag(), tag);
  EXPECT_TRUE(socket_factory_.GetLastProducedUDPSocket()
                  ->tagged_before_data_transferred());

  client_socket_wrapper_.reset();
  EXPECT_TRUE(mock_quic_data_.AllReadDataConsumed());
}
#endif

INSTANTIATE_TEST_CASE_P(
    VersionIncludeStreamDependencySequence,
    HttpProxyClientSocketWrapperTest,
    ::testing::Combine(
        ::testing::ValuesIn(quic::AllSupportedTransportVersions()),
        ::testing::Bool()));

};  // namespace test
};  // namespace net

#endif  // !defined(QUIC_DISABLED_FOR_STARBOARD) || defined(COBALT_QUIC46)
