mirror of https://github.com/aria2/aria2
2010-06-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Made protected member variable private. Added accessor funcs. * src/AbstractCommand.cc * src/AbstractCommand.h * src/AbstractProxyRequestCommand.cc * src/AbstractProxyRequestCommand.h * src/AbstractProxyResponseCommand.cc * src/AbstractProxyResponseCommand.h * src/CreateRequestCommand.cc * src/DownloadCommand.cc * src/DownloadCommand.h * src/FtpDownloadCommand.cc * src/FtpDownloadCommand.h * src/FtpFinishDownloadCommand.cc * src/FtpInitiateConnectionCommand.cc * src/FtpNegotiationCommand.cc * src/FtpNegotiationCommand.h * src/FtpTunnelRequestCommand.cc * src/FtpTunnelResponseCommand.cc * src/HttpDownloadCommand.cc * src/HttpInitiateConnectionCommand.cc * src/HttpProxyRequestCommand.cc * src/HttpProxyResponseCommand.cc * src/HttpRequestCommand.cc * src/HttpResponseCommand.cc * src/HttpResponseCommand.h * src/HttpSkipResponseCommand.cc * src/InitiateConnectionCommand.ccpull/1/head
parent
9afc36152a
commit
970e7f95a6
30
ChangeLog
30
ChangeLog
|
@ -1,3 +1,33 @@
|
|||
2010-06-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Made protected member variable private. Added accessor funcs.
|
||||
* src/AbstractCommand.cc
|
||||
* src/AbstractCommand.h
|
||||
* src/AbstractProxyRequestCommand.cc
|
||||
* src/AbstractProxyRequestCommand.h
|
||||
* src/AbstractProxyResponseCommand.cc
|
||||
* src/AbstractProxyResponseCommand.h
|
||||
* src/CreateRequestCommand.cc
|
||||
* src/DownloadCommand.cc
|
||||
* src/DownloadCommand.h
|
||||
* src/FtpDownloadCommand.cc
|
||||
* src/FtpDownloadCommand.h
|
||||
* src/FtpFinishDownloadCommand.cc
|
||||
* src/FtpInitiateConnectionCommand.cc
|
||||
* src/FtpNegotiationCommand.cc
|
||||
* src/FtpNegotiationCommand.h
|
||||
* src/FtpTunnelRequestCommand.cc
|
||||
* src/FtpTunnelResponseCommand.cc
|
||||
* src/HttpDownloadCommand.cc
|
||||
* src/HttpInitiateConnectionCommand.cc
|
||||
* src/HttpProxyRequestCommand.cc
|
||||
* src/HttpProxyResponseCommand.cc
|
||||
* src/HttpRequestCommand.cc
|
||||
* src/HttpResponseCommand.cc
|
||||
* src/HttpResponseCommand.h
|
||||
* src/HttpSkipResponseCommand.cc
|
||||
* src/InitiateConnectionCommand.cc
|
||||
|
||||
2010-06-09 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Made protected member variables of Command private. Added accessor
|
||||
|
|
|
@ -77,15 +77,16 @@ AbstractCommand::AbstractCommand(cuid_t cuid,
|
|||
RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
const SocketHandle& s):
|
||||
Command(cuid), checkPoint(global::wallclock), _requestGroup(requestGroup),
|
||||
req(req), _fileEntry(fileEntry), e(e), socket(s),
|
||||
checkSocketIsReadable(false), checkSocketIsWritable(false),
|
||||
nameResolverCheck(false)
|
||||
Command(cuid), _checkPoint(global::wallclock),
|
||||
_timeout(requestGroup->getTimeout()),
|
||||
_requestGroup(requestGroup),
|
||||
_req(req), _fileEntry(fileEntry), _e(e), _socket(s),
|
||||
_checkSocketIsReadable(false), _checkSocketIsWritable(false),
|
||||
_nameResolverCheck(false)
|
||||
{
|
||||
if(!socket.isNull() && socket->isOpen()) {
|
||||
setReadCheckSocket(socket);
|
||||
if(!_socket.isNull() && _socket->isOpen()) {
|
||||
setReadCheckSocket(_socket);
|
||||
}
|
||||
timeout = _requestGroup->getTimeout();
|
||||
_requestGroup->increaseStreamConnection();
|
||||
_requestGroup->increaseNumCommand();
|
||||
}
|
||||
|
@ -113,19 +114,19 @@ bool AbstractCommand::execute() {
|
|||
if(_requestGroup->downloadFinished() || _requestGroup->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
if(!req.isNull() && req->removalRequested()) {
|
||||
if(!_req.isNull() && _req->removalRequested()) {
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug
|
||||
("CUID#%s - Discard original URI=%s because it is requested.",
|
||||
util::itos(getCuid()).c_str(), req->getUri().c_str());
|
||||
util::itos(getCuid()).c_str(), _req->getUri().c_str());
|
||||
}
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
// TODO it is not needed to check other PeerStats every time.
|
||||
// Find faster Request when no segment is available.
|
||||
if(!req.isNull() && _fileEntry->countPooledRequest() > 0 &&
|
||||
!_requestGroup->getPieceStorage()->hasMissingUnusedPiece()) {
|
||||
SharedHandle<Request> fasterRequest = _fileEntry->findFasterRequest(req);
|
||||
if(!_req.isNull() && _fileEntry->countPooledRequest() > 0 &&
|
||||
!getPieceStorage()->hasMissingUnusedPiece()) {
|
||||
SharedHandle<Request> fasterRequest = _fileEntry->findFasterRequest(_req);
|
||||
if(!fasterRequest.isNull()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info("CUID#%s - Use faster Request hostname=%s, port=%u",
|
||||
|
@ -134,29 +135,28 @@ bool AbstractCommand::execute() {
|
|||
fasterRequest->getPort());
|
||||
}
|
||||
// Cancel current Request object and use faster one.
|
||||
_fileEntry->removeRequest(req);
|
||||
_fileEntry->removeRequest(_req);
|
||||
Command* command =
|
||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand
|
||||
(getCuid(), fasterRequest, _fileEntry, _requestGroup, e);
|
||||
e->setNoWait(true);
|
||||
e->addCommand(command);
|
||||
(getCuid(), fasterRequest, _fileEntry, _requestGroup, _e);
|
||||
_e->setNoWait(true);
|
||||
_e->addCommand(command);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if((checkSocketIsReadable && readEventEnabled()) ||
|
||||
(checkSocketIsWritable && writeEventEnabled()) ||
|
||||
if((_checkSocketIsReadable && readEventEnabled()) ||
|
||||
(_checkSocketIsWritable && writeEventEnabled()) ||
|
||||
hupEventEnabled() ||
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
(nameResolverCheck && nameResolveFinished()) ||
|
||||
(_nameResolverCheck && nameResolveFinished()) ||
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
(!checkSocketIsReadable && !checkSocketIsWritable &&
|
||||
!nameResolverCheck)) {
|
||||
checkPoint = global::wallclock;
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
(!_checkSocketIsReadable && !_checkSocketIsWritable &&
|
||||
!_nameResolverCheck)) {
|
||||
_checkPoint = global::wallclock;
|
||||
if(!getPieceStorage().isNull()) {
|
||||
_segments.clear();
|
||||
_requestGroup->getSegmentMan()->getInFlightSegment
|
||||
(_segments, getCuid());
|
||||
if(!req.isNull() && _segments.empty()) {
|
||||
getSegmentMan()->getInFlightSegment(_segments, getCuid());
|
||||
if(!_req.isNull() && _segments.empty()) {
|
||||
// This command previously has assigned segments, but it is
|
||||
// canceled. So discard current request chain.
|
||||
if(getLogger()->debug()) {
|
||||
|
@ -166,11 +166,11 @@ bool AbstractCommand::execute() {
|
|||
}
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
if(req.isNull() || req->getMaxPipelinedRequest() == 1 ||
|
||||
if(_req.isNull() || _req->getMaxPipelinedRequest() == 1 ||
|
||||
_requestGroup->getDownloadContext()->getFileEntries().size() == 1) {
|
||||
if(_segments.empty()) {
|
||||
SharedHandle<Segment> segment =
|
||||
_requestGroup->getSegmentMan()->getSegment(getCuid());
|
||||
getSegmentMan()->getSegment(getCuid());
|
||||
if(!segment.isNull()) {
|
||||
_segments.push_back(segment);
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ bool AbstractCommand::execute() {
|
|||
}
|
||||
// When all segments are ignored in SegmentMan, there are
|
||||
// no URIs available, so don't retry.
|
||||
if(_requestGroup->getSegmentMan()->allSegmentsIgnored()) {
|
||||
if(getSegmentMan()->allSegmentsIgnored()) {
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug("All segments are ignored.");
|
||||
}
|
||||
|
@ -193,9 +193,9 @@ bool AbstractCommand::execute() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
size_t maxSegments = req->getMaxPipelinedRequest();
|
||||
size_t maxSegments = _req->getMaxPipelinedRequest();
|
||||
if(_segments.size() < maxSegments) {
|
||||
_requestGroup->getSegmentMan()->getSegment
|
||||
getSegmentMan()->getSegment
|
||||
(_segments, getCuid(), _fileEntry, maxSegments);
|
||||
}
|
||||
if(_segments.empty()) {
|
||||
|
@ -207,23 +207,23 @@ bool AbstractCommand::execute() {
|
|||
} else if(errorEventEnabled()) {
|
||||
throw DL_RETRY_EX
|
||||
(StringFormat(MSG_NETWORK_PROBLEM,
|
||||
socket->getSocketError().c_str()).str());
|
||||
_socket->getSocketError().c_str()).str());
|
||||
} else {
|
||||
if(checkPoint.difference(global::wallclock) >= timeout) {
|
||||
if(_checkPoint.difference(global::wallclock) >= _timeout) {
|
||||
// timeout triggers ServerStat error state.
|
||||
|
||||
SharedHandle<ServerStat> ss =
|
||||
e->getRequestGroupMan()->getOrCreateServerStat(req->getHost(),
|
||||
req->getProtocol());
|
||||
_e->getRequestGroupMan()->getOrCreateServerStat(_req->getHost(),
|
||||
_req->getProtocol());
|
||||
ss->setError();
|
||||
|
||||
throw DL_RETRY_EX2(EX_TIME_OUT, downloadresultcode::TIME_OUT);
|
||||
}
|
||||
e->addCommand(this);
|
||||
_e->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
} catch(DlAbortEx& err) {
|
||||
if(req.isNull()) {
|
||||
if(_req.isNull()) {
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug(EX_EXCEPTION_CAUGHT, err);
|
||||
}
|
||||
|
@ -231,10 +231,10 @@ bool AbstractCommand::execute() {
|
|||
getLogger()->error
|
||||
(MSG_DOWNLOAD_ABORTED,
|
||||
DL_ABORT_EX2(StringFormat
|
||||
("URI=%s", req->getCurrentUri().c_str()).str(),err),
|
||||
util::itos(getCuid()).c_str(), req->getUri().c_str());
|
||||
_fileEntry->addURIResult(req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(req->getUri(), err.getCode());
|
||||
("URI=%s", _req->getCurrentUri().c_str()).str(),err),
|
||||
util::itos(getCuid()).c_str(), _req->getUri().c_str());
|
||||
_fileEntry->addURIResult(_req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(_req->getUri(), err.getCode());
|
||||
if(err.getCode() == downloadresultcode::CANNOT_RESUME) {
|
||||
_requestGroup->increaseResumeFailureCount();
|
||||
}
|
||||
|
@ -243,29 +243,29 @@ bool AbstractCommand::execute() {
|
|||
tryReserved();
|
||||
return true;
|
||||
} catch(DlRetryEx& err) {
|
||||
assert(!req.isNull());
|
||||
assert(!_req.isNull());
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info
|
||||
(MSG_RESTARTING_DOWNLOAD,
|
||||
DL_RETRY_EX2(StringFormat
|
||||
("URI=%s", req->getCurrentUri().c_str()).str(),
|
||||
("URI=%s", _req->getCurrentUri().c_str()).str(),
|
||||
err),
|
||||
util::itos(getCuid()).c_str(), req->getUri().c_str());
|
||||
util::itos(getCuid()).c_str(), _req->getUri().c_str());
|
||||
}
|
||||
req->addTryCount();
|
||||
req->resetRedirectCount();
|
||||
_req->addTryCount();
|
||||
_req->resetRedirectCount();
|
||||
const unsigned int maxTries = getOption()->getAsInt(PREF_MAX_TRIES);
|
||||
bool isAbort = maxTries != 0 && req->getTryCount() >= maxTries;
|
||||
bool isAbort = maxTries != 0 && _req->getTryCount() >= maxTries;
|
||||
if(isAbort) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(MSG_MAX_TRY,
|
||||
util::itos(getCuid()).c_str(), req->getTryCount());
|
||||
util::itos(getCuid()).c_str(), _req->getTryCount());
|
||||
}
|
||||
getLogger()->error(MSG_DOWNLOAD_ABORTED, err,
|
||||
util::itos(getCuid()).c_str(),
|
||||
req->getUri().c_str());
|
||||
_fileEntry->addURIResult(req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(req->getUri(), err.getCode());
|
||||
_req->getUri().c_str());
|
||||
_fileEntry->addURIResult(_req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(_req->getUri(), err.getCode());
|
||||
if(err.getCode() == downloadresultcode::CANNOT_RESUME) {
|
||||
_requestGroup->increaseResumeFailureCount();
|
||||
}
|
||||
|
@ -277,9 +277,9 @@ bool AbstractCommand::execute() {
|
|||
}
|
||||
} catch(DownloadFailureException& err) {
|
||||
getLogger()->error(EX_EXCEPTION_CAUGHT, err);
|
||||
if(!req.isNull()) {
|
||||
_fileEntry->addURIResult(req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(req->getUri(), err.getCode());
|
||||
if(!_req.isNull()) {
|
||||
_fileEntry->addURIResult(_req->getUri(), err.getCode());
|
||||
_requestGroup->setLastUriResult(_req->getUri(), err.getCode());
|
||||
}
|
||||
_requestGroup->setHaltRequested(true);
|
||||
return true;
|
||||
|
@ -308,59 +308,58 @@ void AbstractCommand::tryReserved() {
|
|||
util::itos(getCuid()).c_str());
|
||||
}
|
||||
std::vector<Command*> commands;
|
||||
_requestGroup->createNextCommand(commands, e, 1);
|
||||
e->setNoWait(true);
|
||||
e->addCommand(commands);
|
||||
_requestGroup->createNextCommand(commands, _e, 1);
|
||||
_e->setNoWait(true);
|
||||
_e->addCommand(commands);
|
||||
}
|
||||
|
||||
bool AbstractCommand::prepareForRetry(time_t wait) {
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(getCuid());
|
||||
if(!getPieceStorage().isNull()) {
|
||||
getSegmentMan()->cancelSegment(getCuid());
|
||||
}
|
||||
if(!req.isNull()) {
|
||||
_fileEntry->poolRequest(req);
|
||||
if(!_req.isNull()) {
|
||||
_fileEntry->poolRequest(_req);
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug("CUID#%s - Pooling request URI=%s",
|
||||
util::itos(getCuid()).c_str(), req->getUri().c_str());
|
||||
util::itos(getCuid()).c_str(), _req->getUri().c_str());
|
||||
}
|
||||
if(!_requestGroup->getSegmentMan().isNull()) {
|
||||
_requestGroup->getSegmentMan()->recognizeSegmentFor(_fileEntry);
|
||||
if(!getSegmentMan().isNull()) {
|
||||
getSegmentMan()->recognizeSegmentFor(_fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
Command* command = new CreateRequestCommand(getCuid(), _requestGroup, e);
|
||||
Command* command = new CreateRequestCommand(getCuid(), _requestGroup, _e);
|
||||
if(wait == 0) {
|
||||
e->setNoWait(true);
|
||||
e->addCommand(command);
|
||||
_e->setNoWait(true);
|
||||
_e->addCommand(command);
|
||||
} else {
|
||||
SleepCommand* scom = new SleepCommand(getCuid(), e, _requestGroup,
|
||||
SleepCommand* scom = new SleepCommand(getCuid(), _e, _requestGroup,
|
||||
command, wait);
|
||||
e->addCommand(scom);
|
||||
_e->addCommand(scom);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AbstractCommand::onAbort() {
|
||||
if(!req.isNull()) {
|
||||
if(!_req.isNull()) {
|
||||
// TODO This might be a problem if the failure is caused by proxy.
|
||||
e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(req->getHost(), req->getProtocol())->setError();
|
||||
_fileEntry->removeIdenticalURI(req->getUri());
|
||||
_fileEntry->removeRequest(req);
|
||||
_e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(_req->getHost(), _req->getProtocol())->setError();
|
||||
_fileEntry->removeIdenticalURI(_req->getUri());
|
||||
_fileEntry->removeRequest(_req);
|
||||
}
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug("CUID#%s - Aborting download",
|
||||
util::itos(getCuid()).c_str());
|
||||
}
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
SharedHandle<SegmentMan> segmentMan = _requestGroup->getSegmentMan();
|
||||
segmentMan->cancelSegment(getCuid());
|
||||
if(!getPieceStorage().isNull()) {
|
||||
getSegmentMan()->cancelSegment(getCuid());
|
||||
// Don't do following process if BitTorrent is involved or files
|
||||
// in DownloadContext is more than 1. The latter condition is
|
||||
// limitation of current implementation.
|
||||
if(!getOption()->getAsBool(PREF_ALWAYS_RESUME) &&
|
||||
!_fileEntry.isNull() &&
|
||||
segmentMan->calculateSessionDownloadLength() == 0 &&
|
||||
getSegmentMan()->calculateSessionDownloadLength() == 0 &&
|
||||
!_requestGroup->p2pInvolved() &&
|
||||
_requestGroup->getDownloadContext()->getFileEntries().size() == 1) {
|
||||
const int maxTries = getOption()->getAsInt(PREF_MAX_RESUME_FAILURE_TRIES);
|
||||
|
@ -383,9 +382,9 @@ void AbstractCommand::onAbort() {
|
|||
std::deque<URIResult> res;
|
||||
_fileEntry->extractURIResult(res, downloadresultcode::CANNOT_RESUME);
|
||||
if(!res.empty()) {
|
||||
segmentMan->cancelAllSegments();
|
||||
segmentMan->eraseSegmentWrittenLengthMemo();
|
||||
_requestGroup->getPieceStorage()->markPiecesDone(0);
|
||||
getSegmentMan()->cancelAllSegments();
|
||||
getSegmentMan()->eraseSegmentWrittenLengthMemo();
|
||||
getPieceStorage()->markPiecesDone(0);
|
||||
std::vector<std::string> uris;
|
||||
uris.reserve(res.size());
|
||||
std::transform(res.begin(), res.end(), std::back_inserter(uris),
|
||||
|
@ -396,7 +395,7 @@ void AbstractCommand::onAbort() {
|
|||
static_cast<unsigned long int>(uris.size()));
|
||||
}
|
||||
_fileEntry->addUris(uris.begin(), uris.end());
|
||||
segmentMan->recognizeSegmentFor(_fileEntry);
|
||||
getSegmentMan()->recognizeSegmentFor(_fileEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -404,10 +403,10 @@ void AbstractCommand::onAbort() {
|
|||
}
|
||||
|
||||
void AbstractCommand::disableReadCheckSocket() {
|
||||
if(checkSocketIsReadable) {
|
||||
e->deleteSocketForReadCheck(readCheckTarget, this);
|
||||
checkSocketIsReadable = false;
|
||||
readCheckTarget = SocketHandle();
|
||||
if(_checkSocketIsReadable) {
|
||||
_e->deleteSocketForReadCheck(_readCheckTarget, this);
|
||||
_checkSocketIsReadable = false;
|
||||
_readCheckTarget.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,16 +414,16 @@ void AbstractCommand::setReadCheckSocket(const SocketHandle& socket) {
|
|||
if(!socket->isOpen()) {
|
||||
disableReadCheckSocket();
|
||||
} else {
|
||||
if(checkSocketIsReadable) {
|
||||
if(readCheckTarget != socket) {
|
||||
e->deleteSocketForReadCheck(readCheckTarget, this);
|
||||
e->addSocketForReadCheck(socket, this);
|
||||
readCheckTarget = socket;
|
||||
if(_checkSocketIsReadable) {
|
||||
if(_readCheckTarget != socket) {
|
||||
_e->deleteSocketForReadCheck(_readCheckTarget, this);
|
||||
_e->addSocketForReadCheck(socket, this);
|
||||
_readCheckTarget = socket;
|
||||
}
|
||||
} else {
|
||||
e->addSocketForReadCheck(socket, this);
|
||||
checkSocketIsReadable = true;
|
||||
readCheckTarget = socket;
|
||||
_e->addSocketForReadCheck(socket, this);
|
||||
_checkSocketIsReadable = true;
|
||||
_readCheckTarget = socket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -440,10 +439,10 @@ void AbstractCommand::setReadCheckSocketIf
|
|||
}
|
||||
|
||||
void AbstractCommand::disableWriteCheckSocket() {
|
||||
if(checkSocketIsWritable) {
|
||||
e->deleteSocketForWriteCheck(writeCheckTarget, this);
|
||||
checkSocketIsWritable = false;
|
||||
writeCheckTarget = SocketHandle();
|
||||
if(_checkSocketIsWritable) {
|
||||
_e->deleteSocketForWriteCheck(_writeCheckTarget, this);
|
||||
_checkSocketIsWritable = false;
|
||||
_writeCheckTarget.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,16 +450,16 @@ void AbstractCommand::setWriteCheckSocket(const SocketHandle& socket) {
|
|||
if(!socket->isOpen()) {
|
||||
disableWriteCheckSocket();
|
||||
} else {
|
||||
if(checkSocketIsWritable) {
|
||||
if(writeCheckTarget != socket) {
|
||||
e->deleteSocketForWriteCheck(writeCheckTarget, this);
|
||||
e->addSocketForWriteCheck(socket, this);
|
||||
writeCheckTarget = socket;
|
||||
if(_checkSocketIsWritable) {
|
||||
if(_writeCheckTarget != socket) {
|
||||
_e->deleteSocketForWriteCheck(_writeCheckTarget, this);
|
||||
_e->addSocketForWriteCheck(socket, this);
|
||||
_writeCheckTarget = socket;
|
||||
}
|
||||
} else {
|
||||
e->addSocketForWriteCheck(socket, this);
|
||||
checkSocketIsWritable = true;
|
||||
writeCheckTarget = socket;
|
||||
_e->addSocketForWriteCheck(socket, this);
|
||||
_checkSocketIsWritable = true;
|
||||
_writeCheckTarget = socket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -570,17 +569,17 @@ static bool inNoProxy(const SharedHandle<Request>& req,
|
|||
|
||||
bool AbstractCommand::isProxyDefined() const
|
||||
{
|
||||
return isProxyRequest(req->getProtocol(), getOption()) &&
|
||||
!inNoProxy(req, getOption()->get(PREF_NO_PROXY));
|
||||
return isProxyRequest(_req->getProtocol(), getOption()) &&
|
||||
!inNoProxy(_req, getOption()->get(PREF_NO_PROXY));
|
||||
}
|
||||
|
||||
SharedHandle<Request> AbstractCommand::createProxyRequest() const
|
||||
{
|
||||
SharedHandle<Request> proxyRequest;
|
||||
if(inNoProxy(req, getOption()->get(PREF_NO_PROXY))) {
|
||||
if(inNoProxy(_req, getOption()->get(PREF_NO_PROXY))) {
|
||||
return proxyRequest;
|
||||
}
|
||||
std::string proxy = getProxyUri(req->getProtocol(), getOption());
|
||||
std::string proxy = getProxyUri(_req->getProtocol(), getOption());
|
||||
if(!proxy.empty()) {
|
||||
proxyRequest.reset(new Request());
|
||||
if(proxyRequest->setUri(proxy)) {
|
||||
|
@ -625,9 +624,9 @@ bool AbstractCommand::asyncResolveHostname()
|
|||
return true;
|
||||
case AsyncNameResolver::STATUS_ERROR:
|
||||
disableNameResolverCheck(_asyncNameResolver);
|
||||
if(!isProxyRequest(req->getProtocol(), getOption())) {
|
||||
e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(req->getHost(), req->getProtocol())->setError();
|
||||
if(!isProxyRequest(_req->getProtocol(), getOption())) {
|
||||
_e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(_req->getHost(), _req->getProtocol())->setError();
|
||||
}
|
||||
throw DL_ABORT_EX
|
||||
(StringFormat(MSG_NAME_RESOLUTION_FAILED,
|
||||
|
@ -647,16 +646,16 @@ const std::vector<std::string>& AbstractCommand::getResolvedAddresses()
|
|||
void AbstractCommand::setNameResolverCheck
|
||||
(const SharedHandle<AsyncNameResolver>& resolver) {
|
||||
if(!resolver.isNull()) {
|
||||
nameResolverCheck = true;
|
||||
e->addNameResolverCheck(resolver, this);
|
||||
_nameResolverCheck = true;
|
||||
_e->addNameResolverCheck(resolver, this);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractCommand::disableNameResolverCheck
|
||||
(const SharedHandle<AsyncNameResolver>& resolver) {
|
||||
if(!resolver.isNull()) {
|
||||
nameResolverCheck = false;
|
||||
e->deleteNameResolverCheck(resolver, this);
|
||||
_nameResolverCheck = false;
|
||||
_e->deleteNameResolverCheck(resolver, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -670,7 +669,7 @@ bool AbstractCommand::nameResolveFinished() const {
|
|||
std::string AbstractCommand::resolveHostname
|
||||
(std::vector<std::string>& addrs, const std::string& hostname, uint16_t port)
|
||||
{
|
||||
e->findAllCachedIPAddresses(std::back_inserter(addrs), hostname, port);
|
||||
_e->findAllCachedIPAddresses(std::back_inserter(addrs), hostname, port);
|
||||
std::string ipaddr;
|
||||
if(addrs.empty()) {
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
|
@ -688,7 +687,7 @@ std::string AbstractCommand::resolveHostname
|
|||
{
|
||||
NameResolver res;
|
||||
res.setSocktype(SOCK_STREAM);
|
||||
if(e->getOption()->getAsBool(PREF_DISABLE_IPV6)) {
|
||||
if(_e->getOption()->getAsBool(PREF_DISABLE_IPV6)) {
|
||||
res.setFamily(AF_INET);
|
||||
}
|
||||
res.resolve(addrs, hostname);
|
||||
|
@ -701,9 +700,9 @@ std::string AbstractCommand::resolveHostname
|
|||
}
|
||||
for(std::vector<std::string>::const_iterator i = addrs.begin(),
|
||||
eoi = addrs.end(); i != eoi; ++i) {
|
||||
e->cacheIPAddress(hostname, *i, port);
|
||||
_e->cacheIPAddress(hostname, *i, port);
|
||||
}
|
||||
ipaddr = e->findCachedIPAddress(hostname, port);
|
||||
ipaddr = _e->findCachedIPAddress(hostname, port);
|
||||
} else {
|
||||
ipaddr = addrs.front();
|
||||
if(getLogger()->info()) {
|
||||
|
@ -725,13 +724,13 @@ void AbstractCommand::prepareForNextAction(Command* nextCommand)
|
|||
|
||||
std::vector<Command*> commands;
|
||||
try {
|
||||
_requestGroup->processCheckIntegrityEntry(commands, entry, e);
|
||||
_requestGroup->processCheckIntegrityEntry(commands, entry, _e);
|
||||
} catch(RecoverableException& e) {
|
||||
std::for_each(commands.begin(), commands.end(), Deleter());
|
||||
throw;
|
||||
}
|
||||
e->addCommand(commands);
|
||||
e->setNoWait(true);
|
||||
_e->addCommand(commands);
|
||||
_e->setNoWait(true);
|
||||
}
|
||||
|
||||
bool AbstractCommand::checkIfConnectionEstablished
|
||||
|
@ -744,8 +743,8 @@ bool AbstractCommand::checkIfConnectionEstablished
|
|||
std::string error = socket->getSocketError();
|
||||
if(!error.empty()) {
|
||||
// See also InitiateConnectionCommand::executeInternal()
|
||||
e->markBadIPAddress(connectedHostname, connectedAddr, connectedPort);
|
||||
if(!e->findCachedIPAddress(connectedHostname, connectedPort).empty()) {
|
||||
_e->markBadIPAddress(connectedHostname, connectedAddr, connectedPort);
|
||||
if(!_e->findCachedIPAddress(connectedHostname, connectedPort).empty()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(MSG_CONNECT_FAILED_AND_RETRY,
|
||||
util::itos(getCuid()).c_str(),
|
||||
|
@ -753,17 +752,17 @@ bool AbstractCommand::checkIfConnectionEstablished
|
|||
}
|
||||
Command* command =
|
||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, e);
|
||||
e->setNoWait(true);
|
||||
e->addCommand(command);
|
||||
(getCuid(), _req, _fileEntry, _requestGroup, _e);
|
||||
_e->setNoWait(true);
|
||||
_e->addCommand(command);
|
||||
return false;
|
||||
}
|
||||
e->removeCachedIPAddress(connectedHostname, connectedPort);
|
||||
_e->removeCachedIPAddress(connectedHostname, connectedPort);
|
||||
// Don't set error if proxy server is used and its method is GET.
|
||||
if(resolveProxyMethod(req->getProtocol()) != V_GET ||
|
||||
!isProxyRequest(req->getProtocol(), getOption())) {
|
||||
e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(req->getHost(), req->getProtocol())->setError();
|
||||
if(resolveProxyMethod(_req->getProtocol()) != V_GET ||
|
||||
!isProxyRequest(_req->getProtocol(), getOption())) {
|
||||
_e->getRequestGroupMan()->getOrCreateServerStat
|
||||
(_req->getHost(), _req->getProtocol())->setError();
|
||||
}
|
||||
throw DL_RETRY_EX
|
||||
(StringFormat(MSG_ESTABLISHING_CONNECTION_FAILED, error.c_str()).str());
|
||||
|
@ -788,4 +787,9 @@ const SharedHandle<Option>& AbstractCommand::getOption() const
|
|||
return _requestGroup->getOption();
|
||||
}
|
||||
|
||||
void AbstractCommand::createSocket()
|
||||
{
|
||||
_socket.reset(new SocketCore());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -55,19 +55,83 @@ class AsyncNameResolver;
|
|||
|
||||
class AbstractCommand : public Command {
|
||||
private:
|
||||
Timer checkPoint;
|
||||
time_t timeout;
|
||||
protected:
|
||||
Timer _checkPoint;
|
||||
time_t _timeout;
|
||||
|
||||
RequestGroup* _requestGroup;
|
||||
SharedHandle<Request> req;
|
||||
SharedHandle<Request> _req;
|
||||
SharedHandle<FileEntry> _fileEntry;
|
||||
DownloadEngine* e;
|
||||
SharedHandle<SocketCore> socket;
|
||||
DownloadEngine* _e;
|
||||
SharedHandle<SocketCore> _socket;
|
||||
std::vector<SharedHandle<Segment> > _segments;
|
||||
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
SharedHandle<AsyncNameResolver> _asyncNameResolver;
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
|
||||
bool _checkSocketIsReadable;
|
||||
bool _checkSocketIsWritable;
|
||||
SharedHandle<SocketCore> _readCheckTarget;
|
||||
SharedHandle<SocketCore> _writeCheckTarget;
|
||||
bool _nameResolverCheck;
|
||||
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
void setNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
|
||||
|
||||
void disableNameResolverCheck
|
||||
(const SharedHandle<AsyncNameResolver>& resolver);
|
||||
|
||||
bool nameResolveFinished() const;
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
protected:
|
||||
RequestGroup* getRequestGroup() const
|
||||
{
|
||||
return _requestGroup;
|
||||
}
|
||||
|
||||
const SharedHandle<Request>& getRequest() const
|
||||
{
|
||||
return _req;
|
||||
}
|
||||
|
||||
void setRequest(const SharedHandle<Request>& request)
|
||||
{
|
||||
_req = request;
|
||||
}
|
||||
|
||||
const SharedHandle<FileEntry>& getFileEntry() const
|
||||
{
|
||||
return _fileEntry;
|
||||
}
|
||||
|
||||
void setFileEntry(const SharedHandle<FileEntry>& fileEntry)
|
||||
{
|
||||
_fileEntry = fileEntry;
|
||||
}
|
||||
|
||||
DownloadEngine* getDownloadEngine() const
|
||||
{
|
||||
return _e;
|
||||
}
|
||||
|
||||
const SharedHandle<SocketCore>& getSocket() const
|
||||
{
|
||||
return _socket;
|
||||
}
|
||||
|
||||
void setSocket(const SharedHandle<SocketCore>& s)
|
||||
{
|
||||
_socket = s;
|
||||
}
|
||||
|
||||
void createSocket();
|
||||
|
||||
const std::vector<SharedHandle<Segment> >& getSegments() const
|
||||
{
|
||||
return _segments;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
bool isAsyncNameResolverInitialized() const;
|
||||
|
||||
void initAsyncNameResolver(const std::string& hostname);
|
||||
|
@ -106,7 +170,7 @@ protected:
|
|||
*/
|
||||
void setWriteCheckSocketIf(const SharedHandle<SocketCore>& socket, bool pred);
|
||||
|
||||
void setTimeout(time_t timeout) { this->timeout = timeout; }
|
||||
void setTimeout(time_t timeout) { _timeout = timeout; }
|
||||
|
||||
void prepareForNextAction(Command* nextCommand = 0);
|
||||
|
||||
|
@ -143,20 +207,16 @@ protected:
|
|||
{
|
||||
return _requestGroup->getDownloadContext();
|
||||
}
|
||||
private:
|
||||
bool checkSocketIsReadable;
|
||||
bool checkSocketIsWritable;
|
||||
SharedHandle<SocketCore> readCheckTarget;
|
||||
SharedHandle<SocketCore> writeCheckTarget;
|
||||
bool nameResolverCheck;
|
||||
|
||||
#ifdef ENABLE_ASYNC_DNS
|
||||
const SharedHandle<SegmentMan>& getSegmentMan() const
|
||||
{
|
||||
return _requestGroup->getSegmentMan();
|
||||
}
|
||||
|
||||
void setNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
|
||||
|
||||
void disableNameResolverCheck(const SharedHandle<AsyncNameResolver>& resolver);
|
||||
bool nameResolveFinished() const;
|
||||
#endif // ENABLE_ASYNC_DNS
|
||||
const SharedHandle<PieceStorage>& getPieceStorage() const
|
||||
{
|
||||
return _requestGroup->getPieceStorage();
|
||||
}
|
||||
public:
|
||||
AbstractCommand(cuid_t cuid, const SharedHandle<Request>& req,
|
||||
const SharedHandle<FileEntry>& fileEntry,
|
||||
|
|
|
@ -64,37 +64,37 @@ AbstractProxyRequestCommand::AbstractProxyRequestCommand
|
|||
:
|
||||
AbstractCommand(cuid, req, fileEntry, requestGroup, e, s),
|
||||
_proxyRequest(proxyRequest),
|
||||
httpConnection(new HttpConnection(cuid, s, getOption().get()))
|
||||
_httpConnection(new HttpConnection(cuid, s, getOption().get()))
|
||||
{
|
||||
setTimeout(getOption()->getAsInt(PREF_CONNECT_TIMEOUT));
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
|
||||
AbstractProxyRequestCommand::~AbstractProxyRequestCommand() {}
|
||||
|
||||
bool AbstractProxyRequestCommand::executeInternal() {
|
||||
//socket->setBlockingMode();
|
||||
if(httpConnection->sendBufferIsEmpty()) {
|
||||
if(_httpConnection->sendBufferIsEmpty()) {
|
||||
if(!checkIfConnectionEstablished
|
||||
(socket, _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
(getSocket(), _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
return true;
|
||||
}
|
||||
SharedHandle<HttpRequest> httpRequest(new HttpRequest());
|
||||
httpRequest->setUserAgent(getOption()->get(PREF_USER_AGENT));
|
||||
httpRequest->setRequest(req);
|
||||
httpRequest->setRequest(getRequest());
|
||||
httpRequest->setProxyRequest(_proxyRequest);
|
||||
|
||||
httpConnection->sendProxyRequest(httpRequest);
|
||||
_httpConnection->sendProxyRequest(httpRequest);
|
||||
} else {
|
||||
httpConnection->sendPendingData();
|
||||
_httpConnection->sendPendingData();
|
||||
}
|
||||
if(httpConnection->sendBufferIsEmpty()) {
|
||||
e->addCommand(getNextCommand());
|
||||
if(_httpConnection->sendBufferIsEmpty()) {
|
||||
getDownloadEngine()->addCommand(getNextCommand());
|
||||
return true;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
e->addCommand(this);
|
||||
setWriteCheckSocket(getSocket());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,16 +43,21 @@ class HttpConnection;
|
|||
class SocketCore;
|
||||
|
||||
class AbstractProxyRequestCommand : public AbstractCommand {
|
||||
protected:
|
||||
private:
|
||||
SharedHandle<Request> _proxyRequest;
|
||||
|
||||
SharedHandle<HttpConnection> httpConnection;
|
||||
SharedHandle<HttpConnection> _httpConnection;
|
||||
|
||||
std::string _connectedHostname;
|
||||
std::string _connectedAddr;
|
||||
uint16_t _connectedPort;
|
||||
|
||||
protected:
|
||||
virtual bool executeInternal();
|
||||
|
||||
const SharedHandle<HttpConnection>& getHttpConnection() const
|
||||
{
|
||||
return _httpConnection;
|
||||
}
|
||||
public:
|
||||
AbstractProxyRequestCommand(cuid_t cuid,
|
||||
const SharedHandle<Request>& req,
|
||||
|
|
|
@ -62,21 +62,21 @@ AbstractProxyResponseCommand::AbstractProxyResponseCommand
|
|||
DownloadEngine* e,
|
||||
const SocketHandle& s)
|
||||
:AbstractCommand(cuid, req, fileEntry, requestGroup, e, s),
|
||||
httpConnection(httpConnection) {}
|
||||
_httpConnection(httpConnection) {}
|
||||
|
||||
AbstractProxyResponseCommand::~AbstractProxyResponseCommand() {}
|
||||
|
||||
bool AbstractProxyResponseCommand::executeInternal() {
|
||||
SharedHandle<HttpResponse> httpResponse = httpConnection->receiveResponse();
|
||||
SharedHandle<HttpResponse> httpResponse = _httpConnection->receiveResponse();
|
||||
if(httpResponse.isNull()) {
|
||||
// the server has not responded our request yet.
|
||||
e->addCommand(this);
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
if(httpResponse->getResponseStatus() != HttpHeader::S200) {
|
||||
throw DL_RETRY_EX(EX_PROXY_CONNECTION_FAILED);
|
||||
}
|
||||
e->addCommand(getNextCommand());
|
||||
getDownloadEngine()->addCommand(getNextCommand());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,10 +43,15 @@ class HttpConnection;
|
|||
class SocketCore;
|
||||
|
||||
class AbstractProxyResponseCommand : public AbstractCommand {
|
||||
private:
|
||||
SharedHandle<HttpConnection> _httpConnection;
|
||||
protected:
|
||||
SharedHandle<HttpConnection> httpConnection;
|
||||
|
||||
virtual bool executeInternal();
|
||||
|
||||
const SharedHandle<HttpConnection>& getHttpConnection() const
|
||||
{
|
||||
return _httpConnection;
|
||||
}
|
||||
public:
|
||||
AbstractProxyResponseCommand
|
||||
(cuid_t cuid,
|
||||
|
|
|
@ -67,39 +67,41 @@ CreateRequestCommand::CreateRequestCommand(cuid_t cuid,
|
|||
|
||||
bool CreateRequestCommand::executeInternal()
|
||||
{
|
||||
if(_segments.empty()) {
|
||||
_fileEntry = _requestGroup->getDownloadContext()->findFileEntryByOffset(0);
|
||||
if(getSegments().empty()) {
|
||||
setFileEntry(getDownloadContext()->findFileEntryByOffset(0));
|
||||
} else {
|
||||
// We assume all segments belongs to same file.
|
||||
_fileEntry = _requestGroup->getDownloadContext()->findFileEntryByOffset
|
||||
(_segments.front()->getPositionToWrite());
|
||||
setFileEntry(getDownloadContext()->findFileEntryByOffset
|
||||
(getSegments().front()->getPositionToWrite()));
|
||||
}
|
||||
if(_fileEntry->getRemainingUris().empty() &&
|
||||
if(getFileEntry()->getRemainingUris().empty() &&
|
||||
getOption()->getAsBool(PREF_REUSE_URI) &&
|
||||
_fileEntry->countPooledRequest() == 0) {
|
||||
_fileEntry->reuseUri(_requestGroup->getNumConcurrentCommand());
|
||||
getFileEntry()->countPooledRequest() == 0) {
|
||||
getFileEntry()->reuseUri(getRequestGroup()->getNumConcurrentCommand());
|
||||
}
|
||||
req = _fileEntry->getRequest(_requestGroup->getURISelector(),
|
||||
getOption()->get(PREF_REFERER),
|
||||
// Don't use HEAD request when file
|
||||
// size is known.
|
||||
// Use HEAD for dry-run mode.
|
||||
(_fileEntry->getLength() == 0 &&
|
||||
getOption()->getAsBool(PREF_USE_HEAD)) ||
|
||||
getOption()->getAsBool(PREF_DRY_RUN)?
|
||||
Request::METHOD_HEAD:Request::METHOD_GET);
|
||||
if(req.isNull()) {
|
||||
if(!_requestGroup->getSegmentMan().isNull()) {
|
||||
_requestGroup->getSegmentMan()->ignoreSegmentFor(_fileEntry);
|
||||
setRequest
|
||||
(getFileEntry()->getRequest(getRequestGroup()->getURISelector(),
|
||||
getOption()->get(PREF_REFERER),
|
||||
// Don't use HEAD request when file
|
||||
// size is known.
|
||||
// Use HEAD for dry-run mode.
|
||||
(getFileEntry()->getLength() == 0 &&
|
||||
getOption()->getAsBool(PREF_USE_HEAD)) ||
|
||||
getOption()->getAsBool(PREF_DRY_RUN)?
|
||||
Request::METHOD_HEAD:Request::METHOD_GET));
|
||||
if(getRequest().isNull()) {
|
||||
if(!getSegmentMan().isNull()) {
|
||||
getSegmentMan()->ignoreSegmentFor(getFileEntry());
|
||||
}
|
||||
throw DL_ABORT_EX("No URI available.");
|
||||
}
|
||||
|
||||
Command* command =
|
||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, e);
|
||||
e->setNoWait(true);
|
||||
e->addCommand(command);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
getDownloadEngine());
|
||||
getDownloadEngine()->setNoWait(true);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -113,16 +115,16 @@ bool CreateRequestCommand::prepareForRetry(time_t wait)
|
|||
// called repeatedly. This means that newly created
|
||||
// CreateRequestCommand is deleted one second later: This is not
|
||||
// efficient. For this reason, reuse current CreateRequestCommand.
|
||||
if(!_requestGroup->getPieceStorage().isNull()) {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(getCuid());
|
||||
if(!getPieceStorage().isNull()) {
|
||||
getSegmentMan()->cancelSegment(getCuid());
|
||||
}
|
||||
if(getLogger()->debug()) {
|
||||
getLogger()->debug("CUID#%s - Reusing CreateRequestCommand",
|
||||
util::itos(getCuid()).c_str());
|
||||
}
|
||||
SleepCommand* scom = new SleepCommand
|
||||
(getCuid(), e, _requestGroup, this, wait);
|
||||
e->addCommand(scom);
|
||||
(getCuid(), getDownloadEngine(), getRequestGroup(), this, wait);
|
||||
getDownloadEngine()->addCommand(scom);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,9 @@ DownloadCommand::DownloadCommand(cuid_t cuid,
|
|||
DownloadEngine* e,
|
||||
const SocketHandle& s):
|
||||
AbstractCommand(cuid, req, fileEntry, requestGroup, e, s),
|
||||
_buf(new unsigned char[BUFSIZE])
|
||||
_buf(new unsigned char[BUFSIZE]),
|
||||
_startupIdleTime(10),
|
||||
_lowestDownloadSpeedLimit(0)
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
, _pieceHashValidationEnabled(false)
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
|
@ -84,8 +86,7 @@ DownloadCommand::DownloadCommand(cuid_t cuid,
|
|||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
{
|
||||
if(getOption()->getAsBool(PREF_REALTIME_CHUNK_CHECKSUM)) {
|
||||
std::string algo =
|
||||
_requestGroup->getDownloadContext()->getPieceHashAlgo();
|
||||
const std::string& algo = getDownloadContext()->getPieceHashAlgo();
|
||||
if(MessageDigestContext::supports(algo)) {
|
||||
_messageDigestContext.reset(new MessageDigestContext());
|
||||
_messageDigestContext->trySetAlgo(algo);
|
||||
|
@ -97,46 +98,47 @@ DownloadCommand::DownloadCommand(cuid_t cuid,
|
|||
}
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
|
||||
peerStat = req->initPeerStat();
|
||||
peerStat->downloadStart();
|
||||
_requestGroup->getSegmentMan()->registerPeerStat(peerStat);
|
||||
_peerStat = req->initPeerStat();
|
||||
_peerStat->downloadStart();
|
||||
getSegmentMan()->registerPeerStat(_peerStat);
|
||||
}
|
||||
|
||||
DownloadCommand::~DownloadCommand() {
|
||||
peerStat->downloadStop();
|
||||
_requestGroup->getSegmentMan()->updateFastestPeerStat(peerStat);
|
||||
_peerStat->downloadStop();
|
||||
getSegmentMan()->updateFastestPeerStat(_peerStat);
|
||||
delete [] _buf;
|
||||
}
|
||||
|
||||
bool DownloadCommand::executeInternal() {
|
||||
if(e->getRequestGroupMan()->doesOverallDownloadSpeedExceed() ||
|
||||
_requestGroup->doesDownloadSpeedExceed()) {
|
||||
e->addCommand(this);
|
||||
if(getDownloadEngine()->getRequestGroupMan()->doesOverallDownloadSpeedExceed()
|
||||
|| getRequestGroup()->doesDownloadSpeedExceed()) {
|
||||
getDownloadEngine()->addCommand(this);
|
||||
disableReadCheckSocket();
|
||||
return false;
|
||||
}
|
||||
setReadCheckSocket(socket);
|
||||
SharedHandle<Segment> segment = _segments.front();
|
||||
setReadCheckSocket(getSocket());
|
||||
SharedHandle<Segment> segment = getSegments().front();
|
||||
|
||||
size_t bufSize;
|
||||
if(segment->getLength() > 0) {
|
||||
if(static_cast<uint64_t>(segment->getPosition()+segment->getLength()) <=
|
||||
static_cast<uint64_t>(_fileEntry->getLastOffset())) {
|
||||
static_cast<uint64_t>(getFileEntry()->getLastOffset())) {
|
||||
bufSize = std::min(segment->getLength()-segment->getWrittenLength(),
|
||||
BUFSIZE);
|
||||
} else {
|
||||
bufSize =
|
||||
std::min(static_cast<size_t>
|
||||
(_fileEntry->getLastOffset()-segment->getPositionToWrite()),
|
||||
BUFSIZE);
|
||||
std::min
|
||||
(static_cast<size_t>
|
||||
(getFileEntry()->getLastOffset()-segment->getPositionToWrite()),
|
||||
BUFSIZE);
|
||||
}
|
||||
} else {
|
||||
bufSize = BUFSIZE;
|
||||
}
|
||||
socket->readData(_buf, bufSize);
|
||||
getSocket()->readData(_buf, bufSize);
|
||||
|
||||
const SharedHandle<DiskAdaptor>& diskAdaptor =
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor();
|
||||
getPieceStorage()->getDiskAdaptor();
|
||||
|
||||
const unsigned char* bufFinal;
|
||||
size_t bufSizeFinal;
|
||||
|
@ -173,24 +175,21 @@ bool DownloadCommand::executeInternal() {
|
|||
if(bufSizeFinal > 0) {
|
||||
segment->updateWrittenLength(bufSizeFinal);
|
||||
}
|
||||
|
||||
peerStat->updateDownloadLength(bufSize);
|
||||
|
||||
_requestGroup->getSegmentMan()->updateDownloadSpeedFor(peerStat);
|
||||
|
||||
_peerStat->updateDownloadLength(bufSize);
|
||||
getSegmentMan()->updateDownloadSpeedFor(_peerStat);
|
||||
bool segmentPartComplete = false;
|
||||
// Note that GrowSegment::complete() always returns false.
|
||||
if(_transferEncodingDecoder.isNull() && _contentEncodingDecoder.isNull()) {
|
||||
if(segment->complete() ||
|
||||
segment->getPositionToWrite() == _fileEntry->getLastOffset()) {
|
||||
segment->getPositionToWrite() == getFileEntry()->getLastOffset()) {
|
||||
segmentPartComplete = true;
|
||||
} else if(segment->getLength() == 0 && bufSize == 0 &&
|
||||
!socket->wantRead() && !socket->wantWrite()) {
|
||||
!getSocket()->wantRead() && !getSocket()->wantWrite()) {
|
||||
segmentPartComplete = true;
|
||||
}
|
||||
} else if(!_transferEncodingDecoder.isNull() &&
|
||||
(segment->complete() ||
|
||||
segment->getPositionToWrite() == _fileEntry->getLastOffset())) {
|
||||
segment->getPositionToWrite() == getFileEntry()->getLastOffset())){
|
||||
// In this case, transferEncodingDecoder is used and
|
||||
// Content-Length is known.
|
||||
segmentPartComplete = true;
|
||||
|
@ -202,7 +201,7 @@ bool DownloadCommand::executeInternal() {
|
|||
}
|
||||
|
||||
if(!segmentPartComplete && bufSize == 0 &&
|
||||
!socket->wantRead() && !socket->wantWrite()) {
|
||||
!getSocket()->wantRead() && !getSocket()->wantWrite()) {
|
||||
throw DL_RETRY_EX(EX_GOT_EOF);
|
||||
}
|
||||
|
||||
|
@ -219,8 +218,7 @@ bool DownloadCommand::executeInternal() {
|
|||
|
||||
{
|
||||
const std::string& expectedPieceHash =
|
||||
_requestGroup->getDownloadContext()->getPieceHash
|
||||
(segment->getIndex());
|
||||
getDownloadContext()->getPieceHash(segment->getIndex());
|
||||
if(_pieceHashValidationEnabled && !expectedPieceHash.empty()) {
|
||||
if(segment->isHashCalculated()) {
|
||||
if(getLogger()->debug()) {
|
||||
|
@ -236,31 +234,31 @@ bool DownloadCommand::executeInternal() {
|
|||
(segment, expectedPieceHash,
|
||||
MessageDigestHelper::digest
|
||||
(_messageDigestContext.get(),
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor(),
|
||||
getPieceStorage()->getDiskAdaptor(),
|
||||
segment->getPosition(),
|
||||
segment->getLength()));
|
||||
}
|
||||
} else {
|
||||
_requestGroup->getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
}
|
||||
}
|
||||
|
||||
#else // !ENABLE_MESSAGE_DIGEST
|
||||
_requestGroup->getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
#endif // !ENABLE_MESSAGE_DIGEST
|
||||
} else {
|
||||
// If segment is not canceled here, in the next pipelining
|
||||
// request, aria2 requests bad range
|
||||
// [FileEntry->getLastOffset(), FileEntry->getLastOffset())
|
||||
_requestGroup->getSegmentMan()->cancelSegment(getCuid(), segment);
|
||||
getSegmentMan()->cancelSegment(getCuid(), segment);
|
||||
}
|
||||
checkLowestDownloadSpeed();
|
||||
// this unit is going to download another segment.
|
||||
return prepareForNextSegment();
|
||||
} else {
|
||||
checkLowestDownloadSpeed();
|
||||
setWriteCheckSocketIf(socket, socket->wantWrite());
|
||||
e->addCommand(this);
|
||||
setWriteCheckSocketIf(getSocket(), getSocket()->wantWrite());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -268,67 +266,62 @@ bool DownloadCommand::executeInternal() {
|
|||
void DownloadCommand::checkLowestDownloadSpeed() const
|
||||
{
|
||||
// calculate downloading speed
|
||||
if(peerStat->getDownloadStartTime().difference(global::wallclock) >=
|
||||
startupIdleTime) {
|
||||
unsigned int nowSpeed = peerStat->calculateDownloadSpeed();
|
||||
if(lowestDownloadSpeedLimit > 0 && nowSpeed <= lowestDownloadSpeedLimit) {
|
||||
if(_peerStat->getDownloadStartTime().difference(global::wallclock) >=
|
||||
_startupIdleTime) {
|
||||
unsigned int nowSpeed = _peerStat->calculateDownloadSpeed();
|
||||
if(_lowestDownloadSpeedLimit > 0 && nowSpeed <= _lowestDownloadSpeedLimit) {
|
||||
throw DL_ABORT_EX2(StringFormat(EX_TOO_SLOW_DOWNLOAD_SPEED,
|
||||
nowSpeed,
|
||||
lowestDownloadSpeedLimit,
|
||||
req->getHost().c_str()).str(),
|
||||
_lowestDownloadSpeedLimit,
|
||||
getRequest()->getHost().c_str()).str(),
|
||||
downloadresultcode::TOO_SLOW_DOWNLOAD_SPEED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DownloadCommand::prepareForNextSegment() {
|
||||
if(_requestGroup->downloadFinished()) {
|
||||
const SharedHandle<DownloadContext>& dctx =
|
||||
_requestGroup->getDownloadContext();
|
||||
if(getRequestGroup()->downloadFinished()) {
|
||||
// Remove in-flight request here.
|
||||
_fileEntry->poolRequest(req);
|
||||
getFileEntry()->poolRequest(getRequest());
|
||||
// If this is a single file download, and file size becomes known
|
||||
// just after downloading, set total length to FileEntry object
|
||||
// here.
|
||||
if(dctx->getFileEntries().size() == 1) {
|
||||
const SharedHandle<FileEntry>& fileEntry = dctx->getFirstFileEntry();
|
||||
if(fileEntry->getLength() == 0) {
|
||||
fileEntry->setLength
|
||||
(_requestGroup->getPieceStorage()->getCompletedLength());
|
||||
if(getDownloadContext()->getFileEntries().size() == 1) {
|
||||
if(getFileEntry()->getLength() == 0) {
|
||||
getFileEntry()->setLength(getPieceStorage()->getCompletedLength());
|
||||
}
|
||||
}
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
if(dctx->getPieceHashAlgo().empty()) {
|
||||
if(getDownloadContext()->getPieceHashAlgo().empty()) {
|
||||
SharedHandle<CheckIntegrityEntry> entry
|
||||
(new ChecksumCheckIntegrityEntry(_requestGroup));
|
||||
(new ChecksumCheckIntegrityEntry(getRequestGroup()));
|
||||
if(entry->isValidationReady()) {
|
||||
entry->initValidator();
|
||||
// TODO do we need cuttrailinggarbage here?
|
||||
e->getCheckIntegrityMan()->pushEntry(entry);
|
||||
getDownloadEngine()->getCheckIntegrityMan()->pushEntry(entry);
|
||||
}
|
||||
}
|
||||
// Following 2lines are needed for DownloadEngine to detect
|
||||
// completed RequestGroups without 1sec delay.
|
||||
e->setNoWait(true);
|
||||
e->setRefreshInterval(0);
|
||||
getDownloadEngine()->setNoWait(true);
|
||||
getDownloadEngine()->setRefreshInterval(0);
|
||||
#endif // ENABLE_MESSAGE_DIGEST
|
||||
return true;
|
||||
} else {
|
||||
// The number of segments should be 1 in order to pass through the next
|
||||
// segment.
|
||||
if(_segments.size() == 1) {
|
||||
SharedHandle<Segment> tempSegment = _segments.front();
|
||||
if(getSegments().size() == 1) {
|
||||
SharedHandle<Segment> tempSegment = getSegments().front();
|
||||
if(!tempSegment->complete()) {
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
SharedHandle<SegmentMan> segmentMan = _requestGroup->getSegmentMan();
|
||||
SharedHandle<Segment> nextSegment =
|
||||
segmentMan->getCleanSegmentIfOwnerIsIdle
|
||||
getSegmentMan()->getCleanSegmentIfOwnerIsIdle
|
||||
(getCuid(), tempSegment->getIndex()+1);
|
||||
if(nextSegment.isNull()) {
|
||||
return prepareForRetry(0);
|
||||
} else {
|
||||
e->addCommand(this);
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -345,7 +338,7 @@ void DownloadCommand::validatePieceHash(const SharedHandle<Segment>& segment,
|
|||
{
|
||||
if(actualPieceHash == expectedPieceHash) {
|
||||
getLogger()->info(MSG_GOOD_CHUNK_CHECKSUM, actualPieceHash.c_str());
|
||||
_requestGroup->getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
getSegmentMan()->completeSegment(getCuid(), segment);
|
||||
} else {
|
||||
getLogger()->info(EX_INVALID_CHUNK_CHECKSUM,
|
||||
segment->getIndex(),
|
||||
|
@ -353,7 +346,7 @@ void DownloadCommand::validatePieceHash(const SharedHandle<Segment>& segment,
|
|||
expectedPieceHash.c_str(),
|
||||
actualPieceHash.c_str());
|
||||
segment->clear();
|
||||
_requestGroup->getSegmentMan()->cancelSegment(getCuid());
|
||||
getSegmentMan()->cancelSegment(getCuid());
|
||||
throw DL_RETRY_EX
|
||||
(StringFormat("Invalid checksum index=%d", segment->getIndex()).str());
|
||||
}
|
||||
|
|
|
@ -49,9 +49,9 @@ class DownloadCommand : public AbstractCommand {
|
|||
private:
|
||||
unsigned char* _buf;
|
||||
|
||||
time_t startupIdleTime;
|
||||
unsigned int lowestDownloadSpeedLimit;
|
||||
SharedHandle<PeerStat> peerStat;
|
||||
time_t _startupIdleTime;
|
||||
unsigned int _lowestDownloadSpeedLimit;
|
||||
SharedHandle<PeerStat> _peerStat;
|
||||
|
||||
#ifdef ENABLE_MESSAGE_DIGEST
|
||||
|
||||
|
@ -66,15 +66,14 @@ private:
|
|||
const std::string& actualPieceHash);
|
||||
|
||||
void checkLowestDownloadSpeed() const;
|
||||
protected:
|
||||
|
||||
SharedHandle<Decoder> _transferEncodingDecoder;
|
||||
|
||||
SharedHandle<Decoder> _contentEncodingDecoder;
|
||||
|
||||
protected:
|
||||
virtual bool executeInternal();
|
||||
|
||||
virtual bool prepareForNextSegment();
|
||||
|
||||
public:
|
||||
DownloadCommand(cuid_t cuid,
|
||||
const SharedHandle<Request>& req,
|
||||
|
@ -84,16 +83,28 @@ public:
|
|||
const SharedHandle<SocketCore>& s);
|
||||
virtual ~DownloadCommand();
|
||||
|
||||
const SharedHandle<Decoder>& getTransferEncodingDecoder() const
|
||||
{
|
||||
return _transferEncodingDecoder;
|
||||
}
|
||||
|
||||
void setTransferEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
||||
|
||||
const SharedHandle<Decoder>& getContentEncodingDecoder() const
|
||||
{
|
||||
return _contentEncodingDecoder;
|
||||
}
|
||||
|
||||
void setContentEncodingDecoder(const SharedHandle<Decoder>& decoder);
|
||||
|
||||
void setStartupIdleTime(time_t startupIdleTime) {
|
||||
this->startupIdleTime = startupIdleTime;
|
||||
void setStartupIdleTime(time_t startupIdleTime)
|
||||
{
|
||||
_startupIdleTime = startupIdleTime;
|
||||
}
|
||||
|
||||
void setLowestDownloadSpeedLimit(unsigned int lowestDownloadSpeedLimit) {
|
||||
this->lowestDownloadSpeedLimit = lowestDownloadSpeedLimit;
|
||||
void setLowestDownloadSpeedLimit(unsigned int lowestDownloadSpeedLimit)
|
||||
{
|
||||
_lowestDownloadSpeedLimit = lowestDownloadSpeedLimit;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ FtpDownloadCommand::FtpDownloadCommand
|
|||
const SocketHandle& ctrlSocket)
|
||||
:DownloadCommand(cuid, req, fileEntry, requestGroup, e, dataSocket),
|
||||
_ftpConnection(ftpConnection),
|
||||
ctrlSocket(ctrlSocket) {}
|
||||
_ctrlSocket(ctrlSocket) {}
|
||||
|
||||
FtpDownloadCommand::~FtpDownloadCommand() {}
|
||||
|
||||
|
@ -71,14 +71,14 @@ bool FtpDownloadCommand::prepareForNextSegment()
|
|||
{
|
||||
if(getOption()->getAsBool(PREF_FTP_REUSE_CONNECTION) &&
|
||||
static_cast<uint64_t>
|
||||
(_fileEntry->gtoloff(_segments.front()->getPositionToWrite())) ==
|
||||
_fileEntry->getLength()) {
|
||||
(getFileEntry()->gtoloff(getSegments().front()->getPositionToWrite())) ==
|
||||
getFileEntry()->getLength()) {
|
||||
Command* command = new FtpFinishDownloadCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, _ftpConnection, e,
|
||||
ctrlSocket);
|
||||
e->addCommand(command);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
_ftpConnection, getDownloadEngine(), _ctrlSocket);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
|
||||
if(_requestGroup->downloadFinished()) {
|
||||
if(getRequestGroup()->downloadFinished()) {
|
||||
// To run checksum checking, we had to call following function here.
|
||||
DownloadCommand::prepareForNextSegment();
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class FtpDownloadCommand : public DownloadCommand {
|
|||
private:
|
||||
SharedHandle<FtpConnection> _ftpConnection;
|
||||
|
||||
SharedHandle<SocketCore> ctrlSocket;
|
||||
SharedHandle<SocketCore> _ctrlSocket;
|
||||
protected:
|
||||
virtual bool prepareForNextSegment();
|
||||
public:
|
||||
|
|
|
@ -71,13 +71,13 @@ FtpFinishDownloadCommand::FtpFinishDownloadCommand
|
|||
// AbstractCommand::_segments is empty.
|
||||
bool FtpFinishDownloadCommand::execute()
|
||||
{
|
||||
if(_requestGroup->isHaltRequested()) {
|
||||
if(getRequestGroup()->isHaltRequested()) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
unsigned int status = _ftpConnection->receiveResponse();
|
||||
if(status == 0) {
|
||||
e->addCommand(this);
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
if(status != 226) {
|
||||
|
@ -86,13 +86,14 @@ bool FtpFinishDownloadCommand::execute()
|
|||
if(getOption()->getAsBool(PREF_FTP_REUSE_CONNECTION)) {
|
||||
std::map<std::string, std::string> options;
|
||||
options["baseWorkingDir"] = _ftpConnection->getBaseWorkingDir();
|
||||
e->poolSocket(req, _ftpConnection->getUser(), createProxyRequest(),
|
||||
socket, options);
|
||||
getDownloadEngine()->poolSocket
|
||||
(getRequest(), _ftpConnection->getUser(), createProxyRequest(),
|
||||
getSocket(), options);
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
getLogger()->info(EX_EXCEPTION_CAUGHT, e);
|
||||
}
|
||||
if(_requestGroup->downloadFinished()) {
|
||||
if(getRequestGroup()->downloadFinished()) {
|
||||
return true;
|
||||
} else {
|
||||
return prepareForRetry(0);
|
||||
|
|
|
@ -80,16 +80,16 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
if(!proxyRequest.isNull()) {
|
||||
std::map<std::string, std::string> options;
|
||||
SharedHandle<SocketCore> pooledSocket;
|
||||
std::string proxyMethod = resolveProxyMethod(req->getProtocol());
|
||||
std::string proxyMethod = resolveProxyMethod(getRequest()->getProtocol());
|
||||
if(proxyMethod == V_GET) {
|
||||
pooledSocket = e->popPooledSocket
|
||||
(req->getHost(), req->getPort(),
|
||||
pooledSocket = getDownloadEngine()->popPooledSocket
|
||||
(getRequest()->getHost(), getRequest()->getPort(),
|
||||
proxyRequest->getHost(), proxyRequest->getPort());
|
||||
} else {
|
||||
pooledSocket = e->popPooledSocket
|
||||
(options, req->getHost(), req->getPort(),
|
||||
e->getAuthConfigFactory()->createAuthConfig
|
||||
(req, getOption().get())->getUser(),
|
||||
pooledSocket = getDownloadEngine()->popPooledSocket
|
||||
(options, getRequest()->getHost(), getRequest()->getPort(),
|
||||
getDownloadEngine()->getAuthConfigFactory()->createAuthConfig
|
||||
(getRequest(), getOption().get())->getUser(),
|
||||
proxyRequest->getHost(), proxyRequest->getPort());
|
||||
}
|
||||
if(pooledSocket.isNull()) {
|
||||
|
@ -97,26 +97,27 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
getLogger()->info(MSG_CONNECTING_TO_SERVER,
|
||||
util::itos(getCuid()).c_str(), addr.c_str(), port);
|
||||
}
|
||||
socket.reset(new SocketCore());
|
||||
socket->establishConnection(addr, port);
|
||||
createSocket();
|
||||
getSocket()->establishConnection(addr, port);
|
||||
|
||||
if(proxyMethod == V_GET) {
|
||||
// Use GET for FTP via HTTP proxy.
|
||||
req->setMethod(Request::METHOD_GET);
|
||||
getRequest()->setMethod(Request::METHOD_GET);
|
||||
SharedHandle<HttpConnection> hc
|
||||
(new HttpConnection(getCuid(), socket, getOption().get()));
|
||||
(new HttpConnection(getCuid(), getSocket(), getOption().get()));
|
||||
|
||||
HttpRequestCommand* c =
|
||||
new HttpRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, hc, e, socket);
|
||||
new HttpRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), hc, getDownloadEngine(),
|
||||
getSocket());
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
c->setProxyRequest(proxyRequest);
|
||||
command = c;
|
||||
} else if(proxyMethod == V_TUNNEL) {
|
||||
FtpTunnelRequestCommand* c =
|
||||
new FtpTunnelRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e,
|
||||
proxyRequest, socket);
|
||||
new FtpTunnelRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getDownloadEngine(),
|
||||
proxyRequest, getSocket());
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
command = c;
|
||||
} else {
|
||||
|
@ -126,19 +127,21 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
} else {
|
||||
if(proxyMethod == V_TUNNEL) {
|
||||
command =
|
||||
new FtpNegotiationCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e, pooledSocket,
|
||||
new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getDownloadEngine(),
|
||||
pooledSocket,
|
||||
FtpNegotiationCommand::SEQ_SEND_CWD,
|
||||
options["baseWorkingDir"]);
|
||||
} else if(proxyMethod == V_GET) {
|
||||
// Use GET for FTP via HTTP proxy.
|
||||
req->setMethod(Request::METHOD_GET);
|
||||
getRequest()->setMethod(Request::METHOD_GET);
|
||||
SharedHandle<HttpConnection> hc
|
||||
(new HttpConnection(getCuid(), pooledSocket, getOption().get()));
|
||||
|
||||
HttpRequestCommand* c =
|
||||
new HttpRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, hc, e, pooledSocket);
|
||||
new HttpRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), hc, getDownloadEngine(),
|
||||
pooledSocket);
|
||||
c->setProxyRequest(proxyRequest);
|
||||
command = c;
|
||||
} else {
|
||||
|
@ -149,25 +152,29 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
} else {
|
||||
std::map<std::string, std::string> options;
|
||||
SharedHandle<SocketCore> pooledSocket =
|
||||
e->popPooledSocket(options, resolvedAddresses, req->getPort(),
|
||||
e->getAuthConfigFactory()->createAuthConfig
|
||||
(req, getOption().get())->getUser());
|
||||
getDownloadEngine()->popPooledSocket
|
||||
(options, resolvedAddresses,
|
||||
getRequest()->getPort(),
|
||||
getDownloadEngine()->getAuthConfigFactory()->createAuthConfig
|
||||
(getRequest(), getOption().get())->getUser());
|
||||
if(pooledSocket.isNull()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(MSG_CONNECTING_TO_SERVER,
|
||||
util::itos(getCuid()).c_str(), addr.c_str(), port);
|
||||
}
|
||||
socket.reset(new SocketCore());
|
||||
socket->establishConnection(addr, port);
|
||||
createSocket();
|
||||
getSocket()->establishConnection(addr, port);
|
||||
FtpNegotiationCommand* c =
|
||||
new FtpNegotiationCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e, socket);
|
||||
new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getDownloadEngine(),
|
||||
getSocket());
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
command = c;
|
||||
} else {
|
||||
command =
|
||||
new FtpNegotiationCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e, pooledSocket,
|
||||
new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getDownloadEngine(),
|
||||
pooledSocket,
|
||||
FtpNegotiationCommand::SEQ_SEND_CWD,
|
||||
options["baseWorkingDir"]);
|
||||
}
|
||||
|
|
|
@ -83,104 +83,105 @@ FtpNegotiationCommand::FtpNegotiationCommand
|
|||
const SharedHandle<FileEntry>& fileEntry,
|
||||
RequestGroup* requestGroup,
|
||||
DownloadEngine* e,
|
||||
const SocketHandle& s,
|
||||
const SocketHandle& socket,
|
||||
Seq seq,
|
||||
const std::string& baseWorkingDir):
|
||||
AbstractCommand(cuid, req, fileEntry, requestGroup, e, s), sequence(seq),
|
||||
ftp(new FtpConnection(cuid, socket, req,
|
||||
AbstractCommand(cuid, req, fileEntry, requestGroup, e, socket), _sequence(seq),
|
||||
_ftp(new FtpConnection(cuid, socket, req,
|
||||
e->getAuthConfigFactory()->createAuthConfig
|
||||
(req, requestGroup->getOption().get()),
|
||||
getOption().get()))
|
||||
{
|
||||
ftp->setBaseWorkingDir(baseWorkingDir);
|
||||
_ftp->setBaseWorkingDir(baseWorkingDir);
|
||||
if(seq == SEQ_RECV_GREETING) {
|
||||
setTimeout(getOption()->getAsInt(PREF_CONNECT_TIMEOUT));
|
||||
}
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
|
||||
FtpNegotiationCommand::~FtpNegotiationCommand() {}
|
||||
|
||||
bool FtpNegotiationCommand::executeInternal() {
|
||||
while(processSequence(_segments.front()));
|
||||
if(sequence == SEQ_RETRY) {
|
||||
while(processSequence(getSegments().front()));
|
||||
if(_sequence == SEQ_RETRY) {
|
||||
return prepareForRetry(0);
|
||||
} else if(sequence == SEQ_NEGOTIATION_COMPLETED) {
|
||||
} else if(_sequence == SEQ_NEGOTIATION_COMPLETED) {
|
||||
FtpDownloadCommand* command =
|
||||
new FtpDownloadCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, ftp, e, dataSocket, socket);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(), _ftp,
|
||||
getDownloadEngine(), _dataSocket, getSocket());
|
||||
command->setStartupIdleTime(getOption()->getAsInt(PREF_STARTUP_IDLE_TIME));
|
||||
command->setLowestDownloadSpeedLimit
|
||||
(getOption()->getAsInt(PREF_LOWEST_SPEED_LIMIT));
|
||||
if(!_fileEntry->isSingleHostMultiConnectionEnabled()) {
|
||||
_fileEntry->removeURIWhoseHostnameIs(req->getHost());
|
||||
if(!getFileEntry()->isSingleHostMultiConnectionEnabled()) {
|
||||
getFileEntry()->removeURIWhoseHostnameIs(getRequest()->getHost());
|
||||
}
|
||||
_requestGroup->getURISelector()->tuneDownloadCommand
|
||||
(_fileEntry->getRemainingUris(), command);
|
||||
e->addCommand(command);
|
||||
getRequestGroup()->getURISelector()->tuneDownloadCommand
|
||||
(getFileEntry()->getRemainingUris(), command);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
} else if(sequence == SEQ_HEAD_OK ||
|
||||
sequence == SEQ_DOWNLOAD_ALREADY_COMPLETED) {
|
||||
} else if(_sequence == SEQ_HEAD_OK ||
|
||||
_sequence == SEQ_DOWNLOAD_ALREADY_COMPLETED) {
|
||||
return true;
|
||||
} else if(sequence == SEQ_FILE_PREPARATION) {
|
||||
} else if(_sequence == SEQ_FILE_PREPARATION) {
|
||||
if(getOption()->getAsBool(PREF_FTP_PASV)) {
|
||||
sequence = SEQ_SEND_PASV;
|
||||
_sequence = SEQ_SEND_PASV;
|
||||
} else {
|
||||
sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
_sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
}
|
||||
return false;
|
||||
} else if(sequence == SEQ_EXIT) {
|
||||
} else if(_sequence == SEQ_EXIT) {
|
||||
return true;
|
||||
} else {
|
||||
e->addCommand(this);
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvGreeting() {
|
||||
if(!checkIfConnectionEstablished
|
||||
(socket, _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
sequence = SEQ_EXIT;
|
||||
(getSocket(), _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
_sequence = SEQ_EXIT;
|
||||
return false;
|
||||
}
|
||||
setTimeout(_requestGroup->getTimeout());
|
||||
setTimeout(getRequestGroup()->getTimeout());
|
||||
//socket->setBlockingMode();
|
||||
disableWriteCheckSocket();
|
||||
setReadCheckSocket(socket);
|
||||
setReadCheckSocket(getSocket());
|
||||
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 220) {
|
||||
throw DL_ABORT_EX(EX_CONNECTION_FAILED);
|
||||
}
|
||||
sequence = SEQ_SEND_USER;
|
||||
_sequence = SEQ_SEND_USER;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendUser() {
|
||||
if(ftp->sendUser()) {
|
||||
if(_ftp->sendUser()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_USER;
|
||||
_sequence = SEQ_RECV_USER;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvUser() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
switch(status) {
|
||||
case 0:
|
||||
return false;
|
||||
case 230:
|
||||
sequence = SEQ_SEND_TYPE;
|
||||
_sequence = SEQ_SEND_TYPE;
|
||||
break;
|
||||
case 331:
|
||||
sequence = SEQ_SEND_PASS;
|
||||
_sequence = SEQ_SEND_PASS;
|
||||
break;
|
||||
default:
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
|
@ -189,56 +190,56 @@ bool FtpNegotiationCommand::recvUser() {
|
|||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendPass() {
|
||||
if(ftp->sendPass()) {
|
||||
if(_ftp->sendPass()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_PASS;
|
||||
_sequence = SEQ_RECV_PASS;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvPass() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 230) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
sequence = SEQ_SEND_TYPE;
|
||||
_sequence = SEQ_SEND_TYPE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendType() {
|
||||
if(ftp->sendType()) {
|
||||
if(_ftp->sendType()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_TYPE;
|
||||
_sequence = SEQ_RECV_TYPE;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvType() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 200) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
sequence = SEQ_SEND_PWD;
|
||||
_sequence = SEQ_SEND_PWD;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendPwd()
|
||||
{
|
||||
if(ftp->sendPwd()) {
|
||||
if(_ftp->sendPwd()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_PWD;
|
||||
_sequence = SEQ_RECV_PWD;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -246,42 +247,42 @@ bool FtpNegotiationCommand::sendPwd()
|
|||
bool FtpNegotiationCommand::recvPwd()
|
||||
{
|
||||
std::string pwd;
|
||||
unsigned int status = ftp->receivePwdResponse(pwd);
|
||||
unsigned int status = _ftp->receivePwdResponse(pwd);
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 257) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
ftp->setBaseWorkingDir(pwd);
|
||||
_ftp->setBaseWorkingDir(pwd);
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info("CUID#%s - base working directory is '%s'",
|
||||
util::itos(getCuid()).c_str(), pwd.c_str());
|
||||
}
|
||||
sequence = SEQ_SEND_CWD;
|
||||
_sequence = SEQ_SEND_CWD;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendCwd() {
|
||||
// Calling setReadCheckSocket() is needed when the socket is reused,
|
||||
setReadCheckSocket(socket);
|
||||
if(ftp->sendCwd()) {
|
||||
setReadCheckSocket(getSocket());
|
||||
if(_ftp->sendCwd()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_CWD;
|
||||
_sequence = SEQ_RECV_CWD;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvCwd() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 250) {
|
||||
poolConnection();
|
||||
_requestGroup->increaseAndValidateFileNotFoundCount();
|
||||
getRequestGroup()->increaseAndValidateFileNotFoundCount();
|
||||
if (status == 550)
|
||||
throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND,
|
||||
downloadresultcode::RESOURCE_NOT_FOUND);
|
||||
|
@ -289,20 +290,20 @@ bool FtpNegotiationCommand::recvCwd() {
|
|||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
if(getOption()->getAsBool(PREF_REMOTE_TIME)) {
|
||||
sequence = SEQ_SEND_MDTM;
|
||||
_sequence = SEQ_SEND_MDTM;
|
||||
} else {
|
||||
sequence = SEQ_SEND_SIZE;
|
||||
_sequence = SEQ_SEND_SIZE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendMdtm()
|
||||
{
|
||||
if(ftp->sendMdtm()) {
|
||||
if(_ftp->sendMdtm()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_MDTM;
|
||||
_sequence = SEQ_RECV_MDTM;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -310,13 +311,13 @@ bool FtpNegotiationCommand::sendMdtm()
|
|||
bool FtpNegotiationCommand::recvMdtm()
|
||||
{
|
||||
Time lastModifiedTime = Time::null();
|
||||
unsigned int status = ftp->receiveMdtmResponse(lastModifiedTime);
|
||||
unsigned int status = _ftp->receiveMdtmResponse(lastModifiedTime);
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status == 213) {
|
||||
if(lastModifiedTime.good()) {
|
||||
_requestGroup->updateLastModifiedTime(lastModifiedTime);
|
||||
getRequestGroup()->updateLastModifiedTime(lastModifiedTime);
|
||||
time_t t = lastModifiedTime.getTime();
|
||||
struct tm* tms = gmtime(&t); // returned struct is statically allocated.
|
||||
if(tms) {
|
||||
|
@ -340,84 +341,87 @@ bool FtpNegotiationCommand::recvMdtm()
|
|||
util::itos(getCuid()).c_str());
|
||||
}
|
||||
}
|
||||
sequence = SEQ_SEND_SIZE;
|
||||
_sequence = SEQ_SEND_SIZE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendSize() {
|
||||
if(ftp->sendSize()) {
|
||||
if(_ftp->sendSize()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_SIZE;
|
||||
_sequence = SEQ_RECV_SIZE;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength)
|
||||
{
|
||||
_fileEntry->setLength(totalLength);
|
||||
if(_fileEntry->getPath().empty()) {
|
||||
_fileEntry->setPath
|
||||
getFileEntry()->setLength(totalLength);
|
||||
if(getFileEntry()->getPath().empty()) {
|
||||
getFileEntry()->setPath
|
||||
(util::applyDir
|
||||
(getDownloadContext()->getDir(),
|
||||
util::fixTaintedBasename(util::percentDecode(req->getFile()))));
|
||||
util::fixTaintedBasename
|
||||
(util::percentDecode(getRequest()->getFile()))));
|
||||
}
|
||||
_requestGroup->preDownloadProcessing();
|
||||
if(e->getRequestGroupMan()->isSameFileBeingDownloaded(_requestGroup)) {
|
||||
getRequestGroup()->preDownloadProcessing();
|
||||
if(getDownloadEngine()->getRequestGroupMan()->
|
||||
isSameFileBeingDownloaded(getRequestGroup())) {
|
||||
throw DOWNLOAD_FAILURE_EXCEPTION
|
||||
(StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
|
||||
_requestGroup->getFirstFilePath().c_str()).str());
|
||||
getRequestGroup()->getFirstFilePath().c_str()).str());
|
||||
}
|
||||
if(totalLength == 0) {
|
||||
|
||||
if(getOption()->getAsBool(PREF_FTP_PASV)) {
|
||||
sequence = SEQ_SEND_PASV;
|
||||
_sequence = SEQ_SEND_PASV;
|
||||
} else {
|
||||
sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
_sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
}
|
||||
|
||||
if(getOption()->getAsBool(PREF_DRY_RUN)) {
|
||||
_requestGroup->initPieceStorage();
|
||||
getRequestGroup()->initPieceStorage();
|
||||
onDryRunFileFound();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_requestGroup->downloadFinishedByFileLength()) {
|
||||
_requestGroup->initPieceStorage();
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
if(getRequestGroup()->downloadFinishedByFileLength()) {
|
||||
getRequestGroup()->initPieceStorage();
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
_sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
|
||||
getLogger()->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
||||
util::itos(_requestGroup->getGID()).c_str(),
|
||||
_requestGroup->getFirstFilePath().c_str());
|
||||
util::itos(getRequestGroup()->getGID()).c_str(),
|
||||
getRequestGroup()->getFirstFilePath().c_str());
|
||||
|
||||
poolConnection();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_requestGroup->shouldCancelDownloadForSafety();
|
||||
_requestGroup->initPieceStorage();
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
|
||||
getRequestGroup()->shouldCancelDownloadForSafety();
|
||||
getRequestGroup()->initPieceStorage();
|
||||
getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
|
||||
|
||||
if(getDownloadContext()->knowsTotalLength()) {
|
||||
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
_sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
poolConnection();
|
||||
return false;
|
||||
}
|
||||
// We have to make sure that command that has Request object must
|
||||
// have segment after PieceStorage is initialized. See
|
||||
// AbstractCommand::execute()
|
||||
_requestGroup->getSegmentMan()->getSegment(getCuid(), 0);
|
||||
getSegmentMan()->getSegment(getCuid(), 0);
|
||||
return true;
|
||||
} else {
|
||||
_requestGroup->adjustFilename
|
||||
(SharedHandle<BtProgressInfoFile>(new DefaultBtProgressInfoFile
|
||||
(_requestGroup->getDownloadContext(),
|
||||
SharedHandle<PieceStorage>(),
|
||||
getOption().get())));
|
||||
_requestGroup->initPieceStorage();
|
||||
getRequestGroup()->adjustFilename
|
||||
(SharedHandle<BtProgressInfoFile>
|
||||
(new DefaultBtProgressInfoFile
|
||||
(getDownloadContext(),
|
||||
SharedHandle<PieceStorage>(),
|
||||
getOption().get())));
|
||||
getRequestGroup()->initPieceStorage();
|
||||
|
||||
if(getOption()->getAsBool(PREF_DRY_RUN)) {
|
||||
onDryRunFileFound();
|
||||
|
@ -425,27 +429,28 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength)
|
|||
}
|
||||
|
||||
BtProgressInfoFileHandle infoFile
|
||||
(new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(),
|
||||
_requestGroup->getPieceStorage(),
|
||||
(new DefaultBtProgressInfoFile(getDownloadContext(),
|
||||
getPieceStorage(),
|
||||
getOption().get()));
|
||||
if(!infoFile->exists() && _requestGroup->downloadFinishedByFileLength()) {
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
if(!infoFile->exists() &&
|
||||
getRequestGroup()->downloadFinishedByFileLength()) {
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
|
||||
sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
_sequence = SEQ_DOWNLOAD_ALREADY_COMPLETED;
|
||||
|
||||
getLogger()->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
||||
util::itos(_requestGroup->getGID()).c_str(),
|
||||
_requestGroup->getFirstFilePath().c_str());
|
||||
util::itos(getRequestGroup()->getGID()).c_str(),
|
||||
getRequestGroup()->getFirstFilePath().c_str());
|
||||
|
||||
poolConnection();
|
||||
|
||||
return false;
|
||||
}
|
||||
_requestGroup->loadAndOpenFile(infoFile);
|
||||
getRequestGroup()->loadAndOpenFile(infoFile);
|
||||
// We have to make sure that command that has Request object must
|
||||
// have segment after PieceStorage is initialized. See
|
||||
// AbstractCommand::execute()
|
||||
_requestGroup->getSegmentMan()->getSegment(getCuid(), 0);
|
||||
getSegmentMan()->getSegment(getCuid(), 0);
|
||||
|
||||
prepareForNextAction(this);
|
||||
|
||||
|
@ -456,7 +461,7 @@ bool FtpNegotiationCommand::onFileSizeDetermined(uint64_t totalLength)
|
|||
|
||||
bool FtpNegotiationCommand::recvSize() {
|
||||
uint64_t size = 0;
|
||||
unsigned int status = ftp->receiveSizeResponse(size);
|
||||
unsigned int status = _ftp->receiveSizeResponse(size);
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -467,13 +472,13 @@ bool FtpNegotiationCommand::recvSize() {
|
|||
(StringFormat(EX_TOO_LARGE_FILE,
|
||||
util::uitos(size, true).c_str()).str());
|
||||
}
|
||||
if(_requestGroup->getPieceStorage().isNull()) {
|
||||
if(getPieceStorage().isNull()) {
|
||||
|
||||
sequence = SEQ_FILE_PREPARATION;
|
||||
_sequence = SEQ_FILE_PREPARATION;
|
||||
return onFileSizeDetermined(size);
|
||||
|
||||
} else {
|
||||
_requestGroup->validateTotalLength(_fileEntry->getLength(), size);
|
||||
getRequestGroup()->validateTotalLength(getFileEntry()->getLength(), size);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -484,7 +489,7 @@ bool FtpNegotiationCommand::recvSize() {
|
|||
// Even if one of the other servers waiting in the queue supports SIZE
|
||||
// command, resuming and segmented downloading are disabled when the first
|
||||
// contacted FTP server doesn't support it.
|
||||
if(_requestGroup->getPieceStorage().isNull()) {
|
||||
if(getPieceStorage().isNull()) {
|
||||
getDownloadContext()->markTotalLengthIsUnknown();
|
||||
return onFileSizeDetermined(0);
|
||||
|
||||
|
@ -493,62 +498,62 @@ bool FtpNegotiationCommand::recvSize() {
|
|||
// wrong file to be downloaded if user-specified URL is wrong.
|
||||
}
|
||||
if(getOption()->getAsBool(PREF_FTP_PASV)) {
|
||||
sequence = SEQ_SEND_PASV;
|
||||
_sequence = SEQ_SEND_PASV;
|
||||
} else {
|
||||
sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
_sequence = SEQ_PREPARE_SERVER_SOCKET;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FtpNegotiationCommand::afterFileAllocation()
|
||||
{
|
||||
setReadCheckSocket(socket);
|
||||
setReadCheckSocket(getSocket());
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::prepareServerSocket()
|
||||
{
|
||||
serverSocket = ftp->createServerSocket();
|
||||
sequence = SEQ_SEND_PORT;
|
||||
_serverSocket = _ftp->createServerSocket();
|
||||
_sequence = SEQ_SEND_PORT;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendPort() {
|
||||
afterFileAllocation();
|
||||
if(ftp->sendPort(serverSocket)) {
|
||||
if(_ftp->sendPort(_serverSocket)) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_PORT;
|
||||
_sequence = SEQ_RECV_PORT;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvPort() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 200) {
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
sequence = SEQ_SEND_REST;
|
||||
_sequence = SEQ_SEND_REST;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendPasv() {
|
||||
afterFileAllocation();
|
||||
if(ftp->sendPasv()) {
|
||||
if(_ftp->sendPasv()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_PASV;
|
||||
_sequence = SEQ_RECV_PASV;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvPasv() {
|
||||
std::pair<std::string, uint16_t> dest;
|
||||
unsigned int status = ftp->receivePasvResponse(dest);
|
||||
unsigned int status = _ftp->receivePasvResponse(dest);
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -558,7 +563,7 @@ bool FtpNegotiationCommand::recvPasv() {
|
|||
// TODO Should we check to see that dest.first is not in noProxy list?
|
||||
if(isProxyDefined()) {
|
||||
_dataConnAddr = dest;
|
||||
sequence = SEQ_RESOLVE_PROXY;
|
||||
_sequence = SEQ_RESOLVE_PROXY;
|
||||
return true;
|
||||
} else {
|
||||
// make a data connection to the server.
|
||||
|
@ -567,11 +572,11 @@ bool FtpNegotiationCommand::recvPasv() {
|
|||
dest.first.c_str(),
|
||||
dest.second);
|
||||
}
|
||||
dataSocket.reset(new SocketCore());
|
||||
dataSocket->establishConnection(dest.first, dest.second);
|
||||
_dataSocket.reset(new SocketCore());
|
||||
_dataSocket->establishConnection(dest.first, dest.second);
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(dataSocket);
|
||||
sequence = SEQ_SEND_REST_PASV;
|
||||
setWriteCheckSocket(_dataSocket);
|
||||
_sequence = SEQ_SEND_REST_PASV;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -589,27 +594,29 @@ bool FtpNegotiationCommand::resolveProxy()
|
|||
getLogger()->info(MSG_CONNECTING_TO_SERVER, util::itos(getCuid()).c_str(),
|
||||
_proxyAddr.c_str(), proxyReq->getPort());
|
||||
}
|
||||
dataSocket.reset(new SocketCore());
|
||||
dataSocket->establishConnection(_proxyAddr, proxyReq->getPort());
|
||||
_dataSocket.reset(new SocketCore());
|
||||
_dataSocket->establishConnection(_proxyAddr, proxyReq->getPort());
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(dataSocket);
|
||||
_http.reset(new HttpConnection(getCuid(), dataSocket, getOption().get()));
|
||||
sequence = SEQ_SEND_TUNNEL_REQUEST;
|
||||
setWriteCheckSocket(_dataSocket);
|
||||
_http.reset(new HttpConnection(getCuid(), _dataSocket, getOption().get()));
|
||||
_sequence = SEQ_SEND_TUNNEL_REQUEST;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendTunnelRequest()
|
||||
{
|
||||
if(_http->sendBufferIsEmpty()) {
|
||||
if(dataSocket->isReadable(0)) {
|
||||
std::string error = socket->getSocketError();
|
||||
if(_dataSocket->isReadable(0)) {
|
||||
std::string error = getSocket()->getSocketError();
|
||||
if(!error.empty()) {
|
||||
SharedHandle<Request> proxyReq = createProxyRequest();
|
||||
e->markBadIPAddress(proxyReq->getHost(),_proxyAddr,proxyReq->getPort());
|
||||
std::string nextProxyAddr = e->findCachedIPAddress
|
||||
getDownloadEngine()->markBadIPAddress(proxyReq->getHost(),
|
||||
_proxyAddr,proxyReq->getPort());
|
||||
std::string nextProxyAddr = getDownloadEngine()->findCachedIPAddress
|
||||
(proxyReq->getHost(), proxyReq->getPort());
|
||||
if(nextProxyAddr.empty()) {
|
||||
e->removeCachedIPAddress(proxyReq->getHost(), proxyReq->getPort());
|
||||
getDownloadEngine()->removeCachedIPAddress(proxyReq->getHost(),
|
||||
proxyReq->getPort());
|
||||
throw DL_RETRY_EX
|
||||
(StringFormat(MSG_ESTABLISHING_CONNECTION_FAILED,
|
||||
error.c_str()).str());
|
||||
|
@ -625,7 +632,7 @@ bool FtpNegotiationCommand::sendTunnelRequest()
|
|||
util::itos(getCuid()).c_str(),
|
||||
_proxyAddr.c_str(), proxyReq->getPort());
|
||||
}
|
||||
dataSocket->establishConnection(_proxyAddr, proxyReq->getPort());
|
||||
_dataSocket->establishConnection(_proxyAddr, proxyReq->getPort());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -644,11 +651,11 @@ bool FtpNegotiationCommand::sendTunnelRequest()
|
|||
}
|
||||
if(_http->sendBufferIsEmpty()) {
|
||||
disableWriteCheckSocket();
|
||||
setReadCheckSocket(dataSocket);
|
||||
sequence = SEQ_RECV_TUNNEL_RESPONSE;
|
||||
setReadCheckSocket(_dataSocket);
|
||||
_sequence = SEQ_RECV_TUNNEL_RESPONSE;
|
||||
return false;
|
||||
} else {
|
||||
setWriteCheckSocket(dataSocket);
|
||||
setWriteCheckSocket(_dataSocket);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -662,29 +669,29 @@ bool FtpNegotiationCommand::recvTunnelResponse()
|
|||
if(httpResponse->getResponseStatus() != HttpHeader::S200) {
|
||||
throw DL_RETRY_EX(EX_PROXY_CONNECTION_FAILED);
|
||||
}
|
||||
sequence = SEQ_SEND_REST_PASV;
|
||||
_sequence = SEQ_SEND_REST_PASV;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendRestPasv(const SharedHandle<Segment>& segment) {
|
||||
//dataSocket->setBlockingMode();
|
||||
setReadCheckSocket(socket);
|
||||
//_dataSocket->setBlockingMode();
|
||||
setReadCheckSocket(getSocket());
|
||||
disableWriteCheckSocket();
|
||||
return sendRest(segment);
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendRest(const SharedHandle<Segment>& segment) {
|
||||
if(ftp->sendRest(segment)) {
|
||||
if(_ftp->sendRest(segment)) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_REST;
|
||||
_sequence = SEQ_RECV_REST;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvRest(const SharedHandle<Segment>& segment) {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -696,27 +703,27 @@ bool FtpNegotiationCommand::recvRest(const SharedHandle<Segment>& segment) {
|
|||
downloadresultcode::CANNOT_RESUME);
|
||||
}
|
||||
}
|
||||
sequence = SEQ_SEND_RETR;
|
||||
_sequence = SEQ_SEND_RETR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::sendRetr() {
|
||||
if(ftp->sendRetr()) {
|
||||
if(_ftp->sendRetr()) {
|
||||
disableWriteCheckSocket();
|
||||
sequence = SEQ_RECV_RETR;
|
||||
_sequence = SEQ_RECV_RETR;
|
||||
} else {
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::recvRetr() {
|
||||
unsigned int status = ftp->receiveResponse();
|
||||
unsigned int status = _ftp->receiveResponse();
|
||||
if(status == 0) {
|
||||
return false;
|
||||
}
|
||||
if(status != 150 && status != 125) {
|
||||
_requestGroup->increaseAndValidateFileNotFoundCount();
|
||||
getRequestGroup()->increaseAndValidateFileNotFoundCount();
|
||||
if (status == 550)
|
||||
throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND,
|
||||
downloadresultcode::RESOURCE_NOT_FOUND);
|
||||
|
@ -724,12 +731,12 @@ bool FtpNegotiationCommand::recvRetr() {
|
|||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, status).str());
|
||||
}
|
||||
if(getOption()->getAsBool(PREF_FTP_PASV)) {
|
||||
sequence = SEQ_NEGOTIATION_COMPLETED;
|
||||
_sequence = SEQ_NEGOTIATION_COMPLETED;
|
||||
return false;
|
||||
} else {
|
||||
disableReadCheckSocket();
|
||||
setReadCheckSocket(serverSocket);
|
||||
sequence = SEQ_WAIT_CONNECTION;
|
||||
setReadCheckSocket(_serverSocket);
|
||||
_sequence = SEQ_WAIT_CONNECTION;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -737,17 +744,17 @@ bool FtpNegotiationCommand::recvRetr() {
|
|||
bool FtpNegotiationCommand::waitConnection()
|
||||
{
|
||||
disableReadCheckSocket();
|
||||
setReadCheckSocket(socket);
|
||||
dataSocket.reset(serverSocket->acceptConnection());
|
||||
dataSocket->setNonBlockingMode();
|
||||
sequence = SEQ_NEGOTIATION_COMPLETED;
|
||||
setReadCheckSocket(getSocket());
|
||||
_dataSocket.reset(_serverSocket->acceptConnection());
|
||||
_dataSocket->setNonBlockingMode();
|
||||
_sequence = SEQ_NEGOTIATION_COMPLETED;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FtpNegotiationCommand::processSequence
|
||||
(const SharedHandle<Segment>& segment) {
|
||||
bool doNextSequence = true;
|
||||
switch(sequence) {
|
||||
switch(_sequence) {
|
||||
case SEQ_RECV_GREETING:
|
||||
return recvGreeting();
|
||||
case SEQ_SEND_USER:
|
||||
|
@ -816,16 +823,17 @@ void FtpNegotiationCommand::poolConnection() const
|
|||
{
|
||||
if(getOption()->getAsBool(PREF_FTP_REUSE_CONNECTION)) {
|
||||
std::map<std::string, std::string> options;
|
||||
options["baseWorkingDir"] = ftp->getBaseWorkingDir();
|
||||
e->poolSocket(req, ftp->getUser(), createProxyRequest(), socket, options);
|
||||
options["baseWorkingDir"] = _ftp->getBaseWorkingDir();
|
||||
getDownloadEngine()->poolSocket(getRequest(), _ftp->getUser(),
|
||||
createProxyRequest(), getSocket(), options);
|
||||
}
|
||||
}
|
||||
|
||||
void FtpNegotiationCommand::onDryRunFileFound()
|
||||
{
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
poolConnection();
|
||||
sequence = SEQ_HEAD_OK;
|
||||
_sequence = SEQ_HEAD_OK;
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -122,10 +122,10 @@ private:
|
|||
|
||||
void onDryRunFileFound();
|
||||
|
||||
SharedHandle<SocketCore> dataSocket;
|
||||
SharedHandle<SocketCore> serverSocket;
|
||||
Seq sequence;
|
||||
SharedHandle<FtpConnection> ftp;
|
||||
SharedHandle<SocketCore> _dataSocket;
|
||||
SharedHandle<SocketCore> _serverSocket;
|
||||
Seq _sequence;
|
||||
SharedHandle<FtpConnection> _ftp;
|
||||
// For tunneling
|
||||
SharedHandle<HttpConnection> _http;
|
||||
// IP, Port pair in pasv response
|
||||
|
|
|
@ -58,7 +58,8 @@ FtpTunnelRequestCommand::~FtpTunnelRequestCommand() {}
|
|||
Command* FtpTunnelRequestCommand::getNextCommand()
|
||||
{
|
||||
return new FtpTunnelResponseCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, httpConnection, e, socket);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
getHttpConnection(), getDownloadEngine(), getSocket());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -59,8 +59,9 @@ FtpTunnelResponseCommand::~FtpTunnelResponseCommand() {}
|
|||
|
||||
Command* FtpTunnelResponseCommand::getNextCommand()
|
||||
{
|
||||
return new FtpNegotiationCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e, socket);
|
||||
return new FtpNegotiationCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getDownloadEngine(),
|
||||
getSocket());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -71,29 +71,29 @@ HttpDownloadCommand::HttpDownloadCommand
|
|||
HttpDownloadCommand::~HttpDownloadCommand() {}
|
||||
|
||||
bool HttpDownloadCommand::prepareForNextSegment() {
|
||||
bool downloadFinished = _requestGroup->downloadFinished();
|
||||
if(req->isPipeliningEnabled() && !downloadFinished) {
|
||||
bool downloadFinished = getRequestGroup()->downloadFinished();
|
||||
if(getRequest()->isPipeliningEnabled() && !downloadFinished) {
|
||||
HttpRequestCommand* command =
|
||||
new HttpRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, _httpConnection, e,
|
||||
socket);
|
||||
new HttpRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), _httpConnection,
|
||||
getDownloadEngine(), getSocket());
|
||||
// Set proxy request here. aria2 sends the HTTP request specialized for
|
||||
// proxy.
|
||||
if(resolveProxyMethod(req->getProtocol()) == V_GET) {
|
||||
if(resolveProxyMethod(getRequest()->getProtocol()) == V_GET) {
|
||||
command->setProxyRequest(createProxyRequest());
|
||||
}
|
||||
e->addCommand(command);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
} else {
|
||||
if(req->isPipeliningEnabled() ||
|
||||
(req->isKeepAliveEnabled() &&
|
||||
if(getRequest()->isPipeliningEnabled() ||
|
||||
(getRequest()->isKeepAliveEnabled() &&
|
||||
(
|
||||
((!_transferEncodingDecoder.isNull() &&
|
||||
_transferEncodingDecoder->finished()) ||
|
||||
(!_contentEncodingDecoder.isNull() &&
|
||||
_contentEncodingDecoder->finished())) ||
|
||||
_fileEntry->getLastOffset() ==
|
||||
_segments.front()->getPositionToWrite()
|
||||
((!getTransferEncodingDecoder().isNull() &&
|
||||
getTransferEncodingDecoder()->finished()) ||
|
||||
(!getContentEncodingDecoder().isNull() &&
|
||||
getContentEncodingDecoder()->finished())) ||
|
||||
getFileEntry()->getLastOffset() ==
|
||||
getSegments().front()->getPositionToWrite()
|
||||
)
|
||||
)
|
||||
) {
|
||||
|
@ -102,20 +102,23 @@ bool HttpDownloadCommand::prepareForNextSegment() {
|
|||
// pool terminated socket. In HTTP/1.1, keep-alive is default,
|
||||
// so closing connection without Connection: close header means
|
||||
// that server is broken or not configured properly.
|
||||
e->poolSocket(req, createProxyRequest(), socket);
|
||||
getDownloadEngine()->poolSocket
|
||||
(getRequest(), createProxyRequest(), getSocket());
|
||||
}
|
||||
// The request was sent assuming that server supported pipelining, but
|
||||
// it turned out that server didn't support it.
|
||||
// We detect this situation by comparing the end byte in range header
|
||||
// of the response with the end byte of segment.
|
||||
// If it is the same, HTTP negotiation is necessary for the next request.
|
||||
if(!req->isPipeliningEnabled() && req->isPipeliningHint() &&
|
||||
if(!getRequest()->isPipeliningEnabled() &&
|
||||
getRequest()->isPipeliningHint() &&
|
||||
!downloadFinished) {
|
||||
const SharedHandle<Segment>& segment = _segments.front();
|
||||
const SharedHandle<Segment>& segment = getSegments().front();
|
||||
|
||||
off_t lastOffset =_fileEntry->gtoloff
|
||||
(std::min(static_cast<off_t>(segment->getPosition()+segment->getLength()),
|
||||
_fileEntry->getLastOffset()));
|
||||
off_t lastOffset =getFileEntry()->gtoloff
|
||||
(std::min(static_cast<off_t>
|
||||
(segment->getPosition()+segment->getLength()),
|
||||
getFileEntry()->getLastOffset()));
|
||||
|
||||
if(lastOffset ==
|
||||
_httpResponse->getHttpHeader()->getRange()->getEndByte()+1) {
|
||||
|
|
|
@ -73,32 +73,39 @@ Command* HttpInitiateConnectionCommand::createNextCommand
|
|||
Command* command;
|
||||
if(!proxyRequest.isNull()) {
|
||||
SharedHandle<SocketCore> pooledSocket =
|
||||
e->popPooledSocket(req->getHost(), req->getPort(),
|
||||
proxyRequest->getHost(), proxyRequest->getPort());
|
||||
std::string proxyMethod = resolveProxyMethod(req->getProtocol());
|
||||
getDownloadEngine()->popPooledSocket
|
||||
(getRequest()->getHost(), getRequest()->getPort(),
|
||||
proxyRequest->getHost(), proxyRequest->getPort());
|
||||
std::string proxyMethod = resolveProxyMethod(getRequest()->getProtocol());
|
||||
if(pooledSocket.isNull()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(MSG_CONNECTING_TO_SERVER,
|
||||
util::itos(getCuid()).c_str(), addr.c_str(), port);
|
||||
}
|
||||
socket.reset(new SocketCore());
|
||||
socket->establishConnection(addr, port);
|
||||
createSocket();
|
||||
getSocket()->establishConnection(addr, port);
|
||||
|
||||
if(proxyMethod == V_TUNNEL) {
|
||||
HttpProxyRequestCommand* c =
|
||||
new HttpProxyRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, e,
|
||||
proxyRequest, socket);
|
||||
new HttpProxyRequestCommand(getCuid(),
|
||||
getRequest(),
|
||||
getFileEntry(),
|
||||
getRequestGroup(),
|
||||
getDownloadEngine(),
|
||||
proxyRequest,
|
||||
getSocket());
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
command = c;
|
||||
} else if(proxyMethod == V_GET) {
|
||||
SharedHandle<HttpConnection> httpConnection
|
||||
(new HttpConnection(getCuid(), socket, getOption().get()));
|
||||
HttpRequestCommand* c = new HttpRequestCommand(getCuid(), req,
|
||||
_fileEntry,
|
||||
_requestGroup,
|
||||
httpConnection, e,
|
||||
socket);
|
||||
(new HttpConnection(getCuid(), getSocket(), getOption().get()));
|
||||
HttpRequestCommand* c = new HttpRequestCommand(getCuid(),
|
||||
getRequest(),
|
||||
getFileEntry(),
|
||||
getRequestGroup(),
|
||||
httpConnection,
|
||||
getDownloadEngine(),
|
||||
getSocket());
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
c->setProxyRequest(proxyRequest);
|
||||
command = c;
|
||||
|
@ -109,10 +116,12 @@ Command* HttpInitiateConnectionCommand::createNextCommand
|
|||
} else {
|
||||
SharedHandle<HttpConnection> httpConnection
|
||||
(new HttpConnection(getCuid(), pooledSocket, getOption().get()));
|
||||
HttpRequestCommand* c = new HttpRequestCommand(getCuid(), req,
|
||||
_fileEntry,
|
||||
_requestGroup,
|
||||
httpConnection, e,
|
||||
HttpRequestCommand* c = new HttpRequestCommand(getCuid(),
|
||||
getRequest(),
|
||||
getFileEntry(),
|
||||
getRequestGroup(),
|
||||
httpConnection,
|
||||
getDownloadEngine(),
|
||||
pooledSocket);
|
||||
if(proxyMethod == V_GET) {
|
||||
c->setProxyRequest(proxyRequest);
|
||||
|
@ -121,22 +130,26 @@ Command* HttpInitiateConnectionCommand::createNextCommand
|
|||
}
|
||||
} else {
|
||||
SharedHandle<SocketCore> pooledSocket =
|
||||
e->popPooledSocket(resolvedAddresses, req->getPort());
|
||||
getDownloadEngine()->popPooledSocket
|
||||
(resolvedAddresses, getRequest()->getPort());
|
||||
if(pooledSocket.isNull()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(MSG_CONNECTING_TO_SERVER,
|
||||
util::itos(getCuid()).c_str(), addr.c_str(), port);
|
||||
}
|
||||
socket.reset(new SocketCore());
|
||||
socket->establishConnection(addr, port);
|
||||
createSocket();
|
||||
getSocket()->establishConnection(addr, port);
|
||||
} else {
|
||||
socket = pooledSocket;
|
||||
setSocket(pooledSocket);
|
||||
}
|
||||
SharedHandle<HttpConnection> httpConnection
|
||||
(new HttpConnection(getCuid(), socket, getOption().get()));
|
||||
(new HttpConnection(getCuid(), getSocket(), getOption().get()));
|
||||
HttpRequestCommand* c =
|
||||
new HttpRequestCommand(getCuid(), req, _fileEntry, _requestGroup,
|
||||
httpConnection, e, socket);
|
||||
new HttpRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(),
|
||||
httpConnection,
|
||||
getDownloadEngine(),
|
||||
getSocket());
|
||||
if(pooledSocket.isNull()) {
|
||||
c->setConnectedAddr(hostname, addr, port);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,8 @@ HttpProxyRequestCommand::~HttpProxyRequestCommand() {}
|
|||
Command* HttpProxyRequestCommand::getNextCommand()
|
||||
{
|
||||
return new HttpProxyResponseCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, httpConnection, e, socket);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
getHttpConnection(), getDownloadEngine(), getSocket());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -59,8 +59,9 @@ HttpProxyResponseCommand::~HttpProxyResponseCommand() {}
|
|||
|
||||
Command* HttpProxyResponseCommand::getNextCommand()
|
||||
{
|
||||
return new HttpRequestCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup, httpConnection, e, socket);
|
||||
return new HttpRequestCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(), getHttpConnection(),
|
||||
getDownloadEngine(), getSocket());
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -73,7 +73,7 @@ HttpRequestCommand::HttpRequestCommand
|
|||
{
|
||||
setTimeout(getOption()->getAsInt(PREF_CONNECT_TIMEOUT));
|
||||
disableReadCheckSocket();
|
||||
setWriteCheckSocket(socket);
|
||||
setWriteCheckSocket(getSocket());
|
||||
}
|
||||
|
||||
HttpRequestCommand::~HttpRequestCommand() {}
|
||||
|
@ -115,47 +115,48 @@ createHttpRequest(const SharedHandle<Request>& req,
|
|||
|
||||
bool HttpRequestCommand::executeInternal() {
|
||||
//socket->setBlockingMode();
|
||||
if(req->getProtocol() == Request::PROTO_HTTPS) {
|
||||
socket->prepareSecureConnection();
|
||||
if(!socket->initiateSecureConnection(req->getHost())) {
|
||||
setReadCheckSocketIf(socket, socket->wantRead());
|
||||
setWriteCheckSocketIf(socket, socket->wantWrite());
|
||||
e->addCommand(this);
|
||||
if(getRequest()->getProtocol() == Request::PROTO_HTTPS) {
|
||||
getSocket()->prepareSecureConnection();
|
||||
if(!getSocket()->initiateSecureConnection(getRequest()->getHost())) {
|
||||
setReadCheckSocketIf(getSocket(), getSocket()->wantRead());
|
||||
setWriteCheckSocketIf(getSocket(), getSocket()->wantWrite());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(_httpConnection->sendBufferIsEmpty()) {
|
||||
if(!checkIfConnectionEstablished
|
||||
(socket, _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
(getSocket(), _connectedHostname, _connectedAddr, _connectedPort)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(_segments.empty()) {
|
||||
if(getSegments().empty()) {
|
||||
SharedHandle<HttpRequest> httpRequest
|
||||
(createHttpRequest(req,
|
||||
_fileEntry,
|
||||
(createHttpRequest(getRequest(),
|
||||
getFileEntry(),
|
||||
SharedHandle<Segment>(),
|
||||
_requestGroup->getTotalLength(),
|
||||
getRequestGroup()->getTotalLength(),
|
||||
getOption(),
|
||||
_requestGroup,
|
||||
e->getCookieStorage(),
|
||||
e->getAuthConfigFactory(),
|
||||
getRequestGroup(),
|
||||
getDownloadEngine()->getCookieStorage(),
|
||||
getDownloadEngine()->getAuthConfigFactory(),
|
||||
_proxyRequest));
|
||||
_httpConnection->sendRequest(httpRequest);
|
||||
} else {
|
||||
for(std::vector<SharedHandle<Segment> >::const_iterator itr =
|
||||
_segments.begin(), eoi = _segments.end(); itr != eoi; ++itr) {
|
||||
getSegments().begin(), eoi = getSegments().end();
|
||||
itr != eoi; ++itr) {
|
||||
const SharedHandle<Segment>& segment = *itr;
|
||||
if(!_httpConnection->isIssued(segment)) {
|
||||
SharedHandle<HttpRequest> httpRequest
|
||||
(createHttpRequest(req,
|
||||
_fileEntry,
|
||||
(createHttpRequest(getRequest(),
|
||||
getFileEntry(),
|
||||
segment,
|
||||
_requestGroup->getTotalLength(),
|
||||
getRequestGroup()->getTotalLength(),
|
||||
getOption(),
|
||||
_requestGroup,
|
||||
e->getCookieStorage(),
|
||||
e->getAuthConfigFactory(),
|
||||
getRequestGroup(),
|
||||
getDownloadEngine()->getCookieStorage(),
|
||||
getDownloadEngine()->getAuthConfigFactory(),
|
||||
_proxyRequest));
|
||||
_httpConnection->sendRequest(httpRequest);
|
||||
}
|
||||
|
@ -165,15 +166,19 @@ bool HttpRequestCommand::executeInternal() {
|
|||
_httpConnection->sendPendingData();
|
||||
}
|
||||
if(_httpConnection->sendBufferIsEmpty()) {
|
||||
Command* command = new HttpResponseCommand(getCuid(), req, _fileEntry,
|
||||
_requestGroup,
|
||||
_httpConnection, e, socket);
|
||||
e->addCommand(command);
|
||||
Command* command = new HttpResponseCommand(getCuid(),
|
||||
getRequest(),
|
||||
getFileEntry(),
|
||||
getRequestGroup(),
|
||||
_httpConnection,
|
||||
getDownloadEngine(),
|
||||
getSocket());
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
} else {
|
||||
setReadCheckSocketIf(socket, socket->wantRead());
|
||||
setWriteCheckSocketIf(socket, socket->wantWrite());
|
||||
e->addCommand(this);
|
||||
setReadCheckSocketIf(getSocket(), getSocket()->wantRead());
|
||||
setWriteCheckSocketIf(getSocket(), getSocket()->wantWrite());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,21 +87,21 @@ HttpResponseCommand::HttpResponseCommand
|
|||
DownloadEngine* e,
|
||||
const SocketHandle& s)
|
||||
:AbstractCommand(cuid, req, fileEntry, requestGroup, e, s),
|
||||
httpConnection(httpConnection)
|
||||
_httpConnection(httpConnection)
|
||||
{}
|
||||
|
||||
HttpResponseCommand::~HttpResponseCommand() {}
|
||||
|
||||
bool HttpResponseCommand::executeInternal()
|
||||
{
|
||||
SharedHandle<HttpRequest> httpRequest = httpConnection->getFirstHttpRequest();
|
||||
SharedHandle<HttpResponse> httpResponse = httpConnection->receiveResponse();
|
||||
SharedHandle<HttpRequest> httpRequest =_httpConnection->getFirstHttpRequest();
|
||||
SharedHandle<HttpResponse> httpResponse = _httpConnection->receiveResponse();
|
||||
if(httpResponse.isNull()) {
|
||||
// The server has not responded to our request yet.
|
||||
// For socket->wantRead() == true, setReadCheckSocket(socket) is already
|
||||
// done in the constructor.
|
||||
setWriteCheckSocketIf(socket, socket->wantWrite());
|
||||
e->addCommand(this);
|
||||
setWriteCheckSocketIf(getSocket(), getSocket()->wantWrite());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
// check HTTP status number
|
||||
|
@ -112,39 +112,40 @@ bool HttpResponseCommand::executeInternal()
|
|||
// Disable persistent connection if:
|
||||
// Connection: close is received or the remote server is not HTTP/1.1.
|
||||
// We don't care whether non-HTTP/1.1 server returns Connection: keep-alive.
|
||||
req->supportsPersistentConnection
|
||||
getRequest()->supportsPersistentConnection
|
||||
(httpResponse->supportsPersistentConnection());
|
||||
if(req->isPipeliningEnabled()) {
|
||||
req->setMaxPipelinedRequest
|
||||
if(getRequest()->isPipeliningEnabled()) {
|
||||
getRequest()->setMaxPipelinedRequest
|
||||
(getOption()->getAsInt(PREF_MAX_HTTP_PIPELINING));
|
||||
}
|
||||
|
||||
if(httpResponse->getResponseStatus() >= HttpHeader::S300) {
|
||||
if(httpResponse->getResponseStatus() == HttpHeader::S404) {
|
||||
_requestGroup->increaseAndValidateFileNotFoundCount();
|
||||
getRequestGroup()->increaseAndValidateFileNotFoundCount();
|
||||
}
|
||||
return skipResponseBody(httpResponse);
|
||||
}
|
||||
if(!_fileEntry->isSingleHostMultiConnectionEnabled()) {
|
||||
if(!getFileEntry()->isSingleHostMultiConnectionEnabled()) {
|
||||
// TODO redirection should be considered here. We need to parse
|
||||
// original URI to get hostname.
|
||||
_fileEntry->removeURIWhoseHostnameIs(req->getHost());
|
||||
getFileEntry()->removeURIWhoseHostnameIs(getRequest()->getHost());
|
||||
}
|
||||
if(_requestGroup->getPieceStorage().isNull()) {
|
||||
if(getPieceStorage().isNull()) {
|
||||
uint64_t totalLength = httpResponse->getEntityLength();
|
||||
_fileEntry->setLength(totalLength);
|
||||
if(_fileEntry->getPath().empty()) {
|
||||
_fileEntry->setPath
|
||||
getFileEntry()->setLength(totalLength);
|
||||
if(getFileEntry()->getPath().empty()) {
|
||||
getFileEntry()->setPath
|
||||
(util::applyDir
|
||||
(getDownloadContext()->getDir(),
|
||||
util::fixTaintedBasename(httpResponse->determinFilename())));
|
||||
}
|
||||
_fileEntry->setContentType(httpResponse->getContentType());
|
||||
_requestGroup->preDownloadProcessing();
|
||||
if(e->getRequestGroupMan()->isSameFileBeingDownloaded(_requestGroup)) {
|
||||
getFileEntry()->setContentType(httpResponse->getContentType());
|
||||
getRequestGroup()->preDownloadProcessing();
|
||||
if(getDownloadEngine()->getRequestGroupMan()->
|
||||
isSameFileBeingDownloaded(getRequestGroup())) {
|
||||
throw DOWNLOAD_FAILURE_EXCEPTION
|
||||
(StringFormat(EX_DUPLICATE_FILE_DOWNLOAD,
|
||||
_requestGroup->getFirstFilePath().c_str()).str());
|
||||
getRequestGroup()->getFirstFilePath().c_str()).str());
|
||||
}
|
||||
// update last modified time
|
||||
updateLastModifiedTime(httpResponse->getLastModifiedTime());
|
||||
|
@ -153,8 +154,8 @@ bool HttpResponseCommand::executeInternal()
|
|||
// assume we can do segmented downloading
|
||||
if(totalLength == 0 || shouldInflateContentEncoding(httpResponse)) {
|
||||
// we ignore content-length when inflate is required
|
||||
_fileEntry->setLength(0);
|
||||
if(req->getMethod() == Request::METHOD_GET &&
|
||||
getFileEntry()->setLength(0);
|
||||
if(getRequest()->getMethod() == Request::METHOD_GET &&
|
||||
(totalLength != 0 ||
|
||||
!httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH))){
|
||||
// DownloadContext::knowsTotalLength() == true only when
|
||||
|
@ -167,22 +168,22 @@ bool HttpResponseCommand::executeInternal()
|
|||
}
|
||||
} else {
|
||||
// validate totalsize
|
||||
_requestGroup->validateTotalLength(_fileEntry->getLength(),
|
||||
getRequestGroup()->validateTotalLength(getFileEntry()->getLength(),
|
||||
httpResponse->getEntityLength());
|
||||
// update last modified time
|
||||
updateLastModifiedTime(httpResponse->getLastModifiedTime());
|
||||
if(_requestGroup->getTotalLength() == 0) {
|
||||
if(getRequestGroup()->getTotalLength() == 0) {
|
||||
// Since total length is unknown, the file size in previously
|
||||
// failed download could be larger than the size this time.
|
||||
// Also we can't resume in this case too. So truncate the file
|
||||
// anyway.
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->truncate(0);
|
||||
e->addCommand
|
||||
getPieceStorage()->getDiskAdaptor()->truncate(0);
|
||||
getDownloadEngine()->addCommand
|
||||
(createHttpDownloadCommand(httpResponse,
|
||||
getTransferEncodingDecoder(httpResponse),
|
||||
getContentEncodingDecoder(httpResponse)));
|
||||
} else {
|
||||
e->addCommand(createHttpDownloadCommand
|
||||
getDownloadEngine()->addCommand(createHttpDownloadCommand
|
||||
(httpResponse, getTransferEncodingDecoder(httpResponse)));
|
||||
}
|
||||
return true;
|
||||
|
@ -192,7 +193,7 @@ bool HttpResponseCommand::executeInternal()
|
|||
void HttpResponseCommand::updateLastModifiedTime(const Time& lastModified)
|
||||
{
|
||||
if(getOption()->getAsBool(PREF_REMOTE_TIME)) {
|
||||
_requestGroup->updateLastModifiedTime(lastModified);
|
||||
getRequestGroup()->updateLastModifiedTime(lastModified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,12 +216,12 @@ bool HttpResponseCommand::handleDefaultEncoding
|
|||
(const SharedHandle<HttpResponse>& httpResponse)
|
||||
{
|
||||
SharedHandle<HttpRequest> httpRequest = httpResponse->getHttpRequest();
|
||||
_requestGroup->adjustFilename
|
||||
getRequestGroup()->adjustFilename
|
||||
(SharedHandle<BtProgressInfoFile>(new DefaultBtProgressInfoFile
|
||||
(_requestGroup->getDownloadContext(),
|
||||
(getDownloadContext(),
|
||||
SharedHandle<PieceStorage>(),
|
||||
getOption().get())));
|
||||
_requestGroup->initPieceStorage();
|
||||
getRequestGroup()->initPieceStorage();
|
||||
|
||||
if(getOption()->getAsBool(PREF_DRY_RUN)) {
|
||||
onDryRunFileFound();
|
||||
|
@ -228,47 +229,44 @@ bool HttpResponseCommand::handleDefaultEncoding
|
|||
}
|
||||
|
||||
BtProgressInfoFileHandle infoFile
|
||||
(new DefaultBtProgressInfoFile(_requestGroup->getDownloadContext(),
|
||||
_requestGroup->getPieceStorage(),
|
||||
(new DefaultBtProgressInfoFile(getDownloadContext(),
|
||||
getPieceStorage(),
|
||||
getOption().get()));
|
||||
if(!infoFile->exists() && _requestGroup->downloadFinishedByFileLength()) {
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
|
||||
if(!infoFile->exists() && getRequestGroup()->downloadFinishedByFileLength()) {
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
getLogger()->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
||||
util::itos(_requestGroup->getGID()).c_str(),
|
||||
_requestGroup->getFirstFilePath().c_str());
|
||||
|
||||
util::itos(getRequestGroup()->getGID()).c_str(),
|
||||
getRequestGroup()->getFirstFilePath().c_str());
|
||||
return true;
|
||||
}
|
||||
_requestGroup->loadAndOpenFile(infoFile);
|
||||
File file(_requestGroup->getFirstFilePath());
|
||||
getRequestGroup()->loadAndOpenFile(infoFile);
|
||||
File file(getRequestGroup()->getFirstFilePath());
|
||||
// We have to make sure that command that has Request object must
|
||||
// have segment after PieceStorage is initialized. See
|
||||
// AbstractCommand::execute()
|
||||
SharedHandle<Segment> segment =
|
||||
_requestGroup->getSegmentMan()->getSegment(getCuid(), 0);
|
||||
SharedHandle<Segment> segment = getSegmentMan()->getSegment(getCuid(), 0);
|
||||
// pipelining requires implicit range specified. But the request for
|
||||
// this response most likely dones't contains range header. This means
|
||||
// we can't continue to use this socket because server sends all entity
|
||||
// body instead of a segment.
|
||||
// Therefore, we shutdown the socket here if pipelining is enabled.
|
||||
DownloadCommand* command = 0;
|
||||
if(req->getMethod() == Request::METHOD_GET &&
|
||||
if(getRequest()->getMethod() == Request::METHOD_GET &&
|
||||
!segment.isNull() && segment->getPositionToWrite() == 0 &&
|
||||
!req->isPipeliningEnabled()) {
|
||||
!getRequest()->isPipeliningEnabled()) {
|
||||
command = createHttpDownloadCommand
|
||||
(httpResponse, getTransferEncodingDecoder(httpResponse));
|
||||
} else {
|
||||
_requestGroup->getSegmentMan()->cancelSegment(getCuid());
|
||||
_fileEntry->poolRequest(req);
|
||||
getSegmentMan()->cancelSegment(getCuid());
|
||||
getFileEntry()->poolRequest(getRequest());
|
||||
}
|
||||
// After command is passed to prepareForNextAction(), it is managed
|
||||
// by CheckIntegrityEntry.
|
||||
prepareForNextAction(command);
|
||||
command = 0;
|
||||
if(req->getMethod() == Request::METHOD_HEAD) {
|
||||
if(getRequest()->getMethod() == Request::METHOD_HEAD) {
|
||||
poolConnection();
|
||||
req->setMethod(Request::METHOD_GET);
|
||||
getRequest()->setMethod(Request::METHOD_GET);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -314,47 +312,43 @@ bool HttpResponseCommand::handleOtherEncoding
|
|||
SharedHandle<HttpRequest> httpRequest = httpResponse->getHttpRequest();
|
||||
|
||||
if(getOption()->getAsBool(PREF_DRY_RUN)) {
|
||||
_requestGroup->initPieceStorage();
|
||||
getRequestGroup()->initPieceStorage();
|
||||
onDryRunFileFound();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(req->getMethod() == Request::METHOD_HEAD) {
|
||||
if(getRequest()->getMethod() == Request::METHOD_HEAD) {
|
||||
poolConnection();
|
||||
req->setMethod(Request::METHOD_GET);
|
||||
getRequest()->setMethod(Request::METHOD_GET);
|
||||
return prepareForRetry(0);
|
||||
}
|
||||
|
||||
// For zero-length file, check existing file comparing its size
|
||||
if(_requestGroup->downloadFinishedByFileLength()) {
|
||||
_requestGroup->initPieceStorage();
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
|
||||
if(getRequestGroup()->downloadFinishedByFileLength()) {
|
||||
getRequestGroup()->initPieceStorage();
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
getLogger()->notice(MSG_DOWNLOAD_ALREADY_COMPLETED,
|
||||
util::itos(_requestGroup->getGID()).c_str(),
|
||||
_requestGroup->getFirstFilePath().c_str());
|
||||
|
||||
util::itos(getRequestGroup()->getGID()).c_str(),
|
||||
getRequestGroup()->getFirstFilePath().c_str());
|
||||
poolConnection();
|
||||
return true;
|
||||
}
|
||||
|
||||
_requestGroup->shouldCancelDownloadForSafety();
|
||||
_requestGroup->initPieceStorage();
|
||||
|
||||
_requestGroup->getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
|
||||
|
||||
getRequestGroup()->shouldCancelDownloadForSafety();
|
||||
getRequestGroup()->initPieceStorage();
|
||||
getPieceStorage()->getDiskAdaptor()->initAndOpenFile();
|
||||
// In this context, knowsTotalLength() is true only when the file is
|
||||
// really zero-length.
|
||||
if(_requestGroup->getDownloadContext()->knowsTotalLength()) {
|
||||
if(getDownloadContext()->knowsTotalLength()) {
|
||||
poolConnection();
|
||||
return true;
|
||||
}
|
||||
// We have to make sure that command that has Request object must
|
||||
// have segment after PieceStorage is initialized. See
|
||||
// AbstractCommand::execute()
|
||||
_requestGroup->getSegmentMan()->getSegment(getCuid(), 0);
|
||||
getSegmentMan()->getSegment(getCuid(), 0);
|
||||
|
||||
e->addCommand
|
||||
getDownloadEngine()->addCommand
|
||||
(createHttpDownloadCommand(httpResponse,
|
||||
getTransferEncodingDecoder(httpResponse),
|
||||
getContentEncodingDecoder(httpResponse)));
|
||||
|
@ -369,22 +363,23 @@ bool HttpResponseCommand::skipResponseBody
|
|||
// thrown away.
|
||||
|
||||
HttpSkipResponseCommand* command = new HttpSkipResponseCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, httpConnection, httpResponse,
|
||||
e, socket);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
_httpConnection, httpResponse,
|
||||
getDownloadEngine(), getSocket());
|
||||
command->setTransferEncodingDecoder(decoder);
|
||||
|
||||
// If request method is HEAD or the response body is zero-length,
|
||||
// set command's status to real time so that avoid read check blocking
|
||||
if(req->getMethod() == Request::METHOD_HEAD ||
|
||||
if(getRequest()->getMethod() == Request::METHOD_HEAD ||
|
||||
(httpResponse->getEntityLength() == 0 &&
|
||||
!httpResponse->isTransferEncodingSpecified())) {
|
||||
command->setStatusRealtime();
|
||||
// If entity length == 0, then socket read/write check must be disabled.
|
||||
command->disableSocketCheck();
|
||||
e->setNoWait(true);
|
||||
getDownloadEngine()->setNoWait(true);
|
||||
}
|
||||
|
||||
e->addCommand(command);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -395,8 +390,10 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand
|
|||
{
|
||||
|
||||
HttpDownloadCommand* command =
|
||||
new HttpDownloadCommand(getCuid(), req, _fileEntry, _requestGroup,
|
||||
httpResponse, httpConnection, e, socket);
|
||||
new HttpDownloadCommand(getCuid(), getRequest(), getFileEntry(),
|
||||
getRequestGroup(),
|
||||
httpResponse, _httpConnection,
|
||||
getDownloadEngine(), getSocket());
|
||||
command->setStartupIdleTime(getOption()->getAsInt(PREF_STARTUP_IDLE_TIME));
|
||||
command->setLowestDownloadSpeedLimit
|
||||
(getOption()->getAsInt(PREF_LOWEST_SPEED_LIMIT));
|
||||
|
@ -407,25 +404,26 @@ HttpDownloadCommand* HttpResponseCommand::createHttpDownloadCommand
|
|||
// Since the compressed file's length are returned in the response header
|
||||
// and the decompressed file size is unknown at this point, disable file
|
||||
// allocation here.
|
||||
_requestGroup->setFileAllocationEnabled(false);
|
||||
getRequestGroup()->setFileAllocationEnabled(false);
|
||||
}
|
||||
|
||||
_requestGroup->getURISelector()->tuneDownloadCommand
|
||||
(_fileEntry->getRemainingUris(), command);
|
||||
getRequestGroup()->getURISelector()->tuneDownloadCommand
|
||||
(getFileEntry()->getRemainingUris(), command);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
void HttpResponseCommand::poolConnection()
|
||||
{
|
||||
if(req->supportsPersistentConnection()) {
|
||||
e->poolSocket(req, createProxyRequest(), socket);
|
||||
if(getRequest()->supportsPersistentConnection()) {
|
||||
getDownloadEngine()->poolSocket(getRequest(), createProxyRequest(),
|
||||
getSocket());
|
||||
}
|
||||
}
|
||||
|
||||
void HttpResponseCommand::onDryRunFileFound()
|
||||
{
|
||||
_requestGroup->getPieceStorage()->markAllPiecesDone();
|
||||
getPieceStorage()->markAllPiecesDone();
|
||||
poolConnection();
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class SocketCore;
|
|||
|
||||
class HttpResponseCommand : public AbstractCommand {
|
||||
private:
|
||||
SharedHandle<HttpConnection> httpConnection;
|
||||
SharedHandle<HttpConnection> _httpConnection;
|
||||
|
||||
bool handleDefaultEncoding(const SharedHandle<HttpResponse>& httpResponse);
|
||||
bool handleOtherEncoding(const SharedHandle<HttpResponse>& httpResponse);
|
||||
|
|
|
@ -87,13 +87,13 @@ void HttpSkipResponseCommand::setTransferEncodingDecoder
|
|||
|
||||
bool HttpSkipResponseCommand::executeInternal()
|
||||
{
|
||||
if(req->getMethod() == Request::METHOD_HEAD ||
|
||||
if(getRequest()->getMethod() == Request::METHOD_HEAD ||
|
||||
(_totalLength == 0 && _transferEncodingDecoder.isNull())) {
|
||||
// If request method is HEAD or content-length header is present and
|
||||
// it's value is 0, then pool socket for reuse.
|
||||
// If content-length header is not present, then EOF is expected in the end.
|
||||
// In this case, the content is thrown away and socket cannot be pooled.
|
||||
if(req->getMethod() == Request::METHOD_HEAD ||
|
||||
if(getRequest()->getMethod() == Request::METHOD_HEAD ||
|
||||
_httpResponse->getHttpHeader()->defined(HttpHeader::CONTENT_LENGTH)) {
|
||||
poolConnection();
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ bool HttpSkipResponseCommand::executeInternal()
|
|||
size_t bufSize = BUFSIZE;
|
||||
|
||||
try {
|
||||
socket->readData(buf, bufSize);
|
||||
getSocket()->readData(buf, bufSize);
|
||||
|
||||
if(_transferEncodingDecoder.isNull()) {
|
||||
_receivedBytes += bufSize;
|
||||
|
@ -114,7 +114,7 @@ bool HttpSkipResponseCommand::executeInternal()
|
|||
_transferEncodingDecoder->decode(buf, bufSize);
|
||||
}
|
||||
if(_totalLength != 0 && bufSize == 0 &&
|
||||
!socket->wantRead() && !socket->wantWrite()) {
|
||||
!getSocket()->wantRead() && !getSocket()->wantWrite()) {
|
||||
throw DL_RETRY_EX(EX_GOT_EOF);
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
|
@ -127,7 +127,7 @@ bool HttpSkipResponseCommand::executeInternal()
|
|||
bool finished = false;
|
||||
if(_transferEncodingDecoder.isNull()) {
|
||||
if(bufSize == 0) {
|
||||
if(!socket->wantRead() && !socket->wantWrite()) {
|
||||
if(!getSocket()->wantRead() && !getSocket()->wantWrite()) {
|
||||
return processResponse();
|
||||
}
|
||||
} else {
|
||||
|
@ -140,16 +140,17 @@ bool HttpSkipResponseCommand::executeInternal()
|
|||
poolConnection();
|
||||
return processResponse();
|
||||
} else {
|
||||
setWriteCheckSocketIf(socket, socket->wantWrite());
|
||||
e->addCommand(this);
|
||||
setWriteCheckSocketIf(getSocket(), getSocket()->wantWrite());
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void HttpSkipResponseCommand::poolConnection() const
|
||||
{
|
||||
if(req->supportsPersistentConnection()) {
|
||||
e->poolSocket(req, createProxyRequest(), socket);
|
||||
if(getRequest()->supportsPersistentConnection()) {
|
||||
getDownloadEngine()->poolSocket
|
||||
(getRequest(), createProxyRequest(), getSocket());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +160,8 @@ bool HttpSkipResponseCommand::processResponse()
|
|||
unsigned int rnum =
|
||||
_httpResponse->getHttpRequest()->getRequest()->getRedirectCount();
|
||||
if(rnum >= Request::MAX_REDIRECT) {
|
||||
throw DL_ABORT_EX(StringFormat("Too many redirects: count=%u", rnum).str());
|
||||
throw DL_ABORT_EX
|
||||
(StringFormat("Too many redirects: count=%u", rnum).str());
|
||||
}
|
||||
_httpResponse->processRedirect();
|
||||
return prepareForRetry(0);
|
||||
|
@ -167,8 +169,8 @@ bool HttpSkipResponseCommand::processResponse()
|
|||
if(_httpResponse->getResponseStatus() == HttpHeader::S401) {
|
||||
if(getOption()->getAsBool(PREF_HTTP_AUTH_CHALLENGE) &&
|
||||
!_httpResponse->getHttpRequest()->authenticationUsed() &&
|
||||
e->getAuthConfigFactory()->activateBasicCred
|
||||
(req->getHost(), req->getDir(), getOption().get())) {
|
||||
getDownloadEngine()->getAuthConfigFactory()->activateBasicCred
|
||||
(getRequest()->getHost(), getRequest()->getDir(), getOption().get())) {
|
||||
return prepareForRetry(0);
|
||||
} else {
|
||||
throw DL_ABORT_EX(EX_AUTH_FAILED);
|
||||
|
@ -177,7 +179,10 @@ bool HttpSkipResponseCommand::processResponse()
|
|||
throw DL_ABORT_EX2(MSG_RESOURCE_NOT_FOUND,
|
||||
downloadresultcode::RESOURCE_NOT_FOUND);
|
||||
} else {
|
||||
throw DL_ABORT_EX(StringFormat(EX_BAD_STATUS, util::parseUInt(_httpResponse->getResponseStatus())).str());
|
||||
throw DL_ABORT_EX
|
||||
(StringFormat
|
||||
(EX_BAD_STATUS,
|
||||
util::parseUInt(_httpResponse->getResponseStatus())).str());
|
||||
}
|
||||
} else {
|
||||
return prepareForRetry(0);
|
||||
|
|
|
@ -77,8 +77,8 @@ bool InitiateConnectionCommand::executeInternal() {
|
|||
uint16_t port;
|
||||
SharedHandle<Request> proxyRequest = createProxyRequest();
|
||||
if(proxyRequest.isNull()) {
|
||||
hostname = req->getHost();
|
||||
port = req->getPort();
|
||||
hostname = getRequest()->getHost();
|
||||
port = getRequest()->getPort();
|
||||
} else {
|
||||
hostname = proxyRequest->getHost();
|
||||
port = proxyRequest->getPort();
|
||||
|
@ -86,21 +86,21 @@ bool InitiateConnectionCommand::executeInternal() {
|
|||
std::vector<std::string> addrs;
|
||||
std::string ipaddr = resolveHostname(addrs, hostname, port);
|
||||
if(ipaddr.empty()) {
|
||||
e->addCommand(this);
|
||||
getDownloadEngine()->addCommand(this);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Command* command = createNextCommand(hostname, ipaddr, port,
|
||||
addrs, proxyRequest);
|
||||
e->addCommand(command);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
} catch(RecoverableException& ex) {
|
||||
// Catch exception and retry another address.
|
||||
// See also AbstractCommand::checkIfConnectionEstablished
|
||||
|
||||
// TODO ipaddr might not be used if pooled sockt was found.
|
||||
e->markBadIPAddress(hostname, ipaddr, port);
|
||||
if(!e->findCachedIPAddress(hostname, port).empty()) {
|
||||
getDownloadEngine()->markBadIPAddress(hostname, ipaddr, port);
|
||||
if(!getDownloadEngine()->findCachedIPAddress(hostname, port).empty()) {
|
||||
if(getLogger()->info()) {
|
||||
getLogger()->info(EX_EXCEPTION_CAUGHT, ex);
|
||||
getLogger()->info(MSG_CONNECT_FAILED_AND_RETRY,
|
||||
|
@ -108,12 +108,13 @@ bool InitiateConnectionCommand::executeInternal() {
|
|||
}
|
||||
Command* command =
|
||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand
|
||||
(getCuid(), req, _fileEntry, _requestGroup, e);
|
||||
e->setNoWait(true);
|
||||
e->addCommand(command);
|
||||
(getCuid(), getRequest(), getFileEntry(), getRequestGroup(),
|
||||
getDownloadEngine());
|
||||
getDownloadEngine()->setNoWait(true);
|
||||
getDownloadEngine()->addCommand(command);
|
||||
return true;
|
||||
}
|
||||
e->removeCachedIPAddress(hostname, port);
|
||||
getDownloadEngine()->removeCachedIPAddress(hostname, port);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue