RequestGroup.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program 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. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #include "RequestGroup.h"
  36. #include <cassert>
  37. #include <algorithm>
  38. #include "PostDownloadHandler.h"
  39. #include "DownloadEngine.h"
  40. #include "DefaultSegmentManFactory.h"
  41. #include "SegmentMan.h"
  42. #include "NullProgressInfoFile.h"
  43. #include "Dependency.h"
  44. #include "prefs.h"
  45. #include "InitiateConnectionCommandFactory.h"
  46. #include "File.h"
  47. #include "message.h"
  48. #include "Util.h"
  49. #include "BtRegistry.h"
  50. #include "LogFactory.h"
  51. #include "Logger.h"
  52. #include "DiskAdaptor.h"
  53. #include "DiskWriterFactory.h"
  54. #include "RecoverableException.h"
  55. #include "StreamCheckIntegrityEntry.h"
  56. #include "CheckIntegrityCommand.h"
  57. #include "UnknownLengthPieceStorage.h"
  58. #include "BtContext.h"
  59. #include "SingleFileDownloadContext.h"
  60. #include "DlAbortEx.h"
  61. #include "DownloadFailureException.h"
  62. #include "RequestGroupMan.h"
  63. #include "DefaultBtProgressInfoFile.h"
  64. #include "DefaultPieceStorage.h"
  65. #include "DownloadResult.h"
  66. #include "DownloadHandlerFactory.h"
  67. #include "MemoryBufferPreDownloadHandler.h"
  68. #include "DownloadHandlerConstants.h"
  69. #include "ServerHost.h"
  70. #include "Option.h"
  71. #include "FileEntry.h"
  72. #include "Request.h"
  73. #include "FileAllocationIterator.h"
  74. #include "StringFormat.h"
  75. #include "A2STR.h"
  76. #include "URISelector.h"
  77. #include "InOrderURISelector.h"
  78. #ifdef ENABLE_MESSAGE_DIGEST
  79. # include "CheckIntegrityCommand.h"
  80. #endif // ENABLE_MESSAGE_DIGEST
  81. #ifdef ENABLE_BITTORRENT
  82. # include "BtCheckIntegrityEntry.h"
  83. # include "DefaultPeerStorage.h"
  84. # include "DefaultBtAnnounce.h"
  85. # include "BtRuntime.h"
  86. # include "BtSetup.h"
  87. # include "BtFileAllocationEntry.h"
  88. # include "BtPostDownloadHandler.h"
  89. # include "DHTSetup.h"
  90. # include "DHTRegistry.h"
  91. # include "BtMessageFactory.h"
  92. # include "BtRequestFactory.h"
  93. # include "BtMessageDispatcher.h"
  94. # include "BtMessageReceiver.h"
  95. # include "PeerConnection.h"
  96. # include "ExtensionMessageFactory.h"
  97. # include "DHTPeerAnnounceStorage.h"
  98. # include "DHTEntryPointNameResolveCommand.h"
  99. #endif // ENABLE_BITTORRENT
  100. #ifdef ENABLE_METALINK
  101. # include "MetalinkPostDownloadHandler.h"
  102. #endif // ENABLE_METALINK
  103. namespace aria2 {
  104. int32_t RequestGroup::_gidCounter = 0;
  105. const std::string RequestGroup::ACCEPT_METALINK = "application/metalink+xml";
  106. RequestGroup::RequestGroup(const Option* option,
  107. const std::deque<std::string>& uris):
  108. _gid(++_gidCounter),
  109. _uris(uris),
  110. _numConcurrentCommand(option->getAsInt(PREF_SPLIT)),
  111. _numStreamConnection(0),
  112. _numCommand(0),
  113. _segmentManFactory(new DefaultSegmentManFactory(option)),
  114. _progressInfoFile(new NullProgressInfoFile()),
  115. _preLocalFileCheckEnabled(true),
  116. _haltRequested(false),
  117. _forceHaltRequested(false),
  118. _singleHostMultiConnectionEnabled(true),
  119. _uriSelector(new InOrderURISelector()),
  120. _lastModifiedTime(Time::null()),
  121. _fileNotFoundCount(0),
  122. _inMemoryDownload(false),
  123. _option(option),
  124. _logger(LogFactory::getInstance())
  125. {
  126. if(_option->get(PREF_FILE_ALLOCATION) == V_PREALLOC) {
  127. _fileAllocationEnabled = true;
  128. } else {
  129. _fileAllocationEnabled = false;
  130. }
  131. // Add types to be sent as a Accept header value here.
  132. // It would be good to put this value in Option so that user can tweak
  133. // and add this list.
  134. // ACCEPT_METALINK is used for `transparent metalink'.
  135. addAcceptType(ACCEPT_METALINK);
  136. initializePreDownloadHandler();
  137. initializePostDownloadHandler();
  138. }
  139. RequestGroup::~RequestGroup() {}
  140. SegmentManHandle RequestGroup::initSegmentMan()
  141. {
  142. _segmentMan = _segmentManFactory->createNewInstance(_downloadContext,
  143. _pieceStorage);
  144. return _segmentMan;
  145. }
  146. bool RequestGroup::downloadFinished() const
  147. {
  148. if(_pieceStorage.isNull()) {
  149. return false;
  150. } else {
  151. return _pieceStorage->downloadFinished();
  152. }
  153. }
  154. bool RequestGroup::allDownloadFinished() const
  155. {
  156. if(_pieceStorage.isNull()) {
  157. return false;
  158. } else {
  159. return _pieceStorage->allDownloadFinished();
  160. }
  161. }
  162. void RequestGroup::closeFile()
  163. {
  164. if(!_pieceStorage.isNull()) {
  165. _pieceStorage->getDiskAdaptor()->closeFile();
  166. }
  167. }
  168. void RequestGroup::createInitialCommand(std::deque<Command*>& commands,
  169. DownloadEngine* e)
  170. {
  171. #ifdef ENABLE_BITTORRENT
  172. {
  173. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  174. if(!btContext.isNull()) {
  175. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  176. throw DownloadFailureException
  177. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  178. getFilePath().c_str()).str());
  179. }
  180. initPieceStorage();
  181. if(btContext->getFileEntries().size() > 1) {
  182. // this is really multi file torrent.
  183. // clear http/ftp uris because the current implementation does not
  184. // allow integrating multi-file torrent and http/ftp.
  185. _logger->debug("Clearing http/ftp URIs because the current implementation does not allow integrating multi-file torrent and http/ftp.");
  186. _uris.clear();
  187. _pieceStorage->setFileFilter(Util::parseIntRange(_option->get(PREF_SELECT_FILE)));
  188. }
  189. SharedHandle<DefaultBtProgressInfoFile>
  190. progressInfoFile(new DefaultBtProgressInfoFile(_downloadContext,
  191. _pieceStorage,
  192. _option));
  193. SharedHandle<BtRegistry> btRegistry = e->getBtRegistry();
  194. btRegistry->registerBtContext(btContext->getInfoHashAsString(),
  195. btContext);
  196. btRegistry->registerPieceStorage(btContext->getInfoHashAsString(),
  197. _pieceStorage);
  198. btRegistry->registerBtProgressInfoFile(btContext->getInfoHashAsString(),
  199. progressInfoFile);
  200. BtRuntimeHandle btRuntime(new BtRuntime());
  201. btRuntime->setListenPort(_option->getAsInt(PREF_LISTEN_PORT));
  202. btRegistry->registerBtRuntime(btContext->getInfoHashAsString(),
  203. btRuntime);
  204. _btRuntime = btRuntime;
  205. progressInfoFile->setBtRuntime(btRuntime);
  206. SharedHandle<DefaultPeerStorage> peerStorage
  207. (new DefaultPeerStorage(btContext, _option));
  208. peerStorage->setBtRuntime(btRuntime);
  209. peerStorage->setPieceStorage(_pieceStorage);
  210. btRegistry->registerPeerStorage(btContext->getInfoHashAsString(),
  211. peerStorage);
  212. _peerStorage = peerStorage;
  213. progressInfoFile->setPeerStorage(peerStorage);
  214. SharedHandle<DefaultBtAnnounce> btAnnounce
  215. (new DefaultBtAnnounce(btContext, _option));
  216. btAnnounce->setBtRuntime(btRuntime);
  217. btAnnounce->setPieceStorage(_pieceStorage);
  218. btAnnounce->setPeerStorage(peerStorage);
  219. btRegistry->registerBtAnnounce(btContext->getInfoHashAsString(),
  220. btAnnounce);
  221. btAnnounce->shuffleAnnounce();
  222. // Remove the control file if download file doesn't exist
  223. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  224. progressInfoFile->removeFile();
  225. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  226. progressInfoFile->getFilename().c_str(),
  227. _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
  228. }
  229. // Call Load, Save and file allocation command here
  230. if(progressInfoFile->exists()) {
  231. // load .aria2 file if it exists.
  232. progressInfoFile->load();
  233. _pieceStorage->getDiskAdaptor()->openFile();
  234. } else {
  235. if(_pieceStorage->getDiskAdaptor()->fileExists()) {
  236. if(!_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  237. !_option->getAsBool(PREF_ALLOW_OVERWRITE) &&
  238. !_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  239. // TODO we need this->haltRequested = true?
  240. throw DownloadFailureException
  241. (StringFormat
  242. (MSG_FILE_ALREADY_EXISTS,
  243. _pieceStorage->getDiskAdaptor()->getFilePath().c_str()).str());
  244. } else {
  245. _pieceStorage->getDiskAdaptor()->openFile();
  246. }
  247. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED)) {
  248. _pieceStorage->markAllPiecesDone();
  249. }
  250. } else {
  251. _pieceStorage->getDiskAdaptor()->openFile();
  252. }
  253. }
  254. _progressInfoFile = progressInfoFile;
  255. if(!btContext->isPrivate() && _option->getAsBool(PREF_ENABLE_DHT)) {
  256. std::deque<Command*> commands;
  257. DHTSetup().setup(commands, e, _option);
  258. e->addCommand(commands);
  259. if(!btContext->getNodes().empty() && DHTSetup::initialized()) {
  260. DHTEntryPointNameResolveCommand* command =
  261. new DHTEntryPointNameResolveCommand(e->newCUID(), e,
  262. btContext->getNodes());
  263. command->setTaskQueue(DHTRegistry::_taskQueue);
  264. command->setTaskFactory(DHTRegistry::_taskFactory);
  265. command->setRoutingTable(DHTRegistry::_routingTable);
  266. command->setLocalNode(DHTRegistry::_localNode);
  267. e->commands.push_back(command);
  268. }
  269. }
  270. CheckIntegrityEntryHandle entry(new BtCheckIntegrityEntry(this));
  271. // --bt-seed-unverified=true is given and download has completed, skip
  272. // validation for piece hashes.
  273. if(_option->getAsBool(PREF_BT_SEED_UNVERIFIED) &&
  274. _pieceStorage->downloadFinished()) {
  275. entry->onDownloadFinished(commands, e);
  276. } else {
  277. processCheckIntegrityEntry(commands, entry, e);
  278. }
  279. return;
  280. }
  281. }
  282. #endif // ENABLE_BITTORRENT
  283. // TODO I assume here when totallength is set to DownloadContext and it is
  284. // not 0, then filepath is also set DownloadContext correctly....
  285. if(_downloadContext->getTotalLength() == 0) {
  286. createNextCommand(commands, e, 1);
  287. }else {
  288. if(e->_requestGroupMan->isSameFileBeingDownloaded(this)) {
  289. throw DownloadFailureException
  290. (StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
  291. getFilePath().c_str()).str());
  292. }
  293. initPieceStorage();
  294. BtProgressInfoFileHandle infoFile
  295. (new DefaultBtProgressInfoFile(_downloadContext, _pieceStorage, _option));
  296. if(infoFile->exists() || !downloadFinishedByFileLength()) {
  297. loadAndOpenFile(infoFile);
  298. SharedHandle<CheckIntegrityEntry> checkIntegrityEntry
  299. (new StreamCheckIntegrityEntry(SharedHandle<Request>(), this));
  300. processCheckIntegrityEntry(commands, checkIntegrityEntry, e);
  301. }
  302. }
  303. }
  304. void RequestGroup::processCheckIntegrityEntry(std::deque<Command*>& commands,
  305. const CheckIntegrityEntryHandle& entry,
  306. DownloadEngine* e)
  307. {
  308. #ifdef ENABLE_MESSAGE_DIGEST
  309. if(e->option->getAsBool(PREF_CHECK_INTEGRITY) &&
  310. entry->isValidationReady()) {
  311. entry->initValidator();
  312. entry->cutTrailingGarbage();
  313. CheckIntegrityCommand* command =
  314. new CheckIntegrityCommand(e->newCUID(), this, e, entry);
  315. commands.push_back(command);
  316. } else
  317. #endif // ENABLE_MESSAGE_DIGEST
  318. {
  319. entry->onDownloadIncomplete(commands, e);
  320. }
  321. }
  322. void RequestGroup::initPieceStorage()
  323. {
  324. if(_downloadContext->getTotalLength() == 0) {
  325. UnknownLengthPieceStorageHandle ps(new UnknownLengthPieceStorage(_downloadContext, _option));
  326. if(!_diskWriterFactory.isNull()) {
  327. ps->setDiskWriterFactory(_diskWriterFactory);
  328. }
  329. _pieceStorage = ps;
  330. } else {
  331. DefaultPieceStorageHandle ps(new DefaultPieceStorage(_downloadContext, _option));
  332. if(!_diskWriterFactory.isNull()) {
  333. ps->setDiskWriterFactory(_diskWriterFactory);
  334. }
  335. _pieceStorage = ps;
  336. }
  337. _pieceStorage->initStorage();
  338. initSegmentMan();
  339. }
  340. bool RequestGroup::downloadFinishedByFileLength()
  341. {
  342. // assuming that a control file doesn't exist.
  343. if(!isPreLocalFileCheckEnabled() ||
  344. _option->getAsBool(PREF_ALLOW_OVERWRITE) ||
  345. (_option->getAsBool(PREF_CHECK_INTEGRITY) &&
  346. !_downloadContext->getPieceHashes().empty())) {
  347. return false;
  348. }
  349. // TODO consider the case when the getFilePath() returns dir path.
  350. File outfile(getFilePath());
  351. if(outfile.exists() && getTotalLength() == outfile.size()) {
  352. _pieceStorage->markAllPiecesDone();
  353. _logger->notice(MSG_DOWNLOAD_ALREADY_COMPLETED, _gid, getFilePath().c_str());
  354. return true;
  355. } else {
  356. return false;
  357. }
  358. }
  359. void RequestGroup::loadAndOpenFile(const BtProgressInfoFileHandle& progressInfoFile)
  360. {
  361. try {
  362. if(!isPreLocalFileCheckEnabled()) {
  363. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  364. return;
  365. }
  366. // Remove the control file if download file doesn't exist
  367. if(progressInfoFile->exists() && !_pieceStorage->getDiskAdaptor()->fileExists()) {
  368. progressInfoFile->removeFile();
  369. _logger->notice(MSG_REMOVED_DEFUNCT_CONTROL_FILE,
  370. progressInfoFile->getFilename().c_str(),
  371. _pieceStorage->getDiskAdaptor()->getFilePath().c_str());
  372. }
  373. while(1) {
  374. if(progressInfoFile->exists()) {
  375. progressInfoFile->load();
  376. _pieceStorage->getDiskAdaptor()->openExistingFile();
  377. } else {
  378. File outfile(getFilePath());
  379. if(outfile.exists() && _option->getAsBool(PREF_CONTINUE)) {
  380. if(getTotalLength() < outfile.size()) {
  381. throw DlAbortEx
  382. (StringFormat(EX_FILE_LENGTH_MISMATCH_BETWEEN_LOCAL_AND_REMOTE,
  383. getFilePath().c_str(),
  384. Util::itos(outfile.size()).c_str(),
  385. Util::itos(getTotalLength()).c_str()).str());
  386. }
  387. _pieceStorage->getDiskAdaptor()->openExistingFile();
  388. _pieceStorage->markPiecesDone(outfile.size());
  389. } else {
  390. #ifdef ENABLE_MESSAGE_DIGEST
  391. if(outfile.exists() && _option->getAsBool(PREF_CHECK_INTEGRITY)) {
  392. _pieceStorage->getDiskAdaptor()->openExistingFile();
  393. } else {
  394. #endif // ENABLE_MESSAGE_DIGEST
  395. shouldCancelDownloadForSafety();
  396. // call updateFilename here in case when filename is renamed
  397. // by tryAutoFileRenaming()
  398. progressInfoFile->updateFilename();
  399. if(progressInfoFile->exists()) {
  400. // Close DiskAdaptor here. Renmaed file will be opened in the
  401. // next loop .
  402. _pieceStorage->getDiskAdaptor()->closeFile();
  403. continue;
  404. }
  405. _pieceStorage->getDiskAdaptor()->initAndOpenFile();
  406. #ifdef ENABLE_MESSAGE_DIGEST
  407. }
  408. #endif // ENABLE_MESSAGE_DIGEST
  409. }
  410. }
  411. setProgressInfoFile(progressInfoFile);
  412. break;
  413. }
  414. } catch(RecoverableException& e) {
  415. throw DownloadFailureException
  416. (StringFormat(EX_DOWNLOAD_ABORTED).str(), e);
  417. }
  418. }
  419. // assuming that a control file does not exist
  420. void RequestGroup::shouldCancelDownloadForSafety()
  421. {
  422. if(_option->getAsBool(PREF_ALLOW_OVERWRITE)) {
  423. return;
  424. }
  425. File outfile(getFilePath());
  426. if(outfile.exists()) {
  427. if(_option->getAsBool(PREF_AUTO_FILE_RENAMING)) {
  428. if(tryAutoFileRenaming()) {
  429. _logger->notice(MSG_FILE_RENAMED, getFilePath().c_str());
  430. } else {
  431. throw DownloadFailureException
  432. (StringFormat("File renaming failed: %s",
  433. getFilePath().c_str()).str());
  434. }
  435. } else {
  436. throw DownloadFailureException
  437. (StringFormat(MSG_FILE_ALREADY_EXISTS,
  438. getFilePath().c_str()).str());
  439. }
  440. }
  441. }
  442. bool RequestGroup::tryAutoFileRenaming()
  443. {
  444. std::string filepath = getFilePath();
  445. if(filepath.empty()) {
  446. return false;
  447. }
  448. SingleFileDownloadContextHandle ctx =
  449. dynamic_pointer_cast<SingleFileDownloadContext>(_downloadContext);
  450. // Make a copy of ctx.
  451. SingleFileDownloadContextHandle tempCtx(new SingleFileDownloadContext(*ctx.get()));
  452. DefaultBtProgressInfoFile tempInfoFile(tempCtx, SharedHandle<PieceStorage>(), 0);
  453. for(unsigned int i = 1; i < 10000; ++i) {
  454. File newfile(filepath+"."+Util::uitos(i));
  455. std::string newFilename = newfile.getBasename();
  456. tempCtx->setUFilename(newFilename);
  457. tempInfoFile.updateFilename();
  458. if(!newfile.exists() || (newfile.exists() && tempInfoFile.exists())) {
  459. ctx->setUFilename(newFilename);
  460. return true;
  461. }
  462. }
  463. return false;
  464. }
  465. void RequestGroup::createNextCommandWithAdj(std::deque<Command*>& commands,
  466. DownloadEngine* e, int numAdj)
  467. {
  468. int numCommand;
  469. if(getTotalLength() == 0) {
  470. numCommand = 1+numAdj;
  471. } else {
  472. if(_numConcurrentCommand == 0) {
  473. // TODO remove _uris.size() support
  474. numCommand = _uris.size();
  475. } else {
  476. numCommand = _numConcurrentCommand;
  477. }
  478. numCommand = std::min(static_cast<int>(_downloadContext->getNumPieces()),
  479. numCommand);
  480. numCommand += numAdj;
  481. }
  482. if(numCommand > 0) {
  483. createNextCommand(commands, e, numCommand);
  484. }
  485. }
  486. void RequestGroup::createNextCommand(std::deque<Command*>& commands,
  487. DownloadEngine* e,
  488. unsigned int numCommand,
  489. const std::string& method)
  490. {
  491. std::deque<std::string> pendingURIs;
  492. for(; !_uris.empty() && numCommand--; ) {
  493. std::string uri = _uriSelector->select(_uris);
  494. RequestHandle req(new Request());
  495. if(req->setUrl(uri)) {
  496. ServerHostHandle sv;
  497. if(!_singleHostMultiConnectionEnabled){
  498. sv = searchServerHost(req->getHost());
  499. }
  500. if(sv.isNull()) {
  501. _spentUris.push_back(uri);
  502. req->setReferer(_option->get(PREF_REFERER));
  503. req->setMethod(method);
  504. Command* command =
  505. InitiateConnectionCommandFactory::createInitiateConnectionCommand
  506. (e->newCUID(), req, this, e);
  507. ServerHostHandle sv(new ServerHost(command->getCuid(), req->getHost()));
  508. registerServerHost(sv);
  509. // give a chance to be executed in the next loop in DownloadEngine
  510. command->setStatus(Command::STATUS_ONESHOT_REALTIME);
  511. commands.push_back(command);
  512. } else {
  513. pendingURIs.push_back(uri);
  514. }
  515. } else {
  516. _logger->error(MSG_UNRECOGNIZED_URI, req->getUrl().c_str());
  517. }
  518. }
  519. _uris.insert(_uris.begin(), pendingURIs.begin(), pendingURIs.end());
  520. }
  521. std::string RequestGroup::getFilePath() const
  522. {
  523. assert(!_downloadContext.isNull());
  524. if(inMemoryDownload()) {
  525. static const std::string DIR_MEMORY("[MEMORY]");
  526. return DIR_MEMORY+File(_downloadContext->getActualBasePath()).getBasename();
  527. } else {
  528. return _downloadContext->getActualBasePath();
  529. }
  530. }
  531. uint64_t RequestGroup::getTotalLength() const
  532. {
  533. if(_pieceStorage.isNull()) {
  534. return 0;
  535. } else {
  536. if(_pieceStorage->isSelectiveDownloadingMode()) {
  537. return _pieceStorage->getFilteredTotalLength();
  538. } else {
  539. return _pieceStorage->getTotalLength();
  540. }
  541. }
  542. }
  543. uint64_t RequestGroup::getCompletedLength() const
  544. {
  545. if(_pieceStorage.isNull()) {
  546. return 0;
  547. } else {
  548. if(_pieceStorage->isSelectiveDownloadingMode()) {
  549. return _pieceStorage->getFilteredCompletedLength();
  550. } else {
  551. return _pieceStorage->getCompletedLength();
  552. }
  553. }
  554. }
  555. void RequestGroup::validateFilename(const std::string& expectedFilename,
  556. const std::string& actualFilename) const
  557. {
  558. if(expectedFilename.empty()) {
  559. return;
  560. }
  561. if(expectedFilename != actualFilename) {
  562. throw DlAbortEx(StringFormat(EX_FILENAME_MISMATCH,
  563. expectedFilename.c_str(),
  564. actualFilename.c_str()).str());
  565. }
  566. }
  567. void RequestGroup::validateTotalLength(uint64_t expectedTotalLength,
  568. uint64_t actualTotalLength) const
  569. {
  570. if(expectedTotalLength <= 0) {
  571. return;
  572. }
  573. if(expectedTotalLength != actualTotalLength) {
  574. throw DlAbortEx
  575. (StringFormat(EX_SIZE_MISMATCH,
  576. Util::itos(expectedTotalLength, true).c_str(),
  577. Util::itos(actualTotalLength, true).c_str()).str());
  578. }
  579. }
  580. void RequestGroup::validateFilename(const std::string& actualFilename) const
  581. {
  582. validateFilename(_downloadContext->getFileEntries().front()->getBasename(), actualFilename);
  583. }
  584. void RequestGroup::validateTotalLength(uint64_t actualTotalLength) const
  585. {
  586. validateTotalLength(getTotalLength(), actualTotalLength);
  587. }
  588. void RequestGroup::increaseStreamConnection()
  589. {
  590. ++_numStreamConnection;
  591. }
  592. void RequestGroup::decreaseStreamConnection()
  593. {
  594. --_numStreamConnection;
  595. }
  596. unsigned int RequestGroup::getNumConnection() const
  597. {
  598. unsigned int numConnection = _numStreamConnection;
  599. #ifdef ENABLE_BITTORRENT
  600. if(!_btRuntime.isNull()) {
  601. numConnection += _btRuntime->getConnections();
  602. }
  603. #endif // ENABLE_BITTORRENT
  604. return numConnection;
  605. }
  606. void RequestGroup::increaseNumCommand()
  607. {
  608. ++_numCommand;
  609. }
  610. void RequestGroup::decreaseNumCommand()
  611. {
  612. --_numCommand;
  613. }
  614. TransferStat RequestGroup::calculateStat()
  615. {
  616. TransferStat stat;
  617. #ifdef ENABLE_BITTORRENT
  618. if(!_peerStorage.isNull()) {
  619. stat = _peerStorage->calculateStat();
  620. }
  621. #endif // ENABLE_BITTORRENT
  622. if(!_segmentMan.isNull()) {
  623. stat.setDownloadSpeed(stat.getDownloadSpeed()+_segmentMan->calculateDownloadSpeed());
  624. }
  625. return stat;
  626. }
  627. void RequestGroup::setHaltRequested(bool f)
  628. {
  629. _haltRequested = f;
  630. #ifdef ENABLE_BITTORRENT
  631. if(!_btRuntime.isNull()) {
  632. _btRuntime->setHalt(f);
  633. }
  634. #endif // ENABLE_BITTORRENT
  635. }
  636. void RequestGroup::setForceHaltRequested(bool f)
  637. {
  638. setHaltRequested(f);
  639. _forceHaltRequested = f;
  640. }
  641. void RequestGroup::releaseRuntimeResource(DownloadEngine* e)
  642. {
  643. #ifdef ENABLE_BITTORRENT
  644. BtContextHandle btContext = dynamic_pointer_cast<BtContext>(_downloadContext);
  645. if(!btContext.isNull()) {
  646. SharedHandle<BtRegistry> btRegistry = e->getBtRegistry();
  647. BtContextHandle btContextInReg =
  648. btRegistry->getBtContext(btContext->getInfoHashAsString());
  649. if(!btContextInReg.isNull() &&
  650. btContextInReg->getOwnerRequestGroup()->getGID() ==
  651. btContext->getOwnerRequestGroup()->getGID()) {
  652. btRegistry->unregister(btContext->getInfoHashAsString());
  653. if(!DHTRegistry::_peerAnnounceStorage.isNull()) {
  654. DHTRegistry::_peerAnnounceStorage->
  655. removeLocalPeerAnnounce(btContext->getInfoHash());
  656. }
  657. }
  658. }
  659. #endif // ENABLE_BITTORRENT
  660. if(!_pieceStorage.isNull()) {
  661. _pieceStorage->removeAdvertisedPiece(0);
  662. }
  663. }
  664. void RequestGroup::preDownloadProcessing()
  665. {
  666. _logger->debug("Finding PreDownloadHandler for path %s.", getFilePath().c_str());
  667. try {
  668. for(PreDownloadHandlers::const_iterator itr = _preDownloadHandlers.begin();
  669. itr != _preDownloadHandlers.end(); ++itr) {
  670. if((*itr)->canHandle(this)) {
  671. (*itr)->execute(this);
  672. return;
  673. }
  674. }
  675. } catch(RecoverableException& ex) {
  676. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  677. return;
  678. }
  679. _logger->debug("No PreDownloadHandler found.");
  680. return;
  681. }
  682. void RequestGroup::postDownloadProcessing
  683. (std::deque<SharedHandle<RequestGroup> >& groups)
  684. {
  685. _logger->debug("Finding PostDownloadHandler for path %s.", getFilePath().c_str());
  686. try {
  687. for(PostDownloadHandlers::const_iterator itr = _postDownloadHandlers.begin();
  688. itr != _postDownloadHandlers.end(); ++itr) {
  689. if((*itr)->canHandle(this)) {
  690. (*itr)->getNextRequestGroups(groups, this);
  691. return;
  692. }
  693. }
  694. } catch(RecoverableException& ex) {
  695. _logger->error(EX_EXCEPTION_CAUGHT, ex);
  696. }
  697. _logger->debug("No PostDownloadHandler found.");
  698. }
  699. void RequestGroup::initializePreDownloadHandler()
  700. {
  701. #ifdef ENABLE_BITTORRENT
  702. if(_option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  703. _preDownloadHandlers.push_back(DownloadHandlerFactory::getBtPreDownloadHandler());
  704. }
  705. #endif // ENABLE_BITTORRENT
  706. #ifdef ENABLE_METALINK
  707. if(_option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  708. _preDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPreDownloadHandler());
  709. }
  710. #endif // ENABLE_METALINK
  711. }
  712. void RequestGroup::initializePostDownloadHandler()
  713. {
  714. #ifdef ENABLE_BITTORRENT
  715. if(_option->getAsBool(PREF_FOLLOW_TORRENT) ||
  716. _option->get(PREF_FOLLOW_TORRENT) == V_MEM) {
  717. _postDownloadHandlers.push_back(DownloadHandlerFactory::getBtPostDownloadHandler());
  718. }
  719. #endif // ENABLE_BITTORRENT
  720. #ifdef ENABLE_METALINK
  721. if(_option->getAsBool(PREF_FOLLOW_METALINK) ||
  722. _option->get(PREF_FOLLOW_METALINK) == V_MEM) {
  723. _postDownloadHandlers.push_back(DownloadHandlerFactory::getMetalinkPostDownloadHandler());
  724. }
  725. #endif // ENABLE_METALINK
  726. }
  727. void RequestGroup::getURIs(std::deque<std::string>& uris) const
  728. {
  729. uris.insert(uris.end(), _spentUris.begin(), _spentUris.end());
  730. uris.insert(uris.end(), _uris.begin(), _uris.end());
  731. }
  732. bool RequestGroup::isDependencyResolved()
  733. {
  734. if(_dependency.isNull()) {
  735. return true;
  736. }
  737. return _dependency->resolve();
  738. }
  739. void RequestGroup::setSegmentManFactory(const SegmentManFactoryHandle& segmentManFactory)
  740. {
  741. _segmentManFactory = segmentManFactory;
  742. }
  743. void RequestGroup::dependsOn(const DependencyHandle& dep)
  744. {
  745. _dependency = dep;
  746. }
  747. void RequestGroup::setDiskWriterFactory(const DiskWriterFactoryHandle& diskWriterFactory)
  748. {
  749. _diskWriterFactory = diskWriterFactory;
  750. }
  751. DiskWriterFactoryHandle RequestGroup::getDiskWriterFactory() const
  752. {
  753. return _diskWriterFactory;
  754. }
  755. void RequestGroup::addPostDownloadHandler(const PostDownloadHandlerHandle& handler)
  756. {
  757. _postDownloadHandlers.push_back(handler);
  758. }
  759. void RequestGroup::addPreDownloadHandler(const PreDownloadHandlerHandle& handler)
  760. {
  761. _preDownloadHandlers.push_back(handler);
  762. }
  763. void RequestGroup::clearPostDowloadHandler()
  764. {
  765. _postDownloadHandlers.clear();
  766. }
  767. void RequestGroup::clearPreDowloadHandler()
  768. {
  769. _preDownloadHandlers.clear();
  770. }
  771. SegmentManHandle RequestGroup::getSegmentMan() const
  772. {
  773. return _segmentMan;
  774. }
  775. DownloadContextHandle RequestGroup::getDownloadContext() const
  776. {
  777. return _downloadContext;
  778. }
  779. void RequestGroup::setDownloadContext(const DownloadContextHandle& downloadContext)
  780. {
  781. _downloadContext = downloadContext;
  782. }
  783. PieceStorageHandle RequestGroup::getPieceStorage() const
  784. {
  785. return _pieceStorage;
  786. }
  787. void RequestGroup::setPieceStorage(const PieceStorageHandle& pieceStorage)
  788. {
  789. _pieceStorage = pieceStorage;
  790. }
  791. BtProgressInfoFileHandle RequestGroup::getProgressInfoFile() const
  792. {
  793. return _progressInfoFile;
  794. }
  795. void RequestGroup::setProgressInfoFile(const BtProgressInfoFileHandle& progressInfoFile)
  796. {
  797. _progressInfoFile = progressInfoFile;
  798. }
  799. bool RequestGroup::needsFileAllocation() const
  800. {
  801. return isFileAllocationEnabled() &&
  802. (uint64_t)_option->getAsLLInt(PREF_NO_FILE_ALLOCATION_LIMIT) <= getTotalLength() &&
  803. !_pieceStorage->getDiskAdaptor()->fileAllocationIterator()->finished();
  804. }
  805. DownloadResultHandle RequestGroup::createDownloadResult() const
  806. {
  807. std::deque<std::string> uris;
  808. getURIs(uris);
  809. uint64_t sessionDownloadLength = 0;
  810. #ifdef ENABLE_BITTORRENT
  811. if(!_peerStorage.isNull()) {
  812. sessionDownloadLength =
  813. _peerStorage->calculateStat().getSessionDownloadLength();
  814. } else
  815. #endif // ENABLE_BITTORRENT
  816. if(!_segmentMan.isNull()) {
  817. sessionDownloadLength =
  818. _segmentMan->calculateSessionDownloadLength();
  819. }
  820. return
  821. SharedHandle<DownloadResult>
  822. (new DownloadResult(_gid,
  823. getFilePath(),
  824. getTotalLength(),
  825. uris.empty() ? A2STR::NIL:uris.front(),
  826. uris.size(),
  827. sessionDownloadLength,
  828. _downloadContext->calculateSessionTime(),
  829. downloadFinished()?
  830. DownloadResult::FINISHED :
  831. DownloadResult::NOT_YET));
  832. }
  833. void RequestGroup::registerServerHost(const ServerHostHandle& serverHost)
  834. {
  835. _serverHosts.push_back(serverHost);
  836. }
  837. class FindServerHostByCUID
  838. {
  839. private:
  840. int32_t _cuid;
  841. public:
  842. FindServerHostByCUID(int32_t cuid):_cuid(cuid) {}
  843. bool operator()(const ServerHostHandle& sv) const
  844. {
  845. return sv->getCuid() == _cuid;
  846. }
  847. };
  848. ServerHostHandle RequestGroup::searchServerHost(int32_t cuid) const
  849. {
  850. std::deque<SharedHandle<ServerHost> >::const_iterator itr =
  851. std::find_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByCUID(cuid));
  852. if(itr == _serverHosts.end()) {
  853. return SharedHandle<ServerHost>();
  854. } else {
  855. return *itr;
  856. }
  857. }
  858. class FindServerHostByHostname
  859. {
  860. private:
  861. std::string _hostname;
  862. public:
  863. FindServerHostByHostname(const std::string& hostname):_hostname(hostname) {}
  864. bool operator()(const ServerHostHandle& sv) const
  865. {
  866. return sv->getHostname() == _hostname;
  867. }
  868. };
  869. ServerHostHandle RequestGroup::searchServerHost(const std::string& hostname) const
  870. {
  871. std::deque<SharedHandle<ServerHost> >::const_iterator itr =
  872. std::find_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByHostname(hostname));
  873. if(itr == _serverHosts.end()) {
  874. return SharedHandle<ServerHost>();
  875. } else {
  876. return *itr;
  877. }
  878. }
  879. void RequestGroup::removeServerHost(int32_t cuid)
  880. {
  881. _serverHosts.erase(std::remove_if(_serverHosts.begin(), _serverHosts.end(), FindServerHostByCUID(cuid)), _serverHosts.end());
  882. }
  883. void RequestGroup::removeURIWhoseHostnameIs(const std::string& hostname)
  884. {
  885. std::deque<std::string> newURIs;
  886. Request req;
  887. for(std::deque<std::string>::const_iterator itr = _uris.begin(); itr != _uris.end(); ++itr) {
  888. if(((*itr).find(hostname) == std::string::npos) ||
  889. (req.setUrl(*itr) && (req.getHost() != hostname))) {
  890. newURIs.push_back(*itr);
  891. }
  892. }
  893. _logger->debug("GUID#%d - Removed %d duplicate hostname URIs",
  894. _gid, _uris.size()-newURIs.size());
  895. _uris = newURIs;
  896. }
  897. void RequestGroup::removeIdenticalURI(const std::string& uri)
  898. {
  899. _uris.erase(std::remove(_uris.begin(), _uris.end(), uri), _uris.end());
  900. }
  901. void RequestGroup::reportDownloadFinished()
  902. {
  903. _logger->notice(MSG_FILE_DOWNLOAD_COMPLETED,
  904. getFilePath().c_str());
  905. #ifdef ENABLE_BITTORRENT
  906. SharedHandle<BtContext> ctx = dynamic_pointer_cast<BtContext>(_downloadContext);
  907. if(!ctx.isNull()) {
  908. TransferStat stat = calculateStat();
  909. double shareRatio = ((stat.getAllTimeUploadLength()*10)/getCompletedLength())/10.0;
  910. _logger->notice(MSG_SHARE_RATIO_REPORT,
  911. shareRatio,
  912. Util::abbrevSize(stat.getAllTimeUploadLength()).c_str(),
  913. Util::abbrevSize(getCompletedLength()).c_str());
  914. }
  915. #endif // ENABLE_BITTORRENT
  916. }
  917. const std::deque<std::string>& RequestGroup::getAcceptFeatures() const
  918. {
  919. return _acceptFeatures;
  920. }
  921. void RequestGroup::addAcceptFeatureHeader(const std::string& feature)
  922. {
  923. if(std::find(_acceptFeatures.begin(), _acceptFeatures.end(), feature) == _acceptFeatures.end()) {
  924. _acceptFeatures.push_back(feature);
  925. }
  926. }
  927. void RequestGroup::removeAcceptFeatureHeader(const std::string& feature)
  928. {
  929. std::deque<std::string>::iterator i = std::find(_acceptFeatures.begin(), _acceptFeatures.end(), feature);
  930. if(i != _acceptFeatures.end()) {
  931. _acceptFeatures.erase(i);
  932. }
  933. }
  934. const std::deque<std::string>& RequestGroup::getAcceptTypes() const
  935. {
  936. return _acceptTypes;
  937. }
  938. void RequestGroup::addAcceptType(const std::string& type)
  939. {
  940. if(std::find(_acceptTypes.begin(), _acceptTypes.end(), type) == _acceptTypes.end()) {
  941. _acceptTypes.push_back(type);
  942. }
  943. }
  944. void RequestGroup::removeAcceptType(const std::string& type)
  945. {
  946. _acceptTypes.erase(std::remove(_acceptTypes.begin(), _acceptTypes.end(), type),
  947. _acceptTypes.end());
  948. }
  949. void RequestGroup::setURISelector(const SharedHandle<URISelector>& uriSelector)
  950. {
  951. _uriSelector = uriSelector;
  952. }
  953. void RequestGroup::applyLastModifiedTimeToLocalFiles()
  954. {
  955. if(!_pieceStorage.isNull() && _lastModifiedTime.good()) {
  956. time_t t = _lastModifiedTime.getTime();
  957. _logger->info("Applying Last-Modified time: %s in local time zone",
  958. ctime(&t));
  959. size_t n =
  960. _pieceStorage->getDiskAdaptor()->utime(Time(), _lastModifiedTime);
  961. _logger->info("Last-Modified attrs of %lu files were updated.",
  962. static_cast<unsigned long>(n));
  963. }
  964. }
  965. void RequestGroup::updateLastModifiedTime(const Time& time)
  966. {
  967. if(time.good() && _lastModifiedTime < time) {
  968. _lastModifiedTime = time;
  969. }
  970. }
  971. void RequestGroup::increaseAndValidateFileNotFoundCount()
  972. {
  973. ++_fileNotFoundCount;
  974. const unsigned int maxCount = _option->getAsInt(PREF_MAX_FILE_NOT_FOUND);
  975. if(maxCount > 0 && _fileNotFoundCount >= maxCount &&
  976. _segmentMan->calculateSessionDownloadLength() == 0) {
  977. throw DownloadFailureException
  978. (StringFormat("Reached max-file-not-found count=%u", maxCount).str());
  979. }
  980. }
  981. unsigned int RequestGroup::getNumConcurrentCommand() const
  982. {
  983. return _numConcurrentCommand;
  984. }
  985. void RequestGroup::markInMemoryDownload()
  986. {
  987. _inMemoryDownload = true;
  988. }
  989. bool RequestGroup::inMemoryDownload() const
  990. {
  991. return _inMemoryDownload;
  992. }
  993. } // namespace aria2