blob: 3310cc92b4d34bf64934fc4991b9f082758e82df [file] [log] [blame]
Andreea Costinase45d54b2020-03-10 09:21:14 +01001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4#ifndef SYSTEM_PROXY_PROXY_CONNECT_JOB_H_
5#define SYSTEM_PROXY_PROXY_CONNECT_JOB_H_
6
7#include <list>
8#include <memory>
9#include <string>
10#include <string_view>
11#include <vector>
12
13#include <base/callback_forward.h>
14#include <base/files/file_descriptor_watcher_posix.h>
15#include <gtest/gtest_prod.h> // for FRIEND_TEST
16
Garrick Evans3388a032020-03-24 11:25:55 +090017namespace patchpanel {
Andreea Costinase45d54b2020-03-10 09:21:14 +010018class SocketForwarder;
19class Socket;
Garrick Evans3388a032020-03-24 11:25:55 +090020} // namespace patchpanel
Andreea Costinase45d54b2020-03-10 09:21:14 +010021
22namespace system_proxy {
23// ProxyConnectJob asynchronously sets up a connection to a remote target on
24// behalf of a client. Internally, it performs the following steps:
25// - waits for the client to send a HTTP connect request;
26// - extracts the target url from the connect request;
27// - requests proxy resolution for the target url and waits for the result;
28// - performs the proxy authentication and connection setup to the remote
29// target.
30class ProxyConnectJob {
31 public:
32 using OnConnectionSetupFinishedCallback = base::OnceCallback<void(
Garrick Evans3388a032020-03-24 11:25:55 +090033 std::unique_ptr<patchpanel::SocketForwarder>, ProxyConnectJob*)>;
Andreea Costinase45d54b2020-03-10 09:21:14 +010034
35 // Will be invoked by ProxyConnectJob to resolve the proxy for |target_url_|.
36 // The passed |callback| is expected to be called with the list of proxy
37 // servers, which will always contain at least one entry, the default proxy.
38 using ResolveProxyCallback = base::OnceCallback<void(
39 const std::string& url,
40 base::OnceCallback<void(const std::list<std::string>&)> callback)>;
41
Garrick Evans3388a032020-03-24 11:25:55 +090042 ProxyConnectJob(std::unique_ptr<patchpanel::Socket> socket,
Andreea Costinase45d54b2020-03-10 09:21:14 +010043 const std::string& credentials,
44 ResolveProxyCallback resolve_proxy_callback,
45 OnConnectionSetupFinishedCallback setup_finished_callback);
46 ProxyConnectJob(const ProxyConnectJob&) = delete;
47 ProxyConnectJob& operator=(const ProxyConnectJob&) = delete;
48 virtual ~ProxyConnectJob();
49
50 // Marks |client_socket_| as non-blocking and adds a watcher that calls
51 // |OnClientReadReady| when the socket is read ready.
52 virtual bool Start();
53 void OnProxyResolution(const std::list<std::string>& proxy_servers);
54
55 friend std::ostream& operator<<(std::ostream& stream,
56 const ProxyConnectJob& job);
57
58 private:
59 friend class ServerProxyTest;
60 friend class ProxyConnectJobTest;
61 FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
Andreea Costinas5862b102020-03-19 14:45:36 +010062 FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
Andreea Costinase45d54b2020-03-10 09:21:14 +010063 FRIEND_TEST(ProxyConnectJobTest, SuccessfulConnection);
64 FRIEND_TEST(ProxyConnectJobTest, BadHttpRequestWrongMethod);
65 FRIEND_TEST(ProxyConnectJobTest, BadHttpRequestNoEmptyLine);
66
67 // Reads data from the socket into |raw_request| until the first empty line,
68 // which would mark the end of the HTTP request header.
69 // This method does not validate the headers.
70 bool TryReadHttpHeader(std::vector<char>* raw_request);
71
72 // Called when the client socket is ready for reading.
73 void OnClientReadReady();
74
75 // Called from |OnProxyResolution|, after the proxy for |target_url_| is
76 // resolved.
77 void DoCurlServerConnection(const std::string& proxy_url);
78
79 void OnError(const std::string_view& http_error_message);
80
81 std::string target_url_;
82 const std::string credentials_;
83 std::list<std::string> proxy_servers_;
84 ResolveProxyCallback resolve_proxy_callback_;
85 OnConnectionSetupFinishedCallback setup_finished_callback_;
Garrick Evans3388a032020-03-24 11:25:55 +090086 std::unique_ptr<patchpanel::Socket> client_socket_;
Andreea Costinase45d54b2020-03-10 09:21:14 +010087 std::unique_ptr<base::FileDescriptorWatcher::Controller> read_watcher_;
88};
89} // namespace system_proxy
90
91#endif // SYSTEM_PROXY_PROXY_CONNECT_JOB_H_