system-proxy: Accept CONNECT requests

This CL enables workers to process proxy CONNECT requests.
It extracts the url from the incoming request and sets up a
connection to the remote proxy using curl for
authentication.

BUG=chromium:1042626
TEST=unittests

Change-Id: Iebbed5a8229f17aa0f13fb2c7413e084bf276051
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2106136
Reviewed-by: Pavol Marko <pmarko@chromium.org>
Tested-by: Andreea-Elena Costinas <acostinas@google.com>
Commit-Queue: Andreea-Elena Costinas <acostinas@google.com>
diff --git a/system-proxy/server_proxy.h b/system-proxy/server_proxy.h
index 0704b14..5096636 100644
--- a/system-proxy/server_proxy.h
+++ b/system-proxy/server_proxy.h
@@ -4,17 +4,31 @@
 #ifndef SYSTEM_PROXY_SERVER_PROXY_H_
 #define SYSTEM_PROXY_SERVER_PROXY_H_
 
+#include <list>
+#include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
-#include <arc/network/socket.h>
 #include <base/callback_forward.h>
 #include <base/files/file_descriptor_watcher_posix.h>
+#include <base/files/scoped_file.h>
+#include <base/memory/weak_ptr.h>
 #include <brillo/asynchronous_signal_handler.h>
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
 
+namespace arc_networkd {
+class Socket;
+class SocketForwarder;
+}  // namespace arc_networkd
+
 namespace system_proxy {
 
+using OnProxyResolvedCallback =
+    base::OnceCallback<void(const std::list<std::string>&)>;
+
+class ProxyConnectJob;
+
 // ServerProxy listens for connections from the host (system services, ARC++
 // apps) and sets-up connections to the remote server.
 // Note: System-proxy only supports proxying over IPv4 networks.
@@ -27,6 +41,15 @@
 
   void Init();
 
+  // Creates a proxy resolution request that is forwarded to the parent process
+  // trough the standard output. When the request is resolved, the parent
+  // process will send the result trough the standard input.
+  // |callback| will be called when the proxy is resolved, with the list of
+  // proxy servers as parameter ,or in case of failure, with a list containing
+  // only the direct proxy.
+  void ResolveProxy(const std::string& target_url,
+                    OnProxyResolvedCallback callback);
+
  protected:
   virtual int GetStdinPipe();
 
@@ -34,27 +57,48 @@
   friend class ServerProxyTest;
   FRIEND_TEST(ServerProxyTest, FetchCredentials);
   FRIEND_TEST(ServerProxyTest, FetchListeningAddress);
+  FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
+  FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
 
   void HandleStdinReadable();
   bool HandleSignal(const struct signalfd_siginfo& siginfo);
 
   void CreateListeningSocket();
-  void OnConnectionRequest();
+  void OnConnectionAccept();
+
+  // Called by |ProxyConnectJob| after setting up the connection with the remote
+  // server via the remote proxy server. If the connection is successful, |fwd|
+  // corresponds to the tunnel between the client and the server that has
+  // started to forward data. In case of failure, |fwd| is empty.
+  void OnConnectionSetupFinished(
+      std::unique_ptr<arc_networkd::SocketForwarder> fwd,
+      ProxyConnectJob* connect_job);
 
   // The proxy listening address in network-byte order.
   uint32_t listening_addr_ = 0;
   int listening_port_;
 
-  std::string username_;
-  std::string password_;
-
+  // The user name and password to use for proxy authentication in the format
+  // compatible with libcurl's CURLOPT_USERPWD: both user name and password URL
+  // encoded and separated by colon.
+  std::string credentials_;
   std::unique_ptr<arc_networkd::Socket> listening_fd_;
 
+  // List of SocketForwarders that corresponds to the TCP tunnel between the
+  // local client and the remote  proxy, forwarding data between the TCP
+  // connection initiated by the local client to the local proxy and the TCP
+  // connection initiated by the local proxy to the remote proxy.
+  std::list<std::unique_ptr<arc_networkd::SocketForwarder>> forwarders_;
+
+  std::map<ProxyConnectJob*, std::unique_ptr<ProxyConnectJob>>
+      pending_connect_jobs_;
+
   base::OnceClosure quit_closure_;
   std::unique_ptr<base::FileDescriptorWatcher::Controller> stdin_watcher_;
   std::unique_ptr<base::FileDescriptorWatcher::Controller> fd_watcher_;
-
   brillo::AsynchronousSignalHandler signal_handler_;
+
+  base::WeakPtrFactory<ServerProxy> weak_ptr_factory_;
 };
 }  // namespace system_proxy