// 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"

#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/socket/transport_connect_job.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_utils.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";

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_data_stream_id1_(
            quic::QuicUtils::GetHeadersStreamId(quic_version_) +
            quic::QuicUtils::StreamIdDelta(quic_version_)),
        client_headers_include_h2_stream_dependency_(std::get<1>(GetParam())),
        client_maker_(
            quic_version_,
            quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
            &clock_,
            kProxyHost,
            quic::Perspective::IS_CLIENT,
            client_headers_include_h2_stream_dependency_),
        server_maker_(
            quic_version_,
            quic::QuicUtils::CreateRandomConnectionId(&random_generator_),
            &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_, &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_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,
      RequestPriority priority) {
    spdy::SpdyHeaderBlock block;
    PopulateConnectRequestIR(&block);
    return client_maker_.MakeRequestHeadersPacket(
        packet_number, client_data_stream_id1_, kIncludeVersion, !kFin,
        ConvertRequestPriorityToQuicPriority(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, client_data_stream_id1_, !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, client_data_stream_id1_, 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 quic::QuicStreamId client_data_stream_id1_;
  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, HIGHEST));
  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());

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

  client_socket_wrapper_.reset(new HttpProxyClientSocketWrapper(
      /*group_name=*/std::string(), /*requiest_priority=*/DEFAULT_PRIORITY,
      /*socket_tag=*/SocketTag(),
      /*respect_limits=*/ClientSocketPool::RespectLimits::ENABLED,
      /*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, /*proxy_delegate=*/nullptr,
      TRAFFIC_ANNOTATION_FOR_TESTS, net_log_));

  TestCompletionCallback callback;
  client_socket_wrapper_->Connect(callback.callback());
  EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_.request_priority(1));

  client_socket_wrapper_->SetPriority(HIGHEST);

  // Expect connect request packet with HIGHEST priority, not DEFAULT_PRIORITY.
  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, DEFAULT_PRIORITY));
  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());

  scoped_refptr<SSLSocketParams> ssl_params =
      new SSLSocketParams(transport_params, nullptr, nullptr, proxy_host_port_,
                          SSLConfig(), privacy_mode_);
  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::ENABLED,
      /*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, /*proxy_delegate=*/nullptr,
      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
