neighbors.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2020 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 15 Neighbor Routines */
10 
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "anyp/PortCfg.h"
14 #include "base/EnumIterator.h"
15 #include "CacheDigest.h"
16 #include "CachePeer.h"
17 #include "comm/Connection.h"
18 #include "comm/ConnOpener.h"
19 #include "event.h"
20 #include "FwdState.h"
21 #include "globals.h"
22 #include "htcp.h"
23 #include "HttpRequest.h"
24 #include "icmp/net_db.h"
25 #include "ICP.h"
26 #include "int.h"
27 #include "ip/Address.h"
28 #include "ip/tools.h"
29 #include "ipcache.h"
30 #include "MemObject.h"
31 #include "mgr/Registration.h"
32 #include "multicast.h"
33 #include "neighbors.h"
34 #include "NeighborTypeDomainList.h"
35 #include "pconn.h"
36 #include "PeerDigest.h"
37 #include "PeerPoolMgr.h"
38 #include "PeerSelectState.h"
39 #include "RequestFlags.h"
40 #include "SquidConfig.h"
41 #include "SquidMath.h"
42 #include "SquidTime.h"
43 #include "stat.h"
44 #include "Store.h"
45 #include "store_key_md5.h"
46 #include "tools.h"
47 
48 /* count mcast group peers every 15 minutes */
49 #define MCAST_COUNT_RATE 900
50 
51 bool peerAllowedToUse(const CachePeer *, PeerSelector *);
52 static int peerWouldBePinged(const CachePeer *, PeerSelector *);
53 static void neighborRemove(CachePeer *);
54 static void neighborAlive(CachePeer *, const MemObject *, const icp_common_t *);
55 #if USE_HTCP
56 static void neighborAliveHtcp(CachePeer *, const MemObject *, const HtcpReplyData *);
57 #endif
58 static void neighborCountIgnored(CachePeer *);
59 static void peerRefreshDNS(void *);
61 static void peerProbeConnect(CachePeer *, const bool reprobeIfBusy = false);
63 static void peerCountMcastPeersDone(void *data);
64 static void peerCountMcastPeersStart(void *data);
65 static void peerCountMcastPeersSchedule(CachePeer * p, time_t when);
69 
70 static void neighborIgnoreNonPeer(const Ip::Address &, icp_opcode);
73 static void dump_peers(StoreEntry * sentry, CachePeer * peers);
74 
75 static unsigned short echo_port;
76 
77 static int NLateReplies = 0;
79 
80 const char *
82 {
83  if (p->type == PEER_NONE)
84  return "Non-Peer";
85 
86  if (p->type == PEER_SIBLING)
87  return "Sibling";
88 
89  if (p->type == PEER_MULTICAST)
90  return "Multicast Group";
91 
92  return "Parent";
93 }
94 
95 CachePeer *
96 whichPeer(const Ip::Address &from)
97 {
98  int j;
99 
100  CachePeer *p = NULL;
101  debugs(15, 3, "whichPeer: from " << from);
102 
103  for (p = Config.peers; p; p = p->next) {
104  for (j = 0; j < p->n_addresses; ++j) {
105  if (from == p->addresses[j] && from.port() == p->icp.port) {
106  return p;
107  }
108  }
109  }
110 
111  return NULL;
112 }
113 
114 peer_t
115 neighborType(const CachePeer * p, const AnyP::Uri &url)
116 {
117 
118  const NeighborTypeDomainList *d = NULL;
119 
120  for (d = p->typelist; d; d = d->next) {
121  if (0 == matchDomainName(url.host(), d->domain))
122  if (d->type != PEER_NONE)
123  return d->type;
124  }
125 #if PEER_MULTICAST_SIBLINGS
126  if (p->type == PEER_MULTICAST)
127  if (p->options.mcast_siblings)
128  return PEER_SIBLING;
129 #endif
130 
131  return p->type;
132 }
133 
137 bool
139 {
140  assert(ps);
141  HttpRequest *request = ps->request;
142  assert(request != NULL);
143 
144  if (neighborType(p, request->url) == PEER_SIBLING) {
145 #if PEER_MULTICAST_SIBLINGS
146  if (p->type == PEER_MULTICAST && p->options.mcast_siblings &&
147  (request->flags.noCache || request->flags.refresh || request->flags.loopDetected || request->flags.needValidation))
148  debugs(15, 2, "peerAllowedToUse(" << p->name << ", " << request->url.authority() << ") : multicast-siblings optimization match");
149 #endif
150  if (request->flags.noCache)
151  return false;
152 
153  if (request->flags.refresh)
154  return false;
155 
156  if (request->flags.loopDetected)
157  return false;
158 
159  if (request->flags.needValidation)
160  return false;
161  }
162 
163  // CONNECT requests are proxy requests. Not to be forwarded to origin servers.
164  // Unless the destination port matches, in which case we MAY perform a 'DIRECT' to this CachePeer.
166  return false;
167 
168  if (p->access == NULL)
169  return true;
170 
171  ACLFilledChecklist checklist(p->access, request, NULL);
172  checklist.al = ps->al;
173  if (ps->al && ps->al->reply) {
174  checklist.reply = ps->al->reply.getRaw();
175  HTTPMSGLOCK(checklist.reply);
176  }
177  checklist.syncAle(request, nullptr);
178  return checklist.fastCheck().allowed();
179 }
180 
181 /* Return TRUE if it is okay to send an ICP request to this CachePeer. */
182 static int
184 {
185  assert(ps);
186  HttpRequest *request = ps->request;
187 
188  if (p->icp.port == 0)
189  return 0;
190 
191  if (p->options.no_query)
192  return 0;
193 
194  if (p->options.mcast_responder)
195  return 0;
196 
197  if (p->n_addresses == 0)
198  return 0;
199 
201  return 0;
202 
203  /* the case below seems strange, but can happen if the
204  * URL host is on the other side of a firewall */
205  if (p->type == PEER_SIBLING)
206  if (!request->flags.hierarchical)
207  return 0;
208 
209  if (!peerAllowedToUse(p, ps))
210  return 0;
211 
212  /* Ping dead peers every timeout interval */
214  return 1;
215 
216  if (!neighborUp(p))
217  return 0;
218 
219  return 1;
220 }
221 
222 bool
224 {
225  const int effectiveLimit = p->max_conn <= 0 ? Squid_MaxFD : p->max_conn;
226  const int remaining = effectiveLimit - p->stats.conn_open;
227  debugs(15, 7, remaining << '=' << effectiveLimit << '-' << p->stats.conn_open);
228  return remaining > 0;
229 }
230 
231 bool
233 {
234  // Standby connections can be used without opening new connections.
235  const int standbys = p->standby.pool ? p->standby.pool->count() : 0;
236 
237  // XXX: Some idle pconns can be used without opening new connections.
238  // Complication: Idle pconns cannot be reused for some requests.
239  const int usableIdles = 0;
240 
241  const int available = standbys + usableIdles;
242  debugs(15, 7, available << '=' << standbys << '+' << usableIdles);
243  return available > 0;
244 }
245 
246 void
248 {
249  --p->stats.conn_open;
250  if (p->standby.waitingForClose && peerCanOpenMore(p)) {
251  p->standby.waitingForClose = false;
252  PeerPoolMgr::Checkpoint(p->standby.mgr, "conn closed");
253  }
254 }
255 
256 /* Return TRUE if it is okay to send an HTTP request to this CachePeer. */
257 int
259 {
260  if (!peerCanOpenMore(p) && !peerHasConnAvailable(p))
261  return 0;
262 
263  if (!peerAllowedToUse(p, ps))
264  return 0;
265 
266  if (!neighborUp(p))
267  return 0;
268 
269  return 1;
270 }
271 
272 int
274 {
275  CachePeer *p = NULL;
276  int count = 0;
277 
278  for (p = Config.peers; p; p = p->next)
279  if (peerWouldBePinged(p, ps))
280  ++count;
281 
282  debugs(15, 3, "neighborsCount: " << count);
283 
284  return count;
285 }
286 
287 CachePeer *
289 {
290  assert(ps);
291  HttpRequest *request = ps->request;
292 
293  CachePeer *p = NULL;
294 
295  for (p = Config.peers; p; p = p->next) {
296  if (!neighborUp(p))
297  continue;
298 
299  if (neighborType(p, request->url) != PEER_PARENT)
300  continue;
301 
302  if (!peerHTTPOkay(p, ps))
303  continue;
304 
305  break;
306  }
307 
308  debugs(15, 3, "getFirstUpParent: returning " << (p ? p->host : "NULL"));
309  return p;
310 }
311 
312 CachePeer *
314 {
315  assert(ps);
316  HttpRequest *request = ps->request;
317 
318  CachePeer *p;
319  CachePeer *q = NULL;
320 
321  for (p = Config.peers; p; p = p->next) {
322  if (!p->options.roundrobin)
323  continue;
324 
325  if (neighborType(p, request->url) != PEER_PARENT)
326  continue;
327 
328  if (!peerHTTPOkay(p, ps))
329  continue;
330 
331  if (p->weight == 0)
332  continue;
333 
334  if (q) {
335  if (p->weight == q->weight) {
336  if (q->rr_count < p->rr_count)
337  continue;
338  } else if ( ((double) q->rr_count / q->weight) < ((double) p->rr_count / p->weight)) {
339  continue;
340  }
341  }
342 
343  q = p;
344  }
345 
346  if (q)
347  ++ q->rr_count;
348 
349  debugs(15, 3, HERE << "returning " << (q ? q->host : "NULL"));
350 
351  return q;
352 }
353 
354 CachePeer *
356 {
357  assert(ps);
358  HttpRequest *request = ps->request;
359 
360  CachePeer *p;
361  CachePeer *q = NULL;
362  int weighted_rtt;
363 
364  for (p = Config.peers; p; p = p->next) {
366  continue;
367 
368  if (neighborType(p, request->url) != PEER_PARENT)
369  continue;
370 
371  if (!peerHTTPOkay(p, ps))
372  continue;
373 
374  if (q && q->rr_count < p->rr_count)
375  continue;
376 
377  q = p;
378  }
379 
380  if (q && q->rr_count > 1000000)
381  for (p = Config.peers; p; p = p->next) {
383  continue;
384 
385  if (neighborType(p, request->url) != PEER_PARENT)
386  continue;
387 
388  p->rr_count = 0;
389  }
390 
391  if (q) {
392  weighted_rtt = (q->stats.rtt - q->basetime) / q->weight;
393 
394  if (weighted_rtt < 1)
395  weighted_rtt = 1;
396 
397  q->rr_count += weighted_rtt;
398 
399  debugs(15, 3, "getWeightedRoundRobinParent: weighted_rtt " << weighted_rtt);
400  }
401 
402  debugs(15, 3, "getWeightedRoundRobinParent: returning " << (q ? q->host : "NULL"));
403  return q;
404 }
405 
416 static void
418 {
419  peerClearRR();
420  eventAdd("peerClearRR", peerClearRRLoop, data, 5 * 60.0, 0);
421 }
422 
428 void
430 {
431  static bool event_added = false;
432  if (!event_added) {
434  event_added=true;
435  }
436 }
437 
445 void
447 {
448  CachePeer *p = NULL;
449  for (p = Config.peers; p; p = p->next) {
450  p->rr_count = 1;
451  }
452 }
453 
457 void
459 {
460  if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
461  debugs(15, DBG_IMPORTANT, "Detected REVIVED " << neighborTypeStr(p) << ": " << p->name);
463  peerClearRR();
464  if (p->standby.mgr.valid())
465  PeerPoolMgr::Checkpoint(p->standby.mgr, "revived peer");
466  }
467 
469  p->stats.probe_start = 0;
470 }
471 
472 CachePeer *
474 {
475  assert(ps);
476  HttpRequest *request = ps->request;
477 
478  CachePeer *p = NULL;
479 
480  for (p = Config.peers; p; p = p->next) {
481  if (neighborType(p, request->url) != PEER_PARENT)
482  continue;
483 
484  if (!p->options.default_parent)
485  continue;
486 
487  if (!peerHTTPOkay(p, ps))
488  continue;
489 
490  debugs(15, 3, "getDefaultParent: returning " << p->host);
491 
492  return p;
493  }
494 
495  debugs(15, 3, "getDefaultParent: returning NULL");
496  return NULL;
497 }
498 
499 CachePeer *
501 {
502  return p->next;
503 }
504 
505 CachePeer *
507 {
508  return Config.peers;
509 }
510 
511 static void
513 {
514  CachePeer *p = NULL;
515  CachePeer **P = NULL;
516  p = Config.peers;
517  P = &Config.peers;
518 
519  while (p) {
520  if (target == p)
521  break;
522 
523  P = &p->next;
524 
525  p = p->next;
526  }
527 
528  if (p) {
529  *P = p->next;
530  p->next = NULL;
531  delete p;
532  --Config.npeers;
533  }
534 
536 }
537 
538 static void
540 {
541  Mgr::RegisterAction("server_list",
542  "Peer Cache Statistics",
543  neighborDumpPeers, 0, 1);
544 
546  Mgr::RegisterAction("non_peers",
547  "List of Unknown sites sending ICP messages",
548  neighborDumpNonPeers, 0, 1);
549  }
550 }
551 
552 void
554 {
555  struct servent *sep = NULL;
556  const char *me = getMyHostname();
557  CachePeer *thisPeer = NULL;
558  CachePeer *next = NULL;
559 
561 
563 
564  for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
565  next = thisPeer->next;
566 
567  if (0 != strcmp(thisPeer->host, me))
568  continue;
569 
570  for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
571  if (thisPeer->http_port != s->s.port())
572  continue;
573 
574  debugs(15, DBG_IMPORTANT, "WARNING: Peer looks like this host." <<
575  Debug::Extra << "Ignoring " <<
576  neighborTypeStr(thisPeer) << " " << thisPeer->host <<
577  "/" << thisPeer->http_port << "/" <<
578  thisPeer->icp.port);
579 
580  neighborRemove(thisPeer);
581  }
582  }
583  }
584 
585  peerRefreshDNS((void *) 1);
586 
587  sep = getservbyname("echo", "udp");
588  echo_port = sep ? ntohs((unsigned short) sep->s_port) : 7;
589 
591 }
592 
593 int
595  StoreEntry * entry,
596  IRCB * callback,
597  PeerSelector *ps,
598  int *exprep,
599  int *timeout)
600 {
601  const char *url = entry->url();
602  MemObject *mem = entry->mem_obj;
603  CachePeer *p = NULL;
604  int i;
605  int reqnum = 0;
606  int flags;
607  int queries_sent = 0;
608  int peers_pinged = 0;
609  int parent_timeout = 0, parent_exprep = 0;
610  int sibling_timeout = 0, sibling_exprep = 0;
611  int mcast_timeout = 0, mcast_exprep = 0;
612 
613  if (Config.peers == NULL)
614  return 0;
615 
616  assert(!entry->hasDisk());
617 
618  mem->start_ping = current_time;
619 
621 
622  mem->ircb_data = ps;
623 
624  reqnum = icpSetCacheKey((const cache_key *)entry->key);
625 
626  for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
627  if (p == NULL)
628  p = Config.peers;
629 
630  debugs(15, 5, "neighborsUdpPing: Peer " << p->host);
631 
632  if (!peerWouldBePinged(p, ps))
633  continue; /* next CachePeer */
634 
635  ++peers_pinged;
636 
637  debugs(15, 4, "neighborsUdpPing: pinging peer " << p->host << " for '" << url << "'");
638 
639  debugs(15, 3, "neighborsUdpPing: key = '" << entry->getMD5Text() << "'");
640 
641  debugs(15, 3, "neighborsUdpPing: reqnum = " << reqnum);
642 
643 #if USE_HTCP
644  if (p->options.htcp && !p->options.htcp_only_clr) {
645  if (Config.Port.htcp <= 0) {
646  debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer.");
647  continue;
648  }
649 
650  debugs(15, 3, "neighborsUdpPing: sending HTCP query");
651  if (htcpQuery(entry, request, p) <= 0)
652  continue; // unable to send.
653  } else
654 #endif
655  {
657  debugs(15, DBG_CRITICAL, "ICP is disabled! Cannot send ICP request to peer.");
658  continue;
659  } else {
660 
661  if (p->type == PEER_MULTICAST)
663 
664  if (p->icp.port == echo_port) {
665  debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping");
666  // TODO: Get ALE from callback_data if possible.
667  icpCreateAndSend(ICP_DECHO, 0, url, reqnum, 0,
668  icpOutgoingConn->fd, p->in_addr, nullptr);
669  } else {
670  flags = 0;
671 
672  if (Config.onoff.query_icmp)
673  if (p->icp.version == ICP_VERSION_2)
674  flags |= ICP_FLAG_SRC_RTT;
675 
676  // TODO: Get ALE from callback_data if possible.
677  icpCreateAndSend(ICP_QUERY, flags, url, reqnum, 0,
678  icpOutgoingConn->fd, p->in_addr, nullptr);
679  }
680  }
681  }
682 
683  ++queries_sent;
684 
685  ++ p->stats.pings_sent;
686 
687  if (p->type == PEER_MULTICAST) {
688  mcast_exprep += p->mcast.n_replies_expected;
689  mcast_timeout += (p->stats.rtt * p->mcast.n_replies_expected);
690  } else if (neighborUp(p)) {
691  /* its alive, expect a reply from it */
692 
693  if (neighborType(p, request->url) == PEER_PARENT) {
694  ++parent_exprep;
695  parent_timeout += p->stats.rtt;
696  } else {
697  ++sibling_exprep;
698  sibling_timeout += p->stats.rtt;
699  }
700  } else {
701  /* Neighbor is dead; ping it anyway, but don't expect a reply */
702  /* log it once at the threshold */
703 
704  if (p->stats.logged_state == PEER_ALIVE) {
705  debugs(15, DBG_IMPORTANT, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name);
707  }
708  }
709 
711 
712  /*
713  * keep probe_start == 0 for a multicast CachePeer,
714  * so neighborUp() never says this CachePeer is dead.
715  */
716 
717  if ((p->type != PEER_MULTICAST) && (p->stats.probe_start == 0))
719  }
720 
721  if ((first_ping = first_ping->next) == NULL)
723 
724  /*
725  * How many replies to expect?
726  */
727  *exprep = parent_exprep + sibling_exprep + mcast_exprep;
728 
729  /*
730  * If there is a configured timeout, use it
731  */
733  *timeout = Config.Timeout.icp_query;
734  else {
735  if (*exprep > 0) {
736  if (parent_exprep)
737  *timeout = 2 * parent_timeout / parent_exprep;
738  else if (mcast_exprep)
739  *timeout = 2 * mcast_timeout / mcast_exprep;
740  else
741  *timeout = 2 * sibling_timeout / sibling_exprep;
742  } else
743  *timeout = 2000; /* 2 seconds */
744 
746  if (*timeout > Config.Timeout.icp_query_max)
747  *timeout = Config.Timeout.icp_query_max;
748 
749  if (*timeout < Config.Timeout.icp_query_min)
750  *timeout = Config.Timeout.icp_query_min;
751  }
752 
753  return peers_pinged;
754 }
755 
756 /* lookup the digest of a given CachePeer */
757 lookup_t
759 {
760 #if USE_CACHE_DIGESTS
761  assert(ps);
762  HttpRequest *request = ps->request;
764  assert(p);
765  assert(request);
766  debugs(15, 5, "peerDigestLookup: peer " << p->host);
767  /* does the peeer have a valid digest? */
768 
769  if (!p->digest) {
770  debugs(15, 5, "peerDigestLookup: gone!");
771  return LOOKUP_NONE;
772  } else if (!peerHTTPOkay(p, ps)) {
773  debugs(15, 5, "peerDigestLookup: !peerHTTPOkay");
774  return LOOKUP_NONE;
775  } else if (!p->digest->flags.needed) {
776  debugs(15, 5, "peerDigestLookup: note need");
778  return LOOKUP_NONE;
779  } else if (!p->digest->flags.usable) {
780  debugs(15, 5, "peerDigestLookup: !ready && " << (p->digest->flags.requested ? "" : "!") << "requested");
781  return LOOKUP_NONE;
782  }
783 
784  debugs(15, 5, "peerDigestLookup: OK to lookup peer " << p->host);
785  assert(p->digest->cd);
786  /* does digest predict a hit? */
787 
788  if (!p->digest->cd->contains(key))
789  return LOOKUP_MISS;
790 
791  debugs(15, 5, "peerDigestLookup: peer " << p->host << " says HIT!");
792 
793  return LOOKUP_HIT;
794 
795 #endif
796 
797  return LOOKUP_NONE;
798 }
799 
800 /* select best CachePeer based on cache digests */
801 CachePeer *
803 {
804  CachePeer *best_p = NULL;
805 #if USE_CACHE_DIGESTS
806  assert(ps);
807  HttpRequest *request = ps->request;
808 
809  int best_rtt = 0;
810  int choice_count = 0;
811  int ichoice_count = 0;
812  CachePeer *p;
813  int p_rtt;
814  int i;
815 
816  if (!request->flags.hierarchical)
817  return NULL;
818 
820 
821  for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
822  lookup_t lookup;
823 
824  if (!p)
825  p = Config.peers;
826 
827  if (i == 1)
828  first_ping = p;
829 
830  lookup = peerDigestLookup(p, ps);
831 
832  if (lookup == LOOKUP_NONE)
833  continue;
834 
835  ++choice_count;
836 
837  if (lookup == LOOKUP_MISS)
838  continue;
839 
840  p_rtt = netdbHostRtt(p->host);
841 
842  debugs(15, 5, "neighborsDigestSelect: peer " << p->host << " rtt: " << p_rtt);
843 
844  /* is this CachePeer better than others in terms of rtt ? */
845  if (!best_p || (p_rtt && p_rtt < best_rtt)) {
846  best_p = p;
847  best_rtt = p_rtt;
848 
849  if (p_rtt) /* informative choice (aka educated guess) */
850  ++ichoice_count;
851 
852  debugs(15, 4, "neighborsDigestSelect: peer " << p->host << " leads with rtt " << best_rtt);
853  }
854  }
855 
856  debugs(15, 4, "neighborsDigestSelect: choices: " << choice_count << " (" << ichoice_count << ")");
858  best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
859  request->hier.n_choices = choice_count;
860  request->hier.n_ichoices = ichoice_count;
861 #endif
862 
863  return best_p;
864 }
865 
866 void
868 {
869 #if USE_CACHE_DIGESTS
870  if (p)
871  strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host)-1);
872  else
873  *request->hier.cd_host = '\0';
874 
875  request->hier.cd_lookup = lookup;
876  debugs(15, 4, "peerNoteDigestLookup: peer " << (p? p->host : "<none>") << ", lookup: " << lookup_t_str[lookup] );
877 #endif
878 }
879 
880 static void
881 neighborAlive(CachePeer * p, const MemObject *, const icp_common_t * header)
882 {
883  peerAlive(p);
884  ++ p->stats.pings_acked;
885 
886  if ((icp_opcode) header->opcode <= ICP_END)
887  ++ p->icp.counts[header->opcode];
888 
889  p->icp.version = (int) header->version;
890 }
891 
892 static void
894 {
895  int rtt, rtt_av_factor;
896 
897  if (!mem)
898  return;
899 
900  if (!mem->start_ping.tv_sec)
901  return;
902 
903  rtt = tvSubMsec(mem->start_ping, current_time);
904 
905  if (rtt < 1 || rtt > 10000)
906  return;
907 
908  rtt_av_factor = RTT_AV_FACTOR;
909 
911  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
912 
913  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor);
914 }
915 
916 #if USE_HTCP
917 static void
919 {
920  peerAlive(p);
921  ++ p->stats.pings_acked;
922  ++ p->htcp.counts[htcp->hit ? 1 : 0];
923  p->htcp.version = htcp->version;
924 }
925 
926 #endif
927 
928 static void
930 {
931  if (p == NULL)
932  return;
933 
934  ++ p->stats.ignored_replies;
935 
936  ++NLateReplies;
937 }
938 
940 
941 static void
943 {
944  CachePeer *np;
945 
946  for (np = non_peers; np; np = np->next) {
947  if (np->in_addr != from)
948  continue;
949 
950  if (np->in_addr.port() != from.port())
951  continue;
952 
953  break;
954  }
955 
956  if (np == NULL) {
957  np = new CachePeer;
958  np->in_addr = from;
959  np->icp.port = from.port();
960  np->type = PEER_NONE;
961  np->host = new char[MAX_IPSTRLEN];
962  from.toStr(np->host,MAX_IPSTRLEN);
963  np->next = non_peers;
964  non_peers = np;
965  }
966 
967  ++ np->icp.counts[opcode];
968 
969  if (isPowTen(++np->stats.ignored_replies))
970  debugs(15, DBG_IMPORTANT, "WARNING: Ignored " << np->stats.ignored_replies << " replies from non-peer " << np->host);
971 }
972 
973 /* ignoreMulticastReply
974  *
975  * * We want to ignore replies from multicast peers if the
976  * * cache_host_domain rules would normally prevent the CachePeer
977  * * from being used
978  */
979 static int
981 {
982  if (p == NULL)
983  return 0;
984 
985  if (!p->options.mcast_responder)
986  return 0;
987 
988  if (peerHTTPOkay(p, ps))
989  return 0;
990 
991  return 1;
992 }
993 
1001 void
1002 neighborsUdpAck(const cache_key * key, icp_common_t * header, const Ip::Address &from)
1003 {
1004  CachePeer *p = NULL;
1005  StoreEntry *entry;
1006  MemObject *mem = NULL;
1007  peer_t ntype = PEER_NONE;
1008  icp_opcode opcode = (icp_opcode) header->opcode;
1009 
1010  debugs(15, 6, "neighborsUdpAck: opcode " << opcode << " '" << storeKeyText(key) << "'");
1011 
1012  if ((entry = Store::Root().findCallbackXXX(key)))
1013  mem = entry->mem_obj;
1014 
1015  if ((p = whichPeer(from)))
1016  neighborAlive(p, mem, header);
1017 
1018  if (opcode > ICP_END)
1019  return;
1020 
1021  const char *opcode_d = icp_opcode_str[opcode];
1022 
1023  if (p)
1024  neighborUpdateRtt(p, mem);
1025 
1026  /* Does the entry exist? */
1027  if (NULL == entry) {
1028  debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found");
1030  return;
1031  }
1032 
1033  /* check if someone is already fetching it */
1034  if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
1035  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1037  return;
1038  }
1039 
1040  if (mem == NULL) {
1041  debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key));
1043  return;
1044  }
1045 
1046  if (entry->ping_status != PING_WAITING) {
1047  debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key));
1049  return;
1050  }
1051 
1052  if (!entry->locked()) {
1053  // TODO: many entries are unlocked; why is this reported at level 1?
1054  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1056  return;
1057  }
1058 
1059  if (!mem->ircb_data) {
1060  debugs(12, DBG_IMPORTANT, "BUG: missing ICP callback data for " << *entry);
1062  return;
1063  }
1064 
1065  debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " ");
1066 
1067  if (p) {
1068  ntype = neighborType(p, mem->request->url);
1069  }
1070 
1071  if (ignoreMulticastReply(p, mem->ircb_data)) {
1073  } else if (opcode == ICP_MISS) {
1074  if (p == NULL) {
1075  neighborIgnoreNonPeer(from, opcode);
1076  } else {
1077  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1078  }
1079  } else if (opcode == ICP_HIT) {
1080  if (p == NULL) {
1081  neighborIgnoreNonPeer(from, opcode);
1082  } else {
1083  header->opcode = ICP_HIT;
1084  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1085  }
1086  } else if (opcode == ICP_DECHO) {
1087  if (p == NULL) {
1088  neighborIgnoreNonPeer(from, opcode);
1089  } else if (ntype == PEER_SIBLING) {
1090  debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
1091  debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n");
1092  } else {
1093  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1094  }
1095  } else if (opcode == ICP_SECHO) {
1096  if (p) {
1097  debugs(15, DBG_IMPORTANT, "Ignoring SECHO from neighbor " << p->host);
1099  } else {
1100  debugs(15, DBG_IMPORTANT, "Unsolicited SECHO from " << from);
1101  }
1102  } else if (opcode == ICP_DENIED) {
1103  if (p == NULL) {
1104  neighborIgnoreNonPeer(from, opcode);
1105  } else if (p->stats.pings_acked > 100) {
1106  if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
1107  debugs(15, DBG_CRITICAL, "95%% of replies from '" << p->host << "' are UDP_DENIED");
1108  debugs(15, DBG_CRITICAL, "Disabling '" << p->host << "', please check your configuration.");
1109  neighborRemove(p);
1110  p = NULL;
1111  } else {
1113  }
1114  }
1115  } else if (opcode == ICP_MISS_NOFETCH) {
1116  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1117  } else {
1118  debugs(15, DBG_CRITICAL, "neighborsUdpAck: Unexpected ICP reply: " << opcode_d);
1119  }
1120 }
1121 
1122 CachePeer *
1123 peerFindByName(const char *name)
1124 {
1125  CachePeer *p = NULL;
1126 
1127  for (p = Config.peers; p; p = p->next) {
1128  if (!strcasecmp(name, p->name))
1129  break;
1130  }
1131 
1132  return p;
1133 }
1134 
1135 CachePeer *
1136 peerFindByNameAndPort(const char *name, unsigned short port)
1137 {
1138  CachePeer *p = NULL;
1139 
1140  for (p = Config.peers; p; p = p->next) {
1141  if (strcasecmp(name, p->name))
1142  continue;
1143 
1144  if (port != p->http_port)
1145  continue;
1146 
1147  break;
1148  }
1149 
1150  return p;
1151 }
1152 
1153 int
1155 {
1156  if (!p->tcp_up) {
1157  peerProbeConnect(const_cast<CachePeer*>(p));
1158  return 0;
1159  }
1160 
1161  /*
1162  * The CachePeer can not be UP if we don't have any IP addresses
1163  * for it.
1164  */
1165  if (0 == p->n_addresses) {
1166  debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")");
1167  return 0;
1168  }
1169 
1170  if (p->options.no_query) {
1171  debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")");
1172  return 1;
1173  }
1174 
1175  if (p->stats.probe_start != 0 &&
1177  debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")");
1178  return 0;
1179  }
1180 
1181  debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")");
1182  return 1;
1183 }
1184 
1186 time_t
1188 {
1189  return peer->connect_timeout_raw > 0 ?
1191 }
1192 
1193 time_t
1194 positiveTimeout(const time_t timeout)
1195 {
1196  return max(static_cast<time_t>(1), timeout);
1197 }
1198 
1199 static void
1201 {
1202  // TODO: connections to no-longer valid IP addresses should be
1203  // closed when we can detect such IP addresses.
1204 
1205  CachePeer *p = (CachePeer *)data;
1206 
1207  if (p->n_addresses == 0) {
1208  debugs(15, DBG_IMPORTANT, "Configuring " << neighborTypeStr(p) << " " << p->host << "/" << p->http_port << "/" << p->icp.port);
1209 
1210  if (p->type == PEER_MULTICAST)
1211  debugs(15, DBG_IMPORTANT, " Multicast TTL = " << p->mcast.ttl);
1212  }
1213 
1214  p->n_addresses = 0;
1215 
1216  if (ia == NULL) {
1217  debugs(0, DBG_CRITICAL, "WARNING: DNS lookup for '" << p->host << "' failed!");
1218  return;
1219  }
1220 
1221  if (ia->empty()) {
1222  debugs(0, DBG_CRITICAL, "WARNING: No IP address found for '" << p->host << "'!");
1223  return;
1224  }
1225 
1226  for (const auto &ip: ia->goodAndBad()) { // TODO: Consider using just good().
1227  if (p->n_addresses < PEER_MAX_ADDRESSES) {
1228  const auto idx = p->n_addresses++;
1229  p->addresses[idx] = ip;
1230  debugs(15, 2, "--> IP address #" << idx << ": " << p->addresses[idx]);
1231  } else {
1232  debugs(15, 3, "ignoring remaining " << (ia->size() - p->n_addresses) << " ips");
1233  break;
1234  }
1235  }
1236 
1237  p->in_addr.setEmpty();
1238  p->in_addr = p->addresses[0];
1239  p->in_addr.port(p->icp.port);
1240 
1241  peerProbeConnect(p, true); // detect any died or revived peers ASAP
1242 
1243  if (p->type == PEER_MULTICAST)
1245 
1246 #if USE_ICMP
1247  if (p->type != PEER_MULTICAST && IamWorkerProcess())
1248  if (!p->options.no_netdb_exchange)
1249  eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
1250 #endif
1251 
1252  if (p->standby.mgr.valid())
1253  PeerPoolMgr::Checkpoint(p->standby.mgr, "resolved peer");
1254 }
1255 
1256 static void
1258 {
1259  CachePeer *p = NULL;
1260 
1263 
1264  if (!data && 0 == stat5minClientRequests()) {
1265  /* no recent client traffic, wait a bit */
1266  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
1267  return;
1268  }
1269 
1270  for (p = Config.peers; p; p = p->next)
1272 
1273  /* Reconfigure the peers every hour */
1274  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1);
1275 }
1276 
1277 static void
1279 {
1281 
1282  if (!p->tcp_up) {
1283  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port <<
1284  " dead");
1285  return;
1286  }
1287 
1288  -- p->tcp_up;
1289 
1290  if (!p->tcp_up) {
1291  debugs(15, DBG_IMPORTANT, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name);
1293  }
1294 }
1295 
1296 void
1298 {
1299  debugs(15, DBG_IMPORTANT, "TCP connection to " << p->host << "/" << p->http_port << " failed");
1301 }
1302 
1303 void
1305 {
1306  if (!p->tcp_up) {
1307  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeeded");
1308  p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly.
1309  peerAlive(p);
1310  if (!p->n_addresses)
1312  } else
1313  p->tcp_up = p->connect_fail_limit;
1314 }
1315 
1317 static bool
1319 {
1320  if (p->testing_now > 0) {
1321  debugs(15, 8, "yes, probing " << p);
1322  return true;
1323  }
1324  if (squid_curtime - p->stats.last_connect_probe == 0) {
1325  debugs(15, 8, "yes, just probed " << p);
1326  return true;
1327  }
1328  return false;
1329 }
1330 /*
1331 * peerProbeConnect will be called on dead peers by neighborUp
1332 */
1333 static void
1334 peerProbeConnect(CachePeer *p, const bool reprobeIfBusy)
1335 {
1336  if (peerProbeIsBusy(p)) {
1337  p->reprobe = reprobeIfBusy;
1338  return;
1339  }
1340  p->reprobe = false;
1341 
1342  const time_t ctimeout = peerConnectTimeout(p);
1343  /* for each IP address of this CachePeer. find one that we can connect to and probe it. */
1344  for (int i = 0; i < p->n_addresses; ++i) {
1346  conn->remote = p->addresses[i];
1347  conn->remote.port(p->http_port);
1348  conn->setPeer(p);
1350 
1351  ++ p->testing_now;
1352 
1353  AsyncCall::Pointer call = commCbCall(15,3, "peerProbeConnectDone", CommConnectCbPtrFun(peerProbeConnectDone, p));
1354  Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, ctimeout);
1355  cs->setHost(p->host);
1356  AsyncJob::Start(cs);
1357  }
1358 
1360 }
1361 
1362 static void
1364 {
1365  CachePeer *p = (CachePeer*)data;
1366 
1367  if (status == Comm::OK) {
1369  } else {
1371  }
1372 
1373  -- p->testing_now;
1374  conn->close();
1375  // TODO: log this traffic.
1376 
1377  if (p->reprobe)
1378  peerProbeConnect(p);
1379 }
1380 
1381 static void
1383 {
1384  if (p->mcast.flags.count_event_pending)
1385  return;
1386 
1387  eventAdd("peerCountMcastPeersStart",
1389  p,
1390  (double) when, 1);
1391 
1392  p->mcast.flags.count_event_pending = true;
1393 }
1394 
1395 static void
1397 {
1398  const auto peer = static_cast<CachePeer*>(data);
1399  CallContextCreator([peer] {
1401  });
1403 }
1404 
1406 static void
1408 {
1409  // XXX: Do not create lots of complex fake objects (while abusing their
1410  // APIs) to pass around a few basic data points like start_ping and ping!
1411  MemObject *mem;
1412  int reqnum;
1413  // TODO: use class AnyP::Uri instead of constructing and re-parsing a string
1414  LOCAL_ARRAY(char, url, MAX_URL);
1415  assert(p->type == PEER_MULTICAST);
1416  p->mcast.flags.count_event_pending = false;
1417  snprintf(url, MAX_URL, "http://");
1418  p->in_addr.toUrl(url+7, MAX_URL -8 );
1419  strcat(url, "/");
1421  auto *req = HttpRequest::FromUrlXXX(url, mx);
1422  assert(req != nullptr);
1423  const AccessLogEntry::Pointer ale = new AccessLogEntry;
1424  ale->request = req;
1425  CodeContext::Reset(ale);
1427  const auto psstate = new PeerSelector(nullptr);
1428  psstate->request = req;
1429  HTTPMSGLOCK(psstate->request);
1430  psstate->entry = fake;
1431  psstate->peerCountMcastPeerXXX = cbdataReference(p);
1432  psstate->ping.start = current_time;
1433  psstate->al = ale;
1434  mem = fake->mem_obj;
1435  mem->request = psstate->request;
1436  mem->start_ping = current_time;
1438  mem->ircb_data = psstate;
1440  p->mcast.id = mem->id;
1441  reqnum = icpSetCacheKey((const cache_key *)fake->key);
1442  icpCreateAndSend(ICP_QUERY, 0, url, reqnum, 0,
1443  icpOutgoingConn->fd, p->in_addr, psstate->al);
1444  fake->ping_status = PING_WAITING;
1445  eventAdd("peerCountMcastPeersDone",
1447  psstate,
1448  Config.Timeout.mcast_icp_query / 1000.0, 1);
1449  p->mcast.flags.counting = true;
1450 }
1451 
1452 static void
1454 {
1455  const auto psstate = static_cast<PeerSelector*>(data);
1456  CallBack(psstate->al, [psstate] {
1457  peerCountMcastPeersAbort(psstate);
1458  delete psstate;
1459  });
1460 }
1461 
1464 static void
1466 {
1467  StoreEntry *fake = psstate->entry;
1468 
1470  CachePeer *p = (CachePeer *)psstate->peerCountMcastPeerXXX;
1471  p->mcast.flags.counting = false;
1473  debugs(15, DBG_IMPORTANT, "Group " << p->host << ": " << psstate->ping.n_recv <<
1474  " replies, "<< std::setw(4)<< std::setprecision(2) <<
1475  p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt);
1477  }
1478 
1480 
1481  fake->abort(); // sets ENTRY_ABORTED and initiates related cleanup
1482  fake->mem_obj->request = nullptr;
1483  fake->unlock("peerCountMcastPeersDone");
1484 }
1485 
1486 static void
1488 {
1489  const auto psstate = static_cast<PeerSelector*>(data);
1490  StoreEntry *fake = psstate->entry;
1491  assert(fake);
1492  MemObject *mem = fake->mem_obj;
1493  assert(mem);
1494  int rtt = tvSubMsec(mem->start_ping, current_time);
1495  assert(proto == AnyP::PROTO_ICP);
1496  ++ psstate->ping.n_recv;
1497  int rtt_av_factor = RTT_AV_FACTOR;
1498 
1500  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
1501 
1502  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1503 }
1504 
1505 static void
1507 {
1508  dump_peers(sentry, Config.peers);
1509 }
1510 
1511 static void
1513 {
1514  dump_peers(sentry, non_peers);
1515 }
1516 
1517 void
1519 {
1520  if (p->options.proxy_only)
1521  storeAppendPrintf(sentry, " proxy-only");
1522 
1523  if (p->options.no_query)
1524  storeAppendPrintf(sentry, " no-query");
1525 
1526  if (p->options.background_ping)
1527  storeAppendPrintf(sentry, " background-ping");
1528 
1529  if (p->options.no_digest)
1530  storeAppendPrintf(sentry, " no-digest");
1531 
1532  if (p->options.default_parent)
1533  storeAppendPrintf(sentry, " default");
1534 
1535  if (p->options.roundrobin)
1536  storeAppendPrintf(sentry, " round-robin");
1537 
1538  if (p->options.carp)
1539  storeAppendPrintf(sentry, " carp");
1540 
1541 #if USE_AUTH
1542  if (p->options.userhash)
1543  storeAppendPrintf(sentry, " userhash");
1544 #endif
1545 
1546  if (p->options.sourcehash)
1547  storeAppendPrintf(sentry, " sourcehash");
1548 
1550  storeAppendPrintf(sentry, " weighted-round-robin");
1551 
1552  if (p->options.mcast_responder)
1553  storeAppendPrintf(sentry, " multicast-responder");
1554 
1555 #if PEER_MULTICAST_SIBLINGS
1556  if (p->options.mcast_siblings)
1557  storeAppendPrintf(sentry, " multicast-siblings");
1558 #endif
1559 
1560  if (p->weight != 1)
1561  storeAppendPrintf(sentry, " weight=%d", p->weight);
1562 
1563  if (p->options.closest_only)
1564  storeAppendPrintf(sentry, " closest-only");
1565 
1566 #if USE_HTCP
1567  if (p->options.htcp) {
1568  storeAppendPrintf(sentry, " htcp");
1570  bool doneopts = false;
1571  if (p->options.htcp_oldsquid) {
1572  storeAppendPrintf(sentry, "oldsquid");
1573  doneopts = true;
1574  }
1575  if (p->options.htcp_no_clr) {
1576  storeAppendPrintf(sentry, "%sno-clr",(doneopts?",":"="));
1577  doneopts = true;
1578  }
1579  if (p->options.htcp_no_purge_clr) {
1580  storeAppendPrintf(sentry, "%sno-purge-clr",(doneopts?",":"="));
1581  doneopts = true;
1582  }
1583  if (p->options.htcp_only_clr) {
1584  storeAppendPrintf(sentry, "%sonly-clr",(doneopts?",":"="));
1585  //doneopts = true; // uncomment if more opts are added
1586  }
1587  }
1588  }
1589 #endif
1590 
1591  if (p->options.no_netdb_exchange)
1592  storeAppendPrintf(sentry, " no-netdb-exchange");
1593 
1594 #if USE_DELAY_POOLS
1595  if (p->options.no_delay)
1596  storeAppendPrintf(sentry, " no-delay");
1597 #endif
1598 
1599  if (p->login)
1600  storeAppendPrintf(sentry, " login=%s", p->login);
1601 
1602  if (p->mcast.ttl > 0)
1603  storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl);
1604 
1605  if (p->connect_timeout_raw > 0)
1606  storeAppendPrintf(sentry, " connect-timeout=%d", (int)p->connect_timeout_raw);
1607 
1609  storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit);
1610 
1611 #if USE_CACHE_DIGESTS
1612 
1613  if (p->digest_url)
1614  storeAppendPrintf(sentry, " digest-url=%s", p->digest_url);
1615 
1616 #endif
1617 
1618  if (p->options.allow_miss)
1619  storeAppendPrintf(sentry, " allow-miss");
1620 
1621  if (p->options.no_tproxy)
1622  storeAppendPrintf(sentry, " no-tproxy");
1623 
1624  if (p->max_conn > 0)
1625  storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
1626  if (p->standby.limit > 0)
1627  storeAppendPrintf(sentry, " standby=%d", p->standby.limit);
1628 
1629  if (p->options.originserver)
1630  storeAppendPrintf(sentry, " originserver");
1631 
1632  if (p->domain)
1633  storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
1634 
1635  if (p->connection_auth == 0)
1636  storeAppendPrintf(sentry, " connection-auth=off");
1637  else if (p->connection_auth == 1)
1638  storeAppendPrintf(sentry, " connection-auth=on");
1639  else if (p->connection_auth == 2)
1640  storeAppendPrintf(sentry, " connection-auth=auto");
1641 
1642  p->secure.dumpCfg(sentry,"tls-");
1643  storeAppendPrintf(sentry, "\n");
1644 }
1645 
1646 static void
1647 dump_peers(StoreEntry * sentry, CachePeer * peers)
1648 {
1649  char ntoabuf[MAX_IPSTRLEN];
1650  int i;
1651 
1652  if (peers == NULL)
1653  storeAppendPrintf(sentry, "There are no neighbors installed.\n");
1654 
1655  for (CachePeer *e = peers; e; e = e->next) {
1656  assert(e->host != NULL);
1657  storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
1658  neighborTypeStr(e),
1659  e->name);
1660  storeAppendPrintf(sentry, "Host : %s/%d/%d\n",
1661  e->host,
1662  e->http_port,
1663  e->icp.port);
1664  storeAppendPrintf(sentry, "Flags :");
1665  dump_peer_options(sentry, e);
1666 
1667  for (i = 0; i < e->n_addresses; ++i) {
1668  storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
1669  e->addresses[i].toStr(ntoabuf,MAX_IPSTRLEN) );
1670  }
1671 
1672  storeAppendPrintf(sentry, "Status : %s\n",
1673  neighborUp(e) ? "Up" : "Down");
1674  storeAppendPrintf(sentry, "FETCHES : %d\n", e->stats.fetches);
1675  storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
1676  storeAppendPrintf(sentry, "AVG RTT : %d msec\n", e->stats.rtt);
1677 
1678  if (!e->options.no_query) {
1679  storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
1680  (int) (squid_curtime - e->stats.last_query));
1681 
1682  if (e->stats.last_reply > 0)
1683  storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
1684  (int) (squid_curtime - e->stats.last_reply));
1685  else
1686  storeAppendPrintf(sentry, "LAST REPLY : none received\n");
1687 
1688  storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
1689 
1690  storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
1691  e->stats.pings_acked,
1692  Math::intPercent(e->stats.pings_acked, e->stats.pings_sent));
1693  }
1694 
1695  storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked));
1696 
1697  if (!e->options.no_query) {
1698  storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
1699 #if USE_HTCP
1700 
1701  if (e->options.htcp) {
1702  storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
1703  e->htcp.counts[0],
1704  Math::intPercent(e->htcp.counts[0], e->stats.pings_acked));
1705  storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
1706  e->htcp.counts[1],
1707  Math::intPercent(e->htcp.counts[1], e->stats.pings_acked));
1708  } else {
1709 #endif
1710 
1711  for (auto op : WholeEnum<icp_opcode>()) {
1712  if (e->icp.counts[op] == 0)
1713  continue;
1714 
1715  storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n",
1716  icp_opcode_str[op],
1717  e->icp.counts[op],
1718  Math::intPercent(e->icp.counts[op], e->stats.pings_acked));
1719  }
1720 
1721 #if USE_HTCP
1722 
1723  }
1724 
1725 #endif
1726 
1727  }
1728 
1729  if (e->stats.last_connect_failure) {
1730  storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
1731  Time::FormatHttpd(e->stats.last_connect_failure));
1732  }
1733 
1734  storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1735  }
1736 }
1737 
1738 #if USE_HTCP
1739 void
1740 neighborsHtcpReply(const cache_key * key, HtcpReplyData * htcp, const Ip::Address &from)
1741 {
1743  MemObject *mem = NULL;
1744  CachePeer *p;
1745  peer_t ntype = PEER_NONE;
1746  debugs(15, 6, "neighborsHtcpReply: " <<
1747  (htcp->hit ? "HIT" : "MISS") << " " <<
1748  storeKeyText(key) );
1749 
1750  if (NULL != e)
1751  mem = e->mem_obj;
1752 
1753  if ((p = whichPeer(from)))
1754  neighborAliveHtcp(p, mem, htcp);
1755 
1756  /* Does the entry exist? */
1757  if (NULL == e) {
1758  debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found");
1760  return;
1761  }
1762 
1763  /* check if someone is already fetching it */
1764  if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
1765  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1767  return;
1768  }
1769 
1770  if (mem == NULL) {
1771  debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key));
1773  return;
1774  }
1775 
1776  if (e->ping_status != PING_WAITING) {
1777  debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING");
1779  return;
1780  }
1781 
1782  if (!e->locked()) {
1783  // TODO: many entries are unlocked; why is this reported at level 1?
1784  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1786  return;
1787  }
1788 
1789  if (!mem->ircb_data) {
1790  debugs(12, DBG_IMPORTANT, "BUG: missing HTCP callback data for " << *e);
1792  return;
1793  }
1794 
1795  if (p) {
1796  ntype = neighborType(p, mem->request->url);
1797  neighborUpdateRtt(p, mem);
1798  }
1799 
1800  if (ignoreMulticastReply(p, mem->ircb_data)) {
1802  return;
1803  }
1804 
1805  debugs(15, 3, "neighborsHtcpReply: e = " << e);
1806  // TODO: Refactor (ping_reply_callback,ircb_data) to add CodeContext.
1807  mem->ping_reply_callback(p, ntype, AnyP::PROTO_HTCP, htcp, mem->ircb_data);
1808 }
1809 
1810 /*
1811  * Send HTCP CLR messages to all peers configured to receive them.
1812  */
1813 void
1815 {
1816  CachePeer *p;
1817  char buf[128];
1818 
1819  for (p = Config.peers; p; p = p->next) {
1820  if (!p->options.htcp) {
1821  continue;
1822  }
1823  if (p->options.htcp_no_clr) {
1824  continue;
1825  }
1826  if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
1827  continue;
1828  }
1829  debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.toUrl(buf, 128));
1830  htcpClear(e, req, method, p, reason);
1831  }
1832 }
1833 
1834 #endif
1835 
bool waitingForClose
a conn must close before we open a standby conn
Definition: CachePeer.h:181
bool usable
Definition: PeerDigest.h:89
bool proxy_only
Definition: CachePeer.h:79
int testing_now
Definition: CachePeer.h:151
time_t peerConnectTimeout(const CachePeer *peer)
Definition: neighbors.cc:1187
bool no_query
Definition: CachePeer.h:80
Ip::Address addresses[10]
Definition: CachePeer.h:147
char method[16]
Definition: tcp-banger2.c:115
int eventFind(EVH *func, void *arg)
Definition: event.cc:155
bool htcp_no_clr
Definition: CachePeer.h:91
static void neighborAlive(CachePeer *, const MemObject *, const icp_common_t *)
Definition: neighbors.cc:881
int connection_auth
0 - off, 1 - on, 2 - auto
Definition: CachePeer.h:192
@ PEER_MULTICAST
Definition: enums.h:31
bool background_ping
Definition: CachePeer.h:81
double version
Definition: CachePeer.h:68
PeerDigest * digest
Definition: CachePeer.h:139
CachePeer * peerFindByName(const char *name)
Definition: neighbors.cc:1123
const cache_key * storeKeyPublicByRequest(HttpRequest *request, const KeyScope keyScope)
int icp_query_max
Definition: SquidConfig.h:123
@ LOOKUP_NONE
Definition: lookup_t.h:13
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
bool needed
Definition: PeerDigest.h:88
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1297
struct CachePeer::@31 options
acl_access * access
Definition: CachePeer.h:76
int intPercent(const int a, const int b)
Definition: SquidMath.cc:13
Definition: Uri.h:30
HttpRequest * request
Ip::Address in_addr
Definition: CachePeer.h:40
static std::ostream & Extra(std::ostream &os)
prefixes each grouped debugs() line after the first one in the group
Definition: Debug.h:104
unsigned char cache_key
Store key.
Definition: forward.h:29
time_t last_connect_failure
Definition: CachePeer.h:53
AnyP::PortCfgPointer HttpPortList
list of Squid http(s)_port configured
Definition: PortCfg.cc:21
@ initPeerMcast
neighbor multicast
void eventDelete(EVH *func, void *arg)
Definition: event.cc:131
CachePeer * getDefaultParent(PeerSelector *ps)
Definition: neighbors.cc:473
int neighborsUdpPing(HttpRequest *request, StoreEntry *entry, IRCB *callback, PeerSelector *ps, int *exprep, int *timeout)
Definition: neighbors.cc:594
peer_t type
Definition: CachePeer.h:38
int icp_query_min
Definition: SquidConfig.h:124
int n_recv
Definition: PingData.h:22
MemObject * mem_obj
Definition: Store.h:209
PconnPool * pool
idle connection pool for this peer
Definition: CachePeer.h:178
#define MCAST_COUNT_RATE
Definition: neighbors.cc:49
const char * url() const
Definition: store.cc:1612
CacheDigest * cd
Definition: PeerDigest.h:83
unsigned short icp
Definition: SquidConfig.h:137
struct timeval start_ping
Definition: MemObject.h:191
virtual void dumpCfg(Packable *, const char *pfx) const
output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
Definition: PeerOptions.cc:103
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:881
static void peerProbeConnect(CachePeer *, const bool reprobeIfBusy=false)
Definition: neighbors.cc:1334
ping_data ping
char * login
Definition: CachePeer.h:171
#define PEER_ALIVE
Definition: defines.h:126
HttpReplyPointer reply
bool requested
Definition: PeerDigest.h:90
Comm::ConnectionPointer icpOutgoingConn
Definition: icp_v2.cc:104
@ PING_WAITING
Definition: enums.h:41
void netdbExchangeStart(void *data)
Definition: net_db.cc:1269
int neighborsCount(PeerSelector *ps)
Definition: neighbors.cc:273
@ ICP_DECHO
Definition: icp_opcode.h:26
bool reprobe
whether to do another TCP probe after current TCP probes
Definition: CachePeer.h:145
const A & max(A const &lhs, A const &rhs)
StoreEntry * entry
int isPowTen(int count)
Definition: int.cc:16
CachePeer * getNextPeer(CachePeer *p)
Definition: neighbors.cc:500
C * getRaw() const
Definition: RefCount.h:80
uint16_t flags
Definition: Store.h:220
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:412
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:26
bool allow_miss
Definition: CachePeer.h:100
@ OK
Definition: Flag.h:16
unsigned short port
Definition: CachePeer.h:63
void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntryPointer)
Definition: icp_v2.cc:442
int connect_fail_limit
Definition: CachePeer.h:173
#define LOCAL_ARRAY(type, name, size)
Definition: leakcheck.h:18
bool IamWorkerProcess()
whether the current process handles HTTP transactions and such
Definition: stub_tools.cc:49
char * toUrl(char *buf, unsigned int len) const
Definition: Address.cc:884
bool no_tproxy
Definition: CachePeer.h:115
int netdbHostRtt(const char *host)
Definition: net_db.cc:1051
#define DBG_CRITICAL
Definition: Debug.h:45
void CallBack(const CodeContext::Pointer &callbackContext, Fun &&callback)
Definition: CodeContext.h:81
int matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
Definition: Uri.cc:748
int limit
the limit itself
Definition: CachePeer.h:180
static OBJH neighborDumpNonPeers
Definition: neighbors.cc:72
#define cbdataReference(var)
Definition: cbdata.h:341
int intAverage(const int, const int, int, const int)
Definition: SquidMath.cc:40
bool sourcehash
Definition: CachePeer.h:113
int hit
Definition: htcp.h:29
char * name
Definition: CachePeer.h:36
#define DBG_IMPORTANT
Definition: Debug.h:46
void htcpClear(StoreEntry *e, HttpRequest *req, const HttpRequestMethod &, CachePeer *p, htcp_clr_reason reason)
Definition: htcp.cc:1567
static int port
Definition: ldap_backend.cc:69
int stat5minClientRequests(void)
Definition: stat.cc:1726
void setHost(const char *)
set the hostname note for this connection
Definition: ConnOpener.cc:89
@ LOOKUP_MISS
Definition: lookup_t.h:15
bool roundrobin
Definition: CachePeer.h:84
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:802
void peerDigestNeeded(PeerDigest *pd)
Definition: peer_digest.cc:177
void IRCB(CachePeer *, peer_t, AnyP::ProtocolType, void *, void *data)
Definition: typedefs.h:22
static CNCB peerProbeConnectDone
Definition: neighbors.cc:62
void getOutgoingAddress(HttpRequest *request, const Comm::ConnectionPointer &conn)
Definition: FwdState.cc:1416
#define ICP_FLAG_SRC_RTT
Definition: defines.h:73
char * domain
Forced domain.
Definition: CachePeer.h:184
CachePeer * getFirstUpParent(PeerSelector *ps)
Definition: neighbors.cc:288
peer_t neighborType(const CachePeer *p, const AnyP::Uri &url)
Definition: neighbors.cc:115
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:23
static IPH peerDNSConfigure
Definition: neighbors.cc:60
static void Reset()
forgets the current context, setting it to nil/unknown
Definition: CodeContext.cc:75
int pings_acked
Definition: CachePeer.h:44
int weight
Definition: CachePeer.h:122
CachePeer * getWeightedRoundRobinParent(PeerSelector *ps)
Definition: neighbors.cc:355
void CNCB(const Comm::ConnectionPointer &conn, Comm::Flag status, int xerrno, void *data)
Definition: CommCalls.h:35
NeighborTypeDomainList * typelist
Definition: CachePeer.h:75
#define MAX_URL
Definition: defines.h:118
struct CachePeer::@30 htcp
ProtocolType
Definition: ProtocolType.h:23
HttpRequest * request
void neighborsHtcpReply(const cache_key *key, HtcpReplyData *htcp, const Ip::Address &from)
Definition: neighbors.cc:1740
@ ICP_MISS_NOFETCH
Definition: icp_opcode.h:36
#define PEER_MAX_ADDRESSES
Definition: defines.h:121
static CachePeer * first_ping
Definition: neighbors.cc:78
static void peerConnectFailedSilent(CachePeer *p)
Definition: neighbors.cc:1278
static void peerCountMcastPeersCreateAndSend(CachePeer *p)
initiates an ICP transaction to a multicast peer
Definition: neighbors.cc:1407
static void peerCountMcastPeersDone(void *data)
Definition: neighbors.cc:1453
static void neighborRemove(CachePeer *)
Definition: neighbors.cc:512
time_t last_reply
Definition: CachePeer.h:52
bool userhash
Definition: CachePeer.h:111
peer_t
Definition: enums.h:27
unsigned char opcode
Definition: ICP.h:38
void peerConnectSucceded(CachePeer *p)
Definition: neighbors.cc:1304
bool no_digest
Definition: CachePeer.h:82
void OBJH(StoreEntry *)
Definition: forward.h:44
#define NULL
Definition: types.h:166
void dump_peer_options(StoreEntry *sentry, CachePeer *p)
Definition: neighbors.cc:1518
PeerSelector * ircb_data
Definition: MemObject.h:193
time_t deadPeer
Definition: SquidConfig.h:120
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:128
static void neighborIgnoreNonPeer(const Ip::Address &, icp_opcode)
Definition: neighbors.cc:942
@ PEER_PARENT
Definition: enums.h:30
void peerConnClosed(CachePeer *p)
Notifies peer of an associated connection closure.
Definition: neighbors.cc:247
bool htcp_no_purge_clr
Definition: CachePeer.h:92
int n_addresses
Definition: CachePeer.h:148
void abort()
Definition: store.cc:1104
bool no_netdb_exchange
Definition: CachePeer.h:96
void count(int uses)
@ HTCP_CLR_PURGE
Definition: enums.h:238
bool peerAllowedToUse(const CachePeer *, PeerSelector *)
Definition: neighbors.cc:138
void neighborsUdpAck(const cache_key *key, icp_common_t *header, const Ip::Address &from)
Definition: neighbors.cc:1002
void peerClearRR()
Definition: neighbors.cc:446
const Acl::Answer & fastCheck()
Definition: Checklist.cc:336
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1980
static Pointer Start(AsyncJob *job)
starts a freshly created job (i.e., makes the job asynchronous)
Definition: AsyncJob.cc:23
unsigned short port() const
Definition: Address.cc:778
double avg_n_members
Definition: CachePeer.h:126
#define EBIT_TEST(flag, bit)
Definition: defines.h:107
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:600
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:157
CbcPointer< PeerPoolMgr > mgr
pool manager
Definition: CachePeer.h:179
ping_status_t ping_status
Definition: Store.h:230
struct CachePeer::@32::@38 flags
static unsigned short echo_port
Definition: neighbors.cc:75
@ METHOD_CONNECT
Definition: MethodType.h:29
representation of a neighbor_type_domain configuration directive. A POD
#define PEER_TCP_MAGIC_COUNT
Definition: defines.h:192
time_t peer_connect
Definition: SquidConfig.h:113
void const char HLPCB void * data
Definition: stub_helper.cc:16
time_t backgroundPingRate
Definition: SquidConfig.h:104
void debug_trap(const char *message)
Definition: tools.cc:403
int unlock(const char *context)
Definition: store.cc:463
CachePeer * getFirstPeer(void)
Definition: neighbors.cc:506
AccessLogEntry::Pointer al
info for the future access.log entry
struct CachePeer::icp_ icp
@ PEER_NONE
Definition: enums.h:28
int tvSubMsec(struct timeval, struct timeval)
Definition: stub_time.cc:20
bool default_parent
Definition: CachePeer.h:83
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
Definition: CommCalls.h:342
bool closest_only
Definition: CachePeer.h:87
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:19
static OBJH neighborDumpPeers
Definition: neighbors.cc:71
static CachePeer * non_peers
Definition: neighbors.cc:939
lookup_t
Definition: lookup_t.h:12
CachePeer * whichPeer(const Ip::Address &from)
Definition: neighbors.cc:96
@ ICP_HIT
Definition: icp_opcode.h:17
virtual void syncAle(HttpRequest *adaptedRequest, const char *logUri) const
assigns uninitialized adapted_request and url ALE components
void HTTPMSGLOCK(Http::Message *a)
Definition: Message.h:160
void neighborsHtcpClear(StoreEntry *e, HttpRequest *req, const HttpRequestMethod &method, htcp_clr_reason reason)
Definition: neighbors.cc:1814
bool no_delay
Definition: CachePeer.h:98
encapsulates DNS lookup results
Definition: LookupDetails.h:20
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
CachePeer * neighborsDigestSelect(PeerSelector *ps)
Definition: neighbors.cc:802
@ ICP_SECHO
Definition: icp_opcode.h:25
bool peerCanOpenMore(const CachePeer *p)
Whether we can open new connections to the peer (e.g., despite max-conn)
Definition: neighbors.cc:223
time_t squid_curtime
Definition: stub_time.cc:17
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
Definition: Address.cc:184
StoreEntry * storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod &method)
Definition: store.cc:783
int Squid_MaxFD
static bool peerProbeIsBusy(const CachePeer *p)
whether new TCP probes are currently banned
Definition: neighbors.cc:1318
struct SquidConfig::@112 onoff
Comm::ConnectionPointer icpIncomingConn
Definition: icp_v2.cc:102
const char * lookup_t_str[]
static void peerRefreshDNS(void *)
Definition: neighbors.cc:1257
void peerNoteDigestLookup(HttpRequest *request, CachePeer *p, lookup_t lookup)
Definition: neighbors.cc:867
@ ENTRY_DISPATCHED
Definition: enums.h:97
bool carp
Definition: CachePeer.h:101
int n_times_counted
Definition: CachePeer.h:127
Flag
Definition: Flag.h:15
struct CachePeer::@36 standby
optional "cache_peer standby=limit" feature
static void peerClearRRLoop(void *data)
Definition: neighbors.cc:417
bool mcast_responder
Definition: CachePeer.h:86
@ ICP_QUERY
Definition: icp_opcode.h:16
static void neighborsRegisterWithCacheManager()
Definition: neighbors.cc:539
@ ICP_MISS
Definition: icp_opcode.h:18
struct servent * getservbyname()
static int peerWouldBePinged(const CachePeer *, PeerSelector *)
Definition: neighbors.cc:183
time_t positiveTimeout(const time_t timeout)
Definition: neighbors.cc:1194
unsigned char version
Definition: ICP.h:40
int pings_sent
Definition: CachePeer.h:43
NeighborTypeDomainList * next
double doubleAverage(const double, const double, int, const int)
Definition: SquidMath.cc:31
int tcp_up
Definition: CachePeer.h:143
#define PEER_DEAD
Definition: defines.h:125
time_t last_query
Definition: CachePeer.h:51
char * host
Definition: CachePeer.h:37
struct timeval current_time
Definition: stub_time.cc:15
bool allowed() const
Definition: Acl.h:143
int htcpQuery(StoreEntry *e, HttpRequest *req, CachePeer *p)
Definition: htcp.cc:1518
bool mcast_siblings
Definition: CachePeer.h:117
bool htcp_oldsquid
Definition: CachePeer.h:90
StoreEntry * findCallbackXXX(const cache_key *)
Definition: Controller.cc:374
@ LOOKUP_HIT
Definition: lookup_t.h:14
int max_conn
Definition: CachePeer.h:174
int mcastSetTtl(int fd, int mcast_ttl)
Definition: multicast.cc:20
void peerAlive(CachePeer *p)
Definition: neighbors.cc:458
char * url
Definition: tcp-banger2.c:114
const char * getMyHostname(void)
Definition: tools.cc:412
time_t connect_timeout_raw
connect_timeout; use peerConnectTimeout() instead!
Definition: CachePeer.h:172
struct SquidConfig::@99 Port
int rtt
Definition: CachePeer.h:46
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:108
int mcast_icp_query
Definition: SquidConfig.h:125
static HttpRequest * FromUrlXXX(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:546
int rr_count
Definition: CachePeer.h:149
bool contains(const cache_key *key) const
Definition: CacheDigest.cc:93
static IRCB peerCountHandleIcpReply
Definition: neighbors.cc:68
void const char HLPCB * callback
Definition: stub_helper.cc:16
const char * storeKeyText(const cache_key *key)
int logged_state
so we can print dead/revived msgs
Definition: CachePeer.h:55
int neighborUp(const CachePeer *p)
Definition: neighbors.cc:1154
const char * neighborTypeStr(const CachePeer *p)
Definition: neighbors.cc:81
static void neighborAliveHtcp(CachePeer *, const MemObject *, const HtcpReplyData *)
Definition: neighbors.cc:918
@ ICP_END
Definition: icp_opcode.h:39
bool htcp_only_clr
Definition: CachePeer.h:93
CachePeer * peers
Definition: SquidConfig.h:249
lookup_t peerDigestLookup(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:758
static void peerCountMcastPeersAbort(PeerSelector *)
Definition: neighbors.cc:1465
static int ignoreMulticastReply(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:980
time_t last_connect_probe
Definition: CachePeer.h:54
double version
Definition: htcp.h:32
@ ICP_DENIED
Definition: icp_opcode.h:37
@ PROTO_HTCP
Definition: ProtocolType.h:35
const char * FormatHttpd(time_t t)
Definition: stub_time.cc:25
int ignored_replies
Definition: CachePeer.h:47
#define RTT_BACKGROUND_AV_FACTOR
Definition: defines.h:123
void CallContextCreator(Fun &&creator)
Definition: CodeContext.h:113
void eventAddIsh(const char *name, EVH *func, void *arg, double delta_ish, int weight)
Definition: event.cc:116
struct SquidConfig::@98 Timeout
int locked() const
Definition: Store.h:136
bool weighted_roundrobin
Definition: CachePeer.h:85
CachePeer * next
Definition: CachePeer.h:150
#define ICP_VERSION_2
Definition: defines.h:76
static int NLateReplies
Definition: neighbors.cc:77
CachePeer * peerFindByNameAndPort(const char *name, unsigned short port)
Definition: neighbors.cc:1136
IRCB * ping_reply_callback
Definition: MemObject.h:192
int peerHTTPOkay(const CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:258
void RegisterAction(char const *action, char const *desc, OBJH *handler, int pw_req_flag, int atomic)
Definition: Registration.cc:16
icp_opcode
Definition: icp_opcode.h:13
void neighbors_init(void)
Definition: neighbors.cc:553
@ METHOD_GET
Definition: MethodType.h:25
static void Checkpoint(const Pointer &mgr, const char *reason)
Definition: PeerPoolMgr.cc:261
struct PeerDigest::@90 flags
static void peerCountMcastPeersStart(void *data)
Definition: neighbors.cc:1396
static void neighborCountIgnored(CachePeer *)
Definition: neighbors.cc:929
struct CachePeer::@32 mcast
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:187
int counts[2]
Definition: CachePeer.h:69
void host(const char *src)
Definition: Uri.cc:98
bool peerHasConnAvailable(const CachePeer *p)
Whether the peer has idle or standby connections that can be used now.
Definition: neighbors.cc:232
@ PEER_SIBLING
Definition: enums.h:29
static void peerCountMcastPeersSchedule(CachePeer *p, time_t when)
Definition: neighbors.cc:1382
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
int counts[ICP_END+1]
Definition: CachePeer.h:62
htcp_clr_reason
Definition: enums.h:237
#define RTT_AV_FACTOR
Definition: defines.h:122
void * peerCountMcastPeerXXX
a hack to help peerCountMcastPeersStart()
static void neighborUpdateRtt(CachePeer *p, MemObject *mem)
Definition: neighbors.cc:893
void peerClearRRStart(void)
Definition: neighbors.cc:429
HttpRequestPointer request
Definition: MemObject.h:189
unsigned short http_port
Definition: CachePeer.h:74
int icpSetCacheKey(const cache_key *key)
Definition: icp_v2.cc:873
int conn_open
current opened connections
Definition: CachePeer.h:56
struct CachePeer::@29 stats
int n_replies_expected
Definition: CachePeer.h:128
const char * getMD5Text() const
Definition: store.cc:185
void const char * buf
Definition: stub_helper.cc:16
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:109
int basetime
Definition: CachePeer.h:123
bool originserver
Definition: CachePeer.h:114
@ PROTO_ICP
Definition: ProtocolType.h:33
unsigned short htcp
Definition: SquidConfig.h:140
static void dump_peers(StoreEntry *sentry, CachePeer *peers)
Definition: neighbors.cc:1647
CachePeer * getRoundRobinParent(PeerSelector *ps)
Definition: neighbors.cc:313
const char * icp_opcode_str[]
void IPH(const ipcache_addrs *, const Dns::LookupDetails &details, void *)
Definition: ipcache.h:219
time_t probe_start
Definition: CachePeer.h:50
class SquidConfig Config
Definition: SquidConfig.cc:12
char * digest_url
Definition: CachePeer.h:140
IpsSelector< IpsIterator > goodAndBad() const
all IPs
Definition: ipcache.h:249
Controller & Root()
safely access controller singleton
Definition: Controller.cc:905

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors