67 waitingForOrigin(false),
68 originDataDownloadAbortedOnError(false)
76 closeDataConnection();
101 debugs(33, 5,
"FTP transparent URL: " << uri);
104 writeEarlyReply(220,
"Service ready");
111 if (reader !=
nullptr)
114 const size_t availSpace =
sizeof(uploadBuf) - uploadAvailSize;
118 debugs(33, 4, dataConn <<
": reading FTP data...");
122 comm_read(dataConn, uploadBuf + uploadAvailSize, availSpace,
131 Must(pipeline.count() == 1);
133 Must(context !=
nullptr);
140 const bool mayForward = !http->
storeEntry() && handleRequest(request);
143 debugs(33, 4,
"got an immediate response");
146 }
else if (mayForward) {
147 debugs(33, 4,
"forwarding request to server side");
151 debugs(33, 4,
"will resume processing later");
158 Must(pipeline.count() == 1);
171 Must(reader !=
nullptr);
181 char *
const current_buf = uploadBuf + uploadAvailSize;
182 if (io.
buf != current_buf)
183 memmove(current_buf, io.
buf, io.
size);
184 uploadAvailSize += io.
size;
186 }
else if (io.
size == 0) {
188 closeDataConnection();
189 if (uploadAvailSize <= 0)
190 finishDechunkingRequest(
true);
194 closeDataConnection();
195 finishDechunkingRequest(
false);
204 assert(bodyPipe !=
nullptr);
206 debugs(33, 5,
"handling FTP request data for " << clientConnection);
207 const size_t putSize = bodyPipe->putMoreData(uploadBuf,
210 uploadAvailSize -= putSize;
211 if (uploadAvailSize > 0)
212 memmove(uploadBuf, uploadBuf + putSize, uploadAvailSize);
216 maybeReadUploadData();
217 else if (uploadAvailSize <= 0)
218 finishDechunkingRequest(
true);
237 closeDataConnection();
258 xact->tcpClient = params.
conn;
292 if (s->listenConn !=
nullptr) {
294 s->listenConn->close();
295 s->listenConn =
nullptr;
306 Must(context !=
nullptr);
308 Must(http !=
nullptr);
310 Must(request !=
nullptr);
312 pinBusyConnection(conn, request);
323 clientConnection->close();
338 debugs(33, 5,
"will need to re-login due to " << reason);
339 master->clientReadGreeting =
false;
350 if (
port->ftp_track_dirs && master->workingDir.length()) {
351 if (master->workingDir[0] !=
'/')
353 uri.append(master->workingDir);
356 if (uri[uri.length() - 1] !=
'/')
359 if (
port->ftp_track_dirs && file) {
363 uri.append(
tok.remaining());
372 closeDataConnection();
376 conn->
local = transparent() ?
port->s : clientConnection->local;
378 const char *
const note = uri.c_str();
382 conn->
local <<
" error: " << errno);
383 writeCustomReply(451,
"Internal error");
391 listener = call.getRaw();
392 dataListenConn = conn;
397 return listeningPort;
405 debugs(33, 2, dataListenConn <<
": accept "
413 if (!clientConnection) {
414 debugs(33, 5,
"late data connection?");
415 closeDataConnection();
417 }
else if (params.
conn->
remote != clientConnection->remote) {
418 debugs(33, 2,
"rogue data conn? ctrl: " << clientConnection->remote);
423 closeDataConnection();
424 dataConn = params.
conn;
427 debugs(33, 7,
"ready for data");
428 if (onDataAcceptCall !=
nullptr) {
430 onDataAcceptCall =
nullptr;
433 maybeReadUploadData();
438 mb.
appendf(
"150 Data connection opened.\r\n");
447 if (listener !=
nullptr) {
448 listener->cancel(
"no longer needed");
453 debugs(33, 5,
"FTP closing client data listen socket: " <<
455 dataListenConn->close();
457 dataListenConn =
nullptr;
459 if (reader !=
nullptr) {
466 debugs(33, 5,
"FTP closing client data connection: " <<
478 debugs(33, 7, code <<
' ' << msg);
479 assert(99 < code && code < 1000);
483 mb.
appendf(
"%i %s\r\n", code, msg);
489 flags.readMore =
false;
497 debugs(9, 2,
"FTP Client " << clientConnection);
498 debugs(9, 2,
"FTP Client REPLY:\n---------\n" << mb.
buf <<
509 debugs(33, 7, code <<
' ' << msg);
510 assert(99 < code && code < 1000);
512 const bool sendDetails = reply !=
nullptr &&
518 mb.
appendf(
"%i-%s\r\n", code, msg);
519 mb.
appendf(
" Server reply:\r\n");
523 mb.
appendf(
"%i %s\r\n", code, msg);
531 if (master->serverState == newState) {
532 debugs(33, 3,
"client state unchanged at " << master->serverState <<
533 " because " << reason);
534 master->serverState = newState;
536 debugs(33, 3,
"client state was " << master->serverState <<
537 ", now " << newState <<
" because " << reason);
538 master->serverState = newState;
546 static std::set<SBuf> PathedCommands;
547 if (!PathedCommands.size()) {
548 PathedCommands.insert(
cmdMlst());
549 PathedCommands.insert(
cmdMlsd());
550 PathedCommands.insert(
cmdStat());
551 PathedCommands.insert(
cmdNlst());
552 PathedCommands.insert(
cmdList());
553 PathedCommands.insert(
cmdMkd());
554 PathedCommands.insert(
cmdRmd());
555 PathedCommands.insert(
cmdDele());
556 PathedCommands.insert(
cmdRnto());
557 PathedCommands.insert(
cmdRnfr());
558 PathedCommands.insert(
cmdAppe());
559 PathedCommands.insert(
cmdStor());
560 PathedCommands.insert(
cmdRetr());
561 PathedCommands.insert(
cmdSmnt());
562 PathedCommands.insert(
cmdCwd());
565 return PathedCommands.find(cmd) != PathedCommands.end();
574 const char *reason =
"Internal error";
575 const char *errUri =
"error:ftp-internal-early-error";
578 case EarlyErrorKind::HugeRequest:
580 reason =
"Huge request";
581 errUri =
"error:ftp-huge-request";
584 case EarlyErrorKind::MissingLogin:
586 reason =
"Must login first";
587 errUri =
"error:ftp-must-login-first";
590 case EarlyErrorKind::MissingUsername:
592 reason =
"Missing username";
593 errUri =
"error:ftp-missing-username";
596 case EarlyErrorKind::MissingHost:
598 reason =
"Missing host";
599 errUri =
"error:ftp-missing-host";
602 case EarlyErrorKind::UnsupportedCommand:
604 reason =
"Unknown or unsupported command";
605 errUri =
"error:ftp-unsupported-command";
608 case EarlyErrorKind::InvalidUri:
610 reason =
"Invalid URI";
611 errUri =
"error:ftp-invalid-uri";
614 case EarlyErrorKind::MalformedCommand:
616 reason =
"Malformed command";
617 errUri =
"error:ftp-malformed-command";
642 flags.readMore =
false;
648 static const char *
const InlineSpaceChars =
" \f\r\t\v";
656 static const CharacterSet &LeadingSpace = FullWhiteSpace;
663 (void)
tok.skipAll(LeadingSpace);
664 const bool parsed =
tok.prefix(cmd, CommandChars);
667 if (parsed &&
tok.skipAll(InlineSpace) &&
tok.prefix(params, TailChars)) {
670 static const SBuf bufWhiteSpace(InlineSpaceChars);
671 params.
trim(bufWhiteSpace,
false,
true);
679 if (cmd.
length() > tokenMax || params.
length() > tokenMax) {
680 changeState(
fssError,
"huge req token");
681 quitAfterError(
nullptr);
682 return earlyError(EarlyErrorKind::HugeRequest);
690 quitAfterError(
nullptr);
691 return earlyError(EarlyErrorKind::HugeRequest);
693 flags.readMore =
true;
694 debugs(33, 5,
"Waiting for more, up to " <<
701 consumeInput(
tok.parsedSize());
703 debugs(33, 2,
">>ftp " << cmd << (params.
isEmpty() ?
"" :
" ") << params);
708 if (!transparent()) {
709 if (!master->clientReadGreeting) {
711 if (!pinning.pinned && cmd !=
cmdUser())
712 return earlyError(EarlyErrorKind::MissingLogin);
717 if (
Http::Stream *errCtx = handleUserRequest(cmd, params))
723 return earlyError(EarlyErrorKind::UnsupportedCommand);
733 mx->tcpClient = clientConnection;
736 debugs(33, 5,
"Invalid FTP URL: " << uri);
738 return earlyError(EarlyErrorKind::InvalidUri);
740 char *newUri =
xstrdup(uri.c_str());
742 request->flags.ftpNative =
true;
746 request->flags.disableCacheUse(
"FTP command wrapper");
782 assert(context !=
nullptr);
784 static ReplyHandler handlers[] = {
801 if (
const ReplyHandler handler = handlers[
server.master->serverState])
802 (this->*handler)(reply, data);
804 writeForwardedReply(reply);
805 }
catch (
const std::exception &e) {
814 if (pipeline.front()->http->request->error) {
815 writeCustomReply(502,
"Server does not support FEAT", reply);
824 bool hasEPRT =
false;
825 bool hasEPSV =
false;
826 int prependSpaces = 1;
838 static const CharacterSet AfterFeatNameChars(
"AfterFeatName",
" \"");
842 if (!
tok.skip(
'"') || !
tok.skip(
' '))
849 if (!
tok.prefix(cmd, FeatNameChars))
867 snprintf(buf,
sizeof(buf),
"\"%*s\"", prependSpaces + 4,
"EPRT");
871 snprintf(buf,
sizeof(buf),
"\"%*s\"", prependSpaces + 4,
"EPSV");
877 writeForwardedReply(featReply.
getRaw());
884 assert(context !=
nullptr);
886 if (context->http->request->error) {
887 writeCustomReply(502,
"Server does not support PASV", reply);
891 const unsigned short localPort = listenForDataConnection();
898 clientConnection->local : dataListenConn->local;
901 for (
char *c = addr; *c !=
'\0'; ++c) {
912 mb.
appendf(
"227 Entering Passive Mode (%s,%i,%i).\r\n",
914 static_cast<int>(localPort / 256),
915 static_cast<int>(localPort % 256));
923 if (pipeline.front()->http->request->error) {
924 writeCustomReply(502,
"Server does not support PASV (converted from PORT)", reply);
928 writeCustomReply(200,
"PORT successfully converted to PASV.");
939 writeErrorReply(reply, 421);
946 writeForwardedReply(reply);
948 debugs(33, 3,
"closing " << dataConn <<
" on KO reply");
949 closeDataConnection();
956 debugs(33, 3,
"ignoring FTP srv data response after clt data closure");
960 if (!checkDataConnPost()) {
961 writeCustomReply(425,
"Data connection is not established.");
962 closeDataConnection();
969 replyDataWritingCheckpoint();
981 pipeline.front()->noteSentBodyBytes(data.
length);
993 userDataCompletionCheckpoint(426);
997 assert(pipeline.front()->http);
998 pipeline.front()->http->out.size += io.
size;
999 replyDataWritingCheckpoint();
1006 switch (pipeline.front()->socketState()) {
1008 debugs(33, 3,
"Keep going");
1009 pipeline.front()->pullData();
1012 debugs(33, 3,
"FTP reply data transfer successfully complete");
1013 userDataCompletionCheckpoint(226);
1016 debugs(33, 3,
"FTP reply data transfer failed: STREAM_UNPLANNED_COMPLETE");
1017 userDataCompletionCheckpoint(451);
1020 userDataCompletionCheckpoint(451);
1021 debugs(33, 3,
"FTP reply data transfer failed: STREAM_FAILED");
1024 fatal(
"unreachable code");
1031 writeForwardedReply(reply);
1040 if (waitingForOrigin) {
1041 Must(delayedReply ==
nullptr);
1042 delayedReply = reply;
1049 writeForwardedForeign(reply);
1055 writeForwardedReplyAndCall(reply, call);
1061 if (pipeline.front()->http->request->error) {
1062 writeCustomReply(502,
"Server does not support PASV (converted from EPRT)", reply);
1066 writeCustomReply(200,
"EPRT successfully converted to PASV.");
1074 if (pipeline.front()->http->request->error) {
1075 writeCustomReply(502,
"Cannot connect to server", reply);
1079 const unsigned short localPort = listenForDataConnection();
1087 mb.
appendf(
"229 Entering Extended Passive Mode (|||%u|)\r\n", localPort);
1097 const HttpRequest *request = pipeline.front()->http->request;
1114 if (ah !=
nullptr) {
1124 const char *reason =
"Lost Error";
1131 mb.
appendf(
"%i %s\r\n", scode, reason);
1146 closeDataConnection();
1148 writeErrorReply(reply, 451);
1156 writeForwardedReplyAndCall(reply, call);
1163 assert(reply !=
nullptr);
1170 debugs(33, 7,
"scode: " << scode);
1174 if ((scode == 125 || scode == 150) &&
1177 if (checkDataConnPost()) {
1180 debugs(33, 7,
"data connection established, start data transfer");
1182 maybeReadUploadData();
1186 debugs(33, 7,
"wait for the client to establish a data connection");
1187 onDataAcceptCall = call;
1195 debugs(33, 7,
"done with data OR active connection failed");
1205 debugs(9, 2,
"FTP Client " << clientConnection);
1206 debugs(9, 2,
"FTP Client REPLY:\n---------\n" << mb.
buf <<
1229 (reason ? reason :
""));
1246 if (context !=
nullptr && context->http) {
1247 context->http->out.size += io.
size;
1248 context->http->out.headers_sz += io.
size;
1251 flags.readMore =
true;
1269 context->http->out.size += io.
size;
1270 context->http->out.headers_sz += io.
size;
1272 if (master->serverState ==
fssError) {
1273 debugs(33, 5,
"closing on FTP server error");
1279 debugs(33, 5,
"FTP client stream state " << socketState);
1280 switch (socketState) {
1288 flags.readMore =
true;
1291 finishDechunkingRequest(
false);
1292 context->finished();
1315 debugs(9, 2,
"FTP Client " << clientConnection);
1316 debugs(9, 2,
"FTP Client REQUEST:\n---------\n" << mb.
buf <<
1321 typedef std::map<const std::string, RequestHandler> RequestHandlers;
1322 static RequestHandlers handlers;
1323 if (!handlers.size()) {
1338 RequestHandler handler =
nullptr;
1342 const RequestHandlers::const_iterator hi = handlers.find(cmd.
termedBuf());
1343 if (hi != handlers.end())
1344 handler = hi->second;
1348 debugs(9, 7,
"forwarding " << cmd <<
" as is, no post-processing");
1352 return (this->*handler)(cmd, params);
1361 return earlyError(EarlyErrorKind::MissingUsername);
1366 return earlyError(EarlyErrorKind::MissingHost);
1382 params.
chop(0, eou);
1385 if (master->clientReadGreeting)
1388 master->workingDir.
clear();
1391 if (!master->clientReadGreeting) {
1392 debugs(9, 3,
"set URI to " << uri);
1393 }
else if (oldUri.
caseCmp(uri) == 0) {
1394 debugs(9, 5,
"kept URI as " << oldUri);
1396 debugs(9, 3,
"reset URI from " << oldUri <<
" to " << uri);
1397 closeDataConnection();
1398 unpinConnection(
true);
1399 resetLogin(
"URI reset");
1416 setReply(500,
"Bad PASV command");
1420 if (params.
size() > 0) {
1421 setReply(501,
"Unexpected parameter");
1434 assert(clientConnection !=
nullptr);
1435 assert(!clientConnection->remote.isAnyAddr());
1437 if (cltAddr != clientConnection->remote) {
1438 debugs(33, 2,
"rogue PORT " << cltAddr <<
" request? ctrl: " << clientConnection->remote);
1442 setReply(501,
"Prohibited parameter value");
1446 closeDataConnection();
1471 conn->
setAddrs(clientConnection->local, cltAddr);
1482 debugs(9, 3,
"will actively connect from " << conn->
local <<
" to " <<
1486 uploadAvailSize = 0;
1496 setReply(500,
"Rejecting PORT after EPSV ALL");
1500 if (!params.
size()) {
1501 setReply(501,
"Missing parameter");
1507 setReply(501,
"Invalid parameter");
1511 if (!createDataConnection(cltAddr))
1522 if (!checkDataConnPre())
1525 master->userDataDone = 0;
1526 originDataDownloadAbortedOnError =
false;
1536 if (!checkDataConnPre())
1543 bodyContinuationCheck.
al = http->
al;
1547 if (checkDataConnPost()) {
1549 writeEarlyReply(150,
"Data connection opened");
1550 maybeReadUploadData();
1556 onDataAcceptCall = call;
1569 debugs(9, 3,
"Process an EPRT " << params);
1572 setReply(500,
"Rejecting EPRT after EPSV ALL");
1576 if (!params.
size()) {
1577 setReply(501,
"Missing parameter");
1583 setReply(501,
"Invalid parameter");
1587 if (!createDataConnection(cltAddr))
1598 debugs(9, 3,
"Process an EPSV command with params: " << params);
1599 if (params.
size() <= 0) {
1601 }
else if (params.
caseCmp(
"ALL") == 0) {
1602 setReply(200,
"EPSV ALL ok");
1605 }
else if (params.
cmp(
"2") == 0) {
1606 if (!Ip::EnableIpv6) {
1607 setReply(522,
"Network protocol not supported, use (1)");
1610 }
else if (params.
cmp(
"1") != 0) {
1611 setReply(501,
"Unsupported EPSV parameter");
1649 assert(request !=
nullptr);
1651 static const SBuf pasvValue(
"PASV");
1653 static const SBuf emptyValue(
"");
1655 debugs(9, 5,
"client data command converted to fake PASV");
1670 debugs(33, 3,
"expecting clt data conn " << dataListenConn);
1674 if (!dataConn || dataConn->remote.isAnyAddr()) {
1675 debugs(33, 5,
"missing " << dataConn);
1677 setReply(425,
"Use PORT or PASV first");
1686 dataConnWait.start(cs, callback);
1695 debugs(33, 3,
"missing client data conn: " << dataConn);
1705 dataConnWait.finish();
1708 setReply(425,
"Cannot open data connection.");
1710 Must(context->http);
1711 Must(context->http->storeEntry() !=
nullptr);
1717 assert(!dataConn->isOpen());
1718 dataConn = params.
conn;
1741 assert(repContext !=
nullptr);
1752 debugs(33, 2,
"FTP::Server job caught: " << e.what());
1753 closeDataConnection();
1754 unpinConnection(
true);
1756 clientConnection->close();
1766 debugs(33, 5,
"waiting for Ftp::Client data transfer to end");
1767 waitingForOrigin =
true;
1773 Must(waitingForOrigin);
1774 waitingForOrigin =
false;
1782 delayedReply =
nullptr;
1783 writeForwardedReply(reply.
getRaw());
1793 if (master->userDataDone) {
1798 completeDataDownload();
1800 debugs(33, 5,
"too early to write the response");
1805 originDataDownloadAbortedOnError = (originStatus >= 400);
1811 Must(!master->userDataDone);
1812 master->userDataDone = finalStatusCode;
1815 finishDechunkingRequest(
false);
1817 if (waitingForOrigin) {
1822 debugs(33, 5,
"Transferring from FTP server is not complete");
1827 if (master->userDataDone == 226 && originDataDownloadAbortedOnError) {
1828 debugs(33, 5,
"Transferring from FTP server terminated with an error, adjust status code");
1829 master->userDataDone = 451;
1831 completeDataDownload();
1836 writeCustomReply(master->userDataDone, master->userDataDone == 226 ?
"Transfer complete" :
"Server error; transfer aborted");
1837 closeDataConnection();
1844 static std::set<SBuf> BlockList;
1845 if (BlockList.empty()) {
1854 return BlockList.find(name) == BlockList.end();
#define Assure(condition)
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
#define CallJobHere(debugSection, debugLevel, job, Class, method)
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
#define COMM_INTERCEPTION
AnyP::PortCfgPointer FtpPortList
list of Squid ftp_port configured
#define MAXTCPLISTENPORTS
void comm_read(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer &callback)
#define SQUIDSBUFPRINT(s)
#define TexcHere(msg)
legacy convenience macro; it is not difficult to type Here() now
static char server[MAXLINE]
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
Acl::Answer const & fastCheck()
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
void syncAle(HttpRequest *adaptedRequest, const char *logUri) const override
assigns uninitialized adapted_request and url ALE components
HttpHeader allMeta
All REQMOD and RESPMOD meta headers merged. Last field wins conflicts.
static void Start(const Pointer &job)
virtual void callException(const std::exception &e)
called when the job throws during an async call
optimized set of C chars, with quick membership test and merge support
CharacterSet complement(const char *complementLabel=nullptr) const
static const CharacterSet SP
static const CharacterSet LF
HttpRequest *const request
void initRequest(HttpRequest *)
size_t req_sz
raw request size on input, not current request size
StoreEntry * storeEntry() const
const AccessLogEntry::Pointer al
access.log entry
static const Pointer & Current()
static void Reset()
forgets the current context, setting it to nil/unknown
AnyP::PortCfgPointer port
the configuration listening port this call relates to (may be nil)
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Comm::Flag flag
comm layer result status.
Comm::ConnectionPointer conn
void setAddrs(const Ip::Address &aLocal, const Ip::Address &aRemote)
void leaveOrphanage()
resume relying on owner(s) to initiate an explicit connection closure
virtual void clientPinnedConnectionClosed(const CommCloseCbParams &io)
Our close handler called by Comm when the pinned connection is closed.
void start() override
called by AsyncStart; do not call directly
struct ConnStateData::@28 flags
bool readMore
needs comm_read (for this request or new requests)
void noteBodyConsumerAborted(BodyPipe::Pointer) override=0
static bool Enabled(const int section, const int level)
whether debugging the given section and the given level produces output
err_type category
primary error classification (or ERR_NONE)
Transaction information shared among our FTP client and server jobs.
Manages a control connection from an FTP client.
void writeCustomReply(const int code, const char *msg, const HttpReply *reply=nullptr)
void handleDataReply(const HttpReply *header, StoreIOBuffer receivedData)
void calcUri(const SBuf *file)
computes uri member from host and, if tracked, working dir with file name
bool handlePasvRequest(String &cmd, String ¶ms)
bool handleDataRequest(String &cmd, String ¶ms)
bool handleUploadRequest(String &cmd, String ¶ms)
void writeForwardedReply(const HttpReply *reply)
void userDataCompletionCheckpoint(int finalStatusCode)
void connectedForData(const CommConnectCbParams ¶ms)
Done establishing a data connection to the user.
bool handleCdupRequest(String &cmd, String ¶ms)
void writeForwardedForeign(const HttpReply *reply)
static void AcceptCtrlConnection(const CommAcceptCbParams ¶ms)
accept a new FTP control connection and hand it to a dedicated Server
void maybeReadUploadData()
schedules another data connection read if needed
void handleEprtReply(const HttpReply *header, StoreIOBuffer receivedData)
void changeState(const Ftp::ServerState newState, const char *reason)
void wroteReply(const CommIoCbParams &io)
void handlePasvReply(const HttpReply *header, StoreIOBuffer receivedData)
Http::Stream * earlyError(const EarlyErrorKind eek)
creates a context filled with an error message for a given early error
void callException(const std::exception &e) override
called when the job throws during an async call
void completeDataDownload()
void handleFeatReply(const HttpReply *header, StoreIOBuffer receivedData)
bool handlePortRequest(String &cmd, String ¶ms)
void acceptDataConnection(const CommAcceptCbParams ¶ms)
bool handleFeatRequest(String &cmd, String ¶ms)
void writeErrorReply(const HttpReply *reply, const int status)
writes FTP error response with given status and reply-derived error details
void startWaitingForOrigin()
void writeReply(MemBuf &mb)
void resetLogin(const char *reason)
clear client and server login-related state after the old login is gone
void processParsedRequest(Http::StreamPointer &context) override
start processing a freshly parsed request
void noteBodyConsumerAborted(BodyPipe::Pointer ptr) override
void wroteReplyData(const CommIoCbParams &io)
called when we are done writing a chunk of the response data
time_t idleTimeout() const override
timeout to use when waiting for the next request
void clientPinnedConnectionClosed(const CommCloseCbParams &io) override
Our close handler called by Comm when the pinned connection is closed.
Server(const MasterXaction::Pointer &xact)
bool writeControlMsgAndCall(HttpReply *rep, AsyncCall::Pointer &call) override
handle a control message received by context from a peer and call back
void start() override
called by AsyncStart; do not call directly
void handlePortReply(const HttpReply *header, StoreIOBuffer receivedData)
void handleErrorReply(const HttpReply *header, StoreIOBuffer receivedData)
void notePeerConnection(Comm::ConnectionPointer conn) override
called just before a FwdState-dispatched job starts using connection
Http::Stream * parseOneRequest() override
char uploadBuf[CLIENT_REQ_BUF_SZ]
data connection input buffer
void handleReply(HttpReply *header, StoreIOBuffer receivedData) override
bool createDataConnection(Ip::Address cltAddr)
[Re]initializes dataConn for active data transfers. Does not connect.
bool handleEpsvRequest(String &cmd, String ¶ms)
void setReply(const int code, const char *msg)
void replyDataWritingCheckpoint()
ClientStream checks after (actual or skipped) reply data writing.
bool handlePassRequest(String &cmd, String ¶ms)
void handleEpsvReply(const HttpReply *header, StoreIOBuffer receivedData)
void wroteEarlyReply(const CommIoCbParams &io)
Http::Stream * handleUserRequest(const SBuf &cmd, SBuf ¶ms)
void handleUploadReply(const HttpReply *header, StoreIOBuffer receivedData)
bool handleRequest(HttpRequest *)
void noteMoreBodySpaceAvailable(BodyPipe::Pointer) override
void stopWaitingForOrigin(int status)
void shovelUploadData()
shovel upload data from the internal buffer to the body pipe if possible
unsigned int listenForDataConnection()
void writeForwardedReplyAndCall(const HttpReply *reply, AsyncCall::Pointer &call)
int pipelinePrefetchMax() const override
returning N allows a pipeline of 1+N requests (see pipeline_prefetch)
bool checkDataConnPost() const
Check that client data connection is ready for immediate I/O.
void doProcessRequest()
react to the freshly parsed request
void readUploadData(const CommIoCbParams &io)
imports more upload data from the data connection
bool handleCwdRequest(String &cmd, String ¶ms)
bool handleEprtRequest(String &cmd, String ¶ms)
void writeEarlyReply(const int code, const char *msg)
void closeDataConnection()
Adaptation::History::Pointer adaptHistory(bool createIfNone=false) const
Returns possibly nil history, creating it if requested.
void pack(Packable *p, bool maskSensitiveInfo=false) const
bool forcedBodyContinuation
whether we have responded with HTTP 100 or FTP 150 already
static HttpRequest * FromUrl(const SBuf &url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Error error
the first transaction problem encountered (or falsy)
const char * reason() const
retrieve the reason string for this status line
Http::StatusCode status() const
retrieve the status code for this status line
unsigned parsed_ok
Was this parsed correctly?
struct Http::Stream::@58 flags
char reqbuf[HTTP_REQBUF_SZ]
clientStreamNode * getClientReplyContext() const
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
unsigned int toHostStr(char *buf, const unsigned int len) const
void setAnyAddr()
NOTE: Does NOT clear the Port stored. Only the Address and Type.
unsigned short port() const
static Pointer MakePortful(const AnyP::PortCfgPointer &aPort)
void append(const char *c, int sz) override
void init(mb_size_t szInit, mb_size_t szMax)
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
void disableCacheUse(const char *reason)
void toUpper()
converts all characters to upper case;
int caseCmp(const SBuf &S, const size_type n) const
shorthand version for case-insensitive compare()
static const size_type npos
SBuf & chop(size_type pos, size_type n=npos)
size_type length() const
Returns the number of bytes stored in SBuf.
size_type rfind(char c, size_type endPos=npos) const
SBuf & trim(const SBuf &toRemove, bool atBeginning=true, bool atEnd=true)
SBuf substr(size_type pos, size_type n=npos) const
MemBlob::size_type size_type
struct SquidConfig::@77 Timeout
size_t maxRequestHeaderSize
struct SquidConfig::@91 accessList
acl_access * forceRequestBodyContinuation
struct StatCounters::@104 client_http
void replaceHttpReply(const HttpReplyPointer &, const bool andStartWriting=true)
int cmp(char const *) const
char const * termedBuf() const
int caseCmp(char const *) const
void setReplyToReply(HttpReply *reply)
creates a store entry for the reply and appends error reply to it
void createStoreEntry(const HttpRequestMethod &m, RequestFlags flags)
void clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, Http::Stream *context)
void clientSetKeepaliveFlag(ClientHttpRequest *http)
decide whether to expect multiple requests on the corresponding connection
void clientStartListeningOn(AnyP::PortCfgPointer &port, const RefCount< CommCbFunPtrCallT< CommAcceptCbPtrFun > > &subCall, const Ipc::FdNoteId fdNote)
accept requests to a given port and inform subCall about them
CSCB clientSocketRecipient
unsigned short comm_local_port(int fd)
void comm_open_listener(int sock_type, int proto, Comm::ConnectionPointer &conn, const char *note)
bool isOpen(const int fd)
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
@ STREAM_UNPLANNED_COMPLETE
void fatal(const char *message)
void fd_note(int fd, const char *s)
void clientStreamInit(dlink_list *list, CSR *func, CSD *rdetach, CSS *readstatus, const ClientStreamData &readdata, CSCB *callback, CSD *cdetach, const ClientStreamData &callbackdata, StoreIOBuffer tailBuffer)
const char * errorPageName(int pageId)
error ID to string
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
bool IsConnOpen(const Comm::ConnectionPointer &conn)
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
static bool SupportedCommand(const SBuf &name)
Whether Squid FTP Relay supports a named feature (e.g., a command).
AnyP::ProtocolVersion ProtocolVersion()
Protocol version to use in Http::Message structures wrapping FTP messages.
bool ParseProtoIpPort(const char *buf, Ip::Address &addr)
static bool CommandHasPathParameter(const SBuf &cmd)
whether the given FTP command has a pathname parameter
bool ParseIpPort(const char *buf, const char *forceIp, Ip::Address &addr)
parses and validates "A1,A2,A3,A4,P1,P2" IP,port sequence
HttpReply * HttpReplyWrapper(const int ftpStatus, const char *ftpReason, const Http::StatusCode httpStatus, const int64_t clen)
Create an internal HttpReply structure to house FTP control response info.
void StopListening()
reject new connections to any configured ftp_port
void StartListening()
accept connections on all configured ftp_ports
static void PrintReply(MemBuf &mb, const HttpReply *reply, const char *const prefix="")
AnyP::ProtocolVersion ProtocolVersion()
const char * xstrerr(int error)