FtpRelay.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 /* DEBUG: section 09 File Transfer Protocol (FTP) */
10 
11 #include "squid.h"
12 #include "anyp/PortCfg.h"
13 #include "base/AsyncCbdataCalls.h"
14 #include "client_side.h"
15 #include "clients/forward.h"
16 #include "clients/FtpClient.h"
17 #include "error/SysErrorDetail.h"
18 #include "ftp/Elements.h"
19 #include "ftp/Parsing.h"
20 #include "http/Stream.h"
21 #include "HttpHdrCc.h"
22 #include "HttpRequest.h"
23 #include "sbuf/SBuf.h"
24 #include "servers/FtpServer.h"
25 #include "SquidTime.h"
26 #include "Store.h"
27 #include "wordlist.h"
28 
29 namespace Ftp
30 {
31 
35 class Relay: public Ftp::Client
36 {
38 
39 public:
40  explicit Relay(FwdState *const fwdState);
41  virtual ~Relay();
42 
43 protected:
44  const Ftp::MasterState &master() const;
47  void serverState(const Ftp::ServerState newState);
48 
49  /* Ftp::Client API */
50  virtual void failed(err_type error = ERR_NONE, int xerrno = 0, ErrorState *ftperr = nullptr);
51  virtual void dataChannelConnected(const CommConnectCbParams &io);
52 
53  /* Client API */
54  virtual void serverComplete();
55  virtual void handleControlReply();
56  virtual void processReplyBody();
57  virtual void handleRequestBodyProducerAborted();
58  virtual bool mayReadVirginReplyBody() const;
59  virtual void completeForwarding();
60  virtual bool abortOnData(const char *reason);
61 
62  /* AsyncJob API */
63  virtual void start();
64  virtual void swanSong();
65 
66  void forwardReply();
67  void forwardError(err_type error = ERR_NONE, int xerrno = 0);
68  void failedErrorMessage(err_type error, int xerrno);
69  HttpReply *createHttpReply(const Http::StatusCode httpStatus, const int64_t clen = 0);
70  void handleDataRequest();
71  void startDataDownload();
72  void startDataUpload();
73  bool startDirTracking();
74  void stopDirTracking();
75  bool weAreTrackingDir() const {return savedReply.message != NULL;}
76 
77  typedef void (Relay::*PreliminaryCb)();
81 
82  typedef void (Relay::*SM_FUNC)();
83  static const SM_FUNC SM_FUNCS[];
84  void readGreeting();
85  void sendCommand();
86  void readReply();
87  void readFeatReply();
88  void readPasvReply();
89  void readDataReply();
90  void readTransferDoneReply();
91  void readEpsvReply();
92  void readCwdOrCdupReply();
93  void readUserOrPassReply();
94 
96 
98  void stopOriginWait(int code);
100  static void HandleStoreAbort(Relay *);
101 
103 
107 
108  struct {
110  char *lastCommand;
111  char *lastReply;
112  int replyCode;
114 };
115 
116 } // namespace Ftp
117 
119 
121  &Ftp::Relay::readGreeting, // BEGIN
122  &Ftp::Relay::readUserOrPassReply, // SENT_USER
123  &Ftp::Relay::readUserOrPassReply, // SENT_PASS
124  NULL,/* &Ftp::Relay::readReply */ // SENT_TYPE
125  NULL,/* &Ftp::Relay::readReply */ // SENT_MDTM
126  NULL,/* &Ftp::Relay::readReply */ // SENT_SIZE
127  NULL, // SENT_EPRT
128  NULL, // SENT_PORT
129  &Ftp::Relay::readEpsvReply, // SENT_EPSV_ALL
130  &Ftp::Relay::readEpsvReply, // SENT_EPSV_1
131  &Ftp::Relay::readEpsvReply, // SENT_EPSV_2
132  &Ftp::Relay::readPasvReply, // SENT_PASV
133  &Ftp::Relay::readCwdOrCdupReply, // SENT_CWD
134  NULL,/* &Ftp::Relay::readDataReply, */ // SENT_LIST
135  NULL,/* &Ftp::Relay::readDataReply, */ // SENT_NLST
136  NULL,/* &Ftp::Relay::readReply */ // SENT_REST
137  NULL,/* &Ftp::Relay::readDataReply */ // SENT_RETR
138  NULL,/* &Ftp::Relay::readReply */ // SENT_STOR
139  NULL,/* &Ftp::Relay::readReply */ // SENT_QUIT
140  &Ftp::Relay::readTransferDoneReply, // READING_DATA
141  &Ftp::Relay::readReply, // WRITING_DATA
142  NULL,/* &Ftp::Relay::readReply */ // SENT_MKDIR
143  &Ftp::Relay::readFeatReply, // SENT_FEAT
144  NULL,/* &Ftp::Relay::readPwdReply */ // SENT_PWD
145  &Ftp::Relay::readCwdOrCdupReply, // SENT_CDUP
146  &Ftp::Relay::readDataReply,// SENT_DATA_REQUEST
147  &Ftp::Relay::readReply, // SENT_COMMAND
148  NULL
149 };
150 
151 Ftp::Relay::Relay(FwdState *const fwdState):
152  AsyncJob("Ftp::Relay"),
153  Ftp::Client(fwdState),
154  thePreliminaryCb(NULL),
155  forwardingCompleted(false),
156  originWaitInProgress(false)
157 {
158  savedReply.message = NULL;
159  savedReply.lastCommand = NULL;
160  savedReply.lastReply = NULL;
161  savedReply.replyCode = 0;
162 
163  // Prevent the future response from becoming public and being shared/cached
164  // because FTP does not support response cachability and freshness checks.
166  AsyncCall::Pointer call = asyncCall(9, 4, "Ftp::Relay::Abort", cbdataDialer(&Relay::HandleStoreAbort, this));
168 }
169 
171 {
172  entry->unregisterAbortCallback("Ftp::Relay object destructed");
173  // Client, our parent, calls entry->unlock().
174  // Client does not currently un/registerAbortCallback() because
175  // FwdState does that for other Client kids; \see FwdState::start().
176 
177  closeServer(); // TODO: move to clients/Client.cc?
178  if (savedReply.message)
179  wordlistDestroy(&savedReply.message);
180 
181  xfree(savedReply.lastCommand);
182  xfree(savedReply.lastReply);
183 }
184 
185 void
187 {
188  if (!master().clientReadGreeting)
190  else if (serverState() == fssHandleDataRequest ||
191  serverState() == fssHandleUploadRequest)
192  handleDataRequest();
193  else
194  sendCommand();
195 }
196 
197 void
199 {
200  stopOriginWait(0);
202 }
203 
206 void
208 {
209  stopOriginWait(ctrl.replycode);
210 
211  CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
212  if (mgr.valid()) {
213  if (Comm::IsConnOpen(ctrl.conn)) {
214  debugs(9, 7, "completing FTP server " << ctrl.conn <<
215  " after " << ctrl.replycode);
216  fwd->unregister(ctrl.conn);
217  if (ctrl.replycode == 221) { // Server sends FTP 221 before closing
218  mgr->unpinConnection(false);
219  ctrl.close();
220  } else {
221  CallJobHere1(9, 4, mgr,
223  notePinnedConnectionBecameIdle,
224  ConnStateData::PinnedIdleContext(ctrl.conn, fwd->request));
225  ctrl.forget();
226  }
227  }
228  }
230 }
231 
236 {
237  CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
238  if (mgr.valid()) {
239  if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get()))
240  return *srv->master;
241  }
242  // this code will not be necessary once the master is inside MasterXaction
243  debugs(9, 3, "our server side is gone: " << mgr);
244  static Ftp::MasterState Master;
245  Master = Ftp::MasterState();
246  return Master;
247 }
248 
250 const Ftp::MasterState &
252 {
253  return const_cast<Ftp::Relay*>(this)->updateMaster(); // avoid code dupe
254 }
255 
257 void
259 {
260  Ftp::ServerState &cltState = updateMaster().serverState;
261  debugs(9, 3, "client state was " << cltState << " now: " << newState);
262  cltState = newState;
263 }
264 
273 void
275 {
276  debugs(9, 5, forwardingCompleted);
277  if (forwardingCompleted)
278  return;
279  forwardingCompleted = true;
281 }
282 
283 void
285 {
286  if (!doneWithServer())
287  serverState(fssError);
288 
289  // TODO: we need to customize ErrorState instead
290  if (entry->isEmpty())
291  failedErrorMessage(error, xerrno); // as a reply
292 
293  Ftp::Client::failed(error, xerrno, ftpErr);
294 }
295 
296 void
298 {
299  const Http::StatusCode httpStatus = failedHttpStatus(error);
300  HttpReply *const reply = createHttpReply(httpStatus);
301  entry->replaceHttpReply(reply);
302  fwd->request->detailError(error, SysErrorDetail::NewIfAny(xerrno));
303 }
304 
305 void
307 {
308  debugs(9, 3, status());
309 
310  if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
311  /*
312  * probably was aborted because content length exceeds one
313  * of the maximum size limits.
314  */
315  abortOnData("entry aborted after calling appendSuccessHeader()");
316  return;
317  }
318 
319  if (master().userDataDone) {
320  // Squid-to-client data transfer done. Abort data transfer on our
321  // side to allow new commands from ftp client
322  abortOnData("Squid-to-client data connection is closed");
323  return;
324  }
325 
326 #if USE_ADAPTATION
327 
328  if (adaptationAccessCheckPending) {
329  debugs(9, 3, "returning due to adaptationAccessCheckPending");
330  return;
331  }
332 
333 #endif
334 
335  if (data.readBuf != NULL && data.readBuf->hasContent()) {
336  const mb_size_t csize = data.readBuf->contentSize();
337  debugs(9, 5, "writing " << csize << " bytes to the reply");
338  addVirginReplyBody(data.readBuf->content(), csize);
339  data.readBuf->consume(csize);
340  }
341 
342  entry->flush();
343 
344  maybeReadVirginBody();
345 }
346 
347 void
349 {
350  if (!request->clientConnectionManager.valid()) {
351  debugs(9, 5, "client connection gone");
352  closeServer();
353  return;
354  }
355 
357  if (ctrl.message == NULL)
358  return; // didn't get complete reply yet
359 
360  assert(state < END);
361  assert(this->SM_FUNCS[state] != NULL);
362  (this->*SM_FUNCS[state])();
363 }
364 
365 void
367 {
369 
370  failed(ERR_READ_ERROR);
371 }
372 
373 bool
375 {
376  // TODO: move this method to the regular FTP server?
377  return Comm::IsConnOpen(data.conn);
378 }
379 
380 void
382 {
383  assert(entry->isEmpty());
384 
385  HttpReply *const reply = createHttpReply(Http::scNoContent);
386  reply->sources |= Http::Message::srcFtp;
387 
388  setVirginReply(reply);
389  markParsedVirginReplyAsWhole("Ftp::Relay::handleControlReply() does not forward partial replies");
390  adaptOrFinalizeReply();
391 
392  serverComplete();
393 }
394 
395 void
396 Ftp::Relay::forwardPreliminaryReply(const PreliminaryCb cb)
397 {
398  debugs(9, 5, "forwarding preliminary reply to client");
399 
400  // we must prevent concurrent ConnStateData::sendControlMsg() calls
401  Must(thePreliminaryCb == NULL);
402  thePreliminaryCb = cb;
403 
404  const HttpReply::Pointer reply = createHttpReply(Http::scContinue);
405 
406  // the Sink will use this to call us back after writing 1xx to the client
407  typedef NullaryMemFunT<Relay> CbDialer;
408  const AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, this,
410 
411  CallJobHere1(9, 4, request->clientConnectionManager, ConnStateData,
413 }
414 
415 void
417 {
418  debugs(9, 5, "proceeding after preliminary reply to client");
419 
420  Must(thePreliminaryCb != NULL);
421  const PreliminaryCb cb = thePreliminaryCb;
422  thePreliminaryCb = NULL;
423  (this->*cb)();
424 }
425 
426 void
428 {
429  failed(error, xerrno);
430 }
431 
432 HttpReply *
433 Ftp::Relay::createHttpReply(const Http::StatusCode httpStatus, const int64_t clen)
434 {
435  HttpReply *const reply = Ftp::HttpReplyWrapper(ctrl.replycode, ctrl.last_reply, httpStatus, clen);
436  if (ctrl.message) {
437  for (wordlist *W = ctrl.message; W && W->next; W = W->next)
439  // no hdrCacheInit() is needed for after Http::HdrType::FTP_PRE addition
440  }
441  return reply;
442 }
443 
444 void
446 {
447  data.addr(master().clientDataAddr);
448  connectDataChannel();
449 }
450 
451 void
453 {
454  assert(Comm::IsConnOpen(data.conn));
455 
456  debugs(9, 3, "begin data transfer from " << data.conn->remote <<
457  " (" << data.conn->local << ")");
458 
459  HttpReply *const reply = createHttpReply(Http::scOkay, -1);
460  reply->sources |= Http::Message::srcFtp;
461 
462  setVirginReply(reply);
463  adaptOrFinalizeReply();
464 
465  maybeReadVirginBody();
466  state = READING_DATA;
467 }
468 
469 void
471 {
472  assert(Comm::IsConnOpen(data.conn));
473 
474  debugs(9, 3, "begin data transfer to " << data.conn->remote <<
475  " (" << data.conn->local << ")");
476 
477  if (!startRequestBodyFlow()) { // register to receive body data
478  failed();
479  return;
480  }
481 
482  state = WRITING_DATA;
483 }
484 
485 void
487 {
488  assert(!master().clientReadGreeting);
489 
490  switch (ctrl.replycode) {
491  case 220:
492  updateMaster().clientReadGreeting = true;
493  if (serverState() == fssBegin)
494  serverState(fssConnected);
495 
496  // Do not forward server greeting to the user because our FTP Server
497  // has greeted the user already. Also, an original origin greeting may
498  // confuse a user that has changed the origin mid-air.
499 
500  start();
501  break;
502  case 120:
503  if (NULL != ctrl.message)
504  debugs(9, DBG_IMPORTANT, "FTP server is busy: " << ctrl.message->key);
505  forwardPreliminaryReply(&Ftp::Relay::scheduleReadControlReply);
506  break;
507  default:
508  failed();
509  break;
510  }
511 }
512 
513 void
515 {
516  if (!fwd->request->header.has(Http::HdrType::FTP_COMMAND)) {
517  abortAll("Internal error: FTP relay request with no command");
518  return;
519  }
520 
521  HttpHeader &header = fwd->request->header;
523  const String &cmd = header.findEntry(Http::HdrType::FTP_COMMAND)->value;
525  const String &params = header.findEntry(Http::HdrType::FTP_ARGUMENTS)->value;
526 
527  if (params.size() > 0)
528  debugs(9, 5, "command: " << cmd << ", parameters: " << params);
529  else
530  debugs(9, 5, "command: " << cmd << ", no parameters");
531 
532  if (serverState() == fssHandlePasv ||
533  serverState() == fssHandleEpsv ||
534  serverState() == fssHandleEprt ||
535  serverState() == fssHandlePort) {
536  sendPassive();
537  return;
538  }
539 
540  SBuf buf;
541  if (params.size() > 0)
542  buf.Printf("%s %s%s", cmd.termedBuf(), params.termedBuf(), Ftp::crlf);
543  else
544  buf.Printf("%s%s", cmd.termedBuf(), Ftp::crlf);
545 
546  writeCommand(buf.c_str());
547 
548  state =
549  serverState() == fssHandleCdup ? SENT_CDUP :
550  serverState() == fssHandleCwd ? SENT_CWD :
551  serverState() == fssHandleFeat ? SENT_FEAT :
552  serverState() == fssHandleDataRequest ? SENT_DATA_REQUEST :
553  serverState() == fssHandleUploadRequest ? SENT_DATA_REQUEST :
554  serverState() == fssConnected ? SENT_USER :
555  serverState() == fssHandlePass ? SENT_PASS :
556  SENT_COMMAND;
557 
558  if (state == SENT_DATA_REQUEST) {
559  CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
560  if (mgr.valid()) {
561  if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
562  typedef NullaryMemFunT<Ftp::Server> CbDialer;
563  AsyncCall::Pointer call = JobCallback(11, 3, CbDialer, srv,
565  ScheduleCallHere(call);
566  originWaitInProgress = true;
567  }
568  }
569  }
570 }
571 
572 void
574 {
575  assert(serverState() == fssConnected ||
576  serverState() == fssHandleUploadRequest);
577 
578  if (Is1xx(ctrl.replycode))
579  forwardPreliminaryReply(&Ftp::Relay::scheduleReadControlReply);
580  else
581  forwardReply();
582 }
583 
584 void
586 {
587  assert(serverState() == fssHandleFeat);
588 
589  if (Is1xx(ctrl.replycode))
590  return; // ignore preliminary replies
591 
592  forwardReply();
593 }
594 
595 void
597 {
598  assert(serverState() == fssHandlePasv || serverState() == fssHandleEpsv || serverState() == fssHandlePort || serverState() == fssHandleEprt);
599 
600  if (Is1xx(ctrl.replycode))
601  return; // ignore preliminary replies
602 
603  if (handlePasvReply(updateMaster().clientDataAddr))
604  forwardReply();
605  else
606  forwardError();
607 }
608 
609 void
611 {
612  if (Is1xx(ctrl.replycode))
613  return; // ignore preliminary replies
614 
615  if (handleEpsvReply(updateMaster().clientDataAddr)) {
616  if (ctrl.message == NULL)
617  return; // didn't get complete reply yet
618 
619  forwardReply();
620  } else
621  forwardError();
622 }
623 
624 void
626 {
627  assert(serverState() == fssHandleDataRequest ||
628  serverState() == fssHandleUploadRequest);
629 
630  if (ctrl.replycode == 125 || ctrl.replycode == 150) {
631  if (serverState() == fssHandleDataRequest)
632  forwardPreliminaryReply(&Ftp::Relay::startDataDownload);
633  else if (fwd->request->forcedBodyContinuation /*&& serverState() == fssHandleUploadRequest*/)
634  startDataUpload();
635  else // serverState() == fssHandleUploadRequest
636  forwardPreliminaryReply(&Ftp::Relay::startDataUpload);
637  } else
638  forwardReply();
639 }
640 
641 bool
643 {
644  if (!fwd->request->clientConnectionManager->port->ftp_track_dirs)
645  return false;
646 
647  debugs(9, 5, "start directory tracking");
648  savedReply.message = ctrl.message;
649  savedReply.lastCommand = ctrl.last_command;
650  savedReply.lastReply = ctrl.last_reply;
651  savedReply.replyCode = ctrl.replycode;
652 
653  ctrl.last_command = NULL;
654  ctrl.last_reply = NULL;
655  ctrl.message = NULL;
656  ctrl.offset = 0;
657  writeCommand("PWD\r\n");
658  return true;
659 }
660 
661 void
663 {
664  debugs(9, 5, "got code from pwd: " << ctrl.replycode << ", msg: " << ctrl.last_reply);
665 
666  if (ctrl.replycode == 257)
667  updateMaster().workingDir = Ftp::UnescapeDoubleQuoted(ctrl.last_reply);
668 
669  wordlistDestroy(&ctrl.message);
670  safe_free(ctrl.last_command);
671  safe_free(ctrl.last_reply);
672 
673  ctrl.message = savedReply.message;
674  ctrl.last_command = savedReply.lastCommand;
675  ctrl.last_reply = savedReply.lastReply;
676  ctrl.replycode = savedReply.replyCode;
677 
678  savedReply.message = NULL;
679  savedReply.lastReply = NULL;
680  savedReply.lastCommand = NULL;
681 }
682 
683 void
685 {
686  assert(serverState() == fssHandleCwd ||
687  serverState() == fssHandleCdup);
688 
689  debugs(9, 5, "got code " << ctrl.replycode << ", msg: " << ctrl.last_reply);
690 
691  if (Is1xx(ctrl.replycode))
692  return;
693 
694  if (weAreTrackingDir()) { // we are tracking
695  stopDirTracking(); // and forward the delayed response below
696  } else if (startDirTracking())
697  return;
698 
699  forwardReply();
700 }
701 
702 void
704 {
705  if (Is1xx(ctrl.replycode))
706  return; //Just ignore
707 
708  if (weAreTrackingDir()) { // we are tracking
709  stopDirTracking(); // and forward the delayed response below
710  } else if (ctrl.replycode == 230) { // successful login
711  if (startDirTracking())
712  return;
713  }
714 
715  forwardReply();
716 }
717 
718 void
720 {
721  debugs(9, 3, status());
722 
723  // RFC 959 says that code 226 may indicate a successful response to a file
724  // transfer and file abort commands, but since we do not send abort
725  // commands, let's assume it was a successful file transfer.
726  if (ctrl.replycode == 226 || ctrl.replycode == 250) {
727  markParsedVirginReplyAsWhole("Ftp::Relay::readTransferDoneReply() code 226 or 250");
728  } else {
729  debugs(9, DBG_IMPORTANT, "got FTP code " << ctrl.replycode <<
730  " after reading response data");
731  }
732 
733  debugs(9, 2, "Complete data downloading");
734 
735  serverComplete();
736 }
737 
738 void
740 {
741  debugs(9, 3, status());
742  dataConnWait.finish();
743 
744  if (io.flag != Comm::OK) {
745  debugs(9, 2, "failed to connect FTP server data channel");
746  forwardError(ERR_CONNECT_FAIL, io.xerrno);
747  return;
748  }
749 
750  debugs(9, 2, "connected FTP server data channel: " << io.conn);
751 
752  data.opened(io.conn, dataCloser());
753 
754  sendCommand();
755 }
756 
757 void
759 {
761 }
762 
763 bool
764 Ftp::Relay::abortOnData(const char *reason)
765 {
766  debugs(9, 3, "aborting transaction for " << reason <<
767  "; FD " << (ctrl.conn != NULL ? ctrl.conn->fd : -1) << ", Data FD " << (data.conn != NULL ? data.conn->fd : -1) << ", this " << this);
768  // this method is only called to handle data connection problems
769  // the control connection should keep going
770 
771 #if USE_ADAPTATION
772  if (adaptedBodySource != NULL)
773  stopConsumingFrom(adaptedBodySource);
774 #endif
775 
776  if (Comm::IsConnOpen(data.conn))
777  dataComplete();
778 
779  return !Comm::IsConnOpen(ctrl.conn);
780 }
781 
782 void
784 {
785  if (originWaitInProgress) {
786  CbcPointer<ConnStateData> &mgr = fwd->request->clientConnectionManager;
787  if (mgr.valid()) {
788  if (Ftp::Server *srv = dynamic_cast<Ftp::Server*>(mgr.get())) {
789  typedef UnaryMemFunT<Ftp::Server, int> CbDialer;
790  AsyncCall::Pointer call = asyncCall(11, 3, "Ftp::Server::stopWaitingForOrigin",
791  CbDialer(srv, &Ftp::Server::stopWaitingForOrigin, code));
792  ScheduleCallHere(call);
793  }
794  }
795  originWaitInProgress = false;
796  }
797 }
798 
799 void
801 {
802  debugs(9, 2, "Client Data connection closed!");
803  if (Comm::IsConnOpen(ftpClient->data.conn))
804  ftpClient->dataComplete();
805 }
806 
807 void
808 Ftp::StartRelay(FwdState *const fwdState)
809 {
810  AsyncJob::Start(new Ftp::Relay(fwdState));
811 }
812 
int replyCode
the reply status
Definition: FtpRelay.cc:112
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
@ fssHandleCdup
Definition: FtpServer.h:34
void startDataUpload()
Definition: FtpRelay.cc:470
void readFeatReply()
Definition: FtpRelay.cc:585
StoreEntry * entry
Definition: Client.h:168
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
@ ERR_READ_ERROR
Definition: forward.h:28
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
bool Is1xx(const int sc)
whether this is an informational 1xx response status code
Definition: Elements.h:53
void releaseRequest(const bool shareable=false)
Definition: store.cc:472
virtual void swanSong()
Definition: Client.cc:69
HttpHeader header
Definition: Message.h:75
virtual bool abortOnData(const char *reason)
Definition: FtpRelay.cc:764
Transaction information shared among our FTP client and server jobs.
Definition: FtpServer.h:42
@ fssHandleUploadRequest
Definition: FtpServer.h:29
const char *const crlf
Definition: FtpClient.cc:38
@ fssBegin
Definition: FtpServer.h:23
#define ScheduleCallHere(call)
Definition: AsyncCall.h:166
virtual void handleRequestBodyProducerAborted()=0
Definition: Client.cc:352
void error(char *format,...)
Ftp::MasterState & updateMaster()
Definition: FtpRelay.cc:235
@ fssHandleCwd
Definition: FtpServer.h:32
Definition: SBuf.h:87
virtual void sendControlMsg(HttpControlMsg)
called to send the 1xx message and notify the Source
static const SM_FUNC SM_FUNCS[]
Definition: FtpRelay.cc:83
void sendCommand()
Definition: FtpRelay.cc:514
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.
Definition: Elements.cc:30
const Ftp::MasterState & master() const
A const variant of updateMaster().
Definition: FtpRelay.cc:251
bool originWaitInProgress
Definition: FtpRelay.cc:106
void startDataDownload()
Definition: FtpRelay.cc:452
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
@ OK
Definition: Flag.h:16
virtual void failed(err_type error=ERR_NONE, int xerrno=0, ErrorState *ftperr=nullptr)
handle a fatal transaction error, closing the control connection
Definition: FtpClient.cc:260
SBuf & Printf(const char *fmt,...)
Definition: SBuf.cc:214
bool forwardingCompleted
completeForwarding() has been called
Definition: FtpRelay.cc:102
@ ERR_NONE
Definition: forward.h:15
StatusCode
Definition: StatusCode.h:20
err_type
Definition: forward.h:14
ServerState
Definition: FtpServer.h:22
#define DBG_IMPORTANT
Definition: Debug.h:41
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Definition: CommCalls.h:88
char * lastCommand
the command caused the reply
Definition: FtpRelay.cc:110
void serverComplete()
Definition: Client.cc:181
FTP client functionality shared among FTP Gateway and Relay clients.
Definition: FtpClient.h:111
Definition: forward.h:28
void scheduleReadControlReply()
Definition: FtpRelay.cc:758
virtual void completeForwarding()
Definition: Client.cc:231
@ ENTRY_ABORTED
Definition: enums.h:115
virtual bool mayReadVirginReplyBody() const
whether we may receive more virgin response body bytes
Definition: FtpRelay.cc:374
static void HandleStoreAbort(Relay *)
called by Store if the entry is no longer usable
Definition: FtpRelay.cc:800
void stopOriginWait(int code)
Inform Ftp::Server that we are done if originWaitInProgress.
Definition: FtpRelay.cc:783
UnaryCbdataDialer< Argument1 > cbdataDialer(typename UnaryCbdataDialer< Argument1 >::Handler *handler, Argument1 *arg1)
virtual void start()
called by AsyncStart; do not call directly
Definition: FtpClient.cc:213
@ fssConnected
Definition: FtpServer.h:24
parameters for the async notePinnedConnectionBecameIdle() call
Definition: client_side.h:184
void readCwdOrCdupReply()
Definition: FtpRelay.cc:684
#define NULL
Definition: types.h:166
virtual void handleRequestBodyProducerAborted()
Definition: FtpRelay.cc:366
void readDataReply()
Definition: FtpRelay.cc:625
HttpReply * createHttpReply(const Http::StatusCode httpStatus, const int64_t clen=0)
Definition: FtpRelay.cc:433
virtual void handleControlReply()
Definition: FtpClient.cc:417
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
bundles HTTP 1xx reply and the "successfully forwarded" callback
static ErrorDetail::Pointer NewIfAny(const int errorNo)
void readEpsvReply()
Definition: FtpRelay.cc:610
CBDATA_NAMESPACED_CLASS_INIT(Ftp, Relay)
virtual void processReplyBody()
Definition: FtpRelay.cc:306
void dataComplete()
Definition: FtpClient.cc:1008
void handleDataRequest()
Definition: FtpRelay.cc:445
virtual void handleControlReply()
Definition: FtpRelay.cc:348
bool startDirTracking()
Definition: FtpRelay.cc:642
#define EBIT_TEST(flag, bit)
Definition: defines.h:69
unsigned char code
Definition: html_quote.c:20
@ fssHandlePort
Definition: FtpServer.h:27
void stopDirTracking()
Definition: FtpRelay.cc:662
void scheduleReadControlReply(int buffered_ok)
Definition: FtpClient.cc:323
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
#define safe_free(x)
Definition: xalloc.h:73
@ srcFtp
ftp_port or FTP server
Definition: Message.h:40
void stopWaitingForOrigin(int status)
Definition: FtpServer.cc:1763
#define assert(EX)
Definition: assert.h:19
char const * termedBuf() const
Definition: SquidString.h:92
@ scContinue
Definition: StatusCode.h:22
SBuf httpHeaderQuoteString(const char *raw)
quotes string using RFC 7230 quoted-string rules
char * lastReply
last line of reply: reply status plus message
Definition: FtpRelay.cc:111
const char * UnescapeDoubleQuoted(const char *quotedPath)
parses an FTP-quoted quote-escaped path
Definition: Parsing.cc:90
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:87
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
Definition: AsyncJobCalls.h:69
@ fssHandlePasv
Definition: FtpServer.h:26
Comm::ConnectionPointer conn
channel descriptor
Definition: FtpClient.h:58
const char * c_str()
Definition: SBuf.cc:516
void readTransferDoneReply()
Definition: FtpRelay.cc:719
void readReply()
Definition: FtpRelay.cc:573
Manages a control connection from an FTP client.
Definition: FtpServer.h:58
void forwardError(err_type error=ERR_NONE, int xerrno=0)
Definition: FtpRelay.cc:427
#define xfree
void forwardPreliminaryReply(const PreliminaryCb cb)
Definition: FtpRelay.cc:396
DataChannel data
FTP data channel state.
Definition: FtpClient.h:143
wordlist * next
Definition: wordlist.h:33
Relay(FwdState *const fwdState)
Definition: FtpRelay.cc:151
@ fssHandleEpsv
Definition: FtpServer.h:31
uint32_t sources
The message sources.
Definition: Message.h:100
@ fssHandlePass
Definition: FtpServer.h:33
virtual void dataChannelConnected(const CommConnectCbParams &io)
Definition: FtpRelay.cc:739
void readGreeting()
Definition: FtpRelay.cc:486
@ fssError
Definition: FtpServer.h:35
void readUserOrPassReply()
Definition: FtpRelay.cc:703
HttpHeaderEntry * findEntry(Http::HdrType id) const
Definition: HttpHeader.cc:630
virtual void completeForwarding()
Definition: FtpRelay.cc:274
virtual void serverComplete()
Definition: FtpRelay.cc:207
void StartRelay(FwdState *const fwdState)
A new FTP Relay job.
Definition: FtpRelay.cc:808
@ scNoContent
Definition: StatusCode.h:30
ServerState serverState
what our FTP server is doing
Definition: FtpServer.h:50
int has(Http::HdrType id) const
Definition: HttpHeader.cc:990
void putStr(Http::HdrType id, const char *str)
Definition: HttpHeader.cc:1051
size_type size() const
Definition: SquidString.h:73
@ ERR_CONNECT_FAIL
Definition: forward.h:30
Ftp::ServerState serverState() const
Definition: FtpRelay.cc:46
@ fssHandleEprt
Definition: FtpServer.h:30
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
void failedErrorMessage(err_type error, int xerrno)
Definition: FtpRelay.cc:297
PreliminaryCb thePreliminaryCb
Definition: FtpRelay.cc:80
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
struct Ftp::Relay::@41 savedReply
set and delayed while we are tracking using PWD
ssize_t mb_size_t
Definition: MemBuf.h:17
@ fssHandleDataRequest
Definition: FtpServer.h:28
bool weAreTrackingDir() const
Definition: FtpRelay.cc:75
void readPasvReply()
Definition: FtpRelay.cc:596
virtual void failed(err_type error=ERR_NONE, int xerrno=0, ErrorState *ftperr=nullptr)
handle a fatal transaction error, closing the control connection
Definition: FtpRelay.cc:284
@ scOkay
Definition: StatusCode.h:26
void registerAbortCallback(const AsyncCall::Pointer &)
notify the StoreEntry writer of a 3rd-party initiated StoreEntry abort
Definition: store.cc:1498
void proceedAfterPreliminaryReply()
Definition: FtpRelay.cc:416
#define false
Definition: GnuRegex.c:233
virtual void start()
called by AsyncStart; do not call directly
Definition: FtpRelay.cc:186
wordlist * message
reply message, one wordlist entry per message line
Definition: FtpRelay.cc:109
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void startWaitingForOrigin()
Definition: FtpServer.cc:1753
void forwardReply()
Definition: FtpRelay.cc:381
void unpinConnection(const bool andClose)
Undo pinConnection() and, optionally, close the pinned connection.
CBDATA_CLASS(Relay)
void(Relay::* PreliminaryCb)()
Definition: FtpRelay.cc:77
virtual ~Relay()
Definition: FtpRelay.cc:170
@ fssHandleFeat
Definition: FtpServer.h:25
void(Relay::* SM_FUNC)()
Definition: FtpRelay.cc:82
virtual void swanSong()
Definition: FtpRelay.cc:198
static void Start(const Pointer &job)
Definition: AsyncJob.cc:24
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:63

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors