1 //
2 // Copyright (C) 2013 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef UPDATE_ENGINE_P2P_MANAGER_H_
18 #define UPDATE_ENGINE_P2P_MANAGER_H_
19 
20 #include <string>
21 #include <vector>
22 
23 #include <base/callback.h>
24 #include <base/files/file_path.h>
25 #include <base/memory/ref_counted.h>
26 #include <base/time/time.h>
27 #include <policy/device_policy.h>
28 #include <policy/libpolicy.h>
29 
30 #include "update_engine/common/clock_interface.h"
31 #include "update_engine/common/prefs_interface.h"
32 #include "update_engine/update_manager/update_manager.h"
33 
34 namespace chromeos_update_engine {
35 
36 // Interface for sharing and discovering files via p2p.
37 class P2PManager {
38  public:
39   // Interface used for P2PManager implementations. The sole reason
40   // for this interface is unit testing.
41   class Configuration {
42    public:
~Configuration()43     virtual ~Configuration() {}
44 
45     // Gets the path to the p2p dir being used, e.g. /var/cache/p2p.
46     virtual base::FilePath GetP2PDir() = 0;
47 
48     // Gets the argument vector for starting (if |is_start| is True)
49     // resp. stopping (if |is_start| is False) the p2p service
50     // e.g. ["initctl", "start", "p2p"] or ["initctl", "stop", "p2p"].
51     virtual std::vector<std::string> GetInitctlArgs(bool is_start) = 0;
52 
53     // Gets the argument vector for invoking p2p-client, e.g.
54     // "p2p-client --get-url=file_id_we_want --minimum-size=42123".
55     virtual std::vector<std::string> GetP2PClientArgs(
56         const std::string& file_id, size_t minimum_size) = 0;
57   };
58 
~P2PManager()59   virtual ~P2PManager() {}
60 
61   // The type for the callback used in LookupUrlForFile().
62   // If the lookup failed, |url| is empty.
63   typedef base::Callback<void(const std::string& url)> LookupCallback;
64 
65   // Use the device policy specified by |device_policy|. If this is
66   // null, then no device policy is used.
67   virtual void SetDevicePolicy(const policy::DevicePolicy* device_policy) = 0;
68 
69   // Returns true iff P2P is currently allowed for use on this device. This
70   // value is determined and maintained by the Update Manager.
71   virtual bool IsP2PEnabled() = 0;
72 
73   // Ensures that the p2p subsystem is running (e.g. starts it if it's
74   // not already running) and blocks until this is so. Returns false
75   // if an error occurred.
76   virtual bool EnsureP2PRunning() = 0;
77 
78   // Ensures that the p2p subsystem is not running (e.g. stops it if
79   // it's running) and blocks until this is so. Returns false if an
80   // error occurred.
81   virtual bool EnsureP2PNotRunning() = 0;
82 
83   // Cleans up files in /var/cache/p2p owned by this application as
84   // per the |file_extension| and |num_files_to_keep| values passed
85   // when the object was constructed. This may be called even if
86   // the p2p subsystem is not running.
87   virtual bool PerformHousekeeping() = 0;
88 
89   // Asynchronously finds a peer that serves the file identified by
90   // |file_id|. If |minimum_size| is non-zero, will find a peer that
91   // has at least that many bytes. When the result is ready |callback|
92   // is called from the current message loop.
93   //
94   // This operation may take a very long time to complete because part
95   // of the p2p protocol involves waiting for the LAN-wide sum of all
96   // num-connections to drop below a given threshold. However, if
97   // |max_time_to_wait| is non-zero, the operation is guaranteed to
98   // not exceed this duration.
99   //
100   // If the file is not available on the LAN (or if mDNS/DNS-SD is
101   // filtered), this is guaranteed to not take longer than 5 seconds.
102   virtual void LookupUrlForFile(const std::string& file_id,
103                                 size_t minimum_size,
104                                 base::TimeDelta max_time_to_wait,
105                                 LookupCallback callback) = 0;
106 
107   // Shares a file identified by |file_id| in the directory
108   // /var/cache/p2p. Initially the file will not be visible, that is,
109   // it will have a .tmp extension and not be shared via p2p. Use the
110   // FileMakeVisible() method to change this.
111   //
112   // If you know the final size of the file, pass it in the
113   // |expected_size| parameter. Otherwise pass zero. If non-zero, the
114   // amount of free space in /var/cache/p2p is checked and if there is
115   // less than twice the amount of space available, this method
116   // fails. Additionally, disk space will be reserved via fallocate(2)
117   // and |expected_size| is written to the user.cros-p2p-filesize
118   // xattr of the created file.
119   //
120   // If the file already exists, true is returned. Any on-disk xattr
121   // is not updated.
122   virtual bool FileShare(const std::string& file_id, size_t expected_size) = 0;
123 
124   // Gets a fully qualified path for the file identified by |file_id|.
125   // If the file has not been shared already using the FileShare()
126   // method, an empty base::FilePath is returned - use FilePath::empty() to
127   // find out.
128   virtual base::FilePath FileGetPath(const std::string& file_id) = 0;
129 
130   // Gets the actual size of the file identified by |file_id|. This is
131   // equivalent to reading the value of the st_size field of the
132   // struct stat on the file given by FileGetPath(). Returns -1 if an
133   // error occurs.
134   //
135   // For a file just created with FileShare() this will return 0.
136   virtual ssize_t FileGetSize(const std::string& file_id) = 0;
137 
138   // Gets the expected size of the file identified by |file_id|. This
139   // is equivalent to reading the value of the user.cros-p2p-filesize
140   // xattr on the file given by FileGetPath(). Returns -1 if an error
141   // occurs.
142   //
143   // For a file just created with FileShare() this will return the
144   // value of the |expected_size| parameter passed to that method.
145   virtual ssize_t FileGetExpectedSize(const std::string& file_id) = 0;
146 
147   // Gets whether the file identified by |file_id| is publicly
148   // visible. If |out_result| is not null, the result is returned
149   // there. Returns false if an error occurs.
150   virtual bool FileGetVisible(const std::string& file_id, bool* out_result) = 0;
151 
152   // Makes the file identified by |file_id| publicly visible
153   // (e.g. removes the .tmp extension). If the file is already
154   // visible, this method does nothing. Returns False if
155   // the method fails or there is no file for |file_id|.
156   virtual bool FileMakeVisible(const std::string& file_id) = 0;
157 
158   // Counts the number of shared files used by this application
159   // (cf. the |file_extension parameter|. Returns -1 if an error
160   // occurred.
161   virtual int CountSharedFiles() = 0;
162 
163   // Creates a suitable P2PManager instance and initializes the object
164   // so it's ready for use. The |file_extension| parameter is used to
165   // identify your application, use e.g. "cros_au".  If
166   // |configuration| is non-null, the P2PManager will take ownership
167   // of the Configuration object and use it (hence, it must be
168   // heap-allocated).
169   //
170   // The |num_files_to_keep| parameter specifies how many files to
171   // keep after performing housekeeping (cf. the PerformHousekeeping()
172   // method) - pass zero to allow infinitely many files. The
173   // |max_file_age| parameter specifies the maximum file age after
174   // performing housekeeping (pass zero to allow files of any age).
175   static P2PManager* Construct(
176       Configuration* configuration,
177       ClockInterface* clock,
178       chromeos_update_manager::UpdateManager* update_manager,
179       const std::string& file_extension,
180       const int num_files_to_keep,
181       const base::TimeDelta& max_file_age);
182 };
183 
184 }  // namespace chromeos_update_engine
185 
186 #endif  // UPDATE_ENGINE_P2P_MANAGER_H_
187