1 // Copyright 2018 The Chromium 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 
5 #ifndef CHROME_BROWSER_CHROMEOS_SMB_CLIENT_DISCOVERY_NETWORK_SCANNER_H_
6 #define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_DISCOVERY_NETWORK_SCANNER_H_
7 
8 #include <map>
9 #include <vector>
10 
11 #include "base/callback.h"
12 #include "base/memory/weak_ptr.h"
13 #include "chrome/browser/chromeos/smb_client/discovery/host_locator.h"
14 #include "net/base/ip_address.h"
15 
16 namespace chromeos {
17 namespace smb_client {
18 
19 // Holds the number of in-flight requests and the callback to call once all the
20 // HostLocators are finished. Also holds the hosts found from the HostLocators
21 // that have already returned.
22 struct RequestInfo {
23   uint32_t remaining_requests;
24   FindHostsCallback callback;
25   HostMap hosts_found;
26 
27   RequestInfo(uint32_t remaining_requests, FindHostsCallback callback);
28   RequestInfo(RequestInfo&& other);
29   ~RequestInfo();
30 
31   DISALLOW_COPY_AND_ASSIGN(RequestInfo);
32 };
33 
34 // NetworkScanner discovers SMB hosts in the local network by querying
35 // registered HostLocators and aggregating their results. RegisterHostLocator is
36 // used to register HostLocators that are responsible for finding hosts.
37 // FindHostsInNetwork is called to get a list of discoverable hosts in the
38 // network. ResolveHost is used to get the IP address of a given host.
39 class NetworkScanner : public base::SupportsWeakPtr<NetworkScanner> {
40  public:
41   NetworkScanner();
42   ~NetworkScanner();
43 
44   // Query the registered HostLocators and return all the hosts found.
45   // |callback| is called once all the HostLocators have responded with their
46   // results. If there are no locators, the callback is fired immediately with
47   // an empty result and success set to false. Once this call has returned, the
48   // hosts found are cached locally and are resolvable individually through
49   // ResolveHost().
50   void FindHostsInNetwork(FindHostsCallback callback);
51 
52   // Registeres a |locator| to be queried when FindHostsInNetwork() is called.
53   void RegisterHostLocator(std::unique_ptr<HostLocator> locator);
54 
55   // Resolves |host| to an address using the cached results of
56   // FindHostsInNetwork(). FindHostsInNetwork() has to be called beforehand. If
57   // no address is found, this returns an invalid IPAddress.
58   net::IPAddress ResolveHost(const std::string& host) const;
59 
60  private:
61   // Callback handler for HostLocator::FindHosts().
62   void OnHostsFound(uint32_t request_id, bool success, const HostMap& host_map);
63 
64   // Adds |host_map| hosts to current results. The host will not be added if the
65   // hostname already exists in results, and if the IP address does not match,
66   // it will be logged.
67   void AddHostsToResults(uint32_t request_id, const HostMap& host_map);
68 
69   // Adds a new request to track and saves |callback| to be called when the
70   // request is finished. Returns the request id.
71   uint32_t AddNewRequest(FindHostsCallback callback);
72 
73   // Called after a HostLocator returns with results and decrements the count of
74   // requests in RequestInfo for |request_id|. Fires the callback for if
75   // there are no more requests and deletes the corresponding RequestInfo.
76   void FireCallbackIfFinished(uint32_t request_id);
77 
78   std::vector<std::unique_ptr<HostLocator>> locators_;
79 
80   // Used for tracking in-flight requests to HostLocators. The key is the
81   // request id, and the value is the RequestInfo struct.
82   std::map<uint32_t, RequestInfo> requests_;
83 
84   uint32_t next_request_id_ = 0;
85 
86   // Hosts that are found from FindHostsInNetwork(). This is cached for name
87   // resolution when calling ResolveHost().
88   HostMap found_hosts_;
89 
90   // True if FindHostsInNetwork() has been called and returned results
91   // regardless if any hosts are found.
92   bool find_hosts_returned_ = false;
93 
94   // True if FindHostsInNetwork() has been called and is waiting for
95   // FindHostsCallback to be invoked. This is to prevent multiple calls of
96   // FindHostsInNetwork() from concurrently executing. Used only for DCHECKing
97   // if FindHostsInNetwork() is already running.
98   bool running_ = false;
99 
100   DISALLOW_COPY_AND_ASSIGN(NetworkScanner);
101 };
102 
103 }  // namespace smb_client
104 }  // namespace chromeos
105 
106 #endif  // CHROME_BROWSER_CHROMEOS_SMB_CLIENT_DISCOVERY_NETWORK_SCANNER_H_
107