From 5a8710676d58be3b3f3606993e802c6a075dbd89 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 21 Feb 2006 12:27:17 +0000 Subject: --- src/HttpResponseCommand.cc | 50 +++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'src/HttpResponseCommand.cc') diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 22c7fa71..1fd273bb 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -28,10 +28,12 @@ HttpResponseCommand::HttpResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s): AbstractCommand(cuid, req, e, s) { - AbstractCommand::checkSocketIsReadable = true; + http = new HttpConnection(cuid, socket, req, e->option, e->logger); } -HttpResponseCommand::~HttpResponseCommand() {} +HttpResponseCommand::~HttpResponseCommand() { + delete http; +} bool HttpResponseCommand::executeInternal(Segment seg) { if(SEGMENT_EQUAL(req->seg, seg) == false) { @@ -39,26 +41,30 @@ bool HttpResponseCommand::executeInternal(Segment seg) { return prepareForRetry(0); } HttpHeader headers; - HttpConnection httpConnection(cuid, socket, e->option, e->logger); - int status = httpConnection.receiveResponse(headers); + int status = http->receiveResponse(headers); + if(status == 0) { + // didn't receive header fully + e->commands.push(this); + return false; + } // check HTTP status number checkResponse(status, seg); retrieveCookie(headers); // check whether Location header exists. If it does, update request object // with redirected URL. // then establish a connection to the new host and port - if(headers.count("Location")) { - return handleRedirect((*headers.find("Location")).second, headers); + if(headers.defined("Location")) { + return handleRedirect(headers.getFirst("Location"), headers); } if(!e->segmentMan->downloadStarted) { string transferEncoding; - headers.find("Transfer-Encoding"); - if(headers.count("Transfer-Encoding")) { - return handleOtherEncoding((*headers.find("Transfer-Encoding")).second, headers); + if(headers.defined("Transfer-Encoding")) { + return handleOtherEncoding(headers.getFirst("Transfer-Encoding"), headers); } else { return handleDefaultEncoding(headers); } } else { + // TODO we must check headers["size"] == e->segmentMan->totalSize here if(req->getFile() != e->segmentMan->filename) { throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str()); } @@ -83,28 +89,25 @@ bool HttpResponseCommand::handleRedirect(string url, const HttpHeader& headers) } bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { - long long int size; - if(headers.count("Content-Length") == 0) { - size = 0; - } else { - size = STRTOLL((*headers.find("Content-Length")).second.c_str()); - if(size == LONG_LONG_MAX || size == LONG_LONG_MIN) { - throw new DlAbortEx(EX_TOO_LARGE_FILE, size); - } + long long int size = headers.getFirstAsLLInt("Content-Length"); + if(size == LONG_LONG_MAX || size == LONG_LONG_MIN || size < 0) { + throw new DlAbortEx(EX_TOO_LARGE_FILE, size); } e->segmentMan->isSplittable = !(size == 0); e->segmentMan->filename = req->getFile(); - e->segmentMan->totalSize = size; bool segFileExists = e->segmentMan->segmentFileExists(); e->segmentMan->downloadStarted = true; if(segFileExists) { - e->segmentMan->load(); + e->diskWriter->openExistingFile(e->segmentMan->getFilePath()); + // we must check headers["size"] == e->segmentMan->totalSize here + if(e->segmentMan->totalSize != size) { + return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); + } // send request again to the server with Range header return prepareForRetry(0); } else { - Segment seg; - e->segmentMan->getSegment(seg, cuid); + e->segmentMan->totalSize = size; e->diskWriter->initAndOpenFile(e->segmentMan->getFilePath()); createHttpDownloadCommand(); return true; @@ -140,9 +143,10 @@ void HttpResponseCommand::createHttpDownloadCommand(string transferEncoding) { } void HttpResponseCommand::retrieveCookie(const HttpHeader& headers) { - for(HttpHeader::const_iterator itr = headers.find("Set-Cookie"); itr != headers.end(); itr++) { + vector v = headers.get("Set-Cookie"); + for(vector::const_iterator itr = v.begin(); itr != v.end(); itr++) { Cookie c; - req->cookieBox->parse(c, (*itr).second); + req->cookieBox->parse(c, *itr); req->cookieBox->add(c); } } -- cgit From 32e8f2b011d1e1db9f724108894d9e2cd01d9f2a Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 21 Feb 2006 14:00:58 +0000 Subject: --- README | 2 +- src/AbstractCommand.cc | 11 ++-- src/DownloadEngine.cc | 3 +- src/FtpConnection.cc | 18 ++++-- src/FtpInitiateConnectionCommand.cc | 16 ++--- src/FtpNegotiationCommand.cc | 30 +++++---- src/HttpConnection.cc | 22 ++++--- src/HttpInitiateConnectionCommand.cc | 12 ++-- src/HttpResponseCommand.cc | 5 +- src/Request.h | 4 +- src/main.cc | 120 ++++++++++++++++++++++++++--------- src/message.h | 2 +- src/prefs.h | 79 +++++++++++++++++++++++ 13 files changed, 237 insertions(+), 87 deletions(-) create mode 100644 src/prefs.h (limited to 'src/HttpResponseCommand.cc') diff --git a/README b/README index 785c7da0..ed44c9d6 100644 --- a/README +++ b/README @@ -7,7 +7,7 @@ You must use this program at your own risk. 2. About aria2 -------------- -aria2 has segmented downloading engine in its core. By segmented downloding, +aria2 has segmented downloading engine in its core. By segmented downloading, it can download files very much faster than ordinary browsers. aria2 is in very early development stage. Currently it has following features: diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 89683a70..a16bf6a6 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -27,8 +27,7 @@ #include "Util.h" #include "message.h" #include "SleepCommand.h" - -#define TIMEOUT_SEC 60 +#include "prefs.h" AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, Socket* s): Command(cuid), req(req), e(e), checkSocketIsReadable(false), checkSocketIsWritable(false) { @@ -63,7 +62,7 @@ bool AbstractCommand::isTimeoutDetected() { return false; } else { long long int elapsed = Util::difftv(now, checkPoint); - if(elapsed >= TIMEOUT_SEC*1000000) { + if(elapsed >= e->option->getAsInt(PREF_TIMEOUT)*1000000) { return true; } else { return false; @@ -103,11 +102,11 @@ bool AbstractCommand::execute() { delete(err); //req->resetUrl(); req->addTryCount(); - if(req->noMoreTry()) { - e->logger->error(MSG_MAX_RETRY, cuid); + if(req->getTryCount() >= e->option->getAsInt(PREF_MAX_TRY)) { + e->logger->error(MSG_MAX_TRY, cuid, req->getTryCount()); return true; } else { - return prepareForRetry(e->option->getAsInt("retry_wait")); + return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT)); } } } diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc index 337e221c..80b98141 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -20,12 +20,11 @@ */ /* copyright --> */ #include "DownloadEngine.h" +#include "Util.h" #include #include #include #include -#include "DlAbortEx.h" -#include "Util.h" using namespace std; diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 4c528ada..4614304e 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -22,26 +22,34 @@ #include "FtpConnection.h" #include "Util.h" #include "DlAbortEx.h" +#include "DlRetryEx.h" #include "message.h" +#include "prefs.h" FtpConnection::FtpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger):cuid(cuid), socket(socket), req(req), option(op), logger(logger) {} FtpConnection::~FtpConnection() {} void FtpConnection::sendUser() const { - string request = "USER "+option->get("ftp_user")+"\r\n"; + string request = "USER "+option->get(PREF_FTP_USER)+"\r\n"; logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str()); socket->writeData(request); } void FtpConnection::sendPass() const { - string request = "PASS "+option->get("ftp_passwd")+"\r\n"; + string request = "PASS "+option->get(PREF_FTP_PASSWD)+"\r\n"; logger->info(MSG_SENDING_FTP_REQUEST, cuid, "PASS ********"); socket->writeData(request); } void FtpConnection::sendType() const { - string request = "TYPE "+option->get("ftp_type")+"\r\n"; + string type; + if(option->get(PREF_FTP_TYPE) == V_ASCII) { + type = "A"; + } else { + type = "I"; + } + string request = "TYPE "+type+"\r\n"; logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str()); socket->writeData(request); } @@ -143,7 +151,7 @@ bool FtpConnection::bulkReceiveResponse(pair& response) { if(strbuf.size() >= 4) { status = getStatus(strbuf); if(status == 0) { - throw new DlAbortEx(EX_INVALID_RESPONSE); + throw new DlRetryEx(EX_INVALID_RESPONSE); } } else { return false; @@ -197,7 +205,7 @@ int FtpConnection::receivePasvResponse(pair& dest) { // port number dest.second = 256*p1+p2; } else { - throw new DlAbortEx(EX_INVALID_RESPONSE); + throw new DlRetryEx(EX_INVALID_RESPONSE); } } return response.first; diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc index 26bec02c..03af4232 100644 --- a/src/FtpInitiateConnectionCommand.cc +++ b/src/FtpInitiateConnectionCommand.cc @@ -25,6 +25,7 @@ #include "FtpTunnelRequestCommand.h" #include "DlAbortEx.h" #include "message.h" +#include "prefs.h" FtpInitiateConnectionCommand::FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e):AbstractCommand(cuid, req, e) {} @@ -47,10 +48,10 @@ bool FtpInitiateConnectionCommand::executeInternal(Segment segment) { Command* command; if(useHttpProxy()) { e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, - e->option->get("http_proxy_host").c_str(), - e->option->getAsInt("http_proxy_port")); - socket->establishConnection(e->option->get("http_proxy_host"), - e->option->getAsInt("http_proxy_port")); + e->option->get(PREF_HTTP_PROXY_HOST).c_str(), + e->option->getAsInt(PREF_HTTP_PROXY_PORT)); + socket->establishConnection(e->option->get(PREF_HTTP_PROXY_HOST), + e->option->getAsInt(PREF_HTTP_PROXY_PORT)); if(useHttpProxyGet()) { command = new HttpRequestCommand(cuid, req, e, socket); @@ -71,14 +72,13 @@ bool FtpInitiateConnectionCommand::executeInternal(Segment segment) { } bool FtpInitiateConnectionCommand::useHttpProxy() const { - return e->option->defined("http_proxy_enabled") && - e->option->get("http_proxy_enabled") == "true"; + return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; } bool FtpInitiateConnectionCommand::useHttpProxyGet() const { - return useHttpProxy() && e->option->get("ftp_via_http_proxy") == "get"; + return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET; } bool FtpInitiateConnectionCommand::useHttpProxyConnect() const { - return useHttpProxy() && e->option->get("ftp_via_http_proxy") == "tunnel"; + return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL; } diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index ee6821ec..2f5bb342 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -22,7 +22,9 @@ #include "FtpNegotiationCommand.h" #include "FtpDownloadCommand.h" #include "DlAbortEx.h" +#include "DlRetryEx.h" #include "message.h" +#include "prefs.h" FtpNegotiationCommand::FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e, Socket* s): AbstractCommand(cuid, req, e, s), @@ -64,7 +66,7 @@ bool FtpNegotiationCommand::recvGreeting() { return false; } if(status != 220) { - throw new DlAbortEx(EX_CONNECTION_FAILED); + throw new DlRetryEx(EX_CONNECTION_FAILED); } sequence = SEQ_SEND_USER; @@ -92,7 +94,7 @@ bool FtpNegotiationCommand::recvUser() { sequence = SEQ_SEND_PASS; break; default: - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } return true; } @@ -109,7 +111,7 @@ bool FtpNegotiationCommand::recvPass() { return false; } if(status != 230) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } sequence = SEQ_SEND_TYPE; return true; @@ -127,7 +129,7 @@ bool FtpNegotiationCommand::recvType() { return false; } if(status != 200) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } sequence = SEQ_SEND_CWD; return true; @@ -145,7 +147,7 @@ bool FtpNegotiationCommand::recvCwd() { return false; } if(status != 250) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } sequence = SEQ_SEND_SIZE; return true; @@ -164,16 +166,18 @@ bool FtpNegotiationCommand::recvSize() { return false; } if(status != 213) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); + } + if(size == LONG_LONG_MAX || size < 0) { + throw new DlAbortEx(EX_TOO_LARGE_FILE, size); } - // TODO check the value of size if(!e->segmentMan->downloadStarted) { e->segmentMan->downloadStarted = true; e->segmentMan->totalSize = size; } else if(e->segmentMan->totalSize != size) { throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); } - if(e->option->get("ftp_pasv_enabled") == "true") { + if(e->option->get(PREF_FTP_PASV_ENABLED) == V_TRUE) { sequence = SEQ_SEND_PASV; } else { sequence = SEQ_SEND_PORT; @@ -193,7 +197,7 @@ bool FtpNegotiationCommand::recvPort() { return false; } if(status != 200) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } sequence = SEQ_SEND_REST; return true; @@ -212,7 +216,7 @@ bool FtpNegotiationCommand::recvPasv() { return false; } if(status != 227) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } // make a data connection to the server. dataSocket = new Socket(); @@ -249,7 +253,7 @@ bool FtpNegotiationCommand::recvRest() { } // TODO if we recieve negative response, then we set e->segmentMan->splittable = false, and continue. if(status != 350) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } sequence = SEQ_SEND_RETR; return true; @@ -267,9 +271,9 @@ bool FtpNegotiationCommand::recvRetr() { return false; } if(status != 150) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } - if(e->option->get("ftp_pasv_enabled") != "true") { + if(e->option->get(PREF_FTP_PASV_ENABLED) != V_TRUE) { assert(serverSocket); dataSocket = serverSocket->acceptConnection(); } diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc index 9f373d33..535e745f 100644 --- a/src/HttpConnection.cc +++ b/src/HttpConnection.cc @@ -20,11 +20,11 @@ */ /* copyright --> */ #include "HttpConnection.h" -#include "DlAbortEx.h" #include "DlRetryEx.h" #include "Util.h" #include "Base64.h" #include "message.h" +#include "prefs.h" HttpConnection::HttpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger): cuid(cuid), socket(socket), req(req), option(op), logger(logger) {} @@ -36,12 +36,14 @@ void HttpConnection::sendRequest(const Segment& segment) const { } void HttpConnection::sendProxyRequest() const { - string request = string("CONNECT ")+req->getHost()+":"+Util::llitos(req->getPort())+ + string request = + string("CONNECT ")+req->getHost()+":"+Util::llitos(req->getPort())+ string(" HTTP/1.1\r\n")+ "Host: "+getHost(req->getHost(), req->getPort())+"\r\n"; if(useProxyAuth()) { request += "Proxy-Authorization: Basic "+ - Base64::encode(option->get("http_proxy_user")+":"+option->get("http_proxy_passwd"))+"\r\n"; + Base64::encode(option->get(PREF_HTTP_PROXY_USER)+":"+ + option->get(PREF_HTTP_PROXY_PORT))+"\r\n"; } request += "\r\n"; logger->info(MSG_SENDING_HTTP_REQUEST, cuid, request.c_str()); @@ -65,11 +67,13 @@ string HttpConnection::createRequest(const Segment& segment) const { "Pragma: no-cache\r\n"+ "Cache-Control: no-cache\r\n"; if(segment.sp+segment.ds > 0) { - request += "Range: bytes="+Util::llitos(segment.sp+segment.ds)+"-"+Util::llitos(segment.ep)+"\r\n"; + request += "Range: bytes="+ + Util::llitos(segment.sp+segment.ds)+"-"+Util::llitos(segment.ep)+"\r\n"; } - if(option->get("http_auth_scheme") == "BASIC") { + if(option->get(PREF_HTTP_AUTH_SCHEME) == V_BASIC) { request += "Authorization: Basic "+ - Base64::encode(option->get("http_user")+":"+option->get("http_passwd"))+"\r\n"; + Base64::encode(option->get(PREF_HTTP_USER)+":"+ + option->get(PREF_HTTP_PASSWD))+"\r\n"; } if(req->getPreviousUrl().size()) { request += "Referer: "+req->getPreviousUrl()+"\r\n"; @@ -135,11 +139,9 @@ int HttpConnection::receiveResponse(HttpHeader& headers) { } bool HttpConnection::useProxy() const { - return option->defined("http_proxy_enabled") && - option->get("http_proxy_enabled") == "true"; + return option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; } bool HttpConnection::useProxyAuth() const { - return option->defined("http_proxy_auth_enabled") && - option->get("http_proxy_auth_enabled") == "true"; + return option->get(PREF_HTTP_PROXY_AUTH_ENABLED) == V_TRUE; } diff --git a/src/HttpInitiateConnectionCommand.cc b/src/HttpInitiateConnectionCommand.cc index e94c39c9..8b53aab8 100644 --- a/src/HttpInitiateConnectionCommand.cc +++ b/src/HttpInitiateConnectionCommand.cc @@ -24,6 +24,7 @@ #include "HttpProxyRequestCommand.h" #include "Util.h" #include "message.h" +#include "prefs.h" HttpInitiateConnectionCommand::HttpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e):AbstractCommand(cuid, req, e) {} @@ -35,10 +36,10 @@ bool HttpInitiateConnectionCommand::executeInternal(Segment segment) { Command* command; if(useProxy()) { e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, - e->option->get("http_proxy_host").c_str(), - e->option->getAsInt("http_proxy_port")); - socket->establishConnection(e->option->get("http_proxy_host"), - e->option->getAsInt("http_proxy_port")); + e->option->get(PREF_HTTP_PROXY_HOST).c_str(), + e->option->getAsInt(PREF_HTTP_PROXY_PORT)); + socket->establishConnection(e->option->get(PREF_HTTP_PROXY_HOST), + e->option->getAsInt(PREF_HTTP_PROXY_PORT)); command = new HttpProxyRequestCommand(cuid, req, e, socket); } else { @@ -52,6 +53,5 @@ bool HttpInitiateConnectionCommand::executeInternal(Segment segment) { } bool HttpInitiateConnectionCommand::useProxy() { - return e->option->defined("http_proxy_enabled") && - e->option->get("http_proxy_enabled") == "true"; + return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE; } diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 1fd273bb..f5788be7 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -21,6 +21,7 @@ /* copyright --> */ #include "HttpResponseCommand.h" #include "DlAbortEx.h" +#include "DlRetryEx.h" #include "HttpDownloadCommand.h" #include "HttpInitiateConnectionCommand.h" #include "message.h" @@ -77,7 +78,7 @@ void HttpResponseCommand::checkResponse(int status, const Segment& segment) { if(!(status < 400 && status >= 300 || (segment.sp+segment.ds == 0 && status == 200) || (segment.sp+segment.ds > 0 && status == 206))) { - throw new DlAbortEx(EX_BAD_STATUS, status); + throw new DlRetryEx(EX_BAD_STATUS, status); } } @@ -90,7 +91,7 @@ bool HttpResponseCommand::handleRedirect(string url, const HttpHeader& headers) bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { long long int size = headers.getFirstAsLLInt("Content-Length"); - if(size == LONG_LONG_MAX || size == LONG_LONG_MIN || size < 0) { + if(size == LONG_LONG_MAX || size < 0) { throw new DlAbortEx(EX_TOO_LARGE_FILE, size); } e->segmentMan->isSplittable = !(size == 0); diff --git a/src/Request.h b/src/Request.h index 7a7b0fce..8d8676ef 100644 --- a/src/Request.h +++ b/src/Request.h @@ -29,8 +29,6 @@ using namespace std; -#define MAX_TRY_COUNT 5 - #define SAFE_CHARS "abcdefghijklmnopqrstuvwxyz"\ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\ "0123456789"\ @@ -77,7 +75,7 @@ public: void resetTryCount() { tryCount = 0; } void addTryCount() { tryCount++; } int getTryCount() const { return tryCount; } - bool noMoreTry() const { return tryCount >= MAX_TRY_COUNT; } + //bool noMoreTry() const { return tryCount >= PREF_MAX_TRY; } string getUrl() const { return url; } string getCurrentUrl() const { return currentUrl; } diff --git a/src/main.cc b/src/main.cc index 773bdd17..63c46a95 100644 --- a/src/main.cc +++ b/src/main.cc @@ -27,6 +27,7 @@ #include "DefaultDiskWriter.h" #include "Util.h" #include "InitiateConnectionCommandFactory.h" +#include "prefs.h" #include #include #include @@ -96,7 +97,9 @@ void showVersion() { } void showUsage() { + cout << endl; cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl; + cout << endl; cout << "Options:" << endl; cout << " -d, --dir=DIR The directory to store downloaded file." << endl; cout << " -o, --out=FILE The file name for downloaded file." << endl; @@ -106,31 +109,47 @@ void showUsage() { 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 << " 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 << " for errors. Specify a value between 0 and 60." << endl; + cout << " -t, --timeout=SEC Set timeout in second." << endl; cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl; cout << " URLs." << endl; cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl; cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl; cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl; cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl; - cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, BASIC" << endl; + cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic" << endl; cout << " is the only supported scheme. You MUST specify" << endl; cout << " this option in order to use HTTP authentication" << endl; cout << " as well as --http-proxy option." << endl; - cout << " --referer Set Referer. This affects to all URLs." << endl; - cout << " --retry-wait Set amount of time in second between requests" << endl; - cout << " for errors. Specify a value between 0 and 60." << endl; + cout << " --referer=REFERER Set Referer. This affects to all URLs." << endl; + cout << " --ftp-user=USER Set FTP user. This affects to all URLs." << endl; + cout << " Default: anonymous" << endl; + cout << " --ftp-passwd=PASSWD Set FTP password. This affects to all URLs." << endl; + cout << " Default: ARIA2USER@" << endl; + cout << " --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'" << endl; + cout << " or 'ascii'." << 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 << "URL:" << endl; cout << " You can specify multiple URLs. All URLs must point to the same file" << endl; - cout << " or a download fails." << endl; + cout << " or downloading fails." << endl; + cout << endl; cout << "Examples:" << endl; cout << " Download a file by 1 connection:" << endl; cout << " aria2c http://AAA.BBB.CCC/file.zip" << endl; cout << " Download a file by 2 connections:" << endl; cout << " aria2c -s 2 http://AAA.BBB.CCC/file.zip" << endl; - cout << " Download a file by 2 connections, each connects to a different server." << endl; + cout << " Download a file by 2 connections, each connects to a different server:" << endl; cout << " aria2c http://AAA.BBB.CCC/file.zip http://DDD.EEE.FFF/GGG/file.zip" << endl; + cout << " You can mix up different protocols:" << endl; + cout << " aria2c http://AAA.BBB.CCC/file.zip ftp://DDD.EEE.FFF/GGG/file.zip" << endl; + cout << endl; cout << "Reports bugs to " << endl; } @@ -145,16 +164,13 @@ int main(int argc, char* argv[]) { int c; Option* op = new Option(); - op->put("retry_wait", "5"); - - // TODO warning! Delete username/password line when commit - op->put("ftp_user", "anonymous"); - op->put("ftp_passwd", "IE60USER@"); - op->put("ftp_type", "I"); - - op->put("ftp_pasv_enabled", "true"); - op->put("ftp_via_http_proxy", "tunnel"); - op->put("http_abs_uri_request_enabled", "true"); + op->put(PREF_RETRY_WAIT, "5"); + op->put(PREF_TIMEOUT, "60"); + op->put(PREF_FTP_USER, "anonymous"); + op->put(PREF_FTP_PASSWD, "ARIA2USER@"); + op->put(PREF_FTP_TYPE, V_BINARY); + op->put(PREF_FTP_PASV_ENABLED, V_TRUE); + op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL); while(1) { int optIndex = 0; @@ -165,6 +181,7 @@ int main(int argc, char* argv[]) { { "out", required_argument, NULL, 'o' }, { "log", required_argument, NULL, 'l' }, { "split", required_argument, NULL, 's' }, + { "timeout", required_argument, NULL, 't' }, { "http-proxy", required_argument, &lopt, 1 }, { "http-user", required_argument, &lopt, 2 }, { "http-passwd", required_argument, &lopt, 3 }, @@ -173,11 +190,16 @@ int main(int argc, char* argv[]) { { "http-auth-scheme", required_argument, &lopt, 6 }, { "referer", required_argument, &lopt, 7 }, { "retry-wait", required_argument, &lopt, 8 }, + { "ftp-user", required_argument, &lopt, 9 }, + { "ftp-passwd", required_argument, &lopt, 10 }, + { "ftp-type", required_argument, &lopt, 11 }, + { "ftp-pasv", no_argument, NULL, 'p' }, + { "ftp-via-http-proxy", required_argument, &lopt, 12 }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "Dd:o:l:s:vh", longOpts, &optIndex); + c = getopt_long(argc, argv, "Dd:o:l:s:pt:vh", longOpts, &optIndex); if(c == -1) { break; } @@ -194,29 +216,29 @@ int main(int argc, char* argv[]) { showUsage(); exit(1); } - op->put("http_proxy_host", proxy.first); - op->put("http_proxy_port", Util::itos(port)); - op->put("http_proxy_enabled", "true"); + op->put(PREF_HTTP_PROXY_HOST, proxy.first); + op->put(PREF_HTTP_PROXY_PORT, Util::itos(port)); + op->put(PREF_HTTP_PROXY_ENABLED, V_TRUE); break; } case 2: - op->put("http_user", optarg); + op->put(PREF_HTTP_USER, optarg); break; case 3: - op->put("http_passwd", optarg); + op->put(PREF_HTTP_PASSWD, optarg); break; case 4: - op->put("http_proxy_user", optarg); - op->put("http_proxy_auth_enabled", "true"); + op->put(PREF_HTTP_PROXY_USER, optarg); + op->put(PREF_HTTP_PROXY_AUTH_ENABLED, V_TRUE); break; case 5: - op->put("http_proxy_passwd", optarg); + op->put(PREF_HTTP_PROXY_PASSWD, optarg); break; case 6: - if(string("BASIC") == optarg) { - op->put("http_auth_scheme", "BASIC"); + if(string(V_BASIC) == optarg) { + op->put(PREF_HTTP_AUTH_SCHEME, V_BASIC); } else { - cerr << "Currently, supported authentication scheme is BASIC." << endl; + cerr << "Currently, supported authentication scheme is basic." << endl; } break; case 7: @@ -229,9 +251,33 @@ int main(int argc, char* argv[]) { showUsage(); exit(1); } - op->put("retry-wait", Util::itos(wait)); + op->put(PREF_RETRY_WAIT, Util::itos(wait)); break; } + case 9: + op->put(PREF_FTP_USER, optarg); + break; + case 10: + op->put(PREF_FTP_PASSWD, optarg); + break; + case 11: + if(string(optarg) == V_BINARY || string(optarg) == V_ASCII) { + op->put(PREF_FTP_TYPE, optarg); + } else { + cerr << "ftp-type must be either 'binary' or 'ascii'." << endl; + showUsage(); + exit(1); + } + break; + case 12: + if(string(optarg) == V_GET || string(optarg) == V_TUNNEL) { + op->put(PREF_FTP_VIA_HTTP_PROXY, optarg); + } else { + cerr << "ftp-via-http-proxy must be either 'get' or 'tunnel'." << endl; + showUsage(); + exit(1); + } + break; } break; } @@ -253,12 +299,26 @@ int main(int argc, char* argv[]) { break; case 's': split = (int)strtol(optarg, NULL, 10); - if(!(1 < split && split < 5)) { + if(!(1 <= split && split <= 5)) { cerr << "split must be between 1 and 5." << endl; showUsage(); exit(1); } break; + case 't': { + int timeout = (int)strtol(optarg, NULL, 10); + if(1 <= timeout && timeout <= 600) { + op->put(PREF_TIMEOUT, Util::itos(timeout)); + } else { + cerr << "timeout must be between 1 and 600" << endl; + showUsage(); + exit(1); + } + break; + } + case 'p': + op->put(PREF_FTP_PASV_ENABLED, V_TRUE); + break; case 'v': showVersion(); exit(0); diff --git a/src/message.h b/src/message.h index d326953c..7323c58e 100644 --- a/src/message.h +++ b/src/message.h @@ -32,7 +32,7 @@ #define MSG_RECEIVE_RESPONSE "CUID#%d - Response received:\n%s" #define MSG_DOWNLOAD_ABORTED "CUID#%d - Download aborted." #define MSG_RESTARTING_DOWNLOAD "CUID#%d - Restarting the download." -#define MSG_MAX_RETRY "CUID#%d - The retry count reached its max value. Download aborted." +#define MSG_MAX_TRY "CUID#%d - %d times attempted, but no success. Download aborted." #define MSG_UNREGISTER_CUID "CUID#%d - Unregistering cuid from segmentManager." #define MSG_SEGMENT_FILE_EXISTS "The segment file %s exists." diff --git a/src/prefs.h b/src/prefs.h new file mode 100644 index 00000000..847990da --- /dev/null +++ b/src/prefs.h @@ -0,0 +1,79 @@ +/* */ +#ifndef _D_PREFS_H_ +#define _D_PREFS_H_ + +/** + * Constants + */ +#define V_TRUE "true" +//#define V_FALSE "false" + +/** + * General preferences + */ +// values: 1*digit +#define PREF_RETRY_WAIT "retry_wait" +// values: 1*digit +#define PREF_TIMEOUT "timeout" +// values: 1*digit +#define PREF_MAX_TRY "max_try" + +/** + * FTP related preferences + */ +#define PREF_FTP_USER "ftp_user" +#define PREF_FTP_PASSWD "ftp_passwd" +// values: binary | ascii +#define PREF_FTP_TYPE "ftp_type" +# define V_BINARY "binary" +# define V_ASCII "ascii" +// values: get | tunnel +#define PREF_FTP_VIA_HTTP_PROXY "ftp_via_http_proxy" +# define V_GET "get" +# define V_TUNNEL "tunnel" +// values: true | false +#define PREF_FTP_PASV_ENABLED "ftp_pasv_enabled" + +/** + * HTTP related preferences + */ +#define PREF_HTTP_USER "http_user" +#define PREF_HTTP_PASSWD "http_passwd" +// values: basic +#define PREF_HTTP_AUTH_SCHEME "http_auth_scheme" +# define V_BASIC "basic" + +/** + * HTTP proxy related preferences + */ +#define PREF_HTTP_PROXY_USER "http_proxy_user" +#define PREF_HTTP_PROXY_PASSWD "http_proxy_passwd" +#define PREF_HTTP_PROXY_HOST "http_proxy_host" +#define PREF_HTTP_PROXY_PORT "http_proxy_port" +// values: true | false +#define PREF_HTTP_PROXY_ENABLED "http_proxy_enabled" +// values: true | false +#define PREF_HTTP_PROXY_AUTH_ENABLED "http_proxy_auth_enabled" + + +#endif // _D_PREFS_H_ -- cgit From ebdb4b86cff8247b1a275748c60173581e034f46 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 22 Feb 2006 11:18:47 +0000 Subject: --- ChangeLog | 2 + TODO | 1 + src/AbstractCommand.cc | 3 +- src/DownloadEngine.h | 4 +- src/FtpConnection.cc | 8 +++- src/HttpResponseCommand.cc | 7 +-- src/Option.cc | 9 ++++ src/Option.h | 1 + src/Request.cc | 4 +- src/SegmentMan.cc | 3 +- src/SegmentMan.h | 2 + src/main.cc | 110 ++++++++++++++++++++++++++++++--------------- src/prefs.h | 4 +- 13 files changed, 110 insertions(+), 48 deletions(-) (limited to 'src/HttpResponseCommand.cc') diff --git a/ChangeLog b/ChangeLog index 04756041..c7cbe795 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,8 @@ * main.cc: The value of --http-auth-scheme option is chagned from 'BASIC' to 'basic' * 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 2006-02-19 Tatsuhiro Tsujikawa diff --git a/TODO b/TODO index 90d5a5f9..2435e4b0 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,4 @@ * Add SSL client cert support * Better HTTP status handling * Download files listed in a specifed file. +* check MD5 checksum \ No newline at end of file diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index a16bf6a6..6fe1d2ae 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -102,7 +102,8 @@ bool AbstractCommand::execute() { delete(err); //req->resetUrl(); 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()); return true; } else { diff --git a/src/DownloadEngine.h b/src/DownloadEngine.h index f8eaa97d..b3d2a70b 100644 --- a/src/DownloadEngine.h +++ b/src/DownloadEngine.h @@ -47,8 +47,8 @@ public: queue commands; SegmentMan* segmentMan; DiskWriter* diskWriter; - Logger* logger; - Option* option; + const Logger* logger; + const Option* option; DownloadEngine(); ~DownloadEngine(); diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 1d478f1b..54844e74 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -110,8 +110,12 @@ void FtpConnection::sendRetr() const { int FtpConnection::getStatus(string response) const { int status; - // TODO we must handle when the response is not like "%d %*s" - // In this case, we return 0 + // When the response is not like "%d %*s", + // 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) { return status; } else { diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index f5788be7..4f808a8b 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -65,10 +65,13 @@ bool HttpResponseCommand::executeInternal(Segment seg) { return handleDefaultEncoding(headers); } } else { - // TODO we must check headers["size"] == e->segmentMan->totalSize here if(req->getFile() != e->segmentMan->filename) { 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(); return true; } @@ -99,9 +102,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { bool segFileExists = e->segmentMan->segmentFileExists(); e->segmentMan->downloadStarted = true; if(segFileExists) { - e->diskWriter->openExistingFile(e->segmentMan->getFilePath()); - // we must check headers["size"] == e->segmentMan->totalSize here if(e->segmentMan->totalSize != size) { return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); } diff --git a/src/Option.cc b/src/Option.cc index 96576b83..35e4a35c 100644 --- a/src/Option.cc +++ b/src/Option.cc @@ -50,3 +50,12 @@ int Option::getAsInt(const string& name) const { return (int)strtol((*itr).second.c_str(), NULL, 10); } } + +long long int Option::getAsLLInt(const string& name) const { + map::const_iterator itr = table.find(name); + if(itr == table.end()) { + return 0; + } else { + return (int)strtoll((*itr).second.c_str(), NULL, 10); + } +} diff --git a/src/Option.h b/src/Option.h index fa1e0c67..7cacef50 100644 --- a/src/Option.h +++ b/src/Option.h @@ -38,6 +38,7 @@ public: bool defined(const string& name) const; string get(const string& name) const; int getAsInt(const string& name) const; + long long int getAsLLInt(const string& name) const; }; #endif // _D_OPTION_H_ diff --git a/src/Request.cc b/src/Request.cc index 6eb4aa1e..9d183cd4 100644 --- a/src/Request.cc +++ b/src/Request.cc @@ -79,14 +79,12 @@ bool Request::parseUrl(string url) { Util::split(hostAndPort, url.substr(hp, hep-hp), ':'); host = hostAndPort.first; if(hostAndPort.second != "") { - // TODO rewrite this using strtoul function. If strtoul fails, - // return false. port = (int)strtol(hostAndPort.second.c_str(), NULL, 10); if(!(0 < port && port <= 65535)) { return false; } } 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; } string::size_type direp = url.find_last_of("/"); diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 579c2bfe..0089575a 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -28,6 +28,7 @@ #include "Util.h" #include "File.h" #include "message.h" +#include "prefs.h" SegmentMan::SegmentMan():totalSize(0),isSplittable(true),downloadStarted(false),dir(".") {} @@ -85,7 +86,7 @@ bool SegmentMan::getSegment(Segment& seg, int cuid) { if(s.finish) { 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); //nseg = { cuid, nep+1, s.ep, 0, false }; seg.cuid = cuid; diff --git a/src/SegmentMan.h b/src/SegmentMan.h index e971a176..075453ff 100644 --- a/src/SegmentMan.h +++ b/src/SegmentMan.h @@ -26,6 +26,7 @@ #include "common.h" #include "Logger.h" #include "Segment.h" +#include "Option.h" using namespace std; @@ -81,6 +82,7 @@ public: string ufilename; const Logger* logger; + const Option* option; SegmentMan(); ~SegmentMan(); diff --git a/src/main.cc b/src/main.cc index 63c46a95..a352a674 100644 --- a/src/main.cc +++ b/src/main.cc @@ -101,40 +101,45 @@ void showUsage() { cout << "Usage: " << PACKAGE_NAME << " [options] URL ..." << endl; cout << endl; cout << "Options:" << endl; - cout << " -d, --dir=DIR The directory to store 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 << " log is written to stdout." << endl; - cout << " -D, --daemon Run as daemon." << 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 << " 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 << " for errors. Specify a value between 0 and 60." << endl; - cout << " -t, --timeout=SEC Set timeout in second." << endl; - cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl; - cout << " URLs." << endl; - cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl; - cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl; - cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl; - cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl; - cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic" << endl; - cout << " is the only supported scheme. You MUST specify" << endl; - cout << " this option in order to use HTTP authentication" << endl; - cout << " as well as --http-proxy option." << endl; - cout << " --referer=REFERER Set Referer. This affects to all URLs." << endl; - cout << " --ftp-user=USER Set FTP user. This affects to all URLs." << endl; - cout << " Default: anonymous" << endl; - cout << " --ftp-passwd=PASSWD Set FTP password. This affects to all URLs." << endl; - cout << " Default: ARIA2USER@" << endl; - cout << " --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'" << endl; - cout << " or 'ascii'." << 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 << " -d, --dir=DIR The directory to store 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 << " log is written to stdout." << endl; + cout << " -D, --daemon Run as daemon." << 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 << " 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 << " for errors. Specify a value between 0 and 60." << endl; + cout << " Default: 5" << endl; + cout << " -t, --timeout=SEC Set timeout in second. Default: 60" << endl; + cout << " -m, --max-tries=N Set number of tries. 0 means unlimited." << endl; + cout << " Default: 5" << endl; + cout << " --min-segment-size=SIZE[K|M] Set minimum segment size. You can append" << endl; + cout << " K or M(1K = 1024, 1M = 1024K)." << endl; + cout << " --http-proxy=HOST:PORT Use HTTP proxy server. This affects to all" << endl; + cout << " URLs." << endl; + cout << " --http-user=USER Set HTTP user. This affects to all URLs." << endl; + cout << " --http-passwd=PASSWD Set HTTP password. This affects to all URLs." << endl; + cout << " --http-proxy-user=USER Set HTTP proxy user. This affects to all URLs" << endl; + cout << " --http-proxy-passwd=PASSWD Set HTTP proxy password. This affects to all URLs." << endl; + cout << " --http-auth-scheme=SCHEME Set HTTP authentication scheme. Currently, basic" << endl; + cout << " is the only supported scheme. You MUST specify" << endl; + cout << " this option in order to use HTTP authentication" << endl; + cout << " as well as --http-proxy option." << endl; + cout << " --referer=REFERER Set Referer. This affects to all URLs." << endl; + cout << " --ftp-user=USER Set FTP user. This affects to all URLs." << endl; + cout << " Default: anonymous" << endl; + cout << " --ftp-passwd=PASSWD Set FTP password. This affects to all URLs." << endl; + cout << " Default: ARIA2USER@" << endl; + cout << " --ftp-type=TYPE Set FTP transfer type. TYPE is either 'binary'" << endl; + cout << " or 'ascii'." << 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 << "URL:" << 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(); op->put(PREF_RETRY_WAIT, "5"); 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_PASSWD, "ARIA2USER@"); op->put(PREF_FTP_TYPE, V_BINARY); @@ -182,6 +189,7 @@ int main(int argc, char* argv[]) { { "log", required_argument, NULL, 'l' }, { "split", required_argument, NULL, 's' }, { "timeout", required_argument, NULL, 't' }, + { "max-retries", required_argument, NULL, 'm' }, { "http-proxy", required_argument, &lopt, 1 }, { "http-user", required_argument, &lopt, 2 }, { "http-passwd", required_argument, &lopt, 3 }, @@ -195,11 +203,12 @@ int main(int argc, char* argv[]) { { "ftp-type", required_argument, &lopt, 11 }, { "ftp-pasv", no_argument, NULL, 'p' }, { "ftp-via-http-proxy", required_argument, &lopt, 12 }, + { "min-segment-size", required_argument, &lopt, 13 }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { 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) { break; } @@ -278,6 +287,26 @@ int main(int argc, char* argv[]) { exit(1); } 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; } @@ -316,6 +345,16 @@ int main(int argc, char* argv[]) { } 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': op->put(PREF_FTP_PASV_ENABLED, V_TRUE); break; @@ -363,6 +402,7 @@ int main(int argc, char* argv[]) { e->segmentMan->dir = dir; e->segmentMan->ufilename = ufilename; e->segmentMan->logger = logger; + e->segmentMan->option = op; vector requests; if(split > 0) { for(int i = 1; i <= split; i++) { diff --git a/src/prefs.h b/src/prefs.h index 847990da..bce670e4 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -36,7 +36,9 @@ // values: 1*digit #define PREF_TIMEOUT "timeout" // 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 -- cgit From 27d392d5f2c0cbddeacd53995b2831ddc7f5d08a Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 22 Feb 2006 12:16:10 +0000 Subject: --- ChangeLog | 6 ++++++ TODO | 4 +++- src/DlAbortEx.h | 4 ++-- src/DlRetryEx.h | 2 +- src/HttpResponseCommand.cc | 8 +------- src/main.cc | 18 ++++++------------ src/message.h | 4 ++-- 7 files changed, 21 insertions(+), 25 deletions(-) (limited to 'src/HttpResponseCommand.cc') diff --git a/ChangeLog b/ChangeLog index c7cbe795..af586269 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-02-22 Tatsuhiro Tsujikawa + + * main.cc: -s option now affects all URLs in command-line arguemtns. + * HttpResponseCommand.cc: Fixed bug that segment file is not loaded. + * message.h: Change file size related %d to %lld. + 2006-02-21 Tatsuhiro Tsujikawa * FtpInitiateConnectionCommand.{h,cc}: diff --git a/TODO b/TODO index 2435e4b0..e8c1e273 100644 --- a/TODO +++ b/TODO @@ -4,4 +4,6 @@ * Add SSL client cert support * Better HTTP status handling * Download files listed in a specifed file. -* check MD5 checksum \ No newline at end of file +* check MD5 checksum +* Apply "split longest remianing time first" algorithm to SegmentMan. +* split algorithm must be separate class. \ No newline at end of file diff --git a/src/DlAbortEx.h b/src/DlAbortEx.h index 151e2e60..4d7fe7e6 100644 --- a/src/DlAbortEx.h +++ b/src/DlAbortEx.h @@ -26,10 +26,10 @@ class DlAbortEx:public Exception { public: DlAbortEx():Exception() {} - DlAbortEx(string msg, ...):Exception() { + DlAbortEx(const char* msg, ...):Exception() { va_list ap; va_start(ap, msg); - setMsg(msg, ap); + setMsg(string(msg), ap); va_end(ap); } }; diff --git a/src/DlRetryEx.h b/src/DlRetryEx.h index 29bf6f70..0ba5f50b 100644 --- a/src/DlRetryEx.h +++ b/src/DlRetryEx.h @@ -26,7 +26,7 @@ class DlRetryEx:public Exception { public: DlRetryEx():Exception() {} - DlRetryEx(string msg, ...):Exception() { + DlRetryEx(const char* msg, ...):Exception() { va_list ap; va_start(ap, msg); setMsg(msg, ap); diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 4f808a8b..30e65db1 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -68,10 +68,6 @@ bool HttpResponseCommand::executeInternal(Segment seg) { if(req->getFile() != e->segmentMan->filename) { 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(); return true; } @@ -102,10 +98,8 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { bool segFileExists = e->segmentMan->segmentFileExists(); e->segmentMan->downloadStarted = true; if(segFileExists) { + e->segmentMan->load(); e->diskWriter->openExistingFile(e->segmentMan->getFilePath()); - if(e->segmentMan->totalSize != size) { - return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); - } // send request again to the server with Range header return prepareForRetry(0); } else { diff --git a/src/main.cc b/src/main.cc index a352a674..1f08d4ba 100644 --- a/src/main.cc +++ b/src/main.cc @@ -107,8 +107,8 @@ void showUsage() { cout << " log is written to stdout." << endl; cout << " -D, --daemon Run as daemon." << 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 << " first URL is used, and the other URLs are ignored." << endl; + cout << " between 1 and 5. This option affects all URLs." << endl; + cout << " Thus, aria2 connects to each URL with N connections." << 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 << " Default: 5" << endl; @@ -163,7 +163,7 @@ int main(int argc, char* argv[]) { string logfile; string dir; string ufilename; - int split = 0; + int split = 1; bool daemonMode = false; string referer; @@ -393,7 +393,6 @@ int main(int argc, char* argv[]) { } else { logger = new SimpleLogger("/dev/null"); } - e = new DownloadEngine(); e->logger = logger; e->option = op; @@ -404,16 +403,11 @@ int main(int argc, char* argv[]) { e->segmentMan->logger = logger; e->segmentMan->option = op; vector requests; - if(split > 0) { - for(int i = 1; i <= split; i++) { - addCommand(i, argv[optind], referer, requests); - } - } else { - for(int i = 1; optind < argc; i++) { - addCommand(i, argv[optind++], referer, requests); + for(int i = 1; optind+i-1 < argc; i++) { + for(int s = 1; s <= split; s++) { + addCommand(split*(i-1)+s, argv[optind+i-1], referer, requests); } } - struct sigaction sigact; sigact.sa_handler = handler; sigact.sa_flags = 0; diff --git a/src/message.h b/src/message.h index 0a75b239..ca8514f3 100644 --- a/src/message.h +++ b/src/message.h @@ -52,9 +52,9 @@ #define EX_CONNECTION_FAILED "Connection failed." #define EX_FILENAME_MISMATCH "The requested filename and the previously registered one are not same. %s != %s" #define EX_BAD_STATUS "The response status is not successful. status = %d" -#define EX_TOO_LARGE_FILE "Too large file size. size = %d" +#define EX_TOO_LARGE_FILE "Too large file size. size = %lld" #define EX_TRANSFER_ENCODING_NOT_SUPPORTED "Transfer encoding %s is not supported." #define EX_SSL_INIT_FAILURE "SSL initialization failed." -#define EX_SIZE_MISMATCH "Size mismatch %d != %d" +#define EX_SIZE_MISMATCH "Size mismatch %lld != %lld" #endif // _D_MESSAGE_H_ -- cgit