/*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2020 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
public:
typedef RefCount<MasterState> Pointer;
- MasterState(): serverState(fssBegin), clientReadGreeting(false) {}
+ MasterState(): serverState(fssBegin), clientReadGreeting(false), userDataDone(0) {}
Ip::Address clientDataAddr; ///< address of our FTP client data connection
SBuf workingDir; ///< estimated current working directory for URI formation
ServerState serverState; ///< what our FTP server is doing
bool clientReadGreeting; ///< whether our FTP client read their FTP server greeting
+ /// Squid will send or has sent this final status code to the FTP client
+ int userDataDone;
};
/// Manages a control connection from an FTP client.
class Server: public ConnStateData
{
- CBDATA_CLASS(Server);
+ CBDATA_CHILD(Server);
public:
explicit Server(const MasterXaction::Pointer &xact);
- virtual ~Server();
+ virtual ~Server() override;
+
+ /* AsyncJob API */
+ virtual void callException(const std::exception &e) override;
+
+ /// Called by Ftp::Client class when it is start receiving or
+ /// sending data.
+ void startWaitingForOrigin();
+
+ /// Called by Ftp::Client class when it is done receiving or
+ /// sending data. Waits for both agents to be done before
+ /// responding to the FTP client and closing the data connection.
+ void stopWaitingForOrigin(int status);
// This is a pointer in hope to minimize future changes when MasterState
// becomes a part of MasterXaction. Guaranteed not to be nil.
friend void StartListening();
// errors detected before it is possible to create an HTTP request wrapper
- typedef enum {
- eekHugeRequest,
- eekMissingLogin,
- eekMissingUsername,
- eekMissingHost,
- eekUnsupportedCommand,
- eekInvalidUri,
- eekMalformedCommand
- } EarlyErrorKind;
+ enum class EarlyErrorKind {
+ HugeRequest,
+ MissingLogin,
+ MissingUsername,
+ MissingHost,
+ UnsupportedCommand,
+ InvalidUri,
+ MalformedCommand
+ };
/* ConnStateData API */
- virtual ClientSocketContext *parseOneRequest();
- virtual void processParsedRequest(ClientSocketContext *context);
- virtual void notePeerConnection(Comm::ConnectionPointer conn);
- virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io);
- virtual void handleReply(HttpReply *header, StoreIOBuffer receivedData);
- virtual int pipelinePrefetchMax() const;
- virtual void writeControlMsgAndCall(ClientSocketContext *context, HttpReply *rep, AsyncCall::Pointer &call);
- virtual time_t idleTimeout() const;
+ virtual Http::Stream *parseOneRequest() override;
+ virtual void processParsedRequest(Http::StreamPointer &context) override;
+ virtual void notePeerConnection(Comm::ConnectionPointer conn) override;
+ virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io) override;
+ virtual void handleReply(HttpReply *header, StoreIOBuffer receivedData) override;
+ virtual int pipelinePrefetchMax() const override;
+ virtual bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) override;
+ virtual time_t idleTimeout() const override;
/* BodyPipe API */
- virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer);
- virtual void noteBodyConsumerAborted(BodyPipe::Pointer ptr);
+ virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer) override;
+ virtual void noteBodyConsumerAborted(BodyPipe::Pointer ptr) override;
/* AsyncJob API */
- virtual void start();
+ virtual void start() override;
/* Comm callbacks */
static void AcceptCtrlConnection(const CommAcceptCbParams ¶ms);
bool createDataConnection(Ip::Address cltAddr);
void closeDataConnection();
+ /// Called after data trasfer on client-to-squid data connection is
+ /// finished.
+ void userDataCompletionCheckpoint(int finalStatusCode);
+
+ /// Writes the data-transfer status reply to the FTP client and
+ /// closes the data connection.
+ void completeDataDownload();
+
void calcUri(const SBuf *file);
void changeState(const Ftp::ServerState newState, const char *reason);
- ClientSocketContext *handleUserRequest(const SBuf &cmd, SBuf ¶ms);
+ Http::Stream *handleUserRequest(const SBuf &cmd, SBuf ¶ms);
bool checkDataConnPost() const;
void replyDataWritingCheckpoint();
void maybeReadUploadData();
void writeForwardedReplyAndCall(const HttpReply *reply, AsyncCall::Pointer &call);
void writeReply(MemBuf &mb);
- ClientSocketContext *earlyError(const EarlyErrorKind eek);
+ Http::Stream *earlyError(const EarlyErrorKind eek);
bool handleRequest(HttpRequest *);
void setDataCommand();
bool checkDataConnPre();
AsyncCall::Pointer listener; ///< set when we are passively listening
AsyncCall::Pointer connector; ///< set when we are actively connecting
AsyncCall::Pointer reader; ///< set when we are reading FTP data
+
+ /// whether we wait for the origin data transfer to end
+ bool waitingForOrigin;
+ /// whether the origin data transfer aborted
+ bool originDataDownloadAbortedOnError;
+
+ /// a response which writing was postponed until stopWaitingForOrigin()
+ HttpReply::Pointer delayedReply;
};
} // namespace Ftp