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

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors