2 * Copyright (C) 1996-2025 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_FWDSTATE_H
10 #define SQUID_SRC_FWDSTATE_H
12 #include "base/forward.h"
13 #include "base/JobWait.h"
14 #include "base/RefCount.h"
15 #include "clients/forward.h"
17 #include "comm/Connection.h"
18 #include "error/forward.h"
20 #include "http/StatusCode.h"
21 #include "ip/Address.h"
22 #include "ip/forward.h"
23 #include "PeerSelectState.h"
24 #include "ResolvedPeers.h"
25 #include "security/forward.h"
27 #include "ssl/support.h"
33 typedef RefCount
<AccessLogEntry
> AccessLogEntryPointer
;
37 typedef RefCount
<ResolvedPeers
> ResolvedPeersPointer
;
39 class HappyConnOpener
;
40 class HappyConnOpenerAnswer
;
42 /// Sets initial TOS value and Netfilter for the future outgoing connection.
43 /// Updates the given Connection object, not the future transport connection.
44 void GetMarkingsToServer(HttpRequest
* request
, Comm::Connection
&conn
);
46 /// Recomputes and applies TOS value and Netfilter to the outgoing connection.
47 /// Updates both the given Connection object and the transport connection.
48 void ResetMarkingsToServer(HttpRequest
*, Comm::Connection
&);
52 /// Eliminates excessive Stopwatch pause() calls in a task with multiple code
53 /// locations that pause a stopwatch. Ideally, there would be just one such
54 /// location (e.g., a task class destructor), but current code idiosyncrasies
55 /// necessitate this state. For simplicity sake, this class currently manages a
56 /// Stopwatch at a hard-coded location: HttpRequest::hier.totalPeeringTime.
57 class PeeringActivityTimer
60 PeeringActivityTimer(const HttpRequestPointer
&); ///< resumes timer
61 ~PeeringActivityTimer(); ///< \copydoc stop()
63 /// pauses timer if stop() has not been called
73 /// managed Stopwatch object within HierarchyLogEntry
76 /// the owner of managed HierarchyLogEntry
77 HttpRequestPointer request
;
79 // We cannot rely on timer().ran(): This class eliminates excessive calls
80 // within a single task (e.g., an AsyncJob) while the timer (and its ran()
81 // state) may be shared/affected by multiple concurrent tasks.
82 /// Whether the task is done participating in the managed activity.
86 class FwdState
: public RefCountable
, public PeerSelectionInitiator
88 CBDATA_CHILD(FwdState
);
91 typedef RefCount
<FwdState
> Pointer
;
93 static void initModule();
95 /// Initiates request forwarding to a peer or origin server.
96 static void Start(const Comm::ConnectionPointer
&client
, StoreEntry
*, HttpRequest
*, const AccessLogEntryPointer
&alp
);
97 /// Same as Start() but no master xaction info (AccessLogEntry) available.
98 static void fwdStart(const Comm::ConnectionPointer
&client
, StoreEntry
*, HttpRequest
*);
99 /// time left to finish the whole forwarding process (which started at fwdStart)
100 static time_t ForwardTimeout(const time_t fwdStart
);
101 /// Whether there is still time to re-try after a previous connection failure.
102 /// \param fwdStart The start time of the peer selection/connection process.
103 static bool EnoughTimeToReForward(const time_t fwdStart
);
105 /// This is the real beginning of server connection. Call it whenever
106 /// the forwarding server destination has changed and a new one needs to be opened.
107 /// Produces the cannot-forward error on fail if no better error exists.
108 void useDestinations();
110 void fail(ErrorState
*err
);
111 void unregister(Comm::ConnectionPointer
&conn
);
112 void unregister(int fd
);
115 /// Mark reply as written to Store in its entirety, including the header and
116 /// any body. If the reply has a body, the entire body has to be stored.
117 void markStoredReplyAsWhole(const char *whyWeAreSure
);
119 void handleUnregisteredServerEnd();
123 void connectDone(const Comm::ConnectionPointer
& conn
, Comm::Flag status
, int xerrno
);
125 bool checkRetriable();
128 void pconnPush(Comm::ConnectionPointer
& conn
, const char *domain
);
130 bool dontRetry() { return flags
.dont_retry
; }
132 void dontRetry(bool val
) { flags
.dont_retry
= val
; }
134 /// get rid of a to-server connection that failed to become serverConn
135 void closePendingConnection(const Comm::ConnectionPointer
&conn
, const char *reason
);
137 /** return a ConnectionPointer to the current server connection (may or may not be open) */
138 Comm::ConnectionPointer
const & serverConnection() const { return serverConn
; };
141 // hidden for safer management of self; use static fwdStart
142 FwdState(const Comm::ConnectionPointer
&client
, StoreEntry
*, HttpRequest
*, const AccessLogEntryPointer
&alp
);
143 void start(Pointer aSelf
);
144 void stopAndDestroy(const char *reason
);
146 /* PeerSelectionInitiator API */
147 void noteDestination(Comm::ConnectionPointer conn
) override
;
148 void noteDestinationsEnd(ErrorState
*selectionError
) override
;
150 bool transporting() const;
152 void noteConnection(HappyConnOpenerAnswer
&);
154 #if STRICT_ORIGINAL_DST
155 void selectPeerForIntercepted();
157 static void logReplyStatus(int tries
, const Http::StatusCode status
);
158 void doneWithRetries();
164 /// whether a pinned to-peer connection can be replaced with another one
165 /// (in order to retry or reforward a failed request)
166 bool pinnedCanRetry() const;
168 template <typename StepStart
>
169 void advanceDestination(const char *stepDescription
, const Comm::ConnectionPointer
&conn
, const StepStart
&startStep
);
171 ErrorState
*makeConnectingError(const err_type type
) const;
172 void connectedToPeer(Security::EncryptorAnswer
&answer
);
173 static void RegisterWithCacheManager(void);
175 void establishTunnelThruProxy(const Comm::ConnectionPointer
&);
176 void tunnelEstablishmentDone(Http::TunnelerAnswer
&answer
);
177 void secureConnectionToPeerIfNeeded(const Comm::ConnectionPointer
&);
178 void secureConnectionToPeer(const Comm::ConnectionPointer
&);
179 void successfullyConnectedToPeer(const Comm::ConnectionPointer
&);
181 /// stops monitoring server connection for closure and updates pconn stats
182 void closeServerConnection(const char *reason
);
184 void syncWithServerConn(const Comm::ConnectionPointer
&server
, const char *host
, const bool reused
);
185 void syncHierNote(const Comm::ConnectionPointer
&server
, const char *host
);
187 /// whether we have used up all permitted forwarding attempts
188 bool exhaustedTries() const;
189 void updateAttempts(int);
191 /// \returns the time left for this connection to become connected or 1 second if it is less than one second left
192 time_t connectingTimeout(const Comm::ConnectionPointer
&conn
) const;
194 void cancelStep(const char *reason
);
196 void notifyConnOpener();
197 void reactToZeroSizeObject();
199 void updateAleWithFinalError();
203 HttpRequest
*request
;
204 AccessLogEntryPointer al
; ///< info for the future access.log entry
206 /// called by Store if the entry is no longer usable
207 static void HandleStoreAbort(FwdState
*);
212 Comm::ConnectionPointer clientConn
; ///< a possibly open connection to the client.
214 int n_tries
; ///< the number of forwarding attempts so far
217 bool connected_okay
; ///< TCP link ever opened properly. This affects retry of POST,PUT,CONNECT,etc
219 bool forward_completed
;
220 bool destinationsFound
; ///< at least one candidate path found
223 /// waits for a transport connection to the peer to be established/opened
224 JobWait
<HappyConnOpener
> transportWait
;
226 /// waits for the established transport connection to be secured/encrypted
227 JobWait
<Security::PeerConnector
> encryptionWait
;
229 /// waits for an HTTP CONNECT tunnel through a cache_peer to be negotiated
230 /// over the (encrypted, if needed) transport connection to that cache_peer
231 JobWait
<Http::Tunneler
> peerWait
;
233 /// whether we are waiting for the last dispatch()ed activity to end
234 bool waitingForDispatched
;
236 ResolvedPeersPointer destinations
; ///< paths for forwarding the request
237 Comm::ConnectionPointer serverConn
; ///< a successfully opened connection to a server.
238 PeerConnectionPointer destinationReceipt
; ///< peer selection result (or nil)
240 AsyncCall::Pointer closeHandler
; ///< The serverConn close handler
242 /// possible pconn race states
243 typedef enum { raceImpossible
, racePossible
, raceHappened
} PconnRace
;
244 PconnRace pconnRace
; ///< current pconn race state
246 /// Whether the entire reply (including any body) was written to Store.
247 /// The string literal value is only used for debugging.
248 const char *storedWholeReply_
;
250 /// Measures time spent on selecting and communicating with peers.
251 PeeringActivityTimer peeringTimer
;
255 tos_t
aclMapTOS(acl_tos
*, ACLChecklist
*);
257 Ip::NfMarkConfig
aclFindNfMarkConfig(acl_nfmark
*, ACLChecklist
*);
258 void getOutgoingAddress(HttpRequest
*, const Comm::ConnectionPointer
&);
260 /// a collection of previously used persistent Squid-to-peer HTTP(S) connections
261 extern PconnPool
*fwdPconnPool
;
263 #endif /* SQUID_SRC_FWDSTATE_H */