31 noteFwdPconnUse(false),
35 lifetimeLimit(timeout),
38 requestWritten(false),
39 tunnelEstablished(false)
41 debugs(83, 5,
"Http::Tunneler constructed, this=" << (
void*)
this);
50 debugs(83, 5,
"Http::Tunneler destructed, this=" << (
void*)
this);
56 return !callback || (requestWritten && tunnelEstablished);
66 Must(lifetimeLimit >= 0);
71 if (
fd_table[connection->fd].closing()) {
76 const auto peer = connection->getPeer();
82 request->prepForPeering(*peer);
85 startReadingResponse();
93 countFailingConnection();
94 connection->noteClosure();
107 debugs(83, 5, connection);
125 debugs(83, 5, connection << status());
134 debugs(83, 5, connection);
144 request->masterXaction->generatingConnect =
true;
147 mb.
appendf(
"CONNECT %s HTTP/1.1\r\n", url.c_str());
153 connection->getPeer(),
159 request->masterXaction->generatingConnect =
false;
162 request->masterXaction->generatingConnect =
false;
166 debugs(11, 2,
"Tunnel Server REQUEST: " << connection <<
167 ":\n----------\n" << mb.
buf <<
"\n----------");
168 fd_note(connection->fd,
"Tunnel Server CONNECT");
185 request->hier.notePeerWrite();
196 requestWritten =
true;
213 rd.
size = delayId.bytesWanted(1, readBuf.spaceSize());
215 rd.
size = readBuf.spaceSize();
226 delayId.bytesIn(rd.
size);
230 request->hier.notePeerRead();
231 handleResponse(
false);
237 handleResponse(
true);
281 auto parsedOk = hp->
parse(readBuf);
282 readBuf = hp->remaining();
283 if (hp->needsMoreData()) {
286 bailOnResponseError(
"huge CONNECT response from peer",
nullptr);
294 readBuf.append(
"\r\n\r\n", 4);
295 parsedOk = hp->parse(readBuf);
302 debugs(11, 3,
"Non-HTTP-compliant header:\n---------\n" << readBuf <<
"\n----------");
303 bailOnResponseError(
"malformed CONNECT response from peer",
nullptr);
308 debugs(11, 2,
"Tunnel Server " << connection);
309 debugs(11, 2,
"Tunnel Server RESPONSE:\n---------\n" <<
310 hp->messageProtocol() <<
" " << hp->messageStatus() <<
" " << hp->reasonPhrase() <<
"\n" <<
316 rep->
sline.
set(hp->messageProtocol(), hp->messageStatus());
318 bailOnResponseError(
"malformed CONNECT response headers mime block from peer",
nullptr);
323 auto &futureAnswer = callback.answer();
324 futureAnswer.peerResponseStatus = rep->
sline.
status();
325 request->hier.peer_reply_status = rep->
sline.
status();
330 bailOnResponseError(
"unsupported CONNECT response status code", rep.
getRaw());
335 futureAnswer.leftovers = readBuf;
337 tunnelEstablished =
true;
348 err =
new ErrorState(request.getRaw(), errorReply, al);
360 callback.answer().squidError =
error;
362 if (
const auto failingConnection = connection) {
364 countFailingConnection();
366 failingConnection->close();
375 assert(callback.answer().positive());
377 callback.answer().conn = connection;
389 if (noteFwdPconnUse && connection->isOpen())
413 connection =
nullptr;
419 debugs(83, 5, callback.answer().conn << status());
448 buf.
append(
" [state:", 8);
449 if (requestWritten) buf.
append(
"w", 1);
450 if (tunnelEstablished) buf.
append(
"t", 1);
451 if (!callback) buf.
append(
"x", 1);
452 if (stopReason !=
nullptr) {
453 buf.
append(
" stopped, reason:", 16);
456 if (connection !=
nullptr)
457 buf.
appendf(
" FD %d", connection->fd);
458 buf.
appendf(
" %s%u]",
id.prefix(),
id.value);
#define ScheduleCallHere(call)
#define JobCallback(dbgSection, dbgLevel, Dialer, job, method)
Convenience macro to create a Dialer-based job callback.
PconnPool * fwdPconnPool
a collection of previously used persistent Squid-to-peer HTTP(S) connections
void error(char *format,...)
#define SQUID_TCP_SO_RCVBUF
#define CBDATA_NAMESPACED_CLASS_INIT(namespace, type)
SBuf & authority(bool requirePort=false) const
a smart AsyncCall pointer for delivery of future results
virtual void start()
called by AsyncStart; do not call directly
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Comm::Flag flag
comm layer result status.
Comm::ConnectionPointer conn
bool parseHeader(Http1::Parser &hp)
parses reply header using Parser
AnyP::Uri url
the request URI
static void httpBuildRequestHeader(HttpRequest *request, StoreEntry *entry, const AccessLogEntryPointer &al, HttpHeader *hdr_out, const CachePeer *peer, const Http::StateFlags &flags)
@ srcHttp
http_port or HTTP server
uint32_t sources
The message sources.
bool parse(const SBuf &aBuf) override
bool peering
Whether the next TCP hop is a cache_peer, including originserver.
void set(const AnyP::ProtocolVersion &newVersion, Http::StatusCode newStatus, const char *newReason=nullptr)
Http::StatusCode status() const
retrieve the status code for this status line
bool doneAll() const override
whether positive goal has been reached
void countFailingConnection()
updates connection usage history before the connection is closed
void disconnect()
stops monitoring the connection
void bailOnResponseError(const char *error, HttpReply *)
void handleResponse(const bool eof)
Parses [possibly incomplete] CONNECT response and reacts to it.
void callBack()
a bailWith(), sendSuccess() helper: sends results to the initiator
void bailWith(ErrorState *)
sends the given error to the initiator
const char * status() const override
internal cleanup; do not call directly
void handleConnectionClosure(const CommCloseCbParams &)
void start() override
called by AsyncStart; do not call directly
void handleWrittenRequest(const CommIoCbParams &)
Called when we are done writing a CONNECT request header to a peer.
void watchForClosures()
make sure we quit if/when the connection is gone
void sendSuccess()
sends the ready-to-use tunnel to the initiator
void startReadingResponse()
Tunneler(const Comm::ConnectionPointer &, const HttpRequestPointer &, const AsyncCallback< Answer > &, time_t timeout, const AccessLogEntryPointer &)
SBuf url
request-target for the CONNECT request
HttpRequestPointer request
peer connection trigger or cause
void handleTimeout(const CommTimeoutCbParams &)
The connection read timeout callback handler.
void handleReadyRead(const CommIoCbParams &)
Called when we read [a part of] CONNECT response from the peer.
Comm::ConnectionPointer connection
TCP connection to the cache_peer.
void append(const char *c, int sz) override
void init(mb_size_t szInit, mb_size_t szMax)
char * content()
start of the added data
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
struct StatCounters::@105 server
struct StatCounters::@105::@115 other
struct StatCounters::@105::@115 all
void commUnsetConnTimeout(const Comm::ConnectionPointer &conn)
AsyncCall::Pointer comm_add_close_handler(int fd, CLCB *handler, void *data)
void comm_remove_close_handler(int fd, CLCB *handler, void *data)
void commSetConnTimeout(const Comm::ConnectionPointer &conn, time_t timeout, AsyncCall::Pointer &callback)
#define debugs(SECTION, LEVEL, CONTENT)
void fd_note(int fd, const char *s)
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
void Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
bool IsConnOpen(const Comm::ConnectionPointer &conn)
void Write(const Comm::ConnectionPointer &conn, const char *buf, int size, AsyncCall::Pointer &callback, FREE *free_func)
time_t MortalReadTimeout(const time_t startTime, const time_t lifetimeLimit)
maximum read delay for readers with limited lifetime
Comm::Flag ReadNow(CommIoCbParams ¶ms, SBuf &buf)