2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_RESOLVEDPEERS_H
10 #define SQUID_SRC_RESOLVEDPEERS_H
12 #include "base/RefCount.h"
13 #include "comm/Connection.h"
14 #include "mem/AllocatorProxy.h"
20 class ResolvedPeerPath
23 explicit ResolvedPeerPath(const Comm::ConnectionPointer
&conn
) : connection(conn
), available(true) {}
25 Comm::ConnectionPointer connection
; ///< (the address of) a path
26 bool available
; ///< whether this path may be used (i.e., has not been tried already)
29 class PeerConnectionPointer
;
31 /// cache_peer and origin server addresses (a.k.a. paths)
32 /// selected and resolved by the peering code
33 class ResolvedPeers
: public RefCountable
35 MEMPROXY_CLASS(ResolvedPeers
);
38 // ResolvedPeerPaths in addPath() call order
39 typedef std::vector
<ResolvedPeerPath
> Paths
;
40 using size_type
= Paths::size_type
;
41 typedef RefCount
<ResolvedPeers
> Pointer
;
45 /// whether we lack any known candidate paths
46 bool empty() const { return !availablePaths
; }
48 /// add a candidate path to try after all the existing paths
49 void addPath(const Comm::ConnectionPointer
&);
51 /// makes the previously extracted path available for extraction at its
53 void reinstatePath(const PeerConnectionPointer
&);
55 /// extracts and returns the first queued address
56 PeerConnectionPointer
extractFront();
58 /// extracts and returns the first same-peer same-family address
59 /// \returns nil if it cannot find the requested address
60 PeerConnectionPointer
extractPrime(const Comm::Connection
¤tPeer
);
62 /// extracts and returns the first same-peer different-family address
63 /// \returns nil if it cannot find the requested address
64 PeerConnectionPointer
extractSpare(const Comm::Connection
¤tPeer
);
66 /// whether extractSpare() would return a non-nil path right now
67 bool haveSpare(const Comm::Connection
¤tPeer
);
69 /// whether extractPrime() returns and will continue to return nil
70 bool doneWithPrimes(const Comm::Connection
¤tPeer
);
72 /// whether extractSpare() returns and will continue to return nil
73 bool doneWithSpares(const Comm::Connection
¤tPeer
);
75 /// whether doneWithPrimes() and doneWithSpares() are true for currentPeer
76 bool doneWithPeer(const Comm::Connection
¤tPeer
);
78 /// the current number of candidate paths
79 size_type
size() const { return availablePaths
; }
81 /// whether all of the available candidate paths received from DNS
82 bool destinationsFinalized
= false;
84 /// whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
85 bool notificationPending
= false;
88 /// A find*() result: An iterator of the found path (or paths_.end()) and
89 /// whether the "other" path was found instead.
90 typedef std::pair
<Paths::iterator
, bool> Finding
;
92 /// The protocol family of the given path, AF_INET or AF_INET6
93 static int ConnectionFamily(const Comm::Connection
&conn
);
95 Paths::iterator
start();
96 Finding
findSpare(const Comm::Connection
¤tPeer
);
97 Finding
findPrime(const Comm::Connection
¤tPeer
);
98 Finding
findPeer(const Comm::Connection
¤tPeer
);
99 PeerConnectionPointer
extractFound(const char *description
, const Paths::iterator
&found
);
100 Finding
makeFinding(const Paths::iterator
&found
, bool foundOther
);
102 bool doneWith(const Finding
&findings
) const;
104 void increaseAvailability();
105 void decreaseAvailability();
107 Paths paths_
; ///< resolved addresses in (peer, family) order
109 /// the number of leading paths_ elements that are all currently unavailable
110 /// i.e. the size of the front paths_ segment comprised of unavailable items
111 /// i.e. the position of the first available path (or paths_.size())
112 size_type pathsToSkip
= 0;
114 /// the total number of currently available elements in paths_
115 size_type availablePaths
= 0;
118 /// An invasive reference-counting Comm::Connection pointer that also keeps an
119 /// (optional) ResolvedPeers position for the ResolvedPeers::reinstatePath() usage.
120 /// Reference counting mechanism is compatible with Comm::ConnectionPointer.
121 class PeerConnectionPointer
124 using size_type
= ResolvedPeers::size_type
;
126 PeerConnectionPointer() = default;
127 PeerConnectionPointer(std::nullptr_t
): PeerConnectionPointer() {} ///< implicit nullptr conversion
128 PeerConnectionPointer(const Comm::ConnectionPointer
&conn
, const size_type pos
): connection_(conn
), position_(pos
) {}
130 /* read-only pointer API; for Connection assignment, see finalize() */
131 explicit operator bool() const { return static_cast<bool>(connection_
); }
132 Comm::Connection
*operator->() const { assert(connection_
); return connection_
.getRaw(); }
133 Comm::Connection
&operator *() const { assert(connection_
); return *connection_
; }
135 /// convenience conversion to Comm::ConnectionPointer
136 operator const Comm::ConnectionPointer
&() const { return connection_
; }
138 /// upgrade stored peer selection details with a matching actual connection
139 void finalize(const Comm::ConnectionPointer
&conn
) { connection_
= conn
; }
142 void print(std::ostream
&) const;
145 /// non-existent position for nil connection
146 static constexpr auto npos
= std::numeric_limits
<size_type
>::max();
148 /// half-baked, open, failed, or closed Comm::Connection (or nil)
149 Comm::ConnectionPointer connection_
;
151 /// ResolvedPeers-maintained membership index (or npos)
152 size_type position_
= npos
;
153 friend class ResolvedPeers
;
156 /// summarized ResolvedPeers (for debugging)
157 std::ostream
&operator <<(std::ostream
&, const ResolvedPeers
&);
159 inline std::ostream
&
160 operator <<(std::ostream
&os
, const PeerConnectionPointer
&dest
)
166 #endif /* SQUID_SRC_RESOLVEDPEERS_H */