138 template <
typename Method>
154 void error(
int const xerrno);
258 template <
typename StepStart>
320 os <<
" buf=" << c.
len;
389 if (remainingConnection.
writer) {
390 debugs(26, 5,
"waiting to finish writing to " << remainingConnection);
421 if (
const auto c = h->getConn())
422 if (
const auto ctx = c->pipeline.front())
443 destinationsFound(false),
444 committedToServer(false),
450 debugs(26, 3,
"TunnelStateData constructed this=" <<
this);
461 al = clientRequest->
al;
462 http = clientRequest;
475 debugs(26, 3,
"TunnelStateData destructed this=" <<
this);
489 readPending(nullptr),
490 readPendingFunc(nullptr)
506 return "shutting down";
508 return "exhausted tries";
510 return "forwarding timeout";
514 return "no connections";
518 return "received HTTP status code is not reforwardable";
530 if (!bailDescription) {
535 debugs(26, 4,
"wait for more destinations to try");
564 return delayId.bytesWanted(lowerbound, upperbound);
574 debugs(26, 3,
"len=" << len <<
" + count=" << count);
576 delayId.bytesIn(count);
611 if (xerrno == ECONNRESET)
630 tunnelState->
readServer(buf, len, errcode, xerrno);
636 debugs(26, 3,
server <<
", read " << len <<
" bytes, err=" << errcode);
661 debugs(50, debugLevelForError(xerrno), *
this <<
": read/write failure: " <<
xstrerr(xerrno));
674 tunnelState->
readClient(buf, len, errcode, xerrno);
680 debugs(26, 3,
client <<
", read " << len <<
" bytes, err=" << errcode);
705 debugs(26, 3,
"from=" << from <<
"; writing to=" << to);
734 debugs(26, 3,
"closing " << from <<
" after a zero-byte read");
748 debugs(26, 3,
"closing " << from <<
" because " << to <<
" is gone");
763 debugs(26, 3,
"Schedule Write");
766 to.
write(from.
buf, len, call,
nullptr);
783 debugs(26, 3,
server <<
", " << len <<
" bytes written, flag=" << flag);
792 debugs(26, 4,
"to-server write failed: " << xerrno);
799 debugs(26, 4,
"No read input. Closing server connection.");
811 debugs(26, 4,
"Client gone away. Shutting down server connection.");
836 debugs(26, 3,
"len=" << len <<
" - amount=" << amount);
837 assert(amount == (
size_t)len);
854template <
typename Method>
858 debugs(26, 3, *
this <<
" uses " << aConn);
879 debugs(26, 3,
"from " << *
this);
886 debugs(26, 3,
client <<
", " << len <<
" bytes written, flag=" << flag);
893 debugs(26, 4,
"to-client write failed: " << xerrno);
900 debugs(26, 4,
"Closing client connection due to 0 byte read.");
911 debugs(26, 4,
"Server has gone away. Terminating client connection.");
936 debugs(26, 3,
"because " << reason <<
"; " << conn);
938 if (IsConnOpen(conn))
961 static uint64_t counter=0;
962 debugs(26, 7,
"Client read(2) delayed " << ++counter <<
" times");
977 static uint64_t counter=0;
978 debugs(26, 7,
"Server read(2) delayed " << ++counter <<
" times");
986 debugs(26, 5,
"from=" << from <<
"; writing to=" << to);
1066 debugs(26,
DBG_DATA,
"Tunnel client PUSH Payload: \n" << *in <<
"\n----------");
1083 debugs(26, 3, tunnelState->
client <<
", flag=" << flag);
1112 auto sawProblem =
false;
1157 client.
write(mb->content(), mb->contentSize(), call, mb->freeFunc());
1175 debugs(26, 3,
"FD " << fd);
1176 assert(tunnelState !=
nullptr);
1235 bool toOrigin =
false;
1236 if (
const auto *
const peer = conn->
getPeer()) {
1238 toOrigin = peer->options.originserver;
1285 debugs(26, 4,
"MISS access forbidden.");
1308 if (
const auto p = conn->
getPeer()) {
1309 if (p->secure.encryptTransport)
1328template <
typename StepStart>
1428 return sendError(selectionError,
"path selection has failed");
1432 return sendError(
savedError,
"path selection found no paths (with an impossible early error)");
1435 "path selection found no paths");
1439 Must(!selectionError);
1450 debugs(17, 7,
"keep transporting");
1455 debugs(17, 7,
"no more destinations to try after " <<
n_tries <<
" failed attempts");
1460 finalError->detailError(d);
1492 debugs(26, 3,
"aborting transaction for " << reason);
1538 cs->setRetriable(
false);
1539 cs->allowPersistent(
false);
1554 debugs(26, 7,
"pinned peer connection: " << serverConn);
1570 if (connManager->pinnedAuth())
1574 const auto reused =
true;
1575 connectDone(serverConn, connManager->pinning.host, reused);
1600 debugs(17, 7,
"reusing pending notification");
1620 debugs(26,5,
"Revert to tunnel FD " << clientConn->
fd <<
" with FD " << srvConn->
fd);
1629 Must(context && context->http);
1644 debugs(26, 4,
"determine post-connect handling pathway.");
1645 if (
const auto peer = srvConn->
getPeer())
#define Assure(condition)
#define asyncCallback(dbgSection, dbgLevel, method, object)
#define CallJobHere(debugSection, debugLevel, job, Class, method)
CommCbFunPtrCallT< Dialer > * commCbCall(int debugSection, int debugLevel, const char *callName, const Dialer &dialer)
void CTCB(const CommTimeoutCbParams ¶ms)
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
void CLCB(const CommCloseCbParams ¶ms)
ErrorDetail::Pointer MakeNamedErrorDetail(const char *name)
void ResetMarkingsToServer(HttpRequest *request, Comm::Connection &conn)
void comm_read(const Comm::ConnectionPointer &conn, char *buf, int len, AsyncCall::Pointer &callback)
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
void error(char *format,...)
#define SQUID_TCP_SO_RCVBUF
static char server[MAXLINE]
int cbdataReferenceValid(const void *p)
#define CBDATA_CLASS_INIT(type)
Acl::Answer const & fastCheck()
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
void syncAle(HttpRequest *adaptedRequest, const char *logUri) const override
assigns uninitialized adapted_request and url ALE components
MessageSizes clientRequestSz
counters for the original request received from client
class AccessLogEntry::CacheDetails cache
class AccessLogEntry::HttpDetails http
void host(const char *src)
struct CachePeer::@20 options
Cbc * valid() const
was set and is valid
void clear()
make pointer not set; does not invalidate cbdata
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
struct ClientHttpRequest::Out out
HttpRequest *const request
ConnStateData * getConn() const
void updateLoggingTags(const LogTags_ot code)
update the code in the transaction processing tags
const AccessLogEntry::Pointer al
access.log entry
static const Pointer & Current()
static void Reset()
forgets the current context, setting it to nil/unknown
Comm::ConnectionPointer conn
InstanceId< Connection, uint64_t > id
CachePeer * getPeer() const
Ssl::ServerBump * serverBump()
static Comm::ConnectionPointer BorrowPinnedConnection(HttpRequest *, const AccessLogEntryPointer &)
static DelayId DelayClient(ClientHttpRequest *, HttpReply *reply=nullptr)
Http::StatusCode httpStatus
static bool EnoughTimeToReForward(const time_t fwdStart)
Final result (an open connection or an error) sent to the job initiator.
bool reused
whether conn was open earlier, by/for somebody else
PeerConnectionPointer conn
CbcPointer< ErrorState > error
problem details (nil on success)
Http::StatusCode peer_reply_status
last HTTP status code received
void resetPeerNotes(const Comm::ConnectionPointer &server, const char *requestedHost)
static HttpReplyPointer MakeConnectionEstablished()
construct and return an HTTP/200 (Connection Established) response
CbcPointer< ConnStateData > clientConnectionManager
void prepForDirect()
get ready to be sent directly to an origin server, excluding originserver
void prepForPeering(const CachePeer &peer)
get ready to be sent to the given cache_peer, including originserver
ConnStateData * pinnedConnection()
AnyP::Uri url
the request URI
AnyP::ProtocolVersion http_ver
Comm::ConnectionPointer conn
StatusCode peerResponseStatus
the status code of the successfully parsed CONNECT response (or scNone)
SBuf leftovers
peer-generated bytes after a positive answer (or empty)
CbcPointer< ErrorState > squidError
problem details (or nil)
void cancel(const char *reason)
void start(const JobPointer &aJob, const AsyncCall::Pointer &aCallback)
starts waiting for the given job to call the given callback
uint64_t payloadData
total size of payload block(s) excluding transfer encoding overheads
Interface for those who need a list of peers to forward a request to.
bool subscribed
whether noteDestination() and noteDestinationsEnd() calls are allowed
void startSelectingDestinations(HttpRequest *request, const AccessLogEntry::Pointer &ale, StoreEntry *entry)
void stop()
pauses timer if stop() has not been called
bool interceptTproxy
Set for requests handled by a "tproxy" port.
bool forceTunnel
whether to forward via TunnelStateData (instead of FwdState)
bool notificationPending
whether HappyConnOpener::noteCandidatesChange() is scheduled to fire
bool empty() const
whether we lack any known candidate paths
bool destinationsFinalized
whether all of the available candidate paths received from DNS
void addPath(const Comm::ConnectionPointer &)
add a candidate path to try after all the existing paths
const char * rawContent() const
SBuf consume(size_type n=npos)
size_type length() const
Returns the number of bytes stored in SBuf.
SBuf & append(const SBuf &S)
A PeerConnector for TLS cache_peers and origin servers. No SslBump capabilities.
CbcPointer< ErrorState > error
problem details (nil on success)
Comm::ConnectionPointer conn
peer connection (secured on success)
bool tunneled
whether we spliced the connections instead of negotiating encryption
Comm::ConnectionPointer clientConnection
SBuf inBuf
read I/O buffer for the client connection
struct SquidConfig::@77 Timeout
struct SquidConfig::@91 accessList
bool at(const BumpStep stp) const
whether we are currently performing the given processing step
struct StatCounters::@105 server
struct StatCounters::@105::@115 other
struct StatCounters::@104 client_http
struct StatCounters::@105::@115 all
void noteClosure()
reacts to the external closure of our connection
int bytesWanted(int lower=0, int upper=INT_MAX) const
void bytesIn(int const &)
void write(const char *b, int size, AsyncCall::Pointer &callback, FREE *free_func)
writes 'b' buffer, setting the 'writer' member to 'callback'.
void initConnection(const Comm::ConnectionPointer &aConn, Method method, const char *name, TunnelStateData *tunnelState)
initiates Comm::Connection ownership, including closure monitoring
void error(int const xerrno)
bool receivedEof
whether read() has returned zero bytes
void dataSent(size_t amount)
void setDelayId(DelayId const &)
Comm::ConnectionPointer conn
The currently connected connection.
AsyncCall::Pointer writer
pending Comm::Write callback
Connection(const char *aSide)
uint8_t delayedLoops
how many times a read on this connection has been postponed.
AsyncCall::Pointer closer
the registered close handler for the connection
bool dirty
whether write() has been called (at least once)
TunnelStateData * readPending
int debugLevelForError(int const xerrno) const
void noteEof()
reacts to a successful zero-size read(2)
static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
const char * banRetries
a reason to ban reforwarding attempts (or nil)
void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno)
JobWait< HappyConnOpener > transportWait
waits for a transport connection to the peer to be established/opened
void closeConnections()
closes both client and server connections
void notePeerReadyToShovel(const Comm::ConnectionPointer &)
called when negotiations with the peer have been successfully completed
CbcPointer< ClientHttpRequest > http
void copyRead(Connection &from, Connection &to, IOCB *completion)
void sendError(ErrorState *finalError, const char *reason)
void serverClosed()
handles Squid-to-server connection closure; may destroy us
void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
void notifyConnOpener()
makes sure connection opener knows that the destinations have changed
void updateAttempts(int)
sets n_tries to the given value (while keeping ALE in sync)
void tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
resumes operations after the (possibly failed) HTTP CONNECT exchange
void finishWritingAndDelete(Connection &)
bool noConnections() const
void noteDestinationsEnd(ErrorState *selectionError) override
void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
Start using an established connection.
CBDATA_CHILD(TunnelStateData)
void connectedToPeer(const Comm::ConnectionPointer &)
called after connection setup (including any encryption)
const char * getHost() const
TunnelStateData(const TunnelStateData &)
void noteConnection(HappyConnOpenerAnswer &)
static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno)
TunnelStateData(ClientHttpRequest *)
const char * checkRetry()
TunnelStateData & operator=(const TunnelStateData &)
void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno)
void saveError(ErrorState *finalError)
remembers an error to be used if there will be no more connection attempts
HttpRequest::Pointer request
void usePinned()
send request on an existing connection dedicated to the requesting client
void establishTunnelThruProxy(const Comm::ConnectionPointer &)
int n_tries
the number of forwarding attempts so far
void connectToPeer(const Comm::ConnectionPointer &)
continue to set up connection to a peer, going async for SSL peers
void copy(size_t len, Connection &from, Connection &to, IOCB *)
void commitToServer(const Comm::ConnectionPointer &)
void retryOrBail(const char *context)
void clientClosed()
handles client-to-Squid connection closure; may destroy us
ResolvedPeersPointer destinations
paths for forwarding the request
PeeringActivityTimer peeringTimer
Measures time spent on selecting and communicating with peers.
void syncHierNote(const Comm::ConnectionPointer &server, const char *origin)
void closePendingConnection(const Comm::ConnectionPointer &conn, const char *reason)
void noteSecurityPeerConnectorAnswer(Security::EncryptorAnswer &)
callback handler for the Security::PeerConnector encryptor
void deleteThis()
destroys the tunnel (after performing potentially-throwing cleanup)
void advanceDestination(const char *stepDescription, const Comm::ConnectionPointer &conn, const StepStart &startStep)
starts a preparation step for an established connection; retries on failures
int * status_ptr
pointer for logging HTTP status
bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to)
bool committedToServer
whether the decision to tunnel to a particular destination was final
bool clientExpectsConnectResponse() const
Whether the client sent a CONNECT request to us.
ErrorState * savedError
details of the "last tunneling attempt" failure (if it failed)
static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
JobWait< Security::PeerConnector > encryptionWait
waits for the established transport connection to be secured/encrypted
void cancelStep(const char *reason)
bool destinationsFound
At least one candidate path found.
CodeContext::Pointer codeContext
our creator context
void secureConnectionToPeer(const Comm::ConnectionPointer &)
encrypts an established TCP connection to peer
JobWait< Http::Tunneler > peerWait
~TunnelStateData() override
time_t startTime
object creation time, before any peer selection/connection attempts
bool exhaustedTries() const
whether we have used up all permitted forwarding attempts
bool transporting() const
void noteDestination(Comm::ConnectionPointer conn) override
called when a new unique destination has been found
static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
void commSetConnTimeout(const Comm::ConnectionPointer &conn, time_t timeout, AsyncCall::Pointer &callback)
int ignoreErrno(int ierrno)
#define debugs(SECTION, LEVEL, CONTENT)
void ERCB(int fd, void *, size_t)
error page callback
void eventDelete(EVH *func, void *arg)
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
void errorSend(const Comm::ConnectionPointer &conn, ErrorState *err)
bool IsConnOpen(const Comm::ConnectionPointer &conn)
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
bool IsReforwardableStatus(StatusCode)
whether to send the request to another peer based on the current response status code
void netdbPingSite(const char *hostname)
size_t headers_sz
Response header bytes written to the client connection.
uint64_t size
Response header and body bytes written to the client connection.
static auto & guaranteedRequest(const ClientHttpRequest *const cr)
safely extracts HttpRequest from a never-nil ClientHttpRequest pointer
static CLCB tunnelServerClosed
static CTCB tunnelTimeout
static std::ostream & operator<<(std::ostream &os, const TunnelStateData::Connection &c)
void tunnelStart(ClientHttpRequest *http)
static ERCB tunnelErrorComplete
static EVH tunnelDelayedClientRead
static void tunnelStartShoveling(TunnelStateData *tunnelState)
static EVH tunnelDelayedServerRead
static void tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
void switchToTunnel(HttpRequest *request, const Comm::ConnectionPointer &clientConn, const Comm::ConnectionPointer &srvConn, const SBuf &preReadServerData)
static CLCB tunnelClientClosed
const char * xstrerr(int error)