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