FwdState.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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 #if STRICT_ORIGINAL_DST
169  // Bug 3243: CVE 2009-0801
170  // Bypass of browser same-origin access control in intercepted communication
171  // To resolve this we must force DIRECT and only to the original client destination.
172  const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.interceptTproxy);
173  const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified);
174  if (isIntercepted && useOriginalDst) {
175  selectPeerForIntercepted();
176  // 3.2 does not suppro re-wrapping inside CONNECT.
177  // our only alternative is to fake destination "found" and continue with the forwarding.
179  return;
180  }
181 #endif
182 
183  // do full route options selection
185 }
186 
188 void
189 FwdState::stopAndDestroy(const char *reason)
190 {
191  debugs(17, 3, "for " << reason);
192  PeerSelectionInitiator::subscribed = false; // may already be false
193  self = nullptr; // we hope refcounting destroys us soon; may already be nil
194  /* do not place any code here as this object may be gone by now */
195 }
196 
197 #if STRICT_ORIGINAL_DST
198 void
200 FwdState::selectPeerForIntercepted()
201 {
202  // use pinned connection if available
204  if (ConnStateData *client = request->pinnedConnection()) {
205  p = client->validatePinnedConnection(request, NULL);
206  if (Comm::IsConnOpen(p)) {
207  /* duplicate peerSelectPinned() effects */
208  p->peerType = PINNED;
209  entry->ping_status = PING_DONE; /* Skip ICP */
210 
211  debugs(17, 3, "reusing a pinned conn: " << *p);
212  serverDestinations.push_back(p);
213  } else {
214  debugs(17,2, "Pinned connection is not valid: " << p);
216  fail(anErr);
217  }
218  // Either use the valid pinned connection or fail if it is invalid.
219  return;
220  }
221 
222  // use client original destination as second preferred choice
223  p = new Comm::Connection();
224  p->peerType = ORIGINAL_DST;
225  p->remote = clientConn->local;
227 
228  debugs(17, 3, HERE << "using client original destination: " << *p);
229  serverDestinations.push_back(p);
230 }
231 #endif
232 
233 void
235 {
236  if (flags.forward_completed) {
237  debugs(17, DBG_IMPORTANT, HERE << "FwdState::completed called on a completed request! Bad!");
238  return;
239  }
240 
241  flags.forward_completed = true;
242 
243  request->hier.stopPeerClock(false);
244 
246  debugs(17, 3, HERE << "entry aborted");
247  return ;
248  }
249 
250 #if URL_CHECKSUM_DEBUG
251 
252  entry->mem_obj->checkUrlChecksum();
253 #endif
254 
255  if (entry->store_status == STORE_PENDING) {
256  if (entry->isEmpty()) {
257  if (!err) // we quit (e.g., fd closed) before an error or content
259  assert(err);
261  err = NULL;
262 #if USE_OPENSSL
266  }
267 #endif
268  } else {
269  entry->complete();
271  }
272  }
273 
274  if (storePendingNClients(entry) > 0)
276 
277 }
278 
280 {
281  debugs(17, 3, "FwdState destructor start");
282 
283  if (! flags.forward_completed)
284  completed();
285 
286  doneWithRetries();
287 
289 
290  delete err;
291 
293 
294  entry->unlock("FwdState");
295 
296  entry = NULL;
297 
298  if (calls.connector != NULL) {
299  calls.connector->cancel("FwdState destructed");
300  calls.connector = NULL;
301  }
302 
304  closeServerConnection("~FwdState");
305 
306  serverDestinations.clear();
307 
308  debugs(17, 3, "FwdState destructed, this=" << this);
309 }
310 
316 void
318 {
325  if ( Config.accessList.miss && !request->client_addr.isNoAddr() &&
326  !request->flags.internal && request->url.getScheme() != AnyP::PROTO_CACHE_OBJECT) {
333  ch.al = al;
334  ch.src_addr = request->client_addr;
335  ch.syncAle(request, nullptr);
336  if (ch.fastCheck().denied()) {
337  err_type page_id;
339 
340  if (page_id == ERR_NONE)
341  page_id = ERR_FORWARDING_DENIED;
342 
343  ErrorState *anErr = new ErrorState(page_id, Http::scForbidden, request);
344  errorAppendEntry(entry, anErr); // frees anErr
345  return;
346  }
347  }
348 
349  debugs(17, 3, HERE << "'" << entry->url() << "'");
350  /*
351  * This seems like an odd place to bind mem_obj and request.
352  * Might want to assert that request is NULL at this point
353  */
354  entry->mem_obj->request = request;
355 #if URL_CHECKSUM_DEBUG
356 
357  entry->mem_obj->checkUrlChecksum();
358 #endif
359 
360  if (shutting_down) {
361  /* more yuck */
363  errorAppendEntry(entry, anErr); // frees anErr
364  return;
365  }
366 
367  if (request->flags.internal) {
368  debugs(17, 2, "calling internalStart() due to request flag");
369  internalStart(clientConn, request, entry);
370  return;
371  }
372 
373  switch (request->url.getScheme()) {
374 
376  debugs(17, 2, "calling CacheManager due to request scheme " << request->url.getScheme());
377  CacheManager::GetInstance()->Start(clientConn, request, entry);
378  return;
379 
380  case AnyP::PROTO_URN:
381  urnStart(request, entry, al);
382  return;
383 
384  default:
385  FwdState::Pointer fwd = new FwdState(clientConn, entry, request, al);
386  fwd->start(fwd);
387  return;
388  }
389 
390  /* NOTREACHED */
391 }
392 
393 void
395 {
396  // Hides AccessLogEntry.h from code that does not supply ALE anyway.
397  Start(clientConn, entry, request, NULL);
398 }
399 
402 static inline time_t
403 diffOrZero(const time_t larger, const time_t smaller)
404 {
405  return (larger > smaller) ? (larger - smaller) : 0;
406 }
407 
409 time_t
411 {
412  // time already spent on forwarding (0 if clock went backwards)
413  const time_t timeSpent = diffOrZero(squid_curtime, fwdStart);
414  return diffOrZero(Config.Timeout.forward, timeSpent);
415 }
416 
417 bool
419 {
420  return ForwardTimeout(fwdStart) > 0;
421 }
422 
423 void
425 {
426  debugs(17, 3, HERE << entry->url());
427 
428  if (serverDestinations.size() > 0) {
429  // Ditch error page if it was created before.
430  // A new one will be created if there's another problem
431  delete err;
432  err = NULL;
433 
434  // Update the logging information about this new server connection.
435  // Done here before anything else so the errors get logged for
436  // this server link regardless of what happens when connecting to it.
437  // IF sucessfuly connected this top destination will become the serverConnection().
439  request->clearError();
440 
441  connectStart();
442  } else {
444  debugs(17, 4, "wait for more destinations to try");
445  return; // expect a noteDestination*() call
446  }
447 
448  debugs(17, 3, HERE << "Connection failed: " << entry->url());
449  if (!err) {
451  fail(anErr);
452  } // else use actual error from last connection attempt
453 
454  stopAndDestroy("tried all destinations");
455  }
456 }
457 
458 void
460 {
461  debugs(17, 3, err_type_str[errorState->type] << " \"" << Http::StatusCodeString(errorState->httpStatus) << "\"\n\t" << entry->url());
462 
463  delete err;
464  err = errorState;
465 
466  if (!errorState->request)
467  errorState->request = request;
468 
469  if (err->type != ERR_ZERO_SIZE_OBJECT)
470  return;
471 
472  if (pconnRace == racePossible) {
473  debugs(17, 5, HERE << "pconn race happened");
475  }
476 
477  if (ConnStateData *pinned_connection = request->pinnedConnection()) {
478  pinned_connection->pinning.zeroReply = true;
479  flags.dont_retry = true; // we want to propagate failure to the client
480  debugs(17, 4, "zero reply on pinned connection");
481  }
482 }
483 
487 void
489 {
490  debugs(17, 3, HERE << entry->url() );
491  assert(serverConnection() == conn);
492  assert(Comm::IsConnOpen(conn));
494  closeHandler = NULL;
495  serverConn = NULL;
496 }
497 
498 // \deprecated use unregister(Comm::ConnectionPointer &conn) instead
499 void
501 {
502  debugs(17, 3, HERE << entry->url() );
503  assert(fd == serverConnection()->fd);
505 }
506 
513 void
515 {
516  debugs(17, 3, HERE << entry->url() << "\n\tstatus " << entry->getReply()->sline.status());
517 #if URL_CHECKSUM_DEBUG
518 
519  entry->mem_obj->checkUrlChecksum();
520 #endif
521 
523 
524  if (reforward()) {
525  debugs(17, 3, HERE << "re-forwarding " << entry->getReply()->sline.status() << " " << entry->url());
526 
529 
530  entry->reset();
531 
532  // drop the last path off the selection list. try the next one.
533  if (!serverDestinations.empty()) // paranoid
534  serverDestinations.erase(serverDestinations.begin());
536 
537  } else {
539  debugs(17, 3, HERE << "server FD " << serverConnection()->fd << " not re-forwarding status " << entry->getReply()->sline.status());
540  else
541  debugs(17, 3, HERE << "server (FD closed) not re-forwarding status " << entry->getReply()->sline.status());
542  entry->complete();
543 
545  completed();
546 
547  stopAndDestroy("forwarding completed");
548  }
549 }
550 
551 void
553 {
554  const bool wasBlocked = serverDestinations.empty();
555  serverDestinations.push_back(path);
556  if (wasBlocked)
558  // else continue to use one of the previously noted destinations;
559  // if all of them fail, we may try this path
560 }
561 
562 void
564 {
566  if (serverDestinations.empty()) { // was blocked, waiting for more paths
567 
568  if (selectionError) {
569  debugs(17, 3, "Will abort forwarding because path selection has failed.");
570  Must(!err); // if we tried to connect, then path selection succeeded
571  fail(selectionError);
572  }
573  else if (err)
574  debugs(17, 3, "Will abort forwarding because all found paths have failed.");
575  else
576  debugs(17, 3, "Will abort forwarding because path selection found no paths.");
577 
578  startConnectionOrFail(); // will choose the OrFail code path
579  return;
580  }
581  // else continue to use one of the previously noted destinations;
582  // if all of them fail, forwarding as whole will fail
583  Must(!selectionError); // finding at least one path means selection succeeded
584 }
585 
586 /**** CALLBACK WRAPPERS ************************************************************/
587 
588 static void
590 {
591  FwdState *fwd = (FwdState *)params.data;
592  fwd->serverClosed(params.fd);
593 }
594 
595 void
597 {
598  FwdState *fwd = (FwdState *) data;
599  fwd->connectDone(conn, status, xerrno);
600 }
601 
602 /**** PRIVATE *****************************************************************/
603 
604 /*
605  * FwdState::checkRetry
606  *
607  * Return TRUE if the request SHOULD be retried. This method is
608  * called when the HTTP connection fails, or when the connection
609  * is closed before reading the end of HTTP headers from the server.
610  */
611 bool
613 {
614  if (shutting_down)
615  return false;
616 
617  if (!self) { // we have aborted before the server called us back
618  debugs(17, 5, HERE << "not retrying because of earlier abort");
619  // we will be destroyed when the server clears its Pointer to us
620  return false;
621  }
622 
624  return false;
625 
626  if (!entry->isEmpty())
627  return false;
628 
629  if (exhaustedTries())
630  return false;
631 
633  return false;
634 
635  if (flags.dont_retry)
636  return false;
637 
638  if (request->bodyNibbled())
639  return false;
640 
641  // NP: not yet actually connected anywhere. retry is safe.
642  if (!flags.connected_okay)
643  return true;
644 
645  if (!checkRetriable())
646  return false;
647 
648  return true;
649 }
650 
652 bool
654 {
655  // Optimize: A compliant proxy may retry PUTs, but Squid lacks the [rather
656  // complicated] code required to protect the PUT request body from being
657  // nibbled during the first try. Thus, Squid cannot retry some PUTs today.
658  if (request->body_pipe != NULL)
659  return false;
660 
661  // RFC2616 9.1 Safe and Idempotent Methods
663 }
664 
665 void
667 {
668  // XXX: fd is often -1 here
669  debugs(17, 2, "FD " << fd << " " << entry->url() << " after " <<
670  (fd >= 0 ? fd_table[fd].pconn.uses : -1) << " requests");
671  if (fd >= 0 && serverConnection()->fd == fd)
672  fwdPconnPool->noteUses(fd_table[fd].pconn.uses);
673  retryOrBail();
674 }
675 
676 void
678 {
679  if (checkRetry()) {
680  debugs(17, 3, HERE << "re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)");
681  // we should retry the same destination if it failed due to pconn race
682  if (pconnRace == raceHappened)
683  debugs(17, 4, HERE << "retrying the same destination");
684  else
685  serverDestinations.erase(serverDestinations.begin()); // last one failed. try another.
687  return;
688  }
689 
690  // TODO: should we call completed() here and move doneWithRetries there?
691  doneWithRetries();
692 
693  request->hier.stopPeerClock(false);
694 
695  if (self != NULL && !err && shutting_down && entry->isEmpty()) {
697  errorAppendEntry(entry, anErr);
698  }
699 
700  stopAndDestroy("cannot retry");
701 }
702 
703 // If the Server quits before nibbling at the request body, the body sender
704 // will not know (so that we can retry). Call this if we will not retry. We
705 // will notify the sender so that it does not get stuck waiting for space.
706 void
708 {
709  if (request && request->body_pipe != NULL)
711 }
712 
713 // called by the server that failed after calling unregister()
714 void
716 {
717  debugs(17, 2, HERE << "self=" << self << " err=" << err << ' ' << entry->url());
719  retryOrBail();
720 }
721 
722 void
724 {
725  if (status != Comm::OK) {
727  anErr->xerrno = xerrno;
728  fail(anErr);
729 
730  /* it might have been a timeout with a partially open link */
731  if (conn != NULL) {
732  if (conn->getPeer())
733  peerConnectFailed(conn->getPeer());
734 
735  conn->close();
736  }
737  retryOrBail();
738  return;
739  }
740 
741  serverConn = conn;
742  debugs(17, 3, HERE << serverConnection() << ": '" << entry->url() << "'" );
743 
745 
746  if (!request->flags.pinned) {
747  const CachePeer *p = serverConnection()->getPeer();
748  const bool peerWantsTls = p && p->secure.encryptTransport;
749  // userWillTlsToPeerForUs assumes CONNECT == HTTPS
750  const bool userWillTlsToPeerForUs = p && p->options.originserver &&
752  const bool needTlsToPeer = peerWantsTls && !userWillTlsToPeerForUs;
753  const bool needTlsToOrigin = !p && request->url.getScheme() == AnyP::PROTO_HTTPS;
754  if (needTlsToPeer || needTlsToOrigin || request->flags.sslPeek) {
755  HttpRequest::Pointer requestPointer = request;
757  "FwdState::ConnectedToPeer",
759  // Use positive timeout when less than one second is left.
760  const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t);
761  const time_t sslNegotiationTimeout = positiveTimeout(connTimeout);
763 #if USE_OPENSSL
764  if (request->flags.sslPeek)
765  connector = new Ssl::PeekingPeerConnector(requestPointer, serverConnection(), clientConn, callback, al, sslNegotiationTimeout);
766  else
767 #endif
768  connector = new Security::BlindPeerConnector(requestPointer, serverConnection(), callback, al, sslNegotiationTimeout);
769  AsyncJob::Start(connector); // will call our callback
770  return;
771  }
772  }
773 
774  // if not encrypting just run the post-connect actions
776  connectedToPeer(nil);
777 }
778 
779 void
781 {
782  if (ErrorState *error = answer.error.get()) {
783  fail(error);
784  answer.error.clear(); // preserve error for errorSendComplete()
785  if (CachePeer *p = serverConnection()->getPeer())
787  serverConnection()->close();
788  return;
789  }
790 
791  if (answer.tunneled) {
792  // TODO: When ConnStateData establishes tunnels, its state changes
793  // [in ways that may affect logging?]. Consider informing
794  // ConnStateData about our tunnel or otherwise unifying tunnel
795  // establishment [side effects].
796  unregister(serverConn); // async call owns it now
797  complete(); // destroys us
798  return;
799  }
800 
801  // should reach ConnStateData before the dispatched Client job starts
804 
805  if (serverConnection()->getPeer())
807 
808  flags.connected_okay = true;
809  dispatch();
810 }
811 
812 void
814 {
815  debugs(17, 2, "fwdConnectTimeout: FD " << fd << ": '" << entry->url() << "'" );
817  assert(fd == serverDestinations[0]->fd);
818 
819  if (entry->isEmpty()) {
821  anErr->xerrno = ETIMEDOUT;
822  fail(anErr);
823 
824  /* This marks the peer DOWN ... */
825  if (serverDestinations[0]->getPeer())
826  peerConnectFailed(serverDestinations[0]->getPeer());
827  }
828 
830  serverDestinations[0]->close();
831  }
832 }
833 
835 void
837 {
838  if (Ip::Qos::TheConfig.isAclTosActive())
840 
841 #if SO_MARK
842  if (Ip::Qos::TheConfig.isAclNfmarkActive())
844 #endif
845 
846  syncHierNote(serverConn, host);
847 }
848 
849 void
851 {
852  if (request)
853  request->hier.resetPeerNotes(server, host);
854  if (al)
855  al->hier.resetPeerNotes(server, host);
856 }
857 
863 void
865 {
866  assert(serverDestinations.size() > 0);
867 
868  debugs(17, 3, "fwdConnectStart: " << entry->url());
869 
871 
872  // Do not fowrward bumped connections to parent proxy unless it is an
873  // origin server
874  if (serverDestinations[0]->getPeer() && !serverDestinations[0]->getPeer()->options.originserver && request->flags.sslBumped) {
875  debugs(50, 4, "fwdConnectStart: Ssl bumped connections through parent proxy are not allowed");
877  fail(anErr);
878  stopAndDestroy("SslBump misconfiguration");
879  return;
880  }
881 
882  request->flags.pinned = false; // XXX: what if the ConnStateData set this to flag existing credentials?
883  // XXX: answer: the peer selection *should* catch it and give us only the pinned peer. so we reverse the =0 step below.
884  // XXX: also, logs will now lie if pinning is broken and leads to an error message.
885  if (serverDestinations[0]->peerType == PINNED) {
886  ConnStateData *pinned_connection = request->pinnedConnection();
887  debugs(17,7, "pinned peer connection: " << pinned_connection);
888  // pinned_connection may become nil after a pconn race
889  serverConn = pinned_connection ? pinned_connection->borrowPinnedConnection(request, serverDestinations[0]->getPeer()) : nullptr;
891  flags.connected_okay = true;
892  ++n_tries;
893  request->flags.pinned = true;
894 
895  if (pinned_connection->pinnedAuth())
896  request->flags.auth = true;
897 
899 
900  syncWithServerConn(pinned_connection->pinning.host);
901 
902  // the server may close the pinned connection before this request
904  dispatch();
905  return;
906  }
907 
908  // Pinned connection failure.
909  debugs(17,2,HERE << "Pinned connection failed: " << pinned_connection);
911  fail(anErr);
912  stopAndDestroy("pinned connection failure");
913  return;
914  }
915 
916  // Use pconn to avoid opening a new connection.
917  const char *host = NULL;
918  if (!serverDestinations[0]->getPeer())
919  host = request->url.host();
920 
922  // Avoid pconns after races so that the same client does not suffer twice.
923  // This does not increase the total number of connections because we just
924  // closed the connection that failed the race. And re-pinning assumes this.
925  if (pconnRace != raceHappened)
926  temp = pconnPop(serverDestinations[0], host);
927 
928  const bool openedPconn = Comm::IsConnOpen(temp);
929  pconnRace = openedPconn ? racePossible : raceImpossible;
930 
931  // if we found an open persistent connection to use. use it.
932  if (openedPconn) {
933  serverConn = temp;
934  flags.connected_okay = true;
935  debugs(17, 3, HERE << "reusing pconn " << serverConnection());
936  ++n_tries;
937 
939 
941 
942  dispatch();
943  return;
944  }
945 
946  // We will try to open a new connection, possibly to the same destination.
947  // We reset serverDestinations[0] in case we are using it again because
948  // ConnOpener modifies its destination argument.
949  serverDestinations[0]->local.port(0);
950  serverConn = NULL;
951 
952 #if URL_CHECKSUM_DEBUG
953  entry->mem_obj->checkUrlChecksum();
954 #endif
955 
957 
958  calls.connector = commCbCall(17,3, "fwdConnectDoneWrapper", CommConnectCbPtrFun(fwdConnectDoneWrapper, this));
959  const time_t connTimeout = serverDestinations[0]->connectTimeout(start_t);
960  Comm::ConnOpener *cs = new Comm::ConnOpener(serverDestinations[0], calls.connector, connTimeout);
961  if (host)
962  cs->setHost(host);
963  ++n_tries;
964  AsyncJob::Start(cs);
965 }
966 
967 void
969 {
970  debugs(17, 3, clientConn << ": Fetching " << request->method << ' ' << entry->url());
971  /*
972  * Assert that server_fd is set. This is to guarantee that fwdState
973  * is attached to something and will be deallocated when server_fd
974  * is closed.
975  */
977 
978  fd_note(serverConnection()->fd, entry->url());
979 
980  fd_table[serverConnection()->fd].noteUse();
981 
982  /*assert(!EBIT_TEST(entry->flags, ENTRY_DISPATCHED)); */
984 
985  assert(entry->locked());
986 
988 
990 
991  /* Retrieves remote server TOS or MARK value, and stores it as part of the
992  * original client request FD object. It is later used to forward
993  * remote server's TOS/MARK in the response to the client in case of a MISS.
994  */
995  if (Ip::Qos::TheConfig.isHitNfmarkActive()) {
997  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
998  /* Get the netfilter CONNMARK */
1000  }
1001  }
1002 
1003 #if _SQUID_LINUX_
1004  /* Bug 2537: The TOS forward part of QOS only applies to patched Linux kernels. */
1005  if (Ip::Qos::TheConfig.isHitTosActive()) {
1007  fde * clientFde = &fd_table[clientConn->fd]; // XXX: move the fd_table access into Ip::Qos
1008  /* Get the TOS value for the packet */
1010  }
1011  }
1012 #endif
1013 
1014 #if USE_OPENSSL
1015  if (request->flags.sslPeek) {
1018  unregister(serverConn); // async call owns it now
1019  complete(); // destroys us
1020  return;
1021  }
1022 #endif
1023 
1024  if (serverConnection()->getPeer() != NULL) {
1029  httpStart(this);
1030  } else {
1032  request->peer_login = NULL;
1035 
1036  switch (request->url.getScheme()) {
1037 
1038  case AnyP::PROTO_HTTPS:
1039  httpStart(this);
1040  break;
1041 
1042  case AnyP::PROTO_HTTP:
1043  httpStart(this);
1044  break;
1045 
1046  case AnyP::PROTO_GOPHER:
1047  gopherStart(this);
1048  break;
1049 
1050  case AnyP::PROTO_FTP:
1051  if (request->flags.ftpNative)
1052  Ftp::StartRelay(this);
1053  else
1054  Ftp::StartGateway(this);
1055  break;
1056 
1058 
1059  case AnyP::PROTO_URN:
1060  fatal_dump("Should never get here");
1061  break;
1062 
1063  case AnyP::PROTO_WHOIS:
1064  whoisStart(this);
1065  break;
1066 
1067  case AnyP::PROTO_WAIS: /* Not implemented */
1068 
1069  default:
1070  debugs(17, DBG_IMPORTANT, "WARNING: Cannot retrieve '" << entry->url() << "'.");
1072  fail(anErr);
1073  // Set the dont_retry flag because this is not a transient (network) error.
1074  flags.dont_retry = true;
1076  serverConn->close();
1077  }
1078  break;
1079  }
1080  }
1081 }
1082 
1083 /*
1084  * FwdState::reforward
1085  *
1086  * returns TRUE if the transaction SHOULD be re-forwarded to the
1087  * next choice in the serverDestinations list. This method is called when
1088  * peer communication completes normally, or experiences
1089  * some error after receiving the end of HTTP headers.
1090  */
1091 int
1093 {
1094  StoreEntry *e = entry;
1095 
1096  if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
1097  debugs(17, 3, HERE << "entry aborted");
1098  return 0;
1099  }
1100 
1102  assert(e->mem_obj);
1103 #if URL_CHECKSUM_DEBUG
1104 
1105  e->mem_obj->checkUrlChecksum();
1106 #endif
1107 
1108  debugs(17, 3, HERE << e->url() << "?" );
1109 
1110  if (!EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
1111  debugs(17, 3, HERE << "No, ENTRY_FWD_HDR_WAIT isn't set");
1112  return 0;
1113  }
1114 
1115  if (exhaustedTries())
1116  return 0;
1117 
1118  if (request->bodyNibbled())
1119  return 0;
1120 
1122  // NP: <= 1 since total count includes the recently failed one.
1123  debugs(17, 3, HERE << "No alternative forwarding paths left");
1124  return 0;
1125  }
1126 
1127  const Http::StatusCode s = e->getReply()->sline.status();
1128  debugs(17, 3, HERE << "status " << s);
1129  return reforwardableStatus(s);
1130 }
1131 
1138 ErrorState *
1140 {
1141  return new ErrorState(type, request->flags.needValidation ?
1143 }
1144 
1145 static void
1147 {
1148  int i;
1149  int j;
1150  storeAppendPrintf(s, "Status");
1151 
1152  for (j = 1; j < MAX_FWD_STATS_IDX; ++j) {
1153  storeAppendPrintf(s, "\ttry#%d", j);
1154  }
1155 
1156  storeAppendPrintf(s, "\n");
1157 
1158  for (i = 0; i <= (int) Http::scInvalidHeader; ++i) {
1159  if (FwdReplyCodes[0][i] == 0)
1160  continue;
1161 
1162  storeAppendPrintf(s, "%3d", i);
1163 
1164  for (j = 0; j <= MAX_FWD_STATS_IDX; ++j) {
1165  storeAppendPrintf(s, "\t%d", FwdReplyCodes[j][i]);
1166  }
1167 
1168  storeAppendPrintf(s, "\n");
1169  }
1170 }
1171 
1172 /**** STATIC MEMBER FUNCTIONS *************************************************/
1173 
1174 bool
1176 {
1177  switch (s) {
1178 
1179  case Http::scBadGateway:
1180 
1182  return true;
1183 
1184  case Http::scForbidden:
1185 
1187 
1189 
1191  return Config.retry.onerror;
1192 
1193  default:
1194  return false;
1195  }
1196 
1197  /* NOTREACHED */
1198 }
1199 
1206 void
1208 {
1209  if (conn->getPeer()) {
1210  fwdPconnPool->push(conn, NULL);
1211  } else {
1212  fwdPconnPool->push(conn, domain);
1213  }
1214 }
1215 
1217 FwdState::pconnPop(const Comm::ConnectionPointer &dest, const char *domain)
1218 {
1219  bool retriable = checkRetriable();
1220  if (!retriable && Config.accessList.serverPconnForNonretriable) {
1222  ch.al = al;
1223  ch.syncAle(request, nullptr);
1224  retriable = ch.fastCheck().allowed();
1225  }
1226  // always call shared pool first because we need to close an idle
1227  // connection there if we have to use a standby connection.
1228  Comm::ConnectionPointer conn = fwdPconnPool->pop(dest, domain, retriable);
1229  if (!Comm::IsConnOpen(conn)) {
1230  // either there was no pconn to pop or this is not a retriable xaction
1231  if (CachePeer *peer = dest->getPeer()) {
1232  if (peer->standby.pool)
1233  conn = peer->standby.pool->pop(dest, domain, true);
1234  }
1235  }
1236  return conn; // open, closed, or nil
1237 }
1238 
1239 void
1241 {
1243 }
1244 
1245 void
1247 {
1248  Mgr::RegisterAction("forward", "Request Forwarding Statistics", fwdStats, 0, 1);
1249 }
1250 
1251 void
1253 {
1254  if (status > Http::scInvalidHeader)
1255  return;
1256 
1257  assert(tries >= 0);
1258 
1259  if (tries > MAX_FWD_STATS_IDX)
1260  tries = MAX_FWD_STATS_IDX;
1261 
1262  ++ FwdReplyCodes[tries][status];
1263 }
1264 
1265 bool
1267 {
1268  return n_tries >= Config.forward_max_tries;
1269 }
1270 
1271 /**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
1272 
1273 /*
1274  * DPW 2007-05-19
1275  * Formerly static, but now used by client_side_request.cc
1276  */
1278 tos_t
1280 {
1281  for (acl_tos *l = head; l; l = l->next) {
1282  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1283  return l->tos;
1284  }
1285 
1286  return 0;
1287 }
1288 
1292 {
1293  for (acl_nfmark *l = head; l; l = l->next) {
1294  if (!l->aclList || ch->fastCheck(l->aclList).allowed())
1295  return l->markConfig;
1296  }
1297 
1298  return {};
1299 }
1300 
1301 void
1303 {
1304  // skip if an outgoing address is already set.
1305  if (!conn->local.isAnyAddr()) return;
1306 
1307  // ensure that at minimum the wildcard local matches remote protocol
1308  if (conn->remote.isIPv4())
1309  conn->local.setIPv4();
1310 
1311  // maybe use TPROXY client address
1312  if (request && request->flags.spoofClientIp) {
1313  if (!conn->getPeer() || !conn->getPeer()->options.no_tproxy) {
1314 #if FOLLOW_X_FORWARDED_FOR && LINUX_NETFILTER
1316  conn->local = request->indirect_client_addr;
1317  else
1318 #endif
1319  conn->local = request->client_addr;
1320  conn->local.port(0); // let OS pick the source port to prevent address clashes
1321  // some flags need setting on the socket to use this address
1322  conn->flags |= COMM_DOBIND;
1323  conn->flags |= COMM_TRANSPARENT;
1324  return;
1325  }
1326  // else no tproxy today ...
1327  }
1328 
1330  return; // anything will do.
1331  }
1332 
1333  ACLFilledChecklist ch(NULL, request, NULL);
1334  ch.dst_peer_name = conn->getPeer() ? conn->getPeer()->name : NULL;
1335  ch.dst_addr = conn->remote;
1336 
1337  // TODO use the connection details in ACL.
1338  // needs a bit of rework in ACLFilledChecklist to use Comm::Connection instead of ConnStateData
1339 
1340  for (Acl::Address *l = Config.accessList.outgoing_address; l; l = l->next) {
1341 
1342  /* check if the outgoing address is usable to the destination */
1343  if (conn->remote.isIPv4() != l->addr.isIPv4()) continue;
1344 
1345  /* check ACLs for this outgoing address */
1346  if (!l->aclList || ch.fastCheck(l->aclList).allowed()) {
1347  conn->local = l->addr;
1348  return;
1349  }
1350  }
1351 }
1352 
1353 tos_t
1355 {
1356  ACLFilledChecklist ch(NULL, request, NULL);
1357  return aclMapTOS(Ip::Qos::TheConfig.tosToServer, &ch);
1358 }
1359 
1360 nfmark_t
1362 {
1363  ACLFilledChecklist ch(NULL, request, NULL);
1364  const auto mc = aclFindNfMarkConfig(Ip::Qos::TheConfig.nfmarkToServer, &ch);
1365  return mc.mark;
1366 }
1367 
1368 void
1370 {
1371  // Get the server side TOS and Netfilter mark to be set on the connection.
1372  if (Ip::Qos::TheConfig.isAclTosActive()) {
1373  conn.tos = GetTosToServer(request);
1374  debugs(17, 3, "from " << conn.local << " tos " << int(conn.tos));
1375  }
1376 
1377 #if SO_MARK && USE_LIBCAP
1378  conn.nfmark = GetNfmarkToServer(request);
1379  debugs(17, 3, "from " << conn.local << " netfilter mark " << conn.nfmark);
1380 #else
1381  conn.nfmark = 0;
1382 #endif
1383 }
1384 
bool setIPv4()
Definition: Address.cc:217
void getOutgoingAddress(HttpRequest *request, Comm::ConnectionPointer conn)
Definition: FwdState.cc:1302
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:1361
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:771
#define assert(EX)
Definition: assert.h:17
int reforward()
Definition: FwdState.cc:1092
bool isIdempotent() const
const char * StatusCodeString(const Http::StatusCode status)
Definition: StatusCode.cc:14
virtual void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
Definition: FwdState.cc:552
void const char HLPCB * callback
Definition: stub_helper.cc:16
void connectedToPeer(Security::EncryptorAnswer &answer)
Definition: FwdState.cc:780
static bool EnoughTimeToReForward(const time_t fwdStart)
Definition: FwdState.cc:418
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:403
void noteUses(int uses)
Definition: pconn.cc:507
void pconnPush(Comm::ConnectionPointer &conn, const char *domain)
Definition: FwdState.cc:1207
int unlock(const char *context)
Definition: store.cc:457
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:666
Ip::Address dst_addr
int storePendingNClients(const StoreEntry *e)
CbcPointer< ErrorState > error
problem details (nil on success)
int type
Definition: errorpage.cc:78
bool ftpNative
carries a representation of an FTP command [received on ftp_port]
Definition: RequestFlags.h:105
void dispatch()
Definition: FwdState.cc:968
tos_t GetTosToServer(HttpRequest *request)
Definition: FwdState.cc:1354
char * domain
Forced domain.
Definition: CachePeer.h:184
bool isNoAddr() const
Definition: Address.cc:277
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:1279
static void RegisterWithCacheManager(void)
Definition: FwdState.cc:1246
Definition: Flag.h:16
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
int locked() const
Definition: store.cc:1249
bool pinnedAuth() const
Definition: client_side.h:197
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:813
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:141
#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:1670
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:189
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
list of address-based ACLs.
Definition: Address.h:19
void retryOrBail()
Definition: FwdState.cc:677
void completed()
Definition: FwdState.cc:234
const char * err_type_str[]
time_t squid_curtime
Definition: stub_time.cc:17
void Start(const Comm::ConnectionPointer &client, HttpRequest *request, StoreEntry *entry)
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:394
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:156
void complete()
Definition: store.cc:1058
bool isIPv4() const
Definition: Address.cc:151
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:1369
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:279
parameters for the async notePinnedConnectionBecameIdle() call
Definition: client_side.h:167
void whoisStart(FwdState *fwd)
Definition: whois.cc:57
void connectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno)
Definition: FwdState.cc:723
void push(const Comm::ConnectionPointer &serverConn, const char *domain)
Definition: pconn.cc:407
time_t forward
Definition: SquidConfig.h:110
int shutting_down
Definition: testAddress.cc:36
#define COMM_DOBIND
Definition: Connection.h:47
time_t start_t
Definition: FwdState.h:150
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:24
ping_status_t ping_status
Definition: Store.h:218
void syncHierNote(const Comm::ConnectionPointer &server, const char *host)
Definition: FwdState.cc:850
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:149
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
CbcPointer< FwdState > fwd_
Definition: FwdState.cc:100
const char * url() const
Definition: store.cc:1600
#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:514
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:410
bool bodyNibbled() const
Definition: HttpRequest.cc:450
Comm::ConnectionList serverDestinations
Definition: FwdState.h:165
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:715
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:1252
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:143
void releaseRequest(const bool shareable=false)
Definition: store.cc:446
uint16_t flags
Definition: Store.h:208
static CLCB fwdServerClosedWrapper
Definition: FwdState.cc:69
PconnRace pconnRace
current pconn race state
Definition: FwdState.h:173
#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1)
Definition: AsyncJobCalls.h:62
int fetches
Definition: CachePeer.h:45
void connectStart()
Definition: FwdState.cc:864
Http::StatusLine sline
Definition: HttpReply.h:60
const char * AclMatchedName
Definition: Acl.cc:30
void host(const char *src)
Definition: Uri.cc:47
void doneWithRetries()
Definition: FwdState.cc:707
MemObject * mem_obj
Definition: Store.h:197
bool tunneled
whether we spliced the connections instead of negotiating encryption
bool isAnyAddr() const
Definition: Address.cc:163
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:929
void syncWithServerConn(const char *host)
called when serverConn is set to an open to-peer connection
Definition: FwdState.cc:836
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:1139
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:169
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
AclDenyInfoList * denyInfoList
Definition: SquidConfig.h:407
void startConnectionOrFail()
Definition: FwdState.cc:424
bool reforwardableStatus(const Http::StatusCode s) const
Definition: FwdState.cc:1175
AccessLogEntryPointer al
info for the future access.log entry
Definition: FwdState.h:142
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:220
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:140
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 internalStart(const Comm::ConnectionPointer &clientConn, HttpRequest *request, StoreEntry *entry)
Definition: internal.cc:31
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:147
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:122
bool allowed() const
Definition: Acl.h:141
Comm::ConnectionPointer serverConn
a successfully opened connection to a server.
Definition: FwdState.h:167
hier_code peerType
Definition: Connection.h:141
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:575
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:317
void fail(ErrorState *err)
Definition: FwdState.cc:459
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:1514
bool no_tproxy
Definition: CachePeer.h:115
virtual void noteDestinationsEnd(ErrorState *selectionError) override
Definition: FwdState.cc:563
static void initModule()
Definition: FwdState.cc:1240
void dial(AsyncCall &call)
Definition: FwdState.cc:90
int n_tries
the number of forwarding attempts so far
Definition: FwdState.h:151
AsyncJobPointer StartRelay(FwdState *const fwdState)
A new FTP Relay job.
Definition: FtpRelay.cc:798
int xerrno
Definition: errorpage.h:149
bool checkRetriable()
Whether we may try sending this request again after a failure.
Definition: FwdState.cc:653
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:1523
struct ConnStateData::@40 pinning
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:1676
bool checkRetry()
Definition: FwdState.cc:612
ErrorState * err
Definition: FwdState.h:148
bool exhaustedTries() const
whether we have used up all permitted forwarding attempts
Definition: FwdState.cc:1266
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:875
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:140
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
Ip::NfMarkConfig aclFindNfMarkConfig(acl_nfmark *head, ACLChecklist *ch)
Checks for a netfilter mark value to apply depending on the ACL.
Definition: FwdState.cc:1291
squidaio_request_t * head
Definition: aiops.cc:127
#define NULL
Definition: types.h:166
Comm::ConnectionPointer borrowPinnedConnection(HttpRequest *request, const CachePeer *aPeer)
Returns validated pinnned server connection (and stops its monitoring).
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:1217
err_type
Definition: err_type.h:12
err_type aclGetDenyInfoPage(AclDenyInfoList **head, const char *name, int redirect_allowed)
Definition: Gadgets.cc:40
void unregister(Comm::ConnectionPointer &conn)
Definition: FwdState.cc:488
Comm::ConnectionPointer pop(const Comm::ConnectionPointer &dest, const char *domain, bool keepOpen)
Definition: pconn.cc:444
void lock(const char *context)
Definition: store.cc:433
AsyncCall::Pointer connector
a call linking us to the ConnOpener producing serverConn.
Definition: FwdState.h:155

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors