blob: 57da52512f259af60ed923127c5edb2820337d15 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SYSTEM_PROXY_SERVER_PROXY_H_
#define SYSTEM_PROXY_SERVER_PROXY_H_
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#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 patchpanel {
class Socket;
class SocketForwarder;
} // namespace patchpanel
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.
class ServerProxy {
public:
explicit ServerProxy(base::OnceClosure quit_closure);
ServerProxy(const ServerProxy&) = delete;
ServerProxy& operator=(const ServerProxy&) = delete;
virtual ~ServerProxy();
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();
virtual int GetStdoutPipe();
private:
friend class ServerProxyTest;
FRIEND_TEST(ServerProxyTest, FetchCredentials);
FRIEND_TEST(ServerProxyTest, FetchListeningAddress);
FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
FRIEND_TEST(ServerProxyTest, SetupConnection);
void HandleStdinReadable();
bool HandleSignal(const struct signalfd_siginfo& siginfo);
void CreateListeningSocket();
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<patchpanel::SocketForwarder> fwd,
ProxyConnectJob* connect_job);
// Called when the proxy resolution result for |target_url| is received via
// the standard input (see |ResolveProxy| method). |proxy_servers| will always
// contain at least one entry, the direct proxy.
void OnProxyResolved(const std::string& target_url,
const std::list<std::string>& proxy_servers);
// The proxy listening address in network-byte order.
uint32_t listening_addr_ = 0;
int listening_port_;
// 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<patchpanel::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<patchpanel::SocketForwarder>> forwarders_;
std::map<ProxyConnectJob*, std::unique_ptr<ProxyConnectJob>>
pending_connect_jobs_;
// Collection of ongoing proxy resolution requests. The key represents the
// target url to be resolved and it's mapped to a list of callbaks to pending
// connect jobs that are connecting to the same target url.
std::map<std::string, std::list<OnProxyResolvedCallback>>
pending_proxy_resolution_requests_;
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
#endif // SYSTEM_PROXY_SERVER_PROXY_H_