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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors