xref: /aosp_15_r20/external/cronet/net/proxy_resolution/win/dhcp_pac_file_fetcher_win.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_PROXY_RESOLUTION_WIN_DHCP_PAC_FILE_FETCHER_WIN_H_
6 #define NET_PROXY_RESOLUTION_WIN_DHCP_PAC_FILE_FETCHER_WIN_H_
7 
8 #include <memory>
9 #include <set>
10 #include <string>
11 #include <vector>
12 
13 #include "base/memory/raw_ptr.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/threading/thread_checker.h"
16 #include "base/time/time.h"
17 #include "base/timer/timer.h"
18 #include "net/base/completion_once_callback.h"
19 #include "net/base/net_export.h"
20 #include "net/log/net_log_with_source.h"
21 #include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
22 #include "net/traffic_annotation/network_traffic_annotation.h"
23 
24 namespace base {
25 class TaskRunner;
26 }
27 
28 namespace net {
29 
30 struct DhcpAdapterNamesLoggingInfo;
31 class DhcpPacFileAdapterFetcher;
32 class URLRequestContext;
33 
34 // Windows-specific implementation.
35 class NET_EXPORT_PRIVATE DhcpPacFileFetcherWin
36     : public DhcpPacFileFetcher,
37       public base::SupportsWeakPtr<DhcpPacFileFetcherWin> {
38  public:
39   DhcpPacFileFetcherWin() = delete;
40 
41   // Creates a DhcpPacFileFetcherWin that issues requests through
42   // |url_request_context|. |url_request_context| must remain valid for
43   // the lifetime of DhcpPacFileFetcherWin.
44   explicit DhcpPacFileFetcherWin(URLRequestContext* url_request_context);
45 
46   DhcpPacFileFetcherWin(const DhcpPacFileFetcherWin&) = delete;
47   DhcpPacFileFetcherWin& operator=(const DhcpPacFileFetcherWin&) = delete;
48 
49   ~DhcpPacFileFetcherWin() override;
50 
51   // DhcpPacFileFetcher implementation.
52   int Fetch(std::u16string* utf16_text,
53             CompletionOnceCallback callback,
54             const NetLogWithSource& net_log,
55             const NetworkTrafficAnnotationTag traffic_annotation) override;
56   void Cancel() override;
57   void OnShutdown() override;
58   const GURL& GetPacURL() const override;
59   std::string GetFetcherName() const override;
60 
61   // Sets |adapter_names| to contain the name of each network adapter on
62   // this machine that has DHCP enabled and is not a loop-back adapter. May
63   // optionally update |info| (if non-null) with information for logging.
64   // Returns false on error.
65   static bool GetCandidateAdapterNames(std::set<std::string>* adapter_names,
66                                        DhcpAdapterNamesLoggingInfo* info);
67 
68  protected:
69   int num_pending_fetchers() const;
70 
71   URLRequestContext* url_request_context() const;
72 
73   scoped_refptr<base::TaskRunner> GetTaskRunner();
74 
75   // This inner class encapsulate work done on a worker pool thread.
76   // The class calls GetCandidateAdapterNames, which can take a couple of
77   // hundred milliseconds.
78   class NET_EXPORT_PRIVATE AdapterQuery
79       : public base::RefCountedThreadSafe<AdapterQuery> {
80    public:
81     AdapterQuery();
82 
83     AdapterQuery(const AdapterQuery&) = delete;
84     AdapterQuery& operator=(const AdapterQuery&) = delete;
85 
86     // This is the method that runs on the worker pool thread.
87     void GetCandidateAdapterNames();
88 
89     // This set is valid after GetCandidateAdapterNames has
90     // been run. Its lifetime is scoped by this object.
91     const std::set<std::string>& adapter_names() const;
92 
logging_info()93     DhcpAdapterNamesLoggingInfo* logging_info() { return logging_info_.get(); }
94 
95    protected:
96     // Virtual method introduced to allow unit testing.
97     virtual bool ImplGetCandidateAdapterNames(
98         std::set<std::string>* adapter_names,
99         DhcpAdapterNamesLoggingInfo* info);
100 
101     friend class base::RefCountedThreadSafe<AdapterQuery>;
102     virtual ~AdapterQuery();
103 
104    private:
105     // These are constructed on the originating thread, then used on the
106     // worker thread, then used again on the originating thread only when
107     // the task has completed on the worker thread. No locking required.
108     std::set<std::string> adapter_names_;
109     std::unique_ptr<DhcpAdapterNamesLoggingInfo> logging_info_;
110   };
111 
112   // Virtual methods introduced to allow unit testing.
113   virtual std::unique_ptr<DhcpPacFileAdapterFetcher> ImplCreateAdapterFetcher();
114   virtual scoped_refptr<AdapterQuery> ImplCreateAdapterQuery();
115   virtual base::TimeDelta ImplGetMaxWait();
ImplOnGetCandidateAdapterNamesDone()116   virtual void ImplOnGetCandidateAdapterNamesDone() {}
117 
118  private:
119   // Event/state transition handlers
120   void CancelImpl();
121   void OnGetCandidateAdapterNamesDone(
122       scoped_refptr<AdapterQuery> query,
123       const NetworkTrafficAnnotationTag traffic_annotation);
124   void OnFetcherDone(size_t fetcher_i, int result);
125   void OnWaitTimer();
126   void TransitionToDone();
127 
128   // This is the outer state machine for fetching PAC configuration from
129   // DHCP.  It relies for sub-states on the state machine of the
130   // DhcpPacFileAdapterFetcher class.
131   //
132   // The goal of the implementation is to the following work in parallel
133   // for all network adapters that are using DHCP:
134   // a) Try to get the PAC URL configured in DHCP;
135   // b) If one is configured, try to fetch the PAC URL.
136   // c) Once this is done for all adapters, or a timeout has passed after
137   //    it has completed for the fastest adapter, return the PAC file
138   //    available for the most preferred network adapter, if any.
139   //
140   // The state machine goes from START->WAIT_ADAPTERS when it starts a
141   // worker thread to get the list of adapters with DHCP enabled.
142   // It then goes from WAIT_ADAPTERS->NO_RESULTS when it creates
143   // and starts an DhcpPacFileAdapterFetcher for each adapter.  It goes
144   // from NO_RESULTS->SOME_RESULTS when it gets the first result; at this
145   // point a wait timer is started.  It goes from SOME_RESULTS->DONE in
146   // two cases: All results are known, or the wait timer expired.  A call
147   // to Cancel() will also go straight to DONE from any state.  Any
148   // way the DONE state is entered, we will at that point cancel any
149   // outstanding work and return the best known PAC script or the empty
150   // string.
151   //
152   // The state machine is reset for each Fetch(), a call to which is
153   // only valid in states START and DONE, as only one Fetch() is
154   // allowed to be outstanding at any given time.
155   enum State {
156     STATE_START,
157     STATE_WAIT_ADAPTERS,
158     STATE_NO_RESULTS,
159     STATE_SOME_RESULTS,
160     STATE_DONE,
161   };
162 
163   // Vector, in Windows' network adapter preference order, of
164   // DhcpPacFileAdapterFetcher objects that are or were attempting
165   // to fetch a PAC file based on DHCP configuration.
166   using FetcherVector = std::vector<std::unique_ptr<DhcpPacFileAdapterFetcher>>;
167   FetcherVector fetchers_;
168 
169   // Current state of this state machine.
170   State state_ = STATE_START;
171 
172   // The following members are associated with the latest call to Fetch().
173 
174   // Number of fetchers we are waiting for.
175   int num_pending_fetchers_ = 0;
176 
177   // Lets our client know we're done. Not valid in states START or DONE.
178   CompletionOnceCallback callback_;
179 
180   // The NetLog to use for the current Fetch().
181   NetLogWithSource net_log_;
182 
183   // Pointer to string we will write results to. Not valid in states
184   // START and DONE.
185   raw_ptr<std::u16string, AcrossTasksDanglingUntriaged> destination_string_ =
186       nullptr;
187 
188   // PAC URL retrieved from DHCP, if any. Valid only in state STATE_DONE.
189   GURL pac_url_;
190 
191   base::OneShotTimer wait_timer_;
192 
193   // Set to nullptr on cancellation.
194   raw_ptr<URLRequestContext> url_request_context_;
195 
196   // NULL or the AdapterQuery currently in flight.
197   scoped_refptr<AdapterQuery> last_query_;
198 
199   // TaskRunner used for all DHCP lookup tasks.
200   const scoped_refptr<base::TaskRunner> task_runner_;
201 
202   THREAD_CHECKER(thread_checker_);
203 };
204 
205 }  // namespace net
206 
207 #endif  // NET_PROXY_RESOLUTION_WIN_DHCP_PAC_FILE_FETCHER_WIN_H_
208