~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/neighbors.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2010-05-04 11:15:49 UTC
  • mfrom: (1.3.1 upstream)
  • mto: (20.3.1 squeeze) (21.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100504111549-1apjh2g5sndki4te
Tags: upstream-3.1.3
ImportĀ upstreamĀ versionĀ 3.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
1
/*
3
 
 * $Id: neighbors.cc,v 1.350.2.1 2008/02/25 02:55:16 amosjeffries Exp $
4
 
 *
5
2
 * DEBUG: section 15    Neighbor Routines
6
3
 * AUTHOR: Harvest Derived
7
4
 *
21
18
 *  it under the terms of the GNU General Public License as published by
22
19
 *  the Free Software Foundation; either version 2 of the License, or
23
20
 *  (at your option) any later version.
24
 
 *  
 
21
 *
25
22
 *  This program is distributed in the hope that it will be useful,
26
23
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27
24
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
25
 *  GNU General Public License for more details.
29
 
 *  
 
26
 *
30
27
 *  You should have received a copy of the GNU General Public License
31
28
 *  along with this program; if not, write to the Free Software
32
29
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
34
31
 */
35
32
 
36
33
#include "squid.h"
37
 
#include "ACLChecklist.h"
 
34
#include "ProtoPort.h"
 
35
#include "acl/FilledChecklist.h"
38
36
#include "event.h"
39
37
#include "CacheManager.h"
40
38
#include "htcp.h"
43
41
#include "MemObject.h"
44
42
#include "PeerDigest.h"
45
43
#include "PeerSelectState.h"
 
44
#include "SquidMath.h"
46
45
#include "SquidTime.h"
47
46
#include "Store.h"
 
47
#include "icmp/net_db.h"
 
48
#include "ip/IpAddress.h"
48
49
 
49
50
/* count mcast group peers every 15 minutes */
50
51
#define MCAST_COUNT_RATE 900
51
52
 
52
 
static int peerAllowedToUse(const peer *, HttpRequest *);
 
53
int peerAllowedToUse(const peer *, HttpRequest *);
53
54
static int peerWouldBePinged(const peer *, HttpRequest *);
54
55
static void neighborRemove(peer *);
55
56
static void neighborAlive(peer *, const MemObject *, const icp_common_t *);
66
67
static void peerCountMcastPeersSchedule(peer * p, time_t when);
67
68
static IRCB peerCountHandleIcpReply;
68
69
 
69
 
static void neighborIgnoreNonPeer(const struct sockaddr_in *, icp_opcode);
 
70
static void neighborIgnoreNonPeer(const IpAddress &, icp_opcode);
70
71
static OBJH neighborDumpPeers;
71
72
static OBJH neighborDumpNonPeers;
72
73
static void dump_peers(StoreEntry * sentry, peer * peers);
94
95
 
95
96
 
96
97
peer *
97
 
 
98
 
whichPeer(const struct sockaddr_in * from)
 
98
whichPeer(const IpAddress &from)
99
99
{
100
100
    int j;
101
 
    u_short port = ntohs(from->sin_port);
102
101
 
103
 
    struct IN_ADDR ip = from->sin_addr;
104
102
    peer *p = NULL;
105
 
    debugs(15, 3, "whichPeer: from " << inet_ntoa(ip) << " port " << port);
 
103
    debugs(15, 3, "whichPeer: from " << from);
106
104
 
107
 
    for (p = Config.peers; p; p = p->next)
108
 
    {
 
105
    for (p = Config.peers; p; p = p->next) {
109
106
        for (j = 0; j < p->n_addresses; j++) {
110
 
            if (ip.s_addr == p->addresses[j].s_addr && port == p->icp.port) {
 
107
            if (from == p->addresses[j] && from.GetPort() == p->icp.port) {
111
108
                return p;
112
109
            }
113
110
        }
123
120
    const struct _domain_type *d = NULL;
124
121
 
125
122
    for (d = p->typelist; d; d = d->next) {
126
 
        if (0 == matchDomainName(request->host, d->domain))
 
123
        if (0 == matchDomainName(request->GetHost(), d->domain))
127
124
            if (d->type != PEER_NONE)
128
125
                return d->type;
129
126
    }
 
127
#if PEER_MULTICAST_SIBLINGS
 
128
    if (p->type == PEER_MULTICAST)
 
129
        if (p->options.mcast_siblings)
 
130
            return PEER_SIBLING;
 
131
#endif
130
132
 
131
133
    return p->type;
132
134
}
137
139
 * this function figures out if it is appropriate to fetch REQUEST
138
140
 * from PEER.
139
141
 */
140
 
static int
 
142
int
141
143
peerAllowedToUse(const peer * p, HttpRequest * request)
142
144
{
143
145
 
146
148
    assert(request != NULL);
147
149
 
148
150
    if (neighborType(p, request) == PEER_SIBLING) {
 
151
#if PEER_MULTICAST_SIBLINGS
 
152
        if (p->type == PEER_MULTICAST && p->options.mcast_siblings &&
 
153
                (request->flags.nocache || request->flags.refresh || request->flags.loopdetect || request->flags.need_validation))
 
154
            debugs(15, 2, "peerAllowedToUse(" << p->name << ", " << request->GetHost() << ") : multicast-siblings optimization match");
 
155
#endif
149
156
        if (request->flags.nocache)
150
157
            return 0;
151
158
 
165
172
    do_ping = 0;
166
173
 
167
174
    for (d = p->peer_domain; d; d = d->next) {
168
 
        if (0 == matchDomainName(request->host, d->domain)) {
 
175
        if (0 == matchDomainName(request->GetHost(), d->domain)) {
169
176
            do_ping = d->do_ping;
170
177
            break;
171
178
        }
179
186
    if (p->access == NULL)
180
187
        return do_ping;
181
188
 
182
 
    ACLChecklist checklist;
183
 
 
 
189
    ACLFilledChecklist checklist(p->access, request, NULL);
184
190
    checklist.src_addr = request->client_addr;
185
 
 
186
191
    checklist.my_addr = request->my_addr;
187
192
 
188
 
    checklist.my_port = request->my_port;
189
 
 
190
 
    checklist.request = HTTPMSGLOCK(request);
191
 
 
192
 
    checklist.accessList = cbdataReference(p->access);
193
 
 
194
 
    /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
195
 
 
196
193
#if 0 && USE_IDENT
197
194
    /*
198
195
     * this is currently broken because 'request->user_ident' has been
397
394
 \param data    unused.
398
395
 \todo Make the reset timing a selectable parameter in squid.conf
399
396
 */
400
 
static void 
 
397
static void
401
398
peerClearRRLoop(void *data)
402
399
{
403
400
    peerClearRR();
421
418
/**
422
419
 * Called whenever the round-robin counters need to be reset to a sane state.
423
420
 * So far those times are:
424
 
 \item On startup and reconfigure - to set the counters to sane initial settings.
425
 
 \item When a peer has revived from dead, to prevent the revived peer being
 
421
 *  - On startup and reconfigure - to set the counters to sane initial settings.
 
422
 *  -  When a peer has revived from dead, to prevent the revived peer being
426
423
 *     flooded with requests which it has 'missed' during the down period.
427
424
 */
428
425
void
477
474
/*
478
475
 * XXX DW thinks this function is equivalent to/redundant with
479
476
 * getFirstUpParent().  peerHTTPOkay() only returns true if the
480
 
 * peer is UP anyway, so this function would not return a 
 
477
 * peer is UP anyway, so this function would not return a
481
478
 * DOWN parent.
482
479
 */
483
480
peer *
539
536
    first_ping = Config.peers;
540
537
}
541
538
 
 
539
static void
 
540
neighborsRegisterWithCacheManager()
 
541
{
 
542
    CacheManager *manager = CacheManager::GetInstance();
 
543
    manager->registerAction("server_list",
 
544
                            "Peer Cache Statistics",
 
545
                            neighborDumpPeers, 0, 1);
 
546
 
 
547
    if (theInIcpConnection >= 0) {
 
548
        manager->registerAction("non_peers",
 
549
                                "List of Unknown sites sending ICP messages",
 
550
                                neighborDumpNonPeers, 0, 1);
 
551
    }
 
552
}
 
553
 
542
554
void
543
555
neighbors_init(void)
544
556
{
545
 
 
546
 
    struct sockaddr_in name;
547
 
 
548
 
    socklen_t len = sizeof(struct sockaddr_in);
549
 
 
 
557
    IpAddress nul;
 
558
    struct addrinfo *AI = NULL;
550
559
    struct servent *sep = NULL;
551
560
    const char *me = getMyHostname();
552
 
    peer *thisPeer;
553
 
    peer *next;
 
561
    peer *thisPeer = NULL;
 
562
    peer *next = NULL;
554
563
    int fd = theInIcpConnection;
555
564
 
 
565
    neighborsRegisterWithCacheManager();
 
566
 
 
567
    /* setup addrinfo for use */
 
568
    nul.InitAddrInfo(AI);
 
569
 
556
570
    if (fd >= 0) {
557
571
 
558
 
        memset(&name, '\0', sizeof(struct sockaddr_in));
559
 
 
560
 
        if (getsockname(fd, (struct sockaddr *) &name, &len) < 0)
561
 
            debugs(15, 1, "getsockname(" << fd << "," << &name << "," << &len << ") failed.");
 
572
        if (getsockname(fd, AI->ai_addr, &AI->ai_addrlen) < 0)
 
573
            debugs(15, 1, "getsockname(" << fd << "," << AI->ai_addr << "," << &AI->ai_addrlen << ") failed.");
562
574
 
563
575
        for (thisPeer = Config.peers; thisPeer; thisPeer = next) {
564
 
            http_port_list *s;
 
576
            http_port_list *s = NULL;
565
577
            next = thisPeer->next;
566
578
 
567
579
            if (0 != strcmp(thisPeer->host, me))
568
580
                continue;
569
581
 
570
582
            for (s = Config.Sockaddr.http; s; s = s->next) {
571
 
                if (thisPeer->http_port != ntohs(s->s.sin_port))
 
583
                if (thisPeer->http_port != s->s.GetPort())
572
584
                    continue;
573
585
 
574
586
                debugs(15, 1, "WARNING: Peer looks like this host");
578
590
                       "/" << thisPeer->http_port << "/" <<
579
591
                       thisPeer->icp.port);
580
592
 
581
 
 
582
593
                neighborRemove(thisPeer);
583
594
            }
584
595
        }
593
604
        echo_hdr.reqnum = 0;
594
605
        echo_hdr.flags = 0;
595
606
        echo_hdr.pad = 0;
596
 
        echo_hdr.shostid = name.sin_addr.s_addr;
 
607
        nul = *AI;
 
608
        nul.GetInAddr( *((struct in_addr*)&echo_hdr.shostid) );
597
609
        sep = getservbyname("echo", "udp");
598
610
        echo_port = sep ? ntohs((u_short) sep->s_port) : 7;
599
611
    }
600
612
 
601
613
    first_ping = Config.peers;
602
 
}
603
 
 
604
 
void
605
 
neighborsRegisterWithCacheManager(CacheManager & manager)
606
 
{
607
 
    manager.registerAction("server_list",
608
 
                           "Peer Cache Statistics",
609
 
                           neighborDumpPeers, 0, 1);
610
 
 
611
 
    if (theInIcpConnection >= 0) {
612
 
        manager.registerAction("non_peers",
613
 
                               "List of Unknown sites sending ICP messages",
614
 
                               neighborDumpNonPeers, 0, 1);
615
 
    }
616
 
 
617
 
    /* XXX FIXME: unregister if we were registered. Something like:
618
 
     * else {
619
 
     *   CacheManagerAction * action = manager.findAction("non_peers");
620
 
     *   if (action != NULL)
621
 
     *       manager.unregisterAction(action);
622
 
     *  }
623
 
     */
 
614
    nul.FreeAddrInfo(AI);
624
615
}
625
616
 
626
617
int
675
666
        debugs(15, 3, "neighborsUdpPing: reqnum = " << reqnum);
676
667
 
677
668
#if USE_HTCP
678
 
 
679
 
        if (p->options.htcp) {
 
669
        if (p->options.htcp && !p->options.htcp_only_clr) {
680
670
            if (Config.Port.htcp <= 0) {
681
671
                debugs(15, DBG_CRITICAL, "HTCP is disabled! Cannot send HTCP request to peer.");
682
672
                continue;
699
689
                    debugs(15, 4, "neighborsUdpPing: Looks like a dumb cache, send DECHO ping");
700
690
                    echo_hdr.reqnum = reqnum;
701
691
                    query = _icp_common_t::createMessage(ICP_DECHO, 0, url, reqnum, 0);
702
 
                    icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0);
 
692
                    icpUdpSend(theOutIcpConnection,p->in_addr,query,LOG_ICP_QUERY,0);
703
693
                } else {
704
694
                    flags = 0;
705
695
 
709
699
 
710
700
                    query = _icp_common_t::createMessage(ICP_QUERY, flags, url, reqnum, 0);
711
701
 
712
 
                    icpUdpSend(theOutIcpConnection, &p->in_addr, query, LOG_ICP_QUERY, 0);
 
702
                    icpUdpSend(theOutIcpConnection, p->in_addr, query, LOG_ICP_QUERY, 0);
713
703
                }
714
704
            }
715
705
        }
755
745
    if ((first_ping = first_ping->next) == NULL)
756
746
        first_ping = Config.peers;
757
747
 
758
 
#if ALLOW_SOURCE_PING
759
 
    /* only do source_ping if we have neighbors */
760
 
    if (Config.npeers) {
761
 
        const ipcache_addrs *ia = NULL;
762
 
 
763
 
        struct sockaddr_in to_addr;
764
 
        char *host = request->host;
765
 
 
766
 
        if (!Config.onoff.source_ping) {
767
 
            debugs(15, 6, "neighborsUdpPing: Source Ping is disabled.");
768
 
        } else if ((ia = ipcache_gethostbyname(host, 0))) {
769
 
            debugs(15, 6, "neighborsUdpPing: Source Ping: to " << host << " for '" << url << "'");
770
 
            echo_hdr.reqnum = reqnum;
771
 
 
772
 
            if (icmp_sock != -1) {
773
 
                icmpSourcePing(ia->in_addrs[ia->cur], &echo_hdr, url);
774
 
            } else {
775
 
                to_addr.sin_family = AF_INET;
776
 
                to_addr.sin_addr = ia->in_addrs[ia->cur];
777
 
                to_addr.sin_port = htons(echo_port);
778
 
                query = _icp_common_t::createMessage(ICP_SECHO, 0, url, reqnum, 0);
779
 
                icpUdpSend(theOutIcpConnection,
780
 
                           &to_addr,
781
 
                           query,
782
 
                           LOG_ICP_QUERY,
783
 
                           0);
784
 
            }
785
 
        } else {
786
 
            debugs(15, 6, "neighborsUdpPing: Source Ping: unknown host: " << host);
787
 
        }
788
 
    }
789
 
 
790
 
#endif
791
748
    /*
792
749
     * How many replies to expect?
793
750
     */
939
896
 
940
897
    request->hier.cd_lookup = lookup;
941
898
 
942
 
    debugs(15, 4, "peerNoteDigestLookup: peer " << 
943
 
                  (p ? p->host : "<none>") << ", lookup: " << 
944
 
                  lookup_t_str[lookup]  );
 
899
    debugs(15, 4, "peerNoteDigestLookup: peer " <<
 
900
           (p ? p->host : "<none>") << ", lookup: " <<
 
901
           lookup_t_str[lookup]  );
945
902
 
946
903
#endif
947
904
}
979
936
    if (p->options.weighted_roundrobin)
980
937
        rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
981
938
 
982
 
    p->stats.rtt = intAverage(p->stats.rtt, rtt,
983
 
                              p->stats.pings_acked, rtt_av_factor);
 
939
    p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, p->stats.pings_acked, rtt_av_factor);
984
940
}
985
941
 
986
942
#if USE_HTCP
1009
965
static peer *non_peers = NULL;
1010
966
 
1011
967
static void
1012
 
 
1013
 
neighborIgnoreNonPeer(const struct sockaddr_in *from, icp_opcode opcode)
 
968
neighborIgnoreNonPeer(const IpAddress &from, icp_opcode opcode)
1014
969
{
1015
970
    peer *np;
1016
971
 
1017
 
    for (np = non_peers; np; np = np->next)
1018
 
    {
1019
 
        if (np->in_addr.sin_addr.s_addr != from->sin_addr.s_addr)
 
972
    for (np = non_peers; np; np = np->next) {
 
973
        if (np->in_addr != from)
1020
974
            continue;
1021
975
 
1022
 
        if (np->in_addr.sin_port != from->sin_port)
 
976
        if (np->in_addr.GetPort() != from.GetPort())
1023
977
            continue;
1024
978
 
1025
979
        break;
1026
980
    }
1027
981
 
1028
 
    if (np == NULL)
1029
 
    {
 
982
    if (np == NULL) {
1030
983
        np = (peer *)xcalloc(1, sizeof(peer));
1031
 
        np->in_addr.sin_addr = from->sin_addr;
1032
 
        np->in_addr.sin_port = from->sin_port;
1033
 
        np->icp.port = ntohl(from->sin_port);
 
984
        np->in_addr = from;
 
985
        np->icp.port = from.GetPort();
1034
986
        np->type = PEER_NONE;
1035
 
        np->host = xstrdup(inet_ntoa(from->sin_addr));
 
987
        np->host = new char[MAX_IPSTRLEN];
 
988
        from.NtoA(np->host,MAX_IPSTRLEN);
1036
989
        np->next = non_peers;
1037
990
        non_peers = np;
1038
991
    }
1044
997
}
1045
998
 
1046
999
/* ignoreMulticastReply
1047
 
 * 
 
1000
 *
1048
1001
 * * We want to ignore replies from multicast peers if the
1049
1002
 * * cache_host_domain rules would normally prevent the peer
1050
1003
 * * from being used
1067
1020
/* I should attach these records to the entry.  We take the first
1068
1021
 * hit we get our wait until everyone misses.  The timeout handler
1069
1022
 * call needs to nip this shopping list or call one of the misses.
1070
 
 * 
 
1023
 *
1071
1024
 * If a hit process is already started, then sobeit
1072
1025
 */
1073
1026
void
1074
1027
 
1075
 
neighborsUdpAck(const cache_key * key, icp_common_t * header, const struct sockaddr_in *from)
 
1028
neighborsUdpAck(const cache_key * key, icp_common_t * header, const IpAddress &from)
1076
1029
{
1077
1030
    peer *p = NULL;
1078
1031
    StoreEntry *entry;
1098
1051
        neighborUpdateRtt(p, mem);
1099
1052
 
1100
1053
    /* Does the entry exist? */
1101
 
    if (NULL == entry)
1102
 
    {
 
1054
    if (NULL == entry) {
1103
1055
        debugs(12, 3, "neighborsUdpAck: Cache key '" << storeKeyText(key) << "' not found");
1104
1056
        neighborCountIgnored(p);
1105
1057
        return;
1106
1058
    }
1107
1059
 
1108
1060
    /* check if someone is already fetching it */
1109
 
    if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED))
1110
 
    {
 
1061
    if (EBIT_TEST(entry->flags, ENTRY_DISPATCHED)) {
1111
1062
        debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1112
1063
        neighborCountIgnored(p);
1113
1064
        return;
1114
1065
    }
1115
1066
 
1116
 
    if (mem == NULL)
1117
 
    {
 
1067
    if (mem == NULL) {
1118
1068
        debugs(15, 2, "Ignoring " << opcode_d << " for missing mem_obj: " << storeKeyText(key));
1119
1069
        neighborCountIgnored(p);
1120
1070
        return;
1121
1071
    }
1122
1072
 
1123
 
    if (entry->ping_status != PING_WAITING)
1124
 
    {
 
1073
    if (entry->ping_status != PING_WAITING) {
1125
1074
        debugs(15, 2, "neighborsUdpAck: Late " << opcode_d << " for " << storeKeyText(key));
1126
1075
        neighborCountIgnored(p);
1127
1076
        return;
1128
1077
    }
1129
1078
 
1130
 
    if (entry->lock_count == 0)
1131
 
    {
 
1079
    if (entry->lock_count == 0) {
1132
1080
        debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1133
1081
        neighborCountIgnored(p);
1134
1082
        return;
1136
1084
 
1137
1085
    debugs(15, 3, "neighborsUdpAck: " << opcode_d << " for '" << storeKeyText(key) << "' from " << (p ? p->host : "source") << " ");
1138
1086
 
1139
 
    if (p)
1140
 
    {
 
1087
    if (p) {
1141
1088
        ntype = neighborType(p, mem->request);
1142
1089
    }
1143
1090
 
1144
 
    if (ignoreMulticastReply(p, mem))
1145
 
    {
 
1091
    if (ignoreMulticastReply(p, mem)) {
1146
1092
        neighborCountIgnored(p);
1147
 
    } else if (opcode == ICP_MISS)
1148
 
    {
 
1093
    } else if (opcode == ICP_MISS) {
1149
1094
        if (p == NULL) {
1150
1095
            neighborIgnoreNonPeer(from, opcode);
1151
1096
        } else {
1152
1097
            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1153
1098
        }
1154
 
    } else if (opcode == ICP_HIT)
1155
 
    {
 
1099
    } else if (opcode == ICP_HIT) {
1156
1100
        if (p == NULL) {
1157
1101
            neighborIgnoreNonPeer(from, opcode);
1158
1102
        } else {
1159
1103
            header->opcode = ICP_HIT;
1160
1104
            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1161
1105
        }
1162
 
    } else if (opcode == ICP_DECHO)
1163
 
    {
 
1106
    } else if (opcode == ICP_DECHO) {
1164
1107
        if (p == NULL) {
1165
1108
            neighborIgnoreNonPeer(from, opcode);
1166
1109
        } else if (ntype == PEER_SIBLING) {
1169
1112
        } else {
1170
1113
            mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1171
1114
        }
1172
 
    } else if (opcode == ICP_SECHO)
1173
 
    {
 
1115
    } else if (opcode == ICP_SECHO) {
1174
1116
        if (p) {
1175
1117
            debugs(15, 1, "Ignoring SECHO from neighbor " << p->host);
1176
1118
            neighborCountIgnored(p);
1177
 
#if ALLOW_SOURCE_PING
1178
 
 
1179
 
        } else if (Config.onoff.source_ping) {
1180
 
            mem->ping_reply_callback(NULL, ntype, PROTO_ICP, header, mem->ircb_data);
1181
 
#endif
1182
 
 
1183
1119
        } else {
1184
 
            debugs(15, 1, "Unsolicited SECHO from " << inet_ntoa(from->sin_addr));
 
1120
            debugs(15, 1, "Unsolicited SECHO from " << from);
1185
1121
        }
1186
 
    } else if (opcode == ICP_DENIED)
1187
 
    {
 
1122
    } else if (opcode == ICP_DENIED) {
1188
1123
        if (p == NULL) {
1189
1124
            neighborIgnoreNonPeer(from, opcode);
1190
1125
        } else if (p->stats.pings_acked > 100) {
1197
1132
                neighborCountIgnored(p);
1198
1133
            }
1199
1134
        }
1200
 
    } else if (opcode == ICP_MISS_NOFETCH)
1201
 
    {
 
1135
    } else if (opcode == ICP_MISS_NOFETCH) {
1202
1136
        mem->ping_reply_callback(p, ntype, PROTO_ICP, header, mem->ircb_data);
1203
 
    } else
1204
 
    {
 
1137
    } else {
1205
1138
        debugs(15, 0, "neighborsUdpAck: Unexpected ICP reply: " << opcode_d);
1206
1139
    }
1207
1140
}
1241
1174
neighborUp(const peer * p)
1242
1175
{
1243
1176
    if (!p->tcp_up) {
1244
 
        if (!peerProbeConnect((peer *) p))
 
1177
        if (!peerProbeConnect((peer *) p)) {
 
1178
            debugs(15, 8, "neighborUp: DOWN (probed): " << p->host << " (" << p->in_addr << ")");
1245
1179
            return 0;
 
1180
        }
1246
1181
    }
1247
1182
 
1248
1183
    /*
1249
1184
     * The peer can not be UP if we don't have any IP addresses
1250
 
     * for it. 
 
1185
     * for it.
1251
1186
     */
1252
 
    if (0 == p->n_addresses)
 
1187
    if (0 == p->n_addresses) {
 
1188
        debugs(15, 8, "neighborUp: DOWN (no-ip): " << p->host << " (" << p->in_addr << ")");
1253
1189
        return 0;
 
1190
    }
1254
1191
 
1255
 
    if (p->options.no_query)
 
1192
    if (p->options.no_query) {
 
1193
        debugs(15, 8, "neighborUp: UP (no-query): " << p->host << " (" << p->in_addr << ")");
1256
1194
        return 1;
 
1195
    }
1257
1196
 
1258
1197
    if (p->stats.probe_start != 0 &&
1259
 
            squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer)
 
1198
            squid_curtime - p->stats.probe_start > Config.Timeout.deadPeer) {
 
1199
        debugs(15, 8, "neighborUp: DOWN (dead): " << p->host << " (" << p->in_addr << ")");
1260
1200
        return 0;
 
1201
    }
1261
1202
 
 
1203
    debugs(15, 8, "neighborUp: UP: " << p->host << " (" << p->in_addr << ")");
1262
1204
    return 1;
1263
1205
}
1264
1206
 
1298
1240
}
1299
1241
 
1300
1242
static void
1301
 
peerDNSConfigure(const ipcache_addrs * ia, void *data)
 
1243
peerDNSConfigure(const ipcache_addrs *ia, const DnsLookupDetails &, void *data)
1302
1244
{
1303
1245
    peer *p = (peer *)data;
1304
1246
 
1305
 
    struct sockaddr_in *ap;
1306
1247
    int j;
1307
1248
 
1308
1249
    if (p->n_addresses == 0) {
1324
1265
        return;
1325
1266
    }
1326
1267
 
1327
 
    p->tcp_up = PEER_TCP_MAGIC_COUNT;
 
1268
    p->tcp_up = p->connect_fail_limit;
1328
1269
 
1329
1270
    for (j = 0; j < (int) ia->count && j < PEER_MAX_ADDRESSES; j++) {
1330
1271
        p->addresses[j] = ia->in_addrs[j];
1331
 
        debugs(15, 2, "--> IP address #" << j << ": " << inet_ntoa(p->addresses[j]));
 
1272
        debugs(15, 2, "--> IP address #" << j << ": " << p->addresses[j]);
1332
1273
        p->n_addresses++;
1333
1274
    }
1334
1275
 
1335
 
    ap = &p->in_addr;
1336
 
 
1337
 
    memset(ap, '\0', sizeof(struct sockaddr_in));
1338
 
    ap->sin_family = AF_INET;
1339
 
    ap->sin_addr = p->addresses[0];
1340
 
    ap->sin_port = htons(p->icp.port);
 
1276
    p->in_addr.SetEmpty();
 
1277
    p->in_addr = p->addresses[0];
 
1278
    p->in_addr.SetPort(p->icp.port);
1341
1279
 
1342
1280
    if (p->type == PEER_MULTICAST)
1343
1281
        peerCountMcastPeersSchedule(p, 10);
1344
1282
 
 
1283
#if USE_ICMP
1345
1284
    if (p->type != PEER_MULTICAST)
1346
1285
        if (!p->options.no_netdb_exchange)
1347
1286
            eventAddIsh("netdbExchangeStart", netdbExchangeStart, p, 30.0, 1);
 
1287
#endif
 
1288
 
1348
1289
}
1349
1290
 
1350
1291
static void
1399
1340
{
1400
1341
    if (!p->tcp_up) {
1401
1342
        debugs(15, 2, "TCP connection to " << p->host << "/" << p->http_port << " succeded");
1402
 
        p->tcp_up = PEER_TCP_MAGIC_COUNT; // NP: so peerAlive(p) works properly.
 
1343
        p->tcp_up = p->connect_fail_limit; // NP: so peerAlive(p) works properly.
1403
1344
        peerAlive(p);
1404
 
        if (!p->n_addresses)
1405
 
            ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
1406
 
    }
1407
 
    else
1408
 
        p->tcp_up = PEER_TCP_MAGIC_COUNT;
 
1345
        if (!p->n_addresses)
 
1346
            ipcache_nbgethostbyname(p->host, peerDNSConfigure, p);
 
1347
    } else
 
1348
        p->tcp_up = p->connect_fail_limit;
 
1349
}
 
1350
 
 
1351
/// called by Comm when test_fd is closed while connect is in progress
 
1352
static void
 
1353
peerProbeClosed(int fd, void *data)
 
1354
{
 
1355
    peer *p = (peer*)data;
 
1356
    p->test_fd = -1;
 
1357
    // it is a failure because we failed to connect
 
1358
    peerConnectFailedSilent(p);
1409
1359
}
1410
1360
 
1411
1361
static void
1412
1362
peerProbeConnectTimeout(int fd, void *data)
1413
1363
{
1414
1364
    peer * p = (peer *)data;
 
1365
    comm_remove_close_handler(fd, &peerProbeClosed, p);
1415
1366
    comm_close(fd);
1416
1367
    p->test_fd = -1;
1417
1368
    peerConnectFailedSilent(p);
1418
1369
}
1419
1370
 
1420
1371
/*
1421
 
* peerProbeConnect will be called on dead peers by neighborUp 
 
1372
* peerProbeConnect will be called on dead peers by neighborUp
1422
1373
*/
1423
1374
static int
1424
1375
peerProbeConnect(peer * p)
1434
1385
    if (squid_curtime - p->stats.last_connect_probe == 0)
1435
1386
        return ret;/* don't probe to often */
1436
1387
 
1437
 
    fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL),
1438
 
                   0, COMM_NONBLOCKING, p->host);
 
1388
    IpAddress temp(getOutgoingAddr(NULL,p));
 
1389
 
 
1390
    fd = comm_open(SOCK_STREAM, IPPROTO_TCP, temp, COMM_NONBLOCKING, p->host);
1439
1391
 
1440
1392
    if (fd < 0)
1441
1393
        return ret;
1442
1394
 
 
1395
    comm_add_close_handler(fd, &peerProbeClosed, p);
1443
1396
    commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p);
1444
1397
 
1445
1398
    p->test_fd = fd;
1456
1409
}
1457
1410
 
1458
1411
static void
1459
 
peerProbeConnectDone(int fd, comm_err_t status, int xerrno, void *data)
 
1412
peerProbeConnectDone(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data)
1460
1413
{
1461
1414
    peer *p = (peer*)data;
1462
1415
 
1466
1419
        peerConnectFailedSilent(p);
1467
1420
    }
1468
1421
 
 
1422
    comm_remove_close_handler(fd, &peerProbeClosed, p);
1469
1423
    comm_close(fd);
1470
1424
    p->test_fd = -1;
1471
1425
    return;
1497
1451
    LOCAL_ARRAY(char, url, MAX_URL);
1498
1452
    assert(p->type == PEER_MULTICAST);
1499
1453
    p->mcast.flags.count_event_pending = 0;
1500
 
    snprintf(url, MAX_URL, "http://%s/", inet_ntoa(p->in_addr.sin_addr));
 
1454
    snprintf(url, MAX_URL, "http://");
 
1455
    p->in_addr.ToURL(url+7, MAX_URL -8 );
 
1456
    strcat(url, "/");
1501
1457
    fake = storeCreateEntry(url, url, request_flags(), METHOD_GET);
1502
1458
    HttpRequest *req = HttpRequest::CreateFromUrl(url);
1503
1459
    psstate = new ps_state;
1516
1472
    reqnum = icpSetCacheKey((const cache_key *)fake->key);
1517
1473
    query = _icp_common_t::createMessage(ICP_QUERY, 0, url, reqnum, 0);
1518
1474
    icpUdpSend(theOutIcpConnection,
1519
 
               &p->in_addr,
 
1475
               p->in_addr,
1520
1476
               query,
1521
1477
               LOG_ICP_QUERY,
1522
1478
               0);
1538
1494
    if (cbdataReferenceValid(psstate->callback_data)) {
1539
1495
        peer *p = (peer *)psstate->callback_data;
1540
1496
        p->mcast.flags.counting = 0;
1541
 
        p->mcast.avg_n_members = doubleAverage(p->mcast.avg_n_members,
1542
 
                                               (double) psstate->ping.n_recv,
1543
 
                                               ++p->mcast.n_times_counted,
1544
 
                                               10);
 
1497
        p->mcast.avg_n_members = Math::doubleAverage(p->mcast.avg_n_members, (double) psstate->ping.n_recv, ++p->mcast.n_times_counted, 10);
1545
1498
        debugs(15, 1, "Group " << p->host  << ": " << psstate->ping.n_recv  <<
1546
1499
               " replies, "<< std::setw(4)<< std::setprecision(2) <<
1547
1500
               p->mcast.avg_n_members <<" average, RTT " << p->stats.rtt);
1576
1529
    if (p->options.weighted_roundrobin)
1577
1530
        rtt_av_factor = RTT_BACKGROUND_AV_FACTOR;
1578
1531
 
1579
 
    p->stats.rtt = intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
 
1532
    p->stats.rtt = Math::intAverage(p->stats.rtt, rtt, psstate->ping.n_recv, rtt_av_factor);
1580
1533
}
1581
1534
 
1582
1535
static void
1612
1565
    if (p->options.roundrobin)
1613
1566
        storeAppendPrintf(sentry, " round-robin");
1614
1567
 
1615
 
#if USE_CARP
1616
1568
    if (p->options.carp)
1617
1569
        storeAppendPrintf(sentry, " carp");
1618
 
#endif
1619
1570
 
1620
1571
    if (p->options.userhash)
1621
1572
        storeAppendPrintf(sentry, " userhash");
1629
1580
    if (p->options.mcast_responder)
1630
1581
        storeAppendPrintf(sentry, " multicast-responder");
1631
1582
 
 
1583
#if PEER_MULTICAST_SIBLINGS
 
1584
    if (p->options.mcast_siblings)
 
1585
        storeAppendPrintf(sentry, " multicast-siblings");
 
1586
#endif
 
1587
 
1632
1588
    if (p->weight != 1)
1633
1589
        storeAppendPrintf(sentry, " weight=%d", p->weight);
1634
1590
 
1636
1592
        storeAppendPrintf(sentry, " closest-only");
1637
1593
 
1638
1594
#if USE_HTCP
1639
 
 
1640
1595
    if (p->options.htcp)
1641
1596
        storeAppendPrintf(sentry, " htcp");
1642
 
 
 
1597
    if (p->options.htcp_oldsquid)
 
1598
        storeAppendPrintf(sentry, " htcp-oldsquid");
 
1599
    if (p->options.htcp_no_clr)
 
1600
        storeAppendPrintf(sentry, " htcp-no-clr");
 
1601
    if (p->options.htcp_no_purge_clr)
 
1602
        storeAppendPrintf(sentry, " htcp-no-purge-clr");
 
1603
    if (p->options.htcp_only_clr)
 
1604
        storeAppendPrintf(sentry, " htcp-only-clr");
1643
1605
#endif
1644
1606
 
1645
1607
    if (p->options.no_netdb_exchange)
1661
1623
    if (p->connect_timeout > 0)
1662
1624
        storeAppendPrintf(sentry, " connect-timeout=%d", (int) p->connect_timeout);
1663
1625
 
 
1626
    if (p->connect_fail_limit != PEER_TCP_MAGIC_COUNT)
 
1627
        storeAppendPrintf(sentry, " connect-fail-limit=%d", p->connect_fail_limit);
 
1628
 
1664
1629
#if USE_CACHE_DIGESTS
1665
1630
 
1666
1631
    if (p->digest_url)
1671
1636
    if (p->options.allow_miss)
1672
1637
        storeAppendPrintf(sentry, " allow-miss");
1673
1638
 
 
1639
    if (p->options.no_tproxy)
 
1640
        storeAppendPrintf(sentry, " no-tproxy");
 
1641
 
1674
1642
    if (p->max_conn > 0)
1675
1643
        storeAppendPrintf(sentry, " max-conn=%d", p->max_conn);
1676
1644
 
1680
1648
    if (p->domain)
1681
1649
        storeAppendPrintf(sentry, " forceddomain=%s", p->domain);
1682
1650
 
 
1651
    if (p->connection_auth == 0)
 
1652
        storeAppendPrintf(sentry, " connection-auth=off");
 
1653
    else if (p->connection_auth == 1)
 
1654
        storeAppendPrintf(sentry, " connection-auth=on");
 
1655
    else if (p->connection_auth == 2)
 
1656
        storeAppendPrintf(sentry, " connection-auth=auto");
 
1657
 
1683
1658
    storeAppendPrintf(sentry, "\n");
1684
1659
}
1685
1660
 
1687
1662
dump_peers(StoreEntry * sentry, peer * peers)
1688
1663
{
1689
1664
    peer *e = NULL;
1690
 
 
 
1665
    char ntoabuf[MAX_IPSTRLEN];
1691
1666
    struct _domain_ping *d = NULL;
1692
1667
    icp_opcode op;
1693
1668
    int i;
1709
1684
 
1710
1685
        for (i = 0; i < e->n_addresses; i++) {
1711
1686
            storeAppendPrintf(sentry, "Address[%d] : %s\n", i,
1712
 
                              inet_ntoa(e->addresses[i]));
 
1687
                              e->addresses[i].NtoA(ntoabuf,MAX_IPSTRLEN) );
1713
1688
        }
1714
1689
 
1715
1690
        storeAppendPrintf(sentry, "Status     : %s\n",
1732
1707
 
1733
1708
            storeAppendPrintf(sentry, "PINGS ACKED: %8d %3d%%\n",
1734
1709
                              e->stats.pings_acked,
1735
 
                              percent(e->stats.pings_acked, e->stats.pings_sent));
 
1710
                              Math::intPercent(e->stats.pings_acked, e->stats.pings_sent));
1736
1711
        }
1737
1712
 
1738
 
        storeAppendPrintf(sentry, "IGNORED    : %8d %3d%%\n",
1739
 
                          e->stats.ignored_replies,
1740
 
                          percent(e->stats.ignored_replies, e->stats.pings_acked));
 
1713
        storeAppendPrintf(sentry, "IGNORED    : %8d %3d%%\n", e->stats.ignored_replies, Math::intPercent(e->stats.ignored_replies, e->stats.pings_acked));
1741
1714
 
1742
1715
        if (!e->options.no_query) {
1743
1716
            storeAppendPrintf(sentry, "Histogram of PINGS ACKED:\n");
1746
1719
            if (e->options.htcp) {
1747
1720
                storeAppendPrintf(sentry, "\tMisses\t%8d %3d%%\n",
1748
1721
                                  e->htcp.counts[0],
1749
 
                                  percent(e->htcp.counts[0], e->stats.pings_acked));
 
1722
                                  Math::intPercent(e->htcp.counts[0], e->stats.pings_acked));
1750
1723
                storeAppendPrintf(sentry, "\tHits\t%8d %3d%%\n",
1751
1724
                                  e->htcp.counts[1],
1752
 
                                  percent(e->htcp.counts[1], e->stats.pings_acked));
 
1725
                                  Math::intPercent(e->htcp.counts[1], e->stats.pings_acked));
1753
1726
            } else {
1754
1727
#endif
1755
1728
 
1760
1733
                    storeAppendPrintf(sentry, "    %12.12s : %8d %3d%%\n",
1761
1734
                                      icp_opcode_str[op],
1762
1735
                                      e->icp.counts[op],
1763
 
                                      percent(e->icp.counts[op], e->stats.pings_acked));
 
1736
                                      Math::intPercent(e->icp.counts[op], e->stats.pings_acked));
1764
1737
                }
1765
1738
 
1766
1739
#if USE_HTCP
1787
1760
            storeAppendPrintf(sentry, "\n");
1788
1761
        }
1789
1762
 
1790
 
        storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
1791
 
                          percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
 
1763
        storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n", Math::intPercent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
1792
1764
    }
1793
1765
}
1794
1766
 
1795
1767
#if USE_HTCP
1796
1768
void
1797
 
 
1798
 
neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const struct sockaddr_in *from)
 
1769
neighborsHtcpReply(const cache_key * key, htcpReplyData * htcp, const IpAddress &from)
1799
1770
{
1800
1771
    StoreEntry *e = Store::Root().get(key);
1801
1772
    MemObject *mem = NULL;
1802
1773
    peer *p;
1803
1774
    peer_t ntype = PEER_NONE;
1804
 
    debugs(15, 6, "neighborsHtcpReply: " << 
1805
 
                  (htcp->hit ? "HIT" : "MISS") << " " << 
1806
 
                  storeKeyText(key)  );
 
1775
    debugs(15, 6, "neighborsHtcpReply: " <<
 
1776
           (htcp->hit ? "HIT" : "MISS") << " " <<
 
1777
           storeKeyText(key)  );
1807
1778
 
1808
1779
    if (NULL != e)
1809
1780
        mem = e->mem_obj;
1812
1783
        neighborAliveHtcp(p, mem, htcp);
1813
1784
 
1814
1785
    /* Does the entry exist? */
1815
 
    if (NULL == e)
1816
 
    {
 
1786
    if (NULL == e) {
1817
1787
        debugs(12, 3, "neighyborsHtcpReply: Cache key '" << storeKeyText(key) << "' not found");
1818
1788
        neighborCountIgnored(p);
1819
1789
        return;
1820
1790
    }
1821
1791
 
1822
1792
    /* check if someone is already fetching it */
1823
 
    if (EBIT_TEST(e->flags, ENTRY_DISPATCHED))
1824
 
    {
 
1793
    if (EBIT_TEST(e->flags, ENTRY_DISPATCHED)) {
1825
1794
        debugs(15, 3, "neighborsUdpAck: '" << storeKeyText(key) << "' already being fetched.");
1826
1795
        neighborCountIgnored(p);
1827
1796
        return;
1828
1797
    }
1829
1798
 
1830
 
    if (mem == NULL)
1831
 
    {
 
1799
    if (mem == NULL) {
1832
1800
        debugs(15, 2, "Ignoring reply for missing mem_obj: " << storeKeyText(key));
1833
1801
        neighborCountIgnored(p);
1834
1802
        return;
1835
1803
    }
1836
1804
 
1837
 
    if (e->ping_status != PING_WAITING)
1838
 
    {
 
1805
    if (e->ping_status != PING_WAITING) {
1839
1806
        debugs(15, 2, "neighborsUdpAck: Entry " << storeKeyText(key) << " is not PING_WAITING");
1840
1807
        neighborCountIgnored(p);
1841
1808
        return;
1842
1809
    }
1843
1810
 
1844
 
    if (e->lock_count == 0)
1845
 
    {
 
1811
    if (e->lock_count == 0) {
1846
1812
        debugs(12, 1, "neighborsUdpAck: '" << storeKeyText(key) << "' has no locks");
1847
1813
        neighborCountIgnored(p);
1848
1814
        return;
1849
1815
    }
1850
1816
 
1851
 
    if (p)
1852
 
    {
 
1817
    if (p) {
1853
1818
        ntype = neighborType(p, mem->request);
1854
1819
        neighborUpdateRtt(p, mem);
1855
1820
    }
1856
1821
 
1857
 
    if (ignoreMulticastReply(p, mem))
1858
 
    {
 
1822
    if (ignoreMulticastReply(p, mem)) {
1859
1823
        neighborCountIgnored(p);
1860
1824
        return;
1861
1825
    }
1864
1828
    mem->ping_reply_callback(p, ntype, PROTO_HTCP, htcp, mem->ircb_data);
1865
1829
}
1866
1830
 
 
1831
/*
 
1832
 * Send HTCP CLR messages to all peers configured to receive them.
 
1833
 */
 
1834
void
 
1835
neighborsHtcpClear(StoreEntry * e, const char *uri, HttpRequest * req, const HttpRequestMethod &method, htcp_clr_reason reason)
 
1836
{
 
1837
    peer *p;
 
1838
    char buf[128];
 
1839
 
 
1840
    for (p = Config.peers; p; p = p->next) {
 
1841
        if (!p->options.htcp) {
 
1842
            continue;
 
1843
        }
 
1844
        if (p->options.htcp_no_clr) {
 
1845
            continue;
 
1846
        }
 
1847
        if (p->options.htcp_no_purge_clr && reason == HTCP_CLR_PURGE) {
 
1848
            continue;
 
1849
        }
 
1850
        debugs(15, 3, "neighborsHtcpClear: sending CLR to " << p->in_addr.ToURL(buf, 128));
 
1851
        htcpClear(e, uri, req, method, p, reason);
 
1852
    }
 
1853
}
 
1854
 
1867
1855
#endif