This commit is contained in:
Tatsuhiro Tsujikawa 2006-02-22 11:18:47 +00:00
parent 28fc3405dd
commit ebdb4b86cf
13 changed files with 110 additions and 48 deletions

View File

@ -8,6 +8,8 @@
* main.cc: The value of --http-auth-scheme option is chagned from * main.cc: The value of --http-auth-scheme option is chagned from
'BASIC' to 'basic' 'BASIC' to 'basic'
* main.cc: Added --timeout command-line option. * main.cc: Added --timeout command-line option.
* main.cc: Added --min-segment-size command-line option.
* main.cc: Added --max-retries command-line option.
* prefs.h: option string constants are now defined in prefs.h * prefs.h: option string constants are now defined in prefs.h
2006-02-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> 2006-02-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

1
TODO
View File

@ -4,3 +4,4 @@
* Add SSL client cert support * Add SSL client cert support
* Better HTTP status handling * Better HTTP status handling
* Download files listed in a specifed file. * Download files listed in a specifed file.
* check MD5 checksum

View File

@ -102,7 +102,8 @@ bool AbstractCommand::execute() {
delete(err); delete(err);
//req->resetUrl(); //req->resetUrl();
req->addTryCount(); req->addTryCount();
if(req->getTryCount() >= e->option->getAsInt(PREF_MAX_TRY)) { if(e->option->getAsInt(PREF_MAX_TRIES) != 0 &&
req->getTryCount() >= e->option->getAsInt(PREF_MAX_TRIES)) {
e->logger->error(MSG_MAX_TRY, cuid, req->getTryCount()); e->logger->error(MSG_MAX_TRY, cuid, req->getTryCount());
return true; return true;
} else { } else {

View File

@ -47,8 +47,8 @@ public:
queue<Command*> commands; queue<Command*> commands;
SegmentMan* segmentMan; SegmentMan* segmentMan;
DiskWriter* diskWriter; DiskWriter* diskWriter;
Logger* logger; const Logger* logger;
Option* option; const Option* option;
DownloadEngine(); DownloadEngine();
~DownloadEngine(); ~DownloadEngine();

View File

@ -110,8 +110,12 @@ void FtpConnection::sendRetr() const {
int FtpConnection::getStatus(string response) const { int FtpConnection::getStatus(string response) const {
int status; int status;
// TODO we must handle when the response is not like "%d %*s" // When the response is not like "%d %*s",
// In this case, we return 0 // we return 0.
if(response.find_first_not_of("0123456789") != 3
|| response.find(" ") != 3) {
return 0;
}
if(sscanf(response.c_str(), "%d %*s", &status) == 1) { if(sscanf(response.c_str(), "%d %*s", &status) == 1) {
return status; return status;
} else { } else {

View File

@ -65,10 +65,13 @@ bool HttpResponseCommand::executeInternal(Segment seg) {
return handleDefaultEncoding(headers); return handleDefaultEncoding(headers);
} }
} else { } else {
// TODO we must check headers["size"] == e->segmentMan->totalSize here
if(req->getFile() != e->segmentMan->filename) { if(req->getFile() != e->segmentMan->filename) {
throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str()); throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str());
} }
long long int size = headers.getFirstAsLLInt("Content-Length");
if(e->segmentMan->totalSize != size) {
throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size);
}
createHttpDownloadCommand(); createHttpDownloadCommand();
return true; return true;
} }
@ -99,9 +102,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
bool segFileExists = e->segmentMan->segmentFileExists(); bool segFileExists = e->segmentMan->segmentFileExists();
e->segmentMan->downloadStarted = true; e->segmentMan->downloadStarted = true;
if(segFileExists) { if(segFileExists) {
e->diskWriter->openExistingFile(e->segmentMan->getFilePath()); e->diskWriter->openExistingFile(e->segmentMan->getFilePath());
// we must check headers["size"] == e->segmentMan->totalSize here
if(e->segmentMan->totalSize != size) { if(e->segmentMan->totalSize != size) {
return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size);
} }

View File

@ -50,3 +50,12 @@ int Option::getAsInt(const string& name) const {
return (int)strtol((*itr).second.c_str(), NULL, 10); return (int)strtol((*itr).second.c_str(), NULL, 10);
} }
} }
long long int Option::getAsLLInt(const string& name) const {
map<string, string>::const_iterator itr = table.find(name);
if(itr == table.end()) {
return 0;
} else {
return (int)strtoll((*itr).second.c_str(), NULL, 10);
}
}

View File

@ -38,6 +38,7 @@ public:
bool defined(const string& name) const; bool defined(const string& name) const;
string get(const string& name) const; string get(const string& name) const;
int getAsInt(const string& name) const; int getAsInt(const string& name) const;
long long int getAsLLInt(const string& name) const;
}; };
#endif // _D_OPTION_H_ #endif // _D_OPTION_H_

View File

@ -79,14 +79,12 @@ bool Request::parseUrl(string url) {
Util::split(hostAndPort, url.substr(hp, hep-hp), ':'); Util::split(hostAndPort, url.substr(hp, hep-hp), ':');
host = hostAndPort.first; host = hostAndPort.first;
if(hostAndPort.second != "") { if(hostAndPort.second != "") {
// TODO rewrite this using strtoul function. If strtoul fails,
// return false.
port = (int)strtol(hostAndPort.second.c_str(), NULL, 10); port = (int)strtol(hostAndPort.second.c_str(), NULL, 10);
if(!(0 < port && port <= 65535)) { if(!(0 < port && port <= 65535)) {
return false; return false;
} }
} else { } else {
// If port is not specified, then we leave it 0. // If port is not specified, then we set it to default port of its protocol..
port = defPort; port = defPort;
} }
string::size_type direp = url.find_last_of("/"); string::size_type direp = url.find_last_of("/");

View File

@ -28,6 +28,7 @@
#include "Util.h" #include "Util.h"
#include "File.h" #include "File.h"
#include "message.h" #include "message.h"
#include "prefs.h"
SegmentMan::SegmentMan():totalSize(0),isSplittable(true),downloadStarted(false),dir(".") {} SegmentMan::SegmentMan():totalSize(0),isSplittable(true),downloadStarted(false),dir(".") {}
@ -85,7 +86,7 @@ bool SegmentMan::getSegment(Segment& seg, int cuid) {
if(s.finish) { if(s.finish) {
continue; continue;
} }
if(s.ep-(s.sp+s.ds) > 524288) { if(s.ep-(s.sp+s.ds) > option->getAsLLInt(PREF_MIN_SEGMENT_SIZE)) {
long long int nep = (s.ep-(s.sp+s.ds))/2+(s.sp+s.ds); long long int nep = (s.ep-(s.sp+s.ds))/2+(s.sp+s.ds);
//nseg = { cuid, nep+1, s.ep, 0, false }; //nseg = { cuid, nep+1, s.ep, 0, false };
seg.cuid = cuid; seg.cuid = cuid;

View File

@ -26,6 +26,7 @@
#include "common.h" #include "common.h"
#include "Logger.h" #include "Logger.h"
#include "Segment.h" #include "Segment.h"
#include "Option.h"
using namespace std; using namespace std;
@ -81,6 +82,7 @@ public:
string ufilename; string ufilename;
const Logger* logger; const Logger* logger;
const Option* option;
SegmentMan(); SegmentMan();
~SegmentMan(); ~SegmentMan();

View File

@ -101,40 +101,45 @@ void showUsage() {
cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl; cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl;
cout << endl; cout << endl;
cout << "Options:" << endl; cout << "Options:" << endl;
cout << " -d, --dir=DIR The directory to store downloaded file." << endl; cout << " -d, --dir=DIR The directory to store downloaded file." << endl;
cout << " -o, --out=FILE The file name for downloaded file." << endl; cout << " -o, --out=FILE The file name for downloaded file." << endl;
cout << " -l, --log=LOG The file path to store log. If '-' is specified," << endl; cout << " -l, --log=LOG The file path to store log. If '-' is specified," << endl;
cout << " log is written to stdout." << endl; cout << " log is written to stdout." << endl;
cout << " -D, --daemon Run as daemon." << endl; cout << " -D, --daemon Run as daemon." << endl;
cout << " -s, --split=N Download a file using s connections. s must be" << endl; cout << " -s, --split=N Download a file using s connections. s must be" << endl;
cout << " between 1 and 5. If this option is specified the" << endl; cout << " between 1 and 5. If this option is specified the" << endl;
cout << " first URL is used, and the other URLs are ignored." << endl; cout << " first URL is used, and the other URLs are ignored." << endl;
cout << " --retry-wait=SEC Set amount of time in second between requests" << endl; cout << " --retry-wait=SEC Set amount of time in second between requests" << endl;
cout << " for errors. Specify a value between 0 and 60." << endl; cout << " for errors. Specify a value between 0 and 60." << endl;
cout << " -t, --timeout=SEC Set timeout in second." << endl; cout << " Default: 5" << endl;
cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl; cout << " -t, --timeout=SEC Set timeout in second. Default: 60" << endl;
cout << " URLs." << endl; cout << " -m, --max-tries=N Set number of tries. 0 means unlimited." << endl;
cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl; cout << " Default: 5" << endl;
cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl; cout << " --min-segment-size=SIZE[K|M] Set minimum segment size. You can append" << endl;
cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl; cout << " K or M(1K = 1024, 1M = 1024K)." << endl;
cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl; cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl;
cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic" << endl; cout << " URLs." << endl;
cout << " is the only supported scheme. You MUST specify" << endl; cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl;
cout << " this option in order to use HTTP authentication" << endl; cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl;
cout << " as well as --http-proxy option." << endl; cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl;
cout << " --referer=REFERER Set Referer. This affects to all URLs." << endl; cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl;
cout << " --ftp-user=USER Set FTP user. This affects to all URLs." << endl; cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic" << endl;
cout << " Default: anonymous" << endl; cout << " is the only supported scheme. You MUST specify" << endl;
cout << " --ftp-passwd=PASSWD Set FTP password. This affects to all URLs." << endl; cout << " this option in order to use HTTP authentication" << endl;
cout << " Default: ARIA2USER@" << endl; cout << " as well as --http-proxy option." << endl;
cout << " --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'" << endl; cout << " --referer=REFERER Set Referer. This affects to all URLs." << endl;
cout << " or 'ascii'." << endl; cout << " --ftp-user=USER Set FTP user. This affects to all URLs." << endl;
cout << " Default: binary" << endl; cout << " Default: anonymous" << endl;
cout << " -p, --ftp-pasv Use passive mode in FTP." << endl; cout << " --ftp-passwd=PASSWD Set FTP password. This affects to all URLs." << endl;
cout << " --ftp-via-http-proxy=WAY Use HTTP proxy in FTP. WAY is either 'get' or" << endl; cout << " Default: ARIA2USER@" << endl;
cout << " 'tunnel'." << endl; cout << " --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'" << endl;
cout << " -v, --version Print the version number and exit." << endl; cout << " or 'ascii'." << endl;
cout << " -h, --help Print this message and exit." << endl; cout << " Default: binary" << endl;
cout << " -p, --ftp-pasv Use passive mode in FTP." << endl;
cout << " --ftp-via-http-proxy=WAY Use HTTP proxy in FTP. WAY is either 'get' or" << endl;
cout << " 'tunnel'." << endl;
cout << " -v, --version Print the version number and exit." << endl;
cout << " -h, --help Print this message and exit." << endl;
cout << endl; cout << endl;
cout << "URL:" << endl; cout << "URL:" << endl;
cout << " You can specify multiple URLs. All URLs must point to the same file" << endl; cout << " You can specify multiple URLs. All URLs must point to the same file" << endl;
@ -166,6 +171,8 @@ int main(int argc, char* argv[]) {
Option* op = new Option(); Option* op = new Option();
op->put(PREF_RETRY_WAIT, "5"); op->put(PREF_RETRY_WAIT, "5");
op->put(PREF_TIMEOUT, "60"); op->put(PREF_TIMEOUT, "60");
op->put(PREF_MIN_SEGMENT_SIZE, "1048576");// 1M
op->put(PREF_MAX_TRIES, "5");
op->put(PREF_FTP_USER, "anonymous"); op->put(PREF_FTP_USER, "anonymous");
op->put(PREF_FTP_PASSWD, "ARIA2USER@"); op->put(PREF_FTP_PASSWD, "ARIA2USER@");
op->put(PREF_FTP_TYPE, V_BINARY); op->put(PREF_FTP_TYPE, V_BINARY);
@ -182,6 +189,7 @@ int main(int argc, char* argv[]) {
{ "log", required_argument, NULL, 'l' }, { "log", required_argument, NULL, 'l' },
{ "split", required_argument, NULL, 's' }, { "split", required_argument, NULL, 's' },
{ "timeout", required_argument, NULL, 't' }, { "timeout", required_argument, NULL, 't' },
{ "max-retries", required_argument, NULL, 'm' },
{ "http-proxy", required_argument, &lopt, 1 }, { "http-proxy", required_argument, &lopt, 1 },
{ "http-user", required_argument, &lopt, 2 }, { "http-user", required_argument, &lopt, 2 },
{ "http-passwd", required_argument, &lopt, 3 }, { "http-passwd", required_argument, &lopt, 3 },
@ -195,11 +203,12 @@ int main(int argc, char* argv[]) {
{ "ftp-type", required_argument, &lopt, 11 }, { "ftp-type", required_argument, &lopt, 11 },
{ "ftp-pasv", no_argument, NULL, 'p' }, { "ftp-pasv", no_argument, NULL, 'p' },
{ "ftp-via-http-proxy", required_argument, &lopt, 12 }, { "ftp-via-http-proxy", required_argument, &lopt, 12 },
{ "min-segment-size", required_argument, &lopt, 13 },
{ "version", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
c = getopt_long(argc, argv, "Dd:o:l:s:pt:vh", longOpts, &optIndex); c = getopt_long(argc, argv, "Dd:o:l:s:pt:m:vh", longOpts, &optIndex);
if(c == -1) { if(c == -1) {
break; break;
} }
@ -278,6 +287,26 @@ int main(int argc, char* argv[]) {
exit(1); exit(1);
} }
break; 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;
if(size <= 0) {
cerr << "min-segment-size invalid" << endl;
showUsage();
exit(1);
}
op->put(PREF_MIN_SEGMENT_SIZE, Util::llitos(size));
break;
}
} }
break; break;
} }
@ -316,6 +345,16 @@ int main(int argc, char* argv[]) {
} }
break; break;
} }
case 'm': {
int retries = (int)strtol(optarg, NULL, 10);
if(retries < 0) {
cerr << "max-retires invalid" << endl;
showUsage();
exit(1);
}
op->put(PREF_MAX_TRIES, Util::itos(retries));
break;
}
case 'p': case 'p':
op->put(PREF_FTP_PASV_ENABLED, V_TRUE); op->put(PREF_FTP_PASV_ENABLED, V_TRUE);
break; break;
@ -363,6 +402,7 @@ int main(int argc, char* argv[]) {
e->segmentMan->dir = dir; e->segmentMan->dir = dir;
e->segmentMan->ufilename = ufilename; e->segmentMan->ufilename = ufilename;
e->segmentMan->logger = logger; e->segmentMan->logger = logger;
e->segmentMan->option = op;
vector<Request*> requests; vector<Request*> requests;
if(split > 0) { if(split > 0) {
for(int i = 1; i <= split; i++) { for(int i = 1; i <= split; i++) {

View File

@ -36,7 +36,9 @@
// values: 1*digit // values: 1*digit
#define PREF_TIMEOUT "timeout" #define PREF_TIMEOUT "timeout"
// values: 1*digit // values: 1*digit
#define PREF_MAX_TRY "max_try" #define PREF_MAX_TRIES "max_try"
// values: 1*digit
#define PREF_MIN_SEGMENT_SIZE "min_segment_size"
/** /**
* FTP related preferences * FTP related preferences