tunnel.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 26 Secure Sockets Layer Proxy */
10 
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "base/CbcPointer.h"
14 #include "base/JobWait.h"
15 #include "CachePeer.h"
16 #include "cbdata.h"
17 #include "client_side.h"
18 #include "client_side_request.h"
19 #include "clients/HttpTunneler.h"
20 #include "comm.h"
21 #include "comm/Connection.h"
22 #include "comm/ConnOpener.h"
23 #include "comm/Read.h"
24 #include "comm/Write.h"
25 #include "errorpage.h"
26 #include "fd.h"
27 #include "fde.h"
28 #include "FwdState.h"
29 #include "globals.h"
30 #include "HappyConnOpener.h"
31 #include "http.h"
32 #include "http/Stream.h"
33 #include "HttpRequest.h"
34 #include "icmp/net_db.h"
35 #include "ip/QosConfig.h"
36 #include "LogTags.h"
37 #include "MemBuf.h"
38 #include "neighbors.h"
39 #include "PeerSelectState.h"
40 #include "ResolvedPeers.h"
41 #include "sbuf/SBuf.h"
43 #include "SquidConfig.h"
44 #include "SquidTime.h"
45 #include "StatCounters.h"
46 #if USE_OPENSSL
47 #include "ssl/bio.h"
48 #include "ssl/ServerBump.h"
49 #endif
50 #include "tools.h"
51 #include "tunnel.h"
52 #if USE_DELAY_POOLS
53 #include "DelayId.h"
54 #endif
55 
56 #include <climits>
57 #include <cerrno>
58 
64 /*
65  * TODO 1: implement a read/write API on ConnStateData to send/receive blocks
66  * of pre-formatted data. Then we can use that as the client side of the tunnel
67  * instead of re-implementing it here and occasionally getting the ConnStateData
68  * read/write state wrong.
69  *
70  * TODO 2: then convert this into a AsyncJob, possibly a child of 'Server'
71  */
73 {
75 
76 public:
78  virtual ~TunnelStateData();
79  TunnelStateData(const TunnelStateData &); // do not implement
80  TunnelStateData &operator =(const TunnelStateData &); // do not implement
81 
82  class Connection;
83  static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
84  static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
85  static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
86  static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
87 
88  bool noConnections() const;
90  void closeConnections();
91 
92  char *url;
96 
97  const char * getHost() const {
98  return (server.conn != NULL && server.conn->getPeer() ? server.conn->getPeer()->host : request->url.host());
99  };
100 
103  // If we are forcing a tunnel after receiving a client CONNECT, then we
104  // have already responded to that CONNECT before tunnel.cc started.
106  return false;
107 #if USE_OPENSSL
108  // We are bumping and we had already send "OK CONNECTED"
109  if (http.valid() && http->getConn() && http->getConn()->serverBump() && http->getConn()->serverBump()->at(XactionStep::tlsBump2, XactionStep::tlsBump3))
110  return false;
111 #endif
112  return !(request != NULL &&
114  }
115 
118  void startConnecting();
119  void closePendingConnection(const Comm::ConnectionPointer &conn, const char *reason);
120 
123 
125  {
126 
127  public:
128  Connection() : len (0), buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), delayedLoops(0),
129  dirty(false),
131 
132  ~Connection();
133 
135  template <typename Method>
136  void initConnection(const Comm::ConnectionPointer &aConn, Method method, const char *name, TunnelStateData *tunnelState);
137 
139  void noteClosure();
140 
141  int bytesWanted(int lower=0, int upper = INT_MAX) const;
142  void bytesIn(int const &);
143 #if USE_DELAY_POOLS
144 
145  void setDelayId(DelayId const &);
146 #endif
147 
148  void error(int const xerrno);
149  int debugLevelForError(int const xerrno) const;
150 
151  void dataSent (size_t amount);
153  void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func);
154  int len;
155  char *buf;
157  uint64_t *size_ptr; /* pointer to size in an ConnStateData for logging */
158 
160  uint8_t delayedLoops;
161 
162  bool dirty;
163 
164  // XXX: make these an AsyncCall when event API can handle them
167 
168 #if USE_DELAY_POOLS
169 
171 #endif
172 
173  private:
176  };
177 
179  int *status_ptr;
180 
183  time_t startTime;
186  bool retriable;
189  // TODO: remove after fixing deferred reads in TunnelStateData::copyRead()
191 
194 
197 
201 
202  void copyRead(Connection &from, IOCB *completion);
203 
207 
208  /* PeerSelectionInitiator API */
209  virtual void noteDestination(Comm::ConnectionPointer conn) override;
210  virtual void noteDestinationsEnd(ErrorState *selectionError) override;
211 
212  void syncHierNote(const Comm::ConnectionPointer &server, const char *origin);
213 
217 
219  void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused);
220 
221  void notifyConnOpener();
222 
223  void saveError(ErrorState *finalError);
224  void sendError(ErrorState *finalError, const char *reason);
225 
226 private:
229  {
230  public:
232 
234  method_(method), tunnel_(tunnel), answer_() {}
235 
236  /* CallDialer API */
237  virtual bool canDial(AsyncCall &) { return tunnel_.valid(); }
238  void dial(AsyncCall &) { ((&(*tunnel_))->*method_)(answer_); }
239  virtual void print(std::ostream &os) const {
240  os << '(' << tunnel_.get() << ", " << answer_ << ')';
241  }
242 
243  /* Security::PeerConnector::CbDialer API */
244  virtual Security::EncryptorAnswer &answer() { return answer_; }
245 
246  private:
250  };
251 
252  void usePinned();
253 
256 
260 
261  template <typename StepStart>
262  void advanceDestination(const char *stepDescription, const Comm::ConnectionPointer &conn, const StepStart &startStep);
263 
265  const char *checkRetry();
268  bool usingDestination() const;
269 
271  ErrorState *savedError = nullptr;
272 
275 
276  void deleteThis();
277 
278  void cancelStep(const char *reason);
279 
280 public:
281  bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to);
282  void copy(size_t len, Connection &from, Connection &to, IOCB *);
283  void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno);
284  void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno);
285  void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
286  void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
287 
288  void copyClientBytes();
289  void copyServerBytes();
290 
292  void clientClosed();
293 
295  void serverClosed();
296 
299  void retryOrBail(const char *context);
300 };
301 
308 
310 static void
312 {
313  const auto tunnelState = reinterpret_cast<TunnelStateData *>(params.data);
314  tunnelState->serverClosed();
315 }
316 
317 void
319 {
321 }
322 
324 static void
326 {
327  const auto tunnelState = reinterpret_cast<TunnelStateData *>(params.data);
328  tunnelState->clientClosed();
329 }
330 
331 void
333 {
335 
336  if (noConnections())
337  return deleteThis();
338 
339  if (!server.writer)
340  server.conn->close();
341 }
342 
344 void
346 {
348  // ConnStateData pipeline should contain the CONNECT we are performing
349  // but it may be invalid already (bug 4392)
350  if (const auto h = http.valid()) {
351  if (const auto c = h->getConn())
352  if (const auto ctx = c->pipeline.front())
353  ctx->finished();
354  }
355  delete this;
356 }
357 
359  startTime(squid_curtime),
360  destinations(new ResolvedPeers()),
361  destinationsFound(false),
362  retriable(true),
363  codeContext(CodeContext::Current())
364 {
365  debugs(26, 3, "TunnelStateData constructed this=" << this);
368 
369  assert(clientRequest);
370  url = xstrdup(clientRequest->uri);
371  request = clientRequest->request;
372  Must(request);
373  server.size_ptr = &clientRequest->out.size;
374  client.size_ptr = &clientRequest->al->http.clientRequestSz.payloadData;
375  status_ptr = &clientRequest->al->http.code;
376  al = clientRequest->al;
377  http = clientRequest;
378 
379  client.initConnection(clientRequest->getConn()->clientConnection, tunnelClientClosed, "tunnelClientClosed", this);
380 
381  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
384 }
385 
387 {
388  debugs(26, 3, "TunnelStateData destructed this=" << this);
390  xfree(url);
391  cancelStep("~TunnelStateData");
392  delete savedError;
393 }
394 
396 {
397  if (readPending)
399 
400  safe_free(buf);
401 }
402 
403 const char *
405 {
406  if (shutting_down)
407  return "shutting down";
409  return "forwarding timeout";
410  if (!retriable)
411  return "not retriable";
412  if (noConnections())
413  return "no connections";
414  return nullptr;
415 }
416 
417 void
418 TunnelStateData::retryOrBail(const char *context)
419 {
420  // Since no TCP payload has been passed to client or server, we may
421  // TCP-connect to other destinations (including alternate IPs).
422 
423  assert(!server.conn);
424 
425  const auto *bailDescription = checkRetry();
426  if (!bailDescription) {
427  if (!destinations->empty())
428  return startConnecting(); // try connecting to another destination
429 
430  if (subscribed) {
431  debugs(26, 4, "wait for more destinations to try");
432  return; // expect a noteDestination*() call
433  }
434 
435  // fall through to bail
436  }
437 
438  /* bail */
439 
440  if (request)
441  request->hier.stopPeerClock(false);
442 
443  // TODO: Add sendSavedErrorOr(err_type type, Http::StatusCode, context).
444  // Then, the remaining method code (below) should become the common part of
445  // sendNewError() and sendSavedErrorOr(), used in "error detected" cases.
446  if (!savedError)
448  const auto canSendError = Comm::IsConnOpen(client.conn) && !client.dirty &&
450  if (canSendError)
451  return sendError(savedError, bailDescription ? bailDescription : context);
453 
454  if (noConnections())
455  return deleteThis();
456 
457  // This is a "Comm::IsConnOpen(client.conn) but !canSendError" case.
458  // Closing the connection (after finishing writing) is the best we can do.
459  if (!client.writer)
460  client.conn->close();
461  // else writeClientDone() must notice a closed server and close the client
462 }
463 
464 int
465 TunnelStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
466 {
467 #if USE_DELAY_POOLS
468  return delayId.bytesWanted(lowerbound, upperbound);
469 #else
470  (void)lowerbound;
471  return upperbound;
472 #endif
473 }
474 
475 void
477 {
478  debugs(26, 3, HERE << "len=" << len << " + count=" << count);
479 #if USE_DELAY_POOLS
480  delayId.bytesIn(count);
481 #endif
482 
483  len += count;
484 }
485 
488 void
490 {
491  request->hier.resetPeerNotes(conn, origin);
492  al->hier.resetPeerNotes(conn, origin);
493 }
494 
495 int
497 {
498 #ifdef ECONNRESET
499 
500  if (xerrno == ECONNRESET)
501  return 2;
502 
503 #endif
504 
505  if (ignoreErrno(xerrno))
506  return 3;
507 
508  return 1;
509 }
510 
511 /* Read from server side and queue it for writing to the client */
512 void
513 TunnelStateData::ReadServer(const Comm::ConnectionPointer &c, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
514 {
515  TunnelStateData *tunnelState = (TunnelStateData *)data;
516  assert(cbdataReferenceValid(tunnelState));
517  debugs(26, 3, HERE << c);
518 
519  tunnelState->readServer(buf, len, errcode, xerrno);
520 }
521 
522 void
523 TunnelStateData::readServer(char *, size_t len, Comm::Flag errcode, int xerrno)
524 {
525  debugs(26, 3, HERE << server.conn << ", read " << len << " bytes, err=" << errcode);
527 
528  /*
529  * Bail out early on Comm::ERR_CLOSING
530  * - close handlers will tidy up for us
531  */
532 
533  if (errcode == Comm::ERR_CLOSING)
534  return;
535 
536  if (len > 0) {
537  server.bytesIn(len);
538  statCounter.server.all.kbytes_in += len;
539  statCounter.server.other.kbytes_in += len;
541  }
542 
543  if (keepGoingAfterRead(len, errcode, xerrno, server, client))
545 }
546 
547 void
549 {
550  debugs(50, debugLevelForError(xerrno), HERE << conn << ": read/write failure: " << xstrerr(xerrno));
551 
552  if (!ignoreErrno(xerrno))
553  conn->close();
554 }
555 
556 /* Read from client side and queue it for writing to the server */
557 void
558 TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
559 {
560  TunnelStateData *tunnelState = (TunnelStateData *)data;
561  assert (cbdataReferenceValid (tunnelState));
562 
563  tunnelState->readClient(buf, len, errcode, xerrno);
564 }
565 
566 void
567 TunnelStateData::readClient(char *, size_t len, Comm::Flag errcode, int xerrno)
568 {
569  debugs(26, 3, HERE << client.conn << ", read " << len << " bytes, err=" << errcode);
571 
572  /*
573  * Bail out early on Comm::ERR_CLOSING
574  * - close handlers will tidy up for us
575  */
576 
577  if (errcode == Comm::ERR_CLOSING)
578  return;
579 
580  if (len > 0) {
581  client.bytesIn(len);
583  }
584 
585  if (keepGoingAfterRead(len, errcode, xerrno, client, server))
587 }
588 
591 bool
592 TunnelStateData::keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to)
593 {
594  debugs(26, 3, HERE << "from={" << from.conn << "}, to={" << to.conn << "}");
595 
596  /* I think this is to prevent free-while-in-a-callback behaviour
597  * - RBC 20030229
598  * from.conn->close() / to.conn->close() done here trigger close callbacks which may free TunnelStateData
599  */
600  const CbcPointer<TunnelStateData> safetyLock(this);
601 
602  /* Bump the source connection read timeout on any activity */
603  if (Comm::IsConnOpen(from.conn)) {
604  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
606  commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
607  }
608 
609  /* Bump the dest connection read timeout on any activity */
610  /* see Bug 3659: tunnels can be weird, with very long one-way transfers */
611  if (Comm::IsConnOpen(to.conn)) {
612  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
614  commSetConnTimeout(to.conn, Config.Timeout.read, timeoutCall);
615  }
616 
617  if (errcode)
618  from.error (xerrno);
619  else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
620  debugs(26, 3, HERE << "Nothing to write or client gone. Terminate the tunnel.");
621  from.conn->close();
622 
623  /* Only close the remote end if we've finished queueing data to it */
624  if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
625  to.conn->close();
626  }
627  } else if (cbdataReferenceValid(this)) {
628  return true;
629  }
630 
631  return false;
632 }
633 
634 void
635 TunnelStateData::copy(size_t len, Connection &from, Connection &to, IOCB *completion)
636 {
637  debugs(26, 3, HERE << "Schedule Write");
638  AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler",
639  CommIoCbPtrFun(completion, this));
640  to.write(from.buf, len, call, NULL);
641 }
642 
643 /* Writes data from the client buffer to the server side */
644 void
645 TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
646 {
647  TunnelStateData *tunnelState = (TunnelStateData *)data;
648  assert (cbdataReferenceValid (tunnelState));
649  tunnelState->server.writer = NULL;
650 
651  tunnelState->writeServerDone(buf, len, flag, xerrno);
652 }
653 
654 void
655 TunnelStateData::writeServerDone(char *, size_t len, Comm::Flag flag, int xerrno)
656 {
657  debugs(26, 3, HERE << server.conn << ", " << len << " bytes written, flag=" << flag);
658 
659  if (flag == Comm::ERR_CLOSING)
660  return;
661 
663 
664  /* Error? */
665  if (flag != Comm::OK) {
666  debugs(26, 4, "to-server write failed: " << xerrno);
667  server.error(xerrno); // may call comm_close
668  return;
669  }
670 
671  /* EOF? */
672  if (len == 0) {
673  debugs(26, 4, HERE << "No read input. Closing server connection.");
674  server.conn->close();
675  return;
676  }
677 
678  /* Valid data */
679  statCounter.server.all.kbytes_out += len;
680  statCounter.server.other.kbytes_out += len;
681  client.dataSent(len);
682 
683  /* If the other end has closed, so should we */
684  if (!Comm::IsConnOpen(client.conn)) {
685  debugs(26, 4, HERE << "Client gone away. Shutting down server connection.");
686  server.conn->close();
687  return;
688  }
689 
690  const CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
691 
692  if (cbdataReferenceValid(this))
693  copyClientBytes();
694 }
695 
696 /* Writes data from the server buffer to the client side */
697 void
698 TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
699 {
700  TunnelStateData *tunnelState = (TunnelStateData *)data;
701  assert (cbdataReferenceValid (tunnelState));
702  tunnelState->client.writer = NULL;
703 
704  tunnelState->writeClientDone(buf, len, flag, xerrno);
705 }
706 
707 void
709 {
710  debugs(26, 3, HERE << "len=" << len << " - amount=" << amount);
711  assert(amount == (size_t)len);
712  len =0;
713  /* increment total object size */
714 
715  if (size_ptr)
716  *size_ptr += amount;
717 
718 }
719 
720 void
721 TunnelStateData::Connection::write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func)
722 {
723  writer = callback;
724  dirty = true;
725  Comm::Write(conn, b, size, callback, free_func);
726 }
727 
728 template <typename Method>
729 void
731 {
733  Must(!closer);
734  Must(Comm::IsConnOpen(aConn));
735  conn = aConn;
736  closer = commCbCall(5, 4, name, CommCloseCbPtrFun(method, tunnelState));
737  comm_add_close_handler(conn->fd, closer);
738 }
739 
740 void
742 {
743  debugs(26, 3, conn);
744  conn = nullptr;
745  closer = nullptr;
746  writer = nullptr; // may already be nil
747 }
748 
749 void
750 TunnelStateData::writeClientDone(char *, size_t len, Comm::Flag flag, int xerrno)
751 {
752  debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
753 
754  if (flag == Comm::ERR_CLOSING)
755  return;
756 
757  /* Error? */
758  if (flag != Comm::OK) {
759  debugs(26, 4, "from-client read failed: " << xerrno);
760  client.error(xerrno); // may call comm_close
761  return;
762  }
763 
764  /* EOF? */
765  if (len == 0) {
766  debugs(26, 4, HERE << "Closing client connection due to 0 byte read.");
767  client.conn->close();
768  return;
769  }
770 
771  /* Valid data */
773  server.dataSent(len);
774 
775  /* If the other end has closed, so should we */
776  if (!Comm::IsConnOpen(server.conn)) {
777  debugs(26, 4, HERE << "Server has gone away. Terminating client connection.");
778  client.conn->close();
779  return;
780  }
781 
782  CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
783 
784  if (cbdataReferenceValid(this))
785  copyServerBytes();
786 }
787 
788 static void
790 {
791  TunnelStateData *tunnelState = static_cast<TunnelStateData *>(io.data);
792  debugs(26, 3, HERE << io.conn);
793  /* Temporary lock to protect our own feets (comm_close -> tunnelClientClosed -> Free) */
794  CbcPointer<TunnelStateData> safetyLock(tunnelState);
795 
796  tunnelState->closeConnections();
797 }
798 
799 void
801 {
802  debugs(26, 3, "because " << reason << "; " << conn);
803  assert(!server.conn);
804  if (IsConnOpen(conn))
805  conn->close();
806 }
807 
808 void
810 {
812  server.conn->close();
814  client.conn->close();
815 }
816 
817 static void
819 {
820  if (!data)
821  return;
822 
823  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
824  const auto savedContext = CodeContext::Current();
826  tunnel->client.readPending = NULL;
827  static uint64_t counter=0;
828  debugs(26, 7, "Client read(2) delayed " << ++counter << " times");
829  tunnel->copyRead(tunnel->client, TunnelStateData::ReadClient);
830  CodeContext::Reset(savedContext);
831 }
832 
833 static void
835 {
836  if (!data)
837  return;
838 
839  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
840  const auto savedContext = CodeContext::Current();
842  tunnel->server.readPending = NULL;
843  static uint64_t counter=0;
844  debugs(26, 7, "Server read(2) delayed " << ++counter << " times");
845  tunnel->copyRead(tunnel->server, TunnelStateData::ReadServer);
846  CodeContext::Reset(savedContext);
847 }
848 
849 void
851 {
852  assert(from.len == 0);
853  // If only the minimum permitted read size is going to be attempted
854  // then we schedule an event to try again in a few I/O cycles.
855  // Allow at least 1 byte to be read every (0.3*10) seconds.
856  int bw = from.bytesWanted(1, SQUID_TCP_SO_RCVBUF);
857  // XXX: Delay pools must not delay client-to-Squid traffic (i.e. when
858  // from.readPendingFunc is tunnelDelayedClientRead()).
859  // XXX: Bug #4913: Use DeferredRead instead.
860  if (bw == 1 && ++from.delayedLoops < 10) {
861  from.readPending = this;
862  eventAdd("tunnelDelayedServerRead", from.readPendingFunc, from.readPending, 0.3, true);
863  return;
864  }
865 
866  AsyncCall::Pointer call = commCbCall(5,4, "TunnelBlindCopyReadHandler",
867  CommIoCbPtrFun(completion, this));
868  comm_read(from.conn, from.buf, bw, call);
869 }
870 
871 void
873 {
874  if (preReadClientData.length()) {
875  size_t copyBytes = preReadClientData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadClientData.length();
876  memcpy(client.buf, preReadClientData.rawContent(), copyBytes);
877  preReadClientData.consume(copyBytes);
878  client.bytesIn(copyBytes);
879  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, client, server))
881  } else
883 }
884 
885 void
887 {
888  if (preReadServerData.length()) {
889  size_t copyBytes = preReadServerData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadServerData.length();
890  memcpy(server.buf, preReadServerData.rawContent(), copyBytes);
891  preReadServerData.consume(copyBytes);
892  server.bytesIn(copyBytes);
893  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, server, client))
895  } else
897 }
898 
903 static void
905 {
906  assert(!tunnelState->transportWait);
907  assert(!tunnelState->encryptionWait);
908  assert(!tunnelState->peerWait);
909 
910  assert(tunnelState->server.conn);
911  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
912  CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
913  commSetConnTimeout(tunnelState->server.conn, Config.Timeout.read, timeoutCall);
914 
915  *tunnelState->status_ptr = Http::scOkay;
916  tunnelState->al->cache.code.update(LOG_TCP_TUNNEL);
917  if (cbdataReferenceValid(tunnelState)) {
918 
919  // Shovel any payload already pushed into reply buffer by the server response
920  if (!tunnelState->server.len)
921  tunnelState->copyServerBytes();
922  else {
923  debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
924  tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
925  }
926 
927  if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->inBuf.isEmpty()) {
928  SBuf * const in = &tunnelState->http->getConn()->inBuf;
929  debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << *in << "\n----------");
930  tunnelState->preReadClientData.append(*in);
931  in->consume(); // ConnStateData buffer accounting after the shuffle.
932  }
933  tunnelState->copyClientBytes();
934  }
935 }
936 
942 static void
943 tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
944 {
945  TunnelStateData *tunnelState = (TunnelStateData *)data;
946  debugs(26, 3, HERE << conn << ", flag=" << flag);
947  tunnelState->client.writer = NULL;
948 
949  if (flag != Comm::OK) {
950  *tunnelState->status_ptr = Http::scInternalServerError;
951  tunnelErrorComplete(conn->fd, data, 0);
952  return;
953  }
954 
955  if (auto http = tunnelState->http.get()) {
956  http->out.headers_sz += len;
957  http->out.size += len;
958  }
959 
960  tunnelStartShoveling(tunnelState);
961 }
962 
963 void
965 {
966  peerWait.finish();
967  server.len = 0;
968 
970 
971  if (answer.peerResponseStatus != Http::scNone)
972  *status_ptr = answer.peerResponseStatus;
973 
974  auto sawProblem = false;
975 
976  if (!answer.positive()) {
977  sawProblem = true;
978  assert(!answer.conn);
979  } else if (!Comm::IsConnOpen(answer.conn) || fd_table[answer.conn->fd].closing()) {
980  sawProblem = true;
981  closePendingConnection(answer.conn, "conn was closed while waiting for tunnelEstablishmentDone");
982  }
983 
984  if (!sawProblem) {
985  assert(answer.positive()); // paranoid
986  // copy any post-200 OK bytes to our buffer
987  preReadServerData = answer.leftovers;
988  notePeerReadyToShovel(answer.conn);
989  return;
990  }
991 
992  ErrorState *error = nullptr;
993  if (answer.positive()) {
995  } else {
996  error = answer.squidError.get();
997  Must(error);
998  answer.squidError.clear(); // preserve error for errorSendComplete()
999  }
1000  assert(error);
1001  saveError(error);
1002  retryOrBail("tunneler error");
1003 }
1004 
1005 void
1007 {
1008  assert(!client.dirty);
1009  retriable = false;
1010  server.initConnection(conn, tunnelServerClosed, "tunnelServerClosed", this);
1011 
1013  tunnelStartShoveling(this); // ssl-bumped connection, be quiet
1014  else {
1016  AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
1019  const auto mb = al->reply->pack();
1020  client.write(mb->content(), mb->contentSize(), call, mb->freeFunc());
1021  delete mb;
1022  }
1023 }
1024 
1025 static void
1026 tunnelErrorComplete(int fd/*const Comm::ConnectionPointer &*/, void *data, size_t)
1027 {
1028  TunnelStateData *tunnelState = (TunnelStateData *)data;
1029  debugs(26, 3, HERE << "FD " << fd);
1030  assert(tunnelState != NULL);
1031  /* temporary lock to save our own feets (comm_close -> tunnelClientClosed -> Free) */
1032  CbcPointer<TunnelStateData> safetyLock(tunnelState);
1033 
1034  if (Comm::IsConnOpen(tunnelState->client.conn))
1035  tunnelState->client.conn->close();
1036 
1037  if (Comm::IsConnOpen(tunnelState->server.conn))
1038  tunnelState->server.conn->close();
1039 }
1040 
1041 void
1043 {
1044  transportWait.finish();
1045 
1046  ErrorState *error = nullptr;
1047  if ((error = answer.error.get())) {
1048  Must(!Comm::IsConnOpen(answer.conn));
1049  syncHierNote(answer.conn, request->url.host());
1050  answer.error.clear();
1051  } else if (!Comm::IsConnOpen(answer.conn) || fd_table[answer.conn->fd].closing()) {
1053  closePendingConnection(answer.conn, "conn was closed while waiting for noteConnection");
1054  }
1055 
1056  if (error) {
1057  saveError(error);
1058  retryOrBail("tried all destinations");
1059  return;
1060  }
1061 
1062  connectDone(answer.conn, request->url.host(), answer.reused);
1063 }
1064 
1065 void
1066 TunnelStateData::connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
1067 {
1069 
1070  if (reused)
1072  // else Comm::ConnOpener already applied proper/current markings
1073 
1074  syncHierNote(conn, origin);
1075 
1076 #if USE_DELAY_POOLS
1077  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
1078  if (conn->getPeer() && conn->getPeer()->options.no_delay)
1080 #endif
1081 
1083 
1084  request->peer_host = conn->getPeer() ? conn->getPeer()->host : nullptr;
1085 
1086  bool toOrigin = false; // same semantics as StateFlags::toOrigin
1087  if (const auto * const peer = conn->getPeer()) {
1088  request->prepForPeering(*peer);
1089  toOrigin = peer->options.originserver;
1090  } else {
1092  toOrigin = true;
1093  }
1094 
1095  if (!toOrigin)
1097  else {
1099  }
1100 }
1101 
1102 void
1104 {
1105  debugs(26, 3, HERE);
1106  /* Create state structure. */
1107  TunnelStateData *tunnelState = NULL;
1108  ErrorState *err = NULL;
1110  char *url = http->uri;
1111 
1112  /*
1113  * client_addr.isNoAddr() indicates this is an "internal" request
1114  * from peer_digest.c, asn.c, netdb.c, etc and should always
1115  * be allowed. yuck, I know.
1116  */
1117 
1119  /*
1120  * Check if this host is allowed to fetch MISSES from us (miss_access)
1121  * default is to allow.
1122  */
1124  ch.al = http->al;
1126  ch.my_addr = request->my_addr;
1127  ch.syncAle(request, http->log_uri);
1128  if (ch.fastCheck().denied()) {
1129  debugs(26, 4, HERE << "MISS access forbidden.");
1131  http->al->http.code = Http::scForbidden;
1133  return;
1134  }
1135  }
1136 
1137  debugs(26, 3, request->method << ' ' << url << ' ' << request->http_ver);
1138  ++statCounter.server.all.requests;
1139  ++statCounter.server.other.requests;
1140 
1141  tunnelState = new TunnelStateData(http);
1142 #if USE_DELAY_POOLS
1143  tunnelState->server.setDelayId(DelayId::DelayClient(http));
1144 #endif
1145  tunnelState->startSelectingDestinations(request, http->al, nullptr);
1146 }
1147 
1148 void
1150 {
1151  if (const auto p = conn->getPeer()) {
1152  if (p->secure.encryptTransport)
1153  return advanceDestination("secure connection to peer", conn, [this,&conn] {
1155  });
1156  }
1157 
1159 }
1160 
1162 void
1164 {
1165  AsyncCall::Pointer callback = asyncCall(5,4, "TunnelStateData::noteSecurityPeerConnectorAnswer",
1167  const auto connector = new Security::BlindPeerConnector(request, conn, callback, al);
1168  encryptionWait.start(connector, callback);
1169 }
1170 
1172 template <typename StepStart>
1173 void
1174 TunnelStateData::advanceDestination(const char *stepDescription, const Comm::ConnectionPointer &conn, const StepStart &startStep)
1175 {
1176  // TODO: Extract destination-specific handling from TunnelStateData so that
1177  // all the awkward, limited-scope advanceDestination() calls can be replaced
1178  // with a single simple try/catch,retry block.
1179  try {
1180  startStep();
1181  // now wait for the step callback
1182  } catch (...) {
1183  debugs (26, 2, "exception while trying to " << stepDescription << ": " << CurrentException);
1184  closePendingConnection(conn, "connection preparation exception");
1185  if (!savedError)
1187  retryOrBail(stepDescription);
1188  }
1189 }
1190 
1192 void
1194 {
1195  encryptionWait.finish();
1196 
1197  ErrorState *error = nullptr;
1198  assert(!answer.tunneled);
1199  if ((error = answer.error.get())) {
1200  assert(!answer.conn);
1201  answer.error.clear();
1202  } else if (!Comm::IsConnOpen(answer.conn) || fd_table[answer.conn->fd].closing()) {
1204  closePendingConnection(answer.conn, "conn was closed while waiting for noteSecurityPeerConnectorAnswer");
1205  }
1206 
1207  if (error) {
1208  saveError(error);
1209  retryOrBail("TLS peer connection error");
1210  return;
1211  }
1212 
1213  connectedToPeer(answer.conn);
1214 }
1215 
1216 void
1218 {
1219  advanceDestination("establish tunnel through proxy", conn, [this,&conn] {
1221  });
1222 }
1223 
1224 void
1226 {
1227  AsyncCall::Pointer callback = asyncCall(5,4,
1228  "TunnelStateData::tunnelEstablishmentDone",
1230  const auto tunneler = new Http::Tunneler(conn, request, callback, Config.Timeout.lifetime, al);
1231 #if USE_DELAY_POOLS
1232  tunneler->setDelayId(server.delayId);
1233 #endif
1234  peerWait.start(tunneler, callback);
1235 }
1236 
1237 void
1239 {
1240  destinationsFound = true;
1241 
1242  if (!path) { // decided to use a pinned connection
1243  // We can call usePinned() without fear of clashing with an earlier
1244  // forwarding attempt because PINNED must be the first destination.
1246  usePinned();
1247  return;
1248  }
1249 
1250  destinations->addPath(path);
1251 
1252  if (usingDestination()) {
1253  // We are already using a previously opened connection but also
1254  // receiving destinations in case we need to re-forward.
1255  Must(!transportWait);
1256  return;
1257  }
1258 
1259  if (transportWait) {
1260  notifyConnOpener();
1261  return; // and continue to wait for tunnelConnectDone() callback
1262  }
1263 
1264  startConnecting();
1265 }
1266 
1267 void
1269 {
1272  if (!destinationsFound) {
1273 
1274  // XXX: Honor clientExpectsConnectResponse() before replying.
1275 
1276  if (selectionError)
1277  return sendError(selectionError, "path selection has failed");
1278 
1279  if (savedError)
1280  return sendError(savedError, "all found paths have failed");
1281 
1283  "path selection found no paths");
1284  }
1285  // else continue to use one of the previously noted destinations;
1286  // if all of them fail, tunneling as whole will fail
1287  Must(!selectionError); // finding at least one path means selection succeeded
1288 
1289  if (usingDestination()) {
1290  // We are already using a previously opened connection but also
1291  // receiving destinations in case we need to re-forward.
1292  Must(!transportWait);
1293  return;
1294  }
1295 
1296  Must(transportWait); // or we would be stuck with nothing to do or wait for
1297  notifyConnOpener();
1298 }
1299 
1300 bool
1302 {
1304 }
1305 
1307 void
1309 {
1310  debugs(26, 4, savedError << " ? " << error);
1311  assert(error);
1312  delete savedError; // may be nil
1313  savedError = error;
1314 }
1315 
1318 void
1319 TunnelStateData::sendError(ErrorState *finalError, const char *reason)
1320 {
1321  debugs(26, 3, "aborting transaction for " << reason);
1322 
1323  if (request)
1324  request->hier.stopPeerClock(false);
1325 
1326  cancelStep(reason);
1327 
1328  assert(finalError);
1329 
1330  // get rid of any cached error unless that is what the caller is sending
1331  if (savedError != finalError)
1332  delete savedError; // may be nil
1333  savedError = nullptr;
1334 
1335  // we cannot try other destinations after responding with an error
1336  PeerSelectionInitiator::subscribed = false; // may already be false
1337 
1338  *status_ptr = finalError->httpStatus;
1339  finalError->callback = tunnelErrorComplete;
1340  finalError->callback_data = this;
1341  errorSend(client.conn, finalError);
1342 }
1343 
1347 void
1348 TunnelStateData::cancelStep(const char *reason)
1349 {
1350  transportWait.cancel(reason);
1351  encryptionWait.cancel(reason);
1352  peerWait.cancel(reason);
1353 }
1354 
1355 void
1357 {
1358  if (request)
1360 
1361  assert(!destinations->empty());
1363  AsyncCall::Pointer callback = asyncCall(17, 5, "TunnelStateData::noteConnection", HappyConnOpener::CbDialer<TunnelStateData>(&TunnelStateData::noteConnection, this));
1364  const auto cs = new HappyConnOpener(destinations, callback, request, startTime, 0, al);
1365  cs->setHost(request->url.host());
1366  cs->setRetriable(false);
1367  cs->allowPersistent(false);
1368  destinations->notificationPending = true; // start() is async
1369  transportWait.start(cs, callback);
1370 }
1371 
1373 void
1375 {
1376  Must(request);
1377  const auto connManager = request->pinnedConnection();
1378  try {
1379  const auto serverConn = ConnStateData::BorrowPinnedConnection(request.getRaw(), al);
1380  debugs(26, 7, "pinned peer connection: " << serverConn);
1381 
1382  // Set HttpRequest pinned related flags for consistency even if
1383  // they are not really used by tunnel.cc code.
1384  request->flags.pinned = true;
1385  if (connManager->pinnedAuth())
1386  request->flags.auth = true;
1387 
1388  // the server may close the pinned connection before this request
1389  const auto reused = true;
1390  connectDone(serverConn, connManager->pinning.host, reused);
1391  } catch (ErrorState * const error) {
1392  syncHierNote(nullptr, connManager ? connManager->pinning.host : request->url.host());
1393  // XXX: Honor clientExpectsConnectResponse() before replying.
1394  // a PINNED path failure is fatal; do not wait for more paths
1395  sendError(error, "pinned path failure");
1396  return;
1397  }
1398 
1399 }
1400 
1402 
1403 bool
1405 {
1407 }
1408 
1409 #if USE_DELAY_POOLS
1410 void
1412 {
1413  delayId = newDelay;
1414 }
1415 
1416 #endif
1417 
1419 void
1421 {
1423  debugs(17, 7, "reusing pending notification");
1424  } else {
1426  CallJobHere(17, 5, transportWait.job(), HappyConnOpener, noteCandidatesChange);
1427  }
1428 }
1429 
1437 void
1439 {
1440  Must(Comm::IsConnOpen(clientConn));
1441  Must(Comm::IsConnOpen(srvConn));
1442 
1443  debugs(26,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << srvConn->fd);
1444 
1445  /* Create state structure. */
1446  ++statCounter.server.all.requests;
1447  ++statCounter.server.other.requests;
1448 
1450  Must(conn);
1451  Http::StreamPointer context = conn->pipeline.front();
1452  Must(context && context->http);
1453 
1454  debugs(26, 3, request->method << " " << context->http->uri << " " << request->http_ver);
1455 
1456  TunnelStateData *tunnelState = new TunnelStateData(context->http);
1457  tunnelState->retriable = false;
1458 
1459  request->hier.resetPeerNotes(srvConn, tunnelState->getHost());
1460 
1461  tunnelState->server.initConnection(srvConn, tunnelServerClosed, "tunnelServerClosed", tunnelState);
1462 
1463 #if USE_DELAY_POOLS
1464  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
1465  if (!srvConn->getPeer() || !srvConn->getPeer()->options.no_delay)
1466  tunnelState->server.setDelayId(DelayId::DelayClient(context->http));
1467 #endif
1468 
1469  request->peer_host = srvConn->getPeer() ? srvConn->getPeer()->host : nullptr;
1470 
1471  debugs(26, 4, "determine post-connect handling pathway.");
1472  if (const auto peer = srvConn->getPeer())
1473  request->prepForPeering(*peer);
1474  else
1476 
1477  tunnelState->preReadServerData = preReadServerData;
1478 
1479  tunnelStartShoveling(tunnelState);
1480 }
1481 
const char * xstrerr(int error)
Definition: xstrerror.cc:83
void noteConnection(HappyConnOpenerAnswer &)
Definition: tunnel.cc:1042
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
virtual void print(std::ostream &os) const
Definition: tunnel.cc:239
void ERCB(int fd, void *, size_t)
error page callback
Definition: errorpage.h:28
static DelayId DelayClient(ClientHttpRequest *, HttpReply *reply=nullptr)
Definition: DelayId.cc:67
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:922
JobPointer job() const
Definition: JobWait.h:76
void dial(AsyncCall &)
Definition: tunnel.cc:238
bool tunneled
whether we spliced the connections instead of negotiating encryption
char * peer_host
Definition: HttpRequest.h:165
TunnelStateData(const TunnelStateData &)
CodeContext::Pointer codeContext
our creator context
Definition: tunnel.cc:190
AnyP::ProtocolVersion http_ver
Definition: Message.h:73
struct SquidConfig::@97 Timeout
int * status_ptr
pointer for logging HTTP status
Definition: tunnel.cc:179
time_t startTime
object creation time, before any peer selection/connection attempts
Definition: tunnel.cc:183
void notePeerReadyToShovel(const Comm::ConnectionPointer &)
called when negotiations with the peer have been successfully completed
Definition: tunnel.cc:1006
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
bool interceptTproxy
Set for requests handled by a "tproxy" port.
Definition: RequestFlags.h:66
#define xmalloc
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
void copyClientBytes()
Definition: tunnel.cc:872
CbcPointer< TunnelStateData > tunnel_
Definition: tunnel.cc:248
bool noConnections() const
Definition: tunnel.cc:1404
void clientClosed()
handles client-to-Squid connection closure; may destroy us
Definition: tunnel.cc:332
Gives Security::PeerConnector access to Answer in the TunnelStateData callback dialer.
Definition: tunnel.cc:229
Interface for those who need a list of peers to forward a request to.
JobWait< Http::Tunneler > peerWait
Definition: tunnel.cc:200
void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
Start using an established connection.
Definition: tunnel.cc:1066
void noteClosure()
reacts to the external closure of our connection
Definition: tunnel.cc:741
Ip::Address src_addr
void stopPeerClock(const bool force)
Definition: access_log.cc:304
ERCB * callback
Definition: errorpage.h:184
bool destinationsFinalized
whether all of the available candidate paths received from DNS
Definition: ResolvedPeers.h:81
@ scNone
Definition: StatusCode.h:21
SBuf inBuf
read I/O buffer for the client connection
Definition: Server.h:111
void FREE(void *)
Definition: forward.h:36
void eventDelete(EVH *func, void *arg)
Definition: event.cc:130
CbcPointer< ErrorState > error
problem details (nil on success)
bool isEmpty() const
Definition: SBuf.h:424
RequestFlags flags
Definition: HttpRequest.h:141
static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
Definition: tunnel.cc:698
CbcPointer< ErrorState > error
problem details (nil on success)
void addPath(const Comm::ConnectionPointer &)
add a candidate path to try after all the existing paths
static ERCB tunnelErrorComplete
Definition: tunnel.cc:302
ConnStateData * getConn() const
void(TunnelStateData::* Method)(Security::EncryptorAnswer &)
Definition: tunnel.cc:231
Connection server
Definition: tunnel.cc:178
TunnelStateData & operator=(const TunnelStateData &)
static void tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
Definition: tunnel.cc:943
void error(char *format,...)
void saveError(ErrorState *finalError)
remembers an error to be used if there will be no more connection attempts
Definition: tunnel.cc:1308
void copyServerBytes()
Definition: tunnel.cc:886
HttpReplyPointer reply
void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry)
Definition: peer_select.cc:335
void closePendingConnection(const Comm::ConnectionPointer &conn, const char *reason)
Definition: tunnel.cc:800
Definition: SBuf.h:87
acl_access * miss
Definition: SquidConfig.h:369
void secureConnectionToPeer(const Comm::ConnectionPointer &)
encrypts an established TCP connection to peer
Definition: tunnel.cc:1163
int bytesWanted(int lower=0, int upper=INT_MAX) const
Definition: tunnel.cc:465
int commSetConnTimeout(const Comm::ConnectionPointer &conn, int timeout, AsyncCall::Pointer &callback)
Definition: comm.cc:564
#define xstrdup
bool clientExpectsConnectResponse() const
Whether the client sent a CONNECT request to us.
Definition: tunnel.cc:102
void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno)
Definition: tunnel.cc:567
HierarchyLogEntry hier
struct ClientHttpRequest::Out out
C * getRaw() const
Definition: RefCount.h:80
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: tunnel.cc:1238
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
Acl::Answer const & fastCheck()
Definition: Checklist.cc:332
bool dirty
whether write() has been called (at least once)
Definition: tunnel.cc:162
TunnelStateData * readPending
Definition: tunnel.cc:165
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
struct StatCounters::@129 server
@ OK
Definition: Flag.h:16
void error(int const xerrno)
Definition: tunnel.cc:548
void closeConnections()
closes both client and server connections
Definition: tunnel.cc:809
void connectToPeer(const Comm::ConnectionPointer &)
continue to set up connection to a peer, going async for SSL peers
Definition: tunnel.cc:1149
void CLCB(const CommCloseCbParams &params)
Definition: CommCalls.h:42
@ ERR_CLOSING
Definition: Flag.h:25
AsyncCall::Pointer writer
pending Comm::Write callback
Definition: tunnel.cc:156
Callback dialer API to allow Tunneler to set the answer.
Definition: HttpTunneler.h:40
TunnelStateData(ClientHttpRequest *)
Definition: tunnel.cc:358
bool usingDestination() const
Definition: tunnel.cc:1301
bool empty() const
whether we lack any known candidate paths
Definition: ResolvedPeers.h:45
static void Reset()
forgets the current context, setting it to nil/unknown
Definition: CodeContext.cc:75
void advanceDestination(const char *stepDescription, const Comm::ConnectionPointer &conn, const StepStart &startStep)
starts a preparation step for an established connection; retries on failures
Definition: tunnel.cc:1174
const char * checkRetry()
Definition: tunnel.cc:404
void syncHierNote(const Comm::ConnectionPointer &server, const char *origin)
Definition: tunnel.cc:489
ErrorState * savedError
details of the "last tunneling attempt" failure (if it failed)
Definition: tunnel.cc:271
Definition: Debug.h:184
void comm_read(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer &callback)
Definition: Read.h:59
static CLCB tunnelClientClosed
Definition: tunnel.cc:304
void update(const LogTags_ot t)
Definition: LogTags.cc:54
static void tunnelStartShoveling(TunnelStateData *tunnelState)
Definition: tunnel.cc:904
void copyRead(Connection &from, IOCB *completion)
Definition: tunnel.cc:850
void tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
resumes operations after the (possibly failed) HTTP CONNECT exchange
Definition: tunnel.cc:964
Comm::ConnectionPointer conn
peer connection (secured on success)
ByteCounter kbytes_in
Definition: StatCounters.h:45
int size
Definition: ModDevPoll.cc:76
void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err)
Definition: errorpage.cc:751
#define NULL
Definition: types.h:166
const char * rawContent() const
Definition: SBuf.cc:509
SBuf consume(size_type n=npos)
Definition: SBuf.cc:481
void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
Definition: tunnel.cc:750
time_t read
Definition: SquidConfig.h:110
void sendError(ErrorState *finalError, const char *reason)
Definition: tunnel.cc:1319
@ scForbidden
Definition: StatusCode.h:47
void ResetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1609
void CTCB(const CommTimeoutCbParams &params)
Definition: CommCalls.h:39
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
@ LOG_TCP_TUNNEL
Definition: LogTags.h:56
SBuf preReadClientData
Definition: tunnel.cc:181
struct StatCounters::@129::@139 all
void write(const char *b, int size, AsyncCall::Pointer &callback, FREE *free_func)
writes 'b' buffer, setting the 'writer' member to 'callback'.
Definition: tunnel.cc:721
bool destinationsFound
Definition: tunnel.cc:185
Security::EncryptorAnswer answer_
Definition: tunnel.cc:249
AccessLogEntryPointer al
Definition: tunnel.cc:95
void setDelayId(DelayId const &)
Definition: tunnel.cc:1411
CbcPointer< ClientHttpRequest > http
Definition: tunnel.cc:93
MemBuf * pack() const
Definition: HttpReply.cc:111
#define true
Definition: GnuRegex.c:234
#define INT_MAX
Definition: types.h:76
ConnStateData * pinnedConnection()
Definition: HttpRequest.cc:733
void copy(size_t len, Connection &from, Connection &to, IOCB *)
Definition: tunnel.cc:635
CachePeer * getPeer() const
Definition: Connection.cc:124
bool subscribed
whether noteDestination() and noteDestinationsEnd() calls are allowed
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:152
void dataSent(size_t amount)
Definition: tunnel.cc:708
void switchToTunnel(HttpRequest *request, const Comm::ConnectionPointer &clientConn, const Comm::ConnectionPointer &srvConn, const SBuf &preReadServerData)
Definition: tunnel.cc:1438
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
Definition: CommCalls.h:36
void startConnecting()
Definition: tunnel.cc:1356
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:57
virtual ~TunnelStateData()
Definition: tunnel.cc:386
void bytesIn(int const &)
Definition: tunnel.cc:476
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
Comm::ConnectionPointer conn
The currently connected connection.
Definition: tunnel.cc:159
uint8_t delayedLoops
how many times a read on this connection has been postponed.
Definition: tunnel.cc:160
bool denied() const
Definition: Acl.h:149
virtual void noteDestinationsEnd(ErrorState *selectionError) override
Definition: tunnel.cc:1268
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
#define safe_free(x)
Definition: xalloc.h:73
struct SquidConfig::@112 accessList
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
Definition: CommCalls.h:342
void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
Definition: tunnel.cc:655
int conn
the current server connection FD
Definition: Transport.cc:26
JobWait< HappyConnOpener > transportWait
waits for a transport connection to the peer to be established/opened
Definition: tunnel.cc:193
#define assert(EX)
Definition: assert.h:19
void startPeerClock()
Start recording total time spent communicating with peers.
Definition: access_log.cc:297
bool intercepted
Definition: RequestFlags.h:62
class AccessLogEntry::CacheDetails cache
HierarchyLogEntry hier
Definition: HttpRequest.h:157
bool retriable
Definition: tunnel.cc:188
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
static bool EnoughTimeToReForward(const time_t fwdStart)
Definition: FwdState.cc:463
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
void clear()
make pointer not set; does not invalidate cbdata
Definition: CbcPointer.h:144
@ scServiceUnavailable
Definition: StatusCode.h:74
MyAnswerDialer(Method method, TunnelStateData *tunnel)
Definition: tunnel.cc:233
char * url
Definition: tunnel.cc:92
Ip::Address my_addr
Definition: HttpRequest.h:155
virtual bool canDial(AsyncCall &)
Definition: tunnel.cc:237
@ scInternalServerError
Definition: StatusCode.h:71
JobWait< Security::PeerConnector > encryptionWait
waits for the established transport connection to be secured/encrypted
Definition: tunnel.cc:196
static CTCB tunnelTimeout
Definition: tunnel.cc:305
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition: Write.cc:34
static CLCB tunnelServerClosed
Definition: tunnel.cc:303
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:408
time_t squid_curtime
Definition: stub_time.cc:17
CBDATA_CHILD(TunnelStateData)
Comm::ConnectionPointer clientConnection
Definition: Server.h:98
void establishTunnelThruProxy(const Comm::ConnectionPointer &)
Definition: tunnel.cc:1225
uint64_t size
Response header and body bytes written to the client connection.
SBuf & append(const SBuf &S)
Definition: SBuf.cc:185
bool isNoAddr() const
Definition: Address.cc:284
#define xfree
bool notificationPending
whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
Definition: ResolvedPeers.h:84
void EVH(void *)
Definition: event.h:18
Final result (an open connection or an error) sent to the job initiator.
Flag
Definition: Flag.h:15
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
void retryOrBail(const char *context)
Definition: tunnel.cc:418
int ignoreErrno(int ierrno)
Definition: comm.cc:1411
#define fd_table
Definition: fde.h:189
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: tunnel.cc:244
void start(const JobPointer &aJob, const AsyncCall::Pointer &aCallback)
starts waiting for the given job to call the given callback
Definition: JobWait.h:69
int debugLevelForError(int const xerrno) const
Definition: tunnel.cc:496
static Comm::ConnectionPointer BorrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &)
void usePinned()
send request on an existing connection dedicated to the requesting client
Definition: tunnel.cc:1374
HttpRequestMethod method
Definition: HttpRequest.h:114
Comm::ConnectionPointer conn
PeerConnectionPointer conn
static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
Definition: tunnel.cc:558
char * host
Definition: CachePeer.h:40
bool at(const BumpStep stp) const
whether we are currently performing the given processing step
Definition: ServerBump.h:47
void prepForPeering(const CachePeer &peer)
get ready to be sent to the given cache_peer, including originserver
Definition: HttpRequest.cc:447
@ ERR_FORWARDING_DENIED
Definition: forward.h:21
static const Pointer & Current()
Definition: CodeContext.cc:33
void cancelStep(const char *reason)
Definition: tunnel.cc:1348
static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
Definition: tunnel.cc:645
bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to)
Definition: tunnel.cc:592
HttpRequest::Pointer request
Definition: tunnel.cc:94
void notifyConnOpener()
makes sure connection opener knows that the destinations have changed
Definition: tunnel.cc:1420
AsyncCall dialer for our callback. Gives us access to callback Answer.
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:73
void tunnelStart(ClientHttpRequest *http)
Definition: tunnel.cc:1103
SBuf preReadServerData
Definition: tunnel.cc:182
void initConnection(const Comm::ConnectionPointer &aConn, Method method, const char *name, TunnelStateData *tunnelState)
initiates Comm::Connection ownership, including closure monitoring
Definition: tunnel.cc:730
SBuf leftovers
peer-generated bytes after a positive answer (or empty)
Ssl::ServerBump * serverBump()
Definition: client_side.h:286
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
static HttpReplyPointer MakeConnectionEstablished()
construct and return an HTTP/200 (Connection Established) response
Definition: HttpReply.cc:120
void resetPeerNotes(const Comm::ConnectionPointer &server, const char *requestedHost)
Definition: access_log.cc:251
const AccessLogEntry::Pointer al
access.log entry
bool reused
whether conn was open earlier, by/for somebody else
struct StatCounters::@128 client_http
int shutting_down
void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno)
Definition: tunnel.cc:523
ResolvedPeersPointer destinations
paths for forwarding the request
Definition: tunnel.cc:184
struct StatCounters::@129::@139 other
void prepForDirect()
get ready to be sent directly to an origin server, excluding originserver
Definition: HttpRequest.cc:457
@ ERR_CANNOT_FORWARD
Definition: forward.h:23
AsyncCall::Pointer closer
the registered close handler for the connection
Definition: tunnel.cc:175
void serverClosed()
handles Squid-to-server connection closure; may destroy us
Definition: tunnel.cc:318
@ scOkay
Definition: StatusCode.h:26
const char * getHost() const
Definition: tunnel.cc:97
time_t lifetime
Definition: SquidConfig.h:112
void connectedToPeer(const Comm::ConnectionPointer &)
called after connection setup (including any encryption)
Definition: tunnel.cc:1217
void * callback_data
Definition: errorpage.h:185
void noteSecurityPeerConnectorAnswer(Security::EncryptorAnswer &)
callback handler for the Security::PeerConnector encryptor
Definition: tunnel.cc:1193
#define false
Definition: GnuRegex.c:233
static EVH tunnelDelayedServerRead
Definition: tunnel.cc:307
Ip::Address client_addr
Definition: HttpRequest.h:149
StatusCode peerResponseStatus
the status code of the successfully parsed CONNECT response (or scNone)
void host(const char *src)
Definition: Uri.cc:98
Connection client
Definition: tunnel.cc:178
void netdbPingSite(const char *hostname)
Definition: net_db.cc:908
bool forceTunnel
whether to forward via TunnelStateData (instead of FwdState)
Definition: RequestFlags.h:111
ByteCounter kbytes_out
Definition: StatCounters.h:46
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:108
static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
Definition: tunnel.cc:513
Http::StatusCode httpStatus
Definition: errorpage.h:171
CbcPointer< ErrorState > squidError
problem details (or nil)
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:232
class SquidConfig Config
Definition: SquidConfig.cc:12
HttpRequest *const request
StatCounters statCounter
Definition: StatCounters.cc:12
#define DBG_DATA
Definition: Debug.h:43
void deleteThis()
destroys the tunnel (after performing potentially-throwing cleanup)
Definition: tunnel.cc:345
static EVH tunnelDelayedClientRead
Definition: tunnel.cc:306

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors