]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ResolvedPeers.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / ResolvedPeers.h
1 /*
2 * Copyright (C) 1996-2021 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_RESOLVEDPEERS_H
10 #define SQUID_RESOLVEDPEERS_H
11
12 #include "base/RefCount.h"
13 #include "comm/forward.h"
14
15 #include <iosfwd>
16 #include <limits>
17 #include <utility>
18
19 class ResolvedPeerPath
20 {
21 public:
22 explicit ResolvedPeerPath(const Comm::ConnectionPointer &conn) : connection(conn), available(true) {}
23
24 Comm::ConnectionPointer connection; ///< (the address of) a path
25 bool available; ///< whether this path may be used (i.e., has not been tried already)
26 };
27
28 class PeerConnectionPointer;
29
30 /// cache_peer and origin server addresses (a.k.a. paths)
31 /// selected and resolved by the peering code
32 class ResolvedPeers: public RefCountable
33 {
34 MEMPROXY_CLASS(ResolvedPeers);
35
36 public:
37 // ResolvedPeerPaths in addPath() call order
38 typedef std::vector<ResolvedPeerPath> Paths;
39 using size_type = Paths::size_type;
40 typedef RefCount<ResolvedPeers> Pointer;
41
42 ResolvedPeers();
43
44 /// whether we lack any known candidate paths
45 bool empty() const { return !availablePaths; }
46
47 /// add a candidate path to try after all the existing paths
48 void addPath(const Comm::ConnectionPointer &);
49
50 /// makes the previously extracted path available for extraction at its
51 /// original position
52 void reinstatePath(const PeerConnectionPointer &);
53
54 /// extracts and returns the first queued address
55 PeerConnectionPointer extractFront();
56
57 /// extracts and returns the first same-peer same-family address
58 /// \returns nil if it cannot find the requested address
59 PeerConnectionPointer extractPrime(const Comm::Connection &currentPeer);
60
61 /// extracts and returns the first same-peer different-family address
62 /// \returns nil if it cannot find the requested address
63 PeerConnectionPointer extractSpare(const Comm::Connection &currentPeer);
64
65 /// whether extractSpare() would return a non-nil path right now
66 bool haveSpare(const Comm::Connection &currentPeer);
67
68 /// whether extractPrime() returns and will continue to return nil
69 bool doneWithPrimes(const Comm::Connection &currentPeer);
70
71 /// whether extractSpare() returns and will continue to return nil
72 bool doneWithSpares(const Comm::Connection &currentPeer);
73
74 /// whether doneWithPrimes() and doneWithSpares() are true for currentPeer
75 bool doneWithPeer(const Comm::Connection &currentPeer);
76
77 /// the current number of candidate paths
78 size_type size() const { return availablePaths; }
79
80 /// whether all of the available candidate paths received from DNS
81 bool destinationsFinalized = false;
82
83 /// whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
84 bool notificationPending = false;
85
86 private:
87 /// A find*() result: An iterator of the found path (or paths_.end()) and
88 /// whether the "other" path was found instead.
89 typedef std::pair<Paths::iterator, bool> Finding;
90
91 /// The protocol family of the given path, AF_INET or AF_INET6
92 static int ConnectionFamily(const Comm::Connection &conn);
93
94 Paths::iterator start();
95 Finding findSpare(const Comm::Connection &currentPeer);
96 Finding findPrime(const Comm::Connection &currentPeer);
97 Finding findPeer(const Comm::Connection &currentPeer);
98 PeerConnectionPointer extractFound(const char *description, const Paths::iterator &found);
99 Finding makeFinding(const Paths::iterator &found, bool foundOther);
100
101 bool doneWith(const Finding &findings) const;
102
103 void increaseAvailability();
104 void decreaseAvailability();
105
106 Paths paths_; ///< resolved addresses in (peer, family) order
107
108 /// the number of leading paths_ elements that are all currently unavailable
109 /// i.e. the size of the front paths_ segment comprised of unavailable items
110 /// i.e. the position of the first available path (or paths_.size())
111 size_type pathsToSkip = 0;
112
113 /// the total number of currently available elements in paths_
114 size_type availablePaths = 0;
115 };
116
117 /// An invasive reference-counting Comm::Connection pointer that also keeps an
118 /// (optional) ResolvedPeers position for the ResolvedPeers::reinstatePath() usage.
119 /// Reference counting mechanism is compatible with Comm::ConnectionPointer.
120 class PeerConnectionPointer
121 {
122 public:
123 using size_type = ResolvedPeers::size_type;
124
125 PeerConnectionPointer() = default;
126 PeerConnectionPointer(std::nullptr_t): PeerConnectionPointer() {} ///< implicit nullptr conversion
127 PeerConnectionPointer(const Comm::ConnectionPointer &conn, const size_type pos): connection_(conn), position_(pos) {}
128
129 /* read-only pointer API; for Connection assignment, see finalize() */
130 explicit operator bool() const { return static_cast<bool>(connection_); }
131 Comm::Connection *operator->() const { assert(connection_); return connection_.getRaw(); }
132 Comm::Connection &operator *() const { assert(connection_); return *connection_; }
133
134 /// convenience conversion to Comm::ConnectionPointer
135 operator const Comm::ConnectionPointer&() const { return connection_; }
136
137 /// upgrade stored peer selection details with a matching actual connection
138 void finalize(const Comm::ConnectionPointer &conn) { connection_ = conn; }
139
140 /// debugging dump
141 void print(std::ostream &) const;
142
143 private:
144 /// non-existent position for nil connection
145 static constexpr auto npos = std::numeric_limits<size_type>::max();
146
147 /// half-baked, open, failed, or closed Comm::Connection (or nil)
148 Comm::ConnectionPointer connection_;
149
150 /// ResolvedPeers-maintained membership index (or npos)
151 size_type position_ = npos;
152 friend class ResolvedPeers;
153 };
154
155 /// summarized ResolvedPeers (for debugging)
156 std::ostream &operator <<(std::ostream &, const ResolvedPeers &);
157
158 inline std::ostream &
159 operator <<(std::ostream &os, const PeerConnectionPointer &dest)
160 {
161 dest.print(os);
162 return os;
163 }
164
165 #endif /* SQUID_RESOLVEDPEERS_H */
166