TorrentMan.cc 14 KB

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