From f0f4f8f703b8c927fe8008daecb2d0547d486973 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 1 Dec 2010 21:26:58 +0900 Subject: [PATCH] Added more error code values. I have not set error code for all exception invocation. In this change, I set error code where error likely occurs. --- src/AbstractCommand.cc | 10 +++-- src/AbstractDiskWriter.cc | 72 ++++++++++++++++++++------------- src/DlAbortEx.h | 2 +- src/DownloadFailureException.cc | 7 ++++ src/DownloadFailureException.h | 7 ++++ src/Exception.cc | 18 ++++++++- src/Exception.h | 8 +++- src/ExpatMetalinkProcessor.cc | 19 ++++++--- src/FtpConnection.cc | 7 +++- src/FtpNegotiationCommand.cc | 37 +++++++++++------ src/HttpHeaderProcessor.cc | 7 +++- src/HttpResponse.cc | 10 +++-- src/HttpSkipResponseCommand.cc | 10 +++-- src/NameResolver.cc | 6 ++- src/OptionHandlerException.cc | 5 ++- src/OptionParser.cc | 4 +- src/RecoverableException.cc | 7 ++++ src/RecoverableException.h | 4 ++ src/XML2SAXMetalinkProcessor.cc | 22 ++++++---- src/bencode2.cc | 46 ++++++++++++--------- src/bittorrent_helper.cc | 47 +++++++++++++-------- src/error_code.h | 16 +++++++- src/option_processing.cc | 19 +++++---- src/util.cc | 8 ++-- 24 files changed, 275 insertions(+), 123 deletions(-) diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc index 3c1580f9..8c928274 100644 --- a/src/AbstractCommand.cc +++ b/src/AbstractCommand.cc @@ -65,6 +65,7 @@ #include "NameResolver.h" #include "uri.h" #include "FileEntry.h" +#include "error_code.h" #ifdef ENABLE_ASYNC_DNS #include "AsyncNameResolver.h" #endif // ENABLE_ASYNC_DNS @@ -650,11 +651,12 @@ bool AbstractCommand::asyncResolveHostname() e_->getRequestGroupMan()->getOrCreateServerStat (req_->getHost(), req_->getProtocol())->setError(); } - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt(MSG_NAME_RESOLUTION_FAILED, - getCuid(), - asyncNameResolver_->getHostname().c_str(), - asyncNameResolver_->getError().c_str())); + getCuid(), + asyncNameResolver_->getHostname().c_str(), + asyncNameResolver_->getError().c_str()), + error_code::NAME_RESOLVE_ERROR); default: return false; } diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index 39b989f4..e796ab51 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -51,6 +51,7 @@ #include "a2io.h" #include "fmt.h" #include "DownloadFailureException.h" +#include "error_code.h" namespace aria2 { @@ -100,10 +101,12 @@ void AbstractDiskWriter::openExistingFile(uint64_t totalLength) errno == EINTR); if(fd_ < 0) { int errNum = errno; - throw DL_ABORT_EX2 - (errNum, fmt(EX_FILE_OPEN, - filename_.c_str(), - util::safeStrerror(errNum).c_str())); + throw DL_ABORT_EX3 + (errNum, + fmt(EX_FILE_OPEN, + filename_.c_str(), + util::safeStrerror(errNum).c_str()), + error_code::FILE_OPEN_ERROR); } } @@ -116,10 +119,12 @@ void AbstractDiskWriter::createFile(int addFlags) OPEN_MODE)) == -1 && errno == EINTR); if(fd_ < 0) { int errNum = errno; - throw DL_ABORT_EX2 - (errNum, fmt(EX_FILE_OPEN, - filename_.c_str(), - util::safeStrerror(errNum).c_str())); + throw DL_ABORT_EX3 + (errNum, + fmt(EX_FILE_OPEN, + filename_.c_str(), + util::safeStrerror(errNum).c_str()), + error_code::FILE_CREATE_ERROR); } } @@ -148,9 +153,10 @@ void AbstractDiskWriter::seek(off_t offset) { if(a2lseek(fd_, offset, SEEK_SET) == (off_t)-1) { int errNum = errno; - throw DL_ABORT_EX(fmt(EX_FILE_SEEK, - filename_.c_str(), - util::safeStrerror(errNum).c_str())); + throw DL_ABORT_EX2(fmt(EX_FILE_SEEK, + filename_.c_str(), + util::safeStrerror(errNum).c_str()), + error_code::FILE_IO_ERROR); } } @@ -162,16 +168,19 @@ void AbstractDiskWriter::writeData(const unsigned char* data, size_t len, off_t // If errno is ENOSPC(not enough space in device), throw // DownloadFailureException and abort download instantly. if(errNum == ENOSPC) { - throw DOWNLOAD_FAILURE_EXCEPTION2 - (fmt(EX_FILE_WRITE, + throw DOWNLOAD_FAILURE_EXCEPTION3 + (errNum, + fmt(EX_FILE_WRITE, filename_.c_str(), util::safeStrerror(errNum).c_str()), error_code::NOT_ENOUGH_DISK_SPACE); } else { - throw DL_ABORT_EX - (fmt(EX_FILE_WRITE, + throw DL_ABORT_EX3 + (errNum, + fmt(EX_FILE_WRITE, filename_.c_str(), - util::safeStrerror(errNum).c_str())); + util::safeStrerror(errNum).c_str()), + error_code::FILE_IO_ERROR); } } } @@ -182,10 +191,12 @@ ssize_t AbstractDiskWriter::readData(unsigned char* data, size_t len, off_t offs seek(offset); if((ret = readDataInternal(data, len)) < 0) { int errNum = errno; - throw DL_ABORT_EX - (fmt(EX_FILE_READ, + throw DL_ABORT_EX3 + (errNum, + fmt(EX_FILE_READ, filename_.c_str(), - util::safeStrerror(errNum).c_str())); + util::safeStrerror(errNum).c_str()), + error_code::FILE_IO_ERROR); } return ret; } @@ -201,14 +212,17 @@ void AbstractDiskWriter::truncate(uint64_t length) HANDLE handle = LongToHandle(_get_osfhandle(fd_)); seek(length); if(SetEndOfFile(handle) == 0) { - throw DL_ABORT_EX(fmt("SetEndOfFile failed. cause: %s", - GetLastError())); + throw DL_ABORT_EX2(fmt("SetEndOfFile failed. cause: %s", + GetLastError()), + error_code::FILE_IO_ERROR); } #else if(ftruncate(fd_, length) == -1) { int errNum = errno; - throw DL_ABORT_EX(fmt("ftruncate failed. cause: %s", - util::safeStrerror(errNum).c_str())); + throw DL_ABORT_EX3(errNum, + fmt("ftruncate failed. cause: %s", + util::safeStrerror(errNum).c_str()), + error_code::FILE_IO_ERROR); } #endif } @@ -226,14 +240,18 @@ void AbstractDiskWriter::allocate(off_t offset, uint64_t length) while((r = fallocate(fd_, 0, offset, length)) == -1 && errno == EINTR); int errNum = errno; if(r == -1) { - throw DL_ABORT_EX(fmt("fallocate failed. cause: %s", - util::safeStrerror(errNum).c_str())); + throw DL_ABORT_EX3(errNum, + fmt("fallocate failed. cause: %s", + util::safeStrerror(errNum).c_str()), + error_code::FILE_IO_ERROR); } # elif HAVE_POSIX_FALLOCATE int r = posix_fallocate(fd_, offset, length); if(r != 0) { - throw DL_ABORT_EX(fmt("posix_fallocate failed. cause: %s", - util::safeStrerror(r).c_str())); + throw DL_ABORT_EX3(errNum, + fmt("posix_fallocate failed. cause: %s", + util::safeStrerror(r).c_str()), + error_code::FILE_IO_ERROR); } # else # error "no *_fallocate function available." diff --git a/src/DlAbortEx.h b/src/DlAbortEx.h index 7bf4f835..3498b1fb 100644 --- a/src/DlAbortEx.h +++ b/src/DlAbortEx.h @@ -58,7 +58,7 @@ public: #define DL_ABORT_EX(arg) DlAbortEx(__FILE__, __LINE__, arg) #define DL_ABORT_EX2(arg1, arg2) DlAbortEx(__FILE__, __LINE__, arg1, arg2) -#define DL_ABORT_EX3(arg1, arg2, arg3)\ +#define DL_ABORT_EX3(arg1, arg2, arg3) \ DlAbortEx(__FILE__, __LINE__, arg1, arg2, arg3) } // namespace aria2 diff --git a/src/DownloadFailureException.cc b/src/DownloadFailureException.cc index cc0113b5..90411460 100644 --- a/src/DownloadFailureException.cc +++ b/src/DownloadFailureException.cc @@ -57,4 +57,11 @@ DownloadFailureException::DownloadFailureException error_code::Value code): RecoverableException(file, line, msg, code) {} +DownloadFailureException::DownloadFailureException +(const char* file, int line, + int errNum, + const std::string& msg, + error_code::Value code): + RecoverableException(file, line, errNum, msg, code) {} + } // namespace aria2 diff --git a/src/DownloadFailureException.h b/src/DownloadFailureException.h index 2bf7faa3..a4f29206 100644 --- a/src/DownloadFailureException.h +++ b/src/DownloadFailureException.h @@ -54,12 +54,19 @@ public: DownloadFailureException(const char* file, int line, const std::string& msg, error_code::Value code); + + DownloadFailureException(const char* file, int line, + int errNum, + const std::string& msg, + error_code::Value code); }; #define DOWNLOAD_FAILURE_EXCEPTION(arg) \ DownloadFailureException(__FILE__, __LINE__, arg) #define DOWNLOAD_FAILURE_EXCEPTION2(arg1, arg2) \ DownloadFailureException(__FILE__, __LINE__, arg1, arg2) +#define DOWNLOAD_FAILURE_EXCEPTION3(arg1, arg2, arg3) \ + DownloadFailureException(__FILE__, __LINE__, arg1, arg2, arg3) } // namespace aria2 diff --git a/src/Exception.cc b/src/Exception.cc index 9652ce59..1492b59b 100644 --- a/src/Exception.cc +++ b/src/Exception.cc @@ -53,13 +53,27 @@ Exception::Exception (const char* file, int line, const std::string& msg, + error_code::Value errorCode, const Exception& cause) : file_(file), line_(line), errNum_(0), msg_(msg), - cause_(cause.copy()), - errorCode_(cause.errorCode_) + errorCode_(errorCode), + cause_(cause.copy()) +{} + +Exception::Exception +(const char* file, + int line, + const std::string& msg, + const Exception& cause) + : file_(file), + line_(line), + errNum_(0), + msg_(msg), + errorCode_(cause.errorCode_), + cause_(cause.copy()) {} Exception::Exception diff --git a/src/Exception.h b/src/Exception.h index e54b28e0..bf549a64 100644 --- a/src/Exception.h +++ b/src/Exception.h @@ -53,16 +53,20 @@ private: int errNum_; std::string msg_; + // This is application-level error code. + error_code::Value errorCode_; // Exception that this object wraps. Normally this cause_ is the // root cause of this exception. SharedHandle cause_; - // This is application-level error code. - error_code::Value errorCode_; protected: virtual SharedHandle copy() const = 0; public: Exception(const char* file, int line, const std::string& msg); + + Exception(const char* file, int line, const std::string& msg, + error_code::Value errorCode, + const Exception& cause); // errorCode_ is initializedwith cause.errorCode_. Exception(const char* file, int line, const std::string& msg, const Exception& cause); diff --git a/src/ExpatMetalinkProcessor.cc b/src/ExpatMetalinkProcessor.cc index 1e98a1f6..7e89376c 100644 --- a/src/ExpatMetalinkProcessor.cc +++ b/src/ExpatMetalinkProcessor.cc @@ -46,6 +46,7 @@ #include "DlAbortEx.h" #include "MetalinkParserState.h" #include "A2STR.h" +#include "error_code.h" namespace aria2 { @@ -158,16 +159,19 @@ namespace { void checkError(XML_Parser parser) { if(XML_Parse(parser, 0, 0, 1) == XML_STATUS_ERROR) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } SessionData* sessionData = reinterpret_cast(XML_GetUserData(parser)); const SharedHandle& stm = sessionData->stm_; if(!stm->finished()) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } if(!stm->getErrors().empty()) { - throw DL_ABORT_EX(stm->getErrorString()); + throw DL_ABORT_EX2(stm->getErrorString(), + error_code::METALINK_PARSE_ERROR); } } } // namespace @@ -195,11 +199,13 @@ MetalinkProcessor::parseFile(std::istream& stream) while(stream) { stream.read(buf, sizeof(buf)); if(XML_Parse(parser, buf, stream.gcount(), 0) == XML_STATUS_ERROR) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } } if(stream.bad()) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } checkError(parser); return stm_->getResult(); @@ -223,7 +229,8 @@ MetalinkProcessor::parseFromBinaryStream(const SharedHandle& binar } if(XML_Parse(parser, reinterpret_cast(buf), res, 0) == XML_STATUS_ERROR) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } readOffset += res; } diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index da01caac..debde951 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -56,6 +56,7 @@ #include "AuthConfig.h" #include "a2functional.h" #include "util.h" +#include "error_code.h" namespace aria2 { @@ -382,7 +383,8 @@ bool FtpConnection::bulkReceiveResponse if(strbuf_.size() >= 4) { status = getStatus(strbuf_); if(status == 0) { - throw DL_ABORT_EX(EX_INVALID_RESPONSE); + throw DL_ABORT_EX2(EX_INVALID_RESPONSE, + error_code::FTP_PROTOCOL_ERROR); } } else { return false; @@ -549,7 +551,8 @@ unsigned int FtpConnection::receivePwdResponse(std::string& pwd) (last = response.second.find("\"", ++first)) != std::string::npos) { pwd = response.second.substr(first, last-first); } else { - throw DL_ABORT_EX(EX_INVALID_RESPONSE); + throw DL_ABORT_EX2(EX_INVALID_RESPONSE, + error_code::FTP_PROTOCOL_ERROR); } } return response.first; diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 2a18f7ac..626d2a75 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -72,6 +72,7 @@ #include "HttpResponse.h" #include "DlRetryEx.h" #include "CheckIntegrityEntry.h" +#include "error_code.h" namespace aria2 { @@ -154,7 +155,7 @@ bool FtpNegotiationCommand::recvGreeting() { return false; } if(status != 220) { - throw DL_ABORT_EX(EX_CONNECTION_FAILED); + throw DL_ABORT_EX2(EX_CONNECTION_FAILED, error_code::FTP_PROTOCOL_ERROR); } sequence_ = SEQ_SEND_USER; @@ -183,7 +184,8 @@ bool FtpNegotiationCommand::recvUser() { sequence_ = SEQ_SEND_PASS; break; default: - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } return true; } @@ -204,7 +206,8 @@ bool FtpNegotiationCommand::recvPass() { return false; } if(status != 230) { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } sequence_ = SEQ_SEND_TYPE; return true; @@ -226,7 +229,8 @@ bool FtpNegotiationCommand::recvType() { return false; } if(status != 200) { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } sequence_ = SEQ_SEND_PWD; return true; @@ -251,7 +255,8 @@ bool FtpNegotiationCommand::recvPwd() return false; } if(status != 257) { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } ftp_->setBaseWorkingDir(pwd); A2_LOG_INFO(fmt("CUID#%lld - base working directory is '%s'", @@ -295,7 +300,8 @@ bool FtpNegotiationCommand::recvCwd() throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND, error_code::RESOURCE_NOT_FOUND); else - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } cwdDirs_.pop_front(); if(cwdDirs_.empty()) { @@ -461,9 +467,10 @@ bool FtpNegotiationCommand::recvSize() { if(status == 213) { if(size > INT64_MAX) { - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt(EX_TOO_LARGE_FILE, - util::uitos(size, true).c_str())); + util::uitos(size, true).c_str()), + error_code::FTP_PROTOCOL_ERROR); } if(!getPieceStorage()) { @@ -563,7 +570,8 @@ bool FtpNegotiationCommand::recvPort() { return false; } if(status != 200) { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } sequence_ = SEQ_SEND_REST; return true; @@ -624,7 +632,8 @@ bool FtpNegotiationCommand::recvPasv() { return false; } if(status != 227) { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } dataConnAddr_ = dest; @@ -744,8 +753,9 @@ bool FtpNegotiationCommand::sendRestPasv(const SharedHandle& segment) { // Check connection is made properly if(dataSocket_->isReadable(0)) { std::string error = dataSocket_->getSocketError(); - throw DL_ABORT_EX - (fmt(MSG_ESTABLISHING_CONNECTION_FAILED, error.c_str())); + throw DL_ABORT_EX2 + (fmt(MSG_ESTABLISHING_CONNECTION_FAILED, error.c_str()), + error_code::FTP_PROTOCOL_ERROR); } setReadCheckSocket(getSocket()); disableWriteCheckSocket(); @@ -800,7 +810,8 @@ bool FtpNegotiationCommand::recvRetr() { throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND, error_code::RESOURCE_NOT_FOUND); else - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, status)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status), + error_code::FTP_PROTOCOL_ERROR); } if(getOption()->getAsBool(PREF_FTP_PASV)) { sequence_ = SEQ_NEGOTIATION_COMPLETED; diff --git a/src/HttpHeaderProcessor.cc b/src/HttpHeaderProcessor.cc index 86ba19a0..477d7458 100644 --- a/src/HttpHeaderProcessor.cc +++ b/src/HttpHeaderProcessor.cc @@ -43,6 +43,7 @@ #include "DlRetryEx.h" #include "DlAbortEx.h" #include "A2STR.h" +#include "error_code.h" namespace aria2 { @@ -71,7 +72,8 @@ void HttpHeaderProcessor::update(const std::string& data) void HttpHeaderProcessor::checkHeaderLimit(size_t incomingLength) { if(buf_.size()+incomingLength > limit_) { - throw DL_ABORT_EX("Too large http header"); + throw DL_ABORT_EX2("Too large http header", + error_code::HTTP_PROTOCOL_ERROR); } } @@ -138,7 +140,8 @@ SharedHandle HttpHeaderProcessor::getHttpRequestHeader() std::vector firstLine; util::split(buf_.substr(0, delimpos), std::back_inserter(firstLine)," ",true); if(firstLine.size() != 3) { - throw DL_ABORT_EX("Malformed HTTP request header."); + throw DL_ABORT_EX2("Malformed HTTP request header.", + error_code::HTTP_PROTOCOL_ERROR); } SharedHandle httpHeader(new HttpHeader()); httpHeader->setMethod(firstLine[0]); diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index 6ce8be89..8ec7d257 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -50,6 +50,7 @@ #include "AuthConfigFactory.h" #include "AuthConfig.h" #include "ChunkedDecodingStreamFilter.h" +#include "error_code.h" #ifdef HAVE_LIBZ # include "GZipDecodingStreamFilter.h" #endif // HAVE_LIBZ @@ -70,14 +71,16 @@ void HttpResponse::validateResponse() const } if(statusCode == 304) { if(httpRequest_->getIfModifiedSinceHeader().empty()) { - throw DL_ABORT_EX("Got 304 without If-Modified-Since"); + throw DL_ABORT_EX2("Got 304 without If-Modified-Since", + error_code::HTTP_PROTOCOL_ERROR); } } else if(statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307) { if(!httpHeader_->defined(HttpHeader::LOCATION)) { - throw DL_ABORT_EX(fmt(EX_LOCATION_HEADER_REQUIRED, statusCode)); + throw DL_ABORT_EX2(fmt(EX_LOCATION_HEADER_REQUIRED, statusCode), + error_code::HTTP_PROTOCOL_ERROR); } return; } else if(statusCode == 200 || statusCode == 206) { @@ -97,7 +100,8 @@ void HttpResponse::validateResponse() const } } } else { - throw DL_ABORT_EX(fmt("Unexpected status %d", statusCode)); + throw DL_ABORT_EX2(fmt("Unexpected status %d", statusCode), + error_code::HTTP_PROTOCOL_ERROR); } } diff --git a/src/HttpSkipResponseCommand.cc b/src/HttpSkipResponseCommand.cc index f857aee3..05002fad 100644 --- a/src/HttpSkipResponseCommand.cc +++ b/src/HttpSkipResponseCommand.cc @@ -58,6 +58,7 @@ #include "BinaryStream.h" #include "NullSinkStreamFilter.h" #include "SinkStreamFilter.h" +#include "error_code.h" namespace aria2 { @@ -175,7 +176,8 @@ bool HttpSkipResponseCommand::processResponse() unsigned int rnum = httpResponse_->getHttpRequest()->getRequest()->getRedirectCount(); if(rnum >= Request::MAX_REDIRECT) { - throw DL_ABORT_EX(fmt("Too many redirects: count=%u", rnum)); + throw DL_ABORT_EX2(fmt("Too many redirects: count=%u", rnum), + error_code::HTTP_TOO_MANY_REDIRECTS); } httpResponse_->processRedirect(); return prepareForRetry(0); @@ -187,13 +189,15 @@ bool HttpSkipResponseCommand::processResponse() (getRequest()->getHost(), getRequest()->getDir(), getOption().get())) { return prepareForRetry(0); } else { - throw DL_ABORT_EX(EX_AUTH_FAILED); + throw DL_ABORT_EX2(EX_AUTH_FAILED, + error_code::HTTP_AUTH_FAILED); } } else if(statusCode == 404) { throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND, error_code::RESOURCE_NOT_FOUND); } else { - throw DL_ABORT_EX(fmt(EX_BAD_STATUS, statusCode)); + throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, statusCode), + error_code::HTTP_PROTOCOL_ERROR); } } else { return prepareForRetry(0); diff --git a/src/NameResolver.cc b/src/NameResolver.cc index 72695c3b..35f423eb 100644 --- a/src/NameResolver.cc +++ b/src/NameResolver.cc @@ -41,6 +41,7 @@ #include "fmt.h" #include "util.h" #include "SocketCore.h" +#include "error_code.h" namespace aria2 { @@ -53,8 +54,9 @@ void NameResolver::resolve(std::vector& resolvedAddresses, int s; s = callGetaddrinfo(&res, hostname.c_str(), 0, family_, socktype_, 0, 0); if(s) { - throw DL_ABORT_EX(fmt(EX_RESOLVE_HOSTNAME, - hostname.c_str(), gai_strerror(s))); + throw DL_ABORT_EX2(fmt(EX_RESOLVE_HOSTNAME, + hostname.c_str(), gai_strerror(s)), + error_code::NAME_RESOLVE_ERROR); } WSAAPI_AUTO_DELETE resDeleter(res, freeaddrinfo); struct addrinfo* rp; diff --git a/src/OptionHandlerException.cc b/src/OptionHandlerException.cc index fa737465..f3949768 100644 --- a/src/OptionHandlerException.cc +++ b/src/OptionHandlerException.cc @@ -43,14 +43,15 @@ const std::string OptionHandlerException::MESSAGE OptionHandlerException::OptionHandlerException(const char* file, int line, const std::string& optName): RecoverableException - (file, line, fmt(MESSAGE.c_str(), optName.c_str())), + (file, line, fmt(MESSAGE.c_str(), optName.c_str()), error_code::OPTION_ERROR), optName_(optName) {} OptionHandlerException::OptionHandlerException(const char* file, int line, const std::string& optName, const Exception& cause): RecoverableException - (file, line, fmt(MESSAGE.c_str(), optName.c_str()), cause), + (file, line, fmt(MESSAGE.c_str(), optName.c_str()), error_code::OPTION_ERROR, + cause), optName_(optName) {} OptionHandlerException::~OptionHandlerException() throw() {} diff --git a/src/OptionParser.cc b/src/OptionParser.cc index 6b38074f..15e49fa7 100644 --- a/src/OptionParser.cc +++ b/src/OptionParser.cc @@ -49,6 +49,7 @@ #include "array_fun.h" #include "OptionHandlerFactory.h" #include "DlAbortEx.h" +#include "error_code.h" namespace aria2 { @@ -158,7 +159,8 @@ void OptionParser::parseArg op = findByShortName(c); } if(!op) { - throw DL_ABORT_EX("Failed to parse command-line options."); + throw DL_ABORT_EX2("Failed to parse command-line options.", + error_code::OPTION_ERROR); } out << op->getName() << "="; if(optarg) { diff --git a/src/RecoverableException.cc b/src/RecoverableException.cc index 29a0cde9..546c86eb 100644 --- a/src/RecoverableException.cc +++ b/src/RecoverableException.cc @@ -47,6 +47,13 @@ RecoverableException::RecoverableException : Exception(file, line, msg) {} +RecoverableException::RecoverableException +(const char* file, int line, const std::string& msg, + error_code::Value errorCode, + const Exception& cause) + : Exception(file, line, msg, errorCode, cause) +{} + RecoverableException::RecoverableException (const char* file, int line, const std::string& msg, const Exception& cause) diff --git a/src/RecoverableException.h b/src/RecoverableException.h index 6d066b1c..87a6b07e 100644 --- a/src/RecoverableException.h +++ b/src/RecoverableException.h @@ -44,6 +44,10 @@ protected: public: RecoverableException(const char* file, int line, const std::string& msg); + RecoverableException(const char* file, int line, const std::string& msg, + error_code::Value errorCode, + const Exception& cause); + RecoverableException(const char* file, int line, const std::string& msg, const Exception& cause); diff --git a/src/XML2SAXMetalinkProcessor.cc b/src/XML2SAXMetalinkProcessor.cc index 1410f4d2..b069d9c1 100644 --- a/src/XML2SAXMetalinkProcessor.cc +++ b/src/XML2SAXMetalinkProcessor.cc @@ -44,6 +44,7 @@ #include "message.h" #include "DlAbortEx.h" #include "A2STR.h" +#include "error_code.h" namespace aria2 { @@ -200,13 +201,16 @@ MetalinkProcessor::parseFile(const std::string& filename) int retval = xmlSAXUserParseFile(&mySAXHandler, sessionData.get(), nfilename.c_str()); if(retval != 0) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } if(!stm_->finished()) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } if(!stm_->getErrors().empty()) { - throw DL_ABORT_EX(stm_->getErrorString()); + throw DL_ABORT_EX2(stm_->getErrorString(), + error_code::METALINK_PARSE_ERROR); } return stm_->getResult(); } @@ -220,7 +224,8 @@ MetalinkProcessor::parseFromBinaryStream(const SharedHandle& binar ssize_t res = binaryStream->readData(buf, 4, 0); if(res != 4) { - throw DL_ABORT_EX("Too small data for parsing XML."); + throw DL_ABORT_EX2("Too small data for parsing XML.", + error_code::METALINK_PARSE_ERROR); } SharedHandle sessionData(new SessionData(stm_)); @@ -236,17 +241,20 @@ MetalinkProcessor::parseFromBinaryStream(const SharedHandle& binar break; } if(xmlParseChunk(ctx, reinterpret_cast(buf), res, 0) != 0) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } readOffset += res; } xmlParseChunk(ctx, reinterpret_cast(buf), 0, 1); if(!stm_->finished()) { - throw DL_ABORT_EX(MSG_CANNOT_PARSE_METALINK); + throw DL_ABORT_EX2(MSG_CANNOT_PARSE_METALINK, + error_code::METALINK_PARSE_ERROR); } if(!stm_->getErrors().empty()) { - throw DL_ABORT_EX(stm_->getErrorString()); + throw DL_ABORT_EX2(stm_->getErrorString(), + error_code::METALINK_PARSE_ERROR); } return stm_->getResult(); } diff --git a/src/bencode2.cc b/src/bencode2.cc index 29bf20da..10b39cda 100644 --- a/src/bencode2.cc +++ b/src/bencode2.cc @@ -39,6 +39,7 @@ #include "fmt.h" #include "DlAbortEx.h" +#include "error_code.h" namespace aria2 { @@ -53,9 +54,10 @@ void checkdelim(std::istream& ss, const char delim = ':') { char d; if(!(ss.get(d) && d == delim)) { - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt("Bencode decoding failed: Delimiter '%c' not found.", - delim)); + delim), + error_code::BENCODE_PARSE_ERROR); } } } // namespace @@ -66,8 +68,9 @@ std::string decoderawstring(std::istream& ss) int length; ss >> length; if(!ss || length < 0) { - throw DL_ABORT_EX("Bencode decoding failed:" - " A positive integer expected but none found."); + throw DL_ABORT_EX2("Bencode decoding failed:" + " A positive integer expected but none found.", + error_code::BENCODE_PARSE_ERROR); } // TODO check length, it must be less than or equal to INT_MAX checkdelim(ss); @@ -76,11 +79,12 @@ std::string decoderawstring(std::istream& ss) std::string str(&buf[0], &buf[length]); delete [] buf; if(ss.gcount() != static_cast(length)) { - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt("Bencode decoding failed:" " Expected %lu bytes of data, but only %ld read.", static_cast(length), - static_cast(ss.gcount()))); + static_cast(ss.gcount())), + error_code::BENCODE_PARSE_ERROR); } return str; } @@ -99,8 +103,9 @@ SharedHandle decodeinteger(std::istream& ss) Integer::ValueType iv; ss >> iv; if(!ss) { - throw DL_ABORT_EX("Bencode decoding failed:" - " Integer expected but none found"); + throw DL_ABORT_EX2("Bencode decoding failed:" + " Integer expected but none found", + error_code::BENCODE_PARSE_ERROR); } checkdelim(ss, 'e'); return Integer::g(iv); @@ -121,8 +126,9 @@ SharedHandle decodedict(std::istream& ss, size_t depth) dict->put(key, decodeiter(ss, depth)); } } - throw DL_ABORT_EX("Bencode decoding failed:" - " Unexpected EOF in dict context. 'e' expected."); + throw DL_ABORT_EX2("Bencode decoding failed:" + " Unexpected EOF in dict context. 'e' expected.", + error_code::BENCODE_PARSE_ERROR); } } // namespace @@ -139,8 +145,9 @@ SharedHandle decodelist(std::istream& ss, size_t depth) list->append(decodeiter(ss, depth)); } } - throw DL_ABORT_EX("Bencode decoding failed:" - " Unexpected EOF in list context. 'e' expected."); + throw DL_ABORT_EX2("Bencode decoding failed:" + " Unexpected EOF in list context. 'e' expected.", + error_code::BENCODE_PARSE_ERROR); } } // namespace @@ -148,7 +155,8 @@ namespace { void checkDepth(size_t depth) { if(depth >= MAX_STRUCTURE_DEPTH) { - throw DL_ABORT_EX("Bencode decoding failed: Structure is too deep."); + throw DL_ABORT_EX2("Bencode decoding failed: Structure is too deep.", + error_code::BENCODE_PARSE_ERROR); } } } // namespace @@ -159,9 +167,10 @@ SharedHandle decodeiter(std::istream& ss, size_t depth) checkDepth(depth); char c; if(!ss.get(c)) { - throw DL_ABORT_EX("Bencode decoding failed:" - " Unexpected EOF in term context." - " 'd', 'l', 'i' or digit is expected."); + throw DL_ABORT_EX2("Bencode decoding failed:" + " Unexpected EOF in term context." + " 'd', 'l', 'i' or digit is expected.", + error_code::BENCODE_PARSE_ERROR); } if(c == 'd') { return decodedict(ss, depth+1); @@ -215,9 +224,10 @@ SharedHandle decodeFromFile(const std::string& filename) if(f) { return decode(f); } else { - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt("Bencode decoding failed: Cannot open file '%s'.", - filename.c_str())); + filename.c_str()), + error_code::BENCODE_PARSE_ERROR); } } diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 003ac1c9..0ab21a1d 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -58,6 +58,7 @@ #include "Option.h" #include "prefs.h" #include "FileEntry.h" +#include "error_code.h" namespace aria2 { @@ -209,9 +210,10 @@ void extractFileEntries if(nameData) { utf8Name = util::encodeNonUtf8(nameData->s()); if(util::detectDirTraversal(utf8Name)) { - throw DL_ABORT_EX + throw DL_ABORT_EX2 (fmt(MSG_DIR_TRAVERSAL_DETECTED, - nameData->s().c_str())); + nameData->s().c_str()), + error_code::BITTORRENT_PARSE_ERROR); } name = nameData->s(); } else { @@ -237,7 +239,8 @@ void extractFileEntries } const Integer* fileLengthData = asInteger(fileDict->get(C_LENGTH)); if(!fileLengthData) { - throw DL_ABORT_EX(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str())); + throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } length += fileLengthData->i(); @@ -249,7 +252,8 @@ void extractFileEntries } const List* pathList = asList(fileDict->get(pathKey)); if(!pathList || pathList->empty()) { - throw DL_ABORT_EX("Path is empty."); + throw DL_ABORT_EX2("Path is empty.", + error_code::BITTORRENT_PARSE_ERROR); } std::vector pathelem(pathList->size()+1); @@ -262,14 +266,16 @@ void extractFileEntries if(elem) { (*pathelemOutItr++) = elem->s(); } else { - throw DL_ABORT_EX("Path element is not string."); + throw DL_ABORT_EX2("Path element is not string.", + error_code::BITTORRENT_PARSE_ERROR); } } std::string path = strjoin(pathelem.begin(), pathelem.end(), '/'); std::string utf8Path = strjoin(pathelem.begin(), pathelem.end(), '/', std::ptr_fun(util::encodeNonUtf8)); if(util::detectDirTraversal(utf8Path)) { - throw DL_ABORT_EX(fmt(MSG_DIR_TRAVERSAL_DETECTED, utf8Path.c_str())); + throw DL_ABORT_EX2(fmt(MSG_DIR_TRAVERSAL_DETECTED, utf8Path.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } std::string pePath = strjoin(pathelem.begin(), pathelem.end(), '/', @@ -289,7 +295,8 @@ void extractFileEntries torrent->mode = SINGLE; const Integer* lengthData = asInteger(infoDict->get(C_LENGTH)); if(!lengthData) { - throw DL_ABORT_EX(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str())); + throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_LENGTH.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } uint64_t totalLength = lengthData->i(); @@ -391,11 +398,13 @@ void processRootDictionary { const Dict* rootDict = asDict(root); if(!rootDict) { - throw DL_ABORT_EX("torrent file does not contain a root dictionary."); + throw DL_ABORT_EX2("torrent file does not contain a root dictionary.", + error_code::BITTORRENT_PARSE_ERROR); } const Dict* infoDict = asDict(rootDict->get(C_INFO)); if(!infoDict) { - throw DL_ABORT_EX(fmt(MSG_MISSING_BT_INFO, C_INFO.c_str())); + throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_INFO.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } SharedHandle torrent(new TorrentAttribute()); @@ -413,7 +422,8 @@ void processRootDictionary // calculate the number of pieces const String* piecesData = asString(infoDict->get(C_PIECES)); if(!piecesData) { - throw DL_ABORT_EX(fmt(MSG_MISSING_BT_INFO, C_PIECES.c_str())); + throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_PIECES.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } // Commented out To download 0 length torrent. // if(piecesData.s().empty()) { @@ -427,7 +437,8 @@ void processRootDictionary // retrieve piece length const Integer* pieceLengthData = asInteger(infoDict->get(C_PIECE_LENGTH)); if(!pieceLengthData) { - throw DL_ABORT_EX(fmt(MSG_MISSING_BT_INFO, C_PIECE_LENGTH.c_str())); + throw DL_ABORT_EX2(fmt(MSG_MISSING_BT_INFO, C_PIECE_LENGTH.c_str()), + error_code::BITTORRENT_PARSE_ERROR); } size_t pieceLength = pieceLengthData->i(); ctx->setPieceLength(pieceLength); @@ -457,7 +468,8 @@ void processRootDictionary extractFileEntries (ctx, torrent, infoDict, defaultName, overrideName, urlList); if((ctx->getTotalLength()+pieceLength-1)/pieceLength != numPieces) { - throw DL_ABORT_EX("Too few/many piece hash."); + throw DL_ABORT_EX2("Too few/many piece hash.", + error_code::BITTORRENT_PARSE_ERROR); } // retrieve announce extractAnnounce(torrent, rootDict); @@ -908,11 +920,13 @@ SharedHandle parseMagnet(const std::string& magnet) { SharedHandle r = magnet::parse(magnet); if(!r) { - throw DL_ABORT_EX("Bad BitTorrent Magnet URI."); + throw DL_ABORT_EX2("Bad BitTorrent Magnet URI.", + error_code::MAGNET_PARSE_ERROR); } const List* xts = asList(r->get("xt")); if(!xts) { - throw DL_ABORT_EX("Missing xt parameter in Magnet URI."); + throw DL_ABORT_EX2("Missing xt parameter in Magnet URI.", + error_code::MAGNET_PARSE_ERROR); } SharedHandle attrs(new TorrentAttribute()); std::string infoHash; @@ -936,8 +950,9 @@ SharedHandle parseMagnet(const std::string& magnet) } } if(infoHash.empty()) { - throw DL_ABORT_EX("Bad BitTorrent Magnet URI. " - "No valid BitTorrent Info Hash found."); + throw DL_ABORT_EX2("Bad BitTorrent Magnet URI. " + "No valid BitTorrent Info Hash found.", + error_code::MAGNET_PARSE_ERROR); } const List* trs = asList(r->get("tr")); if(trs) { diff --git a/src/error_code.h b/src/error_code.h index 3678c6b6..e9670a11 100644 --- a/src/error_code.h +++ b/src/error_code.h @@ -57,7 +57,21 @@ enum Value { DUPLICATE_DOWNLOAD = 11, DUPLICATE_INFO_HASH = 12, FILE_ALREADY_EXISTS = 13, - FILE_RENAMING_FAILED = 14 + FILE_RENAMING_FAILED = 14, + FILE_OPEN_ERROR = 15, + FILE_CREATE_ERROR = 16, + FILE_IO_ERROR = 17, + DIR_CREATE_ERROR = 18, + NAME_RESOLVE_ERROR = 19, + METALINK_PARSE_ERROR = 20, + FTP_PROTOCOL_ERROR = 21, + HTTP_PROTOCOL_ERROR = 22, + HTTP_TOO_MANY_REDIRECTS = 23, + HTTP_AUTH_FAILED = 24, + BENCODE_PARSE_ERROR = 25, + BITTORRENT_PARSE_ERROR = 26, + MAGNET_PARSE_ERROR = 27, + OPTION_ERROR = 28 }; } // namespace error_code diff --git a/src/option_processing.cc b/src/option_processing.cc index bb5ef3be..c7e74206 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -145,11 +145,11 @@ void option_processing(Option& op, std::vector& uris, << oparser.findByName(e.getOptionName())->getDescription() << std::endl; } - exit(error_code::UNKNOWN_ERROR); + exit(e.getErrorCode()); } catch(Exception& e) { std::cerr << "Parse error in " << cfname << "\n" << e.stackTrace() << std::endl; - exit(error_code::UNKNOWN_ERROR); + exit(e.getErrorCode()); } } else if(!ucfname.empty()) { std::cerr << fmt("Configuration file %s is not found.", cfname.c_str()) @@ -171,15 +171,18 @@ void option_processing(Option& op, std::vector& uris, // finaly let's parse and store command-iine options. oparser.parse(op, cmdstream); } catch(OptionHandlerException& e) { - std::cerr << e.stackTrace() << "\n" - << "Usage:" << "\n" - << *oparser.findByName(e.getOptionName()) - << std::endl; - exit(error_code::UNKNOWN_ERROR); + std::cerr << e.stackTrace() << "\n"; + SharedHandle h = oparser.findByName(e.getOptionName()); + if(h) { + std::cerr << "Usage:" << "\n" + << *h + << std::endl; + } + exit(e.getErrorCode()); } catch(Exception& e) { std::cerr << e.stackTrace() << std::endl; showUsage(TAG_HELP, oparser); - exit(error_code::UNKNOWN_ERROR); + exit(e.getErrorCode()); } if( #ifdef ENABLE_XML_RPC diff --git a/src/util.cc b/src/util.cc index ce2fe522..6b3c6974 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1151,9 +1151,11 @@ void mkdirs(const std::string& dirpath) if(!dir.mkdirs()) { int errNum = errno; if(!dir.isDir()) { - throw DL_ABORT_EX - (fmt(EX_MAKE_DIR, dir.getPath().c_str(), - safeStrerror(errNum).c_str())); + throw DL_ABORT_EX3 + (errNum, + fmt(EX_MAKE_DIR, dir.getPath().c_str(), + safeStrerror(errNum).c_str()), + error_code::DIR_CREATE_ERROR); } } }