neighbors.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 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 "debug/Messages.h"
20 #include "event.h"
21 #include "FwdState.h"
22 #include "globals.h"
23 #include "htcp.h"
24 #include "HttpRequest.h"
25 #include "icmp/net_db.h"
26 #include "ICP.h"
27 #include "int.h"
28 #include "ip/Address.h"
29 #include "ip/tools.h"
30 #include "ipcache.h"
31 #include "MemObject.h"
32 #include "mgr/Registration.h"
33 #include "multicast.h"
34 #include "neighbors.h"
35 #include "NeighborTypeDomainList.h"
36 #include "pconn.h"
37 #include "PeerDigest.h"
38 #include "PeerPoolMgr.h"
39 #include "PeerSelectState.h"
40 #include "RequestFlags.h"
41 #include "SquidConfig.h"
42 #include "SquidMath.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, "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 
417 static void
418 peerClearRRLoop(void *data)
419 {
420  peerClearRR();
421  eventAdd("peerClearRR", peerClearRRLoop, data, 5 * 60.0, 0);
422 }
423 
429 void
431 {
432  static bool event_added = false;
433  if (!event_added) {
435  event_added=true;
436  }
437 }
438 
446 void
448 {
449  CachePeer *p = NULL;
450  for (p = Config.peers; p; p = p->next) {
451  p->rr_count = 1;
452  }
453 }
454 
458 static void
460 {
461  if (p->stats.logged_state == PEER_DEAD && p->tcp_up) {
462  debugs(15, DBG_IMPORTANT, "Detected REVIVED " << neighborTypeStr(p) << ": " << p->name);
464  peerClearRR();
465  if (p->standby.mgr.valid())
466  PeerPoolMgr::Checkpoint(p->standby.mgr, "revived peer");
467  }
468 
470  p->stats.probe_start = 0;
471 }
472 
473 CachePeer *
475 {
476  assert(ps);
477  HttpRequest *request = ps->request;
478 
479  CachePeer *p = NULL;
480 
481  for (p = Config.peers; p; p = p->next) {
482  if (neighborType(p, request->url) != PEER_PARENT)
483  continue;
484 
485  if (!p->options.default_parent)
486  continue;
487 
488  if (!peerHTTPOkay(p, ps))
489  continue;
490 
491  debugs(15, 3, "getDefaultParent: returning " << p->host);
492 
493  return p;
494  }
495 
496  debugs(15, 3, "getDefaultParent: returning NULL");
497  return NULL;
498 }
499 
500 CachePeer *
502 {
503  return p->next;
504 }
505 
506 CachePeer *
508 {
509  return Config.peers;
510 }
511 
512 static void
514 {
515  CachePeer *p = NULL;
516  CachePeer **P = NULL;
517  p = Config.peers;
518  P = &Config.peers;
519 
520  while (p) {
521  if (target == p)
522  break;
523 
524  P = &p->next;
525 
526  p = p->next;
527  }
528 
529  if (p) {
530  *P = p->next;
531  p->next = NULL;
532  delete p;
533  --Config.npeers;
534  }
535 
537 }
538 
539 static void
541 {
542  Mgr::RegisterAction("server_list",
543  "Peer Cache Statistics",
544  neighborDumpPeers, 0, 1);
545 
547  Mgr::RegisterAction("non_peers",
548  "List of Unknown sites sending ICP messages",
549  neighborDumpNonPeers, 0, 1);
550  }
551 }
552 
553 void
555 {
556  struct servent *sep = NULL;
557  const char *me = getMyHostname();
558  CachePeer *thisPeer = NULL;
559  CachePeer *next = NULL;
560 
562 
564 
565  for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
566  next = thisPeer->next;
567 
568  if (0 != strcmp(thisPeer->host, me))
569  continue;
570 
571  for (AnyP::PortCfgPointer s = HttpPortList; s != NULL; s = s->next) {
572  if (thisPeer->http_port != s->s.port())
573  continue;
574 
575  debugs(15, DBG_IMPORTANT, "WARNING: Peer looks like this host." <<
576  Debug::Extra << "Ignoring " <<
577  neighborTypeStr(thisPeer) << " " << thisPeer->host <<
578  "/" << thisPeer->http_port << "/" <<
579  thisPeer->icp.port);
580 
581  neighborRemove(thisPeer);
582  }
583  }
584  }
585 
586  peerRefreshDNS((void *) 1);
587 
588  sep = getservbyname("echo", "udp");
589  echo_port = sep ? ntohs((unsigned short) sep->s_port) : 7;
590 
592 }
593 
594 int
596  StoreEntry * entry,
597  IRCB * callback,
598  PeerSelector *ps,
599  int *exprep,
600  int *timeout)
601 {
602  const char *url = entry->url();
603  MemObject *mem = entry->mem_obj;
604  CachePeer *p = NULL;
605  int i;
606  int reqnum = 0;
607  int flags;
608  int queries_sent = 0;
609  int peers_pinged = 0;
610  int parent_timeout = 0, parent_exprep = 0;
611  int sibling_timeout = 0, sibling_exprep = 0;
612  int mcast_timeout = 0, mcast_exprep = 0;
613 
614  if (Config.peers == NULL)
615  return 0;
616 
617  assert(!entry->hasDisk());
618 
619  mem->start_ping = current_time;
620 
621  mem->ping_reply_callback = callback;
622 
623  mem->ircb_data = ps;
624 
625  reqnum = icpSetCacheKey((const cache_key *)entry->key);
626 
627  for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
628  if (p == NULL)
629  p = Config.peers;
630 
631  debugs(15, 5, "neighborsUdpPing: Peer " << p->host);
632 
633  if (!peerWouldBePinged(p, ps))
634  continue; /* next CachePeer */
635 
636  ++peers_pinged;
637 
638  debugs(15, 4, "neighborsUdpPing: pinging peer " << p->host << " for '" << url << "'");
639 
640  debugs(15, 3, "neighborsUdpPing: key = '" << entry->getMD5Text() << "'");
641 
642  debugs(15, 3, "neighborsUdpPing: reqnum = " << reqnum);
643 
644 #if USE_HTCP
645  if (p->options.htcp && !p->options.htcp_only_clr) {
646  if (Config.Port.htcp <= 0) {
647  debugs(15, DBG_CRITICAL, "ERROR: HTCP is disabled! Cannot send HTCP request to peer.");
648  continue;
649  }
650 
651  debugs(15, 3, "neighborsUdpPing: sending HTCP query");
652  if (htcpQuery(entry, request, p) <= 0)
653  continue; // unable to send.
654  } else
655 #endif
656  {
658  debugs(15, DBG_CRITICAL, "ERROR: ICP is disabled! Cannot send ICP request to peer.");
659  continue;
660  } else {
661 
662  if (p->type == PEER_MULTICAST)
664 
665  if (p->icp.port == echo_port) {
666  debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping");
667  // TODO: Get ALE from callback_data if possible.
668  icpCreateAndSend(ICP_DECHO, 0, url, reqnum, 0,
669  icpOutgoingConn->fd, p->in_addr, nullptr);
670  } else {
671  flags = 0;
672 
673  if (Config.onoff.query_icmp)
674  if (p->icp.version == ICP_VERSION_2)
675  flags |= ICP_FLAG_SRC_RTT;
676 
677  // TODO: Get ALE from callback_data if possible.
678  icpCreateAndSend(ICP_QUERY, flags, url, reqnum, 0,
679  icpOutgoingConn->fd, p->in_addr, nullptr);
680  }
681  }
682  }
683 
684  ++queries_sent;
685 
686  ++ p->stats.pings_sent;
687 
688  if (p->type == PEER_MULTICAST) {
689  mcast_exprep += p->mcast.n_replies_expected;
690  mcast_timeout += (p->stats.rtt * p->mcast.n_replies_expected);
691  } else if (neighborUp(p)) {
692  /* its alive, expect a reply from it */
693 
694  if (neighborType(p, request->url) == PEER_PARENT) {
695  ++parent_exprep;
696  parent_timeout += p->stats.rtt;
697  } else {
698  ++sibling_exprep;
699  sibling_timeout += p->stats.rtt;
700  }
701  } else {
702  /* Neighbor is dead; ping it anyway, but don't expect a reply */
703  /* log it once at the threshold */
704 
705  if (p->stats.logged_state == PEER_ALIVE) {
706  debugs(15, DBG_IMPORTANT, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name);
708  }
709  }
710 
712 
713  /*
714  * keep probe_start == 0 for a multicast CachePeer,
715  * so neighborUp() never says this CachePeer is dead.
716  */
717 
718  if ((p->type != PEER_MULTICAST) && (p->stats.probe_start == 0))
720  }
721 
722  if ((first_ping = first_ping->next) == NULL)
724 
725  /*
726  * How many replies to expect?
727  */
728  *exprep = parent_exprep + sibling_exprep + mcast_exprep;
729 
730  /*
731  * If there is a configured timeout, use it
732  */
734  *timeout = Config.Timeout.icp_query;
735  else {
736  if (*exprep > 0) {
737  if (parent_exprep)
738  *timeout = 2 * parent_timeout / parent_exprep;
739  else if (mcast_exprep)
740  *timeout = 2 * mcast_timeout / mcast_exprep;
741  else
742  *timeout = 2 * sibling_timeout / sibling_exprep;
743  } else
744  *timeout = 2000; /* 2 seconds */
745 
747  if (*timeout > Config.Timeout.icp_query_max)
748  *timeout = Config.Timeout.icp_query_max;
749 
750  if (*timeout < Config.Timeout.icp_query_min)
751  *timeout = Config.Timeout.icp_query_min;
752  }
753 
754  return peers_pinged;
755 }
756 
757 /* lookup the digest of a given CachePeer */
758 lookup_t
760 {
761 #if USE_CACHE_DIGESTS
762  assert(ps);
763  HttpRequest *request = ps->request;
765  assert(p);
766  assert(request);
767  debugs(15, 5, "peerDigestLookup: peer " << p->host);
768  /* does the peeer have a valid digest? */
769 
770  if (!p->digest) {
771  debugs(15, 5, "peerDigestLookup: gone!");
772  return LOOKUP_NONE;
773  } else if (!peerHTTPOkay(p, ps)) {
774  debugs(15, 5, "peerDigestLookup: !peerHTTPOkay");
775  return LOOKUP_NONE;
776  } else if (!p->digest->flags.needed) {
777  debugs(15, 5, "peerDigestLookup: note need");
779  return LOOKUP_NONE;
780  } else if (!p->digest->flags.usable) {
781  debugs(15, 5, "peerDigestLookup: !ready && " << (p->digest->flags.requested ? "" : "!") << "requested");
782  return LOOKUP_NONE;
783  }
784 
785  debugs(15, 5, "peerDigestLookup: OK to lookup peer " << p->host);
786  assert(p->digest->cd);
787  /* does digest predict a hit? */
788 
789  if (!p->digest->cd->contains(key))
790  return LOOKUP_MISS;
791 
792  debugs(15, 5, "peerDigestLookup: peer " << p->host << " says HIT!");
793 
794  return LOOKUP_HIT;
795 #else
796  (void)p;
797  (void)ps;
798 #endif
799 
800  return LOOKUP_NONE;
801 }
802 
803 /* select best CachePeer based on cache digests */
804 CachePeer *
806 {
807  CachePeer *best_p = NULL;
808 #if USE_CACHE_DIGESTS
809  assert(ps);
810  HttpRequest *request = ps->request;
811 
812  int best_rtt = 0;
813  int choice_count = 0;
814  int ichoice_count = 0;
815  CachePeer *p;
816  int p_rtt;
817  int i;
818 
819  if (!request->flags.hierarchical)
820  return NULL;
821 
823 
824  for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
825  lookup_t lookup;
826 
827  if (!p)
828  p = Config.peers;
829 
830  if (i == 1)
831  first_ping = p;
832 
833  lookup = peerDigestLookup(p, ps);
834 
835  if (lookup == LOOKUP_NONE)
836  continue;
837 
838  ++choice_count;
839 
840  if (lookup == LOOKUP_MISS)
841  continue;
842 
843  p_rtt = netdbHostRtt(p->host);
844 
845  debugs(15, 5, "neighborsDigestSelect: peer " << p->host << " rtt: " << p_rtt);
846 
847  /* is this CachePeer better than others in terms of rtt ? */
848  if (!best_p || (p_rtt && p_rtt < best_rtt)) {
849  best_p = p;
850  best_rtt = p_rtt;
851 
852  if (p_rtt) /* informative choice (aka educated guess) */
853  ++ichoice_count;
854 
855  debugs(15, 4, "neighborsDigestSelect: peer " << p->host << " leads with rtt " << best_rtt);
856  }
857  }
858 
859  debugs(15, 4, "neighborsDigestSelect: choices: " << choice_count << " (" << ichoice_count << ")");
861  best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
862  request->hier.n_choices = choice_count;
863  request->hier.n_ichoices = ichoice_count;
864 #else
865  (void)ps;
866 #endif
867 
868  return best_p;
869 }
870 
871 void
873 {
874 #if USE_CACHE_DIGESTS
875  if (p)
876  strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host)-1);
877  else
878  *request->hier.cd_host = '\0';
879 
880  request->hier.cd_lookup = lookup;
881  debugs(15, 4, "peerNoteDigestLookup: peer " << (p? p->host : "<none>") << ", lookup: " << lookup_t_str[lookup] );
882 #else
883  (void)request;
884  (void)p;
885  (void)lookup;
886 #endif
887 }
888 
889 static void
890 neighborAlive(CachePeer * p, const MemObject *, const icp_common_t * header)
891 {
892  peerAlive(p);
893  ++ p->stats.pings_acked;
894 
895  if ((icp_opcode) header->opcode <= ICP_END)
896  ++ p->icp.counts[header->opcode];
897 
898  p->icp.version = (int) header->version;
899 }
900 
901 static void
903 {
904  int rtt, rtt_av_factor;
905 
906  if (!mem)
907  return;
908 
909  if (!mem->start_ping.tv_sec)
910  return;
911 
912  rtt = tvSubMsec(mem->start_ping, current_time);
913 
914  if (rtt < 1 || rtt > 10000)
915  return;
916 
917  rtt_av_factor = RTT_AV_FACTOR;
918 
920  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
921 
922  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor);
923 }
924 
925 #if USE_HTCP
926 static void
928 {
929  peerAlive(p);
930  ++ p->stats.pings_acked;
931  ++ p->htcp.counts[htcp->hit ? 1 : 0];
932  p->htcp.version = htcp->version;
933 }
934 
935 #endif
936 
937 static void
939 {
940  if (p == NULL)
941  return;
942 
943  ++ p->stats.ignored_replies;
944 
945  ++NLateReplies;
946 }
947 
949 
950 static void
952 {
953  CachePeer *np;
954 
955  for (np = non_peers; np; np = np->next) {
956  if (np->in_addr != from)
957  continue;
958 
959  if (np->in_addr.port() != from.port())
960  continue;
961 
962  break;
963  }
964 
965  if (np == NULL) {
966  np = new CachePeer;
967  np->in_addr = from;
968  np->icp.port = from.port();
969  np->type = PEER_NONE;
970  np->host = new char[MAX_IPSTRLEN];
971  from.toStr(np->host,MAX_IPSTRLEN);
972  np->next = non_peers;
973  non_peers = np;
974  }
975 
976  ++ np->icp.counts[opcode];
977 
978  if (isPowTen(++np->stats.ignored_replies))
979  debugs(15, DBG_IMPORTANT, "WARNING: Ignored " << np->stats.ignored_replies << " replies from non-peer " << np->host);
980 }
981 
982 /* ignoreMulticastReply
983  *
984  * * We want to ignore replies from multicast peers if the
985  * * cache_host_domain rules would normally prevent the CachePeer
986  * * from being used
987  */
988 static int
990 {
991  if (p == NULL)
992  return 0;
993 
994  if (!p->options.mcast_responder)
995  return 0;
996 
997  if (peerHTTPOkay(p, ps))
998  return 0;
999 
1000  return 1;
1001 }
1002 
1010 void
1011 neighborsUdpAck(const cache_key * key, icp_common_t * header, const Ip::Address &from)
1012 {
1013  CachePeer *p = NULL;
1014  StoreEntry *entry;
1015  MemObject *mem = NULL;
1016  peer_t ntype = PEER_NONE;
1017  icp_opcode opcode = (icp_opcode) header->opcode;
1018 
1019  debugs(15, 6, "neighborsUdpAck: opcode " << opcode << " '" << storeKeyText(key) << "'");
1020 
1021  if ((entry = Store::Root().findCallbackXXX(key)))
1022  mem = entry->mem_obj;
1023 
1024  if ((p = whichPeer(from)))
1025  neighborAlive(p, mem, header);
1026 
1027  if (opcode > ICP_END)
1028  return;
1029 
1030  const char *opcode_d = icp_opcode_str[opcode];
1031 
1032  if (p)
1033  neighborUpdateRtt(p, mem);
1034 
1035  /* Does the entry exist? */
1036  if (NULL == entry) {
1037  debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found");
1039  return;
1040  }
1041 
1042  /* check if someone is already fetching it */
1043  if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
1044  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1046  return;
1047  }
1048 
1049  if (mem == NULL) {
1050  debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key));
1052  return;
1053  }
1054 
1055  if (entry->ping_status != PING_WAITING) {
1056  debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key));
1058  return;
1059  }
1060 
1061  if (!entry->locked()) {
1062  // TODO: many entries are unlocked; why is this reported at level 1?
1063  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1065  return;
1066  }
1067 
1068  if (!mem->ircb_data) {
1069  debugs(12, DBG_IMPORTANT, "ERROR: Squid BUG: missing ICP callback data for " << *entry);
1071  return;
1072  }
1073 
1074  debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " ");
1075 
1076  if (p) {
1077  ntype = neighborType(p, mem->request->url);
1078  }
1079 
1080  if (ignoreMulticastReply(p, mem->ircb_data)) {
1082  } else if (opcode == ICP_MISS) {
1083  if (p == NULL) {
1084  neighborIgnoreNonPeer(from, opcode);
1085  } else {
1086  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1087  }
1088  } else if (opcode == ICP_HIT) {
1089  if (p == NULL) {
1090  neighborIgnoreNonPeer(from, opcode);
1091  } else {
1092  header->opcode = ICP_HIT;
1093  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1094  }
1095  } else if (opcode == ICP_DECHO) {
1096  if (p == NULL) {
1097  neighborIgnoreNonPeer(from, opcode);
1098  } else if (ntype == PEER_SIBLING) {
1099  debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
1100  debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n");
1101  } else {
1102  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1103  }
1104  } else if (opcode == ICP_SECHO) {
1105  if (p) {
1106  debugs(15, DBG_IMPORTANT, "Ignoring SECHO from neighbor " << p->host);
1108  } else {
1109  debugs(15, DBG_IMPORTANT, "Unsolicited SECHO from " << from);
1110  }
1111  } else if (opcode == ICP_DENIED) {
1112  if (p == NULL) {
1113  neighborIgnoreNonPeer(from, opcode);
1114  } else if (p->stats.pings_acked > 100) {
1115  if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
1116  debugs(15, DBG_CRITICAL, "95%% of replies from '" << p->host << "' are UDP_DENIED");
1117  debugs(15, DBG_CRITICAL, "Disabling '" << p->host << "', please check your configuration.");
1118  neighborRemove(p);
1119  p = NULL;
1120  } else {
1122  }
1123  }
1124  } else if (opcode == ICP_MISS_NOFETCH) {
1125  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1126  } else {
1127  debugs(15, DBG_CRITICAL, "ERROR: neighborsUdpAck: Unexpected ICP reply: " << opcode_d);
1128  }
1129 }
1130 
1131 CachePeer *
1132 peerFindByName(const char *name)
1133 {
1134  CachePeer *p = NULL;
1135 
1136  for (p = Config.peers; p; p = p->next) {
1137  if (!strcasecmp(name, p->name))
1138  break;
1139  }
1140 
1141  return p;
1142 }
1143 
1144 CachePeer *
1145 peerFindByNameAndPort(const char *name, unsigned short port)
1146 {
1147  CachePeer *p = NULL;
1148 
1149  for (p = Config.peers; p; p = p->next) {
1150  if (strcasecmp(name, p->name))
1151  continue;
1152 
1153  if (port != p->http_port)
1154  continue;
1155 
1156  break;
1157  }
1158 
1159  return p;
1160 }
1161 
1162 int
1164 {
1165  if (!p->tcp_up) {
1166  peerProbeConnect(const_cast<CachePeer*>(p));
1167  return 0;
1168  }
1169 
1170  /*
1171  * The CachePeer can not be UP if we don't have any IP addresses
1172  * for it.
1173  */
1174  if (0 == p->n_addresses) {
1175  debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")");
1176  return 0;
1177  }
1178 
1179  if (p->options.no_query) {
1180  debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")");
1181  return 1;
1182  }
1183 
1184  if (p->stats.probe_start != 0 &&
1186  debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")");
1187  return 0;
1188  }
1189 
1190  debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")");
1191  return 1;
1192 }
1193 
1194 time_t
1195 positiveTimeout(const time_t timeout)
1196 {
1197  return max(static_cast<time_t>(1), timeout);
1198 }
1199 
1200 static void
1201 peerDNSConfigure(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data)
1202 {
1203  // TODO: connections to no-longer valid IP addresses should be
1204  // closed when we can detect such IP addresses.
1205 
1206  CachePeer *p = (CachePeer *)data;
1207 
1208  if (p->n_addresses == 0) {
1209  debugs(15, Important(29), "Configuring " << neighborTypeStr(p) << " " << p->host << "/" << p->http_port << "/" << p->icp.port);
1210 
1211  if (p->type == PEER_MULTICAST)
1212  debugs(15, DBG_IMPORTANT, " Multicast TTL = " << p->mcast.ttl);
1213  }
1214 
1215  p->n_addresses = 0;
1216 
1217  if (ia == NULL) {
1218  debugs(0, DBG_CRITICAL, "WARNING: DNS lookup for '" << p->host << "' failed!");
1219  return;
1220  }
1221 
1222  if (ia->empty()) {
1223  debugs(0, DBG_CRITICAL, "WARNING: No IP address found for '" << p->host << "'!");
1224  return;
1225  }
1226 
1227  for (const auto &ip: ia->goodAndBad()) { // TODO: Consider using just good().
1228  if (p->n_addresses < PEER_MAX_ADDRESSES) {
1229  const auto idx = p->n_addresses++;
1230  p->addresses[idx] = ip;
1231  debugs(15, 2, "--> IP address #" << idx << ": " << p->addresses[idx]);
1232  } else {
1233  debugs(15, 3, "ignoring remaining " << (ia->size() - p->n_addresses) << " ips");
1234  break;
1235  }
1236  }
1237 
1238  p->in_addr.setEmpty();
1239  p->in_addr = p->addresses[0];
1240  p->in_addr.port(p->icp.port);
1241 
1242  peerProbeConnect(p, true); // detect any died or revived peers ASAP
1243 
1244  if (p->type == PEER_MULTICAST)
1246 
1247 #if USE_ICMP
1248  if (p->type != PEER_MULTICAST && IamWorkerProcess())
1249  if (!p->options.no_netdb_exchange)
1250  eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
1251 #endif
1252 
1253  if (p->standby.mgr.valid())
1254  PeerPoolMgr::Checkpoint(p->standby.mgr, "resolved peer");
1255 }
1256 
1257 static void
1258 peerRefreshDNS(void *data)
1259 {
1260  CachePeer *p = NULL;
1261 
1264 
1265  if (!data && 0 == stat5minClientRequests()) {
1266  /* no recent client traffic, wait a bit */
1267  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
1268  return;
1269  }
1270 
1271  for (p = Config.peers; p; p = p->next)
1273 
1274  /* Reconfigure the peers every hour */
1275  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1);
1276 }
1277 
1278 static void
1280 {
1282 
1283  if (!p->tcp_up) {
1284  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port <<
1285  " dead");
1286  return;
1287  }
1288 
1289  -- p->tcp_up;
1290 
1291  if (!p->tcp_up) {
1292  debugs(15, DBG_IMPORTANT, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name);
1294  }
1295 }
1296 
1297 void
1299 {
1300  debugs(15, DBG_IMPORTANT, "ERROR: TCP connection to " << p->host << "/" << p->http_port << " failed");
1302 }
1303 
1304 void
1306 {
1307  if (!p->tcp_up) {
1308  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeeded");
1309  p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly.
1310  peerAlive(p);
1311  if (!p->n_addresses)
1313  } else
1314  p->tcp_up = p->connect_fail_limit;
1315 }
1316 
1318 static bool
1320 {
1321  if (p->testing_now > 0) {
1322  debugs(15, 8, "yes, probing " << p);
1323  return true;
1324  }
1325  if (squid_curtime - p->stats.last_connect_probe == 0) {
1326  debugs(15, 8, "yes, just probed " << p);
1327  return true;
1328  }
1329  return false;
1330 }
1331 /*
1332 * peerProbeConnect will be called on dead peers by neighborUp
1333 */
1334 static void
1335 peerProbeConnect(CachePeer *p, const bool reprobeIfBusy)
1336 {
1337  if (peerProbeIsBusy(p)) {
1338  p->reprobe = reprobeIfBusy;
1339  return;
1340  }
1341  p->reprobe = false;
1342 
1343  const auto ctimeout = p->connectTimeout();
1344  /* for each IP address of this CachePeer. find one that we can connect to and probe it. */
1345  for (int i = 0; i < p->n_addresses; ++i) {
1347  conn->remote = p->addresses[i];
1348  conn->remote.port(p->http_port);
1349  conn->setPeer(p);
1351 
1352  ++ p->testing_now;
1353 
1354  AsyncCall::Pointer call = commCbCall(15,3, "peerProbeConnectDone", CommConnectCbPtrFun(peerProbeConnectDone, p));
1355  Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, ctimeout);
1356  cs->setHost(p->host);
1357  AsyncJob::Start(cs);
1358  }
1359 
1361 }
1362 
1363 static void
1365 {
1366  CachePeer *p = (CachePeer*)data;
1367 
1368  if (status == Comm::OK) {
1370  } else {
1372  }
1373 
1374  -- p->testing_now;
1375  conn->close();
1376  // TODO: log this traffic.
1377 
1378  if (p->reprobe)
1379  peerProbeConnect(p);
1380 }
1381 
1382 static void
1384 {
1385  if (p->mcast.flags.count_event_pending)
1386  return;
1387 
1388  eventAdd("peerCountMcastPeersStart",
1390  p,
1391  (double) when, 1);
1392 
1393  p->mcast.flags.count_event_pending = true;
1394 }
1395 
1396 static void
1398 {
1399  const auto peer = static_cast<CachePeer*>(data);
1400  CallContextCreator([peer] {
1402  });
1404 }
1405 
1407 static void
1409 {
1410  // XXX: Do not create lots of complex fake objects (while abusing their
1411  // APIs) to pass around a few basic data points like start_ping and ping!
1412  MemObject *mem;
1413  int reqnum;
1414  // TODO: use class AnyP::Uri instead of constructing and re-parsing a string
1415  LOCAL_ARRAY(char, url, MAX_URL);
1416  assert(p->type == PEER_MULTICAST);
1417  p->mcast.flags.count_event_pending = false;
1418  snprintf(url, MAX_URL, "http://");
1419  p->in_addr.toUrl(url+7, MAX_URL -8 );
1420  strcat(url, "/");
1421  const auto mx = MasterXaction::MakePortless<XactionInitiator::initPeerMcast>();
1422  auto *req = HttpRequest::FromUrlXXX(url, mx);
1423  assert(req != nullptr);
1424  const AccessLogEntry::Pointer ale = new AccessLogEntry;
1425  ale->request = req;
1426  CodeContext::Reset(ale);
1428  const auto psstate = new PeerSelector(nullptr);
1429  psstate->request = req;
1430  HTTPMSGLOCK(psstate->request);
1431  psstate->entry = fake;
1432  psstate->peerCountMcastPeerXXX = cbdataReference(p);
1433  psstate->ping.start = current_time;
1434  psstate->al = ale;
1435  mem = fake->mem_obj;
1436  mem->request = psstate->request;
1437  mem->start_ping = current_time;
1439  mem->ircb_data = psstate;
1441  p->mcast.id = mem->id;
1442  reqnum = icpSetCacheKey((const cache_key *)fake->key);
1443  icpCreateAndSend(ICP_QUERY, 0, url, reqnum, 0,
1444  icpOutgoingConn->fd, p->in_addr, psstate->al);
1445  fake->ping_status = PING_WAITING; // TODO: refactor to use PeerSelector::startPingWaiting()
1446  eventAdd("peerCountMcastPeersDone",
1448  psstate,
1449  Config.Timeout.mcast_icp_query / 1000.0, 1);
1450  p->mcast.flags.counting = true;
1451 }
1452 
1453 static void
1455 {
1456  const auto psstate = static_cast<PeerSelector*>(data);
1457  CallBack(psstate->al, [psstate] {
1458  peerCountMcastPeersAbort(psstate);
1459  delete psstate;
1460  });
1461 }
1462 
1465 static void
1467 {
1468  StoreEntry *fake = psstate->entry;
1469 
1471  CachePeer *p = (CachePeer *)psstate->peerCountMcastPeerXXX;
1472  p->mcast.flags.counting = false;
1474  debugs(15, DBG_IMPORTANT, "Group " << p->host << ": " << psstate->ping.n_recv <<
1475  " replies, "<< std::setw(4)<< std::setprecision(2) <<
1476  p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt);
1478  }
1479 
1481 
1482  fake->abort(); // sets ENTRY_ABORTED and initiates related cleanup
1483  fake->mem_obj->request = nullptr;
1484  fake->unlock("peerCountMcastPeersDone");
1485 }
1486 
1487 static void
1489 {
1490  const auto psstate = static_cast<PeerSelector*>(data);
1491  StoreEntry *fake = psstate->entry;
1492  assert(fake);
1493  MemObject *mem = fake->mem_obj;
1494  assert(mem);
1495  int rtt = tvSubMsec(mem->start_ping, current_time);
1496  assert(proto == AnyP::PROTO_ICP);
1497  ++ psstate->ping.n_recv;
1498  int rtt_av_factor = RTT_AV_FACTOR;
1499 
1501  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
1502 
1503  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1504 }
1505 
1506 static void
1508 {
1509  dump_peers(sentry, Config.peers);
1510 }
1511 
1512 static void
1514 {
1515  dump_peers(sentry, non_peers);
1516 }
1517 
1518 void
1520 {
1521  if (p->options.proxy_only)
1522  storeAppendPrintf(sentry, " proxy-only");
1523 
1524  if (p->options.no_query)
1525  storeAppendPrintf(sentry, " no-query");
1526 
1527  if (p->options.background_ping)
1528  storeAppendPrintf(sentry, " background-ping");
1529 
1530  if (p->options.no_digest)
1531  storeAppendPrintf(sentry, " no-digest");
1532 
1533  if (p->options.default_parent)
1534  storeAppendPrintf(sentry, " default");
1535 
1536  if (p->options.roundrobin)
1537  storeAppendPrintf(sentry, " round-robin");
1538 
1539  if (p->options.carp)
1540  storeAppendPrintf(sentry, " carp");
1541 
1542 #if USE_AUTH
1543  if (p->options.userhash)
1544  storeAppendPrintf(sentry, " userhash");
1545 #endif
1546 
1547  if (p->options.sourcehash)
1548  storeAppendPrintf(sentry, " sourcehash");
1549 
1551  storeAppendPrintf(sentry, " weighted-round-robin");
1552 
1553  if (p->options.mcast_responder)
1554  storeAppendPrintf(sentry, " multicast-responder");
1555 
1556 #if PEER_MULTICAST_SIBLINGS
1557  if (p->options.mcast_siblings)
1558  storeAppendPrintf(sentry, " multicast-siblings");
1559 #endif
1560 
1561  if (p->weight != 1)
1562  storeAppendPrintf(sentry, " weight=%d", p->weight);
1563 
1564  if (p->options.closest_only)
1565  storeAppendPrintf(sentry, " closest-only");
1566 
1567 #if USE_HTCP
1568  if (p->options.htcp) {
1569  storeAppendPrintf(sentry, " htcp");
1571  bool doneopts = false;
1572  if (p->options.htcp_oldsquid) {
1573  storeAppendPrintf(sentry, "oldsquid");
1574  doneopts = true;
1575  }
1576  if (p->options.htcp_no_clr) {
1577  storeAppendPrintf(sentry, "%sno-clr",(doneopts?",":"="));
1578  doneopts = true;
1579  }
1580  if (p->options.htcp_no_purge_clr) {
1581  storeAppendPrintf(sentry, "%sno-purge-clr",(doneopts?",":"="));
1582  doneopts = true;
1583  }
1584  if (p->options.htcp_only_clr) {
1585  storeAppendPrintf(sentry, "%sonly-clr",(doneopts?",":"="));
1586  //doneopts = true; // uncomment if more opts are added
1587  }
1588  }
1589  }
1590 #endif
1591 
1592  if (p->options.no_netdb_exchange)
1593  storeAppendPrintf(sentry, " no-netdb-exchange");
1594 
1595 #if USE_DELAY_POOLS
1596  if (p->options.no_delay)
1597  storeAppendPrintf(sentry, " no-delay");
1598 #endif
1599 
1600  if (p->login)
1601  storeAppendPrintf(sentry, " login=%s", p->login);
1602 
1603  if (p->mcast.ttl > 0)
1604  storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl);
1605 
1606  if (p->connect_timeout_raw > 0)
1607  storeAppendPrintf(sentry, " connect-timeout=%d", (int)p->connect_timeout_raw);
1608 
1610  storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit);
1611 
1612 #if USE_CACHE_DIGESTS
1613 
1614  if (p->digest_url)
1615  storeAppendPrintf(sentry, " digest-url=%s", p->digest_url);
1616 
1617 #endif
1618 
1619  if (p->options.allow_miss)
1620  storeAppendPrintf(sentry, " allow-miss");
1621 
1622  if (p->options.no_tproxy)
1623  storeAppendPrintf(sentry, " no-tproxy");
1624 
1625  if (p->max_conn > 0)
1626  storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
1627  if (p->standby.limit > 0)
1628  storeAppendPrintf(sentry, " standby=%d", p->standby.limit);
1629 
1630  if (p->options.originserver)
1631  storeAppendPrintf(sentry, " originserver");
1632 
1633  if (p->domain)
1634  storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
1635 
1636  if (p->connection_auth == 0)
1637  storeAppendPrintf(sentry, " connection-auth=off");
1638  else if (p->connection_auth == 1)
1639  storeAppendPrintf(sentry, " connection-auth=on");
1640  else if (p->connection_auth == 2)
1641  storeAppendPrintf(sentry, " connection-auth=auto");
1642 
1643  p->secure.dumpCfg(sentry,"tls-");
1644  storeAppendPrintf(sentry, "\n");
1645 }
1646 
1647 static void
1648 dump_peers(StoreEntry * sentry, CachePeer * peers)
1649 {
1650  char ntoabuf[MAX_IPSTRLEN];
1651  int i;
1652 
1653  if (peers == NULL)
1654  storeAppendPrintf(sentry, "There are no neighbors installed.\n");
1655 
1656  for (CachePeer *e = peers; e; e = e->next) {
1657  assert(e->host != NULL);
1658  storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
1659  neighborTypeStr(e),
1660  e->name);
1661  storeAppendPrintf(sentry, "Host : %s/%d/%d\n",
1662  e->host,
1663  e->http_port,
1664  e->icp.port);
1665  storeAppendPrintf(sentry, "Flags :");
1666  dump_peer_options(sentry, e);
1667 
1668  for (i = 0; i < e->n_addresses; ++i) {
1669  storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
1670  e->addresses[i].toStr(ntoabuf,MAX_IPSTRLEN) );
1671  }
1672 
1673  storeAppendPrintf(sentry, "Status : %s\n",
1674  neighborUp(e) ? "Up" : "Down");
1675  storeAppendPrintf(sentry, "FETCHES : %d\n", e->stats.fetches);
1676  storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
1677  storeAppendPrintf(sentry, "AVG RTT : %d msec\n", e->stats.rtt);
1678 
1679  if (!e->options.no_query) {
1680  storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
1681  (int) (squid_curtime - e->stats.last_query));
1682 
1683  if (e->stats.last_reply > 0)
1684  storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
1685  (int) (squid_curtime - e->stats.last_reply));
1686  else
1687  storeAppendPrintf(sentry, "LAST REPLY : none received\n");
1688 
1689  storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
1690 
1691  storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
1692  e->stats.pings_acked,
1693  Math::intPercent(e->stats.pings_acked, e->stats.pings_sent));
1694  }
1695 
1696  storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked));
1697 
1698  if (!e->options.no_query) {
1699  storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
1700 #if USE_HTCP
1701 
1702  if (e->options.htcp) {
1703  storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
1704  e->htcp.counts[0],
1705  Math::intPercent(e->htcp.counts[0], e->stats.pings_acked));
1706  storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
1707  e->htcp.counts[1],
1708  Math::intPercent(e->htcp.counts[1], e->stats.pings_acked));
1709  } else {
1710 #endif
1711 
1712  for (auto op : WholeEnum<icp_opcode>()) {
1713  if (e->icp.counts[op] == 0)
1714  continue;
1715 
1716  storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n",
1717  icp_opcode_str[op],
1718  e->icp.counts[op],
1719  Math::intPercent(e->icp.counts[op], e->stats.pings_acked));
1720  }
1721 
1722 #if USE_HTCP
1723 
1724  }
1725 
1726 #endif
1727 
1728  }
1729 
1730  if (e->stats.last_connect_failure) {
1731  storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
1732  Time::FormatHttpd(e->stats.last_connect_failure));
1733  }
1734 
1735  storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1736  }
1737 }
1738 
1739 #if USE_HTCP
1740 void
1741 neighborsHtcpReply(const cache_key * key, HtcpReplyData * htcp, const Ip::Address &from)
1742 {
1744  MemObject *mem = NULL;
1745  CachePeer *p;
1746  peer_t ntype = PEER_NONE;
1747  debugs(15, 6, "neighborsHtcpReply: " <<
1748  (htcp->hit ? "HIT" : "MISS") << " " <<
1749  storeKeyText(key) );
1750 
1751  if (NULL != e)
1752  mem = e->mem_obj;
1753 
1754  if ((p = whichPeer(from)))
1755  neighborAliveHtcp(p, mem, htcp);
1756 
1757  /* Does the entry exist? */
1758  if (NULL == e) {
1759  debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found");
1761  return;
1762  }
1763 
1764  /* check if someone is already fetching it */
1765  if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
1766  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1768  return;
1769  }
1770 
1771  if (mem == NULL) {
1772  debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key));
1774  return;
1775  }
1776 
1777  if (e->ping_status != PING_WAITING) {
1778  debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING");
1780  return;
1781  }
1782 
1783  if (!e->locked()) {
1784  // TODO: many entries are unlocked; why is this reported at level 1?
1785  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1787  return;
1788  }
1789 
1790  if (!mem->ircb_data) {
1791  debugs(12, DBG_IMPORTANT, "ERROR: Squid BUG: missing HTCP callback data for " << *e);
1793  return;
1794  }
1795 
1796  if (p) {
1797  ntype = neighborType(p, mem->request->url);
1798  neighborUpdateRtt(p, mem);
1799  }
1800 
1801  if (ignoreMulticastReply(p, mem->ircb_data)) {
1803  return;
1804  }
1805 
1806  debugs(15, 3, "neighborsHtcpReply: e = " << e);
1807  // TODO: Refactor (ping_reply_callback,ircb_data) to add CodeContext.
1808  mem->ping_reply_callback(p, ntype, AnyP::PROTO_HTCP, htcp, mem->ircb_data);
1809 }
1810 
1811 /*
1812  * Send HTCP CLR messages to all peers configured to receive them.
1813  */
1814 void
1816 {
1817  CachePeer *p;
1818  char buf[128];
1819 
1820  for (p = Config.peers; p; p = p->next) {
1821  if (!p->options.htcp) {
1822  continue;
1823  }
1824  if (p->options.htcp_no_clr) {
1825  continue;
1826  }
1827  if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
1828  continue;
1829  }
1830  debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.toUrl(buf, 128));
1831  htcpClear(e, req, method, p, reason);
1832  }
1833 }
1834 
1835 #endif
1836 
bool waitingForClose
a conn must close before we open a standby conn
Definition: CachePeer.h:184
bool usable
Definition: PeerDigest.h:89
bool proxy_only
Definition: CachePeer.h:82
int testing_now
Definition: CachePeer.h:154
struct SquidConfig::@96 Timeout
bool no_query
Definition: CachePeer.h:83
Ip::Address addresses[10]
Definition: CachePeer.h:150
char method[16]
Definition: tcp-banger2.c:115
int eventFind(EVH *func, void *arg)
Definition: event.cc:153
bool htcp_no_clr
Definition: CachePeer.h:94
static void neighborAlive(CachePeer *, const MemObject *, const icp_common_t *)
Definition: neighbors.cc:890
int connection_auth
0 - off, 1 - on, 2 - auto
Definition: CachePeer.h:195
@ PEER_MULTICAST
Definition: enums.h:31
bool background_ping
Definition: CachePeer.h:84
double version
Definition: CachePeer.h:71
PeerDigest * digest
Definition: CachePeer.h:142
CachePeer * peerFindByName(const char *name)
Definition: neighbors.cc:1132
const cache_key * storeKeyPublicByRequest(HttpRequest *request, const KeyScope keyScope)
#define DBG_CRITICAL
Definition: Stream.h:40
int icp_query_max
Definition: SquidConfig.h:125
struct SquidConfig::@97 Port
@ LOOKUP_NONE
Definition: lookup_t.h:13
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
Cbc * valid() const
was set and is valid
Definition: CbcPointer.h:41
bool needed
Definition: PeerDigest.h:88
void peerConnectFailed(CachePeer *p)
Definition: neighbors.cc:1298
acl_access * access
Definition: CachePeer.h:79
int intPercent(const int a, const int b)
Definition: SquidMath.cc:13
Definition: Uri.h:31
HttpRequest * request
Ip::Address in_addr
Definition: CachePeer.h:43
static std::ostream & Extra(std::ostream &os)
prefixes each grouped debugs() line after the first one in the group
Definition: Stream.h:117
#define LOCAL_ARRAY(type, name, size)
Definition: squid.h:75
unsigned char cache_key
Store key.
Definition: forward.h:29
time_t last_connect_failure
Definition: CachePeer.h:56
AnyP::PortCfgPointer HttpPortList
list of Squid http(s)_port configured
Definition: PortCfg.cc:22
void eventDelete(EVH *func, void *arg)
Definition: event.cc:129
CachePeer * getDefaultParent(PeerSelector *ps)
Definition: neighbors.cc:474
int neighborsUdpPing(HttpRequest *request, StoreEntry *entry, IRCB *callback, PeerSelector *ps, int *exprep, int *timeout)
Definition: neighbors.cc:595
peer_t type
Definition: CachePeer.h:41
int icp_query_min
Definition: SquidConfig.h:126
struct CachePeer::@30 options
int n_recv
Definition: PingData.h:39
MemObject * mem_obj
Definition: Store.h:219
PconnPool * pool
idle connection pool for this peer
Definition: CachePeer.h:181
#define MCAST_COUNT_RATE
Definition: neighbors.cc:49
const char * url() const
Definition: store.cc:1544
CacheDigest * cd
Definition: PeerDigest.h:83
unsigned short icp
Definition: SquidConfig.h:139
struct timeval start_ping
Definition: MemObject.h:190
virtual void dumpCfg(Packable *, const char *pfx) const
output squid.conf syntax with 'pfx' prefix on parameters for the stored settings
Definition: PeerOptions.cc:105
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:830
static void peerProbeConnect(CachePeer *, const bool reprobeIfBusy=false)
Definition: neighbors.cc:1335
ping_data ping
char * login
Definition: CachePeer.h:174
#define PEER_ALIVE
Definition: defines.h:86
HttpReplyPointer reply
bool requested
Definition: PeerDigest.h:90
Comm::ConnectionPointer icpOutgoingConn
Definition: icp_v2.cc:100
size_t size() const noexcept
all cached IPs
Definition: ipcache.h:62
@ PING_WAITING
Sent ICP queries to peers and still awaiting responses.
Definition: enums.h:43
struct CachePeer::@29 htcp
void netdbExchangeStart(void *data)
Definition: net_db.cc:1292
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:148
struct CachePeer::@35 standby
optional "cache_peer standby=limit" feature
StoreEntry * entry
int isPowTen(int count)
Definition: int.cc:17
CachePeer * getNextPeer(CachePeer *p)
Definition: neighbors.cc:501
C * getRaw() const
Definition: RefCount.h:80
uint16_t flags
Definition: Store.h:230
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
Acl::Answer const & fastCheck()
Definition: Checklist.cc:332
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
bool allow_miss
Definition: CachePeer.h:103
@ OK
Definition: Flag.h:16
unsigned short port
Definition: CachePeer.h:66
void icpCreateAndSend(icp_opcode, int flags, char const *url, int reqnum, int pad, int fd, const Ip::Address &from, AccessLogEntryPointer)
Definition: icp_v2.cc:417
int connect_fail_limit
Definition: CachePeer.h:176
bool IamWorkerProcess()
whether the current process handles HTTP transactions and such
Definition: stub_tools.cc:47
char * toUrl(char *buf, unsigned int len) const
Definition: Address.cc:874
bool no_tproxy
Definition: CachePeer.h:118
int netdbHostRtt(const char *host)
Definition: net_db.cc:1055
void CallBack(const CodeContext::Pointer &callbackContext, Fun &&callback)
Definition: CodeContext.h:112
int matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
Definition: Uri.cc:736
int limit
the limit itself
Definition: CachePeer.h:183
static OBJH neighborDumpNonPeers
Definition: neighbors.cc:72
time_t connectTimeout() const
Definition: CachePeer.cc:51
#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:116
int hit
Definition: htcp.h:29
char * name
Definition: CachePeer.h:39
void htcpClear(StoreEntry *e, HttpRequest *req, const HttpRequestMethod &, CachePeer *p, htcp_clr_reason reason)
Definition: htcp.cc:1565
static int port
Definition: ldap_backend.cc:70
int stat5minClientRequests(void)
Definition: stat.cc:1717
void setHost(const char *)
set the hostname note for this connection
Definition: ConnOpener.cc:100
A const & max(A const &lhs, A const &rhs)
@ LOOKUP_MISS
Definition: lookup_t.h:15
int tvSubMsec(struct timeval t1, struct timeval t2)
Definition: gadgets.cc:51
bool roundrobin
Definition: CachePeer.h:87
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:792
void peerDigestNeeded(PeerDigest *pd)
Definition: peer_digest.cc:176
const char * FormatHttpd(time_t)
Definition: gadgets.cc:116
struct CachePeer::@31 mcast
void IRCB(CachePeer *, peer_t, AnyP::ProtocolType, void *, void *data)
Definition: typedefs.h:22
bool empty() const noexcept
whether we cached no IPs at all
Definition: ipcache.h:61
static CNCB peerProbeConnectDone
Definition: neighbors.cc:62
void getOutgoingAddress(HttpRequest *request, const Comm::ConnectionPointer &conn)
Definition: FwdState.cc:1524
#define ICP_FLAG_SRC_RTT
Definition: defines.h:41
char * domain
Forced domain.
Definition: CachePeer.h:187
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:25
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:47
int weight
Definition: CachePeer.h:125
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:78
#define MAX_URL
Definition: defines.h:78
ProtocolType
Definition: ProtocolType.h:23
void neighborsHtcpReply(const cache_key *key, HtcpReplyData *htcp, const Ip::Address &from)
Definition: neighbors.cc:1741
@ ICP_MISS_NOFETCH
Definition: icp_opcode.h:36
#define PEER_MAX_ADDRESSES
Definition: defines.h:81
static CachePeer * first_ping
Definition: neighbors.cc:78
static void peerConnectFailedSilent(CachePeer *p)
Definition: neighbors.cc:1279
struct CachePeer::@31::@37 flags
static void peerCountMcastPeersCreateAndSend(CachePeer *p)
initiates an ICP transaction to a multicast peer
Definition: neighbors.cc:1408
static void peerCountMcastPeersDone(void *data)
Definition: neighbors.cc:1454
static void neighborRemove(CachePeer *)
Definition: neighbors.cc:513
time_t last_reply
Definition: CachePeer.h:55
bool userhash
Definition: CachePeer.h:114
peer_t
Definition: enums.h:27
unsigned char opcode
Definition: ICP.h:38
void peerConnectSucceded(CachePeer *p)
Definition: neighbors.cc:1305
struct timeval current_time
the current UNIX time in timeval {seconds, microseconds} format
Definition: gadgets.cc:17
bool no_digest
Definition: CachePeer.h:85
void OBJH(StoreEntry *)
Definition: forward.h:44
#define NULL
Definition: types.h:166
void dump_peer_options(StoreEntry *sentry, CachePeer *p)
Definition: neighbors.cc:1519
PeerSelector * ircb_data
Definition: MemObject.h:192
time_t deadPeer
Definition: SquidConfig.h:122
static void neighborIgnoreNonPeer(const Ip::Address &, icp_opcode)
Definition: neighbors.cc:951
@ 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:95
int n_addresses
Definition: CachePeer.h:151
void abort()
Definition: store.cc:1052
bool no_netdb_exchange
Definition: CachePeer.h:99
void count(int uses)
@ HTCP_CLR_PURGE
Definition: enums.h:242
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:1011
void peerClearRR()
Definition: neighbors.cc:447
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1891
unsigned short port() const
Definition: Address.cc:778
double avg_n_members
Definition: CachePeer.h:129
#define EBIT_TEST(flag, bit)
Definition: defines.h:69
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:599
struct CachePeer::@28 stats
CbcPointer< PeerPoolMgr > mgr
pool manager
Definition: CachePeer.h:182
ping_status_t ping_status
Definition: Store.h:240
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:131
time_t backgroundPingRate
Definition: SquidConfig.h:106
void debug_trap(const char *message)
Definition: tools.cc:455
int unlock(const char *context)
Definition: store.cc:444
CachePeer * getFirstPeer(void)
Definition: neighbors.cc:507
AccessLogEntry::Pointer al
info for the future access.log entry
struct CachePeer::icp_ icp
@ PEER_NONE
Definition: enums.h:28
bool default_parent
Definition: CachePeer.h:86
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
Definition: CommCalls.h:342
bool closest_only
Definition: CachePeer.h:90
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:19
struct PeerDigest::@87 flags
static OBJH neighborDumpPeers
Definition: neighbors.cc:71
SSL Connection
Definition: Session.h:45
static CachePeer * non_peers
Definition: neighbors.cc:948
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:161
void neighborsHtcpClear(StoreEntry *e, HttpRequest *req, const HttpRequestMethod &method, htcp_clr_reason reason)
Definition: neighbors.cc:1815
bool no_delay
Definition: CachePeer.h:101
encapsulates DNS lookup results
Definition: LookupDetails.h:21
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
CachePeer * neighborsDigestSelect(PeerSelector *ps)
Definition: neighbors.cc:805
@ 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
static void peerAlive(CachePeer *p)
Definition: neighbors.cc:459
time_t squid_curtime
Definition: stub_libtime.cc:20
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:734
int Squid_MaxFD
static bool peerProbeIsBusy(const CachePeer *p)
whether new TCP probes are currently banned
Definition: neighbors.cc:1319
Comm::ConnectionPointer icpIncomingConn
Definition: icp_v2.cc:98
const char * lookup_t_str[]
static void peerRefreshDNS(void *)
Definition: neighbors.cc:1258
void peerNoteDigestLookup(HttpRequest *request, CachePeer *p, lookup_t lookup)
Definition: neighbors.cc:872
bool carp
Definition: CachePeer.h:104
int n_times_counted
Definition: CachePeer.h:130
Flag
Definition: Flag.h:15
static void peerClearRRLoop(void *data)
Definition: neighbors.cc:418
bool mcast_responder
Definition: CachePeer.h:89
@ ICP_QUERY
Definition: icp_opcode.h:16
static void neighborsRegisterWithCacheManager()
Definition: neighbors.cc:540
@ 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:1195
unsigned char version
Definition: ICP.h:40
int pings_sent
Definition: CachePeer.h:46
NeighborTypeDomainList * next
double doubleAverage(const double, const double, int, const int)
Definition: SquidMath.cc:31
int tcp_up
Definition: CachePeer.h:146
#define PEER_DEAD
Definition: defines.h:85
time_t last_query
Definition: CachePeer.h:54
char * host
Definition: CachePeer.h:40
bool allowed() const
Definition: Acl.h:149
int htcpQuery(StoreEntry *e, HttpRequest *req, CachePeer *p)
Definition: htcp.cc:1516
bool mcast_siblings
Definition: CachePeer.h:120
bool htcp_oldsquid
Definition: CachePeer.h:93
StoreEntry * findCallbackXXX(const cache_key *)
Definition: Controller.cc:400
@ LOOKUP_HIT
Definition: lookup_t.h:14
int max_conn
Definition: CachePeer.h:177
int mcastSetTtl(int fd, int mcast_ttl)
Definition: multicast.cc:20
struct SquidConfig::@110 onoff
char * url
Definition: tcp-banger2.c:114
const char * getMyHostname(void)
Definition: tools.cc:464
time_t connect_timeout_raw
connect_timeout; use connectTimeout() instead!
Definition: CachePeer.h:175
int rtt
Definition: CachePeer.h:49
int mcast_icp_query
Definition: SquidConfig.h:127
static HttpRequest * FromUrlXXX(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:529
#define Important(id)
Definition: Messages.h:91
int rr_count
Definition: CachePeer.h:152
bool contains(const cache_key *key) const
Definition: CacheDigest.cc:93
static IRCB peerCountHandleIcpReply
Definition: neighbors.cc:68
#define DBG_IMPORTANT
Definition: Stream.h:41
const char * storeKeyText(const cache_key *key)
int logged_state
so we can print dead/revived msgs
Definition: CachePeer.h:58
int neighborUp(const CachePeer *p)
Definition: neighbors.cc:1163
const char * neighborTypeStr(const CachePeer *p)
Definition: neighbors.cc:81
static void neighborAliveHtcp(CachePeer *, const MemObject *, const HtcpReplyData *)
Definition: neighbors.cc:927
@ ICP_END
Definition: icp_opcode.h:39
bool htcp_only_clr
Definition: CachePeer.h:96
CachePeer * peers
Definition: SquidConfig.h:252
lookup_t peerDigestLookup(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:759
static void peerCountMcastPeersAbort(PeerSelector *)
Definition: neighbors.cc:1466
static int ignoreMulticastReply(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:989
time_t last_connect_probe
Definition: CachePeer.h:57
double version
Definition: htcp.h:32
@ ICP_DENIED
Definition: icp_opcode.h:37
@ PROTO_HTCP
Definition: ProtocolType.h:35
int ignored_replies
Definition: CachePeer.h:50
#define RTT_BACKGROUND_AV_FACTOR
Definition: defines.h:83
@ ENTRY_DISPATCHED
Definition: enums.h:101
void CallContextCreator(Fun &&creator)
Definition: CodeContext.h:144
void eventAddIsh(const char *name, EVH *func, void *arg, double delta_ish, int weight)
Definition: event.cc:114
int locked() const
Definition: Store.h:144
bool weighted_roundrobin
Definition: CachePeer.h:88
CachePeer * next
Definition: CachePeer.h:153
#define ICP_VERSION_2
Definition: defines.h:44
static int NLateReplies
Definition: neighbors.cc:77
CachePeer * peerFindByNameAndPort(const char *name, unsigned short port)
Definition: neighbors.cc:1145
IRCB * ping_reply_callback
Definition: MemObject.h:191
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:554
@ METHOD_GET
Definition: MethodType.h:25
static void Checkpoint(const Pointer &mgr, const char *reason)
Definition: PeerPoolMgr.cc:241
static void peerCountMcastPeersStart(void *data)
Definition: neighbors.cc:1397
static void neighborCountIgnored(CachePeer *)
Definition: neighbors.cc:938
Security::PeerOptions secure
security settings for peer connection
Definition: CachePeer.h:190
int counts[2]
Definition: CachePeer.h:72
void host(const char *src)
Definition: Uri.cc:99
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:1383
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
int counts[ICP_END+1]
Definition: CachePeer.h:65
htcp_clr_reason
Definition: enums.h:241
#define RTT_AV_FACTOR
Definition: defines.h:82
void * peerCountMcastPeerXXX
a hack to help peerCountMcastPeersStart()
static void neighborUpdateRtt(CachePeer *p, MemObject *mem)
Definition: neighbors.cc:902
void peerClearRRStart(void)
Definition: neighbors.cc:430
HttpRequestPointer request
Definition: MemObject.h:188
unsigned short http_port
Definition: CachePeer.h:77
int icpSetCacheKey(const cache_key *key)
Definition: icp_v2.cc:861
int conn_open
current opened connections
Definition: CachePeer.h:59
int n_replies_expected
Definition: CachePeer.h:131
const char * getMD5Text() const
Definition: store.cc:204
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
int basetime
Definition: CachePeer.h:126
bool originserver
Definition: CachePeer.h:117
@ PROTO_ICP
Definition: ProtocolType.h:33
unsigned short htcp
Definition: SquidConfig.h:142
static void dump_peers(StoreEntry *sentry, CachePeer *peers)
Definition: neighbors.cc:1648
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:53
class SquidConfig Config
Definition: SquidConfig.cc:12
int unsigned int
Definition: stub_fd.cc:19
static void Start(const Pointer &job)
Definition: AsyncJob.cc:24
char * digest_url
Definition: CachePeer.h:143
IpsSelector< IpsIterator > goodAndBad() const
all IPs
Definition: ipcache.h:249
Controller & Root()
safely access controller singleton
Definition: Controller.cc:934

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors