blob: 5320c1716a914a261302c8c34fe09a8b87a50209 [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>
Andreea Costinas08a5d182020-04-29 22:12:47 +020014#include <base/cancelable_callback.h>
Andreea Costinase45d54b2020-03-10 09:21:14 +010015#include <base/files/file_descriptor_watcher_posix.h>
16#include <gtest/gtest_prod.h> // for FRIEND_TEST
17
Garrick Evans3388a032020-03-24 11:25:55 +090018namespace patchpanel {
Andreea Costinase45d54b2020-03-10 09:21:14 +010019class SocketForwarder;
20class Socket;
Garrick Evans3388a032020-03-24 11:25:55 +090021} // namespace patchpanel
Andreea Costinase45d54b2020-03-10 09:21:14 +010022
23namespace system_proxy {
24// ProxyConnectJob asynchronously sets up a connection to a remote target on
25// behalf of a client. Internally, it performs the following steps:
26// - waits for the client to send a HTTP connect request;
27// - extracts the target url from the connect request;
28// - requests proxy resolution for the target url and waits for the result;
29// - performs the proxy authentication and connection setup to the remote
30// target.
31class ProxyConnectJob {
32 public:
33 using OnConnectionSetupFinishedCallback = base::OnceCallback<void(
Garrick Evans3388a032020-03-24 11:25:55 +090034 std::unique_ptr<patchpanel::SocketForwarder>, ProxyConnectJob*)>;
Andreea Costinase45d54b2020-03-10 09:21:14 +010035
36 // Will be invoked by ProxyConnectJob to resolve the proxy for |target_url_|.
37 // The passed |callback| is expected to be called with the list of proxy
38 // servers, which will always contain at least one entry, the default proxy.
39 using ResolveProxyCallback = base::OnceCallback<void(
40 const std::string& url,
41 base::OnceCallback<void(const std::list<std::string>&)> callback)>;
42
Garrick Evans3388a032020-03-24 11:25:55 +090043 ProxyConnectJob(std::unique_ptr<patchpanel::Socket> socket,
Andreea Costinase45d54b2020-03-10 09:21:14 +010044 const std::string& credentials,
45 ResolveProxyCallback resolve_proxy_callback,
46 OnConnectionSetupFinishedCallback setup_finished_callback);
47 ProxyConnectJob(const ProxyConnectJob&) = delete;
48 ProxyConnectJob& operator=(const ProxyConnectJob&) = delete;
49 virtual ~ProxyConnectJob();
50
51 // Marks |client_socket_| as non-blocking and adds a watcher that calls
52 // |OnClientReadReady| when the socket is read ready.
53 virtual bool Start();
54 void OnProxyResolution(const std::list<std::string>& proxy_servers);
55
56 friend std::ostream& operator<<(std::ostream& stream,
57 const ProxyConnectJob& job);
58
59 private:
60 friend class ServerProxyTest;
61 friend class ProxyConnectJobTest;
62 FRIEND_TEST(ServerProxyTest, HandlePendingJobs);
Andreea Costinas5862b102020-03-19 14:45:36 +010063 FRIEND_TEST(ServerProxyTest, HandleConnectRequest);
Andreea Costinase45d54b2020-03-10 09:21:14 +010064 FRIEND_TEST(ProxyConnectJobTest, SuccessfulConnection);
65 FRIEND_TEST(ProxyConnectJobTest, BadHttpRequestWrongMethod);
66 FRIEND_TEST(ProxyConnectJobTest, BadHttpRequestNoEmptyLine);
67
68 // Reads data from the socket into |raw_request| until the first empty line,
69 // which would mark the end of the HTTP request header.
70 // This method does not validate the headers.
71 bool TryReadHttpHeader(std::vector<char>* raw_request);
72
73 // Called when the client socket is ready for reading.
74 void OnClientReadReady();
75
76 // Called from |OnProxyResolution|, after the proxy for |target_url_| is
77 // resolved.
78 void DoCurlServerConnection(const std::string& proxy_url);
79
80 void OnError(const std::string_view& http_error_message);
81
Andreea Costinas08a5d182020-04-29 22:12:47 +020082 void OnClientConnectTimeout();
83
Andreea Costinase45d54b2020-03-10 09:21:14 +010084 std::string target_url_;
85 const std::string credentials_;
86 std::list<std::string> proxy_servers_;
87 ResolveProxyCallback resolve_proxy_callback_;
88 OnConnectionSetupFinishedCallback setup_finished_callback_;
Andreea Costinas08a5d182020-04-29 22:12:47 +020089 base::CancelableClosure client_connect_timeout_callback_;
90
Garrick Evans3388a032020-03-24 11:25:55 +090091 std::unique_ptr<patchpanel::Socket> client_socket_;
Andreea Costinase45d54b2020-03-10 09:21:14 +010092 std::unique_ptr<base::FileDescriptorWatcher::Controller> read_watcher_;
93};
94} // namespace system_proxy
95
96#endif // SYSTEM_PROXY_PROXY_CONNECT_JOB_H_