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 "HappyConnOpener.h"
30 #include "http.h"
31 #include "http/Stream.h"
32 #include "HttpRequest.h"
33 #include "icmp/net_db.h"
34 #include "ip/QosConfig.h"
35 #include "LogTags.h"
36 #include "MemBuf.h"
37 #include "neighbors.h"
38 #include "PeerSelectState.h"
39 #include "ResolvedPeers.h"
40 #include "sbuf/SBuf.h"
42 #include "SquidConfig.h"
43 #include "SquidTime.h"
44 #include "StatCounters.h"
45 #if USE_OPENSSL
46 #include "ssl/bio.h"
47 #include "ssl/ServerBump.h"
48 #endif
49 #include "tools.h"
50 #if USE_DELAY_POOLS
51 #include "DelayId.h"
52 #endif
53 
54 #include <climits>
55 #include <cerrno>
56 
62 /*
63  * TODO 1: implement a read/write API on ConnStateData to send/receive blocks
64  * of pre-formatted data. Then we can use that as the client side of the tunnel
65  * instead of re-implementing it here and occasionally getting the ConnStateData
66  * read/write state wrong.
67  *
68  * TODO 2: then convert this into a AsyncJob, possibly a child of 'Server'
69  */
71 {
73 
74 public:
76  virtual ~TunnelStateData();
77  TunnelStateData(const TunnelStateData &); // do not implement
78  TunnelStateData &operator =(const TunnelStateData &); // do not implement
79 
80  class Connection;
81  static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
82  static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
83  static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
84  static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
85 
86  bool noConnections() const;
87  char *url;
91 
92  const char * getHost() const {
93  return (server.conn != NULL && server.conn->getPeer() ? server.conn->getPeer()->host : request->url.host());
94  };
95 
98  // If we are forcing a tunnel after receiving a client CONNECT, then we
99  // have already responded to that CONNECT before tunnel.cc started.
100  if (request && request->flags.forceTunnel)
101  return false;
102 #if USE_OPENSSL
103  // We are bumping and we had already send "OK CONNECTED"
104  if (http.valid() && http->getConn() && http->getConn()->serverBump() && http->getConn()->serverBump()->step > Ssl::bumpStep1)
105  return false;
106 #endif
107  return !(request != NULL &&
108  (request->flags.interceptTproxy || request->flags.intercepted));
109  }
110 
113  void startConnecting();
114 
116  void notePeerReadyToShovel();
117 
119  {
120 
121  public:
122  Connection() : len (0), buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), delayedLoops(0),
124 
125  ~Connection();
126 
127  int bytesWanted(int lower=0, int upper = INT_MAX) const;
128  void bytesIn(int const &);
129 #if USE_DELAY_POOLS
130 
131  void setDelayId(DelayId const &);
132 #endif
133 
134  void error(int const xerrno);
135  int debugLevelForError(int const xerrno) const;
136  void closeIfOpen();
137  void dataSent (size_t amount);
139  void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func);
140  int len;
141  char *buf;
143  uint64_t *size_ptr; /* pointer to size in an ConnStateData for logging */
144 
146  uint8_t delayedLoops;
147 
148  // XXX: make these an AsyncCall when event API can handle them
151 
152 #if USE_DELAY_POOLS
153 
155 #endif
156 
157  };
158 
160  int *status_ptr;
162 
165  time_t startTime;
171 
172  // AsyncCalls which we set and may need cancelling.
173  struct {
175  } calls;
176 
177  void copyRead(Connection &from, IOCB *completion);
178 
180  void connectToPeer();
181 
182  /* PeerSelectionInitiator API */
183  virtual void noteDestination(Comm::ConnectionPointer conn) override;
184  virtual void noteDestinationsEnd(ErrorState *selectionError) override;
185 
186  void syncHierNote(const Comm::ConnectionPointer &server, const char *origin);
187 
191 
194  bool opening() const { return connOpener.set(); }
195 
196  void cancelOpening(const char *reason);
197 
199  void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused);
200 
201  void notifyConnOpener();
202 
203  void saveError(ErrorState *finalError);
204  void sendError(ErrorState *finalError, const char *reason);
205 
206 private:
209  {
210  public:
212 
214  method_(method), tunnel_(tunnel), answer_() {}
215 
216  /* CallDialer API */
217  virtual bool canDial(AsyncCall &call) { return tunnel_.valid(); }
218  void dial(AsyncCall &call) { ((&(*tunnel_))->*method_)(answer_); }
219  virtual void print(std::ostream &os) const {
220  os << '(' << tunnel_.get() << ", " << answer_ << ')';
221  }
222 
223  /* Security::PeerConnector::CbDialer API */
224  virtual Security::EncryptorAnswer &answer() { return answer_; }
225 
226  private:
230  };
231 
232  void usePinned();
233 
236 
238  ErrorState *savedError = nullptr;
239 
242 
243 public:
244  bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to);
245  void copy(size_t len, Connection &from, Connection &to, IOCB *);
246  void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno);
247  void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno);
248  void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
249  void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
250 
251  void copyClientBytes();
252  void copyServerBytes();
253 };
254 
255 static const char *const conn_established = "HTTP/1.1 200 Connection established\r\n\r\n";
256 
263 
264 static void
266 {
267  TunnelStateData *tunnelState = (TunnelStateData *)params.data;
268  debugs(26, 3, HERE << tunnelState->server.conn);
269  tunnelState->server.conn = NULL;
270  tunnelState->server.writer = NULL;
271 
272  if (tunnelState->request != NULL)
273  tunnelState->request->hier.stopPeerClock(false);
274 
275  if (tunnelState->noConnections()) {
276  // ConnStateData pipeline should contain the CONNECT we are performing
277  // but it may be invalid already (bug 4392)
278  if (tunnelState->http.valid() && tunnelState->http->getConn()) {
279  auto ctx = tunnelState->http->getConn()->pipeline.front();
280  if (ctx != nullptr)
281  ctx->finished();
282  }
283  delete tunnelState;
284  return;
285  }
286 
287  if (!tunnelState->client.writer) {
288  tunnelState->client.conn->close();
289  return;
290  }
291 }
292 
293 static void
295 {
296  TunnelStateData *tunnelState = (TunnelStateData *)params.data;
297  debugs(26, 3, HERE << tunnelState->client.conn);
298  tunnelState->client.conn = NULL;
299  tunnelState->client.writer = NULL;
300 
301  if (tunnelState->noConnections()) {
302  // ConnStateData pipeline should contain the CONNECT we are performing
303  // but it may be invalid already (bug 4392)
304  if (tunnelState->http.valid() && tunnelState->http->getConn()) {
305  auto ctx = tunnelState->http->getConn()->pipeline.front();
306  if (ctx != nullptr)
307  ctx->finished();
308  }
309  delete tunnelState;
310  return;
311  }
312 
313  if (!tunnelState->server.writer) {
314  tunnelState->server.conn->close();
315  return;
316  }
317 }
318 
324 {
325  debugs(26, 3, "TunnelStateData constructed this=" << this);
328 
329  assert(clientRequest);
330  url = xstrdup(clientRequest->uri);
331  request = clientRequest->request;
332  Must(request);
333  server.size_ptr = &clientRequest->out.size;
334  client.size_ptr = &clientRequest->al->http.clientRequestSz.payloadData;
335  status_ptr = &clientRequest->al->http.code;
336  logTag_ptr = &clientRequest->logType;
337  al = clientRequest->al;
338  http = clientRequest;
339 
340  client.conn = clientRequest->getConn()->clientConnection;
342 
343  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
346 }
347 
349 {
350  debugs(26, 3, "TunnelStateData destructed this=" << this);
352  xfree(url);
353  if (opening())
354  cancelOpening("~TunnelStateData");
355  delete savedError;
356 }
357 
359 {
360  if (readPending)
361  eventDelete(readPendingFunc, readPending);
362 
363  safe_free(buf);
364 }
365 
366 int
367 TunnelStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
368 {
369 #if USE_DELAY_POOLS
370  return delayId.bytesWanted(lowerbound, upperbound);
371 #else
372 
373  return upperbound;
374 #endif
375 }
376 
377 void
379 {
380  debugs(26, 3, HERE << "len=" << len << " + count=" << count);
381 #if USE_DELAY_POOLS
382  delayId.bytesIn(count);
383 #endif
384 
385  len += count;
386 }
387 
390 void
392 {
393  request->hier.resetPeerNotes(conn, origin);
394  if (al)
395  al->hier.resetPeerNotes(conn, origin);
396 }
397 
398 int
400 {
401 #ifdef ECONNRESET
402 
403  if (xerrno == ECONNRESET)
404  return 2;
405 
406 #endif
407 
408  if (ignoreErrno(xerrno))
409  return 3;
410 
411  return 1;
412 }
413 
414 /* Read from server side and queue it for writing to the client */
415 void
416 TunnelStateData::ReadServer(const Comm::ConnectionPointer &c, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
417 {
418  TunnelStateData *tunnelState = (TunnelStateData *)data;
419  assert(cbdataReferenceValid(tunnelState));
420  debugs(26, 3, HERE << c);
421 
422  tunnelState->readServer(buf, len, errcode, xerrno);
423 }
424 
425 void
426 TunnelStateData::readServer(char *, size_t len, Comm::Flag errcode, int xerrno)
427 {
428  debugs(26, 3, HERE << server.conn << ", read " << len << " bytes, err=" << errcode);
430 
431  /*
432  * Bail out early on Comm::ERR_CLOSING
433  * - close handlers will tidy up for us
434  */
435 
436  if (errcode == Comm::ERR_CLOSING)
437  return;
438 
439  if (len > 0) {
440  server.bytesIn(len);
441  statCounter.server.all.kbytes_in += len;
442  statCounter.server.other.kbytes_in += len;
444  }
445 
446  if (keepGoingAfterRead(len, errcode, xerrno, server, client))
448 }
449 
450 void
452 {
453  debugs(50, debugLevelForError(xerrno), HERE << conn << ": read/write failure: " << xstrerr(xerrno));
454 
455  if (!ignoreErrno(xerrno))
456  conn->close();
457 }
458 
459 /* Read from client side and queue it for writing to the server */
460 void
461 TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
462 {
463  TunnelStateData *tunnelState = (TunnelStateData *)data;
464  assert (cbdataReferenceValid (tunnelState));
465 
466  tunnelState->readClient(buf, len, errcode, xerrno);
467 }
468 
469 void
470 TunnelStateData::readClient(char *, size_t len, Comm::Flag errcode, int xerrno)
471 {
472  debugs(26, 3, HERE << client.conn << ", read " << len << " bytes, err=" << errcode);
474 
475  /*
476  * Bail out early on Comm::ERR_CLOSING
477  * - close handlers will tidy up for us
478  */
479 
480  if (errcode == Comm::ERR_CLOSING)
481  return;
482 
483  if (len > 0) {
484  client.bytesIn(len);
486  }
487 
488  if (keepGoingAfterRead(len, errcode, xerrno, client, server))
490 }
491 
494 bool
496 {
497  debugs(26, 3, HERE << "from={" << from.conn << "}, to={" << to.conn << "}");
498 
499  /* I think this is to prevent free-while-in-a-callback behaviour
500  * - RBC 20030229
501  * from.conn->close() / to.conn->close() done here trigger close callbacks which may free TunnelStateData
502  */
503  const CbcPointer<TunnelStateData> safetyLock(this);
504 
505  /* Bump the source connection read timeout on any activity */
506  if (Comm::IsConnOpen(from.conn)) {
507  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
509  commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
510  }
511 
512  /* Bump the dest connection read timeout on any activity */
513  /* see Bug 3659: tunnels can be weird, with very long one-way transfers */
514  if (Comm::IsConnOpen(to.conn)) {
515  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
517  commSetConnTimeout(to.conn, Config.Timeout.read, timeoutCall);
518  }
519 
520  if (errcode)
521  from.error (xerrno);
522  else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
523  debugs(26, 3, HERE << "Nothing to write or client gone. Terminate the tunnel.");
524  from.conn->close();
525 
526  /* Only close the remote end if we've finished queueing data to it */
527  if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
528  to.conn->close();
529  }
530  } else if (cbdataReferenceValid(this)) {
531  return true;
532  }
533 
534  return false;
535 }
536 
537 void
538 TunnelStateData::copy(size_t len, Connection &from, Connection &to, IOCB *completion)
539 {
540  debugs(26, 3, HERE << "Schedule Write");
541  AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler",
542  CommIoCbPtrFun(completion, this));
543  to.write(from.buf, len, call, NULL);
544 }
545 
546 /* Writes data from the client buffer to the server side */
547 void
548 TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
549 {
550  TunnelStateData *tunnelState = (TunnelStateData *)data;
551  assert (cbdataReferenceValid (tunnelState));
552  tunnelState->server.writer = NULL;
553 
554  tunnelState->writeServerDone(buf, len, flag, xerrno);
555 }
556 
557 void
558 TunnelStateData::writeServerDone(char *, size_t len, Comm::Flag flag, int xerrno)
559 {
560  debugs(26, 3, HERE << server.conn << ", " << len << " bytes written, flag=" << flag);
561 
562  if (flag == Comm::ERR_CLOSING)
563  return;
564 
566 
567  /* Error? */
568  if (flag != Comm::OK) {
569  debugs(26, 4, "to-server write failed: " << xerrno);
570  server.error(xerrno); // may call comm_close
571  return;
572  }
573 
574  /* EOF? */
575  if (len == 0) {
576  debugs(26, 4, HERE << "No read input. Closing server connection.");
577  server.conn->close();
578  return;
579  }
580 
581  /* Valid data */
582  statCounter.server.all.kbytes_out += len;
583  statCounter.server.other.kbytes_out += len;
584  client.dataSent(len);
585 
586  /* If the other end has closed, so should we */
587  if (!Comm::IsConnOpen(client.conn)) {
588  debugs(26, 4, HERE << "Client gone away. Shutting down server connection.");
589  server.conn->close();
590  return;
591  }
592 
593  const CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
594 
595  if (cbdataReferenceValid(this))
596  copyClientBytes();
597 }
598 
599 /* Writes data from the server buffer to the client side */
600 void
601 TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
602 {
603  TunnelStateData *tunnelState = (TunnelStateData *)data;
604  assert (cbdataReferenceValid (tunnelState));
605  tunnelState->client.writer = NULL;
606 
607  tunnelState->writeClientDone(buf, len, flag, xerrno);
608 }
609 
610 void
612 {
613  debugs(26, 3, HERE << "len=" << len << " - amount=" << amount);
614  assert(amount == (size_t)len);
615  len =0;
616  /* increment total object size */
617 
618  if (size_ptr)
619  *size_ptr += amount;
620 
621 }
622 
623 void
625 {
626  writer = callback;
627  Comm::Write(conn, b, size, callback, free_func);
628 }
629 
630 void
631 TunnelStateData::writeClientDone(char *, size_t len, Comm::Flag flag, int xerrno)
632 {
633  debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
634 
635  if (flag == Comm::ERR_CLOSING)
636  return;
637 
638  /* Error? */
639  if (flag != Comm::OK) {
640  debugs(26, 4, "from-client read failed: " << xerrno);
641  client.error(xerrno); // may call comm_close
642  return;
643  }
644 
645  /* EOF? */
646  if (len == 0) {
647  debugs(26, 4, HERE << "Closing client connection due to 0 byte read.");
648  client.conn->close();
649  return;
650  }
651 
652  /* Valid data */
654  server.dataSent(len);
655 
656  /* If the other end has closed, so should we */
657  if (!Comm::IsConnOpen(server.conn)) {
658  debugs(26, 4, HERE << "Server has gone away. Terminating client connection.");
659  client.conn->close();
660  return;
661  }
662 
663  CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
664 
665  if (cbdataReferenceValid(this))
666  copyServerBytes();
667 }
668 
669 static void
671 {
672  TunnelStateData *tunnelState = static_cast<TunnelStateData *>(io.data);
673  debugs(26, 3, HERE << io.conn);
674  /* Temporary lock to protect our own feets (comm_close -> tunnelClientClosed -> Free) */
675  CbcPointer<TunnelStateData> safetyLock(tunnelState);
676 
677  tunnelState->client.closeIfOpen();
678  tunnelState->server.closeIfOpen();
679 }
680 
681 void
683 {
684  if (Comm::IsConnOpen(conn))
685  conn->close();
686 }
687 
688 static void
690 {
691  if (!data)
692  return;
693 
694  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
695  tunnel->client.readPending = NULL;
696  static uint64_t counter=0;
697  debugs(26, 7, "Client read(2) delayed " << ++counter << " times");
698  tunnel->copyRead(tunnel->client, TunnelStateData::ReadClient);
699 }
700 
701 static void
703 {
704  if (!data)
705  return;
706 
707  TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
708  tunnel->server.readPending = NULL;
709  static uint64_t counter=0;
710  debugs(26, 7, "Server read(2) delayed " << ++counter << " times");
711  tunnel->copyRead(tunnel->server, TunnelStateData::ReadServer);
712 }
713 
714 void
716 {
717  assert(from.len == 0);
718  // If only the minimum permitted read size is going to be attempted
719  // then we schedule an event to try again in a few I/O cycles.
720  // Allow at least 1 byte to be read every (0.3*10) seconds.
721  int bw = from.bytesWanted(1, SQUID_TCP_SO_RCVBUF);
722  if (bw == 1 && ++from.delayedLoops < 10) {
723  from.readPending = this;
724  eventAdd("tunnelDelayedServerRead", from.readPendingFunc, from.readPending, 0.3, true);
725  return;
726  }
727 
728  AsyncCall::Pointer call = commCbCall(5,4, "TunnelBlindCopyReadHandler",
729  CommIoCbPtrFun(completion, this));
730  comm_read(from.conn, from.buf, bw, call);
731 }
732 
733 void
735 {
736  if (preReadClientData.length()) {
737  size_t copyBytes = preReadClientData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadClientData.length();
738  memcpy(client.buf, preReadClientData.rawContent(), copyBytes);
739  preReadClientData.consume(copyBytes);
740  client.bytesIn(copyBytes);
741  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, client, server))
743  } else
745 }
746 
747 void
749 {
750  if (preReadServerData.length()) {
751  size_t copyBytes = preReadServerData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadServerData.length();
752  memcpy(server.buf, preReadServerData.rawContent(), copyBytes);
753  preReadServerData.consume(copyBytes);
754  server.bytesIn(copyBytes);
755  if (keepGoingAfterRead(copyBytes, Comm::OK, 0, server, client))
757  } else
759 }
760 
765 static void
767 {
768  assert(!tunnelState->waitingForConnectExchange);
769  *tunnelState->status_ptr = Http::scOkay;
770  if (tunnelState->logTag_ptr)
771  tunnelState->logTag_ptr->update(LOG_TCP_TUNNEL);
772  if (cbdataReferenceValid(tunnelState)) {
773 
774  // Shovel any payload already pushed into reply buffer by the server response
775  if (!tunnelState->server.len)
776  tunnelState->copyServerBytes();
777  else {
778  debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
779  tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
780  }
781 
782  if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->inBuf.isEmpty()) {
783  SBuf * const in = &tunnelState->http->getConn()->inBuf;
784  debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << *in << "\n----------");
785  tunnelState->preReadClientData.append(*in);
786  in->consume(); // ConnStateData buffer accounting after the shuffle.
787  }
788  tunnelState->copyClientBytes();
789  }
790 }
791 
797 static void
798 tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
799 {
800  TunnelStateData *tunnelState = (TunnelStateData *)data;
801  debugs(26, 3, HERE << conn << ", flag=" << flag);
802  tunnelState->client.writer = NULL;
803 
804  if (flag != Comm::OK) {
805  *tunnelState->status_ptr = Http::scInternalServerError;
806  tunnelErrorComplete(conn->fd, data, 0);
807  return;
808  }
809 
810  if (auto http = tunnelState->http.get()) {
811  http->out.headers_sz += len;
812  http->out.size += len;
813  }
814 
815  tunnelStartShoveling(tunnelState);
816 }
817 
818 void
820 {
821  server.len = 0;
822 
823  if (logTag_ptr)
825 
826  if (answer.peerResponseStatus != Http::scNone)
827  *status_ptr = answer.peerResponseStatus;
828 
830 
831  if (answer.positive()) {
832  // copy any post-200 OK bytes to our buffer
833  preReadServerData = answer.leftovers;
835  return;
836  }
837 
838  // TODO: Reuse to-peer connections after a CONNECT error response.
839 
840  // TODO: We can and, hence, should close now, but tunnelServerClosed()
841  // cannot yet tell whether ErrorState is still writing an error response.
842  // server.closeIfOpen();
843 
845  // closing the non-HTTP client connection is the best we can do
846  debugs(50, 3, server.conn << " closing on CONNECT-to-peer error");
848  return;
849  }
850 
851  ErrorState *error = answer.squidError.get();
852  Must(error);
853  answer.squidError.clear(); // preserve error for errorSendComplete()
854  sendError(error, "tunneler returns error");
855 }
856 
857 void
859 {
861  tunnelStartShoveling(this); // ssl-bumped connection, be quiet
862  else {
864  AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
866  client.write(conn_established, strlen(conn_established), call, nullptr);
867  }
868 }
869 
870 static void
871 tunnelErrorComplete(int fd/*const Comm::ConnectionPointer &*/, void *data, size_t)
872 {
873  TunnelStateData *tunnelState = (TunnelStateData *)data;
874  debugs(26, 3, HERE << "FD " << fd);
875  assert(tunnelState != NULL);
876  /* temporary lock to save our own feets (comm_close -> tunnelClientClosed -> Free) */
877  CbcPointer<TunnelStateData> safetyLock(tunnelState);
878 
879  if (Comm::IsConnOpen(tunnelState->client.conn))
880  tunnelState->client.conn->close();
881 
882  if (Comm::IsConnOpen(tunnelState->server.conn))
883  tunnelState->server.conn->close();
884 }
885 
886 void
888 {
889  calls.connector = nullptr;
890  connOpener.clear();
891 
892  if (const auto error = answer.error.get()) {
893  syncHierNote(answer.conn, request->url.host());
894  saveError(error);
895  answer.error.clear(); // savedError has it now
896  sendError(savedError, "tried all destinations");
897  return;
898  }
899 
900  connectDone(answer.conn, request->url.host(), answer.reused);
901 }
902 
903 void
904 TunnelStateData::connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
905 {
906  Must(Comm::IsConnOpen(conn));
907  server.conn = conn;
908 
909  if (reused)
911  // else Comm::ConnOpener already applied proper/current markings
912 
914 
915  request->hier.resetPeerNotes(conn, origin);
916  if (al)
917  al->hier.resetPeerNotes(conn, origin);
918 
919 #if USE_DELAY_POOLS
920  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
921  if (conn->getPeer() && conn->getPeer()->options.no_delay)
923 #endif
924 
926 
927  request->peer_host = conn->getPeer() ? conn->getPeer()->host : nullptr;
929 
930  bool toOrigin = false; // same semantics as StateFlags::toOrigin
931  if (const auto * const peer = conn->getPeer()) {
932  request->prepForPeering(*peer);
933  toOrigin = peer->options.originserver;
934  } else {
936  toOrigin = true;
937  }
938 
939  if (!toOrigin)
940  connectToPeer();
941  else {
943  }
944 
945  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
947  commSetConnTimeout(conn, Config.Timeout.read, timeoutCall);
948 }
949 
950 void
952 {
953  debugs(26, 3, HERE);
954  /* Create state structure. */
955  TunnelStateData *tunnelState = NULL;
956  ErrorState *err = NULL;
957  HttpRequest *request = http->request;
958  char *url = http->uri;
959 
960  /*
961  * client_addr.isNoAddr() indicates this is an "internal" request
962  * from peer_digest.c, asn.c, netdb.c, etc and should always
963  * be allowed. yuck, I know.
964  */
965 
966  if (Config.accessList.miss && !request->client_addr.isNoAddr()) {
967  /*
968  * Check if this host is allowed to fetch MISSES from us (miss_access)
969  * default is to allow.
970  */
972  ch.al = http->al;
973  ch.src_addr = request->client_addr;
974  ch.my_addr = request->my_addr;
975  ch.syncAle(request, http->log_uri);
976  if (ch.fastCheck().denied()) {
977  debugs(26, 4, HERE << "MISS access forbidden.");
978  err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request, http->al);
979  http->al->http.code = Http::scForbidden;
980  errorSend(http->getConn()->clientConnection, err);
981  return;
982  }
983  }
984 
985  debugs(26, 3, request->method << ' ' << url << ' ' << request->http_ver);
986  ++statCounter.server.all.requests;
987  ++statCounter.server.other.requests;
988 
989  tunnelState = new TunnelStateData(http);
990 #if USE_DELAY_POOLS
991  tunnelState->server.setDelayId(DelayId::DelayClient(http));
992 #endif
993  tunnelState->startSelectingDestinations(request, http->al, nullptr);
994 }
995 
996 void
998 {
999  if (CachePeer *p = server.conn->getPeer()) {
1000  if (p->secure.encryptTransport) {
1002  "TunnelStateData::ConnectedToPeer",
1004  auto *connector = new Security::BlindPeerConnector(request, server.conn, callback, al);
1005  AsyncJob::Start(connector); // will call our callback
1006  return;
1007  }
1008  }
1009 
1011  connectedToPeer(nil);
1012 }
1013 
1014 void
1016 {
1017  if (ErrorState *error = answer.error.get()) {
1018  answer.error.clear(); // sendError() will own the error
1019  sendError(error, "TLS peer connection error");
1020  return;
1021  }
1022 
1024 
1026  "TunnelStateData::tunnelEstablishmentDone",
1028  const auto tunneler = new Http::Tunneler(server.conn, request, callback, Config.Timeout.lifetime, al);
1029 #if USE_DELAY_POOLS
1030  tunneler->setDelayId(server.delayId);
1031 #endif
1032  AsyncJob::Start(tunneler);
1034  // and wait for the tunnelEstablishmentDone() call
1035 }
1036 
1037 void
1039 {
1040  destinationsFound = true;
1041 
1042  if (!path) { // decided to use a pinned connection
1043  // We can call usePinned() without fear of clashing with an earlier
1044  // forwarding attempt because PINNED must be the first destination.
1046  usePinned();
1047  return;
1048  }
1049 
1050  destinations->addPath(path);
1051 
1052  if (Comm::IsConnOpen(server.conn)) {
1053  // We are already using a previously opened connection but also
1054  // receiving destinations in case we need to re-forward.
1055  Must(!opening());
1056  return;
1057  }
1058 
1059  if (opening()) {
1060  notifyConnOpener();
1061  return; // and continue to wait for tunnelConnectDone() callback
1062  }
1063 
1064  startConnecting();
1065 }
1066 
1067 void
1069 {
1072  if (!destinationsFound) {
1073 
1074  if (selectionError)
1075  return sendError(selectionError, "path selection has failed");
1076 
1077  if (savedError)
1078  return sendError(savedError, "all found paths have failed");
1079 
1081  "path selection found no paths");
1082  }
1083  // else continue to use one of the previously noted destinations;
1084  // if all of them fail, tunneling as whole will fail
1085  Must(!selectionError); // finding at least one path means selection succeeded
1086 
1087  if (Comm::IsConnOpen(server.conn)) {
1088  // We are already using a previously opened connection but also
1089  // receiving destinations in case we need to re-forward.
1090  Must(!opening());
1091  return;
1092  }
1093 
1094  Must(opening()); // or we would be stuck with nothing to do or wait for
1095  notifyConnOpener();
1096 }
1097 
1099 void
1101 {
1102  debugs(26, 4, savedError << " ? " << error);
1103  assert(error);
1104  delete savedError; // may be nil
1105  savedError = error;
1106 }
1107 
1110 void
1111 TunnelStateData::sendError(ErrorState *finalError, const char *reason)
1112 {
1113  debugs(26, 3, "aborting transaction for " << reason);
1114 
1115  if (request)
1116  request->hier.stopPeerClock(false);
1117 
1118  if (opening())
1119  cancelOpening(reason);
1120 
1121  assert(finalError);
1122 
1123  // get rid of any cached error unless that is what the caller is sending
1124  if (savedError != finalError)
1125  delete savedError; // may be nil
1126  savedError = nullptr;
1127 
1128  // we cannot try other destinations after responding with an error
1129  PeerSelectionInitiator::subscribed = false; // may already be false
1130 
1131  *status_ptr = finalError->httpStatus;
1132  finalError->callback = tunnelErrorComplete;
1133  finalError->callback_data = this;
1134  errorSend(client.conn, finalError);
1135 }
1136 
1141 void
1143 {
1144  assert(calls.connector);
1145  calls.connector->cancel(reason);
1146  calls.connector = nullptr;
1147  notifyConnOpener();
1148  connOpener.clear();
1149 }
1150 
1151 void
1153 {
1154  if (request)
1156 
1157  assert(!destinations->empty());
1158 
1159  calls.connector = asyncCall(17, 5, "TunnelStateData::noteConnection", HappyConnOpener::CbDialer<TunnelStateData>(&TunnelStateData::noteConnection, this));
1160  const auto cs = new HappyConnOpener(destinations, calls.connector, request, startTime, 0, al);
1161  cs->setHost(request->url.host());
1162  cs->setRetriable(false);
1163  cs->allowPersistent(false);
1164  destinations->notificationPending = true; // start() is async
1165  connOpener = cs;
1166  AsyncJob::Start(cs);
1167 }
1168 
1170 void
1172 {
1173  Must(request);
1174  const auto connManager = request->pinnedConnection();
1175  try {
1176  const auto serverConn = ConnStateData::BorrowPinnedConnection(request.getRaw(), al);
1177  debugs(26, 7, "pinned peer connection: " << serverConn);
1178 
1179  // Set HttpRequest pinned related flags for consistency even if
1180  // they are not really used by tunnel.cc code.
1181  request->flags.pinned = true;
1182  if (connManager->pinnedAuth())
1183  request->flags.auth = true;
1184 
1185  // the server may close the pinned connection before this request
1186  const auto reused = true;
1187  connectDone(serverConn, connManager->pinning.host, reused);
1188  } catch (ErrorState * const error) {
1189  syncHierNote(nullptr, connManager ? connManager->pinning.host : request->url.host());
1190  // a PINNED path failure is fatal; do not wait for more paths
1191  sendError(error, "pinned path failure");
1192  return;
1193  }
1194 
1195 }
1196 
1198 
1199 bool
1201 {
1203 }
1204 
1205 #if USE_DELAY_POOLS
1206 void
1208 {
1209  delayId = newDelay;
1210 }
1211 
1212 #endif
1213 
1215 void
1217 {
1219  debugs(17, 7, "reusing pending notification");
1220  } else {
1222  CallJobHere(17, 5, connOpener, HappyConnOpener, noteCandidatesChange);
1223  }
1224 }
1225 
1226 #if USE_OPENSSL
1227 void
1229 {
1230  debugs(26,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << srvConn->fd);
1231 
1232  /* Create state structure. */
1233  ++statCounter.server.all.requests;
1234  ++statCounter.server.other.requests;
1235 
1236  auto conn = request->clientConnectionManager.get();
1237  Must(conn);
1238  Http::StreamPointer context = conn->pipeline.front();
1239  Must(context && context->http);
1240 
1241  debugs(26, 3, request->method << " " << context->http->uri << " " << request->http_ver);
1242 
1243  TunnelStateData *tunnelState = new TunnelStateData(context->http);
1244 
1245  // tunnelStartShoveling() drains any buffered from-client data (inBuf)
1246  fd_table[clientConn->fd].useDefaultIo();
1247 
1248  request->hier.resetPeerNotes(srvConn, tunnelState->getHost());
1249 
1250  tunnelState->server.conn = srvConn;
1251 
1252 #if USE_DELAY_POOLS
1253  /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
1254  if (!srvConn->getPeer() || !srvConn->getPeer()->options.no_delay)
1255  tunnelState->server.setDelayId(DelayId::DelayClient(context->http));
1256 #endif
1257 
1258  request->peer_host = srvConn->getPeer() ? srvConn->getPeer()->host : nullptr;
1259  comm_add_close_handler(srvConn->fd, tunnelServerClosed, tunnelState);
1260 
1261  debugs(26, 4, "determine post-connect handling pathway.");
1262  if (const auto peer = srvConn->getPeer())
1263  request->prepForPeering(*peer);
1264  else
1265  request->prepForDirect();
1266 
1267  AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
1268  CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
1269  commSetConnTimeout(srvConn, Config.Timeout.read, timeoutCall);
1270 
1271  // we drain any already buffered from-server data below (rBufData)
1272  fd_table[srvConn->fd].useDefaultIo();
1273 
1274  auto ssl = fd_table[srvConn->fd].ssl.get();
1275  assert(ssl);
1276  BIO *b = SSL_get_rbio(ssl);
1277  Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
1278  tunnelState->preReadServerData = srvBio->rBufData();
1279  tunnelStartShoveling(tunnelState);
1280 }
1281 #endif //USE_OPENSSL
1282 
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
void cancelOpening(const char *reason)
Definition: tunnel.cc:1142
HierarchyLogEntry hier
Definition: HttpRequest.h:157
static Comm::ConnectionPointer BorrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &)
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:416
#define fd_table
Definition: fde.h:174
Ssl::ServerBump * serverBump()
Definition: client_side.h:250
ConnStateData * pinnedConnection()
Definition: HttpRequest.cc:686
struct StatCounters::@130::@139 all
void usePinned()
send request on an existing connection dedicated to the requesting client
Definition: tunnel.cc:1171
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:461
void const char HLPCB * callback
Definition: stub_helper.cc:16
Comm::ConnectionPointer conn
The currently connected connection.
Definition: tunnel.cc:145
int * status_ptr
pointer for logging HTTP status
Definition: tunnel.cc:160
Security::EncryptorAnswer answer_
Definition: tunnel.cc:229
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
void copyClientBytes()
Definition: tunnel.cc:734
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: tunnel.cc:1038
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:88
void CTCB(const CommTimeoutCbParams &params)
Definition: CommCalls.h:39
int debugLevelForError(int const xerrno) const
Definition: tunnel.cc:399
CbcPointer< ErrorState > error
problem details (nil on success)
MyAnswerDialer(Method method, TunnelStateData *tunnel)
Definition: tunnel.cc:213
Definition: SBuf.h:86
struct TunnelStateData::@152 calls
bool isNoAddr() const
Definition: Address.cc:284
Ip::Address src_addr
void syncHierNote(const Comm::ConnectionPointer &server, const char *origin)
Definition: tunnel.cc:391
bool opening() const
Definition: tunnel.cc:194
void copyServerBytes()
Definition: tunnel.cc:748
bool reused
whether conn was open earlier, by/for somebody else
struct StatCounters::@130 server
HttpRequestMethod method
Definition: HttpRequest.h:114
void error(char *format,...)
void ResetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1443
#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:798
Comm::ConnectionPointer conn
ERCB * callback
Definition: errorpage.h:187
#define safe_free(x)
Definition: xalloc.h:73
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:631
StatusCode peerResponseStatus
the status code of the successfully parsed CONNECT response (or scNone)
time_t startTime
Definition: tunnel.cc:165
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:1100
#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:90
AsyncCall dialer for our callback. Gives us access to callback Answer.
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:449
char * p
Definition: membanger.c:43
void FREE(void *)
Definition: forward.h:36
int conn
the current server connection FD
Definition: Transport.cc:26
void * callback_data
Definition: errorpage.h:188
Final result (an open connection or an error) sent to the job initiator.
Connection server
Definition: tunnel.cc:159
time_t squid_curtime
Definition: stub_time.cc:17
Acl::Answer const & fastCheck()
Definition: Checklist.cc:336
void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
Start using an established connection.
Definition: tunnel.cc:904
ErrorState * savedError
details of the "last tunneling attempt" failure (if it failed)
Definition: tunnel.cc:238
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:459
bool waitingForConnectExchange
Whether we are waiting for the CONNECT request/response exchange with the peer.
Definition: tunnel.cc:167
SBuf preReadClientData
Definition: tunnel.cc:163
ByteCounter kbytes_in
Definition: StatCounters.h:45
char * url
Definition: tunnel.cc:87
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:1015
static const char *const conn_established
Definition: tunnel.cc:255
void startConnecting()
Definition: tunnel.cc:1152
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
bool destinationsFinalized
whether all of the available candidate paths received from DNS
Definition: ResolvedPeers.h:64
static void tunnelStartShoveling(TunnelStateData *tunnelState)
Definition: tunnel.cc:766
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:601
void const char HLPCB void * data
Definition: stub_helper.cc:16
LogTags logType
the processing tags associated with this request transaction.
bool notificationPending
whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
Definition: ResolvedPeers.h:67
void EVH(void *)
Definition: event.h:19
bool subscribed
whether noteDestination() and noteDestinationsEnd() calls are allowed
static CLCB tunnelClientClosed
Definition: tunnel.cc:259
#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:228
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:1068
static CTCB tunnelTimeout
Definition: tunnel.cc:260
bool destinationsFound
At least one candidate path found.
Definition: tunnel.cc:170
bool clientExpectsConnectResponse() const
Whether the client sent a CONNECT request to us.
Definition: tunnel.cc:97
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
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:233
void tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
resumes operations after the (possibly failed) HTTP CONNECT exchange
Definition: tunnel.cc:819
struct SquidConfig::@113 accessList
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:495
TunnelStateData(ClientHttpRequest *)
Definition: tunnel.cc:319
AccessLogEntry::Pointer al
access.log entry
void copyRead(Connection &from, IOCB *completion)
Definition: tunnel.cc:715
LogTags * logTag_ptr
pointer for logging Squid processing code
Definition: tunnel.cc:161
class AccessLogEntry::HttpDetails http
void host(const char *src)
Definition: Uri.cc:48
void notifyConnOpener()
makes sure connOpener knows that destinations have changed
Definition: tunnel.cc:1216
void dial(AsyncCall &call)
Definition: tunnel.cc:218
virtual void print(std::ostream &os) const
Definition: tunnel.cc:219
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 StatCounters::@130::@139 other
struct ClientHttpRequest::Out out
CBDATA_CHILD(TunnelStateData)
HappyConnOpenerPointer connOpener
current connection opening job
Definition: tunnel.cc:168
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:208
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:258
void connectToPeer()
continue to set up connection to a peer, going async for SSL peers
Definition: tunnel.cc:997
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:261
int ignoreErrno(int ierrno)
Definition: comm.cc:1477
static EVH tunnelDelayedServerRead
Definition: tunnel.cc:262
void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
Definition: tunnel.cc:558
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:1228
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
void copy(size_t len, Connection &from, Connection &to, IOCB *)
Definition: tunnel.cc:538
int bytesWanted(int lower=0, int upper=INT_MAX) const
Definition: tunnel.cc:367
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
struct StatCounters::@129 client_http
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:71
AsyncCall::Pointer writer
pending Comm::Write callback
Definition: tunnel.cc:142
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:348
SBuf inBuf
read I/O buffer for the client connection
Definition: Server.h:110
void sendError(ErrorState *finalError, const char *reason)
Definition: tunnel.cc:1111
Comm::ConnectionPointer clientConnection
Definition: Server.h:97
AsyncCall::Pointer connector
a call linking us to the ConnOpener producing serverConn.
Definition: tunnel.cc:174
struct CachePeer::@31 options
void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno)
Definition: tunnel.cc:426
struct SquidConfig::@98 Timeout
TunnelStateData * readPending
Definition: tunnel.cc:149
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:858
void error(int const xerrno)
Definition: tunnel.cc:451
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:951
ResolvedPeersPointer destinations
paths for forwarding the request
Definition: tunnel.cc:169
HttpRequest *const request
Definition: Debug.h:184
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 noteConnection(HappyConnOpenerAnswer &)
Definition: tunnel.cc:887
bool denied() const
Definition: Acl.h:149
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:470
const char * getHost() const
Definition: tunnel.cc:92
static ERCB tunnelErrorComplete
Definition: tunnel.cc:257
ByteCounter kbytes_out
Definition: StatCounters.h:46
HttpRequest::Pointer request
Definition: tunnel.cc:89
TunnelStateData & operator=(const TunnelStateData &)
#define xfree
bool set() const
was set but may be invalid
Definition: CbcPointer.h:40
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:624
CbcPointer< ErrorState > squidError
problem details (or nil)
SBuf preReadServerData
Definition: tunnel.cc:164
HierarchyLogEntry hier
uint64_t payloadData
total size of payload block(s) excluding transfer encoding overheads
Definition: MessageSizes.h:24
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:1207
bool noConnections() const
Definition: tunnel.cc:1200
void addPath(const Comm::ConnectionPointer &)
add a candidate path to try after all the existing paths
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:159
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: tunnel.cc:224
int size
Definition: ModDevPoll.cc:77
CbcPointer< ErrorState > error
problem details (nil on success)
bool empty() const
whether we lack any known candidate paths
Definition: ResolvedPeers.h:29
const char * rawContent() const
Definition: SBuf.cc:519
void dataSent(size_t amount)
Definition: tunnel.cc:611
time_t read
Definition: SquidConfig.h:106
void bytesIn(int const &)
Definition: tunnel.cc:378
#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:548
virtual bool canDial(AsyncCall &call)
Definition: tunnel.cc:217
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:146

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors