]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tunnel.cc
Fix "BUG: Lost previously bumped from-Squid connection" (#460)
[thirdparty/squid.git] / src / tunnel.cc
CommitLineData
983061ed 1/*
f6e9a3ee 2 * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
e25c139f 3 *
bbc27441
AJ
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.
983061ed 7 */
983061ed 8
bbc27441
AJ
9/* DEBUG: section 26 Secure Sockets Layer Proxy */
10
582c2af2 11#include "squid.h"
a011edee 12#include "acl/FilledChecklist.h"
6c420975 13#include "base/CbcPointer.h"
a011edee 14#include "CachePeer.h"
9fe3d316 15#include "cbdata.h"
a011edee 16#include "client_side.h"
602d9612 17#include "client_side_request.h"
f5e17947 18#include "clients/HttpTunneler.h"
9f518b4a 19#include "comm.h"
cfd66529 20#include "comm/Connection.h"
aed188fd 21#include "comm/ConnOpener.h"
7e66d5e2 22#include "comm/Read.h"
ec41b64c 23#include "comm/Write.h"
a011edee 24#include "errorpage.h"
6821c276 25#include "fd.h"
a011edee 26#include "fde.h"
4f3c27a1 27#include "FwdState.h"
40f1e76d 28#include "globals.h"
55622953 29#include "HappyConnOpener.h"
e5ee81f0 30#include "http.h"
d3dddfb5 31#include "http/Stream.h"
a011edee 32#include "HttpRequest.h"
9710965e 33#include "icmp/net_db.h"
6dc6127b 34#include "ip/QosConfig.h"
8a713747 35#include "LogTags.h"
a011edee 36#include "MemBuf.h"
0ce8e93b 37#include "neighbors.h"
cfd66529 38#include "PeerSelectState.h"
55622953 39#include "ResolvedPeers.h"
65e41a45 40#include "sbuf/SBuf.h"
a72b6e88 41#include "security/BlindPeerConnector.h"
4d5904f7 42#include "SquidConfig.h"
16b70e2a 43#include "SquidTime.h"
765afa31 44#include "StatCounters.h"
a23223bf 45#if USE_OPENSSL
93ead3fd 46#include "ssl/bio.h"
5d65362c 47#include "ssl/ServerBump.h"
a23223bf 48#endif
4e540555 49#include "tools.h"
582c2af2
FC
50#if USE_DELAY_POOLS
51#include "DelayId.h"
52#endif
53
074d6a40
AJ
54#include <climits>
55#include <cerrno>
582c2af2 56
8ca1d33d
AJ
57/**
58 * TunnelStateData is the state engine performing the tasks for
59 * setup of a TCP tunnel from an existing open client FD to a server
60 * then shuffling binary data between the resulting FD pair.
61 */
62/*
63 * TODO 1: implement a read/write API on ConnStateData to send/receive blocks
64 * of pre-formatted data. Then we can use that as the client side of the tunnel
65 * instead of re-implementing it here and occasionally getting the ConnStateData
66 * read/write state wrong.
67 *
68 * TODO 2: then convert this into a AsyncJob, possibly a child of 'Server'
69 */
6043e368 70class TunnelStateData: public PeerSelectionInitiator
62e76326 71{
6043e368 72 CBDATA_CHILD(TunnelStateData);
a46d2c0e 73
74public:
6b2b6cfe 75 TunnelStateData(ClientHttpRequest *);
6043e368 76 virtual ~TunnelStateData();
8ca1d33d
AJ
77 TunnelStateData(const TunnelStateData &); // do not implement
78 TunnelStateData &operator =(const TunnelStateData &); // do not implement
a46d2c0e 79
80 class Connection;
c8407295
AJ
81 static void ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
82 static void ReadServer(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
83 static void WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
84 static void WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data);
a46d2c0e 85
86 bool noConnections() const;
983061ed 87 char *url;
6c420975 88 CbcPointer<ClientHttpRequest> http;
8a70cdbb 89 HttpRequest::Pointer request;
06521a10 90 AccessLogEntryPointer al;
62e76326 91
fb046c1b 92 const char * getHost() const {
5c51bffb 93 return (server.conn != NULL && server.conn->getPeer() ? server.conn->getPeer()->host : request->url.host());
fb046c1b
AJ
94 };
95
3ed5793b 96 /// Whether the client sent a CONNECT request to us.
1c8fc082 97 bool clientExpectsConnectResponse() const {
aff439e0 98 // If we are forcing a tunnel after receiving a client CONNECT, then we
6b2b6cfe
CT
99 // have already responded to that CONNECT before tunnel.cc started.
100 if (request && request->flags.forceTunnel)
101 return false;
5d65362c
CT
102#if USE_OPENSSL
103 // We are bumping and we had already send "OK CONNECTED"
104 if (http.valid() && http->getConn() && http->getConn()->serverBump() && http->getConn()->serverBump()->step > Ssl::bumpStep1)
105 return false;
106#endif
1c8fc082
A
107 return !(request != NULL &&
108 (request->flags.interceptTproxy || request->flags.intercepted));
109 }
3ed5793b 110
0ce8e93b
EB
111 /// starts connecting to the next hop, either for the first time or while
112 /// recovering from the previous connect failure
113 void startConnecting();
114
f5e17947
CT
115 /// called when negotiations with the peer have been successfully completed
116 void notePeerReadyToShovel();
117
a46d2c0e 118 class Connection
62e76326 119 {
a46d2c0e 120
121 public:
215c41fa 122 Connection() : len (0), buf ((char *)xmalloc(SQUID_TCP_SO_RCVBUF)), size_ptr(NULL), delayedLoops(0),
be75380c 123 readPending(NULL), readPendingFunc(NULL) {}
a46d2c0e 124
8a467c4b
AJ
125 ~Connection();
126
127 int bytesWanted(int lower=0, int upper = INT_MAX) const;
a46d2c0e 128 void bytesIn(int const &);
9a0a18de 129#if USE_DELAY_POOLS
a46d2c0e 130
131 void setDelayId(DelayId const &);
132#endif
133
134 void error(int const xerrno);
5c926411 135 int debugLevelForError(int const xerrno) const;
a46d2c0e 136 void closeIfOpen();
8a467c4b 137 void dataSent (size_t amount);
74f35ca8
AR
138 /// writes 'b' buffer, setting the 'writer' member to 'callback'.
139 void write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func);
62e76326 140 int len;
8a467c4b 141 char *buf;
74f35ca8 142 AsyncCall::Pointer writer; ///< pending Comm::Write callback
ac9f46af 143 uint64_t *size_ptr; /* pointer to size in an ConnStateData for logging */
62e76326 144
fb046c1b 145 Comm::ConnectionPointer conn; ///< The currently connected connection.
9fe3d316 146 uint8_t delayedLoops; ///< how many times a read on this connection has been postponed.
fb046c1b 147
215c41fa
AJ
148 // XXX: make these an AsyncCall when event API can handle them
149 TunnelStateData *readPending;
150 EVH *readPendingFunc;
f5e17947 151
9a0a18de 152#if USE_DELAY_POOLS
62e76326 153
a46d2c0e 154 DelayId delayId;
59715b38 155#endif
62e76326 156
a46d2c0e 157 };
158
159 Connection client, server;
8a713747
AJ
160 int *status_ptr; ///< pointer for logging HTTP status
161 LogTags *logTag_ptr; ///< pointer for logging Squid processing code
f5e17947 162
3248e962 163 SBuf preReadClientData;
6821c276 164 SBuf preReadServerData;
0ce8e93b 165 time_t startTime; ///< object creation time, before any peer selection/connection attempts
f5e17947
CT
166 /// Whether we are waiting for the CONNECT request/response exchange with the peer.
167 bool waitingForConnectExchange;
55622953
CT
168 HappyConnOpenerPointer connOpener; ///< current connection opening job
169 ResolvedPeersPointer destinations; ///< paths for forwarding the request
170 bool destinationsFound; ///< At least one candidate path found
171
172 // AsyncCalls which we set and may need cancelling.
173 struct {
174 AsyncCall::Pointer connector; ///< a call linking us to the ConnOpener producing serverConn.
175 } calls;
3ed5793b 176
a46d2c0e 177 void copyRead(Connection &from, IOCB *completion);
178
a23223bf
CT
179 /// continue to set up connection to a peer, going async for SSL peers
180 void connectToPeer();
181
6043e368
AR
182 /* PeerSelectionInitiator API */
183 virtual void noteDestination(Comm::ConnectionPointer conn) override;
184 virtual void noteDestinationsEnd(ErrorState *selectionError) override;
185
55622953
CT
186 void syncHierNote(const Comm::ConnectionPointer &server, const char *origin);
187
188 /// called when a connection has been successfully established or
189 /// when all candidate destinations have been tried and all have failed
190 void noteConnection(HappyConnOpenerAnswer &);
191
192 /// whether we are waiting for HappyConnOpener
193 /// same as calls.connector but may differ from connOpener.valid()
194 bool opening() const { return connOpener.set(); }
195
196 void cancelOpening(const char *reason);
197
198 /// Start using an established connection
199 void connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused);
200
201 void notifyConnOpener();
202
6043e368
AR
203 void saveError(ErrorState *finalError);
204 void sendError(ErrorState *finalError, const char *reason);
205
a46d2c0e 206private:
0166128b 207 /// Gives Security::PeerConnector access to Answer in the TunnelStateData callback dialer.
a72b6e88 208 class MyAnswerDialer: public CallDialer, public Security::PeerConnector::CbDialer
a23223bf
CT
209 {
210 public:
fcfdf7f9 211 typedef void (TunnelStateData::*Method)(Security::EncryptorAnswer &);
a23223bf
CT
212
213 MyAnswerDialer(Method method, TunnelStateData *tunnel):
f53969cc 214 method_(method), tunnel_(tunnel), answer_() {}
a23223bf
CT
215
216 /* CallDialer API */
217 virtual bool canDial(AsyncCall &call) { return tunnel_.valid(); }
218 void dial(AsyncCall &call) { ((&(*tunnel_))->*method_)(answer_); }
219 virtual void print(std::ostream &os) const {
e2849af8
A
220 os << '(' << tunnel_.get() << ", " << answer_ << ')';
221 }
a23223bf 222
a72b6e88 223 /* Security::PeerConnector::CbDialer API */
fcfdf7f9 224 virtual Security::EncryptorAnswer &answer() { return answer_; }
a23223bf
CT
225
226 private:
227 Method method_;
228 CbcPointer<TunnelStateData> tunnel_;
fcfdf7f9 229 Security::EncryptorAnswer answer_;
a23223bf 230 };
a23223bf 231
3dde9e52
CT
232 void usePinned();
233
fcfdf7f9
AJ
234 /// callback handler after connection setup (including any encryption)
235 void connectedToPeer(Security::EncryptorAnswer &answer);
236
6043e368
AR
237 /// details of the "last tunneling attempt" failure (if it failed)
238 ErrorState *savedError = nullptr;
239
f5e17947
CT
240 /// resumes operations after the (possibly failed) HTTP CONNECT exchange
241 void tunnelEstablishmentDone(Http::TunnelerAnswer &answer);
242
5c2f68b7 243public:
c8407295 244 bool keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to);
3ed5793b 245 void copy(size_t len, Connection &from, Connection &to, IOCB *);
c8407295
AJ
246 void readServer(char *buf, size_t len, Comm::Flag errcode, int xerrno);
247 void readClient(char *buf, size_t len, Comm::Flag errcode, int xerrno);
248 void writeClientDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
249 void writeServerDone(char *buf, size_t len, Comm::Flag flag, int xerrno);
3ed5793b 250
3248e962 251 void copyClientBytes();
6821c276 252 void copyServerBytes();
a46d2c0e 253};
983061ed 254
3c4fcf0f 255static const char *const conn_established = "HTTP/1.1 200 Connection established\r\n\r\n";
983061ed 256
11007d4b 257static ERCB tunnelErrorComplete;
575d05c4
AJ
258static CLCB tunnelServerClosed;
259static CLCB tunnelClientClosed;
8d77a37c 260static CTCB tunnelTimeout;
215c41fa
AJ
261static EVH tunnelDelayedClientRead;
262static EVH tunnelDelayedServerRead;
30a4f2a8 263
b8d8561b 264static void
575d05c4 265tunnelServerClosed(const CommCloseCbParams &params)
30a4f2a8 266{
575d05c4
AJ
267 TunnelStateData *tunnelState = (TunnelStateData *)params.data;
268 debugs(26, 3, HERE << tunnelState->server.conn);
fb046c1b 269 tunnelState->server.conn = NULL;
74f35ca8 270 tunnelState->server.writer = NULL;
62e76326 271
16b70e2a
CT
272 if (tunnelState->request != NULL)
273 tunnelState->request->hier.stopPeerClock(false);
274
71a2ced6 275 if (tunnelState->noConnections()) {
1326d980 276 // ConnStateData pipeline should contain the CONNECT we are performing
056ddbd7
AJ
277 // but it may be invalid already (bug 4392)
278 if (tunnelState->http.valid() && tunnelState->http->getConn()) {
279 auto ctx = tunnelState->http->getConn()->pipeline.front();
280 if (ctx != nullptr)
281 ctx->finished();
282 }
8ca1d33d 283 delete tunnelState;
26ac0430 284 return;
71a2ced6 285 }
26ac0430 286
74f35ca8 287 if (!tunnelState->client.writer) {
fb046c1b 288 tunnelState->client.conn->close();
26ac0430 289 return;
71a2ced6 290 }
30a4f2a8 291}
292
b177367b 293static void
575d05c4 294tunnelClientClosed(const CommCloseCbParams &params)
30a4f2a8 295{
575d05c4
AJ
296 TunnelStateData *tunnelState = (TunnelStateData *)params.data;
297 debugs(26, 3, HERE << tunnelState->client.conn);
fb046c1b 298 tunnelState->client.conn = NULL;
74f35ca8 299 tunnelState->client.writer = NULL;
62e76326 300
71a2ced6 301 if (tunnelState->noConnections()) {
1326d980 302 // ConnStateData pipeline should contain the CONNECT we are performing
056ddbd7
AJ
303 // but it may be invalid already (bug 4392)
304 if (tunnelState->http.valid() && tunnelState->http->getConn()) {
305 auto ctx = tunnelState->http->getConn()->pipeline.front();
306 if (ctx != nullptr)
307 ctx->finished();
308 }
8ca1d33d 309 delete tunnelState;
26ac0430 310 return;
71a2ced6 311 }
26ac0430 312
74f35ca8 313 if (!tunnelState->server.writer) {
fb046c1b 314 tunnelState->server.conn->close();
26ac0430 315 return;
71a2ced6 316 }
30a4f2a8 317}
983061ed 318
6b2b6cfe 319TunnelStateData::TunnelStateData(ClientHttpRequest *clientRequest) :
f5e17947 320 startTime(squid_curtime),
55622953
CT
321 waitingForConnectExchange(false),
322 destinations(new ResolvedPeers()),
323 destinationsFound(false)
8ca1d33d
AJ
324{
325 debugs(26, 3, "TunnelStateData constructed this=" << this);
215c41fa
AJ
326 client.readPendingFunc = &tunnelDelayedClientRead;
327 server.readPendingFunc = &tunnelDelayedServerRead;
6b2b6cfe
CT
328
329 assert(clientRequest);
330 url = xstrdup(clientRequest->uri);
331 request = clientRequest->request;
55622953 332 Must(request);
6b2b6cfe
CT
333 server.size_ptr = &clientRequest->out.size;
334 client.size_ptr = &clientRequest->al->http.clientRequestSz.payloadData;
335 status_ptr = &clientRequest->al->http.code;
336 logTag_ptr = &clientRequest->logType;
337 al = clientRequest->al;
338 http = clientRequest;
339
340 client.conn = clientRequest->getConn()->clientConnection;
341 comm_add_close_handler(client.conn->fd, tunnelClientClosed, this);
342
343 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
344 CommTimeoutCbPtrFun(tunnelTimeout, this));
345 commSetConnTimeout(client.conn, Config.Timeout.lifetime, timeoutCall);
8ca1d33d
AJ
346}
347
348TunnelStateData::~TunnelStateData()
983061ed 349{
8ca1d33d
AJ
350 debugs(26, 3, "TunnelStateData destructed this=" << this);
351 assert(noConnections());
352 xfree(url);
55622953
CT
353 if (opening())
354 cancelOpening("~TunnelStateData");
6043e368 355 delete savedError;
983061ed 356}
357
8a467c4b
AJ
358TunnelStateData::Connection::~Connection()
359{
215c41fa
AJ
360 if (readPending)
361 eventDelete(readPendingFunc, readPending);
362
8a467c4b
AJ
363 safe_free(buf);
364}
365
a46d2c0e 366int
8a467c4b 367TunnelStateData::Connection::bytesWanted(int lowerbound, int upperbound) const
447e176b 368{
9a0a18de 369#if USE_DELAY_POOLS
8a467c4b 370 return delayId.bytesWanted(lowerbound, upperbound);
a46d2c0e 371#else
8a467c4b
AJ
372
373 return upperbound;
a46d2c0e 374#endif
375}
62e76326 376
a46d2c0e 377void
fa34dd97 378TunnelStateData::Connection::bytesIn(int const &count)
a46d2c0e 379{
fd54d9b2 380 debugs(26, 3, HERE << "len=" << len << " + count=" << count);
9a0a18de 381#if USE_DELAY_POOLS
a46d2c0e 382 delayId.bytesIn(count);
383#endif
62e76326 384
a46d2c0e 385 len += count;
447e176b 386}
62e76326 387
55622953
CT
388/// update "hierarchy" annotations with a new (possibly failed) destination
389/// \param origin the name of the origin server we were trying to reach
390void
391TunnelStateData::syncHierNote(const Comm::ConnectionPointer &conn, const char *origin)
392{
393 request->hier.resetPeerNotes(conn, origin);
394 if (al)
395 al->hier.resetPeerNotes(conn, origin);
396}
397
a46d2c0e 398int
fa34dd97 399TunnelStateData::Connection::debugLevelForError(int const xerrno) const
a46d2c0e 400{
401#ifdef ECONNRESET
402
403 if (xerrno == ECONNRESET)
404 return 2;
405
447e176b 406#endif
407
a46d2c0e 408 if (ignoreErrno(xerrno))
409 return 3;
410
411 return 1;
412}
adb78bd4 413
983061ed 414/* Read from server side and queue it for writing to the client */
a46d2c0e 415void
c8407295 416TunnelStateData::ReadServer(const Comm::ConnectionPointer &c, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
983061ed 417{
fa34dd97 418 TunnelStateData *tunnelState = (TunnelStateData *)data;
e0d28505 419 assert(cbdataReferenceValid(tunnelState));
fd54d9b2 420 debugs(26, 3, HERE << c);
c4b7a5a9 421
11007d4b 422 tunnelState->readServer(buf, len, errcode, xerrno);
a46d2c0e 423}
62e76326 424
a46d2c0e 425void
ced8def3 426TunnelStateData::readServer(char *, size_t len, Comm::Flag errcode, int xerrno)
a46d2c0e 427{
fd54d9b2 428 debugs(26, 3, HERE << server.conn << ", read " << len << " bytes, err=" << errcode);
9fe3d316 429 server.delayedLoops=0;
d01053a2 430
a46d2c0e 431 /*
c8407295 432 * Bail out early on Comm::ERR_CLOSING
26ac0430 433 * - close handlers will tidy up for us
a46d2c0e 434 */
a55f4cea 435
c8407295 436 if (errcode == Comm::ERR_CLOSING)
a46d2c0e 437 return;
62e76326 438
ee1679df 439 if (len > 0) {
a46d2c0e 440 server.bytesIn(len);
a0864754
AJ
441 statCounter.server.all.kbytes_in += len;
442 statCounter.server.other.kbytes_in += len;
d8165775 443 request->hier.notePeerRead();
ee1679df 444 }
62e76326 445
3ed5793b
AR
446 if (keepGoingAfterRead(len, errcode, xerrno, server, client))
447 copy(len, server, client, WriteClientDone);
448}
449
a46d2c0e 450void
fa34dd97 451TunnelStateData::Connection::error(int const xerrno)
a46d2c0e 452{
b69e9ffa 453 debugs(50, debugLevelForError(xerrno), HERE << conn << ": read/write failure: " << xstrerr(xerrno));
62e76326 454
a46d2c0e 455 if (!ignoreErrno(xerrno))
fb046c1b 456 conn->close();
983061ed 457}
458
459/* Read from client side and queue it for writing to the server */
a46d2c0e 460void
c8407295 461TunnelStateData::ReadClient(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data)
983061ed 462{
fa34dd97 463 TunnelStateData *tunnelState = (TunnelStateData *)data;
11007d4b 464 assert (cbdataReferenceValid (tunnelState));
62e76326 465
11007d4b 466 tunnelState->readClient(buf, len, errcode, xerrno);
a46d2c0e 467}
62e76326 468
a46d2c0e 469void
ced8def3 470TunnelStateData::readClient(char *, size_t len, Comm::Flag errcode, int xerrno)
a46d2c0e 471{
fd54d9b2 472 debugs(26, 3, HERE << client.conn << ", read " << len << " bytes, err=" << errcode);
9fe3d316 473 client.delayedLoops=0;
d01053a2 474
a46d2c0e 475 /*
c8407295 476 * Bail out early on Comm::ERR_CLOSING
26ac0430 477 * - close handlers will tidy up for us
a46d2c0e 478 */
a55f4cea 479
c8407295 480 if (errcode == Comm::ERR_CLOSING)
a46d2c0e 481 return;
a55f4cea 482
a46d2c0e 483 if (len > 0) {
484 client.bytesIn(len);
a0864754 485 statCounter.client_http.kbytes_in += len;
a46d2c0e 486 }
62e76326 487
3ed5793b
AR
488 if (keepGoingAfterRead(len, errcode, xerrno, client, server))
489 copy(len, client, server, WriteServerDone);
a46d2c0e 490}
62e76326 491
3ed5793b
AR
492/// Updates state after reading from client or server.
493/// Returns whether the caller should use the data just read.
494bool
c8407295 495TunnelStateData::keepGoingAfterRead(size_t len, Comm::Flag errcode, int xerrno, Connection &from, Connection &to)
a46d2c0e 496{
fd54d9b2
AJ
497 debugs(26, 3, HERE << "from={" << from.conn << "}, to={" << to.conn << "}");
498
a46d2c0e 499 /* I think this is to prevent free-while-in-a-callback behaviour
26ac0430 500 * - RBC 20030229
fb046c1b 501 * from.conn->close() / to.conn->close() done here trigger close callbacks which may free TunnelStateData
a46d2c0e 502 */
83564ee7 503 const CbcPointer<TunnelStateData> safetyLock(this);
62e76326 504
60dafd5e 505 /* Bump the source connection read timeout on any activity */
8d77a37c
AJ
506 if (Comm::IsConnOpen(from.conn)) {
507 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
dc49061a 508 CommTimeoutCbPtrFun(tunnelTimeout, this));
8d77a37c
AJ
509 commSetConnTimeout(from.conn, Config.Timeout.read, timeoutCall);
510 }
99c02c10 511
2677c3b1
JPM
512 /* Bump the dest connection read timeout on any activity */
513 /* see Bug 3659: tunnels can be weird, with very long one-way transfers */
514 if (Comm::IsConnOpen(to.conn)) {
515 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
516 CommTimeoutCbPtrFun(tunnelTimeout, this));
517 commSetConnTimeout(to.conn, Config.Timeout.read, timeoutCall);
518 }
519
58c0b17d 520 if (errcode)
a46d2c0e 521 from.error (xerrno);
60dafd5e 522 else if (len == 0 || !Comm::IsConnOpen(to.conn)) {
fd54d9b2 523 debugs(26, 3, HERE << "Nothing to write or client gone. Terminate the tunnel.");
fb046c1b 524 from.conn->close();
62e76326 525
60dafd5e 526 /* Only close the remote end if we've finished queueing data to it */
97c81191 527 if (from.len == 0 && Comm::IsConnOpen(to.conn) ) {
fb046c1b 528 to.conn->close();
c4b7a5a9 529 }
ec41b64c 530 } else if (cbdataReferenceValid(this)) {
3ed5793b
AR
531 return true;
532 }
533
534 return false;
535}
536
537void
538TunnelStateData::copy(size_t len, Connection &from, Connection &to, IOCB *completion)
539{
1c8fc082
A
540 debugs(26, 3, HERE << "Schedule Write");
541 AsyncCall::Pointer call = commCbCall(5,5, "TunnelBlindCopyWriteHandler",
542 CommIoCbPtrFun(completion, this));
74f35ca8 543 to.write(from.buf, len, call, NULL);
983061ed 544}
545
546/* Writes data from the client buffer to the server side */
a46d2c0e 547void
c8407295 548TunnelStateData::WriteServerDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
983061ed 549{
fa34dd97 550 TunnelStateData *tunnelState = (TunnelStateData *)data;
11007d4b 551 assert (cbdataReferenceValid (tunnelState));
74f35ca8 552 tunnelState->server.writer = NULL;
a46d2c0e 553
11007d4b 554 tunnelState->writeServerDone(buf, len, flag, xerrno);
a46d2c0e 555}
a55f4cea 556
a46d2c0e 557void
ced8def3 558TunnelStateData::writeServerDone(char *, size_t len, Comm::Flag flag, int xerrno)
a46d2c0e 559{
fd54d9b2 560 debugs(26, 3, HERE << server.conn << ", " << len << " bytes written, flag=" << flag);
62e76326 561
d8165775
AR
562 if (flag == Comm::ERR_CLOSING)
563 return;
564
565 request->hier.notePeerWrite();
566
5dacdf3f 567 /* Error? */
c8407295 568 if (flag != Comm::OK) {
d8165775
AR
569 debugs(26, 4, "to-server write failed: " << xerrno);
570 server.error(xerrno); // may call comm_close
5dacdf3f 571 return;
c4b7a5a9 572 }
62e76326 573
5dacdf3f 574 /* EOF? */
a46d2c0e 575 if (len == 0) {
fd54d9b2 576 debugs(26, 4, HERE << "No read input. Closing server connection.");
fb046c1b 577 server.conn->close();
a46d2c0e 578 return;
579 }
62e76326 580
5dacdf3f 581 /* Valid data */
a0864754
AJ
582 statCounter.server.all.kbytes_out += len;
583 statCounter.server.other.kbytes_out += len;
5dacdf3f 584 client.dataSent(len);
585
a46d2c0e 586 /* If the other end has closed, so should we */
97c81191 587 if (!Comm::IsConnOpen(client.conn)) {
fd54d9b2 588 debugs(26, 4, HERE << "Client gone away. Shutting down server connection.");
fb046c1b 589 server.conn->close();
a55f4cea 590 return;
c4b7a5a9 591 }
62e76326 592
f53969cc 593 const CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
a46d2c0e 594
5dacdf3f 595 if (cbdataReferenceValid(this))
3248e962 596 copyClientBytes();
983061ed 597}
598
599/* Writes data from the server buffer to the client side */
a46d2c0e 600void
c8407295 601TunnelStateData::WriteClientDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag flag, int xerrno, void *data)
983061ed 602{
fa34dd97 603 TunnelStateData *tunnelState = (TunnelStateData *)data;
11007d4b 604 assert (cbdataReferenceValid (tunnelState));
74f35ca8 605 tunnelState->client.writer = NULL;
a46d2c0e 606
11007d4b 607 tunnelState->writeClientDone(buf, len, flag, xerrno);
a46d2c0e 608}
609
610void
e0d28505 611TunnelStateData::Connection::dataSent(size_t amount)
a46d2c0e 612{
fd54d9b2 613 debugs(26, 3, HERE << "len=" << len << " - amount=" << amount);
a46d2c0e 614 assert(amount == (size_t)len);
615 len =0;
616 /* increment total object size */
617
618 if (size_ptr)
619 *size_ptr += amount;
d8165775 620
a46d2c0e 621}
622
74f35ca8
AR
623void
624TunnelStateData::Connection::write(const char *b, int size, AsyncCall::Pointer &callback, FREE * free_func)
625{
626 writer = callback;
627 Comm::Write(conn, b, size, callback, free_func);
628}
629
a46d2c0e 630void
ced8def3 631TunnelStateData::writeClientDone(char *, size_t len, Comm::Flag flag, int xerrno)
a46d2c0e 632{
fd54d9b2 633 debugs(26, 3, HERE << client.conn << ", " << len << " bytes written, flag=" << flag);
62e76326 634
d8165775
AR
635 if (flag == Comm::ERR_CLOSING)
636 return;
637
5dacdf3f 638 /* Error? */
c8407295 639 if (flag != Comm::OK) {
d8165775
AR
640 debugs(26, 4, "from-client read failed: " << xerrno);
641 client.error(xerrno); // may call comm_close
5dacdf3f 642 return;
c4b7a5a9 643 }
62e76326 644
5dacdf3f 645 /* EOF? */
a46d2c0e 646 if (len == 0) {
fd54d9b2 647 debugs(26, 4, HERE << "Closing client connection due to 0 byte read.");
fb046c1b 648 client.conn->close();
62e76326 649 return;
983061ed 650 }
62e76326 651
5dacdf3f 652 /* Valid data */
a0864754 653 statCounter.client_http.kbytes_out += len;
5dacdf3f 654 server.dataSent(len);
655
a46d2c0e 656 /* If the other end has closed, so should we */
97c81191 657 if (!Comm::IsConnOpen(server.conn)) {
fd54d9b2 658 debugs(26, 4, HERE << "Server has gone away. Terminating client connection.");
fb046c1b 659 client.conn->close();
a55f4cea 660 return;
983061ed 661 }
62e76326 662
f53969cc 663 CbcPointer<TunnelStateData> safetyLock(this); /* ??? should be locked by the caller... */
a55f4cea 664
5dacdf3f 665 if (cbdataReferenceValid(this))
6821c276 666 copyServerBytes();
983061ed 667}
668
b8d8561b 669static void
8d77a37c 670tunnelTimeout(const CommTimeoutCbParams &io)
983061ed 671{
8d77a37c
AJ
672 TunnelStateData *tunnelState = static_cast<TunnelStateData *>(io.data);
673 debugs(26, 3, HERE << io.conn);
11007d4b 674 /* Temporary lock to protect our own feets (comm_close -> tunnelClientClosed -> Free) */
83564ee7 675 CbcPointer<TunnelStateData> safetyLock(tunnelState);
a55f4cea 676
11007d4b 677 tunnelState->client.closeIfOpen();
678 tunnelState->server.closeIfOpen();
a46d2c0e 679}
62e76326 680
a46d2c0e 681void
fa34dd97 682TunnelStateData::Connection::closeIfOpen()
a46d2c0e 683{
97c81191 684 if (Comm::IsConnOpen(conn))
fb046c1b 685 conn->close();
a46d2c0e 686}
687
9fe3d316
AJ
688static void
689tunnelDelayedClientRead(void *data)
690{
691 if (!data)
692 return;
4846303f 693
215c41fa 694 TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
215c41fa 695 tunnel->client.readPending = NULL;
9fe3d316 696 static uint64_t counter=0;
215c41fa 697 debugs(26, 7, "Client read(2) delayed " << ++counter << " times");
9fe3d316
AJ
698 tunnel->copyRead(tunnel->client, TunnelStateData::ReadClient);
699}
700
701static void
702tunnelDelayedServerRead(void *data)
703{
704 if (!data)
705 return;
4846303f 706
215c41fa 707 TunnelStateData *tunnel = static_cast<TunnelStateData*>(data);
215c41fa 708 tunnel->server.readPending = NULL;
9fe3d316 709 static uint64_t counter=0;
215c41fa 710 debugs(26, 7, "Server read(2) delayed " << ++counter << " times");
9fe3d316
AJ
711 tunnel->copyRead(tunnel->server, TunnelStateData::ReadServer);
712}
713
a46d2c0e 714void
fa34dd97 715TunnelStateData::copyRead(Connection &from, IOCB *completion)
a46d2c0e 716{
717 assert(from.len == 0);
9fe3d316
AJ
718 // If only the minimum permitted read size is going to be attempted
719 // then we schedule an event to try again in a few I/O cycles.
720 // Allow at least 1 byte to be read every (0.3*10) seconds.
721 int bw = from.bytesWanted(1, SQUID_TCP_SO_RCVBUF);
722 if (bw == 1 && ++from.delayedLoops < 10) {
215c41fa
AJ
723 from.readPending = this;
724 eventAdd("tunnelDelayedServerRead", from.readPendingFunc, from.readPending, 0.3, true);
9fe3d316
AJ
725 return;
726 }
727
fd54d9b2 728 AsyncCall::Pointer call = commCbCall(5,4, "TunnelBlindCopyReadHandler",
abd8f140 729 CommIoCbPtrFun(completion, this));
9fe3d316 730 comm_read(from.conn, from.buf, bw, call);
983061ed 731}
732
3248e962
CT
733void
734TunnelStateData::copyClientBytes()
735{
736 if (preReadClientData.length()) {
737 size_t copyBytes = preReadClientData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadClientData.length();
738 memcpy(client.buf, preReadClientData.rawContent(), copyBytes);
739 preReadClientData.consume(copyBytes);
740 client.bytesIn(copyBytes);
741 if (keepGoingAfterRead(copyBytes, Comm::OK, 0, client, server))
742 copy(copyBytes, client, server, TunnelStateData::WriteServerDone);
743 } else
744 copyRead(client, ReadClient);
745}
746
6821c276
CT
747void
748TunnelStateData::copyServerBytes()
749{
750 if (preReadServerData.length()) {
751 size_t copyBytes = preReadServerData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadServerData.length();
752 memcpy(server.buf, preReadServerData.rawContent(), copyBytes);
753 preReadServerData.consume(copyBytes);
754 server.bytesIn(copyBytes);
755 if (keepGoingAfterRead(copyBytes, Comm::OK, 0, server, client))
756 copy(copyBytes, server, client, TunnelStateData::WriteClientDone);
757 } else
758 copyRead(server, ReadServer);
759}
760
379e8c1c 761/**
87f237a9 762 * Set the HTTP status for this request and sets the read handlers for client
379e8c1c
AR
763 * and server side connections.
764 */
765static void
766tunnelStartShoveling(TunnelStateData *tunnelState)
767{
f5e17947 768 assert(!tunnelState->waitingForConnectExchange);
955394ce 769 *tunnelState->status_ptr = Http::scOkay;
a95989ed 770 if (tunnelState->logTag_ptr)
d2a6dcba 771 tunnelState->logTag_ptr->update(LOG_TCP_TUNNEL);
379e8c1c 772 if (cbdataReferenceValid(tunnelState)) {
6c420975 773
5eedd56a 774 // Shovel any payload already pushed into reply buffer by the server response
3ed5793b 775 if (!tunnelState->server.len)
6821c276 776 tunnelState->copyServerBytes();
6c420975
AJ
777 else {
778 debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
3ed5793b 779 tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
6c420975
AJ
780 }
781
fcc444e3
AJ
782 if (tunnelState->http.valid() && tunnelState->http->getConn() && !tunnelState->http->getConn()->inBuf.isEmpty()) {
783 SBuf * const in = &tunnelState->http->getConn()->inBuf;
784 debugs(26, DBG_DATA, "Tunnel client PUSH Payload: \n" << *in << "\n----------");
785 tunnelState->preReadClientData.append(*in);
786 in->consume(); // ConnStateData buffer accounting after the shuffle.
3248e962
CT
787 }
788 tunnelState->copyClientBytes();
379e8c1c
AR
789 }
790}
791
b0388924
AJ
792/**
793 * All the pieces we need to write to client and/or server connection
1b76e6c1 794 * have been written.
379e8c1c 795 * Call the tunnelStartShoveling to start the blind pump.
b0388924 796 */
c4b7a5a9 797static void
c6f9a0ff 798tunnelConnectedWriteDone(const Comm::ConnectionPointer &conn, char *, size_t len, Comm::Flag flag, int, void *data)
c4b7a5a9 799{
fa34dd97 800 TunnelStateData *tunnelState = (TunnelStateData *)data;
fd54d9b2 801 debugs(26, 3, HERE << conn << ", flag=" << flag);
74f35ca8 802 tunnelState->client.writer = NULL;
62e76326 803
c8407295 804 if (flag != Comm::OK) {
955394ce 805 *tunnelState->status_ptr = Http::scInternalServerError;
e0d28505 806 tunnelErrorComplete(conn->fd, data, 0);
62e76326 807 return;
808 }
809
c6f9a0ff
CT
810 if (auto http = tunnelState->http.get()) {
811 http->out.headers_sz += len;
812 http->out.size += len;
813 }
814
379e8c1c 815 tunnelStartShoveling(tunnelState);
c4b7a5a9 816}
817
f5e17947
CT
818void
819TunnelStateData::tunnelEstablishmentDone(Http::TunnelerAnswer &answer)
3ed5793b 820{
f5e17947 821 server.len = 0;
3ed5793b 822
f5e17947
CT
823 if (logTag_ptr)
824 logTag_ptr->update(LOG_TCP_TUNNEL);
d8165775 825
f5e17947
CT
826 if (answer.peerResponseStatus != Http::scNone)
827 *status_ptr = answer.peerResponseStatus;
828
829 waitingForConnectExchange = false;
830
831 if (answer.positive()) {
832 // copy any post-200 OK bytes to our buffer
833 preReadServerData = answer.leftovers;
834 notePeerReadyToShovel();
3ed5793b
AR
835 return;
836 }
837
f5e17947 838 // TODO: Reuse to-peer connections after a CONNECT error response.
d8165775 839
f5e17947
CT
840 // TODO: We can and, hence, should close now, but tunnelServerClosed()
841 // cannot yet tell whether ErrorState is still writing an error response.
842 // server.closeIfOpen();
3ed5793b 843
f5e17947
CT
844 if (!clientExpectsConnectResponse()) {
845 // closing the non-HTTP client connection is the best we can do
846 debugs(50, 3, server.conn << " closing on CONNECT-to-peer error");
847 server.closeIfOpen();
848 return;
3ed5793b 849 }
f5e17947
CT
850
851 ErrorState *error = answer.squidError.get();
852 Must(error);
853 answer.squidError.clear(); // preserve error for errorSendComplete()
854 sendError(error, "tunneler returns error");
3ed5793b
AR
855}
856
f5e17947
CT
857void
858TunnelStateData::notePeerReadyToShovel()
983061ed 859{
f5e17947
CT
860 if (!clientExpectsConnectResponse())
861 tunnelStartShoveling(this); // ssl-bumped connection, be quiet
379e8c1c 862 else {
f5e17947 863 *status_ptr = Http::scOkay;
379e8c1c 864 AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
f5e17947
CT
865 CommIoCbPtrFun(tunnelConnectedWriteDone, this));
866 client.write(conn_established, strlen(conn_established), call, nullptr);
379e8c1c 867 }
983061ed 868}
869
b8d8561b 870static void
fd54d9b2 871tunnelErrorComplete(int fd/*const Comm::ConnectionPointer &*/, void *data, size_t)
30a4f2a8 872{
fa34dd97 873 TunnelStateData *tunnelState = (TunnelStateData *)data;
fd54d9b2 874 debugs(26, 3, HERE << "FD " << fd);
11007d4b 875 assert(tunnelState != NULL);
876 /* temporary lock to save our own feets (comm_close -> tunnelClientClosed -> Free) */
83564ee7 877 CbcPointer<TunnelStateData> safetyLock(tunnelState);
62e76326 878
97c81191 879 if (Comm::IsConnOpen(tunnelState->client.conn))
fb046c1b 880 tunnelState->client.conn->close();
62e76326 881
97c81191 882 if (Comm::IsConnOpen(tunnelState->server.conn))
fb046c1b 883 tunnelState->server.conn->close();
30a4f2a8 884}
885
6043e368 886void
55622953 887TunnelStateData::noteConnection(HappyConnOpener::Answer &answer)
6043e368 888{
55622953
CT
889 calls.connector = nullptr;
890 connOpener.clear();
891
892 if (const auto error = answer.error.get()) {
893 syncHierNote(answer.conn, request->url.host());
894 saveError(error);
895 answer.error.clear(); // savedError has it now
896 sendError(savedError, "tried all destinations");
897 return;
898 }
6043e368 899
55622953 900 connectDone(answer.conn, request->url.host(), answer.reused);
6043e368
AR
901}
902
55622953
CT
903void
904TunnelStateData::connectDone(const Comm::ConnectionPointer &conn, const char *origin, const bool reused)
983061ed 905{
55622953
CT
906 Must(Comm::IsConnOpen(conn));
907 server.conn = conn;
cfd66529 908
55622953
CT
909 if (reused)
910 ResetMarkingsToServer(request.getRaw(), *conn);
911 // else Comm::ConnOpener already applied proper/current markings
912
913 syncHierNote(server.conn, request->url.host());
914
915 request->hier.resetPeerNotes(conn, origin);
916 if (al)
917 al->hier.resetPeerNotes(conn, origin);
cfd66529 918
4beb4bab
AJ
919#if USE_DELAY_POOLS
920 /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
921 if (conn->getPeer() && conn->getPeer()->options.no_delay)
55622953 922 server.setDelayId(DelayId());
4beb4bab
AJ
923#endif
924
55622953 925 netdbPingSite(request->url.host());
4beb4bab 926
55622953
CT
927 request->peer_host = conn->getPeer() ? conn->getPeer()->host : nullptr;
928 comm_add_close_handler(conn->fd, tunnelServerClosed, this);
cfd66529 929
f5e17947
CT
930 bool toOrigin = false; // same semantics as StateFlags::toOrigin
931 if (const auto * const peer = conn->getPeer()) {
55622953 932 request->prepForPeering(*peer);
f5e17947 933 toOrigin = peer->options.originserver;
fe40a877 934 } else {
55622953 935 request->prepForDirect();
f5e17947 936 toOrigin = true;
cfd66529 937 }
62e76326 938
f5e17947 939 if (!toOrigin)
55622953 940 connectToPeer();
cfd66529 941 else {
55622953 942 notePeerReadyToShovel();
983061ed 943 }
cfd66529 944
8d77a37c 945 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
55622953 946 CommTimeoutCbPtrFun(tunnelTimeout, this));
8d77a37c 947 commSetConnTimeout(conn, Config.Timeout.read, timeoutCall);
983061ed 948}
30a4f2a8 949
770f051d 950void
ac9f46af 951tunnelStart(ClientHttpRequest * http)
30a4f2a8 952{
fd54d9b2 953 debugs(26, 3, HERE);
30a4f2a8 954 /* Create state structure. */
fa34dd97 955 TunnelStateData *tunnelState = NULL;
9b312a19 956 ErrorState *err = NULL;
190154cf 957 HttpRequest *request = http->request;
d5964d58 958 char *url = http->uri;
fb046c1b 959
f1003989 960 /*
4dd643d5 961 * client_addr.isNoAddr() indicates this is an "internal" request
a4b8110e 962 * from peer_digest.c, asn.c, netdb.c, etc and should always
963 * be allowed. yuck, I know.
964 */
62e76326 965
4dd643d5 966 if (Config.accessList.miss && !request->client_addr.isNoAddr()) {
62e76326 967 /*
968 * Check if this host is allowed to fetch MISSES from us (miss_access)
b50e327b 969 * default is to allow.
62e76326 970 */
c0941a6a 971 ACLFilledChecklist ch(Config.accessList.miss, request, NULL);
cb365059 972 ch.al = http->al;
62e76326 973 ch.src_addr = request->client_addr;
974 ch.my_addr = request->my_addr;
cb365059 975 ch.syncAle(request, http->log_uri);
06bf5384 976 if (ch.fastCheck().denied()) {
fd54d9b2 977 debugs(26, 4, HERE << "MISS access forbidden.");
7e6eabbc 978 err = new ErrorState(ERR_FORWARDING_DENIED, Http::scForbidden, request, http->al);
ac9f46af 979 http->al->http.code = Http::scForbidden;
73c36fd9 980 errorSend(http->getConn()->clientConnection, err);
62e76326 981 return;
982 }
f1003989 983 }
62e76326 984
7f06a3d8 985 debugs(26, 3, request->method << ' ' << url << ' ' << request->http_ver);
5db6bf73
FC
986 ++statCounter.server.all.requests;
987 ++statCounter.server.other.requests;
62e76326 988
6b2b6cfe 989 tunnelState = new TunnelStateData(http);
9a0a18de 990#if USE_DELAY_POOLS
f5e17947 991 tunnelState->server.setDelayId(DelayId::DelayClient(http));
59715b38 992#endif
6043e368 993 tunnelState->startSelectingDestinations(request, http->al, nullptr);
30a4f2a8 994}
98ffb7e4 995
a23223bf 996void
e2849af8
A
997TunnelStateData::connectToPeer()
998{
fcfdf7f9 999 if (CachePeer *p = server.conn->getPeer()) {
1f1f29e8 1000 if (p->secure.encryptTransport) {
a23223bf 1001 AsyncCall::Pointer callback = asyncCall(5,4,
e2849af8
A
1002 "TunnelStateData::ConnectedToPeer",
1003 MyAnswerDialer(&TunnelStateData::connectedToPeer, this));
a72b6e88 1004 auto *connector = new Security::BlindPeerConnector(request, server.conn, callback, al);
a23223bf
CT
1005 AsyncJob::Start(connector); // will call our callback
1006 return;
1007 }
1008 }
a23223bf 1009
fcfdf7f9
AJ
1010 Security::EncryptorAnswer nil;
1011 connectedToPeer(nil);
a23223bf
CT
1012}
1013
a23223bf 1014void
fcfdf7f9 1015TunnelStateData::connectedToPeer(Security::EncryptorAnswer &answer)
a23223bf
CT
1016{
1017 if (ErrorState *error = answer.error.get()) {
6043e368
AR
1018 answer.error.clear(); // sendError() will own the error
1019 sendError(error, "TLS peer connection error");
a23223bf
CT
1020 return;
1021 }
1022
f5e17947 1023 assert(!waitingForConnectExchange);
8d77a37c 1024
f5e17947
CT
1025 AsyncCall::Pointer callback = asyncCall(5,4,
1026 "TunnelStateData::tunnelEstablishmentDone",
1027 Http::Tunneler::CbDialer<TunnelStateData>(&TunnelStateData::tunnelEstablishmentDone, this));
1028 const auto tunneler = new Http::Tunneler(server.conn, request, callback, Config.Timeout.lifetime, al);
1029#if USE_DELAY_POOLS
1030 tunneler->setDelayId(server.delayId);
1031#endif
1032 AsyncJob::Start(tunneler);
1033 waitingForConnectExchange = true;
1034 // and wait for the tunnelEstablishmentDone() call
98ffb7e4 1035}
33ea9fff 1036
6043e368
AR
1037void
1038TunnelStateData::noteDestination(Comm::ConnectionPointer path)
33ea9fff 1039{
55622953 1040 destinationsFound = true;
3dde9e52
CT
1041
1042 if (!path) { // decided to use a pinned connection
1043 // We can call usePinned() without fear of clashing with an earlier
1044 // forwarding attempt because PINNED must be the first destination.
55622953 1045 assert(destinations->empty());
3dde9e52
CT
1046 usePinned();
1047 return;
1048 }
1049
55622953
CT
1050 destinations->addPath(path);
1051
1052 if (Comm::IsConnOpen(server.conn)) {
1053 // We are already using a previously opened connection but also
1054 // receiving destinations in case we need to re-forward.
1055 Must(!opening());
1056 return;
1057 }
1058
1059 if (opening()) {
1060 notifyConnOpener();
1061 return; // and continue to wait for tunnelConnectDone() callback
1062 }
1063
1064 startConnecting();
6043e368 1065}
62e76326 1066
6043e368
AR
1067void
1068TunnelStateData::noteDestinationsEnd(ErrorState *selectionError)
1069{
1070 PeerSelectionInitiator::subscribed = false;
55622953
CT
1071 destinations->destinationsFinalized = true;
1072 if (!destinationsFound) {
6b2b6cfe 1073
6043e368
AR
1074 if (selectionError)
1075 return sendError(selectionError, "path selection has failed");
6b2b6cfe 1076
6043e368
AR
1077 if (savedError)
1078 return sendError(savedError, "all found paths have failed");
1079
7e6eabbc 1080 return sendError(new ErrorState(ERR_CANNOT_FORWARD, Http::scServiceUnavailable, request.getRaw(), al),
6043e368 1081 "path selection found no paths");
db1cd23c 1082 }
6043e368
AR
1083 // else continue to use one of the previously noted destinations;
1084 // if all of them fail, tunneling as whole will fail
1085 Must(!selectionError); // finding at least one path means selection succeeded
55622953
CT
1086
1087 if (Comm::IsConnOpen(server.conn)) {
1088 // We are already using a previously opened connection but also
1089 // receiving destinations in case we need to re-forward.
1090 Must(!opening());
1091 return;
1092 }
1093
1094 Must(opening()); // or we would be stuck with nothing to do or wait for
1095 notifyConnOpener();
6043e368 1096}
a37fdd8a 1097
6043e368
AR
1098/// remembers an error to be used if there will be no more connection attempts
1099void
1100TunnelStateData::saveError(ErrorState *error)
1101{
1102 debugs(26, 4, savedError << " ? " << error);
1103 assert(error);
1104 delete savedError; // may be nil
1105 savedError = error;
1106}
1107
1108/// Starts sending the given error message to the client, leading to the
1109/// eventual transaction termination. Call with savedError to send savedError.
1110void
1111TunnelStateData::sendError(ErrorState *finalError, const char *reason)
1112{
1113 debugs(26, 3, "aborting transaction for " << reason);
1114
1115 if (request)
1116 request->hier.stopPeerClock(false);
1117
55622953
CT
1118 if (opening())
1119 cancelOpening(reason);
1120
6043e368 1121 assert(finalError);
16b70e2a 1122
6043e368
AR
1123 // get rid of any cached error unless that is what the caller is sending
1124 if (savedError != finalError)
1125 delete savedError; // may be nil
1126 savedError = nullptr;
62e76326 1127
6043e368
AR
1128 // we cannot try other destinations after responding with an error
1129 PeerSelectionInitiator::subscribed = false; // may already be false
1130
1131 *status_ptr = finalError->httpStatus;
1132 finalError->callback = tunnelErrorComplete;
1133 finalError->callback_data = this;
1134 errorSend(client.conn, finalError);
0ce8e93b
EB
1135}
1136
55622953
CT
1137/// Notify connOpener that we no longer need connections. We do not have to do
1138/// this -- connOpener would eventually notice on its own, but notifying reduces
1139/// waste and speeds up spare connection opening for other transactions (that
1140/// could otherwise wait for this transaction to use its spare allowance).
1141void
1142TunnelStateData::cancelOpening(const char *reason)
1143{
1144 assert(calls.connector);
1145 calls.connector->cancel(reason);
1146 calls.connector = nullptr;
1147 notifyConnOpener();
1148 connOpener.clear();
1149}
1150
0ce8e93b
EB
1151void
1152TunnelStateData::startConnecting()
1153{
6043e368
AR
1154 if (request)
1155 request->hier.startPeerClock();
1156
55622953 1157 assert(!destinations->empty());
6043e368 1158
55622953
CT
1159 calls.connector = asyncCall(17, 5, "TunnelStateData::noteConnection", HappyConnOpener::CbDialer<TunnelStateData>(&TunnelStateData::noteConnection, this));
1160 const auto cs = new HappyConnOpener(destinations, calls.connector, request, startTime, 0, al);
1161 cs->setHost(request->url.host());
1162 cs->setRetriable(false);
1163 cs->allowPersistent(false);
1164 destinations->notificationPending = true; // start() is async
1165 connOpener = cs;
855150a4 1166 AsyncJob::Start(cs);
33ea9fff 1167}
a46d2c0e 1168
3dde9e52
CT
1169/// send request on an existing connection dedicated to the requesting client
1170void
1171TunnelStateData::usePinned()
1172{
55622953
CT
1173 Must(request);
1174 const auto connManager = request->pinnedConnection();
daf80700
CT
1175 try {
1176 const auto serverConn = ConnStateData::BorrowPinnedConnection(request.getRaw(), al);
1177 debugs(26, 7, "pinned peer connection: " << serverConn);
1178
1179 // Set HttpRequest pinned related flags for consistency even if
1180 // they are not really used by tunnel.cc code.
1181 request->flags.pinned = true;
1182 if (connManager->pinnedAuth())
1183 request->flags.auth = true;
1184
1185 // the server may close the pinned connection before this request
1186 const auto reused = true;
1187 connectDone(serverConn, connManager->pinning.host, reused);
1188 } catch (ErrorState * const error) {
1189 syncHierNote(nullptr, connManager ? connManager->pinning.host : request->url.host());
3dde9e52 1190 // a PINNED path failure is fatal; do not wait for more paths
daf80700 1191 sendError(error, "pinned path failure");
3dde9e52
CT
1192 return;
1193 }
1194
3dde9e52
CT
1195}
1196
fa34dd97 1197CBDATA_CLASS_INIT(TunnelStateData);
a46d2c0e 1198
a46d2c0e 1199bool
fa34dd97 1200TunnelStateData::noConnections() const
a46d2c0e 1201{
97c81191 1202 return !Comm::IsConnOpen(server.conn) && !Comm::IsConnOpen(client.conn);
a46d2c0e 1203}
1204
9a0a18de 1205#if USE_DELAY_POOLS
a46d2c0e 1206void
fa34dd97 1207TunnelStateData::Connection::setDelayId(DelayId const &newDelay)
a46d2c0e 1208{
1209 delayId = newDelay;
1210}
1211
1212#endif
93ead3fd 1213
55622953
CT
1214/// makes sure connOpener knows that destinations have changed
1215void
1216TunnelStateData::notifyConnOpener()
1217{
1218 if (destinations->notificationPending) {
1219 debugs(17, 7, "reusing pending notification");
1220 } else {
1221 destinations->notificationPending = true;
1222 CallJobHere(17, 5, connOpener, HappyConnOpener, noteCandidatesChange);
1223 }
1224}
1225
1110989a 1226#if USE_OPENSSL
93ead3fd 1227void
c91d4d4e 1228switchToTunnel(HttpRequest *request, Comm::ConnectionPointer &clientConn, Comm::ConnectionPointer &srvConn)
93ead3fd 1229{
c91d4d4e 1230 debugs(26,5, "Revert to tunnel FD " << clientConn->fd << " with FD " << srvConn->fd);
93ead3fd 1231
6b2b6cfe 1232 /* Create state structure. */
93ead3fd
CT
1233 ++statCounter.server.all.requests;
1234 ++statCounter.server.other.requests;
1235
6b2b6cfe
CT
1236 auto conn = request->clientConnectionManager.get();
1237 Must(conn);
1238 Http::StreamPointer context = conn->pipeline.front();
1239 Must(context && context->http);
a95989ed 1240
6b2b6cfe 1241 debugs(26, 3, request->method << " " << context->http->uri << " " << request->http_ver);
a95989ed 1242
6b2b6cfe 1243 TunnelStateData *tunnelState = new TunnelStateData(context->http);
93ead3fd 1244
ed4c6863
EB
1245 // tunnelStartShoveling() drains any buffered from-client data (inBuf)
1246 fd_table[clientConn->fd].useDefaultIo();
93ead3fd 1247
d8165775 1248 request->hier.resetPeerNotes(srvConn, tunnelState->getHost());
93ead3fd
CT
1249
1250 tunnelState->server.conn = srvConn;
6b2b6cfe
CT
1251
1252#if USE_DELAY_POOLS
1253 /* no point using the delayIsNoDelay stuff since tunnel is nice and simple */
f5e17947 1254 if (!srvConn->getPeer() || !srvConn->getPeer()->options.no_delay)
6b2b6cfe
CT
1255 tunnelState->server.setDelayId(DelayId::DelayClient(context->http));
1256#endif
1257
f53e6e84 1258 request->peer_host = srvConn->getPeer() ? srvConn->getPeer()->host : nullptr;
93ead3fd
CT
1259 comm_add_close_handler(srvConn->fd, tunnelServerClosed, tunnelState);
1260
e4f14091 1261 debugs(26, 4, "determine post-connect handling pathway.");
f5e17947
CT
1262 if (const auto peer = srvConn->getPeer())
1263 request->prepForPeering(*peer);
1264 else
1265 request->prepForDirect();
93ead3fd 1266
6b2b6cfe
CT
1267 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "tunnelTimeout",
1268 CommTimeoutCbPtrFun(tunnelTimeout, tunnelState));
93ead3fd 1269 commSetConnTimeout(srvConn, Config.Timeout.read, timeoutCall);
ed4c6863
EB
1270
1271 // we drain any already buffered from-server data below (rBufData)
1272 fd_table[srvConn->fd].useDefaultIo();
93ead3fd 1273
33cc0629 1274 auto ssl = fd_table[srvConn->fd].ssl.get();
a95989ed
CT
1275 assert(ssl);
1276 BIO *b = SSL_get_rbio(ssl);
2a268a06 1277 Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(BIO_get_data(b));
6821c276
CT
1278 tunnelState->preReadServerData = srvBio->rBufData();
1279 tunnelStartShoveling(tunnelState);
93ead3fd 1280}
1110989a 1281#endif //USE_OPENSSL
f53969cc 1282