From: Alex Rousskov Date: Tue, 5 Aug 2014 00:17:16 +0000 (-0600) Subject: Done moving FTP code around. Polished moved code to match new locations. X-Git-Tag: SQUID_3_5_0_1~117^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5517260ac271f3b217a1d7f8e955221ba4c1156a;p=thirdparty%2Fsquid.git Done moving FTP code around. Polished moved code to match new locations. src/clients/FtpNative is now src/clients/FtpRelay. It was awkward to use a non-noun "Native" as a class name, and the class was already described as "relaying FTP". --- diff --git a/src/FwdState.cc b/src/FwdState.cc index 081f4326ab..7cfffb7116 100644 --- a/src/FwdState.cc +++ b/src/FwdState.cc @@ -1001,9 +1001,9 @@ FwdState::dispatch() case AnyP::PROTO_FTP: if (request->flags.ftpNative) - ftpGatewayServerStart(this); + Ftp::StartRelay(this); else - ftpStart(this); + Ftp::StartGateway(this); break; case AnyP::PROTO_CACHE_OBJECT: diff --git a/src/clients/FtpClient.cc b/src/clients/FtpClient.cc index 0f15040e17..166c0f2d62 100644 --- a/src/clients/FtpClient.cc +++ b/src/clients/FtpClient.cc @@ -61,7 +61,7 @@ escapeIAC(const char *buf) /// configures the channel with a descriptor and registers a close handler void -FtpChannel::opened(const Comm::ConnectionPointer &newConn, +Ftp::Channel::opened(const Comm::ConnectionPointer &newConn, const AsyncCall::Pointer &aCloser) { assert(!Comm::IsConnOpen(conn)); @@ -77,7 +77,7 @@ FtpChannel::opened(const Comm::ConnectionPointer &newConn, /// planned close: removes the close handler and calls comm_close void -FtpChannel::close() +Ftp::Channel::close() { // channels with active listeners will be closed when the listener handler dies. if (Comm::IsConnOpen(conn)) { @@ -88,7 +88,7 @@ FtpChannel::close() } void -FtpChannel::forget() +Ftp::Channel::forget() { if (Comm::IsConnOpen(conn)) { commUnsetConnTimeout(conn); @@ -98,14 +98,14 @@ FtpChannel::forget() } void -FtpChannel::clear() +Ftp::Channel::clear() { conn = NULL; closer = NULL; } -ServerStateData::ServerStateData(FwdState *fwdState): - AsyncJob("Ftp::ServerStateData"), ::ServerStateData(fwdState) +Ftp::Client::Client(FwdState *fwdState): + AsyncJob("Ftp::Client"), ::ServerStateData(fwdState) { ++statCounter.server.all.requests; ++statCounter.server.ftp.requests; @@ -114,14 +114,14 @@ ServerStateData::ServerStateData(FwdState *fwdState): ctrl.buf = static_cast(memAllocBuf(4096, &ctrl.size)); ctrl.offset = 0; - typedef CommCbMemFunT Dialer; + typedef CommCbMemFunT Dialer; const AsyncCall::Pointer closer = JobCallback(9, 5, Dialer, this, - ServerStateData::ctrlClosed); + Ftp::Client::ctrlClosed); ctrl.opened(fwdState->serverConnection(), closer); } void -ServerStateData::DataChannel::addr(const Ip::Address &import) +Ftp::Client::DataChannel::addr(const Ip::Address &import) { static char addrBuf[MAX_IPSTRLEN]; import.toStr(addrBuf, sizeof(addrBuf)); @@ -130,10 +130,10 @@ ServerStateData::DataChannel::addr(const Ip::Address &import) port = import.port(); } -ServerStateData::~ServerStateData() +Ftp::Client::~Client() { if (data.opener != NULL) { - data.opener->cancel("Ftp::ServerStateData destructed"); + data.opener->cancel("Ftp::Client destructed"); data.opener = NULL; } data.close(); @@ -162,13 +162,13 @@ ServerStateData::~ServerStateData() } void -ServerStateData::start() +Ftp::Client::start() { scheduleReadControlReply(0); } void -ServerStateData::initReadBuf() +Ftp::Client::initReadBuf() { if (data.readBuf == NULL) { data.readBuf = new MemBuf; @@ -180,7 +180,7 @@ ServerStateData::initReadBuf() * Close the FTP server connection(s). Used by serverComplete(). */ void -ServerStateData::closeServer() +Ftp::Client::closeServer() { if (Comm::IsConnOpen(ctrl.conn)) { debugs(9,3, HERE << "closing FTP server FD " << ctrl.conn->fd << ", this " << this); @@ -203,13 +203,13 @@ ServerStateData::closeServer() \retval false Either control channel or data is still active. */ bool -ServerStateData::doneWithServer() const +Ftp::Client::doneWithServer() const { return !Comm::IsConnOpen(ctrl.conn) && !Comm::IsConnOpen(data.conn); } void -ServerStateData::failed(err_type error, int xerrno) +Ftp::Client::failed(err_type error, int xerrno) { debugs(9,3,HERE << "entry-null=" << (entry?entry->isEmpty():0) << ", entry=" << entry); @@ -247,7 +247,7 @@ ServerStateData::failed(err_type error, int xerrno) } Http::StatusCode -ServerStateData::failedHttpStatus(err_type &error) +Ftp::Client::failedHttpStatus(err_type &error) { if (error == ERR_NONE) error = ERR_FTP_FAILURE; @@ -261,7 +261,7 @@ ServerStateData::failedHttpStatus(err_type &error) * buffered_ok=1. Perhaps it can be removed at some point. */ void -ServerStateData::scheduleReadControlReply(int buffered_ok) +Ftp::Client::scheduleReadControlReply(int buffered_ok) { debugs(9, 3, HERE << ctrl.conn); @@ -277,18 +277,18 @@ ServerStateData::scheduleReadControlReply(int buffered_ok) commUnsetConnTimeout(data.conn); } - typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, ServerStateData::timeout); + typedef CommCbMemFunT TimeoutDialer; + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, Ftp::Client::timeout); commSetConnTimeout(ctrl.conn, Config.Timeout.read, timeoutCall); - typedef CommCbMemFunT Dialer; - AsyncCall::Pointer reader = JobCallback(9, 5, Dialer, this, ServerStateData::readControlReply); + typedef CommCbMemFunT Dialer; + AsyncCall::Pointer reader = JobCallback(9, 5, Dialer, this, Ftp::Client::readControlReply); comm_read(ctrl.conn, ctrl.buf + ctrl.offset, ctrl.size - ctrl.offset, reader); } } void -ServerStateData::readControlReply(const CommIoCbParams &io) +Ftp::Client::readControlReply(const CommIoCbParams &io) { debugs(9, 3, HERE << "FD " << io.fd << ", Read " << io.size << " bytes"); @@ -345,7 +345,7 @@ ServerStateData::readControlReply(const CommIoCbParams &io) } void -ServerStateData::handleControlReply() +Ftp::Client::handleControlReply() { debugs(9, 3, HERE); @@ -381,7 +381,7 @@ ServerStateData::handleControlReply() } bool -ServerStateData::handlePasvReply(Ip::Address &srvAddr) +Ftp::Client::handlePasvReply(Ip::Address &srvAddr) { int code = ctrl.replycode; char *buf; @@ -412,7 +412,7 @@ ServerStateData::handlePasvReply(Ip::Address &srvAddr) } bool -ServerStateData::handleEpsvReply(Ip::Address &remoteAddr) +Ftp::Client::handleEpsvReply(Ip::Address &remoteAddr) { int code = ctrl.replycode; char *buf; @@ -517,10 +517,10 @@ ServerStateData::handleEpsvReply(Ip::Address &remoteAddr) } // The server-side EPRT and PORT commands are not yet implemented. -// The ServerStateData::sendEprt() will fail because of the unimplemented +// The Ftp::Client::sendEprt() will fail because of the unimplemented // openListenSocket() or sendPort() methods bool -ServerStateData::sendEprt() +Ftp::Client::sendEprt() { if (!Config.Ftp.eprt) { /* Disabled. Switch immediately to attempting old PORT command. */ @@ -559,14 +559,14 @@ ServerStateData::sendEprt() } bool -ServerStateData::sendPort() +Ftp::Client::sendPort() { failed(ERR_FTP_FAILURE, 0); return false; } bool -ServerStateData::sendPassive() +Ftp::Client::sendPassive() { debugs(9, 3, HERE); @@ -687,7 +687,7 @@ ServerStateData::sendPassive() void -ServerStateData::connectDataChannel() +Ftp::Client::connectDataChannel() { safe_free(ctrl.last_command); @@ -705,37 +705,37 @@ ServerStateData::connectDataChannel() debugs(9, 3, HERE << "connecting to " << conn->remote); - data.opener = commCbCall(9,3, "Ftp::ServerStateData::dataChannelConnected", - CommConnectCbPtrFun(ServerStateData::dataChannelConnected, this)); + data.opener = commCbCall(9,3, "Ftp::Client::dataChannelConnected", + CommConnectCbPtrFun(Ftp::Client::dataChannelConnected, this)); Comm::ConnOpener *cs = new Comm::ConnOpener(conn, data.opener, Config.Timeout.connect); cs->setHost(data.host); AsyncJob::Start(cs); } void -ServerStateData::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data) +Ftp::Client::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data) { - ServerStateData *ftpState = static_cast(data); + Client *ftpState = static_cast(data); ftpState->dataChannelConnected(conn, status, xerrno); } bool -ServerStateData::openListenSocket() +Ftp::Client::openListenSocket() { return false; } /// creates a data channel Comm close callback AsyncCall::Pointer -ServerStateData::dataCloser() +Ftp::Client::dataCloser() { - typedef CommCbMemFunT Dialer; - return JobCallback(9, 5, Dialer, this, ServerStateData::dataClosed); + typedef CommCbMemFunT Dialer; + return JobCallback(9, 5, Dialer, this, Ftp::Client::dataClosed); } /// handler called by Comm when FTP data channel is closed unexpectedly void -ServerStateData::dataClosed(const CommCloseCbParams &io) +Ftp::Client::dataClosed(const CommCloseCbParams &io) { debugs(9, 4, HERE); if (data.listenConn != NULL) { @@ -747,7 +747,7 @@ ServerStateData::dataClosed(const CommCloseCbParams &io) } void -ServerStateData::writeCommand(const char *buf) +Ftp::Client::writeCommand(const char *buf) { char *ebuf; /* trace FTP protocol communications at level 2 */ @@ -770,16 +770,16 @@ ServerStateData::writeCommand(const char *buf) return; } - typedef CommCbMemFunT Dialer; + typedef CommCbMemFunT Dialer; AsyncCall::Pointer call = JobCallback(9, 5, Dialer, this, - ServerStateData::writeCommandCallback); + Ftp::Client::writeCommandCallback); Comm::Write(ctrl.conn, ctrl.last_command, strlen(ctrl.last_command), call, NULL); scheduleReadControlReply(0); } void -ServerStateData::writeCommandCallback(const CommIoCbParams &io) +Ftp::Client::writeCommandCallback(const CommIoCbParams &io) { debugs(9, 5, HERE << "wrote " << io.size << " bytes"); @@ -803,15 +803,15 @@ ServerStateData::writeCommandCallback(const CommIoCbParams &io) /// handler called by Comm when FTP control channel is closed unexpectedly void -ServerStateData::ctrlClosed(const CommCloseCbParams &io) +Ftp::Client::ctrlClosed(const CommCloseCbParams &io) { debugs(9, 4, HERE); ctrl.clear(); - mustStop("Ftp::ServerStateData::ctrlClosed"); + mustStop("Ftp::Client::ctrlClosed"); } void -ServerStateData::timeout(const CommTimeoutCbParams &io) +Ftp::Client::timeout(const CommTimeoutCbParams &io) { debugs(9, 4, HERE << io.conn << ": '" << entry->url() << "'" ); @@ -823,13 +823,13 @@ ServerStateData::timeout(const CommTimeoutCbParams &io) } const Comm::ConnectionPointer & -ServerStateData::dataConnection() const +Ftp::Client::dataConnection() const { return data.conn; } void -ServerStateData::maybeReadVirginBody() +Ftp::Client::maybeReadVirginBody() { // too late to read if (!Comm::IsConnOpen(data.conn) || fd_table[data.conn->fd].closing()) @@ -849,20 +849,20 @@ ServerStateData::maybeReadVirginBody() data.read_pending = true; - typedef CommCbMemFunT TimeoutDialer; + typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(9, 5, - TimeoutDialer, this, ServerStateData::timeout); + TimeoutDialer, this, Ftp::Client::timeout); commSetConnTimeout(data.conn, Config.Timeout.read, timeoutCall); debugs(9,5,HERE << "queueing read on FD " << data.conn->fd); - typedef CommCbMemFunT Dialer; + typedef CommCbMemFunT Dialer; entry->delayAwareRead(data.conn, data.readBuf->space(), read_sz, - JobCallback(9, 5, Dialer, this, ServerStateData::dataRead)); + JobCallback(9, 5, Dialer, this, Ftp::Client::dataRead)); } void -ServerStateData::dataRead(const CommIoCbParams &io) +Ftp::Client::dataRead(const CommIoCbParams &io) { int j; int bin; @@ -931,7 +931,7 @@ ServerStateData::dataRead(const CommIoCbParams &io) } void -ServerStateData::dataComplete() +Ftp::Client::dataComplete() { debugs(9, 3,HERE); @@ -966,7 +966,7 @@ ServerStateData::dataComplete() * including canceling close handlers */ void -ServerStateData::abortTransaction(const char *reason) +Ftp::Client::abortTransaction(const char *reason) { debugs(9, 3, HERE << "aborting transaction for " << reason << "; FD " << (ctrl.conn!=NULL?ctrl.conn->fd:-1) << ", Data FD " << (data.conn!=NULL?data.conn->fd:-1) << ", this " << this); @@ -976,7 +976,7 @@ ServerStateData::abortTransaction(const char *reason) } fwd->handleUnregisteredServerEnd(); - mustStop("ServerStateData::abortTransaction"); + mustStop("Ftp::Client::abortTransaction"); } /** @@ -984,18 +984,18 @@ ServerStateData::abortTransaction(const char *reason) * on the data socket */ void -ServerStateData::switchTimeoutToDataChannel() +Ftp::Client::switchTimeoutToDataChannel() { commUnsetConnTimeout(ctrl.conn); - typedef CommCbMemFunT TimeoutDialer; + typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(9, 5, TimeoutDialer, this, - ServerStateData::timeout); + Ftp::Client::timeout); commSetConnTimeout(data.conn, Config.Timeout.read, timeoutCall); } void -ServerStateData::sentRequestBody(const CommIoCbParams &io) +Ftp::Client::sentRequestBody(const CommIoCbParams &io) { if (io.size > 0) kb_incr(&(statCounter.server.ftp.kbytes_out), io.size); @@ -1006,7 +1006,7 @@ ServerStateData::sentRequestBody(const CommIoCbParams &io) * called after we wrote the last byte of the request body */ void -ServerStateData::doneSendingRequestBody() +Ftp::Client::doneSendingRequestBody() { ::ServerStateData::doneSendingRequestBody(); debugs(9,3, HERE); @@ -1020,7 +1020,7 @@ ServerStateData::doneSendingRequestBody() /// Parses FTP server control response into ctrl structure fields, /// setting bytesUsed and returning true on success. bool -ServerStateData::parseControlReply(size_t &bytesUsed) +Ftp::Client::parseControlReply(size_t &bytesUsed) { char *s; char *sbuf; diff --git a/src/clients/FtpClient.h b/src/clients/FtpClient.h index b2fc76971f..ab90b3dbbf 100644 --- a/src/clients/FtpClient.h +++ b/src/clients/FtpClient.h @@ -3,8 +3,8 @@ * */ -#ifndef SQUID_FTP_SERVER_H -#define SQUID_FTP_SERVER_H +#ifndef SQUID_FTP_CLIENT_H +#define SQUID_FTP_CLIENT_H #include "Server.h" @@ -14,8 +14,8 @@ namespace Ftp { extern const char *const crlf; /// common code for FTP server control and data channels -/// does not own the channel descriptor, which is managed by FtpStateData -class FtpChannel +/// does not own the channel descriptor, which is managed by Ftp::Client +class Channel { public: /// called after the socket is opened, sets up close handler @@ -44,17 +44,22 @@ private: AsyncCall::Pointer closer; ///< Comm close handler callback }; -/// Base class for FTP over HTTP and FTP Gateway server state. -class ServerStateData: public ::ServerStateData +/// Base class for FTP Gateway and FTP Native client classes. +class Client: public ::ServerStateData { public: - ServerStateData(FwdState *fwdState); - virtual ~ServerStateData(); + explicit Client(FwdState *fwdState); + virtual ~Client(); + /// handle a fatal transaction error, closing the control connection virtual void failed(err_type error = ERR_NONE, int xerrno = 0); + + /// read timeout handler virtual void timeout(const CommTimeoutCbParams &io); - virtual const Comm::ConnectionPointer & dataConnection() const; - virtual void abortTransaction(const char *reason); + + /* ServerStateData API */ + virtual void maybeReadVirginBody(); + void writeCommand(const char *buf); /// extracts remoteAddr from PASV response, validates it, @@ -67,12 +72,11 @@ public: bool sendPassive(); void connectDataChannel(); bool openListenSocket(); - virtual void maybeReadVirginBody(); void switchTimeoutToDataChannel(); // \todo: optimize ctrl and data structs member order, to minimize size /// FTP control channel info; the channel is opened once per transaction - struct CtrlChannel: public FtpChannel { + struct CtrlChannel: public Ftp::Channel { char *buf; size_t size; size_t offset; @@ -83,7 +87,7 @@ public: } ctrl; /// FTP data channel info; the channel may be opened/closed a few times - struct DataChannel: public FtpChannel { + struct DataChannel: public Ftp::Channel { MemBuf *readBuf; char *host; unsigned short port; @@ -128,11 +132,15 @@ public: char *old_reply; protected: + /* AsyncJob API */ virtual void start(); - void initReadBuf(); + /* ServerStateData API */ virtual void closeServer(); virtual bool doneWithServer() const; + virtual const Comm::ConnectionPointer & dataConnection() const; + virtual void abortTransaction(const char *reason); + virtual Http::StatusCode failedHttpStatus(err_type &error); void ctrlClosed(const CommCloseCbParams &io); void scheduleReadControlReply(int buffered_ok); @@ -145,6 +153,7 @@ protected: void dataComplete(); AsyncCall::Pointer dataCloser(); virtual void dataClosed(const CommCloseCbParams &io); + void initReadBuf(); // sending of the request body to the server virtual void sentRequestBody(const CommIoCbParams &io); @@ -153,15 +162,9 @@ protected: private: bool parseControlReply(size_t &bytesUsed); - CBDATA_CLASS2(ServerStateData); + CBDATA_CLASS2(Client); }; -/// parses and validates "A1,A2,A3,A4,P1,P2" IP,port sequence -bool ParseIpPort(const char *buf, const char *forceIp, Ip::Address &addr); -/// parses and validates EPRT "" proto,ip,port sequence -bool ParseProtoIpPort(const char *buf, Ip::Address &addr); -/// parses a ftp quoted quote-escaped path -const char *unescapeDoubleQuoted(const char *quotedPath); } // namespace Ftp -#endif /* SQUID_FTP_SERVER_H */ +#endif /* SQUID_FTP_CLIENT_H */ diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc index d32216e500..ecab798771 100644 --- a/src/clients/FtpGateway.cc +++ b/src/clients/FtpGateway.cc @@ -32,6 +32,7 @@ #include "squid.h" #include "acl/FilledChecklist.h" +#include "clients/forward.h" #include "clients/FtpClient.h" #include "comm.h" #include "comm/ConnOpener.h" @@ -71,17 +72,15 @@ #include +namespace Ftp { + /** \defgroup ServerProtocolFTPInternal Server-Side FTP Internals \ingroup ServerProtocolFTPAPI */ -#define CTRL_BUFLEN 1024 -/// \ingroup ServerProtocolFTPInternal -static char cbuf[CTRL_BUFLEN]; - /// \ingroup ServerProtocolFTPInternal -struct _ftp_flags { +struct GatewayFlags { /* passive mode */ bool pasv_supported; ///< PASV command is allowed @@ -113,17 +112,20 @@ struct _ftp_flags { bool completed_forwarding; }; -class FtpStateData; +class Gateway; /// \ingroup ServerProtocolFTPInternal -typedef void (FTPSM) (FtpStateData *); +typedef void (StateMethod)(Ftp::Gateway *); /// \ingroup ServerProtocolFTPInternal -class FtpStateData : public Ftp::ServerStateData +/// FTP Gateway: An FTP client that takes an HTTP request with an ftp:// URI, +/// converts it into one or more FTP commands, and then +/// converts one or more FTP responses into the final HTTP response. +class Gateway : public Ftp::Client { public: - FtpStateData(FwdState *); - virtual ~FtpStateData(); + Gateway(FwdState *); + virtual ~Gateway(); char user[MAX_URL]; char password[MAX_URL]; int password_url; @@ -147,7 +149,7 @@ public: char typecode; MemBuf listing; ///< FTP directory listing in HTML format. - struct _ftp_flags flags; + GatewayFlags flags; public: // these should all be private @@ -156,7 +158,7 @@ public: void loginParser(const char *, int escaped); int restartable(); void appendSuccessHeader(); - void hackShortcut(FTPSM * nextState); + void hackShortcut(StateMethod *nextState); void unhack(); void readStor(); void parseListing(); @@ -198,10 +200,14 @@ private: // BodyConsumer for HTTP: consume request body. virtual void handleRequestBodyProducerAborted(); - CBDATA_CLASS2(FtpStateData); + CBDATA_CLASS2(Gateway); }; -CBDATA_CLASS_INIT(FtpStateData); +} // namespace Ftp + +typedef Ftp::StateMethod FTPSM; // to avoid lots of non-changes + +CBDATA_NAMESPACED_CLASS_INIT(Ftp, Gateway); /// \ingroup ServerProtocolFTPInternal typedef struct { @@ -219,6 +225,10 @@ typedef struct { /// \ingroup ServerProtocolFTPInternal #define FTP_LOGIN_NOT_ESCAPED 0 +#define CTRL_BUFLEN 1024 +/// \ingroup ServerProtocolFTPInternal +static char cbuf[CTRL_BUFLEN]; + /* * State machine functions * send == state transition @@ -342,9 +352,9 @@ FTPSM *FTP_SM_FUNCS[] = { /// handler called by Comm when FTP data channel is closed unexpectedly void -FtpStateData::dataClosed(const CommCloseCbParams &io) +Ftp::Gateway::dataClosed(const CommCloseCbParams &io) { - Ftp::ServerStateData::dataClosed(io); + Ftp::Client::dataClosed(io); failed(ERR_FTP_FAILURE, 0); /* failed closes ctrl.conn and frees ftpState */ @@ -354,8 +364,9 @@ FtpStateData::dataClosed(const CommCloseCbParams &io) */ } -FtpStateData::FtpStateData(FwdState *fwdState): AsyncJob("FtpStateData"), - Ftp::ServerStateData(fwdState) +Ftp::Gateway::Gateway(FwdState *fwdState): + AsyncJob("FtpStateData"), + Ftp::Client(fwdState) { const char *url = entry->url(); debugs(9, 3, HERE << "'" << url << "'" ); @@ -373,7 +384,7 @@ FtpStateData::FtpStateData(FwdState *fwdState): AsyncJob("FtpStateData"), initReadBuf(); } -FtpStateData::~FtpStateData() +Ftp::Gateway::~Gateway() { debugs(9, 3, HERE << entry->url() ); @@ -408,7 +419,7 @@ FtpStateData::~FtpStateData() * Produces filled member variables user, password, password_url if anything found. */ void -FtpStateData::loginParser(const char *login, int escaped) +Ftp::Gateway::loginParser(const char *login, int escaped) { const char *u = NULL; // end of the username sub-string int len; // length of the current sub-string to handle. @@ -461,13 +472,13 @@ FtpStateData::loginParser(const char *login, int escaped) } void -FtpStateData::listenForDataChannel(const Comm::ConnectionPointer &conn) +Ftp::Gateway::listenForDataChannel(const Comm::ConnectionPointer &conn) { assert(!Comm::IsConnOpen(data.conn)); - typedef CommCbMemFunT AcceptDialer; + typedef CommCbMemFunT AcceptDialer; typedef AsyncCallT AcceptCall; - RefCount call = static_cast(JobCallback(11, 5, AcceptDialer, this, FtpStateData::ftpAcceptDataConnection)); + RefCount call = static_cast(JobCallback(11, 5, AcceptDialer, this, Ftp::Gateway::ftpAcceptDataConnection)); Subscription::Pointer sub = new CallSubscription(call); const char *note = entry->url(); @@ -493,7 +504,7 @@ FtpStateData::listenForDataChannel(const Comm::ConnectionPointer &conn) } void -FtpStateData::timeout(const CommTimeoutCbParams &io) +Ftp::Gateway::timeout(const CommTimeoutCbParams &io) { if (SENT_PASV == state) { /* stupid ftp.netscape.com, of FTP server behind stupid firewall rules */ @@ -508,7 +519,7 @@ FtpStateData::timeout(const CommTimeoutCbParams &io) data.close(); } - Ftp::ServerStateData::timeout(io); + Ftp::Client::timeout(io); } /// \ingroup ServerProtocolFTPInternal @@ -546,7 +557,7 @@ ftpListPartsFree(ftpListParts ** parts) /// \ingroup ServerProtocolFTPInternal static ftpListParts * -ftpListParseParts(const char *buf, struct _ftp_flags flags) +ftpListParseParts(const char *buf, struct Ftp::GatewayFlags flags) { ftpListParts *p = NULL; char *t = NULL; @@ -776,7 +787,7 @@ found: } MemBuf * -FtpStateData::htmlifyListEntry(const char *line) +Ftp::Gateway::htmlifyListEntry(const char *line) { char icon[2048]; char href[2048 + 40]; @@ -913,7 +924,7 @@ FtpStateData::htmlifyListEntry(const char *line) } void -FtpStateData::parseListing() +Ftp::Gateway::parseListing() { char *buf = data.readBuf->content(); char *sbuf; /* NULL-terminated copy of termedBuf */ @@ -996,9 +1007,9 @@ FtpStateData::parseListing() } void -FtpStateData::processReplyBody() +Ftp::Gateway::processReplyBody() { - debugs(9, 3, HERE << "FtpStateData::processReplyBody starting."); + debugs(9, 3, HERE << "Ftp::Gateway::processReplyBody starting."); if (request->method == Http::METHOD_HEAD && (flags.isdir || theSize != -1)) { serverComplete(); @@ -1021,7 +1032,7 @@ FtpStateData::processReplyBody() #if USE_ADAPTATION if (adaptationAccessCheckPending) { - debugs(9,3, HERE << "returning from FtpStateData::processReplyBody due to adaptationAccessCheckPending"); + debugs(9,3, HERE << "returning from Ftp::Gateway::processReplyBody due to adaptationAccessCheckPending"); return; } @@ -1063,7 +1074,7 @@ FtpStateData::processReplyBody() \retval 0 if something is missing. */ int -FtpStateData::checkAuth(const HttpHeader * req_hdr) +Ftp::Gateway::checkAuth(const HttpHeader * req_hdr) { /* default username */ xstrncpy(user, "anonymous", MAX_URL); @@ -1108,7 +1119,7 @@ FtpStateData::checkAuth(const HttpHeader * req_hdr) static String str_type_eq; void -FtpStateData::checkUrlpath() +Ftp::Gateway::checkUrlpath() { int l; size_t t; @@ -1146,7 +1157,7 @@ FtpStateData::checkUrlpath() } void -FtpStateData::buildTitleUrl() +Ftp::Gateway::buildTitleUrl() { title_url = "ftp://"; @@ -1188,15 +1199,8 @@ FtpStateData::buildTitleUrl() base_href.append("/"); } -/// \ingroup ServerProtocolFTPAPI void -ftpStart(FwdState * fwd) -{ - AsyncJob::Start(new FtpStateData(fwd)); -} - -void -FtpStateData::start() +Ftp::Gateway::start() { if (!checkAuth(&request->header)) { /* create appropriate reply */ @@ -1213,15 +1217,15 @@ FtpStateData::start() state = BEGIN; - Ftp::ServerStateData::start(); + Ftp::Client::start(); } /* ====================================================================== */ void -FtpStateData::handleControlReply() +Ftp::Gateway::handleControlReply() { - Ftp::ServerStateData::handleControlReply(); + Ftp::Client::handleControlReply(); if (ctrl.message == NULL) return; // didn't get complete reply yet @@ -1240,7 +1244,7 @@ FtpStateData::handleControlReply() /// \ingroup ServerProtocolFTPInternal static void -ftpReadWelcome(FtpStateData * ftpState) +ftpReadWelcome(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1271,7 +1275,7 @@ ftpReadWelcome(FtpStateData * ftpState) * its NOT a general failure. But a correct FTP response type. */ void -FtpStateData::loginFailed() +Ftp::Gateway::loginFailed() { ErrorState *err = NULL; const char *command, *reply; @@ -1335,7 +1339,7 @@ FtpStateData::loginFailed() } const char * -FtpStateData::ftpRealm() +Ftp::Gateway::ftpRealm() { static char realm[8192]; @@ -1352,7 +1356,7 @@ FtpStateData::ftpRealm() /// \ingroup ServerProtocolFTPInternal static void -ftpSendUser(FtpStateData * ftpState) +ftpSendUser(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendUser")) @@ -1367,12 +1371,12 @@ ftpSendUser(FtpStateData * ftpState) ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_USER; + ftpState->state = Ftp::Client::SENT_USER; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadUser(FtpStateData * ftpState) +ftpReadUser(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1388,7 +1392,7 @@ ftpReadUser(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendPass(FtpStateData * ftpState) +ftpSendPass(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendPass")) @@ -1396,12 +1400,12 @@ ftpSendPass(FtpStateData * ftpState) snprintf(cbuf, CTRL_BUFLEN, "PASS %s\r\n", ftpState->password); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_PASS; + ftpState->state = Ftp::Client::SENT_PASS; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadPass(FtpStateData * ftpState) +ftpReadPass(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE << "code=" << code); @@ -1415,7 +1419,7 @@ ftpReadPass(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendType(FtpStateData * ftpState) +ftpSendType(Ftp::Gateway * ftpState) { const char *t; const char *filename; @@ -1463,12 +1467,12 @@ ftpSendType(FtpStateData * ftpState) ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_TYPE; + ftpState->state = Ftp::Client::SENT_TYPE; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadType(FtpStateData * ftpState) +ftpReadType(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; char *path; @@ -1509,7 +1513,7 @@ ftpReadType(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpTraverseDirectory(FtpStateData * ftpState) +ftpTraverseDirectory(Ftp::Gateway * ftpState) { wordlist *w; debugs(9, 4, HERE << (ftpState->filepath ? ftpState->filepath : "")); @@ -1547,7 +1551,7 @@ ftpTraverseDirectory(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendCwd(FtpStateData * ftpState) +ftpSendCwd(Ftp::Gateway * ftpState) { char *path = NULL; @@ -1569,12 +1573,12 @@ ftpSendCwd(FtpStateData * ftpState) ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_CWD; + ftpState->state = Ftp::Client::SENT_CWD; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadCwd(FtpStateData * ftpState) +ftpReadCwd(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1605,7 +1609,7 @@ ftpReadCwd(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendMkdir(FtpStateData * ftpState) +ftpSendMkdir(Ftp::Gateway * ftpState) { char *path = NULL; @@ -1617,12 +1621,12 @@ ftpSendMkdir(FtpStateData * ftpState) debugs(9, 3, HERE << "with path=" << path); snprintf(cbuf, CTRL_BUFLEN, "MKD %s\r\n", path); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_MKDIR; + ftpState->state = Ftp::Client::SENT_MKDIR; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadMkdir(FtpStateData * ftpState) +ftpReadMkdir(Ftp::Gateway * ftpState) { char *path = ftpState->filepath; int code = ftpState->ctrl.replycode; @@ -1644,7 +1648,7 @@ ftpReadMkdir(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpGetFile(FtpStateData * ftpState) +ftpGetFile(Ftp::Gateway * ftpState) { assert(*ftpState->filepath != '\0'); ftpState->flags.isdir = 0; @@ -1653,7 +1657,7 @@ ftpGetFile(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpListDir(FtpStateData * ftpState) +ftpListDir(Ftp::Gateway * ftpState) { if (ftpState->flags.dir_slash) { debugs(9, 3, HERE << "Directory path did not end in /"); @@ -1666,7 +1670,7 @@ ftpListDir(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendMdtm(FtpStateData * ftpState) +ftpSendMdtm(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendMdtm")) @@ -1675,12 +1679,12 @@ ftpSendMdtm(FtpStateData * ftpState) assert(*ftpState->filepath != '\0'); snprintf(cbuf, CTRL_BUFLEN, "MDTM %s\r\n", ftpState->filepath); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_MDTM; + ftpState->state = Ftp::Client::SENT_MDTM; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadMdtm(FtpStateData * ftpState) +ftpReadMdtm(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1698,7 +1702,7 @@ ftpReadMdtm(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendSize(FtpStateData * ftpState) +ftpSendSize(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendSize")) @@ -1712,7 +1716,7 @@ ftpSendSize(FtpStateData * ftpState) assert(*ftpState->filepath != '\0'); snprintf(cbuf, CTRL_BUFLEN, "SIZE %s\r\n", ftpState->filepath); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_SIZE; + ftpState->state = Ftp::Client::SENT_SIZE; } else /* Skip to next state no non-binary transfers */ ftpSendPassive(ftpState); @@ -1720,7 +1724,7 @@ ftpSendSize(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpReadSize(FtpStateData * ftpState) +ftpReadSize(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1747,7 +1751,7 @@ ftpReadSize(FtpStateData * ftpState) \ingroup ServerProtocolFTPInternal */ static void -ftpReadEPSV(FtpStateData* ftpState) +ftpReadEPSV(Ftp::Gateway* ftpState) { Ip::Address srvAddr; // unused if (ftpState->handleEpsvReply(srvAddr)) { @@ -1765,7 +1769,7 @@ ftpReadEPSV(FtpStateData* ftpState) * The failover mechanism should check for previous state and re-call with alternates on failure. */ static void -ftpSendPassive(FtpStateData * ftpState) +ftpSendPassive(Ftp::Gateway * ftpState) { /** Checks the server control channel is still available before running. */ if (!ftpState || !ftpState->haveControlChannel("ftpSendPassive")) @@ -1774,7 +1778,7 @@ ftpSendPassive(FtpStateData * ftpState) debugs(9, 3, HERE); /** \par - * Checks for 'HEAD' method request and passes off for special handling by FtpStateData::processHeadResponse(). */ + * Checks for 'HEAD' method request and passes off for special handling by Ftp::Gateway::processHeadResponse(). */ if (ftpState->request->method == Http::METHOD_HEAD && (ftpState->flags.isdir || ftpState->theSize != -1)) { ftpState->processHeadResponse(); // may call serverComplete return; @@ -1782,13 +1786,13 @@ ftpSendPassive(FtpStateData * ftpState) if (ftpState->sendPassive()) { // SENT_EPSV_ALL blocks other non-EPSV connections being attempted - if (ftpState->state == Ftp::ServerStateData::SENT_EPSV_ALL) + if (ftpState->state == Ftp::Client::SENT_EPSV_ALL) ftpState->flags.epsv_all_sent = true; } } void -FtpStateData::processHeadResponse() +Ftp::Gateway::processHeadResponse() { debugs(9, 5, HERE << "handling HEAD response"); ftpSendQuit(this); @@ -1817,7 +1821,7 @@ FtpStateData::processHeadResponse() /// \ingroup ServerProtocolFTPInternal static void -ftpReadPasv(FtpStateData * ftpState) +ftpReadPasv(Ftp::Gateway * ftpState) { Ip::Address srvAddr; // unused if (ftpState->handlePasvReply(srvAddr)) @@ -1829,7 +1833,7 @@ ftpReadPasv(FtpStateData * ftpState) } void -FtpStateData::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag err, int xerrno) +Ftp::Gateway::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag err, int xerrno) { debugs(9, 3, HERE); data.opener = NULL; @@ -1852,7 +1856,7 @@ FtpStateData::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Fl /// \ingroup ServerProtocolFTPInternal static void -ftpOpenListenSocket(FtpStateData * ftpState, int fallback) +ftpOpenListenSocket(Ftp::Gateway * ftpState, int fallback) { /// Close old data channels, if any. We may open a new one below. if (ftpState->data.conn != NULL) { @@ -1890,7 +1894,7 @@ ftpOpenListenSocket(FtpStateData * ftpState, int fallback) /// \ingroup ServerProtocolFTPInternal static void -ftpSendPORT(FtpStateData * ftpState) +ftpSendPORT(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendPort")) @@ -1930,14 +1934,14 @@ ftpSendPORT(FtpStateData * ftpState) addrptr[0], addrptr[1], addrptr[2], addrptr[3], portptr[0], portptr[1]); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_PORT; + ftpState->state = Ftp::Client::SENT_PORT; Ip::Address::FreeAddrInfo(AI); } /// \ingroup ServerProtocolFTPInternal static void -ftpReadPORT(FtpStateData * ftpState) +ftpReadPORT(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -1953,7 +1957,7 @@ ftpReadPORT(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendEPRT(FtpStateData * ftpState) +ftpSendEPRT(Ftp::Gateway * ftpState) { if (Config.Ftp.epsv_all && ftpState->flags.epsv_all_sent) { debugs(9, DBG_IMPORTANT, "FTP does not allow EPRT method after 'EPSV ALL' has been sent."); @@ -1988,11 +1992,11 @@ ftpSendEPRT(FtpStateData * ftpState) ftpState->data.listenConn->local.port() ); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_EPRT; + ftpState->state = Ftp::Client::SENT_EPRT; } static void -ftpReadEPRT(FtpStateData * ftpState) +ftpReadEPRT(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2015,7 +2019,7 @@ ftpReadEPRT(FtpStateData * ftpState) \param io comm accept(2) callback parameters */ void -FtpStateData::ftpAcceptDataConnection(const CommAcceptCbParams &io) +Ftp::Gateway::ftpAcceptDataConnection(const CommAcceptCbParams &io) { debugs(9, 3, HERE); @@ -2087,7 +2091,7 @@ FtpStateData::ftpAcceptDataConnection(const CommAcceptCbParams &io) /// \ingroup ServerProtocolFTPInternal static void -ftpRestOrList(FtpStateData * ftpState) +ftpRestOrList(Ftp::Gateway * ftpState) { debugs(9, 3, HERE); @@ -2111,7 +2115,7 @@ ftpRestOrList(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendStor(FtpStateData * ftpState) +ftpSendStor(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendStor")) @@ -2123,12 +2127,12 @@ ftpSendStor(FtpStateData * ftpState) /* Plain file upload */ snprintf(cbuf, CTRL_BUFLEN, "STOR %s\r\n", ftpState->filepath); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_STOR; + ftpState->state = Ftp::Client::SENT_STOR; } else if (ftpState->request->header.getInt64(HDR_CONTENT_LENGTH) > 0) { /* File upload without a filename. use STOU to generate one */ snprintf(cbuf, CTRL_BUFLEN, "STOU\r\n"); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_STOR; + ftpState->state = Ftp::Client::SENT_STOR; } else { /* No file to transfer. Only create directories if needed */ ftpSendReply(ftpState); @@ -2138,12 +2142,12 @@ ftpSendStor(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal /// \deprecated use ftpState->readStor() instead. static void -ftpReadStor(FtpStateData * ftpState) +ftpReadStor(Ftp::Gateway * ftpState) { ftpState->readStor(); } -void FtpStateData::readStor() +void Ftp::Gateway::readStor() { int code = ctrl.replycode; debugs(9, 3, HERE); @@ -2180,7 +2184,7 @@ void FtpStateData::readStor() /// \ingroup ServerProtocolFTPInternal static void -ftpSendRest(FtpStateData * ftpState) +ftpSendRest(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendRest")) @@ -2190,11 +2194,11 @@ ftpSendRest(FtpStateData * ftpState) snprintf(cbuf, CTRL_BUFLEN, "REST %" PRId64 "\r\n", ftpState->restart_offset); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_REST; + ftpState->state = Ftp::Client::SENT_REST; } int -FtpStateData::restartable() +Ftp::Gateway::restartable() { if (restart_offset > 0) return 1; @@ -2222,7 +2226,7 @@ FtpStateData::restartable() /// \ingroup ServerProtocolFTPInternal static void -ftpReadRest(FtpStateData * ftpState) +ftpReadRest(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2242,7 +2246,7 @@ ftpReadRest(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendList(FtpStateData * ftpState) +ftpSendList(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendList")) @@ -2257,12 +2261,12 @@ ftpSendList(FtpStateData * ftpState) } ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_LIST; + ftpState->state = Ftp::Client::SENT_LIST; } /// \ingroup ServerProtocolFTPInternal static void -ftpSendNlst(FtpStateData * ftpState) +ftpSendNlst(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendNlst")) @@ -2279,12 +2283,12 @@ ftpSendNlst(FtpStateData * ftpState) } ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_NLST; + ftpState->state = Ftp::Client::SENT_NLST; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadList(FtpStateData * ftpState) +ftpReadList(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2294,7 +2298,7 @@ ftpReadList(FtpStateData * ftpState) debugs(9, 3, HERE << "begin data transfer from " << ftpState->data.conn->remote << " (" << ftpState->data.conn->local << ")"); ftpState->switchTimeoutToDataChannel(); ftpState->maybeReadVirginBody(); - ftpState->state = Ftp::ServerStateData::READING_DATA; + ftpState->state = Ftp::Client::READING_DATA; return; } else if (code == 150) { /* Accept data channel */ @@ -2311,7 +2315,7 @@ ftpReadList(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendRetr(FtpStateData * ftpState) +ftpSendRetr(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendRetr")) @@ -2322,12 +2326,12 @@ ftpSendRetr(FtpStateData * ftpState) assert(ftpState->filepath != NULL); snprintf(cbuf, CTRL_BUFLEN, "RETR %s\r\n", ftpState->filepath); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_RETR; + ftpState->state = Ftp::Client::SENT_RETR; } /// \ingroup ServerProtocolFTPInternal static void -ftpReadRetr(FtpStateData * ftpState) +ftpReadRetr(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2337,7 +2341,7 @@ ftpReadRetr(FtpStateData * ftpState) debugs(9, 3, HERE << "begin data transfer from " << ftpState->data.conn->remote << " (" << ftpState->data.conn->local << ")"); ftpState->switchTimeoutToDataChannel(); ftpState->maybeReadVirginBody(); - ftpState->state = Ftp::ServerStateData::READING_DATA; + ftpState->state = Ftp::Client::READING_DATA; } else if (code == 150) { /* Accept data channel */ ftpState->listenForDataChannel(ftpState->data.conn); @@ -2358,10 +2362,10 @@ ftpReadRetr(FtpStateData * ftpState) * directory listing display. */ void -FtpStateData::completedListing() +Ftp::Gateway::completedListing() { assert(entry); - entry->lock("FtpStateData"); + entry->lock("Ftp::Gateway"); ErrorState ferr(ERR_DIR_LISTING, Http::scOkay, request); ferr.ftp.listing = &listing; ferr.ftp.cwd_msg = xstrdup(cwd_message.size()? cwd_message.termedBuf() : ""); @@ -2370,12 +2374,12 @@ FtpStateData::completedListing() entry->replaceHttpReply( ferr.BuildHttpReply() ); EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); entry->flush(); - entry->unlock("FtpStateData"); + entry->unlock("Ftp::Gateway"); } /// \ingroup ServerProtocolFTPInternal static void -ftpReadTransferDone(FtpStateData * ftpState) +ftpReadTransferDone(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2397,7 +2401,7 @@ ftpReadTransferDone(FtpStateData * ftpState) // premature end of the request body void -FtpStateData::handleRequestBodyProducerAborted() +Ftp::Gateway::handleRequestBodyProducerAborted() { ServerStateData::handleRequestBodyProducerAborted(); debugs(9, 3, HERE << "ftpState=" << this); @@ -2406,7 +2410,7 @@ FtpStateData::handleRequestBodyProducerAborted() /// \ingroup ServerProtocolFTPInternal static void -ftpWriteTransferDone(FtpStateData * ftpState) +ftpWriteTransferDone(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; debugs(9, 3, HERE); @@ -2423,7 +2427,7 @@ ftpWriteTransferDone(FtpStateData * ftpState) /// \ingroup ServerProtocolFTPInternal static void -ftpSendQuit(FtpStateData * ftpState) +ftpSendQuit(Ftp::Gateway * ftpState) { /* check the server control channel is still available */ if (!ftpState || !ftpState->haveControlChannel("ftpSendQuit")) @@ -2431,7 +2435,7 @@ ftpSendQuit(FtpStateData * ftpState) snprintf(cbuf, CTRL_BUFLEN, "QUIT\r\n"); ftpState->writeCommand(cbuf); - ftpState->state = Ftp::ServerStateData::SENT_QUIT; + ftpState->state = Ftp::Client::SENT_QUIT; } /** @@ -2441,14 +2445,14 @@ ftpSendQuit(FtpStateData * ftpState) * generated and stored in the entry field by the code issuing QUIT. */ static void -ftpReadQuit(FtpStateData * ftpState) +ftpReadQuit(Ftp::Gateway * ftpState) { ftpState->serverComplete(); } /// \ingroup ServerProtocolFTPInternal static void -ftpTrySlashHack(FtpStateData * ftpState) +ftpTrySlashHack(Ftp::Gateway * ftpState) { char *path; ftpState->flags.try_slash_hack = 1; @@ -2476,7 +2480,7 @@ ftpTrySlashHack(FtpStateData * ftpState) * Forget hack status. Next error is shown to the user */ void -FtpStateData::unhack() +Ftp::Gateway::unhack() { debugs(9, 3, HERE); @@ -2487,7 +2491,7 @@ FtpStateData::unhack() } void -FtpStateData::hackShortcut(FTPSM * nextState) +Ftp::Gateway::hackShortcut(FTPSM * nextState) { /* Clear some unwanted state */ setCurrentOffset(0); @@ -2512,7 +2516,7 @@ FtpStateData::hackShortcut(FTPSM * nextState) /// \ingroup ServerProtocolFTPInternal static void -ftpFail(FtpStateData *ftpState) +ftpFail(Ftp::Gateway *ftpState) { debugs(9, 6, HERE << "flags(" << (ftpState->flags.isdir?"IS_DIR,":"") << @@ -2528,9 +2532,9 @@ ftpFail(FtpStateData *ftpState) switch (ftpState->state) { - case Ftp::ServerStateData::SENT_CWD: + case Ftp::Client::SENT_CWD: - case Ftp::ServerStateData::SENT_RETR: + case Ftp::Client::SENT_RETR: /* Try the / hack */ ftpState->hackShortcut(ftpTrySlashHack); return; @@ -2545,7 +2549,7 @@ ftpFail(FtpStateData *ftpState) } Http::StatusCode -FtpStateData::failedHttpStatus(err_type &error) +Ftp::Gateway::failedHttpStatus(err_type &error) { if (error == ERR_NONE) { switch (state) { @@ -2570,12 +2574,12 @@ FtpStateData::failedHttpStatus(err_type &error) break; } } - return Ftp::ServerStateData::failedHttpStatus(error); + return Ftp::Client::failedHttpStatus(error); } /// \ingroup ServerProtocolFTPInternal static void -ftpSendReply(FtpStateData * ftpState) +ftpSendReply(Ftp::Gateway * ftpState) { int code = ftpState->ctrl.replycode; Http::StatusCode http_code; @@ -2620,7 +2624,7 @@ ftpSendReply(FtpStateData * ftpState) } void -FtpStateData::appendSuccessHeader() +Ftp::Gateway::appendSuccessHeader() { const char *mime_type = NULL; const char *mime_enc = NULL; @@ -2701,7 +2705,7 @@ FtpStateData::appendSuccessHeader() } void -FtpStateData::haveParsedReplyHeaders() +Ftp::Gateway::haveParsedReplyHeaders() { ServerStateData::haveParsedReplyHeaders(); @@ -2722,7 +2726,7 @@ FtpStateData::haveParsedReplyHeaders() } HttpReply * -FtpStateData::ftpAuthRequired(HttpRequest * request, const char *realm) +Ftp::Gateway::ftpAuthRequired(HttpRequest * request, const char *realm) { ErrorState err(ERR_CACHE_ACCESS_DENIED, Http::scUnauthorized, request); HttpReply *newrep = err.BuildHttpReply(); @@ -2746,7 +2750,7 @@ FtpStateData::ftpAuthRequired(HttpRequest * request, const char *realm) * ftp:host:port/%2froot/path AKA 'the FTP %2f hack'. */ const char * -ftpUrlWith2f(HttpRequest * request) +Ftp::UrlWith2f(HttpRequest * request) { String newbuf = "%2f"; @@ -2767,7 +2771,7 @@ ftpUrlWith2f(HttpRequest * request) } void -FtpStateData::printfReplyBody(const char *fmt, ...) +Ftp::Gateway::printfReplyBody(const char *fmt, ...) { va_list args; va_start (args, fmt); @@ -2783,7 +2787,7 @@ FtpStateData::printfReplyBody(const char *fmt, ...) * which should be sent to either StoreEntry, or to ICAP... */ void -FtpStateData::writeReplyBody(const char *dataToWrite, size_t dataLength) +Ftp::Gateway::writeReplyBody(const char *dataToWrite, size_t dataLength) { debugs(9, 5, HERE << "writing " << dataLength << " bytes to the reply"); addVirginReplyBody(dataToWrite, dataLength); @@ -2792,11 +2796,11 @@ FtpStateData::writeReplyBody(const char *dataToWrite, size_t dataLength) /** * A hack to ensure we do not double-complete on the forward entry. * - \todo FtpStateData logic should probably be rewritten to avoid + \todo Ftp::Gateway logic should probably be rewritten to avoid * double-completion or FwdState should be rewritten to allow it. */ void -FtpStateData::completeForwarding() +Ftp::Gateway::completeForwarding() { if (fwd == NULL || flags.completed_forwarding) { debugs(9, 3, HERE << "completeForwarding avoids " << @@ -2816,7 +2820,7 @@ FtpStateData::completeForwarding() \retval false The server control channel is not available. */ bool -FtpStateData::haveControlChannel(const char *caller_name) const +Ftp::Gateway::haveControlChannel(const char *caller_name) const { if (doneWithServer()) return false; @@ -2830,3 +2834,9 @@ FtpStateData::haveControlChannel(const char *caller_name) const return true; } + +AsyncJob::Pointer +Ftp::StartGateway(FwdState *const fwdState) +{ + return AsyncJob::Start(new Ftp::Gateway(fwdState)); +} diff --git a/src/clients/FtpNative.cc b/src/clients/FtpRelay.cc similarity index 78% rename from src/clients/FtpNative.cc rename to src/clients/FtpRelay.cc index e4a29cdea1..fda91a8979 100644 --- a/src/clients/FtpNative.cc +++ b/src/clients/FtpRelay.cc @@ -7,6 +7,7 @@ #include "anyp/PortCfg.h" #include "client_side.h" +#include "clients/forward.h" #include "clients/FtpClient.h" #include "ftp/Parsing.h" #include "HttpHdrCc.h" @@ -19,30 +20,35 @@ namespace Ftp { -namespace Gateway { - -class ServerStateData: public Ftp::ServerStateData +/// An FTP client receiving native FTP commands from our FTP server +/// (Ftp::Server), forwarding them to the next FTP hop, +/// and then relaying FTP replies back to our FTP server. +class Relay: public Ftp::Client { public: - ServerStateData(FwdState *const fwdState); - ~ServerStateData(); - - virtual void processReplyBody(); + explicit Relay(FwdState *const fwdState); + virtual ~Relay(); protected: - virtual void start(); - const Ftp::MasterState &master() const; Ftp::MasterState &updateMaster(); Ftp::ServerState clientState() const; void clientState(Ftp::ServerState newState); - virtual void serverComplete(); + /* Ftp::Client API */ virtual void failed(err_type error = ERR_NONE, int xerrno = 0); + + /* ServerStateData API */ + virtual void serverComplete(); virtual void handleControlReply(); + virtual void processReplyBody(); virtual void handleRequestBodyProducerAborted(); virtual bool mayReadVirginReplyBody() const; virtual void completeForwarding(); + + /* AsyncJob API */ + virtual void start(); + void forwardReply(); void forwardError(err_type error = ERR_NONE, int xerrno = 0); void failedErrorMessage(err_type error, int xerrno); @@ -54,12 +60,12 @@ protected: void stopDirTracking(); bool weAreTrackingDir() const {return savedReply.message != NULL;} - typedef void (ServerStateData::*PreliminaryCb)(); + typedef void (Relay::*PreliminaryCb)(); void forwardPreliminaryReply(const PreliminaryCb cb); void proceedAfterPreliminaryReply(); PreliminaryCb thePreliminaryCb; - typedef void (ServerStateData::*SM_FUNC)(); + typedef void (Relay::*SM_FUNC)(); static const SM_FUNC SM_FUNCS[]; void readGreeting(); void sendCommand(); @@ -84,45 +90,48 @@ protected: int replyCode; ///< the reply status } savedReply; ///< set and delayed while we are tracking using PWD - CBDATA_CLASS2(ServerStateData); + CBDATA_CLASS2(Relay); }; -CBDATA_CLASS_INIT(ServerStateData); +} // namespace Ftp -const ServerStateData::SM_FUNC ServerStateData::SM_FUNCS[] = { - &ServerStateData::readGreeting, // BEGIN - &ServerStateData::readUserOrPassReply, // SENT_USER - &ServerStateData::readUserOrPassReply, // SENT_PASS - NULL,/*&ServerStateData::readReply*/ // SENT_TYPE - NULL,/*&ServerStateData::readReply*/ // SENT_MDTM - NULL,/*&ServerStateData::readReply*/ // SENT_SIZE +CBDATA_NAMESPACED_CLASS_INIT(Ftp, Relay); + +const Ftp::Relay::SM_FUNC Ftp::Relay::SM_FUNCS[] = { + &Ftp::Relay::readGreeting, // BEGIN + &Ftp::Relay::readUserOrPassReply, // SENT_USER + &Ftp::Relay::readUserOrPassReply, // SENT_PASS + NULL,/*&Ftp::Relay::readReply*/ // SENT_TYPE + NULL,/*&Ftp::Relay::readReply*/ // SENT_MDTM + NULL,/*&Ftp::Relay::readReply*/ // SENT_SIZE NULL, // SENT_EPRT NULL, // SENT_PORT - &ServerStateData::readEpsvReply, // SENT_EPSV_ALL - &ServerStateData::readEpsvReply, // SENT_EPSV_1 - &ServerStateData::readEpsvReply, // SENT_EPSV_2 - &ServerStateData::readPasvReply, // SENT_PASV - &ServerStateData::readCwdOrCdupReply, // SENT_CWD - NULL,/*&ServerStateData::readDataReply,*/ // SENT_LIST - NULL,/*&ServerStateData::readDataReply,*/ // SENT_NLST - NULL,/*&ServerStateData::readReply*/ // SENT_REST - NULL,/*&ServerStateData::readDataReply*/ // SENT_RETR - NULL,/*&ServerStateData::readReply*/ // SENT_STOR - NULL,/*&ServerStateData::readReply*/ // SENT_QUIT - &ServerStateData::readTransferDoneReply, // READING_DATA - &ServerStateData::readReply, // WRITING_DATA - NULL,/*&ServerStateData::readReply*/ // SENT_MKDIR - &ServerStateData::readFeatReply, // SENT_FEAT - NULL,/*&ServerStateData::readPwdReply*/ // SENT_PWD - &ServerStateData::readCwdOrCdupReply, // SENT_CDUP - &ServerStateData::readDataReply,// SENT_DATA_REQUEST - &ServerStateData::readReply, // SENT_COMMAND + &Ftp::Relay::readEpsvReply, // SENT_EPSV_ALL + &Ftp::Relay::readEpsvReply, // SENT_EPSV_1 + &Ftp::Relay::readEpsvReply, // SENT_EPSV_2 + &Ftp::Relay::readPasvReply, // SENT_PASV + &Ftp::Relay::readCwdOrCdupReply, // SENT_CWD + NULL,/*&Ftp::Relay::readDataReply,*/ // SENT_LIST + NULL,/*&Ftp::Relay::readDataReply,*/ // SENT_NLST + NULL,/*&Ftp::Relay::readReply*/ // SENT_REST + NULL,/*&Ftp::Relay::readDataReply*/ // SENT_RETR + NULL,/*&Ftp::Relay::readReply*/ // SENT_STOR + NULL,/*&Ftp::Relay::readReply*/ // SENT_QUIT + &Ftp::Relay::readTransferDoneReply, // READING_DATA + &Ftp::Relay::readReply, // WRITING_DATA + NULL,/*&Ftp::Relay::readReply*/ // SENT_MKDIR + &Ftp::Relay::readFeatReply, // SENT_FEAT + NULL,/*&Ftp::Relay::readPwdReply*/ // SENT_PWD + &Ftp::Relay::readCwdOrCdupReply, // SENT_CDUP + &Ftp::Relay::readDataReply,// SENT_DATA_REQUEST + &Ftp::Relay::readReply, // SENT_COMMAND NULL }; -ServerStateData::ServerStateData(FwdState *const fwdState): - AsyncJob("Ftp::Gateway::ServerStateData"), Ftp::ServerStateData(fwdState), - forwardingCompleted(false) +Ftp::Relay::Relay(FwdState *const fwdState): + AsyncJob("Ftp::Relay"), + Ftp::Client(fwdState), + forwardingCompleted(false) { savedReply.message = NULL; savedReply.lastCommand = NULL; @@ -134,7 +143,7 @@ ServerStateData::ServerStateData(FwdState *const fwdState): entry->releaseRequest(); } -ServerStateData::~ServerStateData() +Ftp::Relay::~Relay() { closeServer(); // TODO: move to Server.cc? if (savedReply.message) @@ -145,10 +154,10 @@ ServerStateData::~ServerStateData() } void -ServerStateData::start() +Ftp::Relay::start() { if (!master().clientReadGreeting) - Ftp::ServerStateData::start(); + Ftp::Client::start(); else if (clientState() == fssHandleDataRequest || clientState() == fssHandleUploadRequest) @@ -160,7 +169,7 @@ ServerStateData::start() /// Keep control connection for future requests, after we are done with it. /// Similar to COMPLETE_PERSISTENT_MSG handling in http.cc. void -ServerStateData::serverComplete() +Ftp::Relay::serverComplete() { CbcPointer &mgr = fwd->request->clientConnectionManager; if (mgr.valid()) { @@ -179,11 +188,11 @@ ServerStateData::serverComplete() } } } - Ftp::ServerStateData::serverComplete(); + Ftp::Client::serverComplete(); } Ftp::MasterState & -ServerStateData::updateMaster() +Ftp::Relay::updateMaster() { CbcPointer &mgr = fwd->request->clientConnectionManager; if (mgr.valid()) { @@ -198,19 +207,19 @@ ServerStateData::updateMaster() } const Ftp::MasterState & -ServerStateData::master() const +Ftp::Relay::master() const { - return const_cast(this)->updateMaster(); + return const_cast(this)->updateMaster(); } Ftp::ServerState -ServerStateData::clientState() const +Ftp::Relay::clientState() const { return master().serverState; } void -ServerStateData::clientState(Ftp::ServerState newState) +Ftp::Relay::clientState(Ftp::ServerState newState) { // XXX: s/client/server/g Ftp::ServerState &cltState = updateMaster().serverState; @@ -227,17 +236,17 @@ ServerStateData::clientState(Ftp::ServerState newState) \todo Rewrite FwdState to ignore double completion? */ void -ServerStateData::completeForwarding() +Ftp::Relay::completeForwarding() { debugs(9, 5, forwardingCompleted); if (forwardingCompleted) return; forwardingCompleted = true; - Ftp::ServerStateData::completeForwarding(); + Ftp::Client::completeForwarding(); } void -ServerStateData::failed(err_type error, int xerrno) +Ftp::Relay::failed(err_type error, int xerrno) { if (!doneWithServer()) clientState(fssError); @@ -246,11 +255,11 @@ ServerStateData::failed(err_type error, int xerrno) if (entry->isEmpty()) failedErrorMessage(error, xerrno); // as a reply - Ftp::ServerStateData::failed(error, xerrno); + Ftp::Client::failed(error, xerrno); } void -ServerStateData::failedErrorMessage(err_type error, int xerrno) +Ftp::Relay::failedErrorMessage(err_type error, int xerrno) { const Http::StatusCode httpStatus = failedHttpStatus(error); HttpReply *const reply = createHttpReply(httpStatus); @@ -260,7 +269,7 @@ ServerStateData::failedErrorMessage(err_type error, int xerrno) } void -ServerStateData::processReplyBody() +Ftp::Relay::processReplyBody() { debugs(9, 3, HERE << "starting"); @@ -295,7 +304,7 @@ ServerStateData::processReplyBody() } void -ServerStateData::handleControlReply() +Ftp::Relay::handleControlReply() { if (!request->clientConnectionManager.valid()) { debugs(9, 5, "client connection gone"); @@ -303,7 +312,7 @@ ServerStateData::handleControlReply() return; } - Ftp::ServerStateData::handleControlReply(); + Ftp::Client::handleControlReply(); if (ctrl.message == NULL) return; // didn't get complete reply yet @@ -313,7 +322,7 @@ ServerStateData::handleControlReply() } void -ServerStateData::handleRequestBodyProducerAborted() +Ftp::Relay::handleRequestBodyProducerAborted() { ::ServerStateData::handleRequestBodyProducerAborted(); @@ -321,14 +330,14 @@ ServerStateData::handleRequestBodyProducerAborted() } bool -ServerStateData::mayReadVirginReplyBody() const +Ftp::Relay::mayReadVirginReplyBody() const { // TODO: move this method to the regular FTP server? return Comm::IsConnOpen(data.conn); } void -ServerStateData::forwardReply() +Ftp::Relay::forwardReply() { assert(entry->isEmpty()); EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); @@ -342,7 +351,7 @@ ServerStateData::forwardReply() } void -ServerStateData::forwardPreliminaryReply(const PreliminaryCb cb) +Ftp::Relay::forwardPreliminaryReply(const PreliminaryCb cb) { debugs(9, 5, HERE << "Forwarding preliminary reply to client"); @@ -353,16 +362,16 @@ ServerStateData::forwardPreliminaryReply(const PreliminaryCb cb) const HttpReply::Pointer reply = createHttpReply(Http::scContinue); // the Sink will use this to call us back after writing 1xx to the client - typedef NullaryMemFunT CbDialer; + typedef NullaryMemFunT CbDialer; const AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, this, - ServerStateData::proceedAfterPreliminaryReply); + Ftp::Relay::proceedAfterPreliminaryReply); CallJobHere1(9, 4, request->clientConnectionManager, ConnStateData, ConnStateData::sendControlMsg, HttpControlMsg(reply, call)); } void -ServerStateData::proceedAfterPreliminaryReply() +Ftp::Relay::proceedAfterPreliminaryReply() { debugs(9, 5, HERE << "Proceeding after preliminary reply to client"); @@ -373,13 +382,13 @@ ServerStateData::proceedAfterPreliminaryReply() } void -ServerStateData::forwardError(err_type error, int xerrno) +Ftp::Relay::forwardError(err_type error, int xerrno) { failed(error, xerrno); } HttpReply * -ServerStateData::createHttpReply(const Http::StatusCode httpStatus, const int clen) +Ftp::Relay::createHttpReply(const Http::StatusCode httpStatus, const int clen) { HttpReply *const reply = new HttpReply; reply->sline.set(Http::ProtocolVersion(1, 1), httpStatus); @@ -408,14 +417,14 @@ ServerStateData::createHttpReply(const Http::StatusCode httpStatus, const int cl } void -ServerStateData::handleDataRequest() +Ftp::Relay::handleDataRequest() { data.addr(master().clientDataAddr); connectDataChannel(); } void -ServerStateData::startDataDownload() +Ftp::Relay::startDataDownload() { assert(Comm::IsConnOpen(data.conn)); @@ -432,7 +441,7 @@ ServerStateData::startDataDownload() } void -ServerStateData::startDataUpload() +Ftp::Relay::startDataUpload() { assert(Comm::IsConnOpen(data.conn)); @@ -448,7 +457,7 @@ ServerStateData::startDataUpload() } void -ServerStateData::readGreeting() +Ftp::Relay::readGreeting() { assert(!master().clientReadGreeting); @@ -467,7 +476,7 @@ ServerStateData::readGreeting() case 120: if (NULL != ctrl.message) debugs(9, DBG_IMPORTANT, "FTP server is busy: " << ctrl.message->key); - forwardPreliminaryReply(&ServerStateData::scheduleReadControlReply); + forwardPreliminaryReply(&Ftp::Relay::scheduleReadControlReply); break; default: failed(); @@ -476,7 +485,7 @@ ServerStateData::readGreeting() } void -ServerStateData::sendCommand() +Ftp::Relay::sendCommand() { if (!fwd->request->header.has(HDR_FTP_COMMAND)) { abortTransaction("Internal error: FTP gateway request with no command"); @@ -523,19 +532,19 @@ ServerStateData::sendCommand() } void -ServerStateData::readReply() +Ftp::Relay::readReply() { assert(clientState() == fssConnected || clientState() == fssHandleUploadRequest); if (100 <= ctrl.replycode && ctrl.replycode < 200) - forwardPreliminaryReply(&ServerStateData::scheduleReadControlReply); + forwardPreliminaryReply(&Ftp::Relay::scheduleReadControlReply); else forwardReply(); } void -ServerStateData::readFeatReply() +Ftp::Relay::readFeatReply() { assert(clientState() == fssHandleFeat); @@ -546,7 +555,7 @@ ServerStateData::readFeatReply() } void -ServerStateData::readPasvReply() +Ftp::Relay::readPasvReply() { assert(clientState() == fssHandlePasv || clientState() == fssHandleEpsv || clientState() == fssHandlePort || clientState() == fssHandleEprt); @@ -560,7 +569,7 @@ ServerStateData::readPasvReply() } void -ServerStateData::readEpsvReply() +Ftp::Relay::readEpsvReply() { if (100 <= ctrl.replycode && ctrl.replycode < 200) return; // ignore preliminary replies @@ -575,22 +584,22 @@ ServerStateData::readEpsvReply() } void -ServerStateData::readDataReply() +Ftp::Relay::readDataReply() { assert(clientState() == fssHandleDataRequest || clientState() == fssHandleUploadRequest); if (ctrl.replycode == 125 || ctrl.replycode == 150) { if (clientState() == fssHandleDataRequest) - forwardPreliminaryReply(&ServerStateData::startDataDownload); + forwardPreliminaryReply(&Ftp::Relay::startDataDownload); else // clientState() == fssHandleUploadRequest - forwardPreliminaryReply(&ServerStateData::startDataUpload); + forwardPreliminaryReply(&Ftp::Relay::startDataUpload); } else forwardReply(); } bool -ServerStateData::startDirTracking() +Ftp::Relay::startDirTracking() { if (!fwd->request->clientConnectionManager->port->ftp_track_dirs) return false; @@ -610,7 +619,7 @@ ServerStateData::startDirTracking() } void -ServerStateData::stopDirTracking() +Ftp::Relay::stopDirTracking() { debugs(9, 5, "Got code from pwd: " << ctrl.replycode << ", msg: " << ctrl.last_reply); @@ -632,7 +641,7 @@ ServerStateData::stopDirTracking() } void -ServerStateData::readCwdOrCdupReply() +Ftp::Relay::readCwdOrCdupReply() { assert(clientState() == fssHandleCwd || clientState() == fssHandleCdup); @@ -651,7 +660,7 @@ ServerStateData::readCwdOrCdupReply() } void -ServerStateData::readUserOrPassReply() +Ftp::Relay::readUserOrPassReply() { if (100 <= ctrl.replycode && ctrl.replycode < 200) return; //Just ignore @@ -667,7 +676,7 @@ ServerStateData::readUserOrPassReply() } void -ServerStateData::readTransferDoneReply() +Ftp::Relay::readTransferDoneReply() { debugs(9, 3, HERE); @@ -680,7 +689,7 @@ ServerStateData::readTransferDoneReply() } void -ServerStateData::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag err, int xerrno) +Ftp::Relay::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm::Flag err, int xerrno) { debugs(9, 3, HERE); data.opener = NULL; @@ -699,17 +708,13 @@ ServerStateData::dataChannelConnected(const Comm::ConnectionPointer &conn, Comm: } void -ServerStateData::scheduleReadControlReply() +Ftp::Relay::scheduleReadControlReply() { - Ftp::ServerStateData::scheduleReadControlReply(0); + Ftp::Client::scheduleReadControlReply(0); } -}; // namespace Gateway - -}; // namespace Ftp - -void -ftpGatewayServerStart(FwdState *const fwdState) +AsyncJob::Pointer +Ftp::StartRelay(FwdState *const fwdState) { - AsyncJob::Start(new Ftp::Gateway::ServerStateData(fwdState)); + return AsyncJob::Start(new Ftp::Relay(fwdState)); } diff --git a/src/clients/Makefile.am b/src/clients/Makefile.am index bd71786313..af867511fd 100644 --- a/src/clients/Makefile.am +++ b/src/clients/Makefile.am @@ -6,6 +6,6 @@ libclients_la_SOURCES = \ FtpClient.cc \ FtpClient.h \ FtpGateway.cc \ - FtpNative.cc \ + FtpRelay.cc \ \ forward.h diff --git a/src/clients/forward.h b/src/clients/forward.h index e3d6e439a1..d32c4612dd 100644 --- a/src/clients/forward.h +++ b/src/clients/forward.h @@ -4,16 +4,26 @@ class FwdState; class HttpRequest; +class AsyncJob; +template class CbcPointer; +typedef CbcPointer AsyncJobPointer; + +namespace Ftp { + +/// A new FTP Gateway job +AsyncJobPointer StartGateway(FwdState *const fwdState); + +/// A new FTP Relay job +AsyncJobPointer StartRelay(FwdState *const fwdState); + /** * \defgroup ServerProtocolFTPAPI Server-Side FTP API * \ingroup ServerProtocol */ /// \ingroup ServerProtocolFTPAPI -void ftpStart(FwdState *); -/// \ingroup ServerProtocolFTPAPI -const char *ftpUrlWith2f(HttpRequest *); +const char *UrlWith2f(HttpRequest *); -void ftpGatewayServerStart(FwdState *const); +} // namespace Ftp #endif /* SQUID_CLIENTS_FORWARD_H */ diff --git a/src/errorpage.cc b/src/errorpage.cc index d5fde9e3ab..44d6d18d8f 100644 --- a/src/errorpage.cc +++ b/src/errorpage.cc @@ -831,7 +831,7 @@ ErrorState::Convert(char token, bool building_deny_info_url, bool allowRecursion case 'B': if (building_deny_info_url) break; - p = request ? ftpUrlWith2f(request) : "[no URL]"; + p = request ? Ftp::UrlWith2f(request) : "[no URL]"; break; case 'c': diff --git a/src/ftp/Parsing.h b/src/ftp/Parsing.h index 1363a88fb9..89dd64a138 100644 --- a/src/ftp/Parsing.h +++ b/src/ftp/Parsing.h @@ -5,9 +5,14 @@ namespace Ftp { -// TODO: Document +/// parses and validates "A1,A2,A3,A4,P1,P2" IP,port sequence bool ParseIpPort(const char *buf, const char *forceIp, Ip::Address &addr); + +/// parses and validates EPRT "" +/// proto,IP,port sequence bool ParseProtoIpPort(const char *buf, Ip::Address &addr); + +/// parses an FTP-quoted quote-escaped path const char *UnescapeDoubleQuoted(const char *quotedPath); } // namespace Ftp