summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-02-22 16:01:54 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-02-22 16:01:54 +0000
commit44beebd257b0fb265bea5387850b9beb33c0adc2 (patch)
tree0ec08e4aad18ccff2d578aca1c0b3799d2716c6c /src
parentd027ca8e7c383e9755d6fb997e8a880df99e88b9 (diff)
parent87a229cab18679042beb06076e5dec1dcfadaeae (diff)
Tagging release 0.2.0 of aria2release-0.2.0
Diffstat (limited to 'src')
-rw-r--r--src/AbstractCommand.cc76
-rw-r--r--src/AbstractCommand.h13
-rw-r--r--src/DlAbortEx.h4
-rw-r--r--src/DlRetryEx.h2
-rw-r--r--src/DownloadCommand.cc24
-rw-r--r--src/DownloadCommand.h5
-rw-r--r--src/DownloadEngine.cc47
-rw-r--r--src/DownloadEngine.h4
-rw-r--r--src/FtpConnection.cc219
-rw-r--r--src/FtpConnection.h65
-rw-r--r--src/FtpDownloadCommand.cc38
-rw-r--r--src/FtpDownloadCommand.h37
-rw-r--r--src/FtpInitiateConnectionCommand.cc84
-rw-r--r--src/FtpInitiateConnectionCommand.h39
-rw-r--r--src/FtpNegotiationCommand.cc332
-rw-r--r--src/FtpNegotiationCommand.h87
-rw-r--r--src/FtpTunnelRequestCommand.cc41
-rw-r--r--src/FtpTunnelRequestCommand.h35
-rw-r--r--src/FtpTunnelResponseCommand.cc49
-rw-r--r--src/FtpTunnelResponseCommand.h39
-rw-r--r--src/HttpConnection.cc130
-rw-r--r--src/HttpConnection.h27
-rw-r--r--src/HttpDownloadCommand.h3
-rw-r--r--src/HttpHeader.cc66
-rw-r--r--src/HttpHeader.h46
-rw-r--r--src/HttpInitiateConnectionCommand.cc31
-rw-r--r--src/HttpInitiateConnectionCommand.h2
-rw-r--r--src/HttpProxyRequestCommand.cc11
-rw-r--r--src/HttpProxyResponseCommand.cc15
-rw-r--r--src/HttpProxyResponseCommand.h3
-rw-r--r--src/HttpRequestCommand.cc11
-rw-r--r--src/HttpResponseCommand.cc46
-rw-r--r--src/HttpResponseCommand.h1
-rw-r--r--src/InitiateConnectionCommandFactory.cc3
-rw-r--r--src/Logger.h12
-rw-r--r--src/Makefile.am10
-rw-r--r--src/Makefile.in174
-rw-r--r--src/Option.cc9
-rw-r--r--src/Option.h1
-rw-r--r--src/Request.cc21
-rw-r--r--src/Request.h11
-rw-r--r--src/Segment.h7
-rw-r--r--src/SegmentMan.cc60
-rw-r--r--src/SegmentMan.h26
-rw-r--r--src/SegmentSplitter.cc46
-rw-r--r--src/SegmentSplitter.h42
-rw-r--r--src/SimpleLogger.cc25
-rw-r--r--src/SimpleLogger.h14
-rw-r--r--src/Socket.cc40
-rw-r--r--src/Socket.h26
-rw-r--r--src/SocketCore.cc113
-rw-r--r--src/SocketCore.h22
-rw-r--r--src/SplitFirstSegmentSplitter.cc37
-rw-r--r--src/SplitFirstSegmentSplitter.h34
-rw-r--r--src/SplitSlowestSegmentSplitter.cc50
-rw-r--r--src/SplitSlowestSegmentSplitter.h35
-rw-r--r--src/Util.cc29
-rw-r--r--src/Util.h6
-rw-r--r--src/main.cc222
-rw-r--r--src/message.h11
-rw-r--r--src/prefs.h83
61 files changed, 2420 insertions, 381 deletions
diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc
index 0a2f78d3..6fe1d2ae 100644
--- a/src/AbstractCommand.cc
+++ b/src/AbstractCommand.cc
@@ -27,14 +27,14 @@
#include "Util.h"
#include "message.h"
#include "SleepCommand.h"
-
-#define TIMEOUT_SEC 5
+#include "prefs.h"
AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):
Command(cuid), req(req), e(e), checkSocketIsReadable(false), checkSocketIsWritable(false) {
+
if(s != NULL) {
socket = new Socket(*s);
- e->addSocketForReadCheck(socket);
+ setReadCheckSocket(socket);
} else {
socket = NULL;
}
@@ -43,8 +43,8 @@ AbstractCommand::AbstractCommand(int cuid, Request* req, DownloadEngine* e, Sock
}
AbstractCommand::~AbstractCommand() {
- e->deleteSocketForReadCheck(socket);
- e->deleteSocketForWriteCheck(socket);
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(NULL);
if(socket != NULL) {
delete(socket);
}
@@ -58,10 +58,11 @@ bool AbstractCommand::isTimeoutDetected() {
struct timeval now;
gettimeofday(&now, NULL);
if(checkPoint.tv_sec == 0 && checkPoint.tv_usec == 0) {
+ checkPoint = now;
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;
@@ -71,12 +72,11 @@ bool AbstractCommand::isTimeoutDetected() {
bool AbstractCommand::execute() {
try {
- if(checkSocketIsReadable && !socket->isReadable(0)
- || checkSocketIsWritable && !socket->isWritable(0)) {
+ if(checkSocketIsReadable && !readCheckTarget->isReadable(0)
+ || checkSocketIsWritable && !writeCheckTarget->isWritable(0)) {
if(isTimeoutDetected()) {
throw new DlRetryEx(EX_TIME_OUT);
}
- updateCheckPoint();
e->commands.push(this);
return false;
}
@@ -93,21 +93,21 @@ bool AbstractCommand::execute() {
return executeInternal(seg);
} catch(DlAbortEx* err) {
e->logger->error(MSG_DOWNLOAD_ABORTED, err, cuid);
- onError(err);
+ onAbort(err);
delete(err);
req->resetUrl();
return true;
} catch(DlRetryEx* err) {
e->logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid);
- onError(err);
delete(err);
//req->resetUrl();
- req->addRetryCount();
- if(req->noMoreRetry()) {
- e->logger->error(MSG_MAX_RETRY, cuid);
+ req->addTryCount();
+ 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 {
- return prepareForRetry(e->option->getAsInt("retry_wait"));
+ return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
}
}
}
@@ -123,5 +123,49 @@ bool AbstractCommand::prepareForRetry(int wait) {
return true;
}
-void AbstractCommand::onError(Exception* e) {
+void AbstractCommand::onAbort(Exception* e) {
+}
+
+void AbstractCommand::setReadCheckSocket(Socket* socket) {
+ if(socket == NULL) {
+ if(checkSocketIsReadable) {
+ e->deleteSocketForReadCheck(readCheckTarget);
+ checkSocketIsReadable = false;
+ readCheckTarget = NULL;
+ }
+ } else {
+ if(checkSocketIsReadable) {
+ if(readCheckTarget != socket) {
+ e->deleteSocketForReadCheck(readCheckTarget);
+ e->addSocketForReadCheck(socket);
+ readCheckTarget = socket;
+ }
+ } else {
+ e->addSocketForReadCheck(socket);
+ checkSocketIsReadable = true;
+ readCheckTarget = socket;
+ }
+ }
+}
+
+void AbstractCommand::setWriteCheckSocket(Socket* socket) {
+ if(socket == NULL) {
+ if(checkSocketIsWritable) {
+ e->deleteSocketForWriteCheck(writeCheckTarget);
+ checkSocketIsWritable = false;
+ writeCheckTarget = NULL;
+ }
+ } else {
+ if(checkSocketIsWritable) {
+ if(writeCheckTarget != socket) {
+ e->deleteSocketForWriteCheck(writeCheckTarget);
+ e->addSocketForWriteCheck(socket);
+ writeCheckTarget = socket;
+ }
+ } else {
+ e->addSocketForWriteCheck(socket);
+ checkSocketIsWritable = true;
+ writeCheckTarget = socket;
+ }
+ }
}
diff --git a/src/AbstractCommand.h b/src/AbstractCommand.h
index 3d94511b..10b36462 100644
--- a/src/AbstractCommand.h
+++ b/src/AbstractCommand.h
@@ -37,11 +37,18 @@ protected:
Request* req;
DownloadEngine* e;
Socket* socket;
- bool checkSocketIsReadable;
- bool checkSocketIsWritable;
+
virtual bool prepareForRetry(int wait);
- virtual void onError(Exception* e);
+ virtual void onAbort(Exception* e);
virtual bool executeInternal(Segment segment) = 0;
+
+ void setReadCheckSocket(Socket* socket);
+ void setWriteCheckSocket(Socket* socket);
+private:
+ bool checkSocketIsReadable;
+ bool checkSocketIsWritable;
+ Socket* readCheckTarget;
+ Socket* writeCheckTarget;
public:
AbstractCommand(int cuid, Request* req, DownloadEngine* e, Socket* s= NULL);
virtual ~AbstractCommand();
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/DownloadCommand.cc b/src/DownloadCommand.cc
index 39391963..b771cbe5 100644
--- a/src/DownloadCommand.cc
+++ b/src/DownloadCommand.cc
@@ -27,8 +27,9 @@
#include "InitiateConnectionCommandFactory.h"
#include "message.h"
-DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
- AbstractCommand::checkSocketIsReadable = true;
+DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s), lastSize(0) {
+ sw.tv_sec = 0;
+ sw.tv_usec = 0;
}
DownloadCommand::~DownloadCommand() {}
@@ -52,6 +53,20 @@ bool DownloadCommand::executeInternal(Segment seg) {
e->diskWriter->writeData(buf, bufSize, seg.sp+seg.ds);
seg.ds += bufSize;
}
+ // calculate downloading speed
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if(sw.tv_sec == 0 && sw.tv_usec == 0) {
+ sw = now;
+ lastSize = seg.ds;
+ } else {
+ long long int diff = Util::difftv(now, sw);
+ if(diff >= 1000000) {
+ seg.speed = (int)((seg.ds-lastSize)/(diff/1000000.0));
+ sw = now;
+ lastSize = seg.ds;
+ }
+ }
if(te != NULL && te->finished()
|| te == NULL && seg.ds >= seg.ep-seg.sp+1
@@ -84,3 +99,8 @@ bool DownloadCommand::prepareForNextSegment() {
return true;
}
}
+
+void DownloadCommand::onAbort(Exception* ex) {
+ e->logger->debug(MSG_UNREGISTER_CUID, cuid);
+ e->segmentMan->unregisterId(cuid);
+}
diff --git a/src/DownloadCommand.h b/src/DownloadCommand.h
index 0ea9d680..3dd374e7 100644
--- a/src/DownloadCommand.h
+++ b/src/DownloadCommand.h
@@ -29,12 +29,15 @@
using namespace std;
class DownloadCommand : public AbstractCommand {
+private:
+ struct timeval sw;
+ long long int lastSize;
protected:
bool executeInternal(Segment segment);
bool prepareForRetry(int wait);
bool prepareForNextSegment();
-
+ void onAbort(Exception* ex);
public:
DownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
virtual ~DownloadCommand();
diff --git a/src/DownloadEngine.cc b/src/DownloadEngine.cc
index 0621e66b..80b98141 100644
--- a/src/DownloadEngine.cc
+++ b/src/DownloadEngine.cc
@@ -20,12 +20,11 @@
*/
/* copyright --> */
#include "DownloadEngine.h"
+#include "Util.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include "DlAbortEx.h"
-#include "Util.h"
using namespace std;
@@ -51,30 +50,31 @@ void DownloadEngine::run() {
}
if(!noWait && !commands.empty()) {
waitData();
- long long int dlSize = segmentMan->getDownloadedSize();
+ }
+ noWait = false;
- struct timeval now;
- gettimeofday(&now, NULL);
- if(cp.tv_sec == 0 && cp.tv_usec == 0) {
+ long long int dlSize = segmentMan->getDownloadedSize();
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if(cp.tv_sec == 0 && cp.tv_usec == 0) {
+ cp = now;
+ psize = dlSize;
+ } else {
+ long long int elapsed = Util::difftv(now, cp);
+ if(elapsed >= 500000) {
+ int nspeed = (int)((dlSize-psize)/(elapsed/1000000.0));
+ speed = (nspeed+speed)/2;
cp = now;
psize = dlSize;
- } else {
- long long int elapsed = Util::difftv(now, cp);
- if(elapsed >= 500000) {
- int nspeed = (int)((dlSize-psize)/(elapsed/1000000.0));
- speed = (nspeed+speed)/2;
- cp = now;
- psize = dlSize;
- cout << "\r ";
- cout << "\rProgress " << Util::llitos(dlSize, true) << " Bytes/" <<
- Util::llitos(segmentMan->totalSize, true) << " Bytes " <<
- (segmentMan->totalSize == 0 ? 0 : (dlSize*100)/segmentMan->totalSize) << "% " <<
- speed/1000.0 << "KB/s " <<
- "(" << commands.size() << " connections)" << flush;
- }
+ cout << "\r ";
+ cout << "\rProgress " << Util::llitos(dlSize, true) << " Bytes/" <<
+ Util::llitos(segmentMan->totalSize, true) << " Bytes " <<
+ (segmentMan->totalSize == 0 ? 0 : (dlSize*100)/segmentMan->totalSize) << "% " <<
+ speed/1000.0 << "KB/s " <<
+ "(" << commands.size() << " connections)" << flush;
}
}
- noWait = false;
+
}
segmentMan->removeIfFinished();
diskWriter->closeFile();
@@ -99,7 +99,7 @@ void DownloadEngine::waitData() {
fd_set wfds;
struct timeval tv;
int retval;
-
+
FD_ZERO(&rfds);
FD_ZERO(&wfds);
int max = 0;
@@ -110,6 +110,7 @@ void DownloadEngine::waitData() {
}
}
for(vector<Socket*>::iterator itr = wsockets.begin(); itr != wsockets.end(); itr++) {
+
FD_SET((*itr)->getSockfd(), &wfds);
if(max < (*itr)->getSockfd()) {
max = (*itr)->getSockfd();
@@ -118,7 +119,7 @@ void DownloadEngine::waitData() {
tv.tv_sec = 1;
tv.tv_usec = 0;
- retval = select(max+1, &rfds, &wfds, NULL, &tv);
+ retval = select(max+1, &rfds, /*&wfds*/NULL, NULL, &tv);
}
bool DownloadEngine::addSocket(vector<Socket*>& sockets, Socket* socket) {
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<Command*> 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
new file mode 100644
index 00000000..9e7b9d44
--- /dev/null
+++ b/src/FtpConnection.cc
@@ -0,0 +1,219 @@
+/* <!-- 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 "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(PREF_FTP_USER)+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendPass() const {
+ string request = "PASS "+option->get(PREF_FTP_PASSWD)+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, "PASS ********");
+ socket->writeData(request);
+}
+
+void FtpConnection::sendType() const {
+ 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_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendCwd() const {
+ string request = "CWD "+req->getDir()+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendSize() const {
+ string request = "SIZE "+req->getFile()+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendPasv() const {
+ string request = "PASV\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+Socket* FtpConnection::sendPort() const {
+ Socket* serverSocket = new Socket();
+ try {
+ serverSocket->beginListen();
+
+ pair<string, int> addrinfo;
+ socket->getAddrInfo(addrinfo);
+ int ipaddr[4];
+ sscanf(addrinfo.first.c_str(), "%d.%d.%d.%d",
+ &ipaddr[0], &ipaddr[1], &ipaddr[2], &ipaddr[3]);
+ serverSocket->getAddrInfo(addrinfo);
+ string request = "PORT "+
+ Util::itos(ipaddr[0])+","+Util::itos(ipaddr[1])+","+
+ Util::itos(ipaddr[2])+","+Util::itos(ipaddr[3])+","+
+ Util::itos(addrinfo.second/256)+","+Util::itos(addrinfo.second%256)+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+ } catch (Exception* ex) {
+ delete serverSocket;
+ throw;
+ }
+ return serverSocket;
+}
+
+void FtpConnection::sendRest(const Segment& segment) const {
+ string request = "REST "+Util::llitos(segment.sp+segment.ds)+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendRetr() const {
+ string request = "RETR "+req->getFile()+"\r\n";
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+int FtpConnection::getStatus(string response) const {
+ int status;
+ // When the response is not like "%d %*s",
+ // we return 0.
+ if(response.find_first_not_of("0123456789") != 3
+ || !(response.find(" ") == 3 || response.find("-") == 3)) {
+ return 0;
+ }
+ if(sscanf(response.c_str(), "%d %*s", &status) == 1) {
+ return status;
+ } else {
+ return 0;
+ }
+}
+
+bool FtpConnection::isEndOfResponse(int status, string response) const {
+ if(response.size() <= 4) {
+ return false;
+ }
+ // if forth character of buf is '-', then multi line response is expected.
+ if(response.at(3) == '-') {
+ // multi line response
+ string::size_type p;
+ p = response.find("\r\n"+Util::itos(status)+" ");
+ if(p == string::npos) {
+ return false;
+ }
+ }
+ if(Util::endsWith(response, "\r\n")) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FtpConnection::bulkReceiveResponse(pair<int, string>& response) {
+ char buf[1024];
+ while(socket->isReadable(0)) {
+ int size = sizeof(buf)-1;
+ socket->readData(buf, size);
+ buf[size] = '\0';
+ strbuf += buf;
+ }
+ int status;
+ if(strbuf.size() >= 4) {
+ status = getStatus(strbuf);
+ if(status == 0) {
+ throw new DlRetryEx(EX_INVALID_RESPONSE);
+ }
+ } else {
+ return false;
+ }
+ if(isEndOfResponse(status, strbuf)) {
+ logger->info(MSG_RECEIVE_RESPONSE, cuid, strbuf.c_str());
+ response.first = status;
+ response.second = strbuf;
+ strbuf.erase();
+ return true;
+ } else {
+ // didn't receive response fully.
+ return false;
+ }
+}
+
+int FtpConnection::receiveResponse() {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ return response.first;
+ } else {
+ return 0;
+ }
+}
+
+int FtpConnection::receiveSizeResponse(long long int& size) {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ if(response.first == 213) {
+ sscanf(response.second.c_str(), "%*d %Ld", &size);
+ }
+ return response.first;
+ } else {
+ return 0;
+ }
+}
+
+int FtpConnection::receivePasvResponse(pair<string, int>& dest) {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ if(response.first == 227) {
+ // we assume the format of response is "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)."
+ int h1, h2, h3, h4, p1, p2;
+ string::size_type p = response.second.find("(");
+ if(p >= 4) {
+ sscanf(response.second.substr(response.second.find("(")).c_str(),
+ "(%d,%d,%d,%d,%d,%d).",
+ &h1, &h2, &h3, &h4, &p1, &p2);
+ // ip address
+ dest.first = Util::itos(h1)+"."+Util::itos(h2)+"."+Util::itos(h3)+"."+Util::itos(h4);
+ // port number
+ dest.second = 256*p1+p2;
+ } else {
+ throw new DlRetryEx(EX_INVALID_RESPONSE);
+ }
+ }
+ return response.first;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/FtpConnection.h b/src/FtpConnection.h
new file mode 100644
index 00000000..6dab8e68
--- /dev/null
+++ b/src/FtpConnection.h
@@ -0,0 +1,65 @@
+/* <!-- 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_FTP_CONNECTION_H_
+#define _D_FTP_CONNECTION_H_
+
+#include "Socket.h"
+#include "Option.h"
+#include "Logger.h"
+#include "Segment.h"
+#include "Request.h"
+#include <utility>
+
+using namespace std;
+
+class FtpConnection {
+private:
+ int cuid;
+ const Socket* socket;
+ const Request* req;
+ const Option* option;
+ const Logger* logger;
+
+ string strbuf;
+
+ int getStatus(string response) const;
+ bool isEndOfResponse(int status, string response) const;
+ bool bulkReceiveResponse(pair<int, string>& response);
+public:
+ FtpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger);
+ ~FtpConnection();
+ void sendUser() const;
+ void sendPass() const;
+ void sendType() const;
+ void sendCwd() const;
+ void sendSize() const;
+ void sendPasv() const;
+ Socket* sendPort() const;
+ void sendRest(const Segment& segment) const;
+ void sendRetr() const;
+
+ int receiveResponse();
+ int receiveSizeResponse(long long int& size);
+ int receivePasvResponse(pair<string, int>& dest);
+};
+
+#endif // _D_FTP_CONNECTION_H_
diff --git a/src/FtpDownloadCommand.cc b/src/FtpDownloadCommand.cc
new file mode 100644
index 00000000..3d29c84c
--- /dev/null
+++ b/src/FtpDownloadCommand.cc
@@ -0,0 +1,38 @@
+/* <!-- 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 "FtpDownloadCommand.h"
+
+FtpDownloadCommand::FtpDownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* dataSocket, Socket* ctrlSocket):
+ DownloadCommand(cuid, req, e, dataSocket)
+{
+ this->ctrlSocket = new Socket(*ctrlSocket);
+}
+
+FtpDownloadCommand::~FtpDownloadCommand() {
+ if(ctrlSocket != NULL) {
+ delete ctrlSocket;
+ }
+}
+
+TransferEncoding* FtpDownloadCommand::getTransferEncoding(string name) {
+ return NULL;
+}
diff --git a/src/FtpDownloadCommand.h b/src/FtpDownloadCommand.h
new file mode 100644
index 00000000..b2db68a8
--- /dev/null
+++ b/src/FtpDownloadCommand.h
@@ -0,0 +1,37 @@
+/* <!-- 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_FTP_DOWNLOAD_COMMAND_H_
+#define _D_FTP_DOWNLOAD_COMMAND_H_
+
+#include "DownloadCommand.h"
+
+class FtpDownloadCommand : public DownloadCommand {
+private:
+ Socket* ctrlSocket;
+public:
+ FtpDownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* dataSocket, Socket* ctrlSocket);
+ ~FtpDownloadCommand();
+
+ TransferEncoding* getTransferEncoding(string name);
+};
+
+#endif // _D_FTP_DOWNLOAD_COMMAND_H_
diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc
new file mode 100644
index 00000000..03af4232
--- /dev/null
+++ b/src/FtpInitiateConnectionCommand.cc
@@ -0,0 +1,84 @@
+/* <!-- 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 "FtpInitiateConnectionCommand.h"
+#include "FtpNegotiationCommand.h"
+#include "HttpRequestCommand.h"
+#include "FtpTunnelRequestCommand.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include "prefs.h"
+
+FtpInitiateConnectionCommand::FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e):AbstractCommand(cuid, req, e) {}
+
+FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {}
+
+bool FtpInitiateConnectionCommand::executeInternal(Segment segment) {
+ if(!e->segmentMan->downloadStarted) {
+ e->segmentMan->filename = req->getFile();
+ bool segFileExists = e->segmentMan->segmentFileExists();
+ if(segFileExists) {
+ e->segmentMan->load();
+ e->diskWriter->openExistingFile(e->segmentMan->getFilePath());
+ e->segmentMan->downloadStarted = true;
+ } else {
+ e->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
+ }
+ }
+
+ socket = new Socket();
+ Command* command;
+ if(useHttpProxy()) {
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid,
+ 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);
+ } else if(useHttpProxyConnect()) {
+ command = new FtpTunnelRequestCommand(cuid, req, e, socket);
+ } else {
+ // TODO
+ throw new DlAbortEx("ERROR");
+ }
+ } else {
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(),
+ req->getPort());
+ socket->establishConnection(req->getHost(), req->getPort());
+ command = new FtpNegotiationCommand(cuid, req, e, socket);
+ }
+ e->commands.push(command);
+ return true;
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxy() const {
+ return e->option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE;
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxyGet() const {
+ return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_GET;
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxyConnect() const {
+ return useHttpProxy() && e->option->get(PREF_FTP_VIA_HTTP_PROXY) == V_TUNNEL;
+}
diff --git a/src/FtpInitiateConnectionCommand.h b/src/FtpInitiateConnectionCommand.h
new file mode 100644
index 00000000..0f997bf8
--- /dev/null
+++ b/src/FtpInitiateConnectionCommand.h
@@ -0,0 +1,39 @@
+/* <!-- 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_FTP_INITIATE_CONNECTION_COMMAND_H_
+#define _D_FTP_INITIATE_CONNECTION_COMMAND_H_
+
+#include "AbstractCommand.h"
+
+class FtpInitiateConnectionCommand : public AbstractCommand {
+private:
+ bool useHttpProxy() const;
+ bool useHttpProxyGet() const;
+ bool useHttpProxyConnect() const;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
+ ~FtpInitiateConnectionCommand();
+};
+
+#endif // _D_FTP_INITIATE_CONNECTION_COMMAND_H_
diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc
new file mode 100644
index 00000000..2f5bb342
--- /dev/null
+++ b/src/FtpNegotiationCommand.cc
@@ -0,0 +1,332 @@
+/* <!-- 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 "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),
+ dataSocket(NULL), serverSocket(NULL), sequence(SEQ_RECV_GREETING)
+{
+ ftp = new FtpConnection(cuid, socket, req, e->option, e->logger);
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(socket);
+}
+
+FtpNegotiationCommand::~FtpNegotiationCommand() {
+ if(dataSocket != NULL) {
+ delete dataSocket;
+ }
+ if(serverSocket != NULL) {
+ delete serverSocket;
+ }
+ delete ftp;
+}
+
+bool FtpNegotiationCommand::executeInternal(Segment segment) {
+ while(processSequence(segment));
+ if(sequence == SEQ_RETRY) {
+ return prepareForRetry(0);
+ } else if(sequence == SEQ_NEGOTIATION_COMPLETED) {
+ FtpDownloadCommand* command = new FtpDownloadCommand(cuid, req, e, dataSocket, socket);
+ e->commands.push(command);
+ return true;
+ } else {
+ e->commands.push(this);
+ return false;
+ }
+}
+
+bool FtpNegotiationCommand::recvGreeting() {
+ socket->setBlockingMode();
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 220) {
+ throw new DlRetryEx(EX_CONNECTION_FAILED);
+ }
+ sequence = SEQ_SEND_USER;
+
+ setReadCheckSocket(socket);
+ setWriteCheckSocket(NULL);
+
+ return true;
+}
+
+bool FtpNegotiationCommand::sendUser() {
+ ftp->sendUser();
+ sequence = SEQ_RECV_USER;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvUser() {
+ int status = ftp->receiveResponse();
+ switch(status) {
+ case 0:
+ return false;
+ case 230:
+ sequence = SEQ_SEND_TYPE;
+ break;
+ case 331:
+ sequence = SEQ_SEND_PASS;
+ break;
+ default:
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPass() {
+ ftp->sendPass();
+ sequence = SEQ_RECV_PASS;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPass() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 230) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_TYPE;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendType() {
+ ftp->sendType();
+ sequence = SEQ_RECV_TYPE;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvType() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 200) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_CWD;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendCwd() {
+ ftp->sendCwd();
+ sequence = SEQ_RECV_CWD;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvCwd() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 250) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_SIZE;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendSize() {
+ ftp->sendSize();
+ sequence = SEQ_RECV_SIZE;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvSize() {
+ long long int size = 0;
+ int status = ftp->receiveSizeResponse(size);
+ if(status == 0) {
+ return false;
+ }
+ if(status != 213) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ if(size == LONG_LONG_MAX || size < 0) {
+ throw new DlAbortEx(EX_TOO_LARGE_FILE, 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(PREF_FTP_PASV_ENABLED) == V_TRUE) {
+ sequence = SEQ_SEND_PASV;
+ } else {
+ sequence = SEQ_SEND_PORT;
+ }
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPort() {
+ serverSocket = ftp->sendPort();
+ sequence = SEQ_RECV_PORT;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPort() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 200) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_REST;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPasv() {
+ ftp->sendPasv();
+ sequence = SEQ_RECV_PASV;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPasv() {
+ pair<string, int> dest;
+ int status = ftp->receivePasvResponse(dest);
+ if(status == 0) {
+ return false;
+ }
+ if(status != 227) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ // make a data connection to the server.
+ dataSocket = new Socket();
+
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid,
+ dest.first.c_str(),
+ dest.second);
+ dataSocket->establishConnection(dest.first, dest.second);
+
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(dataSocket);
+
+ sequence = SEQ_SEND_REST_PASV;
+ return false;
+}
+
+bool FtpNegotiationCommand::sendRestPasv(const Segment& segment) {
+ dataSocket->setBlockingMode();
+ setReadCheckSocket(socket);
+ setWriteCheckSocket(NULL);
+ return sendRest(segment);
+}
+
+bool FtpNegotiationCommand::sendRest(const Segment& segment) {
+ ftp->sendRest(segment);
+ sequence = SEQ_RECV_REST;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvRest() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ // TODO if we recieve negative response, then we set e->segmentMan->splittable = false, and continue.
+ if(status != 350) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_RETR;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendRetr() {
+ ftp->sendRetr();
+ sequence = SEQ_RECV_RETR;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvRetr() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 150) {
+ throw new DlRetryEx(EX_BAD_STATUS, status);
+ }
+ if(e->option->get(PREF_FTP_PASV_ENABLED) != V_TRUE) {
+ assert(serverSocket);
+ dataSocket = serverSocket->acceptConnection();
+ }
+ sequence = SEQ_NEGOTIATION_COMPLETED;
+
+ return false;
+}
+
+bool FtpNegotiationCommand::processSequence(const Segment& segment) {
+ bool doNextSequence = true;
+ switch(sequence) {
+ case SEQ_RECV_GREETING:
+ return recvGreeting();
+ case SEQ_SEND_USER:
+ return sendUser();
+ case SEQ_RECV_USER:
+ return recvUser();
+ case SEQ_SEND_PASS:
+ return sendPass();
+ case SEQ_RECV_PASS:
+ return recvPass();
+ case SEQ_SEND_TYPE:
+ return sendType();
+ case SEQ_RECV_TYPE:
+ return recvType();
+ case SEQ_SEND_CWD:
+ return sendCwd();
+ case SEQ_RECV_CWD:
+ return recvCwd();
+ case SEQ_SEND_SIZE:
+ return sendSize();
+ case SEQ_RECV_SIZE:
+ return recvSize();
+ case SEQ_SEND_PORT:
+ return sendPort();
+ case SEQ_RECV_PORT:
+ return recvPort();
+ case SEQ_SEND_PASV:
+ return sendPasv();
+ case SEQ_RECV_PASV:
+ return recvPasv();
+ case SEQ_SEND_REST_PASV:
+ return sendRestPasv(segment);
+ case SEQ_SEND_REST:
+ return sendRest(segment);
+ case SEQ_RECV_REST:
+ return recvRest();
+ case SEQ_SEND_RETR:
+ return sendRetr();
+ case SEQ_RECV_RETR:
+ return recvRetr();
+ default:
+ abort();
+ }
+ return doNextSequence;
+}
diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h
new file mode 100644
index 00000000..29e2c0e6
--- /dev/null
+++ b/src/FtpNegotiationCommand.h
@@ -0,0 +1,87 @@
+/* <!-- 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_FTP_NEGOTIATION_COMMAND_H_
+#define _D_FTP_NEGOTIATION_COMMAND_H_
+
+#include "AbstractCommand.h"
+#include "FtpConnection.h"
+
+class FtpNegotiationCommand : public AbstractCommand {
+private:
+ enum Seq {
+ SEQ_RECV_GREETING,
+ SEQ_SEND_USER,
+ SEQ_RECV_USER,
+ SEQ_SEND_PASS,
+ SEQ_RECV_PASS,
+ SEQ_SEND_TYPE,
+ SEQ_RECV_TYPE,
+ SEQ_SEND_CWD,
+ SEQ_RECV_CWD,
+ SEQ_SEND_SIZE,
+ SEQ_RECV_SIZE,
+ SEQ_SEND_PORT,
+ SEQ_RECV_PORT,
+ SEQ_SEND_PASV,
+ SEQ_RECV_PASV,
+ SEQ_SEND_REST_PASV,
+ SEQ_SEND_REST,
+ SEQ_RECV_REST,
+ SEQ_SEND_RETR,
+ SEQ_RECV_RETR,
+ SEQ_NEGOTIATION_COMPLETED,
+ SEQ_RETRY
+ };
+ bool recvGreeting();
+ bool sendUser();
+ bool recvUser();
+ bool sendPass();
+ bool recvPass();
+ bool sendType();
+ bool recvType();
+ bool sendCwd();
+ bool recvCwd();
+ bool sendSize();
+ bool recvSize();
+ bool sendPort();
+ bool recvPort();
+ bool sendPasv();
+ bool recvPasv();
+ bool sendRest(const Segment& segment);
+ bool sendRestPasv(const Segment& segment);
+ bool recvRest();
+ bool sendRetr();
+ bool recvRetr();
+ bool processSequence(const Segment& segment);
+
+ Socket* dataSocket;
+ Socket* serverSocket;
+ int sequence;
+ FtpConnection* ftp;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpNegotiationCommand();
+};
+
+#endif // _D_FTP_NEGOTIATION_COMMAND_H_
diff --git a/src/FtpTunnelRequestCommand.cc b/src/FtpTunnelRequestCommand.cc
new file mode 100644
index 00000000..f103f7ce
--- /dev/null
+++ b/src/FtpTunnelRequestCommand.cc
@@ -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 --> */
+#include "FtpTunnelRequestCommand.h"
+#include "FtpTunnelResponseCommand.h"
+#include "HttpConnection.h"
+
+FtpTunnelRequestCommand::FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(NULL);
+}
+
+FtpTunnelRequestCommand::~FtpTunnelRequestCommand() {}
+
+bool FtpTunnelRequestCommand::executeInternal(Segment segment) {
+ socket->setBlockingMode();
+ HttpConnection httpConnection(cuid, socket, req, e->option, e->logger);
+ httpConnection.sendProxyRequest();
+
+ FtpTunnelResponseCommand* command = new FtpTunnelResponseCommand(cuid, req, e, socket);
+ e->commands.push(command);
+ return true;
+}
diff --git a/src/FtpTunnelRequestCommand.h b/src/FtpTunnelRequestCommand.h
new file mode 100644
index 00000000..817f1c9d
--- /dev/null
+++ b/src/FtpTunnelRequestCommand.h
@@ -0,0 +1,35 @@
+/* <!-- 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_FTP_TUNNEL_REQUEST_COMMAND_H_
+#define _D_FTP_TUNNEL_REQUEST_COMMAND_H_
+
+#include "AbstractCommand.h"
+
+class FtpTunnelRequestCommand : public AbstractCommand {
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpTunnelRequestCommand();
+};
+
+#endif // _D_FTP_TUNNEL_REQUEST_COMMAND_H_
diff --git a/src/FtpTunnelResponseCommand.cc b/src/FtpTunnelResponseCommand.cc
new file mode 100644
index 00000000..7009310c
--- /dev/null
+++ b/src/FtpTunnelResponseCommand.cc
@@ -0,0 +1,49 @@
+/* <!-- 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 "FtpTunnelResponseCommand.h"
+#include "FtpNegotiationCommand.h"
+#include "DlRetryEx.h"
+#include "message.h"
+
+FtpTunnelResponseCommand::FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
+ http = new HttpConnection(cuid, socket, req, e->option, e->logger);
+}
+
+FtpTunnelResponseCommand::~FtpTunnelResponseCommand() {
+ delete http;
+}
+
+bool FtpTunnelResponseCommand::executeInternal(Segment segment) {
+ HttpHeader headers;
+ int status = http->receiveResponse(headers);
+ if(status == 0) {
+ // we didn't receive all of headers yet.
+ e->commands.push(this);
+ return false;
+ }
+ if(status != 200) {
+ throw new DlRetryEx(EX_PROXY_CONNECTION_FAILED);
+ }
+ FtpNegotiationCommand* command = new FtpNegotiationCommand(cuid, req, e, socket);
+ e->commands.push(command);
+ return true;
+}
diff --git a/src/FtpTunnelResponseCommand.h b/src/FtpTunnelResponseCommand.h
new file mode 100644
index 00000000..eeba75ac
--- /dev/null
+++ b/src/FtpTunnelResponseCommand.h
@@ -0,0 +1,39 @@
+/* <!-- 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_FTP_TUNNEL_RESPONSE_COMMAND_H_
+#define _D_FTP_TUNNEL_RESPONSE_COMMAND_H_
+
+#include "AbstractCommand.h"
+#include "HttpConnection.h"
+
+class FtpTunnelResponseCommand : public AbstractCommand {
+private:
+ HttpConnection* http;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpTunnelResponseCommand();
+};
+
+#endif // _D_FTP_TUNNEL_RESPONSE_COMMAND_H_
+
diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc
index b22d9126..815975d2 100644
--- a/src/HttpConnection.cc
+++ b/src/HttpConnection.cc
@@ -20,55 +20,67 @@
*/
/* 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, Socket* socket, const Option* op, Logger* logger):cuid(cuid), socket(socket),option(op),logger(logger) {}
+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) {}
-void HttpConnection::sendRequest(const Request* req, const Segment& segment) {
- string request = createRequest(req, segment);
- logger->info(MSG_SENDING_HTTP_REQUEST, cuid, request.c_str());
+void HttpConnection::sendRequest(const Segment& segment) const {
+ string request = createRequest(segment);
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request.c_str(), request.size());
}
-void HttpConnection::sendProxyRequest(const Request* req) {
- string request = string("CONNECT ")+req->getHost()+":"+Util::llitos(req->getPort())+
+void HttpConnection::sendProxyRequest() const {
+ 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";
+ request += getProxyAuthString();
}
request += "\r\n";
- logger->info(MSG_SENDING_HTTP_REQUEST, cuid, request.c_str());
+ logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
socket->writeData(request.c_str(), request.size());
}
-string HttpConnection::getHost(const string& host, int port) {
+string HttpConnection::getProxyAuthString() const {
+ return "Proxy-Authorization: Basic "+
+ Base64::encode(option->get(PREF_HTTP_PROXY_USER)+":"+
+ option->get(PREF_HTTP_PROXY_PORT))+"\r\n";
+}
+
+string HttpConnection::getHost(const string& host, int port) const {
return host+(port == 80 || port == 443 ? "" : ":"+Util::llitos(port));
}
-string HttpConnection::createRequest(const Request* req, const Segment& segment) {
+string HttpConnection::createRequest(const Segment& segment) const {
string request = string("GET ")+
- // some servers cannot permit absolute URI as requet URI.
- //req->getCurrentUrl()+
- (req->getDir() == "/" ? "/" : req->getDir()+"/")+req->getFile()+
+ (req->getProtocol() == "ftp" || useProxy() && useProxyGet() ?
+ req->getCurrentUrl() :
+ ((req->getDir() == "/" ? "/" : req->getDir()+"/")+req->getFile()))+
string(" HTTP/1.1\r\n")+
"User-Agent: aria2\r\n"+
"Connection: close\r\n"+
- "Accept: */*\r\n"+
+ "Accept: */*\r\n"+ /* */
"Host: "+getHost(req->getHost(), req->getPort())+"\r\n"+
"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(useProxy() && useProxyAuth() && useProxyGet()) {
+ request += getProxyAuthString();
}
- 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";
@@ -87,48 +99,34 @@ string HttpConnection::createRequest(const Request* req, const Segment& segment)
}
int HttpConnection::receiveResponse(HttpHeader& headers) {
- string header;
- char* buf = NULL;
- try {
- // read a line of the header
- int bufSize = 256;
- // TODO limit iteration count
- while(1) {
- bufSize += 256;
- if(bufSize > 2048) {
- throw new DlAbortEx(EX_INVALID_HEADER);
- }
- buf = new char[bufSize];
- int tbufSize = bufSize-1;
- socket->peekData(buf, tbufSize);
- if(tbufSize > 0) {
- buf[tbufSize] = '\0';
- }
- header = buf;
- char* p;
- if((p = strstr(buf, "\r\n")) == buf) {
- throw new DlAbortEx(EX_NO_HEADER);
- }
- if((p = strstr(buf, "\r\n\r\n")) != NULL) {
- *(p+4) = '\0';
- header = buf;
- tbufSize = header.size();
- socket->readData(buf, tbufSize);
- delete [] buf;
- buf = NULL;
- break;
+ char buf[512];
+ while(socket->isReadable(0)) {
+ int size = sizeof(buf)-1;
+ socket->peekData(buf, size);
+ if(size == 0) {
+ throw new DlRetryEx(EX_INVALID_RESPONSE);
+ }
+ buf[size] = '\0';
+ int hlenTemp = header.size();
+ header += buf;
+ string::size_type p;
+ if((p = header.find("\r\n\r\n")) == string::npos) {
+ socket->readData(buf, size);
+ } else {
+ if(Util::endsWith(header, "\r\n\r\n")) {
+ socket->readData(buf, size);
} else {
- delete [] buf;
- buf = NULL;
+ header.erase(p+4);
+ size = p+4-hlenTemp;
+ socket->readData(buf, size);
}
+ break;
}
- } catch(Exception* e) {
- if(buf != NULL) {
- delete [] buf;
- }
- throw;
}
- // OK, i got all headers.
+ if(!Util::endsWith(header, "\r\n\r\n")) {
+ return 0;
+ }
+ // OK, we got all headers.
logger->info(MSG_RECEIVE_RESPONSE, cuid, header.c_str());
string::size_type p, np;
p = np = 0;
@@ -145,19 +143,19 @@ int HttpConnection::receiveResponse(HttpHeader& headers) {
p = np+2;
pair<string, string> hp;
Util::split(hp, line, ':');
- HttpHeader::value_type nh(hp.first, hp.second);
- headers.insert(nh);
+ headers.put(hp.first, hp.second);
}
- // TODO rewrite this using strtoul
return (int)strtol(status.c_str(), NULL, 10);
}
-bool HttpConnection::useProxy() {
- return option->defined("http_proxy_enabled") &&
- option->get("http_proxy_enabled") == "true";
+bool HttpConnection::useProxy() const {
+ return option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE;
+}
+
+bool HttpConnection::useProxyAuth() const {
+ return option->get(PREF_HTTP_PROXY_AUTH_ENABLED) == V_TRUE;
}
-bool HttpConnection::useProxyAuth() {
- return option->defined("http_proxy_auth_enabled") &&
- option->get("http_proxy_auth_enabled") == "true";
+bool HttpConnection::useProxyGet() const {
+ return option->get(PREF_HTTP_PROXY_METHOD) == V_GET;
}
diff --git a/src/HttpConnection.h b/src/HttpConnection.h
index c918d21d..f37ed892 100644
--- a/src/HttpConnection.h
+++ b/src/HttpConnection.h
@@ -27,30 +27,33 @@
#include "Request.h"
#include "Option.h"
#include "Logger.h"
+#include "HttpHeader.h"
#include <map>
#include <string>
using namespace std;
-typedef multimap<string, string> HttpHeader;
+//typedef multimap<string, string> HttpHeader;
class HttpConnection {
private:
- string getHost(const string& host, int port);
- string createRequest(const Request* req, const Segment& segment);
- bool useProxy();
- bool useProxyAuth();
- bool useBasicAuth();
+ string getHost(const string& host, int port) const;
+ string createRequest(const Segment& segment) const;
+ bool useProxy() const;
+ bool useProxyAuth() const;
+ bool useProxyGet() const;
+ string getProxyAuthString() const;
int cuid;
- Socket* socket;
+ const Socket* socket;
+ const Request* req;
const Option* option;
- Logger* logger;
+ const Logger* logger;
+ string header;
public:
+ HttpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger);
- HttpConnection(int cuid, Socket* socket, const Option* op, Logger* logger);
-
- void sendRequest(const Request* req, const Segment& segment);
- void sendProxyRequest(const Request* req);
+ void sendRequest(const Segment& segment) const;
+ void sendProxyRequest() const;
int receiveResponse(HttpHeader& headers);
};
diff --git a/src/HttpDownloadCommand.h b/src/HttpDownloadCommand.h
index dbd50fa6..81a537d0 100644
--- a/src/HttpDownloadCommand.h
+++ b/src/HttpDownloadCommand.h
@@ -37,13 +37,10 @@ class HttpDownloadCommand:public DownloadCommand {
private:
map<string, TransferEncoding*> transferEncodings;
public:
- int cuid;
-
HttpDownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
~HttpDownloadCommand();
TransferEncoding* getTransferEncoding(string transferEncoding);
-
};
#endif // _D_HTTP_DOWNLOAD_COMMAND_H_
diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc
new file mode 100644
index 00000000..eb80cf5b
--- /dev/null
+++ b/src/HttpHeader.cc
@@ -0,0 +1,66 @@
+/* <!-- 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 "HttpHeader.h"
+
+void HttpHeader::put(const string& name, const string& value) {
+ multimap<string, string>::value_type vt(name, value);
+ table.insert(vt);
+}
+
+bool HttpHeader::defined(const string& name) const {
+ return table.count(name) == 1;
+}
+
+string HttpHeader::getFirst(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return "";
+ } else {
+ return (*itr).second;
+ }
+}
+
+vector<string> HttpHeader::get(const string& name) const {
+ vector<string> v;
+ for(multimap<string, string>::const_iterator itr = table.find(name); itr != table.end(); itr++) {
+ v.push_back((*itr).second);
+ }
+ return v;
+}
+
+int HttpHeader::getFirstAsInt(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return 0;
+ } else {
+ return (int)strtol((*itr).second.c_str(), NULL, 10);
+ }
+}
+
+long long int HttpHeader::getFirstAsLLInt(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return 0;
+ } else {
+ return strtoll((*itr).second.c_str(), NULL, 10);
+ }
+}
diff --git a/src/HttpHeader.h b/src/HttpHeader.h
new file mode 100644
index 00000000..3bcaa479
--- /dev/null
+++ b/src/HttpHeader.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_HTTP_HEADER_H_
+#define _D_HTTP_HEADER_H_
+
+#include <map>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+class HttpHeader {
+private:
+ multimap<string, string> table;
+public:
+ HttpHeader() {}
+ ~HttpHeader() {}
+
+ void put(const string& name, const string& value);
+ bool defined(const string& name) const;
+ string getFirst(const string& name) const;
+ vector<string> get(const string& name) const;
+ int getFirstAsInt(const string& name) const;
+ long long int getFirstAsLLInt(const string& name) const;
+};
+
+#endif // _D_HTTP_HEADER_H_
diff --git a/src/HttpInitiateConnectionCommand.cc b/src/HttpInitiateConnectionCommand.cc
index e94c39c9..f3cdc655 100644
--- a/src/HttpInitiateConnectionCommand.cc
+++ b/src/HttpInitiateConnectionCommand.cc
@@ -23,7 +23,9 @@
#include "HttpRequestCommand.h"
#include "HttpProxyRequestCommand.h"
#include "Util.h"
+#include "DlAbortEx.h"
#include "message.h"
+#include "prefs.h"
HttpInitiateConnectionCommand::HttpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e):AbstractCommand(cuid, req, e) {}
@@ -35,12 +37,18 @@ 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"));
- command = new HttpProxyRequestCommand(cuid, req, e, socket);
-
+ 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(useProxyTunnel()) {
+ command = new HttpProxyRequestCommand(cuid, req, e, socket);
+ } else if(useProxyGet()) {
+ command = new HttpRequestCommand(cuid, req, e, socket);
+ } else {
+ // TODO
+ throw new DlAbortEx("ERROR");
+ }
} else {
e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(),
req->getPort());
@@ -52,6 +60,13 @@ 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;
+}
+
+bool HttpInitiateConnectionCommand::useProxyGet() {
+ return e->option->get(PREF_HTTP_PROXY_METHOD) == V_GET;
+}
+
+bool HttpInitiateConnectionCommand::useProxyTunnel() {
+ return e->option->get(PREF_HTTP_PROXY_METHOD) == V_TUNNEL;
}
diff --git a/src/HttpInitiateConnectionCommand.h b/src/HttpInitiateConnectionCommand.h
index 19cc9bd3..e605ec1b 100644
--- a/src/HttpInitiateConnectionCommand.h
+++ b/src/HttpInitiateConnectionCommand.h
@@ -27,6 +27,8 @@
class HttpInitiateConnectionCommand : public AbstractCommand {
private:
bool useProxy();
+ bool useProxyGet();
+ bool useProxyTunnel();
protected:
/**
* Connect to the server.
diff --git a/src/HttpProxyRequestCommand.cc b/src/HttpProxyRequestCommand.cc
index bbff980a..f1a5a8c9 100644
--- a/src/HttpProxyRequestCommand.cc
+++ b/src/HttpProxyRequestCommand.cc
@@ -24,17 +24,16 @@
#include "HttpProxyResponseCommand.h"
HttpProxyRequestCommand::HttpProxyRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
- AbstractCommand::checkSocketIsWritable = true;
- e->deleteSocketForReadCheck(socket);
- e->addSocketForWriteCheck(socket);
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(socket);
}
HttpProxyRequestCommand::~HttpProxyRequestCommand() {}
bool HttpProxyRequestCommand::executeInternal(Segment segment) {
- socket->setNonBlockingMode();
- HttpConnection httpConnection(cuid, socket, e->option, e->logger);
- httpConnection.sendProxyRequest(req);
+ socket->setBlockingMode();
+ HttpConnection httpConnection(cuid, socket, req, e->option, e->logger);
+ httpConnection.sendProxyRequest();
HttpProxyResponseCommand* command = new HttpProxyResponseCommand(cuid, req, e, socket);
e->commands.push(command);
diff --git a/src/HttpProxyResponseCommand.cc b/src/HttpProxyResponseCommand.cc
index e62d3939..cb2764b9 100644
--- a/src/HttpProxyResponseCommand.cc
+++ b/src/HttpProxyResponseCommand.cc
@@ -22,19 +22,24 @@
#include "HttpProxyResponseCommand.h"
#include "HttpRequestCommand.h"
#include "DlRetryEx.h"
-#include "HttpConnection.h"
#include "message.h"
HttpProxyResponseCommand::HttpProxyResponseCommand(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);
}
-HttpProxyResponseCommand::~HttpProxyResponseCommand() {}
+HttpProxyResponseCommand::~HttpProxyResponseCommand() {
+ delete http;
+}
bool HttpProxyResponseCommand::executeInternal(Segment segment) {
HttpHeader headers;
- HttpConnection httpConnection(cuid, socket, e->option, e->logger);
- int status = httpConnection.receiveResponse(headers);
+ int status = http->receiveResponse(headers);
+ if(status == 0) {
+ // we didn't receive all of headers yet.
+ e->commands.push(this);
+ return false;
+ }
if(status != 200) {
throw new DlRetryEx(EX_PROXY_CONNECTION_FAILED);
}
diff --git a/src/HttpProxyResponseCommand.h b/src/HttpProxyResponseCommand.h
index 6ff0f2ab..370066e4 100644
--- a/src/HttpProxyResponseCommand.h
+++ b/src/HttpProxyResponseCommand.h
@@ -23,8 +23,11 @@
#define _D_HTTP_PROXY_RESPONSE_COMMAND_H_
#include "AbstractCommand.h"
+#include "HttpConnection.h"
class HttpProxyResponseCommand : public AbstractCommand {
+private:
+ HttpConnection* http;
protected:
bool executeInternal(Segment segment);
public:
diff --git a/src/HttpRequestCommand.cc b/src/HttpRequestCommand.cc
index caa8413a..42090bef 100644
--- a/src/HttpRequestCommand.cc
+++ b/src/HttpRequestCommand.cc
@@ -27,22 +27,21 @@
#include "HttpConnection.h"
HttpRequestCommand::HttpRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
- AbstractCommand::checkSocketIsWritable = true;
- e->deleteSocketForReadCheck(socket);
- e->addSocketForWriteCheck(socket);
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(socket);
}
HttpRequestCommand::~HttpRequestCommand() {}
bool HttpRequestCommand::executeInternal(Segment seg) {
- socket->setNonBlockingMode();
+ socket->setBlockingMode();
if(req->getProtocol() == "https") {
socket->initiateSecureConnection();
}
- HttpConnection httpConnection(cuid, socket, e->option, e->logger);
+ HttpConnection http(cuid, socket, req, e->option, e->logger);
// set seg to request in order to remember the request range
req->seg = seg;
- httpConnection.sendRequest(req, seg);
+ http.sendRequest(seg);
HttpResponseCommand* command = new HttpResponseCommand(cuid, req, e, socket);
e->commands.push(command);
diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc
index 22c7fa71..30e65db1 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"
@@ -28,10 +29,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,22 +42,25 @@ 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);
}
@@ -71,7 +77,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);
}
}
@@ -83,18 +89,12 @@ 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 < 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) {
@@ -103,8 +103,7 @@ bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) {
// 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 +139,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<string> v = headers.get("Set-Cookie");
+ for(vector<string>::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);
}
}
diff --git a/src/HttpResponseCommand.h b/src/HttpResponseCommand.h
index 8300bdc2..c5269235 100644
--- a/src/HttpResponseCommand.h
+++ b/src/HttpResponseCommand.h
@@ -33,6 +33,7 @@ private:
bool handleOtherEncoding(string transferEncoding, const HttpHeader& headers);
void createHttpDownloadCommand(string transferEncoding = "");
void retrieveCookie(const HttpHeader& headers);
+ HttpConnection* http;
protected:
bool executeInternal(Segment segment);
public:
diff --git a/src/InitiateConnectionCommandFactory.cc b/src/InitiateConnectionCommandFactory.cc
index 3ba177bd..e72c6020 100644
--- a/src/InitiateConnectionCommandFactory.cc
+++ b/src/InitiateConnectionCommandFactory.cc
@@ -21,6 +21,7 @@
/* copyright --> */
#include "InitiateConnectionCommandFactory.h"
#include "HttpInitiateConnectionCommand.h"
+#include "FtpInitiateConnectionCommand.h"
Command* InitiateConnectionCommandFactory::createInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e) {
if(req->getProtocol() == "http"
@@ -30,6 +31,8 @@ Command* InitiateConnectionCommandFactory::createInitiateConnectionCommand(int c
#endif // HAVE_LIBSSL
) {
return new HttpInitiateConnectionCommand(cuid, req, e);
+ } else if(req->getProtocol() == "ftp") {
+ return new FtpInitiateConnectionCommand(cuid, req, e);
} else {
// these protocols are not supported yet
return NULL;
diff --git a/src/Logger.h b/src/Logger.h
index 620544ea..7e842b76 100644
--- a/src/Logger.h
+++ b/src/Logger.h
@@ -29,12 +29,12 @@ using namespace std;
class Logger {
public:
virtual ~Logger() {}
- virtual void debug(string msg, ...) = 0;
- virtual void debug(string msg, Exception* ex, ...) = 0;
- virtual void info(string msg, ...) = 0;
- virtual void info(string msg, Exception* ex, ...) = 0;
- virtual void error(string msg, ...) = 0;
- virtual void error(string msg, Exception* ex, ...) = 0;
+ virtual void debug(string msg, ...) const = 0;
+ virtual void debug(string msg, Exception* ex, ...) const = 0;
+ virtual void info(string msg, ...) const = 0;
+ virtual void info(string msg, Exception* ex, ...) const = 0;
+ virtual void error(string msg, ...) const = 0;
+ virtual void error(string msg, Exception* ex, ...) const = 0;
};
#endif // _D_LOGGER_H_
diff --git a/src/Makefile.am b/src/Makefile.am
index 6b5994ea..796cdd82 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,11 +12,21 @@ SRCS = Socket.cc Socket.h\
HttpProxyRequestCommand.cc HttpProxyRequestCommand.h\
HttpProxyResponseCommand.cc HttpProxyResponseCommand.h\
HttpDownloadCommand.cc HttpDownloadCommand.h\
+ HttpHeader.cc HttpHeader.h\
HttpConnection.cc HttpConnection.h\
+ FtpConnection.cc FtpConnection.h\
+ FtpInitiateConnectionCommand.cc FtpInitiateConnectionCommand.h\
+ FtpNegotiationCommand.cc FtpNegotiationCommand.h\
+ FtpDownloadCommand.cc FtpDownloadCommand.h\
+ FtpTunnelRequestCommand.cc FtpTunnelRequestCommand.h\
+ FtpTunnelResponseCommand.cc FtpTunnelResponseCommand.h\
SleepCommand.cc SleepCommand.h\
DownloadEngine.cc DownloadEngine.h\
Segment.h\
SegmentMan.cc SegmentMan.h\
+ SegmentSplitter.cc SegmentSplitter.h\
+ SplitFirstSegmentSplitter.cc SplitFirstSegmentSplitter.h\
+ SplitSlowestSegmentSplitter.cc SplitSlowestSegmentSplitter.h\
Util.cc Util.h\
Request.cc Request.h\
common.h\
diff --git a/src/Makefile.in b/src/Makefile.in
index 006717df..51f4454a 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -61,11 +61,21 @@ am__objects_1 = libaria2c_a-Socket.$(OBJEXT) \
libaria2c_a-HttpProxyRequestCommand.$(OBJEXT) \
libaria2c_a-HttpProxyResponseCommand.$(OBJEXT) \
libaria2c_a-HttpDownloadCommand.$(OBJEXT) \
+ libaria2c_a-HttpHeader.$(OBJEXT) \
libaria2c_a-HttpConnection.$(OBJEXT) \
+ libaria2c_a-FtpConnection.$(OBJEXT) \
+ libaria2c_a-FtpInitiateConnectionCommand.$(OBJEXT) \
+ libaria2c_a-FtpNegotiationCommand.$(OBJEXT) \
+ libaria2c_a-FtpDownloadCommand.$(OBJEXT) \
+ libaria2c_a-FtpTunnelRequestCommand.$(OBJEXT) \
+ libaria2c_a-FtpTunnelResponseCommand.$(OBJEXT) \
libaria2c_a-SleepCommand.$(OBJEXT) \
libaria2c_a-DownloadEngine.$(OBJEXT) \
- libaria2c_a-SegmentMan.$(OBJEXT) libaria2c_a-Util.$(OBJEXT) \
- libaria2c_a-Request.$(OBJEXT) \
+ libaria2c_a-SegmentMan.$(OBJEXT) \
+ libaria2c_a-SegmentSplitter.$(OBJEXT) \
+ libaria2c_a-SplitFirstSegmentSplitter.$(OBJEXT) \
+ libaria2c_a-SplitSlowestSegmentSplitter.$(OBJEXT) \
+ libaria2c_a-Util.$(OBJEXT) libaria2c_a-Request.$(OBJEXT) \
libaria2c_a-SimpleLogger.$(OBJEXT) \
libaria2c_a-ChunkedEncoding.$(OBJEXT) \
libaria2c_a-DefaultDiskWriter.$(OBJEXT) \
@@ -192,11 +202,21 @@ SRCS = Socket.cc Socket.h\
HttpProxyRequestCommand.cc HttpProxyRequestCommand.h\
HttpProxyResponseCommand.cc HttpProxyResponseCommand.h\
HttpDownloadCommand.cc HttpDownloadCommand.h\
+ HttpHeader.cc HttpHeader.h\
HttpConnection.cc HttpConnection.h\
+ FtpConnection.cc FtpConnection.h\
+ FtpInitiateConnectionCommand.cc FtpInitiateConnectionCommand.h\
+ FtpNegotiationCommand.cc FtpNegotiationCommand.h\
+ FtpDownloadCommand.cc FtpDownloadCommand.h\
+ FtpTunnelRequestCommand.cc FtpTunnelRequestCommand.h\
+ FtpTunnelResponseCommand.cc FtpTunnelResponseCommand.h\
SleepCommand.cc SleepCommand.h\
DownloadEngine.cc DownloadEngine.h\
Segment.h\
SegmentMan.cc SegmentMan.h\
+ SegmentSplitter.cc SegmentSplitter.h\
+ SplitFirstSegmentSplitter.cc SplitFirstSegmentSplitter.h\
+ SplitSlowestSegmentSplitter.cc SplitSlowestSegmentSplitter.h\
Util.cc Util.h\
Request.cc Request.h\
common.h\
@@ -305,8 +325,15 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-DownloadCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-DownloadEngine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-File.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpConnection.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpConnection.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpDownloadCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpHeader.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpInitiateConnectionCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpProxyRequestCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-HttpProxyResponseCommand.Po@am__quote@
@@ -316,10 +343,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Option.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SegmentMan.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SegmentSplitter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SimpleLogger.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SleepCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Socket.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SocketCore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaria2c_a-Util.Po@am__quote@
.cc.o:
@@ -490,6 +520,20 @@ libaria2c_a-HttpDownloadCommand.obj: HttpDownloadCommand.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-HttpDownloadCommand.obj `if test -f 'HttpDownloadCommand.cc'; then $(CYGPATH_W) 'HttpDownloadCommand.cc'; else $(CYGPATH_W) '$(srcdir)/HttpDownloadCommand.cc'; fi`
+libaria2c_a-HttpHeader.o: HttpHeader.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-HttpHeader.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo" -c -o libaria2c_a-HttpHeader.o `test -f 'HttpHeader.cc' || echo '$(srcdir)/'`HttpHeader.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo" "$(DEPDIR)/libaria2c_a-HttpHeader.Po"; else rm -f "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='HttpHeader.cc' object='libaria2c_a-HttpHeader.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-HttpHeader.o `test -f 'HttpHeader.cc' || echo '$(srcdir)/'`HttpHeader.cc
+
+libaria2c_a-HttpHeader.obj: HttpHeader.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-HttpHeader.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo" -c -o libaria2c_a-HttpHeader.obj `if test -f 'HttpHeader.cc'; then $(CYGPATH_W) 'HttpHeader.cc'; else $(CYGPATH_W) '$(srcdir)/HttpHeader.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo" "$(DEPDIR)/libaria2c_a-HttpHeader.Po"; else rm -f "$(DEPDIR)/libaria2c_a-HttpHeader.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='HttpHeader.cc' object='libaria2c_a-HttpHeader.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-HttpHeader.obj `if test -f 'HttpHeader.cc'; then $(CYGPATH_W) 'HttpHeader.cc'; else $(CYGPATH_W) '$(srcdir)/HttpHeader.cc'; fi`
+
libaria2c_a-HttpConnection.o: HttpConnection.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-HttpConnection.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-HttpConnection.Tpo" -c -o libaria2c_a-HttpConnection.o `test -f 'HttpConnection.cc' || echo '$(srcdir)/'`HttpConnection.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-HttpConnection.Tpo" "$(DEPDIR)/libaria2c_a-HttpConnection.Po"; else rm -f "$(DEPDIR)/libaria2c_a-HttpConnection.Tpo"; exit 1; fi
@@ -504,6 +548,90 @@ libaria2c_a-HttpConnection.obj: HttpConnection.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-HttpConnection.obj `if test -f 'HttpConnection.cc'; then $(CYGPATH_W) 'HttpConnection.cc'; else $(CYGPATH_W) '$(srcdir)/HttpConnection.cc'; fi`
+libaria2c_a-FtpConnection.o: FtpConnection.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpConnection.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo" -c -o libaria2c_a-FtpConnection.o `test -f 'FtpConnection.cc' || echo '$(srcdir)/'`FtpConnection.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo" "$(DEPDIR)/libaria2c_a-FtpConnection.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpConnection.cc' object='libaria2c_a-FtpConnection.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpConnection.o `test -f 'FtpConnection.cc' || echo '$(srcdir)/'`FtpConnection.cc
+
+libaria2c_a-FtpConnection.obj: FtpConnection.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpConnection.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo" -c -o libaria2c_a-FtpConnection.obj `if test -f 'FtpConnection.cc'; then $(CYGPATH_W) 'FtpConnection.cc'; else $(CYGPATH_W) '$(srcdir)/FtpConnection.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo" "$(DEPDIR)/libaria2c_a-FtpConnection.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpConnection.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpConnection.cc' object='libaria2c_a-FtpConnection.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpConnection.obj `if test -f 'FtpConnection.cc'; then $(CYGPATH_W) 'FtpConnection.cc'; else $(CYGPATH_W) '$(srcdir)/FtpConnection.cc'; fi`
+
+libaria2c_a-FtpInitiateConnectionCommand.o: FtpInitiateConnectionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpInitiateConnectionCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo" -c -o libaria2c_a-FtpInitiateConnectionCommand.o `test -f 'FtpInitiateConnectionCommand.cc' || echo '$(srcdir)/'`FtpInitiateConnectionCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpInitiateConnectionCommand.cc' object='libaria2c_a-FtpInitiateConnectionCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpInitiateConnectionCommand.o `test -f 'FtpInitiateConnectionCommand.cc' || echo '$(srcdir)/'`FtpInitiateConnectionCommand.cc
+
+libaria2c_a-FtpInitiateConnectionCommand.obj: FtpInitiateConnectionCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpInitiateConnectionCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo" -c -o libaria2c_a-FtpInitiateConnectionCommand.obj `if test -f 'FtpInitiateConnectionCommand.cc'; then $(CYGPATH_W) 'FtpInitiateConnectionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpInitiateConnectionCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpInitiateConnectionCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpInitiateConnectionCommand.cc' object='libaria2c_a-FtpInitiateConnectionCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpInitiateConnectionCommand.obj `if test -f 'FtpInitiateConnectionCommand.cc'; then $(CYGPATH_W) 'FtpInitiateConnectionCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpInitiateConnectionCommand.cc'; fi`
+
+libaria2c_a-FtpNegotiationCommand.o: FtpNegotiationCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpNegotiationCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo" -c -o libaria2c_a-FtpNegotiationCommand.o `test -f 'FtpNegotiationCommand.cc' || echo '$(srcdir)/'`FtpNegotiationCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpNegotiationCommand.cc' object='libaria2c_a-FtpNegotiationCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpNegotiationCommand.o `test -f 'FtpNegotiationCommand.cc' || echo '$(srcdir)/'`FtpNegotiationCommand.cc
+
+libaria2c_a-FtpNegotiationCommand.obj: FtpNegotiationCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpNegotiationCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo" -c -o libaria2c_a-FtpNegotiationCommand.obj `if test -f 'FtpNegotiationCommand.cc'; then $(CYGPATH_W) 'FtpNegotiationCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpNegotiationCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpNegotiationCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpNegotiationCommand.cc' object='libaria2c_a-FtpNegotiationCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpNegotiationCommand.obj `if test -f 'FtpNegotiationCommand.cc'; then $(CYGPATH_W) 'FtpNegotiationCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpNegotiationCommand.cc'; fi`
+
+libaria2c_a-FtpDownloadCommand.o: FtpDownloadCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpDownloadCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo" -c -o libaria2c_a-FtpDownloadCommand.o `test -f 'FtpDownloadCommand.cc' || echo '$(srcdir)/'`FtpDownloadCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpDownloadCommand.cc' object='libaria2c_a-FtpDownloadCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpDownloadCommand.o `test -f 'FtpDownloadCommand.cc' || echo '$(srcdir)/'`FtpDownloadCommand.cc
+
+libaria2c_a-FtpDownloadCommand.obj: FtpDownloadCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpDownloadCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo" -c -o libaria2c_a-FtpDownloadCommand.obj `if test -f 'FtpDownloadCommand.cc'; then $(CYGPATH_W) 'FtpDownloadCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpDownloadCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpDownloadCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpDownloadCommand.cc' object='libaria2c_a-FtpDownloadCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpDownloadCommand.obj `if test -f 'FtpDownloadCommand.cc'; then $(CYGPATH_W) 'FtpDownloadCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpDownloadCommand.cc'; fi`
+
+libaria2c_a-FtpTunnelRequestCommand.o: FtpTunnelRequestCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpTunnelRequestCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo" -c -o libaria2c_a-FtpTunnelRequestCommand.o `test -f 'FtpTunnelRequestCommand.cc' || echo '$(srcdir)/'`FtpTunnelRequestCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpTunnelRequestCommand.cc' object='libaria2c_a-FtpTunnelRequestCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpTunnelRequestCommand.o `test -f 'FtpTunnelRequestCommand.cc' || echo '$(srcdir)/'`FtpTunnelRequestCommand.cc
+
+libaria2c_a-FtpTunnelRequestCommand.obj: FtpTunnelRequestCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpTunnelRequestCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo" -c -o libaria2c_a-FtpTunnelRequestCommand.obj `if test -f 'FtpTunnelRequestCommand.cc'; then $(CYGPATH_W) 'FtpTunnelRequestCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpTunnelRequestCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpTunnelRequestCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpTunnelRequestCommand.cc' object='libaria2c_a-FtpTunnelRequestCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpTunnelRequestCommand.obj `if test -f 'FtpTunnelRequestCommand.cc'; then $(CYGPATH_W) 'FtpTunnelRequestCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpTunnelRequestCommand.cc'; fi`
+
+libaria2c_a-FtpTunnelResponseCommand.o: FtpTunnelResponseCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpTunnelResponseCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo" -c -o libaria2c_a-FtpTunnelResponseCommand.o `test -f 'FtpTunnelResponseCommand.cc' || echo '$(srcdir)/'`FtpTunnelResponseCommand.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpTunnelResponseCommand.cc' object='libaria2c_a-FtpTunnelResponseCommand.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpTunnelResponseCommand.o `test -f 'FtpTunnelResponseCommand.cc' || echo '$(srcdir)/'`FtpTunnelResponseCommand.cc
+
+libaria2c_a-FtpTunnelResponseCommand.obj: FtpTunnelResponseCommand.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-FtpTunnelResponseCommand.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo" -c -o libaria2c_a-FtpTunnelResponseCommand.obj `if test -f 'FtpTunnelResponseCommand.cc'; then $(CYGPATH_W) 'FtpTunnelResponseCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpTunnelResponseCommand.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo" "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-FtpTunnelResponseCommand.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='FtpTunnelResponseCommand.cc' object='libaria2c_a-FtpTunnelResponseCommand.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-FtpTunnelResponseCommand.obj `if test -f 'FtpTunnelResponseCommand.cc'; then $(CYGPATH_W) 'FtpTunnelResponseCommand.cc'; else $(CYGPATH_W) '$(srcdir)/FtpTunnelResponseCommand.cc'; fi`
+
libaria2c_a-SleepCommand.o: SleepCommand.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SleepCommand.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-SleepCommand.Tpo" -c -o libaria2c_a-SleepCommand.o `test -f 'SleepCommand.cc' || echo '$(srcdir)/'`SleepCommand.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SleepCommand.Tpo" "$(DEPDIR)/libaria2c_a-SleepCommand.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SleepCommand.Tpo"; exit 1; fi
@@ -546,6 +674,48 @@ libaria2c_a-SegmentMan.obj: SegmentMan.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SegmentMan.obj `if test -f 'SegmentMan.cc'; then $(CYGPATH_W) 'SegmentMan.cc'; else $(CYGPATH_W) '$(srcdir)/SegmentMan.cc'; fi`
+libaria2c_a-SegmentSplitter.o: SegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SegmentSplitter.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo" -c -o libaria2c_a-SegmentSplitter.o `test -f 'SegmentSplitter.cc' || echo '$(srcdir)/'`SegmentSplitter.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SegmentSplitter.cc' object='libaria2c_a-SegmentSplitter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SegmentSplitter.o `test -f 'SegmentSplitter.cc' || echo '$(srcdir)/'`SegmentSplitter.cc
+
+libaria2c_a-SegmentSplitter.obj: SegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SegmentSplitter.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo" -c -o libaria2c_a-SegmentSplitter.obj `if test -f 'SegmentSplitter.cc'; then $(CYGPATH_W) 'SegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SegmentSplitter.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SegmentSplitter.cc' object='libaria2c_a-SegmentSplitter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SegmentSplitter.obj `if test -f 'SegmentSplitter.cc'; then $(CYGPATH_W) 'SegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SegmentSplitter.cc'; fi`
+
+libaria2c_a-SplitFirstSegmentSplitter.o: SplitFirstSegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SplitFirstSegmentSplitter.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo" -c -o libaria2c_a-SplitFirstSegmentSplitter.o `test -f 'SplitFirstSegmentSplitter.cc' || echo '$(srcdir)/'`SplitFirstSegmentSplitter.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SplitFirstSegmentSplitter.cc' object='libaria2c_a-SplitFirstSegmentSplitter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SplitFirstSegmentSplitter.o `test -f 'SplitFirstSegmentSplitter.cc' || echo '$(srcdir)/'`SplitFirstSegmentSplitter.cc
+
+libaria2c_a-SplitFirstSegmentSplitter.obj: SplitFirstSegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SplitFirstSegmentSplitter.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo" -c -o libaria2c_a-SplitFirstSegmentSplitter.obj `if test -f 'SplitFirstSegmentSplitter.cc'; then $(CYGPATH_W) 'SplitFirstSegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SplitFirstSegmentSplitter.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SplitFirstSegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SplitFirstSegmentSplitter.cc' object='libaria2c_a-SplitFirstSegmentSplitter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SplitFirstSegmentSplitter.obj `if test -f 'SplitFirstSegmentSplitter.cc'; then $(CYGPATH_W) 'SplitFirstSegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SplitFirstSegmentSplitter.cc'; fi`
+
+libaria2c_a-SplitSlowestSegmentSplitter.o: SplitSlowestSegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SplitSlowestSegmentSplitter.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo" -c -o libaria2c_a-SplitSlowestSegmentSplitter.o `test -f 'SplitSlowestSegmentSplitter.cc' || echo '$(srcdir)/'`SplitSlowestSegmentSplitter.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SplitSlowestSegmentSplitter.cc' object='libaria2c_a-SplitSlowestSegmentSplitter.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SplitSlowestSegmentSplitter.o `test -f 'SplitSlowestSegmentSplitter.cc' || echo '$(srcdir)/'`SplitSlowestSegmentSplitter.cc
+
+libaria2c_a-SplitSlowestSegmentSplitter.obj: SplitSlowestSegmentSplitter.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-SplitSlowestSegmentSplitter.obj -MD -MP -MF "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo" -c -o libaria2c_a-SplitSlowestSegmentSplitter.obj `if test -f 'SplitSlowestSegmentSplitter.cc'; then $(CYGPATH_W) 'SplitSlowestSegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SplitSlowestSegmentSplitter.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo" "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Po"; else rm -f "$(DEPDIR)/libaria2c_a-SplitSlowestSegmentSplitter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='SplitSlowestSegmentSplitter.cc' object='libaria2c_a-SplitSlowestSegmentSplitter.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -c -o libaria2c_a-SplitSlowestSegmentSplitter.obj `if test -f 'SplitSlowestSegmentSplitter.cc'; then $(CYGPATH_W) 'SplitSlowestSegmentSplitter.cc'; else $(CYGPATH_W) '$(srcdir)/SplitSlowestSegmentSplitter.cc'; fi`
+
libaria2c_a-Util.o: Util.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libaria2c_a_CXXFLAGS) $(CXXFLAGS) -MT libaria2c_a-Util.o -MD -MP -MF "$(DEPDIR)/libaria2c_a-Util.Tpo" -c -o libaria2c_a-Util.o `test -f 'Util.cc' || echo '$(srcdir)/'`Util.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libaria2c_a-Util.Tpo" "$(DEPDIR)/libaria2c_a-Util.Po"; else rm -f "$(DEPDIR)/libaria2c_a-Util.Tpo"; exit 1; fi
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<string, string>::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 b87cab1d..9d183cd4 100644
--- a/src/Request.cc
+++ b/src/Request.cc
@@ -22,14 +22,13 @@
#include "Request.h"
#include "Util.h"
-#define MAX_RETRY_COUNT 5
-
-Request::Request():port(0), retryCount(0) {
+Request::Request():port(0), tryCount(0) {
defaultPorts["http"] = 80;
#ifdef HAVE_LIBSSL
// for SSL
defaultPorts["https"] = 443;
#endif // HAVE_LIBSSL
+ defaultPorts["ftp"] = 21;
seg.sp = 0;
seg.ep = 0;
seg.ds = 0;
@@ -80,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("/");
@@ -102,15 +99,3 @@ bool Request::parseUrl(string url) {
}
return true;
}
-
-void Request::resetRetryCount() {
- this->retryCount = 0;
-}
-
-void Request::addRetryCount() {
- retryCount++;
-}
-
-bool Request::noMoreRetry() {
- return retryCount >= MAX_RETRY_COUNT;
-}
diff --git a/src/Request.h b/src/Request.h
index 0d9554e6..8d8676ef 100644
--- a/src/Request.h
+++ b/src/Request.h
@@ -55,7 +55,7 @@ private:
string dir;
string file;
map<string, int> defaultPorts;
- int retryCount;
+ int tryCount;
bool parseUrl(string url);
public:
Segment seg;
@@ -72,15 +72,14 @@ public:
// Returns true if parsing goes successful, otherwise returns false.
bool redirectUrl(string url);
bool resetUrl();
- void resetRetryCount();
- void addRetryCount();
- int getRetryCount();
- bool noMoreRetry();
+ void resetTryCount() { tryCount = 0; }
+ void addTryCount() { tryCount++; }
+ int getTryCount() const { return tryCount; }
+ //bool noMoreTry() const { return tryCount >= PREF_MAX_TRY; }
string getUrl() const { return url; }
string getCurrentUrl() const { return currentUrl; }
string getPreviousUrl() const { return previousUrl; }
- void setPreviousUrl(string url) { previousUrl = url; }
string getReferer() const { return referer; }
void setReferer(string url) { referer = previousUrl = url; }
string getProtocol() const { return protocol; }
diff --git a/src/Segment.h b/src/Segment.h
index c6c2b36c..035282ae 100644
--- a/src/Segment.h
+++ b/src/Segment.h
@@ -22,6 +22,10 @@
#ifndef _D_SEGMENT_H_
#define _D_SEGMENT_H_
+#include <vector>
+
+using namespace std;
+
/**
* Segment represents a download segment.
* sp, ep is a offset from a begining of a file.
@@ -36,9 +40,12 @@ typedef struct {
long long int sp;
long long int ep;
long long int ds;
+ int speed;
bool finish;
} Segment;
+typedef vector<Segment> Segments;
+
#define SEGMENT_EQUAL(X, Y) (X.cuid == Y.cuid && X.sp == Y.sp && X.ep == Y.ep && X.ds == Y.ds && X.finish == Y.finish ? true : false)
#endif // _D_SEGMENT_H_
diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc
index 8dca0ba0..8046bf7b 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(".") {}
@@ -51,6 +52,7 @@ bool SegmentMan::getSegment(Segment& seg, int cuid) {
seg.sp = 0;
seg.ep = totalSize == 0 ? 0 : totalSize-1;
seg.ds = 0;
+ seg.speed = 0;
seg.finish = false;
segments.push_back(seg);
return true;
@@ -80,35 +82,7 @@ bool SegmentMan::getSegment(Segment& seg, int cuid) {
return true;
}
}
- for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
- Segment& s = *itr;
- if(s.finish) {
- continue;
- }
- if(s.ep-(s.sp+s.ds) > 524288) {
- 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;
- seg.sp = nep+1;
- seg.ep = s.ep;
- seg.ds = 0;
- seg.finish = false;
- s.ep = nep;
- logger->debug("return new segment { "
- "sp = "+Util::llitos(seg.sp)+", "+
- "ep = "+Util::llitos(seg.ep)+", "
- "ds = "+Util::llitos(seg.ds)+" } to "+
- "cuid "+Util::llitos(cuid));
- logger->debug("update segment { "
- "sp = "+Util::llitos(s.sp)+", "+
- "ep = "+Util::llitos(s.ep)+", "
- "ds = "+Util::llitos(s.ds)+" } of "+
- "cuid "+Util::llitos(s.cuid));
- segments.push_back(seg);
- return true;
- }
- }
- return false;
+ return splitter->splitSegment(seg, cuid, segments);
}
void SegmentMan::updateSegment(const Segment& segment) {
@@ -123,7 +97,7 @@ void SegmentMan::updateSegment(const Segment& segment) {
}
-bool SegmentMan::segmentFileExists() {
+bool SegmentMan::segmentFileExists() const {
if(!isSplittable) {
return false;
}
@@ -154,14 +128,17 @@ void SegmentMan::load() {
}
}
-void SegmentMan::save() {
- if(!isSplittable) {
+void SegmentMan::save() const {
+ if(!isSplittable || totalSize == 0) {
return;
}
string segFilename = getSegmentFilePath();
logger->info(MSG_SAVING_SEGMENT_FILE, segFilename.c_str());
FILE* segFile = openSegFile(segFilename, "w");
- for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
+ if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
if(fwrite(&*itr, sizeof(Segment), 1, segFile) < 1) {
throw new DlAbortEx(strerror(errno));
}
@@ -170,7 +147,7 @@ void SegmentMan::save() {
logger->info(MSG_SAVED_SEGMENT_FILE);
}
-FILE* SegmentMan::openSegFile(string segFilename, string mode) {
+FILE* SegmentMan::openSegFile(string segFilename, string mode) const {
FILE* segFile = fopen(segFilename.c_str(), mode.c_str());
if(segFile == NULL) {
throw new DlAbortEx(strerror(errno));
@@ -180,6 +157,9 @@ FILE* SegmentMan::openSegFile(string segFilename, string mode) {
void SegmentMan::read(FILE* file) {
assert(file != NULL);
+ if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
+ throw new DlAbortEx(strerror(errno));
+ }
while(1) {
Segment seg;
if(fread(&seg, sizeof(Segment), 1, file) < 1) {
@@ -193,7 +173,7 @@ void SegmentMan::read(FILE* file) {
}
}
-void SegmentMan::remove() {
+void SegmentMan::remove() const {
if(!isSplittable) {
return;
}
@@ -203,11 +183,11 @@ void SegmentMan::remove() {
}
}
-bool SegmentMan::finished() {
+bool SegmentMan::finished() const {
if(!downloadStarted || segments.size() == 0) {
return false;
}
- for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
+ for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
if(!(*itr).finish) {
return false;
}
@@ -215,15 +195,15 @@ bool SegmentMan::finished() {
return true;
}
-void SegmentMan::removeIfFinished() {
+void SegmentMan::removeIfFinished() const {
if(finished()) {
remove();
}
}
-long long int SegmentMan::getDownloadedSize() {
+long long int SegmentMan::getDownloadedSize() const {
long long int size = 0;
- for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
+ for(vector<Segment>::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
size += (*itr).ds;
}
return size;
diff --git a/src/SegmentMan.h b/src/SegmentMan.h
index 1ef744e3..970a4fd0 100644
--- a/src/SegmentMan.h
+++ b/src/SegmentMan.h
@@ -26,6 +26,8 @@
#include "common.h"
#include "Logger.h"
#include "Segment.h"
+#include "Option.h"
+#include "SegmentSplitter.h"
using namespace std;
@@ -37,7 +39,7 @@ using namespace std;
class SegmentMan {
private:
void read(FILE* file);
- FILE* openSegFile(string segFilename, string mode);
+ FILE* openSegFile(string segFilename, string mode) const;
public:
/**
* The total number of bytes to download.
@@ -63,7 +65,7 @@ public:
/**
* Holds segments.
*/
- vector<Segment> segments;
+ Segments segments;
/**
* Respresents the file name of the downloaded file.
* If the URL does not contain file name part(http://www.rednoah.com/, for
@@ -80,7 +82,9 @@ public:
*/
string ufilename;
- Logger* logger;
+ const Logger* logger;
+ const Option* option;
+ SegmentSplitter* splitter;
SegmentMan();
~SegmentMan();
@@ -89,13 +93,13 @@ public:
* Returns dir+"/"+filename.
* If filename is empty, then returns dir+"/"+"inex.html";
*/
- string getFilePath() {
+ string getFilePath() const {
return (dir == "" ? "." : dir)+"/"+
(ufilename == "" ?
(filename == "" ? "index.html" : filename) : ufilename);
}
- string getSegmentFilePath() {
+ string getSegmentFilePath() const {
return getFilePath()+SEGMENT_FILE_EXTENSION;
}
@@ -129,7 +133,7 @@ public:
* The file name of the segment data is filename appended by ".aria2".
* If isSplittable is false, then returns simply false without any operation.
*/
- bool segmentFileExists();
+ bool segmentFileExists() const;
/**
* Loads the segment data file.
* If isSplittable is false, then returns without any operation.
@@ -139,26 +143,26 @@ public:
* Saves the segment data file.
* If isSplittable is false, then returns without any operation.
*/
- void save();
+ void save() const;
/**
* Removes the segment data file.
* If isSplittable is false, then returns without any operation.
*/
- void remove();
+ void remove() const;
/**
* Returs true when the download has finished.
* If downloadStarted is false or the number of the segments of this object
* holds is 0, then returns false.
*/
- bool finished();
+ bool finished() const;
/**
* if finished() is true, then call remove()
*/
- void removeIfFinished();
+ void removeIfFinished() const;
/**
* Returns the total number of bytes to be downloaded.
*/
- long long int getDownloadedSize();
+ long long int getDownloadedSize() const;
};
#endif // _D_SEGMENT_MAN_H_
diff --git a/src/SegmentSplitter.cc b/src/SegmentSplitter.cc
new file mode 100644
index 00000000..ef144d1f
--- /dev/null
+++ b/src/SegmentSplitter.cc
@@ -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 --> */
+#include "SegmentSplitter.h"
+#include "Util.h"
+
+void SegmentSplitter::split(Segment& seg, int cuid, Segment& s) const {
+ long long int nep = (s.ep-(s.sp+s.ds))/2+(s.sp+s.ds);
+ seg.cuid = cuid;
+ seg.sp = nep+1;
+ seg.ep = s.ep;
+ seg.ds = 0;
+ seg.speed = s.speed;
+ seg.finish = false;
+ s.ep = nep;
+ logger->debug("return new segment { "
+ "sp = "+Util::llitos(seg.sp)+", "+
+ "ep = "+Util::llitos(seg.ep)+", "+
+ "ds = "+Util::llitos(seg.ds)+", "+
+ "speed = "+Util::itos(seg.speed)+" } to "+
+ "cuid "+Util::llitos(cuid));
+ logger->debug("update segment { "
+ "sp = "+Util::llitos(s.sp)+", "+
+ "ep = "+Util::llitos(s.ep)+", "+
+ "ds = "+Util::llitos(s.ds)+", "+
+ "speed = "+Util::itos(s.speed)+" } of "+
+ "cuid "+Util::llitos(s.cuid));
+}
diff --git a/src/SegmentSplitter.h b/src/SegmentSplitter.h
new file mode 100644
index 00000000..887250ae
--- /dev/null
+++ b/src/SegmentSplitter.h
@@ -0,0 +1,42 @@
+/* <!-- 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_SEGMENT_SPLITTER_H_
+#define _D_SEGMENT_SPLITTER_H_
+
+#include "Segment.h"
+#include "Logger.h"
+
+class SegmentSplitter {
+protected:
+ long long int minSegmentSize;
+
+ void split(Segment& seg, int cuid, Segment& s) const;
+public:
+ const Logger* logger;
+
+ virtual ~SegmentSplitter() {}
+ virtual bool splitSegment(Segment& newSegment, int cuid, Segments& segments) = 0;
+ void setMinSegmentSize(long long int size) { minSegmentSize = size; }
+ long long int getMinSegmentSize() const { return minSegmentSize; }
+};
+
+#endif // _D_SEGMENT_SPLITTER_H_
diff --git a/src/SimpleLogger.cc b/src/SimpleLogger.cc
index 9c2b28fe..efb95374 100644
--- a/src/SimpleLogger.cc
+++ b/src/SimpleLogger.cc
@@ -20,6 +20,8 @@
*/
/* copyright --> */
#include "SimpleLogger.h"
+#include "Util.h"
+#include <time.h>
#include <stdarg.h>
SimpleLogger::SimpleLogger(string filename) {
@@ -36,7 +38,8 @@ SimpleLogger::~SimpleLogger() {
}
}
-void SimpleLogger::writeLog(int level, string msg, va_list ap, Exception* e) {
+void SimpleLogger::writeLog(int level, string msg, va_list ap, Exception* e) const
+{
string levelStr;
switch(level) {
case DEBUG:
@@ -49,21 +52,25 @@ void SimpleLogger::writeLog(int level, string msg, va_list ap, Exception* e) {
default:
levelStr = "INFO";
}
- vfprintf(file, string(levelStr+" - "+msg+"\n").c_str(), ap);
+ time_t now = time(NULL);
+ char datestr[26];
+ ctime_r(&now, datestr);
+ datestr[strlen(datestr)-1] = '\0';
+ vfprintf(file, string(string(datestr)+" - "+levelStr+" - "+Util::replace(msg, "\r", "")+"\n").c_str(), ap);
if(e != NULL) {
- fprintf(file, string(levelStr+" - exception: "+e->getMsg()+"\n").c_str());
+ fprintf(file, string(string(datestr)+" - "+levelStr+" - exception: "+Util::replace(e->getMsg(), "\r", "")+"\n").c_str());
}
fflush(stdout);
}
-void SimpleLogger::debug(string msg, ...) {
+void SimpleLogger::debug(string msg, ...) const {
va_list ap;
va_start(ap, msg);
writeLog(DEBUG, msg, ap);
va_end(ap);
}
-void SimpleLogger::debug(string msg, Exception* e, ...) {
+void SimpleLogger::debug(string msg, Exception* e, ...) const {
va_list ap;
va_start(ap, e);
writeLog(DEBUG, msg, ap, e);
@@ -71,14 +78,14 @@ void SimpleLogger::debug(string msg, Exception* e, ...) {
}
-void SimpleLogger::info(string msg, ...) {
+void SimpleLogger::info(string msg, ...) const {
va_list ap;
va_start(ap, msg);
writeLog(INFO, msg, ap);
va_end(ap);
}
-void SimpleLogger::info(string msg, Exception* e, ...) {
+void SimpleLogger::info(string msg, Exception* e, ...) const {
va_list ap;
va_start(ap, e);
writeLog(INFO, msg, ap, e);
@@ -86,14 +93,14 @@ void SimpleLogger::info(string msg, Exception* e, ...) {
}
-void SimpleLogger::error(string msg, ...) {
+void SimpleLogger::error(string msg, ...) const {
va_list ap;
va_start(ap, msg);
writeLog(ERROR, msg, ap);
va_end(ap);
}
-void SimpleLogger::error(string msg, Exception* e, ...) {
+void SimpleLogger::error(string msg, Exception* e, ...) const {
va_list ap;
va_start(ap, e);
writeLog(ERROR, msg, ap, e);
diff --git a/src/SimpleLogger.h b/src/SimpleLogger.h
index 4b3843a2..5caab527 100644
--- a/src/SimpleLogger.h
+++ b/src/SimpleLogger.h
@@ -30,19 +30,19 @@ private:
DEBUG,
INFO,
ERROR};
- void writeLog(int level, string msg, va_list ap, Exception* e = NULL);
+ void writeLog(int level, string msg, va_list ap, Exception* e = NULL) const;
FILE* file;
public:
SimpleLogger(string filename);
SimpleLogger(FILE* logfile);
~SimpleLogger();
- void debug(string msg, ...);
- void debug(string msg, Exception* ex, ...);
- void info(string msg, ...);
- void info(string msg, Exception* ex, ...);
- void error(string msg, ...);
- void error(string msg, Exception* ex, ...);
+ void debug(string msg, ...) const;
+ void debug(string msg, Exception* ex, ...) const;
+ void info(string msg, ...) const;
+ void info(string msg, Exception* ex, ...) const;
+ void error(string msg, ...) const;
+ void error(string msg, Exception* ex, ...) const;
};
#endif // _D_SIMPLE_LOGGER_H_
diff --git a/src/Socket.cc b/src/Socket.cc
index bf9a04f1..f4e0862d 100644
--- a/src/Socket.cc
+++ b/src/Socket.cc
@@ -30,6 +30,10 @@ Socket::Socket(const Socket& s) {
core->use++;
}
+Socket::Socket(SocketCore* core) {
+ this->core = core;
+}
+
Socket::~Socket() {
core->use--;
if(core->use == 0) {
@@ -49,38 +53,54 @@ Socket& Socket::operator=(const Socket& s) {
return *this;
}
-void Socket::establishConnection(string host, int port) {
+void Socket::beginListen() const {
+ core->beginListen();
+}
+
+void Socket::getAddrInfo(pair<string, int>& addrinfo) const {
+ core->getAddrInfo(addrinfo);
+}
+
+Socket* Socket::acceptConnection() const {
+ return new Socket(core->acceptConnection());
+}
+
+void Socket::establishConnection(string host, int port) const {
core->establishConnection(host, port);
}
-void Socket::setNonBlockingMode() {
- core->setNonBlockingMode();
+void Socket::setBlockingMode() const {
+ core->setBlockingMode();
}
-void Socket::closeConnection() {
+void Socket::closeConnection() const {
core->closeConnection();
}
-bool Socket::isWritable(int timeout) {
+bool Socket::isWritable(int timeout) const {
return core->isWritable(timeout);
}
-bool Socket::isReadable(int timeout) {
+bool Socket::isReadable(int timeout) const {
return core->isReadable(timeout);
}
-void Socket::writeData(const char* data, int len, int timeout) {
+void Socket::writeData(const char* data, int len, int timeout) const {
core->writeData(data, len, timeout);
}
-void Socket::readData(char* data, int& len, int timeout) {
+void Socket::writeData(string str, int timeout) const {
+ core->writeData(str.c_str(), str.size(), timeout);
+}
+
+void Socket::readData(char* data, int& len, int timeout) const {
core->readData(data, len, timeout);
}
-void Socket::peekData(char* data, int& len, int timeout) {
+void Socket::peekData(char* data, int& len, int timeout) const {
core->peekData(data, len, timeout);
}
-void Socket::initiateSecureConnection() {
+void Socket::initiateSecureConnection() const {
core->initiateSecureConnection();
}
diff --git a/src/Socket.h b/src/Socket.h
index a4624801..ea895dc5 100644
--- a/src/Socket.h
+++ b/src/Socket.h
@@ -32,6 +32,7 @@ class Socket {
private:
// socket endpoint descriptor
SocketCore* core;
+ Socket(SocketCore* core);
public:
Socket();
Socket(const Socket& s);
@@ -41,46 +42,51 @@ public:
int getSockfd() const { return core->sockfd; }
+ void beginListen() const;
+ void getAddrInfo(pair<string, int>& addrinfo) const;
+ Socket* acceptConnection() const;
+
/**
* Connects to the server named host and the destination port is port.
* This method make socket non-blocking mode.
- * To make the socket blocking mode, call setNonBlockingMode() after
+ * To make the socket blocking mode, call setBlockingMode() after
* the connection is established.
*/
- void establishConnection(string host, int port);
+ void establishConnection(string host, int port) const;
- void setNonBlockingMode();
+ void setBlockingMode() const;
// Closes the connection which this socket object has
- void closeConnection();
+ void closeConnection() const;
// examines whether the socket of this Socket object is available for writing.
// returns true if the socket is available for writing, otherwise returns false.
- bool isWritable(int timeout);
+ bool isWritable(int timeout) const;
// examines whether the socket of this Socket object is available for reading.
// returns true if the socket is available for reading, otherwise returns false.
- bool isReadable(int timeout);
+ bool isReadable(int timeout) const;
// writes characters into the socket. data is a pointer pointing the first
// byte of the data and len is the length of the data.
- void writeData(const char* data, int len, int timeout = 5);
+ void writeData(const char* data, int len, int timeout = 5) const;
+ void writeData(string str, int timeout = 5) const;
// Reads up to len bytes from this socket.
// data is a pointer pointing the first
// byte of the data, which must be allocated before this method is called.
// len is the size of the allocated memory. When this method returns
// successfully, len is replaced by the size of the read data.
- void readData(char* data, int& len, int timeout = 5);
+ void readData(char* data, int& len, int timeout = 5) const;
// Reads up to len bytes from this socket, but bytes are not removed from
// this socket.
- void peekData(char* data, int& len, int timeout = 5);
+ void peekData(char* data, int& len, int timeout = 5) const;
/**
* Makes this socket secure.
* If the system has not OpenSSL, then this method do nothing.
*/
- void initiateSecureConnection();
+ void initiateSecureConnection() const;
};
#endif // _D_SOCKET_H_
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 94b986ed..53051679 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -34,29 +34,92 @@
#include <errno.h>
#include "message.h"
-SocketCore::SocketCore():sockfd(-1), use(1), secure(false)
+SocketCore::SocketCore():sockfd(-1) {
+ init();
+}
+
+SocketCore::SocketCore(int sockfd):sockfd(sockfd) {
+ init();
+}
+
+void SocketCore::init() {
+ use = 1;
+ secure = false;
#ifdef HAVE_LIBSSL
// for SSL
- , sslCtx(NULL), ssl(NULL)
+ sslCtx = NULL;
+ ssl = NULL;
#endif // HAVE_LIBSSL
-{}
+}
SocketCore::~SocketCore() {
closeConnection();
}
+void SocketCore::beginListen() {
+ closeConnection();
+ //sockfd = socket(AF_UNSPEC, SOCK_STREAM, PF_UNSPEC);
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if(sockfd == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ socklen_t sockopt = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
+ close(sockfd);
+ sockfd = -1;
+ throw new DlAbortEx(strerror(errno));
+ }
+
+ struct sockaddr_in sockaddr;
+ memset((char*)&sockaddr, 0, sizeof(sockaddr));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+ sockaddr.sin_port = htons(0);
+
+ if(bind(sockfd, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+
+ if(listen(sockfd, 1) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+}
+
+SocketCore* SocketCore::acceptConnection() const {
+ struct sockaddr_in sockaddr;
+ socklen_t len = sizeof(sockaddr);
+ memset((char*)&sockaddr, 0, sizeof(sockaddr));
+ int fd;
+ if((fd = accept(sockfd, (struct sockaddr*)&sockaddr, &len)) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ SocketCore* s = new SocketCore(fd);
+ return s;
+}
+
+void SocketCore::getAddrInfo(pair<string, int>& addrinfo) const {
+ struct sockaddr_in listenaddr;
+ memset((char*)&listenaddr, 0, sizeof(listenaddr));
+ socklen_t len = sizeof(listenaddr);
+ if(getsockname(sockfd, (struct sockaddr*)&listenaddr, &len) == -1) {
+ throw new DlAbortEx(strerror(errno));
+ }
+ addrinfo.first = inet_ntoa(listenaddr.sin_addr);
+ addrinfo.second = ntohs(listenaddr.sin_port);
+}
+
void SocketCore::establishConnection(string host, int port) {
+ closeConnection();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if(sockfd >= 0) {
- socklen_t sockopt = 1;
- if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0) {
- close(sockfd);
- sockfd = -1;
- throw new DlAbortEx(strerror(errno));
- }
- } else {
+ if(sockfd == -1) {
throw new DlAbortEx(strerror(errno));
}
+ socklen_t sockopt = 1;
+ if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(socklen_t)) < 0) {
+ close(sockfd);
+ sockfd = -1;
+ throw new DlAbortEx(strerror(errno));
+ }
struct sockaddr_in sockaddr;
memset((char*)&sockaddr, 0, sizeof(sockaddr));
@@ -87,7 +150,7 @@ void SocketCore::establishConnection(string host, int port) {
}
}
-void SocketCore::setNonBlockingMode() {
+void SocketCore::setBlockingMode() const {
int flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags&~O_NONBLOCK);
}
@@ -95,7 +158,7 @@ void SocketCore::setNonBlockingMode() {
void SocketCore::closeConnection() {
#ifdef HAVE_LIBSSL
// for SSL
- if(secure) {
+ if(secure && ssl != NULL) {
SSL_shutdown(ssl);
}
#endif // HAVE_LIBSSL
@@ -105,7 +168,7 @@ void SocketCore::closeConnection() {
}
#ifdef HAVE_LIBSSL
// for SSL
- if(secure) {
+ if(secure && ssl != NULL) {
SSL_free(ssl);
SSL_CTX_free(sslCtx);
ssl = NULL;
@@ -114,7 +177,7 @@ void SocketCore::closeConnection() {
#endif // HAVE_LIBSSL
}
-bool SocketCore::isWritable(int timeout) {
+bool SocketCore::isWritable(int timeout) const {
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
@@ -130,11 +193,15 @@ bool SocketCore::isWritable(int timeout) {
// time out
return false;
} else {
- throw new DlRetryEx(strerror(errno));
+ if(errno == EINPROGRESS) {
+ return false;
+ } else {
+ throw new DlRetryEx(strerror(errno));
+ }
}
}
-bool SocketCore::isReadable(int timeout) {
+bool SocketCore::isReadable(int timeout) const {
fd_set fds;
FD_ZERO(&fds);
FD_SET(sockfd, &fds);
@@ -150,11 +217,15 @@ bool SocketCore::isReadable(int timeout) {
// time out
return false;
} else {
- throw new DlRetryEx(strerror(errno));
+ if(errno == EINPROGRESS) {
+ return false;
+ } else {
+ throw new DlRetryEx(strerror(errno));
+ }
}
}
-void SocketCore::writeData(const char* data, int len, int timeout) {
+void SocketCore::writeData(const char* data, int len, int timeout) const {
if(!isWritable(timeout) ||
!secure && send(sockfd, data, (size_t)len, 0) != len
#ifdef HAVE_LIBSSL
@@ -167,7 +238,7 @@ void SocketCore::writeData(const char* data, int len, int timeout) {
}
}
-void SocketCore::readData(char* data, int& len, int timeout) {
+void SocketCore::readData(char* data, int& len, int timeout) const {
if(!isReadable(timeout) ||
!secure && (len = recv(sockfd, data, (size_t)len, 0)) < 0
#ifdef HAVE_LIBSSL
@@ -180,7 +251,7 @@ void SocketCore::readData(char* data, int& len, int timeout) {
}
}
-void SocketCore::peekData(char* data, int& len, int timeout) {
+void SocketCore::peekData(char* data, int& len, int timeout) const {
if(!isReadable(timeout) ||
!secure && (len = recv(sockfd, data, (size_t)len, MSG_PEEK)) < 0
#ifdef HAVE_LIBSSL
diff --git a/src/SocketCore.h b/src/SocketCore.h
index ba5fb7af..a6b7d3f8 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -23,6 +23,7 @@
#define _D_SOCKET_CORE_H_
#include <string>
+#include <utility>
#include "common.h"
#ifdef HAVE_LIBSSL
@@ -45,50 +46,55 @@ private:
SSL_CTX* sslCtx;
SSL* ssl;
#endif // HAVE_LIBSSL
+ void init();
+ SocketCore(int sockfd);
public:
SocketCore();
~SocketCore();
+ void beginListen();
+ void getAddrInfo(pair<string, int>& addrinfo) const;
+ SocketCore* acceptConnection() const;
/**
* Connects to the server named host and the destination port is port.
* This method make socket non-blocking mode.
- * To make the socket blocking mode, call setNonBlockingMode() after
+ * To make the socket blocking mode, call setBlockingMode() after
* the connection is established.
*/
void establishConnection(string host, int port);
- void setNonBlockingMode();
+ void setBlockingMode() const;
// Closes the connection which this socket object has
void closeConnection();
// examines whether the socket of this SocketCore object is available for writing.
// returns true if the socket is available for writing, otherwise returns false.
- bool isWritable(int timeout);
+ bool isWritable(int timeout) const;
// examines whether the socket of this SocketCore object is available for reading.
// returns true if the socket is available for reading, otherwise returns false.
- bool isReadable(int timeout);
+ bool isReadable(int timeout) const;
// writes characters into the socket. data is a pointer pointing the first
// byte of the data and len is the length of the data.
- void writeData(const char* data, int len, int timeout = 5);
+ void writeData(const char* data, int len, int timeout = 5) const;
// Reads up to len bytes from this socket.
// data is a pointer pointing the first
// byte of the data, which must be allocated before this method is called.
// len is the size of the allocated memory. When this method returns
// successfully, len is replaced by the size of the read data.
- void readData(char* data, int& len, int timeout = 5);
+ void readData(char* data, int& len, int timeout = 5) const;
// Reads up to len bytes from this socket, but bytes are not removed from
// this socket.
- void peekData(char* data, int& len, int timeout = 5);
+ void peekData(char* data, int& len, int timeout = 5) const;
/**
* Makes this socket secure.
* If the system has not OpenSSL, then this method do nothing.
*/
- void initiateSecureConnection();
+ void initiateSecureConnection() ;
};
#endif // _D_SOCKET_CORE_H_
diff --git a/src/SplitFirstSegmentSplitter.cc b/src/SplitFirstSegmentSplitter.cc
new file mode 100644
index 00000000..72a3f2d1
--- /dev/null
+++ b/src/SplitFirstSegmentSplitter.cc
@@ -0,0 +1,37 @@
+/* <!-- 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 "SplitFirstSegmentSplitter.h"
+
+bool SplitFirstSegmentSplitter::splitSegment(Segment& seg, int cuid, Segments& segments) {
+ for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
+ Segment& s = *itr;
+ if(s.finish) {
+ continue;
+ }
+ if(s.ep-(s.sp+s.ds) > minSegmentSize) {
+ split(seg, cuid, s);
+ segments.push_back(seg);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/SplitFirstSegmentSplitter.h b/src/SplitFirstSegmentSplitter.h
new file mode 100644
index 00000000..73f76abd
--- /dev/null
+++ b/src/SplitFirstSegmentSplitter.h
@@ -0,0 +1,34 @@
+/* <!-- 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_SPLIT_FIRST_SEGMENT_SPLITTER_H_
+#define _D_SPLIT_FIRST_SEGMENT_SPLITTER_H_
+
+#include "SegmentSplitter.h"
+
+class SplitFirstSegmentSplitter : public SegmentSplitter {
+public:
+ SplitFirstSegmentSplitter() {}
+ ~SplitFirstSegmentSplitter() {}
+ bool splitSegment(Segment& newSegment, int cuid, Segments& segments);
+};
+
+#endif // _D_SPLIT_FIRST_SEGMENT_SPLITTER_H_
diff --git a/src/SplitSlowestSegmentSplitter.cc b/src/SplitSlowestSegmentSplitter.cc
new file mode 100644
index 00000000..47c571bf
--- /dev/null
+++ b/src/SplitSlowestSegmentSplitter.cc
@@ -0,0 +1,50 @@
+/* <!-- 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 "SplitSlowestSegmentSplitter.h"
+
+bool SplitSlowestSegmentSplitter::splitSegment(Segment& seg, int cuid, Segments& segments) {
+ vector<Segment>::iterator slowest = segments.end();;
+ for(vector<Segment>::iterator itr = segments.begin(); itr != segments.end(); itr++) {
+ Segment& s = *itr;
+ if(s.finish) {
+ continue;
+ }
+ if(s.ep-(s.sp+s.ds) <= minSegmentSize) {
+ continue;
+ }
+ if(slowest == segments.end()) {
+ slowest = itr;
+ } else {
+ Segment sl = *slowest;
+ if((sl.ep-(sl.sp+sl.ds))/(sl.speed+1) < (s.ep-(s.sp+s.ds))/(s.speed+1)) {
+ slowest = itr;
+ }
+ }
+ }
+ if(slowest == segments.end()) {
+ return false;
+ } else {
+ split(seg, cuid, *slowest);
+ segments.push_back(seg);
+ return true;
+ }
+}
diff --git a/src/SplitSlowestSegmentSplitter.h b/src/SplitSlowestSegmentSplitter.h
new file mode 100644
index 00000000..90ff3753
--- /dev/null
+++ b/src/SplitSlowestSegmentSplitter.h
@@ -0,0 +1,35 @@
+/* <!-- 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_SPLIT_SLOWEST_SEGMENT_SPLITTER_H_
+#define _D_SPLIT_SLOWEST_SEGMENT_SPLITTER_H_
+
+#include "SegmentSplitter.h"
+
+class SplitSlowestSegmentSplitter : public SegmentSplitter {
+public:
+ SplitSlowestSegmentSplitter() {}
+ ~SplitSlowestSegmentSplitter() {}
+
+ bool splitSegment(Segment& segment, int cuid, Segments& segments);
+};
+
+#endif // _D_SPLIT_SLOWEST_SEGMENT_SPLITTER_H_
diff --git a/src/Util.cc b/src/Util.cc
index 13258e41..72e487e4 100644
--- a/src/Util.cc
+++ b/src/Util.cc
@@ -108,3 +108,32 @@ void Util::slice(vector<string>& result, string src, char delim) {
result.push_back(trim(term));
}
}
+
+bool Util::endsWith(string target, string part) {
+ if(target.size() < part.size()) {
+ return false;
+ }
+ if(target.compare(target.size()-part.size(), part.size(), part, 0, part.size()) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+string Util::replace(string target, string oldstr, string newstr) {
+ if(target == "" || oldstr == "" ) {
+ return target;
+ }
+ string result;
+ string::size_type p = 0;
+ string::size_type np = target.find(oldstr);
+ while(np != string::npos) {
+ result += target.substr(p, np-p)+newstr;
+ p = np+oldstr.size();
+ np = target.find(oldstr, p);
+ }
+ result += target.substr(p);
+
+ return result;
+}
+
diff --git a/src/Util.h b/src/Util.h
index 02f73657..98bb116e 100644
--- a/src/Util.h
+++ b/src/Util.h
@@ -37,7 +37,7 @@ public:
static string llitos(long long int value, bool comma = false);
static string itos(int value, bool comma = false);
/**
- * Computes difference in milli second between tv1 and tv2,
+ * Computes difference in micro-seconds between tv1 and tv2,
* assuming tv1 is newer than tv2.
* If tv1 is older than tv2, then this method returns 0.
*/
@@ -49,6 +49,10 @@ public:
static void slice(vector<string>& result, string src, char delim);
static string trim(string src);
+
+ static bool endsWith(string target, string part);
+
+ static string replace(string target, string oldstr, string newstr);
};
#endif // _D_UTIL_H_
diff --git a/src/main.cc b/src/main.cc
index 718ddd76..b01853b9 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -22,11 +22,13 @@
#include "HttpInitiateConnectionCommand.h"
#include "DownloadEngine.h"
#include "SegmentMan.h"
+#include "SplitSlowestSegmentSplitter.h"
#include "SimpleLogger.h"
#include "common.h"
#include "DefaultDiskWriter.h"
#include "Util.h"
#include "InitiateConnectionCommandFactory.h"
+#include "prefs.h"
#include <vector>
#include <algorithm>
#include <signal.h>
@@ -96,41 +98,68 @@ 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;
- 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 << " --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 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 << " -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 N connections. N must be" << 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;
+ 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-proxy-method=METHOD Set the method to use in proxy request." << endl;
+ cout << " METHOD is either 'get' or 'tunnel'." << endl;
+ cout << " Default: tunnel" << 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=METHOD Use HTTP proxy in FTP. METHOD is either 'get' or" << endl;
+ cout << " 'tunnel'." << endl;
+ cout << " Default: 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 <tujikawa at rednoah dot com>" << endl;
}
@@ -139,13 +168,21 @@ int main(int argc, char* argv[]) {
string logfile;
string dir;
string ufilename;
- int split = 0;
+ int split = 1;
bool daemonMode = false;
string referer;
int c;
Option* op = new Option();
- op->put("retry_wait", "5");
+ 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_HTTP_PROXY_METHOD, V_TUNNEL);
+ op->put(PREF_FTP_USER, "anonymous");
+ op->put(PREF_FTP_PASSWD, "ARIA2USER@");
+ op->put(PREF_FTP_TYPE, V_BINARY);
+ op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL);
while(1) {
int optIndex = 0;
@@ -156,6 +193,8 @@ 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' },
+ { "max-retries", required_argument, NULL, 'm' },
{ "http-proxy", required_argument, &lopt, 1 },
{ "http-user", required_argument, &lopt, 2 },
{ "http-passwd", required_argument, &lopt, 3 },
@@ -164,11 +203,18 @@ 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 },
+ { "min-segment-size", required_argument, &lopt, 13 },
+ { "http-proxy-method", required_argument, &lopt, 14 },
{ "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:m:vh", longOpts, &optIndex);
if(c == -1) {
break;
}
@@ -185,29 +231,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:
@@ -220,9 +266,62 @@ 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;
+ 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;
}
+ case 14:
+ if(string(optarg) == V_GET || string(optarg) == V_TUNNEL) {
+ op->put(PREF_HTTP_PROXY_METHOD, optarg);
+ } else {
+ cerr << "http-proxy-method must be either 'get' or 'tunnel'." << endl;
+ showUsage();
+ exit(1);
+ }
+ break;
}
break;
}
@@ -244,12 +343,36 @@ 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 '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;
case 'v':
showVersion();
exit(0);
@@ -285,7 +408,9 @@ int main(int argc, char* argv[]) {
} else {
logger = new SimpleLogger("/dev/null");
}
-
+ SegmentSplitter* splitter = new SplitSlowestSegmentSplitter();
+ splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
+ splitter->logger = logger;
e = new DownloadEngine();
e->logger = logger;
e->option = op;
@@ -294,17 +419,14 @@ int main(int argc, char* argv[]) {
e->segmentMan->dir = dir;
e->segmentMan->ufilename = ufilename;
e->segmentMan->logger = logger;
+ e->segmentMan->option = op;
+ e->segmentMan->splitter = splitter;
vector<Request*> 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 445828fa..ca8514f3 100644
--- a/src/message.h
+++ b/src/message.h
@@ -27,11 +27,12 @@
#define MSG_CONNECTING_TO_SERVER "CUID#%d - Connecting to %s:%d"
#define MSG_SEGMENT_CHANGED "CUID#%d - The segment changed. We send the request again with new Range header."
#define MSG_REDIRECT "CUID#%d - Redirecting to %s"
-#define MSG_SENDING_HTTP_REQUEST "CUID#%d - Sending the request:\n%s"
+#define MSG_SENDING_REQUEST "CUID#%d - Requesting:\n%s"
#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."
#define MSG_SEGMENT_FILE_DOES_NOT_EXIST "The segment file %s does not exist."
@@ -44,12 +45,16 @@
#define EX_INVALID_CHUNK_SIZE "Invalid chunk size."
#define EX_TOO_LARGE_CHUNK "Too large chunk. size = %d"
#define EX_INVALID_HEADER "Invalid header."
+#define EX_INVALID_RESPONSE "Invalid response."
#define EX_NO_HEADER "No header found."
#define EX_NO_STATUS_HEADER "No status header."
#define EX_PROXY_CONNECTION_FAILED "Proxy connection failed."
+#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 %lld != %lld"
+
#endif // _D_MESSAGE_H_
diff --git a/src/prefs.h b/src/prefs.h
new file mode 100644
index 00000000..080ee961
--- /dev/null
+++ b/src/prefs.h
@@ -0,0 +1,83 @@
+/* <!-- 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_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_TRIES "max_try"
+// values: 1*digit
+#define PREF_MIN_SEGMENT_SIZE "min_segment_size"
+
+/**
+ * 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: get | tunnel
+#define PREF_HTTP_PROXY_METHOD "http_proxy_method"
+// 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_