📄 neighbors.c
字号:
/* * $Id: neighbors.c,v 1.270.2.4 1999/07/07 02:02:26 wessels Exp $ * * DEBUG: section 15 Neighbor Routines * AUTHOR: Harvest Derived * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"/* count mcast group peers every 15 minutes */#define MCAST_COUNT_RATE 900static int peerAllowedToUse(const peer *, request_t *);static int peerWouldBePinged(const peer *, request_t *);static void neighborRemove(peer *);static void neighborAlive(peer *, const MemObject *, const icp_common_t *);#if USE_HTCPstatic void neighborAliveHtcp(peer *, const MemObject *, const htcpReplyData *);#endifstatic void neighborCountIgnored(peer *);static void peerRefreshDNS(void *);static IPH peerDNSConfigure;static EVH peerCheckConnect;static IPH peerCheckConnect2;static CNCB peerCheckConnectDone;static void peerCountMcastPeersDone(void *data);static void peerCountMcastPeersStart(void *data);static void peerCountMcastPeersSchedule(peer * p, time_t when);static IRCB peerCountHandleIcpReply;static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode);static OBJH neighborDumpPeers;static OBJH neighborDumpNonPeers;static void dump_peers(StoreEntry * sentry, peer * peers);static icp_common_t echo_hdr;static u_short echo_port;static int NLateReplies = 0;static peer *first_ping = NULL;char *neighborTypeStr(const peer * p){ if (p->type == PEER_NONE) return "Non-Peer"; if (p->type == PEER_SIBLING) return "Sibling"; if (p->type == PEER_MULTICAST) return "Multicast Group"; return "Parent";}peer *whichPeer(const struct sockaddr_in * from){ int j; u_short port = ntohs(from->sin_port); struct in_addr ip = from->sin_addr; peer *p = NULL; debug(15, 3) ("whichPeer: from %s port %d\n", inet_ntoa(ip), port); for (p = Config.peers; p; p = p->next) { for (j = 0; j < p->n_addresses; j++) { if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) { return p; } } } return NULL;}peer_tneighborType(const peer * p, const request_t * request){ const struct _domain_type *d = NULL; for (d = p->typelist; d; d = d->next) { if (matchDomainName(d->domain, request->host)) if (d->type != PEER_NONE) return d->type; } return p->type;}/* * peerAllowedToUse * * this function figures out if it is appropriate to fetch REQUEST * from PEER. */static intpeerAllowedToUse(const peer * p, request_t * request){ const struct _domain_ping *d = NULL; int do_ping = 1; aclCheck_t checklist; assert(request != NULL); if (neighborType(p, request) == PEER_SIBLING) { if (request->flags.nocache) return 0; if (request->flags.refresh) return 0; if (request->flags.loopdetect) return 0; if (request->flags.need_validation) return 0; } if (p->peer_domain == NULL && p->access == NULL) return do_ping; do_ping = 0; for (d = p->peer_domain; d; d = d->next) { if (matchDomainName(d->domain, request->host)) { do_ping = d->do_ping; break; } do_ping = !d->do_ping; } if (p->peer_domain && 0 == do_ping) return do_ping; if (p->access == NULL) return do_ping; checklist.src_addr = request->client_addr; checklist.my_addr = request->my_addr; checklist.request = request; return aclCheckFast(p->access, &checklist);}/* Return TRUE if it is okay to send an ICP request to this peer. */static intpeerWouldBePinged(const peer * p, request_t * request){ if (!peerAllowedToUse(p, request)) return 0; if (p->options.no_query) return 0; if (p->options.mcast_responder) return 0; /* the case below seems strange, but can happen if the * URL host is on the other side of a firewall */ if (p->type == PEER_SIBLING) if (!request->flags.hierarchical) return 0; if (p->icp.port == echo_port) if (!neighborUp(p)) return 0; if (p->n_addresses == 0) return 0; return 1;}/* Return TRUE if it is okay to send an HTTP request to this peer. */intpeerHTTPOkay(const peer * p, request_t * request){ if (!peerAllowedToUse(p, request)) return 0; if (!neighborUp(p)) return 0; return 1;}intneighborsCount(request_t * request){ peer *p = NULL; int count = 0; for (p = Config.peers; p; p = p->next) if (peerWouldBePinged(p, request)) count++; debug(15, 3) ("neighborsCount: %d\n", count); return count;}peer *getSingleParent(request_t * request){ peer *p = NULL; peer *q = NULL; for (q = Config.peers; q; q = q->next) { if (!peerHTTPOkay(q, request)) continue; if (neighborType(q, request) != PEER_PARENT) return NULL; /* oops, found SIBLING */ if (p) return NULL; /* oops, found second parent */ p = q; } if (p != NULL && !p->options.no_query) return NULL; debug(15, 3) ("getSingleParent: returning %s\n", p ? p->host : "NULL"); return p;}peer *getFirstUpParent(request_t * request){ peer *p = NULL; for (p = Config.peers; p; p = p->next) { if (!neighborUp(p)) continue; if (neighborType(p, request) != PEER_PARENT) continue; if (!peerHTTPOkay(p, request)) continue; break; } debug(15, 3) ("getFirstUpParent: returning %s\n", p ? p->host : "NULL"); return p;}peer *getRoundRobinParent(request_t * request){ peer *p; peer *q = NULL; for (p = Config.peers; p; p = p->next) { if (!p->options.roundrobin) continue; if (neighborType(p, request) != PEER_PARENT) continue; if (!peerHTTPOkay(p, request)) continue; if (q && q->rr_count < p->rr_count) continue; q = p; } if (q) q->rr_count++; debug(15, 3) ("getRoundRobinParent: returning %s\n", q ? q->host : "NULL"); return q;}peer *getDefaultParent(request_t * request){ peer *p = NULL; for (p = Config.peers; p; p = p->next) { if (neighborType(p, request) != PEER_PARENT) continue; if (!p->options.default_parent) continue; if (!peerHTTPOkay(p, request)) continue; debug(15, 3) ("getDefaultParent: returning %s\n", p->host); return p; } debug(15, 3) ("getDefaultParent: returning NULL\n"); return NULL;}peer *getAnyParent(request_t * request){ peer *p = NULL; for (p = Config.peers; p; p = p->next) { if (neighborType(p, request) != PEER_PARENT) continue; if (!peerHTTPOkay(p, request)) continue; debug(15, 3) ("getAnyParent: returning %s\n", p->host); return p; } debug(15, 3) ("getAnyParent: returning NULL\n"); return NULL;}peer *getNextPeer(peer * p){ return p->next;}peer *getFirstPeer(void){ return Config.peers;}static voidneighborRemove(peer * target){ peer *p = NULL; peer **P = NULL; p = Config.peers; P = &Config.peers; while (p) { if (target == p) break; P = &p->next; p = p->next; } if (p) { *P = p->next; cbdataFree(p); Config.npeers--; } first_ping = Config.peers;}voidneighbors_open(int fd){ struct sockaddr_in name; socklen_t len = sizeof(struct sockaddr_in); struct servent *sep = NULL; memset(&name, '\0', sizeof(struct sockaddr_in)); if (getsockname(fd, (struct sockaddr *) &name, &len) < 0) debug(15, 1) ("getsockname(%d,%p,%p) failed.\n", fd, &name, &len); peerRefreshDNS((void *) 1); if (0 == echo_hdr.opcode) { echo_hdr.opcode = ICP_SECHO; echo_hdr.version = ICP_VERSION_CURRENT; echo_hdr.length = 0; echo_hdr.reqnum = 0; echo_hdr.flags = 0; echo_hdr.pad = 0; echo_hdr.shostid = name.sin_addr.s_addr; sep = getservbyname("echo", "udp"); echo_port = sep ? ntohs((u_short) sep->s_port) : 7; } first_ping = Config.peers; cachemgrRegister("server_list", "Peer Cache Statistics", neighborDumpPeers, 0, 1); cachemgrRegister("non_peers", "List of Unknown sites sending ICP messages", neighborDumpNonPeers, 0, 1);}intneighborsUdpPing(request_t * request, StoreEntry * entry, IRCB * callback, void *callback_data, int *exprep, int *timeout){ const char *url = storeUrl(entry); MemObject *mem = entry->mem_obj; peer *p = NULL; int i; int reqnum = 0; int flags; icp_common_t *query; int queries_sent = 0; int peers_pinged = 0; if (Config.peers == NULL) return 0; if (theOutIcpConnection < 0) fatal("neighborsUdpPing: There is no ICP socket!"); assert(entry->swap_status == SWAPOUT_NONE); mem->start_ping = current_time; mem->ping_reply_callback = callback; mem->ircb_data = callback_data; *timeout = 0.0; reqnum = icpSetCacheKey(entry->key); for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) { if (p == NULL) p = Config.peers; debug(15, 5) ("neighborsUdpPing: Peer %s\n", p->host); if (!peerWouldBePinged(p, request)) continue; /* next peer */ peers_pinged++; debug(15, 4) ("neighborsUdpPing: pinging peer %s for '%s'\n", p->host, url); if (p->type == PEER_MULTICAST) mcastSetTtl(theOutIcpConnection, p->mcast.ttl); debug(15, 3) ("neighborsUdpPing: key = '%s'\n", storeKeyText(entry->key)); debug(15, 3) ("neighborsUdpPing: reqnum = %d\n", reqnum);#if USE_HTCP if (p->options.htcp) { debug(15, 3) ("neighborsUdpPing: sending HTCP query\n"); htcpQuery(entry, request, p); } else#endif if (p->icp.port == echo_port) { debug(15, 4) ("neighborsUdpPing: Looks like a dumb cache, send DECHO ping\n"); echo_hdr.reqnum = reqnum; query = icpCreateMessage(ICP_DECHO, 0, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0); } else { flags = 0; if (Config.onoff.query_icmp) if (p->icp.version == ICP_VERSION_2) flags |= ICP_FLAG_SRC_RTT; query = icpCreateMessage(ICP_QUERY, flags, url, reqnum, 0); icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0); } queries_sent++; p->stats.pings_sent++; if (p->type == PEER_MULTICAST) { /* * set a bogus last_reply time so neighborUp() never * says a multicast peer is dead. */ p->stats.last_reply = squid_curtime; (*exprep) += p->mcast.n_replies_expected; } else if (squid_curtime - p->stats.last_query > Config.Timeout.deadPeer) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -