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 "comm/Connection.h"
22 #include "comm/ConnOpener.h"
23 #include "comm/Loops.h"
24 #include "CommCalls.h"
25 #include "errorpage.h"
26 #include "event.h"
27 #include "fd.h"
28 #include "fde.h"
29 #include "FwdState.h"
30 #include "globals.h"
31 #include "gopher.h"
32 #include "hier_code.h"
33 #include "http.h"
34 #include "http/Stream.h"
35 #include "HttpReply.h"
36 #include "HttpRequest.h"
37 #include "icmp/net_db.h"
38 #include "internal.h"
39 #include "ip/Intercept.h"
40 #include "ip/NfMarkConfig.h"
41 #include "ip/QosConfig.h"
42 #include "ip/tools.h"
43 #include "MemObject.h"
44 #include "mgr/Registration.h"
45 #include "neighbors.h"
46 #include "pconn.h"
47 #include "PeerPoolMgr.h"
49 #include "SquidConfig.h"
50 #include "SquidTime.h"
52 #include "Store.h"
53 #include "StoreClient.h"
54 #include "urn.h"
55 #include "whois.h"
56 #if USE_OPENSSL
58 #include "ssl/Config.h"
59 #include "ssl/ErrorDetail.h"
60 #include "ssl/helper.h"
61 #include "ssl/ServerBump.h"
62 #include "ssl/support.h"
63 #else
65 #endif
66 
67 #include <cerrno>
68 
71 
72 static OBJH fwdStats;
73 
74 #define MAX_FWD_STATS_IDX 9
76 
77 static PconnPool *fwdPconnPool = new PconnPool("server-peers", NULL);
79 
81 {
82 public:
84 
86  method_(method), fwd_(fwd), answer_() {}
87 
88  /* CallDialer API */
89  virtual bool canDial(AsyncCall &call) { return fwd_.valid(); }
90  void dial(AsyncCall &call) { ((&(*fwd_))->*method_)(answer_); }
91  virtual void print(std::ostream &os) const {
92  os << '(' << fwd_.get() << ", " << answer_ << ')';
93  }
94 
95  /* Security::PeerConnector::CbDialer API */
96  virtual Security::EncryptorAnswer &answer() { return answer_; }
97 
98 private:
102 };
103 
104 void
106 {
107  FwdState* fwd = (FwdState*)d;
108  Pointer tmp = fwd; // Grab a temporary pointer to keep the object alive during our scope.
109 
110  if (Comm::IsConnOpen(fwd->serverConnection())) {
111  fwd->closeServerConnection("store entry aborted");
112  } else {
113  debugs(17, 7, HERE << "store entry aborted; no connection to close");
114  }
115  fwd->serverDestinations.clear();
116  fwd->stopAndDestroy("store entry aborted");
117 }
118 
119 void
121 {
122  debugs(17, 3, "because " << reason << "; " << serverConn);
123  comm_remove_close_handler(serverConn->fd, closeHandler);
124  closeHandler = NULL;
125  fwdPconnPool->noteUses(fd_table[serverConn->fd].pconn.uses);
126  serverConn->close();
127 }
128 
129 /**** PUBLIC INTERFACE ********************************************************/
130 
132  entry(e),
133  request(r),
134  al(alp),
135  err(NULL),
136  clientConn(client),
137  start_t(squid_curtime),
138  n_tries(0),
139  pconnRace(raceImpossible)
140 {
141  debugs(17, 2, "Forwarding client request " << client << ", url=" << e->url());
144  e->lock("FwdState");
145  flags.connected_okay = false;
146  flags.dont_retry = false;
147  flags.forward_completed = false;
148  debugs(17, 3, "FwdState constructed, this=" << this);
149 }
150 
151 // Called once, right after object creation, when it is safe to set self
153 {
154  // Protect ourselves from being destroyed when the only Server pointing
155  // to us is gone (while we expect to talk to more Servers later).
156  // Once we set self, we are responsible for clearing it when we do not
157  // expect to talk to any servers.
158  self = aSelf; // refcounted
159 
160  // We hope that either the store entry aborts or peer is selected.
161  // Otherwise we are going to leak our object.
162 
163  // Ftp::Relay needs to preserve control connection on data aborts
164  // so it registers its own abort handler that calls ours when needed.
165  if (!request->flags.ftpNative)
167 
168  // just in case; should already be initialized to false
169  request->flags.pinned = false;
170 
171 #if STRICT_ORIGINAL_DST
172  // Bug 3243: CVE 2009-0801
173  // Bypass of browser same-origin access control in intercepted communication
174  // To resolve this we must force DIRECT and only to the original client destination.
175  const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.interceptTproxy);
176  const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified);
177  if (isIntercepted && useOriginalDst) {
178  selectPeerForIntercepted();
179  useDestinations();
180  return;
181  }
182 #endif
183 
184  // do full route options selection
186 }
187 
189 void
190 FwdState::stopAndDestroy(const char *reason)
191 {
192  debugs(17, 3, "for " << reason);
193  PeerSelectionInitiator::subscribed = false; // may already be false
194  self = nullptr; // we hope refcounting destroys us soon; may already be nil
195  /* do not place any code here as this object may be gone by now */
196 }
197 
198 #if STRICT_ORIGINAL_DST
199 void
201 FwdState::selectPeerForIntercepted()
202 {
203  // We do not support re-wrapping inside CONNECT.
204  // Our only alternative is to fake a noteDestination() call.
205 
206  // use pinned connection if available
207  if (ConnStateData *client = request->pinnedConnection()) {
208  // emulate the PeerSelector::selectPinned() "Skip ICP" effect
210 
211  serverDestinations.push_back(nullptr);
212  return;
213  }
214 
215  // use client original destination as second preferred choice
216  const auto p = new Comm::Connection();
217  p->peerType = ORIGINAL_DST;
218  p->remote = clientConn->local;
220 
221  debugs(17, 3, HERE << "using client original destination: " << *p);
222  serverDestinations.push_back(p);
223 }
224 #endif
225 
226 void
228 {
229  if (flags.forward_completed) {
230  debugs(17, DBG_IMPORTANT, HERE << "FwdState::completed called on a completed request! Bad!");
231  return;
232  }
233 
234  flags.forward_completed = true;
235 
236  request->hier.stopPeerClock(false);
237 
239  debugs(17, 3, HERE << "entry aborted");
240  return ;
241  }
242 
243 #if URL_CHECKSUM_DEBUG
244 
245  entry->mem_obj->checkUrlChecksum();
246 #endif
247 
248  if (entry->store_status == STORE_PENDING) {
249  if (entry->isEmpty()) {
250  if (!err) // we quit (e.g., fd closed) before an error or content
252  assert(err);
254  err = NULL;
255 #if USE_OPENSSL
259  }
260 #endif
261  } else {
262  entry->complete();
264  }
265  }
266 
267  if (storePendingNClients(entry) > 0)
269 
270 }
271 
273 {
274  debugs(17, 3, "FwdState destructor start");
275 
276  if (! flags.forward_completed)
277  completed();
278 
279  doneWithRetries();
280 
282 
283  delete err;
284 
286 
287  entry->unlock("FwdState");
288 
289  entry = NULL;
290 
291  if (calls.connector != NULL) {
292  calls.connector->cancel("FwdState destructed");
293  calls.connector = NULL;
294  }
295 
297  closeServerConnection("~FwdState");
298 
299  serverDestinations.clear();
300 
301  debugs(17, 3, "FwdState destructed, this=" << this);
302 }
303 
309 void
311 {
318  if ( Config.accessList.miss && !request->client_addr.isNoAddr() &&
319  !request->flags.internal && request->url.getScheme() != AnyP::PROTO_CACHE_OBJECT) {
326  ch.al = al;
327  ch.src_addr = request->client_addr;
328  ch.syncAle(request, nullptr);
329  if (ch.fastCheck().denied()) {
330  err_type page_id;
332 
333  if (page_id == ERR_NONE)
334  page_id = ERR_FORWARDING_DENIED;
335 
336  const auto anErr = new ErrorState(page_id, Http::scForbidden, request, al);
337  errorAppendEntry(entry, anErr); // frees anErr
338  return;
339  }
340  }
341 
342  debugs(17, 3, HERE << "'" << entry->url() << "'");
343  /*
344  * This seems like an odd place to bind mem_obj and request.
345  * Might want to assert that request is NULL at this point
346  */
347  entry->mem_obj->request = request;
348 #if URL_CHECKSUM_DEBUG
349 
350  entry->mem_obj->checkUrlChecksum();
351 #endif
352 
353  if (shutting_down) {
354  /* more yuck */
355  const auto anErr = new ErrorState(ERR_SHUTTING_DOWN, Http::scServiceUnavailable, request, al);
356  errorAppendEntry(entry, anErr); // frees anErr
357  return;
358  }
359 
360  if (request->flags.internal) {
361  debugs(17, 2, "calling internalStart() due to request flag");
362  internalStart(clientConn, request, entry, al);
363  return;
364  }
365 
366  switch (request->url.getScheme()) {
367 
369  debugs(17, 2, "calling CacheManager due to request scheme " << request->url.getScheme());
370  CacheManager::GetInstance()->start(clientConn, request, entry, al);
371  return;
372 
373  case AnyP::PROTO_URN:
374  urnStart(request, entry, al);
375  return;
376 
377  default:
378  FwdState::Pointer fwd = new FwdState(clientConn, entry, request, al);
379  fwd->start(fwd);
380  return;
381  }
382 
383  /* NOTREACHED */
384 }
385 
386 void
388 {
389  // Hides AccessLogEntry.h from code that does not supply ALE anyway.
390  Start(clientConn, entry, request, NULL);
391 }
392 
395 static inline time_t
396 diffOrZero(const time_t larger, const time_t smaller)
397 {
398  return (larger > smaller) ? (larger - smaller) : 0;
399 }
400 
402 time_t
404 {
405  // time already spent on forwarding (0 if clock went backwards)
406  const time_t timeSpent = diffOrZero(squid_curtime, fwdStart);
407  return diffOrZero(Config.Timeout.forward, timeSpent);
408 }
409 
410 bool
412 {
413  return ForwardTimeout(fwdStart) > 0;
414 }
415 
416 void
418 {
419  debugs(17, 3, serverDestinations.size() << " paths to " << entry->url());
420  if (!serverDestinations.empty()) {
421  if (!serverDestinations[0])
422  usePinned();
423  else
424  connectStart();
425  } else {
427  debugs(17, 4, "wait for more destinations to try");
428  return; // expect a noteDestination*() call
429  }
430 
431  debugs(17, 3, HERE << "Connection failed: " << entry->url());
432  if (!err) {
434  fail(anErr);
435  } // else use actual error from last connection attempt
436 
437  stopAndDestroy("tried all destinations");
438  }
439 }
440 
441 void
443 {
444  debugs(17, 3, err_type_str[errorState->type] << " \"" << Http::StatusCodeString(errorState->httpStatus) << "\"\n\t" << entry->url());
445 
446  delete err;
447  err = errorState;
448 
449  if (!errorState->request)
450  errorState->request = request;
451 
452  if (err->type != ERR_ZERO_SIZE_OBJECT)
453  return;
454 
455  if (pconnRace == racePossible) {
456  debugs(17, 5, HERE << "pconn race happened");
458  }
459 
460  if (ConnStateData *pinned_connection = request->pinnedConnection()) {
461  pinned_connection->pinning.zeroReply = true;
462  debugs(17, 4, "zero reply on pinned connection");
463  }
464 }
465 
469 void
471 {
472  debugs(17, 3, HERE << entry->url() );
473  assert(serverConnection() == conn);
474  assert(Comm::IsConnOpen(conn));
476  closeHandler = NULL;
477  serverConn = NULL;
478 }
479 
480 // \deprecated use unregister(Comm::ConnectionPointer &conn) instead
481 void
483 {
484  debugs(17, 3, HERE << entry->url() );
485  assert(fd == serverConnection()->fd);
487 }
488 
495 void
497 {
498  debugs(17, 3, HERE << entry->url() << "\n\tstatus " << entry->getReply()->sline.status());
499 #if URL_CHECKSUM_DEBUG
500 
501  entry->mem_obj->checkUrlChecksum();
502 #endif
503 
505 
506  if (reforward()) {
507  debugs(17, 3, HERE << "re-forwarding " << entry->getReply()->sline.status() << " " << entry->url());
508 
511 
512  entry->reset();
513 
514  // drop the last path off the selection list. try the next one.
515  if (!serverDestinations.empty()) // paranoid
516  serverDestinations.erase(serverDestinations.begin());
517  useDestinations();
518 
519  } else {
521  debugs(17, 3, HERE << "server FD " << serverConnection()->fd << " not re-forwarding status " << entry->getReply()->sline.status());
522  else
523  debugs(17, 3, HERE << "server (FD closed) not re-forwarding status " << entry->getReply()->sline.status());
524  entry->complete();
525 
527  completed();
528 
529  stopAndDestroy("forwarding completed");
530  }
531 }
532 
533 void
535 {
536  const bool wasBlocked = serverDestinations.empty();
537  // XXX: Push even a nil path so that subsequent noteDestination() calls
538  // can rely on wasBlocked to detect ongoing/concurrent attempts.
539  // Upcoming Happy Eyeballs changes will handle this properly.
540  serverDestinations.push_back(path);
541  assert(wasBlocked || path); // pinned destinations are always selected first
542 
543  if (wasBlocked)
544  useDestinations();
545  // else continue to use one of the previously noted destinations;
546  // if all of them fail, we may try this path
547 }
548 
549 void
551 {
553  if (serverDestinations.empty()) { // was blocked, waiting for more paths
554 
555  if (selectionError) {
556  debugs(17, 3, "Will abort forwarding because path selection has failed.");
557  Must(!err); // if we tried to connect, then path selection succeeded
558  fail(selectionError);
559  }
560  else if (err)
561  debugs(17, 3, "Will abort forwarding because all found paths have failed.");
562  else
563  debugs(17, 3, "Will abort forwarding because path selection found no paths.");
564 
565  useDestinations(); // will detect and handle the lack of paths
566  return;
567  }
568  // else continue to use one of the previously noted destinations;
569  // if all of them fail, forwarding as whole will fail
570  Must(!selectionError); // finding at least one path means selection succeeded
571 }
572 
573 /**** CALLBACK WRAPPERS ************************************************************/
574 
575 static void
577 {
578  FwdState *fwd = (FwdState *)params.data;
579  fwd->serverClosed(params.fd);
580 }
581 
582 void
584 {
585  FwdState *fwd = (FwdState *) data;
586  fwd->connectDone(conn, status, xerrno);
587 }
588 
589 /**** PRIVATE *****************************************************************/
590 
591 /*
592  * FwdState::checkRetry
593  *
594  * Return TRUE if the request SHOULD be retried. This method is
595  * called when the HTTP connection fails, or when the connection
596  * is closed before reading the end of HTTP headers from the server.
597  */
598 bool
600 {
601  if (shutting_down)
602  return false;
603 
604  if (!self) { // we have aborted before the server called us back
605  debugs(17, 5, HERE << "not retrying because of earlier abort");
606  // we will be destroyed when the server clears its Pointer to us
607  return false;
608  }
609 
611  return false;
612 
613  if (!entry->isEmpty())
614  return false;
615 
616  if (exhaustedTries())
617  return false;
618 
619  if (request->flags.pinned && !pinnedCanRetry())
620  return false;
621 
623  return false;
624 
625  if (flags.dont_retry)
626  return false;
627 
628  if (request->bodyNibbled())
629  return false;
630 
631  // NP: not yet actually connected anywhere. retry is safe.
632  if (!flags.connected_okay)
633  return true;
634 
635  if (!checkRetriable())
636  return false;
637 
638  return true;
639 }
640 
642 bool
644 {
645  // Optimize: A compliant proxy may retry PUTs, but Squid lacks the [rather
646  // complicated] code required to protect the PUT request body from being
647  // nibbled during the first try. Thus, Squid cannot retry some PUTs today.
648  if (request->body_pipe != NULL)
649  return false;
650 
651  // RFC2616 9.1 Safe and Idempotent Methods
653 }
654 
655 void
657 {
658  // XXX: fd is often -1 here
659  debugs(17, 2, "FD " << fd << " " << entry->url() << " after " <<
660  (fd >= 0 ? fd_table[fd].pconn.uses : -1) << " requests");
661  if (fd >= 0 && serverConnection()->fd == fd)
662  fwdPconnPool->noteUses(fd_table[fd].pconn.uses);
663  retryOrBail();
664 }
665 
666 void
668 {
669  if (checkRetry()) {
670  debugs(17, 3, HERE << "re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)");
671  // we should retry the same destination if it failed due to pconn race
672  if (pconnRace == raceHappened)
673  debugs(17, 4, HERE << "retrying the same destination");
674  else
675  serverDestinations.erase(serverDestinations.begin()); // last one failed. try another.
676  useDestinations();
677  return;
678  }
679 
680  // TODO: should we call completed() here and move doneWithRetries there?
681  doneWithRetries();
682 
683  request->hier.stopPeerClock(false);
684 
685  if (self != NULL && !err && shutting_down && entry->isEmpty()) {
687  errorAppendEntry(entry, anErr);
688  }
689 
690  stopAndDestroy("cannot retry");
691 }
692 
693 // If the Server quits before nibbling at the request body, the body sender
694 // will not know (so that we can retry). Call this if we will not retry. We
695 // will notify the sender so that it does not get stuck waiting for space.
696 void
698 {
699  if (request && request->body_pipe != NULL)
701 }
702 
703 // called by the server that failed after calling unregister()
704 void
706 {
707  debugs(17, 2, HERE << "self=" << self << " err=" << err << ' ' << entry->url());
709  retryOrBail();
710 }
711 
712 void
714 {
715  if (status != Comm::OK) {
717  anErr->xerrno = xerrno;
718  fail(anErr);
719 
720  /* it might have been a timeout with a partially open link */
721  if (conn != NULL) {
722  if (conn->getPeer())
723  peerConnectFailed(conn->getPeer());
724 
725  conn->close();
726  }
727  retryOrBail();
728  return;
729  }
730 
731  serverConn = conn;
732  debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
733 
735 
736  // request->flags.pinned cannot be true in connectDone(). The flag is
737  // only set when we dispatch the request to an existing (pinned) connection.
739 
740  const CachePeer *p = serverConnection()->getPeer();
741  const bool peerWantsTls = p && p->secure.encryptTransport;
742  // userWillTlsToPeerForUs assumes CONNECT == HTTPS
743  const bool userWillTlsToPeerForUs = p && p->options.originserver &&
745  const bool needTlsToPeer = peerWantsTls && !userWillTlsToPeerForUs;
746  const bool needTlsToOrigin = !p && request->url.getScheme() == AnyP::PROTO_HTTPS;
747  if (needTlsToPeer || needTlsToOrigin || request->flags.sslPeek) {
748  HttpRequest::Pointer requestPointer = request;
750  "FwdState::ConnectedToPeer",
752  // Use positive timeout when less than one second is left.
753  const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t);
754  const time_t sslNegotiationTimeout = positiveTimeout(connTimeout);
756 #if USE_OPENSSL
757  if (request->flags.sslPeek)
758  connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, al, sslNegotiationTimeout);
759  else
760 #endif
761  connector = new Security::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
762  AsyncJob::Start(connector); // will call our callback
763  return;
764  }
765 
766  // if not encrypting just run the post-connect actions
768  connectedToPeer(nil);
769 }
770 
771 void
773 {
774  if (ErrorState *error = answer.error.get()) {
775  fail(error);
776  answer.error.clear(); // preserve error for errorSendComplete()
777  if (CachePeer *p = serverConnection()->getPeer())
779  serverConnection()->close();
780  return;
781  }
782 
783  if (answer.tunneled) {
784  // TODO: When ConnStateData establishes tunnels, its state changes
785  // [in ways that may affect logging?]. Consider informing
786  // ConnStateData about our tunnel or otherwise unifying tunnel
787  // establishment [side effects].
788  unregister(serverConn); // async call owns it now
789  complete(); // destroys us
790  return;
791  }
792 
793  // should reach ConnStateData before the dispatched Client job starts
796 
797  if (serverConnection()->getPeer())
799 
800  flags.connected_okay = true;
801  dispatch();
802 }
803 
804 void
806 {
807  debugs(17, 2, "fwdConnectTimeout: FD " << fd << ": '" << entry->url() << "'" );
809  assert(fd == serverDestinations[0]->fd);
810 
811  if (entry->isEmpty()) {
812  const auto anErr = new ErrorState(ERR_CONNECT_FAIL, Http::scGatewayTimeout, request, al);
813  anErr->xerrno = ETIMEDOUT;
814  fail(anErr);
815 
816  /* This marks the peer DOWN ... */
817  if (serverDestinations[0]->getPeer())
818  peerConnectFailed(serverDestinations[0]->getPeer());
819  }
820 
822  serverDestinations[0]->close();
823  }
824 }
825 
827 void
829 {
830  if (Ip::Qos::TheConfig.isAclTosActive())
832 
833 #if SO_MARK
834  if (Ip::Qos::TheConfig.isAclNfmarkActive())
836 #endif
837 
838  syncHierNote(serverConn, host);
839 }
840 
841 void
843 {
844  if (request)
845  request->hier.resetPeerNotes(server, host);
846  if (al)
847  al->hier.resetPeerNotes(server, host);
848 }
849 
855 void
857 {
858  assert(serverDestinations.size() > 0);
859 
860  debugs(17, 3, "fwdConnectStart: " << entry->url());
861 
862  // pinned connections go through usePinned() rather than connectStart()
863  assert(serverDestinations[0] != nullptr);
864  request->flags.pinned = false;
865 
866  // Ditch the previous error if any.
867  // A new error page will be created if there is another problem.
868  delete err;
869  err = nullptr;
870  request->clearError();
871 
872  // Update logging information with the upcoming server connection
873  // destination. Do this early so that any connection establishment errors
874  // are attributed to this destination. If successfully connected, this
875  // destination becomes serverConnection().
877 
879 
880  // Do not fowrward bumped connections to parent proxy unless it is an
881  // origin server
882  if (serverDestinations[0]->getPeer() && !serverDestinations[0]->getPeer()->options.originserver && request->flags.sslBumped) {
883  debugs(50, 4, "fwdConnectStart: Ssl bumped connections through parent proxy are not allowed");
885  fail(anErr);
886  stopAndDestroy("SslBump misconfiguration");
887  return;
888  }
889 
890  // Use pconn to avoid opening a new connection.
891  const char *host = NULL;
892  if (!serverDestinations[0]->getPeer())
893  host = request->url.host();
894 
896  // Avoid pconns after races so that the same client does not suffer twice.
897  // This does not increase the total number of connections because we just
898  // closed the connection that failed the race. And re-pinning assumes this.
899  if (pconnRace != raceHappened)
900  temp = pconnPop(serverDestinations[0], host);
901 
902  const bool openedPconn = Comm::IsConnOpen(temp);
903  pconnRace = openedPconn ? racePossible : raceImpossible;
904 
905  // if we found an open persistent connection to use. use it.
906  if (openedPconn) {
907  serverConn = temp;
908  flags.connected_okay = true;
909  debugs(17, 3, HERE << "reusing pconn " << serverConnection());
910  ++n_tries;
911 
913 
915 
916  dispatch();
917  return;
918  }
919 
920  // We will try to open a new connection, possibly to the same destination.
921  // We reset serverDestinations[0] in case we are using it again because
922  // ConnOpener modifies its destination argument.
923  serverDestinations[0]->local.port(0);
924  serverConn = NULL;
925 
926 #if URL_CHECKSUM_DEBUG
927  entry->mem_obj->checkUrlChecksum();
928 #endif
929 
931 
932  calls.connector = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
933  const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t);
934  Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, connTimeout);
935  if (host)
936  cs->setHost(host);
937  ++n_tries;
938  AsyncJob::Start(cs);
939 }
940 
942 void
944 {
945  // we only handle pinned destinations; others are handled by connectStart()
946  assert(!serverDestinations.empty());
948 
949  const auto connManager = request->pinnedConnection();
950  debugs(17, 7, "connection manager: " << connManager);
951 
952  // the client connection may close while we get here, nullifying connManager
953  const auto temp = connManager ? connManager->borrowPinnedConnection(request) : nullptr;
954  debugs(17, 5, "connection: " << temp);
955 
956  // the previously pinned idle peer connection may get closed (by the peer)
957  if (!Comm::IsConnOpen(temp)) {
958  syncHierNote(temp, connManager ? connManager->pinning.host : request->url.host());
959  serverConn = nullptr;
961  fail(anErr);
962  // Connection managers monitor their idle pinned to-server
963  // connections and close from-client connections upon seeing
964  // a to-server connection closure. Retrying here is futile.
965  stopAndDestroy("pinned connection failure");
966  return;
967  }
968 
969  serverConn = temp;
970  flags.connected_okay = true;
971  ++n_tries;
972  request->flags.pinned = true;
973 
974  assert(connManager);
975  if (connManager->pinnedAuth())
976  request->flags.auth = true;
977 
979 
980  syncWithServerConn(connManager->pinning.host);
981 
982  // the server may close the pinned connection before this request
984  dispatch();
985 }
986 
987 void
989 {
990  debugs(17, 3, clientConn << ": Fetching " << request->method << ' ' << entry->url());
991  /*
992  * Assert that server_fd is set. This is to guarantee that fwdState
993  * is attached to something and will be deallocated when server_fd
994  * is closed.
995  */
997 
998  fd_note(serverConnection()->fd, entry->url());
999 
1000  fd_table[serverConnection()->fd].noteUse();
1001 
1002  /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
1004 
1005  assert(entry->locked());
1006 
1008 
1010 
1011  /* Retrieves remote server TOS or MARK value, and stores it as part of the
1012  * original client request FD object. It is later used to forward
1013  * remote server's TOS/MARK in the response to the client in case of a MISS.
1014  */
1015  if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
1017  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
1018  /* Get the netfilter CONNMARK */
1020  }
1021  }
1022 
1023 #if _SQUID_LINUX_
1024  /* Bug 2537: The TOS forward part of QOS only applies to patched Linux kernels. */
1025  if (Ip::Qos::TheConfig.isHitTosActive()) {
1027  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
1028  /* Get the TOS value for the packet */
1030  }
1031  }
1032 #endif
1033 
1034 #if USE_OPENSSL
1035  if (request->flags.sslPeek) {
1038  unregister(serverConn); // async call owns it now
1039  complete(); // destroys us
1040  return;
1041  }
1042 #endif
1043 
1044  if (serverConnection()->getPeer() != NULL) {
1049  httpStart(this);
1050  } else {
1052  request->peer_login = NULL;
1055 
1056  switch (request->url.getScheme()) {
1057 
1058  case AnyP::PROTO_HTTPS:
1059  httpStart(this);
1060  break;
1061 
1062  case AnyP::PROTO_HTTP:
1063  httpStart(this);
1064  break;
1065 
1066  case AnyP::PROTO_GOPHER:
1067  gopherStart(this);
1068  break;
1069 
1070  case AnyP::PROTO_FTP:
1071  if (request->flags.ftpNative)
1072  Ftp::StartRelay(this);
1073  else
1074  Ftp::StartGateway(this);
1075  break;
1076 
1078 
1079  case AnyP::PROTO_URN:
1080  fatal_dump("Should never get here");
1081  break;
1082 
1083  case AnyP::PROTO_WHOIS:
1084  whoisStart(this);
1085  break;
1086 
1087  case AnyP::PROTO_WAIS: /* Not implemented */
1088 
1089  default:
1090  debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->url() << "'.");
1091  const auto anErr = new ErrorState(ERR_UNSUP_REQ, Http::scBadRequest, request, al);
1092  fail(anErr);
1093  // Set the dont_retry flag because this is not a transient (network) error.
1094  flags.dont_retry = true;
1096  serverConn->close();
1097  }
1098  break;
1099  }
1100  }
1101 }
1102 
1103 /*
1104  * FwdState::reforward
1105  *
1106  * returns TRUE if the transaction SHOULD be re-forwarded to the
1107  * next choice in the serverDestinations list. This method is called when
1108  * peer communication completes normally, or experiences
1109  * some error after receiving the end of HTTP headers.
1110  */
1111 int
1113 {
1114  StoreEntry *e = entry;
1115 
1116  if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
1117  debugs(17, 3, HERE << "entry aborted");
1118  return 0;
1119  }
1120 
1122  assert(e->mem_obj);
1123 #if URL_CHECKSUM_DEBUG
1124 
1125  e->mem_obj->checkUrlChecksum();
1126 #endif
1127 
1128  debugs(17, 3, HERE << e->url() << "?" );
1129 
1130  if (request->flags.pinned && !pinnedCanRetry()) {
1131  debugs(17, 3, "pinned connection; cannot retry");
1132  return 0;
1133  }
1134 
1135  if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
1136  debugs(17, 3, HERE << "No, ENTRY_FWD_HDR_WAIT isn't set");
1137  return 0;
1138  }
1139 
1140  if (exhaustedTries())
1141  return 0;
1142 
1143  if (request->bodyNibbled())
1144  return 0;
1145 
1147  // NP: <= 1 since total count includes the recently failed one.
1148  debugs(17, 3, HERE << "No alternative forwarding paths left");
1149  return 0;
1150  }
1151 
1152  const Http::StatusCode s = e->getReply()->sline.status();
1153  debugs(17, 3, HERE << "status " << s);
1154  return reforwardableStatus(s);
1155 }
1156 
1163 ErrorState *
1165 {
1166  return new ErrorState(type, request->flags.needValidation ?
1168 }
1169 
1170 static void
1172 {
1173  int i;
1174  int j;
1175  storeAppendPrintf(s, "Status");
1176 
1177  for (j = 1; j < MAX_FWD_STATS_IDX; ++j) {
1178  storeAppendPrintf(s, "\ttry#%d", j);
1179  }
1180 
1181  storeAppendPrintf(s, "\n");
1182 
1183  for (i = 0; i <= (int) Http::scInvalidHeader; ++i) {
1184  if (FwdReplyCodes[0][i] == 0)
1185  continue;
1186 
1187  storeAppendPrintf(s, "%3d", i);
1188 
1189  for (j = 0; j <= MAX_FWD_STATS_IDX; ++j) {
1190  storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]);
1191  }
1192 
1193  storeAppendPrintf(s, "\n");
1194  }
1195 }
1196 
1197 /**** STATIC MEMBER FUNCTIONS *************************************************/
1198 
1199 bool
1201 {
1202  switch (s) {
1203 
1204  case Http::scBadGateway:
1205 
1207  return true;
1208 
1209  case Http::scForbidden:
1210 
1212 
1214 
1216  return Config.retry.onerror;
1217 
1218  default:
1219  return false;
1220  }
1221 
1222  /* NOTREACHED */
1223 }
1224 
1231 void
1233 {
1234  if (conn->getPeer()) {
1235  fwdPconnPool->push(conn, NULL);
1236  } else {
1237  fwdPconnPool->push(conn, domain);
1238  }
1239 }
1240 
1242 FwdState::pconnPop(const Comm::ConnectionPointer &dest, const char *domain)
1243 {
1244  bool retriable = checkRetriable();
1245  if (!retriable && Config.accessList.serverPconnForNonretriable) {
1247  ch.al = al;
1248  ch.syncAle(request, nullptr);
1249  retriable = ch.fastCheck().allowed();
1250  }
1251  // always call shared pool first because we need to close an idle
1252  // connection there if we have to use a standby connection.
1253  Comm::ConnectionPointer conn = fwdPconnPool->pop(dest, domain, retriable);
1254  if (!Comm::IsConnOpen(conn)) {
1255  // either there was no pconn to pop or this is not a retriable xaction
1256  if (CachePeer *peer = dest->getPeer()) {
1257  if (peer->standby.pool)
1258  conn = peer->standby.pool->pop(dest, domain, true);
1259  }
1260  }
1261  return conn; // open, closed, or nil
1262 }
1263 
1264 void
1266 {
1268 }
1269 
1270 void
1272 {
1273  Mgr::RegisterAction("forward", "Request Forwarding Statistics", fwdStats, 0, 1);
1274 }
1275 
1276 void
1278 {
1279  if (status > Http::scInvalidHeader)
1280  return;
1281 
1282  assert(tries >= 0);
1283 
1284  if (tries > MAX_FWD_STATS_IDX)
1285  tries = MAX_FWD_STATS_IDX;
1286 
1287  ++ FwdReplyCodes[tries][status];
1288 }
1289 
1290 bool
1292 {
1293  return n_tries >= Config.forward_max_tries;
1294 }
1295 
1296 bool
1298 {
1300 
1301  // pconn race on pinned connection: Currently we do not have any mechanism
1302  // to retry current pinned connection path.
1303  if (pconnRace == raceHappened)
1304  return false;
1305 
1306  // If a bumped connection was pinned, then the TLS client was given our peer
1307  // details. Do not retry because we do not ensure that those details stay
1308  // constant. Step1-bumped connections do not get our TLS peer details, are
1309  // never pinned, and, hence, never reach this method.
1310  if (request->flags.sslBumped)
1311  return false;
1312 
1313  // The other pinned cases are FTP proxying and connection-based HTTP
1314  // authentication. TODO: Do these cases have restrictions?
1315  return true;
1316 }
1317 
1318 /**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
1319 
1320 /*
1321  * DPW 2007-05-19
1322  * Formerly static, but now used by client_side_request.cc
1323  */
1325 tos_t
1327 {
1328  for (acl_tos *l = head; l; l = l->next) {
1329  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1330  return l->tos;
1331  }
1332 
1333  return 0;
1334 }
1335 
1339 {
1340  for (acl_nfmark *l = head; l; l = l->next) {
1341  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1342  return l->markConfig;
1343  }
1344 
1345  return {};
1346 }
1347 
1348 void
1350 {
1351  // skip if an outgoing address is already set.
1352  if (!conn->local.isAnyAddr()) return;
1353 
1354  // ensure that at minimum the wildcard local matches remote protocol
1355  if (conn->remote.isIPv4())
1356  conn->local.setIPv4();
1357 
1358  // maybe use TPROXY client address
1359  if (request && request->flags.spoofClientIp) {
1360  if (!conn->getPeer() || !conn->getPeer()->options.no_tproxy) {
1361 #if FOLLOW_X_FORWARDED_FOR && LINUX_NETFILTER
1363  conn->local = request->indirect_client_addr;
1364  else
1365 #endif
1366  conn->local = request->client_addr;
1367  conn->local.port(0); // let OS pick the source port to prevent address clashes
1368  // some flags need setting on the socket to use this address
1369  conn->flags |= COMM_DOBIND;
1370  conn->flags |= COMM_TRANSPARENT;
1371  return;
1372  }
1373  // else no tproxy today ...
1374  }
1375 
1377  return; // anything will do.
1378  }
1379 
1380  ACLFilledChecklist ch(NULL, request, NULL);
1381  ch.dst_peer_name = conn->getPeer() ? conn->getPeer()->name : NULL;
1382  ch.dst_addr = conn->remote;
1383 
1384  // TODO use the connection details in ACL.
1385  // needs a bit of rework in ACLFilledChecklist to use Comm::Connection instead of ConnStateData
1386 
1387  for (Acl::Address *l = Config.accessList.outgoing_address; l; l = l->next) {
1388 
1389  /* check if the outgoing address is usable to the destination */
1390  if (conn->remote.isIPv4() != l->addr.isIPv4()) continue;
1391 
1392  /* check ACLs for this outgoing address */
1393  if (!l->aclList || ch.fastCheck(l->aclList).allowed()) {
1394  conn->local = l->addr;
1395  return;
1396  }
1397  }
1398 }
1399 
1400 tos_t
1402 {
1403  ACLFilledChecklist ch(NULL, request, NULL);
1404  return aclMapTOS(Ip::Qos::TheConfig.tosToServer, &ch);
1405 }
1406 
1407 nfmark_t
1409 {
1410  ACLFilledChecklist ch(NULL, request, NULL);
1411  const auto mc = aclFindNfMarkConfig(Ip::Qos::TheConfig.nfmarkToServer, &ch);
1412  return mc.mark;
1413 }
1414 
1415 void
1417 {
1418  // Get the server side TOS and Netfilter mark to be set on the connection.
1419  if (Ip::Qos::TheConfig.isAclTosActive()) {
1420  conn.tos = GetTosToServer(request);
1421  debugs(17, 3, "from " << conn.local << " tos " << int(conn.tos));
1422  }
1423 
1424 #if SO_MARK && USE_LIBCAP
1425  conn.nfmark = GetNfmarkToServer(request);
1426  debugs(17, 3, "from " << conn.local << " netfilter mark " << conn.nfmark);
1427 #else
1428  conn.nfmark = 0;
1429 #endif
1430 }
1431 
bool setIPv4()
Definition: Address.cc:224
void getOutgoingAddress(HttpRequest *request, Comm::ConnectionPointer conn)
Definition: FwdState.cc:1349
void urnStart(HttpRequest *r, StoreEntry *e, const AccessLogEntryPointer &ale)
Definition: urn.cc:227
HierarchyLogEntry hier
Definition: HttpRequest.h:149
nfmark_t GetNfmarkToServer(HttpRequest *request)
Definition: FwdState.cc:1408
bool interceptTproxy
Set for requests handled by a "tproxy" port.
Definition: RequestFlags.h:68
char * login
Definition: CachePeer.h:171
#define fd_table
Definition: fde.h:157
ConnStateData * pinnedConnection()
Definition: HttpRequest.cc:668
unsigned short port() const
Definition: Address.cc:778
#define assert(EX)
Definition: assert.h:17
int reforward()
Definition: FwdState.cc:1112
bool isIdempotent() const
const char * StatusCodeString(const Http::StatusCode status)
Definition: stub_libhttp.cc:86
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: FwdState.cc:534
void const char HLPCB * callback
Definition: stub_helper.cc:16
void connectedToPeer(Security::EncryptorAnswer &answer)
Definition: FwdState.cc:772
static bool EnoughTimeToReForward(const time_t fwdStart)
Definition: FwdState.cc:411
struct FwdState::@72 calls
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:396
void noteUses(int uses)
Definition: pconn.cc:507
void pconnPush(Comm::ConnectionPointer &conn, const char *domain)
Definition: FwdState.cc:1232
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:250
void serverClosed(int fd)
Definition: FwdState.cc:656
Ip::Address dst_addr
int storePendingNClients(const StoreEntry *e)
CbcPointer< ErrorState > error
problem details (nil on success)
int type
Definition: errorpage.cc:152
bool ftpNative
carries a representation of an FTP command [received on ftp_port]
Definition: RequestFlags.h:105
void dispatch()
Definition: FwdState.cc:988
tos_t GetTosToServer(HttpRequest *request)
Definition: FwdState.cc:1401
char * domain
Forced domain.
Definition: CachePeer.h:184
bool isNoAddr() const
Definition: Address.cc:284
void(FwdState::* Method)(Security::EncryptorAnswer &)
Definition: FwdState.cc:83
Ip::Address src_addr
HttpRequestMethod method
Definition: HttpRequest.h:106
void setHost(const char *)
set the hostname note for this connection
Definition: ConnOpener.cc:89
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
void error(char *format,...)
Security::EncryptorAnswer answer_
Definition: FwdState.cc:101
int i
Definition: membanger.c:49
int client_dst_passthru
Definition: SquidConfig.h:341
bool denied() const
Definition: Acl.h:147
unsigned int nfConnmarkFromServer
Definition: fde.h:150
struct CachePeer::@29 stats
bool encryptTransport
whether transport encryption (TLS/SSL) is to be used on connections to the peer
Definition: PeerOptions.h:125
tos_t aclMapTOS(acl_tos *head, ACLChecklist *ch)
Checks for a TOS value to apply depending on the ACL.
Definition: FwdState.cc:1326
static void RegisterWithCacheManager(void)
Definition: FwdState.cc:1271
Definition: Flag.h:16
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:131
acl_tos * next
Definition: QosConfig.h:36
void connectTimeout(int fd)
Definition: FwdState.cc:805
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:148
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
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:190
virtual void print(std::ostream &os) const
Definition: FwdState.cc:91
A PeerConnector for HTTP origin servers. Capable of SslBumping.
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:66
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:107
void useDestinations()
Definition: FwdState.cc:417
list of address-based ACLs.
Definition: Address.h:19
void retryOrBail()
Definition: FwdState.cc:667
void completed()
Definition: FwdState.cc:227
const char * err_type_str[]
time_t squid_curtime
Definition: stub_time.cc:17
bool auth_no_keytab
Definition: CachePeer.h:119
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:387
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 GetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
Sets initial TOS value and Netfilter for the future outgoing connection.
Definition: FwdState.cc:1416
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:272
parameters for the async notePinnedConnectionBecameIdle() call
Definition: client_side.h:168
void whoisStart(FwdState *fwd)
Definition: whois.cc:57
void connectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno)
Definition: FwdState.cc:713
void push(const Comm::ConnectionPointer &serverConn, const char *domain)
Definition: pconn.cc:407
time_t forward
Definition: SquidConfig.h:110
int shutting_down
#define COMM_DOBIND
Definition: Connection.h:47
time_t start_t
Definition: FwdState.h:157
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:842
void const char HLPCB void * data
Definition: stub_helper.cc:16
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:152
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1292
Comm::ConnectionPointer clientConn
a possibly open connection to the client.
Definition: FwdState.h:156
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
CbcPointer< FwdState > fwd_
Definition: FwdState.cc:100
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
void complete()
Definition: FwdState.cc:496
bool auth_no_keytab
Definition: RequestFlags.h:30
Ip::Address client_addr
Definition: HttpRequest.h:141
static time_t ForwardTimeout(const time_t fwdStart)
time left to finish the whole forwarding process (which started at fwdStart)
Definition: FwdState.cc:403
void internalStart(const Comm::ConnectionPointer &clientConn, HttpRequest *request, StoreEntry *entry, const AccessLogEntry::Pointer &ale)
Definition: internal.cc:32
bool bodyNibbled() const
Definition: HttpRequest.cc:450
Comm::ConnectionList serverDestinations
Definition: FwdState.h:172
void closeServerConnection(const char *reason)
stops monitoring server connection for closure and updates pconn stats
Definition: FwdState.cc:120
static void abort(void *)
Definition: FwdState.cc:105
void handleUnregisteredServerEnd()
Definition: FwdState.cc:705
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:107
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:1277
void start(const Comm::ConnectionPointer &client, HttpRequest *request, StoreEntry *entry, const AccessLogEntryPointer &ale)
CbcPointer< ConnStateData > clientConnectionManager
Definition: HttpRequest.h:222
struct SquidConfig::@113 accessList
acl_access * miss
Definition: SquidConfig.h:361
#define MAX_FWD_STATS_IDX
Definition: FwdState.cc:74
Http::StatusCode httpStatus
Definition: errorpage.h:166
void releaseRequest(const bool shareable=false)
Definition: store.cc:452
uint16_t flags
Definition: Store.h:210
static CLCB fwdServerClosedWrapper
Definition: FwdState.cc:69
PconnRace pconnRace
current pconn race state
Definition: FwdState.h:180
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:62
int fetches
Definition: CachePeer.h:45
void connectStart()
Definition: FwdState.cc:856
Http::StatusLine sline
Definition: HttpReply.h:60
void usePinned()
send request on an existing connection dedicated to the requesting client
Definition: FwdState.cc:943
const char * AclMatchedName
Definition: Acl.cc:30
void host(const char *src)
Definition: Uri.cc:47
void doneWithRetries()
Definition: FwdState.cc:697
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:89
void clearError()
clear error details, useful for retries/repeats
Definition: HttpRequest.cc:470
void gopherStart(FwdState *fwd)
Definition: gopher.cc:928
void syncWithServerConn(const char *host)
called when serverConn is set to an open to-peer connection
Definition: FwdState.cc:828
static int FwdReplyCodes[MAX_FWD_STATS_IDX+1][Http::scInvalidHeader+1]
Definition: FwdState.cc:75
ErrorState * makeConnectingError(const err_type type) const
Definition: FwdState.cc:1164
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
static CNCB fwdConnectDoneWrapper
Definition: FwdState.cc:70
Flag
Definition: Flag.h:15
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:176
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:1200
AccessLogEntryPointer al
info for the future access.log entry
Definition: FwdState.h:149
void httpStart(FwdState *fwd)
Definition: http.cc:2302
RequestFlags flags
Definition: HttpRequest.h:133
#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:200
virtual Security::EncryptorAnswer & answer()
gives PeerConnector access to the in-dialer answer
Definition: FwdState.cc:96
err_type type
Definition: errorpage.h:163
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:64
void httpsPeeked(PinnedIdleContext pic)
called by FwdState when it is done bumping the server
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:170
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
bool allowed() const
Definition: Acl.h:141
Comm::ConnectionPointer serverConn
a successfully opened connection to a server.
Definition: FwdState.h:174
Definition: fde.h:49
void CNCB(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data)
Definition: CommCalls.h:35
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:691
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:310
void fail(ErrorState *err)
Definition: FwdState.cc:442
allow_t const & fastCheck()
Definition: Checklist.cc:336
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition: Message.h:98
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
Definition: CommCalls.h:342
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:550
static void initModule()
Definition: FwdState.cc:1265
void dial(AsyncCall &call)
Definition: FwdState.cc:90
int n_tries
the number of forwarding attempts so far
Definition: FwdState.h:158
AsyncJobPointer StartRelay(FwdState *const fwdState)
A new FTP Relay job.
Definition: FtpRelay.cc:798
int xerrno
Definition: errorpage.h:172
bool checkRetriable()
Whether we may try sending this request again after a failure.
Definition: FwdState.cc:643
void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry)
Definition: peer_select.cc:193
static OBJH fwdStats
Definition: FwdState.cc:72
void unregisterAbort()
Definition: store.cc:1529
void netdbPingSite(const char *hostname)
Definition: net_db.cc:909
AnyP::UriScheme const & getScheme() const
Definition: Uri.h:67
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:599
ErrorState * err
Definition: FwdState.h:155
bool exhaustedTries() const
whether we have used up all permitted forwarding attempts
Definition: FwdState.cc:1291
int setSockTos(const Comm::ConnectionPointer &conn, tos_t tos)
Definition: QosConfig.cc:558
HierarchyLogEntry hier
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:881
char * peer_login
Definition: HttpRequest.h:156
Ip::Address indirect_client_addr
Definition: HttpRequest.h:144
bool originserver
Definition: CachePeer.h:114
acl_access * serverPconnForNonretriable
Definition: SquidConfig.h:404
bool spoofClientIp
Definition: RequestFlags.h:72
StoreEntry * entry
Definition: FwdState.h:147
void getTosFromServer(const Comm::ConnectionPointer &server, fde *clientFde)
Definition: QosConfig.cc:41
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
void Controller::create() STUB void Controller Controller nil
Ip::NfMarkConfig aclFindNfMarkConfig(acl_nfmark *head, ACLChecklist *ch)
Checks for a netfilter mark value to apply depending on the ACL.
Definition: FwdState.cc:1338
squidaio_request_t * head
Definition: aiops.cc:127
#define NULL
Definition: types.h:166
bool pinnedCanRetry() const
Definition: FwdState.cc:1297
bool needValidation
Definition: RequestFlags.h:48
opened (by Squid to an origin server or peer)
Definition: QosConfig.h:68
char * peer_domain
Definition: HttpRequest.h:165
bool isHttpSafe() const
FwdStatePeerAnswerDialer(Method method, FwdState *fwd)
Definition: FwdState.cc:85
Comm::ConnectionPointer pconnPop(const Comm::ConnectionPointer &dest, const char *domain)
Definition: FwdState.cc:1242
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:470
Comm::ConnectionPointer pop(const Comm::ConnectionPointer &dest, const char *domain, bool keepOpen)
Definition: pconn.cc:444
void lock(const char *context)
Definition: store.cc:439
AsyncCall::Pointer connector
a call linking us to the ConnOpener producing serverConn.
Definition: FwdState.h:162

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors