]> git.ipfire.org Git - thirdparty/squid.git/blob - src/PeerSelectState.h
c682b094c211e31700b6b8216554d4fc8fafc5d2
[thirdparty/squid.git] / src / PeerSelectState.h
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #ifndef SQUID_PEERSELECTSTATE_H
10 #define SQUID_PEERSELECTSTATE_H
11
12 #include "AccessLogEntry.h"
13 #include "acl/Checklist.h"
14 #include "base/CbcPointer.h"
15 #include "comm/forward.h"
16 #include "hier_code.h"
17 #include "ip/Address.h"
18 #include "ipcache.h"
19 #include "mem/forward.h"
20 #include "PingData.h"
21
22 class ErrorState;
23 class HtcpReplyData;
24 class HttpRequest;
25 class icp_common_t;
26 class StoreEntry;
27
28 void peerSelectInit(void);
29
30 /// Interface for those who need a list of peers to forward a request to.
31 class PeerSelectionInitiator: public CbdataParent
32 {
33 public:
34 virtual ~PeerSelectionInitiator() = default;
35
36 /// called when a new unique destination has been found
37 virtual void noteDestination(Comm::ConnectionPointer path) = 0;
38
39 /// called when there will be no more noteDestination() calls
40 /// \param error is a possible reason why no destinations were found; it is
41 /// guaranteed to be nil if there was at least one noteDestination() call
42 virtual void noteDestinationsEnd(ErrorState *error) = 0;
43
44 /// whether noteDestination() and noteDestinationsEnd() calls are allowed
45 bool subscribed = false;
46
47 /* protected: */
48 /// Initiates asynchronous peer selection that eventually
49 /// results in zero or more noteDestination() calls and
50 /// exactly one noteDestinationsEnd() call.
51 void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry);
52 };
53
54 class FwdServer;
55
56 /// Finds peer (including origin server) IPs for forwarding a single request.
57 /// Gives PeerSelectionInitiator each found destination, in the right order.
58 class PeerSelector: public Dns::IpReceiver
59 {
60 CBDATA_CHILD(PeerSelector);
61
62 public:
63 explicit PeerSelector(PeerSelectionInitiator*);
64 virtual ~PeerSelector() override;
65
66 /* Dns::IpReceiver API */
67 virtual void noteIp(const Ip::Address &ip) override;
68 virtual void noteIps(const Dns::CachedIps *ips, const Dns::LookupDetails &details) override;
69 virtual void noteLookup(const Dns::LookupDetails &details) override;
70
71 // Produce a URL for display identifying the transaction we are
72 // trying to locate a peer for.
73 const SBuf url() const;
74
75 /// \returns valid/interested peer initiator or nil
76 PeerSelectionInitiator *interestedInitiator();
77
78 /// \returns whether the initiator may use more destinations
79 bool wantsMoreDestinations() const;
80
81 /// processes a newly discovered/finalized path
82 void handlePath(Comm::ConnectionPointer &path, FwdServer &fs);
83
84 /// a single selection loop iteration: attempts to add more destinations
85 void selectMore();
86
87 HttpRequest *request;
88 AccessLogEntry::Pointer al; ///< info for the future access.log entry
89 StoreEntry *entry;
90
91 void *peerCountMcastPeerXXX = nullptr; ///< a hack to help peerCountMcastPeersStart()
92
93 ping_data ping;
94
95 protected:
96 bool selectionAborted();
97
98 void handlePingTimeout();
99 void handleIcpReply(CachePeer*, const peer_t, icp_common_t *header);
100 void handleIcpParentMiss(CachePeer*, icp_common_t*);
101 #if USE_HTCP
102 void handleHtcpParentMiss(CachePeer*, HtcpReplyData*);
103 void handleHtcpReply(CachePeer*, const peer_t, HtcpReplyData*);
104 #endif
105
106 int checkNetdbDirect();
107 void checkAlwaysDirectDone(const allow_t answer);
108 void checkNeverDirectDone(const allow_t answer);
109
110 void selectSomeNeighbor();
111 void selectSomeNeighborReplies();
112 void selectSomeDirect();
113 void selectSomeParent();
114 void selectAllParents();
115 void selectPinned();
116
117 void addSelection(CachePeer*, const hier_code);
118
119 void resolveSelected();
120
121 static IRCB HandlePingReply;
122 static ACLCB CheckAlwaysDirectDone;
123 static ACLCB CheckNeverDirectDone;
124 static EVH HandlePingTimeout;
125
126 private:
127 allow_t always_direct;
128 allow_t never_direct;
129 int direct; // TODO: fold always_direct/never_direct/prefer_direct into this now that ACL can do a multi-state result.
130 size_t foundPaths = 0; ///< number of unique destinations identified so far
131 ErrorState *lastError;
132
133 FwdServer *servers; ///< a linked list of (unresolved) selected peers
134
135 /*
136 * Why are these Ip::Address instead of CachePeer *? Because a
137 * CachePeer structure can become invalid during the CachePeer selection
138 * phase, specifically after a reconfigure. Thus we need to lookup
139 * the CachePeer * based on the address when we are finally ready to
140 * reference the CachePeer structure.
141 */
142
143 Ip::Address first_parent_miss;
144
145 Ip::Address closest_parent_miss;
146 /*
147 * ->hit can be CachePeer* because it should only be
148 * accessed during the thread when it is set
149 */
150 CachePeer *hit;
151 peer_t hit_type;
152 ACLChecklist *acl_checklist;
153
154 typedef CbcPointer<PeerSelectionInitiator> Initiator;
155 Initiator initiator_; ///< recipient of the destinations we select; use interestedInitiator() to access
156
157 const InstanceId<PeerSelector> id; ///< unique identification in worker log
158 };
159
160 #endif /* SQUID_PEERSELECTSTATE_H */
161