From 280dc8eb627245c20ead8d2f1a7a6b6c22880715 Mon Sep 17 00:00:00 2001
From: klzgrad <kizdiv@gmail.com>
Date: Wed, 12 Dec 2018 23:22:18 -0500
Subject: [PATCH] Add QUIC client

---
 src/net/socket/connect_job.cc           |   3 +-
 src/net/tools/naive/naive_connection.cc |  47 +++++++--
 src/net/tools/naive/naive_connection.h  |  38 ++++---
 src/net/tools/naive/naive_proxy.cc      | 105 ++++++-------------
 src/net/tools/naive/naive_proxy.h       |  36 +++----
 src/net/tools/naive/naive_proxy_bin.cc  | 131 +++++++++++++-----------
 6 files changed, 176 insertions(+), 184 deletions(-)

diff --git a/src/net/socket/connect_job.cc b/src/net/socket/connect_job.cc
index c7b03ba53d..0dc241f24b 100644
--- a/src/net/socket/connect_job.cc
+++ b/src/net/socket/connect_job.cc
@@ -168,7 +168,8 @@ std::unique_ptr<ConnectJob> ConnectJob::CreateConnectJob(
         std::move(ssl_params), delegate, nullptr /* net_log */);
   }
 
-  if (proxy_server.is_http() || proxy_server.is_https()) {
+  if (proxy_server.is_http() || proxy_server.is_https() ||
+      proxy_server.is_quic()) {
     return std::make_unique<HttpProxyConnectJob>(
         request_priority, socket_tag, common_connect_job_params,
         std::move(http_proxy_params), delegate, nullptr /* net_log */);
diff --git a/src/net/tools/naive/naive_connection.cc b/src/net/tools/naive/naive_connection.cc
index 27aacf8ea9..31a0040b06 100644
--- a/src/net/tools/naive/naive_connection.cc
+++ b/src/net/tools/naive/naive_connection.cc
@@ -12,20 +12,19 @@
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/rand_util.h"
+#include "base/strings/strcat.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/base/io_buffer.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/privacy_mode.h"
-#include "net/http/http_network_session.h"
-#include "net/proxy_resolution/proxy_config.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_list.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/socket/stream_socket.h"
 #include "net/spdy/spdy_session.h"
+#include "net/tools/naive/http_proxy_socket.h"
+#include "net/tools/naive/socks5_server_socket.h"
 
 namespace net {
 
@@ -38,14 +37,24 @@ constexpr int kMaxPaddingSize = 255;
 
 NaiveConnection::NaiveConnection(
     unsigned int id,
+    Protocol protocol,
     Direction pad_direction,
+    const ProxyInfo& proxy_info,
+    const SSLConfig& server_ssl_config,
+    const SSLConfig& proxy_ssl_config,
+    HttpNetworkSession* session,
+    const NetLogWithSource& net_log,
     std::unique_ptr<StreamSocket> accepted_socket,
-    Delegate* delegate,
     const NetworkTrafficAnnotationTag& traffic_annotation)
     : id_(id),
+      protocol_(protocol),
       pad_direction_(pad_direction),
+      proxy_info_(proxy_info),
+      server_ssl_config_(server_ssl_config),
+      proxy_ssl_config_(proxy_ssl_config),
+      session_(session),
+      net_log_(net_log),
       next_state_(STATE_NONE),
-      delegate_(delegate),
       client_socket_(std::move(accepted_socket)),
       server_socket_handle_(std::make_unique<ClientSocketHandle>()),
       sockets_{client_socket_.get(), nullptr},
@@ -167,11 +176,31 @@ int NaiveConnection::DoConnectClientComplete(int result) {
 }
 
 int NaiveConnection::DoConnectServer() {
-  DCHECK(delegate_);
   next_state_ = STATE_CONNECT_SERVER_COMPLETE;
 
-  return delegate_->OnConnectServer(id_, client_socket_.get(),
-                                    server_socket_handle_.get(), io_callback_);
+  HostPortPair origin;
+  if (protocol_ == kSocks5) {
+    const auto* socket =
+        static_cast<const Socks5ServerSocket*>(client_socket_.get());
+    origin = socket->request_endpoint();
+  } else if (protocol_ == kHttp) {
+    const auto* socket =
+        static_cast<const HttpProxySocket*>(client_socket_.get());
+    origin = socket->request_endpoint();
+  }
+
+  if (origin.IsEmpty()) {
+    LOG(ERROR) << "Connection " << id_ << " to invalid origin";
+    return ERR_ADDRESS_INVALID;
+  }
+
+  LOG(INFO) << "Connection " << id_ << " to " << origin.ToString();
+
+  // Ignores socket limit set by socket pool for this type of socket.
+  return InitSocketHandleForRawConnect2(
+      origin, session_, LOAD_IGNORE_LIMITS, MAXIMUM_PRIORITY, proxy_info_,
+      server_ssl_config_, proxy_ssl_config_, PRIVACY_MODE_DISABLED, net_log_,
+      server_socket_handle_.get(), io_callback_);
 }
 
 int NaiveConnection::DoConnectServerComplete(int result) {
diff --git a/src/net/tools/naive/naive_connection.h b/src/net/tools/naive/naive_connection.h
index c87bbbe504..ff1e68ec52 100644
--- a/src/net/tools/naive/naive_connection.h
+++ b/src/net/tools/naive/naive_connection.h
@@ -20,14 +20,23 @@ namespace net {
 
 class ClientSocketHandle;
 class DrainableIOBuffer;
+class HttpNetworkSession;
 class IOBuffer;
+class NetLogWithSource;
+class ProxyInfo;
 class StreamSocket;
 struct NetworkTrafficAnnotationTag;
+struct SSLConfig;
 
 class NaiveConnection {
  public:
   using TimeFunc = base::TimeTicks (*)();
 
+  enum Protocol {
+    kSocks5,
+    kHttp,
+  };
+
   // From this direction.
   enum Direction {
     kClient = 0,
@@ -36,24 +45,15 @@ class NaiveConnection {
     kNone = 2,
   };
 
-  class Delegate {
-   public:
-    Delegate() {}
-    virtual ~Delegate() {}
-
-    virtual int OnConnectServer(unsigned int connection_id,
-                                const StreamSocket* accepted_socket,
-                                ClientSocketHandle* server_socket,
-                                CompletionRepeatingCallback callback) = 0;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(Delegate);
-  };
-
   NaiveConnection(unsigned int id,
+                  Protocol protocol,
                   Direction pad_direction,
+                  const ProxyInfo& proxy_info,
+                  const SSLConfig& server_ssl_config,
+                  const SSLConfig& proxy_ssl_config,
+                  HttpNetworkSession* session,
+                  const NetLogWithSource& net_log,
                   std::unique_ptr<StreamSocket> accepted_socket,
-                  Delegate* delegate,
                   const NetworkTrafficAnnotationTag& traffic_annotation);
   ~NaiveConnection();
 
@@ -97,7 +97,13 @@ class NaiveConnection {
   void OnPushComplete(Direction from, Direction to, int result);
 
   unsigned int id_;
+  Protocol protocol_;
   Direction pad_direction_;
+  const ProxyInfo& proxy_info_;
+  const SSLConfig& server_ssl_config_;
+  const SSLConfig& proxy_ssl_config_;
+  HttpNetworkSession* session_;
+  const NetLogWithSource& net_log_;
 
   CompletionRepeatingCallback io_callback_;
   CompletionOnceCallback connect_callback_;
@@ -105,8 +111,6 @@ class NaiveConnection {
 
   State next_state_;
 
-  Delegate* delegate_;
-
   std::unique_ptr<StreamSocket> client_socket_;
   std::unique_ptr<ClientSocketHandle> server_socket_handle_;
 
diff --git a/src/net/tools/naive/naive_proxy.cc b/src/net/tools/naive/naive_proxy.cc
index 14f489123a..e5671be37c 100644
--- a/src/net/tools/naive/naive_proxy.cc
+++ b/src/net/tools/naive/naive_proxy.cc
@@ -14,31 +14,41 @@
 #include "net/base/net_errors.h"
 #include "net/http/http_network_session.h"
 #include "net/proxy_resolution/proxy_config.h"
-#include "net/proxy_resolution/proxy_info.h"
 #include "net/proxy_resolution/proxy_list.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/socket/server_socket.h"
 #include "net/socket/stream_socket.h"
-#include "net/third_party/quic/core/quic_versions.h"
 #include "net/tools/naive/http_proxy_socket.h"
 #include "net/tools/naive/socks5_server_socket.h"
 
 namespace net {
 
 NaiveProxy::NaiveProxy(std::unique_ptr<ServerSocket> listen_socket,
-                       Protocol protocol,
-                       bool use_proxy,
+                       NaiveConnection::Protocol protocol,
+                       bool use_padding,
                        HttpNetworkSession* session,
                        const NetworkTrafficAnnotationTag& traffic_annotation)
     : listen_socket_(std::move(listen_socket)),
       protocol_(protocol),
-      use_proxy_(use_proxy),
+      use_padding_(use_padding),
       session_(session),
       net_log_(
           NetLogWithSource::Make(session->net_log(), NetLogSourceType::NONE)),
       last_id_(0),
       traffic_annotation_(traffic_annotation) {
+  const auto& proxy_config = session_->proxy_resolution_service()->config();
+  DCHECK(proxy_config);
+  const ProxyList& proxy_list =
+      proxy_config.value().value().proxy_rules().single_proxies;
+  DCHECK(!proxy_list.IsEmpty());
+  proxy_info_.UseProxyList(proxy_list);
+  proxy_info_.set_traffic_annotation(
+      net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
+
+  session_->GetSSLConfig(&server_ssl_config_, &proxy_ssl_config_);
+  proxy_ssl_config_.disable_cert_verification_network_fetches = true;
+
   DCHECK(listen_socket_);
   // Start accepting connections in next run loop in case when delegate is not
   // ready to get callbacks.
@@ -78,19 +88,24 @@ void NaiveProxy::HandleAcceptResult(int result) {
 void NaiveProxy::DoConnect() {
   std::unique_ptr<StreamSocket> socket;
   NaiveConnection::Direction pad_direction;
-  if (protocol_ == kSocks5) {
+  if (protocol_ == NaiveConnection::kSocks5) {
     socket = std::make_unique<Socks5ServerSocket>(std::move(accepted_socket_),
                                                   traffic_annotation_);
     pad_direction = NaiveConnection::kClient;
-  } else if (protocol_ == kHttp) {
+  } else if (protocol_ == NaiveConnection::kHttp) {
     socket = std::make_unique<HttpProxySocket>(std::move(accepted_socket_),
                                                traffic_annotation_);
     pad_direction = NaiveConnection::kServer;
   } else {
     return;
   }
+  if (!use_padding_) {
+    pad_direction = NaiveConnection::kNone;
+  }
   auto connection_ptr = std::make_unique<NaiveConnection>(
-      ++last_id_, pad_direction, std::move(socket), this, traffic_annotation_);
+      ++last_id_, protocol_, pad_direction, proxy_info_, server_ssl_config_,
+      proxy_ssl_config_, session_, net_log_, std::move(socket),
+      traffic_annotation_);
   auto* connection = connection_ptr.get();
   connection_by_id_[connection->id()] = std::move(connection_ptr);
   int result = connection->Connect(
@@ -101,62 +116,8 @@ void NaiveProxy::DoConnect() {
   HandleConnectResult(connection, result);
 }
 
-int NaiveProxy::OnConnectServer(unsigned int connection_id,
-                                const StreamSocket* client_socket,
-                                ClientSocketHandle* server_socket,
-                                CompletionRepeatingCallback callback) {
-  // Ignores socket limit set by socket pool for this type of socket.
-  constexpr int request_load_flags = LOAD_IGNORE_LIMITS;
-  constexpr RequestPriority request_priority = MAXIMUM_PRIORITY;
-
-  ProxyInfo proxy_info;
-  SSLConfig server_ssl_config;
-  SSLConfig proxy_ssl_config;
-
-  if (use_proxy_) {
-    const auto& proxy_config = session_->proxy_resolution_service()->config();
-    DCHECK(proxy_config);
-    const ProxyList& proxy_list =
-        proxy_config.value().value().proxy_rules().single_proxies;
-    if (proxy_list.IsEmpty())
-      return ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
-    proxy_info.UseProxyList(proxy_list);
-    proxy_info.set_traffic_annotation(
-        net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
-
-    HttpRequestInfo req_info;
-    session_->GetSSLConfig(req_info, &server_ssl_config, &proxy_ssl_config);
-    proxy_ssl_config.disable_cert_verification_network_fetches = true;
-  } else {
-    proxy_info.UseDirect();
-  }
-
-  HostPortPair request_endpoint;
-  if (protocol_ == kSocks5) {
-    const auto* socket = static_cast<const Socks5ServerSocket*>(client_socket);
-    request_endpoint = socket->request_endpoint();
-  } else if (protocol_ == kHttp) {
-    const auto* socket = static_cast<const HttpProxySocket*>(client_socket);
-    request_endpoint = socket->request_endpoint();
-  }
-  if (request_endpoint.IsEmpty()) {
-    LOG(ERROR) << "Connection " << connection_id << " to invalid origin";
-    return ERR_ADDRESS_INVALID;
-  }
-
-  LOG(INFO) << "Connection " << connection_id << " to "
-            << request_endpoint.ToString();
-
-  auto quic_version = quic::QUIC_VERSION_UNSUPPORTED;
-
-  return InitSocketHandleForRawConnect2(
-      request_endpoint, session_, request_load_flags, request_priority,
-      proxy_info, quic_version, server_ssl_config, proxy_ssl_config,
-      PRIVACY_MODE_DISABLED, net_log_, server_socket, callback);
-}
-
-void NaiveProxy::OnConnectComplete(int connection_id, int result) {
-  NaiveConnection* connection = FindConnection(connection_id);
+void NaiveProxy::OnConnectComplete(unsigned int connection_id, int result) {
+  auto* connection = FindConnection(connection_id);
   if (!connection)
     return;
   HandleConnectResult(connection, result);
@@ -179,8 +140,8 @@ void NaiveProxy::DoRun(NaiveConnection* connection) {
   HandleRunResult(connection, result);
 }
 
-void NaiveProxy::OnRunComplete(int connection_id, int result) {
-  NaiveConnection* connection = FindConnection(connection_id);
+void NaiveProxy::OnRunComplete(unsigned int connection_id, int result) {
+  auto* connection = FindConnection(connection_id);
   if (!connection)
     return;
   HandleRunResult(connection, result);
@@ -190,7 +151,7 @@ void NaiveProxy::HandleRunResult(NaiveConnection* connection, int result) {
   Close(connection->id(), result);
 }
 
-void NaiveProxy::Close(int connection_id, int reason) {
+void NaiveProxy::Close(unsigned int connection_id, int reason) {
   auto it = connection_by_id_.find(connection_id);
   if (it == connection_by_id_.end())
     return;
@@ -207,19 +168,11 @@ void NaiveProxy::Close(int connection_id, int reason) {
   connection_by_id_.erase(it);
 }
 
-NaiveConnection* NaiveProxy::FindConnection(int connection_id) {
+NaiveConnection* NaiveProxy::FindConnection(unsigned int connection_id) {
   auto it = connection_by_id_.find(connection_id);
   if (it == connection_by_id_.end())
     return nullptr;
   return it->second.get();
 }
 
-// This is called after any delegate callbacks are called to check if Close()
-// has been called during callback processing. Using the pointer of connection,
-// |connection| is safe here because Close() deletes the connection in next run
-// loop.
-bool NaiveProxy::HasClosedConnection(NaiveConnection* connection) {
-  return FindConnection(connection->id()) != connection;
-}
-
 }  // namespace net
diff --git a/src/net/tools/naive/naive_proxy.h b/src/net/tools/naive/naive_proxy.h
index e304085571..270106ae42 100644
--- a/src/net/tools/naive/naive_proxy.h
+++ b/src/net/tools/naive/naive_proxy.h
@@ -13,6 +13,8 @@
 #include "base/memory/weak_ptr.h"
 #include "net/base/completion_repeating_callback.h"
 #include "net/log/net_log_with_source.h"
+#include "net/proxy_resolution/proxy_info.h"
+#include "net/ssl/ssl_config.h"
 #include "net/tools/naive/naive_connection.h"
 
 namespace net {
@@ -24,24 +26,14 @@ class ServerSocket;
 class StreamSocket;
 struct NetworkTrafficAnnotationTag;
 
-class NaiveProxy : public NaiveConnection::Delegate {
+class NaiveProxy {
  public:
-  enum Protocol {
-    kSocks5,
-    kHttp,
-  };
-
   NaiveProxy(std::unique_ptr<ServerSocket> server_socket,
-             Protocol protocol,
-             bool use_proxy,
+             NaiveConnection::Protocol protocol,
+             bool use_padding,
              HttpNetworkSession* session,
              const NetworkTrafficAnnotationTag& traffic_annotation);
-  ~NaiveProxy() override;
-
-  int OnConnectServer(unsigned int connection_id,
-                      const StreamSocket* accepted_socket,
-                      ClientSocketHandle* server_socket,
-                      CompletionRepeatingCallback callback) override;
+  ~NaiveProxy();
 
  private:
   void DoAcceptLoop();
@@ -49,21 +41,23 @@ class NaiveProxy : public NaiveConnection::Delegate {
   void HandleAcceptResult(int result);
 
   void DoConnect();
-  void OnConnectComplete(int connection_id, int result);
+  void OnConnectComplete(unsigned int connection_id, int result);
   void HandleConnectResult(NaiveConnection* connection, int result);
 
   void DoRun(NaiveConnection* connection);
-  void OnRunComplete(int connection_id, int result);
+  void OnRunComplete(unsigned int connection_id, int result);
   void HandleRunResult(NaiveConnection* connection, int result);
 
-  void Close(int connection_id, int reason);
+  void Close(unsigned int connection_id, int reason);
 
-  NaiveConnection* FindConnection(int connection_id);
-  bool HasClosedConnection(NaiveConnection* connection);
+  NaiveConnection* FindConnection(unsigned int connection_id);
 
   std::unique_ptr<ServerSocket> listen_socket_;
-  Protocol protocol_;
-  bool use_proxy_;
+  NaiveConnection::Protocol protocol_;
+  bool use_padding_;
+  ProxyInfo proxy_info_;
+  SSLConfig server_ssl_config_;
+  SSLConfig proxy_ssl_config_;
   HttpNetworkSession* session_;
   NetLogWithSource net_log_;
 
diff --git a/src/net/tools/naive/naive_proxy_bin.cc b/src/net/tools/naive/naive_proxy_bin.cc
index 58997ee3b2..aa6180938e 100644
--- a/src/net/tools/naive/naive_proxy_bin.cc
+++ b/src/net/tools/naive/naive_proxy_bin.cc
@@ -4,6 +4,7 @@
 // found in the LICENSE file.
 
 #include <cstdlib>
+#include <iostream>
 #include <limits>
 #include <memory>
 #include <string>
@@ -52,6 +53,7 @@
 #include "net/url_request/url_request_context_builder.h"
 #include "url/gurl.h"
 #include "url/scheme_host_port.h"
+#include "url/url_util.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_nsautorelease_pool.h"
@@ -67,15 +69,16 @@ constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
     net::DefineNetworkTrafficAnnotation("naive", "");
 
 struct Params {
+  net::NaiveConnection::Protocol protocol;
   std::string listen_addr;
   int listen_port;
-  net::NaiveProxy::Protocol protocol;
-  bool use_proxy;
+  bool use_padding;
   std::string proxy_url;
   std::string proxy_user;
   std::string proxy_pass;
   std::string host_resolver_rules;
   logging::LoggingSettings log_settings;
+  base::FilePath log_path;
   base::FilePath net_log_path;
   base::FilePath ssl_key_path;
 };
@@ -112,9 +115,7 @@ std::unique_ptr<net::URLRequestContext> BuildURLRequestContext(
   builder.set_net_log(net_log);
 
   net::ProxyConfig proxy_config;
-  if (params.use_proxy) {
-    proxy_config.proxy_rules().ParseFromString(params.proxy_url);
-  }
+  proxy_config.proxy_rules().ParseFromString(params.proxy_url);
   auto proxy_service = net::ProxyResolutionService::CreateWithoutProxyResolver(
       std::make_unique<net::ProxyConfigServiceFixed>(
           net::ProxyConfigWithAnnotation(proxy_config, kTrafficAnnotation)),
@@ -128,11 +129,15 @@ std::unique_ptr<net::URLRequestContext> BuildURLRequestContext(
 
   auto context = builder.Build();
 
-  if (params.use_proxy) {
-    net::HttpNetworkSession* session =
-        context->http_transaction_factory()->GetSession();
-    net::HttpAuthCache* auth_cache = session->http_auth_cache();
-    GURL auth_origin(params.proxy_url);
+  if (!params.proxy_url.empty() && !params.proxy_user.empty() &&
+      !params.proxy_pass.empty()) {
+    auto* session = context->http_transaction_factory()->GetSession();
+    auto* auth_cache = session->http_auth_cache();
+    std::string proxy_url = params.proxy_url;
+    if (proxy_url.compare(0, 7, "quic://") == 0) {
+      proxy_url.replace(0, 4, "https");
+    }
+    GURL auth_origin(proxy_url);
     net::AuthCredentials credentials(base::ASCIIToUTF16(params.proxy_user),
                                      base::ASCIIToUTF16(params.proxy_pass));
     auth_cache->Add(auth_origin, net::HttpAuth::AUTH_PROXY,
@@ -148,79 +153,73 @@ bool ParseCommandLineFlags(Params* params) {
   const base::CommandLine& line = *base::CommandLine::ForCurrentProcess();
 
   if (line.HasSwitch("h") || line.HasSwitch("help")) {
-    LOG(INFO) << "Usage: naive [options]\n"
+    std::cout << "Usage: naive [options]\n"
                  "\n"
                  "Options:\n"
                  "-h, --help                 Show this message\n"
                  "--version                  Print version\n"
-                 "--addr=<address>           Address to listen on (0.0.0.0)\n"
-                 "--port=<port>              Port to listen on (1080)\n"
-                 "--proto=[socks|http]       Protocol to accept (socks)\n"
-                 "--proxy=https://<user>:<pass>@<hostname>[:<port>]\n"
-                 "                           Proxy specification.\n"
-                 "--log                      Log to stderr, otherwise no log\n"
+                 "--listen=<proto>://[addr][:port]\n"
+                 "                           proto: socks, http\n"
+                 "--proxy=<proto>://[<user>:<pass>@]<hostname>[:<port>]\n"
+                 "                           proto: https, quic\n"
+                 "--padding                  Use padding\n"
+                 "--log[=<path>]             Log to stderr, or file\n"
                  "--log-net-log=<path>       Save NetLog\n"
-                 "--ssl-key-log-file=<path>  Save SSL keys for Wireshark\n";
+                 "--ssl-key-log-file=<path>  Save SSL keys for Wireshark\n"
+              << std::endl;
     exit(EXIT_SUCCESS);
     return false;
   }
 
   if (line.HasSwitch("version")) {
-    LOG(INFO) << "Version: " << version_info::GetVersionNumber();
+    std::cout << "Version: " << version_info::GetVersionNumber() << std::endl;
     exit(EXIT_SUCCESS);
     return false;
   }
 
+  params->protocol = net::NaiveConnection::kSocks5;
   params->listen_addr = "0.0.0.0";
-  if (line.HasSwitch("addr")) {
-    params->listen_addr = line.GetSwitchValueASCII("addr");
-  }
-  if (params->listen_addr.empty()) {
-    LOG(ERROR) << "Invalid --addr";
-    return false;
-  }
-
   params->listen_port = 1080;
-  if (line.HasSwitch("port")) {
-    if (!base::StringToInt(line.GetSwitchValueASCII("port"),
-                           &params->listen_port)) {
-      LOG(ERROR) << "Invalid --port";
-      return false;
-    }
-    if (params->listen_port <= 0 ||
-        params->listen_port > std::numeric_limits<uint16_t>::max()) {
-      LOG(ERROR) << "Invalid --port";
-      return false;
-    }
-  }
-
-  params->protocol = net::NaiveProxy::kSocks5;
-  if (line.HasSwitch("proto")) {
-    const auto& proto = line.GetSwitchValueASCII("proto");
-    if (proto == "socks") {
-      params->protocol = net::NaiveProxy::kSocks5;
-    } else if (proto == "http") {
-      params->protocol = net::NaiveProxy::kHttp;
+  url::AddStandardScheme("socks", url::SCHEME_WITH_HOST_AND_PORT);
+  if (line.HasSwitch("listen")) {
+    GURL url(line.GetSwitchValueASCII("listen"));
+    if (url.scheme() == "socks") {
+      params->protocol = net::NaiveConnection::kSocks5;
+      params->listen_port = 1080;
+    } else if (url.scheme() == "http") {
+      params->protocol = net::NaiveConnection::kHttp;
+      params->listen_port = 8080;
     } else {
-      LOG(ERROR) << "Invalid --proto";
+      LOG(ERROR) << "Invalid scheme in --listen";
       return false;
     }
+    if (!url.host().empty()) {
+      params->listen_addr = url.host();
+    }
+    if (!url.port().empty()) {
+      if (!base::StringToInt(url.port(), &params->listen_port)) {
+        LOG(ERROR) << "Invalid port in --listen";
+        return false;
+      }
+      if (params->listen_port <= 0 ||
+          params->listen_port > std::numeric_limits<uint16_t>::max()) {
+        LOG(ERROR) << "Invalid port in --listen";
+        return false;
+      }
+    }
   }
 
-  params->use_proxy = false;
+  url::AddStandardScheme("quic",
+                         url::SCHEME_WITH_HOST_PORT_AND_USER_INFORMATION);
+  params->proxy_url = "direct://";
   GURL url(line.GetSwitchValueASCII("proxy"));
   if (line.HasSwitch("proxy")) {
-    params->use_proxy = true;
     if (!url.is_valid()) {
       LOG(ERROR) << "Invalid proxy URL";
       return false;
     }
-    if (url.scheme() != "https") {
-      LOG(ERROR) << "Must be HTTPS proxy";
-      return false;
-    }
-    if (url.username().empty() || url.password().empty()) {
-      LOG(ERROR) << "Missing user or pass";
+    if (url.scheme() != "https" && url.scheme() != "quic") {
+      LOG(ERROR) << "Must be HTTPS or QUIC proxy";
       return false;
     }
     params->proxy_url = url::SchemeHostPort(url).Serialize();
@@ -228,13 +227,25 @@ bool ParseCommandLineFlags(Params* params) {
     params->proxy_pass = url.password();
   }
 
+  params->use_padding = false;
+  if (line.HasSwitch("padding")) {
+    params->use_padding = true;
+  }
+
   if (line.HasSwitch("host-resolver-rules")) {
     params->host_resolver_rules =
         line.GetSwitchValueASCII("host-resolver-rules");
   }
 
   if (line.HasSwitch("log")) {
-    params->log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
+    params->log_settings.logging_dest = logging::LOG_DEFAULT;
+    params->log_path = line.GetSwitchValuePath("log");
+    if (!params->log_path.empty()) {
+      params->log_settings.logging_dest = logging::LOG_TO_FILE;
+    } else if (params->log_settings.logging_dest == logging::LOG_TO_FILE) {
+      params->log_path = base::FilePath::FromUTF8Unsafe("naive.log");
+    }
+    params->log_settings.log_file_path = params->log_path.value().c_str();
   } else {
     params->log_settings.logging_dest = logging::LOG_NONE;
   }
@@ -352,6 +363,7 @@ int main(int argc, char* argv[]) {
   }
 
   auto context = BuildURLRequestContext(params, net_log);
+  auto* session = context->http_transaction_factory()->GetSession();
 
   auto listen_socket =
       std::make_unique<net::TCPServerSocket>(net_log, net::NetLogSource());
@@ -363,9 +375,8 @@ int main(int argc, char* argv[]) {
     return EXIT_FAILURE;
   }
 
-  net::NaiveProxy naive_proxy(
-      std::move(listen_socket), params.protocol, params.use_proxy,
-      context->http_transaction_factory()->GetSession(), kTrafficAnnotation);
+  net::NaiveProxy naive_proxy(std::move(listen_socket), params.protocol,
+                              params.use_padding, session, kTrafficAnnotation);
 
   base::RunLoop().Run();