1 /**
2  * @file mega/transfer.h
3  * @brief pending/active up/download ordered by file fingerprint
4  *
5  * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
6  *
7  * This file is part of the MEGA SDK - Client Access Engine.
8  *
9  * Applications using the MEGA API must present a valid application key
10  * and comply with the the rules set forth in the Terms of Service.
11  *
12  * The MEGA SDK is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * @copyright Simplified (2-clause) BSD License.
17  *
18  * You should have received a copy of the license along with this
19  * program.
20  */
21 
22 #ifndef MEGA_TRANSFER_H
23 #define MEGA_TRANSFER_H 1
24 
25 #include "filefingerprint.h"
26 #include "backofftimer.h"
27 #include "http.h"
28 #include "command.h"
29 #include "raid.h"
30 
31 namespace mega {
32 
33 // helper class for categorizing transfers for upload/download queues
34 struct TransferCategory
35 {
36     direction_t direction = NONE;
37     filesizetype_t sizetype = LARGEFILE;
38 
39     TransferCategory(direction_t d, filesizetype_t s);
40     TransferCategory(Transfer*);
41     unsigned index();
42     unsigned directionIndex();
43 };
44 
45 class DBTableTransactionCommitter;
46 
47 // pending/active up/download ordered by file fingerprint (size - mtime - sparse CRC)
48 struct MEGA_API Transfer : public FileFingerprint
49 {
50     // PUT or GET
51     direction_t type;
52 
53     // transfer slot this transfer is active in (can be NULL if still queued)
54     TransferSlot* slot;
55 
56     // files belonging to this transfer - transfer terminates upon its last
57     // file is removed
58     file_list files;
59 
60     // failures/backoff
61     unsigned failcount;
62     BackoffTimerTracked bt;
63 
64     // representative local filename for this transfer
65     LocalPath localfilename;
66 
67     // progress completed
68     m_off_t progresscompleted;
69 
70     m_off_t pos;
71 
72     byte filekey[FILENODEKEYLENGTH];
73 
74     // CTR mode IV
75     int64_t ctriv;
76 
77     // meta MAC
78     int64_t metamac;
79 
80     // file crypto key and shared cipher
81     std::array<byte, SymmCipher::KEYLENGTH> transferkey;
82     SymmCipher *transfercipher();
83 
84     chunkmac_map chunkmacs;
85 
86     // upload handle for file attribute attachment (only set if file attribute queued)
87     handle uploadhandle;
88 
89     // minimum number of file attributes that need to be posted before a PUT transfer can complete
90     int minfa;
91 
92     // position in transfers[type]
93     transfer_map::iterator transfers_it;
94 
95     // position in faputcompletion[uploadhandle]
96     handletransfer_map::iterator faputcompletion_it;
97 
98     // upload result
99     byte *ultoken;
100 
101     // backlink to base
102     MegaClient* client;
103     int tag;
104 
105     // signal failure.  Either the transfer's slot or the transfer itself (including slot) will be deleted.
106     void failed(const Error&, DBTableTransactionCommitter&, dstime = 0);
107 
108     // signal completion
109     void complete(DBTableTransactionCommitter&);
110 
111     // execute completion
112     void completefiles();
113 
114     // remove file from transfer including in cache
115     void removeTransferFile(error, File* f, DBTableTransactionCommitter* committer);
116 
117     // previous wrong fingerprint
118     FileFingerprint badfp;
119 
120     // flag to know if prevmetamac is valid
121     bool hasprevmetamac;
122 
123     // previous wrong metamac
124     int64_t prevmetamac;
125 
126     // flag to know if currentmetamac is valid
127     bool hascurrentmetamac;
128 
129     // current wrong metamac
130     int64_t currentmetamac;
131 
132     // transfer state
133     bool finished;
134 
135     // temp URLs for upload/download data.  They can be cached.  For uploads, a new url means any previously uploaded data is abandoned.
136     // downloads can have 6 for raid, 1 for non-raid.  Uploads always have 1
137     std::vector<string> tempurls;
138 
139     // context of the async fopen operation
140     AsyncIOContext* asyncopencontext;
141 
142     // timestamp of the start of the transfer
143     m_time_t lastaccesstime;
144 
145     // priority of the transfer
146     uint64_t priority;
147 
148     // state of the transfer
149     transferstate_t state;
150 
151     bool skipserialization;
152 
153     Transfer(MegaClient*, direction_t);
154     virtual ~Transfer();
155 
156     // serialize the Transfer object
157     bool serialize(string*) override;
158 
159     // unserialize a Transfer and add it to the transfer map
160     static Transfer* unserialize(MegaClient *, string*, transfer_map *);
161 
162     // examine a file on disk for video/audio attributes to attach to the file, on upload/download
163     void addAnyMissingMediaFileAttributes(Node* node, LocalPath& localpath);
164 
165     // whether the Transfer needs to remove itself from the list it's in (for quick shutdown we can skip)
166     bool mOptimizedDelete = false;
167 };
168 
169 
170 struct LazyEraseTransferPtr
171 {
172     // This class enables us to relatively quickly and efficiently delete many items from the middle of std::deque
173     // By being the class actualy stored in a mega::deque_with_lazy_bulk_erase.
174     // Such builk deletion is done by marking the ones to delete, and finally performing those as a single remove_if.
175     Transfer* transfer;
176     uint64_t preErasurePriority = 0;
177     bool erased = false;
178 
LazyEraseTransferPtrLazyEraseTransferPtr179     explicit LazyEraseTransferPtr(Transfer* t) : transfer(t) {}
180     operator Transfer*&() { return transfer; }
eraseLazyEraseTransferPtr181     void erase() { preErasurePriority = transfer->priority; transfer = nullptr; erased = true; }
isErasedLazyEraseTransferPtr182     bool isErased() const { return erased; }
183     bool operator==(const LazyEraseTransferPtr& e) { return transfer && transfer == e.transfer; }
184 };
185 
186 class MEGA_API TransferList
187 {
188 public:
189     static const uint64_t PRIORITY_START = 0x0000800000000000ull;
190     static const uint64_t PRIORITY_STEP  = 0x0000000000010000ull;
191 
192     typedef deque_with_lazy_bulk_erase<Transfer*, LazyEraseTransferPtr> transfer_list;
193 
194     TransferList();
195     void addtransfer(Transfer* transfer, DBTableTransactionCommitter&, bool startFirst = false);
196     void removetransfer(Transfer *transfer);
197     void movetransfer(Transfer *transfer, Transfer *prevTransfer, DBTableTransactionCommitter& committer);
198     void movetransfer(Transfer *transfer, unsigned int position, DBTableTransactionCommitter& committer);
199     void movetransfer(Transfer *transfer, transfer_list::iterator dstit, DBTableTransactionCommitter&);
200     void movetransfer(transfer_list::iterator it, transfer_list::iterator dstit, DBTableTransactionCommitter&);
201     void movetofirst(Transfer *transfer, DBTableTransactionCommitter& committer);
202     void movetofirst(transfer_list::iterator it, DBTableTransactionCommitter& committer);
203     void movetolast(Transfer *transfer, DBTableTransactionCommitter& committer);
204     void movetolast(transfer_list::iterator it, DBTableTransactionCommitter& committer);
205     void moveup(Transfer *transfer, DBTableTransactionCommitter& committer);
206     void moveup(transfer_list::iterator it, DBTableTransactionCommitter& committer);
207     void movedown(Transfer *transfer, DBTableTransactionCommitter& committer);
208     void movedown(transfer_list::iterator it, DBTableTransactionCommitter& committer);
209     error pause(Transfer *transfer, bool enable, DBTableTransactionCommitter& committer);
210     transfer_list::iterator begin(direction_t direction);
211     transfer_list::iterator end(direction_t direction);
212     bool getIterator(Transfer *transfer, transfer_list::iterator&, bool canHandleErasedElements = false);
213     std::array<vector<Transfer*>, 6> nexttransfers(std::function<bool(Transfer*)>& continuefunction);
214     Transfer *transferat(direction_t direction, unsigned int position);
215 
216     std::array<transfer_list, 2> transfers;
217     MegaClient *client;
218     uint64_t currentpriority;
219 
220 private:
221     void prepareIncreasePriority(Transfer *transfer, transfer_list::iterator srcit, transfer_list::iterator dstit, DBTableTransactionCommitter& committer);
222     void prepareDecreasePriority(Transfer *transfer, transfer_list::iterator it, transfer_list::iterator dstit);
223     bool isReady(Transfer *transfer);
224 };
225 
226 struct MEGA_API DirectReadSlot
227 {
228     m_off_t pos;
229 
230     // values to calculate the transfer speed
231     static const int MEAN_SPEED_INTERVAL_DS = 100;
232     static const int MIN_BYTES_PER_SECOND = 1024 * 15;
233     static const int TIMEOUT_DS = 100;
234     static const int TEMPURL_TIMEOUT_DS = 3000;
235 
236     DirectRead* dr;
237     std::vector<HttpReq*> reqs;
238 
239     drs_list::iterator drs_it;
240     SpeedController speedController;
241     m_off_t speed;
242     m_off_t meanSpeed;
243 
244     bool doio();
245 
246     DirectReadSlot(DirectRead*);
247     ~DirectReadSlot();
248 
249 private:
250     std::string adjustURLPort(std::string url);
251     bool processAnyOutputPieces();
252 };
253 
254 struct MEGA_API DirectRead
255 {
256     m_off_t count;
257     m_off_t offset;
258     m_off_t progress;
259     m_off_t nextrequestpos;
260 
261     DirectReadBufferManager drbuf;
262 
263     DirectReadNode* drn;
264     DirectReadSlot* drs;
265 
266     dr_list::iterator reads_it;
267     dr_list::iterator drq_it;
268 
269     void* appdata;
270 
271     int reqtag;
272 
273     void abort();
274 
275     DirectRead(DirectReadNode*, m_off_t, m_off_t, int, void*);
276     ~DirectRead();
277 };
278 
279 struct MEGA_API DirectReadNode
280 {
281     handle h;
282     bool p;
283     string publicauth;
284     string privateauth;
285     string chatauth;
286     m_off_t partiallen;
287     dstime partialstarttime;
288 
289     std::vector<std::string> tempurls;
290 
291     m_off_t size;
292 
293     class CommandDirectRead* pendingcmd;
294 
295     int retries;
296 
297     int64_t ctriv;
298     SymmCipher symmcipher;
299 
300     dr_list reads;
301 
302     MegaClient* client;
303 
304     handledrn_map::iterator hdrn_it;
305     dsdrn_map::iterator dsdrn_it;
306 
307     // API command result
308     void cmdresult(const Error&, dstime = 0);
309 
310     // enqueue new read
311     void enqueue(m_off_t, m_off_t, int, void*);
312 
313     // dispatch all reads
314     void dispatch();
315 
316     // schedule next event
317     void schedule(dstime);
318 
319     // report failure to app and abort or retry all reads
320     void retry(const Error &, dstime = 0);
321 
322     DirectReadNode(MegaClient*, handle, bool, SymmCipher*, int64_t, const char*, const char*, const char*);
323     ~DirectReadNode();
324 };
325 } // namespace
326 
327 #endif
328