TorrentMan.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - a simple utility for downloading files faster
  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. /* copyright --> */
  22. #include "TorrentMan.h"
  23. #include "Dictionary.h"
  24. #include "List.h"
  25. #include "ShaVisitor.h"
  26. #include "Util.h"
  27. #include "MetaFileUtil.h"
  28. #include "DlAbortEx.h"
  29. #include "File.h"
  30. #include "message.h"
  31. #include "PreAllocationDiskWriter.h"
  32. #include <errno.h>
  33. #include <libgen.h>
  34. #include <string.h>
  35. TorrentMan::TorrentMan():bitfield(NULL),
  36. peerEntryIdCounter(0), cuidCounter(0),
  37. downloadedSize(0), uploadedSize(0),
  38. deltaDownload(0), deltaUpload(0),
  39. storeDir("."),
  40. multiFileTopDir(NULL),
  41. setupComplete(false),
  42. interval(DEFAULT_ANNOUNCE_INTERVAL),
  43. minInterval(DEFAULT_ANNOUNCE_MIN_INTERVAL),
  44. complete(0), incomplete(0),
  45. connections(0), diskWriter(NULL) {}
  46. TorrentMan::~TorrentMan() {
  47. if(bitfield != NULL) {
  48. delete bitfield;
  49. }
  50. if(multiFileTopDir != NULL) {
  51. delete multiFileTopDir;
  52. }
  53. for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
  54. delete *itr;
  55. }
  56. if(diskWriter != NULL) {
  57. delete diskWriter;
  58. }
  59. }
  60. // TODO do not use this method in application code
  61. void TorrentMan::updatePeers(const Peers& peers) {
  62. this->peers = peers;
  63. }
  64. bool TorrentMan::addPeer(Peer* peer, bool duplicate) {
  65. if(duplicate) {
  66. for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
  67. Peer* p = *itr;
  68. if(p->ipaddr == peer->ipaddr && p->port == peer->port && p->error > 0) {
  69. return false;
  70. }
  71. }
  72. } else {
  73. if(peers.size() >= MAX_PEER_LIST_SIZE) {
  74. deleteOldErrorPeers(100);
  75. if(peers.size() >= MAX_PEER_LIST_SIZE) {
  76. return false;
  77. }
  78. }
  79. for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
  80. Peer* p = *itr;
  81. if(p->ipaddr == peer->ipaddr && p->port == peer->port) {
  82. return false;
  83. }
  84. }
  85. }
  86. ++peerEntryIdCounter;
  87. peer->entryId = peerEntryIdCounter;
  88. peers.push_back(peer);
  89. return true;
  90. }
  91. /*
  92. void TorrentMan::updatePeer(const Peer& peer) {
  93. for(Peers::iterator itr = peers.begin(); itr != peers.end(); itr++) {
  94. Peer& p = *itr;
  95. if(p.eid == peer.eid) {
  96. p = peer;
  97. break;
  98. }
  99. }
  100. }
  101. */
  102. bool TorrentMan::isPeerAvailable() const {
  103. return getPeer() != Peer::nullPeer;
  104. }
  105. int TorrentMan::deleteOldErrorPeers(int maxNum) {
  106. int counter = 0;
  107. for(Peers::iterator itr = peers.begin(); itr != peers.end();) {
  108. Peer* p = *itr;
  109. if(p->error != 0 && p->cuid == 0) {
  110. delete p;
  111. itr = peers.erase(itr);
  112. counter++;
  113. if(maxNum <= counter) {
  114. break;
  115. }
  116. } else {
  117. itr++;
  118. }
  119. }
  120. return counter;
  121. }
  122. Peer* TorrentMan::getPeer() const {
  123. for(Peers::const_iterator itr = peers.begin(); itr != peers.end(); itr++) {
  124. Peer* p = *itr;
  125. if(p->cuid == 0 && p->error == 0) {
  126. return p;
  127. }
  128. }
  129. return Peer::nullPeer;
  130. }
  131. bool TorrentMan::isEndGame() const {
  132. return bitfield->countMissingBlock() <= END_GAME_PIECE_NUM;
  133. }
  134. Piece TorrentMan::getMissingPiece(const Peer* peer) {
  135. int index = -1;
  136. if(isEndGame()) {
  137. index = bitfield->getMissingIndex(peer->getBitfield(), peer->getBitfieldLength());
  138. } else {
  139. index = bitfield->getMissingUnusedIndex(peer->getBitfield(), peer->getBitfieldLength());
  140. }
  141. if(index == -1) {
  142. return Piece::nullPiece;
  143. }
  144. bitfield->setUseBit(index);
  145. Piece piece = findUsedPiece(index);
  146. if(Piece::isNull(piece)) {
  147. Piece piece(index, bitfield->getBlockLength(index));
  148. addUsedPiece(piece);
  149. return piece;
  150. } else {
  151. return piece;
  152. }
  153. }
  154. int TorrentMan::deleteUsedPiecesByFillRate(int fillRate, int toDelete) {
  155. int deleted = 0;
  156. for(UsedPieces::iterator itr = usedPieces.begin();
  157. itr != usedPieces.end() && deleted < toDelete;) {
  158. Piece& piece = *itr;
  159. if(!bitfield->isUseBitSet(piece.getIndex()) &&
  160. piece.countCompleteBlock() <= piece.countBlock()*(fillRate/100.0)) {
  161. logger->debug("deleting used piece index=%d, fillRate(%%)=%d<=%d",
  162. piece.getIndex(),
  163. (piece.countCompleteBlock()*100)/piece.countBlock(),
  164. fillRate);
  165. itr = usedPieces.erase(itr);
  166. deleted++;
  167. } else {
  168. itr++;
  169. }
  170. }
  171. return deleted;
  172. }
  173. void TorrentMan::reduceUsedPieces(int max) {
  174. int toDelete = usedPieces.size()-max;
  175. if(toDelete <= 0) {
  176. return;
  177. }
  178. int fillRate = 10;
  179. while(fillRate < 50) {
  180. int deleted = deleteUsedPiecesByFillRate(fillRate, toDelete);
  181. if(deleted == 0) {
  182. break;
  183. }
  184. toDelete -= deleted;
  185. fillRate += 10;
  186. }
  187. }
  188. void TorrentMan::addUsedPiece(const Piece& piece) {
  189. usedPieces.push_back(piece);
  190. }
  191. Piece TorrentMan::findUsedPiece(int index) const {
  192. for(UsedPieces::const_iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
  193. const Piece& piece = *itr;
  194. if(piece.getIndex() == index) {
  195. return piece;
  196. }
  197. }
  198. return Piece::nullPiece;
  199. }
  200. void TorrentMan::deleteUsedPiece(const Piece& piece) {
  201. if(Piece::isNull(piece)) {
  202. return;
  203. }
  204. for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
  205. if(itr->getIndex() == piece.getIndex()) {
  206. usedPieces.erase(itr);
  207. break;
  208. }
  209. }
  210. }
  211. void TorrentMan::completePiece(const Piece& piece) {
  212. if(Piece::isNull(piece)) {
  213. return;
  214. }
  215. if(!hasPiece(piece.getIndex())) {
  216. addDownloadedSize(piece.getLength());
  217. }
  218. bitfield->setBit(piece.getIndex());
  219. bitfield->unsetUseBit(piece.getIndex());
  220. deleteUsedPiece(piece);
  221. if(!isEndGame()) {
  222. reduceUsedPieces(100);
  223. }
  224. }
  225. void TorrentMan::cancelPiece(const Piece& piece) {
  226. if(Piece::isNull(piece)) {
  227. return;
  228. }
  229. bitfield->unsetUseBit(piece.getIndex());
  230. if(!isEndGame()) {
  231. if(piece.countCompleteBlock() == 0) {
  232. deleteUsedPiece(piece);
  233. }
  234. }
  235. }
  236. void TorrentMan::updatePiece(const Piece& piece) {
  237. if(Piece::isNull(piece)) {
  238. return;
  239. }
  240. for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
  241. if(itr->getIndex() == piece.getIndex()) {
  242. *itr = piece;
  243. break;
  244. }
  245. }
  246. }
  247. void TorrentMan::syncPiece(Piece& piece) {
  248. if(Piece::isNull(piece)) {
  249. return;
  250. }
  251. for(UsedPieces::iterator itr = usedPieces.begin(); itr != usedPieces.end(); itr++) {
  252. if(itr->getIndex() == piece.getIndex()) {
  253. piece = *itr;
  254. return;
  255. }
  256. }
  257. // hasPiece(piece.getIndex()) is true, then set all bit of
  258. // piece.bitfield to 1
  259. if(hasPiece(piece.getIndex())) {
  260. piece.setAllBlock();
  261. }
  262. }
  263. void TorrentMan::initBitfield() {
  264. if(bitfield != NULL) {
  265. delete bitfield;
  266. }
  267. bitfield = new BitfieldMan(pieceLength, totalSize);
  268. }
  269. void TorrentMan::setBitfield(unsigned char* bitfield, int bitfieldLength) {
  270. if(this->bitfield == NULL) {
  271. initBitfield();
  272. }
  273. this->bitfield->setBitfield(bitfield, bitfieldLength);
  274. }
  275. bool TorrentMan::downloadComplete() const {
  276. return bitfield->isAllBitSet();
  277. }
  278. void TorrentMan::setup(string metaInfoFile) {
  279. peerId = "-A2****-";
  280. for(int i = 0; i < 12; i++) {
  281. peerId += Util::itos((int)(((double)10)*random()/(RAND_MAX+1.0)));
  282. }
  283. uploadedSize = 0;
  284. downloadedSize = 0;
  285. Dictionary* topDic = (Dictionary*)MetaFileUtil::parseMetaFile(metaInfoFile);
  286. const Dictionary* infoDic = (const Dictionary*)topDic->get("info");
  287. ShaVisitor v;
  288. infoDic->accept(&v);
  289. unsigned char md[20];
  290. int len;
  291. v.getHash(md, len);
  292. setInfoHash(md);
  293. Data* topName = (Data*)infoDic->get("name");
  294. if(topName != NULL) {
  295. name = topName->toString();
  296. } else {
  297. char* basec = strdup(metaInfoFile.c_str());
  298. name = string(basename(basec))+".file";
  299. free(basec);
  300. }
  301. List* files = (List*)infoDic->get("files");
  302. if(files == NULL) {
  303. // single-file mode;
  304. setFileMode(SINGLE);
  305. Data* length = (Data*)infoDic->get("length");
  306. totalSize = length->toLLInt();
  307. } else {
  308. long long int length = 0;
  309. // multi-file mode
  310. setFileMode(MULTI);
  311. multiFileTopDir = new Directory(name);
  312. const MetaList& metaList = files->getList();
  313. for(MetaList::const_iterator itr = metaList.begin(); itr != metaList.end();
  314. itr++) {
  315. Dictionary* fileDic = (Dictionary*)(*itr);
  316. Data* lengthData = (Data*)fileDic->get("length");
  317. length += lengthData->toLLInt();
  318. List* path = (List*)fileDic->get("path");
  319. const MetaList& paths = path->getList();
  320. Directory* parentDir = multiFileTopDir;
  321. string filePath = name;
  322. for(int i = 0; i < (int)paths.size()-1; i++) {
  323. Data* subpath = (Data*)paths.at(i);
  324. Directory* dir = new Directory(subpath->toString());
  325. parentDir->addFile(dir);
  326. parentDir = dir;
  327. filePath.append("/").append(subpath->toString());
  328. }
  329. Data* lastpath = (Data*)paths.back();
  330. filePath.append("/").append(lastpath->toString());
  331. FileEntry fileEntry(filePath, lengthData->toLLInt());
  332. multiFileEntries.push_back(fileEntry);
  333. }
  334. totalSize = length;
  335. }
  336. announce = ((Data*)topDic->get("announce"))->toString();
  337. pieceLength = ((Data*)infoDic->get("piece length"))->toInt();
  338. pieces = totalSize/pieceLength+(totalSize%pieceLength ? 1 : 0);
  339. Data* piecesHashData = (Data*)infoDic->get("pieces");
  340. if(piecesHashData->getLen() != pieces*20) {
  341. throw new DlAbortEx("the number of pieces is wrong.");
  342. }
  343. for(int index = 0; index < pieces; index++) {
  344. string hex = Util::toHex((unsigned char*)&piecesHashData->getData()[index*20], 20);
  345. pieceHashes.push_back(hex);
  346. logger->debug("piece #%d, hash:%s", index, hex.c_str());
  347. }
  348. initBitfield();
  349. delete topDic;
  350. diskWriter = new PreAllocationDiskWriter(totalSize);
  351. if(segmentFileExists()) {
  352. load();
  353. diskWriter->openExistingFile(getTempFilePath());
  354. } else {
  355. diskWriter->initAndOpenFile(getTempFilePath());
  356. }
  357. setupComplete = true;
  358. }
  359. bool TorrentMan::hasPiece(int index) const {
  360. return bitfield->isBitSet(index);
  361. }
  362. string TorrentMan::getPieceHash(int index) const {
  363. return pieceHashes.at(index);
  364. }
  365. string TorrentMan::getFilePath() const {
  366. return storeDir+"/"+name;
  367. }
  368. string TorrentMan::getTempFilePath() const {
  369. return getFilePath()+".a2tmp";
  370. }
  371. string TorrentMan::getSegmentFilePath() const {
  372. return getFilePath()+".aria2";
  373. }
  374. bool TorrentMan::segmentFileExists() const {
  375. string segFilename = getSegmentFilePath();
  376. File f(segFilename);
  377. if(f.isFile()) {
  378. logger->info(MSG_SEGMENT_FILE_EXISTS, segFilename.c_str());
  379. return true;
  380. } else {
  381. logger->info(MSG_SEGMENT_FILE_DOES_NOT_EXIST, segFilename.c_str());
  382. return false;
  383. }
  384. }
  385. FILE* TorrentMan::openSegFile(string segFilename, string mode) const {
  386. FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
  387. if(segFile == NULL) {
  388. throw new DlAbortEx(strerror(errno));
  389. }
  390. return segFile;
  391. }
  392. void TorrentMan::load() {
  393. string segFilename = getSegmentFilePath();
  394. logger->info(MSG_LOADING_SEGMENT_FILE, segFilename.c_str());
  395. FILE* segFile = openSegFile(segFilename, "r+");
  396. read(segFile);
  397. fclose(segFile);
  398. logger->info(MSG_LOADED_SEGMENT_FILE);
  399. }
  400. void TorrentMan::read(FILE* file) {
  401. assert(file != NULL);
  402. unsigned char savedInfoHash[INFO_HASH_LENGTH];
  403. if(fread(savedInfoHash, INFO_HASH_LENGTH, 1, file) < 1) {
  404. throw new DlAbortEx(strerror(errno));
  405. }
  406. if(Util::toHex(savedInfoHash, INFO_HASH_LENGTH) != Util::toHex(infoHash, INFO_HASH_LENGTH)) {
  407. throw new DlAbortEx("info hash mismatch");
  408. }
  409. unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
  410. try {
  411. if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
  412. throw new DlAbortEx(strerror(errno));
  413. }
  414. setBitfield(savedBitfield, bitfield->getBitfieldLength());
  415. if(fread(&downloadedSize, sizeof(downloadedSize), 1, file) < 1) {
  416. throw new DlAbortEx(strerror(errno));
  417. }
  418. if(fread(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
  419. throw new DlAbortEx(strerror(errno));
  420. }
  421. delete [] savedBitfield;
  422. } catch(Exception* ex) {
  423. delete [] savedBitfield;
  424. throw;
  425. }
  426. }
  427. void TorrentMan::save() const {
  428. if(!setupComplete) {
  429. return;
  430. }
  431. string segFilename = getSegmentFilePath();
  432. logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
  433. FILE* file = openSegFile(segFilename, "w");
  434. if(fwrite(infoHash, INFO_HASH_LENGTH, 1, file) < 1) {
  435. throw new DlAbortEx(strerror(errno));
  436. }
  437. if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(), 1, file) < 1) {
  438. throw new DlAbortEx(strerror(errno));
  439. }
  440. if(fwrite(&downloadedSize, sizeof(downloadedSize), 1, file) < 1) {
  441. throw new DlAbortEx(strerror(errno));
  442. }
  443. if(fwrite(&uploadedSize, sizeof(uploadedSize), 1, file) < 1) {
  444. throw new DlAbortEx(strerror(errno));
  445. }
  446. fclose(file);
  447. logger->info(MSG_SAVED_SEGMENT_FILE);
  448. }
  449. void TorrentMan::remove() const {
  450. if(segmentFileExists()) {
  451. File f(getSegmentFilePath());
  452. f.remove();
  453. }
  454. }
  455. void TorrentMan::fixFilename() const {
  456. if(fileMode == SINGLE) {
  457. copySingleFile();
  458. } else {
  459. splitMultiFile();
  460. }
  461. }
  462. void TorrentMan::copySingleFile() const {
  463. logger->info("writing file %s", getFilePath().c_str());
  464. Util::fileCopy(getFilePath(), getTempFilePath());
  465. }
  466. void TorrentMan::splitMultiFile() const {
  467. logger->info("creating directories");
  468. multiFileTopDir->createDir(storeDir, true);
  469. long long int offset = 0;
  470. for(MultiFileEntries::const_iterator itr = multiFileEntries.begin();
  471. itr != multiFileEntries.end(); itr++) {
  472. string dest = storeDir+"/"+itr->path;
  473. logger->info("writing file %s", dest.c_str());
  474. Util::rangedFileCopy(dest, getTempFilePath(), offset, itr->length);
  475. offset += itr->length;
  476. }
  477. }
  478. void TorrentMan::deleteTempFile() const {
  479. unlink(getTempFilePath().c_str());
  480. }