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