2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* DEBUG: section 33 Client-side Routines */
11 #ifndef SQUID_SRC_SERVERS_FTPSERVER_H
12 #define SQUID_SRC_SERVERS_FTPSERVER_H
14 #include "base/JobWait.h"
15 #include "base/Lock.h"
16 #include "client_side.h"
17 #include "comm/forward.h"
18 #include "http/forward.h"
30 fssHandleUploadRequest
,
39 // TODO: This should become a part of MasterXaction when we start sending
40 // master transactions to the clients/ code.
41 /// Transaction information shared among our FTP client and server jobs.
42 class MasterState
: public RefCountable
45 typedef RefCount
<MasterState
> Pointer
;
47 MasterState(): serverState(fssBegin
), clientReadGreeting(false), userDataDone(0) {}
49 Ip::Address clientDataAddr
; ///< address of our FTP client data connection
50 SBuf workingDir
; ///< estimated current working directory for URI formation
51 ServerState serverState
; ///< what our FTP server is doing
52 bool clientReadGreeting
; ///< whether our FTP client read their FTP server greeting
53 /// Squid will send or has sent this final status code to the FTP client
57 /// Manages a control connection from an FTP client.
58 class Server
: public ConnStateData
63 explicit Server(const MasterXaction::Pointer
&xact
);
67 void callException(const std::exception
&e
) override
;
69 /// Called by Ftp::Client class when it is start receiving or
71 void startWaitingForOrigin();
73 /// Called by Ftp::Client class when it is done receiving or
74 /// sending data. Waits for both agents to be done before
75 /// responding to the FTP client and closing the data connection.
76 void stopWaitingForOrigin(int status
);
78 // This is a pointer in hope to minimize future changes when MasterState
79 // becomes a part of MasterXaction. Guaranteed not to be nil.
80 MasterState::Pointer master
; ///< info shared among our FTP client and server jobs
83 friend void StartListening();
85 // errors detected before it is possible to create an HTTP request wrapper
86 enum class EarlyErrorKind
{
96 /* ConnStateData API */
97 Http::Stream
*parseOneRequest() override
;
98 void processParsedRequest(Http::StreamPointer
&context
) override
;
99 void notePeerConnection(Comm::ConnectionPointer conn
) override
;
100 void clientPinnedConnectionClosed(const CommCloseCbParams
&io
) override
;
101 void handleReply(HttpReply
*header
, StoreIOBuffer receivedData
) override
;
102 int pipelinePrefetchMax() const override
;
103 bool writeControlMsgAndCall(HttpReply
*rep
, AsyncCall::Pointer
&call
) override
;
104 time_t idleTimeout() const override
;
107 void noteMoreBodySpaceAvailable(BodyPipe::Pointer
) override
;
108 void noteBodyConsumerAborted(BodyPipe::Pointer ptr
) override
;
111 void start() override
;
114 static void AcceptCtrlConnection(const CommAcceptCbParams
¶ms
);
115 void acceptDataConnection(const CommAcceptCbParams
¶ms
);
116 void readUploadData(const CommIoCbParams
&io
);
117 void wroteEarlyReply(const CommIoCbParams
&io
);
118 void wroteReply(const CommIoCbParams
&io
);
119 void wroteReplyData(const CommIoCbParams
&io
);
120 void connectedForData(const CommConnectCbParams
¶ms
);
122 unsigned int listenForDataConnection();
123 bool createDataConnection(Ip::Address cltAddr
);
124 void closeDataConnection();
126 /// Called after data transfer on client-to-squid data connection is
128 void userDataCompletionCheckpoint(int finalStatusCode
);
130 /// Writes the data-transfer status reply to the FTP client and
131 /// closes the data connection.
132 void completeDataDownload();
134 void calcUri(const SBuf
*file
);
135 void changeState(const Ftp::ServerState newState
, const char *reason
);
136 Http::Stream
*handleUserRequest(const SBuf
&cmd
, SBuf
¶ms
);
137 bool checkDataConnPost() const;
138 void replyDataWritingCheckpoint();
139 void maybeReadUploadData();
141 void setReply(const int code
, const char *msg
);
142 void writeCustomReply(const int code
, const char *msg
, const HttpReply
*reply
= nullptr);
143 void writeEarlyReply(const int code
, const char *msg
);
144 void writeErrorReply(const HttpReply
*reply
, const int status
);
145 void writeForwardedForeign(const HttpReply
*reply
);
146 void writeForwardedReply(const HttpReply
*reply
);
147 void writeForwardedReplyAndCall(const HttpReply
*reply
, AsyncCall::Pointer
&call
);
148 void writeReply(MemBuf
&mb
);
150 Http::Stream
*earlyError(const EarlyErrorKind eek
);
151 bool handleRequest(HttpRequest
*);
152 void setDataCommand();
153 bool checkDataConnPre();
155 /// a method handling an FTP command; selected by handleRequest()
156 typedef bool (Ftp::Server::*RequestHandler
)(String
&cmd
, String
¶ms
);
157 bool handleFeatRequest(String
&cmd
, String
¶ms
);
158 bool handlePasvRequest(String
&cmd
, String
¶ms
);
159 bool handlePortRequest(String
&cmd
, String
¶ms
);
160 bool handleDataRequest(String
&cmd
, String
¶ms
);
161 bool handleUploadRequest(String
&cmd
, String
¶ms
);
162 bool handleEprtRequest(String
&cmd
, String
¶ms
);
163 bool handleEpsvRequest(String
&cmd
, String
¶ms
);
164 bool handleCwdRequest(String
&cmd
, String
¶ms
);
165 bool handlePassRequest(String
&cmd
, String
¶ms
);
166 bool handleCdupRequest(String
&cmd
, String
¶ms
);
168 /// a method handling an FTP response; selected by handleReply()
169 typedef void (Ftp::Server::*ReplyHandler
)(const HttpReply
*reply
, StoreIOBuffer data
);
170 void handleFeatReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
171 void handlePasvReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
172 void handlePortReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
173 void handleErrorReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
174 void handleDataReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
175 void handleUploadReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
176 void handleEprtReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
177 void handleEpsvReply(const HttpReply
*header
, StoreIOBuffer receivedData
);
180 void doProcessRequest();
181 void shovelUploadData();
182 void resetLogin(const char *reason
);
184 SBuf uri
; ///< a URI reconstructed from various FTP message details
185 SBuf host
; ///< intended dest. of a transparently intercepted FTP conn
186 bool gotEpsvAll
; ///< restrict data conn setup commands to just EPSV
187 AsyncCall::Pointer onDataAcceptCall
; ///< who to call upon data conn acceptance
188 Comm::ConnectionPointer dataListenConn
; ///< data connection listening socket
189 Comm::ConnectionPointer dataConn
; ///< data connection
190 char uploadBuf
[CLIENT_REQ_BUF_SZ
]; ///< data connection input buffer
191 size_t uploadAvailSize
; ///< number of yet unused uploadBuf bytes
193 AsyncCall::Pointer listener
; ///< set when we are passively listening
195 /// Waits for an FTP data connection to the client to be established/opened.
196 /// This wait only happens in FTP active mode (via PORT or EPRT).
197 JobWait
<Comm::ConnOpener
> dataConnWait
;
199 AsyncCall::Pointer reader
; ///< set when we are reading FTP data
201 /// whether we wait for the origin data transfer to end
202 bool waitingForOrigin
;
203 /// whether the origin data transfer aborted
204 bool originDataDownloadAbortedOnError
;
206 /// a response which writing was postponed until stopWaitingForOrigin()
207 HttpReply::Pointer delayedReply
;
212 #endif /* SQUID_SRC_SERVERS_FTPSERVER_H */