/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
#include "clients/FtpClient.h"
#include "ftp/Elements.h"
#include "ftp/Parsing.h"
+#include "http/Stream.h"
#include "HttpHdrCc.h"
#include "HttpRequest.h"
-#include "SBuf.h"
+#include "sbuf/SBuf.h"
#include "servers/FtpServer.h"
#include "SquidTime.h"
#include "Store.h"
void serverState(const Ftp::ServerState newState);
/* Ftp::Client API */
- virtual void failed(err_type error = ERR_NONE, int xerrno = 0);
+ virtual void failed(err_type error = ERR_NONE, int xerrno = 0, ErrorState *ftperr = nullptr);
virtual void dataChannelConnected(const CommConnectCbParams &io);
/* Client API */
/* AsyncJob API */
virtual void start();
+ virtual void swanSong();
void forwardReply();
void forwardError(err_type error = ERR_NONE, int xerrno = 0);
void readUserOrPassReply();
void scheduleReadControlReply();
- void finalizeDataDownload();
+
+ /// Inform Ftp::Server that we are done if originWaitInProgress
+ void stopOriginWait(int code);
static void abort(void *d); // TODO: Capitalize this and FwdState::abort().
bool forwardingCompleted; ///< completeForwarding() has been called
+ /// whether we are between Ftp::Server::startWaitingForOrigin() and
+ /// Ftp::Server::stopWaitingForOrigin() calls
+ bool originWaitInProgress;
+
struct {
wordlist *message; ///< reply message, one wordlist entry per message line
char *lastCommand; ///< the command caused the reply
AsyncJob("Ftp::Relay"),
Ftp::Client(fwdState),
thePreliminaryCb(NULL),
- forwardingCompleted(false)
+ forwardingCompleted(false),
+ originWaitInProgress(false)
{
savedReply.message = NULL;
savedReply.lastCommand = NULL;
sendCommand();
}
+void
+Ftp::Relay::swanSong()
+{
+ stopOriginWait(0);
+ Ftp::Client::swanSong();
+}
+
/// Keep control connection for future requests, after we are done with it.
/// Similar to COMPLETE_PERSISTENT_MSG handling in http.cc.
void
Ftp::Relay::serverComplete()
{
+ stopOriginWait(ctrl.replycode);
+
CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
if (mgr.valid()) {
if (Comm::IsConnOpen(ctrl.conn)) {
}
void
-Ftp::Relay::failed(err_type error, int xerrno)
+Ftp::Relay::failed(err_type error, int xerrno, ErrorState *ftpErr)
{
if (!doneWithServer())
serverState(fssError);
if (entry->isEmpty())
failedErrorMessage(error, xerrno); // as a reply
- Ftp::Client::failed(error, xerrno);
+ Ftp::Client::failed(error, xerrno, ftpErr);
}
void
serverState() == fssConnected ? SENT_USER :
serverState() == fssHandlePass ? SENT_PASS :
SENT_COMMAND;
+
+ if (state == SENT_DATA_REQUEST) {
+ CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
+ if (mgr.valid()) {
+ if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
+ typedef NullaryMemFunT<Ftp::Server> CbDialer;
+ AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, srv,
+ Ftp::Server::startWaitingForOrigin);
+ ScheduleCallHere(call);
+ originWaitInProgress = true;
+ }
+ }
+ }
}
void
" after reading response data");
}
- finalizeDataDownload();
+ debugs(9, 2, "Complete data downloading");
+
+ serverComplete();
}
void
Ftp::Client::scheduleReadControlReply(0);
}
-void
-Ftp::Relay::finalizeDataDownload()
-{
- debugs(9, 2, "Complete data downloading/Uploading");
-
- updateMaster().waitForOriginData = false;
-
- CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
- if (mgr.valid()) {
- if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
- typedef NullaryMemFunT<Ftp::Server> CbDialer;
- AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, srv,
- Ftp::Server::originDataCompletionCheckpoint);
- ScheduleCallHere(call);
- }
- }
- serverComplete();
-}
-
bool
Ftp::Relay::abortOnData(const char *reason)
{
return !Comm::IsConnOpen(ctrl.conn);
}
+void
+Ftp::Relay::stopOriginWait(int code)
+{
+ if (originWaitInProgress) {
+ CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
+ if (mgr.valid()) {
+ if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
+ typedef UnaryMemFunT<Ftp::Server, int> CbDialer;
+ AsyncCall::Pointer call = asyncCall(11, 3, "Ftp::Server::stopWaitingForOrigin",
+ CbDialer(srv, &Ftp::Server::stopWaitingForOrigin, code));
+ ScheduleCallHere(call);
+ }
+ }
+ originWaitInProgress = false;
+ }
+}
+
void
Ftp::Relay::abort(void *d)
{