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 
417 static void
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 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 
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, "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, "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 
796 #endif
797 
798  return LOOKUP_NONE;
799 }
800 
801 /* select best CachePeer based on cache digests */
802 CachePeer *
804 {
805  CachePeer *best_p = NULL;
806 #if USE_CACHE_DIGESTS
807  assert(ps);
808  HttpRequest *request = ps->request;
809 
810  int best_rtt = 0;
811  int choice_count = 0;
812  int ichoice_count = 0;
813  CachePeer *p;
814  int p_rtt;
815  int i;
816 
817  if (!request->flags.hierarchical)
818  return NULL;
819 
821 
822  for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) {
823  lookup_t lookup;
824 
825  if (!p)
826  p = Config.peers;
827 
828  if (i == 1)
829  first_ping = p;
830 
831  lookup = peerDigestLookup(p, ps);
832 
833  if (lookup == LOOKUP_NONE)
834  continue;
835 
836  ++choice_count;
837 
838  if (lookup == LOOKUP_MISS)
839  continue;
840 
841  p_rtt = netdbHostRtt(p->host);
842 
843  debugs(15, 5, "neighborsDigestSelect: peer " << p->host << " rtt: " << p_rtt);
844 
845  /* is this CachePeer better than others in terms of rtt ? */
846  if (!best_p || (p_rtt && p_rtt < best_rtt)) {
847  best_p = p;
848  best_rtt = p_rtt;
849 
850  if (p_rtt) /* informative choice (aka educated guess) */
851  ++ichoice_count;
852 
853  debugs(15, 4, "neighborsDigestSelect: peer " << p->host << " leads with rtt " << best_rtt);
854  }
855  }
856 
857  debugs(15, 4, "neighborsDigestSelect: choices: " << choice_count << " (" << ichoice_count << ")");
859  best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE));
860  request->hier.n_choices = choice_count;
861  request->hier.n_ichoices = ichoice_count;
862 #endif
863 
864  return best_p;
865 }
866 
867 void
869 {
870 #if USE_CACHE_DIGESTS
871  if (p)
872  strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host)-1);
873  else
874  *request->hier.cd_host = '\0';
875 
876  request->hier.cd_lookup = lookup;
877  debugs(15, 4, "peerNoteDigestLookup: peer " << (p? p->host : "<none>") << ", lookup: " << lookup_t_str[lookup] );
878 #endif
879 }
880 
881 static void
882 neighborAlive(CachePeer * p, const MemObject *, const icp_common_t * header)
883 {
884  peerAlive(p);
885  ++ p->stats.pings_acked;
886 
887  if ((icp_opcode) header->opcode <= ICP_END)
888  ++ p->icp.counts[header->opcode];
889 
890  p->icp.version = (int) header->version;
891 }
892 
893 static void
895 {
896  int rtt, rtt_av_factor;
897 
898  if (!mem)
899  return;
900 
901  if (!mem->start_ping.tv_sec)
902  return;
903 
904  rtt = tvSubMsec(mem->start_ping, current_time);
905 
906  if (rtt < 1 || rtt > 10000)
907  return;
908 
909  rtt_av_factor = RTT_AV_FACTOR;
910 
912  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
913 
914  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor);
915 }
916 
917 #if USE_HTCP
918 static void
920 {
921  peerAlive(p);
922  ++ p->stats.pings_acked;
923  ++ p->htcp.counts[htcp->hit ? 1 : 0];
924  p->htcp.version = htcp->version;
925 }
926 
927 #endif
928 
929 static void
931 {
932  if (p == NULL)
933  return;
934 
935  ++ p->stats.ignored_replies;
936 
937  ++NLateReplies;
938 }
939 
941 
942 static void
944 {
945  CachePeer *np;
946 
947  for (np = non_peers; np; np = np->next) {
948  if (np->in_addr != from)
949  continue;
950 
951  if (np->in_addr.port() != from.port())
952  continue;
953 
954  break;
955  }
956 
957  if (np == NULL) {
958  np = new CachePeer;
959  np->in_addr = from;
960  np->icp.port = from.port();
961  np->type = PEER_NONE;
962  np->host = new char[MAX_IPSTRLEN];
963  from.toStr(np->host,MAX_IPSTRLEN);
964  np->next = non_peers;
965  non_peers = np;
966  }
967 
968  ++ np->icp.counts[opcode];
969 
970  if (isPowTen(++np->stats.ignored_replies))
971  debugs(15, DBG_IMPORTANT, "WARNING: Ignored " << np->stats.ignored_replies << " replies from non-peer " << np->host);
972 }
973 
974 /* ignoreMulticastReply
975  *
976  * * We want to ignore replies from multicast peers if the
977  * * cache_host_domain rules would normally prevent the CachePeer
978  * * from being used
979  */
980 static int
982 {
983  if (p == NULL)
984  return 0;
985 
986  if (!p->options.mcast_responder)
987  return 0;
988 
989  if (peerHTTPOkay(p, ps))
990  return 0;
991 
992  return 1;
993 }
994 
1002 void
1003 neighborsUdpAck(const cache_key * key, icp_common_t * header, const Ip::Address &from)
1004 {
1005  CachePeer *p = NULL;
1006  StoreEntry *entry;
1007  MemObject *mem = NULL;
1008  peer_t ntype = PEER_NONE;
1009  icp_opcode opcode = (icp_opcode) header->opcode;
1010 
1011  debugs(15, 6, "neighborsUdpAck: opcode " << opcode << " '" << storeKeyText(key) << "'");
1012 
1013  if ((entry = Store::Root().findCallbackXXX(key)))
1014  mem = entry->mem_obj;
1015 
1016  if ((p = whichPeer(from)))
1017  neighborAlive(p, mem, header);
1018 
1019  if (opcode > ICP_END)
1020  return;
1021 
1022  const char *opcode_d = icp_opcode_str[opcode];
1023 
1024  if (p)
1025  neighborUpdateRtt(p, mem);
1026 
1027  /* Does the entry exist? */
1028  if (NULL == entry) {
1029  debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found");
1031  return;
1032  }
1033 
1034  /* check if someone is already fetching it */
1035  if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
1036  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1038  return;
1039  }
1040 
1041  if (mem == NULL) {
1042  debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key));
1044  return;
1045  }
1046 
1047  if (entry->ping_status != PING_WAITING) {
1048  debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key));
1050  return;
1051  }
1052 
1053  if (!entry->locked()) {
1054  // TODO: many entries are unlocked; why is this reported at level 1?
1055  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1057  return;
1058  }
1059 
1060  if (!mem->ircb_data) {
1061  debugs(12, DBG_IMPORTANT, "BUG: missing ICP callback data for " << *entry);
1063  return;
1064  }
1065 
1066  debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " ");
1067 
1068  if (p) {
1069  ntype = neighborType(p, mem->request->url);
1070  }
1071 
1072  if (ignoreMulticastReply(p, mem->ircb_data)) {
1074  } else if (opcode == ICP_MISS) {
1075  if (p == NULL) {
1076  neighborIgnoreNonPeer(from, opcode);
1077  } else {
1078  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1079  }
1080  } else if (opcode == ICP_HIT) {
1081  if (p == NULL) {
1082  neighborIgnoreNonPeer(from, opcode);
1083  } else {
1084  header->opcode = ICP_HIT;
1085  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1086  }
1087  } else if (opcode == ICP_DECHO) {
1088  if (p == NULL) {
1089  neighborIgnoreNonPeer(from, opcode);
1090  } else if (ntype == PEER_SIBLING) {
1091  debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n");
1092  debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n");
1093  } else {
1094  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1095  }
1096  } else if (opcode == ICP_SECHO) {
1097  if (p) {
1098  debugs(15, DBG_IMPORTANT, "Ignoring SECHO from neighbor " << p->host);
1100  } else {
1101  debugs(15, DBG_IMPORTANT, "Unsolicited SECHO from " << from);
1102  }
1103  } else if (opcode == ICP_DENIED) {
1104  if (p == NULL) {
1105  neighborIgnoreNonPeer(from, opcode);
1106  } else if (p->stats.pings_acked > 100) {
1107  if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) {
1108  debugs(15, DBG_CRITICAL, "95%% of replies from '" << p->host << "' are UDP_DENIED");
1109  debugs(15, DBG_CRITICAL, "Disabling '" << p->host << "', please check your configuration.");
1110  neighborRemove(p);
1111  p = NULL;
1112  } else {
1114  }
1115  }
1116  } else if (opcode == ICP_MISS_NOFETCH) {
1117  mem->ping_reply_callback(p, ntype, AnyP::PROTO_ICP, header, mem->ircb_data);
1118  } else {
1119  debugs(15, DBG_CRITICAL, "neighborsUdpAck: Unexpected ICP reply: " << opcode_d);
1120  }
1121 }
1122 
1123 CachePeer *
1124 peerFindByName(const char *name)
1125 {
1126  CachePeer *p = NULL;
1127 
1128  for (p = Config.peers; p; p = p->next) {
1129  if (!strcasecmp(name, p->name))
1130  break;
1131  }
1132 
1133  return p;
1134 }
1135 
1136 CachePeer *
1137 peerFindByNameAndPort(const char *name, unsigned short port)
1138 {
1139  CachePeer *p = NULL;
1140 
1141  for (p = Config.peers; p; p = p->next) {
1142  if (strcasecmp(name, p->name))
1143  continue;
1144 
1145  if (port != p->http_port)
1146  continue;
1147 
1148  break;
1149  }
1150 
1151  return p;
1152 }
1153 
1154 int
1156 {
1157  if (!p->tcp_up) {
1158  peerProbeConnect(const_cast<CachePeer*>(p));
1159  return 0;
1160  }
1161 
1162  /*
1163  * The CachePeer can not be UP if we don't have any IP addresses
1164  * for it.
1165  */
1166  if (0 == p->n_addresses) {
1167  debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")");
1168  return 0;
1169  }
1170 
1171  if (p->options.no_query) {
1172  debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")");
1173  return 1;
1174  }
1175 
1176  if (p->stats.probe_start != 0 &&
1178  debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")");
1179  return 0;
1180  }
1181 
1182  debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")");
1183  return 1;
1184 }
1185 
1186 time_t
1187 positiveTimeout(const time_t timeout)
1188 {
1189  return max(static_cast<time_t>(1), timeout);
1190 }
1191 
1192 static void
1194 {
1195  // TODO: connections to no-longer valid IP addresses should be
1196  // closed when we can detect such IP addresses.
1197 
1198  CachePeer *p = (CachePeer *)data;
1199 
1200  if (p->n_addresses == 0) {
1201  debugs(15, DBG_IMPORTANT, "Configuring " << neighborTypeStr(p) << " " << p->host << "/" << p->http_port << "/" << p->icp.port);
1202 
1203  if (p->type == PEER_MULTICAST)
1204  debugs(15, DBG_IMPORTANT, " Multicast TTL = " << p->mcast.ttl);
1205  }
1206 
1207  p->n_addresses = 0;
1208 
1209  if (ia == NULL) {
1210  debugs(0, DBG_CRITICAL, "WARNING: DNS lookup for '" << p->host << "' failed!");
1211  return;
1212  }
1213 
1214  if (ia->empty()) {
1215  debugs(0, DBG_CRITICAL, "WARNING: No IP address found for '" << p->host << "'!");
1216  return;
1217  }
1218 
1219  for (const auto &ip: ia->goodAndBad()) { // TODO: Consider using just good().
1220  if (p->n_addresses < PEER_MAX_ADDRESSES) {
1221  const auto idx = p->n_addresses++;
1222  p->addresses[idx] = ip;
1223  debugs(15, 2, "--> IP address #" << idx << ": " << p->addresses[idx]);
1224  } else {
1225  debugs(15, 3, "ignoring remaining " << (ia->size() - p->n_addresses) << " ips");
1226  break;
1227  }
1228  }
1229 
1230  p->in_addr.setEmpty();
1231  p->in_addr = p->addresses[0];
1232  p->in_addr.port(p->icp.port);
1233 
1234  peerProbeConnect(p, true); // detect any died or revived peers ASAP
1235 
1236  if (p->type == PEER_MULTICAST)
1238 
1239 #if USE_ICMP
1240  if (p->type != PEER_MULTICAST && IamWorkerProcess())
1241  if (!p->options.no_netdb_exchange)
1242  eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
1243 #endif
1244 
1245  if (p->standby.mgr.valid())
1246  PeerPoolMgr::Checkpoint(p->standby.mgr, "resolved peer");
1247 }
1248 
1249 static void
1251 {
1252  CachePeer *p = NULL;
1253 
1256 
1257  if (!data && 0 == stat5minClientRequests()) {
1258  /* no recent client traffic, wait a bit */
1259  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1);
1260  return;
1261  }
1262 
1263  for (p = Config.peers; p; p = p->next)
1265 
1266  /* Reconfigure the peers every hour */
1267  eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1);
1268 }
1269 
1270 static void
1272 {
1274 
1275  if (!p->tcp_up) {
1276  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port <<
1277  " dead");
1278  return;
1279  }
1280 
1281  -- p->tcp_up;
1282 
1283  if (!p->tcp_up) {
1284  debugs(15, DBG_IMPORTANT, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name);
1286  }
1287 }
1288 
1289 void
1291 {
1292  debugs(15, DBG_IMPORTANT, "TCP connection to " << p->host << "/" << p->http_port << " failed");
1294 }
1295 
1296 void
1298 {
1299  if (!p->tcp_up) {
1300  debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeeded");
1301  p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly.
1302  peerAlive(p);
1303  if (!p->n_addresses)
1305  } else
1306  p->tcp_up = p->connect_fail_limit;
1307 }
1308 
1310 static bool
1312 {
1313  if (p->testing_now > 0) {
1314  debugs(15, 8, "yes, probing " << p);
1315  return true;
1316  }
1317  if (squid_curtime - p->stats.last_connect_probe == 0) {
1318  debugs(15, 8, "yes, just probed " << p);
1319  return true;
1320  }
1321  return false;
1322 }
1323 /*
1324 * peerProbeConnect will be called on dead peers by neighborUp
1325 */
1326 static void
1327 peerProbeConnect(CachePeer *p, const bool reprobeIfBusy)
1328 {
1329  if (peerProbeIsBusy(p)) {
1330  p->reprobe = reprobeIfBusy;
1331  return;
1332  }
1333  p->reprobe = false;
1334 
1335  const auto ctimeout = p->connectTimeout();
1336  /* for each IP address of this CachePeer. find one that we can connect to and probe it. */
1337  for (int i = 0; i < p->n_addresses; ++i) {
1339  conn->remote = p->addresses[i];
1340  conn->remote.port(p->http_port);
1341  conn->setPeer(p);
1343 
1344  ++ p->testing_now;
1345 
1346  AsyncCall::Pointer call = commCbCall(15,3, "peerProbeConnectDone", CommConnectCbPtrFun(peerProbeConnectDone, p));
1347  Comm::ConnOpener *cs = new Comm::ConnOpener(conn, call, ctimeout);
1348  cs->setHost(p->host);
1349  AsyncJob::Start(cs);
1350  }
1351 
1353 }
1354 
1355 static void
1357 {
1358  CachePeer *p = (CachePeer*)data;
1359 
1360  if (status == Comm::OK) {
1362  } else {
1364  }
1365 
1366  -- p->testing_now;
1367  conn->close();
1368  // TODO: log this traffic.
1369 
1370  if (p->reprobe)
1371  peerProbeConnect(p);
1372 }
1373 
1374 static void
1376 {
1377  if (p->mcast.flags.count_event_pending)
1378  return;
1379 
1380  eventAdd("peerCountMcastPeersStart",
1382  p,
1383  (double) when, 1);
1384 
1385  p->mcast.flags.count_event_pending = true;
1386 }
1387 
1388 static void
1390 {
1391  const auto peer = static_cast<CachePeer*>(data);
1392  CallContextCreator([peer] {
1394  });
1396 }
1397 
1399 static void
1401 {
1402  // XXX: Do not create lots of complex fake objects (while abusing their
1403  // APIs) to pass around a few basic data points like start_ping and ping!
1404  MemObject *mem;
1405  int reqnum;
1406  // TODO: use class AnyP::Uri instead of constructing and re-parsing a string
1407  LOCAL_ARRAY(char, url, MAX_URL);
1408  assert(p->type == PEER_MULTICAST);
1409  p->mcast.flags.count_event_pending = false;
1410  snprintf(url, MAX_URL, "http://");
1411  p->in_addr.toUrl(url+7, MAX_URL -8 );
1412  strcat(url, "/");
1414  auto *req = HttpRequest::FromUrlXXX(url, mx);
1415  assert(req != nullptr);
1416  const AccessLogEntry::Pointer ale = new AccessLogEntry;
1417  ale->request = req;
1418  CodeContext::Reset(ale);
1420  const auto psstate = new PeerSelector(nullptr);
1421  psstate->request = req;
1422  HTTPMSGLOCK(psstate->request);
1423  psstate->entry = fake;
1424  psstate->peerCountMcastPeerXXX = cbdataReference(p);
1425  psstate->ping.start = current_time;
1426  psstate->al = ale;
1427  mem = fake->mem_obj;
1428  mem->request = psstate->request;
1429  mem->start_ping = current_time;
1431  mem->ircb_data = psstate;
1433  p->mcast.id = mem->id;
1434  reqnum = icpSetCacheKey((const cache_key *)fake->key);
1435  icpCreateAndSend(ICP_QUERY, 0, url, reqnum, 0,
1436  icpOutgoingConn->fd, p->in_addr, psstate->al);
1437  fake->ping_status = PING_WAITING; // TODO: refactor to use PeerSelector::startPingWaiting()
1438  eventAdd("peerCountMcastPeersDone",
1440  psstate,
1441  Config.Timeout.mcast_icp_query / 1000.0, 1);
1442  p->mcast.flags.counting = true;
1443 }
1444 
1445 static void
1447 {
1448  const auto psstate = static_cast<PeerSelector*>(data);
1449  CallBack(psstate->al, [psstate] {
1450  peerCountMcastPeersAbort(psstate);
1451  delete psstate;
1452  });
1453 }
1454 
1457 static void
1459 {
1460  StoreEntry *fake = psstate->entry;
1461 
1463  CachePeer *p = (CachePeer *)psstate->peerCountMcastPeerXXX;
1464  p->mcast.flags.counting = false;
1466  debugs(15, DBG_IMPORTANT, "Group " << p->host << ": " << psstate->ping.n_recv <<
1467  " replies, "<< std::setw(4)<< std::setprecision(2) <<
1468  p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt);
1470  }
1471 
1473 
1474  fake->abort(); // sets ENTRY_ABORTED and initiates related cleanup
1475  fake->mem_obj->request = nullptr;
1476  fake->unlock("peerCountMcastPeersDone");
1477 }
1478 
1479 static void
1481 {
1482  const auto psstate = static_cast<PeerSelector*>(data);
1483  StoreEntry *fake = psstate->entry;
1484  assert(fake);
1485  MemObject *mem = fake->mem_obj;
1486  assert(mem);
1487  int rtt = tvSubMsec(mem->start_ping, current_time);
1488  assert(proto == AnyP::PROTO_ICP);
1489  ++ psstate->ping.n_recv;
1490  int rtt_av_factor = RTT_AV_FACTOR;
1491 
1493  rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
1494 
1495  p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1496 }
1497 
1498 static void
1500 {
1501  dump_peers(sentry, Config.peers);
1502 }
1503 
1504 static void
1506 {
1507  dump_peers(sentry, non_peers);
1508 }
1509 
1510 void
1512 {
1513  if (p->options.proxy_only)
1514  storeAppendPrintf(sentry, " proxy-only");
1515 
1516  if (p->options.no_query)
1517  storeAppendPrintf(sentry, " no-query");
1518 
1519  if (p->options.background_ping)
1520  storeAppendPrintf(sentry, " background-ping");
1521 
1522  if (p->options.no_digest)
1523  storeAppendPrintf(sentry, " no-digest");
1524 
1525  if (p->options.default_parent)
1526  storeAppendPrintf(sentry, " default");
1527 
1528  if (p->options.roundrobin)
1529  storeAppendPrintf(sentry, " round-robin");
1530 
1531  if (p->options.carp)
1532  storeAppendPrintf(sentry, " carp");
1533 
1534 #if USE_AUTH
1535  if (p->options.userhash)
1536  storeAppendPrintf(sentry, " userhash");
1537 #endif
1538 
1539  if (p->options.sourcehash)
1540  storeAppendPrintf(sentry, " sourcehash");
1541 
1543  storeAppendPrintf(sentry, " weighted-round-robin");
1544 
1545  if (p->options.mcast_responder)
1546  storeAppendPrintf(sentry, " multicast-responder");
1547 
1548 #if PEER_MULTICAST_SIBLINGS
1549  if (p->options.mcast_siblings)
1550  storeAppendPrintf(sentry, " multicast-siblings");
1551 #endif
1552 
1553  if (p->weight != 1)
1554  storeAppendPrintf(sentry, " weight=%d", p->weight);
1555 
1556  if (p->options.closest_only)
1557  storeAppendPrintf(sentry, " closest-only");
1558 
1559 #if USE_HTCP
1560  if (p->options.htcp) {
1561  storeAppendPrintf(sentry, " htcp");
1563  bool doneopts = false;
1564  if (p->options.htcp_oldsquid) {
1565  storeAppendPrintf(sentry, "oldsquid");
1566  doneopts = true;
1567  }
1568  if (p->options.htcp_no_clr) {
1569  storeAppendPrintf(sentry, "%sno-clr",(doneopts?",":"="));
1570  doneopts = true;
1571  }
1572  if (p->options.htcp_no_purge_clr) {
1573  storeAppendPrintf(sentry, "%sno-purge-clr",(doneopts?",":"="));
1574  doneopts = true;
1575  }
1576  if (p->options.htcp_only_clr) {
1577  storeAppendPrintf(sentry, "%sonly-clr",(doneopts?",":"="));
1578  //doneopts = true; // uncomment if more opts are added
1579  }
1580  }
1581  }
1582 #endif
1583 
1584  if (p->options.no_netdb_exchange)
1585  storeAppendPrintf(sentry, " no-netdb-exchange");
1586 
1587 #if USE_DELAY_POOLS
1588  if (p->options.no_delay)
1589  storeAppendPrintf(sentry, " no-delay");
1590 #endif
1591 
1592  if (p->login)
1593  storeAppendPrintf(sentry, " login=%s", p->login);
1594 
1595  if (p->mcast.ttl > 0)
1596  storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl);
1597 
1598  if (p->connect_timeout_raw > 0)
1599  storeAppendPrintf(sentry, " connect-timeout=%d", (int)p->connect_timeout_raw);
1600 
1602  storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit);
1603 
1604 #if USE_CACHE_DIGESTS
1605 
1606  if (p->digest_url)
1607  storeAppendPrintf(sentry, " digest-url=%s", p->digest_url);
1608 
1609 #endif
1610 
1611  if (p->options.allow_miss)
1612  storeAppendPrintf(sentry, " allow-miss");
1613 
1614  if (p->options.no_tproxy)
1615  storeAppendPrintf(sentry, " no-tproxy");
1616 
1617  if (p->max_conn > 0)
1618  storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
1619  if (p->standby.limit > 0)
1620  storeAppendPrintf(sentry, " standby=%d", p->standby.limit);
1621 
1622  if (p->options.originserver)
1623  storeAppendPrintf(sentry, " originserver");
1624 
1625  if (p->domain)
1626  storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
1627 
1628  if (p->connection_auth == 0)
1629  storeAppendPrintf(sentry, " connection-auth=off");
1630  else if (p->connection_auth == 1)
1631  storeAppendPrintf(sentry, " connection-auth=on");
1632  else if (p->connection_auth == 2)
1633  storeAppendPrintf(sentry, " connection-auth=auto");
1634 
1635  p->secure.dumpCfg(sentry,"tls-");
1636  storeAppendPrintf(sentry, "\n");
1637 }
1638 
1639 static void
1640 dump_peers(StoreEntry * sentry, CachePeer * peers)
1641 {
1642  char ntoabuf[MAX_IPSTRLEN];
1643  int i;
1644 
1645  if (peers == NULL)
1646  storeAppendPrintf(sentry, "There are no neighbors installed.\n");
1647 
1648  for (CachePeer *e = peers; e; e = e->next) {
1649  assert(e->host != NULL);
1650  storeAppendPrintf(sentry, "\n%-11.11s: %s\n",
1651  neighborTypeStr(e),
1652  e->name);
1653  storeAppendPrintf(sentry, "Host : %s/%d/%d\n",
1654  e->host,
1655  e->http_port,
1656  e->icp.port);
1657  storeAppendPrintf(sentry, "Flags :");
1658  dump_peer_options(sentry, e);
1659 
1660  for (i = 0; i < e->n_addresses; ++i) {
1661  storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
1662  e->addresses[i].toStr(ntoabuf,MAX_IPSTRLEN) );
1663  }
1664 
1665  storeAppendPrintf(sentry, "Status : %s\n",
1666  neighborUp(e) ? "Up" : "Down");
1667  storeAppendPrintf(sentry, "FETCHES : %d\n", e->stats.fetches);
1668  storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open);
1669  storeAppendPrintf(sentry, "AVG RTT : %d msec\n", e->stats.rtt);
1670 
1671  if (!e->options.no_query) {
1672  storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n",
1673  (int) (squid_curtime - e->stats.last_query));
1674 
1675  if (e->stats.last_reply > 0)
1676  storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n",
1677  (int) (squid_curtime - e->stats.last_reply));
1678  else
1679  storeAppendPrintf(sentry, "LAST REPLY : none received\n");
1680 
1681  storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent);
1682 
1683  storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
1684  e->stats.pings_acked,
1685  Math::intPercent(e->stats.pings_acked, e->stats.pings_sent));
1686  }
1687 
1688  storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked));
1689 
1690  if (!e->options.no_query) {
1691  storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
1692 #if USE_HTCP
1693 
1694  if (e->options.htcp) {
1695  storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
1696  e->htcp.counts[0],
1697  Math::intPercent(e->htcp.counts[0], e->stats.pings_acked));
1698  storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
1699  e->htcp.counts[1],
1700  Math::intPercent(e->htcp.counts[1], e->stats.pings_acked));
1701  } else {
1702 #endif
1703 
1704  for (auto op : WholeEnum<icp_opcode>()) {
1705  if (e->icp.counts[op] == 0)
1706  continue;
1707 
1708  storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n",
1709  icp_opcode_str[op],
1710  e->icp.counts[op],
1711  Math::intPercent(e->icp.counts[op], e->stats.pings_acked));
1712  }
1713 
1714 #if USE_HTCP
1715 
1716  }
1717 
1718 #endif
1719 
1720  }
1721 
1722  if (e->stats.last_connect_failure) {
1723  storeAppendPrintf(sentry, "Last failed connect() at: %s\n",
1724  Time::FormatHttpd(e->stats.last_connect_failure));
1725  }
1726 
1727  storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1728  }
1729 }
1730 
1731 #if USE_HTCP
1732 void
1733 neighborsHtcpReply(const cache_key * key, HtcpReplyData * htcp, const Ip::Address &from)
1734 {
1736  MemObject *mem = NULL;
1737  CachePeer *p;
1738  peer_t ntype = PEER_NONE;
1739  debugs(15, 6, "neighborsHtcpReply: " <<
1740  (htcp->hit ? "HIT" : "MISS") << " " <<
1741  storeKeyText(key) );
1742 
1743  if (NULL != e)
1744  mem = e->mem_obj;
1745 
1746  if ((p = whichPeer(from)))
1747  neighborAliveHtcp(p, mem, htcp);
1748 
1749  /* Does the entry exist? */
1750  if (NULL == e) {
1751  debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found");
1753  return;
1754  }
1755 
1756  /* check if someone is already fetching it */
1757  if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
1758  debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1760  return;
1761  }
1762 
1763  if (mem == NULL) {
1764  debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key));
1766  return;
1767  }
1768 
1769  if (e->ping_status != PING_WAITING) {
1770  debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING");
1772  return;
1773  }
1774 
1775  if (!e->locked()) {
1776  // TODO: many entries are unlocked; why is this reported at level 1?
1777  debugs(12, DBG_IMPORTANT, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1779  return;
1780  }
1781 
1782  if (!mem->ircb_data) {
1783  debugs(12, DBG_IMPORTANT, "BUG: missing HTCP callback data for " << *e);
1785  return;
1786  }
1787 
1788  if (p) {
1789  ntype = neighborType(p, mem->request->url);
1790  neighborUpdateRtt(p, mem);
1791  }
1792 
1793  if (ignoreMulticastReply(p, mem->ircb_data)) {
1795  return;
1796  }
1797 
1798  debugs(15, 3, "neighborsHtcpReply: e = " << e);
1799  // TODO: Refactor (ping_reply_callback,ircb_data) to add CodeContext.
1800  mem->ping_reply_callback(p, ntype, AnyP::PROTO_HTCP, htcp, mem->ircb_data);
1801 }
1802 
1803 /*
1804  * Send HTCP CLR messages to all peers configured to receive them.
1805  */
1806 void
1808 {
1809  CachePeer *p;
1810  char buf[128];
1811 
1812  for (p = Config.peers; p; p = p->next) {
1813  if (!p->options.htcp) {
1814  continue;
1815  }
1816  if (p->options.htcp_no_clr) {
1817  continue;
1818  }
1819  if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
1820  continue;
1821  }
1822  debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.toUrl(buf, 128));
1823  htcpClear(e, req, method, p, reason);
1824  }
1825 }
1826 
1827 #endif
1828 
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
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:155
bool htcp_no_clr
Definition: CachePeer.h:94
static void neighborAlive(CachePeer *, const MemObject *, const icp_common_t *)
Definition: neighbors.cc:882
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:1124
const cache_key * storeKeyPublicByRequest(HttpRequest *request, const KeyScope keyScope)
int icp_query_max
Definition: SquidConfig.h:124
@ 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:1290
struct CachePeer::@31 options
acl_access * access
Definition: CachePeer.h:79
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:43
static std::ostream & Extra(std::ostream &os)
prefixes each grouped debugs() line after the first one in the group
Definition: Debug.h:104
#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:21
@ initPeerMcast
neighbor multicast
void eventDelete(EVH *func, void *arg)
Definition: event.cc:131
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:125
int n_recv
Definition: PingData.h:39
MemObject * mem_obj
Definition: Store.h:213
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:1622
CacheDigest * cd
Definition: PeerDigest.h:83
unsigned short icp
Definition: SquidConfig.h:138
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:901
static void peerProbeConnect(CachePeer *, const bool reprobeIfBusy=false)
Definition: neighbors.cc:1327
ping_data ping
char * login
Definition: CachePeer.h:174
#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
Sent ICP queries to peers and still awaiting responses.
Definition: enums.h:43
int const char int
Definition: stub_libmem.cc:75
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:148
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:501
C * getRaw() const
Definition: RefCount.h:80
uint16_t flags
Definition: Store.h:224
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:412
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: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:442
int connect_fail_limit
Definition: CachePeer.h:176
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:118
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:744
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
#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:87
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:1440
#define ICP_FLAG_SRC_RTT
Definition: defines.h:73
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: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: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:118
struct CachePeer::@30 htcp
ProtocolType
Definition: ProtocolType.h:23
void neighborsHtcpReply(const cache_key *key, HtcpReplyData *htcp, const Ip::Address &from)
Definition: neighbors.cc:1733
@ 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:1271
static void peerCountMcastPeersCreateAndSend(CachePeer *p)
initiates an ICP transaction to a multicast peer
Definition: neighbors.cc:1400
static void peerCountMcastPeersDone(void *data)
Definition: neighbors.cc:1446
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:1297
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:1511
PeerSelector * ircb_data
Definition: MemObject.h:192
time_t deadPeer
Definition: SquidConfig.h:121
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:128
static void neighborIgnoreNonPeer(const Ip::Address &, icp_opcode)
Definition: neighbors.cc:943
@ 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:1124
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:1003
void peerClearRR()
Definition: neighbors.cc:447
const Acl::Answer & fastCheck()
Definition: Checklist.cc:336
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1990
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:129
#define EBIT_TEST(flag, bit)
Definition: defines.h:107
void ipcache_nbgethostbyname(const char *name, IPH *handler, void *handlerData)
Definition: ipcache.cc:598
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:157
CbcPointer< PeerPoolMgr > mgr
pool manager
Definition: CachePeer.h:182
ping_status_t ping_status
Definition: Store.h:234
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
void const char HLPCB void * data
Definition: stub_helper.cc:16
time_t backgroundPingRate
Definition: SquidConfig.h:105
void debug_trap(const char *message)
Definition: tools.cc:403
int unlock(const char *context)
Definition: store.cc:483
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
int tvSubMsec(struct timeval, struct timeval)
Definition: time.cc:37
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
static OBJH neighborDumpPeers
Definition: neighbors.cc:71
static CachePeer * non_peers
Definition: neighbors.cc:940
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:1807
bool no_delay
Definition: CachePeer.h:101
encapsulates DNS lookup results
Definition: LookupDetails.h:20
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
CachePeer * neighborsDigestSelect(PeerSelector *ps)
Definition: neighbors.cc:803
@ 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:803
int Squid_MaxFD
static bool peerProbeIsBusy(const CachePeer *p)
whether new TCP probes are currently banned
Definition: neighbors.cc:1311
struct SquidConfig::@112 onoff
Comm::ConnectionPointer icpIncomingConn
Definition: icp_v2.cc:102
const char * lookup_t_str[]
static void peerRefreshDNS(void *)
Definition: neighbors.cc:1250
void peerNoteDigestLookup(HttpRequest *request, CachePeer *p, lookup_t lookup)
Definition: neighbors.cc:868
@ ENTRY_DISPATCHED
Definition: enums.h:101
bool carp
Definition: CachePeer.h:104
int n_times_counted
Definition: CachePeer.h:130
Flag
Definition: Flag.h:15
struct CachePeer::@36 standby
optional "cache_peer standby=limit" feature
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:1187
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:125
time_t last_query
Definition: CachePeer.h:54
char * host
Definition: CachePeer.h:40
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:120
bool htcp_oldsquid
Definition: CachePeer.h:93
StoreEntry * findCallbackXXX(const cache_key *)
Definition: Controller.cc:407
@ 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
void peerAlive(CachePeer *p)
Definition: neighbors.cc:459
char * url
Definition: tcp-banger2.c:114
const char * getMyHostname(void)
Definition: tools.cc:412
time_t connect_timeout_raw
connect_timeout; use connectTimeout() instead!
Definition: CachePeer.h:175
struct SquidConfig::@99 Port
int rtt
Definition: CachePeer.h:49
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:108
int mcast_icp_query
Definition: SquidConfig.h:126
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:152
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:58
int neighborUp(const CachePeer *p)
Definition: neighbors.cc:1155
const char * neighborTypeStr(const CachePeer *p)
Definition: neighbors.cc:81
static void neighborAliveHtcp(CachePeer *, const MemObject *, const HtcpReplyData *)
Definition: neighbors.cc:919
@ ICP_END
Definition: icp_opcode.h:39
bool htcp_only_clr
Definition: CachePeer.h:96
CachePeer * peers
Definition: SquidConfig.h:250
lookup_t peerDigestLookup(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:759
static void peerCountMcastPeersAbort(PeerSelector *)
Definition: neighbors.cc:1458
static int ignoreMulticastReply(CachePeer *p, PeerSelector *ps)
Definition: neighbors.cc:981
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
const char * FormatHttpd(time_t t)
Definition: time.cc:111
int ignored_replies
Definition: CachePeer.h:50
#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:88
CachePeer * next
Definition: CachePeer.h:153
#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:1137
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:261
struct PeerDigest::@90 flags
static void peerCountMcastPeersStart(void *data)
Definition: neighbors.cc:1389
static void neighborCountIgnored(CachePeer *)
Definition: neighbors.cc:930
struct CachePeer::@32 mcast
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: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:1375
struct _request * request(char *urlin)
Definition: tcp-banger2.c:291
int counts[ICP_END+1]
Definition: CachePeer.h:65
htcp_clr_reason
Definition: enums.h:241
#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:894
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:873
int conn_open
current opened connections
Definition: CachePeer.h:59
struct CachePeer::@29 stats
int n_replies_expected
Definition: CachePeer.h:131
const char * getMD5Text() const
Definition: store.cc:205
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:126
bool originserver
Definition: CachePeer.h:117
@ PROTO_ICP
Definition: ProtocolType.h:33
unsigned short htcp
Definition: SquidConfig.h:141
static void dump_peers(StoreEntry *sentry, CachePeer *peers)
Definition: neighbors.cc:1640
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
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:938

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors