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 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 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 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 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 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 ftp_; // For tunneling SharedHandle http_; - // IP, Port pair in pasv response - std::pair 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& addrinfo) const +int SocketCore::getAddrInfo(std::pair& 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& peerinfo) const +int SocketCore::getPeerInfo(std::pair& peerinfo) const { sockaddr_union sockaddr; socklen_t len = sizeof(sockaddr); @@ -378,6 +379,7 @@ void SocketCore::getPeerInfo(std::pair& 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& addrinfo) const; + int getAddrInfo(std::pair& 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& peerinfo) const; + int getPeerInfo(std::pair& peerinfo) const; /** * Accepts incoming connection on this socket.