diff --git a/ChangeLog b/ChangeLog index b1cba4de..d7f788b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-02-19 Tatsuhiro Tsujikawa + + * Fixed timeout bug in AbstractCommand + * Added totalSize entry to .aria2 file. No compatibility for + version 0.1.0's. + 2006-02-18 Tatsuhiro Tsujikawa * Added --enable-ssl option to configure script. diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 0a2f78d3..89683a70 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -28,13 +28,14 @@ #include "message.h" #include "SleepCommand.h" -#define TIMEOUT_SEC 5 +#define TIMEOUT_SEC 60 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 +44,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,6 +59,7 @@ 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); @@ -71,12 +73,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,17 +94,16 @@ 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()) { + req->addTryCount(); + if(req->noMoreTry()) { e->logger->error(MSG_MAX_RETRY, cuid); return true; } else { @@ -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; + + virtual bool prepareForRetry(int wait); + virtual void onAbort(Exception* e); + virtual bool executeInternal(Segment segment) = 0; + + void setReadCheckSocket(Socket* socket); + void setWriteCheckSocket(Socket* socket); +private: bool checkSocketIsReadable; bool checkSocketIsWritable; - virtual bool prepareForRetry(int wait); - virtual void onError(Exception* e); - virtual bool executeInternal(Segment segment) = 0; + Socket* readCheckTarget; + Socket* writeCheckTarget; public: AbstractCommand(int cuid, Request* req, DownloadEngine* e, Socket* s= NULL); virtual ~AbstractCommand(); diff --git a/src/DownloadCommand.cc b/src/DownloadCommand.cc index 39391963..0cc15661 100644 --- a/src/DownloadCommand.cc +++ b/src/DownloadCommand.cc @@ -27,9 +27,7 @@ #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) {} DownloadCommand::~DownloadCommand() {} @@ -84,3 +82,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..af44901c 100644 --- a/src/DownloadCommand.h +++ b/src/DownloadCommand.h @@ -34,7 +34,7 @@ protected: 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..337e221c 100644 --- a/src/DownloadEngine.cc +++ b/src/DownloadEngine.cc @@ -51,30 +51,31 @@ void DownloadEngine::run() { } if(!noWait && !commands.empty()) { waitData(); - 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; - 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; + + 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; + 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; + } + } + } segmentMan->removeIfFinished(); diskWriter->closeFile(); @@ -99,7 +100,7 @@ void DownloadEngine::waitData() { fd_set wfds; struct timeval tv; int retval; - + FD_ZERO(&rfds); FD_ZERO(&wfds); int max = 0; @@ -110,6 +111,7 @@ void DownloadEngine::waitData() { } } for(vector::iterator itr = wsockets.begin(); itr != wsockets.end(); itr++) { + FD_SET((*itr)->getSockfd(), &wfds); if(max < (*itr)->getSockfd()) { max = (*itr)->getSockfd(); @@ -118,7 +120,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& sockets, Socket* socket) { diff --git a/src/HttpConnection.cc b/src/HttpConnection.cc index b22d9126..9f373d33 100644 --- a/src/HttpConnection.cc +++ b/src/HttpConnection.cc @@ -26,15 +26,16 @@ #include "Base64.h" #include "message.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); +void HttpConnection::sendRequest(const Segment& segment) const { + string request = createRequest(segment); logger->info(MSG_SENDING_HTTP_REQUEST, cuid, request.c_str()); socket->writeData(request.c_str(), request.size()); } -void HttpConnection::sendProxyRequest(const Request* req) { +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"; @@ -47,19 +48,19 @@ void HttpConnection::sendProxyRequest(const Request* req) { socket->writeData(request.c_str(), request.size()); } -string HttpConnection::getHost(const string& host, int port) { +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" ? + 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"; @@ -87,48 +88,31 @@ 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); + 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 +129,17 @@ int HttpConnection::receiveResponse(HttpHeader& headers) { p = np+2; pair 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() { +bool HttpConnection::useProxy() const { return option->defined("http_proxy_enabled") && option->get("http_proxy_enabled") == "true"; } -bool HttpConnection::useProxyAuth() { +bool HttpConnection::useProxyAuth() const { return option->defined("http_proxy_auth_enabled") && option->get("http_proxy_auth_enabled") == "true"; } diff --git a/src/HttpConnection.h b/src/HttpConnection.h index c918d21d..a5a5eceb 100644 --- a/src/HttpConnection.h +++ b/src/HttpConnection.h @@ -27,30 +27,31 @@ #include "Request.h" #include "Option.h" #include "Logger.h" +#include "HttpHeader.h" #include #include using namespace std; -typedef multimap HttpHeader; +//typedef multimap 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; 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 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/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..1fd273bb 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -28,10 +28,12 @@ HttpResponseCommand::HttpResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s): AbstractCommand(cuid, req, e, s) { - AbstractCommand::checkSocketIsReadable = true; + http = new HttpConnection(cuid, socket, req, e->option, e->logger); } -HttpResponseCommand::~HttpResponseCommand() {} +HttpResponseCommand::~HttpResponseCommand() { + delete http; +} bool HttpResponseCommand::executeInternal(Segment seg) { if(SEGMENT_EQUAL(req->seg, seg) == false) { @@ -39,26 +41,30 @@ bool HttpResponseCommand::executeInternal(Segment seg) { return prepareForRetry(0); } HttpHeader headers; - HttpConnection httpConnection(cuid, socket, e->option, e->logger); - int status = httpConnection.receiveResponse(headers); + int status = http->receiveResponse(headers); + if(status == 0) { + // didn't receive header fully + e->commands.push(this); + return false; + } // check HTTP status number checkResponse(status, seg); retrieveCookie(headers); // check whether Location header exists. If it does, update request object // with redirected URL. // then establish a connection to the new host and port - if(headers.count("Location")) { - return handleRedirect((*headers.find("Location")).second, headers); + if(headers.defined("Location")) { + return handleRedirect(headers.getFirst("Location"), headers); } if(!e->segmentMan->downloadStarted) { string transferEncoding; - headers.find("Transfer-Encoding"); - if(headers.count("Transfer-Encoding")) { - return handleOtherEncoding((*headers.find("Transfer-Encoding")).second, headers); + if(headers.defined("Transfer-Encoding")) { + return handleOtherEncoding(headers.getFirst("Transfer-Encoding"), headers); } else { return handleDefaultEncoding(headers); } } else { + // TODO we must check headers["size"] == e->segmentMan->totalSize here if(req->getFile() != e->segmentMan->filename) { throw new DlAbortEx(EX_FILENAME_MISMATCH, req->getFile().c_str(), e->segmentMan->filename.c_str()); } @@ -83,28 +89,25 @@ bool HttpResponseCommand::handleRedirect(string url, const HttpHeader& headers) } bool HttpResponseCommand::handleDefaultEncoding(const HttpHeader& headers) { - long long int size; - if(headers.count("Content-Length") == 0) { - size = 0; - } else { - size = STRTOLL((*headers.find("Content-Length")).second.c_str()); - if(size == LONG_LONG_MAX || size == LONG_LONG_MIN) { - throw new DlAbortEx(EX_TOO_LARGE_FILE, size); - } + long long int size = headers.getFirstAsLLInt("Content-Length"); + if(size == LONG_LONG_MAX || size == LONG_LONG_MIN || size < 0) { + throw new DlAbortEx(EX_TOO_LARGE_FILE, size); } e->segmentMan->isSplittable = !(size == 0); e->segmentMan->filename = req->getFile(); - e->segmentMan->totalSize = size; bool segFileExists = e->segmentMan->segmentFileExists(); e->segmentMan->downloadStarted = true; if(segFileExists) { - e->segmentMan->load(); + e->diskWriter->openExistingFile(e->segmentMan->getFilePath()); + // we must check headers["size"] == e->segmentMan->totalSize here + if(e->segmentMan->totalSize != size) { + return new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size); + } // send request again to the server with Range header return prepareForRetry(0); } else { - Segment seg; - e->segmentMan->getSegment(seg, cuid); + e->segmentMan->totalSize = size; e->diskWriter->initAndOpenFile(e->segmentMan->getFilePath()); createHttpDownloadCommand(); return true; @@ -140,9 +143,10 @@ void HttpResponseCommand::createHttpDownloadCommand(string transferEncoding) { } void HttpResponseCommand::retrieveCookie(const HttpHeader& headers) { - for(HttpHeader::const_iterator itr = headers.find("Set-Cookie"); itr != headers.end(); itr++) { + vector v = headers.get("Set-Cookie"); + for(vector::const_iterator itr = v.begin(); itr != v.end(); itr++) { Cookie c; - req->cookieBox->parse(c, (*itr).second); + req->cookieBox->parse(c, *itr); req->cookieBox->add(c); } } 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..4ae30cca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,14 @@ 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\ diff --git a/src/Makefile.in b/src/Makefile.in index 006717df..760a3bce 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -61,7 +61,14 @@ 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) \ @@ -192,7 +199,14 @@ 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\ @@ -305,8 +319,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@ @@ -490,6 +511,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 +539,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 diff --git a/src/Request.cc b/src/Request.cc index b87cab1d..6eb4aa1e 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; @@ -102,15 +101,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..7a7b0fce 100644 --- a/src/Request.h +++ b/src/Request.h @@ -29,6 +29,8 @@ using namespace std; +#define MAX_TRY_COUNT 5 + #define SAFE_CHARS "abcdefghijklmnopqrstuvwxyz"\ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\ "0123456789"\ @@ -55,7 +57,7 @@ private: string dir; string file; map defaultPorts; - int retryCount; + int tryCount; bool parseUrl(string url); public: Segment seg; @@ -72,15 +74,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 >= MAX_TRY_COUNT; } 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/SegmentMan.cc b/src/SegmentMan.cc index 8dca0ba0..579c2bfe 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -123,7 +123,7 @@ void SegmentMan::updateSegment(const Segment& segment) { } -bool SegmentMan::segmentFileExists() { +bool SegmentMan::segmentFileExists() const { if(!isSplittable) { return false; } @@ -154,14 +154,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::iterator itr = segments.begin(); itr != segments.end(); itr++) { + if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) { + throw new DlAbortEx(strerror(errno)); + } + for(vector::const_iterator itr = segments.begin(); itr != segments.end(); itr++) { if(fwrite(&*itr, sizeof(Segment), 1, segFile) < 1) { throw new DlAbortEx(strerror(errno)); } @@ -170,7 +173,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 +183,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 +199,7 @@ void SegmentMan::read(FILE* file) { } } -void SegmentMan::remove() { +void SegmentMan::remove() const { if(!isSplittable) { return; } @@ -203,11 +209,11 @@ void SegmentMan::remove() { } } -bool SegmentMan::finished() { +bool SegmentMan::finished() const { if(!downloadStarted || segments.size() == 0) { return false; } - for(vector::iterator itr = segments.begin(); itr != segments.end(); itr++) { + for(vector::const_iterator itr = segments.begin(); itr != segments.end(); itr++) { if(!(*itr).finish) { return false; } @@ -215,15 +221,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::iterator itr = segments.begin(); itr != segments.end(); itr++) { + for(vector::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..e971a176 100644 --- a/src/SegmentMan.h +++ b/src/SegmentMan.h @@ -37,7 +37,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. @@ -80,7 +80,7 @@ public: */ string ufilename; - Logger* logger; + const Logger* logger; SegmentMan(); ~SegmentMan(); @@ -89,13 +89,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 +129,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 +139,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/SimpleLogger.cc b/src/SimpleLogger.cc index 9c2b28fe..476428fd 100644 --- a/src/SimpleLogger.cc +++ b/src/SimpleLogger.cc @@ -36,7 +36,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: @@ -56,14 +57,14 @@ void SimpleLogger::writeLog(int level, string msg, va_list ap, Exception* e) { 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 +72,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 +87,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& 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& 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 #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::establishConnection(string host, int port) { +void SocketCore::beginListen() { + closeConnection(); + //sockfd = socket(AF_UNSPEC, SOCK_STREAM, PF_UNSPEC); 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)); + 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& 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 == -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 +#include #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& 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/Util.cc b/src/Util.cc index 13258e41..99b70785 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -108,3 +108,14 @@ void Util::slice(vector& 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; + } +} diff --git a/src/Util.h b/src/Util.h index 02f73657..ebe67910 100644 --- a/src/Util.h +++ b/src/Util.h @@ -49,6 +49,8 @@ public: static void slice(vector& result, string src, char delim); static string trim(string src); + + static bool endsWith(string target, string part); }; #endif // _D_UTIL_H_ diff --git a/src/main.cc b/src/main.cc index 718ddd76..773bdd17 100644 --- a/src/main.cc +++ b/src/main.cc @@ -147,6 +147,15 @@ int main(int argc, char* argv[]) { Option* op = new Option(); op->put("retry_wait", "5"); + // TODO warning! Delete username/password line when commit + op->put("ftp_user", "anonymous"); + op->put("ftp_passwd", "IE60USER@"); + op->put("ftp_type", "I"); + + op->put("ftp_pasv_enabled", "true"); + op->put("ftp_via_http_proxy", "tunnel"); + op->put("http_abs_uri_request_enabled", "true"); + while(1) { int optIndex = 0; int lopt; diff --git a/src/message.h b/src/message.h index 445828fa..d326953c 100644 --- a/src/message.h +++ b/src/message.h @@ -28,10 +28,12 @@ #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_FTP_REQUEST "CUID#%d - Sending the request: %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_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 +46,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_TRANSFER_ENCODING_NOT_SUPPORTED "Transfer encoding %s is not supported." #define EX_SSL_INIT_FAILURE "SSL initialization failed." +#define EX_SIZE_MISMATCH "Size mismatch %d != %d" + #endif // _D_MESSAGE_H_ diff --git a/test/UtilTest.cc b/test/UtilTest.cc index 5dbc6148..0100adbb 100644 --- a/test/UtilTest.cc +++ b/test/UtilTest.cc @@ -10,6 +10,7 @@ class UtilTest:public CppUnit::TestFixture { CPPUNIT_TEST(testTrim); CPPUNIT_TEST(testSplit); CPPUNIT_TEST(testSlice); + CPPUNIT_TEST(testEndsWith); CPPUNIT_TEST_SUITE_END(); private: @@ -20,6 +21,7 @@ public: void testTrim(); void testSplit(); void testSlice(); + void testEndsWith(); }; @@ -75,3 +77,37 @@ void UtilTest::testSlice() { CPPUNIT_ASSERT_EQUAL(string("name2=value2"), *itr++); CPPUNIT_ASSERT_EQUAL(string("name3=value3"), *itr++); } + +void UtilTest::testEndsWith() { + string target = "abcdefg"; + string part = "fg"; + CPPUNIT_ASSERT(Util::endsWith(target, part)); + + target = "abdefg"; + part = "g"; + CPPUNIT_ASSERT(Util::endsWith(target, part)); + + target = "abdefg"; + part = "eg"; + CPPUNIT_ASSERT(!Util::endsWith(target, part)); + + target = "g"; + part = "eg"; + CPPUNIT_ASSERT(!Util::endsWith(target, part)); + + target = "g"; + part = "g"; + CPPUNIT_ASSERT(Util::endsWith(target, part)); + + target = "g"; + part = ""; + CPPUNIT_ASSERT(Util::endsWith(target, part)); + + target = ""; + part = ""; + CPPUNIT_ASSERT(Util::endsWith(target, part)); + + target = ""; + part = "g"; + CPPUNIT_ASSERT(!Util::endsWith(target, part)); +}