diff options
Diffstat (limited to 'src')
47 files changed, 1300 insertions, 623 deletions
diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h index 6d84013d..5289d14e 100644 --- a/src/AbstractCommand.h +++ b/src/AbstractCommand.h @@ -26,7 +26,7 @@ #include "Request.h" #include "DownloadEngine.h" #include "SegmentMan.h" -#include "Time.h" +#include "TimeA2.h" class AbstractCommand : public Command { private: diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index 7f6f85c8..ff56fa57 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -30,17 +30,21 @@ #include <errno.h> #include <fcntl.h> -AbstractDiskWriter::AbstractDiskWriter():fd(0) { +AbstractDiskWriter::AbstractDiskWriter(): + fd(0) +#ifdef ENABLE_MESSAGE_DIGEST + ,ctx(DIGEST_ALGO_SHA1) +#endif // ENABLE_MESSAGE_DIGEST +{ #ifdef ENABLE_MESSAGE_DIGEST - ctx.setAlgo(MessageDigestContext::ALGO_SHA1); - digestInit(ctx); + ctx.digestInit(); #endif // ENABLE_MESSAGE_DIGEST } AbstractDiskWriter::~AbstractDiskWriter() { closeFile(); #ifdef ENABLE_MESSAGE_DIGEST - digestFree(ctx); + ctx.digestFree(); #endif // ENABLE_MESSAGE_DIGEST } @@ -100,7 +104,7 @@ int AbstractDiskWriter::readDataInternal(char* data, int len) { string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) { #ifdef ENABLE_MESSAGE_DIGEST - digestReset(ctx); + ctx.digestReset(); try { int BUFSIZE = 16*1024; char buf[BUFSIZE]; @@ -108,7 +112,7 @@ string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) { if(BUFSIZE != readData(buf, BUFSIZE, offset)) { throw string("error"); } - digestUpdate(ctx, buf, BUFSIZE); + ctx.digestUpdate(buf, BUFSIZE); offset += BUFSIZE; } int r = length%BUFSIZE; @@ -116,10 +120,10 @@ string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) { if(r != readData(buf, r, offset)) { throw string("error"); } - digestUpdate(ctx, buf, r); + ctx.digestUpdate(buf, r); } unsigned char hashValue[20]; - digestFinal(ctx, hashValue); + ctx.digestFinal(hashValue); return Util::toHex(hashValue, 20); } catch(string ex) { throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno)); diff --git a/src/Checksum.h b/src/Checksum.h new file mode 100644 index 00000000..220befe7 --- /dev/null +++ b/src/Checksum.h @@ -0,0 +1,64 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_CHECKSUM_H_ +#define _D_CHECKSUM_H_ + +#include "common.h" +#include "messageDigest.h" + +#ifdef ENABLE_MESSAGE_DIGEST +class Checksum { +private: + string md; + MessageDigestContext::DigestAlgo algo; +public: + Checksum(const string& md, MessageDigestContext::DigestAlgo algo): + md(md), + algo(algo) {} + Checksum(): + algo(DIGEST_ALGO_SHA1) {} + ~Checksum() {} + + bool isEmpty() const { + return md.size() == 0; + } + + void setMessageDigest(const string& md) { + this->md = md; + } + const string& getMessageDigest() const { + return md; + } + + void setDigestAlgo(MessageDigestContext::DigestAlgo algo) { + this->algo = algo; + } + const MessageDigestContext::DigestAlgo& getDigestAlgo() const { + return algo; + } +}; +#else +class Checksum { +}; +#endif // ENABLE_MESSAGE_DIGEST + +#endif // _D_CHECKSUM_H_ diff --git a/src/Command.cc b/src/Command.cc new file mode 100644 index 00000000..6227aee2 --- /dev/null +++ b/src/Command.cc @@ -0,0 +1,24 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#include "Command.h" + +int Command::uuidGen = 0; diff --git a/src/ConsoleDownloadEngine.h b/src/ConsoleDownloadEngine.h index f708c008..8b009f75 100644 --- a/src/ConsoleDownloadEngine.h +++ b/src/ConsoleDownloadEngine.h @@ -23,7 +23,7 @@ #define _D_CONSOLE_DOWNLOAD_ENGINE_H_ #include "DownloadEngine.h" -#include "Time.h" +#include "TimeA2.h" class ConsoleDownloadEngine : public DownloadEngine { private: diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 441b00de..4e948f53 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -20,12 +20,14 @@ */ /* copyright --> */ #include "DownloadCommand.h" -#include <sys/time.h> #include "Util.h" #include "DlRetryEx.h" +#include "DlAbortEx.h" #include "HttpInitiateConnectionCommand.h" #include "InitiateConnectionCommandFactory.h" #include "message.h" +#include "prefs.h" +#include <sys/time.h> DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e, const SocketHandle& s): @@ -59,6 +61,13 @@ bool DownloadCommand::executeInternal(Segment seg) { seg.speed = (int)((seg.ds-lastSize)/(diff*1.0)); sw.reset(); lastSize = seg.ds; + int lowestLimit = e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT); + if(lowestLimit > 0 && seg.speed <= lowestLimit) { + throw new DlAbortEx("CUID#%d - Too slow Downloading speed: %d <= %d(B/s)", + cuid, + seg.speed, + lowestLimit); + } } if(e->segmentMan->totalSize != 0 && bufSize == 0) { throw new DlRetryEx(EX_GOT_EOF); diff --git a/src/DownloadCommand.h b/src/DownloadCommand.h index 9f10de02..60403adf 100644 --- a/src/DownloadCommand.h +++ b/src/DownloadCommand.h @@ -24,7 +24,7 @@ #include "AbstractCommand.h" #include "TransferEncoding.h" -#include "Time.h" +#include "TimeA2.h" using namespace std; diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 0f6f36af..912381da 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -22,7 +22,7 @@ #include "DownloadEngine.h" #include "Util.h" #include "LogFactory.h" -#include "Time.h" +#include "TimeA2.h" #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> @@ -32,14 +32,13 @@ using namespace std; -DownloadEngine::DownloadEngine():noWait(false), segmentMan(NULL) { +DownloadEngine::DownloadEngine():noWait(false), segmentMan(0) { logger = LogFactory::getInstance(); } DownloadEngine::~DownloadEngine() { - if(segmentMan != NULL) { - delete segmentMan; - } + delete segmentMan; + cleanQueue(); } void DownloadEngine::cleanQueue() { @@ -66,7 +65,7 @@ public: void DownloadEngine::run() { initStatistics(); Time cp; - CommandUuids activeCommandUuids; + CommandUuids activeUuids; while(!commands.empty()) { if(cp.elapsed(1)) { cp.reset(); @@ -79,8 +78,8 @@ void DownloadEngine::run() { } } } else { - for(CommandUuids::iterator itr = activeCommandUuids.begin(); - itr != activeCommandUuids.end(); itr++) { + for(CommandUuids::iterator itr = activeUuids.begin(); + itr != activeUuids.end(); itr++) { Commands::iterator comItr = find_if(commands.begin(), commands.end(), FindCommand(*itr)); assert(comItr != commands.end()); @@ -92,9 +91,9 @@ void DownloadEngine::run() { } } afterEachIteration(); - activeCommandUuids.clear(); + activeUuids.clear(); if(!noWait && !commands.empty()) { - waitData(activeCommandUuids); + waitData(activeUuids); } noWait = false; calculateStatistics(); @@ -113,63 +112,86 @@ void DownloadEngine::shortSleep() const { class SetDescriptor { private: - fd_set* fds_ptr; int* max_ptr; + fd_set* rfds_ptr; + fd_set* wfds_ptr; public: - SetDescriptor(int* max_ptr, fd_set* fds_ptr) - :fds_ptr(fds_ptr), max_ptr(max_ptr) {} - - void operator()(const SockCmdMap::value_type& pa) { - int fd = pa.first->getSockfd(); - FD_SET(fd, fds_ptr); + SetDescriptor(int* max_ptr, fd_set* rfds_ptr, fd_set* wfds_ptr): + max_ptr(max_ptr), + rfds_ptr(rfds_ptr), + wfds_ptr(wfds_ptr) {} + + void operator()(const SocketEntry& entry) { + int fd = entry.socket->getSockfd(); + switch(entry.type) { + case SocketEntry::TYPE_RD: + FD_SET(fd, rfds_ptr); + break; + case SocketEntry::TYPE_WR: + FD_SET(fd, wfds_ptr); + break; + } if(*max_ptr < fd) { *max_ptr = fd; } } }; -class AccumulateActiveCommandUuid { +class AccumulateActiveUuid { private: - CommandUuids* activeCommandUuids_ptr; - fd_set* fds_ptr; + CommandUuids* activeUuids_ptr; + fd_set* rfds_ptr; + fd_set* wfds_ptr; public: - AccumulateActiveCommandUuid(CommandUuids* activeCommandUuids_ptr, - fd_set* fds_ptr) - :activeCommandUuids_ptr(activeCommandUuids_ptr), fds_ptr(fds_ptr) {} - - void operator()(const SockCmdMap::value_type& pa) { - if(FD_ISSET(pa.first->getSockfd(), fds_ptr)) { - activeCommandUuids_ptr->push_back(pa.second); + AccumulateActiveUuid(CommandUuids* activeUuids_ptr, + fd_set* rfds_ptr, + fd_set* wfds_ptr): + activeUuids_ptr(activeUuids_ptr), + rfds_ptr(rfds_ptr), + wfds_ptr(wfds_ptr) {} + + void operator()(const SocketEntry& entry) { + if(FD_ISSET(entry.socket->getSockfd(), rfds_ptr) || + FD_ISSET(entry.socket->getSockfd(), wfds_ptr)) { + activeUuids_ptr->push_back(entry.commandUuid); } + /* + switch(entry.type) { + case SocketEntry::TYPE_RD: + if(FD_ISSET(entry.socket->getSockfd(), rfds_ptr)) { + activeUuids_ptr->push_back(entry.commandUuid); + } + break; + case SocketEntry::TYPE_WR: + if(FD_ISSET(entry.socket->getSockfd(), wfds_ptr)) { + activeUuids_ptr->push_back(entry.commandUuid); + } + break; + } + */ } }; -void DownloadEngine::waitData(CommandUuids& activeCommandUuids) { +void DownloadEngine::waitData(CommandUuids& activeUuids) { fd_set rfds; fd_set wfds; int retval = 0; - while(1) { - struct timeval tv; - - memcpy(&rfds, &rfdset, sizeof(fd_set)); - memcpy(&wfds, &wfdset, sizeof(fd_set)); - - tv.tv_sec = 1; - tv.tv_usec = 0; - retval = select(fdmax+1, &rfds, &wfds, NULL, &tv); - if(retval != -1 || errno != EINTR) { - break; - } - } + struct timeval tv; + + memcpy(&rfds, &rfdset, sizeof(fd_set)); + memcpy(&wfds, &wfdset, sizeof(fd_set)); + + tv.tv_sec = 1; + tv.tv_usec = 0; + retval = select(fdmax+1, &rfds, &wfds, NULL, &tv); if(retval > 0) { - for_each(rsockmap.begin(), rsockmap.end(), - AccumulateActiveCommandUuid(&activeCommandUuids, &rfds)); - for_each(wsockmap.begin(), wsockmap.end(), - AccumulateActiveCommandUuid(&activeCommandUuids, &wfds)); - sort(activeCommandUuids.begin(), activeCommandUuids.end()); - activeCommandUuids.erase(unique(activeCommandUuids.begin(), - activeCommandUuids.end()), - activeCommandUuids.end()); + for_each(socketEntries.begin(), socketEntries.end(), + AccumulateActiveUuid(&activeUuids, &rfds, &wfds)); + + sort(activeUuids.begin(), activeUuids.end()); + activeUuids.erase(unique(activeUuids.begin(), + activeUuids.end()), + activeUuids.end()); } } @@ -177,18 +199,15 @@ void DownloadEngine::updateFdSet() { fdmax = 0; FD_ZERO(&rfdset); FD_ZERO(&wfdset); - for_each(rsockmap.begin(), rsockmap.end(), SetDescriptor(&fdmax, &rfdset)); - for_each(wsockmap.begin(), wsockmap.end(), SetDescriptor(&fdmax, &wfdset)); + for_each(socketEntries.begin(), socketEntries.end(), + SetDescriptor(&fdmax, &rfdset, &wfdset)); } -bool DownloadEngine::addSocket(SockCmdMap& sockmap, - const SocketHandle& socket, - const CommandUuid& commandUuid) { - SockCmdMap::iterator itr = find_if(sockmap.begin(), sockmap.end(), - PairFind<SocketHandle, CommandUuid>(socket, commandUuid)); - if(itr == sockmap.end()) { - SockCmdMap::value_type vt(socket, commandUuid); - sockmap.insert(vt); +bool DownloadEngine::addSocket(const SocketEntry& entry) { + SocketEntries::iterator itr = + find(socketEntries.begin(), socketEntries.end(), entry); + if(itr == socketEntries.end()) { + socketEntries.push_back(entry); updateFdSet(); return true; } else { @@ -196,15 +215,13 @@ bool DownloadEngine::addSocket(SockCmdMap& sockmap, } } -bool DownloadEngine::deleteSocket(SockCmdMap& sockmap, - const SocketHandle& socket, - const CommandUuid& commandUuid) { - SockCmdMap::iterator itr = find_if(sockmap.begin(), sockmap.end(), - PairFind<SocketHandle, CommandUuid>(socket, commandUuid)); - if(itr == sockmap.end()) { +bool DownloadEngine::deleteSocket(const SocketEntry& entry) { + SocketEntries::iterator itr = + find(socketEntries.begin(), socketEntries.end(), entry); + if(itr == socketEntries.end()) { return false; } else { - sockmap.erase(itr); + socketEntries.erase(itr); updateFdSet(); return true; } @@ -212,20 +229,24 @@ bool DownloadEngine::deleteSocket(SockCmdMap& sockmap, bool DownloadEngine::addSocketForReadCheck(const SocketHandle& socket, const CommandUuid& commandUuid) { - return addSocket(rsockmap, socket, commandUuid); + SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_RD); + return addSocket(entry); } bool DownloadEngine::deleteSocketForReadCheck(const SocketHandle& socket, const CommandUuid& commandUuid) { - return deleteSocket(rsockmap, socket, commandUuid); + SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_RD); + return deleteSocket(entry); } bool DownloadEngine::addSocketForWriteCheck(const SocketHandle& socket, const CommandUuid& commandUuid) { - return addSocket(wsockmap, socket, commandUuid); + SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_WR); + return addSocket(entry); } bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket, const CommandUuid& commandUuid) { - return deleteSocket(wsockmap, socket, commandUuid); + SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_WR); + return deleteSocket(entry); } diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h index d2dd0521..aa118ac7 100644 --- a/src/DownloadEngine.h +++ b/src/DownloadEngine.h @@ -32,22 +32,44 @@ typedef deque<SocketHandle> Sockets; typedef deque<Command*> Commands; typedef deque<CommandUuid> CommandUuids; -typedef multimap<SocketHandle, int> SockCmdMap; + +class SocketEntry { +public: + enum TYPE { + TYPE_RD, + TYPE_WR, + }; + + SocketHandle socket; + CommandUuid commandUuid; + TYPE type; +public: + SocketEntry(const SocketHandle& socket, + const CommandUuid& commandUuid, + TYPE type): + socket(socket), commandUuid(commandUuid), type(type) {} + ~SocketEntry() {} + + bool operator==(const SocketEntry& entry) { + return socket == entry.socket && + commandUuid == entry.commandUuid && + type == entry.type; + } +}; + +typedef deque<SocketEntry> SocketEntries; class DownloadEngine { private: - void waitData(CommandUuids& activeCommandUuids); - SockCmdMap rsockmap; - SockCmdMap wsockmap; + void waitData(CommandUuids& activeUuids); + SocketEntries socketEntries; fd_set rfdset; fd_set wfdset; int fdmax; void shortSleep() const; - bool addSocket(SockCmdMap& sockmap, const SocketHandle& socket, - const CommandUuid& commandUuid); - bool deleteSocket(SockCmdMap& sockmap, const SocketHandle& socket, - const CommandUuid& commandUuid); + bool addSocket(const SocketEntry& socketEntry); + bool deleteSocket(const SocketEntry& socketEntry); protected: const Logger* logger; virtual void initStatistics() = 0; @@ -80,22 +102,5 @@ public: }; -template<class T1, class T2> -class PairFind { -private: - T1 first; - T2 second; -public: - PairFind(T1 t1, T2 t2):first(t1), second(t2) {} - - bool operator()(const pair<T1, T2>& pa) { - if(pa.first == first && pa.second == second) { - return true; - } else { - return false; - } - } -}; - #endif // _D_DOWNLOAD_ENGINE_H_ diff --git a/src/DownloadEngineFactory.cc b/src/DownloadEngineFactory.cc new file mode 100644 index 00000000..52da662c --- /dev/null +++ b/src/DownloadEngineFactory.cc @@ -0,0 +1,123 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#include "DownloadEngineFactory.h" +#include "prefs.h" +#include "DefaultDiskWriter.h" +#include "SplitSlowestSegmentSplitter.h" +#include "InitiateConnectionCommandFactory.h" +#include "ByteArrayDiskWriter.h" +#include "Util.h" +#ifdef ENABLE_BITTORRENT +# include "PeerListenCommand.h" +# include "TrackerWatcherCommand.h" +# include "TrackerUpdateCommand.h" +# include "TorrentAutoSaveCommand.h" +# include "PeerChokeCommand.h" +# include "HaveEraseCommand.h" +#endif // ENABLE_BITTORRENT + +ConsoleDownloadEngine* +DownloadEngineFactory::newConsoleEngine(const Option* op, + const Requests& requests, + const Requests& reserved) +{ + ConsoleDownloadEngine* e = new ConsoleDownloadEngine(); + e->option = op; + e->segmentMan = new SegmentMan(); + e->segmentMan->diskWriter = new DefaultDiskWriter(); + e->segmentMan->dir = op->get(PREF_DIR); + e->segmentMan->ufilename = op->get(PREF_OUT); + e->segmentMan->option = op; + e->segmentMan->splitter = new SplitSlowestSegmentSplitter(); + e->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE)); + e->segmentMan->reserved = reserved; + + int cuidCounter = 1; + for(Requests::const_iterator itr = requests.begin(); + itr != requests.end(); + itr++, cuidCounter++) { + e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e)); + } + return e; +} + +#ifdef ENABLE_BITTORRENT +TorrentConsoleDownloadEngine* +DownloadEngineFactory::newTorrentConsoleEngine(const Option* op, + const string& torrentFile, + const Strings& targetFiles) +{ + Request* req = new Request(); + req->isTorrent = true; + req->setTrackerEvent(Request::STARTED); + TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine(); + te->option = op; + ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter(); + te->segmentMan = new SegmentMan(); + te->segmentMan->diskWriter = byteArrayDiskWriter; + te->segmentMan->option = op; + te->segmentMan->splitter = new SplitSlowestSegmentSplitter(); + te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE)); + te->torrentMan = new TorrentMan(); + te->torrentMan->setStoreDir(op->get(PREF_DIR)); + te->torrentMan->option = op; + te->torrentMan->req = req; + Integers selectIndexes; + Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes); + if(selectIndexes.size()) { + te->torrentMan->setup(torrentFile, selectIndexes); + } else { + te->torrentMan->setup(torrentFile, targetFiles); + } + + PeerListenCommand* listenCommand = + new PeerListenCommand(te->torrentMan->getNewCuid(), te); + int port; + int listenPort = op->getAsInt(PREF_LISTEN_PORT); + if(listenPort == -1) { + port = listenCommand->bindPort(6881, 6999); + } else { + port = listenCommand->bindPort(listenPort, listenPort); + } + if(port == -1) { + printf(_("Errors occurred while binding port.\n")); + exit(EXIT_FAILURE); + } + te->torrentMan->setPort(port); + te->commands.push_back(listenCommand); + + te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(), + te, + te->torrentMan->minInterval)); + te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(), + te)); + te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(), + te, + op->getAsInt(PREF_AUTO_SAVE_INTERVAL))); + te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(), + te, 10)); + te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(), + te, 10)); + + return te; +} +#endif // ENABLE_BITTORRENT diff --git a/src/DownloadEngineFactory.h b/src/DownloadEngineFactory.h new file mode 100644 index 00000000..10108fbc --- /dev/null +++ b/src/DownloadEngineFactory.h @@ -0,0 +1,46 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_DOWNLOAD_ENGINE_FACTORY_H_ +#define _D_DOWNLOAD_ENGINE_FACTORY_H_ + +#include "common.h" +#include "ConsoleDownloadEngine.h" +#ifdef ENABLE_BITTORRENT +# include "TorrentConsoleDownloadEngine.h" +#endif // ENABLE_BITTORRENT + +class DownloadEngineFactory { +public: + static ConsoleDownloadEngine* + newConsoleEngine(const Option* option, + const Requests& requests, + const Requests& reserved); + +#ifdef ENABLE_BITTORRENT + static TorrentConsoleDownloadEngine* + newTorrentConsoleEngine(const Option* option, + const string& torrentFile, + const Strings& targetFiles); +#endif // ENABLE_BITTORRENT +}; + +#endif // _D_DOWNLOAD_ENGINE_FACTORY_H_ diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 67b08f6b..34641e27 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -57,6 +57,9 @@ bool FtpNegotiationCommand::executeInternal(Segment segment) { bool FtpNegotiationCommand::recvGreeting() { socket->setBlockingMode(); + disableWriteCheckSocket(); + setReadCheckSocket(socket); + int status = ftp->receiveResponse(); if(status == 0) { return false; @@ -66,9 +69,6 @@ bool FtpNegotiationCommand::recvGreeting() { } sequence = SEQ_SEND_USER; - setReadCheckSocket(socket); - disableWriteCheckSocket(); - return true; } @@ -264,7 +264,7 @@ bool FtpNegotiationCommand::recvRetr() { if(status == 0) { return false; } - if(status != 150) { + if(status != 150 && status != 125) { throw new DlRetryEx(EX_BAD_STATUS, status); } if(e->option->get(PREF_FTP_PASV_ENABLED) != V_TRUE) { diff --git a/src/Makefile.am b/src/Makefile.am index 1cfbac55..5344ccfa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,9 +50,12 @@ SRCS = Socket.h\ messageDigest.h\ LogFactory.cc LogFactory.h\ NullLogger.h\ - Time.cc Time.h\ + TimeA2.cc TimeA2.h\ SharedHandle.h\ - FeatureConfig.cc FeatureConfig.h + FeatureConfig.cc FeatureConfig.h\ + DownloadEngineFactory.cc DownloadEngineFactory.h\ + RequestInfo.h\ + UrlRequestInfo.cc UrlRequestInfo.h if ENABLE_BITTORRENT SRCS += MetaEntry.h\ @@ -108,7 +111,8 @@ SRCS += MetaEntry.h\ SuggestPieceMessage.cc SuggestPieceMessage.h\ SimplePeerMessage.cc SimplePeerMessage.h\ PeerMessageFactory.cc PeerMessageFactory.h\ - HaveEraseCommand.cc HaveEraseCommand.h + HaveEraseCommand.cc HaveEraseCommand.h\ + TorrentRequestInfo.cc TorrentRequestInfo.h endif # ENABLE_BITTORRENT if ENABLE_METALINK @@ -116,15 +120,16 @@ SRCS += Metalinker.cc Metalinker.h\ MetalinkEntry.cc MetalinkEntry.h\ MetalinkResource.cc MetalinkResource.h\ MetalinkProcessor.h\ - Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h + Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\ + MetalinkRequestInfo.cc MetalinkRequestInfo.h endif # ENABLE_METALINK noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ -aria2c_LDFLAGS = -pg +#aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ - -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg
\ No newline at end of file + -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg
\ No newline at end of file diff --git a/src/Makefile.in b/src/Makefile.in index 12f65d27..f542ff0c 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -91,13 +91,15 @@ bin_PROGRAMS = aria2c$(EXEEXT) @ENABLE_BITTORRENT_TRUE@ SuggestPieceMessage.cc SuggestPieceMessage.h\ @ENABLE_BITTORRENT_TRUE@ SimplePeerMessage.cc SimplePeerMessage.h\ @ENABLE_BITTORRENT_TRUE@ PeerMessageFactory.cc PeerMessageFactory.h\ -@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.cc HaveEraseCommand.h +@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.cc HaveEraseCommand.h\ +@ENABLE_BITTORRENT_TRUE@ TorrentRequestInfo.cc TorrentRequestInfo.h @ENABLE_METALINK_TRUE@am__append_2 = Metalinker.cc Metalinker.h\ @ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\ @ENABLE_METALINK_TRUE@ MetalinkResource.cc MetalinkResource.h\ @ENABLE_METALINK_TRUE@ MetalinkProcessor.h\ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h +@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\ +@ENABLE_METALINK_TRUE@ MetalinkRequestInfo.cc MetalinkRequestInfo.h subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c @@ -154,14 +156,15 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ PreAllocationDiskWriter.h AbstractDiskWriter.cc \ AbstractDiskWriter.h File.cc File.h Option.cc Option.h \ Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \ - LogFactory.cc LogFactory.h NullLogger.h Time.cc Time.h \ - SharedHandle.h FeatureConfig.cc FeatureConfig.h MetaEntry.h \ - Data.cc Data.h Dictionary.cc Dictionary.h List.cc List.h \ - MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \ - ShaVisitor.cc ShaVisitor.h TorrentMan.cc TorrentMan.h \ - PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \ - PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \ - PeerInitiateConnectionCommand.cc \ + LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \ + SharedHandle.h FeatureConfig.cc FeatureConfig.h \ + DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ + UrlRequestInfo.cc UrlRequestInfo.h MetaEntry.h Data.cc Data.h \ + Dictionary.cc Dictionary.h List.cc List.h MetaFileUtil.cc \ + MetaFileUtil.h MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \ + TorrentMan.cc TorrentMan.h PeerConnection.cc PeerConnection.h \ + PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \ + PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \ PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \ PeerInteractionCommand.h Peer.cc Peer.h BitfieldMan.cc \ BitfieldMan.h TorrentDownloadEngine.cc TorrentDownloadEngine.h \ @@ -191,9 +194,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ SuggestPieceMessage.cc SuggestPieceMessage.h \ SimplePeerMessage.cc SimplePeerMessage.h PeerMessageFactory.cc \ PeerMessageFactory.h HaveEraseCommand.cc HaveEraseCommand.h \ - Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \ + TorrentRequestInfo.cc TorrentRequestInfo.h Metalinker.cc \ + Metalinker.h MetalinkEntry.cc MetalinkEntry.h \ MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \ - Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h + Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \ + MetalinkRequestInfo.cc MetalinkRequestInfo.h @ENABLE_BITTORRENT_TRUE@am__objects_1 = Data.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ Dictionary.$(OBJEXT) List.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ MetaFileUtil.$(OBJEXT) \ @@ -241,11 +246,13 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \ @ENABLE_BITTORRENT_TRUE@ SuggestPieceMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ SimplePeerMessage.$(OBJEXT) \ @ENABLE_BITTORRENT_TRUE@ PeerMessageFactory.$(OBJEXT) \ -@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.$(OBJEXT) +@ENABLE_BITTORRENT_TRUE@ HaveEraseCommand.$(OBJEXT) \ +@ENABLE_BITTORRENT_TRUE@ TorrentRequestInfo.$(OBJEXT) @ENABLE_METALINK_TRUE@am__objects_2 = Metalinker.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \ @ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \ -@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.$(OBJEXT) +@ENABLE_METALINK_TRUE@ Xml2MetalinkProcessor.$(OBJEXT) \ +@ENABLE_METALINK_TRUE@ MetalinkRequestInfo.$(OBJEXT) am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ AbstractCommand.$(OBJEXT) \ InitiateConnectionCommandFactory.$(OBJEXT) \ @@ -268,8 +275,9 @@ am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \ ChunkedEncoding.$(OBJEXT) DefaultDiskWriter.$(OBJEXT) \ PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \ File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \ - CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) Time.$(OBJEXT) \ - FeatureConfig.$(OBJEXT) $(am__objects_1) $(am__objects_2) + CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) TimeA2.$(OBJEXT) \ + FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \ + UrlRequestInfo.$(OBJEXT) $(am__objects_1) $(am__objects_2) am_libaria2c_a_OBJECTS = $(am__objects_3) libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" @@ -457,19 +465,21 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \ PreAllocationDiskWriter.h AbstractDiskWriter.cc \ AbstractDiskWriter.h File.cc File.h Option.cc Option.h \ Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \ - LogFactory.cc LogFactory.h NullLogger.h Time.cc Time.h \ + LogFactory.cc LogFactory.h NullLogger.h TimeA2.cc TimeA2.h \ SharedHandle.h FeatureConfig.cc FeatureConfig.h \ - $(am__append_1) $(am__append_2) + DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \ + UrlRequestInfo.cc UrlRequestInfo.h $(am__append_1) \ + $(am__append_2) noinst_LIBRARIES = libaria2c.a libaria2c_a_SOURCES = $(SRCS) aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\ @LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@ -aria2c_LDFLAGS = -pg +#aria2c_LDFLAGS = -pg AM_CPPFLAGS = -Wall\ -I../lib -I../intl -I$(top_srcdir)/intl\ @LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\ - -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg + -D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg all: all-am @@ -567,6 +577,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@ @@ -595,6 +606,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkRequestInfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkResource.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalinker.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptor.Po@am__quote@ @@ -630,14 +642,16 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitFirstSegmentSplitter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SplitSlowestSegmentSplitter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SuggestPieceMessage.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeA2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentAutoSaveCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentMan.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentRequestInfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerUpdateCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnchokeMessage.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UrlRequestInfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ diff --git a/src/MetalinkEntry.cc b/src/MetalinkEntry.cc index 6eb86f50..4a4327a8 100644 --- a/src/MetalinkEntry.cc +++ b/src/MetalinkEntry.cc @@ -29,30 +29,6 @@ MetalinkEntry::~MetalinkEntry() { for_each(resources.begin(), resources.end(), Deleter()); } -bool MetalinkEntry::check(const string& filename) const { -#ifdef ENABLE_MESSAGE_DIGEST - unsigned char buf[20]; - int digestLength; - const string* digestPtr; - MessageDigestContext::HashAlgo algo; - if(!sha1.empty()) { - digestLength = 20; - algo = MessageDigestContext::ALGO_SHA1; - digestPtr = &sha1; - } else if(!md5.empty()) { - digestLength = 16; - algo = MessageDigestContext::ALGO_MD5; - digestPtr = &md5; - } else { - return true; - } - Util::fileChecksum(filename, buf, algo); - return *digestPtr == Util::toHex(buf, digestLength); -#else - return true; -#endif //ENABLE_MESSAGE_DIGEST -} - class PrefOrder { public: bool operator()(const MetalinkResource* res1, const MetalinkResource* res2) { @@ -71,6 +47,10 @@ public: switch(res->type) { case MetalinkResource::TYPE_FTP: case MetalinkResource::TYPE_HTTP: + case MetalinkResource::TYPE_HTTPS: +#ifdef ENABLE_BITTORRENT + case MetalinkResource::TYPE_BITTORRENT: +#endif // ENABLE_BITTORRENT return true; default: return false; @@ -81,5 +61,6 @@ public: void MetalinkEntry::dropUnsupportedResource() { MetalinkResources::iterator split = partition(resources.begin(), resources.end(), Supported()); + for_each(split, resources.end(), Deleter()); resources.erase(split, resources.end()); } diff --git a/src/MetalinkEntry.h b/src/MetalinkEntry.h index 8e1f98e8..2d6c3a96 100644 --- a/src/MetalinkEntry.h +++ b/src/MetalinkEntry.h @@ -24,6 +24,7 @@ #include "common.h" #include "MetalinkResource.h" +#include "Checksum.h" #include <deque> typedef deque<MetalinkResource*> MetalinkResources; @@ -35,8 +36,7 @@ public: string language; string os; long long int size; - string md5; - string sha1; + Checksum checksum; public: MetalinkResources resources; public: @@ -50,14 +50,11 @@ public: this->language = metalinkEntry.language; this->os = metalinkEntry.os; this->size = metalinkEntry.size; - this->md5 = metalinkEntry.md5; - this->sha1 = metalinkEntry.sha1; + this->checksum = metalinkEntry.checksum; } return *this; } - bool check(const string& filename) const; - void dropUnsupportedResource(); void reorderResourcesByPreference(); diff --git a/src/MetalinkRequestInfo.cc b/src/MetalinkRequestInfo.cc new file mode 100644 index 00000000..6b58c102 --- /dev/null +++ b/src/MetalinkRequestInfo.cc @@ -0,0 +1,111 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#include "MetalinkRequestInfo.h" +#include "Xml2MetalinkProcessor.h" +#include "prefs.h" +#include "DlAbortEx.h" +#include "UrlRequestInfo.h" + +class AccumulateNonP2PUrl { +private: + Strings* urlsPtr; + int split; +public: + AccumulateNonP2PUrl(Strings* urlsPtr, + int split) + :urlsPtr(urlsPtr), + split(split) {} + + void operator()(const MetalinkResource* resource) { + switch(resource->type) { + case MetalinkResource::TYPE_HTTP: + case MetalinkResource::TYPE_HTTPS: + case MetalinkResource::TYPE_FTP: + for(int s = 1; s <= split; s++) { + urlsPtr->push_back(resource->url); + } + break; + } + } +}; + +class FindBitTorrentUrl { +public: + FindBitTorrentUrl() {} + + bool operator()(const MetalinkResource* resource) { + if(resource->type == MetalinkResource::TYPE_BITTORRENT) { + return true; + } else { + return false; + } + } +}; + +RequestInfo* MetalinkRequestInfo::execute() { + RequestInfo* next = 0; + Xml2MetalinkProcessor proc; + Metalinker* metalinker = 0; + try { + metalinker = proc.parseFile(metalinkFile); + + MetalinkEntry* entry = + metalinker->queryEntry(op->get(PREF_METALINK_VERSION), + op->get(PREF_METALINK_LANGUAGE), + op->get(PREF_METALINK_OS)); + if(entry == 0) { + printf("No file matched with your preference.\n"); + throw new DlAbortEx("No file matched with your preference."); + } + entry->dropUnsupportedResource(); + MetalinkResources::iterator itr = + find_if(entry->resources.begin(), + entry->resources.end(), + FindBitTorrentUrl()); + Strings urls; + int maxConnection = 0; + Checksum checksum; + if(itr == entry->resources.end()) { + entry->reorderResourcesByPreference(); + + for_each(entry->resources.begin(), entry->resources.end(), + AccumulateNonP2PUrl(&urls, op->getAsInt(PREF_SPLIT))); + maxConnection = + op->getAsInt(PREF_METALINK_SERVERS)*op->getAsInt(PREF_SPLIT); + + // TODO + // set checksum + checksum = entry->checksum; + } else { + // BitTorrent downloading + urls.push_back((*itr)->url); + } + next = new UrlRequestInfo(urls, maxConnection, op); + next->setChecksum(checksum); + } catch(Exception* e) { + logger->error("Exception caught", e); + delete e; + fail = true; + } + delete metalinker; + return next; +} diff --git a/src/MetalinkRequestInfo.h b/src/MetalinkRequestInfo.h new file mode 100644 index 00000000..763537d5 --- /dev/null +++ b/src/MetalinkRequestInfo.h @@ -0,0 +1,41 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_METALINK_REQUEST_INFO_H_ +#define _D_METALINK_REQUEST_INFO_H_ + +#include "RequestInfo.h" + +class MetalinkRequestInfo : public RequestInfo { +private: + string metalinkFile; +public: + MetalinkRequestInfo(const string& metalinkFile, const Option* op): + RequestInfo(op), + metalinkFile(metalinkFile) {} + virtual ~MetalinkRequestInfo() {} + + virtual RequestInfo* execute(); + + virtual DownloadEngine* getDownloadEngine() { return 0; } +}; + +#endif // _D_METALINK_REQUEST_INFO_H_ diff --git a/src/MetalinkResource.h b/src/MetalinkResource.h index 497e65c8..44ddc23b 100644 --- a/src/MetalinkResource.h +++ b/src/MetalinkResource.h @@ -29,6 +29,7 @@ public: enum TYPE { TYPE_FTP, TYPE_HTTP, + TYPE_HTTPS, TYPE_BITTORRENT, TYPE_NOT_SUPPORTED }; diff --git a/src/MultiDiskWriter.cc b/src/MultiDiskWriter.cc index f40f6da0..d0a13776 100644 --- a/src/MultiDiskWriter.cc +++ b/src/MultiDiskWriter.cc @@ -25,18 +25,15 @@ #include "message.h" #include <errno.h> -MultiDiskWriter::MultiDiskWriter(int pieceLength):pieceLength(pieceLength) { -#ifdef ENABLE_MESSAGE_DIGEST - ctx.setAlgo(MessageDigestContext::ALGO_SHA1); - digestInit(ctx); -#endif // ENABLE_MESSAGE_DIGEST +MultiDiskWriter::MultiDiskWriter(int pieceLength): + pieceLength(pieceLength), + ctx(DIGEST_ALGO_SHA1) { + ctx.digestInit(); } MultiDiskWriter::~MultiDiskWriter() { clearEntries(); -#ifdef ENABLE_MESSAGE_DIGEST - digestFree(ctx); -#endif // ENABLE_MESSAGE_DIGEST + ctx.digestFree(); } void MultiDiskWriter::clearEntries() { @@ -143,7 +140,6 @@ int MultiDiskWriter::readData(char* data, int len, long long int offset) { return totalReadLength; } -#ifdef ENABLE_MESSAGE_DIGEST void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length) { int BUFSIZE = 16*1024; char buf[BUFSIZE]; @@ -151,7 +147,7 @@ void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, l if(BUFSIZE != entry->diskWriter->readData(buf, BUFSIZE, offset)) { throw string("error"); } - digestUpdate(ctx, buf, BUFSIZE); + ctx.digestUpdate(buf, BUFSIZE); offset += BUFSIZE; } int r = length%BUFSIZE; @@ -159,17 +155,15 @@ void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, l if(r != entry->diskWriter->readData(buf, r, offset)) { throw string("error"); } - digestUpdate(ctx, buf, r); + ctx.digestUpdate(buf, r); } } -#endif // ENABLE_MESSAGE_DIGEST string MultiDiskWriter::sha1Sum(long long int offset, long long int length) { -#ifdef ENABLE_MESSAGE_DIGEST long long int fileOffset = offset; bool reading = false; int rem = length; - digestReset(ctx); + ctx.digestReset(); try { for(DiskWriterEntries::iterator itr = diskWriterEntries.begin(); itr != diskWriterEntries.end() && rem != 0; itr++) { @@ -187,13 +181,10 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) { throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset); } unsigned char hashValue[20]; - digestFinal(ctx, hashValue); + ctx.digestFinal(hashValue); return Util::toHex(hashValue, 20); } catch(string ex) { throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno)); } -#else - return ""; -#endif // ENABLE_MESSAGE_DIGEST } diff --git a/src/MultiDiskWriter.h b/src/MultiDiskWriter.h index 0cd18cb5..a903424d 100644 --- a/src/MultiDiskWriter.h +++ b/src/MultiDiskWriter.h @@ -48,10 +48,8 @@ private: bool isInRange(const DiskWriterEntry* entry, long long int offset) const; int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const; void clearEntries(); -#ifdef ENABLE_MESSAGE_DIGEST MessageDigestContext ctx; void hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length); -#endif // ENABLE_MESSAGE_DIGEST public: MultiDiskWriter(int pieceLength); diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h index 95d9a448..f0a71a8b 100644 --- a/src/PeerAbstractCommand.h +++ b/src/PeerAbstractCommand.h @@ -25,7 +25,7 @@ #include "Command.h" #include "Request.h" #include "TorrentDownloadEngine.h" -#include "Time.h" +#include "TimeA2.h" class PeerAbstractCommand : public Command { private: diff --git a/src/PeerChokeCommand.cc b/src/PeerChokeCommand.cc index 7a32e6da..8fdb44fa 100644 --- a/src/PeerChokeCommand.cc +++ b/src/PeerChokeCommand.cc @@ -22,7 +22,7 @@ #include "PeerChokeCommand.h" #include "Util.h" -PeerChokeCommand::PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e):Command(cuid), interval(interval), e(e), rotate(0) {} +PeerChokeCommand::PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), interval(interval), e(e), rotate(0) {} PeerChokeCommand::~PeerChokeCommand() {} diff --git a/src/PeerChokeCommand.h b/src/PeerChokeCommand.h index c0019bf6..c3f9b242 100644 --- a/src/PeerChokeCommand.h +++ b/src/PeerChokeCommand.h @@ -24,7 +24,7 @@ #include "Command.h" #include "TorrentDownloadEngine.h" -#include "Time.h" +#include "TimeA2.h" class PeerChokeCommand : public Command { private: @@ -38,7 +38,7 @@ private: void optUnchokingPeer(Peers& peers) const; public: - PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e); + PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval); virtual ~PeerChokeCommand(); bool execute(); diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h index ff0abb82..8f1ae0ed 100644 --- a/src/PeerInteractionCommand.h +++ b/src/PeerInteractionCommand.h @@ -25,7 +25,7 @@ #include "PeerAbstractCommand.h" #include "PeerConnection.h" #include "PeerInteraction.h" -#include "Time.h" +#include "TimeA2.h" using namespace std; diff --git a/src/RequestInfo.h b/src/RequestInfo.h new file mode 100644 index 00000000..b8a6bdf0 --- /dev/null +++ b/src/RequestInfo.h @@ -0,0 +1,116 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_REQUEST_INFO_H_ +#define _D_REQUEST_INFO_H_ + +#include "common.h" +#include "LogFactory.h" +#include "Option.h" +#include "DownloadEngine.h" +#include "Util.h" +#include "Checksum.h" +#include <signal.h> + +class FileInfo { +public: + string filename; + long long int length; + Checksum checksum; +public: + FileInfo():length(0) {} + ~FileInfo() {} + + bool isEmpty() const { + return filename.size() == 0 && length == 0; + } + + bool checkReady() const { +#ifdef ENABLE_MESSAGE_DIGEST + return !isEmpty() && !checksum.isEmpty(); +#else + return false; +#endif // ENABLE_MESSAGE_DIGEST + } + + bool check() const { +#ifdef ENABLE_MESSAGE_DIGEST + unsigned char md[MAX_MD_LENGTH]; + Util::fileChecksum(filename, md, checksum.getDigestAlgo()); + return Util::toHex(md, + MessageDigestContext::digestLength(checksum.getDigestAlgo())) + == checksum.getMessageDigest(); +#else + return false; +#endif // ENABLE_MESSAGE_DIGEST + } + + bool isTorrentFile() const { + return Util::endsWith(filename, ".torrent"); + } + + bool isMetalinkFile() const { + return Util::endsWith(filename, ".metalink"); + } +}; + +class RequestInfo { +protected: + const Option* op; + const Logger* logger; + Checksum checksum; + FileInfo fileInfo; + bool fail; + + void printDownloadCompeleteMessage(const string& filename) { + printf(_("\nThe download was complete. <%s>\n"), filename.c_str()); + } + + void printDownloadCompeleteMessage() { + printf("\nThe download was complete.\n"); + } + + void printDownloadAbortMessage() { + printf(_("\nThe download was not complete because of errors. Check the log.\n")); + } +public: + RequestInfo(const Option* op): + op(op), + fail(false) + { + logger = LogFactory::getInstance(); + } + virtual ~RequestInfo() {} + + virtual RequestInfo* execute() = 0; + + virtual DownloadEngine* getDownloadEngine() = 0; + + bool isFail() const { return fail; } + + void setChecksum(const Checksum& checksum) { + this->checksum = checksum; + } + const Checksum& getChecksum() const { return checksum; } + const FileInfo& getFileInfo() const { return fileInfo; } +}; + +#endif // _D_REQUEST_INFO_H_ diff --git a/src/RequestSlot.h b/src/RequestSlot.h index 4946ce84..46d6a269 100644 --- a/src/RequestSlot.h +++ b/src/RequestSlot.h @@ -23,7 +23,7 @@ #define _D_REQUEST_SLOT_H_ #include "common.h" -#include "Time.h" +#include "TimeA2.h" class RequestSlot { private: diff --git a/src/ShaVisitor.cc b/src/ShaVisitor.cc index 6807e7c2..e1cbc2c3 100644 --- a/src/ShaVisitor.cc +++ b/src/ShaVisitor.cc @@ -22,60 +22,49 @@ #include "ShaVisitor.h" #include "Util.h" -ShaVisitor::ShaVisitor() { -#ifdef ENABLE_MESSAGE_DIGEST - ctx.setAlgo(MessageDigestContext::ALGO_SHA1); - digestInit(ctx); - digestReset(ctx); -#endif // ENABLE_MESSAGE_DIGEST +ShaVisitor::ShaVisitor(): + ctx(DIGEST_ALGO_SHA1) { + ctx.digestInit(); } ShaVisitor::~ShaVisitor() { -#ifdef ENABLE_MESSAGE_DIGEST - digestFree(ctx); -#endif // ENABLE_MESSAGE_DIGEST + ctx.digestFree(); } void ShaVisitor::visit(const Data* d) { -#ifdef ENABLE_MESSAGE_DIGEST if(d->isNumber()) { - digestUpdate(ctx, "i", 1); + ctx.digestUpdate("i", 1); } else { string lenStr = Util::llitos(d->getLen()); - digestUpdate(ctx, lenStr.c_str(), lenStr.size()); - digestUpdate(ctx, ":", 1); + ctx.digestUpdate(lenStr.c_str(), lenStr.size()); + ctx.digestUpdate(":", 1); } - digestUpdate(ctx, d->getData(), d->getLen()); + ctx.digestUpdate(d->getData(), d->getLen()); if(d->isNumber()) { - digestUpdate(ctx, "e", 1); + ctx.digestUpdate("e", 1); } -#endif // ENABLE_MESSAGE_DIGEST } void ShaVisitor::visit(const Dictionary* d) { -#ifdef ENABLE_MESSAGE_DIGEST - digestUpdate(ctx, "d", 1); + ctx.digestUpdate("d", 1); const Order& v = d->getOrder(); for(Order::const_iterator itr = v.begin(); itr != v.end(); itr++) { string lenStr = Util::llitos(itr->size()); - digestUpdate(ctx, lenStr.c_str(), lenStr.size()); - digestUpdate(ctx, ":", 1); - digestUpdate(ctx, itr->c_str(), itr->size()); + ctx.digestUpdate(lenStr.c_str(), lenStr.size()); + ctx.digestUpdate(":", 1); + ctx.digestUpdate(itr->c_str(), itr->size()); const MetaEntry* e = d->get(*itr); this->visit(e); } - digestUpdate(ctx, "e", 1); -#endif // ENABLE_MESSAGE_DIGEST + ctx.digestUpdate("e", 1); } void ShaVisitor::visit(const List* l) { -#ifdef ENABLE_MESSAGE_DIGEST - digestUpdate(ctx, "l", 1); + ctx.digestUpdate("l", 1); for(MetaList::const_iterator itr = l->getList().begin(); itr != l->getList().end(); itr++) { this->visit(*itr); } - digestUpdate(ctx, "e", 1); -#endif // ENABLE_MESSAGE_DIGEST + ctx.digestUpdate("e", 1); } void ShaVisitor::visit(const MetaEntry* e) { @@ -89,8 +78,6 @@ void ShaVisitor::visit(const MetaEntry* e) { } void ShaVisitor::getHash(unsigned char* hashValue, int& len) { -#ifdef ENABLE_MESSAGE_DIGEST - digestFinal(ctx, hashValue); - len = 20; -#endif // ENABLE_MESSAGE_DIGEST + len = ctx.digestLength(); + ctx.digestFinal(hashValue); } diff --git a/src/ShaVisitor.h b/src/ShaVisitor.h index 87f98d9a..cecced65 100644 --- a/src/ShaVisitor.h +++ b/src/ShaVisitor.h @@ -27,15 +27,11 @@ #include "Dictionary.h" #include "List.h" #include "common.h" -#ifdef ENABLE_MESSAGE_DIGEST #include "messageDigest.h" -#endif // ENABLE_MESSAGE_DIGEST class ShaVisitor : public MetaEntryVisitor { private: -#ifdef ENABLE_MESSAGE_DIGEST MessageDigestContext ctx; -#endif // ENABLE_MESSAGE_DIGEST public: ShaVisitor(); ~ShaVisitor(); diff --git a/src/SleepCommand.h b/src/SleepCommand.h index 06310daa..ecf8e676 100644 --- a/src/SleepCommand.h +++ b/src/SleepCommand.h @@ -24,7 +24,7 @@ #include "DownloadEngine.h" #include "Command.h" -#include "Time.h" +#include "TimeA2.h" class SleepCommand:public Command { private: diff --git a/src/Time.cc b/src/TimeA2.cc index 03a77afa..2d38b2ad 100644 --- a/src/Time.cc +++ b/src/TimeA2.cc @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* copyright --> */ -#include "Time.h" +#include "TimeA2.h" #include "Util.h" Time::Time() { diff --git a/src/Time.h b/src/TimeA2.h index c7cc1fad..c7cc1fad 100644 --- a/src/Time.h +++ b/src/TimeA2.h diff --git a/src/TorrentAutoSaveCommand.h b/src/TorrentAutoSaveCommand.h index a770f4c2..cbf880a9 100644 --- a/src/TorrentAutoSaveCommand.h +++ b/src/TorrentAutoSaveCommand.h @@ -24,7 +24,7 @@ #include "Command.h" #include "TorrentDownloadEngine.h" -#include "Time.h" +#include "TimeA2.h" class TorrentAutoSaveCommand : public Command { private: diff --git a/src/TorrentDownloadEngine.h b/src/TorrentDownloadEngine.h index facbedf7..a2ecc634 100644 --- a/src/TorrentDownloadEngine.h +++ b/src/TorrentDownloadEngine.h @@ -24,7 +24,7 @@ #include "DownloadEngine.h" #include "TorrentMan.h" -#include "Time.h" +#include "TimeA2.h" class TorrentDownloadEngine : public DownloadEngine { private: diff --git a/src/TorrentMan.cc b/src/TorrentMan.cc index 0e97453e..5704bdd5 100644 --- a/src/TorrentMan.cc +++ b/src/TorrentMan.cc @@ -43,7 +43,7 @@ extern PeerHandle nullPeer; -TorrentMan::TorrentMan():bitfield(NULL), +TorrentMan::TorrentMan():bitfield(0), peerEntryIdCounter(0), cuidCounter(0), downloadLength(0), @@ -61,18 +61,16 @@ TorrentMan::TorrentMan():bitfield(NULL), incomplete(0), connections(0), trackers(0), - diskAdaptor(NULL) + req(0), + diskAdaptor(0) { logger = LogFactory::getInstance(); } TorrentMan::~TorrentMan() { - if(bitfield != NULL) { - delete bitfield; - } - if(diskAdaptor != NULL) { - delete diskAdaptor; - } + delete bitfield; + delete diskAdaptor; + delete req; } // TODO do not use this method in application code diff --git a/src/TorrentMan.h b/src/TorrentMan.h index f9201787..219e7483 100644 --- a/src/TorrentMan.h +++ b/src/TorrentMan.h @@ -33,7 +33,7 @@ #include "FileEntry.h" #include "DiskAdaptor.h" #include "Request.h" -#include "Time.h" +#include "TimeA2.h" #include <deque> #include <map> #include <string> diff --git a/src/TorrentRequestInfo.cc b/src/TorrentRequestInfo.cc new file mode 100644 index 00000000..bfc2945c --- /dev/null +++ b/src/TorrentRequestInfo.cc @@ -0,0 +1,81 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#include "TorrentRequestInfo.h" +#include "DownloadEngineFactory.h" +#include "prefs.h" +#include "Util.h" + +extern RequestInfo* requestInfo; +extern void setSignalHander(int signal, void (*handler)(int), int flags); + +void torrentHandler(int signal) { + ((TorrentDownloadEngine*)requestInfo->getDownloadEngine())-> + torrentMan->setHalt(true); +} + +RequestInfo* TorrentRequestInfo::execute() { + if(op->get(PREF_SHOW_FILES) == V_TRUE) { + showFileEntry(); + return 0; + } + e = DownloadEngineFactory::newTorrentConsoleEngine(op, + torrentFile, + targetFiles); + setSignalHander(SIGINT, torrentHandler, SA_RESETHAND); + setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND); + + try { + e->run(); + if(e->torrentMan->downloadComplete()) { + printDownloadCompeleteMessage(); + } + } catch(Exception* e) { + logger->error("Exception caught", e); + delete e; + fail = true; + } + setSignalHander(SIGINT, SIG_DFL, 0); + setSignalHander(SIGTERM, SIG_DFL, 0); + delete e; + + return 0; +} + +// TODO should be const TorrentMan* torrentMan +void TorrentRequestInfo::showFileEntry() +{ + TorrentMan torrentMan; + torrentMan.option = op; + + FileEntries fileEntries = + torrentMan.readFileEntryFromMetaInfoFile(torrentFile); + cout << _("Files:") << endl; + cout << "idx|path/length" << endl; + cout << "===+===========================================================================" << endl; + int count = 1; + for(FileEntries::const_iterator itr = fileEntries.begin(); + itr != fileEntries.end(); count++, itr++) { + printf("%3d|%s\n |%s Bytes\n", count, itr->path.c_str(), + Util::llitos(itr->length, true).c_str()); + cout << "---+---------------------------------------------------------------------------" << endl; + } +} diff --git a/src/TorrentRequestInfo.h b/src/TorrentRequestInfo.h new file mode 100644 index 00000000..f9e61d22 --- /dev/null +++ b/src/TorrentRequestInfo.h @@ -0,0 +1,51 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_TORRENT_REQUEST_INFO_H_ +#define _D_TORRENT_REQUEST_INFO_H_ + +#include "RequestInfo.h" +#include "TorrentDownloadEngine.h" + +class TorrentRequestInfo : public RequestInfo { +private: + string torrentFile; + TorrentDownloadEngine* e; + Strings targetFiles; + + void showFileEntry(); +public: + TorrentRequestInfo(const string& torrentFile, const Option* op): + RequestInfo(op), + torrentFile(torrentFile), + e(0) {} + virtual ~TorrentRequestInfo() {} + + virtual RequestInfo* execute(); + + void setTargetFiles(const Strings& targetFiles) { + this->targetFiles = targetFiles; + } + virtual DownloadEngine* getDownloadEngine() { return e; } + +}; + +#endif // _D_TORRENT_REQUEST_INFO_H_ diff --git a/src/TrackerWatcherCommand.h b/src/TrackerWatcherCommand.h index fd0cccf7..c4da87f5 100644 --- a/src/TrackerWatcherCommand.h +++ b/src/TrackerWatcherCommand.h @@ -24,7 +24,7 @@ #include "Command.h" #include "TorrentDownloadEngine.h" -#include "Time.h" +#include "TimeA2.h" class TrackerWatcherCommand : public Command { private: diff --git a/src/UrlRequestInfo.cc b/src/UrlRequestInfo.cc new file mode 100644 index 00000000..986dbc97 --- /dev/null +++ b/src/UrlRequestInfo.cc @@ -0,0 +1,146 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#include "UrlRequestInfo.h" +#include "TorrentRequestInfo.h" +#include "MetalinkRequestInfo.h" +#include "prefs.h" +#include "DownloadEngineFactory.h" + +extern RequestInfo* requestInfo; +extern void setSignalHander(int signal, void (*handler)(int), int flags); + +void UrlRequestInfo::adjustRequestSize(Requests& requests, + Requests& reserved, + int maxConnections) const +{ + if(maxConnections > 0 && (int)requests.size() > maxConnections) { + copy(requests.begin()+maxConnections, requests.end(), + back_inserter(reserved)); + //insert_iterator<Requests>(reserved, reserved.end())); + requests.erase(requests.begin()+maxConnections, requests.end()); + } +} + +RequestInfo* UrlRequestInfo::createNextRequestInfo() const +{ +#ifdef ENABLE_BITTORRENT + if(op->getAsBool(PREF_FOLLOW_TORRENT) && + Util::endsWith(fileInfo.filename, ".torrent")) { + return new TorrentRequestInfo(fileInfo.filename, op); + } else +#endif // ENABLE_BITTORRENT +#ifdef ENABLE_METALINK + if(op->getAsBool(PREF_FOLLOW_METALINK) && + Util::endsWith(fileInfo.filename, ".metalink")) { + return new MetalinkRequestInfo(fileInfo.filename, op); + } else +#endif // ENABLE_METALINK + { + return 0; + } +} + +void handler(int signal) { + printf(_("\nstopping application...\n")); + fflush(stdout); + requestInfo->getDownloadEngine()->segmentMan->save(); + requestInfo->getDownloadEngine()->segmentMan->diskWriter->closeFile(); + delete requestInfo->getDownloadEngine(); + printf(_("done\n")); + exit(EXIT_SUCCESS); +} + +class CreateRequest { +private: + Requests* requestsPtr; + string referer; + int split; +public: + CreateRequest(Requests* requestsPtr, + const string& referer, + int split) + :requestsPtr(requestsPtr), + referer(referer), + split(split) {} + + void operator()(const string& url) { + for(int s = 1; s <= split; s++) { + Request* req = new Request(); + req->setReferer(referer); + if(req->setUrl(url)) { + requestsPtr->push_back(req); + } else { + fprintf(stderr, _("Unrecognized URL or unsupported protocol: %s\n"), + req->getUrl().c_str()); + delete req; + } + } + } +}; + +RequestInfo* UrlRequestInfo::execute() { + Requests requests; + Requests reserved; + for_each(urls.begin(), urls.end(), + CreateRequest(&requests, + op->get(PREF_REFERER), + op->getAsInt(PREF_SPLIT))); + + adjustRequestSize(requests, reserved, maxConnections); + + e = DownloadEngineFactory::newConsoleEngine(op, requests, reserved); + + setSignalHander(SIGINT, handler, 0); + setSignalHander(SIGTERM, handler, 0); + + RequestInfo* next = 0; + try { + e->run(); + + if(e->segmentMan->finished()) { + printDownloadCompeleteMessage(e->segmentMan->getFilePath()); + fileInfo.filename = e->segmentMan->getFilePath(); + fileInfo.length = e->segmentMan->totalSize; + fileInfo.checksum = checksum; + + next = createNextRequestInfo(); + } else { + e->segmentMan->save(); + e->segmentMan->diskWriter->closeFile(); + printDownloadAbortMessage(); + } + } catch(Exception *e) { + logger->error("Exception caught", e); + delete e; + fail = true; + } + for_each(requests.begin(), requests.end(), Deleter()); + for_each(reserved.begin(), reserved.end(), Deleter()); + + setSignalHander(SIGINT, SIG_DFL, 0); + setSignalHander(SIGTERM, SIG_DFL, 0); + + delete e; + e = 0; + + return next; +} diff --git a/src/UrlRequestInfo.h b/src/UrlRequestInfo.h new file mode 100644 index 00000000..85172b29 --- /dev/null +++ b/src/UrlRequestInfo.h @@ -0,0 +1,52 @@ +/* <!-- copyright */ +/* + * aria2 - a simple utility for downloading files faster + * + * Copyright (C) 2006 Tatsuhiro Tsujikawa + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/* copyright --> */ +#ifndef _D_URL_REQUEST_INFO_H_ +#define _D_URL_REQUEST_INFO_H_ + +#include "RequestInfo.h" + +class UrlRequestInfo : public RequestInfo { +private: + Strings urls; + int maxConnections; + DownloadEngine* e; + + RequestInfo* createNextRequestInfo() const; + void adjustRequestSize(Requests& requests, + Requests& reserved, + int maxConnections) const; +public: + UrlRequestInfo(const Strings& urls, int maxConnections, const Option* op): + RequestInfo(op), + urls(urls), + maxConnections(maxConnections), + e(0) {} + virtual ~UrlRequestInfo() {} + + virtual RequestInfo* execute(); + + virtual DownloadEngine* getDownloadEngine() { + return e; + } +}; + +#endif // _D_URL_REQUEST_INFO_H_ diff --git a/src/Util.cc b/src/Util.cc index 5780889d..846e8976 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -363,21 +363,20 @@ string Util::getContentDispositionFilename(const string& header) { #ifdef ENABLE_MESSAGE_DIGEST void Util::sha1Sum(unsigned char* digest, const void* data, int dataLength) { - MessageDigestContext ctx(MessageDigestContext::ALGO_SHA1); - digestInit(ctx); - digestReset(ctx); - digestUpdate(ctx, data, dataLength); - digestFinal(ctx, digest); - digestFree(ctx); + MessageDigestContext ctx(DIGEST_ALGO_SHA1); + ctx.digestInit(); + ctx.digestUpdate(data, dataLength); + ctx.digestFinal(digest); + ctx.digestFree(); } #endif // ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST void Util::fileChecksum(const string& filename, unsigned char* digest, - MessageDigestContext::HashAlgo algo) { + MessageDigestContext::DigestAlgo algo) { MessageDigestContext ctx(algo); - digestInit(ctx); - digestReset(ctx); + ctx.digestInit(); + ctx.digestReset(); int BUFLEN = 4096; char buf[BUFLEN]; @@ -396,14 +395,14 @@ void Util::fileChecksum(const string& filename, unsigned char* digest, throw new DlAbortEx(EX_FILE_READ, filename.c_str(), strerror(errno)); } } else if(size > 0) { - digestUpdate(ctx, buf, size); + ctx.digestUpdate(buf, size); } if(size < BUFLEN) { break; } } - digestFinal(ctx, digest); - digestFree(ctx); + ctx.digestFinal(digest); + ctx.digestFree(); } #endif // ENABLE_MESSAGE_DIGEST @@ -92,7 +92,7 @@ public: // For sha1, you need 20 bytes. For md5, 16 bytes. #ifdef ENABLE_MESSAGE_DIGEST static void fileChecksum(const string& filename, unsigned char* digest, - MessageDigestContext::HashAlgo algo); + MessageDigestContext::DigestAlgo algo); #endif // ENABLE_MESSAGE_DIGEST #ifdef ENABLE_BITTORRENT diff --git a/src/Xml2MetalinkProcessor.cc b/src/Xml2MetalinkProcessor.cc index bb3281a9..f68f2da2 100644 --- a/src/Xml2MetalinkProcessor.cc +++ b/src/Xml2MetalinkProcessor.cc @@ -88,8 +88,20 @@ MetalinkEntry* Xml2MetalinkProcessor::getEntry(const string& xpath) { entry->version = Util::trim(xpathContent(xpath+"/m:version")); entry->language = Util::trim(xpathContent(xpath+"/m:language")); entry->os = Util::trim(xpathContent(xpath+"/m:os")); - entry->md5 = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]"))); - entry->sha1 = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]"))); +#ifdef ENABLE_MESSAGE_DIGEST + string md; + md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]"))); + if(md.size() > 0) { + entry->checksum.setMessageDigest(md); + entry->checksum.setDigestAlgo(DIGEST_ALGO_SHA1); + } else { + md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]"))); + if(md.size() > 0) { + entry->checksum.setMessageDigest(md); + entry->checksum.setDigestAlgo(DIGEST_ALGO_MD5); + } + } +#endif // ENABLE_MESSAGE_DIGEST for(int index = 1; 1; index++) { MetalinkResource* resource = getResource(xpath+"/m:resources/m:url["+Util::itos(index)+"]"); @@ -121,6 +133,8 @@ MetalinkResource* Xml2MetalinkProcessor::getResource(const string& xpath) { resource->type = MetalinkResource::TYPE_FTP; } else if(type == "http") { resource->type = MetalinkResource::TYPE_HTTP; + } else if(type == "https") { + resource->type = MetalinkResource::TYPE_HTTPS; } else if(type == "bittorrent") { resource->type = MetalinkResource::TYPE_BITTORRENT; } else { diff --git a/src/main.cc b/src/main.cc index 943a54db..09543542 100644 --- a/src/main.cc +++ b/src/main.cc @@ -30,23 +30,11 @@ #include "InitiateConnectionCommandFactory.h" #include "prefs.h" #include "FeatureConfig.h" - -#ifdef ENABLE_BITTORRENT -# include "TorrentConsoleDownloadEngine.h" -# include "TorrentMan.h" -# include "PeerListenCommand.h" -# include "TorrentAutoSaveCommand.h" -# include "TrackerWatcherCommand.h" -# include "TrackerUpdateCommand.h" -# include "HaveEraseCommand.h" -# include "ByteArrayDiskWriter.h" -# include "PeerChokeCommand.h" -#endif // ENABLE_BITTORRENT - -#ifdef ENABLE_METALINK -# include "Xml2MetalinkProcessor.h" -#endif // ENABLE_METALINK - +#include "DownloadEngineFactory.h" +#include "UrlRequestInfo.h" +#include "TorrentRequestInfo.h" +#include "MetalinkRequestInfo.h" +#include "Xml2MetalinkProcessor.h" #include <deque> #include <algorithm> #include <time.h> @@ -69,22 +57,7 @@ extern int optind, opterr, optopt; using namespace std; -bool readyToTorrentMode = false; -string downloadedTorrentFile; -bool readyToMetalinkMode = false; -string downloadedMetalinkFile; - -void printDownloadCompeleteMessage(string filename) { - printf(_("\nThe download was complete. <%s>\n"), filename.c_str()); -} - -void printDownloadCompeleteMessage() { - printf("\nThe download was complete.\n"); -} - -void printDownloadAbortMessage() { - printf(_("\nThe download was not complete because of errors. Check the log.\n")); -} +RequestInfo* requestInfo; void setSignalHander(int signal, void (*handler)(int), int flags) { struct sigaction sigact; @@ -94,39 +67,6 @@ void setSignalHander(int signal, void (*handler)(int), int flags) { sigaction(signal, &sigact, NULL); } -DownloadEngine* e; -#ifdef ENABLE_BITTORRENT -TorrentDownloadEngine* te; -#endif // ENABLE_BITTORRENT - -void handler(int signal) { - printf(_("\nstopping application...\n")); - fflush(stdout); - e->segmentMan->save(); - e->segmentMan->diskWriter->closeFile(); - e->cleanQueue(); - delete e; - printf(_("done\n")); - exit(EXIT_SUCCESS); -} - -#ifdef ENABLE_BITTORRENT -void torrentHandler(int signal) { - te->torrentMan->setHalt(true); -} -#endif // ENABLE_BITTORRENT - -void createRequest(int cuid, const string& url, string referer, Requests& requests) { - Request* req = new Request(); - req->setReferer(referer); - if(req->setUrl(url)) { - requests.push_back(req); - } else { - fprintf(stderr, _("Unrecognized URL or unsupported protocol: %s\n"), req->getUrl().c_str()); - delete(req); - } -} - void showVersion() { cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl; cout << "Copyright (C) 2006 Tatsuhiro Tsujikawa" << endl; @@ -182,7 +122,7 @@ void showUsage() { cout << _(" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n" " K or M(1K = 1024, 1M = 1024K). This\n" " value must be greater than or equal to\n" - " 1024.") << endl; + " 1024. Default: 1M") << endl; cout << _(" --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all\n" " URLs.") << endl; cout << _(" --http-user=USER Set HTTP user. This affects to all URLs.") << endl; @@ -207,6 +147,12 @@ void showUsage() { cout << _(" --ftp-via-http-proxy=METHOD Use HTTP proxy in FTP. METHOD is either 'get' or\n" " 'tunnel'.\n" " Default: tunnel") << endl; + cout << _(" --lowest-speed-limit Close connection if download speed is lower than\n" + " or equal to this value. 0 means aria2 does not\n" + " care lowest speed limit. You can use K or M in\n" + " the same manner as in --min-segment-size option.\n" + " This option does not affect BitTorrent download.\n" + " Default: 0") << endl; #ifdef ENABLE_BITTORRENT cout << _(" -T, --torrent-file=TORRENT_FILE The file path to .torrent file.") << endl; cout << _(" --follow-torrent=true|false Setting this option to false prevents aria2 to\n" @@ -288,52 +234,19 @@ void showUsage() { cout << endl; } -bool normalDownload(const Requests& requests, - const Requests& reserved, - Option* op, - string& downloadedFilename) { - setSignalHander(SIGINT, handler, 0); - setSignalHander(SIGTERM, handler, 0); - - e = new ConsoleDownloadEngine(); - e->option = op; - e->segmentMan = new SegmentMan(); - e->segmentMan->diskWriter = new DefaultDiskWriter(); - e->segmentMan->dir = op->get(PREF_DIR); - e->segmentMan->ufilename = op->get(PREF_OUT); - e->segmentMan->option = op; - e->segmentMan->splitter = new SplitSlowestSegmentSplitter(); - e->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE)); - e->segmentMan->reserved = reserved; - - int cuidCounter = 1; - for(Requests::const_iterator itr = requests.begin(); - itr != requests.end(); - itr++, cuidCounter++) { - e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e)); - } - e->run(); - bool success = false; - if(e->segmentMan->finished()) { - printDownloadCompeleteMessage(e->segmentMan->getFilePath()); - if(Util::endsWith(e->segmentMan->getFilePath(), ".torrent")) { - downloadedTorrentFile = e->segmentMan->getFilePath(); - readyToTorrentMode = true; - } else if(Util::endsWith(e->segmentMan->getFilePath(), ".metalink")) { - downloadedMetalinkFile = e->segmentMan->getFilePath(); - readyToMetalinkMode = true; +long long int getRealSize(char* optarg) { + string::size_type p = string(optarg).find_first_of("KM"); + int mult = 1; + if(p != string::npos) { + if(optarg[p] == 'K') { + mult = 1024; + } else if(optarg[p] == 'M') { + mult = 1024*1024; } - downloadedFilename = e->segmentMan->getFilePath(); - success = true; - } else { - e->segmentMan->save(); - e->segmentMan->diskWriter->closeFile(); - printDownloadAbortMessage(); + optarg[p] = '\0'; } - e->cleanQueue(); - delete e; - - return success; + long long int size = strtoll(optarg, NULL, 10)*mult; + return size; } int main(int argc, char* argv[]) { @@ -343,18 +256,6 @@ int main(int argc, char* argv[]) { bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); #endif // ENABLE_NLS - Integers selectFileIndexes; -#ifdef ENABLE_BITTORRENT - bool followTorrent = true; -#else - bool followTorrent = false; -#endif // ENABLE_BITTORRENT -#ifdef ENABLE_METALINK - bool followMetalink = true; -#else - bool followMetalink = false; -#endif // ENABLE_METALINK - int c; Option* op = new Option(); op->put(PREF_STDOUT_LOG, V_FALSE); @@ -363,6 +264,20 @@ int main(int argc, char* argv[]) { op->put(PREF_DAEMON, V_FALSE); op->put(PREF_LISTEN_PORT, "-1"); op->put(PREF_METALINK_SERVERS, "15"); + op->put(PREF_FOLLOW_TORRENT, +#ifdef ENABLE_BITTORRENT + V_TRUE +#else + V_FALSE +#endif // ENABLE_BITTORRENT + ); + op->put(PREF_FOLLOW_METALINK, +#ifdef ENABLE_METALINK + V_TRUE +#else + V_FALSE +#endif // ENABLE_METALINK + ); op->put(PREF_RETRY_WAIT, "5"); op->put(PREF_TIMEOUT, "60"); op->put(PREF_PEER_CONNECTION_TIMEOUT, "60"); @@ -377,6 +292,7 @@ int main(int argc, char* argv[]) { op->put(PREF_AUTO_SAVE_INTERVAL, "60"); op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE); op->put(PREF_UPLOAD_LIMIT, "0"); + op->put(PREF_LOWEST_SPEED_LIMIT, "4000"); while(1) { int optIndex = 0; int lopt; @@ -403,6 +319,7 @@ int main(int argc, char* argv[]) { { "ftp-via-http-proxy", required_argument, &lopt, 12 }, { "min-segment-size", required_argument, &lopt, 13 }, { "http-proxy-method", required_argument, &lopt, 14 }, + { "lowest-speed-limit", required_argument, &lopt, 200 }, #ifdef ENABLE_BITTORRENT { "torrent-file", required_argument, NULL, 'T' }, { "listen-port", required_argument, &lopt, 15 }, @@ -506,17 +423,7 @@ int main(int argc, char* argv[]) { } break; case 13: { - string::size_type p = string(optarg).find_first_of("KM"); - int mult = 1; - if(p != string::npos) { - if(optarg[p] == 'K') { - mult = 1024; - } else if(optarg[p] == 'M') { - mult = 1024*1024; - } - optarg[p] = '\0'; - } - long long int size = strtoll(optarg, NULL, 10)*mult; + long long int size = getRealSize(optarg); if(size < 1024) { cerr << _("min-segment-size invalid") << endl; showUsage(); @@ -546,9 +453,9 @@ int main(int argc, char* argv[]) { } case 16: if(string(optarg) == "true") { - followTorrent = true; + op->put(PREF_FOLLOW_TORRENT, V_TRUE); } else if(string(optarg) == "false") { - followTorrent = false; + op->put(PREF_FOLLOW_TORRENT, V_FALSE); } else { cerr << _("follow-torrent must be either 'true' or 'false'.") << endl; showUsage(); @@ -580,7 +487,7 @@ int main(int argc, char* argv[]) { break; } case 21: - Util::unfoldRange(optarg, selectFileIndexes); + op->put(PREF_SELECT_FILE, optarg); break; case 100: op->put(PREF_METALINK_VERSION, optarg); @@ -593,15 +500,25 @@ int main(int argc, char* argv[]) { break; case 103: if(string(optarg) == "true") { - followMetalink = true; + op->put(PREF_FOLLOW_METALINK, V_TRUE); } else if(string(optarg) == "false") { - followMetalink = false; + op->put(PREF_FOLLOW_METALINK, V_FALSE); } else { cerr << _("follow-metalink must be either 'true' or 'false'.") << endl; showUsage(); exit(EXIT_FAILURE); } break; + case 200: { + int limit = getRealSize(optarg); + if(limit < 0) { + cerr << _("lowest-speed-limit must be greater than or equal to 0") << endl; + showUsage(); + exit(EXIT_FAILURE); + } + op->put(PREF_LOWEST_SPEED_LIMIT, Util::itos(limit)); + break; + } } break; } @@ -720,190 +637,58 @@ int main(int argc, char* argv[]) { } // make sure logger is configured properly. try { - LogFactory::getInstance(); - } catch(Exception* ex) { - cerr << ex->getMsg() << endl; - delete ex; - exit(EXIT_FAILURE); - } + Logger* logger = LogFactory::getInstance(); + logger->info("%s %s", PACKAGE, PACKAGE_VERSION); + logger->info("Logging started."); - setSignalHander(SIGPIPE, SIG_IGN, 0); + setSignalHander(SIGPIPE, SIG_IGN, 0); - if(!op->defined(PREF_TORRENT_FILE) && !op->defined(PREF_METALINK_FILE)) { - Requests requests; - int cuidCounter = 1; - for(Strings::const_iterator itr = args.begin(); itr != args.end(); itr++) { - for(int s = 1; s <= op->getAsInt(PREF_SPLIT); s++) { - createRequest(cuidCounter, *itr, op->get(PREF_REFERER), requests); - cuidCounter++; + requestInfo = 0; +#ifdef ENABLE_BITTORRENT + if(op->defined(PREF_TORRENT_FILE)) { + requestInfo = new TorrentRequestInfo(op->get(PREF_TORRENT_FILE), + op); + Strings targetFiles; + if(op->defined(PREF_TORRENT_FILE) && !args.empty()) { + targetFiles = args; } + ((TorrentRequestInfo*)requestInfo)->setTargetFiles(targetFiles); } - setSignalHander(SIGINT, handler, 0); - setSignalHander(SIGTERM, handler, 0); - - Requests reserved; - string downloadedFilename; - normalDownload(requests, reserved, op, downloadedFilename); - - for_each(requests.begin(), requests.end(), Deleter()); - for_each(reserved.begin(), reserved.end(), Deleter()); - requests.clear(); - } + else +#endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK - if(op->defined(PREF_METALINK_FILE) || - followMetalink && readyToMetalinkMode) { - string targetMetalinkFile = op->defined(PREF_METALINK_FILE) ? - op->get(PREF_METALINK_FILE) : downloadedMetalinkFile; - Xml2MetalinkProcessor proc; - Metalinker* metalinker = proc.parseFile(targetMetalinkFile); - - MetalinkEntry* entry = - metalinker->queryEntry(op->get(PREF_METALINK_VERSION), - op->get(PREF_METALINK_LANGUAGE), - op->get(PREF_METALINK_OS)); - if(entry == NULL) { - printf("No file matched with your preference.\n"); - exit(EXIT_FAILURE); - } - entry->dropUnsupportedResource(); - entry->reorderResourcesByPreference(); - Requests requests; - int cuidCounter = 1; - for(MetalinkResources::const_iterator itr = entry->resources.begin(); - itr != entry->resources.end(); itr++) { - MetalinkResource* resource = *itr; - for(int s = 1; s <= op->getAsInt(PREF_SPLIT); s++) { - createRequest(cuidCounter, resource->url, - op->get(PREF_REFERER), requests); - cuidCounter++; - } - } - Requests reserved; - int maxConnection = - op->getAsInt(PREF_METALINK_SERVERS)*op->getAsInt(PREF_SPLIT); - if((int)requests.size() > maxConnection) { - copy(requests.begin()+maxConnection, requests.end(), - insert_iterator<Requests>(reserved, reserved.end())); - requests.erase(requests.begin()+maxConnection, requests.end()); - } - - setSignalHander(SIGINT, handler, 0); - setSignalHander(SIGTERM, handler, 0); - - string downloadedFilename; - bool success = normalDownload(requests, reserved, op, downloadedFilename); - - for_each(requests.begin(), requests.end(), Deleter()); - for_each(reserved.begin(), reserved.end(), Deleter()); - requests.clear(); + if(op->defined(PREF_METALINK_FILE)) { + requestInfo = new MetalinkRequestInfo(op->get(PREF_METALINK_FILE), + op); + } else +#endif // ENABLE_METALINK + { + requestInfo = new UrlRequestInfo(args, 0, op); + } - if(success) { -#ifdef ENABLE_MESSAGE_DIGEST - if(entry->check(downloadedFilename)) { - printf("checksum OK.\n"); - } else { - printf("checksum ERROR.\n"); + while(requestInfo) { + RequestInfo* next = requestInfo->execute(); + if(requestInfo->isFail()) { + delete requestInfo; exit(EXIT_FAILURE); } -#endif // ENABLE_MESSAGE_DIGEST - } - - delete metalinker; - } -#endif // ENABLE_METALINK -#ifdef ENABLE_BITTORRENT - if(op->defined(PREF_TORRENT_FILE) || - followTorrent && readyToTorrentMode) { - try { - //op->put(PREF_MAX_TRIES, "0"); - setSignalHander(SIGINT, torrentHandler, SA_RESETHAND); - setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND); - - Request* req = new Request(); - req->isTorrent = true; - req->setTrackerEvent(Request::STARTED); - te = new TorrentConsoleDownloadEngine(); - te->option = op; - ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter(); - te->segmentMan = new SegmentMan(); - te->segmentMan->diskWriter = byteArrayDiskWriter; - te->segmentMan->option = op; - te->segmentMan->splitter = new SplitSlowestSegmentSplitter(); - te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE)); - te->torrentMan = new TorrentMan(); - te->torrentMan->setStoreDir(op->get(PREF_DIR)); - te->torrentMan->option = op; - te->torrentMan->req = req; - string targetTorrentFile = op->defined(PREF_TORRENT_FILE) ? - op->get(PREF_TORRENT_FILE) : downloadedTorrentFile; - if(op->get(PREF_SHOW_FILES) == V_TRUE) { - FileEntries fileEntries = - te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile); - cout << _("Files:") << endl; - cout << "idx|path/length" << endl; - cout << "===+===========================================================================" << endl; - int count = 1; - for(FileEntries::const_iterator itr = fileEntries.begin(); - itr != fileEntries.end(); count++, itr++) { - printf("%3d|%s\n |%s Bytes\n", count, itr->path.c_str(), - Util::llitos(itr->length, true).c_str()); - cout << "---+---------------------------------------------------------------------------" << endl; - } - exit(EXIT_SUCCESS); - } else { - if(selectFileIndexes.empty()) { - Strings targetFiles; - if(op->defined(PREF_TORRENT_FILE) && !args.empty()) { - targetFiles = args; - } - te->torrentMan->setup(targetTorrentFile, targetFiles); + if(requestInfo->getFileInfo().checkReady()) { + if(requestInfo->getFileInfo().check()) { + printf("checksum OK.\n"); } else { - te->torrentMan->setup(targetTorrentFile, selectFileIndexes); + // TODO + printf("checksum ERROR.\n"); + exit(EXIT_FAILURE); } } - PeerListenCommand* listenCommand = - new PeerListenCommand(te->torrentMan->getNewCuid(), te); - int port; - int listenPort = op->getAsInt(PREF_LISTEN_PORT); - if(listenPort == -1) { - port = listenCommand->bindPort(6881, 6999); - } else { - port = listenCommand->bindPort(listenPort, listenPort); - } - if(port == -1) { - printf(_("Errors occurred while binding port.\n")); - exit(EXIT_FAILURE); - } - te->torrentMan->setPort(port); - te->commands.push_back(listenCommand); - - te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(), - te, - te->torrentMan->minInterval)); - te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(), - te)); - te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(), - te, - op->getAsInt(PREF_AUTO_SAVE_INTERVAL))); - te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(), - 10, te)); - te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(), - te, 10)); - te->run(); - - if(te->torrentMan->downloadComplete()) { - printDownloadCompeleteMessage(); - } - delete req; - te->cleanQueue(); - delete te; - } catch(Exception* ex) { - cerr << ex->getMsg() << endl; - delete ex; - exit(EXIT_FAILURE); + delete requestInfo; + requestInfo = next; } + } catch(Exception* ex) { + cerr << ex->getMsg() << endl; + delete ex; + exit(EXIT_FAILURE); } -#endif // ENABLE_BITTORRENT delete op; LogFactory::release(); #ifdef HAVE_LIBGNUTLS diff --git a/src/messageDigest.h b/src/messageDigest.h index b084f07b..c14c4600 100644 --- a/src/messageDigest.h +++ b/src/messageDigest.h @@ -26,6 +26,8 @@ #ifdef ENABLE_SSL +#define MAX_MD_LENGTH (16+20) + #ifdef HAVE_LIBSSL #include <openssl/evp.h> #endif // HAVE_LIBSSL @@ -36,73 +38,80 @@ class MessageDigestContext { public: - enum HashAlgo { - ALGO_MD5, - ALGO_SHA1 - }; #ifdef HAVE_LIBSSL - EVP_MD_CTX ctx; - const EVP_MD* algo; + typedef const EVP_MD* DigestAlgo; +# define DIGEST_ALGO_MD5 EVP_md5() +# define DIGEST_ALGO_SHA1 EVP_sha1() #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT - gcry_md_hd_t ctx; - int algo; + typedef int DigestAlgo; +# define DIGEST_ALGO_MD5 GCRY_MD_MD5 +# define DIGEST_ALGO_SHA1 GCRY_MD_SHA1 #endif // HAVE_LIBGCRYPT - - MessageDigestContext() {} - MessageDigestContext(HashAlgo algo) { - setAlgo(algo); - } - - void setAlgo(HashAlgo algo) { - switch(algo) { - case ALGO_MD5: +private: #ifdef HAVE_LIBSSL - this->algo = EVP_md5(); -#endif // HAVE_LIBSSL -#ifdef HAVE_LIBGCRYPT - this->algo = GCRY_MD_MD5; -#endif // HAVE_LIBGCRYPT - break; - case ALGO_SHA1: -#ifdef HAVE_LIBSSL - this->algo = EVP_sha1(); + EVP_MD_CTX ctx; #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT - this->algo = GCRY_MD_SHA1; -#endif // HAVE_LIBGCRYPT - break; - default: - break; - } - } -}; + gcry_md_hd_t ctx; +#endif // HAVE_LIBGCRYPT + DigestAlgo algo; +public: + MessageDigestContext(): + algo(DIGEST_ALGO_SHA1) {} + MessageDigestContext(DigestAlgo algo): + algo(algo) {} #ifdef HAVE_LIBSSL -#define digestInit(CTX) EVP_MD_CTX_init(&CTX.ctx) -#define digestReset(CTX) EVP_DigestInit_ex(&CTX.ctx, CTX.algo, NULL) -#define digestUpdate(CTX, DATA, LENGTH) EVP_DigestUpdate(&CTX.ctx, DATA, LENGTH) -#define digestFinal(CTX, HASH) \ -{\ -int len;\ -EVP_DigestFinal_ex(&CTX.ctx, HASH, (unsigned int*)&len);\ -} -#define digestFree(CTX) EVP_MD_CTX_cleanup(&CTX.ctx) - + void digestInit() { + EVP_MD_CTX_init(&ctx); + digestReset(); + } + void digestReset() { + EVP_DigestInit_ex(&ctx, algo, 0); + } + void digestUpdate(const void* data, int length) { + EVP_DigestUpdate(&ctx, data, length); + } + void digestFinal(unsigned char* md) { + int len; + EVP_DigestFinal_ex(&ctx, md, (unsigned int*)&len); + } + void digestFree() { + EVP_MD_CTX_cleanup(&ctx); + } + int digestLength() const { + return digestLength(algo); + } + static int digestLength(DigestAlgo algo) { + return EVP_MD_size(algo); + } #endif // HAVE_LIBSSL #ifdef HAVE_LIBGCRYPT -#define digestInit(CTX) gcry_md_open(&CTX.ctx, CTX.algo, 0) -#define digestReset(CTX) gcry_md_reset(CTX.ctx) -#define digestUpdate(CTX, DATA, LENGTH) gcry_md_write(CTX.ctx, DATA, LENGTH) -#define digestFinal(CTX, HASH) \ -{\ -gcry_md_final(CTX.ctx);\ -memcpy(HASH, gcry_md_read(CTX.ctx, 0), gcry_md_get_algo_dlen(CTX.algo));\ -} -#define digestFree(CTX) gcry_md_close(CTX.ctx) + void digestInit() { + gcry_md_open(&ctx, algo, 0); + } + void digestReset() { + gcry_md_reset(ctx); + } + void digestUpdate(const void* data, int length) { + gcry_md_write(ctx, data, length); + } + void digestFinal(unsigned char* md) { + gcry_md_final(ctx); + memcpy(md, gcry_md_read(ctx, 0), gcry_md_get_algo_dlen(algo)); + } + void digestFree() { + gcry_md_close(ctx); + } + int digestLength() const { + return digestLength(algo); + } + static int digestLength(DigestAlgo algo) { + return gcry_md_get_algo_dlen(algo); + } #endif // HAVE_LIBGCRYPT - +}; #endif // ENABLE_SSL - #endif // _D_MESSAGE_DIGEST_H_ diff --git a/src/prefs.h b/src/prefs.h index 6b48cb63..83fcaba7 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -57,6 +57,8 @@ #define PREF_DAEMON "daemon" // value: a string #define PREF_REFERER "referer" +// value' 1*digit +#define PREF_LOWEST_SPEED_LIMIT "lowest_speed_limit" /** * FTP related preferences @@ -116,6 +118,10 @@ #define PREF_TORRENT_FILE "torrent_file" // values: 1*digit #define PREF_LISTEN_PORT "listen_port" +// values: true | false +#define PREF_FOLLOW_TORRENT "follow_torrent" +// values: 1*digit *( (,|-) 1*digit) +#define PREF_SELECT_FILE "select_file" /** * Metalink related preferences @@ -130,5 +136,7 @@ #define PREF_METALINK_OS "metalink_os" // values: 1*digit #define PREF_METALINK_SERVERS "metalink_servers" +// values: true | false +#define PREF_FOLLOW_METALINK "follow_metalink" #endif // _D_PREFS_H_ |
