-
Notifications
You must be signed in to change notification settings - Fork 638
Expand file tree
/
Copy pathFtpClient.h
More file actions
223 lines (180 loc) · 6.29 KB
/
FtpClient.h
File metadata and controls
223 lines (180 loc) · 6.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
* Copyright (C) 1996-2026 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/
/* DEBUG: section 09 File Transfer Protocol (FTP) */
#ifndef SQUID_SRC_CLIENTS_FTPCLIENT_H
#define SQUID_SRC_CLIENTS_FTPCLIENT_H
#include "clients/Client.h"
#include "error/Detail.h"
class String;
namespace Ftp
{
extern const char *const crlf;
/// Holds FTP server reply error code
/// Squid needs to interpret internally FTP reply codes and respond with
/// custom error (eg in the case of Ftp::Gateway), however still we need
/// to log the exact FTP server error reply code as the reason of error.
class ErrorDetail: public ::ErrorDetail {
MEMPROXY_CLASS(Ftp::ErrorDetail);
public:
explicit ErrorDetail(const int code): completionCode(code) {}
/* ErrorDetail API */
SBuf brief() const override;
SBuf verbose(const HttpRequestPointer &) const override;
private:
int completionCode; ///< FTP reply completion code
};
/// Common code for FTP server control and data channels.
/// 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
void opened(const Comm::ConnectionPointer &conn, const AsyncCall::Pointer &aCloser);
/** Handles all operations needed to properly close the active channel FD.
* clearing the close handler, clearing the listen socket properly, and calling comm_close
*/
void close();
void forget(); /// remove the close handler, leave connection open
void clear(); ///< just drops conn and close handler. does not close active connections.
Comm::ConnectionPointer conn; ///< channel descriptor
/** A temporary handle to the connection being listened on.
* Closing this will also close the waiting Data channel acceptor.
* If a data connection has already been accepted but is still waiting in the event queue
* the callback will still happen and needs to be handled (usually dropped).
*/
Comm::ConnectionPointer listenConn;
private:
AsyncCall::Pointer closer; ///< Comm close handler callback
};
/// FTP channel for control commands.
/// This channel is opened once per transaction.
class CtrlChannel: public Ftp::Channel
{
public:
CtrlChannel();
~CtrlChannel();
char *buf;
size_t size;
size_t offset;
wordlist *message;
char *last_command;
char *last_reply;
int replycode;
private:
CtrlChannel(const CtrlChannel &); // not implemented
CtrlChannel &operator =(const CtrlChannel &); // not implemented
};
/// FTP channel for data exchanges.
/// This channel may be opened/closed a few times.
class DataChannel: public Ftp::Channel
{
public:
DataChannel();
~DataChannel();
void addr(const Ip::Address &addr); ///< import host and port
public:
MemBuf *readBuf;
char *host;
unsigned short port;
bool read_pending;
};
/// FTP client functionality shared among FTP Gateway and Relay clients.
class Client: public ::Client
{
CBDATA_INTERMEDIATE();
public:
explicit Client(FwdState *fwdState);
~Client() override;
/// handle a fatal transaction error, closing the control connection
virtual void failed(err_type error = ERR_NONE, int xerrno = 0,
ErrorState *ftperr = nullptr);
/// read timeout handler
virtual void timeout(const CommTimeoutCbParams &io);
/* Client API */
void maybeReadVirginBody() override;
void writeCommand(const char *buf);
/// extracts remoteAddr from PASV response, validates it,
/// sets data address details, and returns true on success
bool handlePasvReply(Ip::Address &remoteAddr);
bool handleEpsvReply(Ip::Address &remoteAddr);
bool sendEprt();
bool sendPort();
bool sendPassive();
void connectDataChannel();
bool openListenSocket();
void switchTimeoutToDataChannel();
CtrlChannel ctrl; ///< FTP control channel state
DataChannel data; ///< FTP data channel state
enum {
BEGIN,
SENT_USER,
SENT_PASS,
SENT_TYPE,
SENT_MDTM,
SENT_SIZE,
SENT_EPRT,
SENT_PORT,
SENT_EPSV_ALL,
SENT_EPSV_1,
SENT_EPSV_2,
SENT_PASV,
SENT_CWD,
SENT_LIST,
SENT_NLST,
SENT_REST,
SENT_RETR,
SENT_STOR,
SENT_QUIT,
READING_DATA,
WRITING_DATA,
SENT_MKDIR,
SENT_FEAT,
SENT_PWD,
SENT_CDUP,
SENT_DATA_REQUEST, // LIST, NLST or RETR requests..
SENT_COMMAND, // General command
END
} ftp_state_t;
int state;
char *old_request;
char *old_reply;
protected:
/* AsyncJob API */
void start() override;
/* Client API */
void closeServer() override;
bool doneWithServer() const override;
const Comm::ConnectionPointer & dataConnection() const override;
void abortAll(const char *reason) override;
void noteDelayAwareReadChance() override;
virtual Http::StatusCode failedHttpStatus(err_type &error);
void ctrlClosed(const CommCloseCbParams &io);
void scheduleReadControlReply(int buffered_ok);
void readControlReply(const CommIoCbParams &io);
virtual void handleControlReply();
void writeCommandCallback(const CommIoCbParams &io);
virtual void dataChannelConnected(const CommConnectCbParams &io) = 0;
void dataRead(const CommIoCbParams &io);
void dataComplete();
AsyncCall::Pointer dataCloser();
virtual void dataClosed(const CommCloseCbParams &io);
void initReadBuf();
// sending of the request body to the server
void sentRequestBody(const CommIoCbParams &io) override;
void doneSendingRequestBody() override;
/// Waits for an FTP data connection to the server to be established/opened.
/// This wait only happens in FTP passive mode (via PASV or EPSV).
JobWait<Comm::ConnOpener> dataConnWait;
private:
bool parseControlReply(size_t &bytesUsed);
/// XXX: An old hack for FTP servers like ftp.netscape.com that may not
/// respond to PASV. Use faster connect timeout instead of read timeout.
bool shortenReadTimeout;
};
} // namespace Ftp
#endif /* SQUID_SRC_CLIENTS_FTPCLIENT_H */