summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2011-11-14 23:19:37 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2011-11-14 23:19:37 +0900
commit27dda3c65c263a9dcc6b4a4e38f67e6ee0bc9a78 (patch)
treecf883a8b6b4f94243c1386c3330097a4f881592b /src
parent97a9242cbe618ac3c2e3e89c30ee8018268e35a3 (diff)
Support IPv6 address for FTP via HTTP tunneling.
We use control connection address as data connection address, so we don't need to store both address and port. We just store port in PASV/EPSV response and use SocketCore::getPeerInfo() to get peer's address when needed.
Diffstat (limited to 'src')
-rw-r--r--src/FtpNegotiationCommand.cc37
-rw-r--r--src/FtpNegotiationCommand.h4
-rw-r--r--src/SocketCore.cc6
-rw-r--r--src/SocketCore.h12
4 files changed, 33 insertions, 26 deletions
diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc
index ea1ab91f..45e7a69b 100644
--- a/src/FtpNegotiationCommand.cc
+++ b/src/FtpNegotiationCommand.cc
@@ -86,11 +86,13 @@ FtpNegotiationCommand::FtpNegotiationCommand
const SocketHandle& socket,
Seq seq,
const std::string& baseWorkingDir):
- AbstractCommand(cuid, req, fileEntry, requestGroup, e, socket), sequence_(seq),
+ AbstractCommand(cuid, req, fileEntry, requestGroup, e, socket),
+ sequence_(seq),
ftp_(new FtpConnection(cuid, socket, req,
e->getAuthConfigFactory()->createAuthConfig
(req, requestGroup->getOption().get()),
- getOption().get()))
+ getOption().get())),
+ pasvPort_(0)
{
ftp_->setBaseWorkingDir(baseWorkingDir);
if(seq == SEQ_RECV_GREETING) {
@@ -606,10 +608,7 @@ bool FtpNegotiationCommand::recvEpsv() {
return false;
}
if(status == 229) {
- std::pair<std::string, uint16_t> peerInfo;
- getSocket()->getPeerInfo(peerInfo);
- peerInfo.second = port;
- dataConnAddr_ = peerInfo;
+ pasvPort_ = port;
return preparePasvConnect();
} else {
sequence_ = SEQ_SEND_PASV;
@@ -637,27 +636,24 @@ bool FtpNegotiationCommand::recvPasv() {
throw DL_ABORT_EX2(fmt(EX_BAD_STATUS, status),
error_code::FTP_PROTOCOL_ERROR);
}
- std::pair<std::string, uint16_t> peerInfo;
- getSocket()->getPeerInfo(peerInfo);
- peerInfo.second = dest.second;;
- dataConnAddr_ = peerInfo;
+ pasvPort_ = dest.second;;
return preparePasvConnect();
}
bool FtpNegotiationCommand::preparePasvConnect() {
- // TODO Should we check to see that dataConnAddr_.first is not in
- // noProxy list?
if(isProxyDefined()) {
sequence_ = SEQ_RESOLVE_PROXY;
return true;
} else {
+ std::pair<std::string, uint16_t> dataAddr;
+ getSocket()->getPeerInfo(dataAddr);
// make a data connection to the server.
A2_LOG_INFO(fmt(MSG_CONNECTING_TO_SERVER,
getCuid(),
- dataConnAddr_.first.c_str(),
- dataConnAddr_.second));
+ dataAddr.first.c_str(),
+ pasvPort_));
dataSocket_.reset(new SocketCore());
- dataSocket_->establishConnection(dataConnAddr_.first, dataConnAddr_.second);
+ dataSocket_->establishConnection(dataAddr.first, pasvPort_);
disableReadCheckSocket();
setWriteCheckSocket(dataSocket_);
sequence_ = SEQ_SEND_REST_PASV;
@@ -722,9 +718,14 @@ bool FtpNegotiationCommand::sendTunnelRequest()
httpRequest->setUserAgent(getOption()->get(PREF_USER_AGENT));
SharedHandle<Request> req(new Request());
// Construct fake URI in order to use HttpRequest
- // TODO Handle IPv6 address; it must be enclosed with [].
- req->setUri(fmt("ftp://%s:%u",
- dataConnAddr_.first.c_str(), dataConnAddr_.second));
+ std::pair<std::string, uint16_t> dataAddr;
+ int family = getSocket()->getPeerInfo(dataAddr);
+ uri::UriStruct us;
+ us.protocol = "ftp";
+ us.host = dataAddr.first;
+ us.port = pasvPort_;
+ us.ipv6LiteralAddress = (family == AF_INET6);
+ req->setUri(uri::construct(us));
httpRequest->setRequest(req);
httpRequest->setProxyRequest(createProxyRequest());
http_->sendProxyRequest(httpRequest);
diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h
index 3403e907..b155595b 100644
--- a/src/FtpNegotiationCommand.h
+++ b/src/FtpNegotiationCommand.h
@@ -147,8 +147,8 @@ private:
SharedHandle<FtpConnection> ftp_;
// For tunneling
SharedHandle<HttpConnection> http_;
- // IP, Port pair in pasv response
- std::pair<std::string, uint16_t> dataConnAddr_;
+ // Port number in PASV/EPSV response
+ uint16_t pasvPort_;
// Resolved address for proxy
std::string proxyAddr_;
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index f0a3b5bb..793dc1bd 100644
--- a/src/SocketCore.cc
+++ b/src/SocketCore.cc
@@ -345,12 +345,13 @@ SocketCore* SocketCore::acceptConnection() const
return new SocketCore(fd, sockType_);
}
-void SocketCore::getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const
+int SocketCore::getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const
{
sockaddr_union sockaddr;
socklen_t len = sizeof(sockaddr);
getAddrInfo(sockaddr, len);
addrinfo = util::getNumericNameInfo(&sockaddr.sa, len);
+ return sockaddr.storage.ss_family;
}
void SocketCore::getAddrInfo(sockaddr_union& sockaddr, socklen_t& len) const
@@ -369,7 +370,7 @@ int SocketCore::getAddressFamily() const
return sockaddr.storage.ss_family;
}
-void SocketCore::getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const
+int SocketCore::getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const
{
sockaddr_union sockaddr;
socklen_t len = sizeof(sockaddr);
@@ -378,6 +379,7 @@ void SocketCore::getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const
throw DL_ABORT_EX(fmt(EX_SOCKET_GET_NAME, errorMsg(errNum).c_str()));
}
peerinfo = util::getNumericNameInfo(&sockaddr.sa, len);
+ return sockaddr.storage.ss_family;
}
void SocketCore::establishConnection(const std::string& host, uint16_t port)
diff --git a/src/SocketCore.h b/src/SocketCore.h
index 94db37ee..eaf6d946 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -147,10 +147,12 @@ public:
void beginListen();
/**
- * Stores host address and port of this socket to addrinfo.
+ * Stores host address and port of this socket to addrinfo and
+ * returns address family.
+ *
* @param addrinfo placeholder to store host address and port.
*/
- void getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const;
+ int getAddrInfo(std::pair<std::string, uint16_t>& addrinfo) const;
/**
* Stores address of this socket to sockaddr. len must be
@@ -168,10 +170,12 @@ public:
int getAddressFamily() const;
/**
- * Stores peer's address and port to peerinfo.
+ * Stores peer's address and port to peerinfo and returns address
+ * family.
+ *
* @param peerinfo placeholder to store peer's address and port.
*/
- void getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const;
+ int getPeerInfo(std::pair<std::string, uint16_t>& peerinfo) const;
/**
* Accepts incoming connection on this socket.