x>"IPM.Microsoft Mail.Note1  !A0DADE6C42751C4BAEF178A0C112D66D\%[MERGE] Squid Patch (revision 10487)b B @ !A0DADE6C42751C4BAEF178A0C112D66D\ *&6@9(+=G6c=us;a= ;p=Thomson;l=TLRUSMNEAGM-100518212529Z-140896p%[MERGE] Squid Patch (revision 10487)qХ+Gry~J -.g3ead-ͯ0?2$6< na=G yat0 t%M f W'Q  (#0 dium)-4/Â45style-C< IP address #" << j << ": " << p->addresses[j]); - p->n_addresses++; - } - - p->in_addr.SetEmpty(); - p->in_addr = p->addresses[0]; - p->in_addr.SetPort(p->icp.port); - - if (p->type == PEER_MULTICAST) - peerCountMcastPeersSchedule(p, 10); - -#if USE_ICMP - if (p->type != PEER_MULTICAST) - if (!p->options.no_netdb_exchange) - eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1); -#endif - -} - -static void -peerRefreshDNS(void *data) -{ - peer *p = NULL; - - if (eventFind(peerRefreshDNS, NULL)) - eventDelete(peerRefreshDNS, NULL); - - if (!data && 0 == stat5minClientRequests()) { - /* no recent client traffic, wait a bit */ - eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1); - return; - } - - for (p = Config.peers; p; p = p->next) - ipcache_nbgethostbyname(p->host, peerDNSConfigure, p); - - /* Reconfigure the peers every hour */ - eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1); -} - -static void -peerConnectFailedSilent(peer * p) -{ - p->stats.last_connect_failure = squid_curtime; - - if (!p->tcp_up) { - debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << - " dead"); - return; - } - - p->tcp_up--; - - if (!p->tcp_up) { - debugs(15, 1, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name); - p->stats.logged_state = PEER_DEAD; - } -} - -void -peerConnectFailed(peer *p) -{ - debugs(15, 1, "TCP connection to " << p->host << "/" << p->http_port << " failed"); - peerConnectFailedSilent(p); -} - -void -peerConnectSucceded(peer * p) -{ - if (!p->tcp_up) { - debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeded"); - p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly. - peerAlive(p); - if (!p->n_addresses) - ipcache_nbgethostbyname(p->host, peerDNSConfigure, p); - } else - p->tcp_up = p->connect_fail_limit; -} - -/// called by Comm when test_fd is closed while connect is in progress -static void -peerProbeClosed(int fd, void *data) -{ - peer *p = (peer*)data; - p->test_fd = -1; - // it is a failure because we failed to connect - peerConnectFailedSilent(p); -} - -static void -peerProbeConnectTimeout(int fd, void *data) -{ - peer * p = (peer *)data; - comm_remove_close_handler(fd, &peerProbeClosed, p); - comm_close(fd); - p->test_fd = -1; - peerConnectFailedSilent(p); -} - -/* -* peerProbeConnect will be called on dead peers by neighborUp -*/ -static int -peerProbeConnect(peer * p) -{ - int fd; - time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout - : Config.Timeout.peer_connect; - int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10; - - if (p->test_fd != -1) - return ret;/* probe already running */ - - if (squid_curtime - p->stats.last_connect_probe == 0) - return ret;/* don't probe to often */ - - Ip::Address temp(getOutgoingAddr(NULL,p)); - - fd = comm_open(SOCK_STREAM, IPPROTO_TCP, temp, COMM_NONBLOCKING, p->host); - - if (fd < 0) - return ret; - - comm_add_close_handler(fd, &peerProbeClosed, p); - commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p); - - p->test_fd = fd; - - p->stats.last_connect_probe = squid_curtime; - - commConnectStart(p->test_fd, - p->host, - p->http_port, - peerProbeConnectDone, - p); - - return ret; -} - -static void -peerProbeConnectDone(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data) -{ - peer *p = (peer*)data; - - if (status == COMM_OK) { - peerConnectSucceded(p); - } else { - peerConnectFailedSilent(p); - } - - comm_remove_close_handler(fd, &peerProbeClosed, p); - comm_close(fd); - p->test_fd = -1; - return; -} - -static void -peerCountMcastPeersSchedule(peer * p, time_t when) -{ - if (p->mcast.flags.count_event_pending) - return; - - eventAdd("peerCountMcastPeersStart", - peerCountMcastPeersStart, - p, - (double) when, 1); - - p->mcast.flags.count_event_pending = 1; -} - -static void -peerCountMcastPeersStart(void *data) -{ - peer *p = (peer *)data; - ps_state *psstate; - StoreEntry *fake; - MemObject *mem; - icp_common_t *query; - int reqnum; - LOCAL_ARRAY(char, url, MAX_URL); - assert(p->type == PEER_MULTICAST); - p->mcast.flags.count_event_pending = 0; - snprintf(url, MAX_URL, "http://"); - p->in_addr.ToURL(url+7, MAX_URL -8 ); - strcat(url, "/"); - fake = storeCreateEntry(url, url, request_flags(), METHOD_GET); - HttpRequest *req = HttpRequest::CreateFromUrl(url); - psstate = new ps_state; - psstate->request = HTTPMSGLOCK(req); - psstate->entry = fake; - psstate->callback = NULL; - psstate->callback_data = cbdataReference(p); - psstate->ping.start = current_time; - mem = fake->mem_obj; - mem->request = HTTPMSGLOCK(psstate->request); - mem->start_ping = current_time; - mem->ping_reply_callback = peerCountHandleIcpReply; - mem->ircb_data = psstate; - mcastSetTtl(theOutIcpConnection, p->mcast.ttl); - p->mcast.id = mem->id; - reqnum = icpSetCacheKey((const cache_key *)fake->key); - query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0); - icpUdpSend(theOutIcpConnection, - p->in_addr, - query, - LOG_ICP_QUERY, - 0); - fake->ping_status = PING_WAITING; - eventAdd("peerCountMcastPeersDone", - peerCountMcastPeersDone, - psstate, - Config.Timeout.mcast_icp_query / 1000.0, 1); - p->mcast.flags.counting = 1; - peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE); -} - -static void -peerCountMcastPeersDone(void *data) -{ - ps_state *psstate = (ps_state *)data; - StoreEntry *fake = psstate->entry; - - if (cbdataReferenceValid(psstate->callback_data)) { - peer *p = (peer *)psstate->callback_data; - p->mcast.flags.counting = 0; - p->mcast.avg_n_members = Math::doubleAverage(p->mcast.avg_n_members, (double) psstate->ping.n_recv, ++p->mcast.n_times_counted, 10); - debugs(15, 1, "Group " << p->host << ": " << psstate->ping.n_recv << - " replies, "<< std::setw(4)<< std::setprecision(2) << - p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt); - p->mcast.n_replies_expected = (int) p->mcast.avg_n_members; - } - - cbdataReferenceDone(psstate->callback_data); - - EBIT_SET(fake->flags, ENTRY_ABORTED); - HTTPMSGUNLOCK(fake->mem_obj->request); - fake->releaseRequest(); - fake->unlock(); - HTTPMSGUNLOCK(psstate->request); - cbdataFree(psstate); -} - -static void -peerCountHandleIcpReply(peer * p, peer_t type, protocol_t proto, void *hdrnotused, void *data) -{ - int rtt_av_factor; - - ps_state *psstate = (ps_state *)data; - StoreEntry *fake = psstate->entry; - MemObject *mem = fake->mem_obj; - int rtt = tvSubMsec(mem->start_ping, current_time); - assert(proto == PROTO_ICP); - assert(fake); - assert(mem); - psstate->ping.n_recv++; - rtt_av_factor = RTT_AV_FACTOR; - - if (p->options.weighted_roundrobin) - rtt_av_factor = RTT_BACKGROUND_AV_FACTOR; - - p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor); -} - -static void -neighborDumpPeers(StoreEntry * sentry) -{ - dump_peers(sentry, Config.peers); -} - -static void -neighborDumpNonPeers(StoreEntry * sentry) -{ - dump_peers(sentry, non_peers); -} - -void -dump_peer_options(StoreEntry * sentry, peer * p) -{ - if (p->options.proxy_only) - storeAppendPrintf(sentry, " proxy-only"); - - if (p->options.no_query) - storeAppendPrintf(sentry, " no-query"); - - if (p->options.background_ping) - storeAppendPrintf(sentry, " background-ping"); - - if (p->options.no_digest) - storeAppendPrintf(sentry, " no-digest"); - - if (p->options.default_parent) - storeAppendPrintf(sentry, " default"); - - if (p->options.roundrobin) - storeAppendPrintf(sentry, " round-robin"); - - if (p->options.carp) - storeAppendPrintf(sentry, " carp"); - - if (p->options.userhash) - storeAppendPrintf(sentry, " userhash"); - - if (p->options.userhash) - storeAppendPrintf(sentry, " sourcehash"); - - if (p->options.weighted_roundrobin) - storeAppendPrintf(sentry, " weighted-round-robin"); - - if (p->options.mcast_responder) - storeAppendPrintf(sentry, " multicast-responder"); - -#if PEER_MULTICAST_SIBLINGS - if (p->options.mcast_siblings) - storeAppendPrintf(sentry, " multicast-siblings"); -#endif - - if (p->weight != 1) - storeAppendPrintf(sentry, " weight=%d", p->weight); - - if (p->options.closest_only) - storeAppendPrintf(sentry, " closest-only"); - -#if USE_HTCP - if (p->options.htcp) - storeAppendPrintf(sentry, " htcp"); - if (p->options.htcp_oldsquid) - storeAppendPrintf(sentry, " htcp-oldsquid"); - if (p->options.htcp_no_clr) - storeAppendPrintf(sentry, " htcp-no-clr"); - if (p->options.htcp_no_purge_clr) - storeAppendPrintf(sentry, " htcp-no-purge-clr"); - if (p->options.htcp_only_clr) - storeAppendPrintf(sentry, " htcp-only-clr"); -#endif - - if (p->options.no_netdb_exchange) - storeAppendPrintf(sentry, " no-netdb-exchange"); - -#if DELAY_POOLS - - if (p->options.no_delay) - storeAppendPrintf(sentry, " no-delay"); - -#endif - - if (p->login) - storeAppendPrintf(sentry, " login=%s", p->login); - - if (p->mcast.ttl > 0) - storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl); - - if (p->connect_timeout > 0) - storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout); - - if (p->connect_fail_limit != PEER_TCP_MAGIC_COUNT) - storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit); - -#if USE_CACHE_DIGESTS - - if (p->digest_url) - storeAppendPrintf(sentry, " digest-url=%s", p->digest_url); - -#endif - - if (p->options.allow_miss) - storeAppendPrintf(sentry, " allow-miss"); - - if (p->options.no_tproxy) - storeAppendPrintf(sentry, " no-tproxy"); - - if (p->max_conn > 0) - storeAppendPrintf(sentry, " max-conn=%d", p->max_conn); - - if (p->options.originserver) - storeAppendPrintf(sentry, " originserver"); - - if (p->domain) - storeAppendPrintf(sentry, " forceddomain=%s", p->domain); - - if (p->connection_auth == 0) - storeAppendPrintf(sentry, " connection-auth=off"); - else if (p->connection_auth == 1) - storeAppendPrintf(sentry, " connection-auth=on"); - else if (p->connection_auth == 2) - storeAppendPrintf(sentry, " connection-auth=auto"); - - storeAppendPrintf(sentry, "\n"); -} - -static void -dump_peers(StoreEntry * sentry, peer * peers) -{ - peer *e = NULL; - char ntoabuf[MAX_IPSTRLEN]; - struct _domain_ping *d = NULL; - icp_opcode op; - int i; - - if (peers == NULL) - storeAppendPrintf(sentry, "There are no neighbors installed.\n"); - - for (e = peers; e; e = e->next) { - assert(e->host != NULL); - storeAppendPrintf(sentry, "\n%-11.11s: %s\n", - neighborTypeStr(e), - e->name); - storeAppendPrintf(sentry, "Host : %s/%d/%d\n", - e->host, - e->http_port, - e->icp.port); - storeAppendPrintf(sentry, "Flags :"); - dump_peer_options(sentry, e); - - for (i = 0; i < e->n_addresses; i++) { - storeAppendPrintf(sentry, "Address[%d] : %s\n", i, - e->addresses[i].NtoA(ntoabuf,MAX_IPSTRLEN) ); - } - - storeAppendPrintf(sentry, "Status : %s\n", - neighborUp(e) ? "Up" : "Down"); - storeAppendPrintf(sentry, "FETCHES : %d\n", e->stats.fetches); - storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open); - storeAppendPrintf(sentry, "AVG RTT : %d msec\n", e->stats.rtt); - - if (!e->options.no_query) { - storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n", - (int) (squid_curtime - e->stats.last_query)); - - if (e->stats.last_reply > 0) - storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n", - (int) (squid_curtime - e->stats.last_reply)); - else - storeAppendPrintf(sentry, "LAST REPLY : none received\n"); - - storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent); - - storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n", - e->stats.pings_acked, - Math::intPercent(e->stats.pings_acked, e->stats.pings_sent)); - } - - storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked)); - - if (!e->options.no_query) { - storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n"); -#if USE_HTCP - - if (e->options.htcp) { - storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n", - e->htcp.counts[0], - Math::intPercent(e->htcp.counts[0], e->stats.pings_acked)); - storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n", - e->htcp.counts[1], - Math::intPercent(e->htcp.counts[1], e->stats.pings_acked)); - } else { -#endif - - for (op = ICP_INVALID; op < ICP_END; ++op) { - if (e->icp.counts[op] == 0) - continue; - - storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n", - icp_opcode_str[op], - e->icp.counts[op], - Math::intPercent(e->icp.counts[op], e->stats.pings_acked)); - } - -#if USE_HTCP - - } - -#endif - - } - - if (e->stats.last_connect_failure) { - storeAppendPrintf(sentry, "Last failed connect() at: %s\n", - mkhttpdlogtime(&(e->stats.last_connect_failure))); - } - - if (e->peer_domain != NULL) { - storeAppendPrintf(sentry, "DOMAIN LIST: "); - - for (d = e->peer_domain; d; d = d->next) { - storeAppendPrintf(sentry, "%s%s ", - d->do_ping ? null_string : "!", d->domain); - } - - storeAppendPrintf(sentry, "\n"); - } - - storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent)); - } -} - -#if USE_HTCP -void -neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const Ip::Address &from) -{ - StoreEntry *e = Store::Root().get(key); - MemObject *mem = NULL; - peer *p; - peer_t ntype = PEER_NONE; - debugs(15, 6, "neighborsHtcpReply: " << - (htcp->hit ? "HIT" : "MISS") << " " << - storeKeyText(key) ); - - if (NULL != e) - mem = e->mem_obj; - - if ((p = whichPeer(from))) - neighborAliveHtcp(p, mem, htcp); - - /* Does the entry exist? */ - if (NULL == e) { - debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found"); - neighborCountIgnored(p); - return; - } - - /* check if someone is already fetching it */ - if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) { - debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched."); - neighborCountIgnored(p); - return; - } - - if (mem == NULL) { - debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key)); - neighborCountIgnored(p); - return; - } - - if (e->ping_status != PING_WAITING) { - debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING"); - neighborCountIgnored(p); - return; - } - - if (e->lock_count == 0) { - debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks"); - neighborCountIgnored(p); - return; - } - - if (p) { - ntype = neighborType(p, mem->request); - neighborUpdateRtt(p, mem); - } - - if (ignoreMulticastReply(p, mem)) { - neighborCountIgnored(p); - return; - } - - debugs(15, 3, "neighborsHtcpReply: e = " << e); - mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data); -} - -/* - * Send HTCP CLR messages to all peers configured to receive them. - */ -void -neighborsHtcpClear(StoreEntry * e, const char *uri, HttpRequest * req, const HttpRequestMethod &method, htcp_clr_reason reason) -{ - peer *p; - char buf[128]; - - for (p = Config.peers; p; p = p->next) { - if (!p->options.htcp) { - continue; - } - if (p->options.htcp_no_clr) { - continue; - } - if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) { - continue; - } - debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.ToURL(buf, 128)); - htcpClear(e, uri, req, method, p, reason); - } -} - -#endif +/* + * DEBUG: section 15 Neighbor Routines + * AUTHOR: Harvest Derived + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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" +#include "ProtoPort.h" +#include "acl/FilledChecklist.h" +#include "event.h" +#include "CacheManager.h" +#include "htcp.h" +#include "HttpRequest.h" +#include "ICP.h" +#include "MemObject.h" +#include "PeerDigest.h" +#include "PeerSelectState.h" +#include "SquidMath.h" +#include "SquidTime.h" +#include "Store.h" +#include "icmp/net_db.h" +#include "ip/Address.h" + +/* count mcast group peers every 15 minutes */ +#define MCAST_COUNT_RATE 900 + +int peerAllowedToUse(const peer *, HttpRequest *); +static int peerWouldBePinged(const peer *, HttpRequest *); +static void neighborRemove(peer *); +static void neighborAlive(peer *, const MemObject *, const icp_common_t *); +#if USE_HTCP +static void neighborAliveHtcp(peer *, const MemObject *, const htcpReplyData *); +#endif +static void neighborCountIgnored(peer *); +static void peerRefreshDNS(void *); +static IPH peerDNSConfigure; +static int peerProbeConnect(peer *); +static CNCB peerProbeConnectDone; +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 Ip::Address &, 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; + +const 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 Ip::Address &from) +{ + int j; + + peer *p = NULL; + debugs(15, 3, "whichPeer: from " << from); + + for (p = Config.peers; p; p = p->next) { + for (j = 0; j < p->n_addresses; j++) { + if (from == p->addresses[j] && from.GetPort() == p->icp.port) { + return p; + } + } + } + + return NULL; +} + +peer_t +neighborType(const peer * p, const HttpRequest * request) +{ + + const struct _domain_type *d = NULL; + + for (d = p->typelist; d; d = d->next) { + if (0 == matchDomainName(request->GetHost(), d->domain)) + if (d->type != PEER_NONE) + return d->type; + } +#if PEER_MULTICAST_SIBLINGS + if (p->type == PEER_MULTICAST) + if (p->options.mcast_siblings) + return PEER_SIBLING; +#endif + + return p->type; +} + +/* + * peerAllowedToUse + * + * this function figures out if it is appropriate to fetch REQUEST + * from PEER. + */ +int +peerAllowedToUse(const peer * p, HttpRequest * request) +{ + + const struct _domain_ping *d = NULL; + int do_ping = 1; + assert(request != NULL); + + if (neighborType(p, request) == PEER_SIBLING) { +#if PEER_MULTICAST_SIBLINGS + if (p->type == PEER_MULTICAST && p->options.mcast_siblings && + (request->flags.nocache || request->flags.refresh || request->flags.loopdetect || request->flags.need_validation)) + debugs(15, 2, "peerAllowedToUse(" << p->name << ", " << request->GetHost() << ") : multicast-siblings optimization match"); +#endif + if (request->flags.nocache) + return 0; + + /*Ignore refresh flag if access_sibling_for_stale_resource flag is on unless allow_miss is enabled for this peer + (needed to avoid forwarding loops).*/ + if (request->flags.refresh && !Config.onoff.access_sibling_for_stale_resource || + request->flags.refresh && p->options.allow_miss) + return 0; + + if (request->flags.loopdetect) + return 0; + + /*Ignore need_validation flag if access_sibling_for_stale_resource flag is on unless allow_miss is enabled for this peer + (needed to avoid forwarding loops).*/ + if (request->flags.need_validation && !Config.onoff.access_sibling_for_stale_resource || + request->flags.need_validation && p->options.allow_miss) + 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 (0 == matchDomainName(request->GetHost(), d->domain)) { + 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; + + ACLFilledChecklist checklist(p->access, request, NULL); + checklist.src_addr = request->client_addr; + checklist.my_addr = request->my_addr; + +#if 0 && USE_IDENT + /* + * this is currently broken because 'request->user_ident' has been + * moved to conn->rfc931 and we don't have access to the parent + * ConnStateData here. + */ + if (request->user_ident[0]) + xstrncpy(checklist.rfc931, request->user_ident, USER_IDENT_SZ); + +#endif + + return checklist.fastCheck(); +} + +/* Return TRUE if it is okay to send an ICP request to this peer. */ +static int +peerWouldBePinged(const peer * p, HttpRequest * request) +{ + if (!peerAllowedToUse(p, request)) + return 0; + + if (p->options.no_query) + return 0; + + if (p->options.background_ping && (squid_curtime - p->stats.last_query < Config.backgroundPingRate)) + return 0; + + if (p->options.mcast_responder) + return 0; + + if (p->n_addresses == 0) + return 0; + + if (p->icp.port == 0) + 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; + + /* Ping dead peers every timeout interval */ + if (squid_curtime - p->stats.last_query > Config.Timeout.deadPeer) + return 1; + + if (!neighborUp(p)) + return 0; + + return 1; +} + +/* Return TRUE if it is okay to send an HTTP request to this peer. */ +int +peerHTTPOkay(const peer * p, HttpRequest * request) +{ + if (!peerAllowedToUse(p, request)) + return 0; + + if (!neighborUp(p)) + return 0; + + if (p->max_conn) + if (p->stats.conn_open >= p->max_conn) + return 0; + + return 1; +} + +int +neighborsCount(HttpRequest * request) +{ + peer *p = NULL; + int count = 0; + + for (p = Config.peers; p; p = p->next) + if (peerWouldBePinged(p, request)) + count++; + + debugs(15, 3, "neighborsCount: " << count); + + return count; +} + +peer * +getFirstUpParent(HttpRequest * 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; + } + + debugs(15, 3, "getFirstUpParent: returning " << (p ? p->host : "NULL")); + return p; +} + +peer * +getRoundRobinParent(HttpRequest * 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 (p->weight == 0) + continue; + + if (q) { + if (p->weight == q->weight) { + if (q->rr_count < p->rr_count) + continue; + } else if ( (double) q->rr_count / q->weight < (double) p->rr_count / p->weight) { + continue; + } + } + + q = p; + } + + if (q) + q->rr_count++; + + debugs(15, 3, HERE << "returning " << (q ? q->host : "NULL")); + + return q; +} + +peer * +getWeightedRoundRobinParent(HttpRequest * request) +{ + peer *p; + peer *q = NULL; + int weighted_rtt; + + for (p = Config.peers; p; p = p->next) { + if (!p->options.weighted_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 > 1000000) + for (p = Config.peers; p; p = p->next) { + if (!p->options.weighted_roundrobin) + continue; + + if (neighborType(p, request) != PEER_PARENT) + continue; + + p->rr_count = 0; + } + + if (q) { + weighted_rtt = (q->stats.rtt - q->basetime) / q->weight; + + if (weighted_rtt < 1) + weighted_rtt = 1; + + q->rr_count += weighted_rtt; + + debugs(15, 3, "getWeightedRoundRobinParent: weighted_rtt " << weighted_rtt); + } + + debugs(15, 3, "getWeightedRoundRobinParent: returning " << (q ? q->host : "NULL")); + return q; +} + +/** + * This gets called every 5 minutes to clear the round-robin counter. + * The exact timing is an arbitrary default, set on estimate timing of a + * large number of requests in a high-performance environment during the + * period. The larger the number of requests between cycled resets the + * more balanced the operations. + * + \param data unused. + \todo Make the reset timing a selectable parameter in squid.conf + */ +static void +peerClearRRLoop(void *data) +{ + peerClearRR(); + eventAdd("peerClearRR", peerClearRRLoop, data, 5 * 60.0, 0); +} + +/** + * This gets called on startup and restart to kick off the peer round-robin + * maintenance event. It ensures that no matter how many times its called + * no more than one event is scheduled. + */ +void +peerClearRRStart(void) +{ + static int event_added = 0; + if (!event_added) { + peerClearRRLoop(NULL); + } +} + +/** + * Called whenever the round-robin counters need to be reset to a sane state. + * So far those times are: + * - On startup and reconfigure - to set the counters to sane initial settings. + * - When a peer has revived from dead, to prevent the revived peer being + * flooded with requests which it has 'missed' during the down period. + */ +void +peerClearRR() +{ + peer *p = NULL; + for (p = Config.peers; p; p = p->next) { + p->rr_count = 0; + } +} + +/** + * Perform all actions when a peer is detected revived. + */ +void +peerAlive(peer *p) +{ + if (p->stats.logged_state == PEER_DEAD && p->tcp_up) { + debugs(15, 1, "Detected REVIVED " << neighborTypeStr(p) << ": " << p->name); + p->stats.logged_state = PEER_ALIVE; + peerClearRR(); + } + + p->stats.last_reply = squid_curtime; + p->stats.probe_start = 0; +} + +peer * +getDefaultParent(HttpRequest * 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; + + debugs(15, 3, "getDefaultParent: returning " << p->host); + + return p; + } + + debugs(15, 3, "getDefaultParent: returning NULL"); + return NULL; +} + +/* + * XXX DW thinks this function is equivalent to/redundant with + * getFirstUpParent(). peerHTTPOkay() only returns true if the + * peer is UP anyway, so this function would not return a + * DOWN parent. + */ +peer * +getAnyParent(HttpRequest * request) +{ + peer *p = NULL; + + for (p = Config.peers; p; p = p->next) { + if (neighborType(p, request) != PEER_PARENT) + continue; + + if (!peerHTTPOkay(p, request)) + continue; + + debugs(15, 3, "getAnyParent: returning " << p->host); + + return p; + } + + debugs(15, 3, "getAnyParent: returning NULL"); + return NULL; +} + +peer * +getNextPeer(peer * p) +{ + return p->next; +} + +peer * +getFirstPeer(void) +{ + return Config.peers; +} + +static void +neighborRemove(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; +} + +static void +neighborsRegisterWithCacheManager() +{ + CacheManager *manager = CacheManager::GetInstance(); + manager->registerAction("server_list", + "Peer Cache Statistics", + neighborDumpPeers, 0, 1); + + if (theInIcpConnection >= 0) { + manager->registerAction("non_peers", + "List of Unknown sites sending ICP messages", + neighborDumpNonPeers, 0, 1); + } +} + +void +neighbors_init(void) +{ + Ip::Address nul; + struct addrinfo *AI = NULL; + struct servent *sep = NULL; + const char *me = getMyHostname(); + peer *thisPeer = NULL; + peer *next = NULL; + int fd = theInIcpConnection; + + neighborsRegisterWithCacheManager(); + + /* setup addrinfo for use */ + nul.InitAddrInfo(AI); + + if (fd >= 0) { + + if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen) < 0) + debugs(15, 1, "getsockname(" << fd << "," << AI->ai_addr << "," << &AI->ai_addrlen << ") failed."); + + for (thisPeer = Config.peers; thisPeer; thisPeer = next) { + http_port_list *s = NULL; + next = thisPeer->next; + + if (0 != strcmp(thisPeer->host, me)) + continue; + + for (s = Config.Sockaddr.http; s; s = s->next) { + if (thisPeer->http_port != s->s.GetPort()) + continue; + + debugs(15, 1, "WARNING: Peer looks like this host"); + + debugs(15, 1, " Ignoring " << + neighborTypeStr(thisPeer) << " " << thisPeer->host << + "/" << thisPeer->http_port << "/" << + thisPeer->icp.port); + + neighborRemove(thisPeer); + } + } + } + + peerRefreshDNS((void *) 1); + + if (ICP_INVALID == 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; + nul = *AI; + nul.GetInAddr( *((struct in_addr*)&echo_hdr.shostid) ); + sep = getservbyname("echo", "udp"); + echo_port = sep ? ntohs((u_short) sep->s_port) : 7; + } + + first_ping = Config.peers; + nul.FreeAddrInfo(AI); +} + +int +neighborsUdpPing(HttpRequest * request, + StoreEntry * entry, + IRCB * callback, + void *callback_data, + int *exprep, + int *timeout) +{ + const char *url = entry->url(); + 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; + int parent_timeout = 0, parent_exprep = 0; + int sibling_timeout = 0, sibling_exprep = 0; + int mcast_timeout = 0, mcast_exprep = 0; + + if (Config.peers == NULL) + return 0; + + assert(entry->swap_status == SWAPOUT_NONE); + + mem->start_ping = current_time; + + mem->ping_reply_callback = callback; + + mem->ircb_data = callback_data; + + reqnum = icpSetCacheKey((const cache_key *)entry->key); + + for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) { + if (p == NULL) + p = Config.peers; + + debugs(15, 5, "neighborsUdpPing: Peer " << p->host); + + if (!peerWouldBePinged(p, request)) + continue; /* next peer */ + + peers_pinged++; + + debugs(15, 4, "neighborsUdpPing: pinging peer " << p->host << " for '" << url << "'"); + + debugs(15, 3, "neighborsUdpPing: key = '" << entry->getMD5Text() << "'"); + + debugs(15, 3, "neighborsUdpPing: reqnum = " << reqnum); + +#if USE_HTCP + if (p->options.htcp && !p->options.htcp_only_clr) { + if (Config.Port.htcp <= 0) { + debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer."); + continue; + } + + debugs(15, 3, "neighborsUdpPing: sending HTCP query"); + if (htcpQuery(entry, request, p) <= 0) continue; // unable to send. + } else +#endif + { + if (Config.Port.icp <= 0 || theOutIcpConnection <= 0) { + debugs(15, DBG_CRITICAL, "ICP is disabled! Cannot send ICP request to peer."); + continue; + } else { + + if (p->type == PEER_MULTICAST) + mcastSetTtl(theOutIcpConnection, p->mcast.ttl); + + if (p->icp.port == echo_port) { + debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping"); + echo_hdr.reqnum = reqnum; + query = _icp_common_t::createMessage(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 = _icp_common_t::createMessage(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) { + mcast_exprep += p->mcast.n_replies_expected; + mcast_timeout += (p->stats.rtt * p->mcast.n_replies_expected); + } else if (neighborUp(p)) { + /* its alive, expect a reply from it */ + + if (neighborType(p, request) == PEER_PARENT) { + parent_exprep++; + parent_timeout += p->stats.rtt; + } else { + sibling_exprep++; + sibling_timeout += p->stats.rtt; + } + } else { + /* Neighbor is dead; ping it anyway, but don't expect a reply */ + /* log it once at the threshold */ + + if (p->stats.logged_state == PEER_ALIVE) { + debugs(15, 1, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name); + p->stats.logged_state = PEER_DEAD; + } + } + + p->stats.last_query = squid_curtime; + + /* + * keep probe_start == 0 for a multicast peer, + * so neighborUp() never says this peer is dead. + */ + + if ((p->type != PEER_MULTICAST) && (p->stats.probe_start == 0)) + p->stats.probe_start = squid_curtime; + } + + if ((first_ping = first_ping->next) == NULL) + first_ping = Config.peers; + + /* + * How many replies to expect? + */ + *exprep = parent_exprep + sibling_exprep + mcast_exprep; + + /* + * If there is a configured timeout, use it + */ + if (Config.Timeout.icp_query) + *timeout = Config.Timeout.icp_query; + else { + if (*exprep > 0) { + if (parent_exprep) + *timeout = 2 * parent_timeout / parent_exprep; + else if (mcast_exprep) + *timeout = 2 * mcast_timeout / mcast_exprep; + else + *timeout = 2 * sibling_timeout / sibling_exprep; + } else + *timeout = 2000; /* 2 seconds */ + + if (Config.Timeout.icp_query_max) + if (*timeout > Config.Timeout.icp_query_max) + *timeout = Config.Timeout.icp_query_max; + + if (*timeout < Config.Timeout.icp_query_min) + *timeout = Config.Timeout.icp_query_min; + } + + return peers_pinged; +} + +/* lookup the digest of a given peer */ +lookup_t +peerDigestLookup(peer * p, HttpRequest * request) +{ +#if USE_CACHE_DIGESTS + const cache_key *key = request ? storeKeyPublicByRequest(request) : NULL; + assert(p); + assert(request); + debugs(15, 5, "peerDigestLookup: peer " << p->host); + /* does the peeer have a valid digest? */ + + if (!p->digest) { + debugs(15, 5, "peerDigestLookup: gone!"); + return LOOKUP_NONE; + } else if (!peerHTTPOkay(p, request)) { + debugs(15, 5, "peerDigestLookup: !peerHTTPOkay"); + return LOOKUP_NONE; + } else if (!p->digest->flags.needed) { + debugs(15, 5, "peerDigestLookup: note need"); + peerDigestNeeded(p->digest); + return LOOKUP_NONE; + } else if (!p->digest->flags.usable) { + debugs(15, 5, "peerDigestLookup: !ready && " << (p->digest->flags.requested ? "" : "!") << "requested"); + return LOOKUP_NONE; + } + + debugs(15, 5, "peerDigestLookup: OK to lookup peer " << p->host); + assert(p->digest->cd); + /* does digest predict a hit? */ + + if (!cacheDigestTest(p->digest->cd, key)) + return LOOKUP_MISS; + + debugs(15, 5, "peerDigestLookup: peer " << p->host << " says HIT!"); + + return LOOKUP_HIT; + +#endif + + return LOOKUP_NONE; +} + +/* select best peer based on cache digests */ +peer * +neighborsDigestSelect(HttpRequest * request) +{ + peer *best_p = NULL; +#if USE_CACHE_DIGESTS + + const cache_key *key; + int best_rtt = 0; + int choice_count = 0; + int ichoice_count = 0; + peer *p; + int p_rtt; + int i; + + if (!request->flags.hierarchical) + return NULL; + + key = storeKeyPublicByRequest(request); + + for (i = 0, p = first_ping; i++ < Config.npeers; p = p->next) { + lookup_t lookup; + + if (!p) + p = Config.peers; + + if (i == 1) + first_ping = p; + + lookup = peerDigestLookup(p, request); + + if (lookup == LOOKUP_NONE) + continue; + + choice_count++; + + if (lookup == LOOKUP_MISS) + continue; + + p_rtt = netdbHostRtt(p->host); + + debugs(15, 5, "neighborsDigestSelect: peer " << p->host << " rtt: " << p_rtt); + + /* is this peer better than others in terms of rtt ? */ + if (!best_p || (p_rtt && p_rtt < best_rtt)) { + best_p = p; + best_rtt = p_rtt; + + if (p_rtt) /* informative choice (aka educated guess) */ + ichoice_count++; + + debugs(15, 4, "neighborsDigestSelect: peer " << p->host << " leads with rtt " << best_rtt); + } + } + + debugs(15, 4, "neighborsDigestSelect: choices: " << choice_count << " (" << ichoice_count << ")"); + peerNoteDigestLookup(request, best_p, + best_p ? LOOKUP_HIT : (choice_count ? LOOKUP_MISS : LOOKUP_NONE)); + request->hier.n_choices = choice_count; + request->hier.n_ichoices = ichoice_count; +#endif + + return best_p; +} + +void +peerNoteDigestLookup(HttpRequest * request, peer * p, lookup_t lookup) +{ +#if USE_CACHE_DIGESTS + if (p) + strncpy(request->hier.cd_host, p->host, sizeof(request->hier.cd_host)); + else + *request->hier.cd_host = '\0'; + + request->hier.cd_lookup = lookup; + debugs(15, 4, "peerNoteDigestLookup: peer " << (p? p->host : "") << ", lookup: " << lookup_t_str[lookup] ); +#endif +} + +static void +neighborAlive(peer * p, const MemObject * mem, const icp_common_t * header) +{ + peerAlive(p); + p->stats.pings_acked++; + + if ((icp_opcode) header->opcode <= ICP_END) + p->icp.counts[header->opcode]++; + + p->icp.version = (int) header->version; +} + +static void +neighborUpdateRtt(peer * p, MemObject * mem) +{ + int rtt, rtt_av_factor; + + if (!mem) + return; + + if (!mem->start_ping.tv_sec) + return; + + rtt = tvSubMsec(mem->start_ping, current_time); + + if (rtt < 1 || rtt > 10000) + return; + + rtt_av_factor = RTT_AV_FACTOR; + + if (p->options.weighted_roundrobin) + rtt_av_factor = RTT_BACKGROUND_AV_FACTOR; + + p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor); +} + +#if USE_HTCP +static void +neighborAliveHtcp(peer * p, const MemObject * mem, const htcpReplyData * htcp) +{ + peerAlive(p); + p->stats.pings_acked++; + p->htcp.counts[htcp->hit ? 1 : 0]++; + p->htcp.version = htcp->version; +} + +#endif + +static void +neighborCountIgnored(peer * p) +{ + if (p == NULL) + return; + + p->stats.ignored_replies++; + + NLateReplies++; +} + +static peer *non_peers = NULL; + +static void +neighborIgnoreNonPeer(const Ip::Address &from, icp_opcode opcode) +{ + peer *np; + + for (np = non_peers; np; np = np->next) { + if (np->in_addr != from) + continue; + + if (np->in_addr.GetPort() != from.GetPort()) + continue; + + break; + } + + if (np == NULL) { + np = (peer *)xcalloc(1, sizeof(peer)); + np->in_addr = from; + np->icp.port = from.GetPort(); + np->type = PEER_NONE; + np->host = new char[MAX_IPSTRLEN]; + from.NtoA(np->host,MAX_IPSTRLEN); + np->next = non_peers; + non_peers = np; + } + + np->icp.counts[opcode]++; + + if (isPowTen(++np->stats.ignored_replies)) + debugs(15, 1, "WARNING: Ignored " << np->stats.ignored_replies << " replies from non-peer " << np->host); +} + +/* ignoreMulticastReply + * + * * We want to ignore replies from multicast peers if the + * * cache_host_domain rules would normally prevent the peer + * * from being used + */ +static int +ignoreMulticastReply(peer * p, MemObject * mem) +{ + if (p == NULL) + return 0; + + if (!p->options.mcast_responder) + return 0; + + if (peerHTTPOkay(p, mem->request)) + return 0; + + return 1; +} + +/** + * I should attach these records to the entry. We take the first + * hit we get our wait until everyone misses. The timeout handler + * call needs to nip this shopping list or call one of the misses. + * + * If a hit process is already started, then sobeit + */ +void +neighborsUdpAck(const cache_key * key, icp_common_t * header, const Ip::Address &from) +{ + peer *p = NULL; + StoreEntry *entry; + MemObject *mem = NULL; + peer_t ntype = PEER_NONE; + icp_opcode opcode = (icp_opcode) header->opcode; + + debugs(15, 6, "neighborsUdpAck: opcode " << opcode << " '" << storeKeyText(key) << "'"); + + if (NULL != (entry = Store::Root().get(key))) + mem = entry->mem_obj; + + if ((p = whichPeer(from))) + neighborAlive(p, mem, header); + + if (opcode > ICP_END) + return; + + const char *opcode_d = icp_opcode_str[opcode]; + + if (p) + neighborUpdateRtt(p, mem); + + /* Does the entry exist? */ + if (NULL == entry) { + debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found"); + neighborCountIgnored(p); + return; + } + + /* check if someone is already fetching it */ + if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) { + debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched."); + neighborCountIgnored(p); + return; + } + + if (mem == NULL) { + debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key)); + neighborCountIgnored(p); + return; + } + + if (entry->ping_status != PING_WAITING) { + debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key)); + neighborCountIgnored(p); + return; + } + + if (entry->lock_count == 0) { + debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks"); + neighborCountIgnored(p); + return; + } + + debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " "); + + if (p) { + ntype = neighborType(p, mem->request); + } + + if (ignoreMulticastReply(p, mem)) { + neighborCountIgnored(p); + } else if (opcode == ICP_MISS) { + if (p == NULL) { + neighborIgnoreNonPeer(from, opcode); + } else { + mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data); + } + } else if (opcode == ICP_HIT) { + if (p == NULL) { + neighborIgnoreNonPeer(from, opcode); + } else { + header->opcode = ICP_HIT; + mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data); + } + } else if (opcode == ICP_DECHO) { + if (p == NULL) { + neighborIgnoreNonPeer(from, opcode); + } else if (ntype == PEER_SIBLING) { + debug_trap("neighborsUdpAck: Found non-ICP cache as SIBLING\n"); + debug_trap("neighborsUdpAck: non-ICP neighbors must be a PARENT\n"); + } else { + mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data); + } + } else if (opcode == ICP_SECHO) { + if (p) { + debugs(15, 1, "Ignoring SECHO from neighbor " << p->host); + neighborCountIgnored(p); + } else { + debugs(15, 1, "Unsolicited SECHO from " << from); + } + } else if (opcode == ICP_DENIED) { + if (p == NULL) { + neighborIgnoreNonPeer(from, opcode); + } else if (p->stats.pings_acked > 100) { + if (100 * p->icp.counts[ICP_DENIED] / p->stats.pings_acked > 95) { + debugs(15, 0, "95%% of replies from '" << p->host << "' are UDP_DENIED"); + debugs(15, 0, "Disabling '" << p->host << "', please check your configuration."); + neighborRemove(p); + p = NULL; + } else { + neighborCountIgnored(p); + } + } + } else if (opcode == ICP_MISS_NOFETCH) { + mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data); + } else { + debugs(15, 0, "neighborsUdpAck: Unexpected ICP reply: " << opcode_d); + } +} + +peer * +peerFindByName(const char *name) +{ + peer *p = NULL; + + for (p = Config.peers; p; p = p->next) { + if (!strcasecmp(name, p->name)) + break; + } + + return p; +} + +peer * +peerFindByNameAndPort(const char *name, unsigned short port) +{ + peer *p = NULL; + + for (p = Config.peers; p; p = p->next) { + if (strcasecmp(name, p->name)) + continue; + + if (port != p->http_port) + continue; + + break; + } + + return p; +} + +int +neighborUp(const peer * p) +{ + if (!p->tcp_up) { + if (!peerProbeConnect((peer *) p)) { + debugs(15, 8, "neighborUp: DOWN (probed): " << p->host << " (" << p->in_addr << ")"); + return 0; + } + } + + /* + * The peer can not be UP if we don't have any IP addresses + * for it. + */ + if (0 == p->n_addresses) { + debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")"); + return 0; + } + + if (p->options.no_query) { + debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")"); + return 1; + } + + if (p->stats.probe_start != 0 && + squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer) { + debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")"); + return 0; + } + + debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")"); + return 1; +} + +void +peerDestroy(void *data) +{ + peer *p = (peer *)data; + + struct _domain_ping *l = NULL; + + struct _domain_ping *nl = NULL; + + if (p == NULL) + return; + + for (l = p->peer_domain; l; l = nl) { + nl = l->next; + safe_free(l->domain); + safe_free(l); + } + + safe_free(p->host); + safe_free(p->name); + safe_free(p->domain); +#if USE_CACHE_DIGESTS + + cbdataReferenceDone(p->digest); +#endif +} + +void +peerNoteDigestGone(peer * p) +{ +#if USE_CACHE_DIGESTS + cbdataReferenceDone(p->digest); +#endif +} + +static void +peerDNSConfigure(const ipcache_addrs *ia, const DnsLookupDetails &, void *data) +{ + peer *p = (peer *)data; + + int j; + + if (p->n_addresses == 0) { + debugs(15, 1, "Configuring " << neighborTypeStr(p) << " " << p->host << "/" << p->http_port << "/" << p->icp.port); + + if (p->type == PEER_MULTICAST) + debugs(15, 1, " Multicast TTL = " << p->mcast.ttl); + } + + p->n_addresses = 0; + + if (ia == NULL) { + debugs(0, 0, "WARNING: DNS lookup for '" << p->host << "' failed!"); + return; + } + + if ((int) ia->count < 1) { + debugs(0, 0, "WARNING: No IP address found for '" << p->host << "'!"); + return; + } + + p->tcp_up = p->connect_fail_limit; + + for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) { + p->addresses[j] = ia->in_addrs[j]; + debugs(15, 2, "--> IP address #" << j << ": " << p->addresses[j]); + p->n_addresses++; + } + + p->in_addr.SetEmpty(); + p->in_addr = p->addresses[0]; + p->in_addr.SetPort(p->icp.port); + + if (p->type == PEER_MULTICAST) + peerCountMcastPeersSchedule(p, 10); + +#if USE_ICMP + if (p->type != PEER_MULTICAST) + if (!p->options.no_netdb_exchange) + eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1); +#endif + +} + +static void +peerRefreshDNS(void *data) +{ + peer *p = NULL; + + if (eventFind(peerRefreshDNS, NULL)) + eventDelete(peerRefreshDNS, NULL); + + if (!data && 0 == stat5minClientRequests()) { + /* no recent client traffic, wait a bit */ + eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 180.0, 1); + return; + } + + for (p = Config.peers; p; p = p->next) + ipcache_nbgethostbyname(p->host, peerDNSConfigure, p); + + /* Reconfigure the peers every hour */ + eventAddIsh("peerRefreshDNS", peerRefreshDNS, NULL, 3600.0, 1); +} + +static void +peerConnectFailedSilent(peer * p) +{ + p->stats.last_connect_failure = squid_curtime; + + if (!p->tcp_up) { + debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << + " dead"); + return; + } + + p->tcp_up--; + + if (!p->tcp_up) { + debugs(15, 1, "Detected DEAD " << neighborTypeStr(p) << ": " << p->name); + p->stats.logged_state = PEER_DEAD; + } +} + +void +peerConnectFailed(peer *p) +{ + debugs(15, 1, "TCP connection to " << p->host << "/" << p->http_port << " failed"); + peerConnectFailedSilent(p); +} + +void +peerConnectSucceded(peer * p) +{ + if (!p->tcp_up) { + debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeded"); + p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly. + peerAlive(p); + if (!p->n_addresses) + ipcache_nbgethostbyname(p->host, peerDNSConfigure, p); + } else + p->tcp_up = p->connect_fail_limit; +} + +/// called by Comm when test_fd is closed while connect is in progress +static void +peerProbeClosed(int fd, void *data) +{ + peer *p = (peer*)data; + p->test_fd = -1; + // it is a failure because we failed to connect + peerConnectFailedSilent(p); +} + +static void +peerProbeConnectTimeout(int fd, void *data) +{ + peer * p = (peer *)data; + comm_remove_close_handler(fd, &peerProbeClosed, p); + comm_close(fd); + p->test_fd = -1; + peerConnectFailedSilent(p); +} + +/* +* peerProbeConnect will be called on dead peers by neighborUp +*/ +static int +peerProbeConnect(peer * p) +{ + int fd; + time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout + : Config.Timeout.peer_connect; + int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10; + + if (p->test_fd != -1) + return ret;/* probe already running */ + + if (squid_curtime - p->stats.last_connect_probe == 0) + return ret;/* don't probe to often */ + + Ip::Address temp(getOutgoingAddr(NULL,p)); + + fd = comm_open(SOCK_STREAM, IPPROTO_TCP, temp, COMM_NONBLOCKING, p->host); + + if (fd < 0) + return ret; + + comm_add_close_handler(fd, &peerProbeClosed, p); + commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p); + + p->test_fd = fd; + + p->stats.last_connect_probe = squid_curtime; + + commConnectStart(p->test_fd, + p->host, + p->http_port, + peerProbeConnectDone, + p); + + return ret; +} + +static void +peerProbeConnectDone(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data) +{ + peer *p = (peer*)data; + + if (status == COMM_OK) { + peerConnectSucceded(p); + } else { + peerConnectFailedSilent(p); + } + + comm_remove_close_handler(fd, &peerProbeClosed, p); + comm_close(fd); + p->test_fd = -1; + return; +} + +static void +peerCountMcastPeersSchedule(peer * p, time_t when) +{ + if (p->mcast.flags.count_event_pending) + return; + + eventAdd("peerCountMcastPeersStart", + peerCountMcastPeersStart, + p, + (double) when, 1); + + p->mcast.flags.count_event_pending = 1; +} + +static void +peerCountMcastPeersStart(void *data) +{ + peer *p = (peer *)data; + ps_state *psstate; + StoreEntry *fake; + MemObject *mem; + icp_common_t *query; + int reqnum; + LOCAL_ARRAY(char, url, MAX_URL); + assert(p->type == PEER_MULTICAST); + p->mcast.flags.count_event_pending = 0; + snprintf(url, MAX_URL, "http://"); + p->in_addr.ToURL(url+7, MAX_URL -8 ); + strcat(url, "/"); + fake = storeCreateEntry(url, url, request_flags(), METHOD_GET); + HttpRequest *req = HttpRequest::CreateFromUrl(url); + psstate = new ps_state; + psstate->request = HTTPMSGLOCK(req); + psstate->entry = fake; + psstate->callback = NULL; + psstate->callback_data = cbdataReference(p); + psstate->ping.start = current_time; + mem = fake->mem_obj; + mem->request = HTTPMSGLOCK(psstate->request); + mem->start_ping = current_time; + mem->ping_reply_callback = peerCountHandleIcpReply; + mem->ircb_data = psstate; + mcastSetTtl(theOutIcpConnection, p->mcast.ttl); + p->mcast.id = mem->id; + reqnum = icpSetCacheKey((const cache_key *)fake->key); + query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0); + icpUdpSend(theOutIcpConnection, + p->in_addr, + query, + LOG_ICP_QUERY, + 0); + fake->ping_status = PING_WAITING; + eventAdd("peerCountMcastPeersDone", + peerCountMcastPeersDone, + psstate, + Config.Timeout.mcast_icp_query / 1000.0, 1); + p->mcast.flags.counting = 1; + peerCountMcastPeersSchedule(p, MCAST_COUNT_RATE); +} + +static void +peerCountMcastPeersDone(void *data) +{ + ps_state *psstate = (ps_state *)data; + StoreEntry *fake = psstate->entry; + + if (cbdataReferenceValid(psstate->callback_data)) { + peer *p = (peer *)psstate->callback_data; + p->mcast.flags.counting = 0; + p->mcast.avg_n_members = Math::doubleAverage(p->mcast.avg_n_members, (double) psstate->ping.n_recv, ++p->mcast.n_times_counted, 10); + debugs(15, 1, "Group " << p->host << ": " << psstate->ping.n_recv << + " replies, "<< std::setw(4)<< std::setprecision(2) << + p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt); + p->mcast.n_replies_expected = (int) p->mcast.avg_n_members; + } + + cbdataReferenceDone(psstate->callback_data); + + EBIT_SET(fake->flags, ENTRY_ABORTED); + HTTPMSGUNLOCK(fake->mem_obj->request); + fake->releaseRequest(); + fake->unlock(); + HTTPMSGUNLOCK(psstate->request); + cbdataFree(psstate); +} + +static void +peerCountHandleIcpReply(peer * p, peer_t type, protocol_t proto, void *hdrnotused, void *data) +{ + int rtt_av_factor; + + ps_state *psstate = (ps_state *)data; + StoreEntry *fake = psstate->entry; + MemObject *mem = fake->mem_obj; + int rtt = tvSubMsec(mem->start_ping, current_time); + assert(proto == PROTO_ICP); + assert(fake); + assert(mem); + psstate->ping.n_recv++; + rtt_av_factor = RTT_AV_FACTOR; + + if (p->options.weighted_roundrobin) + rtt_av_factor = RTT_BACKGROUND_AV_FACTOR; + + p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor); +} + +static void +neighborDumpPeers(StoreEntry * sentry) +{ + dump_peers(sentry, Config.peers); +} + +static void +neighborDumpNonPeers(StoreEntry * sentry) +{ + dump_peers(sentry, non_peers); +} + +void +dump_peer_options(StoreEntry * sentry, peer * p) +{ + if (p->options.proxy_only) + storeAppendPrintf(sentry, " proxy-only"); + + if (p->options.no_query) + storeAppendPrintf(sentry, " no-query"); + + if (p->options.background_ping) + storeAppendPrintf(sentry, " background-ping"); + + if (p->options.no_digest) + storeAppendPrintf(sentry, " no-digest"); + + if (p->options.default_parent) + storeAppendPrintf(sentry, " default"); + + if (p->options.roundrobin) + storeAppendPrintf(sentry, " round-robin"); + + if (p->options.carp) + storeAppendPrintf(sentry, " carp"); + + if (p->options.userhash) + storeAppendPrintf(sentry, " userhash"); + + if (p->options.userhash) + storeAppendPrintf(sentry, " sourcehash"); + + if (p->options.weighted_roundrobin) + storeAppendPrintf(sentry, " weighted-round-robin"); + + if (p->options.mcast_responder) + storeAppendPrintf(sentry, " multicast-responder"); + +#if PEER_MULTICAST_SIBLINGS + if (p->options.mcast_siblings) + storeAppendPrintf(sentry, " multicast-siblings"); +#endif + + if (p->weight != 1) + storeAppendPrintf(sentry, " weight=%d", p->weight); + + if (p->options.closest_only) + storeAppendPrintf(sentry, " closest-only"); + +#if USE_HTCP + if (p->options.htcp) + storeAppendPrintf(sentry, " htcp"); + if (p->options.htcp_oldsquid) + storeAppendPrintf(sentry, " htcp-oldsquid"); + if (p->options.htcp_no_clr) + storeAppendPrintf(sentry, " htcp-no-clr"); + if (p->options.htcp_no_purge_clr) + storeAppendPrintf(sentry, " htcp-no-purge-clr"); + if (p->options.htcp_only_clr) + storeAppendPrintf(sentry, " htcp-only-clr"); +#endif + + if (p->options.no_netdb_exchange) + storeAppendPrintf(sentry, " no-netdb-exchange"); + +#if DELAY_POOLS + + if (p->options.no_delay) + storeAppendPrintf(sentry, " no-delay"); + +#endif + + if (p->login) + storeAppendPrintf(sentry, " login=%s", p->login); + + if (p->mcast.ttl > 0) + storeAppendPrintf(sentry, " ttl=%d", p->mcast.ttl); + + if (p->connect_timeout > 0) + storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout); + + if (p->connect_fail_limit != PEER_TCP_MAGIC_COUNT) + storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit); + +#if USE_CACHE_DIGESTS + + if (p->digest_url) + storeAppendPrintf(sentry, " digest-url=%s", p->digest_url); + +#endif + + if (p->options.allow_miss) + storeAppendPrintf(sentry, " allow-miss"); + + if (p->options.no_tproxy) + storeAppendPrintf(sentry, " no-tproxy"); + + if (p->max_conn > 0) + storeAppendPrintf(sentry, " max-conn=%d", p->max_conn); + + if (p->options.originserver) + storeAppendPrintf(sentry, " originserver"); + + if (p->domain) + storeAppendPrintf(sentry, " forceddomain=%s", p->domain); + + if (p->connection_auth == 0) + storeAppendPrintf(sentry, " connection-auth=off"); + else if (p->connection_auth == 1) + storeAppendPrintf(sentry, " connection-auth=on"); + else if (p->connection_auth == 2) + storeAppendPrintf(sentry, " connection-auth=auto"); + + storeAppendPrintf(sentry, "\n"); +} + +static void +dump_peers(StoreEntry * sentry, peer * peers) +{ + peer *e = NULL; + char ntoabuf[MAX_IPSTRLEN]; + struct _domain_ping *d = NULL; + icp_opcode op; + int i; + + if (peers == NULL) + storeAppendPrintf(sentry, "There are no neighbors installed.\n"); + + for (e = peers; e; e = e->next) { + assert(e->host != NULL); + storeAppendPrintf(sentry, "\n%-11.11s: %s\n", + neighborTypeStr(e), + e->name); + storeAppendPrintf(sentry, "Host : %s/%d/%d\n", + e->host, + e->http_port, + e->icp.port); + storeAppendPrintf(sentry, "Flags :"); + dump_peer_options(sentry, e); + + for (i = 0; i < e->n_addresses; i++) { + storeAppendPrintf(sentry, "Address[%d] : %s\n", i, + e->addresses[i].NtoA(ntoabuf,MAX_IPSTRLEN) ); + } + + storeAppendPrintf(sentry, "Status : %s\n", + neighborUp(e) ? "Up" : "Down"); + storeAppendPrintf(sentry, "FETCHES : %d\n", e->stats.fetches); + storeAppendPrintf(sentry, "OPEN CONNS : %d\n", e->stats.conn_open); + storeAppendPrintf(sentry, "AVG RTT : %d msec\n", e->stats.rtt); + + if (!e->options.no_query) { + storeAppendPrintf(sentry, "LAST QUERY : %8d seconds ago\n", + (int) (squid_curtime - e->stats.last_query)); + + if (e->stats.last_reply > 0) + storeAppendPrintf(sentry, "LAST REPLY : %8d seconds ago\n", + (int) (squid_curtime - e->stats.last_reply)); + else + storeAppendPrintf(sentry, "LAST REPLY : none received\n"); + + storeAppendPrintf(sentry, "PINGS SENT : %8d\n", e->stats.pings_sent); + + storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n", + e->stats.pings_acked, + Math::intPercent(e->stats.pings_acked, e->stats.pings_sent)); + } + + storeAppendPrintf(sentry, "IGNORED : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked)); + + if (!e->options.no_query) { + storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n"); +#if USE_HTCP + + if (e->options.htcp) { + storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n", + e->htcp.counts[0], + Math::intPercent(e->htcp.counts[0], e->stats.pings_acked)); + storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n", + e->htcp.counts[1], + Math::intPercent(e->htcp.counts[1], e->stats.pings_acked)); + } else { +#endif + + for (op = ICP_INVALID; op < ICP_END; ++op) { + if (e->icp.counts[op] == 0) + continue; + + storeAppendPrintf(sentry, " %12.12s : %8d %3d%%\n", + icp_opcode_str[op], + e->icp.counts[op], + Math::intPercent(e->icp.counts[op], e->stats.pings_acked)); + } + +#if USE_HTCP + + } + +#endif + + } + + if (e->stats.last_connect_failure) { + storeAppendPrintf(sentry, "Last failed connect() at: %s\n", + mkhttpdlogtime(&(e->stats.last_connect_failure))); + } + + if (e->peer_domain != NULL) { + storeAppendPrintf(sentry, "DOMAIN LIST: "); + + for (d = e->peer_domain; d; d = d->next) { + storeAppendPrintf(sentry, "%s%s ", + d->do_ping ? null_string : "!", d->domain); + } + + storeAppendPrintf(sentry, "\n"); + } + + storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent)); + } +} + +#if USE_HTCP +void +neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const Ip::Address &from) +{ + StoreEntry *e = Store::Root().get(key); + MemObject *mem = NULL; + peer *p; + peer_t ntype = PEER_NONE; + debugs(15, 6, "neighborsHtcpReply: " << + (htcp->hit ? "HIT" : "MISS") << " " << + storeKeyText(key) ); + + if (NULL != e) + mem = e->mem_obj; + + if ((p = whichPeer(from))) + neighborAliveHtcp(p, mem, htcp); + + /* Does the entry exist? */ + if (NULL == e) { + debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found"); + neighborCountIgnored(p); + return; + } + + /* check if someone is already fetching it */ + if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) { + debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched."); + neighborCountIgnored(p); + return; + } + + if (mem == NULL) { + debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key)); + neighborCountIgnored(p); + return; + } + + if (e->ping_status != PING_WAITING) { + debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING"); + neighborCountIgnored(p); + return; + } + + if (e->lock_count == 0) { + debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks"); + neighborCountIgnored(p); + return; + } + + if (p) { + ntype = neighborType(p, mem->request); + neighborUpdateRtt(p, mem); + } + + if (ignoreMulticastReply(p, mem)) { + neighborCountIgnored(p); + return; + } + + debugs(15, 3, "neighborsHtcpReply: e = " << e); + mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data); +} + +/* + * Send HTCP CLR messages to all peers configured to receive them. + */ +void +neighborsHtcpClear(StoreEntry * e, const char *uri, HttpRequest * req, const HttpRequestMethod &method, htcp_clr_reason reason) +{ + peer *p; + char buf[128]; + + for (p = Config.peers; p; p = p->next) { + if (!p->options.htcp) { + continue; + } + if (p->options.htcp_no_clr) { + continue; + } + if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) { + continue; + } + debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.ToURL(buf, 128)); + htcpClear(e, uri, req, method, p, reason); + } +} + +#endif === modified file 'src/structs.h' --- src/structs.h 2010-04-17 02:29:04 +0000 +++ src/structs.h 2010-05-18 20:24:54 +0000 @@ -1,1308 +1,1309 @@ -/* - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; 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. - * - */ -#ifndef SQUID_STRUCTS_H -#define SQUID_STRUCTS_H - -#include "config.h" -#include "RefCount.h" -#include "cbdata.h" -#include "dlink.h" -#include "err_type.h" - -/* needed for the global config */ -#include "HttpHeader.h" - -/* for ICP_END */ -#include "icp_opcode.h" - -#define PEER_MULTICAST_SIBLINGS 1 - -struct acl_name_list { - char name[ACL_NAME_SZ]; - acl_name_list *next; -}; - -struct acl_deny_info_list { - err_type err_page_id; - char *err_page_name; - acl_name_list *acl_list; - acl_deny_info_list *next; -}; - - -class acl_access; - -struct _header_mangler { - acl_access *access_list; - char *replacement; -}; - -class ACLChecklist; - -#if SQUID_SNMP - -struct _snmp_request_t { - u_char *buf; - u_char *outbuf; - int len; - int sock; - long reqid; - int outlen; - - Ip::Address from; - - struct snmp_pdu *PDU; - ACLChecklist *acl_checklist; - u_char *community; - - struct snmp_session session; -}; - -#endif - -class ACLList; - -struct acl_address { - acl_address *next; - ACLList *aclList; - - Ip::Address addr; -}; - -struct acl_tos { - acl_tos *next; - ACLList *aclList; - int tos; -}; - -struct acl_size_t { - acl_size_t *next; - ACLList *aclList; - int64_t size; -}; - -struct ushortlist { - u_short i; - ushortlist *next; -}; - -struct relist { - char *pattern; - regex_t regex; - relist *next; -}; - -#if DELAY_POOLS -#include "DelayConfig.h" -#endif - -#if USE_ICMP -#include "icmp/IcmpConfig.h" -#endif - -#include "HelperChildConfig.h" - -/* forward decl for SquidConfig, see RemovalPolicy.h */ - -class RemovalPolicySettings; -class external_acl; -class Store; - -struct SquidConfig { - - struct { - /* These should be for the Store::Root instance. - * this needs pluggable parsing to be done smoothly. - */ - int highWaterMark; - int lowWaterMark; - } Swap; - size_t memMaxSize; - - struct { - int64_t min; - int pct; - int64_t max; - } quickAbort; - int64_t readAheadGap; - RemovalPolicySettings *replPolicy; - RemovalPolicySettings *memPolicy; -#if HTTP_VIOLATIONS - time_t negativeTtl; -#endif - time_t negativeDnsTtl; - time_t positiveDnsTtl; - time_t shutdownLifetime; - time_t backgroundPingRate; - - struct { - time_t read; - time_t write; - time_t lifetime; - time_t connect; - time_t forward; - time_t peer_connect; - time_t request; - time_t persistent_request; - time_t pconn; - time_t siteSelect; - time_t deadPeer; - int icp_query; /* msec */ - int icp_query_max; /* msec */ - int icp_query_min; /* msec */ - int mcast_icp_query; /* msec */ - -#if !USE_DNSSERVERS - - time_t idns_retransmit; - time_t idns_query; -#endif - - } Timeout; - size_t maxRequestHeaderSize; - int64_t maxRequestBodySize; - int64_t maxChunkedRequestBodySize; - size_t maxReplyHeaderSize; - acl_size_t *ReplyBodySize; - - struct { - u_short icp; -#if USE_HTCP - - u_short htcp; -#endif -#if SQUID_SNMP - - u_short snmp; -#endif - } Port; - - struct { - http_port_list *http; -#if USE_SSL - - https_port_list *https; -#endif - - } Sockaddr; -#if SQUID_SNMP - - struct { - char *configFile; - char *agentInfo; - } Snmp; -#endif -#if USE_WCCP - - struct { - Ip::Address router; - Ip::Address address; - int version; - } Wccp; -#endif -#if USE_WCCPv2 - - struct { - Ip::Address_list *router; - Ip::Address address; - int forwarding_method; - int return_method; - int assignment_method; - int weight; - int rebuildwait; - void *info; - } Wccp2; -#endif - -#if USE_ICMP - IcmpConfig pinger; -#endif - - char *as_whois_server; - - struct { - char *store; - char *swap; -#if USE_USERAGENT_LOG - - char *useragent; -#endif -#if USE_REFERER_LOG - - char *referer; -#endif -#if WIP_FWD_LOG - - char *forward; -#endif - - logformat *logformats; - - customlog *accesslogs; - -#if ICAP_CLIENT - customlog *icaplogs; -#endif - - int rotateNumber; - } Log; - char *adminEmail; - char *EmailFrom; - char *EmailProgram; - char *effectiveUser; - char *visible_appname_string; - char *effectiveGroup; - - struct { -#if USE_DNSSERVERS - char *dnsserver; -#endif - - wordlist *redirect; -#if USE_UNLINKD - - char *unlinkd; -#endif - - char *diskd; -#if USE_SSL - - char *ssl_password; -#endif - - } Program; -#if USE_DNSSERVERS - - HelperChildConfig dnsChildren; -#endif - - HelperChildConfig redirectChildren; - time_t authenticateGCInterval; - time_t authenticateTTL; - time_t authenticateIpTTL; - - struct { - char *surrogate_id; - } Accel; - char *appendDomain; - size_t appendDomainLen; - char *pidFilename; - char *netdbFilename; - char *mimeTablePathname; - char *etcHostsPath; - char *visibleHostname; - char *uniqueHostname; - wordlist *hostnameAliases; - char *errHtmlText; - - struct { - char *host; - char *file; - time_t period; - u_short port; - } Announce; - - struct { - - Ip::Address udp_incoming; - Ip::Address udp_outgoing; -#if SQUID_SNMP - Ip::Address snmp_incoming; - Ip::Address snmp_outgoing; -#endif - /* FIXME INET6 : this should really be a CIDR value */ - Ip::Address client_netmask; - } Addrs; - size_t tcpRcvBufsz; - size_t udpMaxHitObjsz; - wordlist *hierarchy_stoplist; - wordlist *mcast_group_list; - wordlist *dns_nameservers; - peer *peers; - int npeers; - - struct { - int size; - int low; - int high; - } ipcache; - - struct { - int size; - } fqdncache; - int minDirectHops; - int minDirectRtt; - cachemgr_passwd *passwd_list; - - struct { - int objectsPerBucket; - int64_t avgObjectSize; - int64_t maxObjectSize; - int64_t minObjectSize; - size_t maxInMemObjSize; - } Store; - - struct { - int high; - int low; - time_t period; - } Netdb; - - struct { - int log_udp; - int res_defnames; - int anonymizer; - int client_db; - int query_icmp; - int icp_hit_stale; - int buffered_logs; - int common_log; - int log_mime_hdrs; - int log_fqdn; - int announce; - int mem_pools; - int test_reachability; - int half_closed_clients; - int refresh_all_ims; -#if HTTP_VIOLATIONS - - int reload_into_ims; - int ignore_expect_100; -#endif - - int offline; - int redir_rewrites_host; - int prefer_direct; - int nonhierarchical_direct; - int strip_query_terms; - int redirector_bypass; - int ignore_unknown_nameservers; - int client_pconns; - int server_pconns; - int error_pconns; -#if USE_CACHE_DIGESTS - - int digest_generation; -#endif - - int log_ip_on_direct; - int ie_refresh; - int vary_ignore_expire; - int pipeline_prefetch; - int surrogate_is_remote; - int request_entities; - int detect_broken_server_pconns; - int balance_on_multiple_ip; - int relaxed_header_parser; - int check_hostnames; - int allow_underscore; - int via; - int emailErrData; - int httpd_suppress_version_string; - int global_internal_static; - int dns_require_A; - -#if FOLLOW_X_FORWARDED_FOR - int acl_uses_indirect_client; - int delay_pool_uses_indirect_client; - int log_uses_indirect_client; -#endif /* FOLLOW_X_FORWARDED_FOR */ - - int WIN32_IpAddrChangeMonitor; - int memory_cache_first; - int memory_cache_disk; - } onoff; - - int forward_max_tries; - - class ACL *aclList; - - struct { - acl_access *http; - acl_access *adapted_http; - acl_access *icp; - acl_access *miss; - acl_access *NeverDirect; - acl_access *AlwaysDirect; - acl_access *ASlists; - acl_access *noCache; - acl_access *log; -#if SQUID_SNMP - - acl_access *snmp; -#endif -#if HTTP_VIOLATIONS - acl_access *brokenPosts; -#endif - acl_access *redirector; - acl_access *reply; - acl_address *outgoing_address; - acl_tos *outgoing_tos; - acl_tos *clientside_tos; -#if USE_HTCP - - acl_access *htcp; - acl_access *htcp_clr; -#endif - -#if USE_SSL - acl_access *ssl_bump; -#endif -#if FOLLOW_X_FORWARDED_FOR - acl_access *followXFF; -#endif /* FOLLOW_X_FORWARDED_FOR */ - -#if ICAP_CLIENT - acl_access* icap; -#endif - } accessList; - acl_deny_info_list *denyInfoList; - authConfig authConfiguration; - - struct { - size_t list_width; - int list_wrap; - char *anon_user; - int passive; - int epsv_all; - int epsv; - int sanitycheck; - int telnet; - } Ftp; - refresh_t *Refresh; - - struct _cacheSwap { - RefCount *swapDirs; - int n_allocated; - int n_configured; - } cacheSwap; - /* - * I'm sick of having to keep doing this .. - */ -#define INDEXSD(i) (Config.cacheSwap.swapDirs[(i)].getRaw()) - - struct { - char *directory; - int use_short_names; - } icons; - char *errorDirectory; -#if USE_ERR_LOCALES - char *errorDefaultLanguage; - int errorLogMissingLanguages; -#endif - char *errorStylesheet; - - struct { - int maxtries; - int onerror; - } retry; - - struct { - size_t limit; - } MemPools; -#if DELAY_POOLS - - DelayConfig Delay; -#endif - - struct { - int icp_average; - int dns_average; - int http_average; - int icp_min_poll; - int dns_min_poll; - int http_min_poll; - } comm_incoming; - int max_open_disk_fds; - int uri_whitespace; - acl_size_t *rangeOffsetLimit; -#if MULTICAST_MISS_STREAM - - struct { - - Ip::Address addr; - int ttl; - unsigned short port; - char *encode_key; - } mcast_miss; -#endif - - /* one access list per header type we know of */ - header_mangler request_header_access[HDR_ENUM_END]; - /* one access list per header type we know of */ - header_mangler reply_header_access[HDR_ENUM_END]; - char *coredump_dir; - char *chroot_dir; -#if USE_CACHE_DIGESTS - - struct { - int bits_per_entry; - time_t rebuild_period; - time_t rewrite_period; - size_t swapout_chunk_size; - int rebuild_chunk_percentage; - } digest; -#endif -#if USE_SSL - - struct { - int unclean_shutdown; - char *ssl_engine; - } SSL; -#endif - - wordlist *ext_methods; - - struct { - int high_rptm; - int high_pf; - size_t high_memory; - } warnings; - char *store_dir_select_algorithm; - int sleep_after_fork; /* microseconds */ - time_t minimum_expiry_time; /* seconds */ - external_acl *externalAclHelperList; - -#if USE_SSL - - struct { - char *cert; - char *key; - int version; - char *options; - char *cipher; - char *cafile; - char *capath; - char *crlfile; - char *flags; - acl_access *cert_error; - SSL_CTX *sslContext; - } ssl_client; -#endif - - char *accept_filter; - int umask; - -#if USE_LOADABLE_MODULES - wordlist *loadable_module_names; -#endif - - int client_ip_max_connections; -}; - -SQUIDCEXTERN SquidConfig Config; - -struct SquidConfig2 { - struct { - int enable_purge; - int mangle_request_headers; - } onoff; - uid_t effectiveUserID; - gid_t effectiveGroupID; -}; - -SQUIDCEXTERN SquidConfig2 Config2; - -struct _close_handler { - PF *handler; - void *data; - close_handler *next; -}; - -struct _dread_ctrl { - int fd; - off_t offset; - int req_len; - char *buf; - int end_of_file; - DRCB *handler; - void *client_data; -}; - -struct _dwrite_q { - off_t file_offset; - char *buf; - size_t len; - size_t buf_offset; - dwrite_q *next; - FREE *free_func; -}; - - -/* ETag support is rudimantal; - * this struct is likely to change - * Note: "str" points to memory in HttpHeaderEntry (for now) - * so ETags should be used as tmp variables only (for now) */ - -struct _ETag { - const char *str; /* quoted-string */ - int weak; /* true if it is a weak validator */ -}; - -struct _fde_disk { - DWCB *wrt_handle; - void *wrt_handle_data; - dwrite_q *write_q; - dwrite_q *write_q_tail; - off_t offset; -}; - -struct _fileMap { - int max_n_files; - int n_files_in_map; - int toggle; - int nwords; - unsigned long *file_map; -}; - -/* - * Note: HttpBody is used only for messages with a small content that is - * known a priory (e.g., error messages). - */ - -class MemBuf; - -struct _HttpBody { - /* private */ - MemBuf *mb; -}; - -#include "SquidString.h" -/* http header extention field */ - -class HttpHdrExtField -{ - String name; /* field-name from HTTP/1.1 (no column after name) */ - String value; /* field-value from HTTP/1.1 */ -}; - -/* http cache control header field */ - -class HttpHdrCc -{ - -public: - int mask; - int max_age; - int s_maxage; - int max_stale; - String other; -}; - -/* some fields can hold either time or etag specs (e.g. If-Range) */ - -struct _TimeOrTag { - ETag tag; /* entity tag */ - time_t time; - int valid; /* true if struct is usable */ -}; - -/* per field statistics */ - -class HttpHeaderFieldStat -{ - -public: - HttpHeaderFieldStat() : aliveCount(0), seenCount(0), parsCount(0), errCount(0), repCount(0) {} - - int aliveCount; /* created but not destroyed (count) */ - int seenCount; /* #fields we've seen */ - int parsCount; /* #parsing attempts */ - int errCount; /* #pasring errors */ - int repCount; /* #repetitons */ -}; - -/* compiled version of HttpHeaderFieldAttrs plus stats */ - -class HttpHeaderFieldInfo -{ - -public: - HttpHeaderFieldInfo() : id (HDR_ACCEPT), type (ftInvalid) {} - - http_hdr_type id; - String name; - field_type type; - HttpHeaderFieldStat stat; -}; - -struct _http_state_flags { - unsigned int proxying:1; - unsigned int keepalive:1; - unsigned int only_if_cached:1; - unsigned int headers_parsed:1; - unsigned int front_end_https:2; - unsigned int originpeer:1; - unsigned int keepalive_broken:1; - unsigned int abuse_detected:1; - unsigned int request_sent:1; - unsigned int do_next_read:1; - unsigned int consume_body_data:1; - unsigned int chunked:1; -}; - -struct _ipcache_addrs { - Ip::Address *in_addrs; - unsigned char *bad_mask; - unsigned char count; - unsigned char cur; - unsigned char badcount; -}; - -struct _domain_ping { - char *domain; - int do_ping; /* boolean */ - domain_ping *next; -}; - -struct _domain_type { - char *domain; - peer_t type; - domain_type *next; -}; - -#if USE_CACHE_DIGESTS - -/* statistics for cache digests and other hit "predictors" */ - -struct _cd_guess_stats { - /* public, read-only */ - int true_hits; - int false_hits; - int true_misses; - int false_misses; - int close_hits; /* tmp, remove it later */ -}; - -#endif - -class PeerDigest; - -struct peer { - u_int index; - char *name; - char *host; - peer_t type; - - Ip::Address in_addr; - - struct { - int pings_sent; - int pings_acked; - int fetches; - int rtt; - int ignored_replies; - int n_keepalives_sent; - int n_keepalives_recv; - time_t probe_start; - time_t last_query; - time_t last_reply; - time_t last_connect_failure; - time_t last_connect_probe; - int logged_state; /* so we can print dead/revived msgs */ - int conn_open; /* current opened connections */ - } stats; - - struct { - int version; - int counts[ICP_END+1]; - u_short port; - } icp; - -#if USE_HTCP - struct { - double version; - int counts[2]; - u_short port; - } htcp; -#endif - - u_short http_port; - domain_ping *peer_domain; - domain_type *typelist; - acl_access *access; - - struct { - unsigned int proxy_only:1; - unsigned int no_query:1; - unsigned int background_ping:1; - unsigned int no_digest:1; - unsigned int default_parent:1; - unsigned int roundrobin:1; - unsigned int weighted_roundrobin:1; - unsigned int mcast_responder:1; - unsigned int closest_only:1; -#if USE_HTCP - unsigned int htcp:1; - unsigned int htcp_oldsquid:1; - unsigned int htcp_no_clr:1; - unsigned int htcp_no_purge_clr:1; - unsigned int htcp_only_clr:1; - unsigned int htcp_forward_clr:1; -#endif - unsigned int no_netdb_exchange:1; -#if DELAY_POOLS - unsigned int no_delay:1; -#endif - unsigned int allow_miss:1; - unsigned int carp:1; - unsigned int userhash:1; - unsigned int sourcehash:1; - unsigned int originserver:1; - unsigned int no_tproxy:1; -#if PEER_MULTICAST_SIBLINGS - unsigned int mcast_siblings:1; -#endif - } options; - - int weight; - int basetime; - - struct { - double avg_n_members; - int n_times_counted; - int n_replies_expected; - int ttl; - int id; - - struct { - unsigned int count_event_pending:1; - unsigned int counting:1; - } flags; - } mcast; -#if USE_CACHE_DIGESTS - - PeerDigest *digest; - char *digest_url; -#endif - - int tcp_up; /* 0 if a connect() fails */ - - Ip::Address addresses[10]; - int n_addresses; - int rr_count; - peer *next; - int test_fd; - - struct { - unsigned int hash; - double load_multiplier; - double load_factor; /* normalized weight value */ - } carp; - - struct { - unsigned int hash; - double load_multiplier; - double load_factor; /* normalized weight value */ - } userhash; - - struct { - unsigned int hash; - double load_multiplier; - double load_factor; /* normalized weight value */ - } sourcehash; - - char *login; /* Proxy authorization */ - time_t connect_timeout; - int connect_fail_limit; - int max_conn; - char *domain; /* Forced domain */ -#if USE_SSL - - int use_ssl; - char *sslcert; - char *sslkey; - int sslversion; - char *ssloptions; - char *sslcipher; - char *sslcafile; - char *sslcapath; - char *sslcrlfile; - char *sslflags; - char *ssldomain; - SSL_CTX *sslContext; - SSL_SESSION *sslSession; -#endif - - int front_end_https; - int connection_auth; -}; - -struct _net_db_name { - hash_link hash; /* must be first */ - net_db_name *next; - netdbEntry *net_db_entry; -}; - -struct _net_db_peer { - const char *peername; - double hops; - double rtt; - time_t expires; -}; - -struct _netdbEntry { - hash_link hash; /* must be first */ - char network[MAX_IPSTRLEN]; - int pings_sent; - int pings_recv; - double hops; - double rtt; - time_t next_ping_time; - time_t last_use_time; - int link_count; - net_db_name *hosts; - net_db_peer *peers; - int n_peers_alloc; - int n_peers; -}; - - -struct _iostats { - - struct { - int reads; - int reads_deferred; - int read_hist[16]; - int writes; - int write_hist[16]; - } - - Http, Ftp, Gopher; -}; - - -struct request_flags { - request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),destinationIPLookedUp_(0) { -#if HTTP_VIOLATIONS - nocache_hack = 0; -#endif -#if FOLLOW_X_FORWARDED_FOR - done_follow_x_forwarded_for = 0; -#endif /* FOLLOW_X_FORWARDED_FOR */ - } - - unsigned int range:1; - unsigned int nocache:1; - unsigned int ims:1; - unsigned int auth:1; - unsigned int cachable:1; - unsigned int hierarchical:1; - unsigned int loopdetect:1; - unsigned int proxy_keepalive:1; -unsigned int proxying: - 1; /* this should be killed, also in httpstateflags */ - unsigned int refresh:1; - unsigned int redirected:1; - unsigned int need_validation:1; -#if HTTP_VIOLATIONS - unsigned int nocache_hack:1; /* for changing/ignoring no-cache requests */ -#endif - unsigned int accelerated:1; - unsigned int ignore_cc:1; - unsigned int intercepted:1; /**< transparently intercepted request */ - unsigned int spoof_client_ip:1; /**< spoof client ip if possible */ - unsigned int internal:1; - unsigned int internalclient:1; - unsigned int must_keepalive:1; - unsigned int connection_auth:1; /** Request wants connection oriented auth */ - unsigned int connection_auth_disabled:1; /** Connection oriented auth can not be supported */ - unsigned int connection_proxy_auth:1; /** Request wants connection oriented auth */ - unsigned int pinned:1; /* Request sent on a pinned connection */ - unsigned int auth_sent:1; /* Authentication forwarded */ - unsigned int no_direct:1; /* Deny direct forwarding unless overriden by always_direct. Used in accelerator mode */ - - // When adding new flags, please update cloneAdaptationImmune() as needed. - - bool resetTCP() const; - void setResetTCP(); - void clearResetTCP(); - void destinationIPLookupCompleted(); - bool destinationIPLookedUp() const; - - // returns a partial copy of the flags that includes only those flags - // that are safe for a related (e.g., ICAP-adapted) request to inherit - request_flags cloneAdaptationImmune() const; - -#if FOLLOW_X_FORWARDED_FOR - unsigned int done_follow_x_forwarded_for; -#endif /* FOLLOW_X_FORWARDED_FOR */ -private: - - unsigned int reset_tcp:1; - unsigned int destinationIPLookedUp_:1; -}; - -struct _link_list { - void *ptr; - - struct _link_list *next; -}; - -struct _cachemgr_passwd { - char *passwd; - wordlist *actions; - cachemgr_passwd *next; -}; - -struct _refresh_t { - const char *pattern; - regex_t compiled_pattern; - time_t min; - double pct; - time_t max; - refresh_t *next; - - struct { - unsigned int icase:1; - unsigned int refresh_ims:1; -#if HTTP_VIOLATIONS - unsigned int override_expire:1; - unsigned int override_lastmod:1; - unsigned int reload_into_ims:1; - unsigned int ignore_reload:1; - unsigned int ignore_no_cache:1; - unsigned int ignore_no_store:1; - unsigned int ignore_must_revalidate:1; - unsigned int ignore_private:1; - unsigned int ignore_auth:1; -#endif - } flags; -}; - -/* - * "very generic" histogram; - * see important comments on hbase_f restrictions in StatHist.c - */ - -struct _StatHist { - int *bins; - int capacity; - double min; - double max; - double scale; - hbase_f *val_in; /* e.g., log() for log-based histogram */ - hbase_f *val_out; /* e.g., exp() for log based histogram */ -}; - -/* - * if you add a field to StatCounters, - * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy - */ - -struct _StatCounters { - - struct { - int clients; - int requests; - int hits; - int mem_hits; - int disk_hits; - int errors; - kb_t kbytes_in; - kb_t kbytes_out; - kb_t hit_kbytes_out; - StatHist miss_svc_time; - StatHist nm_svc_time; - StatHist nh_svc_time; - StatHist hit_svc_time; - StatHist all_svc_time; - } client_http; - - struct { - - struct { - int requests; - int errors; - kb_t kbytes_in; - kb_t kbytes_out; - } all , http, ftp, other; - } server; - - struct { - int pkts_sent; - int queries_sent; - int replies_sent; - int pkts_recv; - int queries_recv; - int replies_recv; - int hits_sent; - int hits_recv; - int replies_queued; - int replies_dropped; - kb_t kbytes_sent; - kb_t q_kbytes_sent; - kb_t r_kbytes_sent; - kb_t kbytes_recv; - kb_t q_kbytes_recv; - kb_t r_kbytes_recv; - StatHist query_svc_time; - StatHist reply_svc_time; - int query_timeouts; - int times_used; - } icp; - - struct { - int pkts_sent; - int pkts_recv; - } htcp; - - struct { - int requests; - } unlink; - - struct { - StatHist svc_time; - } dns; - - struct { - int times_used; - kb_t kbytes_sent; - kb_t kbytes_recv; - kb_t memory; - int msgs_sent; - int msgs_recv; -#if USE_CACHE_DIGESTS - - cd_guess_stats guess; -#endif - - StatHist on_xition_count; - } cd; - - struct { - int times_used; - } netdb; - int page_faults; - unsigned long int select_loops; - int select_fds; - double select_time; - double cputime; - - struct timeval timestamp; - StatHist comm_icp_incoming; - StatHist comm_dns_incoming; - StatHist comm_http_incoming; - StatHist select_fds_hist; - - struct { - struct { - int opens; - int closes; - int reads; - int writes; - int seeks; - int unlinks; - } disk; - - struct { - int accepts; - int sockets; - int connects; - int binds; - int closes; - int reads; - int writes; - int recvfroms; - int sendtos; - } sock; - int selects; - } syscalls; - int aborted_requests; - - struct { - int files_cleaned; - int outs; - int ins; - } swap; -}; - -/* per header statistics */ - -struct _HttpHeaderStat { - const char *label; - HttpHeaderMask *owner_mask; - - StatHist hdrUCountDistr; - StatHist fieldTypeDistr; - StatHist ccTypeDistr; - StatHist scTypeDistr; - - int parsedCount; - int ccParsedCount; - int scParsedCount; - int destroyedCount; - int busyDestroyedCount; -}; - - -struct _CacheDigest { - /* public, read-only */ - char *mask; /* bit mask */ - int mask_size; /* mask size in bytes */ - int capacity; /* expected maximum for .count, not a hard limit */ - int bits_per_entry; /* number of bits allocated for each entry from capacity */ - int count; /* number of digested entries */ - int del_count; /* number of deletions performed so far */ -}; - - -struct _store_rebuild_data { - int objcount; /* # objects successfully reloaded */ - int expcount; /* # objects expired */ - int scancount; /* # entries scanned or read from state file */ - int clashcount; /* # swapfile clashes avoided */ - int dupcount; /* # duplicates purged */ - int cancelcount; /* # SWAP_LOG_DEL objects purged */ - int invalid; /* # bad lines */ - int badflags; /* # bad e->flags */ - int bad_log_op; - int zero_object_sz; -}; - -class logformat_token; - -struct _logformat { - char *name; - logformat_token *format; - logformat *next; -}; - -class Logfile; - -struct _customlog { - char *filename; - ACLList *aclList; - logformat *logFormat; - Logfile *logfile; - customlog *next; - customlog_type type; -}; - -#endif /* SQUID_STRUCTS_H */ +/* + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; 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. + * + */ +#ifndef SQUID_STRUCTS_H +#define SQUID_STRUCTS_H + +#include "config.h" +#include "RefCount.h" +#include "cbdata.h" +#include "dlink.h" +#include "err_type.h" + +/* needed for the global config */ +#include "HttpHeader.h" + +/* for ICP_END */ +#include "icp_opcode.h" + +#define PEER_MULTICAST_SIBLINGS 1 + +struct acl_name_list { + char name[ACL_NAME_SZ]; + acl_name_list *next; +}; + +struct acl_deny_info_list { + err_type err_page_id; + char *err_page_name; + acl_name_list *acl_list; + acl_deny_info_list *next; +}; + + +class acl_access; + +struct _header_mangler { + acl_access *access_list; + char *replacement; +}; + +class ACLChecklist; + +#if SQUID_SNMP + +struct _snmp_request_t { + u_char *buf; + u_char *outbuf; + int len; + int sock; + long reqid; + int outlen; + + Ip::Address from; + + struct snmp_pdu *PDU; + ACLChecklist *acl_checklist; + u_char *community; + + struct snmp_session session; +}; + +#endif + +class ACLList; + +struct acl_address { + acl_address *next; + ACLList *aclList; + + Ip::Address addr; +}; + +struct acl_tos { + acl_tos *next; + ACLList *aclList; + int tos; +}; + +struct acl_size_t { + acl_size_t *next; + ACLList *aclList; + int64_t size; +}; + +struct ushortlist { + u_short i; + ushortlist *next; +}; + +struct relist { + char *pattern; + regex_t regex; + relist *next; +}; + +#if DELAY_POOLS +#include "DelayConfig.h" +#endif + +#if USE_ICMP +#include "icmp/IcmpConfig.h" +#endif + +#include "HelperChildConfig.h" + +/* forward decl for SquidConfig, see RemovalPolicy.h */ + +class RemovalPolicySettings; +class external_acl; +class Store; + +struct SquidConfig { + + struct { + /* These should be for the Store::Root instance. + * this needs pluggable parsing to be done smoothly. + */ + int highWaterMark; + int lowWaterMark; + } Swap; + size_t memMaxSize; + + struct { + int64_t min; + int pct; + int64_t max; + } quickAbort; + int64_t readAheadGap; + RemovalPolicySettings *replPolicy; + RemovalPolicySettings *memPolicy; +#if HTTP_VIOLATIONS + time_t negativeTtl; +#endif + time_t negativeDnsTtl; + time_t positiveDnsTtl; + time_t shutdownLifetime; + time_t backgroundPingRate; + + struct { + time_t read; + time_t write; + time_t lifetime; + time_t connect; + time_t forward; + time_t peer_connect; + time_t request; + time_t persistent_request; + time_t pconn; + time_t siteSelect; + time_t deadPeer; + int icp_query; /* msec */ + int icp_query_max; /* msec */ + int icp_query_min; /* msec */ + int mcast_icp_query; /* msec */ + +#if !USE_DNSSERVERS + + time_t idns_retransmit; + time_t idns_query; +#endif + + } Timeout; + size_t maxRequestHeaderSize; + int64_t maxRequestBodySize; + int64_t maxChunkedRequestBodySize; + size_t maxReplyHeaderSize; + acl_size_t *ReplyBodySize; + + struct { + u_short icp; +#if USE_HTCP + + u_short htcp; +#endif +#if SQUID_SNMP + + u_short snmp; +#endif + } Port; + + struct { + http_port_list *http; +#if USE_SSL + + https_port_list *https; +#endif + + } Sockaddr; +#if SQUID_SNMP + + struct { + char *configFile; + char *agentInfo; + } Snmp; +#endif +#if USE_WCCP + + struct { + Ip::Address router; + Ip::Address address; + int version; + } Wccp; +#endif +#if USE_WCCPv2 + + struct { + Ip::Address_list *router; + Ip::Address address; + int forwarding_method; + int return_method; + int assignment_method; + int weight; + int rebuildwait; + void *info; + } Wccp2; +#endif + +#if USE_ICMP + IcmpConfig pinger; +#endif + + char *as_whois_server; + + struct { + char *store; + char *swap; +#if USE_USERAGENT_LOG + + char *useragent; +#endif +#if USE_REFERER_LOG + + char *referer; +#endif +#if WIP_FWD_LOG + + char *forward; +#endif + + logformat *logformats; + + customlog *accesslogs; + +#if ICAP_CLIENT + customlog *icaplogs; +#endif + + int rotateNumber; + } Log; + char *adminEmail; + char *EmailFrom; + char *EmailProgram; + char *effectiveUser; + char *visible_appname_string; + char *effectiveGroup; + + struct { +#if USE_DNSSERVERS + char *dnsserver; +#endif + + wordlist *redirect; +#if USE_UNLINKD + + char *unlinkd; +#endif + + char *diskd; +#if USE_SSL + + char *ssl_password; +#endif + + } Program; +#if USE_DNSSERVERS + + HelperChildConfig dnsChildren; +#endif + + HelperChildConfig redirectChildren; + time_t authenticateGCInterval; + time_t authenticateTTL; + time_t authenticateIpTTL; + + struct { + char *surrogate_id; + } Accel; + char *appendDomain; + size_t appendDomainLen; + char *pidFilename; + char *netdbFilename; + char *mimeTablePathname; + char *etcHostsPath; + char *visibleHostname; + char *uniqueHostname; + wordlist *hostnameAliases; + char *errHtmlText; + + struct { + char *host; + char *file; + time_t period; + u_short port; + } Announce; + + struct { + + Ip::Address udp_incoming; + Ip::Address udp_outgoing; +#if SQUID_SNMP + Ip::Address snmp_incoming; + Ip::Address snmp_outgoing; +#endif + /* FIXME INET6 : this should really be a CIDR value */ + Ip::Address client_netmask; + } Addrs; + size_t tcpRcvBufsz; + size_t udpMaxHitObjsz; + wordlist *hierarchy_stoplist; + wordlist *mcast_group_list; + wordlist *dns_nameservers; + peer *peers; + int npeers; + + struct { + int size; + int low; + int high; + } ipcache; + + struct { + int size; + } fqdncache; + int minDirectHops; + int minDirectRtt; + cachemgr_passwd *passwd_list; + + struct { + int objectsPerBucket; + int64_t avgObjectSize; + int64_t maxObjectSize; + int64_t minObjectSize; + size_t maxInMemObjSize; + } Store; + + struct { + int high; + int low; + time_t period; + } Netdb; + + struct { + int log_udp; + int res_defnames; + int anonymizer; + int client_db; + int query_icmp; + int icp_hit_stale; + int buffered_logs; + int common_log; + int log_mime_hdrs; + int log_fqdn; + int announce; + int mem_pools; + int test_reachability; + int half_closed_clients; + int refresh_all_ims; +#if HTTP_VIOLATIONS + + int reload_into_ims; + int ignore_expect_100; +#endif + + int offline; + int redir_rewrites_host; + int prefer_direct; + int nonhierarchical_direct; + int strip_query_terms; + int redirector_bypass; + int ignore_unknown_nameservers; + int client_pconns; + int server_pconns; + int error_pconns; +#if USE_CACHE_DIGESTS + + int digest_generation; +#endif + + int log_ip_on_direct; + int ie_refresh; + int vary_ignore_expire; + int pipeline_prefetch; + int surrogate_is_remote; + int request_entities; + int detect_broken_server_pconns; + int balance_on_multiple_ip; + int relaxed_header_parser; + int check_hostnames; + int allow_underscore; + int via; + int emailErrData; + int httpd_suppress_version_string; + int global_internal_static; + int dns_require_A; + +#if FOLLOW_X_FORWARDED_FOR + int acl_uses_indirect_client; + int delay_pool_uses_indirect_client; + int log_uses_indirect_client; +#endif /* FOLLOW_X_FORWARDED_FOR */ + + int WIN32_IpAddrChangeMonitor; + int memory_cache_first; + int memory_cache_disk; + int access_sibling_for_stale_resource; + } onoff; + + int forward_max_tries; + + class ACL *aclList; + + struct { + acl_access *http; + acl_access *adapted_http; + acl_access *icp; + acl_access *miss; + acl_access *NeverDirect; + acl_access *AlwaysDirect; + acl_access *ASlists; + acl_access *noCache; + acl_access *log; +#if SQUID_SNMP + + acl_access *snmp; +#endif +#if HTTP_VIOLATIONS + acl_access *brokenPosts; +#endif + acl_access *redirector; + acl_access *reply; + acl_address *outgoing_address; + acl_tos *outgoing_tos; + acl_tos *clientside_tos; +#if USE_HTCP + + acl_access *htcp; + acl_access *htcp_clr; +#endif + +#if USE_SSL + acl_access *ssl_bump; +#endif +#if FOLLOW_X_FORWARDED_FOR + acl_access *followXFF; +#endif /* FOLLOW_X_FORWARDED_FOR */ + +#if ICAP_CLIENT + acl_access* icap; +#endif + } accessList; + acl_deny_info_list *denyInfoList; + authConfig authConfiguration; + + struct { + size_t list_width; + int list_wrap; + char *anon_user; + int passive; + int epsv_all; + int epsv; + int sanitycheck; + int telnet; + } Ftp; + refresh_t *Refresh; + + struct _cacheSwap { + RefCount *swapDirs; + int n_allocated; + int n_configured; + } cacheSwap; + /* + * I'm sick of having to keep doing this .. + */ +#define INDEXSD(i) (Config.cacheSwap.swapDirs[(i)].getRaw()) + + struct { + char *directory; + int use_short_names; + } icons; + char *errorDirectory; +#if USE_ERR_LOCALES + char *errorDefaultLanguage; + int errorLogMissingLanguages; +#endif + char *errorStylesheet; + + struct { + int maxtries; + int onerror; + } retry; + + struct { + size_t limit; + } MemPools; +#if DELAY_POOLS + + DelayConfig Delay; +#endif + + struct { + int icp_average; + int dns_average; + int http_average; + int icp_min_poll; + int dns_min_poll; + int http_min_poll; + } comm_incoming; + int max_open_disk_fds; + int uri_whitespace; + acl_size_t *rangeOffsetLimit; +#if MULTICAST_MISS_STREAM + + struct { + + Ip::Address addr; + int ttl; + unsigned short port; + char *encode_key; + } mcast_miss; +#endif + + /* one access list per header type we know of */ + header_mangler request_header_access[HDR_ENUM_END]; + /* one access list per header type we know of */ + header_mangler reply_header_access[HDR_ENUM_END]; + char *coredump_dir; + char *chroot_dir; +#if USE_CACHE_DIGESTS + + struct { + int bits_per_entry; + time_t rebuild_period; + time_t rewrite_period; + size_t swapout_chunk_size; + int rebuild_chunk_percentage; + } digest; +#endif +#if USE_SSL + + struct { + int unclean_shutdown; + char *ssl_engine; + } SSL; +#endif + + wordlist *ext_methods; + + struct { + int high_rptm; + int high_pf; + size_t high_memory; + } warnings; + char *store_dir_select_algorithm; + int sleep_after_fork; /* microseconds */ + time_t minimum_expiry_time; /* seconds */ + external_acl *externalAclHelperList; + +#if USE_SSL + + struct { + char *cert; + char *key; + int version; + char *options; + char *cipher; + char *cafile; + char *capath; + char *crlfile; + char *flags; + acl_access *cert_error; + SSL_CTX *sslContext; + } ssl_client; +#endif + + char *accept_filter; + int umask; + +#if USE_LOADABLE_MODULES + wordlist *loadable_module_names; +#endif + + int client_ip_max_connections; +}; + +SQUIDCEXTERN SquidConfig Config; + +struct SquidConfig2 { + struct { + int enable_purge; + int mangle_request_headers; + } onoff; + uid_t effectiveUserID; + gid_t effectiveGroupID; +}; + +SQUIDCEXTERN SquidConfig2 Config2; + +struct _close_handler { + PF *handler; + void *data; + close_handler *next; +}; + +struct _dread_ctrl { + int fd; + off_t offset; + int req_len; + char *buf; + int end_of_file; + DRCB *handler; + void *client_data; +}; + +struct _dwrite_q { + off_t file_offset; + char *buf; + size_t len; + size_t buf_offset; + dwrite_q *next; + FREE *free_func; +}; + + +/* ETag support is rudimantal; + * this struct is likely to change + * Note: "str" points to memory in HttpHeaderEntry (for now) + * so ETags should be used as tmp variables only (for now) */ + +struct _ETag { + const char *str; /* quoted-string */ + int weak; /* true if it is a weak validator */ +}; + +struct _fde_disk { + DWCB *wrt_handle; + void *wrt_handle_data; + dwrite_q *write_q; + dwrite_q *write_q_tail; + off_t offset; +}; + +struct _fileMap { + int max_n_files; + int n_files_in_map; + int toggle; + int nwords; + unsigned long *file_map; +}; + +/* + * Note: HttpBody is used only for messages with a small content that is + * known a priory (e.g., error messages). + */ + +class MemBuf; + +struct _HttpBody { + /* private */ + MemBuf *mb; +}; + +#include "SquidString.h" +/* http header extention field */ + +class HttpHdrExtField +{ + String name; /* field-name from HTTP/1.1 (no column after name) */ + String value; /* field-value from HTTP/1.1 */ +}; + +/* http cache control header field */ + +class HttpHdrCc +{ + +public: + int mask; + int max_age; + int s_maxage; + int max_stale; + String other; +}; + +/* some fields can hold either time or etag specs (e.g. If-Range) */ + +struct _TimeOrTag { + ETag tag; /* entity tag */ + time_t time; + int valid; /* true if struct is usable */ +}; + +/* per field statistics */ + +class HttpHeaderFieldStat +{ + +public: + HttpHeaderFieldStat() : aliveCount(0), seenCount(0), parsCount(0), errCount(0), repCount(0) {} + + int aliveCount; /* created but not destroyed (count) */ + int seenCount; /* #fields we've seen */ + int parsCount; /* #parsing attempts */ + int errCount; /* #pasring errors */ + int repCount; /* #repetitons */ +}; + +/* compiled version of HttpHeaderFieldAttrs plus stats */ + +class HttpHeaderFieldInfo +{ + +public: + HttpHeaderFieldInfo() : id (HDR_ACCEPT), type (ftInvalid) {} + + http_hdr_type id; + String name; + field_type type; + HttpHeaderFieldStat stat; +}; + +struct _http_state_flags { + unsigned int proxying:1; + unsigned int keepalive:1; + unsigned int only_if_cached:1; + unsigned int headers_parsed:1; + unsigned int front_end_https:2; + unsigned int originpeer:1; + unsigned int keepalive_broken:1; + unsigned int abuse_detected:1; + unsigned int request_sent:1; + unsigned int do_next_read:1; + unsigned int consume_body_data:1; + unsigned int chunked:1; +}; + +struct _ipcache_addrs { + Ip::Address *in_addrs; + unsigned char *bad_mask; + unsigned char count; + unsigned char cur; + unsigned char badcount; +}; + +struct _domain_ping { + char *domain; + int do_ping; /* boolean */ + domain_ping *next; +}; + +struct _domain_type { + char *domain; + peer_t type; + domain_type *next; +}; + +#if USE_CACHE_DIGESTS + +/* statistics for cache digests and other hit "predictors" */ + +struct _cd_guess_stats { + /* public, read-only */ + int true_hits; + int false_hits; + int true_misses; + int false_misses; + int close_hits; /* tmp, remove it later */ +}; + +#endif + +class PeerDigest; + +struct peer { + u_int index; + char *name; + char *host; + peer_t type; + + Ip::Address in_addr; + + struct { + int pings_sent; + int pings_acked; + int fetches; + int rtt; + int ignored_replies; + int n_keepalives_sent; + int n_keepalives_recv; + time_t probe_start; + time_t last_query; + time_t last_reply; + time_t last_connect_failure; + time_t last_connect_probe; + int logged_state; /* so we can print dead/revived msgs */ + int conn_open; /* current opened connections */ + } stats; + + struct { + int version; + int counts[ICP_END+1]; + u_short port; + } icp; + +#if USE_HTCP + struct { + double version; + int counts[2]; + u_short port; + } htcp; +#endif + + u_short http_port; + domain_ping *peer_domain; + domain_type *typelist; + acl_access *access; + + struct { + unsigned int proxy_only:1; + unsigned int no_query:1; + unsigned int background_ping:1; + unsigned int no_digest:1; + unsigned int default_parent:1; + unsigned int roundrobin:1; + unsigned int weighted_roundrobin:1; + unsigned int mcast_responder:1; + unsigned int closest_only:1; +#if USE_HTCP + unsigned int htcp:1; + unsigned int htcp_oldsquid:1; + unsigned int htcp_no_clr:1; + unsigned int htcp_no_purge_clr:1; + unsigned int htcp_only_clr:1; + unsigned int htcp_forward_clr:1; +#endif + unsigned int no_netdb_exchange:1; +#if DELAY_POOLS + unsigned int no_delay:1; +#endif + unsigned int allow_miss:1; + unsigned int carp:1; + unsigned int userhash:1; + unsigned int sourcehash:1; + unsigned int originserver:1; + unsigned int no_tproxy:1; +#if PEER_MULTICAST_SIBLINGS + unsigned int mcast_siblings:1; +#endif + } options; + + int weight; + int basetime; + + struct { + double avg_n_members; + int n_times_counted; + int n_replies_expected; + int ttl; + int id; + + struct { + unsigned int count_event_pending:1; + unsigned int counting:1; + } flags; + } mcast; +#if USE_CACHE_DIGESTS + + PeerDigest *digest; + char *digest_url; +#endif + + int tcp_up; /* 0 if a connect() fails */ + + Ip::Address addresses[10]; + int n_addresses; + int rr_count; + peer *next; + int test_fd; + + struct { + unsigned int hash; + double load_multiplier; + double load_factor; /* normalized weight value */ + } carp; + + struct { + unsigned int hash; + double load_multiplier; + double load_factor; /* normalized weight value */ + } userhash; + + struct { + unsigned int hash; + double load_multiplier; + double load_factor; /* normalized weight value */ + } sourcehash; + + char *login; /* Proxy authorization */ + time_t connect_timeout; + int connect_fail_limit; + int max_conn; + char *domain; /* Forced domain */ +#if USE_SSL + + int use_ssl; + char *sslcert; + char *sslkey; + int sslversion; + char *ssloptions; + char *sslcipher; + char *sslcafile; + char *sslcapath; + char *sslcrlfile; + char *sslflags; + char *ssldomain; + SSL_CTX *sslContext; + SSL_SESSION *sslSession; +#endif + + int front_end_https; + int connection_auth; +}; + +struct _net_db_name { + hash_link hash; /* must be first */ + net_db_name *next; + netdbEntry *net_db_entry; +}; + +struct _net_db_peer { + const char *peername; + double hops; + double rtt; + time_t expires; +}; + +struct _netdbEntry { + hash_link hash; /* must be first */ + char network[MAX_IPSTRLEN]; + int pings_sent; + int pings_recv; + double hops; + double rtt; + time_t next_ping_time; + time_t last_use_time; + int link_count; + net_db_name *hosts; + net_db_peer *peers; + int n_peers_alloc; + int n_peers; +}; + + +struct _iostats { + + struct { + int reads; + int reads_deferred; + int read_hist[16]; + int writes; + int write_hist[16]; + } + + Http, Ftp, Gopher; +}; + + +struct request_flags { + request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),destinationIPLookedUp_(0) { +#if HTTP_VIOLATIONS + nocache_hack = 0; +#endif +#if FOLLOW_X_FORWARDED_FOR + done_follow_x_forwarded_for = 0; +#endif /* FOLLOW_X_FORWARDED_FOR */ + } + + unsigned int range:1; + unsigned int nocache:1; + unsigned int ims:1; + unsigned int auth:1; + unsigned int cachable:1; + unsigned int hierarchical:1; + unsigned int loopdetect:1; + unsigned int proxy_keepalive:1; +unsigned int proxying: + 1; /* this should be killed, also in httpstateflags */ + unsigned int refresh:1; + unsigned int redirected:1; + unsigned int need_validation:1; +#if HTTP_VIOLATIONS + unsigned int nocache_hack:1; /* for changing/ignoring no-cache requests */ +#endif + unsigned int accelerated:1; + unsigned int ignore_cc:1; + unsigned int intercepted:1; /**< transparently intercepted request */ + unsigned int spoof_client_ip:1; /**< spoof client ip if possible */ + unsigned int internal:1; + unsigned int internalclient:1; + unsigned int must_keepalive:1; + unsigned int connection_auth:1; /** Request wants connection oriented auth */ + unsigned int connection_auth_disabled:1; /** Connection oriented auth can not be supported */ + unsigned int connection_proxy_auth:1; /** Request wants connection oriented auth */ + unsigned int pinned:1; /* Request sent on a pinned connection */ + unsigned int auth_sent:1; /* Authentication forwarded */ + unsigned int no_direct:1; /* Deny direct forwarding unless overriden by always_direct. Used in accelerator mode */ + + // When adding new flags, please update cloneAdaptationImmune() as needed. + + bool resetTCP() const; + void setResetTCP(); + void clearResetTCP(); + void destinationIPLookupCompleted(); + bool destinationIPLookedUp() const; + + // returns a partial copy of the flags that includes only those flags + // that are safe for a related (e.g., ICAP-adapted) request to inherit + request_flags cloneAdaptationImmune() const; + +#if FOLLOW_X_FORWARDED_FOR + unsigned int done_follow_x_forwarded_for; +#endif /* FOLLOW_X_FORWARDED_FOR */ +private: + + unsigned int reset_tcp:1; + unsigned int destinationIPLookedUp_:1; +}; + +struct _link_list { + void *ptr; + + struct _link_list *next; +}; + +struct _cachemgr_passwd { + char *passwd; + wordlist *actions; + cachemgr_passwd *next; +}; + +struct _refresh_t { + const char *pattern; + regex_t compiled_pattern; + time_t min; + double pct; + time_t max; + refresh_t *next; + + struct { + unsigned int icase:1; + unsigned int refresh_ims:1; +#if HTTP_VIOLATIONS + unsigned int override_expire:1; + unsigned int override_lastmod:1; + unsigned int reload_into_ims:1; + unsigned int ignore_reload:1; + unsigned int ignore_no_cache:1; + unsigned int ignore_no_store:1; + unsigned int ignore_must_revalidate:1; + unsigned int ignore_private:1; + unsigned int ignore_auth:1; +#endif + } flags; +}; + +/* + * "very generic" histogram; + * see important comments on hbase_f restrictions in StatHist.c + */ + +struct _StatHist { + int *bins; + int capacity; + double min; + double max; + double scale; + hbase_f *val_in; /* e.g., log() for log-based histogram */ + hbase_f *val_out; /* e.g., exp() for log based histogram */ +}; + +/* + * if you add a field to StatCounters, + * you MUST sync statCountersInitSpecial, statCountersClean, and statCountersCopy + */ + +struct _StatCounters { + + struct { + int clients; + int requests; + int hits; + int mem_hits; + int disk_hits; + int errors; + kb_t kbytes_in; + kb_t kbytes_out; + kb_t hit_kbytes_out; + StatHist miss_svc_time; + StatHist nm_svc_time; + StatHist nh_svc_time; + StatHist hit_svc_time; + StatHist all_svc_time; + } client_http; + + struct { + + struct { + int requests; + int errors; + kb_t kbytes_in; + kb_t kbytes_out; + } all , http, ftp, other; + } server; + + struct { + int pkts_sent; + int queries_sent; + int replies_sent; + int pkts_recv; + int queries_recv; + int replies_recv; + int hits_sent; + int hits_recv; + int replies_queued; + int replies_dropped; + kb_t kbytes_sent; + kb_t q_kbytes_sent; + kb_t r_kbytes_sent; + kb_t kbytes_recv; + kb_t q_kbytes_recv; + kb_t r_kbytes_recv; + StatHist query_svc_time; + StatHist reply_svc_time; + int query_timeouts; + int times_used; + } icp; + + struct { + int pkts_sent; + int pkts_recv; + } htcp; + + struct { + int requests; + } unlink; + + struct { + StatHist svc_time; + } dns; + + struct { + int times_used; + kb_t kbytes_sent; + kb_t kbytes_recv; + kb_t memory; + int msgs_sent; + int msgs_recv; +#if USE_CACHE_DIGESTS + + cd_guess_stats guess; +#endif + + StatHist on_xition_count; + } cd; + + struct { + int times_used; + } netdb; + int page_faults; + unsigned long int select_loops; + int select_fds; + double select_time; + double cputime; + + struct timeval timestamp; + StatHist comm_icp_incoming; + StatHist comm_dns_incoming; + StatHist comm_http_incoming; + StatHist select_fds_hist; + + struct { + struct { + int opens; + int closes; + int reads; + int writes; + int seeks; + int unlinks; + } disk; + + struct { + int accepts; + int sockets; + int connects; + int binds; + int closes; + int reads; + int writes; + int recvfroms; + int sendtos; + } sock; + int selects; + } syscalls; + int aborted_requests; + + struct { + int files_cleaned; + int outs; + int ins; + } swap; +}; + +/* per header statistics */ + +struct _HttpHeaderStat { + const char *label; + HttpHeaderMask *owner_mask; + + StatHist hdrUCountDistr; + StatHist fieldTypeDistr; + StatHist ccTypeDistr; + StatHist scTypeDistr; + + int parsedCount; + int ccParsedCount; + int scParsedCount; + int destroyedCount; + int busyDestroyedCount; +}; + + +struct _CacheDigest { + /* public, read-only */ + char *mask; /* bit mask */ + int mask_size; /* mask size in bytes */ + int capacity; /* expected maximum for .count, not a hard limit */ + int bits_per_entry; /* number of bits allocated for each entry from capacity */ + int count; /* number of digested entries */ + int del_count; /* number of deletions performed so far */ +}; + + +struct _store_rebuild_data { + int objcount; /* # objects successfully reloaded */ + int expcount; /* # objects expired */ + int scancount; /* # entries scanned or read from state file */ + int clashcount; /* # swapfile clashes avoided */ + int dupcount; /* # duplicates purged */ + int cancelcount; /* # SWAP_LOG_DEL objects purged */ + int invalid; /* # bad lines */ + int badflags; /* # bad e->flags */ + int bad_log_op; + int zero_object_sz; +}; + +class logformat_token; + +struct _logformat { + char *name; + logformat_token *format; + logformat *next; +}; + +class Logfile; + +struct _customlog { + char *filename; + ACLList *aclList; + logformat *logFormat; + Logfile *logfile; + customlog *next; + customlog_type type; +}; + +#endif /* SQUID_STRUCTS_H */ # Begin bundle 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 kNsZS58= A  7 !¹DOV<`@0@077trunk-10487.patch 7