FwdState.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 17 Request Forwarding */
10 
11 #include "squid.h"
12 #include "AccessLogEntry.h"
13 #include "acl/Address.h"
14 #include "acl/FilledChecklist.h"
15 #include "acl/Gadgets.h"
16 #include "anyp/PortCfg.h"
17 #include "CacheManager.h"
18 #include "CachePeer.h"
19 #include "client_side.h"
20 #include "clients/forward.h"
21 #include "clients/HttpTunneler.h"
22 #include "comm/Connection.h"
23 #include "comm/ConnOpener.h"
24 #include "comm/Loops.h"
25 #include "CommCalls.h"
26 #include "errorpage.h"
27 #include "event.h"
28 #include "fd.h"
29 #include "fde.h"
30 #include "FwdState.h"
31 #include "globals.h"
32 #include "gopher.h"
33 #include "HappyConnOpener.h"
34 #include "hier_code.h"
35 #include "http.h"
36 #include "http/Stream.h"
37 #include "HttpReply.h"
38 #include "HttpRequest.h"
39 #include "icmp/net_db.h"
40 #include "internal.h"
41 #include "ip/Intercept.h"
42 #include "ip/NfMarkConfig.h"
43 #include "ip/QosConfig.h"
44 #include "ip/tools.h"
45 #include "MemObject.h"
46 #include "mgr/Registration.h"
47 #include "neighbors.h"
48 #include "pconn.h"
49 #include "PeerPoolMgr.h"
50 #include "ResolvedPeers.h"
52 #include "SquidConfig.h"
53 #include "SquidTime.h"
55 #include "Store.h"
56 #include "StoreClient.h"
57 #include "urn.h"
58 #include "whois.h"
59 #if USE_OPENSSL
61 #include "ssl/Config.h"
62 #include "ssl/ErrorDetail.h"
63 #include "ssl/helper.h"
64 #include "ssl/ServerBump.h"
65 #include "ssl/support.h"
66 #else
68 #endif
69 
70 #include <cerrno>
71 
73 
74 static OBJH fwdStats;
75 
76 #define MAX_FWD_STATS_IDX 9
78 
79 PconnPool *fwdPconnPool = new PconnPool("server-peers", nullptr);
80 
82 
84 {
85 public:
87 
89  method_(method), fwd_(fwd), answer_() {}
90 
91  /* CallDialer API */
92  virtual bool canDial(AsyncCall &call) { return fwd_.valid(); }
93  void dial(AsyncCall &call) { ((&(*fwd_))->*method_)(answer_); }
94  virtual void print(std::ostream &os) const {
95  os << '(' << fwd_.get() << ", " << answer_ << ')';
96  }
97 
98  /* Security::PeerConnector::CbDialer API */
99  virtual Security::EncryptorAnswer &answer() { return answer_; }
100 
101 private:
105 };
106 
107 void
109 {
110  FwdState* fwd = (FwdState*)d;
111  Pointer tmp = fwd; // Grab a temporary pointer to keep the object alive during our scope.
112 
113  if (Comm::IsConnOpen(fwd->serverConnection())) {
114  fwd->closeServerConnection("store entry aborted");
115  } else {
116  debugs(17, 7, HERE << "store entry aborted; no connection to close");
117  }
118  fwd->stopAndDestroy("store entry aborted");
119 }
120 
121 void
123 {
124  debugs(17, 3, "because " << reason << "; " << serverConn);
125  comm_remove_close_handler(serverConn->fd, closeHandler);
126  closeHandler = NULL;
127  fwdPconnPool->noteUses(fd_table[serverConn->fd].pconn.uses);
128  serverConn->close();
129 }
130 
131 /**** PUBLIC INTERFACE ********************************************************/
132 
134  entry(e),
135  request(r),
136  al(alp),
137  err(NULL),
138  clientConn(client),
139  start_t(squid_curtime),
140  n_tries(0),
141  destinations(new ResolvedPeers()),
142  pconnRace(raceImpossible)
143 {
144  debugs(17, 2, "Forwarding client request " << client << ", url=" << e->url());
146  e->lock("FwdState");
147  flags.connected_okay = false;
148  flags.dont_retry = false;
149  flags.forward_completed = false;
150  flags.destinationsFound = false;
151  debugs(17, 3, "FwdState constructed, this=" << this);
152 }
153 
154 // Called once, right after object creation, when it is safe to set self
156 {
157  // Protect ourselves from being destroyed when the only Server pointing
158  // to us is gone (while we expect to talk to more Servers later).
159  // Once we set self, we are responsible for clearing it when we do not
160  // expect to talk to any servers.
161  self = aSelf; // refcounted
162 
163  // We hope that either the store entry aborts or peer is selected.
164  // Otherwise we are going to leak our object.
165 
166  // Ftp::Relay needs to preserve control connection on data aborts
167  // so it registers its own abort handler that calls ours when needed.
168  if (!request->flags.ftpNative)
170 
171  // just in case; should already be initialized to false
172  request->flags.pinned = false;
173 
174 #if STRICT_ORIGINAL_DST
175  // Bug 3243: CVE 2009-0801
176  // Bypass of browser same-origin access control in intercepted communication
177  // To resolve this we must force DIRECT and only to the original client destination.
178  const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.interceptTproxy);
179  const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified);
180  if (isIntercepted && useOriginalDst) {
181  selectPeerForIntercepted();
182  return;
183  }
184 #endif
185 
186  // do full route options selection
188 }
189 
191 void
192 FwdState::stopAndDestroy(const char *reason)
193 {
194  debugs(17, 3, "for " << reason);
195 
196  if (opening())
197  cancelOpening(reason);
198 
199  PeerSelectionInitiator::subscribed = false; // may already be false
200  self = nullptr; // we hope refcounting destroys us soon; may already be nil
201  /* do not place any code here as this object may be gone by now */
202 }
203 
208 void
209 FwdState::cancelOpening(const char *reason)
210 {
211  assert(calls.connector);
212  calls.connector->cancel(reason);
213  calls.connector = nullptr;
215  connOpener.clear();
216 }
217 
218 #if STRICT_ORIGINAL_DST
219 void
221 FwdState::selectPeerForIntercepted()
222 {
223  // We do not support re-wrapping inside CONNECT.
224  // Our only alternative is to fake a noteDestination() call.
225 
226  // use pinned connection if available
227  if (ConnStateData *client = request->pinnedConnection()) {
228  // emulate the PeerSelector::selectPinned() "Skip ICP" effect
230 
231  usePinned();
232  return;
233  }
234 
235  // use client original destination as second preferred choice
236  const auto p = new Comm::Connection();
237  p->peerType = ORIGINAL_DST;
238  p->remote = clientConn->local;
240 
241  debugs(17, 3, HERE << "using client original destination: " << *p);
245  useDestinations();
246 }
247 #endif
248 
249 void
251 {
252  if (flags.forward_completed) {
253  debugs(17, DBG_IMPORTANT, HERE << "FwdState::completed called on a completed request! Bad!");
254  return;
255  }
256 
257  flags.forward_completed = true;
258 
259  request->hier.stopPeerClock(false);
260 
262  debugs(17, 3, HERE << "entry aborted");
263  return ;
264  }
265 
266 #if URL_CHECKSUM_DEBUG
267 
268  entry->mem_obj->checkUrlChecksum();
269 #endif
270 
271  if (entry->store_status == STORE_PENDING) {
272  if (entry->isEmpty()) {
273  if (!err) // we quit (e.g., fd closed) before an error or content
275  assert(err);
277  err = NULL;
278 #if USE_OPENSSL
282  }
283 #endif
284  } else {
285  entry->complete();
287  }
288  }
289 
290  if (storePendingNClients(entry) > 0)
292 
293 }
294 
296 {
297  debugs(17, 3, "FwdState destructor start");
298 
299  if (! flags.forward_completed)
300  completed();
301 
302  doneWithRetries();
303 
305 
306  delete err;
307 
309 
310  entry->unlock("FwdState");
311 
312  entry = NULL;
313 
314  if (opening())
315  cancelOpening("~FwdState");
316 
318  closeServerConnection("~FwdState");
319 
320  debugs(17, 3, "FwdState destructed, this=" << this);
321 }
322 
328 void
330 {
337  if ( Config.accessList.miss && !request->client_addr.isNoAddr() &&
338  !request->flags.internal && request->url.getScheme() != AnyP::PROTO_CACHE_OBJECT) {
345  ch.al = al;
346  ch.src_addr = request->client_addr;
347  ch.syncAle(request, nullptr);
348  if (ch.fastCheck().denied()) {
349  err_type page_id;
351 
352  if (page_id == ERR_NONE)
353  page_id = ERR_FORWARDING_DENIED;
354 
355  const auto anErr = new ErrorState(page_id, Http::scForbidden, request, al);
356  errorAppendEntry(entry, anErr); // frees anErr
357  return;
358  }
359  }
360 
361  debugs(17, 3, HERE << "'" << entry->url() << "'");
362  /*
363  * This seems like an odd place to bind mem_obj and request.
364  * Might want to assert that request is NULL at this point
365  */
366  entry->mem_obj->request = request;
367 #if URL_CHECKSUM_DEBUG
368 
369  entry->mem_obj->checkUrlChecksum();
370 #endif
371 
372  if (shutting_down) {
373  /* more yuck */
374  const auto anErr = new ErrorState(ERR_SHUTTING_DOWN, Http::scServiceUnavailable, request, al);
375  errorAppendEntry(entry, anErr); // frees anErr
376  return;
377  }
378 
379  if (request->flags.internal) {
380  debugs(17, 2, "calling internalStart() due to request flag");
381  internalStart(clientConn, request, entry, al);
382  return;
383  }
384 
385  switch (request->url.getScheme()) {
386 
388  debugs(17, 2, "calling CacheManager due to request scheme " << request->url.getScheme());
389  CacheManager::GetInstance()->start(clientConn, request, entry, al);
390  return;
391 
392  case AnyP::PROTO_URN:
393  urnStart(request, entry, al);
394  return;
395 
396  default:
397  FwdState::Pointer fwd = new FwdState(clientConn, entry, request, al);
398  fwd->start(fwd);
399  return;
400  }
401 
402  /* NOTREACHED */
403 }
404 
405 void
407 {
408  // Hides AccessLogEntry.h from code that does not supply ALE anyway.
409  Start(clientConn, entry, request, NULL);
410 }
411 
414 static inline time_t
415 diffOrZero(const time_t larger, const time_t smaller)
416 {
417  return (larger > smaller) ? (larger - smaller) : 0;
418 }
419 
421 time_t
423 {
424  // time already spent on forwarding (0 if clock went backwards)
425  const time_t timeSpent = diffOrZero(squid_curtime, fwdStart);
426  return diffOrZero(Config.Timeout.forward, timeSpent);
427 }
428 
429 bool
431 {
432  return ForwardTimeout(fwdStart) > 0;
433 }
434 
435 void
437 {
438  if (!destinations->empty()) {
439  connectStart();
440  } else {
442  debugs(17, 4, "wait for more destinations to try");
443  return; // expect a noteDestination*() call
444  }
445 
446  debugs(17, 3, HERE << "Connection failed: " << entry->url());
447  if (!err) {
449  fail(anErr);
450  } // else use actual error from last connection attempt
451 
452  stopAndDestroy("tried all destinations");
453  }
454 }
455 
456 void
458 {
459  debugs(17, 3, err_type_str[errorState->type] << " \"" << Http::StatusCodeString(errorState->httpStatus) << "\"\n\t" << entry->url());
460 
461  delete err;
462  err = errorState;
463 
464  if (!errorState->request)
465  errorState->request = request;
466 
467  if (err->type != ERR_ZERO_SIZE_OBJECT)
468  return;
469 
470  if (pconnRace == racePossible) {
471  debugs(17, 5, HERE << "pconn race happened");
474  }
475 
476  if (ConnStateData *pinned_connection = request->pinnedConnection()) {
477  pinned_connection->pinning.zeroReply = true;
478  debugs(17, 4, "zero reply on pinned connection");
479  }
480 }
481 
485 void
487 {
488  debugs(17, 3, HERE << entry->url() );
489  assert(serverConnection() == conn);
490  assert(Comm::IsConnOpen(conn));
492  closeHandler = NULL;
493  serverConn = NULL;
494 }
495 
496 // \deprecated use unregister(Comm::ConnectionPointer &conn) instead
497 void
499 {
500  debugs(17, 3, HERE << entry->url() );
501  assert(fd == serverConnection()->fd);
503 }
504 
511 void
513 {
514  debugs(17, 3, HERE << entry->url() << "\n\tstatus " << entry->getReply()->sline.status());
515 #if URL_CHECKSUM_DEBUG
516 
517  entry->mem_obj->checkUrlChecksum();
518 #endif
519 
521 
522  if (reforward()) {
523  debugs(17, 3, HERE << "re-forwarding " << entry->getReply()->sline.status() << " " << entry->url());
524 
527 
528  entry->reset();
529 
530  useDestinations();
531 
532  } else {
534  debugs(17, 3, HERE << "server FD " << serverConnection()->fd << " not re-forwarding status " << entry->getReply()->sline.status());
535  else
536  debugs(17, 3, HERE << "server (FD closed) not re-forwarding status " << entry->getReply()->sline.status());
537  entry->complete();
538 
540  completed();
541 
542  stopAndDestroy("forwarding completed");
543  }
544 }
545 
546 void
548 {
549  flags.destinationsFound = true;
550 
551  if (!path) {
552  // We can call usePinned() without fear of clashing with an earlier
553  // forwarding attempt because PINNED must be the first destination.
555  usePinned();
556  return;
557  }
558 
559  debugs(17, 3, path);
560 
561  destinations->addPath(path);
562 
564  // We are already using a previously opened connection, so we cannot be
565  // waiting for connOpener. We still receive destinations for backup.
566  Must(!opening());
567  return;
568  }
569 
570  if (opening()) {
572  return; // and continue to wait for FwdState::noteConnection() callback
573  }
574 
575  // This is the first path candidate we have seen. Create connOpener.
576  useDestinations();
577 }
578 
579 void
581 {
584 
585  if (!flags.destinationsFound) {
586  if (selectionError) {
587  debugs(17, 3, "Will abort forwarding because path selection has failed.");
588  Must(!err); // if we tried to connect, then path selection succeeded
589  fail(selectionError);
590  }
591  else if (err)
592  debugs(17, 3, "Will abort forwarding because all found paths have failed.");
593  else
594  debugs(17, 3, "Will abort forwarding because path selection found no paths.");
595 
596  useDestinations(); // will detect and handle the lack of paths
597  return;
598  }
599  // else continue to use one of the previously noted destinations;
600  // if all of them fail, forwarding as whole will fail
601  Must(!selectionError); // finding at least one path means selection succeeded
602 
604  // We are already using a previously opened connection, so we cannot be
605  // waiting for connOpener. We were receiving destinations for backup.
606  Must(!opening());
607  return;
608  }
609 
610  Must(opening()); // or we would be stuck with nothing to do or wait for
612  // and continue to wait for FwdState::noteConnection() callback
613 }
614 
616 void
618 {
620  debugs(17, 7, "reusing pending notification about " << *destinations);
621  } else {
622  debugs(17, 7, "notifying about " << *destinations);
624  CallJobHere(17, 5, connOpener, HappyConnOpener, noteCandidatesChange);
625  }
626 }
627 
628 /**** CALLBACK WRAPPERS ************************************************************/
629 
630 static void
632 {
633  FwdState *fwd = (FwdState *)params.data;
634  fwd->serverClosed(params.fd);
635 }
636 
637 /**** PRIVATE *****************************************************************/
638 
639 /*
640  * FwdState::checkRetry
641  *
642  * Return TRUE if the request SHOULD be retried. This method is
643  * called when the HTTP connection fails, or when the connection
644  * is closed before reading the end of HTTP headers from the server.
645  */
646 bool
648 {
649  if (shutting_down)
650  return false;
651 
652  if (!self) { // we have aborted before the server called us back
653  debugs(17, 5, HERE << "not retrying because of earlier abort");
654  // we will be destroyed when the server clears its Pointer to us
655  return false;
656  }
657 
659  return false;
660 
661  if (!entry->isEmpty())
662  return false;
663 
664  if (exhaustedTries())
665  return false;
666 
667  if (request->flags.pinned && !pinnedCanRetry())
668  return false;
669 
671  return false;
672 
673  if (flags.dont_retry)
674  return false;
675 
676  if (request->bodyNibbled())
677  return false;
678 
679  // NP: not yet actually connected anywhere. retry is safe.
680  if (!flags.connected_okay)
681  return true;
682 
683  if (!checkRetriable())
684  return false;
685 
686  return true;
687 }
688 
690 bool
692 {
693  // Optimize: A compliant proxy may retry PUTs, but Squid lacks the [rather
694  // complicated] code required to protect the PUT request body from being
695  // nibbled during the first try. Thus, Squid cannot retry some PUTs today.
696  if (request->body_pipe != NULL)
697  return false;
698 
699  // RFC2616 9.1 Safe and Idempotent Methods
701 }
702 
703 void
705 {
706  // XXX: fd is often -1 here
707  debugs(17, 2, "FD " << fd << " " << entry->url() << " after " <<
708  (fd >= 0 ? fd_table[fd].pconn.uses : -1) << " requests");
709  if (fd >= 0 && serverConnection()->fd == fd)
710  fwdPconnPool->noteUses(fd_table[fd].pconn.uses);
711  retryOrBail();
712 }
713 
714 void
716 {
717  if (checkRetry()) {
718  debugs(17, 3, HERE << "re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)");
719  useDestinations();
720  return;
721  }
722 
723  // TODO: should we call completed() here and move doneWithRetries there?
724  doneWithRetries();
725 
726  request->hier.stopPeerClock(false);
727 
728  if (self != NULL && !err && shutting_down && entry->isEmpty()) {
730  errorAppendEntry(entry, anErr);
731  }
732 
733  stopAndDestroy("cannot retry");
734 }
735 
736 // If the Server quits before nibbling at the request body, the body sender
737 // will not know (so that we can retry). Call this if we will not retry. We
738 // will notify the sender so that it does not get stuck waiting for space.
739 void
741 {
742  if (request && request->body_pipe != NULL)
744 }
745 
746 // called by the server that failed after calling unregister()
747 void
749 {
750  debugs(17, 2, HERE << "self=" << self << " err=" << err << ' ' << entry->url());
752  retryOrBail();
753 }
754 
757 void
759 {
760  calls.connector = nullptr;
761  connOpener.clear();
762 
763  Must(n_tries <= answer.n_tries); // n_tries cannot decrease
764  n_tries = answer.n_tries;
765 
766  if (const auto error = answer.error.get()) {
767  flags.dont_retry = true; // or HappyConnOpener would not have given up
768  syncHierNote(answer.conn, request->url.host());
769  fail(error);
770  answer.error.clear(); // preserve error for errorSendComplete()
771  retryOrBail(); // will notice flags.dont_retry and bail
772  return;
773  }
774 
775  syncWithServerConn(answer.conn, request->url.host(), answer.reused);
776 
777  if (answer.reused)
778  return dispatch();
779 
780  // Check if we need to TLS before use
781  if (const CachePeer *peer = serverConnection()->getPeer()) {
782  // Assume that it is only possible for the client-first from the
783  // bumping modes to try connect to a remote server. The bumped
784  // requests with other modes are using pinned connections or fails.
785  const bool clientFirstBump = request->flags.sslBumped;
786  // We need a CONNECT tunnel to send encrypted traffic through a proxy,
787  // but we do not support TLS inside TLS, so we exclude HTTPS proxies.
788  const bool originWantsEncryptedTraffic =
790  request->flags.sslPeek ||
791  clientFirstBump;
792  if (originWantsEncryptedTraffic && // the "encrypted traffic" part
793  !peer->options.originserver && // the "through a proxy" part
794  !peer->secure.encryptTransport) // the "exclude HTTPS proxies" part
795  return establishTunnelThruProxy();
796  }
797 
799 }
800 
801 void
803 {
805  "FwdState::tunnelEstablishmentDone",
807  HttpRequest::Pointer requestPointer = request;
808  const auto tunneler = new Http::Tunneler(serverConnection(), requestPointer, callback, connectingTimeout(serverConnection()), al);
809 #if USE_DELAY_POOLS
810  Must(serverConnection()->getPeer());
811  if (!serverConnection()->getPeer()->options.no_delay)
812  tunneler->setDelayId(entry->mem_obj->mostBytesAllowed());
813 #endif
814  AsyncJob::Start(tunneler);
815  // and wait for the tunnelEstablishmentDone() call
816 }
817 
819 void
821 {
822  if (answer.positive()) {
823  if (answer.leftovers.isEmpty()) {
825  return;
826  }
827  // This should not happen because TLS servers do not speak first. If we
828  // have to handle this, then pass answer.leftovers via a PeerConnector
829  // to ServerBio. See ClientBio::setReadBufData().
830  static int occurrences = 0;
831  const auto level = (occurrences++ < 100) ? DBG_IMPORTANT : 2;
832  debugs(17, level, "ERROR: Early data after CONNECT response. " <<
833  "Found " << answer.leftovers.length() << " bytes. " <<
834  "Closing " << serverConnection());
836  closeServerConnection("found early data after CONNECT response");
837  retryOrBail();
838  return;
839  }
840 
841  // TODO: Reuse to-peer connections after a CONNECT error response.
842 
843  if (const auto peer = serverConnection()->getPeer())
844  peerConnectFailed(peer);
845 
846  const auto error = answer.squidError.get();
847  Must(error);
848  answer.squidError.clear(); // preserve error for fail()
849  fail(error);
850  closeServerConnection("Squid-generated CONNECT error");
851  retryOrBail();
852 }
853 
855 void
857 {
859 
860  const CachePeer *p = serverConnection()->getPeer();
861  const bool peerWantsTls = p && p->secure.encryptTransport;
862  // userWillTlsToPeerForUs assumes CONNECT == HTTPS
863  const bool userWillTlsToPeerForUs = p && p->options.originserver &&
865  const bool needTlsToPeer = peerWantsTls && !userWillTlsToPeerForUs;
866  const bool clientFirstBump = request->flags.sslBumped; // client-first (already) bumped connection
867  const bool needsBump = request->flags.sslPeek || clientFirstBump;
868 
869  // 'GET https://...' requests. If a peer is used the request is forwarded
870  // as is
871  const bool needTlsToOrigin = !p && request->url.getScheme() == AnyP::PROTO_HTTPS && !clientFirstBump;
872 
873  if (needTlsToPeer || needTlsToOrigin || needsBump) {
874  HttpRequest::Pointer requestPointer = request;
876  "FwdState::ConnectedToPeer",
878  const auto sslNegotiationTimeout = connectingTimeout(serverConnection());
880 #if USE_OPENSSL
881  if (request->flags.sslPeek)
882  connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, al, sslNegotiationTimeout);
883  else
884 #endif
885  connector = new Security::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
886  AsyncJob::Start(connector); // will call our callback
887  return;
888  }
889 
890  // if not encrypting just run the post-connect actions
892 }
893 
895 void
897 {
898  if (ErrorState *error = answer.error.get()) {
899  fail(error);
900  answer.error.clear(); // preserve error for errorSendComplete()
901  if (CachePeer *p = serverConnection()->getPeer())
903  serverConnection()->close();
904  return;
905  }
906 
907  if (answer.tunneled) {
908  // TODO: When ConnStateData establishes tunnels, its state changes
909  // [in ways that may affect logging?]. Consider informing
910  // ConnStateData about our tunnel or otherwise unifying tunnel
911  // establishment [side effects].
912  unregister(serverConn); // async call owns it now
913  complete(); // destroys us
914  return;
915  }
916 
918 }
919 
921 void
923 {
924  // should reach ConnStateData before the dispatched Client job starts
927 
928  if (serverConnection()->getPeer())
930 
931  dispatch();
932 }
933 
935 void
936 FwdState::syncWithServerConn(const Comm::ConnectionPointer &conn, const char *host, const bool reused)
937 {
938  Must(IsConnOpen(conn));
939  serverConn = conn;
940 
942 
943  if (reused) {
946  } else {
948  // Comm::ConnOpener already applied proper/current markings
949  }
950 
951  syncHierNote(serverConn, host);
952 }
953 
954 void
956 {
957  if (request)
958  request->hier.resetPeerNotes(server, host);
959  if (al)
960  al->hier.resetPeerNotes(server, host);
961 }
962 
968 void
970 {
971  debugs(17, 3, *destinations << " to " << entry->url());
972 
974 
976  assert(!opening());
977 
978  // Ditch error page if it was created before.
979  // A new one will be created if there's another problem
980  delete err;
981  err = nullptr;
982  request->clearError();
983  serverConn = nullptr;
984 
986 
987  calls.connector = asyncCall(17, 5, "FwdState::noteConnection", HappyConnOpener::CbDialer<FwdState>(&FwdState::noteConnection, this));
988 
990  const auto cs = new HappyConnOpener(destinations, calls.connector, cause, start_t, n_tries, al);
991  cs->setHost(request->url.host());
992  bool retriable = checkRetriable();
993  if (!retriable && Config.accessList.serverPconnForNonretriable) {
995  ch.al = al;
996  ch.syncAle(request, nullptr);
997  retriable = ch.fastCheck().allowed();
998  }
999  cs->setRetriable(retriable);
1000  cs->allowPersistent(pconnRace != raceHappened);
1001  destinations->notificationPending = true; // start() is async
1002  connOpener = cs;
1003  AsyncJob::Start(cs);
1004 }
1005 
1007 void
1009 {
1010  const auto connManager = request->pinnedConnection();
1011  debugs(17, 7, "connection manager: " << connManager);
1012 
1013  try {
1015  debugs(17, 5, "connection: " << serverConn);
1016  } catch (ErrorState * const anErr) {
1017  syncHierNote(nullptr, connManager ? connManager->pinning.host : request->url.host());
1018  serverConn = nullptr;
1019  fail(anErr);
1020  // Connection managers monitor their idle pinned to-server
1021  // connections and close from-client connections upon seeing
1022  // a to-server connection closure. Retrying here is futile.
1023  stopAndDestroy("pinned connection failure");
1024  return;
1025  }
1026 
1027  ++n_tries;
1028  request->flags.pinned = true;
1029 
1030  assert(connManager);
1031  if (connManager->pinnedAuth())
1032  request->flags.auth = true;
1033 
1034  // the server may close the pinned connection before this request
1035  const auto reused = true;
1036  syncWithServerConn(serverConn, connManager->pinning.host, reused);
1037 
1038  dispatch();
1039 }
1040 
1041 void
1043 {
1044  debugs(17, 3, clientConn << ": Fetching " << request->method << ' ' << entry->url());
1045  /*
1046  * Assert that server_fd is set. This is to guarantee that fwdState
1047  * is attached to something and will be deallocated when server_fd
1048  * is closed.
1049  */
1051 
1052  fd_note(serverConnection()->fd, entry->url());
1053 
1054  fd_table[serverConnection()->fd].noteUse();
1055 
1056  /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
1058 
1059  assert(entry->locked());
1060 
1062 
1063  flags.connected_okay = true;
1064 
1066 
1067  /* Retrieves remote server TOS or MARK value, and stores it as part of the
1068  * original client request FD object. It is later used to forward
1069  * remote server's TOS/MARK in the response to the client in case of a MISS.
1070  */
1071  if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
1073  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
1074  /* Get the netfilter CONNMARK */
1076  }
1077  }
1078 
1079 #if _SQUID_LINUX_
1080  /* Bug 2537: The TOS forward part of QOS only applies to patched Linux kernels. */
1081  if (Ip::Qos::TheConfig.isHitTosActive()) {
1083  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
1084  /* Get the TOS value for the packet */
1086  }
1087  }
1088 #endif
1089 
1090 #if USE_OPENSSL
1091  if (request->flags.sslPeek) {
1094  unregister(serverConn); // async call owns it now
1095  complete(); // destroys us
1096  return;
1097  }
1098 #endif
1099 
1100  if (const auto peer = serverConnection()->getPeer()) {
1101  ++peer->stats.fetches;
1102  request->prepForPeering(*peer);
1103  httpStart(this);
1104  } else {
1107 
1108  switch (request->url.getScheme()) {
1109 
1110  case AnyP::PROTO_HTTPS:
1111  httpStart(this);
1112  break;
1113 
1114  case AnyP::PROTO_HTTP:
1115  httpStart(this);
1116  break;
1117 
1118  case AnyP::PROTO_GOPHER:
1119  gopherStart(this);
1120  break;
1121 
1122  case AnyP::PROTO_FTP:
1123  if (request->flags.ftpNative)
1124  Ftp::StartRelay(this);
1125  else
1126  Ftp::StartGateway(this);
1127  break;
1128 
1130 
1131  case AnyP::PROTO_URN:
1132  fatal_dump("Should never get here");
1133  break;
1134 
1135  case AnyP::PROTO_WHOIS:
1136  whoisStart(this);
1137  break;
1138 
1139  case AnyP::PROTO_WAIS: /* Not implemented */
1140 
1141  default:
1142  debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->url() << "'.");
1143  const auto anErr = new ErrorState(ERR_UNSUP_REQ, Http::scBadRequest, request, al);
1144  fail(anErr);
1145  // Set the dont_retry flag because this is not a transient (network) error.
1146  flags.dont_retry = true;
1148  serverConn->close();
1149  }
1150  break;
1151  }
1152  }
1153 }
1154 
1155 /*
1156  * FwdState::reforward
1157  *
1158  * returns TRUE if the transaction SHOULD be re-forwarded to the
1159  * next choice in the serverDestinations list. This method is called when
1160  * peer communication completes normally, or experiences
1161  * some error after receiving the end of HTTP headers.
1162  */
1163 int
1165 {
1166  StoreEntry *e = entry;
1167 
1168  if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
1169  debugs(17, 3, HERE << "entry aborted");
1170  return 0;
1171  }
1172 
1174  assert(e->mem_obj);
1175 #if URL_CHECKSUM_DEBUG
1176 
1177  e->mem_obj->checkUrlChecksum();
1178 #endif
1179 
1180  debugs(17, 3, HERE << e->url() << "?" );
1181 
1182  if (request->flags.pinned && !pinnedCanRetry()) {
1183  debugs(17, 3, "pinned connection; cannot retry");
1184  return 0;
1185  }
1186 
1187  if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
1188  debugs(17, 3, HERE << "No, ENTRY_FWD_HDR_WAIT isn't set");
1189  return 0;
1190  }
1191 
1192  if (exhaustedTries())
1193  return 0;
1194 
1195  if (request->bodyNibbled())
1196  return 0;
1197 
1199  debugs(17, 3, HERE << "No alternative forwarding paths left");
1200  return 0;
1201  }
1202 
1203  const Http::StatusCode s = e->getReply()->sline.status();
1204  debugs(17, 3, HERE << "status " << s);
1205  return reforwardableStatus(s);
1206 }
1207 
1208 static void
1210 {
1211  int i;
1212  int j;
1213  storeAppendPrintf(s, "Status");
1214 
1215  for (j = 1; j < MAX_FWD_STATS_IDX; ++j) {
1216  storeAppendPrintf(s, "\ttry#%d", j);
1217  }
1218 
1219  storeAppendPrintf(s, "\n");
1220 
1221  for (i = 0; i <= (int) Http::scInvalidHeader; ++i) {
1222  if (FwdReplyCodes[0][i] == 0)
1223  continue;
1224 
1225  storeAppendPrintf(s, "%3d", i);
1226 
1227  for (j = 0; j <= MAX_FWD_STATS_IDX; ++j) {
1228  storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]);
1229  }
1230 
1231  storeAppendPrintf(s, "\n");
1232  }
1233 }
1234 
1235 /**** STATIC MEMBER FUNCTIONS *************************************************/
1236 
1237 bool
1239 {
1240  switch (s) {
1241 
1242  case Http::scBadGateway:
1243 
1245  return true;
1246 
1247  case Http::scForbidden:
1248 
1250 
1252 
1254  return Config.retry.onerror;
1255 
1256  default:
1257  return false;
1258  }
1259 
1260  /* NOTREACHED */
1261 }
1262 
1263 void
1265 {
1267 }
1268 
1269 void
1271 {
1272  Mgr::RegisterAction("forward", "Request Forwarding Statistics", fwdStats, 0, 1);
1273 }
1274 
1275 void
1277 {
1278  if (status > Http::scInvalidHeader)
1279  return;
1280 
1281  assert(tries >= 0);
1282 
1283  if (tries > MAX_FWD_STATS_IDX)
1284  tries = MAX_FWD_STATS_IDX;
1285 
1286  ++ FwdReplyCodes[tries][status];
1287 }
1288 
1289 bool
1291 {
1292  return n_tries >= Config.forward_max_tries;
1293 }
1294 
1295 bool
1297 {
1299 
1300  // pconn race on pinned connection: Currently we do not have any mechanism
1301  // to retry current pinned connection path.
1302  if (pconnRace == raceHappened)
1303  return false;
1304 
1305  // If a bumped connection was pinned, then the TLS client was given our peer
1306  // details. Do not retry because we do not ensure that those details stay
1307  // constant. Step1-bumped connections do not get our TLS peer details, are
1308  // never pinned, and, hence, never reach this method.
1309  if (request->flags.sslBumped)
1310  return false;
1311 
1312  // The other pinned cases are FTP proxying and connection-based HTTP
1313  // authentication. TODO: Do these cases have restrictions?
1314  return true;
1315 }
1316 
1317 time_t
1319 {
1320  const auto connTimeout = conn->connectTimeout(start_t);
1321  return positiveTimeout(connTimeout);
1322 }
1323 
1324 /**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
1325 
1326 /*
1327  * DPW 2007-05-19
1328  * Formerly static, but now used by client_side_request.cc
1329  */
1331 tos_t
1333 {
1334  for (acl_tos *l = head; l; l = l->next) {
1335  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1336  return l->tos;
1337  }
1338 
1339  return 0;
1340 }
1341 
1345 {
1346  for (acl_nfmark *l = head; l; l = l->next) {
1347  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1348  return l->markConfig;
1349  }
1350 
1351  return {};
1352 }
1353 
1354 void
1356 {
1357  // skip if an outgoing address is already set.
1358  if (!conn->local.isAnyAddr()) return;
1359 
1360  // ensure that at minimum the wildcard local matches remote protocol
1361  if (conn->remote.isIPv4())
1362  conn->local.setIPv4();
1363 
1364  // maybe use TPROXY client address
1365  if (request && request->flags.spoofClientIp) {
1366  if (!conn->getPeer() || !conn->getPeer()->options.no_tproxy) {
1367 #if FOLLOW_X_FORWARDED_FOR && LINUX_NETFILTER
1369  conn->local = request->indirect_client_addr;
1370  else
1371 #endif
1372  conn->local = request->client_addr;
1373  conn->local.port(0); // let OS pick the source port to prevent address clashes
1374  // some flags need setting on the socket to use this address
1375  conn->flags |= COMM_DOBIND;
1376  conn->flags |= COMM_TRANSPARENT;
1377  return;
1378  }
1379  // else no tproxy today ...
1380  }
1381 
1383  return; // anything will do.
1384  }
1385 
1386  ACLFilledChecklist ch(NULL, request, NULL);
1387  ch.dst_peer_name = conn->getPeer() ? conn->getPeer()->name : NULL;
1388  ch.dst_addr = conn->remote;
1389 
1390  // TODO use the connection details in ACL.
1391  // needs a bit of rework in ACLFilledChecklist to use Comm::Connection instead of ConnStateData
1392 
1393  for (Acl::Address *l = Config.accessList.outgoing_address; l; l = l->next) {
1394 
1395  /* check if the outgoing address is usable to the destination */
1396  if (conn->remote.isIPv4() != l->addr.isIPv4()) continue;
1397 
1398  /* check ACLs for this outgoing address */
1399  if (!l->aclList || ch.fastCheck(l->aclList).allowed()) {
1400  conn->local = l->addr;
1401  return;
1402  }
1403  }
1404 }
1405 
1407 static tos_t
1409 {
1410  if (!Ip::Qos::TheConfig.tosToServer)
1411  return 0;
1412 
1413  ACLFilledChecklist ch(NULL, request, NULL);
1414  ch.dst_peer_name = conn.getPeer() ? conn.getPeer()->name : nullptr;
1415  ch.dst_addr = conn.remote;
1416  return aclMapTOS(Ip::Qos::TheConfig.tosToServer, &ch);
1417 }
1418 
1420 static nfmark_t
1422 {
1423  if (!Ip::Qos::TheConfig.nfmarkToServer)
1424  return 0;
1425 
1426  ACLFilledChecklist ch(NULL, request, NULL);
1427  ch.dst_peer_name = conn.getPeer() ? conn.getPeer()->name : nullptr;
1428  ch.dst_addr = conn.remote;
1429  const auto mc = aclFindNfMarkConfig(Ip::Qos::TheConfig.nfmarkToServer, &ch);
1430  return mc.mark;
1431 }
1432 
1433 void
1435 {
1436  // Get the server side TOS and Netfilter mark to be set on the connection.
1437  conn.tos = GetTosToServer(request, conn);
1438  conn.nfmark = GetNfmarkToServer(request, conn);
1439  debugs(17, 3, "from " << conn.local << " tos " << int(conn.tos) << " netfilter mark " << conn.nfmark);
1440 }
1441 
1442 void
1444 {
1445  GetMarkingsToServer(request, conn);
1446 
1447  // TODO: Avoid these calls if markings has not changed.
1448  if (conn.tos)
1449  Ip::Qos::setSockTos(&conn, conn.tos);
1450  if (conn.nfmark)
1451  Ip::Qos::setSockNfmark(&conn, conn.nfmark);
1452 }
1453 
bool setIPv4()
Definition: Address.cc:224
size_type length() const
Returns the number of bytes stored in SBuf.
Definition: SBuf.h:404
void getOutgoingAddress(HttpRequest *request, Comm::ConnectionPointer conn)
Definition: FwdState.cc:1355
void urnStart(HttpRequest *r, StoreEntry *e, const AccessLogEntryPointer &ale)
Definition: urn.cc:213
HierarchyLogEntry hier
Definition: HttpRequest.h:157
static Comm::ConnectionPointer BorrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &)
HappyConnOpenerPointer connOpener
current connection opening job
Definition: FwdState.h:189
bool interceptTproxy
Set for requests handled by a "tproxy" port.
Definition: RequestFlags.h:66
#define fd_table
Definition: fde.h:174
ConnStateData * pinnedConnection()
Definition: HttpRequest.cc:686
unsigned short port() const
Definition: Address.cc:778
#define assert(EX)
Definition: assert.h:17
int reforward()
Definition: FwdState.cc:1164
bool isIdempotent() const
const char * StatusCodeString(const Http::StatusCode status)
Definition: stub_libhttp.cc:86
Callback dialer API to allow Tunneler to set the answer.
Definition: HttpTunneler.h:45
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: FwdState.cc:547
void const char HLPCB * callback
Definition: stub_helper.cc:16
void connectedToPeer(Security::EncryptorAnswer &answer)
called when all negotiations with the TLS-speaking peer have been completed
Definition: FwdState.cc:896
static bool EnoughTimeToReForward(const time_t fwdStart)
Definition: FwdState.cc:430
static tos_t GetTosToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1408
struct FwdState::@72 calls
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
ResolvedPeersPointer destinations
paths for forwarding the request
Definition: FwdState.h:190
void startPeerClock()
Start recording total time spent communicating with peers.
Definition: access_log.cc:296
static time_t diffOrZero(const time_t larger, const time_t smaller)
Definition: FwdState.cc:415
void noteUses(int uses)
Definition: pconn.cc:536
int unlock(const char *context)
Definition: store.cc:463
nfmark_t nfmark
Definition: Connection.h:152
void fd_note(int fd, const char *s)
Definition: fd.cc:246
void serverClosed(int fd)
Definition: FwdState.cc:704
Ip::Address dst_addr
int storePendingNClients(const StoreEntry *e)
CbcPointer< ErrorState > error
problem details (nil on success)
bool ftpNative
carries a representation of an FTP command [received on ftp_port]
Definition: RequestFlags.h:103
void dispatch()
Definition: FwdState.cc:1042
bool isNoAddr() const
Definition: Address.cc:284
void(FwdState::* Method)(Security::EncryptorAnswer &)
Definition: FwdState.cc:86
void retryPath(const Comm::ConnectionPointer &)
add a candidate path to try before all the existing paths
void tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
resumes operations after the (possibly failed) HTTP CONNECT exchange
Definition: FwdState.cc:820
Ip::Address src_addr
DelayId mostBytesAllowed() const
Definition: MemObject.cc:449
time_t connectTimeout(const time_t fwdStart) const
Definition: Connection.cc:138
bool reused
whether conn was open earlier, by/for somebody else
HttpRequestMethod method
Definition: HttpRequest.h:114
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void error(char *format,...)
Security::EncryptorAnswer answer_
Definition: FwdState.cc:104
void ResetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1443
int i
Definition: membanger.c:49
int client_dst_passthru
Definition: SquidConfig.h:341
Comm::ConnectionPointer conn
unsigned int nfConnmarkFromServer
Definition: fde.h:162
bool encryptTransport
whether transport encryption (TLS/SSL) is to be used on connections to the peer
Definition: PeerOptions.h:144
tos_t aclMapTOS(acl_tos *head, ACLChecklist *ch)
Checks for a TOS value to apply depending on the ACL.
Definition: FwdState.cc:1332
static void RegisterWithCacheManager(void)
Definition: FwdState.cc:1270
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
int locked() const
Definition: store.cc:1255
FwdState(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *, const AccessLogEntryPointer &alp)
Definition: FwdState.cc:133
acl_tos * next
Definition: QosConfig.h:36
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:160
struct SquidConfig::@116 retry
char * name
Definition: CachePeer.h:36
CachePeer * getPeer() const
Definition: Connection.cc:98
HttpRequest * request
Definition: FwdState.h:165
#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
HttpReply const * getReply() const
Definition: store.cc:1676
AsyncJobPointer StartGateway(FwdState *const fwdState)
A new FTP Gateway job.
Definition: FtpGateway.cc:2735
void stopAndDestroy(const char *reason)
ends forwarding; relies on refcounting so the effect may not be immediate
Definition: FwdState.cc:192
AsyncCall dialer for our callback. Gives us access to callback Answer.
virtual void print(std::ostream &os) const
Definition: FwdState.cc:94
A PeerConnector for HTTP origin servers. Capable of SslBumping.
void establishTunnelThruProxy()
Definition: FwdState.cc:802
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 OBJH(StoreEntry *)
Definition: forward.h:44
int conn
the current server connection FD
Definition: Transport.cc:26
bool hostVerified
Definition: RequestFlags.h:64
struct FwdState::@73 flags
void expectNoConsumption()
there will be no more setConsumer() calls
Definition: BodyPipe.cc:267
Comm::ConnectionPointer const & serverConnection() const
Definition: FwdState.h:106
void useDestinations()
Definition: FwdState.cc:436
list of address-based ACLs.
Definition: Address.h:19
void retryOrBail()
Definition: FwdState.cc:715
Final result (an open connection or an error) sent to the job initiator.
void completed()
Definition: FwdState.cc:250
const char * err_type_str[]
time_t squid_curtime
Definition: stub_time.cc:17
Acl::Answer const & fastCheck()
Definition: Checklist.cc:336
void prepForDirect()
get ready to be sent directly to an origin server, excluding originserver
Definition: HttpRequest.cc:459
acl_nfmark * next
Definition: QosConfig.h:50
a netfilter mark/mask pair
Definition: NfMarkConfig.h:20
static CacheManager * GetInstance()
static void fwdStart(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *)
Same as Start() but no master xaction info (AccessLogEntry) available.
Definition: FwdState.cc:406
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void complete()
Definition: store.cc:1064
bool isIPv4() const
Definition: Address.cc:158
unsigned char tos_t
Definition: forward.h:26
void fatal_dump(const char *message)
Definition: fatal.cc:78
void peerConnectSucceded(CachePeer *p)
Definition: neighbors.cc:1299
void cancelOpening(const char *reason)
Definition: FwdState.cc:209
void GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1434
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
virtual ~FwdState()
Definition: FwdState.cc:295
bool destinationsFinalized
whether all of the available candidate paths received from DNS
Definition: ResolvedPeers.h:64
parameters for the async notePinnedConnectionBecameIdle() call
Definition: client_side.h:170
void whoisStart(FwdState *fwd)
Definition: whois.cc:55
time_t forward
Definition: SquidConfig.h:110
int shutting_down
#define COMM_DOBIND
Definition: Connection.h:47
time_t start_t
Definition: FwdState.h:174
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
ping_status_t ping_status
Definition: Store.h:220
void syncHierNote(const Comm::ConnectionPointer &server, const char *host)
Definition: FwdState.cc:955
bool notificationPending
whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
Definition: ResolvedPeers.h:67
StatusCode
Definition: StatusCode.h:20
nfmark_t getNfConnmark(const Comm::ConnectionPointer &conn, const ConnectionDirection connDir)
Definition: QosConfig.cc:141
int fd
FD which the call was about. Set by the async call creator.
Definition: CommCalls.h:90
bool subscribed
whether noteDestination() and noteDestinationsEnd() calls are allowed
void start(Pointer aSelf)
Definition: FwdState.cc:155
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1292
Comm::ConnectionPointer clientConn
a possibly open connection to the client.
Definition: FwdState.h:173
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
CbcPointer< FwdState > fwd_
Definition: FwdState.cc:103
const char * url() const
Definition: store.cc:1606
#define DBG_IMPORTANT
Definition: Debug.h:46
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
bool allowed() const
Definition: Acl.h:143
void complete()
Definition: FwdState.cc:512
Ip::Address client_addr
Definition: HttpRequest.h:149
static time_t ForwardTimeout(const time_t fwdStart)
time left to finish the whole forwarding process (which started at fwdStart)
Definition: FwdState.cc:422
void internalStart(const Comm::ConnectionPointer &clientConn, HttpRequest *request, StoreEntry *entry, const AccessLogEntry::Pointer &ale)
Definition: internal.cc:32
bool bodyNibbled() const
Definition: HttpRequest.cc:443
void closeServerConnection(const char *reason)
stops monitoring server connection for closure and updates pconn stats
Definition: FwdState.cc:122
static void abort(void *)
Definition: FwdState.cc:108
void handleUnregisteredServerEnd()
Definition: FwdState.cc:748
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:187
int forward_max_tries
Definition: SquidConfig.h:352
bool isEmpty() const
Definition: Store.h:60
Config TheConfig
Globally available instance of Qos::Config.
Definition: QosConfig.cc:271
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
void clear()
make pointer not set; does not invalidate cbdata
Definition: CbcPointer.h:144
static void logReplyStatus(int tries, const Http::StatusCode status)
Definition: FwdState.cc:1276
void start(const Comm::ConnectionPointer &client, HttpRequest *request, StoreEntry *entry, const AccessLogEntryPointer &ale)
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:233
struct SquidConfig::@113 accessList
static nfmark_t GetNfmarkToServer(HttpRequest *request, Comm::Connection &conn)
Definition: FwdState.cc:1421
acl_access * miss
Definition: SquidConfig.h:361
#define MAX_FWD_STATS_IDX
Definition: FwdState.cc:76
Http::StatusCode httpStatus
Definition: errorpage.h:174
void releaseRequest(const bool shareable=false)
Definition: store.cc:452
uint16_t flags
Definition: Store.h:210
static CLCB fwdServerClosedWrapper
Definition: FwdState.cc:72
PconnRace pconnRace
current pconn race state
Definition: FwdState.h:197
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:63
void connectStart()
Definition: FwdState.cc:969
Http::StatusLine sline
Definition: HttpReply.h:60
void usePinned()
send request on an existing connection dedicated to the requesting client
Definition: FwdState.cc:1008
const char * AclMatchedName
Definition: Acl.cc:30
void host(const char *src)
Definition: Uri.cc:48
void doneWithRetries()
Definition: FwdState.cc:740
MemObject * mem_obj
Definition: Store.h:199
bool tunneled
whether we spliced the connections instead of negotiating encryption
bool isAnyAddr() const
Definition: Address.cc:170
virtual bool canDial(AsyncCall &call)
Definition: FwdState.cc:92
void clearError()
clear error details, useful for retries/repeats
Definition: HttpRequest.cc:482
void gopherStart(FwdState *fwd)
Definition: gopher.cc:928
static int FwdReplyCodes[MAX_FWD_STATS_IDX+1][Http::scInvalidHeader+1]
Definition: FwdState.cc:77
void CLCB(const CommCloseCbParams &params)
Definition: CommCalls.h:42
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
struct SquidConfig::@112 onoff
int tproxy_uses_indirect_client
Definition: SquidConfig.h:333
void syncWithServerConn(const Comm::ConnectionPointer &server, const char *host, const bool reused)
commits to using the given open to-peer connection
Definition: FwdState.cc:936
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
time_t positiveTimeout(const time_t timeout)
Definition: neighbors.cc:1189
Ip::Address local
Definition: Connection.h:135
void resetPeerNotes(const Comm::ConnectionPointer &server, const char *requestedHost)
Definition: access_log.cc:250
void stopPeerClock(const bool force)
Definition: access_log.cc:303
AsyncCall::Pointer closeHandler
The serverConn close handler.
Definition: FwdState.h:193
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
AclDenyInfoList * denyInfoList
Definition: SquidConfig.h:407
bool reforwardableStatus(const Http::StatusCode s) const
Definition: FwdState.cc:1238
AccessLogEntryPointer al
info for the future access.log entry
Definition: FwdState.h:166
void httpStart(FwdState *fwd)
Definition: http.cc:2323
RequestFlags flags
Definition: HttpRequest.h:141
#define EBIT_SET(flag, bit)
Definition: defines.h:105
store_status_t store_status
Definition: Store.h:222
virtual void notePeerConnection(Comm::ConnectionPointer)
called just before a FwdState-dispatched job starts using connection
Definition: client_side.h:197
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: FwdState.cc:99
err_type type
Definition: errorpage.h:171
Ip::Address remote
Definition: Connection.h:138
#define COMM_TRANSPARENT
Definition: Connection.h:48
void Comm::ConnectionPointer & clientConn
Definition: stub_tunnel.cc:19
Acl::Address * outgoing_address
Definition: SquidConfig.h:379
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition: CbcPointer.h:162
static char server[MAXLINE]
bool intercepted
Definition: RequestFlags.h:62
void httpsPeeked(PinnedIdleContext pic)
called by FwdState when it is done bumping the server
void noteConnection(HappyConnOpenerAnswer &)
Definition: FwdState.cc:758
void HTTPMSGUNLOCK(M *&a)
Definition: Message.h:149
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
A simple PeerConnector for SSL/TLS cache_peers. No SslBump capabilities.
HttpRequestPointer request
Definition: errorpage.h:178
Callback dialer API to allow PeerConnector to set the answer.
Definition: PeerConnector.h:71
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:112
Comm::ConnectionPointer serverConn
a successfully opened connection to a server.
Definition: FwdState.h:191
void secureConnectionToPeerIfNeeded()
handles an established TCP connection to peer (including origin servers)
Definition: FwdState.cc:856
Definition: fde.h:49
Acl::Address * next
Definition: Address.h:27
struct CachePeer::@31 options
int setSockNfmark(const Comm::ConnectionPointer &conn, nfmark_t mark)
Definition: QosConfig.cc:586
void errorAppendEntry(StoreEntry *entry, ErrorState *err)
Definition: errorpage.cc:711
struct SquidConfig::@98 Timeout
static void Start(const Comm::ConnectionPointer &client, StoreEntry *, HttpRequest *, const AccessLogEntryPointer &alp)
Initiates request forwarding to a peer or origin server.
Definition: FwdState.cc:329
void fail(ErrorState *err)
Definition: FwdState.cc:457
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition: Message.h:98
Http::StatusCode status() const
retrieve the status code for this status line
Definition: StatusLine.h:45
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:961
void registerAbort(STABH *cb, void *)
Definition: store.cc:1520
bool no_tproxy
Definition: CachePeer.h:115
virtual void noteDestinationsEnd(ErrorState *selectionError) override
Definition: FwdState.cc:580
static void initModule()
Definition: FwdState.cc:1264
void dial(AsyncCall &call)
Definition: FwdState.cc:93
int n_tries
the number of forwarding attempts so far
Definition: FwdState.h:175
AsyncJobPointer StartRelay(FwdState *const fwdState)
A new FTP Relay job.
Definition: FtpRelay.cc:798
bool checkRetriable()
Whether we may try sending this request again after a failure.
Definition: FwdState.cc:691
void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry)
Definition: peer_select.cc:193
static OBJH fwdStats
Definition: FwdState.cc:74
bool denied() const
Definition: Acl.h:149
void unregisterAbort()
Definition: store.cc:1529
void successfullyConnectedToPeer()
called when all negotiations with the peer have been completed
Definition: FwdState.cc:922
void netdbPingSite(const char *hostname)
Definition: net_db.cc:909
AnyP::UriScheme const & getScheme() const
Definition: Uri.h:67
void notifyConnOpener()
makes sure connOpener knows that destinations have changed
Definition: FwdState.cc:617
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
Definition: comm.cc:988
void reset()
Definition: store.cc:1682
bool checkRetry()
Definition: FwdState.cc:647
ErrorState * err
Definition: FwdState.h:172
bool exhaustedTries() const
whether we have used up all permitted forwarding attempts
Definition: FwdState.cc:1290
CbcPointer< ErrorState > squidError
problem details (or nil)
int setSockTos(const Comm::ConnectionPointer &conn, tos_t tos)
Definition: QosConfig.cc:558
time_t connectingTimeout(const Comm::ConnectionPointer &conn) const
Definition: FwdState.cc:1318
HierarchyLogEntry hier
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:881
Ip::Address indirect_client_addr
Definition: HttpRequest.h:152
bool originserver
Definition: CachePeer.h:114
acl_access * serverPconnForNonretriable
Definition: SquidConfig.h:404
bool spoofClientIp
Definition: RequestFlags.h:70
StoreEntry * entry
Definition: FwdState.h:164
void getTosFromServer(const Comm::ConnectionPointer &server, fde *clientFde)
Definition: QosConfig.cc:41
void addPath(const Comm::ConnectionPointer &)
add a candidate path to try after all the existing paths
HttpRequestPointer request
Definition: MemObject.h:155
#define EBIT_TEST(flag, bit)
Definition: defines.h:107
uint32_t nfmark_t
Definition: forward.h:25
class SquidConfig Config
Definition: SquidConfig.cc:12
Ip::NfMarkConfig aclFindNfMarkConfig(acl_nfmark *head, ACLChecklist *ch)
Checks for a netfilter mark value to apply depending on the ACL.
Definition: FwdState.cc:1344
squidaio_request_t * head
Definition: aiops.cc:127
#define NULL
Definition: types.h:166
bool pinnedCanRetry() const
Definition: FwdState.cc:1296
opened (by Squid to an origin server or peer)
Definition: QosConfig.h:68
CbcPointer< ErrorState > error
problem details (nil on success)
bool empty() const
whether we lack any known candidate paths
Definition: ResolvedPeers.h:29
bool isHttpSafe() const
FwdStatePeerAnswerDialer(Method method, FwdState *fwd)
Definition: FwdState.cc:88
err_type
Definition: err_type.h:12
err_type aclGetDenyInfoPage(AclDenyInfoList **head, const char *name, int redirect_allowed)
Definition: Gadgets.cc:41
void unregister(Comm::ConnectionPointer &conn)
Definition: FwdState.cc:486
void lock(const char *context)
Definition: store.cc:439
bool opening() const
Definition: FwdState.h:157
AsyncCall::Pointer connector
a call linking us to the ConnOpener producing serverConn.
Definition: FwdState.h:179

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors