tunnel.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2019 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 "CachePeer.h"
15 #include "cbdata.h"
16 #include "client_side.h"
17 #include "client_side_request.h"
18 #include "clients/HttpTunneler.h"
19 #include "comm.h"
20 #include "comm/Connection.h"
21 #include "comm/ConnOpener.h"
22 #include "comm/Read.h"
23 #include "comm/Write.h"
24 #include "errorpage.h"
25 #include "fd.h"
26 #include "fde.h"
27 #include "FwdState.h"
28 #include "globals.h"
29 #include "http.h"
30 #include "http/Stream.h"
31 #include "HttpRequest.h"
32 #include "icmp/net_db.h"
33 #include "ip/QosConfig.h"
34 #include "LogTags.h"
35 #include "MemBuf.h"
36 #include "neighbors.h"
37 #include "PeerSelectState.h"
38 #include "sbuf/SBuf.h"
40 #include "SquidConfig.h"
41 #include "SquidTime.h"
42 #include "StatCounters.h"
43 #if USE_OPENSSL
44 #include "ssl/bio.h"
45 #include "ssl/ServerBump.h"
46 #endif
47 #include "tools.h"
48 #if USE_DELAY_POOLS
49 #include "DelayId.h"
50 #endif
51 
52 #include <climits>
53 #include <cerrno>
54 
60 /*
61  * TODO 1: implement a read/write API on ConnStateData to send/receive blocks
62  * of pre-formatted data. Then we can use that as the client side of the tunnel
63  * instead of re-implementing it here and occasionally getting the ConnStateData
64  * read/write state wrong.
65  *
66  * TODO 2: then convert this into a AsyncJob, possibly a child of 'Server'
67  */
69 {
71 
72 public:
74  virtual ~TunnelStateData();
75  TunnelStateData(const TunnelStateData &); // do not implement
76  TunnelStateData &operator =(const TunnelStateData &); // do not implement
77 
78  class Connection;
79  static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
80  static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
81  static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
82  static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
83 
84  bool noConnections() const;
85  char *url;
90 
91  const char * getHost() const {
92  return (server.conn != NULL && server.conn->getPeer() ? server.conn->getPeer()->host : request->url.host());
93  };
94 
97  // If we are forcing a tunnel after receiving a client CONNECT, then we
98  // have already responded to that CONNECT before tunnel.cc started.
99  if (request && request->flags.forceTunnel)
100  return false;
101 #if USE_OPENSSL
102  // We are bumping and we had already send "OK CONNECTED"
103  if (http.valid() && http->getConn() && http->getConn()->serverBump() && http->getConn()->serverBump()->step > Ssl::bumpStep1)
104  return false;
105 #endif
106  return !(request != NULL &&
107  (request->flags.interceptTproxy || request->flags.intercepted));
108  }
109 
112  void startConnecting();
113 
115 
117  void notePeerReadyToShovel();
118 
120  {
121 
122  public:
123  Connection() : len (0), buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), delayedLoops(0),
125 
126  ~Connection();
127 
128  int bytesWanted(int lower=0, int upper = INT_MAX) const;
129  void bytesIn(int const &);
130 #if USE_DELAY_POOLS
131 
132  void setDelayId(DelayId const &);
133 #endif
134 
135  void error(int const xerrno);
136  int debugLevelForError(int const xerrno) const;
137  void closeIfOpen();
138  void dataSent (size_t amount);
140  void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func);
141  int len;
142  char *buf;
144  uint64_t *size_ptr; /* pointer to size in an ConnStateData for logging */
145 
147  uint8_t delayedLoops;
148 
149  // XXX: make these an AsyncCall when event API can handle them
152 
153 #if USE_DELAY_POOLS
154 
156 #endif
157 
158  };
159 
161  int *status_ptr;
163 
166  time_t startTime;
169 
170  void copyRead(Connection &from, IOCB *completion);
171 
173  void connectToPeer();
174 
175  /* PeerSelectionInitiator API */
176  virtual void noteDestination(Comm::ConnectionPointer conn) override;
177  virtual void noteDestinationsEnd(ErrorState *selectionError) override;
178 
179  void saveError(ErrorState *finalError);
180  void sendError(ErrorState *finalError, const char *reason);
181 
182 private:
185  {
186  public:
188 
190  method_(method), tunnel_(tunnel), answer_() {}
191 
192  /* CallDialer API */
193  virtual bool canDial(AsyncCall &call) { return tunnel_.valid(); }
194  void dial(AsyncCall &call) { ((&(*tunnel_))->*method_)(answer_); }
195  virtual void print(std::ostream &os) const {
196  os << '(' << tunnel_.get() << ", " << answer_ << ')';
197  }
198 
199  /* Security::PeerConnector::CbDialer API */
200  virtual Security::EncryptorAnswer &answer() { return answer_; }
201 
202  private:
206  };
207 
208  void usePinned();
209 
212 
214  ErrorState *savedError = nullptr;
215 
218 
219 public:
220  bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to);
221  void copy(size_t len, Connection &from, Connection &to, IOCB *);
222  void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno);
223  void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno);
224  void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
225  void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
226 
227  void copyClientBytes();
228  void copyServerBytes();
229 };
230 
231 static const char *const conn_established = "HTTP/1.1 200 Connection established\r\n\r\n";
232 
240 
241 static void
243 {
244  TunnelStateData *tunnelState = (TunnelStateData *)params.data;
245  debugs(26, 3, HERE << tunnelState->server.conn);
246  tunnelState->server.conn = NULL;
247  tunnelState->server.writer = NULL;
248 
249  if (tunnelState->request != NULL)
250  tunnelState->request->hier.stopPeerClock(false);
251 
252  if (tunnelState->noConnections()) {
253  // ConnStateData pipeline should contain the CONNECT we are performing
254  // but it may be invalid already (bug 4392)
255  if (tunnelState->http.valid() && tunnelState->http->getConn()) {
256  auto ctx = tunnelState->http->getConn()->pipeline.front();
257  if (ctx != nullptr)
258  ctx->finished();
259  }
260  delete tunnelState;
261  return;
262  }
263 
264  if (!tunnelState->client.writer) {
265  tunnelState->client.conn->close();
266  return;
267  }
268 }
269 
270 static void
272 {
273  TunnelStateData *tunnelState = (TunnelStateData *)params.data;
274  debugs(26, 3, HERE << tunnelState->client.conn);
275  tunnelState->client.conn = NULL;
276  tunnelState->client.writer = NULL;
277 
278  if (tunnelState->noConnections()) {
279  // ConnStateData pipeline should contain the CONNECT we are performing
280  // but it may be invalid already (bug 4392)
281  if (tunnelState->http.valid() && tunnelState->http->getConn()) {
282  auto ctx = tunnelState->http->getConn()->pipeline.front();
283  if (ctx != nullptr)
284  ctx->finished();
285  }
286  delete tunnelState;
287  return;
288  }
289 
290  if (!tunnelState->server.writer) {
291  tunnelState->server.conn->close();
292  return;
293  }
294 }
295 
299 {
300  debugs(26, 3, "TunnelStateData constructed this=" << this);
303 
304  assert(clientRequest);
305  url = xstrdup(clientRequest->uri);
306  request = clientRequest->request;
307  server.size_ptr = &clientRequest->out.size;
308  client.size_ptr = &clientRequest->al->http.clientRequestSz.payloadData;
309  status_ptr = &clientRequest->al->http.code;
310  logTag_ptr = &clientRequest->logType;
311  al = clientRequest->al;
312  http = clientRequest;
313 
314  client.conn = clientRequest->getConn()->clientConnection;
316 
317  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
320 }
321 
323 {
324  debugs(26, 3, "TunnelStateData destructed this=" << this);
326  xfree(url);
327  serverDestinations.clear();
328  delete savedError;
329 }
330 
332 {
333  if (readPending)
334  eventDelete(readPendingFunc, readPending);
335 
336  safe_free(buf);
337 }
338 
339 int
340 TunnelStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
341 {
342 #if USE_DELAY_POOLS
343  return delayId.bytesWanted(lowerbound, upperbound);
344 #else
345 
346  return upperbound;
347 #endif
348 }
349 
350 void
352 {
353  debugs(26, 3, HERE << "len=" << len << " + count=" << count);
354 #if USE_DELAY_POOLS
355  delayId.bytesIn(count);
356 #endif
357 
358  len += count;
359 }
360 
361 int
363 {
364 #ifdef ECONNRESET
365 
366  if (xerrno == ECONNRESET)
367  return 2;
368 
369 #endif
370 
371  if (ignoreErrno(xerrno))
372  return 3;
373 
374  return 1;
375 }
376 
377 /* Read from server side and queue it for writing to the client */
378 void
379 TunnelStateData::ReadServer(const Comm::ConnectionPointer &c, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
380 {
381  TunnelStateData *tunnelState = (TunnelStateData *)data;
382  assert(cbdataReferenceValid(tunnelState));
383  debugs(26, 3, HERE << c);
384 
385  tunnelState->readServer(buf, len, errcode, xerrno);
386 }
387 
388 void
389 TunnelStateData::readServer(char *, size_t len, Comm::Flag errcode, int xerrno)
390 {
391  debugs(26, 3, HERE << server.conn << ", read " << len << " bytes, err=" << errcode);
393 
394  /*
395  * Bail out early on Comm::ERR_CLOSING
396  * - close handlers will tidy up for us
397  */
398 
399  if (errcode == Comm::ERR_CLOSING)
400  return;
401 
402  if (len > 0) {
403  server.bytesIn(len);
404  statCounter.server.all.kbytes_in += len;
405  statCounter.server.other.kbytes_in += len;
407  }
408 
409  if (keepGoingAfterRead(len, errcode, xerrno, server, client))
411 }
412 
413 void
415 {
416  debugs(50, debugLevelForError(xerrno), HERE << conn << ": read/write failure: " << xstrerr(xerrno));
417 
418  if (!ignoreErrno(xerrno))
419  conn->close();
420 }
421 
422 /* Read from client side and queue it for writing to the server */
423 void
424 TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
425 {
426  TunnelStateData *tunnelState = (TunnelStateData *)data;
427  assert (cbdataReferenceValid (tunnelState));
428 
429  tunnelState->readClient(buf, len, errcode, xerrno);
430 }
431 
432 void
433 TunnelStateData::readClient(char *, size_t len, Comm::Flag errcode, int xerrno)
434 {
435  debugs(26, 3, HERE << client.conn << ", read " << len << " bytes, err=" << errcode);
437 
438  /*
439  * Bail out early on Comm::ERR_CLOSING
440  * - close handlers will tidy up for us
441  */
442 
443  if (errcode == Comm::ERR_CLOSING)
444  return;
445 
446  if (len > 0) {
447  client.bytesIn(len);
449  }
450 
451  if (keepGoingAfterRead(len, errcode, xerrno, client, server))
453 }
454 
457 bool
459 {
460  debugs(26, 3, HERE << "from={" << from.conn << "}, to={" << to.conn << "}");
461 
462  /* I think this is to prevent free-while-in-a-callback behaviour
463  * - RBC 20030229
464  * from.conn->close() / to.conn->close() done here trigger close callbacks which may free TunnelStateData
465  */
466  const CbcPointer<TunnelStateData> safetyLock(this);
467 
468  /* Bump the source connection read timeout on any activity */
469  if (Comm::IsConnOpen(from.conn)) {
470  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
472  commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
473  }
474 
475  /* Bump the dest connection read timeout on any activity */
476  /* see Bug 3659: tunnels can be weird, with very long one-way transfers */
477  if (Comm::IsConnOpen(to.conn)) {
478  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
480  commSetConnTimeout(to.conn, Config.Timeout.read, timeoutCall);
481  }
482 
483  if (errcode)
484  from.error (xerrno);
485  else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
486  debugs(26, 3, HERE << "Nothing to write or client gone. Terminate the tunnel.");
487  from.conn->close();
488 
489  /* Only close the remote end if we've finished queueing data to it */
490  if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
491  to.conn->close();
492  }
493  } else if (cbdataReferenceValid(this)) {
494  return true;
495  }
496 
497  return false;
498 }
499 
500 void
501 TunnelStateData::copy(size_t len, Connection &from, Connection &to, IOCB *completion)
502 {
503  debugs(26, 3, HERE << "Schedule Write");
504  AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler",
505  CommIoCbPtrFun(completion, this));
506  to.write(from.buf, len, call, NULL);
507 }
508 
509 /* Writes data from the client buffer to the server side */
510 void
511 TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
512 {
513  TunnelStateData *tunnelState = (TunnelStateData *)data;
514  assert (cbdataReferenceValid (tunnelState));
515  tunnelState->server.writer = NULL;
516 
517  tunnelState->writeServerDone(buf, len, flag, xerrno);
518 }
519 
520 void
521 TunnelStateData::writeServerDone(char *, size_t len, Comm::Flag flag, int xerrno)
522 {
523  debugs(26, 3, HERE << server.conn << ", " << len << " bytes written, flag=" << flag);
524 
525  if (flag == Comm::ERR_CLOSING)
526  return;
527 
529 
530  /* Error? */
531  if (flag != Comm::OK) {
532  debugs(26, 4, "to-server write failed: " << xerrno);
533  server.error(xerrno); // may call comm_close
534  return;
535  }
536 
537  /* EOF? */
538  if (len == 0) {
539  debugs(26, 4, HERE << "No read input. Closing server connection.");
540  server.conn->close();
541  return;
542  }
543 
544  /* Valid data */
545  statCounter.server.all.kbytes_out += len;
546  statCounter.server.other.kbytes_out += len;
547  client.dataSent(len);
548 
549  /* If the other end has closed, so should we */
550  if (!Comm::IsConnOpen(client.conn)) {
551  debugs(26, 4, HERE << "Client gone away. Shutting down server connection.");
552  server.conn->close();
553  return;
554  }
555 
556  const CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
557 
558  if (cbdataReferenceValid(this))
559  copyClientBytes();
560 }
561 
562 /* Writes data from the server buffer to the client side */
563 void
564 TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
565 {
566  TunnelStateData *tunnelState = (TunnelStateData *)data;
567  assert (cbdataReferenceValid (tunnelState));
568  tunnelState->client.writer = NULL;
569 
570  tunnelState->writeClientDone(buf, len, flag, xerrno);
571 }
572 
573 void
575 {
576  debugs(26, 3, HERE << "len=" << len << " - amount=" << amount);
577  assert(amount == (size_t)len);
578  len =0;
579  /* increment total object size */
580 
581  if (size_ptr)
582  *size_ptr += amount;
583 
584 }
585 
586 void
588 {
589  writer = callback;
590  Comm::Write(conn, b, size, callback, free_func);
591 }
592 
593 void
594 TunnelStateData::writeClientDone(char *, size_t len, Comm::Flag flag, int xerrno)
595 {
596  debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
597 
598  if (flag == Comm::ERR_CLOSING)
599  return;
600 
601  /* Error? */
602  if (flag != Comm::OK) {
603  debugs(26, 4, "from-client read failed: " << xerrno);
604  client.error(xerrno); // may call comm_close
605  return;
606  }
607 
608  /* EOF? */
609  if (len == 0) {
610  debugs(26, 4, HERE << "Closing client connection due to 0 byte read.");
611  client.conn->close();
612  return;
613  }
614 
615  /* Valid data */
617  server.dataSent(len);
618 
619  /* If the other end has closed, so should we */
620  if (!Comm::IsConnOpen(server.conn)) {
621  debugs(26, 4, HERE << "Server has gone away. Terminating client connection.");
622  client.conn->close();
623  return;
624  }
625 
626  CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
627 
628  if (cbdataReferenceValid(this))
629  copyServerBytes();
630 }
631 
632 static void
634 {
635  TunnelStateData *tunnelState = static_cast<TunnelStateData *>(io.data);
636  debugs(26, 3, HERE << io.conn);
637  /* Temporary lock to protect our own feets (comm_close -> tunnelClientClosed -> Free) */
638  CbcPointer<TunnelStateData> safetyLock(tunnelState);
639 
640  tunnelState->client.closeIfOpen();
641  tunnelState->server.closeIfOpen();
642 }
643 
644 void
646 {
647  if (Comm::IsConnOpen(conn))
648  conn->close();
649 }
650 
651 static void
653 {
654  if (!data)
655  return;
656 
657  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
658  tunnel->client.readPending = NULL;
659  static uint64_t counter=0;
660  debugs(26, 7, "Client read(2) delayed " << ++counter << " times");
661  tunnel->copyRead(tunnel->client, TunnelStateData::ReadClient);
662 }
663 
664 static void
666 {
667  if (!data)
668  return;
669 
670  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
671  tunnel->server.readPending = NULL;
672  static uint64_t counter=0;
673  debugs(26, 7, "Server read(2) delayed " << ++counter << " times");
674  tunnel->copyRead(tunnel->server, TunnelStateData::ReadServer);
675 }
676 
677 void
679 {
680  assert(from.len == 0);
681  // If only the minimum permitted read size is going to be attempted
682  // then we schedule an event to try again in a few I/O cycles.
683  // Allow at least 1 byte to be read every (0.3*10) seconds.
684  int bw = from.bytesWanted(1, SQUID_TCP_SO_RCVBUF);
685  if (bw == 1 && ++from.delayedLoops < 10) {
686  from.readPending = this;
687  eventAdd("tunnelDelayedServerRead", from.readPendingFunc, from.readPending, 0.3, true);
688  return;
689  }
690 
691  AsyncCall::Pointer call = commCbCall(5,4, "TunnelBlindCopyReadHandler",
692  CommIoCbPtrFun(completion, this));
693  comm_read(from.conn, from.buf, bw, call);
694 }
695 
696 void
698 {
699  if (preReadClientData.length()) {
700  size_t copyBytes = preReadClientData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadClientData.length();
701  memcpy(client.buf, preReadClientData.rawContent(), copyBytes);
702  preReadClientData.consume(copyBytes);
703  client.bytesIn(copyBytes);
704  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, client, server))
706  } else
708 }
709 
710 void
712 {
713  if (preReadServerData.length()) {
714  size_t copyBytes = preReadServerData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadServerData.length();
715  memcpy(server.buf, preReadServerData.rawContent(), copyBytes);
716  preReadServerData.consume(copyBytes);
717  server.bytesIn(copyBytes);
718  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, server, client))
720  } else
722 }
723 
728 static void
730 {
731  assert(!tunnelState->waitingForConnectExchange);
732  *tunnelState->status_ptr = Http::scOkay;
733  if (tunnelState->logTag_ptr)
734  tunnelState->logTag_ptr->update(LOG_TCP_TUNNEL);
735  if (cbdataReferenceValid(tunnelState)) {
736 
737  // Shovel any payload already pushed into reply buffer by the server response
738  if (!tunnelState->server.len)
739  tunnelState->copyServerBytes();
740  else {
741  debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
742  tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
743  }
744 
745  if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->inBuf.isEmpty()) {
746  SBuf * const in = &tunnelState->http->getConn()->inBuf;
747  debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << *in << "\n----------");
748  tunnelState->preReadClientData.append(*in);
749  in->consume(); // ConnStateData buffer accounting after the shuffle.
750  }
751  tunnelState->copyClientBytes();
752  }
753 }
754 
760 static void
761 tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
762 {
763  TunnelStateData *tunnelState = (TunnelStateData *)data;
764  debugs(26, 3, HERE << conn << ", flag=" << flag);
765  tunnelState->client.writer = NULL;
766 
767  if (flag != Comm::OK) {
768  *tunnelState->status_ptr = Http::scInternalServerError;
769  tunnelErrorComplete(conn->fd, data, 0);
770  return;
771  }
772 
773  if (auto http = tunnelState->http.get()) {
774  http->out.headers_sz += len;
775  http->out.size += len;
776  }
777 
778  tunnelStartShoveling(tunnelState);
779 }
780 
781 void
783 {
784  server.len = 0;
785 
786  if (logTag_ptr)
788 
789  if (answer.peerResponseStatus != Http::scNone)
790  *status_ptr = answer.peerResponseStatus;
791 
793 
794  if (answer.positive()) {
795  // copy any post-200 OK bytes to our buffer
796  preReadServerData = answer.leftovers;
798  return;
799  }
800 
801  // TODO: Reuse to-peer connections after a CONNECT error response.
802 
803  // TODO: We can and, hence, should close now, but tunnelServerClosed()
804  // cannot yet tell whether ErrorState is still writing an error response.
805  // server.closeIfOpen();
806 
808  // closing the non-HTTP client connection is the best we can do
809  debugs(50, 3, server.conn << " closing on CONNECT-to-peer error");
811  return;
812  }
813 
814  ErrorState *error = answer.squidError.get();
815  Must(error);
816  answer.squidError.clear(); // preserve error for errorSendComplete()
817  sendError(error, "tunneler returns error");
818 }
819 
820 void
822 {
824  tunnelStartShoveling(this); // ssl-bumped connection, be quiet
825  else {
827  AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
829  client.write(conn_established, strlen(conn_established), call, nullptr);
830  }
831 }
832 
833 static void
834 tunnelErrorComplete(int fd/*const Comm::ConnectionPointer &*/, void *data, size_t)
835 {
836  TunnelStateData *tunnelState = (TunnelStateData *)data;
837  debugs(26, 3, HERE << "FD " << fd);
838  assert(tunnelState != NULL);
839  /* temporary lock to save our own feets (comm_close -> tunnelClientClosed -> Free) */
840  CbcPointer<TunnelStateData> safetyLock(tunnelState);
841 
842  if (Comm::IsConnOpen(tunnelState->client.conn))
843  tunnelState->client.conn->close();
844 
845  if (Comm::IsConnOpen(tunnelState->server.conn))
846  tunnelState->server.conn->close();
847 }
848 
850 void
852 {
853  debugs(26, 4, "removing the failed one from " << serverDestinations.size() <<
854  " destinations: " << conn);
855 
856  if (CachePeer *peer = conn->getPeer())
857  peerConnectFailed(peer);
858 
859  assert(!serverDestinations.empty());
860  serverDestinations.erase(serverDestinations.begin());
861 
862  // Since no TCP payload has been passed to client or server, we may
863  // TCP-connect to other destinations (including alternate IPs).
864 
866  return sendError(savedError, "forwarding timeout");
867 
868  if (!serverDestinations.empty())
869  return startConnecting();
870 
872  return sendError(savedError, "tried all destinations");
873 
874  debugs(26, 4, "wait for more destinations to try");
875  // expect a noteDestination*() call
876 }
877 
878 static void
880 {
881  TunnelStateData *tunnelState = (TunnelStateData *)data;
882 
883  if (status != Comm::OK) {
884  const auto err = new ErrorState(ERR_CONNECT_FAIL, Http::scServiceUnavailable, tunnelState->request.getRaw(), tunnelState->al);
885  err->xerrno = xerrno;
886  // on timeout is this still: err->xerrno = ETIMEDOUT;
887  err->port = conn->remote.port();
888  tunnelState->saveError(err);
889  tunnelState->noteConnectFailure(conn);
890  return;
891  }
892 
893 #if USE_DELAY_POOLS
894  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
895  if (conn->getPeer() && conn->getPeer()->options.no_delay)
896  tunnelState->server.setDelayId(DelayId());
897 #endif
898 
899  netdbPingSite(tunnelState->request->url.host());
900 
901  tunnelState->request->hier.resetPeerNotes(conn, tunnelState->getHost());
902 
903  tunnelState->server.conn = conn;
904  tunnelState->request->peer_host = conn->getPeer() ? conn->getPeer()->host : NULL;
905  comm_add_close_handler(conn->fd, tunnelServerClosed, tunnelState);
906 
907  bool toOrigin = false; // same semantics as StateFlags::toOrigin
908  if (const auto * const peer = conn->getPeer()) {
909  tunnelState->request->prepForPeering(*peer);
910  toOrigin = peer->options.originserver;
911  } else {
912  tunnelState->request->prepForDirect();
913  toOrigin = true;
914  }
915 
916  if (!toOrigin)
917  tunnelState->connectToPeer();
918  else {
919  tunnelState->notePeerReadyToShovel();
920  }
921 
922  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
923  CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
924  commSetConnTimeout(conn, Config.Timeout.read, timeoutCall);
925 }
926 
927 void
929 {
930  debugs(26, 3, HERE);
931  /* Create state structure. */
932  TunnelStateData *tunnelState = NULL;
933  ErrorState *err = NULL;
934  HttpRequest *request = http->request;
935  char *url = http->uri;
936 
937  /*
938  * client_addr.isNoAddr() indicates this is an "internal" request
939  * from peer_digest.c, asn.c, netdb.c, etc and should always
940  * be allowed. yuck, I know.
941  */
942 
943  if (Config.accessList.miss && !request->client_addr.isNoAddr()) {
944  /*
945  * Check if this host is allowed to fetch MISSES from us (miss_access)
946  * default is to allow.
947  */
949  ch.al = http->al;
950  ch.src_addr = request->client_addr;
951  ch.my_addr = request->my_addr;
952  ch.syncAle(request, http->log_uri);
953  if (ch.fastCheck().denied()) {
954  debugs(26, 4, HERE << "MISS access forbidden.");
955  err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request, http->al);
956  http->al->http.code = Http::scForbidden;
957  errorSend(http->getConn()->clientConnection, err);
958  return;
959  }
960  }
961 
962  debugs(26, 3, request->method << ' ' << url << ' ' << request->http_ver);
963  ++statCounter.server.all.requests;
964  ++statCounter.server.other.requests;
965 
966  tunnelState = new TunnelStateData(http);
967 #if USE_DELAY_POOLS
968  tunnelState->server.setDelayId(DelayId::DelayClient(http));
969 #endif
970  tunnelState->startSelectingDestinations(request, http->al, nullptr);
971 }
972 
973 void
975 {
976  if (CachePeer *p = server.conn->getPeer()) {
977  if (p->secure.encryptTransport) {
979  "TunnelStateData::ConnectedToPeer",
981  auto *connector = new Security::BlindPeerConnector(request, server.conn, callback, al);
982  AsyncJob::Start(connector); // will call our callback
983  return;
984  }
985  }
986 
988  connectedToPeer(nil);
989 }
990 
991 void
993 {
994  if (ErrorState *error = answer.error.get()) {
995  answer.error.clear(); // sendError() will own the error
996  sendError(error, "TLS peer connection error");
997  return;
998  }
999 
1001 
1003  "TunnelStateData::tunnelEstablishmentDone",
1005  const auto tunneler = new Http::Tunneler(server.conn, request, callback, Config.Timeout.lifetime, al);
1006 #if USE_DELAY_POOLS
1007  tunneler->setDelayId(server.delayId);
1008 #endif
1009  AsyncJob::Start(tunneler);
1011  // and wait for the tunnelEstablishmentDone() call
1012 }
1013 
1016 {
1017  // pinned_connection may become nil after a pconn race
1018  if (ConnStateData *pinned_connection = request ? request->pinnedConnection() : nullptr) {
1019  Comm::ConnectionPointer serverConn = pinned_connection->borrowPinnedConnection(request);
1020  return serverConn;
1021  }
1022 
1023  return nullptr;
1024 }
1025 
1026 void
1028 {
1029  const bool wasBlocked = serverDestinations.empty();
1030  // XXX: Push even a nil path so that subsequent noteDestination() calls
1031  // can rely on wasBlocked to detect ongoing/concurrent attempts.
1032  // Upcoming Happy Eyeballs changes will handle this properly.
1033  serverDestinations.push_back(path);
1034 
1035  if (!path) { // decided to use a pinned connection
1036  // We can call usePinned() without fear of clashing with an earlier
1037  // forwarding attempt because PINNED must be the first destination.
1038  assert(wasBlocked);
1039  usePinned();
1040  return;
1041  }
1042 
1043  if (wasBlocked)
1044  startConnecting();
1045  // else continue to use one of the previously noted destinations;
1046  // if all of them fail, we may try this path
1047 }
1048 
1049 void
1051 {
1053  if (serverDestinations.empty()) { // was blocked, waiting for more paths
1054 
1055  if (selectionError)
1056  return sendError(selectionError, "path selection has failed");
1057 
1058  if (savedError)
1059  return sendError(savedError, "all found paths have failed");
1060 
1062  "path selection found no paths");
1063  }
1064  // else continue to use one of the previously noted destinations;
1065  // if all of them fail, tunneling as whole will fail
1066  Must(!selectionError); // finding at least one path means selection succeeded
1067 }
1068 
1070 void
1072 {
1073  debugs(26, 4, savedError << " ? " << error);
1074  assert(error);
1075  delete savedError; // may be nil
1076  savedError = error;
1077 }
1078 
1081 void
1082 TunnelStateData::sendError(ErrorState *finalError, const char *reason)
1083 {
1084  debugs(26, 3, "aborting transaction for " << reason);
1085 
1086  if (request)
1087  request->hier.stopPeerClock(false);
1088 
1089  assert(finalError);
1090 
1091  // get rid of any cached error unless that is what the caller is sending
1092  if (savedError != finalError)
1093  delete savedError; // may be nil
1094  savedError = nullptr;
1095 
1096  // we cannot try other destinations after responding with an error
1097  PeerSelectionInitiator::subscribed = false; // may already be false
1098 
1099  *status_ptr = finalError->httpStatus;
1100  finalError->callback = tunnelErrorComplete;
1101  finalError->callback_data = this;
1102  errorSend(client.conn, finalError);
1103 }
1104 
1105 void
1107 {
1108  if (request)
1110 
1111  assert(!serverDestinations.empty());
1113  debugs(26, 3, "to " << dest);
1114  assert(dest != nullptr);
1115 
1117 
1118  const time_t connectTimeout = dest->connectTimeout(startTime);
1119  AsyncCall::Pointer call = commCbCall(26,3, "tunnelConnectDone", CommConnectCbPtrFun(tunnelConnectDone, this));
1120  Comm::ConnOpener *cs = new Comm::ConnOpener(dest, call, connectTimeout);
1121  cs->setHost(url);
1122  AsyncJob::Start(cs);
1123 }
1124 
1126 void
1128 {
1129  const auto serverConn = borrowPinnedConnection(request.getRaw());
1130  debugs(26,7, "pinned peer connection: " << serverConn);
1131  if (!Comm::IsConnOpen(serverConn)) {
1132  // a PINNED path failure is fatal; do not wait for more paths
1134  "pinned path failure");
1135  return;
1136  }
1137 
1138  tunnelConnectDone(serverConn, Comm::OK, 0, (void *)this);
1139 }
1140 
1142 
1143 bool
1145 {
1147 }
1148 
1149 #if USE_DELAY_POOLS
1150 void
1152 {
1153  delayId = newDelay;
1154 }
1155 
1156 #endif
1157 
1158 #if USE_OPENSSL
1159 void
1161 {
1162  debugs(26,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << srvConn->fd);
1163 
1164  /* Create state structure. */
1165  ++statCounter.server.all.requests;
1166  ++statCounter.server.other.requests;
1167 
1168  auto conn = request->clientConnectionManager.get();
1169  Must(conn);
1170  Http::StreamPointer context = conn->pipeline.front();
1171  Must(context && context->http);
1172 
1173  debugs(26, 3, request->method << " " << context->http->uri << " " << request->http_ver);
1174 
1175  TunnelStateData *tunnelState = new TunnelStateData(context->http);
1176 
1177  fd_table[clientConn->fd].read_method = &default_read_method;
1178  fd_table[clientConn->fd].write_method = &default_write_method;
1179 
1180  request->hier.resetPeerNotes(srvConn, tunnelState->getHost());
1181 
1182  tunnelState->server.conn = srvConn;
1183 
1184 #if USE_DELAY_POOLS
1185  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
1186  if (!srvConn->getPeer() || !srvConn->getPeer()->options.no_delay)
1187  tunnelState->server.setDelayId(DelayId::DelayClient(context->http));
1188 #endif
1189 
1190  request->peer_host = srvConn->getPeer() ? srvConn->getPeer()->host : nullptr;
1191  comm_add_close_handler(srvConn->fd, tunnelServerClosed, tunnelState);
1192 
1193  debugs(26, 4, "determine post-connect handling pathway.");
1194  if (const auto peer = srvConn->getPeer())
1195  request->prepForPeering(*peer);
1196  else
1197  request->prepForDirect();
1198 
1199  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
1200  CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
1201  commSetConnTimeout(srvConn, Config.Timeout.read, timeoutCall);
1202  fd_table[srvConn->fd].read_method = &default_read_method;
1203  fd_table[srvConn->fd].write_method = &default_write_method;
1204 
1205  auto ssl = fd_table[srvConn->fd].ssl.get();
1206  assert(ssl);
1207  BIO *b = SSL_get_rbio(ssl);
1208  Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
1209  tunnelState->preReadServerData = srvBio->rBufData();
1210  tunnelStartShoveling(tunnelState);
1211 }
1212 #endif //USE_OPENSSL
1213 
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
HierarchyLogEntry hier
Definition: HttpRequest.h:157
bool interceptTproxy
Set for requests handled by a "tproxy" port.
Definition: RequestFlags.h:66
static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
Definition: tunnel.cc:379
#define fd_table
Definition: fde.h:157
Ssl::ServerBump * serverBump()
Definition: client_side.h:253
ConnStateData * pinnedConnection()
Definition: HttpRequest.cc:688
void usePinned()
send request on an existing connection dedicated to the requesting client
Definition: tunnel.cc:1127
unsigned short port() const
Definition: Address.cc:778
StatCounters statCounter
Definition: StatCounters.cc:12
#define assert(EX)
Definition: assert.h:17
Ip::Address my_addr
Definition: HttpRequest.h:155
Callback dialer API to allow Tunneler to set the answer.
Definition: HttpTunneler.h:45
static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
Definition: tunnel.cc:424
void const char HLPCB * callback
Definition: stub_helper.cc:16
static bool EnoughTimeToReForward(const time_t fwdStart)
Definition: FwdState.cc:407
Comm::ConnectionPointer conn
The currently connected connection.
Definition: tunnel.cc:146
int * status_ptr
pointer for logging HTTP status
Definition: tunnel.cc:161
Security::EncryptorAnswer answer_
Definition: tunnel.cc:205
void copyClientBytes()
Definition: tunnel.cc:697
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: tunnel.cc:1027
void startPeerClock()
Start recording total time spent communicating with peers.
Definition: access_log.cc:296
const SBuf & rBufData()
The buffered input data.
Definition: bio.h:61
CbcPointer< ClientHttpRequest > http
Definition: tunnel.cc:86
void CTCB(const CommTimeoutCbParams &params)
Definition: CommCalls.h:39
int debugLevelForError(int const xerrno) const
Definition: tunnel.cc:362
CbcPointer< ErrorState > error
problem details (nil on success)
MyAnswerDialer(Method method, TunnelStateData *tunnel)
Definition: tunnel.cc:189
Definition: SBuf.h:86
bool isNoAddr() const
Definition: Address.cc:284
Ip::Address src_addr
void copyServerBytes()
Definition: tunnel.cc:711
HttpRequestMethod method
Definition: HttpRequest.h:114
void setHost(const char *)
set the hostname note for this connection
Definition: ConnOpener.cc:89
void error(char *format,...)
int default_read_method(int, char *, int)
Definition: fd.cc:146
#define xstrdup
SBuf & append(const SBuf &S)
Definition: SBuf.cc:195
ConnStateData * getConn() const
static void tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
Definition: tunnel.cc:761
bool denied() const
Definition: Acl.h:147
ERCB * callback
Definition: errorpage.h:187
#define safe_free(x)
Definition: xalloc.h:73
std::vector< Comm::ConnectionPointer > ConnectionList
Definition: forward.h:29
Definition: Flag.h:16
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
Definition: tunnel.cc:594
StatusCode peerResponseStatus
the status code of the successfully parsed CONNECT response (or scNone)
time_t startTime
Definition: tunnel.cc:166
CachePeer * getPeer() const
Definition: Connection.cc:98
void saveError(ErrorState *finalError)
remembers an error to be used if there will be no more connection attempts
Definition: tunnel.cc:1071
struct StatCounters::@128::@137 other
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
bool isEmpty() const
Definition: SBuf.h:420
Interface for those who need a list of peers to forward a request to.
AccessLogEntryPointer al
Definition: tunnel.cc:88
AnyP::ProtocolVersion http_ver
Definition: Message.h:73
void prepForPeering(const CachePeer &peer)
get ready to be sent to the given cache_peer, including originserver
Definition: HttpRequest.cc:457
char * p
Definition: membanger.c:43
void FREE(void *)
Definition: forward.h:36
int conn
the current server connection FD
Definition: Transport.cc:26
static CNCB tunnelConnectDone
Definition: tunnel.cc:233
void * callback_data
Definition: errorpage.h:188
int default_write_method(int, const char *, int)
Definition: fd.cc:156
Connection server
Definition: tunnel.cc:160
time_t squid_curtime
Definition: stub_time.cc:17
ErrorState * savedError
details of the "last tunneling attempt" failure (if it failed)
Definition: tunnel.cc:214
void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err)
Definition: errorpage.cc:744
void prepForDirect()
get ready to be sent directly to an origin server, excluding originserver
Definition: HttpRequest.cc:467
static Comm::ConnectionPointer borrowPinnedConnection(HttpRequest *request)
Definition: tunnel.cc:1015
bool waitingForConnectExchange
Whether we are waiting for the CONNECT request/response exchange with the peer.
Definition: tunnel.cc:168
SBuf preReadClientData
Definition: tunnel.cc:164
ByteCounter kbytes_in
Definition: StatCounters.h:45
char * url
Definition: tunnel.cc:85
void * BIO_get_data(BIO *table)
Definition: openssl.h:60
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void connectedToPeer(Security::EncryptorAnswer &answer)
callback handler after connection setup (including any encryption)
Definition: tunnel.cc:992
struct StatCounters::@128 server
void noteConnectFailure(const Comm::ConnectionPointer &conn)
reacts to a failure to establish the given TCP connection
Definition: tunnel.cc:851
static const char *const conn_established
Definition: tunnel.cc:231
void startConnecting()
Definition: tunnel.cc:1106
void GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Sets initial TOS value and Netfilter for the future outgoing connection.
Definition: FwdState.cc:1521
SBuf leftovers
peer-generated bytes after a positive answer (or empty)
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
static void tunnelStartShoveling(TunnelStateData *tunnelState)
Definition: tunnel.cc:729
time_t lifetime
Definition: SquidConfig.h:108
Comm::ConnectionPointer conn
Definition: CommCalls.h:85
const char * xstrerr(int error)
Definition: xstrerror.cc:83
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
Http::StreamPointer front() const
get the first request context in the pipeline
Definition: Pipeline.cc:28
static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
Definition: tunnel.cc:564
void const char HLPCB void * data
Definition: stub_helper.cc:16
LogTags logType
the processing tags associated with this request transaction.
void EVH(void *)
Definition: event.h:19
bool subscribed
whether noteDestination() and noteDestinationsEnd() calls are allowed
static CLCB tunnelClientClosed
Definition: tunnel.cc:236
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1292
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
CbcPointer< TunnelStateData > tunnel_
Definition: tunnel.cc:204
void update(const LogTags_ot t)
Definition: LogTags.cc:44
Ip::Address client_addr
Definition: HttpRequest.h:149
virtual void noteDestinationsEnd(ErrorState *selectionError) override
Definition: tunnel.cc:1050
static CTCB tunnelTimeout
Definition: tunnel.cc:237
bool clientExpectsConnectResponse() const
Whether the client sent a CONNECT request to us.
Definition: tunnel.cc:96
char * peer_host
Definition: HttpRequest.h:166
void comm_read(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer &callback)
Definition: Read.h:59
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
void clear()
make pointer not set; does not invalidate cbdata
Definition: CbcPointer.h:144
struct SquidConfig::@112 accessList
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:230
void tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
resumes operations after the (possibly failed) HTTP CONNECT exchange
Definition: tunnel.cc:782
acl_access * miss
Definition: SquidConfig.h:361
Http::StatusCode httpStatus
Definition: errorpage.h:174
bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to)
Definition: tunnel.cc:458
TunnelStateData(ClientHttpRequest *)
Definition: tunnel.cc:296
AccessLogEntry::Pointer al
access.log entry
void copyRead(Connection &from, IOCB *completion)
Definition: tunnel.cc:678
LogTags * logTag_ptr
pointer for logging Squid processing code
Definition: tunnel.cc:162
class AccessLogEntry::HttpDetails http
void host(const char *src)
Definition: Uri.cc:47
void dial(AsyncCall &call)
Definition: tunnel.cc:194
virtual void print(std::ostream &os) const
Definition: tunnel.cc:195
SBuf consume(size_type n=npos)
Definition: SBuf.cc:491
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
struct ClientHttpRequest::Out out
CBDATA_CHILD(TunnelStateData)
void CLCB(const CommCloseCbParams &params)
Definition: CommCalls.h:42
void const char * buf
Definition: stub_helper.cc:16
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
Definition: CommCalls.h:36
void eventDelete(EVH *func, void *arg)
Definition: event.cc:131
Gives Security::PeerConnector access to Answer in the TunnelStateData callback dialer.
Definition: tunnel.cc:184
Flag
Definition: Flag.h:15
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
static CLCB tunnelServerClosed
Definition: tunnel.cc:235
void connectToPeer()
continue to set up connection to a peer, going async for SSL peers
Definition: tunnel.cc:974
void resetPeerNotes(const Comm::ConnectionPointer &server, const char *requestedHost)
Definition: access_log.cc:250
void stopPeerClock(const bool force)
Definition: access_log.cc:303
static EVH tunnelDelayedClientRead
Definition: tunnel.cc:238
struct StatCounters::@127 client_http
int ignoreErrno(int ierrno)
Definition: comm.cc:1477
static EVH tunnelDelayedServerRead
Definition: tunnel.cc:239
void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
Definition: tunnel.cc:521
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:109
RequestFlags flags
Definition: HttpRequest.h:141
void switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn)
Definition: tunnel.cc:1160
Ip::Address remote
Definition: Connection.h:138
void Comm::ConnectionPointer & clientConn
Definition: stub_tunnel.cc:19
#define xmalloc
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
bool intercepted
Definition: RequestFlags.h:62
bool no_delay
Definition: CachePeer.h:98
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
struct SquidConfig::@97 Timeout
void copy(size_t len, Connection &from, Connection &to, IOCB *)
Definition: tunnel.cc:501
int bytesWanted(int lower=0, int upper=INT_MAX) const
Definition: tunnel.cc:340
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:71
AsyncCall::Pointer writer
pending Comm::Write callback
Definition: tunnel.cc:143
C * getRaw() const
Definition: RefCount.h:74
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:112
virtual ~TunnelStateData()
Definition: tunnel.cc:322
SBuf inBuf
read I/O buffer for the client connection
Definition: Server.h:110
void CNCB(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data)
Definition: CommCalls.h:35
void sendError(ErrorState *finalError, const char *reason)
Definition: tunnel.cc:1082
Comm::ConnectionPointer clientConnection
Definition: Server.h:97
struct CachePeer::@31 options
void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno)
Definition: tunnel.cc:389
allow_t const & fastCheck()
Definition: Checklist.cc:336
TunnelStateData * readPending
Definition: tunnel.cc:150
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
Definition: CommCalls.h:342
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:412
void notePeerReadyToShovel()
called when negotiations with the peer have been successfully completed
Definition: tunnel.cc:821
void error(int const xerrno)
Definition: tunnel.cc:414
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:961
#define INT_MAX
Definition: types.h:76
void tunnelStart(ClientHttpRequest *http)
Definition: tunnel.cc:928
HttpRequest *const request
Definition: Debug.h:184
int xerrno
Definition: errorpage.h:180
void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry)
Definition: peer_select.cc:193
Ssl::BumpStep step
The SSL bumping step.
Definition: ServerBump.h:54
void netdbPingSite(const char *hostname)
Definition: net_db.cc:909
void ERCB(int fd, void *, size_t)
error page callback
Definition: errorpage.h:31
#define DBG_DATA
Definition: Debug.h:48
void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno)
Definition: tunnel.cc:433
const char * getHost() const
Definition: tunnel.cc:91
static ERCB tunnelErrorComplete
Definition: tunnel.cc:234
ByteCounter kbytes_out
Definition: StatCounters.h:46
HttpRequest::Pointer request
Definition: tunnel.cc:87
TunnelStateData & operator=(const TunnelStateData &)
#define xfree
void write(const char *b, int size, AsyncCall::Pointer &callback, FREE *free_func)
writes &#39;b&#39; buffer, setting the &#39;writer&#39; member to &#39;callback&#39;.
Definition: tunnel.cc:587
CbcPointer< ErrorState > squidError
problem details (or nil)
SBuf preReadServerData
Definition: tunnel.cc:165
uint64_t payloadData
total size of payload block(s) excluding transfer encoding overheads
Definition: MessageSizes.h:24
struct StatCounters::@128::@137 all
static DelayId DelayClient(ClientHttpRequest *, HttpReply *reply=nullptr)
Definition: DelayId.cc:67
MessageSizes clientRequestSz
counters for the original request received from client
void setDelayId(DelayId const &)
Definition: tunnel.cc:1151
bool noConnections() const
Definition: tunnel.cc:1144
int commSetConnTimeout(const Comm::ConnectionPointer &conn, int timeout, AsyncCall::Pointer &callback)
Definition: comm.cc:552
class SquidConfig Config
Definition: SquidConfig.cc:12
void Controller::create() STUB void Controller Controller nil
#define NULL
Definition: types.h:166
Connection client
Definition: tunnel.cc:160
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: tunnel.cc:200
int size
Definition: ModDevPoll.cc:77
const char * rawContent() const
Definition: SBuf.cc:519
void dataSent(size_t amount)
Definition: tunnel.cc:574
time_t read
Definition: SquidConfig.h:106
void bytesIn(int const &)
Definition: tunnel.cc:351
#define false
Definition: GnuRegex.c:233
char * host
Definition: CachePeer.h:37
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
Definition: Write.cc:35
static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
Definition: tunnel.cc:511
virtual bool canDial(AsyncCall &call)
Definition: tunnel.cc:193
Comm::ConnectionList serverDestinations
Definition: tunnel.cc:89
Pipeline pipeline
set of requests waiting to be serviced
Definition: Server.h:115
bool forceTunnel
whether to forward via TunnelStateData (instead of FwdState)
Definition: RequestFlags.h:111
uint8_t delayedLoops
how many times a read on this connection has been postponed.
Definition: tunnel.cc:147

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors