mirror of https://github.com/aria2/aria2
2010-05-21 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Fixed the bug that FTP download may fail when control connection is reused. This happens because FTP server can offer different root directory for different account. If pooled connections has different root directory, then download will fail. * src/DownloadEngine.cc * src/DownloadEngine.h * src/FtpConnection.cc * src/FtpConnection.h * src/FtpFinishDownloadCommand.cc * src/FtpInitiateConnectionCommand.cc * src/FtpNegotiationCommand.ccpull/1/head
parent
8f3cdfb2de
commit
47adbe618c
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2010-05-21 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Fixed the bug that FTP download may fail when control connection
|
||||
is reused. This happens because FTP server can offer different
|
||||
root directory for different account. If pooled connections has
|
||||
different root directory, then download will fail.
|
||||
* src/DownloadEngine.cc
|
||||
* src/DownloadEngine.h
|
||||
* src/FtpConnection.cc
|
||||
* src/FtpConnection.h
|
||||
* src/FtpFinishDownloadCommand.cc
|
||||
* src/FtpInitiateConnectionCommand.cc
|
||||
* src/FtpNegotiationCommand.cc
|
||||
|
||||
2010-05-20 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
|
||||
|
||||
Removed DownloadResult's ctor because it has many args.
|
||||
|
|
|
@ -309,15 +309,26 @@ void DownloadEngine::poolSocket(const std::string& ipaddr,
|
|||
}
|
||||
}
|
||||
|
||||
static std::string createSockPoolKey
|
||||
(const std::string& host, const std::string& username)
|
||||
{
|
||||
std::string key;
|
||||
key += util::percentEncode(username);
|
||||
key += '@';
|
||||
key += host;
|
||||
return key;
|
||||
}
|
||||
|
||||
void DownloadEngine::poolSocket
|
||||
(const std::string& ipaddr,
|
||||
uint16_t port,
|
||||
const std::string& username,
|
||||
const SharedHandle<SocketCore>& sock,
|
||||
const std::map<std::string, std::string>& options,
|
||||
time_t timeout)
|
||||
{
|
||||
SocketPoolEntry e(sock, options, timeout);
|
||||
poolSocket(ipaddr, port, e);
|
||||
poolSocket(createSockPoolKey(ipaddr, username), port, e);
|
||||
}
|
||||
|
||||
void DownloadEngine::poolSocket
|
||||
|
@ -326,7 +337,7 @@ void DownloadEngine::poolSocket
|
|||
const SharedHandle<SocketCore>& sock,
|
||||
time_t timeout)
|
||||
{
|
||||
SocketPoolEntry e(sock, std::map<std::string, std::string>(), timeout);
|
||||
SocketPoolEntry e(sock, timeout);
|
||||
poolSocket(ipaddr, port, e);
|
||||
}
|
||||
|
||||
|
@ -337,28 +348,31 @@ void DownloadEngine::poolSocket(const SharedHandle<Request>& request,
|
|||
{
|
||||
if(proxyDefined) {
|
||||
// If proxy is defined, then pool socket with its hostname.
|
||||
poolSocket(request->getHost(), request->getPort(), socket);
|
||||
poolSocket(request->getHost(), request->getPort(), socket, timeout);
|
||||
} else {
|
||||
std::pair<std::string, uint16_t> peerInfo;
|
||||
socket->getPeerInfo(peerInfo);
|
||||
poolSocket(peerInfo.first, peerInfo.second, socket);
|
||||
poolSocket(peerInfo.first, peerInfo.second, socket, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadEngine::poolSocket
|
||||
(const SharedHandle<Request>& request,
|
||||
bool proxyDefined,
|
||||
const std::string& username,
|
||||
const SharedHandle<SocketCore>& socket,
|
||||
const std::map<std::string, std::string>& options,
|
||||
time_t timeout)
|
||||
{
|
||||
if(proxyDefined) {
|
||||
// If proxy is defined, then pool socket with its hostname.
|
||||
poolSocket(request->getHost(), request->getPort(), socket, options);
|
||||
poolSocket(request->getHost(), request->getPort(), username,
|
||||
socket, options, timeout);
|
||||
} else {
|
||||
std::pair<std::string, uint16_t> peerInfo;
|
||||
socket->getPeerInfo(peerInfo);
|
||||
poolSocket(peerInfo.first, peerInfo.second, socket, options);
|
||||
poolSocket(peerInfo.first, peerInfo.second, username,
|
||||
socket, options, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,11 +410,12 @@ DownloadEngine::popPooledSocket(const std::string& ipaddr, uint16_t port)
|
|||
|
||||
SharedHandle<SocketCore>
|
||||
DownloadEngine::popPooledSocket(std::map<std::string, std::string>& options,
|
||||
const std::string& ipaddr, uint16_t port)
|
||||
const std::string& ipaddr, uint16_t port,
|
||||
const std::string& username)
|
||||
{
|
||||
SharedHandle<SocketCore> s;
|
||||
std::multimap<std::string, SocketPoolEntry>::iterator i =
|
||||
findSocketPoolEntry(ipaddr, port);
|
||||
findSocketPoolEntry(createSockPoolKey(ipaddr, username), port);
|
||||
if(i != _socketPool.end()) {
|
||||
s = (*i).second.getSocket();
|
||||
options = (*i).second.getOptions();
|
||||
|
@ -427,12 +442,13 @@ DownloadEngine::popPooledSocket
|
|||
SharedHandle<SocketCore>
|
||||
DownloadEngine::popPooledSocket
|
||||
(std::map<std::string, std::string>& options,
|
||||
const std::vector<std::string>& ipaddrs, uint16_t port)
|
||||
const std::vector<std::string>& ipaddrs, uint16_t port,
|
||||
const std::string& username)
|
||||
{
|
||||
SharedHandle<SocketCore> s;
|
||||
for(std::vector<std::string>::const_iterator i = ipaddrs.begin(),
|
||||
eoi = ipaddrs.end(); i != eoi; ++i) {
|
||||
s = popPooledSocket(options, *i, port);
|
||||
s = popPooledSocket(options, *i, port, username);
|
||||
if(!s.isNull()) {
|
||||
break;
|
||||
}
|
||||
|
@ -448,6 +464,11 @@ DownloadEngine::SocketPoolEntry::SocketPoolEntry
|
|||
_options(options),
|
||||
_timeout(timeout) {}
|
||||
|
||||
DownloadEngine::SocketPoolEntry::SocketPoolEntry
|
||||
(const SharedHandle<SocketCore>& socket, time_t timeout):
|
||||
_socket(socket),
|
||||
_timeout(timeout) {}
|
||||
|
||||
DownloadEngine::SocketPoolEntry::~SocketPoolEntry() {}
|
||||
|
||||
bool DownloadEngine::SocketPoolEntry::isTimeout() const
|
||||
|
|
|
@ -98,6 +98,9 @@ private:
|
|||
const std::map<std::string, std::string>& option,
|
||||
time_t timeout);
|
||||
|
||||
SocketPoolEntry(const SharedHandle<SocketCore>& socket,
|
||||
time_t timeout);
|
||||
|
||||
~SocketPoolEntry();
|
||||
|
||||
bool isTimeout() const;
|
||||
|
@ -151,6 +154,16 @@ private:
|
|||
uint16_t port,
|
||||
const SocketPoolEntry& entry);
|
||||
|
||||
void poolSocket(const std::string& ipaddr, uint16_t port,
|
||||
const std::string& username,
|
||||
const SharedHandle<SocketCore>& sock,
|
||||
const std::map<std::string, std::string>& options,
|
||||
time_t timeout);
|
||||
|
||||
void poolSocket(const std::string& ipaddr, uint16_t port,
|
||||
const SharedHandle<SocketCore>& sock,
|
||||
time_t timeout);
|
||||
|
||||
std::multimap<std::string, SocketPoolEntry>::iterator
|
||||
findSocketPoolEntry(const std::string& ipaddr, uint16_t port);
|
||||
public:
|
||||
|
@ -202,17 +215,9 @@ public:
|
|||
|
||||
void addRoutineCommand(Command* command);
|
||||
|
||||
void poolSocket(const std::string& ipaddr, uint16_t port,
|
||||
const SharedHandle<SocketCore>& sock,
|
||||
const std::map<std::string, std::string>& options,
|
||||
time_t timeout = 15);
|
||||
|
||||
void poolSocket(const std::string& ipaddr, uint16_t port,
|
||||
const SharedHandle<SocketCore>& sock,
|
||||
time_t timeout = 15);
|
||||
|
||||
void poolSocket(const SharedHandle<Request>& request,
|
||||
bool proxyDefined,
|
||||
const std::string& username,
|
||||
const SharedHandle<SocketCore>& socket,
|
||||
const std::map<std::string, std::string>& options,
|
||||
time_t timeout = 15);
|
||||
|
@ -228,7 +233,8 @@ public:
|
|||
SharedHandle<SocketCore> popPooledSocket
|
||||
(std::map<std::string, std::string>& options,
|
||||
const std::string& ipaddr,
|
||||
uint16_t port);
|
||||
uint16_t port,
|
||||
const std::string& username);
|
||||
|
||||
SharedHandle<SocketCore>
|
||||
popPooledSocket(const std::vector<std::string>& ipaddrs, uint16_t port);
|
||||
|
@ -237,7 +243,8 @@ public:
|
|||
popPooledSocket
|
||||
(std::map<std::string, std::string>& options,
|
||||
const std::vector<std::string>& ipaddrs,
|
||||
uint16_t port);
|
||||
uint16_t port,
|
||||
const std::string& username);
|
||||
|
||||
const SharedHandle<CookieStorage>& getCookieStorage() const
|
||||
{
|
||||
|
|
|
@ -517,4 +517,9 @@ void FtpConnection::setBaseWorkingDir(const std::string& baseWorkingDir)
|
|||
_baseWorkingDir = baseWorkingDir;
|
||||
}
|
||||
|
||||
const std::string& FtpConnection::getUser() const
|
||||
{
|
||||
return _authConfig->getUser();
|
||||
}
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -119,6 +119,8 @@ public:
|
|||
{
|
||||
return _baseWorkingDir;
|
||||
}
|
||||
|
||||
const std::string& getUser() const;
|
||||
};
|
||||
|
||||
} // namespace aria2
|
||||
|
|
|
@ -82,7 +82,8 @@ bool FtpFinishDownloadCommand::execute()
|
|||
if(getOption()->getAsBool(PREF_FTP_REUSE_CONNECTION)) {
|
||||
std::map<std::string, std::string> options;
|
||||
options["baseWorkingDir"] = _ftpConnection->getBaseWorkingDir();
|
||||
e->poolSocket(req, isProxyDefined(), socket, options);
|
||||
e->poolSocket(req, isProxyDefined(), _ftpConnection->getUser(),
|
||||
socket, options);
|
||||
}
|
||||
} catch(RecoverableException& e) {
|
||||
logger->info(EX_EXCEPTION_CAUGHT, e);
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "Socket.h"
|
||||
#include "DownloadContext.h"
|
||||
#include "util.h"
|
||||
#include "AuthConfigFactory.h"
|
||||
#include "AuthConfig.h"
|
||||
|
||||
namespace aria2 {
|
||||
|
||||
|
@ -73,9 +75,16 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
Command* command;
|
||||
if(!proxyRequest.isNull()) {
|
||||
std::map<std::string, std::string> options;
|
||||
SharedHandle<SocketCore> pooledSocket =
|
||||
e->popPooledSocket(options, req->getHost(), req->getPort());
|
||||
SharedHandle<SocketCore> pooledSocket;
|
||||
std::string proxyMethod = resolveProxyMethod(req->getProtocol());
|
||||
if(proxyMethod == V_GET) {
|
||||
pooledSocket = e->popPooledSocket(req->getHost(), req->getPort());
|
||||
} else {
|
||||
pooledSocket = e->popPooledSocket
|
||||
(options, req->getHost(), req->getPort(),
|
||||
e->getAuthConfigFactory()->createAuthConfig
|
||||
(req, getOption().get())->getUser());
|
||||
}
|
||||
if(pooledSocket.isNull()) {
|
||||
if(logger->info()) {
|
||||
logger->info(MSG_CONNECTING_TO_SERVER,
|
||||
|
@ -133,7 +142,9 @@ Command* FtpInitiateConnectionCommand::createNextCommand
|
|||
} else {
|
||||
std::map<std::string, std::string> options;
|
||||
SharedHandle<SocketCore> pooledSocket =
|
||||
e->popPooledSocket(options, resolvedAddresses, req->getPort());
|
||||
e->popPooledSocket(options, resolvedAddresses, req->getPort(),
|
||||
e->getAuthConfigFactory()->createAuthConfig
|
||||
(req, getOption().get())->getUser());
|
||||
if(pooledSocket.isNull()) {
|
||||
if(logger->info()) {
|
||||
logger->info(MSG_CONNECTING_TO_SERVER,
|
||||
|
|
|
@ -806,7 +806,7 @@ void FtpNegotiationCommand::poolConnection() const
|
|||
if(getOption()->getAsBool(PREF_FTP_REUSE_CONNECTION)) {
|
||||
std::map<std::string, std::string> options;
|
||||
options["baseWorkingDir"] = ftp->getBaseWorkingDir();
|
||||
e->poolSocket(req, isProxyDefined(), socket, options);
|
||||
e->poolSocket(req, isProxyDefined(), ftp->getUser(), socket, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue