aria2/src/FtpConnection.cc

439 lines
12 KiB
C++
Raw Normal View History

2006-02-21 12:28:42 +00:00
/* <!-- copyright */
/*
* aria2 - The high speed download utility
2006-02-21 12:28:42 +00:00
*
* Copyright (C) 2006 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
2006-02-21 12:28:42 +00:00
*/
/* copyright --> */
#include "FtpConnection.h"
#include <cstring>
#include <cstdio>
#include <cassert>
#include "Request.h"
#include "Segment.h"
#include "Option.h"
2006-02-21 12:28:42 +00:00
#include "Util.h"
#include "message.h"
2006-02-21 14:00:58 +00:00
#include "prefs.h"
To add LogFactory which creates singleton logger: * src/LogFactory.h: New class. * src/LogFactory.cc: New class. * src/Command.h (logger): New variable. (Constructor): Use LogFactory. * src/AbstractCommand.cc: Use Command::logger * src/PeerConnection.cc (Constructor): Deleted the argument logger. Use LogFactory. * src/SegmentSplitter.h : Made logger protected. * src/SegmentSplitter.cc (Constructor): Use LogFactory. * src/SegmentMan.cc (Constructor): Use LogFactory. * src/DownloadEngine.h : Made logger protected. * src/DownloadEngine.cc (Constructor): Use LogFactory. * src/PeerInteractionCommand.cc : Use Command::logger. * src/HttpResponseCommand.cc : Use Command::logger. * src/SegmentMan.h : Made logger private. * src/TorrentMan.h : Made logger private. * src/TorrentMan.cc : Use LogFactory. * src/FtpNegotiateCommand.cc : Use Command::logger. * src/HttpConnection.h (Constructor): Deleted the argument logger. * src/HttpConnection.cc (Constructor): Deleted the argument logger. Use LogFactory. * src/FtpConnection.h (Constructor): Deleted the argument logger. * src/FtpConnection.cc (Constructor): Deleted the argument logger. Use LogFactory. * src/DownloadCommand.cc : Use Command::logger. * src/PeerAbstractCommand.cc : Use Command::logger. * src/PeerListenCommand.cc : Use Command::logger. * src/PeerInitiateConnectionCommand.cc : Use Command::logger. * src/HttpInitiateConnectionCommand.cc : Use Command::logger. * src/FtpInitiateConnectionCommand.cc : Use Command::logger. * src/TrackerWatcherCommand.cc : Use Command::logger. * src/TrackerUpdateCommand.cc : Use Command::logger. * src/TrackerDownloadCommand.cc : Use Command::logger. * src/RequestSlotMan.cc (Constructor): Deleted the argument logger. Use LogFactory. * src/SendMessageQueue.h (Constructor): Deleted the argument logger. * src/SendMessageQueue.cc (Constructor): Deleted the argument logger. Use LogFactory. * src/main.cc (main): Use LogFactory. * src/DiskAdaptor.h (logger): New variable. * src/DiskAdaptor.cc (Constructor): Use LogFactory. * src/CopyDiskAdaptor.cc (fixFilename): Added a log message.
2006-04-17 16:17:20 +00:00
#include "LogFactory.h"
#include "Logger.h"
#include "AuthConfigFactory.h"
#include "AuthConfig.h"
2007-11-10 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> Don't connect server before checking file integrity at startup, if filesize and output file path are known. * src/AbstractCommand.cc * src/StreamFileAllocationEntry.cc * src/Metalink2RequestGroup.cc * src/RequestGroup.{h, cc} * src/HttpResponseCommand.cc * src/FtpNegotiationCommand.cc Added DownloadFailureException. If it is thrown, RequestGroup should halt. * src/AbstractCommand.cc * src/DownloadFailureException.h * src/RequestGroup.cc Catch RecoverableException, instead of DlAbortEx. * src/RequestGroupMan.cc * src/FillRequestGroupCommand.cc * src/MetaFileUtil.cc * src/IteratableChunkChecksumValidator.cc Now first parameter of MSG_DOWNLOAD_ABORTED is gid(RequestGroup:: getGID()) * src/CheckIntegrityCommand.cc * src/message.h Print gid instead of idx. * src/RequestGroupMan.cc Removed exception throwers declaration. * src/DirectDiskAdaptor.{h, cc} * src/SocketCore.{h, cc} * src/MultiDiskAdaptor.{h, cc} * src/HttpConnection.{h, cc} * src/HttpResponse.{h, cc} * src/DiskAdaptor.{h, cc} * src/CopyDiskAdaptor.{h, cc} * src/MultiDiskAdaptor.{h, cc} * src/HttpHeaderProcessor.{h, cc} * src/AbstractSingleDiskAdaptor.{h, cc} * src/Util.{h, cc} * test/UtilTest.cc * src/DefaultDiskWriter.{h, cc} * src/FtpConnection.{h, cc} * src/AbstractDiskWriter.{h, cc} Removed duplicate code. * src/StreamCheckIntegrityEntry.cc Removed unnecessary include. * src/DiskWriter.h Included Exception.h * src/option_processing.cc Included 2 files and added doc * src/TrackerWatcherCommand.cc * src/SocketCore.cc (writeData): Fixed send error with GnuTLS.
2007-11-09 18:01:12 +00:00
#include "DlRetryEx.h"
#include "DlAbortEx.h"
#include "Socket.h"
#include "A2STR.h"
#include "StringFormat.h"
#include "AuthConfig.h"
namespace aria2 {
2006-02-21 12:28:42 +00:00
const std::string FtpConnection::A("A");
const std::string FtpConnection::I("I");
FtpConnection::FtpConnection(int32_t cuid, const SocketHandle& socket,
const RequestHandle& req,
const SharedHandle<AuthConfig>& authConfig,
const Option* op):
cuid(cuid), socket(socket), req(req),
_authConfig(authConfig), option(op),
logger(LogFactory::getInstance()),
_socketBuffer(socket),
_baseWorkingDir("/") {}
2006-02-21 12:28:42 +00:00
FtpConnection::~FtpConnection() {}
bool FtpConnection::sendUser()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "USER "+_authConfig->getUser()+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, "USER ********");
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendPass()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "PASS "+_authConfig->getPassword()+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, "PASS ********");
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendType()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string type;
if(option->get(PREF_FTP_TYPE) == V_ASCII) {
type = FtpConnection::A;
} else {
type = FtpConnection::I;
}
std::string request = "TYPE "+type+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
2006-02-21 14:00:58 +00:00
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendPwd()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "PWD\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
}
bool FtpConnection::sendCwd()
{
if(_socketBuffer.sendBufferIsEmpty()) {
logger->info("CUID#%d - Using base working directory '%s'",
cuid, _baseWorkingDir.c_str());
std::string request = "CWD "+
(_baseWorkingDir == "/" ? "" : _baseWorkingDir)+
Util::urldecode(req->getDir())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendMdtm()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "MDTM "+Util::urlencode(req->getFile())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
}
bool FtpConnection::sendSize()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "SIZE "+Util::urldecode(req->getFile())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendPasv()
{
if(_socketBuffer.sendBufferIsEmpty()) {
static const std::string request("PASV\r\n");
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
SharedHandle<SocketCore> FtpConnection::createServerSocket()
{
SharedHandle<SocketCore> serverSocket(new SocketCore());
serverSocket->bind(0);
2006-07-19 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> * src/SharedHandle.h: New class. To wrap Socket, Command, PeerMessage and Peer with SharedHandle: * src/HttpResponseCommand.h (HttpResponseCommand): Wrapped Socket. * src/SocketCore.h (operator==): New function. (operator!=): New function. (operator<): New function. (getSockfd): New function. (isOpen): New function. (writeData): New function. * src/SocketCore.cc (operator==): New function. (operator!=): New function. (operator<): New function. * src/AbstractCommand.h (socket): Changed its type to SocketHandle. (setReadCheckSocket): Replaced Socket with SocketHandle. (setWriteCheckSocket): Replaced Socket with SocketHandle. (disableReadCheckSocket): New function. (disableWriteCheckSocket): New function. (readCheckTarget): Changed its type to SocketHandle. (writeCheckTarget): Changed its type to SocketHandle. (AbstractCommand): Replaced Socket with SocketHandle. * src/AbstractCommand.cc (AbstractCommand): Replaced Socket with SocketHandle. (~AbstractCommand): Removed the deallocation for Socket object. (disableReadCheckSocket): New function. (setReadCheckSocket): Replaced Socket with SocketHandle. (disableWriteCheckSocket): New function. (setWriteCheckSocket): Replaced Socket with SocketHandle. * src/HttpDownloadCommand.cc (DownloadCommand): Replaced Socket with SocketHandle. * src/PeerAbstractCommand.h (socket): Changed its type to SocketHandle. (peer): Changed its type to PeerHandle. (setReadCheckSocket): Replaced Socket with SocketHandle. (setWriteCheckSocket): Replaced Socket with SocketHandle. (disableReadCheckSocket): New function. (disableWriteCheckSocket): New function. (readCheckTarget): Changed its type to SocketHandle. (writeCheckTarget): Changed its type to SocketHandle. (PeerAbstractCommand): Replaced Socket with SocketHandle. Replaced Peer with PeerHandle. * src/HttpRequestCommand.cc (HttpRequestCommand): Replaced Socket with SocketHandle. Use disableReadCheckSocket. * src/PeerInitiateConnectionCommand.h (PeerInitiateConnectionCommand): Replaced Peer with PeerHandle. * src/PeerChokeCommand.cc (UploadFaster::operator()): Replaced Peer with PeerHandle. (DownloadFaster::operator()): Replaced Peer with PeerHandle. (execute): Use PeerHandle. * src/PeerConnection.h (HandshakeMessage.h): Removed include of HandshakeMessage.h. (socket): Changed its type to SocketHandle. (PeerConnection): Replaced Socket with SocketHandle. * src/PeerConnection.cc (PeerConnection): Replaced Socket with SocketHandle. * src/PeerInteractionCommand.h (PeerInteractionCommand): Replaced socket with SocketHandle. Replaced Peer with PeerHandle. * src/PeerInteractionCommand.cc (PeerInteractionCommand): Replaced Socket with SocketHandle. Replaced Peer with PeerHandle. (executeInternal): Use disableWriteCheckSocket. Use HandshakeMessageHandle. (receiveMessages): Use PeerMessageHandle. (prepareForNextPeer): Use PeerHandle. * src/HttpProxyRequestCommand.h (HttpProxyRequestCommand): Replaced Socket with SocketHandle. * src/HttpResponseCommand.cc (HttpResponseCommand): Replaced Socket with SocketHandle. * src/TorrentMan.cc (nullPeer): Added external reference. (~TorrentMan): Removed the deallocation of the elements of peers. (addPeer): Rewritten. (isPeerAvailable): Use nullPeer. (deleteOldpeers): Replaced with deleteErrorPeer. (deleteErrorPeer): New function. (getPeer): Use PeerHandle and nullPeer. (hasMissingPiece): Replaced Peer with PeerHandle. (getMissingPieceIndex): Replaced Peer with PeerHandle. (getMissingFastPieceIndex): Replaced Peer with PeerHandle. (getMissingFastPiece): Replaced Peer with PeerHandle. (getMissingPiece): Replaced Peer with PeerHandle. * src/FtpNegotiateCommand.cc (FtpNegotiationCommand): Replaced Peer with PeerHandle. (~FtpNegotiationCommand): Removed the deallocation of Sockets. (recvGreeting): Use disableWriteCheckSocket. (recvPasv): Removed the allocation of Socket. Use disableReadCheckSocket. (sendRestPasv): Use disableWriteCheckSocket. (recvRetr): Changed assertion. * src/PeerInteraction.h (SharedHandle.h): Included SharedHandle.h. (PeerMessageHandle): New type definition. (HandshakeMessageHandle): New type definition. (MessageQueue): Changed. Now its element is of type PeerMessageHandle. (peer): Changed its type to PeerHandle. (createHandshakeMessage): Replaced HandshakeMessage with HandshakeMessageHandle. (createPeerMessage): Replaced PeerMessageHandle with PeerMessage. (PeerInteraction): Replaced Peer with PeerHandle. Replaced Socket with SocketHandle. (addMessage): Replaced PeerMessage with PeerMessageHandle. (receiveMessage): Replaced PeerMessage with PeerMessageHandle. (receiveHandshake): Replaced HandshakeMessage with HandshakeMessageHandle. * src/PeerInteraction.cc (PeerInteraction): Replaced Peer with PeerHandle. Replaced Socket with SocketHandle. (~PeerInteraction): Removed the deallocation of the elements of messageQueue. (MsgPushBack::operator()): Replaced PeerMessage with PeerMessageHandle. (isSendingMessageInProgress): Replaced PeerMessage with PeerMessageHandle. (sendMessages): Use PeerMessageHandle. Removed try-catch block. (addMessage): Replaced PeerMessage with PeerMessageHandle. (rejectAllPieceMessageInQueue): Use PeerMessageHandle. (rejectPieceMessageInQueue): Use PeerMessageHandle. (abortPiece): Use PeerMessageHandle. (receiveHandshake): Replaced HandshakeMessage with HandshakeMessageHandle. Removed try-catch block. (createHandshakeMessage): Replaced HandshakeMessage with HandshakeMessageHandle. (receiveMessage): Replaced PeerMessage with PeerMessageHandle. Removed try-catch block. (createPeerMessage): Replaced PeerMessage with PeerMessageHandle. * src/HttpProxyResponseCommand.cc (HttpProxyRequestCommand): Replaced Socket with SocketHandle. * src/FtpTunnelResponseCommand.h (FtpTunnelResponseCommand): Replaced Socket with SocketHandle. * src/HttpConnection.cc (HttpConnection): Replaced Socket with SocketHandle. * src/PeerAbstractCommand.cc (PeerAbstractCommand): Replaced Socket with SocketHandle. (~PeerAbstractCommand): Removed the deallocation of socket. Use disableReadCheckSocket, disableWriteCheckSocket. (disableReadCheckSocket): New function. (setReadCheckSocket): Replaced Socket with SocketHandle. (disableWriteCheckSocket): New function. (setWriteCheckSocket): Replaced Socket with SocketHandle. * src/InitiateConnectionCommandFactory.h: Corrected indentation. * src/FtpTunnelRequestCommand.cc (FtpTunnelRequestCommand): Replaced Socket with SocketHandle. (~FtpTunnelRequestCommand): Corrected indentation. * src/DownloadCommand.h (DownloadCommand): Replaced Socket with SocketHandle. * src/PeerListenCommand.cc (PeerListenCommand): Removed the initialization of socket. (~PeerListenCommand): Removed the deallocation of socket. (bindPort): Use SocketHandle. (execute): Use SocketHandle and PeerHandle. * src/FtpDowndloadCommand.cc (FtpDownloadCommand): Replaced Socket with SocketHandle. (~FtpDownloadCommand): Removed the deallocation of ctrlSocket. * src/main.cc (main): Corrected indentation. * src/HttpInitiateConnectionCommand.cc (HttpInitiateConnectionCommand): Replaced Socket with SocketHandle. (executeInternal): Removed the allocation of socket. * src/HttpRequestCommand.h (HttpRequestCommand): Replaced Socket with SocketHandle. * src/FtpNegotiationCommand.h (dataSocket): Changed its type to SocketHandle. (serverSocket): Changed its type to SocketHandle. (FtpNegotiationCommand): Replaced Socket with SocketHandle. * src/TorrentMan.h (MAX_PEER_UPDATE): Removed. (MAX_PEERS): New definition. (Peers): The element is now of type PeerHandle. (addPeer): Replaced Peer with PeerHandle. Removed 'duplicate' argument. (getPeer): Replaced Peer with PeerHandle. (deleteOldErrorPeers): Removed. (deleteErrorPeer): New function. (hasMissingPiece): Replaced Peer with PeerHandle. (getMissingPieceIndex): Replaced Peer with PeerHandle. (getMissingPiece): Replaced Peer with PeerHandle. (getMissingFastPieceIndex): Replaced Peer with PeerHandle. (getMissingFastPiece): Replaced Peer with PeerHandle. (addActivePeer): Replaced Peer with PeerHandle. (deleteActivePeer): Replaced Peer with PeerHandle. Added a check for the return value of find. * src/FtpTunnelResponseCommand.cc (FtpTunnelResponseCommand): Replaced Socket with SocketHandle. * src/FtpInitiateConnectionCommand.cc (executeInternal): Removed the allocation of socket. * src/DownloadEngine.h (Sockets): An element is now of type SocketHandle. (SockCmdMap): A key is of type SocketHandle, a value is of type int. (CommandUuids): New type definition. (rsockets): Changed its type to SockCmdMap. (wsockets): Changed its type to SockCmdMap. (addSocket): Rewritten. (deleteSocket): Rewritten. (addSocketForReadCheck): Rewritten. (deleteSocketForReadCheck): Rewritten. (addSocketForWriteCheck): Rewritten. (deleteSocketForWriteCheck): Rewritten. (PairFind): New template class. * src/HttpDownloadCommand.h (HttpDownloadCommand): Replaced Socket with SocketHandle. * src/FtpConnection.cc (FtpConnection): Replaced Socket with SocketHandle. (sendPort): Removed the allocation of serverSocket. Removed try-catch block. * src/InitiateConnectionCommandFactory.cc (DlAbortEx.h): Included DlAbortEx.h. (createInitiateConnectionCommand): Throw exception if the protocol of requested URI is not supported. * src/Peer.cc (nullPeer): Changed its type to PeerHandle. (operator==): New function. (operator!=): New function. * src/Peer.h (SharedHandle.h): Included SharedHandle.h. (operator==): New function. (operator!=): New function. (Peer): Added the default constructor. Use resetStatus() to initialize member variables. (nullPeer): Removed. * src/TrackerUpdateCommand.cc (execute): Brushed up using SharedHandle. Replaced MAX_PEER_UPDATE with MIN_PEERS. * src/PeerListenCommand.h (socket): Changed its type to SocketHandle. * src/Command.h (CommandUuid): New type definition. (uuid): New variable. (uuidGen): New variable. (Command): Added the initialization of uuid. (getUuid): New function. * src/Socket.h (Socket): Removed. (SocketHandle): New type definition. * src/DownloadEngine.h (FindCommand): New function object. (run): The portion of socket check was rewritten. (SetDescriptor): New function object. (AccumulateActiveCommandUuid): New function object. (waitData): Rewritten. (addSocket): Rewritten. (deleteSocket): Rewritten. (addSocketForReadCheck): Rewritten. (addSocketForWriteCheck): Rewritten. (deleteSocketForReadCheck): Rewritten. (deleteSocketForWriteCheck): Rewritten. * src/HttpProxyResponseCommand.h (HttpProxyResponseCommand): Replaced Socket with SocketHandle. * src/HttpConnection.h (socket): Changed its type to SocketHandle. (HttpConnection): Replaced Socket with SocketHandle. * src/PeerInitiateConnectionCommand.cc (PeerInitiateConnectionCommand): Replaced Peer with PeerHandle. (executeInternal): Removed the allocation of socket. (prepareForNextPeer): Use PeerHandle. * src/PeerMessage.h (peer): Changed its type to PeerHandle. (getPeer): Replaced Peer with PeerHandle. (setPeer): Replaced Peer with PeerHandle. * src/DownloadCommand.cc (DownloadCommand): Replaced Socket with SocketHandle. * src/FtpConnection.h (socket): Changed its type to SocketHandle. (FtpConnection): Replaced Socket with SocketHandle. (sendPort); Replaced Socket with SocketHandle. * src/FtpDowndloadCommand.h (ctrlSocket): Changed its type to SocketHandle. (FtpDownloadCommand): Replaced Socket with SocketHandle. * src/HttpProxyRequestCommand.cc (HttpProxyRequestCommand): Replaced Socket with SocketHandle. * src/FtpTunnelRequestCommand.h (FtpTunnelRequestCommand): Replaced Socket with SocketHandle. etc * src/PeerChokeCommand.h (setAllPeerChoked): Removed. (setAllPeerResetDelta): Removed. * src/PeerChokeCommand.cc (setAllPeerChoked): Removed. (ChokePeer): New function object. (setAllPeerResetDelta): Removed. (ResetDelta): New function object. (orderByDownloadRate): Fixed a bug: use DowloadFaster, not UploadFaster (execute): Show download speed when the local node is a seeder. setAllPeerChoked and setAllPeerResetDelta were rewritten using STL. * src/TrackerWatcherCommand.h (MIN_PEERS): Removed. * src/TorrentMan.cc (getPeer): Replaced MAX_PEER_UPDATE with MIN_PEERS.
2006-07-19 17:07:45 +00:00
serverSocket->beginListen();
serverSocket->setNonBlockingMode();
2006-02-21 12:28:42 +00:00
return serverSocket;
}
bool FtpConnection::sendPort(const SharedHandle<SocketCore>& serverSocket)
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::pair<std::string, uint16_t> addrinfo;
socket->getAddrInfo(addrinfo);
unsigned int ipaddr[4];
sscanf(addrinfo.first.c_str(), "%u.%u.%u.%u",
&ipaddr[0], &ipaddr[1], &ipaddr[2], &ipaddr[3]);
serverSocket->getAddrInfo(addrinfo);
std::string request = "PORT "+
Util::uitos(ipaddr[0])+","+Util::uitos(ipaddr[1])+","+
Util::uitos(ipaddr[2])+","+Util::uitos(ipaddr[3])+","+
Util::uitos(addrinfo.second/256)+","+
Util::uitos(addrinfo.second%256)+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
}
bool FtpConnection::sendRest(const SegmentHandle& segment)
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "REST ";
if(segment.isNull()) {
request += "0";
} else {
request += Util::itos(segment->getPositionToWrite());
}
request += "\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
bool FtpConnection::sendRetr()
{
if(_socketBuffer.sendBufferIsEmpty()) {
std::string request = "RETR "+Util::urldecode(req->getFile())+"\r\n";
logger->info(MSG_SENDING_REQUEST, cuid, request.c_str());
_socketBuffer.feedSendBuffer(request);
}
_socketBuffer.send();
return _socketBuffer.sendBufferIsEmpty();
2006-02-21 12:28:42 +00:00
}
unsigned int FtpConnection::getStatus(const std::string& response) const
{
unsigned int status;
// When the response is not like "%u %*s",
2006-02-22 11:18:47 +00:00
// we return 0.
if(response.find_first_not_of("0123456789") != 3
2006-02-22 14:30:47 +00:00
|| !(response.find(" ") == 3 || response.find("-") == 3)) {
2006-02-22 11:18:47 +00:00
return 0;
}
if(sscanf(response.c_str(), "%u %*s", &status) == 1) {
2006-02-21 12:28:42 +00:00
return status;
} else {
return 0;
}
}
// Returns the length of the reponse if the whole response has been received.
// The length includes \r\n.
// If the whole response has not been recieved, then returns std::string::npos.
std::string::size_type
FtpConnection::findEndOfResponse(unsigned int status,
const std::string& buf) const
{
if(buf.size() <= 4) {
return std::string::npos;
2006-02-21 12:28:42 +00:00
}
// if 4th character of buf is '-', then multi line response is expected.
if(buf.at(3) == '-') {
2006-02-21 12:28:42 +00:00
// multi line response
std::string::size_type p;
p = buf.find(A2STR::CRLF+Util::uitos(status)+" ");
if(p == std::string::npos) {
return std::string::npos;
}
p = buf.find(A2STR::CRLF, p+6);
if(p == std::string::npos) {
return std::string::npos;
} else {
return p+2;
2006-02-21 12:28:42 +00:00
}
} else {
// single line response
std::string::size_type p = buf.find(A2STR::CRLF);
if(p == std::string::npos) {
return std::string::npos;
} else {
return p+2;
}
2006-02-21 12:28:42 +00:00
}
}
bool FtpConnection::bulkReceiveResponse(std::pair<unsigned int, std::string>& response)
{
2006-02-21 12:28:42 +00:00
char buf[1024];
while(socket->isReadable(0)) {
size_t size = sizeof(buf);
2006-02-21 12:28:42 +00:00
socket->readData(buf, size);
2006-11-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> To add Metalink location option: * src/MetalinkRequestInfo.cc (execute): Call MetalinkEntry::setLocationPreference() * src/main.cc (showUsage): Added the help message for --metalink-location option. (main): Added --metalink-location option. * src/prefs.h (PREF_METALINK_LOCATION): New definition. * src/MetalinkEntry.cc (AddLocationPreference): New function object. (setLocationPreference): New function. * src/Xml2MetalinkProcessor.cc (getResource): Set location attribute to MetalinkResource To show URLs to download * src/UrlRequestInfo.h (printUrls): New function. To add multiple <file> Metalink support: * src/MetalinkEntry.h (MetalinkResources): Removed. (setLocationPreference): New function. (MetalinkEntryHandle): New type definition. (MetalinkEntries): New type definition. * src/Xml2MetalinkProcessor.h (getEntry): MetalinkEntry* -> MetalinkEntryHandle (getResource): MetalinkResource* -> MetalinkResourceHandle (parseFile): Metalinker* -> MetalinkerHandle * src/UrlRequestInfo.h (execute): RequestInfo* -> RequestInfos * src/MetalinkRequestInfo.cc (AccumulateNonP2PUrl): MetalinkResource* -> MetalinkResourceHandle (FindBitTorrentUrl): MetalinkResource* -> MetalinkResourceHandle (execute): RequestInfo* -> RequestInfos Added multiple <file> support. Print filename when it is queued. * src/MetalinkRequestInfo.h (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/RequestInfo.h (RequestInfoHandle): New type definition. (RequestInfos): New type definition. (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/MetalinkResource.h (MetalinkResourceHandle): New type definition. (MetalinkResources): New type definition. * src/MetalinkEntry.cc (~MetalinkEntry): Removed the deletion of the elements of resources, because the element is now of type MetalinkResourceHandle. (PrefOrder): MetalinkResource* -> MetalinkResourceHandle (Supported): MetalinkResource* -> MetalinkResourceHandle (dropUnsupportedResource): Removed the deletion of the elements of resources because the element is now of type MetalinkResourceHandle. * src/Xml2MetalinkProcessor.cc (parseFile): Metalinker* -> MetalinkerHandle MetalinkEntry* -> MetalinkEntryHandle Removed try-catch block. (getEntry): MetalinkEntry* -> MetalinkEntryHandle MetalinkResource* -> MetalinkResourceHandle Removed try-catch block. (getResource): MetalinkResource* -> MetalinkResourceHandle Free result by using xmlXPathFreeObject() * src/Metalinker.cc (~Metalinker): Removed the deletion of entries. MetalinkEntry* -> MetalinkEntryHandle (queryEntry): Add multiple <file> Metalink support. * src/Metalinker.h (MetalinkEntries): Removed. (queryEntry): MetalinkEntry* -> MetalinkEntries * src/MetalinkProcessor.h (parseFile): Metalinker* -> MetalinkerHandle Bug fixes: * src/PeerChokeCommand.cc (execute): cat01->cat02 * src/DefaultPieceStorage.cc (DefaultPieceStorage): Added diskAdaptor(0) * src/TrackerWatcherComand.cc: (execute): Use btAnnounce->noMoreAnnounce() to determin whether the function returns true or not. * src/TrackerUpdateCommand.cc: (execute): Use btAnnounce->noMoreAnnounce() to determin whether the function returns true or not. * src/FtpConnection.cc (bulkReceiveResponse): Throw DlRetryEx if EOF got. This is the fix of the busy loop bug. * src/DownloadCommand.cc (DownloadCommand): Reuse PeerStat. segmentMan->getPeerStat() returns cached PeerStat. The value of "name" entry in torrent file is now set by *DiskAdaptor::setTopDir(...) methods. * src/MultiDiskAdaptor.h (topDir): New variable. (setTopDir): New function. (getTopDir): New function. * src/MultiDiskAdaptor.cc (getFilePath): Concat storDir, "/" and topDir. (mkdir): Use getFilePath() to get the directory path for output. * src/DefaultPieceStorage.cc (initStorage): Set the value of "name" entry to MultiDiskAdaptor, CopyDiskAdaptor. * src/CopyDiskAdaptor.h (topDir): New variable. (setTopDir): New function. (getTopDir): New function. * src/CopyDiskAdaptor.cc (fixFilename): Updated. Misc * src/UrlRequestInfo.h (e): Removed. (UrlRequestInfo): Removed e. (getDownloadEngine): Removed. * src/UrlRequestInfo.cc (handler): Rewritten. (printUrls): New function. (execute): Call printUrls(). * src/HandshakeMessage.cc (check): peerinteraction->getBtContext() -> btContext * src/PeerInteraction.h (getBtContext): Removed. * src/TorrentRequestInfo.h (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/TorrentRequestInfo.cc (haltRequested): Removed. (btHaltRequested): New variable. (torrentHandler): haltRequested -> btHaltRequested (execute): RequestInfo* -> RequestInfos * src/TorrentConsoleDownloadEngine.cc (afterEachIteration): haltRequested -> btHaltRequested. * src/ConsoleDownloadEngine.h (initStatistics): Added virtual. (calculateStatistics): Added virtual. (onEndOfRun): Added virtual. (afterEachIteration): Added virtual. * src/ConsoleDownloadEngine.cc (haltRequested): New variable. (afterEachIteration): New function. * src/main.cc (requestInfo): Removed. * src/SegmentMan.cc (findSlowerSegmentEntry): Refactored.
2006-11-08 16:25:38 +00:00
if(size == 0) {
if(socket->wantRead() || socket->wantWrite()) {
return false;
}
throw DlRetryEx(EX_GOT_EOF);
2006-11-09 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com> To add Metalink location option: * src/MetalinkRequestInfo.cc (execute): Call MetalinkEntry::setLocationPreference() * src/main.cc (showUsage): Added the help message for --metalink-location option. (main): Added --metalink-location option. * src/prefs.h (PREF_METALINK_LOCATION): New definition. * src/MetalinkEntry.cc (AddLocationPreference): New function object. (setLocationPreference): New function. * src/Xml2MetalinkProcessor.cc (getResource): Set location attribute to MetalinkResource To show URLs to download * src/UrlRequestInfo.h (printUrls): New function. To add multiple <file> Metalink support: * src/MetalinkEntry.h (MetalinkResources): Removed. (setLocationPreference): New function. (MetalinkEntryHandle): New type definition. (MetalinkEntries): New type definition. * src/Xml2MetalinkProcessor.h (getEntry): MetalinkEntry* -> MetalinkEntryHandle (getResource): MetalinkResource* -> MetalinkResourceHandle (parseFile): Metalinker* -> MetalinkerHandle * src/UrlRequestInfo.h (execute): RequestInfo* -> RequestInfos * src/MetalinkRequestInfo.cc (AccumulateNonP2PUrl): MetalinkResource* -> MetalinkResourceHandle (FindBitTorrentUrl): MetalinkResource* -> MetalinkResourceHandle (execute): RequestInfo* -> RequestInfos Added multiple <file> support. Print filename when it is queued. * src/MetalinkRequestInfo.h (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/RequestInfo.h (RequestInfoHandle): New type definition. (RequestInfos): New type definition. (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/MetalinkResource.h (MetalinkResourceHandle): New type definition. (MetalinkResources): New type definition. * src/MetalinkEntry.cc (~MetalinkEntry): Removed the deletion of the elements of resources, because the element is now of type MetalinkResourceHandle. (PrefOrder): MetalinkResource* -> MetalinkResourceHandle (Supported): MetalinkResource* -> MetalinkResourceHandle (dropUnsupportedResource): Removed the deletion of the elements of resources because the element is now of type MetalinkResourceHandle. * src/Xml2MetalinkProcessor.cc (parseFile): Metalinker* -> MetalinkerHandle MetalinkEntry* -> MetalinkEntryHandle Removed try-catch block. (getEntry): MetalinkEntry* -> MetalinkEntryHandle MetalinkResource* -> MetalinkResourceHandle Removed try-catch block. (getResource): MetalinkResource* -> MetalinkResourceHandle Free result by using xmlXPathFreeObject() * src/Metalinker.cc (~Metalinker): Removed the deletion of entries. MetalinkEntry* -> MetalinkEntryHandle (queryEntry): Add multiple <file> Metalink support. * src/Metalinker.h (MetalinkEntries): Removed. (queryEntry): MetalinkEntry* -> MetalinkEntries * src/MetalinkProcessor.h (parseFile): Metalinker* -> MetalinkerHandle Bug fixes: * src/PeerChokeCommand.cc (execute): cat01->cat02 * src/DefaultPieceStorage.cc (DefaultPieceStorage): Added diskAdaptor(0) * src/TrackerWatcherComand.cc: (execute): Use btAnnounce->noMoreAnnounce() to determin whether the function returns true or not. * src/TrackerUpdateCommand.cc: (execute): Use btAnnounce->noMoreAnnounce() to determin whether the function returns true or not. * src/FtpConnection.cc (bulkReceiveResponse): Throw DlRetryEx if EOF got. This is the fix of the busy loop bug. * src/DownloadCommand.cc (DownloadCommand): Reuse PeerStat. segmentMan->getPeerStat() returns cached PeerStat. The value of "name" entry in torrent file is now set by *DiskAdaptor::setTopDir(...) methods. * src/MultiDiskAdaptor.h (topDir): New variable. (setTopDir): New function. (getTopDir): New function. * src/MultiDiskAdaptor.cc (getFilePath): Concat storDir, "/" and topDir. (mkdir): Use getFilePath() to get the directory path for output. * src/DefaultPieceStorage.cc (initStorage): Set the value of "name" entry to MultiDiskAdaptor, CopyDiskAdaptor. * src/CopyDiskAdaptor.h (topDir): New variable. (setTopDir): New function. (getTopDir): New function. * src/CopyDiskAdaptor.cc (fixFilename): Updated. Misc * src/UrlRequestInfo.h (e): Removed. (UrlRequestInfo): Removed e. (getDownloadEngine): Removed. * src/UrlRequestInfo.cc (handler): Rewritten. (printUrls): New function. (execute): Call printUrls(). * src/HandshakeMessage.cc (check): peerinteraction->getBtContext() -> btContext * src/PeerInteraction.h (getBtContext): Removed. * src/TorrentRequestInfo.h (execute): RequestInfo* -> RequestInfos (getDownloadEngine): Removed. * src/TorrentRequestInfo.cc (haltRequested): Removed. (btHaltRequested): New variable. (torrentHandler): haltRequested -> btHaltRequested (execute): RequestInfo* -> RequestInfos * src/TorrentConsoleDownloadEngine.cc (afterEachIteration): haltRequested -> btHaltRequested. * src/ConsoleDownloadEngine.h (initStatistics): Added virtual. (calculateStatistics): Added virtual. (onEndOfRun): Added virtual. (afterEachIteration): Added virtual. * src/ConsoleDownloadEngine.cc (haltRequested): New variable. (afterEachIteration): New function. * src/main.cc (requestInfo): Removed. * src/SegmentMan.cc (findSlowerSegmentEntry): Refactored.
2006-11-08 16:25:38 +00:00
}
if(strbuf.size()+size > MAX_RECV_BUFFER) {
throw DlRetryEx
(StringFormat("Max FTP recv buffer reached. length=%lu",
static_cast<unsigned long>(strbuf.size()+size)).str());
}
strbuf.append(&buf[0], &buf[size]);
2006-02-21 12:28:42 +00:00
}
unsigned int status;
2006-02-21 12:28:42 +00:00
if(strbuf.size() >= 4) {
status = getStatus(strbuf);
if(status == 0) {
throw DlAbortEx(EX_INVALID_RESPONSE);
2006-02-21 12:28:42 +00:00
}
} else {
return false;
}
std::string::size_type length;
if((length = findEndOfResponse(status, strbuf)) != std::string::npos) {
2006-02-21 12:28:42 +00:00
response.first = status;
response.second = strbuf.substr(0, length);
logger->info(MSG_RECEIVE_RESPONSE, cuid, response.second.c_str());
strbuf.erase(0, length);
2006-02-21 12:28:42 +00:00
return true;
} else {
// didn't receive response fully.
return false;
}
}
unsigned int FtpConnection::receiveResponse()
{
std::pair<unsigned int, std::string> response;
2006-02-21 12:28:42 +00:00
if(bulkReceiveResponse(response)) {
return response.first;
} else {
return 0;
}
}
#ifdef __MINGW32__
# define LONGLONG_PRINTF "%I64d"
# define ULONGLONG_PRINTF "%I64u"
# define LONGLONG_SCANF "%I64d"
# define ULONGLONG_SCANF "%I64u"
#else
# define LONGLONG_PRINTF "%lld"
# define ULONGLONG_PRINTF "%llu"
# define LONGLONG_SCANF "%Ld"
# define ULONGLONG_SCANF "%Lu"
#endif // __MINGW32__
unsigned int FtpConnection::receiveSizeResponse(uint64_t& size)
{
std::pair<unsigned int, std::string> response;
2006-02-21 12:28:42 +00:00
if(bulkReceiveResponse(response)) {
if(response.first == 213) {
sscanf(response.second.c_str(), "%*u " ULONGLONG_SCANF,
reinterpret_cast<long long unsigned int*>(&size));
2006-02-21 12:28:42 +00:00
}
return response.first;
} else {
return 0;
}
}
unsigned int FtpConnection::receiveMdtmResponse(Time& time)
{
// MDTM command, specified in RFC3659.
std::pair<unsigned int, std::string> response;
if(bulkReceiveResponse(response)) {
if(response.first == 213) {
char buf[15]; // YYYYMMDDhhmmss+\0, milli second part is dropped.
sscanf(response.second.c_str(), "%*u %14s", buf);
if(strlen(buf) == 14) {
time = Time::parse(buf, "%Y%m%d%H%M%S");
} else {
time.setTimeInSec(-1);
}
}
return response.first;
} else {
return 0;
}
}
unsigned int FtpConnection::receivePasvResponse(std::pair<std::string, uint16_t>& dest)
{
std::pair<unsigned int, std::string> response;
2006-02-21 12:28:42 +00:00
if(bulkReceiveResponse(response)) {
if(response.first == 227) {
// we assume the format of response is "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)."
unsigned int h1, h2, h3, h4, p1, p2;
std::string::size_type p = response.second.find("(");
2006-02-21 12:28:42 +00:00
if(p >= 4) {
sscanf(response.second.substr(response.second.find("(")).c_str(),
"(%u,%u,%u,%u,%u,%u).",
2006-02-21 12:28:42 +00:00
&h1, &h2, &h3, &h4, &p1, &p2);
// ip address
dest.first = Util::uitos(h1)+"."+Util::uitos(h2)+"."+Util::uitos(h3)+"."+Util::uitos(h4);
2006-02-21 12:28:42 +00:00
// port number
dest.second = 256*p1+p2;
} else {
throw DlRetryEx(EX_INVALID_RESPONSE);
2006-02-21 12:28:42 +00:00
}
}
return response.first;
} else {
return 0;
}
}
unsigned int FtpConnection::receivePwdResponse(std::string& pwd)
{
std::pair<unsigned int, std::string> response;
if(bulkReceiveResponse(response)) {
if(response.first == 257) {
std::string::size_type first;
std::string::size_type last;
if((first = response.second.find("\"")) != std::string::npos &&
(last = response.second.find("\"", ++first)) != std::string::npos) {
pwd = response.second.substr(first, last-first);
} else {
throw DlAbortEx(EX_INVALID_RESPONSE);
}
}
return response.first;
} else {
return 0;
}
}
void FtpConnection::setBaseWorkingDir(const std::string& baseWorkingDir)
{
_baseWorkingDir = baseWorkingDir;
}
const std::string& FtpConnection::getBaseWorkingDir() const
{
return _baseWorkingDir;
}
} // namespace aria2